patch-2.4.0-test2 linux/arch/i386/kernel/traps.c
Next file: linux/arch/i386/kernel/vm86.c
Previous file: linux/arch/i386/kernel/time.c
Back to the patch index
Back to the overall index
- Lines: 204
- Date:
Wed Jun 21 20:59:38 2000
- Orig file:
v2.4.0-test1/linux/arch/i386/kernel/traps.c
- Orig date:
Mon Jun 19 16:31:57 2000
diff -u --recursive --new-file v2.4.0-test1/linux/arch/i386/kernel/traps.c linux/arch/i386/kernel/traps.c
@@ -2,7 +2,9 @@
* linux/arch/i386/traps.c
*
* Copyright (C) 1991, 1992 Linus Torvalds
- * FXSAVE/FXRSTOR support by Ingo Molnar, OS exception support by Goutham Rao
+ *
+ * Pentium III FXSR, SSE support
+ * Gareth Hughes <gareth@valinux.com>, May 2000
*/
/*
@@ -35,6 +37,7 @@
#include <asm/atomic.h>
#include <asm/debugreg.h>
#include <asm/desc.h>
+#include <asm/i387.h>
#include <asm/smp.h>
#include <asm/pgalloc.h>
@@ -136,8 +139,6 @@
unlock_kernel(); \
}
-void page_exception(void);
-
asmlinkage void divide_error(void);
asmlinkage void debug(void);
asmlinkage void nmi(void);
@@ -154,10 +155,10 @@
asmlinkage void general_protection(void);
asmlinkage void page_fault(void);
asmlinkage void coprocessor_error(void);
+asmlinkage void simd_coprocessor_error(void);
asmlinkage void reserved(void);
asmlinkage void alignment_check(void);
asmlinkage void spurious_interrupt_bug(void);
-asmlinkage void xmm_fault(void);
int kstack_depth_to_print = 24;
@@ -320,7 +321,6 @@
DO_ERROR(12, SIGBUS, "stack segment", stack_segment, current)
DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, current, BUS_ADRALN, get_cr2())
DO_ERROR(18, SIGSEGV, "reserved", reserved, current)
-DO_VM86_ERROR(19, SIGFPE, "XMM fault", xmm_fault, current)
asmlinkage void do_general_protection(struct pt_regs * regs, long error_code)
{
@@ -537,12 +537,12 @@
* The TF error should be masked out only if the current
* process is not traced and if the TRAP flag has been set
* previously by a tracing process (condition detected by
- * the PF_DTRACE flag); remember that the i386 TRAP flag
+ * the PT_DTRACE flag); remember that the i386 TRAP flag
* can be modified by the process itself in user mode,
* allowing programs to debug themselves without the ptrace()
* interface.
*/
- if ((tsk->flags & (PF_DTRACE|PF_PTRACED)) == PF_DTRACE)
+ if ((tsk->ptrace & (PT_DTRACE|PT_PTRACED)) == PT_DTRACE)
goto clear_TF;
}
@@ -586,13 +586,13 @@
{
struct task_struct * task;
siginfo_t info;
+ unsigned short cwd, swd;
/*
- * Save the info for the exception handler
- * (this will also clear the error)
+ * Save the info for the exception handler and clear the error.
*/
task = current;
- save_fpu(task);
+ save_init_fpu(task);
task->thread.trap_no = 16;
task->thread.error_code = 0;
info.si_signo = SIGFPE;
@@ -609,9 +609,9 @@
* and it will suffer the consequences since we won't be able to
* fully reproduce the context of the exception
*/
- switch(((~task->thread.i387.hard.cwd) &
- task->thread.i387.hard.swd & 0x3f) |
- (task->thread.i387.hard.swd & 0x240)) {
+ cwd = get_fpu_cwd(task);
+ swd = get_fpu_swd(task);
+ switch (((~cwd) & swd & 0x3f) | (swd & 0x240)) {
case 0x000:
default:
break;
@@ -643,6 +643,79 @@
math_error((void *)regs->eip);
}
+void simd_math_error(void *eip)
+{
+ struct task_struct * task;
+ siginfo_t info;
+ unsigned short mxcsr;
+
+ /*
+ * Save the info for the exception handler and clear the error.
+ */
+ task = current;
+ save_init_fpu(task);
+ load_mxcsr(0x1f80);
+ task->thread.trap_no = 19;
+ task->thread.error_code = 0;
+ info.si_signo = SIGFPE;
+ info.si_errno = 0;
+ info.si_code = __SI_FAULT;
+ info.si_addr = eip;
+ /*
+ * The SIMD FPU exceptions are handled a little differently, as there
+ * is only a single status/control register. Thus, to determine which
+ * unmasked exception was caught we must mask the exception mask bits
+ * at 0x1f80, and then use these to mask the exception bits at 0x3f.
+ */
+ mxcsr = get_fpu_mxcsr(task);
+ switch (~((mxcsr & 0x1f80) >> 7) & (mxcsr & 0x3f)) {
+ case 0x000:
+ default:
+ break;
+ case 0x001: /* Invalid Op */
+ info.si_code = FPE_FLTINV;
+ break;
+ case 0x002: /* Denormalize */
+ case 0x010: /* Underflow */
+ info.si_code = FPE_FLTUND;
+ break;
+ case 0x004: /* Zero Divide */
+ info.si_code = FPE_FLTDIV;
+ break;
+ case 0x008: /* Overflow */
+ info.si_code = FPE_FLTOVF;
+ break;
+ case 0x020: /* Precision */
+ info.si_code = FPE_FLTRES;
+ break;
+ }
+ force_sig_info(SIGFPE, &info, task);
+}
+
+asmlinkage void do_simd_coprocessor_error(struct pt_regs * regs,
+ long error_code)
+{
+ if (cpu_has_xmm) {
+ /* Handle SIMD FPU exceptions on PIII+ processors. */
+ ignore_irq13 = 1;
+ simd_math_error((void *)regs->eip);
+ } else {
+ /*
+ * Handle strange cache flush from user space exception
+ * in all other cases. This is undocumented behaviour.
+ */
+ if (regs->eflags & VM_MASK) {
+ handle_vm86_fault((struct kernel_vm86_regs *)regs,
+ error_code);
+ return;
+ }
+ die_if_kernel("cache flush denied", regs, error_code);
+ current->thread.trap_no = 19;
+ current->thread.error_code = error_code;
+ force_sig(SIGSEGV, current);
+ }
+}
+
asmlinkage void do_spurious_interrupt_bug(struct pt_regs * regs,
long error_code)
{
@@ -663,17 +736,16 @@
{
__asm__ __volatile__("clts"); /* Allow maths ops (or we recurse) */
- if(current->used_math)
- i387_restore_hard(current->thread.i387);
- else
- {
+ if (current->used_math) {
+ restore_fpu(current);
+ } else {
/*
* Our first FPU usage, clean the chip.
*/
__asm__("fninit");
current->used_math = 1;
}
- current->flags|=PF_USEDFPU; /* So we fnsave on switch_to() */
+ current->flags |= PF_USEDFPU; /* So we fnsave on switch_to() */
}
#ifndef CONFIG_MATH_EMULATION
@@ -907,7 +979,7 @@
set_trap_gate(15,&spurious_interrupt_bug);
set_trap_gate(16,&coprocessor_error);
set_trap_gate(17,&alignment_check);
- set_trap_gate(19,&xmm_fault);
+ set_trap_gate(19,&simd_coprocessor_error);
set_system_gate(SYSCALL_VECTOR,&system_call);
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)