Commit e115f2c17cbceee93b34d787a7a4a867fc73e7b4

Authored by Paul Mundt
1 parent c153a58e71

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);