X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Fx86_64%2Fkernel%2Ftraps.c;h=dd879d5fe4892957de480b488112fc73b47502f0;hb=987b0145d94eecf292d8b301228356f44611ab7c;hp=584f5dd71fd2dc3ccaa6a6bd85d6c785f4981b23;hpb=f7ed79d23a47594e7834d66a8f14449796d4f3e6;p=linux-2.6.git diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c index 584f5dd71..dd879d5fe 100644 --- a/arch/x86_64/kernel/traps.c +++ b/arch/x86_64/kernel/traps.c @@ -48,6 +48,8 @@ #include #include +extern struct gate_struct idt_table[256]; + asmlinkage void divide_error(void); asmlinkage void debug(void); asmlinkage void nmi(void); @@ -70,22 +72,18 @@ asmlinkage void alignment_check(void); asmlinkage void machine_check(void); asmlinkage void spurious_interrupt_bug(void); -ATOMIC_NOTIFIER_HEAD(die_chain); - -extern char last_sysfs_file[]; +struct notifier_block *die_chain; +static DEFINE_SPINLOCK(die_notifier_lock); int register_die_notifier(struct notifier_block *nb) { - vmalloc_sync_all(); - return atomic_notifier_chain_register(&die_chain, nb); -} -EXPORT_SYMBOL(register_die_notifier); - -int unregister_die_notifier(struct notifier_block *nb) -{ - return atomic_notifier_chain_unregister(&die_chain, 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; } -EXPORT_SYMBOL(unregister_die_notifier); static inline void conditional_sti(struct pt_regs *regs) { @@ -104,8 +102,6 @@ static inline void preempt_conditional_cli(struct pt_regs *regs) { if (regs->eflags & X86_EFLAGS_IF) local_irq_disable(); - /* Make sure to not schedule here because we could be running - on an exception stack. */ preempt_enable_no_resched(); } @@ -127,7 +123,7 @@ int printk_address(unsigned long address) if (!modname) modname = delim = ""; return printk("<%016lx>{%s%s%s%s%+ld}", - address, delim, modname, delim, symname, offset); + address,delim,modname,delim,symname,offset); } #else int printk_address(unsigned long address) @@ -340,12 +336,13 @@ void show_registers(struct pt_regs *regs) show_stack(NULL, (unsigned long*)rsp); printk("\nCode: "); - if (regs->rip < PAGE_OFFSET) + if(regs->rip < PAGE_OFFSET) goto bad; - for (i=0; i<20; i++) { + for(i=0;i<20;i++) + { unsigned char c; - if (__get_user(c, &((unsigned char*)regs->rip)[i])) { + if(__get_user(c, &((unsigned char*)regs->rip)[i])) { bad: printk(" Bad RIP value."); break; @@ -390,7 +387,6 @@ void out_of_line_bug(void) static DEFINE_SPINLOCK(die_lock); static int die_owner = -1; -static unsigned int die_nest_count; unsigned __kprobes long oops_begin(void) { @@ -405,7 +401,6 @@ unsigned __kprobes long oops_begin(void) else spin_lock(&die_lock); } - die_nest_count++; die_owner = cpu; console_verbose(); bust_spinlocks(1); @@ -416,13 +411,7 @@ void __kprobes oops_end(unsigned long flags) { die_owner = -1; bust_spinlocks(0); - die_nest_count--; - if (die_nest_count) - /* We still own the lock */ - local_irq_restore(flags); - else - /* Nest count reaches zero, release the lock. */ - spin_unlock_irqrestore(&die_lock, flags); + spin_unlock_irqrestore(&die_lock, flags); if (panic_on_oops) panic("Oops"); } @@ -441,9 +430,6 @@ void __kprobes __die(const char * str, struct pt_regs * regs, long err) printk("DEBUG_PAGEALLOC"); #endif printk("\n"); -#ifdef CONFIG_SYSFS - printk(KERN_ALERT "last sysfs file: %s\n", last_sysfs_file); -#endif notify_die(DIE_OOPS, str, regs, err, current->thread.trap_no, SIGSEGV); show_registers(regs); /* Executive summary in case the oops scrolled away */ @@ -480,8 +466,6 @@ void __kprobes die_nmi(char *str, struct pt_regs *regs) panic("nmi watchdog"); printk("console shuts up ...\n"); oops_end(flags); - nmi_exit(); - local_irq_enable(); do_exit(SIGSEGV); } @@ -491,6 +475,8 @@ static void __kprobes do_trap(int trapnr, int signr, char *str, { struct task_struct *tsk = current; + conditional_sti(regs); + tsk->thread.error_code = error_code; tsk->thread.trap_no = trapnr; @@ -499,7 +485,7 @@ static void __kprobes do_trap(int trapnr, int signr, char *str, printk(KERN_INFO "%s[%d] trap %s rip:%lx rsp:%lx error:%lx\n", tsk->comm, tsk->pid, str, - regs->rip, regs->rsp, error_code); + regs->rip,regs->rsp,error_code); if (info) force_sig_info(signr, info, tsk); @@ -513,9 +499,9 @@ static void __kprobes do_trap(int trapnr, int signr, char *str, { const struct exception_table_entry *fixup; fixup = search_exception_tables(regs->rip); - if (fixup) + if (fixup) { regs->rip = fixup->fixup; - else + } else die(str, regs, error_code); return; } @@ -527,7 +513,6 @@ asmlinkage void do_##name(struct pt_regs * regs, long error_code) \ if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \ == NOTIFY_STOP) \ return; \ - conditional_sti(regs); \ do_trap(trapnr, signr, str, regs, error_code, NULL); \ } @@ -542,7 +527,6 @@ asmlinkage void do_##name(struct pt_regs * regs, long error_code) \ if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \ == NOTIFY_STOP) \ return; \ - conditional_sti(regs); \ do_trap(trapnr, signr, str, regs, error_code, &info); \ } @@ -556,17 +540,7 @@ DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS) DO_ERROR(11, SIGBUS, "segment not present", segment_not_present) DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, 0) DO_ERROR(18, SIGSEGV, "reserved", reserved) - -/* Runs on IST stack */ -asmlinkage void do_stack_segment(struct pt_regs *regs, long error_code) -{ - if (notify_die(DIE_TRAP, "stack segment", regs, error_code, - 12, SIGBUS) == NOTIFY_STOP) - return; - preempt_conditional_sti(regs); - do_trap(12, SIGBUS, "stack segment", regs, error_code, NULL); - preempt_conditional_cli(regs); -} +DO_ERROR(12, SIGBUS, "stack segment", stack_segment) asmlinkage void do_double_fault(struct pt_regs * regs, long error_code) { @@ -600,7 +574,7 @@ asmlinkage void __kprobes do_general_protection(struct pt_regs * regs, printk(KERN_INFO "%s[%d] general protection rip:%lx rsp:%lx error:%lx\n", tsk->comm, tsk->pid, - regs->rip, regs->rsp, error_code); + regs->rip,regs->rsp,error_code); force_sig(SIGSEGV, tsk); return; @@ -700,9 +674,8 @@ asmlinkage void __kprobes do_int3(struct pt_regs * regs, long error_code) if (notify_die(DIE_INT3, "int3", regs, error_code, 3, SIGTRAP) == NOTIFY_STOP) { return; } - preempt_conditional_sti(regs); do_trap(3, SIGTRAP, "int3", regs, error_code, NULL); - preempt_conditional_cli(regs); + return; } /* Help handler running on IST stack to switch back to user stack @@ -1007,14 +980,14 @@ void __init trap_init(void) static int __init oops_dummy(char *s) { panic_on_oops = 1; - return 1; + return -1; } __setup("oops=", oops_dummy); static int __init kstack_setup(char *s) { kstack_depth_to_print = simple_strtoul(s,NULL,0); - return 1; + return 0; } __setup("kstack=", kstack_setup);