Initial FP exception flags incorrect on amd64

David Schultz das at FreeBSD.ORG
Wed Jun 2 18:53:15 PDT 2004


On Thu, Jun 03, 2004, Tim Robbins wrote:
> On Tue, Jun 01, 2004 at 11:48:46PM -0700, David Schultz wrote:
> > I discovered that new processes on amd64 have the inexact flag
> > raised by default, at least on sledge.  However, all the sticky
> > flags should be clear initially.
> [...]
> > I don't have any amd64 hardware of my own to test kernel patches
> > on, but if I were to make a wild guess as to how to solve the
> > problem, it would be the following patch.  I would appreciate it
> > if someone could address the problem, or at least let me know
> > whether my proposed fix works.
> > 
> > Index: sys/amd64/amd64/fpu.c
> > ===================================================================
> > RCS file: /cvs/src/sys/amd64/amd64/fpu.c,v
> > retrieving revision 1.149
> > diff -u -r1.149 fpu.c
> > --- fpu.c	5 Apr 2004 21:25:51 -0000	1.149
> > +++ fpu.c	2 Jun 2004 06:08:34 -0000
> > @@ -73,6 +73,7 @@
> >  #define	fnstsw(addr)		__asm __volatile("fnstsw %0" : "=m" (*(addr)))
> >  #define	fxrstor(addr)		__asm("fxrstor %0" : : "m" (*(addr)))
> >  #define	fxsave(addr)		__asm __volatile("fxsave %0" : "=m" (*(addr)))
> > +#define	stmxcsr(addr)		__asm("stmxcsr %0" : "=m" (*(addr)))
> >  #define	start_emulating()	__asm("smsw %%ax; orb %0,%%al; lmsw %%ax" \
> >  				      : : "n" (CR0_TS) : "ax")
> >  #define	stop_emulating()	__asm("clts")
> > @@ -119,6 +120,8 @@
> >  	fninit();
> >  	control = __INITIAL_FPUCW__;
> >  	fldcw(&control);
> > +	control = __INITIAL_MXCSR__;
> > +	stmxcsr(&control);
> >  	fxsave(&fpu_cleanstate);
> >  	start_emulating();
> >  	fpu_cleanstate_ready = 1;
> 
> This seems to cause a panic (trap 12) on startup. Shouldn't it be ldmxcsr
> instead? Changing that causes a different kind of panic (trap 9.)

Oops, you're right.  The other problem is probably that control is
a u_short, so garbage gets loaded into the upper 16 bits of the CSR.
Making 'control' a u_int should fix the problem, but the following
patch introduces a new variable to avoid relying on endianness
for the fldcw.  Thanks, Tim!


Index: sys/amd64/amd64/fpu.c
===================================================================
RCS file: /cvs/src/sys/amd64/amd64/fpu.c,v
retrieving revision 1.149
diff -u -r1.149 fpu.c
--- sys/amd64/amd64/fpu.c	5 Apr 2004 21:25:51 -0000	1.149
+++ sys/amd64/amd64/fpu.c	3 Jun 2004 01:48:23 -0000
@@ -73,6 +73,7 @@
 #define	fnstsw(addr)		__asm __volatile("fnstsw %0" : "=m" (*(addr)))
 #define	fxrstor(addr)		__asm("fxrstor %0" : : "m" (*(addr)))
 #define	fxsave(addr)		__asm __volatile("fxsave %0" : "=m" (*(addr)))
+#define	ldmxcsr(r)		__asm __volatile("ldmxcsr %0" : : "m" (r))
 #define	start_emulating()	__asm("smsw %%ax; orb %0,%%al; lmsw %%ax" \
 				      : : "n" (CR0_TS) : "ax")
 #define	stop_emulating()	__asm("clts")
@@ -111,6 +112,7 @@
 fpuinit(void)
 {
 	register_t savecrit;
+	u_int mxcsr;
 	u_short control;
 
 	savecrit = intr_disable();
@@ -119,6 +121,8 @@
 	fninit();
 	control = __INITIAL_FPUCW__;
 	fldcw(&control);
+	mxcsr = __INITIAL_MXCSR__;
+	ldmxcsr(mxcsr);
 	fxsave(&fpu_cleanstate);
 	start_emulating();
 	fpu_cleanstate_ready = 1;


More information about the freebsd-amd64 mailing list