Commit e115f2c17cbceee93b34d787a7a4a867fc73e7b4
1 parent
c153a58e71
Exists in
master
and in
7 other branches
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>
Showing 4 changed files with 24 additions and 35 deletions Side-by-side Diff
arch/sh/include/asm/bug.h
1 | 1 | #ifndef __ASM_SH_BUG_H |
2 | 2 | #define __ASM_SH_BUG_H |
3 | 3 | |
4 | -#define TRAPA_UNWINDER_BUG_OPCODE 0xc33b /* trapa #0x3b */ | |
5 | 4 | #define TRAPA_BUG_OPCODE 0xc33e /* trapa #0x3e */ |
5 | +#define BUGFLAG_UNWINDER (1 << 1) | |
6 | 6 | |
7 | 7 | #ifdef CONFIG_GENERIC_BUG |
8 | 8 | #define HAVE_ARCH_BUG |
9 | 9 | |
10 | 10 | |
11 | 11 | |
... | ... | @@ -73,15 +73,16 @@ |
73 | 73 | unlikely(__ret_warn_on); \ |
74 | 74 | }) |
75 | 75 | |
76 | -#define UNWINDER_BUG() \ | |
76 | +#define UNWINDER_BUG() \ | |
77 | 77 | do { \ |
78 | 78 | __asm__ __volatile__ ( \ |
79 | 79 | "1:\t.short %O0\n" \ |
80 | - _EMIT_BUG_ENTRY \ | |
80 | + _EMIT_BUG_ENTRY \ | |
81 | 81 | : \ |
82 | - : "n" (TRAPA_UNWINDER_BUG_OPCODE), \ | |
82 | + : "n" (TRAPA_BUG_OPCODE), \ | |
83 | 83 | "i" (__FILE__), \ |
84 | - "i" (__LINE__), "i" (0), \ | |
84 | + "i" (__LINE__), \ | |
85 | + "i" (BUGFLAG_UNWINDER), \ | |
85 | 86 | "i" (sizeof(struct bug_entry))); \ |
86 | 87 | } while (0) |
87 | 88 |
arch/sh/kernel/debugtraps.S
... | ... | @@ -21,10 +21,6 @@ |
21 | 21 | #define sh_bios_handler debug_trap_handler |
22 | 22 | #endif |
23 | 23 | |
24 | -#if !defined(CONFIG_DWARF_UNWINDER) | |
25 | -#define unwinder_trap_handler debug_trap_handler | |
26 | -#endif | |
27 | - | |
28 | 24 | .data |
29 | 25 | |
30 | 26 | ENTRY(debug_trap_table) |
... | ... | @@ -39,7 +35,7 @@ |
39 | 35 | .long debug_trap_handler /* 0x38 */ |
40 | 36 | .long debug_trap_handler /* 0x39 */ |
41 | 37 | .long debug_trap_handler /* 0x3a */ |
42 | - .long unwinder_trap_handler /* 0x3b */ | |
38 | + .long debug_trap_handler /* 0x3b */ | |
43 | 39 | .long breakpoint_trap_handler /* 0x3c */ |
44 | 40 | .long singlestep_trap_handler /* 0x3d */ |
45 | 41 | .long bug_trap_handler /* 0x3e */ |
arch/sh/kernel/traps.c
... | ... | @@ -5,18 +5,32 @@ |
5 | 5 | #include <linux/signal.h> |
6 | 6 | #include <linux/sched.h> |
7 | 7 | #include <linux/uaccess.h> |
8 | +#include <asm/unwinder.h> | |
8 | 9 | #include <asm/system.h> |
9 | 10 | |
10 | 11 | #ifdef CONFIG_BUG |
11 | 12 | void handle_BUG(struct pt_regs *regs) |
12 | 13 | { |
14 | + const struct bug_entry *bug; | |
15 | + unsigned long bugaddr = regs->pc; | |
13 | 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 | 28 | if (tt == BUG_TRAP_TYPE_WARN) { |
16 | - regs->pc += instruction_size(regs->pc); | |
29 | + regs->pc += instruction_size(bugaddr); | |
17 | 30 | return; |
18 | 31 | } |
19 | 32 | |
33 | +invalid: | |
20 | 34 | die("Kernel BUG", regs, TRAPA_BUG_OPCODE & 0xff); |
21 | 35 | } |
22 | 36 | |
... | ... | @@ -28,8 +42,7 @@ |
28 | 42 | return 0; |
29 | 43 | if (probe_kernel_address((insn_size_t *)addr, opcode)) |
30 | 44 | return 0; |
31 | - | |
32 | - if (opcode == TRAPA_BUG_OPCODE || opcode == TRAPA_UNWINDER_BUG_OPCODE) | |
45 | + if (opcode == TRAPA_BUG_OPCODE) | |
33 | 46 | return 1; |
34 | 47 | |
35 | 48 | return 0; |
arch/sh/kernel/unwinder.c
... | ... | @@ -161,26 +161,5 @@ |
161 | 161 | |
162 | 162 | curr_unwinder->dump(task, regs, sp, ops, data); |
163 | 163 | } |
164 | - | |
165 | -/* | |
166 | - * Trap handler for UWINDER_BUG() statements. We must switch to the | |
167 | - * unwinder with the next highest rating. | |
168 | - */ | |
169 | -BUILD_TRAP_HANDLER(unwinder) | |
170 | -{ | |
171 | - insn_size_t insn; | |
172 | - TRAP_HANDLER_DECL; | |
173 | - | |
174 | - /* Rewind */ | |
175 | - regs->pc -= instruction_size(ctrl_inw(regs->pc - 4)); | |
176 | - insn = *(insn_size_t *)instruction_pointer(regs); | |
177 | - | |
178 | - /* Switch unwinders when unwind_stack() is called */ | |
179 | - unwinder_faulted = 1; | |
180 | - | |
181 | -#ifdef CONFIG_BUG | |
182 | - handle_BUG(regs); | |
183 | -#endif | |
184 | -} | |
185 | 164 | EXPORT_SYMBOL_GPL(unwind_stack); |