From 620de2f5dc697f906408743b1139fe5fb7b0b7f8 Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Mon, 4 Feb 2008 23:43:03 -0800 Subject: [PATCH] [IA64] honor notify_die() returning NOTIFY_STOP This requires making die() and die_if_kernel() return a value, and their callers to honor this (and be prepared that it returns). Signed-off-by: Jan Beulich Signed-off-by: Andrew Morton Signed-off-by: Tony Luck --- arch/ia64/ia32/ia32_support.c | 5 +++-- arch/ia64/kernel/traps.c | 35 +++++++++++++++++++++++------------ arch/ia64/kernel/unaligned.c | 13 ++++++++----- arch/ia64/mm/fault.c | 8 +++++--- 4 files changed, 39 insertions(+), 22 deletions(-) diff --git a/arch/ia64/ia32/ia32_support.c b/arch/ia64/ia32/ia32_support.c index d1d50cd1c38..896b1ebbfb2 100644 --- a/arch/ia64/ia32/ia32_support.c +++ b/arch/ia64/ia32/ia32_support.c @@ -27,7 +27,7 @@ #include "ia32priv.h" -extern void die_if_kernel (char *str, struct pt_regs *regs, long err); +extern int die_if_kernel (char *str, struct pt_regs *regs, long err); struct exec_domain ia32_exec_domain; struct page *ia32_shared_page[NR_CPUS]; @@ -217,7 +217,8 @@ ia32_bad_interrupt (unsigned long int_num, struct pt_regs *regs) { siginfo_t siginfo; - die_if_kernel("Bad IA-32 interrupt", regs, int_num); + if (die_if_kernel("Bad IA-32 interrupt", regs, int_num)) + return; siginfo.si_signo = SIGTRAP; siginfo.si_errno = int_num; /* XXX is it OK to abuse si_errno like this? */ diff --git a/arch/ia64/kernel/traps.c b/arch/ia64/kernel/traps.c index 78d65cb947d..f0cda765e68 100644 --- a/arch/ia64/kernel/traps.c +++ b/arch/ia64/kernel/traps.c @@ -35,7 +35,7 @@ trap_init (void) fpswa_interface = __va(ia64_boot_param->fpswa); } -void +int die (const char *str, struct pt_regs *regs, long err) { static struct { @@ -62,8 +62,11 @@ die (const char *str, struct pt_regs *regs, long err) if (++die.lock_owner_depth < 3) { printk("%s[%d]: %s %ld [%d]\n", current->comm, task_pid_nr(current), str, err, ++die_counter); - (void) notify_die(DIE_OOPS, (char *)str, regs, err, 255, SIGSEGV); - show_regs(regs); + if (notify_die(DIE_OOPS, str, regs, err, 255, SIGSEGV) + != NOTIFY_STOP) + show_regs(regs); + else + regs = NULL; } else printk(KERN_ERR "Recursive die() failure, output suppressed\n"); @@ -72,17 +75,22 @@ die (const char *str, struct pt_regs *regs, long err) add_taint(TAINT_DIE); spin_unlock_irq(&die.lock); + if (!regs) + return 1; + if (panic_on_oops) panic("Fatal exception"); do_exit(SIGSEGV); + return 0; } -void +int die_if_kernel (char *str, struct pt_regs *regs, long err) { if (!user_mode(regs)) - die(str, regs, err); + return die(str, regs, err); + return 0; } void @@ -102,7 +110,8 @@ __kprobes ia64_bad_break (unsigned long break_num, struct pt_regs *regs) if (notify_die(DIE_BREAK, "break 0", regs, break_num, TRAP_BRKPT, SIGTRAP) == NOTIFY_STOP) return; - die_if_kernel("bugcheck!", regs, break_num); + if (die_if_kernel("bugcheck!", regs, break_num)) + return; sig = SIGILL; code = ILL_ILLOPC; break; @@ -155,8 +164,9 @@ __kprobes ia64_bad_break (unsigned long break_num, struct pt_regs *regs) break; default: - if (break_num < 0x40000 || break_num > 0x100000) - die_if_kernel("Bad break", regs, break_num); + if ((break_num < 0x40000 || break_num > 0x100000) + && die_if_kernel("Bad break", regs, break_num)) + return; if (break_num < 0x80000) { sig = SIGILL; code = __ILL_BREAK; @@ -402,14 +412,15 @@ ia64_illegal_op_fault (unsigned long ec, long arg1, long arg2, long arg3, #endif sprintf(buf, "IA-64 Illegal operation fault"); - die_if_kernel(buf, ®s, 0); + rv.fkt = 0; + if (die_if_kernel(buf, ®s, 0)) + return rv; memset(&si, 0, sizeof(si)); si.si_signo = SIGILL; si.si_code = ILL_ILLOPC; si.si_addr = (void __user *) (regs.cr_iip + ia64_psr(®s)->ri); force_sig_info(SIGILL, &si, current); - rv.fkt = 0; return rv; } @@ -644,6 +655,6 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa, sprintf(buf, "Fault %lu", vector); break; } - die_if_kernel(buf, ®s, error); - force_sig(SIGILL, current); + if (!die_if_kernel(buf, ®s, error)) + force_sig(SIGILL, current); } diff --git a/arch/ia64/kernel/unaligned.c b/arch/ia64/kernel/unaligned.c index f6a1aeb742b..52f70bbc192 100644 --- a/arch/ia64/kernel/unaligned.c +++ b/arch/ia64/kernel/unaligned.c @@ -23,7 +23,7 @@ #include #include -extern void die_if_kernel(char *str, struct pt_regs *regs, long err); +extern int die_if_kernel(char *str, struct pt_regs *regs, long err); #undef DEBUG_UNALIGNED_TRAP @@ -675,8 +675,9 @@ emulate_load_updates (update_t type, load_store_t ld, struct pt_regs *regs, unsi */ if (ld.x6_op == 1 || ld.x6_op == 3) { printk(KERN_ERR "%s: register update on speculative load, error\n", __FUNCTION__); - die_if_kernel("unaligned reference on speculative load with register update\n", - regs, 30); + if (die_if_kernel("unaligned reference on speculative load with register update\n", + regs, 30)) + return; } @@ -1317,7 +1318,8 @@ ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs) if (ia64_psr(regs)->be) { /* we don't support big-endian accesses */ - die_if_kernel("big-endian unaligned accesses are not supported", regs, 0); + if (die_if_kernel("big-endian unaligned accesses are not supported", regs, 0)) + return; goto force_sigbus; } @@ -1534,7 +1536,8 @@ ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs) ia64_handle_exception(regs, eh); goto done; } - die_if_kernel("error during unaligned kernel access\n", regs, ret); + if (die_if_kernel("error during unaligned kernel access\n", regs, ret)) + return; /* NOT_REACHED */ } force_sigbus: diff --git a/arch/ia64/mm/fault.c b/arch/ia64/mm/fault.c index 7571076a16a..3e69881648a 100644 --- a/arch/ia64/mm/fault.c +++ b/arch/ia64/mm/fault.c @@ -16,7 +16,7 @@ #include #include -extern void die (char *, struct pt_regs *, long); +extern int die(char *, struct pt_regs *, long); #ifdef CONFIG_KPROBES static inline int notify_page_fault(struct pt_regs *regs, int trap) @@ -267,9 +267,11 @@ ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *re else printk(KERN_ALERT "Unable to handle kernel paging request at " "virtual address %016lx\n", address); - die("Oops", regs, isr); + if (die("Oops", regs, isr)) + regs = NULL; bust_spinlocks(0); - do_exit(SIGKILL); + if (regs) + do_exit(SIGKILL); return; out_of_memory: -- 2.41.1