summaryrefslogtreecommitdiffstats
path: root/sys/amd64/isa
diff options
context:
space:
mode:
authorbde <bde@FreeBSD.org>2001-05-20 20:04:40 +0000
committerbde <bde@FreeBSD.org>2001-05-20 20:04:40 +0000
commitb093b83cde6aea209e825c09bd4ed152b1f9aa33 (patch)
treed28f8f15d6306bf8ea82143b3a308caa0f3663f0 /sys/amd64/isa
parente37c5b4039950f6c6b0546d9d23e73a3bdf5ffae (diff)
downloadFreeBSD-src-b093b83cde6aea209e825c09bd4ed152b1f9aa33.zip
FreeBSD-src-b093b83cde6aea209e825c09bd4ed152b1f9aa33.tar.gz
Throw away the complications in npxsave() and their infrastructure.
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. Anyway, the complications were usually no-ops because IRQ13 is not used on i486's and newer CPUs, and because SMPng broke them in rev.1.84. Forcible enabling of interrupts was changed to write_eflags(old_eflags), but since SMPng usually calls npxsave() from cpu_switch() with interrupts disabled, write_eflags() usually just kept interrupts disabled.
Diffstat (limited to 'sys/amd64/isa')
-rw-r--r--sys/amd64/isa/npx.c76
1 files changed, 23 insertions, 53 deletions
diff --git a/sys/amd64/isa/npx.c b/sys/amd64/isa/npx.c
index 477f7ba..60d38c4 100644
--- a/sys/amd64/isa/npx.c
+++ b/sys/amd64/isa/npx.c
@@ -55,6 +55,7 @@
#include <sys/syslog.h>
#endif
#include <sys/signalvar.h>
+#include <sys/user.h>
#ifndef SMP
#include <machine/asmacros.h>
@@ -93,7 +94,6 @@
#define fldcw(addr) __asm("fldcw %0" : : "m" (*(addr)))
#define fnclex() __asm("fnclex")
#define fninit() __asm("fninit")
-#define fnop() __asm("fnop")
#define fnsave(addr) __asm __volatile("fnsave %0" : "=m" (*(addr)))
#define fnstcw(addr) __asm __volatile("fnstcw %0" : "=m" (*(addr)))
#define fnstsw(addr) __asm __volatile("fnstsw %0" : "=m" (*(addr)))
@@ -108,7 +108,6 @@
void fldcw __P((caddr_t addr));
void fnclex __P((void));
void fninit __P((void));
-void fnop __P((void));
void fnsave __P((caddr_t addr));
void fnstcw __P((caddr_t addr));
void fnstsw __P((caddr_t addr));
@@ -138,9 +137,6 @@ SYSCTL_INT(_hw,HW_FLOATINGPT, floatingpoint,
"Floatingpoint instructions executed in hardware");
#ifndef SMP
-static u_int npx0_imask = 0;
-static struct gate_descriptor npx_idt_probeintr;
-static int npx_intrno;
static volatile u_int npx_intrs_while_probing;
static volatile u_int npx_traps_while_probing;
#endif
@@ -220,6 +216,7 @@ npx_probe(dev)
#else /* SMP */
+ int npx_intrno;
int result;
critical_t savecrit;
u_char save_icu1_mask;
@@ -245,7 +242,6 @@ npx_probe(dev)
outb(IO_ICU2 + 1, ~(1 << (npx_irq - 8)));
setidt(16, probetrap, SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
setidt(npx_intrno, probeintr, SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
- npx_idt_probeintr = idt[npx_intrno];
/*
* XXX This looks highly bogus, but it appears that npc_probe1
@@ -368,10 +364,6 @@ npx_probe1(dev)
* Bad, we are stuck with IRQ13.
*/
npx_irq13 = 1;
- /*
- * npxattach would be too late to set npx0_imask
- */
- npx0_imask |= (1 << npx_irq);
/*
* We allocate these resources permanently,
@@ -850,59 +842,37 @@ npxdna()
}
/*
- * Wrapper for fnsave instruction to handle h/w bugs. If there is an error
- * pending, then fnsave generates a bogus IRQ13 on some systems. Force
- * any IRQ13 to be handled immediately, and then ignore it. This routine is
- * often called at splhigh so it must not use many system services. In
- * particular, it's much easier to install a special handler than to
- * guarantee that it's safe to use npxintr() and its supporting code.
+ * 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 npxproc to NULL; it is
+ * normally retriggered in npxdna() after return to user mode.
+ *
+ * npxsave() must be called with interrupts disabled, so that it clears
+ * npxproc 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 npxproc.
+ *
+ * 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
npxsave(addr)
struct save87 *addr;
{
-#ifdef SMP
stop_emulating();
fnsave(addr);
- /* fnop(); */
start_emulating();
PCPU_SET(npxproc, NULL);
-
-#else /* SMP */
-
- critical_t savecrit;
- u_char icu1_mask;
- u_char icu2_mask;
- u_char old_icu1_mask;
- u_char old_icu2_mask;
- struct gate_descriptor save_idt_npxintr;
-
- savecrit = critical_enter();
- old_icu1_mask = inb(IO_ICU1 + 1);
- old_icu2_mask = inb(IO_ICU2 + 1);
- save_idt_npxintr = idt[npx_intrno];
- outb(IO_ICU1 + 1, old_icu1_mask & ~(IRQ_SLAVE | npx0_imask));
- outb(IO_ICU2 + 1, old_icu2_mask & ~(npx0_imask >> 8));
- idt[npx_intrno] = npx_idt_probeintr;
- critical_exit(savecrit);
- stop_emulating();
- fnsave(addr);
- fnop();
- start_emulating();
- savecrit = critical_enter();
- PCPU_SET(npxproc, NULL);
- icu1_mask = inb(IO_ICU1 + 1); /* masks may have changed */
- icu2_mask = inb(IO_ICU2 + 1);
- outb(IO_ICU1 + 1,
- (icu1_mask & ~npx0_imask) | (old_icu1_mask & npx0_imask));
- outb(IO_ICU2 + 1,
- (icu2_mask & ~(npx0_imask >> 8))
- | (old_icu2_mask & (npx0_imask >> 8)));
- idt[npx_intrno] = save_idt_npxintr;
- critical_exit(savecrit); /* back to previous state */
-
-#endif /* SMP */
}
#ifdef I586_CPU
OpenPOWER on IntegriCloud