Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 2 Mar 2012 13:49:18 GMT
From:      Vladislav Movchan <vladislav.movchan@gmail.com>
To:        freebsd-gnats-submit@FreeBSD.org
Subject:   kern/165622: [ndis][panic][patch] Unregistered use of FPU in kernel on amd64
Message-ID:  <201203021349.q22DnIaS002268@red.freebsd.org>
Resent-Message-ID: <201203021350.q22Do9pi035387@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         165622
>Category:       kern
>Synopsis:       [ndis][panic][patch] Unregistered use of FPU in kernel on amd64
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Fri Mar 02 13:50:09 UTC 2012
>Closed-Date:
>Last-Modified:
>Originator:     Vladislav Movchan
>Release:        FreeBSD 10.0-CURRENT
>Organization:
>Environment:
FreeBSD starlight 10.0-CURRENT FreeBSD 10.0-CURRENT #0 r232379: Fri Mar  2 13:24:25 EET 2012     root@starlight:/usr/obj/usr/src/sys/Mephistopheles  amd64
>Description:
Some miniport drivers (windows NIC drivers) could use FPU in kernel what cause "Unregistered use of FPU in kernel" panic.

I've seen this only in amd64 case; i386 seems to be not affected.
Same is mentioned in this two messages:
http://lists.freebsd.org/pipermail/svn-src-all/2010-March/021770.html
http://lists.freebsd.org/pipermail/svn-src-all/2010-March/021773.html

Point when panic occurs depends on the driver. In my case it happening during the first attempt to transmit a packet.


Panic message:
panic: Unregistered use of FPU in kernel
cpuid = 3
KDB: stack backtrace:
db_trace_self_wrapper() at db_trace_self_wrapper+0x2a
kdb_backtrace() at kdb_backtrace+0x37
panic() at panic+0x1cd
trap() at trap+0x71f
calltrap() at calltrap+0x8
--- trap 0x16, rip = 0xffffffff83c37e0e, rsp = 0xffffff80d116d7c0, rbp = 0xffffff80075df520 ---
__stop_set_sysinit_set() at __stop_set_sysinit_set+0xe6ee
dmapbase() at 0xfffffe0040fb5180
(null)() at 0xffffff80075df520
dmapbase() at 0xfffffe0040f83d00
dmapbase() at 0xfffffe0040f83e00
dmapbase() at 0xfffffe0040f8b080
dmapbase() at 0xfffffe0040f8b180
dmapbase() at 0xfffffe0040f8b280
..
dmapbase() at 0xfffffe0040fb4600
dmapbase() at 0xfffffe0040fb4700
dmapbase() at 0xfffffe0040fb4800
dmapbase() at 0xfffffe0040fb4900
dmapbase() at 0xfffffe0040fb4a00

Backtrace:
#0  doadump (textdump=-787033584) at /usr/src/sys/kern/kern_shutdown.c:268
268             if (textdump && textdump_pending) {
(kgdb) #0  doadump (textdump=-787033584) at /usr/src/sys/kern/kern_shutdown.c:268
#1  0xffffffff802de36c in db_fncall (dummy1=Variable "dummy1" is not available.
)
    at /usr/src/sys/ddb/db_command.c:573
#2  0xffffffff802de6a1 in db_command (last_cmdp=0xffffffff80dcd560, cmd_table=Variable "cmd_table" is not available.

) at /usr/src/sys/ddb/db_command.c:449
#3  0xffffffff802de8f0 in db_command_loop ()
    at /usr/src/sys/ddb/db_command.c:502
#4  0xffffffff802e0ad4 in db_trap (type=Variable "type" is not available.
) at /usr/src/sys/ddb/db_main.c:229
#5  0xffffffff806d3bb1 in kdb_trap (type=3, code=0, tf=0xffffff80d116d440)
    at /usr/src/sys/kern/subr_kdb.c:629
#6  0xffffffff80942f68 in trap (frame=0xffffff80d116d440)
    at /usr/src/sys/amd64/amd64/trap.c:591
#7  0xffffffff8092c1cf in calltrap ()
    at /usr/src/sys/amd64/amd64/exception.S:228
#8  0xffffffff806d36ab in kdb_enter (why=0xffffffff80a3fb16 "panic",
    msg=0x80 <Address 0x80 out of bounds>) at cpufunc.h:63
#9  0xffffffff8069aea6 in panic (fmt=Variable "fmt" is not available.
)
    at /usr/src/sys/kern/kern_shutdown.c:633
#10 0xffffffff809434ef in trap (frame=Variable "frame" is not available.
) at /usr/src/sys/amd64/amd64/trap.c:478
#11 0xffffffff8092c1cf in calltrap ()
    at /usr/src/sys/amd64/amd64/exception.S:228
#12 0xffffffff83c37e0e in ndis_Rtenic64_sys_drv_data_start ()
   from /boot/modules/Rtenic64_sys.ko
#13 0xffffffffffffffff in ?? ()
#14 0xffffffff80a40a28 in __func__.17200 ()
#15 0x0000074200000001 in ?? ()
#16 0xffffffff80a42b69 in link_elf_methods ()
#17 0xffffff80d116d800 in ?? ()
#18 0x0000000000000000 in ?? ()
#19 0x0000000000000000 in ?? ()
#20 0x0000000000000000 in ?? ()
..
#79 0x0000000000000000 in ?? ()
#80 0x0000000000000000 in ?? ()
#81 0x0000000000000000 in ?? ()
#82 0x0000000000000000 in ?? ()
#83 0xffffff80d116dad0 in ?? ()
#84 0xfffffe007b2b1348 in ?? ()
#85 0xffffff80075de000 in ?? ()
#86 0xfffffe0008410800 in ?? ()
#87 0xffffff80075deff0 in ?? ()
#88 0xffffff80075de000 in ?? ()
#89 0xffffff80075de000 in ?? ()
#90 0xffffff80d116dad0 in ?? ()
#91 0x0000000000000000 in ?? ()
#92 0xffffffff83c3d3ce in ndis_Rtenic64_sys_drv_data_start ()
   from /boot/modules/Rtenic64_sys.ko
#93 0xffffff80d1160000 in ?? ()
#94 0xfffffe0000000000 in ?? ()
#95 0xffffff8000000000 in ?? ()
#96 0xffffff80d116d900 in ?? ()
#97 0xffffffff83c3d284 in ndis_Rtenic64_sys_drv_data_start ()
   from /boot/modules/Rtenic64_sys.ko
#98 0xffffffff840e07b9 in x86_64_call1 ()
    at /usr/src/sys/modules/ndis/../../compat/ndis/winx64_wrap.S:130
#99 0xfffffe007b2b1328 in ?? ()
#100 0xfffffe007b154000 in ?? ()
#101 0xffffff80075deff8 in ?? ()
#102 0xfffffe007b2b1328 in ?? ()
#103 0xffffff80d116dad0 in ?? ()
#104 0xffffffff840d3e87 in ndis_intrhand (dpc=Variable "dpc" is not available.
)
at /usr/src/sys/modules/ndis/../../compat/ndis/subr_ndis.c:2234
Previous frame inner to this frame (corrupt stack?)
(kgdb)


Core/process which triggers this panic:
cpuid        = 3
dynamic pcpu = 0xffffff807f453100
curthread    = 0xfffffe0008bbd000: pid 1547 "Windows DPC 0"
curpcb       = 0xffffff80d116dd00
fpcurthread  = none
idlethread   = 0xfffffe00046b0480: tid 100006 "idle: cpu3"
curpmap      = 0xffffffff80df4c50
tssp         = 0xffffffff82609718
commontssp   = 0xffffffff82609718
rsp0         = 0xffffff80d116dd00
gs32p        = 0xffffffff82607870
ldt          = 0xffffffff826078b0
tss          = 0xffffffff826078a0
spin locks held:


>How-To-Repeat:
Use ndis on amd64:
kldload module created with ndisgen; assign ip address; try to ping something.

I believe not every miniport driver is affected, but drivers of both devices I've tested could trigger this panic.
>Fix:
Attached patch fixed this problem for me. Original version of this patch was written by Paul B Mahol (many thanks to Paul!)

Patch attached with submission follows:

Index: /usr/src/sys/compat/ndis/pe_var.h
===================================================================
--- /usr/src/sys/compat/ndis/pe_var.h	(revision 232379)
+++ /usr/src/sys/compat/ndis/pe_var.h	(working copy)
@@ -460,22 +460,30 @@
 extern uint64_t x86_64_call6(void *, uint64_t, uint64_t, uint64_t, uint64_t,
 	uint64_t, uint64_t);
 
+uint64_t _x86_64_call1(void *, uint64_t);
+uint64_t _x86_64_call2(void *, uint64_t, uint64_t);
+uint64_t _x86_64_call3(void *, uint64_t, uint64_t, uint64_t);
+uint64_t _x86_64_call4(void *, uint64_t, uint64_t, uint64_t, uint64_t);
+uint64_t _x86_64_call5(void *, uint64_t, uint64_t, uint64_t, uint64_t,
+    uint64_t);
+uint64_t _x86_64_call6(void *, uint64_t, uint64_t, uint64_t, uint64_t,
+    uint64_t, uint64_t);
 
 #define	MSCALL1(fn, a)						\
-	x86_64_call1((fn), (uint64_t)(a))
+	_x86_64_call1((fn), (uint64_t)(a))
 #define	MSCALL2(fn, a, b)					\
-	x86_64_call2((fn), (uint64_t)(a), (uint64_t)(b))
+	_x86_64_call2((fn), (uint64_t)(a), (uint64_t)(b))
 #define	MSCALL3(fn, a, b, c)					\
-	x86_64_call3((fn), (uint64_t)(a), (uint64_t)(b),		\
+	_x86_64_call3((fn), (uint64_t)(a), (uint64_t)(b),		\
 	(uint64_t)(c))
 #define	MSCALL4(fn, a, b, c, d)					\
-	x86_64_call4((fn), (uint64_t)(a), (uint64_t)(b),		\
+	_x86_64_call4((fn), (uint64_t)(a), (uint64_t)(b),		\
 	(uint64_t)(c), (uint64_t)(d))
 #define	MSCALL5(fn, a, b, c, d, e)				\
-	x86_64_call5((fn), (uint64_t)(a), (uint64_t)(b),		\
+	_x86_64_call5((fn), (uint64_t)(a), (uint64_t)(b),		\
 	(uint64_t)(c), (uint64_t)(d), (uint64_t)(e))
 #define	MSCALL6(fn, a, b, c, d, e, f)				\
-	x86_64_call6((fn), (uint64_t)(a), (uint64_t)(b),		\
+	_x86_64_call6((fn), (uint64_t)(a), (uint64_t)(b),		\
 	(uint64_t)(c), (uint64_t)(d), (uint64_t)(e), (uint64_t)(f))
 
 #endif /* __amd64__ */
Index: /usr/src/sys/compat/ndis/kern_windrv.c
===================================================================
--- /usr/src/sys/compat/ndis/kern_windrv.c	(revision 232379)
+++ /usr/src/sys/compat/ndis/kern_windrv.c	(working copy)
@@ -56,6 +56,10 @@
 #include <machine/segments.h>
 #endif
 
+#ifdef __amd64__
+#include <machine/fpu.h>
+#endif
+
 #include <dev/usb/usb.h>
 
 #include <compat/ndis/pe_var.h>
@@ -573,6 +577,109 @@
 	return (0);
 }
 
+uint64_t
+_x86_64_call1(void *fn, uint64_t a)
+{
+	struct fpu_kern_ctx *fpu_ctx_save;
+	uint64_t ret;
+
+	fpu_ctx_save = fpu_kern_alloc_ctx(FPU_KERN_NORMAL | FPU_KERN_NOWAIT);
+	if (fpu_ctx_save == NULL)
+		return (ENOMEM);
+	fpu_kern_enter(curthread, fpu_ctx_save, FPU_KERN_NORMAL);
+	ret = x86_64_call1(fn, a);
+	fpu_kern_leave(curthread, fpu_ctx_save);
+	fpu_kern_free_ctx(fpu_ctx_save);
+
+	return (ret);
+}
+
+uint64_t
+_x86_64_call2(void *fn, uint64_t a, uint64_t b)
+{
+	struct fpu_kern_ctx *fpu_ctx_save;
+	uint64_t ret;
+
+	fpu_ctx_save = fpu_kern_alloc_ctx(FPU_KERN_NORMAL | FPU_KERN_NOWAIT);
+	if (fpu_ctx_save == NULL)
+		return (ENOMEM);
+	fpu_kern_enter(curthread, fpu_ctx_save, FPU_KERN_NORMAL);
+	ret = x86_64_call2(fn, a, b);
+	fpu_kern_leave(curthread, fpu_ctx_save);
+	fpu_kern_free_ctx(fpu_ctx_save);
+
+	return (ret);
+}
+
+uint64_t
+_x86_64_call3(void *fn, uint64_t a, uint64_t b, uint64_t c)
+{
+	struct fpu_kern_ctx *fpu_ctx_save;
+	uint64_t ret;
+
+	fpu_ctx_save = fpu_kern_alloc_ctx(FPU_KERN_NORMAL | FPU_KERN_NOWAIT);
+	if (fpu_ctx_save == NULL)
+		return (ENOMEM);
+	fpu_kern_enter(curthread, fpu_ctx_save, FPU_KERN_NORMAL);
+	ret = x86_64_call3(fn, a, b, c);
+	fpu_kern_leave(curthread, fpu_ctx_save);
+	fpu_kern_free_ctx(fpu_ctx_save);
+
+	return (ret);
+}
+
+uint64_t
+_x86_64_call4(void *fn, uint64_t a, uint64_t b, uint64_t c, uint64_t d)
+{
+	struct fpu_kern_ctx *fpu_ctx_save;
+	uint64_t ret;
+
+	fpu_ctx_save = fpu_kern_alloc_ctx(FPU_KERN_NORMAL | FPU_KERN_NOWAIT);
+	if (fpu_ctx_save == NULL)
+		return (ENOMEM);
+	fpu_kern_enter(curthread, fpu_ctx_save, FPU_KERN_NORMAL);
+	ret = x86_64_call4(fn, a, b, c, d);
+	fpu_kern_leave(curthread, fpu_ctx_save);
+	fpu_kern_free_ctx(fpu_ctx_save);
+
+	return (ret);
+}
+
+uint64_t
+_x86_64_call5(void *fn, uint64_t a, uint64_t b, uint64_t c, uint64_t d,
+    uint64_t e)
+{
+	struct fpu_kern_ctx *fpu_ctx_save;
+	uint64_t ret;
+
+	fpu_ctx_save = fpu_kern_alloc_ctx(FPU_KERN_NORMAL | FPU_KERN_NOWAIT);
+	if (fpu_ctx_save == NULL)
+		return (ENOMEM);
+	fpu_kern_enter(curthread, fpu_ctx_save, FPU_KERN_NORMAL);
+	ret = x86_64_call5(fn, a, b, c, d, e);
+	fpu_kern_leave(curthread, fpu_ctx_save);
+	fpu_kern_free_ctx(fpu_ctx_save);
+
+	return (ret);
+}
+
+uint64_t
+_x86_64_call6(void *fn, uint64_t a, uint64_t b, uint64_t c, uint64_t d,
+    uint64_t e, uint64_t f)
+{
+	struct fpu_kern_ctx *fpu_ctx_save;
+	uint64_t ret;
+
+	fpu_ctx_save = fpu_kern_alloc_ctx(FPU_KERN_NORMAL | FPU_KERN_NOWAIT);
+	if (fpu_ctx_save == NULL)
+		return (ENOMEM);
+	fpu_kern_enter(curthread, fpu_ctx_save, FPU_KERN_NORMAL);
+	ret = x86_64_call6(fn, a, b, c, d, e, f);
+	fpu_kern_leave(curthread, fpu_ctx_save);
+	fpu_kern_free_ctx(fpu_ctx_save);
+
+	return (ret);
+}
 #ifdef __amd64__
 
 extern void	x86_64_wrap(void);


>Release-Note:
>Audit-Trail:
>Unformatted:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201203021349.q22DnIaS002268>