patch-2.4.0-test1 linux/arch/i386/kernel/traps.c
Next file: linux/arch/i386/mm/fault.c
Previous file: linux/arch/i386/kernel/smpboot.c
Back to the patch index
Back to the overall index
- Lines: 220
- Date:
Wed May 24 18:38:26 2000
- Orig file:
v2.3.99-pre9/linux/arch/i386/kernel/traps.c
- Orig date:
Tue May 23 15:31:33 2000
diff -u --recursive --new-file v2.3.99-pre9/linux/arch/i386/kernel/traps.c linux/arch/i386/kernel/traps.c
@@ -2,6 +2,7 @@
* linux/arch/i386/traps.c
*
* Copyright (C) 1991, 1992 Linus Torvalds
+ * FXSAVE/FXRSTOR support by Ingo Molnar, OS exception support by Goutham Rao
*/
/*
@@ -82,6 +83,20 @@
force_sig(signr, tsk); \
}
+#define DO_ERROR_INFO(trapnr, signr, str, name, tsk, sicode, siaddr) \
+asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
+{ \
+ siginfo_t info; \
+ tsk->thread.error_code = error_code; \
+ tsk->thread.trap_no = trapnr; \
+ die_if_no_fixup(str,regs,error_code); \
+ info.si_signo = signr; \
+ info.si_errno = 0; \
+ info.si_code = sicode; \
+ info.si_addr = (void *)siaddr; \
+ force_sig_info(signr, &info, tsk); \
+}
+
#define DO_VM86_ERROR(trapnr, signr, str, name, tsk) \
asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
{ \
@@ -99,6 +114,28 @@
unlock_kernel(); \
}
+#define DO_VM86_ERROR_INFO(trapnr, signr, str, name, tsk, sicode, siaddr) \
+asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
+{ \
+ siginfo_t info; \
+ lock_kernel(); \
+ if (regs->eflags & VM_MASK) { \
+ if (!handle_vm86_trap((struct kernel_vm86_regs *) regs, error_code, trapnr)) \
+ goto out; \
+ /* else fall through */ \
+ } \
+ tsk->thread.error_code = error_code; \
+ tsk->thread.trap_no = trapnr; \
+ info.si_signo = signr; \
+ info.si_errno = 0; \
+ info.si_code = sicode; \
+ info.si_addr = (void *)siaddr; \
+ force_sig_info(signr, &info, tsk); \
+ die_if_kernel(str,regs,error_code); \
+out: \
+ unlock_kernel(); \
+}
+
void page_exception(void);
asmlinkage void divide_error(void);
@@ -120,6 +157,7 @@
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;
@@ -260,34 +298,29 @@
}
}
-DO_VM86_ERROR( 0, SIGFPE, "divide error", divide_error, current)
+static inline unsigned long get_cr2(void)
+{
+ unsigned long address;
+
+ /* get the address */
+ __asm__("movl %%cr2,%0":"=r" (address));
+ return address;
+}
+
+DO_VM86_ERROR_INFO( 0, SIGFPE, "divide error", divide_error, current, FPE_INTDIV, regs->eip)
DO_VM86_ERROR( 3, SIGTRAP, "int3", int3, current)
DO_VM86_ERROR( 4, SIGSEGV, "overflow", overflow, current)
DO_VM86_ERROR( 5, SIGSEGV, "bounds", bounds, current)
-DO_ERROR( 6, SIGILL, "invalid operand", invalid_op, current)
+DO_ERROR_INFO( 6, SIGILL, "invalid operand", invalid_op, current, ILL_ILLOPN, regs->eip)
DO_VM86_ERROR( 7, SIGSEGV, "device not available", device_not_available, current)
DO_ERROR( 8, SIGSEGV, "double fault", double_fault, current)
DO_ERROR( 9, SIGFPE, "coprocessor segment overrun", coprocessor_segment_overrun, current)
DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS, current)
DO_ERROR(11, SIGBUS, "segment not present", segment_not_present, current)
DO_ERROR(12, SIGBUS, "stack segment", stack_segment, current)
-DO_ERROR(17, SIGSEGV, "alignment check", alignment_check, current)
+DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, current, BUS_ADRALN, get_cr2())
DO_ERROR(18, SIGSEGV, "reserved", reserved, current)
-/* I don't have documents for this but it does seem to cover the cache
- flush from user space exception some people get. */
-DO_ERROR(19, SIGSEGV, "cache flush denied", cache_flush_denied, current)
-
-asmlinkage void cache_flush_denied(struct pt_regs * regs, long error_code)
-{
- 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.error_code = error_code;
- current->thread.trap_no = 19;
- force_sig(SIGSEGV, current);
-}
+DO_VM86_ERROR(19, SIGFPE, "XMM fault", xmm_fault, current)
asmlinkage void do_general_protection(struct pt_regs * regs, long error_code)
{
@@ -485,6 +518,7 @@
{
unsigned int condition;
struct task_struct *tsk = current;
+ siginfo_t info;
__asm__ __volatile__("movl %%db6,%0" : "=r" (condition));
@@ -519,7 +553,11 @@
/* Ok, finally something we can handle */
tsk->thread.trap_no = 1;
tsk->thread.error_code = error_code;
- force_sig(SIGTRAP, tsk);
+ info.si_signo = SIGTRAP;
+ info.si_errno = 0;
+ info.si_code = TRAP_BRKPT;
+ info.si_addr = (void *)regs->eip;
+ force_sig_info(SIGTRAP, &info, tsk);
return;
debug_vm86:
@@ -544,9 +582,10 @@
* the correct behaviour even in the presence of the asynchronous
* IRQ13 behaviour
*/
-void math_error(void)
+void math_error(void *eip)
{
struct task_struct * task;
+ siginfo_t info;
/*
* Save the info for the exception handler
@@ -556,13 +595,52 @@
save_fpu(task);
task->thread.trap_no = 16;
task->thread.error_code = 0;
- force_sig(SIGFPE, task);
+ info.si_signo = SIGFPE;
+ info.si_errno = 0;
+ info.si_code = __SI_FAULT;
+ info.si_addr = eip;
+ /*
+ * (~cwd & swd) will mask out exceptions that are not set to unmasked
+ * status. 0x3f is the exception bits in these regs, 0x200 is the
+ * C1 reg you need in case of a stack fault, 0x040 is the stack
+ * fault bit. We should only be taking one exception at a time,
+ * so if this combination doesn't produce any single exception,
+ * then we have a bad program that isn't syncronizing its FPU usage
+ * 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)) {
+ case 0x000:
+ default:
+ break;
+ case 0x001: /* Invalid Op */
+ case 0x040: /* Stack Fault */
+ case 0x240: /* Stack Fault | Direction */
+ 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_coprocessor_error(struct pt_regs * regs, long error_code)
{
ignore_irq13 = 1;
- math_error();
+ math_error((void *)regs->eip);
}
asmlinkage void do_spurious_interrupt_bug(struct pt_regs * regs,
@@ -586,7 +664,7 @@
__asm__ __volatile__("clts"); /* Allow maths ops (or we recurse) */
if(current->used_math)
- __asm__("frstor %0": :"m" (current->thread.i387));
+ i387_restore_hard(current->thread.i387);
else
{
/*
@@ -829,6 +907,8 @@
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_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)