cvs commit: src/sys/i386/isa npx.c

David Xu davidxu at freebsd.org
Sun May 28 05:06:55 PDT 2006


On Sunday 28 May 2006 19:15, Bruce Evans wrote:

> Starting with a clean FP state like the old code does is safest, but POSIX
> explicitly requires copying the environment, and bugs in the new code
> result in half of the most dangerous part of the environment (the SSE
> half of the exception flags) being copied anyway.
>
> Pending exceptions are not the only problem here.  Pending exceptions
> are an i387 thing.  Most exceptions are non-pending ones for IEEE inexact.
>
> Bruce

how about following patch ?

Index: npx.c
===================================================================
RCS file: /home/ncvs/src/sys/i386/isa/npx.c,v
retrieving revision 1.168
diff -u -u -r1.168 npx.c
--- npx.c	28 May 2006 04:40:45 -0000	1.168
+++ npx.c	28 May 2006 11:40:58 -0000
@@ -99,6 +99,7 @@
 #define	fxrstor(addr)		__asm("fxrstor %0" : : "m" (*(addr)))
 #define	fxsave(addr)		__asm __volatile("fxsave %0" : "=m" (*(addr)))
 #define	ldmxcsr(__csr)		__asm __volatile("ldmxcsr %0" : : "m" (__csr))
+#define	stmxcsr(addr)		__asm __volatile("stmxcsr %0" : "=m" (*(addr)))
 #endif
 #define	start_emulating()	__asm("smsw %%ax; orb %0,%%al; lmsw %%ax" \
 				      : : "n" (CR0_TS) : "ax")
@@ -950,7 +951,8 @@
 {
 	union savefpu	*state;
 	u_int32_t	mxcsr;
-	u_int32_t	cw;
+	u_int16_t	cw;
+	register_t	s;
 
 	if (!(td->td_pcb->pcb_flags & PCB_NPXINITDONE)) {
 		newtd->td_pcb->pcb_flags &= ~PCB_NPXINITDONE;
@@ -958,21 +960,40 @@
 	}
 		
 	state = &newtd->td_pcb->pcb_save;
-	/* get control word */
-	if (npxgetregs(td, state))
-		return;
-	if (cpu_fxsr) {
-		mxcsr = state->sv_xmm.sv_env.en_mxcsr;
-		cw = state->sv_xmm.sv_env.en_cw;
+	s = intr_disable();
+	if (curthread == PCPU_GET(fpcurthread)) {
+#ifdef CPU_ENABLE_SSE
+		if (cpu_fxsr) {
+			stmxcsr(&mxcsr);
+			fnstcw(&cw);
+		}
+		else
+#endif
+		{
+			mxcsr = 0;
+			fnstcw(&cw);
+		}
 	} else {
-		cw = state->sv_87.sv_env.en_cw;
-		mxcsr = 0;
+#ifdef CPU_ENABLE_SSE
+		if (cpu_fxsr) {
+			mxcsr = td->td_pcb->pcb_save.sv_xmm.sv_env.en_mxcsr;
+			cw = td->td_pcb->pcb_save.sv_87.sv_env.en_cw;
+		}
+		else
+#endif
+		{
+			mxcsr = 0;
+			cw = td->td_pcb->pcb_save.sv_87.sv_env.en_cw;
+		}
 	}
+	intr_restore(s);
 	bcopy(&npx_cleanstate, state, sizeof(*state));
+#ifdef CPU_ENABLE_SSE
 	if (cpu_fxsr) {
 		state->sv_xmm.sv_env.en_cw = cw;
-		state->sv_xmm.sv_env.en_mxcsr = mxcsr;
+		state->sv_xmm.sv_env.en_mxcsr = mxcsr & ~0x3F;
 	} else
+#endif
 		state->sv_87.sv_env.en_cw = cw;
 	newtd->td_pcb->pcb_flags |= PCB_NPXINITDONE;
 }


More information about the cvs-src mailing list