Commit 22f5991c authored by Jan Beulich's avatar Jan Beulich Committed by Ingo Molnar

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: default avatarJan Beulich <jbeulich@novell.com>
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
parent d88879b2
...@@ -192,10 +192,10 @@ void do_machine_check(struct pt_regs * regs, long error_code) ...@@ -192,10 +192,10 @@ void do_machine_check(struct pt_regs * regs, long error_code)
atomic_inc(&mce_entry); atomic_inc(&mce_entry);
if (regs) if ((regs
notify_die(DIE_NMI, "machine check", regs, error_code, 18, && notify_die(DIE_NMI, "machine check", regs, error_code,
SIGKILL); 18, SIGKILL) == NOTIFY_STOP)
if (!banks) || !banks)
goto out2; goto out2;
memset(&m, 0, sizeof(struct mce)); memset(&m, 0, sizeof(struct mce));
......
...@@ -488,7 +488,7 @@ unsigned __kprobes long oops_begin(void) ...@@ -488,7 +488,7 @@ unsigned __kprobes long oops_begin(void)
return flags; return flags;
} }
void __kprobes oops_end(unsigned long flags) void __kprobes oops_end(unsigned long flags, struct pt_regs *regs, int signr)
{ {
die_owner = -1; die_owner = -1;
bust_spinlocks(0); bust_spinlocks(0);
...@@ -497,12 +497,17 @@ void __kprobes oops_end(unsigned long flags) ...@@ -497,12 +497,17 @@ void __kprobes oops_end(unsigned long flags)
/* Nest count reaches zero, release the lock. */ /* Nest count reaches zero, release the lock. */
__raw_spin_unlock(&die_lock); __raw_spin_unlock(&die_lock);
raw_local_irq_restore(flags); raw_local_irq_restore(flags);
if (!regs) {
oops_exit();
return;
}
if (panic_on_oops) if (panic_on_oops)
panic("Fatal exception"); panic("Fatal exception");
oops_exit(); oops_exit();
do_exit(signr);
} }
void __kprobes __die(const char * str, struct pt_regs * regs, long err) int __kprobes __die(const char * str, struct pt_regs * regs, long err)
{ {
static int die_counter; static int die_counter;
printk(KERN_EMERG "%s: %04lx [%u] ", str, err & 0xffff,++die_counter); 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,7 +521,8 @@ void __kprobes __die(const char * str, struct pt_regs * regs, long err)
printk("DEBUG_PAGEALLOC"); printk("DEBUG_PAGEALLOC");
#endif #endif
printk("\n"); printk("\n");
notify_die(DIE_OOPS, str, regs, err, current->thread.trap_no, SIGSEGV); if (notify_die(DIE_OOPS, str, regs, err, current->thread.trap_no, SIGSEGV) == NOTIFY_STOP)
return 1;
show_registers(regs); show_registers(regs);
add_taint(TAINT_DIE); add_taint(TAINT_DIE);
/* Executive summary in case the oops scrolled away */ /* 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,6 +531,7 @@ void __kprobes __die(const char * str, struct pt_regs * regs, long err)
printk(" RSP <%016lx>\n", regs->sp); printk(" RSP <%016lx>\n", regs->sp);
if (kexec_should_crash(current)) if (kexec_should_crash(current))
crash_kexec(regs); crash_kexec(regs);
return 0;
} }
void die(const char * str, struct pt_regs * regs, long err) 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,9 +541,9 @@ void die(const char * str, struct pt_regs * regs, long err)
if (!user_mode(regs)) if (!user_mode(regs))
report_bug(regs->ip, regs); report_bug(regs->ip, regs);
__die(str, regs, err); if (__die(str, regs, err))
oops_end(flags); regs = NULL;
do_exit(SIGSEGV); oops_end(flags, regs, SIGSEGV);
} }
void __kprobes die_nmi(char *str, struct pt_regs *regs, int do_panic) 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,10 +560,10 @@ void __kprobes die_nmi(char *str, struct pt_regs *regs, int do_panic)
crash_kexec(regs); crash_kexec(regs);
if (do_panic || panic_on_oops) if (do_panic || panic_on_oops)
panic("Non maskable interrupt"); panic("Non maskable interrupt");
oops_end(flags); oops_end(flags, NULL, SIGBUS);
nmi_exit(); nmi_exit();
local_irq_enable(); local_irq_enable();
do_exit(SIGSEGV); do_exit(SIGBUS);
} }
static void __kprobes do_trap(int trapnr, int signr, char *str, static void __kprobes do_trap(int trapnr, int signr, char *str,
......
...@@ -227,9 +227,9 @@ static noinline void pgtable_bad(unsigned long address, struct pt_regs *regs, ...@@ -227,9 +227,9 @@ static noinline void pgtable_bad(unsigned long address, struct pt_regs *regs,
tsk->thread.cr2 = address; tsk->thread.cr2 = address;
tsk->thread.trap_no = 14; tsk->thread.trap_no = 14;
tsk->thread.error_code = error_code; tsk->thread.error_code = error_code;
__die("Bad pagetable", regs, error_code); if (__die("Bad pagetable", regs, error_code))
oops_end(flags); regs = NULL;
do_exit(SIGKILL); oops_end(flags, regs, SIGKILL);
} }
/* /*
...@@ -541,11 +541,11 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs, ...@@ -541,11 +541,11 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
tsk->thread.cr2 = address; tsk->thread.cr2 = address;
tsk->thread.trap_no = 14; tsk->thread.trap_no = 14;
tsk->thread.error_code = error_code; tsk->thread.error_code = error_code;
__die("Oops", regs, error_code); if (__die("Oops", regs, error_code))
regs = NULL;
/* Executive summary in case the body of the oops scrolled away */ /* Executive summary in case the body of the oops scrolled away */
printk(KERN_EMERG "CR2: %016lx\n", address); printk(KERN_EMERG "CR2: %016lx\n", address);
oops_end(flags); oops_end(flags, regs, SIGKILL);
do_exit(SIGKILL);
/* /*
* We ran out of memory, or some other thing happened to us that made * We ran out of memory, or some other thing happened to us that made
......
...@@ -25,7 +25,7 @@ enum die_val { ...@@ -25,7 +25,7 @@ enum die_val {
extern void early_printk(const char *fmt, ...) __attribute__((format(printf,1,2))); extern void early_printk(const char *fmt, ...) __attribute__((format(printf,1,2)));
extern void printk_address(unsigned long address); extern void printk_address(unsigned long address);
extern void die(const char *,struct pt_regs *,long); extern void die(const char *,struct pt_regs *,long);
extern void __die(const char *,struct pt_regs *,long); extern int __must_check __die(const char *, struct pt_regs *, long);
extern void show_registers(struct pt_regs *regs); extern void show_registers(struct pt_regs *regs);
extern void __show_registers(struct pt_regs *, int all); extern void __show_registers(struct pt_regs *, int all);
extern void show_trace(struct task_struct *, struct pt_regs *, unsigned long *); 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,6 +33,6 @@ extern void __show_regs(struct pt_regs *regs);
extern void show_regs(struct pt_regs *regs); extern void show_regs(struct pt_regs *regs);
extern void dump_pagetable(unsigned long); extern void dump_pagetable(unsigned long);
extern unsigned long oops_begin(void); extern unsigned long oops_begin(void);
extern void oops_end(unsigned long); extern void oops_end(unsigned long, struct pt_regs *, int signr);
#endif #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment