summaryrefslogtreecommitdiff
path: root/i386
diff options
context:
space:
mode:
Diffstat (limited to 'i386')
-rw-r--r--i386/Makefrag.am1
-rw-r--r--i386/configfrag.ac3
-rw-r--r--i386/i386/fpe_linkage.c363
-rw-r--r--i386/i386/fpu.c72
-rw-r--r--i386/i386/fpu.h28
-rw-r--r--i386/i386/gdt.h5
-rw-r--r--i386/i386/trap.c9
7 files changed, 2 insertions, 479 deletions
diff --git a/i386/Makefrag.am b/i386/Makefrag.am
index f34c7cc..50b7afd 100644
--- a/i386/Makefrag.am
+++ b/i386/Makefrag.am
@@ -80,7 +80,6 @@ libkernel_a_SOURCES += \
i386/i386/debug_i386.c \
i386/i386/debug_trace.S \
i386/i386/eflags.h \
- i386/i386/fpe_linkage.c \
i386/i386/fpu.c \
i386/i386/fpu.h \
i386/i386/gdt.c \
diff --git a/i386/configfrag.ac b/i386/configfrag.ac
index d32f2b8..a82ce5c 100644
--- a/i386/configfrag.ac
+++ b/i386/configfrag.ac
@@ -28,9 +28,6 @@ AC_DEFINE([i386], [1], [i386])
# i386/bogus/com.h
AC_DEFINE([NCOM], [4], [NCOM])
-# i386/bogus/fpe.h
-AC_DEFINE([FPE], [0], [We do not have a floating point implementation.])
-
# i386/bogus/lpr.h
AC_DEFINE([NLPR], [1], [NLPR])
diff --git a/i386/i386/fpe_linkage.c b/i386/i386/fpe_linkage.c
deleted file mode 100644
index f0ac34e..0000000
--- a/i386/i386/fpe_linkage.c
+++ /dev/null
@@ -1,363 +0,0 @@
-/*
- * Mach Operating System
- * Copyright (c) 1991 Carnegie Mellon University
- * All Rights Reserved.
- *
- * Permission to use, copy, modify and distribute this software and its
- * documentation is hereby granted, provided that both the copyright
- * notice and this permission notice appear in all copies of the
- * software, derivative works or modified versions, and any portions
- * thereof, and that both notices appear in supporting documentation.
- *
- * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
- * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
- * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
- *
- * Carnegie Mellon requests users of this software to return to
- *
- * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
- * School of Computer Science
- * Carnegie Mellon University
- * Pittsburgh PA 15213-3890
- *
- * any improvements or extensions that they make and grant Carnegie Mellon
- * the rights to redistribute these changes.
- */
-
-/*
- * Support routines for FP emulator.
- */
-
-#if FPE
-
-#include <cpus.h>
-
-#include <mach/std_types.h>
-#include <mach/exception.h>
-#include <mach/thread_status.h>
-
-#include <kern/cpu_number.h>
-#include <kern/debug.h>
-#include <kern/thread.h>
-
-#include <vm/vm_kern.h>
-
-#include <mach/machine/eflags.h>
-#include "vm_param.h"
-#include <i386/pmap.h>
-#include <i386/thread.h>
-#include <i386/fpu.h>
-#include "proc_reg.h"
-#include "seg.h"
-#include "idt.h"
-#include "gdt.h"
-
-#if NCPUS > 1
-#include <i386/mp_desc.h>
-#endif
-
-extern vm_offset_t kvtophys();
-
-/*
- * Symbols exported from FPE emulator.
- */
-extern char fpe_start[]; /* start of emulator text;
- also emulation entry point */
-extern char fpe_end[]; /* end of emulator text */
-extern int fpe_reg_segment;
- /* word holding segment number for
- FPE register/status area */
-extern char fpe_recover[]; /* emulation fault recovery entry point */
-
-extern void fix_desc();
-
-#if NCPUS > 1
-#define curr_gdt(mycpu) (mp_gdt[mycpu])
-#define curr_idt(mycpu) (mp_desc_table[mycpu]->idt)
-#else
-#define curr_gdt(mycpu) (gdt)
-#define curr_idt(mycpu) (idt)
-#endif
-
-#define gdt_desc_p(mycpu,sel) \
- ((struct real_descriptor *)&curr_gdt(mycpu)[sel_idx(sel)])
-#define idt_desc_p(mycpu,idx) \
- ((struct real_gate *)&curr_idt(mycpu)[idx])
-
-void set_user_access(); /* forward */
-void enable_fpe(register struct i386_fpsave_state *ifps);
-
-/*
- * long pointer for calling FPE register recovery routine.
- */
-struct long_ptr {
- unsigned long offset;
- unsigned short segment;
-};
-
-struct long_ptr fpe_recover_ptr;
-
-/*
- * Initialize descriptors for FP emulator.
- */
-void
-fpe_init()
-{
- register struct real_descriptor *gdt_p;
- register struct real_gate *idt_p;
-
- /*
- * Map in the pages for the FP emulator:
- * read-only, user-accessible.
- */
- set_user_access(pmap_kernel(),
- (vm_offset_t)fpe_start,
- (vm_offset_t)fpe_end,
- FALSE);
-
- /*
- * Put the USER_FPREGS segment value in the FP emulator.
- */
- fpe_reg_segment = USER_FPREGS;
-
- /*
- * Change exception 7 gate (coprocessor not present)
- * to a trap gate to the FPE code segment.
- */
- idt_p = idt_desc_p(cpu_number(), 7);
- idt_p->offset_low = 0; /* offset of FPE entry */
- idt_p->offset_high = 0;
- idt_p->selector = FPE_CS; /* FPE code segment */
- idt_p->word_count = 0;
- idt_p->access = ACC_P|ACC_PL_K|ACC_TRAP_GATE;
- /* trap gate */
- /* kernel privileges only,
- so INT $7 does not call
- the emulator */
-
- /*
- * Build GDT entry for FP code segment.
- */
- gdt_p = gdt_desc_p(cpu_number(), FPE_CS);
- gdt_p->base_low = ((vm_offset_t) fpe_start) & 0xffff;
- gdt_p->base_med = (((vm_offset_t) fpe_start) >> 16) & 0xff;
- gdt_p->base_high = ((vm_offset_t) fpe_start) >> 24;
- gdt_p->limit_low = (vm_offset_t) fpe_end
- - (vm_offset_t) fpe_start
- - 1;
- gdt_p->limit_high = 0;
- gdt_p->granularity = SZ_32;
- gdt_p->access = ACC_P|ACC_PL_K|ACC_CODE_CR;
- /* conforming segment,
- usable by kernel */
-
- /*
- * Build GDT entry for user FP state area - template,
- * since each thread has its own.
- */
- gdt_p = gdt_desc_p(cpu_number(), USER_FPREGS);
- /* descriptor starts as 0 */
- gdt_p->limit_low = sizeof(struct i386_fp_save)
- + sizeof(struct i386_fp_regs)
- - 1;
- gdt_p->limit_high = 0;
- gdt_p->granularity = 0;
- gdt_p->access = ACC_PL_U|ACC_DATA_W;
- /* start as "not present" */
-
- /*
- * Set up the recovery routine pointer
- */
- fpe_recover_ptr.offset = fpe_recover - fpe_start;
- fpe_recover_ptr.segment = FPE_CS;
-
- /*
- * Set i386 to emulate coprocessor.
- */
- set_cr0((get_cr0() & ~CR0_MP) | CR0_EM);
-}
-
-/*
- * Enable FPE use for a new thread.
- * Allocates the FP save area.
- */
-boolean_t
-fp_emul_error(regs)
- struct i386_saved_state *regs;
-{
- register struct i386_fpsave_state *ifps;
- register vm_offset_t start_va;
-
- if ((regs->err & 0xfffc) != (USER_FPREGS & ~SEL_PL))
- return FALSE;
-
- /*
- * Make the FPU save area user-accessible (by FPE)
- */
- ifps = current_thread()->pcb->ims.ifps;
- if (ifps == 0) {
- /*
- * No FP register state yet - allocate it.
- */
- fp_state_alloc();
- ifps = current_thread()->pcb->ims.ifps;
- }
-
- panic("fp_emul_error: FP emulation is probably broken because of VM changes; fix! XXX");
- start_va = (vm_offset_t) &ifps->fp_save_state;
- set_user_access(current_map()->pmap,
- start_va,
- start_va + sizeof(struct i386_fp_save),
- TRUE);
-
- /*
- * Enable FPE use for this thread
- */
- enable_fpe(ifps);
-
- return TRUE;
-}
-
-/*
- * Enable FPE use. ASSUME that kernel does NOT use FPU
- * except to handle user exceptions.
- */
-void
-enable_fpe(ifps)
- register struct i386_fpsave_state *ifps;
-{
- struct real_descriptor *dp;
- vm_offset_t start_va;
-
- dp = gdt_desc_p(cpu_number(), USER_FPREGS);
- start_va = (vm_offset_t)&ifps->fp_save_state;
-
- dp->base_low = start_va & 0xffff;
- dp->base_med = (start_va >> 16) & 0xff;
- dp->base_high = start_va >> 24;
- dp->access |= ACC_P;
-}
-
-void
-disable_fpe()
-{
- /*
- * The kernel might be running with fs & gs segments
- * which refer to USER_FPREGS, if we entered the kernel
- * from a FP-using thread. We have to clear these segments
- * lest we get a Segment Not Present trap. This would happen
- * if the kernel took an interrupt or fault after clearing
- * the present bit but before exiting to user space (which
- * would reset fs & gs from the current user thread).
- */
-
- asm volatile("xorw %ax, %ax\n\t"
- "movw %ax, %fs\n\t"
- "movw %ax, %gs\n\t":::"ax");
-
- gdt_desc_p(cpu_number(), USER_FPREGS)->access &= ~ACC_P;
-}
-
-void
-set_user_access(pmap, start, end, writable)
- pmap_t pmap;
- vm_offset_t start;
- vm_offset_t end;
- boolean_t writable;
-{
- register vm_offset_t va;
- register pt_entry_t * dirbase = pmap->dirbase;
- register pt_entry_t * ptep;
- register pt_entry_t * pdep;
-
- start = i386_trunc_page(start);
- end = i386_round_page(end);
-
- for (va = start; va < end; va += I386_PGBYTES) {
-
- pdep = &dirbase[lin2pdenum(kvtolin(va))];
- *pdep |= INTEL_PTE_USER;
- ptep = (pt_entry_t *)ptetokv(*pdep);
- ptep = &ptep[ptenum(va)];
- *ptep |= INTEL_PTE_USER;
- if (!writable)
- *ptep &= ~INTEL_PTE_WRITE;
- }
-}
-
-/*
- * Route exception through emulator fixup routine if
- * it occured within the emulator.
- */
-extern void exception();
-
-void
-fpe_exception_fixup(exc, code, subcode)
- int exc, code, subcode;
-{
- thread_t thread = current_thread();
- pcb_t pcb = thread->pcb;
-
- if (pcb->iss.efl & EFL_VM) {
- /*
- * The emulator doesn`t handle V86 mode.
- * If this is a GP fault on the emulator`s
- * code segment, change it to an FP not present
- * fault.
- */
- if (exc == EXC_BAD_INSTRUCTION
- && code == EXC_I386_GPFLT
- && subcode == FPE_CS + 1)
- {
- exc = EXC_ARITHMETIC; /* arithmetic error: */
- code = EXC_I386_NOEXT; /* no FPU */
- subcode = 0;
- }
- }
- else
- if ((pcb->iss.cs & 0xfffc) == FPE_CS) {
- /*
- * Pass registers to emulator,
- * to let it fix them up.
- * The emulator fixup routine knows about
- * an i386_thread_state.
- */
- struct i386_thread_state tstate;
- unsigned int count;
-
- count = i386_THREAD_STATE_COUNT;
- (void) thread_getstatus(thread,
- i386_REGS_SEGS_STATE,
- (thread_state_t) &tstate,
- &count);
-
- /*
- * long call to emulator register recovery routine
- */
- asm volatile("pushl %0; lcall %1; addl $4,%%esp"
- :
- : "r" (&tstate),
- "m" (fpe_recover_ptr) );
-
- (void) thread_setstatus(thread,
- i386_REGS_SEGS_STATE,
- (thread_state_t) &tstate,
- count);
- /*
- * In addition, check for a GP fault on 'int 16' in
- * the emulator, since the interrupt gate is protected.
- * If so, change it to an arithmetic error.
- */
- if (exc == EXC_BAD_INSTRUCTION
- && code == EXC_I386_GPFLT
- && subcode == 8*16+2) /* idt[16] */
- {
- exc = EXC_ARITHMETIC;
- code = EXC_I386_EXTERR;
- subcode = pcb->ims.ifps->fp_save_state.fp_status;
- }
- }
- exception(exc, code, subcode);
-}
-#endif /* FPE. */
-
diff --git a/i386/i386/fpu.c b/i386/i386/fpu.c
index 17f5dab..ad88a5d 100644
--- a/i386/i386/fpu.c
+++ b/i386/i386/fpu.c
@@ -138,19 +138,11 @@ init_fpu()
set_cr0(get_cr0() | CR0_TS | CR0_MP);
}
else {
-#if FPE
- /*
- * Use the floating-point emulator.
- */
- fp_kind = FP_SOFT;
- fpe_init();
-#else /* no fpe */
/*
* NO FPU.
*/
fp_kind = FP_NO;
set_cr0(get_cr0() | CR0_EM);
-#endif
}
}
@@ -277,39 +269,7 @@ ASSERT_IPL(SPL0);
ifps->fp_save_state.fp_opcode = user_fp_state->fp_opcode;
ifps->fp_save_state.fp_dp = user_fp_state->fp_dp;
ifps->fp_save_state.fp_ds = user_fp_state->fp_ds;
-
-#if FPE
- if (fp_kind == FP_SOFT) {
- /*
- * The emulator stores the registers by physical
- * register number, not from top-of-stack.
- * Shuffle the registers into the correct order.
- */
- register char *src; /* user regs */
- register char *dst; /* kernel regs */
- int i;
-
- src = (char *)user_fp_regs;
- dst = (char *)&ifps->fp_regs;
- i = (ifps->fp_save_state.fp_status & FPS_TOS)
- >> FPS_TOS_SHIFT; /* physical register
- for st(0) */
- if (i == 0)
- memcpy(dst, src, 8 * 10);
- else {
- memcpy(dst + 10 * i,
- src,
- 10 * (8 - i));
- memcpy(dst,
- src + 10 * (8 - i),
- 10 * i);
- }
- }
- else
- ifps->fp_regs = *user_fp_regs;
-#else /* no FPE */
ifps->fp_regs = *user_fp_regs;
-#endif /* FPE */
simple_unlock(&pcb->lock);
if (new_ifps != 0)
@@ -387,39 +347,7 @@ ASSERT_IPL(SPL0);
user_fp_state->fp_opcode = ifps->fp_save_state.fp_opcode;
user_fp_state->fp_dp = ifps->fp_save_state.fp_dp;
user_fp_state->fp_ds = ifps->fp_save_state.fp_ds;
-
-#if FPE
- if (fp_kind == FP_SOFT) {
- /*
- * The emulator stores the registers by physical
- * register number, not from top-of-stack.
- * Shuffle the registers into the correct order.
- */
- register char *src; /* kernel regs */
- register char *dst; /* user regs */
- int i;
-
- src = (char *)&ifps->fp_regs;
- dst = (char *)user_fp_regs;
- i = (ifps->fp_save_state.fp_status & FPS_TOS)
- >> FPS_TOS_SHIFT; /* physical register
- for st(0) */
- if (i == 0)
- memcpy(dst, src, 8 * 10);
- else {
- memcpy(dst,
- src + 10 * i,
- 10 * (8 - i));
- memcpy(dst + 10 * (8 - i),
- src,
- 10 * i);
- }
- }
- else
- *user_fp_regs = ifps->fp_regs;
-#else /* no FPE */
*user_fp_regs = ifps->fp_regs;
-#endif /* FPE */
}
simple_unlock(&pcb->lock);
diff --git a/i386/i386/fpu.h b/i386/i386/fpu.h
index bb332ad..3e92de7 100644
--- a/i386/i386/fpu.h
+++ b/i386/i386/fpu.h
@@ -69,32 +69,6 @@
#define fwait() \
asm("fwait");
-/*
- * If floating-point instructions are emulated,
- * we must load the floating-point register selector
- * when switching to a new thread.
- */
-#if FPE
-extern void disable_fpe();
-extern void enable_fpe();
-
-#define fpu_save_context(thread) \
- { \
- if (fp_kind == FP_SOFT) \
- disable_fpe(); \
- else \
- set_ts(); \
- }
-
-#define fpu_load_context(pcb) \
- { \
- register struct i386_fpsave_state *ifps; \
- if (fp_kind == FP_SOFT && (ifps = pcb->ims.ifps) != 0) \
- enable_fpe(ifps); \
- }
-
-#else /* no FPE */
-
#define fpu_load_context(pcb)
/*
@@ -124,8 +98,6 @@ extern void enable_fpe();
#endif /* NCPUS == 1 */
-#endif /* no FPE */
-
extern int fp_kind;
#endif /* _I386_FPU_H_ */
diff --git a/i386/i386/gdt.h b/i386/i386/gdt.h
index 4715759..558bd15 100644
--- a/i386/i386/gdt.h
+++ b/i386/i386/gdt.h
@@ -45,9 +45,8 @@
#define USER_LDT 0x28 /* place for per-thread LDT */
#define USER_TSS 0x30 /* place for per-thread TSS
that holds IO bitmap */
-#define FPE_CS 0x38 /* floating-point emulator code */
-#define USER_FPREGS 0x40 /* user-mode access to saved
- floating-point registers */
+/* 0x38 was FPE_CS, now free */
+/* 0x40 was USER_FPREGS, now free */
#define USER_GDT 0x48 /* user-defined GDT entries */
#define USER_GDT_SLOTS 2
diff --git a/i386/i386/trap.c b/i386/i386/trap.c
index 068a0b3..bd0d8e0 100644
--- a/i386/i386/trap.c
+++ b/i386/i386/trap.c
@@ -480,11 +480,6 @@ printf("user trap %d error %d sub %08x\n", type, code, subcode);
break;
case T_SEGMENT_NOT_PRESENT:
-#if FPE
- if (fp_emul_error(regs))
- return 0;
-#endif /* FPE */
-
exc = EXC_BAD_INSTRUCTION;
code = EXC_I386_SEGNPFLT;
subcode = regs->err & 0xffff;
@@ -1035,11 +1030,7 @@ i386_exception(exc, code, subcode)
ast_off(cpu_number(), AST_I386_FP);
splx(s);
-#if FPE
- fpe_exception_fixup(exc, code, subcode);
-#else
exception(exc, code, subcode);
-#endif
/*NOTREACHED*/
}