forked from Minki/linux
[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:
parent
ef3c4cb936
commit
620de2f5dc
@ -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? */
|
||||||
|
@ -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, ®s, 0);
|
rv.fkt = 0;
|
||||||
|
if (die_if_kernel(buf, ®s, 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(®s)->ri);
|
si.si_addr = (void __user *) (regs.cr_iip + ia64_psr(®s)->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, ®s, error);
|
if (!die_if_kernel(buf, ®s, error))
|
||||||
force_sig(SIGILL, current);
|
force_sig(SIGILL, current);
|
||||||
}
|
}
|
||||||
|
@ -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:
|
||||||
|
@ -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:
|
||||||
|
Loading…
Reference in New Issue
Block a user