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>
This commit is contained in:
parent
d88879b2d0
commit
22f5991c85
4 changed files with 27 additions and 20 deletions
|
@ -192,10 +192,10 @@ void do_machine_check(struct pt_regs * regs, long error_code)
|
|||
|
||||
atomic_inc(&mce_entry);
|
||||
|
||||
if (regs)
|
||||
notify_die(DIE_NMI, "machine check", regs, error_code, 18,
|
||||
SIGKILL);
|
||||
if (!banks)
|
||||
if ((regs
|
||||
&& notify_die(DIE_NMI, "machine check", regs, error_code,
|
||||
18, SIGKILL) == NOTIFY_STOP)
|
||||
|| !banks)
|
||||
goto out2;
|
||||
|
||||
memset(&m, 0, sizeof(struct mce));
|
||||
|
|
|
@ -488,7 +488,7 @@ unsigned __kprobes long oops_begin(void)
|
|||
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;
|
||||
bust_spinlocks(0);
|
||||
|
@ -497,12 +497,17 @@ void __kprobes oops_end(unsigned long flags)
|
|||
/* Nest count reaches zero, release the lock. */
|
||||
__raw_spin_unlock(&die_lock);
|
||||
raw_local_irq_restore(flags);
|
||||
if (!regs) {
|
||||
oops_exit();
|
||||
return;
|
||||
}
|
||||
if (panic_on_oops)
|
||||
panic("Fatal exception");
|
||||
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;
|
||||
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)
|
|||
printk("DEBUG_PAGEALLOC");
|
||||
#endif
|
||||
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);
|
||||
add_taint(TAINT_DIE);
|
||||
/* Executive summary in case the oops scrolled away */
|
||||
|
@ -525,6 +531,7 @@ void __kprobes __die(const char * str, struct pt_regs * regs, long err)
|
|||
printk(" RSP <%016lx>\n", regs->sp);
|
||||
if (kexec_should_crash(current))
|
||||
crash_kexec(regs);
|
||||
return 0;
|
||||
}
|
||||
|
||||
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))
|
||||
report_bug(regs->ip, regs);
|
||||
|
||||
__die(str, regs, err);
|
||||
oops_end(flags);
|
||||
do_exit(SIGSEGV);
|
||||
if (__die(str, regs, err))
|
||||
regs = NULL;
|
||||
oops_end(flags, regs, SIGSEGV);
|
||||
}
|
||||
|
||||
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);
|
||||
if (do_panic || panic_on_oops)
|
||||
panic("Non maskable interrupt");
|
||||
oops_end(flags);
|
||||
oops_end(flags, NULL, SIGBUS);
|
||||
nmi_exit();
|
||||
local_irq_enable();
|
||||
do_exit(SIGSEGV);
|
||||
do_exit(SIGBUS);
|
||||
}
|
||||
|
||||
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,
|
|||
tsk->thread.cr2 = address;
|
||||
tsk->thread.trap_no = 14;
|
||||
tsk->thread.error_code = error_code;
|
||||
__die("Bad pagetable", regs, error_code);
|
||||
oops_end(flags);
|
||||
do_exit(SIGKILL);
|
||||
if (__die("Bad pagetable", regs, error_code))
|
||||
regs = NULL;
|
||||
oops_end(flags, regs, SIGKILL);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -541,11 +541,11 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
|
|||
tsk->thread.cr2 = address;
|
||||
tsk->thread.trap_no = 14;
|
||||
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 */
|
||||
printk(KERN_EMERG "CR2: %016lx\n", address);
|
||||
oops_end(flags);
|
||||
do_exit(SIGKILL);
|
||||
oops_end(flags, regs, SIGKILL);
|
||||
|
||||
/*
|
||||
* We ran out of memory, or some other thing happened to us that made
|
||||
|
|
|
@ -25,7 +25,7 @@ enum die_val {
|
|||
extern void early_printk(const char *fmt, ...) __attribute__((format(printf,1,2)));
|
||||
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 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 *, int all);
|
||||
extern void show_trace(struct task_struct *, struct pt_regs *, unsigned long *);
|
||||
|
@ -33,6 +33,6 @@ extern void __show_regs(struct pt_regs *regs);
|
|||
extern void show_regs(struct pt_regs *regs);
|
||||
extern void dump_pagetable(unsigned long);
|
||||
extern unsigned long oops_begin(void);
|
||||
extern void oops_end(unsigned long);
|
||||
extern void oops_end(unsigned long, struct pt_regs *, int signr);
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue