X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Fx86_64%2Fkernel%2Ftraps.c;h=72e672ef3260f0f1e5f1e237ce1fe0f37e379feb;hb=6a77f38946aaee1cd85eeec6cf4229b204c15071;hp=c0a31a4add9e4389cda6bbf25f74c09b8d54a49a;hpb=87fc8d1bb10cd459024a742c6a10961fefcef18f;p=linux-2.6.git diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c index c0a31a4ad..72e672ef3 100644 --- a/arch/x86_64/kernel/traps.c +++ b/arch/x86_64/kernel/traps.c @@ -43,9 +43,11 @@ #include #include #include +#include #include + extern struct gate_struct idt_table[256]; asmlinkage void divide_error(void); @@ -72,6 +74,17 @@ asmlinkage void spurious_interrupt_bug(void); asmlinkage void call_debug(void); struct notifier_block *die_chain; +static DEFINE_SPINLOCK(die_notifier_lock); + +int register_die_notifier(struct notifier_block *nb) +{ + int err = 0; + unsigned long flags; + spin_lock_irqsave(&die_notifier_lock, flags); + err = notifier_chain_register(&die_chain, nb); + spin_unlock_irqrestore(&die_notifier_lock, flags); + return err; +} static inline void conditional_sti(struct pt_regs *regs) { @@ -311,7 +324,7 @@ void out_of_line_bug(void) BUG(); } -static spinlock_t die_lock = SPIN_LOCK_UNLOCKED; +static DEFINE_SPINLOCK(die_lock); static int die_owner = -1; void oops_begin(void) @@ -376,13 +389,20 @@ static inline void die_if_kernel(const char * str, struct pt_regs * regs, long e die(str, regs, err); } -static inline unsigned long get_cr2(void) +void die_nmi(char *str, struct pt_regs *regs) { - unsigned long address; - - /* get the address */ - __asm__("movq %%cr2,%0":"=r" (address)); - return address; + oops_begin(); + /* + * We are in trouble anyway, lets at least try + * to get a message out. + */ + printk(str, safe_smp_processor_id()); + show_registers(regs); + if (panic_on_timeout || panic_on_oops) + panic("nmi watchdog"); + printk("console shuts up ...\n"); + oops_end(); + do_exit(SIGSEGV); } static void do_trap(int trapnr, int signr, char *str, @@ -458,7 +478,6 @@ asmlinkage void do_##name(struct pt_regs * regs, long error_code) \ } DO_ERROR_INFO( 0, SIGFPE, "divide error", divide_error, FPE_INTDIV, regs->rip) -DO_ERROR( 3, SIGTRAP, "int3", int3); DO_ERROR( 4, SIGSEGV, "overflow", overflow) DO_ERROR( 5, SIGSEGV, "bounds", bounds) DO_ERROR_INFO( 6, SIGILL, "invalid operand", invalid_op, ILL_ILLOPN, regs->rip) @@ -528,8 +547,9 @@ asmlinkage void do_general_protection(struct pt_regs * regs, long error_code) regs->rip = fixup->fixup; return; } - notify_die(DIE_GPF, "general protection fault", regs, error_code, - 13, SIGSEGV); + if (notify_die(DIE_GPF, "general protection fault", regs, + error_code, 13, SIGSEGV) == NOTIFY_STOP) + return; die("general protection fault", regs, error_code); } } @@ -563,9 +583,13 @@ static void unknown_nmi_error(unsigned char reason, struct pt_regs * regs) printk("Do you have a strange power saving mode enabled?\n"); } -asmlinkage void default_do_nmi(struct pt_regs * regs) +asmlinkage void default_do_nmi(struct pt_regs *regs) { - unsigned char reason = inb(0x61); + unsigned char reason = 0; + + /* Only the BSP gets external NMIs from the system. */ + if (!smp_processor_id()) + reason = get_nmi_reason(); if (!(reason & 0xc0)) { if (notify_die(DIE_NMI_IPI, "nmi_ipi", regs, reason, 0, SIGINT) @@ -586,6 +610,9 @@ asmlinkage void default_do_nmi(struct pt_regs * regs) } if (notify_die(DIE_NMI, "nmi", regs, reason, 0, SIGINT) == NOTIFY_STOP) return; + + /* AK: following checks seem to be broken on modern chipsets. FIXME */ + if (reason & 0x80) mem_parity_error(reason, regs); if (reason & 0x40) @@ -601,6 +628,15 @@ asmlinkage void default_do_nmi(struct pt_regs * regs) inb(0x71); /* dummy */ } +asmlinkage void do_int3(struct pt_regs * regs, long error_code) +{ + if (notify_die(DIE_INT3, "int3", regs, error_code, 3, SIGTRAP) == NOTIFY_STOP) { + return; + } + do_trap(3, SIGTRAP, "int3", regs, error_code, NULL); + return; +} + /* runs on IST stack. */ asmlinkage void *do_debug(struct pt_regs * regs, unsigned long error_code) { @@ -630,6 +666,10 @@ asmlinkage void *do_debug(struct pt_regs * regs, unsigned long error_code) asm("movq %%db6,%0" : "=r" (condition)); + if (notify_die(DIE_DEBUG, "debug", regs, condition, error_code, + SIGTRAP) == NOTIFY_STOP) { + return regs; + } conditional_sti(regs); /* Mask out spurious debug traps due to lazy DR7 setting */ @@ -642,7 +682,9 @@ asmlinkage void *do_debug(struct pt_regs * regs, unsigned long error_code) tsk->thread.debugreg6 = condition; /* Mask out spurious TF errors due to lazy TF clearing */ - if (condition & DR_STEP) { + if ((condition & DR_STEP) && + (notify_die(DIE_DEBUGSTEP, "debugstep", regs, condition, + 1, SIGTRAP) != NOTIFY_STOP)) { /* * The TF error should be masked out only if the current * process is not traced and if the TRAP flag has been set @@ -834,6 +876,10 @@ asmlinkage void do_spurious_interrupt_bug(struct pt_regs * regs) { } +asmlinkage void __attribute__((weak)) smp_thermal_interrupt(void) +{ +} + /* * 'math_state_restore()' saves the current math information in the * old math state array, and gets the new ones from the current task @@ -846,7 +892,7 @@ asmlinkage void math_state_restore(void) struct task_struct *me = current; clts(); /* Allow maths ops (or we recurse) */ - if (!me->used_math) + if (!used_math()) init_fpu(me); restore_fpu_checking(&me->thread.i387.fxsave); me->thread_info->status |= TS_USEDFPU; @@ -862,8 +908,8 @@ void __init trap_init(void) set_intr_gate(0,÷_error); set_intr_gate_ist(1,&debug,DEBUG_STACK); set_intr_gate_ist(2,&nmi,NMI_STACK); - set_system_gate(3,&int3); /* int3-5 can be called from all */ - set_system_gate(4,&overflow); + set_system_gate(3,&int3); + set_system_gate(4,&overflow); /* int4-5 can be called from all */ set_system_gate(5,&bounds); set_intr_gate(6,&invalid_op); set_intr_gate(7,&device_not_available); @@ -877,7 +923,9 @@ void __init trap_init(void) set_intr_gate(15,&spurious_interrupt_bug); set_intr_gate(16,&coprocessor_error); set_intr_gate(17,&alignment_check); +#ifdef CONFIG_X86_MCE set_intr_gate_ist(18,&machine_check, MCE_STACK); +#endif set_intr_gate(19,&simd_coprocessor_error); #ifdef CONFIG_IA32_EMULATION @@ -900,3 +948,11 @@ static int __init oops_dummy(char *s) return -1; } __setup("oops=", oops_dummy); + +static int __init kstack_setup(char *s) +{ + kstack_depth_to_print = simple_strtoul(s,NULL,0); + return 0; +} +__setup("kstack=", kstack_setup); +