namei (via firmware_get(9)) from taskq in 7.x

Andrew Gallatin gallatin at
Thu Oct 15 21:16:30 UTC 2009


I'm trying to re-initialize a NIC which uses firmware(9)
after a hardware fault.  As part of the process, I need
to re-load the firmware using firmware_get().  If the
firmware kld is not resident, then the machine will panic
like this:

Fatal trap 12: page fault while in kernel mode
cpuid = 0; apic id = 00
fault virtual address   = 0x20
fault code              = supervisor read data, page not present
instruction pointer     = 0x8:0xffffffff805b05d4
stack pointer           = 0x10:0xffffff8000080460
frame pointer           = 0x10:0xffffff8000080510
code segment            = base 0x0, limit 0xfffff, type 0x1b
                         = DPL 0, pres 1, long 1, def32 0, gran 1
processor eflags        = interrupt enabled, resume, IOPL = 0
current process         = 21 (swi5: +)
[thread pid 21 tid 100021 ]
Stopped at      namei+0x174:    movq    0x20(%rbx),%rax
db> bt
Tracing pid 21 tid 100021 td 0xffffff00013c3ae0
namei() at namei+0x174
vn_open_cred() at vn_open_cred+0x3a4
linker_load_module() at linker_load_module+0x1f2
linker_reference_module() at linker_reference_module+0xae
firmware_get() at firmware_get+0x136
mxge_load_firmware() at mxge_load_firmware+0x2d
mxge_watchdog_task() at mxge_watchdog_task+0x2f6
taskqueue_run() at taskqueue_run+0x9d
ithread_loop() at ithread_loop+0x17d
fork_exit() at fork_exit+0x11f
fork_trampoline() at fork_trampoline+0xe

Looking at it in gdb, it seems like the problem is that namei
is trying to use ndp->ni_cnd.cn_thread->td_proc->p_fd->fd_cdir
which is null in this context.

Can somebody tell me what kernel context it is safe to
call firmware_get() (and hence namei) from?  Is there
a safe way to do it from a taskq?

FWIW, this seems to work fine (even from a callout context)
in 8 and higher.  It is only 7 and earlier where I'm having
this problem.


More information about the freebsd-hackers mailing list