Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 5 Mar 2009 18:32:43 +0000 (UTC)
From:      John Baldwin <jhb@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r189418 - in head/sys/i386: i386 include isa
Message-ID:  <200903051832.n25IWhNK096134@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jhb
Date: Thu Mar  5 18:32:43 2009
New Revision: 189418
URL: http://svn.freebsd.org/changeset/base/189418

Log:
  Some cleanups to the i386 FPU support:
  - Remove the control word parameter to npxinit().  It was always set
    to __INITIAL_NPXCW__.
  - Remove npx_cleanstate_ready as the cleanstate is always initalized
    when it is used.
  - Improve the handling of the case when the FPU isn't present.  Now
    the npx0 device no longer succeeds in its probe so all of npx_attach()
    is skipped.  Also, we allow this case with SMP (though that shouldn't
    actually occur as all i386 systems that support SMP have FPUs) now.
    SMP was only an issue back when we had an FPU emulator which was not
    per-CPU.
  - MFamd64: Clear some of the state in npx_cleanstate rather than leaving
    it as garbage.
  - MFamd64: When a user thread first uses the FPU, use npx_cleanstate for
    the initial FPU state.
  
  Reviewed by:	bde

Modified:
  head/sys/i386/i386/mp_machdep.c
  head/sys/i386/include/npx.h
  head/sys/i386/isa/npx.c

Modified: head/sys/i386/i386/mp_machdep.c
==============================================================================
--- head/sys/i386/i386/mp_machdep.c	Thu Mar  5 18:30:50 2009	(r189417)
+++ head/sys/i386/i386/mp_machdep.c	Thu Mar  5 18:32:43 2009	(r189418)
@@ -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: head/sys/i386/include/npx.h
==============================================================================
--- head/sys/i386/include/npx.h	Thu Mar  5 18:30:50 2009	(r189417)
+++ head/sys/i386/include/npx.h	Thu Mar  5 18:32:43 2009	(r189418)
@@ -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: head/sys/i386/isa/npx.c
==============================================================================
--- head/sys/i386/isa/npx.c	Thu Mar  5 18:30:50 2009	(r189417)
+++ head/sys/i386/isa/npx.c	Thu Mar  5 18:32:43 2009	(r189418)
@@ -174,7 +174,6 @@ static	volatile u_int		npx_intrs_while_p
 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;
@@ -376,19 +375,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;
@@ -397,7 +391,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);
 }
 
 /*
@@ -414,32 +408,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))
@@ -460,10 +456,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;
@@ -480,6 +477,7 @@ npxinit(u_short control)
 	if (cpu_fxsr)
 		fninit();
 #endif
+	control = __INITIAL_NPXCW__;
 	fldcw(&control);
 	start_emulating();
 	intr_restore(savecrit);
@@ -760,14 +758,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);
@@ -796,17 +790,9 @@ 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);
 		pcb->pcb_flags |= PCB_NPXINITDONE;
 	} else {
 		/*
@@ -904,10 +890,7 @@ 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));
 		return (_MC_FPOWNED_NONE);
 	}
 	s = intr_disable();



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