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
addq $PCB_SAVEFPU,%r8 /* h/w bugs make saving complicated */
movq %r8, %rdi
call npxsave /* do it in a big C function */
call fpusave /* do it in a big C function */
popq %rsi
popq %rdi
1:
@ -301,16 +301,16 @@ ENTRY(savectx)
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
* 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).
*
* 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
* requested pcb and reload. Copying is easier because we would
* 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
cli
@ -322,7 +322,7 @@ ENTRY(savectx)
pushq %rax
movq TD_PCB(%rax),%rdi
leaq PCB_SAVEFPU(%rdi),%rdi
call npxsave
call fpusave
popq %rax
popq %rcx

View File

@ -37,7 +37,6 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_debug_npx.h"
#include "opt_isa.h"
#include <sys/param.h>
@ -53,9 +52,6 @@ __FBSDID("$FreeBSD$");
#include <sys/sysctl.h>
#include <machine/bus.h>
#include <sys/rman.h>
#ifdef NPX_DEBUG
#include <sys/syslog.h>
#endif
#include <sys/signalvar.h>
#include <sys/user.h>
@ -75,7 +71,7 @@ __FBSDID("$FreeBSD$");
#endif
/*
* 387 and 287 Numeric Coprocessor Extension (NPX) Driver.
* Floating point support.
*/
#if defined(__GNUC__) && !defined(lint)
@ -110,59 +106,50 @@ void stop_emulating(void);
typedef u_char bool_t;
static int npx_attach(device_t dev);
static void npx_identify(driver_t *driver, device_t parent);
static int npx_probe(device_t dev);
static int fpu_attach(device_t dev);
static void fpu_identify(driver_t *driver, device_t parent);
static int fpu_probe(device_t dev);
int hw_float = 1;
SYSCTL_INT(_hw,HW_FLOATINGPT, floatingpoint,
CTLFLAG_RD, &hw_float, 0,
"Floatingpoint instructions executed in hardware");
static struct savefpu npx_cleanstate;
static bool_t npx_cleanstate_ready;
static struct savefpu fpu_cleanstate;
static bool_t fpu_cleanstate_ready;
/*
* Identify routine. Create a connection point on our parent for probing.
*/
static void
npx_identify(driver, parent)
driver_t *driver;
device_t parent;
fpu_identify(driver_t *driver, device_t parent)
{
device_t child;
child = BUS_ADD_CHILD(parent, 0, "npx", 0);
child = BUS_ADD_CHILD(parent, 0, "fpu", 0);
if (child == NULL)
panic("npx_identify");
panic("fpu_identify");
}
/*
* Probe routine. Initialize cr0 to give correct behaviour for [f]wait
* 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.
*/
static int
npx_probe(dev)
device_t dev;
fpu_probe(device_t dev)
{
/*
* Partially reset the coprocessor, if any. Some BIOS's don't reset
* 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
* Prepare to trap all ESC (i.e., FPU) instructions and all WAIT
* 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
* not cause WAIT instructions to trap. It's important to trap
* WAIT instructions - otherwise the "wait" variants of no-wait
* control instructions would degenerate to the "no-wait" variants
* 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.
*
* Try setting CR0_NE to get correct error reporting on 486DX's.
@ -179,6 +166,7 @@ npx_probe(dev)
fninit();
device_set_desc(dev, "math processor");
device_quiet(dev);
return (0);
}
@ -187,19 +175,18 @@ npx_probe(dev)
* Attach routine - announce which it is, and wire into system
*/
static int
npx_attach(dev)
device_t dev;
fpu_attach(device_t dev)
{
register_t s;
npxinit(__INITIAL_NPXCW__);
fpuinit(__INITIAL_FPUCW__);
if (npx_cleanstate_ready == 0) {
if (fpu_cleanstate_ready == 0) {
s = intr_disable();
stop_emulating();
fxsave(&npx_cleanstate);
fxsave(&fpu_cleanstate);
start_emulating();
npx_cleanstate_ready = 1;
fpu_cleanstate_ready = 1;
intr_restore(s);
}
return (0); /* XXX unused */
@ -209,21 +196,20 @@ npx_attach(dev)
* Initialize floating point unit.
*/
void
npxinit(control)
u_short control;
fpuinit(u_short control)
{
static struct savefpu dummy;
register_t savecrit;
/*
* 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.
*/
savecrit = intr_disable();
npxsave(&dummy);
fpusave(&dummy);
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();
fldcw(&control);
start_emulating();
@ -234,34 +220,18 @@ npxinit(control)
* Free coprocessor (if we have it).
*/
void
npxexit(td)
struct thread *td;
fpuexit(struct thread *td)
{
#ifdef NPX_DEBUG
u_int masked_exceptions;
#endif
register_t savecrit;
savecrit = intr_disable();
if (curthread == PCPU_GET(fpcurthread))
npxsave(&PCPU_GET(curpcb)->pcb_save);
fpusave(&PCPU_GET(curpcb)->pcb_save);
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
npxformat()
fpuformat()
{
return (_MC_FPFMT_XMM);
@ -456,7 +426,7 @@ static char fpetable[128] = {
* solution for signals other than SIGFPE.
*/
int
npxtrap()
fputrap()
{
register_t savecrit;
u_short control, status;
@ -493,48 +463,48 @@ npxtrap()
static int err_count = 0;
int
npxdna()
fpudna()
{
struct pcb *pcb;
register_t s;
u_short control;
if (PCPU_GET(fpcurthread) == curthread) {
printf("npxdna: fpcurthread == curthread %d times\n",
printf("fpudna: fpcurthread == curthread %d times\n",
++err_count);
stop_emulating();
return (1);
}
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)->td_proc->p_pid,
curthread, curthread->td_proc->p_pid);
panic("npxdna");
panic("fpudna");
}
s = intr_disable();
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);
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
* the PCB doesn't contain a clean FPU state. Explicitly
* initialize the FPU and load the default control word.
*/
fninit();
control = __INITIAL_NPXCW__;
control = __INITIAL_FPUCW__;
fldcw(&control);
pcb->pcb_flags |= PCB_NPXINITDONE;
pcb->pcb_flags |= PCB_FPUINITDONE;
} else {
/*
* The following frstor may cause a trap when the state
* 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 that should not trigger an error (e.g.,
* 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
* 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.
* Wrapper for fnsave instruction.
*
* 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
* disabling, since most callers need to disable interrupts anyway to call
* npxsave() 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.
* fpusave() atomically with checking fpcurthread.
*/
void
npxsave(addr)
struct savefpu *addr;
fpusave(struct savefpu *addr)
{
stop_emulating();
fxsave(addr);
start_emulating();
PCPU_SET(fpcurthread, NULL);
}
@ -587,13 +540,13 @@ npxsave(addr)
* FPU thread is non-null.
*/
void
npxdrop()
fpudrop()
{
struct thread *td;
td = PCPU_GET(fpcurthread);
PCPU_SET(fpcurthread, NULL);
td->td_pcb->pcb_flags &= ~PCB_NPXINITDONE;
td->td_pcb->pcb_flags &= ~PCB_FPUINITDONE;
start_emulating();
}
@ -602,15 +555,13 @@ npxdrop()
* It returns the FPU ownership status.
*/
int
npxgetregs(td, addr)
struct thread *td;
struct savefpu *addr;
fpugetregs(struct thread *td, struct savefpu *addr)
{
register_t s;
if ((td->td_pcb->pcb_flags & PCB_NPXINITDONE) == 0) {
if (npx_cleanstate_ready)
bcopy(&npx_cleanstate, addr, sizeof(npx_cleanstate));
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));
return (_MC_FPOWNED_NONE);
@ -631,9 +582,7 @@ npxgetregs(td, addr)
* Set the state of the FPU.
*/
void
npxsetregs(td, addr)
struct thread *td;
struct savefpu *addr;
fpusetregs(struct thread *td, struct savefpu *addr)
{
register_t s;
@ -645,14 +594,14 @@ npxsetregs(td, addr)
intr_restore(s);
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 */
DEVMETHOD(device_identify, npx_identify),
DEVMETHOD(device_probe, npx_probe),
DEVMETHOD(device_attach, npx_attach),
DEVMETHOD(device_identify, fpu_identify),
DEVMETHOD(device_probe, fpu_probe),
DEVMETHOD(device_attach, fpu_attach),
DEVMETHOD(device_detach, bus_generic_detach),
DEVMETHOD(device_shutdown, bus_generic_shutdown),
DEVMETHOD(device_suspend, bus_generic_suspend),
@ -661,49 +610,51 @@ static device_method_t npx_methods[] = {
{ 0, 0 }
};
static driver_t npx_driver = {
"npx",
npx_methods,
static driver_t fpu_driver = {
"fpu",
fpu_methods,
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)
* 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
/*
* 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 */
{ 0 }
};
static int
npxisa_probe(device_t dev)
fpuisa_probe(device_t dev)
{
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);
}
return(result);
return (result);
}
static int
npxisa_attach(device_t dev)
fpuisa_attach(device_t dev)
{
return (0);
}
static device_method_t npxisa_methods[] = {
static device_method_t fpuisa_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, npxisa_probe),
DEVMETHOD(device_attach, npxisa_attach),
DEVMETHOD(device_probe, fpuisa_probe),
DEVMETHOD(device_attach, fpuisa_attach),
DEVMETHOD(device_detach, bus_generic_detach),
DEVMETHOD(device_shutdown, bus_generic_shutdown),
DEVMETHOD(device_suspend, bus_generic_suspend),
@ -712,14 +663,14 @@ static device_method_t npxisa_methods[] = {
{ 0, 0 }
};
static driver_t npxisa_driver = {
"npxisa",
npxisa_methods,
static driver_t fpuisa_driver = {
"fpuisa",
fpuisa_methods,
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(npxisa, acpi, npxisa_driver, npxisa_devclass, 0, 0);
DRIVER_MODULE(fpuisa, isa, fpuisa_driver, fpuisa_devclass, 0, 0);
DRIVER_MODULE(fpuisa, acpi, fpuisa_driver, fpuisa_devclass, 0, 0);
#endif /* DEV_ISA */

View File

@ -516,7 +516,6 @@ exec_setregs(td, entry, stack, ps_strings)
bzero((char *)regs, sizeof(struct trapframe));
regs->tf_rip = entry;
/* This strangeness is to ensure alignment after the implied return address */
regs->tf_rsp = ((stack - 8) & ~0xF) + 8;
regs->tf_rdi = stack; /* argv */
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;
/*
* Arrange to trap the next npx or `fwait' instruction (see npx.c
* for why fwait must be trapped at least if there is an npx or an
* Arrange to trap the next fpu or `fwait' instruction (see fpu.c
* 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
* 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
* here allows modifying `npx_exists' for testing the emulator on
* systems with an npx.
* here allows modifying `fpu_exists' for testing the emulator on
* systems with an fpu.
*/
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
* 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
* to force the state to the pcb, and checked the invariant
* (CR0_TS clear) if and only if PCPU_GET(fpcurthread) != NULL).
@ -555,7 +554,7 @@ cpu_setregs(void)
register_t cr0;
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_WP | CR0_AM;
load_cr0(cr0);
@ -1525,8 +1524,8 @@ static void
get_fpcontext(struct thread *td, mcontext_t *mcp)
{
mcp->mc_ownedfp = npxgetregs(td, (struct savefpu *)&mcp->mc_fpstate);
mcp->mc_fpformat = npxformat();
mcp->mc_ownedfp = fpugetregs(td, (struct savefpu *)&mcp->mc_fpstate);
mcp->mc_fpformat = fpuformat();
}
static int
@ -1543,11 +1542,11 @@ set_fpcontext(struct thread *td, const mcontext_t *mcp)
else if (mcp->mc_ownedfp == _MC_FPOWNED_FPU ||
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.
* XXX obsolete on trap-16 systems?
*/
npxsetregs(td, (struct savefpu *)&mcp->mc_fpstate);
fpusetregs(td, (struct savefpu *)&mcp->mc_fpstate);
} else
return (EINVAL);
return (0);
@ -1560,18 +1559,18 @@ fpstate_drop(struct thread *td)
s = intr_disable();
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.
*
* 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.
* 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.
*/
curthread->td_pcb->pcb_flags &= ~PCB_NPXINITDONE;
curthread->td_pcb->pcb_flags &= ~PCB_FPUINITDONE;
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
* child of one of our descendants, not a direct child of nexus0.
* (Exceptions include npx.)
*/
static struct resource *
nexus_alloc_resource(device_t bus, device_t child, int type, int *rid,

View File

@ -244,7 +244,7 @@ trap(frame)
break;
case T_ARITHTRAP: /* arithmetic trap */
ucode = npxtrap();
ucode = fputrap();
if (ucode == -1)
goto userout;
i = SIGFPE;
@ -310,7 +310,7 @@ trap(frame)
case T_DNA:
/* transparent fault (due to context switch "late") */
if (npxdna())
if (fpudna())
goto userout;
i = SIGFPE;
ucode = FPE_FPU_NP_TRAP;
@ -338,12 +338,12 @@ trap(frame)
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
* registered such use.
*/
if (npxdna()) {
printf("npxdna in kernel mode!\n");
if (fpudna()) {
printf("fpudna in kernel mode!\n");
goto out;
}
break;

View File

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

View File

@ -91,7 +91,6 @@
sub ("IO_LPT3", "0x3BC", val);
sub ("IO_MDA", "0x3B0", val);
sub ("IO_NMI", "0x070", val);
sub ("IO_NPX", "0x0F0", val);
sub ("IO_PMP1", "0x026", val);
sub ("IO_PMP2", "0x178", 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
* called, although this requires knowing too much about
* npxgetregs()'s internals.
* fpugetregs()'s internals.
*/
addr = (struct savefpu *)&mcp->mc_fpstate;
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);
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) {
bcopy(addr, &mcp->mc_fpstate, sizeof(mcp->mc_fpstate));
bzero(&mcp->mc_spare2, sizeof(mcp->mc_spare2));
}
mcp->mc_fpformat = npxformat();
mcp->mc_fpformat = fpuformat();
}
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));
}
/*
* XXX we violate the dubious requirement that npxsetregs()
* XXX we violate the dubious requirement that fpusetregs()
* be called with interrupts disabled.
*/
npxsetregs(td, addr);
fpusetregs(td, addr);
/*
* Don't bother putting things back where they were in the
* 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
*/
#ifndef _MACHINE_NPX_H_
#define _MACHINE_NPX_H_
#ifndef _MACHINE_FPU_H_
#define _MACHINE_FPU_H_
/* Contents of each x87 floating point accumulator */
struct fpacc87 {
@ -95,20 +95,20 @@ struct savefpu {
* This is mostly academic for AMD64, because the ABI prefers the use
* 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_MASK__ 0xFFBF
#ifdef _KERNEL
int npxdna(void);
void npxdrop(void);
void npxexit(struct thread *td);
int npxformat(void);
int npxgetregs(struct thread *td, struct savefpu *addr);
void npxinit(u_short control);
void npxsave(struct savefpu *addr);
void npxsetregs(struct thread *td, struct savefpu *addr);
int npxtrap(void);
int fpudna(void);
void fpudrop(void);
void fpuexit(struct thread *td);
int fpuformat(void);
int fpugetregs(struct thread *td, struct savefpu *addr);
void fpuinit(u_short control);
void fpusave(struct savefpu *addr);
void fpusetregs(struct thread *td, struct savefpu *addr);
int fputrap(void);
#endif
#endif /* !_MACHINE_NPX_H_ */
#endif /* !_MACHINE_FPU_H_ */

View File

@ -66,7 +66,7 @@ struct pcb {
struct savefpu pcb_save;
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 */
caddr_t pcb_onfault; /* copyin/out fault recovery */

View File

@ -41,12 +41,9 @@
* Bits in 386 special registers:
*/
#define CR0_PE 0x00000001 /* Protected mode Enable */
#define CR0_MP 0x00000002 /* "Math" Present (NPX or NPX emulator) */
#define CR0_EM 0x00000004 /* EMulate non-NPX coproc. (trap ESC only) */
#define CR0_MP 0x00000002 /* "Math" (fpu) Present */
#define CR0_EM 0x00000004 /* EMulate FPU instructions. (trap ESC only) */
#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 */
/*

View File

@ -33,7 +33,7 @@ eintrnames:
*
* 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
* 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
* 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
@ -42,7 +42,7 @@ eintrnames:
* costs are making the driver interface nonuniform so unpending of
* interrupts is more complicated and slower (call_driver(unit) would
* 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
* instead of frames.
*