Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -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));
+15 −8
Original line number Diff line number Diff line
@@ -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,
+6 −6
Original line number Diff line number Diff line
@@ -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 @@ no_context:
	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
+2 −2
Original line number Diff line number Diff line
@@ -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