The great s/npx/fpu/gi

This commit is contained in:
Peter Wemm 2003-11-08 03:33:38 +00:00
parent d0ff2e64ac
commit bf2f09ee97
12 changed files with 128 additions and 183 deletions

View File

@ -131,7 +131,7 @@ ENTRY(cpu_switch)
pushq %rsi pushq %rsi
addq $PCB_SAVEFPU,%r8 /* h/w bugs make saving complicated */ addq $PCB_SAVEFPU,%r8 /* h/w bugs make saving complicated */
movq %r8, %rdi movq %r8, %rdi
call npxsave /* do it in a big C function */ call fpusave /* do it in a big C function */
popq %rsi popq %rsi
popq %rdi popq %rdi
1: 1:
@ -301,16 +301,16 @@ ENTRY(savectx)
popq PCB_RFLAGS(%rcx) popq PCB_RFLAGS(%rcx)
/* /*
* If fpcurthread == NULL, then the npx h/w state is irrelevant and the * If fpcurthread == NULL, then the fpu h/w state is irrelevant and the
* state had better already be in the pcb. This is true for forks * state had better already be in the pcb. This is true for forks
* but not for dumps (the old book-keeping with FP flags in the pcb * but not for dumps (the old book-keeping with FP flags in the pcb
* always lost for dumps because the dump pcb has 0 flags). * always lost for dumps because the dump pcb has 0 flags).
* *
* If fpcurthread != NULL, then we have to save the npx h/w state to * If fpcurthread != NULL, then we have to save the fpu h/w state to
* fpcurthread's pcb and copy it to the requested pcb, or save to the * fpcurthread's pcb and copy it to the requested pcb, or save to the
* requested pcb and reload. Copying is easier because we would * requested pcb and reload. Copying is easier because we would
* have to handle h/w bugs for reloading. We used to lose the * have to handle h/w bugs for reloading. We used to lose the
* parent's npx state for forks by forgetting to reload. * parent's fpu state for forks by forgetting to reload.
*/ */
pushfq pushfq
cli cli
@ -322,7 +322,7 @@ ENTRY(savectx)
pushq %rax pushq %rax
movq TD_PCB(%rax),%rdi movq TD_PCB(%rax),%rdi
leaq PCB_SAVEFPU(%rdi),%rdi leaq PCB_SAVEFPU(%rdi),%rdi
call npxsave call fpusave
popq %rax popq %rax
popq %rcx popq %rcx

View File

@ -37,7 +37,6 @@
#include <sys/cdefs.h> #include <sys/cdefs.h>
__FBSDID("$FreeBSD$"); __FBSDID("$FreeBSD$");
#include "opt_debug_npx.h"
#include "opt_isa.h" #include "opt_isa.h"
#include <sys/param.h> #include <sys/param.h>
@ -53,9 +52,6 @@ __FBSDID("$FreeBSD$");
#include <sys/sysctl.h> #include <sys/sysctl.h>
#include <machine/bus.h> #include <machine/bus.h>
#include <sys/rman.h> #include <sys/rman.h>
#ifdef NPX_DEBUG
#include <sys/syslog.h>
#endif
#include <sys/signalvar.h> #include <sys/signalvar.h>
#include <sys/user.h> #include <sys/user.h>
@ -75,7 +71,7 @@ __FBSDID("$FreeBSD$");
#endif #endif
/* /*
* 387 and 287 Numeric Coprocessor Extension (NPX) Driver. * Floating point support.
*/ */
#if defined(__GNUC__) && !defined(lint) #if defined(__GNUC__) && !defined(lint)
@ -110,59 +106,50 @@ void stop_emulating(void);
typedef u_char bool_t; typedef u_char bool_t;
static int npx_attach(device_t dev); static int fpu_attach(device_t dev);
static void npx_identify(driver_t *driver, device_t parent); static void fpu_identify(driver_t *driver, device_t parent);
static int npx_probe(device_t dev); static int fpu_probe(device_t dev);
int hw_float = 1; int hw_float = 1;
SYSCTL_INT(_hw,HW_FLOATINGPT, floatingpoint, SYSCTL_INT(_hw,HW_FLOATINGPT, floatingpoint,
CTLFLAG_RD, &hw_float, 0, CTLFLAG_RD, &hw_float, 0,
"Floatingpoint instructions executed in hardware"); "Floatingpoint instructions executed in hardware");
static struct savefpu npx_cleanstate; static struct savefpu fpu_cleanstate;
static bool_t npx_cleanstate_ready; static bool_t fpu_cleanstate_ready;
/* /*
* Identify routine. Create a connection point on our parent for probing. * Identify routine. Create a connection point on our parent for probing.
*/ */
static void static void
npx_identify(driver, parent) fpu_identify(driver_t *driver, device_t parent)
driver_t *driver;
device_t parent;
{ {
device_t child; device_t child;
child = BUS_ADD_CHILD(parent, 0, "npx", 0); child = BUS_ADD_CHILD(parent, 0, "fpu", 0);
if (child == NULL) if (child == NULL)
panic("npx_identify"); panic("fpu_identify");
} }
/* /*
* Probe routine. Initialize cr0 to give correct behaviour for [f]wait * Probe routine. Initialize cr0 to give correct behaviour for [f]wait
* whether the device exists or not (XXX should be elsewhere). * whether the device exists or not (XXX should be elsewhere).
* Modify device struct if npx doesn't need to use interrupts. * Modify device struct if fpu doesn't need to use interrupts.
* Return 0 if device exists. * Return 0 if device exists.
*/ */
static int static int
npx_probe(dev) fpu_probe(device_t dev)
device_t dev;
{ {
/* /*
* Partially reset the coprocessor, if any. Some BIOS's don't reset * Prepare to trap all ESC (i.e., FPU) instructions and all WAIT
* it after a warm boot.
*/
outb(0xf1, 0); /* full reset on some systems, NOP on others */
outb(0xf0, 0); /* clear BUSY# latch */
/*
* Prepare to trap all ESC (i.e., NPX) instructions and all WAIT
* instructions. We must set the CR0_MP bit and use the CR0_TS * instructions. We must set the CR0_MP bit and use the CR0_TS
* bit to control the trap, because setting the CR0_EM bit does * bit to control the trap, because setting the CR0_EM bit does
* not cause WAIT instructions to trap. It's important to trap * not cause WAIT instructions to trap. It's important to trap
* WAIT instructions - otherwise the "wait" variants of no-wait * WAIT instructions - otherwise the "wait" variants of no-wait
* control instructions would degenerate to the "no-wait" variants * control instructions would degenerate to the "no-wait" variants
* after FP context switches but work correctly otherwise. It's * after FP context switches but work correctly otherwise. It's
* particularly important to trap WAITs when there is no NPX - * particularly important to trap WAITs when there is no FPU -
* otherwise the "wait" variants would always degenerate. * otherwise the "wait" variants would always degenerate.
* *
* Try setting CR0_NE to get correct error reporting on 486DX's. * Try setting CR0_NE to get correct error reporting on 486DX's.
@ -179,6 +166,7 @@ npx_probe(dev)
fninit(); fninit();
device_set_desc(dev, "math processor"); device_set_desc(dev, "math processor");
device_quiet(dev);
return (0); return (0);
} }
@ -187,19 +175,18 @@ npx_probe(dev)
* Attach routine - announce which it is, and wire into system * Attach routine - announce which it is, and wire into system
*/ */
static int static int
npx_attach(dev) fpu_attach(device_t dev)
device_t dev;
{ {
register_t s; register_t s;
npxinit(__INITIAL_NPXCW__); fpuinit(__INITIAL_FPUCW__);
if (npx_cleanstate_ready == 0) { if (fpu_cleanstate_ready == 0) {
s = intr_disable(); s = intr_disable();
stop_emulating(); stop_emulating();
fxsave(&npx_cleanstate); fxsave(&fpu_cleanstate);
start_emulating(); start_emulating();
npx_cleanstate_ready = 1; fpu_cleanstate_ready = 1;
intr_restore(s); intr_restore(s);
} }
return (0); /* XXX unused */ return (0); /* XXX unused */
@ -209,21 +196,20 @@ npx_attach(dev)
* Initialize floating point unit. * Initialize floating point unit.
*/ */
void void
npxinit(control) fpuinit(u_short control)
u_short control;
{ {
static struct savefpu dummy; static struct savefpu dummy;
register_t savecrit; register_t savecrit;
/* /*
* fninit has the same h/w bugs as fnsave. Use the detoxified * fninit has the same h/w bugs as fnsave. Use the detoxified
* fnsave to throw away any junk in the fpu. npxsave() initializes * fnsave to throw away any junk in the fpu. fpusave() initializes
* the fpu and sets fpcurthread = NULL as important side effects. * the fpu and sets fpcurthread = NULL as important side effects.
*/ */
savecrit = intr_disable(); savecrit = intr_disable();
npxsave(&dummy); fpusave(&dummy);
stop_emulating(); stop_emulating();
/* XXX npxsave() doesn't actually initialize the fpu in the SSE case. */ /* XXX fpusave() doesn't actually initialize the fpu in the SSE case. */
fninit(); fninit();
fldcw(&control); fldcw(&control);
start_emulating(); start_emulating();
@ -234,34 +220,18 @@ npxinit(control)
* Free coprocessor (if we have it). * Free coprocessor (if we have it).
*/ */
void void
npxexit(td) fpuexit(struct thread *td)
struct thread *td;
{ {
#ifdef NPX_DEBUG
u_int masked_exceptions;
#endif
register_t savecrit; register_t savecrit;
savecrit = intr_disable(); savecrit = intr_disable();
if (curthread == PCPU_GET(fpcurthread)) if (curthread == PCPU_GET(fpcurthread))
npxsave(&PCPU_GET(curpcb)->pcb_save); fpusave(&PCPU_GET(curpcb)->pcb_save);
intr_restore(savecrit); intr_restore(savecrit);
#ifdef NPX_DEBUG
masked_exceptions = GET_FPU_CW(td) & GET_FPU_SW(td) & 0x7f;
/*
* Log exceptions that would have trapped with the old
* control word (overflow, divide by 0, and invalid operand).
*/
if (masked_exceptions & 0x0d)
log(LOG_ERR,
"pid %d (%s) exited with masked floating point exceptions 0x%02x\n",
td->td_proc->p_pid, td->td_proc->p_comm,
masked_exceptions);
#endif
} }
int int
npxformat() fpuformat()
{ {
return (_MC_FPFMT_XMM); return (_MC_FPFMT_XMM);
@ -456,7 +426,7 @@ static char fpetable[128] = {
* solution for signals other than SIGFPE. * solution for signals other than SIGFPE.
*/ */
int int
npxtrap() fputrap()
{ {
register_t savecrit; register_t savecrit;
u_short control, status; u_short control, status;
@ -493,48 +463,48 @@ npxtrap()
static int err_count = 0; static int err_count = 0;
int int
npxdna() fpudna()
{ {
struct pcb *pcb; struct pcb *pcb;
register_t s; register_t s;
u_short control; u_short control;
if (PCPU_GET(fpcurthread) == curthread) { if (PCPU_GET(fpcurthread) == curthread) {
printf("npxdna: fpcurthread == curthread %d times\n", printf("fpudna: fpcurthread == curthread %d times\n",
++err_count); ++err_count);
stop_emulating(); stop_emulating();
return (1); return (1);
} }
if (PCPU_GET(fpcurthread) != NULL) { if (PCPU_GET(fpcurthread) != NULL) {
printf("npxdna: fpcurthread = %p (%d), curthread = %p (%d)\n", printf("fpudna: fpcurthread = %p (%d), curthread = %p (%d)\n",
PCPU_GET(fpcurthread), PCPU_GET(fpcurthread),
PCPU_GET(fpcurthread)->td_proc->p_pid, PCPU_GET(fpcurthread)->td_proc->p_pid,
curthread, curthread->td_proc->p_pid); curthread, curthread->td_proc->p_pid);
panic("npxdna"); panic("fpudna");
} }
s = intr_disable(); s = intr_disable();
stop_emulating(); stop_emulating();
/* /*
* Record new context early in case frstor causes an IRQ13. * Record new context early in case frstor causes a trap.
*/ */
PCPU_SET(fpcurthread, curthread); PCPU_SET(fpcurthread, curthread);
pcb = PCPU_GET(curpcb); pcb = PCPU_GET(curpcb);
if ((pcb->pcb_flags & PCB_NPXINITDONE) == 0) { if ((pcb->pcb_flags & PCB_FPUINITDONE) == 0) {
/* /*
* This is the first time this thread has used the FPU or * This is the first time this thread has used the FPU or
* the PCB doesn't contain a clean FPU state. Explicitly * the PCB doesn't contain a clean FPU state. Explicitly
* initialize the FPU and load the default control word. * initialize the FPU and load the default control word.
*/ */
fninit(); fninit();
control = __INITIAL_NPXCW__; control = __INITIAL_FPUCW__;
fldcw(&control); fldcw(&control);
pcb->pcb_flags |= PCB_NPXINITDONE; pcb->pcb_flags |= PCB_FPUINITDONE;
} else { } else {
/* /*
* The following frstor may cause a trap when the state * The following frstor may cause a trap when the state
* being restored has a pending error. The error will * being restored has a pending error. The error will
* appear to have been triggered by the current (npx) user * appear to have been triggered by the current (fpu) user
* instruction even when that instruction is a no-wait * instruction even when that instruction is a no-wait
* instruction that should not trigger an error (e.g., * instruction that should not trigger an error (e.g.,
* instructions are broken the same as frstor, so our * instructions are broken the same as frstor, so our
@ -548,36 +518,19 @@ npxdna()
} }
/* /*
* Wrapper for fnsave instruction, partly to handle hardware bugs. When npx * Wrapper for fnsave instruction.
* exceptions are reported via IRQ13, spurious IRQ13's may be triggered by
* no-wait npx instructions. See the Intel application note AP-578 for
* details. This doesn't cause any additional complications here. IRQ13's
* are inherently asynchronous unless the CPU is frozen to deliver them --
* one that started in userland may be delivered many instructions later,
* after the process has entered the kernel. It may even be delivered after
* the fnsave here completes. A spurious IRQ13 for the fnsave is handled in
* the same way as a very-late-arriving non-spurious IRQ13 from user mode:
* it is normally ignored at first because we set fpcurthread to NULL; it is
* normally retriggered in npxdna() after return to user mode.
* *
* npxsave() must be called with interrupts disabled, so that it clears * fpusave() must be called with interrupts disabled, so that it clears
* fpcurthread atomically with saving the state. We require callers to do the * fpcurthread atomically with saving the state. We require callers to do the
* disabling, since most callers need to disable interrupts anyway to call * disabling, since most callers need to disable interrupts anyway to call
* npxsave() atomically with checking fpcurthread. * fpusave() atomically with checking fpcurthread.
*
* A previous version of npxsave() went to great lengths to excecute fnsave
* with interrupts enabled in case executing it froze the CPU. This case
* can't happen, at least for Intel CPU/NPX's. Spurious IRQ13's don't imply
* spurious freezes.
*/ */
void void
npxsave(addr) fpusave(struct savefpu *addr)
struct savefpu *addr;
{ {
stop_emulating(); stop_emulating();
fxsave(addr); fxsave(addr);
start_emulating(); start_emulating();
PCPU_SET(fpcurthread, NULL); PCPU_SET(fpcurthread, NULL);
} }
@ -587,13 +540,13 @@ npxsave(addr)
* FPU thread is non-null. * FPU thread is non-null.
*/ */
void void
npxdrop() fpudrop()
{ {
struct thread *td; struct thread *td;
td = PCPU_GET(fpcurthread); td = PCPU_GET(fpcurthread);
PCPU_SET(fpcurthread, NULL); PCPU_SET(fpcurthread, NULL);
td->td_pcb->pcb_flags &= ~PCB_NPXINITDONE; td->td_pcb->pcb_flags &= ~PCB_FPUINITDONE;
start_emulating(); start_emulating();
} }
@ -602,15 +555,13 @@ npxdrop()
* It returns the FPU ownership status. * It returns the FPU ownership status.
*/ */
int int
npxgetregs(td, addr) fpugetregs(struct thread *td, struct savefpu *addr)
struct thread *td;
struct savefpu *addr;
{ {
register_t s; register_t s;
if ((td->td_pcb->pcb_flags & PCB_NPXINITDONE) == 0) { if ((td->td_pcb->pcb_flags & PCB_FPUINITDONE) == 0) {
if (npx_cleanstate_ready) if (fpu_cleanstate_ready)
bcopy(&npx_cleanstate, addr, sizeof(npx_cleanstate)); bcopy(&fpu_cleanstate, addr, sizeof(fpu_cleanstate));
else else
bzero(addr, sizeof(*addr)); bzero(addr, sizeof(*addr));
return (_MC_FPOWNED_NONE); return (_MC_FPOWNED_NONE);
@ -631,9 +582,7 @@ npxgetregs(td, addr)
* Set the state of the FPU. * Set the state of the FPU.
*/ */
void void
npxsetregs(td, addr) fpusetregs(struct thread *td, struct savefpu *addr)
struct thread *td;
struct savefpu *addr;
{ {
register_t s; register_t s;
@ -645,14 +594,14 @@ npxsetregs(td, addr)
intr_restore(s); intr_restore(s);
bcopy(addr, &td->td_pcb->pcb_save, sizeof(*addr)); bcopy(addr, &td->td_pcb->pcb_save, sizeof(*addr));
} }
curthread->td_pcb->pcb_flags |= PCB_NPXINITDONE; curthread->td_pcb->pcb_flags |= PCB_FPUINITDONE;
} }
static device_method_t npx_methods[] = { static device_method_t fpu_methods[] = {
/* Device interface */ /* Device interface */
DEVMETHOD(device_identify, npx_identify), DEVMETHOD(device_identify, fpu_identify),
DEVMETHOD(device_probe, npx_probe), DEVMETHOD(device_probe, fpu_probe),
DEVMETHOD(device_attach, npx_attach), DEVMETHOD(device_attach, fpu_attach),
DEVMETHOD(device_detach, bus_generic_detach), DEVMETHOD(device_detach, bus_generic_detach),
DEVMETHOD(device_shutdown, bus_generic_shutdown), DEVMETHOD(device_shutdown, bus_generic_shutdown),
DEVMETHOD(device_suspend, bus_generic_suspend), DEVMETHOD(device_suspend, bus_generic_suspend),
@ -661,49 +610,51 @@ static device_method_t npx_methods[] = {
{ 0, 0 } { 0, 0 }
}; };
static driver_t npx_driver = { static driver_t fpu_driver = {
"npx", "fpu",
npx_methods, fpu_methods,
1, /* no softc */ 1, /* no softc */
}; };
static devclass_t npx_devclass; static devclass_t fpu_devclass;
/* /*
* We prefer to attach to the root nexus so that the usual case (exception 16) * We prefer to attach to the root nexus so that the usual case (exception 16)
* doesn't describe the processor as being `on isa'. * doesn't describe the processor as being `on isa'.
*/ */
DRIVER_MODULE(npx, nexus, npx_driver, npx_devclass, 0, 0); DRIVER_MODULE(fpu, nexus, fpu_driver, fpu_devclass, 0, 0);
#ifdef DEV_ISA #ifdef DEV_ISA
/* /*
* This sucks up the legacy ISA support assignments from PNPBIOS/ACPI. * This sucks up the legacy ISA support assignments from PNPBIOS/ACPI.
*/ */
static struct isa_pnp_id npxisa_ids[] = { static struct isa_pnp_id fpuisa_ids[] = {
{ 0x040cd041, "Legacy ISA coprocessor support" }, /* PNP0C04 */ { 0x040cd041, "Legacy ISA coprocessor support" }, /* PNP0C04 */
{ 0 } { 0 }
}; };
static int static int
npxisa_probe(device_t dev) fpuisa_probe(device_t dev)
{ {
int result; int result;
if ((result = ISA_PNP_PROBE(device_get_parent(dev), dev, npxisa_ids)) <= 0) {
result = ISA_PNP_PROBE(device_get_parent(dev), dev, fpuisa_ids);
if (result <= 0)
device_quiet(dev); device_quiet(dev);
} return (result);
return(result);
} }
static int static int
npxisa_attach(device_t dev) fpuisa_attach(device_t dev)
{ {
return (0); return (0);
} }
static device_method_t npxisa_methods[] = { static device_method_t fpuisa_methods[] = {
/* Device interface */ /* Device interface */
DEVMETHOD(device_probe, npxisa_probe), DEVMETHOD(device_probe, fpuisa_probe),
DEVMETHOD(device_attach, npxisa_attach), DEVMETHOD(device_attach, fpuisa_attach),
DEVMETHOD(device_detach, bus_generic_detach), DEVMETHOD(device_detach, bus_generic_detach),
DEVMETHOD(device_shutdown, bus_generic_shutdown), DEVMETHOD(device_shutdown, bus_generic_shutdown),
DEVMETHOD(device_suspend, bus_generic_suspend), DEVMETHOD(device_suspend, bus_generic_suspend),
@ -712,14 +663,14 @@ static device_method_t npxisa_methods[] = {
{ 0, 0 } { 0, 0 }
}; };
static driver_t npxisa_driver = { static driver_t fpuisa_driver = {
"npxisa", "fpuisa",
npxisa_methods, fpuisa_methods,
1, /* no softc */ 1, /* no softc */
}; };
static devclass_t npxisa_devclass; static devclass_t fpuisa_devclass;
DRIVER_MODULE(npxisa, isa, npxisa_driver, npxisa_devclass, 0, 0); DRIVER_MODULE(fpuisa, isa, fpuisa_driver, fpuisa_devclass, 0, 0);
DRIVER_MODULE(npxisa, acpi, npxisa_driver, npxisa_devclass, 0, 0); DRIVER_MODULE(fpuisa, acpi, fpuisa_driver, fpuisa_devclass, 0, 0);
#endif /* DEV_ISA */ #endif /* DEV_ISA */

View File

@ -516,7 +516,6 @@ exec_setregs(td, entry, stack, ps_strings)
bzero((char *)regs, sizeof(struct trapframe)); bzero((char *)regs, sizeof(struct trapframe));
regs->tf_rip = entry; regs->tf_rip = entry;
/* This strangeness is to ensure alignment after the implied return address */
regs->tf_rsp = ((stack - 8) & ~0xF) + 8; regs->tf_rsp = ((stack - 8) & ~0xF) + 8;
regs->tf_rdi = stack; /* argv */ regs->tf_rdi = stack; /* argv */
regs->tf_rflags = PSL_USER | (regs->tf_rflags & PSL_T); regs->tf_rflags = PSL_USER | (regs->tf_rflags & PSL_T);
@ -524,20 +523,20 @@ exec_setregs(td, entry, stack, ps_strings)
regs->tf_cs = _ucodesel; regs->tf_cs = _ucodesel;
/* /*
* Arrange to trap the next npx or `fwait' instruction (see npx.c * Arrange to trap the next fpu or `fwait' instruction (see fpu.c
* for why fwait must be trapped at least if there is an npx or an * for why fwait must be trapped at least if there is an fpu or an
* emulator). This is mainly to handle the case where npx0 is not * emulator). This is mainly to handle the case where npx0 is not
* configured, since the npx routines normally set up the trap * configured, since the fpu routines normally set up the trap
* otherwise. It should be done only at boot time, but doing it * otherwise. It should be done only at boot time, but doing it
* here allows modifying `npx_exists' for testing the emulator on * here allows modifying `fpu_exists' for testing the emulator on
* systems with an npx. * systems with an fpu.
*/ */
load_cr0(rcr0() | CR0_MP | CR0_TS); load_cr0(rcr0() | CR0_MP | CR0_TS);
/* Initialize the npx (if any) for the current process. */ /* Initialize the fpu (if any) for the current process. */
/* /*
* XXX the above load_cr0() also initializes it and is a layering * XXX the above load_cr0() also initializes it and is a layering
* violation if NPX is configured. It drops the npx partially * violation. It drops the fpu state partially
* and this would be fatal if we were interrupted now, and decided * and this would be fatal if we were interrupted now, and decided
* to force the state to the pcb, and checked the invariant * to force the state to the pcb, and checked the invariant
* (CR0_TS clear) if and only if PCPU_GET(fpcurthread) != NULL). * (CR0_TS clear) if and only if PCPU_GET(fpcurthread) != NULL).
@ -555,7 +554,7 @@ cpu_setregs(void)
register_t cr0; register_t cr0;
cr0 = rcr0(); cr0 = rcr0();
cr0 |= CR0_NE; /* Done by npxinit() */ cr0 |= CR0_NE; /* Done by fpuinit() */
cr0 |= CR0_MP | CR0_TS; /* Done at every execve() too. */ cr0 |= CR0_MP | CR0_TS; /* Done at every execve() too. */
cr0 |= CR0_WP | CR0_AM; cr0 |= CR0_WP | CR0_AM;
load_cr0(cr0); load_cr0(cr0);
@ -1525,8 +1524,8 @@ static void
get_fpcontext(struct thread *td, mcontext_t *mcp) get_fpcontext(struct thread *td, mcontext_t *mcp)
{ {
mcp->mc_ownedfp = npxgetregs(td, (struct savefpu *)&mcp->mc_fpstate); mcp->mc_ownedfp = fpugetregs(td, (struct savefpu *)&mcp->mc_fpstate);
mcp->mc_fpformat = npxformat(); mcp->mc_fpformat = fpuformat();
} }
static int static int
@ -1543,11 +1542,11 @@ set_fpcontext(struct thread *td, const mcontext_t *mcp)
else if (mcp->mc_ownedfp == _MC_FPOWNED_FPU || else if (mcp->mc_ownedfp == _MC_FPOWNED_FPU ||
mcp->mc_ownedfp == _MC_FPOWNED_PCB) { mcp->mc_ownedfp == _MC_FPOWNED_PCB) {
/* /*
* XXX we violate the dubious requirement that npxsetregs() * XXX we violate the dubious requirement that fpusetregs()
* be called with interrupts disabled. * be called with interrupts disabled.
* XXX obsolete on trap-16 systems? * XXX obsolete on trap-16 systems?
*/ */
npxsetregs(td, (struct savefpu *)&mcp->mc_fpstate); fpusetregs(td, (struct savefpu *)&mcp->mc_fpstate);
} else } else
return (EINVAL); return (EINVAL);
return (0); return (0);
@ -1560,18 +1559,18 @@ fpstate_drop(struct thread *td)
s = intr_disable(); s = intr_disable();
if (PCPU_GET(fpcurthread) == td) if (PCPU_GET(fpcurthread) == td)
npxdrop(); fpudrop();
/* /*
* XXX force a full drop of the npx. The above only drops it if we * XXX force a full drop of the fpu. The above only drops it if we
* owned it. * owned it.
* *
* XXX I don't much like npxgetregs()'s semantics of doing a full * XXX I don't much like fpugetregs()'s semantics of doing a full
* drop. Dropping only to the pcb matches fnsave's behaviour. * drop. Dropping only to the pcb matches fnsave's behaviour.
* We only need to drop to !PCB_INITDONE in sendsig(). But * We only need to drop to !PCB_INITDONE in sendsig(). But
* sendsig() is the only caller of npxgetregs()... perhaps we just * sendsig() is the only caller of fpugetregs()... perhaps we just
* have too many layers. * have too many layers.
*/ */
curthread->td_pcb->pcb_flags &= ~PCB_NPXINITDONE; curthread->td_pcb->pcb_flags &= ~PCB_FPUINITDONE;
intr_restore(s); intr_restore(s);
} }

View File

@ -268,7 +268,6 @@ nexus_add_child(device_t bus, int order, const char *name, int unit)
/* /*
* Allocate a resource on behalf of child. NB: child is usually going to be a * Allocate a resource on behalf of child. NB: child is usually going to be a
* child of one of our descendants, not a direct child of nexus0. * child of one of our descendants, not a direct child of nexus0.
* (Exceptions include npx.)
*/ */
static struct resource * static struct resource *
nexus_alloc_resource(device_t bus, device_t child, int type, int *rid, nexus_alloc_resource(device_t bus, device_t child, int type, int *rid,

View File

@ -244,7 +244,7 @@ trap(frame)
break; break;
case T_ARITHTRAP: /* arithmetic trap */ case T_ARITHTRAP: /* arithmetic trap */
ucode = npxtrap(); ucode = fputrap();
if (ucode == -1) if (ucode == -1)
goto userout; goto userout;
i = SIGFPE; i = SIGFPE;
@ -310,7 +310,7 @@ trap(frame)
case T_DNA: case T_DNA:
/* transparent fault (due to context switch "late") */ /* transparent fault (due to context switch "late") */
if (npxdna()) if (fpudna())
goto userout; goto userout;
i = SIGFPE; i = SIGFPE;
ucode = FPE_FPU_NP_TRAP; ucode = FPE_FPU_NP_TRAP;
@ -338,12 +338,12 @@ trap(frame)
case T_DNA: case T_DNA:
/* /*
* The kernel is apparently using npx for copying. * The kernel is apparently using fpu for copying.
* XXX this should be fatal unless the kernel has * XXX this should be fatal unless the kernel has
* registered such use. * registered such use.
*/ */
if (npxdna()) { if (fpudna()) {
printf("npxdna in kernel mode!\n"); printf("fpudna in kernel mode!\n");
goto out; goto out;
} }
break; break;

View File

@ -118,7 +118,7 @@ cpu_fork(td1, p2, td2, flags)
/* Ensure that p1's pcb is up to date. */ /* Ensure that p1's pcb is up to date. */
savecrit = intr_disable(); savecrit = intr_disable();
if (PCPU_GET(fpcurthread) == td1) if (PCPU_GET(fpcurthread) == td1)
npxsave(&td1->td_pcb->pcb_save); fpusave(&td1->td_pcb->pcb_save);
intr_restore(savecrit); intr_restore(savecrit);
/* Point the pcb to the top of the stack */ /* Point the pcb to the top of the stack */
@ -206,7 +206,7 @@ cpu_thread_exit(struct thread *td)
{ {
if (td == PCPU_GET(fpcurthread)) if (td == PCPU_GET(fpcurthread))
npxdrop(); fpudrop();
} }
void void
@ -266,7 +266,7 @@ cpu_set_upcall(struct thread *td, struct thread *td0)
* more analysis) (need a good safe default). * more analysis) (need a good safe default).
*/ */
bcopy(td0->td_pcb, pcb2, sizeof(*pcb2)); bcopy(td0->td_pcb, pcb2, sizeof(*pcb2));
pcb2->pcb_flags &= ~PCB_NPXINITDONE; pcb2->pcb_flags &= ~PCB_FPUINITDONE;
/* /*
* Create a new fresh stack for the new thread. * Create a new fresh stack for the new thread.

View File

@ -91,7 +91,6 @@
sub ("IO_LPT3", "0x3BC", val); sub ("IO_LPT3", "0x3BC", val);
sub ("IO_MDA", "0x3B0", val); sub ("IO_MDA", "0x3B0", val);
sub ("IO_NMI", "0x070", val); sub ("IO_NMI", "0x070", val);
sub ("IO_NPX", "0x0F0", val);
sub ("IO_PMP1", "0x026", val); sub ("IO_PMP1", "0x026", val);
sub ("IO_PMP2", "0x178", val); sub ("IO_PMP2", "0x178", val);
sub ("IO_PPI", "0x061", val); sub ("IO_PPI", "0x061", val);

View File

@ -108,7 +108,7 @@ ia32_get_fpcontext(struct thread *td, struct ia32_mcontext *mcp)
* *
* XXX unpessimize most cases by only aligning when fxsave might be * XXX unpessimize most cases by only aligning when fxsave might be
* called, although this requires knowing too much about * called, although this requires knowing too much about
* npxgetregs()'s internals. * fpugetregs()'s internals.
*/ */
addr = (struct savefpu *)&mcp->mc_fpstate; addr = (struct savefpu *)&mcp->mc_fpstate;
if (td == PCPU_GET(fpcurthread) && ((uintptr_t)(void *)addr & 0xF)) { if (td == PCPU_GET(fpcurthread) && ((uintptr_t)(void *)addr & 0xF)) {
@ -116,12 +116,12 @@ ia32_get_fpcontext(struct thread *td, struct ia32_mcontext *mcp)
addr = (void *)((char *)addr + 4); addr = (void *)((char *)addr + 4);
while ((uintptr_t)(void *)addr & 0xF); while ((uintptr_t)(void *)addr & 0xF);
} }
mcp->mc_ownedfp = npxgetregs(td, addr); mcp->mc_ownedfp = fpugetregs(td, addr);
if (addr != (struct savefpu *)&mcp->mc_fpstate) { if (addr != (struct savefpu *)&mcp->mc_fpstate) {
bcopy(addr, &mcp->mc_fpstate, sizeof(mcp->mc_fpstate)); bcopy(addr, &mcp->mc_fpstate, sizeof(mcp->mc_fpstate));
bzero(&mcp->mc_spare2, sizeof(mcp->mc_spare2)); bzero(&mcp->mc_spare2, sizeof(mcp->mc_spare2));
} }
mcp->mc_fpformat = npxformat(); mcp->mc_fpformat = fpuformat();
} }
static int static int
@ -148,10 +148,10 @@ ia32_set_fpcontext(struct thread *td, const struct ia32_mcontext *mcp)
bcopy(&mcp->mc_fpstate, addr, sizeof(mcp->mc_fpstate)); bcopy(&mcp->mc_fpstate, addr, sizeof(mcp->mc_fpstate));
} }
/* /*
* XXX we violate the dubious requirement that npxsetregs() * XXX we violate the dubious requirement that fpusetregs()
* be called with interrupts disabled. * be called with interrupts disabled.
*/ */
npxsetregs(td, addr); fpusetregs(td, addr);
/* /*
* Don't bother putting things back where they were in the * Don't bother putting things back where they were in the
* misaligned case, since we know that the caller won't use * misaligned case, since we know that the caller won't use

View File

@ -38,12 +38,12 @@
*/ */
/* /*
* 287/387 NPX Coprocessor Data Structures and Constants * Floating Point Data Structures and Constants
* W. Jolitz 1/90 * W. Jolitz 1/90
*/ */
#ifndef _MACHINE_NPX_H_ #ifndef _MACHINE_FPU_H_
#define _MACHINE_NPX_H_ #define _MACHINE_FPU_H_
/* Contents of each x87 floating point accumulator */ /* Contents of each x87 floating point accumulator */
struct fpacc87 { struct fpacc87 {
@ -95,20 +95,20 @@ struct savefpu {
* This is mostly academic for AMD64, because the ABI prefers the use * This is mostly academic for AMD64, because the ABI prefers the use
* SSE2 based math. For FreeBSD/amd64, we go with the default settings. * SSE2 based math. For FreeBSD/amd64, we go with the default settings.
*/ */
#define __INITIAL_NPXCW__ 0x037F #define __INITIAL_FPUCW__ 0x037F
#define __INITIAL_MXCSR__ 0x1F80 #define __INITIAL_MXCSR__ 0x1F80
#define __INITIAL_MXCSR_MASK__ 0xFFBF #define __INITIAL_MXCSR_MASK__ 0xFFBF
#ifdef _KERNEL #ifdef _KERNEL
int npxdna(void); int fpudna(void);
void npxdrop(void); void fpudrop(void);
void npxexit(struct thread *td); void fpuexit(struct thread *td);
int npxformat(void); int fpuformat(void);
int npxgetregs(struct thread *td, struct savefpu *addr); int fpugetregs(struct thread *td, struct savefpu *addr);
void npxinit(u_short control); void fpuinit(u_short control);
void npxsave(struct savefpu *addr); void fpusave(struct savefpu *addr);
void npxsetregs(struct thread *td, struct savefpu *addr); void fpusetregs(struct thread *td, struct savefpu *addr);
int npxtrap(void); int fputrap(void);
#endif #endif
#endif /* !_MACHINE_NPX_H_ */ #endif /* !_MACHINE_FPU_H_ */

View File

@ -66,7 +66,7 @@ struct pcb {
struct savefpu pcb_save; struct savefpu pcb_save;
u_long pcb_flags; u_long pcb_flags;
#define PCB_NPXINITDONE 0x01 /* fpu state is initialized */ #define PCB_FPUINITDONE 0x01 /* fpu state is initialized */
#define PCB_FULLCTX 0x02 /* full context restore on sysret */ #define PCB_FULLCTX 0x02 /* full context restore on sysret */
caddr_t pcb_onfault; /* copyin/out fault recovery */ caddr_t pcb_onfault; /* copyin/out fault recovery */

View File

@ -41,12 +41,9 @@
* Bits in 386 special registers: * Bits in 386 special registers:
*/ */
#define CR0_PE 0x00000001 /* Protected mode Enable */ #define CR0_PE 0x00000001 /* Protected mode Enable */
#define CR0_MP 0x00000002 /* "Math" Present (NPX or NPX emulator) */ #define CR0_MP 0x00000002 /* "Math" (fpu) Present */
#define CR0_EM 0x00000004 /* EMulate non-NPX coproc. (trap ESC only) */ #define CR0_EM 0x00000004 /* EMulate FPU instructions. (trap ESC only) */
#define CR0_TS 0x00000008 /* Task Switched (if MP, trap ESC and WAIT) */ #define CR0_TS 0x00000008 /* Task Switched (if MP, trap ESC and WAIT) */
#ifdef notused
#define CR0_ET 0x00000010 /* Extension Type (387 (if set) vs 287) */
#endif
#define CR0_PG 0x80000000 /* PaGing enable */ #define CR0_PG 0x80000000 /* PaGing enable */
/* /*

View File

@ -33,7 +33,7 @@ eintrnames:
* *
* XXX - the interrupt frame is set up to look like a trap frame. This is * XXX - the interrupt frame is set up to look like a trap frame. This is
* usually a waste of time. The only interrupt handlers that want a frame * usually a waste of time. The only interrupt handlers that want a frame
* are the clock handler (it wants a clock frame), the npx handler (it's * are the clock handler (it wants a clock frame), the fpu handler (it's
* easier to do right all in assembler). The interrupt return routine * easier to do right all in assembler). The interrupt return routine
* needs a trap frame for rare AST's (it could easily convert the frame). * needs a trap frame for rare AST's (it could easily convert the frame).
* The direct costs of setting up a trap frame are two pushl's (error * The direct costs of setting up a trap frame are two pushl's (error
@ -42,7 +42,7 @@ eintrnames:
* costs are making the driver interface nonuniform so unpending of * costs are making the driver interface nonuniform so unpending of
* interrupts is more complicated and slower (call_driver(unit) would * interrupts is more complicated and slower (call_driver(unit) would
* be easier than ensuring an interrupt frame for all handlers. Finally, * be easier than ensuring an interrupt frame for all handlers. Finally,
* there are some struct copies in the npx handler and maybe in the clock * there are some struct copies in the fpu handler and maybe in the clock
* handler that could be avoided by working more with pointers to frames * handler that could be avoided by working more with pointers to frames
* instead of frames. * instead of frames.
* *