[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[netbsd,08859] lockmgr() で panic
- To: netbsd@xxxxxxxxxxxxx
- Subject: [netbsd,08859] lockmgr() で panic
- From: KIYOHARA Takashi <kiyohara@xxxxxxxxxxxxxx>
- Date: Sat, 26 Jun 2004 13:38:58 +0900 (JST)
清原です
# 昨日送信したメールが、設定の関係ではねられたようですので、再送
# しています。2 通受信した場合は無視して下さい。
# こっちは微妙に文章を捕捉しています。
NetBSD の IEEE1394 に不満を感じて、FreeBSD の firewire のドライバを
移植できないかと思っていろいろやってみてるのですが、わからないこと
が出てきたので、ご存知でしたらお教え下さい。
FreeBSD の fwohci(4) や firewire(4) は動くようになったっぽいのですが、
IEEE1394 の HDD を刺すと panic するという現象が出ます。調べてみると
(FreeBSD の)firewire の fwdma.c 内 fwdma_malloc() で DMA 用のメモリ
を確保していたので、そこを bus_dmamem_{alloc,map},bus_dmamap_{create,
load} に置き換えてみたのですが、bus_dmamem_map() から呼ばれる先にある
lockmgr() 内で panic していました。
メモリ確保部の変更前 (FreeBSD)
bus_dma_tag_create()
bus_dmamem_alloc()
bus_dmamap_load()
変更後
bus_dmamem_alloc()
bus_dmamem_map()
bus_dmamap_create()
bus_dmamap_load()
# KASSERT() が無効になっているので lockmgr() まで呼ばれますが、有効
# になっている場合は uvm_map.c の uvm_map() で落ちるはずです。
kern_lock.c ---
int
#if defined(LOCKDEBUG)
_lockmgr(__volatile struct lock *lkp, u_int flags,
struct simplelock *interlkp, const char *file, int line)
#else
lockmgr(__volatile struct lock *lkp, u_int flags,
struct simplelock *interlkp)
#endif
{
int error;
pid_t pid;
lwpid_t lid;
int extflags;
cpuid_t cpu_id;
struct lwp *l = curlwp;
略
if (extflags & LK_SPIN) {
pid = LK_KERNPROC;
lid = 0;
} else {
if (l == NULL) {
if (!doing_shutdown) {
panic("lockmgr: no context"); <--- ここで
} else {
---
uvm_map.c ---
int
uvm_map(struct vm_map *map, vaddr_t *startp /* IN/OUT */, vsize_t size,
struct uvm_object *uobj, voff_t uoffset, vsize_t align, uvm_flag_t flags)
{
略
KASSERT(doing_shutdown || curlwp != NULL || <---有効ならここで
(map->flags & VM_MAP_INTRSAFE));
---
curlwp が NULL になっている理由は、callout_reset() で呼ばれた関数の中から
bus_dmamem_map() を呼び出しているからなのです。
その上、bus_dmamem_map() で確保するメモリは kernel_map (uvm_map の最初の
引数)のメモリで、これは VM_MAP_INTRSAFE ではないと思っています。
curlwp が「何者」で何時 NULL になるのか、まだ理解できていないのですが、
「現在実行中のプロセスに関する情報」へのポインタであると聞いたので、試し
に次のようなプログラムを複数実行して CPU 使用率が 100% の状態にしてから
HDD を刺してみると panic しませんでした。
負荷をかけるプログラム ---
int
main(int argc, char *argv[])
{
while (1);
}
---
つまり callout_reset() の処理中だと、CPU が IDLE 状態 (curlwp が NULL) に
なっていることがあるので、ここでは bus_dmamem_map() が使えないようだという
ことがわかってきました。
そこでお伺いしたいのですが、このような場合の解決策はどのようになるのでし
ょうか?
1. bus_dmamem_{alloc,map}() を使わずに malloc() で確保したメモリ
を代用する
-> kernel の空間は常に物理メモリ上にあるという前提で。
2. callout 内で bus_dmamem_map() を実行しないで、kthread を作成
してそっちでやる
-> kthread からだと curlwp がどこかを指しているであろうから。
3. その他の方法 ?
宜しくお願い致します。
# この後の CAM -> scsipi(4) への対応がきつそうな気が…
--
kiyohara