diff options
author | Jan Beulich <jbeulich@novell.com> | 2008-02-05 02:43:03 -0500 |
---|---|---|
committer | Tony Luck <tony.luck@intel.com> | 2008-02-05 11:26:44 -0500 |
commit | 620de2f5dc697f906408743b1139fe5fb7b0b7f8 (patch) | |
tree | 01c731dfc3f8aca8f100482ef79d6795e03b4dba /arch/ia64 | |
parent | ef3c4cb936d854d1564172f2dcce9c20d1b08761 (diff) |
[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>
Diffstat (limited to 'arch/ia64')
-rw-r--r-- | arch/ia64/ia32/ia32_support.c | 5 | ||||
-rw-r--r-- | arch/ia64/kernel/traps.c | 35 | ||||
-rw-r--r-- | arch/ia64/kernel/unaligned.c | 13 | ||||
-rw-r--r-- | 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 d1d50cd1c38a..896b1ebbfb26 100644 --- a/arch/ia64/ia32/ia32_support.c +++ b/arch/ia64/ia32/ia32_support.c | |||
@@ -27,7 +27,7 @@ | |||
27 | 27 | ||
28 | #include "ia32priv.h" | 28 | #include "ia32priv.h" |
29 | 29 | ||
30 | extern void die_if_kernel (char *str, struct pt_regs *regs, long err); | 30 | extern int die_if_kernel (char *str, struct pt_regs *regs, long err); |
31 | 31 | ||
32 | struct exec_domain ia32_exec_domain; | 32 | struct exec_domain ia32_exec_domain; |
33 | struct page *ia32_shared_page[NR_CPUS]; | 33 | struct page *ia32_shared_page[NR_CPUS]; |
@@ -217,7 +217,8 @@ ia32_bad_interrupt (unsigned long int_num, struct pt_regs *regs) | |||
217 | { | 217 | { |
218 | siginfo_t siginfo; | 218 | siginfo_t siginfo; |
219 | 219 | ||
220 | die_if_kernel("Bad IA-32 interrupt", regs, int_num); | 220 | if (die_if_kernel("Bad IA-32 interrupt", regs, int_num)) |
221 | return; | ||
221 | 222 | ||
222 | siginfo.si_signo = SIGTRAP; | 223 | siginfo.si_signo = SIGTRAP; |
223 | siginfo.si_errno = int_num; /* XXX is it OK to abuse si_errno like this? */ | 224 | 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 78d65cb947d2..f0cda765e681 100644 --- a/arch/ia64/kernel/traps.c +++ b/arch/ia64/kernel/traps.c | |||
@@ -35,7 +35,7 @@ trap_init (void) | |||
35 | fpswa_interface = __va(ia64_boot_param->fpswa); | 35 | fpswa_interface = __va(ia64_boot_param->fpswa); |
36 | } | 36 | } |
37 | 37 | ||
38 | void | 38 | int |
39 | die (const char *str, struct pt_regs *regs, long err) | 39 | die (const char *str, struct pt_regs *regs, long err) |
40 | { | 40 | { |
41 | static struct { | 41 | static struct { |
@@ -62,8 +62,11 @@ die (const char *str, struct pt_regs *regs, long err) | |||
62 | if (++die.lock_owner_depth < 3) { | 62 | if (++die.lock_owner_depth < 3) { |
63 | printk("%s[%d]: %s %ld [%d]\n", | 63 | printk("%s[%d]: %s %ld [%d]\n", |
64 | current->comm, task_pid_nr(current), str, err, ++die_counter); | 64 | current->comm, task_pid_nr(current), str, err, ++die_counter); |
65 | (void) notify_die(DIE_OOPS, (char *)str, regs, err, 255, SIGSEGV); | 65 | if (notify_die(DIE_OOPS, str, regs, err, 255, SIGSEGV) |
66 | show_regs(regs); | 66 | != NOTIFY_STOP) |
67 | show_regs(regs); | ||
68 | else | ||
69 | regs = NULL; | ||
67 | } else | 70 | } else |
68 | printk(KERN_ERR "Recursive die() failure, output suppressed\n"); | 71 | printk(KERN_ERR "Recursive die() failure, output suppressed\n"); |
69 | 72 | ||
@@ -72,17 +75,22 @@ die (const char *str, struct pt_regs *regs, long err) | |||
72 | add_taint(TAINT_DIE); | 75 | add_taint(TAINT_DIE); |
73 | spin_unlock_irq(&die.lock); | 76 | spin_unlock_irq(&die.lock); |
74 | 77 | ||
78 | if (!regs) | ||
79 | return 1; | ||
80 | |||
75 | if (panic_on_oops) | 81 | if (panic_on_oops) |
76 | panic("Fatal exception"); | 82 | panic("Fatal exception"); |
77 | 83 | ||
78 | do_exit(SIGSEGV); | 84 | do_exit(SIGSEGV); |
85 | return 0; | ||
79 | } | 86 | } |
80 | 87 | ||
81 | void | 88 | int |
82 | die_if_kernel (char *str, struct pt_regs *regs, long err) | 89 | die_if_kernel (char *str, struct pt_regs *regs, long err) |
83 | { | 90 | { |
84 | if (!user_mode(regs)) | 91 | if (!user_mode(regs)) |
85 | die(str, regs, err); | 92 | return die(str, regs, err); |
93 | return 0; | ||
86 | } | 94 | } |
87 | 95 | ||
88 | void | 96 | void |
@@ -102,7 +110,8 @@ __kprobes ia64_bad_break (unsigned long break_num, struct pt_regs *regs) | |||
102 | if (notify_die(DIE_BREAK, "break 0", regs, break_num, TRAP_BRKPT, SIGTRAP) | 110 | if (notify_die(DIE_BREAK, "break 0", regs, break_num, TRAP_BRKPT, SIGTRAP) |
103 | == NOTIFY_STOP) | 111 | == NOTIFY_STOP) |
104 | return; | 112 | return; |
105 | die_if_kernel("bugcheck!", regs, break_num); | 113 | if (die_if_kernel("bugcheck!", regs, break_num)) |
114 | return; | ||
106 | sig = SIGILL; code = ILL_ILLOPC; | 115 | sig = SIGILL; code = ILL_ILLOPC; |
107 | break; | 116 | break; |
108 | 117 | ||
@@ -155,8 +164,9 @@ __kprobes ia64_bad_break (unsigned long break_num, struct pt_regs *regs) | |||
155 | break; | 164 | break; |
156 | 165 | ||
157 | default: | 166 | default: |
158 | if (break_num < 0x40000 || break_num > 0x100000) | 167 | if ((break_num < 0x40000 || break_num > 0x100000) |
159 | die_if_kernel("Bad break", regs, break_num); | 168 | && die_if_kernel("Bad break", regs, break_num)) |
169 | return; | ||
160 | 170 | ||
161 | if (break_num < 0x80000) { | 171 | if (break_num < 0x80000) { |
162 | sig = SIGILL; code = __ILL_BREAK; | 172 | sig = SIGILL; code = __ILL_BREAK; |
@@ -402,14 +412,15 @@ ia64_illegal_op_fault (unsigned long ec, long arg1, long arg2, long arg3, | |||
402 | #endif | 412 | #endif |
403 | 413 | ||
404 | sprintf(buf, "IA-64 Illegal operation fault"); | 414 | sprintf(buf, "IA-64 Illegal operation fault"); |
405 | die_if_kernel(buf, ®s, 0); | 415 | rv.fkt = 0; |
416 | if (die_if_kernel(buf, ®s, 0)) | ||
417 | return rv; | ||
406 | 418 | ||
407 | memset(&si, 0, sizeof(si)); | 419 | memset(&si, 0, sizeof(si)); |
408 | si.si_signo = SIGILL; | 420 | si.si_signo = SIGILL; |
409 | si.si_code = ILL_ILLOPC; | 421 | si.si_code = ILL_ILLOPC; |
410 | si.si_addr = (void __user *) (regs.cr_iip + ia64_psr(®s)->ri); | 422 | si.si_addr = (void __user *) (regs.cr_iip + ia64_psr(®s)->ri); |
411 | force_sig_info(SIGILL, &si, current); | 423 | force_sig_info(SIGILL, &si, current); |
412 | rv.fkt = 0; | ||
413 | return rv; | 424 | return rv; |
414 | } | 425 | } |
415 | 426 | ||
@@ -644,6 +655,6 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa, | |||
644 | sprintf(buf, "Fault %lu", vector); | 655 | sprintf(buf, "Fault %lu", vector); |
645 | break; | 656 | break; |
646 | } | 657 | } |
647 | die_if_kernel(buf, ®s, error); | 658 | if (!die_if_kernel(buf, ®s, error)) |
648 | force_sig(SIGILL, current); | 659 | force_sig(SIGILL, current); |
649 | } | 660 | } |
diff --git a/arch/ia64/kernel/unaligned.c b/arch/ia64/kernel/unaligned.c index f6a1aeb742b3..52f70bbc192a 100644 --- a/arch/ia64/kernel/unaligned.c +++ b/arch/ia64/kernel/unaligned.c | |||
@@ -23,7 +23,7 @@ | |||
23 | #include <asm/uaccess.h> | 23 | #include <asm/uaccess.h> |
24 | #include <asm/unaligned.h> | 24 | #include <asm/unaligned.h> |
25 | 25 | ||
26 | extern void die_if_kernel(char *str, struct pt_regs *regs, long err); | 26 | extern int die_if_kernel(char *str, struct pt_regs *regs, long err); |
27 | 27 | ||
28 | #undef DEBUG_UNALIGNED_TRAP | 28 | #undef DEBUG_UNALIGNED_TRAP |
29 | 29 | ||
@@ -675,8 +675,9 @@ emulate_load_updates (update_t type, load_store_t ld, struct pt_regs *regs, unsi | |||
675 | */ | 675 | */ |
676 | if (ld.x6_op == 1 || ld.x6_op == 3) { | 676 | if (ld.x6_op == 1 || ld.x6_op == 3) { |
677 | printk(KERN_ERR "%s: register update on speculative load, error\n", __FUNCTION__); | 677 | printk(KERN_ERR "%s: register update on speculative load, error\n", __FUNCTION__); |
678 | die_if_kernel("unaligned reference on speculative load with register update\n", | 678 | if (die_if_kernel("unaligned reference on speculative load with register update\n", |
679 | regs, 30); | 679 | regs, 30)) |
680 | return; | ||
680 | } | 681 | } |
681 | 682 | ||
682 | 683 | ||
@@ -1317,7 +1318,8 @@ ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs) | |||
1317 | 1318 | ||
1318 | if (ia64_psr(regs)->be) { | 1319 | if (ia64_psr(regs)->be) { |
1319 | /* we don't support big-endian accesses */ | 1320 | /* we don't support big-endian accesses */ |
1320 | die_if_kernel("big-endian unaligned accesses are not supported", regs, 0); | 1321 | if (die_if_kernel("big-endian unaligned accesses are not supported", regs, 0)) |
1322 | return; | ||
1321 | goto force_sigbus; | 1323 | goto force_sigbus; |
1322 | } | 1324 | } |
1323 | 1325 | ||
@@ -1534,7 +1536,8 @@ ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs) | |||
1534 | ia64_handle_exception(regs, eh); | 1536 | ia64_handle_exception(regs, eh); |
1535 | goto done; | 1537 | goto done; |
1536 | } | 1538 | } |
1537 | die_if_kernel("error during unaligned kernel access\n", regs, ret); | 1539 | if (die_if_kernel("error during unaligned kernel access\n", regs, ret)) |
1540 | return; | ||
1538 | /* NOT_REACHED */ | 1541 | /* NOT_REACHED */ |
1539 | } | 1542 | } |
1540 | force_sigbus: | 1543 | force_sigbus: |
diff --git a/arch/ia64/mm/fault.c b/arch/ia64/mm/fault.c index 7571076a16a1..3e69881648a3 100644 --- a/arch/ia64/mm/fault.c +++ b/arch/ia64/mm/fault.c | |||
@@ -16,7 +16,7 @@ | |||
16 | #include <asm/system.h> | 16 | #include <asm/system.h> |
17 | #include <asm/uaccess.h> | 17 | #include <asm/uaccess.h> |
18 | 18 | ||
19 | extern void die (char *, struct pt_regs *, long); | 19 | extern int die(char *, struct pt_regs *, long); |
20 | 20 | ||
21 | #ifdef CONFIG_KPROBES | 21 | #ifdef CONFIG_KPROBES |
22 | static inline int notify_page_fault(struct pt_regs *regs, int trap) | 22 | 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 | |||
267 | else | 267 | else |
268 | printk(KERN_ALERT "Unable to handle kernel paging request at " | 268 | printk(KERN_ALERT "Unable to handle kernel paging request at " |
269 | "virtual address %016lx\n", address); | 269 | "virtual address %016lx\n", address); |
270 | die("Oops", regs, isr); | 270 | if (die("Oops", regs, isr)) |
271 | regs = NULL; | ||
271 | bust_spinlocks(0); | 272 | bust_spinlocks(0); |
272 | do_exit(SIGKILL); | 273 | if (regs) |
274 | do_exit(SIGKILL); | ||
273 | return; | 275 | return; |
274 | 276 | ||
275 | out_of_memory: | 277 | out_of_memory: |