diff options
author | Paul Mundt <lethal@linux-sh.org> | 2009-08-21 16:28:25 -0400 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2009-08-21 16:28:25 -0400 |
commit | e115f2c17cbceee93b34d787a7a4a867fc73e7b4 (patch) | |
tree | 6ee0f20dcb5eca29793d68e97242c5e483c24cfc /arch/sh/kernel/traps.c | |
parent | c153a58e715e16ffcd6c4b3da7fc6b4a556bf917 (diff) |
sh: unwinder: Use a special bug flag for unwinder traps.
This simplifies the unwinder trap handling, dropping the use of the
special trapa vector and simply piggybacking on top of the BUG support. A
new BUGFLAG_UNWINDER is added for flagging the unwinder fault, before
continuing on with regular BUG dispatch.
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch/sh/kernel/traps.c')
-rw-r--r-- | arch/sh/kernel/traps.c | 21 |
1 files changed, 17 insertions, 4 deletions
diff --git a/arch/sh/kernel/traps.c b/arch/sh/kernel/traps.c index 881b9a32b7de..f69bd968fcca 100644 --- a/arch/sh/kernel/traps.c +++ b/arch/sh/kernel/traps.c | |||
@@ -5,18 +5,32 @@ | |||
5 | #include <linux/signal.h> | 5 | #include <linux/signal.h> |
6 | #include <linux/sched.h> | 6 | #include <linux/sched.h> |
7 | #include <linux/uaccess.h> | 7 | #include <linux/uaccess.h> |
8 | #include <asm/unwinder.h> | ||
8 | #include <asm/system.h> | 9 | #include <asm/system.h> |
9 | 10 | ||
10 | #ifdef CONFIG_BUG | 11 | #ifdef CONFIG_BUG |
11 | void handle_BUG(struct pt_regs *regs) | 12 | void handle_BUG(struct pt_regs *regs) |
12 | { | 13 | { |
14 | const struct bug_entry *bug; | ||
15 | unsigned long bugaddr = regs->pc; | ||
13 | enum bug_trap_type tt; | 16 | enum bug_trap_type tt; |
14 | tt = report_bug(regs->pc, regs); | 17 | |
18 | if (!is_valid_bugaddr(bugaddr)) | ||
19 | goto invalid; | ||
20 | |||
21 | bug = find_bug(bugaddr); | ||
22 | |||
23 | /* Switch unwinders when unwind_stack() is called */ | ||
24 | if (bug->flags & BUGFLAG_UNWINDER) | ||
25 | unwinder_faulted = 1; | ||
26 | |||
27 | tt = report_bug(bugaddr, regs); | ||
15 | if (tt == BUG_TRAP_TYPE_WARN) { | 28 | if (tt == BUG_TRAP_TYPE_WARN) { |
16 | regs->pc += instruction_size(regs->pc); | 29 | regs->pc += instruction_size(bugaddr); |
17 | return; | 30 | return; |
18 | } | 31 | } |
19 | 32 | ||
33 | invalid: | ||
20 | die("Kernel BUG", regs, TRAPA_BUG_OPCODE & 0xff); | 34 | die("Kernel BUG", regs, TRAPA_BUG_OPCODE & 0xff); |
21 | } | 35 | } |
22 | 36 | ||
@@ -28,8 +42,7 @@ int is_valid_bugaddr(unsigned long addr) | |||
28 | return 0; | 42 | return 0; |
29 | if (probe_kernel_address((insn_size_t *)addr, opcode)) | 43 | if (probe_kernel_address((insn_size_t *)addr, opcode)) |
30 | return 0; | 44 | return 0; |
31 | 45 | if (opcode == TRAPA_BUG_OPCODE) | |
32 | if (opcode == TRAPA_BUG_OPCODE || opcode == TRAPA_UNWINDER_BUG_OPCODE) | ||
33 | return 1; | 46 | return 1; |
34 | 47 | ||
35 | return 0; | 48 | return 0; |