[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 <jbeulich@novell.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Tony Luck <tony.luck@intel.com>
This commit is contained in:
Jan Beulich 2008-02-04 23:43:03 -08:00 committed by Tony Luck
parent ef3c4cb936
commit 620de2f5dc
4 changed files with 39 additions and 22 deletions

View File

@ -27,7 +27,7 @@
#include "ia32priv.h" #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 exec_domain ia32_exec_domain;
struct page *ia32_shared_page[NR_CPUS]; 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; 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_signo = SIGTRAP;
siginfo.si_errno = int_num; /* XXX is it OK to abuse si_errno like this? */ siginfo.si_errno = int_num; /* XXX is it OK to abuse si_errno like this? */

View File

@ -35,7 +35,7 @@ trap_init (void)
fpswa_interface = __va(ia64_boot_param->fpswa); fpswa_interface = __va(ia64_boot_param->fpswa);
} }
void int
die (const char *str, struct pt_regs *regs, long err) die (const char *str, struct pt_regs *regs, long err)
{ {
static struct { static struct {
@ -62,8 +62,11 @@ die (const char *str, struct pt_regs *regs, long err)
if (++die.lock_owner_depth < 3) { if (++die.lock_owner_depth < 3) {
printk("%s[%d]: %s %ld [%d]\n", printk("%s[%d]: %s %ld [%d]\n",
current->comm, task_pid_nr(current), str, err, ++die_counter); current->comm, task_pid_nr(current), str, err, ++die_counter);
(void) notify_die(DIE_OOPS, (char *)str, regs, err, 255, SIGSEGV); if (notify_die(DIE_OOPS, str, regs, err, 255, SIGSEGV)
show_regs(regs); != NOTIFY_STOP)
show_regs(regs);
else
regs = NULL;
} else } else
printk(KERN_ERR "Recursive die() failure, output suppressed\n"); 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); add_taint(TAINT_DIE);
spin_unlock_irq(&die.lock); spin_unlock_irq(&die.lock);
if (!regs)
return 1;
if (panic_on_oops) if (panic_on_oops)
panic("Fatal exception"); panic("Fatal exception");
do_exit(SIGSEGV); do_exit(SIGSEGV);
return 0;
} }
void int
die_if_kernel (char *str, struct pt_regs *regs, long err) die_if_kernel (char *str, struct pt_regs *regs, long err)
{ {
if (!user_mode(regs)) if (!user_mode(regs))
die(str, regs, err); return die(str, regs, err);
return 0;
} }
void 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) if (notify_die(DIE_BREAK, "break 0", regs, break_num, TRAP_BRKPT, SIGTRAP)
== NOTIFY_STOP) == NOTIFY_STOP)
return; return;
die_if_kernel("bugcheck!", regs, break_num); if (die_if_kernel("bugcheck!", regs, break_num))
return;
sig = SIGILL; code = ILL_ILLOPC; sig = SIGILL; code = ILL_ILLOPC;
break; break;
@ -155,8 +164,9 @@ __kprobes ia64_bad_break (unsigned long break_num, struct pt_regs *regs)
break; break;
default: default:
if (break_num < 0x40000 || break_num > 0x100000) if ((break_num < 0x40000 || break_num > 0x100000)
die_if_kernel("Bad break", regs, break_num); && die_if_kernel("Bad break", regs, break_num))
return;
if (break_num < 0x80000) { if (break_num < 0x80000) {
sig = SIGILL; code = __ILL_BREAK; sig = SIGILL; code = __ILL_BREAK;
@ -402,14 +412,15 @@ ia64_illegal_op_fault (unsigned long ec, long arg1, long arg2, long arg3,
#endif #endif
sprintf(buf, "IA-64 Illegal operation fault"); sprintf(buf, "IA-64 Illegal operation fault");
die_if_kernel(buf, &regs, 0); rv.fkt = 0;
if (die_if_kernel(buf, &regs, 0))
return rv;
memset(&si, 0, sizeof(si)); memset(&si, 0, sizeof(si));
si.si_signo = SIGILL; si.si_signo = SIGILL;
si.si_code = ILL_ILLOPC; si.si_code = ILL_ILLOPC;
si.si_addr = (void __user *) (regs.cr_iip + ia64_psr(&regs)->ri); si.si_addr = (void __user *) (regs.cr_iip + ia64_psr(&regs)->ri);
force_sig_info(SIGILL, &si, current); force_sig_info(SIGILL, &si, current);
rv.fkt = 0;
return rv; return rv;
} }
@ -644,6 +655,6 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa,
sprintf(buf, "Fault %lu", vector); sprintf(buf, "Fault %lu", vector);
break; break;
} }
die_if_kernel(buf, &regs, error); if (!die_if_kernel(buf, &regs, error))
force_sig(SIGILL, current); force_sig(SIGILL, current);
} }

View File

@ -23,7 +23,7 @@
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/unaligned.h> #include <asm/unaligned.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);
#undef DEBUG_UNALIGNED_TRAP #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) { if (ld.x6_op == 1 || ld.x6_op == 3) {
printk(KERN_ERR "%s: register update on speculative load, error\n", __FUNCTION__); printk(KERN_ERR "%s: register update on speculative load, error\n", __FUNCTION__);
die_if_kernel("unaligned reference on speculative load with register update\n", if (die_if_kernel("unaligned reference on speculative load with register update\n",
regs, 30); regs, 30))
return;
} }
@ -1317,7 +1318,8 @@ ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs)
if (ia64_psr(regs)->be) { if (ia64_psr(regs)->be) {
/* we don't support big-endian accesses */ /* 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; goto force_sigbus;
} }
@ -1534,7 +1536,8 @@ ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs)
ia64_handle_exception(regs, eh); ia64_handle_exception(regs, eh);
goto done; 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 */ /* NOT_REACHED */
} }
force_sigbus: force_sigbus:

View File

@ -16,7 +16,7 @@
#include <asm/system.h> #include <asm/system.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
extern void die (char *, struct pt_regs *, long); extern int die(char *, struct pt_regs *, long);
#ifdef CONFIG_KPROBES #ifdef CONFIG_KPROBES
static inline int notify_page_fault(struct pt_regs *regs, int trap) 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 else
printk(KERN_ALERT "Unable to handle kernel paging request at " printk(KERN_ALERT "Unable to handle kernel paging request at "
"virtual address %016lx\n", address); "virtual address %016lx\n", address);
die("Oops", regs, isr); if (die("Oops", regs, isr))
regs = NULL;
bust_spinlocks(0); bust_spinlocks(0);
do_exit(SIGKILL); if (regs)
do_exit(SIGKILL);
return; return;
out_of_memory: out_of_memory: