summaryrefslogtreecommitdiffstats
path: root/sys/i386
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2010-06-23 11:12:58 +0000
committerkib <kib@FreeBSD.org>2010-06-23 11:12:58 +0000
commit6375d4e4dbfd5685b41e1a8c5bab47946781e84d (patch)
tree835f0e5151b469ebe9a3379bc0ce7594ef78b5f6 /sys/i386
parentb698c6254337111160752bcb9403f907d8001225 (diff)
downloadFreeBSD-src-6375d4e4dbfd5685b41e1a8c5bab47946781e84d.zip
FreeBSD-src-6375d4e4dbfd5685b41e1a8c5bab47946781e84d.tar.gz
Remove the support for int13 FPU exception reporting on i386. It is
believed that all 486-class CPUs FreeBSD is capable to run on, either have no FPU and cannot use external coprocessor, or have FPU on the package and can use #MF. Reviewed by: bde Tested by: pho (previous version)
Diffstat (limited to 'sys/i386')
-rw-r--r--sys/i386/i386/vm_machdep.c2
-rw-r--r--sys/i386/include/npx.h8
-rw-r--r--sys/i386/include/pcb.h1
-rw-r--r--sys/i386/isa/npx.c163
4 files changed, 32 insertions, 142 deletions
diff --git a/sys/i386/i386/vm_machdep.c b/sys/i386/i386/vm_machdep.c
index 01e7245..70c3153 100644
--- a/sys/i386/i386/vm_machdep.c
+++ b/sys/i386/i386/vm_machdep.c
@@ -441,7 +441,7 @@ cpu_set_upcall(struct thread *td, struct thread *td0)
* values here.
*/
bcopy(td0->td_pcb, pcb2, sizeof(*pcb2));
- pcb2->pcb_flags &= ~(PCB_NPXTRAP|PCB_NPXINITDONE|PCB_NPXUSERINITDONE);
+ pcb2->pcb_flags &= ~(PCB_NPXINITDONE | PCB_NPXUSERINITDONE);
pcb2->pcb_save = &pcb2->pcb_user_save;
/*
diff --git a/sys/i386/include/npx.h b/sys/i386/include/npx.h
index 59615fa..71073a6 100644
--- a/sys/i386/include/npx.h
+++ b/sys/i386/include/npx.h
@@ -138,11 +138,6 @@ union savefpu {
#ifdef _KERNEL
-#define IO_NPX 0x0F0 /* Numeric Coprocessor */
-#define IO_NPXSIZE 16 /* 80387/80487 NPX registers */
-
-#define IRQ_NPX 13
-
struct fpu_kern_ctx {
union savefpu hwstate;
union savefpu *prev;
@@ -152,9 +147,6 @@ struct fpu_kern_ctx {
#define PCB_USER_FPU(pcb) (((pcb)->pcb_flags & PCB_KERNNPX) == 0)
-/* full reset on some systems, NOP on others */
-#define npx_full_reset() outb(IO_NPX + 1, 0)
-
int npxdna(void);
void npxdrop(void);
void npxexit(struct thread *td);
diff --git a/sys/i386/include/pcb.h b/sys/i386/include/pcb.h
index 465f497..1311ab1 100644
--- a/sys/i386/include/pcb.h
+++ b/sys/i386/include/pcb.h
@@ -65,7 +65,6 @@ struct pcb {
u_int pcb_flags;
#define FP_SOFTFP 0x01 /* process using software fltng pnt emulator */
#define PCB_DBREGS 0x02 /* process using debug registers */
-#define PCB_NPXTRAP 0x04 /* npx trap pending */
#define PCB_NPXINITDONE 0x08 /* fpu state is initialized */
#define PCB_VM86CALL 0x10 /* in vm86 call */
#define PCB_NPXUSERINITDONE 0x20 /* user fpu state is initialized */
diff --git a/sys/i386/isa/npx.c b/sys/i386/isa/npx.c
index 889dd9d..6059ee8 100644
--- a/sys/i386/isa/npx.c
+++ b/sys/i386/isa/npx.c
@@ -161,21 +161,15 @@ static void fpusave(union savefpu *);
static void fpurstor(union savefpu *);
static int npx_attach(device_t dev);
static void npx_identify(driver_t *driver, device_t parent);
-static int npx_intr(void *);
static int npx_probe(device_t dev);
-int hw_float; /* XXX currently just alias for npx_exists */
+int hw_float;
SYSCTL_INT(_hw, HW_FLOATINGPT, floatingpoint, CTLFLAG_RD,
&hw_float, 0, "Floating point instructions executed in hardware");
-static volatile u_int npx_intrs_while_probing;
static volatile u_int npx_traps_while_probing;
-
static union savefpu npx_initialstate;
-static bool_t npx_ex16;
-static bool_t npx_exists;
-static bool_t npx_irq13;
alias_for_inthand_t probetrap;
__asm(" \n\
@@ -205,58 +199,14 @@ npx_identify(driver, parent)
}
/*
- * Do minimal handling of npx interrupts to convert them to traps.
- */
-static int
-npx_intr(dummy)
- void *dummy;
-{
- struct thread *td;
-
- npx_intrs_while_probing++;
-
- /*
- * The BUSY# latch must be cleared in all cases so that the next
- * unmasked npx exception causes an interrupt.
- */
- outb(IO_NPX, 0);
-
- /*
- * fpcurthread is normally non-null here. In that case, schedule an
- * AST to finish the exception handling in the correct context
- * (this interrupt may occur after the thread has entered the
- * kernel via a syscall or an interrupt). Otherwise, the npx
- * state of the thread that caused this interrupt must have been
- * pushed to the thread's pcb, and clearing of the busy latch
- * above has finished the (essentially null) handling of this
- * interrupt. Control will eventually return to the instruction
- * that caused it and it will repeat. We will eventually (usually
- * soon) win the race to handle the interrupt properly.
- */
- td = PCPU_GET(fpcurthread);
- if (td != NULL) {
- td->td_pcb->pcb_flags |= PCB_NPXTRAP;
- thread_lock(td);
- td->td_flags |= TDF_ASTPENDING;
- thread_unlock(td);
- }
- return (FILTER_HANDLED);
-}
-
-/*
* Probe routine. Set flags to tell npxattach() what to do. Set up an
* interrupt handler if npx needs to use interrupts.
*/
static int
-npx_probe(dev)
- device_t dev;
+npx_probe(device_t dev)
{
struct gate_descriptor save_idt_npxtrap;
- struct resource *ioport_res, *irq_res;
- void *irq_cookie;
- int ioport_rid, irq_num, irq_rid;
- u_short control;
- u_short status;
+ u_short control, status;
device_set_desc(dev, "math processor");
@@ -266,8 +216,7 @@ npx_probe(dev)
* common case right away.
*/
if (cpu_feature & CPUID_FPU) {
- hw_float = npx_exists = 1;
- npx_ex16 = 1;
+ hw_float = 1;
device_quiet(dev);
return (0);
}
@@ -275,28 +224,6 @@ npx_probe(dev)
save_idt_npxtrap = idt[IDT_MF];
setidt(IDT_MF, probetrap, SDT_SYS386TGT, SEL_KPL,
GSEL(GCODE_SEL, SEL_KPL));
- ioport_rid = 0;
- ioport_res = bus_alloc_resource(dev, SYS_RES_IOPORT, &ioport_rid,
- IO_NPX, IO_NPX + IO_NPXSIZE - 1, IO_NPXSIZE, RF_ACTIVE);
- if (ioport_res == NULL)
- panic("npx: can't get ports");
- if (resource_int_value("npx", 0, "irq", &irq_num) != 0)
- irq_num = IRQ_NPX;
- irq_rid = 0;
- irq_res = bus_alloc_resource(dev, SYS_RES_IRQ, &irq_rid, irq_num,
- irq_num, 1, RF_ACTIVE);
- if (irq_res != NULL) {
- if (bus_setup_intr(dev, irq_res, INTR_TYPE_MISC,
- npx_intr, NULL, NULL, &irq_cookie) != 0)
- panic("npx: can't create intr");
- }
-
- /*
- * Partially reset the coprocessor, if any. Some BIOS's don't reset
- * it after a warm boot.
- */
- npx_full_reset();
- outb(IO_NPX, 0);
/*
* Don't trap while we're probing.
@@ -317,9 +244,6 @@ npx_probe(dev)
*/
DELAY(1000); /* wait for any IRQ13 */
#ifdef DIAGNOSTIC
- if (npx_intrs_while_probing != 0)
- printf("fninit caused %u bogus npx interrupt(s)\n",
- npx_intrs_while_probing);
if (npx_traps_while_probing != 0)
printf("fninit caused %u bogus npx trap(s)\n",
npx_traps_while_probing);
@@ -336,7 +260,6 @@ npx_probe(dev)
control = 0x5a5a;
fnstcw(&control);
if ((control & 0x1f3f) == 0x033f) {
- hw_float = npx_exists = 1;
/*
* We have an npx, now divide by 0 to see if exception
* 16 works.
@@ -348,70 +271,46 @@ npx_probe(dev)
* FPU error signal doesn't work on some CPU
* accelerator board.
*/
- npx_ex16 = 1;
+ hw_float = 1;
return (0);
#endif
- npx_traps_while_probing = npx_intrs_while_probing = 0;
+ npx_traps_while_probing = 0;
fp_divide_by_0();
- DELAY(1000); /* wait for any IRQ13 */
if (npx_traps_while_probing != 0) {
/*
* Good, exception 16 works.
*/
- npx_ex16 = 1;
- goto no_irq13;
- }
- if (npx_intrs_while_probing != 0) {
- /*
- * Bad, we are stuck with IRQ13.
- */
- npx_irq13 = 1;
- idt[IDT_MF] = save_idt_npxtrap;
-#ifdef SMP
- if (mp_ncpus > 1)
- panic("npx0 cannot use IRQ 13 on an SMP system");
-#endif
- return (0);
+ hw_float = 1;
+ goto cleanup;
}
- /*
- * Worse, even IRQ13 is broken.
- */
+ device_printf(dev,
+ "FPU does not use exception 16 for error reporting\n");
+ goto cleanup;
}
}
- /* Probe failed. Floating point simply won't work. */
+ /*
+ * Probe failed. Floating point simply won't work.
+ * Notify user and disable FPU/MMX/SSE instruction execution.
+ */
device_printf(dev, "WARNING: no FPU!\n");
+ __asm __volatile("smsw %%ax; orb %0,%%al; lmsw %%ax" : :
+ "n" (CR0_EM | CR0_MP) : "ax");
- /* FALLTHROUGH */
-no_irq13:
+cleanup:
idt[IDT_MF] = save_idt_npxtrap;
- if (irq_res != NULL) {
- bus_teardown_intr(dev, irq_res, irq_cookie);
- bus_release_resource(dev, SYS_RES_IRQ, irq_rid, irq_res);
- }
- bus_release_resource(dev, SYS_RES_IOPORT, ioport_rid, ioport_res);
- return (npx_exists ? 0 : ENXIO);
+ return (hw_float ? 0 : ENXIO);
}
/*
* Attach routine - announce which it is, and wire into system
*/
static int
-npx_attach(dev)
- device_t dev;
+npx_attach(device_t dev)
{
- int flags;
register_t s;
- flags = device_get_flags(dev);
-
- if (npx_irq13)
- device_printf(dev, "IRQ 13 interface\n");
- else if (!device_is_quiet(dev) || bootverbose)
- device_printf(dev, "INT 16 interface\n");
-
npxinit();
-
s = intr_disable();
stop_emulating();
fpusave(&npx_initialstate);
@@ -447,7 +346,7 @@ npxinit(void)
register_t savecrit;
u_short control;
- if (!npx_exists)
+ if (!hw_float)
return;
/*
* fninit has the same h/w bugs as fnsave. Use the detoxified
@@ -482,7 +381,7 @@ npxexit(td)
npxsave(PCPU_GET(curpcb)->pcb_save);
intr_restore(savecrit);
#ifdef NPX_DEBUG
- if (npx_exists) {
+ if (hw_float) {
u_int masked_exceptions;
masked_exceptions = GET_FPU_CW(td) & GET_FPU_SW(td) & 0x7f;
@@ -503,7 +402,7 @@ int
npxformat()
{
- if (!npx_exists)
+ if (!hw_float)
return (_MC_FPFMT_NODEV);
#ifdef CPU_ENABLE_SSE
if (cpu_fxsr)
@@ -706,9 +605,9 @@ npxtrap()
register_t savecrit;
u_short control, status;
- if (!npx_exists) {
- printf("npxtrap: fpcurthread = %p, curthread = %p, npx_exists = %d\n",
- PCPU_GET(fpcurthread), curthread, npx_exists);
+ if (!hw_float) {
+ printf("npxtrap: fpcurthread = %p, curthread = %p, hw_float = %d\n",
+ PCPU_GET(fpcurthread), curthread, hw_float);
panic("npxtrap from nowhere");
}
savecrit = intr_disable();
@@ -748,7 +647,7 @@ npxdna(void)
struct pcb *pcb;
register_t s;
- if (!npx_exists)
+ if (!hw_float)
return (0);
if (PCPU_GET(fpcurthread) == curthread) {
printf("npxdna: fpcurthread == curthread %d times\n",
@@ -879,7 +778,7 @@ npxgetregs(struct thread *td, union savefpu *addr)
struct pcb *pcb;
register_t s;
- if (!npx_exists)
+ if (!hw_float)
return (_MC_FPOWNED_NONE);
pcb = td->td_pcb;
@@ -915,7 +814,7 @@ npxgetuserregs(struct thread *td, union savefpu *addr)
struct pcb *pcb;
register_t s;
- if (!npx_exists)
+ if (!hw_float)
return (_MC_FPOWNED_NONE);
pcb = td->td_pcb;
@@ -954,7 +853,7 @@ npxsetregs(struct thread *td, union savefpu *addr)
struct pcb *pcb;
register_t s;
- if (!npx_exists)
+ if (!hw_float)
return;
pcb = td->td_pcb;
@@ -981,7 +880,7 @@ npxsetuserregs(struct thread *td, union savefpu *addr)
struct pcb *pcb;
register_t s;
- if (!npx_exists)
+ if (!hw_float)
return;
pcb = td->td_pcb;
OpenPOWER on IntegriCloud