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>