aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Beulich <jbeulich@novell.com>2008-01-30 07:31:23 -0500
committerIngo Molnar <mingo@elte.hu>2008-01-30 07:31:23 -0500
commit22f5991c85dec1281cce5c8df9ee92b43b1738c8 (patch)
tree9a0814a5b3c37b3752ee7dfcc6f6b2b6793dfe91
parentd88879b2d0225da3ba460bbdb8361bb049653671 (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.c8
-rw-r--r--arch/x86/kernel/traps_64.c23
-rw-r--r--arch/x86/mm/fault_64.c12
-rw-r--r--include/asm-x86/kdebug.h4
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
491void __kprobes oops_end(unsigned long flags) 491void __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
505void __kprobes __die(const char * str, struct pt_regs * regs, long err) 510int __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
530void die(const char * str, struct pt_regs * regs, long err) 537void 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
542void __kprobes die_nmi(char *str, struct pt_regs *regs, int do_panic) 549void __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
562static void __kprobes do_trap(int trapnr, int signr, char *str, 569static 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 {
25extern void early_printk(const char *fmt, ...) __attribute__((format(printf,1,2))); 25extern void early_printk(const char *fmt, ...) __attribute__((format(printf,1,2)));
26extern void printk_address(unsigned long address); 26extern void printk_address(unsigned long address);
27extern void die(const char *,struct pt_regs *,long); 27extern void die(const char *,struct pt_regs *,long);
28extern void __die(const char *,struct pt_regs *,long); 28extern int __must_check __die(const char *, struct pt_regs *, long);
29extern void show_registers(struct pt_regs *regs); 29extern void show_registers(struct pt_regs *regs);
30extern void __show_registers(struct pt_regs *, int all); 30extern void __show_registers(struct pt_regs *, int all);
31extern void show_trace(struct task_struct *, struct pt_regs *, unsigned long *); 31extern void show_trace(struct task_struct *, struct pt_regs *, unsigned long *);
@@ -33,6 +33,6 @@ extern void __show_regs(struct pt_regs *regs);
33extern void show_regs(struct pt_regs *regs); 33extern void show_regs(struct pt_regs *regs);
34extern void dump_pagetable(unsigned long); 34extern void dump_pagetable(unsigned long);
35extern unsigned long oops_begin(void); 35extern unsigned long oops_begin(void);
36extern void oops_end(unsigned long); 36extern void oops_end(unsigned long, struct pt_regs *, int signr);
37 37
38#endif 38#endif