Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 25 Mar 2009 17:22:15 +0000 (UTC)
From:      John Baldwin <jhb@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-7@freebsd.org
Subject:   svn commit: r190418 - in stable/7/sys: . amd64/amd64 amd64/ia32 amd64/include amd64/linux32 compat/linux contrib/pf dev/ath/ath_hal dev/cxgb i386/i386 i386/include i386/isa i386/linux
Message-ID:  <200903251722.n2PHMFLg082656@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jhb
Date: Wed Mar 25 17:22:15 2009
New Revision: 190418
URL: http://svn.freebsd.org/changeset/base/190418

Log:
  Allow different ABIs to use different initial control words for the FPU on
  amd64 and i386.  This fixes a bug were 32-bit binaries would run with a
  different floating point exception mask under FreeBSD/amd64 vs FreeBSD/i386.
  This commit also includes a few other minor changes to keep the code in
  sync with 8.
  
  Approved by:	re (kib)

Modified:
  stable/7/sys/   (props changed)
  stable/7/sys/amd64/amd64/fpu.c
  stable/7/sys/amd64/amd64/machdep.c
  stable/7/sys/amd64/amd64/trap.c
  stable/7/sys/amd64/ia32/ia32_signal.c
  stable/7/sys/amd64/include/fpu.h
  stable/7/sys/amd64/include/pcb.h
  stable/7/sys/amd64/linux32/linux32_sysvec.c
  stable/7/sys/compat/linux/linux_misc.h
  stable/7/sys/contrib/pf/   (props changed)
  stable/7/sys/dev/ath/ath_hal/   (props changed)
  stable/7/sys/dev/cxgb/   (props changed)
  stable/7/sys/i386/i386/machdep.c
  stable/7/sys/i386/i386/mp_machdep.c
  stable/7/sys/i386/include/npx.h
  stable/7/sys/i386/include/pcb.h
  stable/7/sys/i386/isa/npx.c
  stable/7/sys/i386/linux/linux_sysvec.c

Modified: stable/7/sys/amd64/amd64/fpu.c
==============================================================================
--- stable/7/sys/amd64/amd64/fpu.c	Wed Mar 25 17:02:05 2009	(r190417)
+++ stable/7/sys/amd64/amd64/fpu.c	Wed Mar 25 17:22:15 2009	(r190418)
@@ -98,16 +98,15 @@ typedef u_char bool_t;
 
 static	void	fpu_clean_state(void);
 
-int	hw_float = 1;
-SYSCTL_INT(_hw,HW_FLOATINGPT, floatingpoint,
-	CTLFLAG_RD, &hw_float, 0, 
-	"Floatingpoint instructions executed in hardware");
+SYSCTL_INT(_hw, HW_FLOATINGPT, floatingpoint, CTLFLAG_RD,
+    NULL, 1, "Floating point instructions executed in hardware");
 
 static	struct savefpu		fpu_cleanstate;
-static	bool_t			fpu_cleanstate_ready;
 
 /*
- * Initialize floating point unit.
+ * Initialize the floating point unit.  On the boot CPU we generate a
+ * clean state that is used to initialize the floating point unit when
+ * it is first used by a process.
  */
 void
 fpuinit(void)
@@ -117,22 +116,22 @@ fpuinit(void)
 	u_short control;
 
 	savecrit = intr_disable();
-	PCPU_SET(fpcurthread, 0);
 	stop_emulating();
 	fninit();
 	control = __INITIAL_FPUCW__;
 	fldcw(&control);
 	mxcsr = __INITIAL_MXCSR__;
 	ldmxcsr(mxcsr);
-	fxsave(&fpu_cleanstate);
-	if (fpu_cleanstate.sv_env.en_mxcsr_mask)
-		cpu_mxcsr_mask = fpu_cleanstate.sv_env.en_mxcsr_mask;
-	else
-		cpu_mxcsr_mask = 0xFFBF;
+	if (PCPU_GET(cpuid) == 0) {
+		fxsave(&fpu_cleanstate);
+		if (fpu_cleanstate.sv_env.en_mxcsr_mask)
+			cpu_mxcsr_mask = fpu_cleanstate.sv_env.en_mxcsr_mask;
+		else
+			cpu_mxcsr_mask = 0xFFBF;
+		bzero(fpu_cleanstate.sv_fp, sizeof(fpu_cleanstate.sv_fp));
+		bzero(fpu_cleanstate.sv_xmm, sizeof(fpu_cleanstate.sv_xmm));
+	}
 	start_emulating();
-	bzero(fpu_cleanstate.sv_fp, sizeof(fpu_cleanstate.sv_fp));
-	bzero(fpu_cleanstate.sv_xmm, sizeof(fpu_cleanstate.sv_xmm));
-	fpu_cleanstate_ready = 1;
 	intr_restore(savecrit);
 }
 
@@ -386,8 +385,8 @@ fputrap()
 
 static int err_count = 0;
 
-int
-fpudna()
+void
+fpudna(void)
 {
 	struct pcb *pcb;
 	register_t s;
@@ -396,7 +395,7 @@ fpudna()
 		printf("fpudna: fpcurthread == curthread %d times\n",
 		    ++err_count);
 		stop_emulating();
-		return (1);
+		return;
 	}
 	if (PCPU_GET(fpcurthread) != NULL) {
 		printf("fpudna: fpcurthread = %p (%d), curthread = %p (%d)\n",
@@ -421,12 +420,12 @@ fpudna()
 		 * explicitly load sanitized registers.
 		 */
 		fxrstor(&fpu_cleanstate);
+		if (pcb->pcb_initial_fpucw != __INITIAL_FPUCW__)
+			fldcw(&pcb->pcb_initial_fpucw);
 		pcb->pcb_flags |= PCB_FPUINITDONE;
 	} else
 		fxrstor(&pcb->pcb_save);
 	intr_restore(s);
-
-	return (1);
 }
 
 /*
@@ -454,10 +453,8 @@ fpugetregs(struct thread *td, struct sav
 	register_t s;
 
 	if ((td->td_pcb->pcb_flags & PCB_FPUINITDONE) == 0) {
-		if (fpu_cleanstate_ready)
-			bcopy(&fpu_cleanstate, addr, sizeof(fpu_cleanstate));
-		else
-			bzero(addr, sizeof(*addr));
+		bcopy(&fpu_cleanstate, addr, sizeof(fpu_cleanstate));
+		addr->sv_env.en_cw = td->td_pcb->pcb_initial_fpucw;
 		return (_MC_FPOWNED_NONE);
 	}
 	s = intr_disable();

Modified: stable/7/sys/amd64/amd64/machdep.c
==============================================================================
--- stable/7/sys/amd64/amd64/machdep.c	Wed Mar 25 17:02:05 2009	(r190417)
+++ stable/7/sys/amd64/amd64/machdep.c	Wed Mar 25 17:22:15 2009	(r190418)
@@ -586,7 +586,7 @@ cpu_idle(void)
 void (*cpu_idle_hook)(void) = cpu_idle_default;
 
 /*
- * Clear registers on exec
+ * Reset registers to default values on exec.
  */
 void
 exec_setregs(td, entry, stack, ps_strings)
@@ -613,6 +613,7 @@ exec_setregs(td, entry, stack, ps_string
 	pcb->pcb_es = _udatasel;
 	pcb->pcb_fs = _udatasel;
 	pcb->pcb_gs = _udatasel;
+	pcb->pcb_initial_fpucw = __INITIAL_FPUCW__;
 
 	bzero((char *)regs, sizeof(struct trapframe));
 	regs->tf_rip = entry;

Modified: stable/7/sys/amd64/amd64/trap.c
==============================================================================
--- stable/7/sys/amd64/amd64/trap.c	Wed Mar 25 17:02:05 2009	(r190417)
+++ stable/7/sys/amd64/amd64/trap.c	Wed Mar 25 17:22:15 2009	(r190418)
@@ -421,13 +421,8 @@ trap(struct trapframe *frame)
 
 		case T_DNA:
 			/* transparent fault (due to context switch "late") */
-			if (fpudna())
-				goto userout;
-			printf("pid %d killed due to lack of floating point\n",
-				p->p_pid);
-			i = SIGKILL;
-			ucode = 0;
-			break;
+			fpudna();
+			goto userout;
 
 		case T_FPOPFLT:		/* FPU operand fetch fault */
 			ucode = ILL_COPROC;
@@ -455,11 +450,9 @@ trap(struct trapframe *frame)
 			 * XXX this should be fatal unless the kernel has
 			 * registered such use.
 			 */
-			if (fpudna()) {
-				printf("fpudna in kernel mode!\n");
-				goto out;
-			}
-			break;
+			fpudna();
+			printf("fpudna in kernel mode!\n");
+			goto out;
 
 		case T_STKFLT:		/* stack fault */
 			break;

Modified: stable/7/sys/amd64/ia32/ia32_signal.c
==============================================================================
--- stable/7/sys/amd64/ia32/ia32_signal.c	Wed Mar 25 17:02:05 2009	(r190417)
+++ stable/7/sys/amd64/ia32/ia32_signal.c	Wed Mar 25 17:22:15 2009	(r190418)
@@ -727,6 +727,7 @@ ia32_setregs(td, entry, stack, ps_string
 	pcb->pcb_es = _udatasel;
 	pcb->pcb_fs = _udatasel;
 	pcb->pcb_gs = _udatasel;
+	pcb->pcb_initial_fpucw = __INITIAL_FPUCW_I386__;
 
 	bzero((char *)regs, sizeof(struct trapframe));
 	regs->tf_rip = entry;

Modified: stable/7/sys/amd64/include/fpu.h
==============================================================================
--- stable/7/sys/amd64/include/fpu.h	Wed Mar 25 17:02:05 2009	(r190417)
+++ stable/7/sys/amd64/include/fpu.h	Wed Mar 25 17:22:15 2009	(r190418)
@@ -92,11 +92,12 @@ struct  savefpu {
  * SSE2 based math.  For FreeBSD/amd64, we go with the default settings.
  */
 #define	__INITIAL_FPUCW__	0x037F
+#define	__INITIAL_FPUCW_I386__	0x127F
 #define	__INITIAL_MXCSR__	0x1F80
 #define	__INITIAL_MXCSR_MASK__	0xFFBF
 
 #ifdef _KERNEL
-int	fpudna(void);
+void	fpudna(void);
 void	fpudrop(void);
 void	fpuexit(struct thread *td);
 int	fpuformat(void);

Modified: stable/7/sys/amd64/include/pcb.h
==============================================================================
--- stable/7/sys/amd64/include/pcb.h	Wed Mar 25 17:02:05 2009	(r190417)
+++ stable/7/sys/amd64/include/pcb.h	Wed Mar 25 17:22:15 2009	(r190418)
@@ -55,6 +55,13 @@ struct pcb {
 	register_t	pcb_rip;
 	register_t	pcb_fsbase;
 	register_t	pcb_gsbase;
+	u_long		pcb_flags;
+#define	PCB_DBREGS	0x02	/* process using debug registers */
+#define	PCB_FPUINITDONE	0x08	/* fpu state is initialized */
+#define	PCB_GS32BIT	0x20	/* linux gs switch */
+#define	PCB_32BIT	0x40	/* process has 32 bit context (segs etc) */
+#define	PCB_FULLCTX	0x80	/* full context restore on sysret */
+
 	u_int32_t	pcb_ds;
 	u_int32_t	pcb_es;
 	u_int32_t	pcb_fs;
@@ -67,12 +74,7 @@ struct pcb {
 	u_int64_t	pcb_dr7;
 
 	struct	savefpu	pcb_save;
-	u_long	pcb_flags;
-#define	PCB_DBREGS	0x02	/* process using debug registers */
-#define	PCB_FPUINITDONE	0x08	/* fpu state is initialized */
-#define	PCB_GS32BIT	0x20	/* linux gs switch */
-#define	PCB_32BIT	0x40	/* process has 32 bit context (segs etc) */
-#define	PCB_FULLCTX	0x80	/* full context restore on sysret */
+	uint16_t	pcb_initial_fpucw;
 
 	caddr_t	pcb_onfault;	/* copyin/out fault recovery */
 

Modified: stable/7/sys/amd64/linux32/linux32_sysvec.c
==============================================================================
--- stable/7/sys/amd64/linux32/linux32_sysvec.c	Wed Mar 25 17:02:05 2009	(r190417)
+++ stable/7/sys/amd64/linux32/linux32_sysvec.c	Wed Mar 25 17:22:15 2009	(r190418)
@@ -832,6 +832,7 @@ exec_linux_setregs(td, entry, stack, ps_
 	pcb->pcb_es = _udatasel;
 	pcb->pcb_fs = _udatasel;
 	pcb->pcb_gs = _udatasel;
+	pcb->pcb_initial_fpucw = __LINUX_NPXCW__;
 
 	bzero((char *)regs, sizeof(struct trapframe));
 	regs->tf_rip = entry;

Modified: stable/7/sys/compat/linux/linux_misc.h
==============================================================================
--- stable/7/sys/compat/linux/linux_misc.h	Wed Mar 25 17:02:05 2009	(r190417)
+++ stable/7/sys/compat/linux/linux_misc.h	Wed Mar 25 17:22:15 2009	(r190418)
@@ -45,4 +45,9 @@
 #define	LINUX_MREMAP_MAYMOVE	1
 #define	LINUX_MREMAP_FIXED	2
 
+/* Linux sets the i387 to extended precision. */
+#if defined(__i386__) || defined(__amd64__)
+#define	__LINUX_NPXCW__		0x37f
+#endif
+
 #endif	/* _LINUX_MISC_H_ */

Modified: stable/7/sys/i386/i386/machdep.c
==============================================================================
--- stable/7/sys/i386/i386/machdep.c	Wed Mar 25 17:02:05 2009	(r190417)
+++ stable/7/sys/i386/i386/machdep.c	Wed Mar 25 17:22:15 2009	(r190418)
@@ -1188,7 +1188,7 @@ cpu_idle(void)
 void (*cpu_idle_hook)(void) = cpu_idle_default;
 
 /*
- * Clear registers on exec
+ * Reset registers to default values on exec.
  */
 void
 exec_setregs(td, entry, stack, ps_strings)
@@ -1253,6 +1253,7 @@ exec_setregs(td, entry, stack, ps_string
 	 * emulators don't provide an entry point for initialization.
 	 */
 	td->td_pcb->pcb_flags &= ~FP_SOFTFP;
+	pcb->pcb_initial_npxcw = __INITIAL_NPXCW__;
 
 	/*
 	 * Drop the FP state if we hold it, so that the process gets a

Modified: stable/7/sys/i386/i386/mp_machdep.c
==============================================================================
--- stable/7/sys/i386/i386/mp_machdep.c	Wed Mar 25 17:02:05 2009	(r190417)
+++ stable/7/sys/i386/i386/mp_machdep.c	Wed Mar 25 17:22:15 2009	(r190418)
@@ -575,7 +575,7 @@ init_secondary(void)
 	cpu_setregs();
 
 	/* set up FPU state on the AP */
-	npxinit(__INITIAL_NPXCW__);
+	npxinit();
 
 	/* set up SSE registers */
 	enable_sse();

Modified: stable/7/sys/i386/include/npx.h
==============================================================================
--- stable/7/sys/i386/include/npx.h	Wed Mar 25 17:02:05 2009	(r190417)
+++ stable/7/sys/i386/include/npx.h	Wed Mar 25 17:22:15 2009	(r190418)
@@ -151,7 +151,7 @@ void	npxdrop(void);
 void	npxexit(struct thread *td);
 int	npxformat(void);
 int	npxgetregs(struct thread *td, union savefpu *addr);
-void	npxinit(u_short control);
+void	npxinit(void);
 void	npxsave(union savefpu *addr);
 void	npxsetregs(struct thread *td, union savefpu *addr);
 int	npxtrap(void);

Modified: stable/7/sys/i386/include/pcb.h
==============================================================================
--- stable/7/sys/i386/include/pcb.h	Wed Mar 25 17:02:05 2009	(r190417)
+++ stable/7/sys/i386/include/pcb.h	Wed Mar 25 17:22:15 2009	(r190418)
@@ -61,6 +61,7 @@ struct pcb {
 	int     pcb_dr7;
 
 	union	savefpu	pcb_save;
+	uint16_t pcb_initial_npxcw;
 	u_int	pcb_flags;
 #define	FP_SOFTFP	0x01	/* process using software fltng pnt emulator */
 #define	PCB_DBREGS	0x02	/* process using debug registers */

Modified: stable/7/sys/i386/isa/npx.c
==============================================================================
--- stable/7/sys/i386/isa/npx.c	Wed Mar 25 17:02:05 2009	(r190417)
+++ stable/7/sys/i386/isa/npx.c	Wed Mar 25 17:22:15 2009	(r190418)
@@ -132,11 +132,19 @@ void	stop_emulating(void);
 	(cpu_fxsr ? \
 		(thread)->td_pcb->pcb_save.sv_xmm.sv_env.en_sw : \
 		(thread)->td_pcb->pcb_save.sv_87.sv_env.en_sw)
+#define SET_FPU_CW(savefpu, value) do { \
+	if (cpu_fxsr) \
+		(savefpu)->sv_xmm.sv_env.en_cw = (value); \
+	else \
+		(savefpu)->sv_87.sv_env.en_cw = (value); \
+} while (0)
 #else /* CPU_ENABLE_SSE */
 #define GET_FPU_CW(thread) \
 	(thread->td_pcb->pcb_save.sv_87.sv_env.en_cw)
 #define GET_FPU_SW(thread) \
 	(thread->td_pcb->pcb_save.sv_87.sv_env.en_sw)
+#define SET_FPU_CW(savefpu, value) \
+	(savefpu)->sv_87.sv_env.en_cw = (value)
 #endif /* CPU_ENABLE_SSE */
 
 typedef u_char bool_t;
@@ -158,15 +166,13 @@ static	long	timezero(const char *funcnam
 
 int	hw_float;		/* XXX currently just alias for npx_exists */
 
-SYSCTL_INT(_hw,HW_FLOATINGPT, floatingpoint,
-	CTLFLAG_RD, &hw_float, 0, 
-	"Floatingpoint instructions executed in hardware");
+SYSCTL_INT(_hw, HW_FLOATINGPT, floatingpoint, CTLFLAG_RD,
+    &hw_float, 0, "Floating point instructions executed in hardware");
 
 static	volatile u_int		npx_intrs_while_probing;
 static	volatile u_int		npx_traps_while_probing;
 
 static	union savefpu		npx_cleanstate;
-static	bool_t			npx_cleanstate_ready;
 static	bool_t			npx_ex16;
 static	bool_t			npx_exists;
 static	bool_t			npx_irq13;
@@ -368,19 +374,14 @@ npx_probe(dev)
 				return (0);
 			}
 			/*
-			 * Worse, even IRQ13 is broken.  Use emulator.
+			 * Worse, even IRQ13 is broken.
 			 */
 		}
 	}
-	/*
-	 * Probe failed, but we want to get to npxattach to initialize the
-	 * emulator and say that it has been installed.  XXX handle devices
-	 * that aren't really devices better.
-	 */
-#ifdef SMP
-	if (mp_ncpus > 1)
-		panic("npx0 cannot be emulated on an SMP system");
-#endif
+
+	/* Probe failed.  Floating point simply won't work. */
+	device_printf(dev, "WARNING: no FPU!\n");
+
 	/* FALLTHROUGH */
 no_irq13:
 	idt[IDT_MF] = save_idt_npxtrap;
@@ -389,7 +390,7 @@ no_irq13:
 		bus_release_resource(dev, SYS_RES_IRQ, irq_rid, irq_res);
 	}
 	bus_release_resource(dev, SYS_RES_IOPORT, ioport_rid, ioport_res);
-	return (0);
+	return (npx_exists ? 0 : ENXIO);
 }
 
 /*
@@ -406,32 +407,34 @@ npx_attach(dev)
 
 	if (npx_irq13)
 		device_printf(dev, "IRQ 13 interface\n");
-	else if (!npx_ex16)
-		device_printf(dev, "WARNING: no FPU!\n");
 	else if (!device_is_quiet(dev) || bootverbose)
 		device_printf(dev, "INT 16 interface\n");
 
-	npxinit(__INITIAL_NPXCW__);
+	npxinit();
 
-	if (npx_cleanstate_ready == 0) {
-		s = intr_disable();
-		stop_emulating();
-		fpusave(&npx_cleanstate);
-		start_emulating();
+	s = intr_disable();
+	stop_emulating();
+	fpusave(&npx_cleanstate);
+	start_emulating();
 #ifdef CPU_ENABLE_SSE
-		if (cpu_fxsr) {
-			if (npx_cleanstate.sv_xmm.sv_env.en_mxcsr_mask)
-				cpu_mxcsr_mask = 
-			    	    npx_cleanstate.sv_xmm.sv_env.en_mxcsr_mask;
-			else
-				cpu_mxcsr_mask = 0xFFBF;
-		}
+	if (cpu_fxsr) {
+		if (npx_cleanstate.sv_xmm.sv_env.en_mxcsr_mask)
+			cpu_mxcsr_mask = 
+			    npx_cleanstate.sv_xmm.sv_env.en_mxcsr_mask;
+		else
+			cpu_mxcsr_mask = 0xFFBF;
+		bzero(npx_cleanstate.sv_xmm.sv_fp,
+		    sizeof(npx_cleanstate.sv_xmm.sv_fp));
+		bzero(npx_cleanstate.sv_xmm.sv_xmm,
+		    sizeof(npx_cleanstate.sv_xmm.sv_xmm));
+		/* XXX might need even more zeroing. */
+	} else
 #endif
-		npx_cleanstate_ready = 1;
-		intr_restore(s);
-	}
+		bzero(npx_cleanstate.sv_87.sv_ac,
+		    sizeof(npx_cleanstate.sv_87.sv_ac));
+	intr_restore(s);
 #ifdef I586_CPU_XXX
-	if (cpu_class == CPUCLASS_586 && npx_ex16 && npx_exists &&
+	if (cpu_class == CPUCLASS_586 && npx_ex16 &&
 	    timezero("i586_bzero()", i586_bzero) <
 	    timezero("bzero()", bzero) * 4 / 5) {
 		if (!(flags & NPX_DISABLE_I586_OPTIMIZED_BCOPY))
@@ -452,10 +455,11 @@ npx_attach(dev)
  * Initialize floating point unit.
  */
 void
-npxinit(u_short control)
+npxinit(void)
 {
 	static union savefpu dummy;
 	register_t savecrit;
+	u_short control;
 
 	if (!npx_exists)
 		return;
@@ -472,6 +476,7 @@ npxinit(u_short control)
 	if (cpu_fxsr)
 		fninit();
 #endif
+	control = __INITIAL_NPXCW__;
 	fldcw(&control);
 	start_emulating();
 	intr_restore(savecrit);
@@ -752,14 +757,10 @@ npxtrap()
 static int err_count = 0;
 
 int
-npxdna()
+npxdna(void)
 {
 	struct pcb *pcb;
 	register_t s;
-#ifdef CPU_ENABLE_SSE
-	int mxcsr;
-#endif
-	u_short control;
 
 	if (!npx_exists)
 		return (0);
@@ -788,22 +789,16 @@ npxdna()
 		/*
 		 * This is the first time this thread has used the FPU or
 		 * the PCB doesn't contain a clean FPU state.  Explicitly
-		 * initialize the FPU and load the default control word.
+		 * load sanitized registers.
 		 */
-		fninit();
-		control = __INITIAL_NPXCW__;
-		fldcw(&control);
-#ifdef CPU_ENABLE_SSE
-		if (cpu_fxsr) {
-			mxcsr = __INITIAL_MXCSR__;
-			ldmxcsr(mxcsr);
-		}
-#endif
+		fpurstor(&npx_cleanstate);
+		if (pcb->pcb_initial_npxcw != __INITIAL_NPXCW__)
+			fldcw(&pcb->pcb_initial_npxcw);
 		pcb->pcb_flags |= PCB_NPXINITDONE;
 	} else {
 		/*
-		 * The following frstor may cause an IRQ13 when the state
-		 * being restored has a pending error.  The error will
+		 * The following fpurstor() may cause an IRQ13 when the
+		 * state being restored has a pending error.  The error will
 		 * appear to have been triggered by the current (npx) user
 		 * instruction even when that instruction is a no-wait
 		 * instruction that should not trigger an error (e.g.,
@@ -896,10 +891,8 @@ npxgetregs(td, addr)
 		return (_MC_FPOWNED_NONE);
 
 	if ((td->td_pcb->pcb_flags & PCB_NPXINITDONE) == 0) {
-		if (npx_cleanstate_ready)
-			bcopy(&npx_cleanstate, addr, sizeof(npx_cleanstate));
-		else
-			bzero(addr, sizeof(*addr));
+		bcopy(&npx_cleanstate, addr, sizeof(npx_cleanstate));
+		SET_FPU_CW(addr, td->td_pcb->pcb_initial_npxcw);
 		return (_MC_FPOWNED_NONE);
 	}
 	s = intr_disable();

Modified: stable/7/sys/i386/linux/linux_sysvec.c
==============================================================================
--- stable/7/sys/i386/linux/linux_sysvec.c	Wed Mar 25 17:02:05 2009	(r190417)
+++ stable/7/sys/i386/linux/linux_sysvec.c	Wed Mar 25 17:22:15 2009	(r190418)
@@ -86,9 +86,6 @@ MALLOC_DEFINE(M_LINUX, "linux", "Linux m
 #define	LINUX_SYS_linux_rt_sendsig	0
 #define	LINUX_SYS_linux_sendsig		0
 
-#define	fldcw(addr)		__asm("fldcw %0" : : "m" (*(addr)))
-#define	__LINUX_NPXCW__		0x37f
-
 extern char linux_sigcode[];
 extern int linux_szsigcode;
 
@@ -800,16 +797,15 @@ static void
 exec_linux_setregs(struct thread *td, u_long entry,
 		   u_long stack, u_long ps_strings)
 {
-	static const u_short control = __LINUX_NPXCW__;
 	struct pcb *pcb = td->td_pcb;
 
 	exec_setregs(td, entry, stack, ps_strings);
 
 	/* Linux sets %gs to 0, we default to _udatasel */
-	pcb->pcb_gs = 0; load_gs(0);
+	pcb->pcb_gs = 0;
+	load_gs(0);
 
-	/* Linux sets the i387 to extended precision. */
-	fldcw(&control);
+	pcb->pcb_initial_npxcw = __LINUX_NPXCW__;
 }
 
 struct sysentvec linux_sysvec = {



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