diff options
author | Jan Beulich <jbeulich@novell.com> | 2008-01-30 07:31:23 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-01-30 07:31:23 -0500 |
commit | 22f5991c85dec1281cce5c8df9ee92b43b1738c8 (patch) | |
tree | 9a0814a5b3c37b3752ee7dfcc6f6b2b6793dfe91 | |
parent | d88879b2d0225da3ba460bbdb8361bb049653671 (diff) |
x86-64: honor notify_die() returning NOTIFY_STOP
This requires making die() return a value, making its callers honor
this (and be prepared that it may return), and making oops_end() have
two additional parameters.
Signed-off-by: Jan Beulich <jbeulich@novell.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
-rw-r--r-- | arch/x86/kernel/cpu/mcheck/mce_64.c | 8 | ||||
-rw-r--r-- | arch/x86/kernel/traps_64.c | 23 | ||||
-rw-r--r-- | arch/x86/mm/fault_64.c | 12 | ||||
-rw-r--r-- | include/asm-x86/kdebug.h | 4 |
4 files changed, 27 insertions, 20 deletions
diff --git a/arch/x86/kernel/cpu/mcheck/mce_64.c b/arch/x86/kernel/cpu/mcheck/mce_64.c index 8cd47fe2ef2c..bc6e35153d83 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_64.c +++ b/arch/x86/kernel/cpu/mcheck/mce_64.c | |||
@@ -192,10 +192,10 @@ void do_machine_check(struct pt_regs * regs, long error_code) | |||
192 | 192 | ||
193 | atomic_inc(&mce_entry); | 193 | atomic_inc(&mce_entry); |
194 | 194 | ||
195 | if (regs) | 195 | if ((regs |
196 | notify_die(DIE_NMI, "machine check", regs, error_code, 18, | 196 | && notify_die(DIE_NMI, "machine check", regs, error_code, |
197 | SIGKILL); | 197 | 18, SIGKILL) == NOTIFY_STOP) |
198 | if (!banks) | 198 | || !banks) |
199 | goto out2; | 199 | goto out2; |
200 | 200 | ||
201 | memset(&m, 0, sizeof(struct mce)); | 201 | memset(&m, 0, sizeof(struct mce)); |
diff --git a/arch/x86/kernel/traps_64.c b/arch/x86/kernel/traps_64.c index 1a12a81fdb1b..cf90ceb48f5f 100644 --- a/arch/x86/kernel/traps_64.c +++ b/arch/x86/kernel/traps_64.c | |||
@@ -488,7 +488,7 @@ unsigned __kprobes long oops_begin(void) | |||
488 | return flags; | 488 | return flags; |
489 | } | 489 | } |
490 | 490 | ||
491 | void __kprobes oops_end(unsigned long flags) | 491 | void __kprobes oops_end(unsigned long flags, struct pt_regs *regs, int signr) |
492 | { | 492 | { |
493 | die_owner = -1; | 493 | die_owner = -1; |
494 | bust_spinlocks(0); | 494 | bust_spinlocks(0); |
@@ -497,12 +497,17 @@ void __kprobes oops_end(unsigned long flags) | |||
497 | /* Nest count reaches zero, release the lock. */ | 497 | /* Nest count reaches zero, release the lock. */ |
498 | __raw_spin_unlock(&die_lock); | 498 | __raw_spin_unlock(&die_lock); |
499 | raw_local_irq_restore(flags); | 499 | raw_local_irq_restore(flags); |
500 | if (!regs) { | ||
501 | oops_exit(); | ||
502 | return; | ||
503 | } | ||
500 | if (panic_on_oops) | 504 | if (panic_on_oops) |
501 | panic("Fatal exception"); | 505 | panic("Fatal exception"); |
502 | oops_exit(); | 506 | oops_exit(); |
507 | do_exit(signr); | ||
503 | } | 508 | } |
504 | 509 | ||
505 | void __kprobes __die(const char * str, struct pt_regs * regs, long err) | 510 | int __kprobes __die(const char * str, struct pt_regs * regs, long err) |
506 | { | 511 | { |
507 | static int die_counter; | 512 | static int die_counter; |
508 | printk(KERN_EMERG "%s: %04lx [%u] ", str, err & 0xffff,++die_counter); | 513 | printk(KERN_EMERG "%s: %04lx [%u] ", str, err & 0xffff,++die_counter); |
@@ -516,7 +521,8 @@ void __kprobes __die(const char * str, struct pt_regs * regs, long err) | |||
516 | printk("DEBUG_PAGEALLOC"); | 521 | printk("DEBUG_PAGEALLOC"); |
517 | #endif | 522 | #endif |
518 | printk("\n"); | 523 | printk("\n"); |
519 | notify_die(DIE_OOPS, str, regs, err, current->thread.trap_no, SIGSEGV); | 524 | if (notify_die(DIE_OOPS, str, regs, err, current->thread.trap_no, SIGSEGV) == NOTIFY_STOP) |
525 | return 1; | ||
520 | show_registers(regs); | 526 | show_registers(regs); |
521 | add_taint(TAINT_DIE); | 527 | add_taint(TAINT_DIE); |
522 | /* Executive summary in case the oops scrolled away */ | 528 | /* Executive summary in case the oops scrolled away */ |
@@ -525,6 +531,7 @@ void __kprobes __die(const char * str, struct pt_regs * regs, long err) | |||
525 | printk(" RSP <%016lx>\n", regs->sp); | 531 | printk(" RSP <%016lx>\n", regs->sp); |
526 | if (kexec_should_crash(current)) | 532 | if (kexec_should_crash(current)) |
527 | crash_kexec(regs); | 533 | crash_kexec(regs); |
534 | return 0; | ||
528 | } | 535 | } |
529 | 536 | ||
530 | void die(const char * str, struct pt_regs * regs, long err) | 537 | void die(const char * str, struct pt_regs * regs, long err) |
@@ -534,9 +541,9 @@ void die(const char * str, struct pt_regs * regs, long err) | |||
534 | if (!user_mode(regs)) | 541 | if (!user_mode(regs)) |
535 | report_bug(regs->ip, regs); | 542 | report_bug(regs->ip, regs); |
536 | 543 | ||
537 | __die(str, regs, err); | 544 | if (__die(str, regs, err)) |
538 | oops_end(flags); | 545 | regs = NULL; |
539 | do_exit(SIGSEGV); | 546 | oops_end(flags, regs, SIGSEGV); |
540 | } | 547 | } |
541 | 548 | ||
542 | void __kprobes die_nmi(char *str, struct pt_regs *regs, int do_panic) | 549 | void __kprobes die_nmi(char *str, struct pt_regs *regs, int do_panic) |
@@ -553,10 +560,10 @@ void __kprobes die_nmi(char *str, struct pt_regs *regs, int do_panic) | |||
553 | crash_kexec(regs); | 560 | crash_kexec(regs); |
554 | if (do_panic || panic_on_oops) | 561 | if (do_panic || panic_on_oops) |
555 | panic("Non maskable interrupt"); | 562 | panic("Non maskable interrupt"); |
556 | oops_end(flags); | 563 | oops_end(flags, NULL, SIGBUS); |
557 | nmi_exit(); | 564 | nmi_exit(); |
558 | local_irq_enable(); | 565 | local_irq_enable(); |
559 | do_exit(SIGSEGV); | 566 | do_exit(SIGBUS); |
560 | } | 567 | } |
561 | 568 | ||
562 | static void __kprobes do_trap(int trapnr, int signr, char *str, | 569 | static void __kprobes do_trap(int trapnr, int signr, char *str, |
diff --git a/arch/x86/mm/fault_64.c b/arch/x86/mm/fault_64.c index 162050d4e5a3..121c7bda6297 100644 --- a/arch/x86/mm/fault_64.c +++ b/arch/x86/mm/fault_64.c | |||
@@ -227,9 +227,9 @@ static noinline void pgtable_bad(unsigned long address, struct pt_regs *regs, | |||
227 | tsk->thread.cr2 = address; | 227 | tsk->thread.cr2 = address; |
228 | tsk->thread.trap_no = 14; | 228 | tsk->thread.trap_no = 14; |
229 | tsk->thread.error_code = error_code; | 229 | tsk->thread.error_code = error_code; |
230 | __die("Bad pagetable", regs, error_code); | 230 | if (__die("Bad pagetable", regs, error_code)) |
231 | oops_end(flags); | 231 | regs = NULL; |
232 | do_exit(SIGKILL); | 232 | oops_end(flags, regs, SIGKILL); |
233 | } | 233 | } |
234 | 234 | ||
235 | /* | 235 | /* |
@@ -541,11 +541,11 @@ no_context: | |||
541 | tsk->thread.cr2 = address; | 541 | tsk->thread.cr2 = address; |
542 | tsk->thread.trap_no = 14; | 542 | tsk->thread.trap_no = 14; |
543 | tsk->thread.error_code = error_code; | 543 | tsk->thread.error_code = error_code; |
544 | __die("Oops", regs, error_code); | 544 | if (__die("Oops", regs, error_code)) |
545 | regs = NULL; | ||
545 | /* Executive summary in case the body of the oops scrolled away */ | 546 | /* Executive summary in case the body of the oops scrolled away */ |
546 | printk(KERN_EMERG "CR2: %016lx\n", address); | 547 | printk(KERN_EMERG "CR2: %016lx\n", address); |
547 | oops_end(flags); | 548 | oops_end(flags, regs, SIGKILL); |
548 | do_exit(SIGKILL); | ||
549 | 549 | ||
550 | /* | 550 | /* |
551 | * We ran out of memory, or some other thing happened to us that made | 551 | * We ran out of memory, or some other thing happened to us that made |
diff --git a/include/asm-x86/kdebug.h b/include/asm-x86/kdebug.h index 49e5c91d490c..a5e5e3b7eb23 100644 --- a/include/asm-x86/kdebug.h +++ b/include/asm-x86/kdebug.h | |||
@@ -25,7 +25,7 @@ enum die_val { | |||
25 | extern void early_printk(const char *fmt, ...) __attribute__((format(printf,1,2))); | 25 | extern void early_printk(const char *fmt, ...) __attribute__((format(printf,1,2))); |
26 | extern void printk_address(unsigned long address); | 26 | extern void printk_address(unsigned long address); |
27 | extern void die(const char *,struct pt_regs *,long); | 27 | extern void die(const char *,struct pt_regs *,long); |
28 | extern void __die(const char *,struct pt_regs *,long); | 28 | extern int __must_check __die(const char *, struct pt_regs *, long); |
29 | extern void show_registers(struct pt_regs *regs); | 29 | extern void show_registers(struct pt_regs *regs); |
30 | extern void __show_registers(struct pt_regs *, int all); | 30 | extern void __show_registers(struct pt_regs *, int all); |
31 | extern void show_trace(struct task_struct *, struct pt_regs *, unsigned long *); | 31 | extern void show_trace(struct task_struct *, struct pt_regs *, unsigned long *); |
@@ -33,6 +33,6 @@ extern void __show_regs(struct pt_regs *regs); | |||
33 | extern void show_regs(struct pt_regs *regs); | 33 | extern void show_regs(struct pt_regs *regs); |
34 | extern void dump_pagetable(unsigned long); | 34 | extern void dump_pagetable(unsigned long); |
35 | extern unsigned long oops_begin(void); | 35 | extern unsigned long oops_begin(void); |
36 | extern void oops_end(unsigned long); | 36 | extern void oops_end(unsigned long, struct pt_regs *, int signr); |
37 | 37 | ||
38 | #endif | 38 | #endif |