aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh/include
diff options
context:
space:
mode:
authorMatt Fleming <matt@console-pimps.org>2009-08-16 16:54:48 -0400
committerMatt Fleming <matt@console-pimps.org>2009-08-21 08:02:44 -0400
commitb344e24a8e8ceda83d1285d22e3e5baf4f5e42d3 (patch)
tree4b9500264a797736b48b59c3f0977277ace53386 /arch/sh/include
parent97efbbd5886e27b61c19c77d41f6491f5d96fbd0 (diff)
sh: unwinder: Introduce UNWINDER_BUG() and UNWINDER_BUG_ON()
We can't assume that if we execute the unwinder code and the unwinder was already running that it has faulted. Clearly two kernel threads can invoke the unwinder at the same time and may be running simultaneously. The previous approach used BUG() and BUG_ON() in the unwinder code to detect whether the unwinder was incapable of unwinding the stack, and that the next available unwinder should be used instead. A better approach is to explicitly invoke a trap handler to switch unwinders when the current unwinder cannot continue. Signed-off-by: Matt Fleming <matt@console-pimps.org>
Diffstat (limited to 'arch/sh/include')
-rw-r--r--arch/sh/include/asm/bug.h25
-rw-r--r--arch/sh/include/asm/system.h5
-rw-r--r--arch/sh/include/asm/unwinder.h6
3 files changed, 36 insertions, 0 deletions
diff --git a/arch/sh/include/asm/bug.h b/arch/sh/include/asm/bug.h
index c01718040166..b7d9822fd6c2 100644
--- a/arch/sh/include/asm/bug.h
+++ b/arch/sh/include/asm/bug.h
@@ -1,6 +1,7 @@
1#ifndef __ASM_SH_BUG_H 1#ifndef __ASM_SH_BUG_H
2#define __ASM_SH_BUG_H 2#define __ASM_SH_BUG_H
3 3
4#define TRAPA_UNWINDER_BUG_OPCODE 0xc33b /* trapa #0x3b */
4#define TRAPA_BUG_OPCODE 0xc33e /* trapa #0x3e */ 5#define TRAPA_BUG_OPCODE 0xc33e /* trapa #0x3e */
5 6
6#ifdef CONFIG_GENERIC_BUG 7#ifdef CONFIG_GENERIC_BUG
@@ -72,6 +73,30 @@ do { \
72 unlikely(__ret_warn_on); \ 73 unlikely(__ret_warn_on); \
73}) 74})
74 75
76#define UNWINDER_BUG() \
77do { \
78 __asm__ __volatile__ ( \
79 "1:\t.short %O0\n" \
80 _EMIT_BUG_ENTRY \
81 : \
82 : "n" (TRAPA_UNWINDER_BUG_OPCODE), \
83 "i" (__FILE__), \
84 "i" (__LINE__), "i" (0), \
85 "i" (sizeof(struct bug_entry))); \
86} while (0)
87
88#define UNWINDER_BUG_ON(x) ({ \
89 int __ret_unwinder_on = !!(x); \
90 if (__builtin_constant_p(__ret_unwinder_on)) { \
91 if (__ret_unwinder_on) \
92 UNWINDER_BUG(); \
93 } else { \
94 if (unlikely(__ret_unwinder_on)) \
95 UNWINDER_BUG(); \
96 } \
97 unlikely(__ret_unwinder_on); \
98})
99
75#endif /* CONFIG_GENERIC_BUG */ 100#endif /* CONFIG_GENERIC_BUG */
76 101
77#include <asm-generic/bug.h> 102#include <asm-generic/bug.h>
diff --git a/arch/sh/include/asm/system.h b/arch/sh/include/asm/system.h
index ab79e1f4fbe0..f9e2ceb94d9b 100644
--- a/arch/sh/include/asm/system.h
+++ b/arch/sh/include/asm/system.h
@@ -181,6 +181,11 @@ BUILD_TRAP_HANDLER(breakpoint);
181BUILD_TRAP_HANDLER(singlestep); 181BUILD_TRAP_HANDLER(singlestep);
182BUILD_TRAP_HANDLER(fpu_error); 182BUILD_TRAP_HANDLER(fpu_error);
183BUILD_TRAP_HANDLER(fpu_state_restore); 183BUILD_TRAP_HANDLER(fpu_state_restore);
184BUILD_TRAP_HANDLER(unwinder);
185
186#ifdef CONFIG_BUG
187extern void handle_BUG(struct pt_regs *);
188#endif
184 189
185#define arch_align_stack(x) (x) 190#define arch_align_stack(x) (x)
186 191
diff --git a/arch/sh/include/asm/unwinder.h b/arch/sh/include/asm/unwinder.h
index 3dc551453e28..1e65c07b3e18 100644
--- a/arch/sh/include/asm/unwinder.h
+++ b/arch/sh/include/asm/unwinder.h
@@ -22,4 +22,10 @@ extern void stack_reader_dump(struct task_struct *, struct pt_regs *,
22 unsigned long *, const struct stacktrace_ops *, 22 unsigned long *, const struct stacktrace_ops *,
23 void *); 23 void *);
24 24
25/*
26 * Used by fault handling code to signal to the unwinder code that it
27 * should switch to a different unwinder.
28 */
29extern int unwinder_faulted;
30
25#endif /* _LINUX_UNWINDER_H */ 31#endif /* _LINUX_UNWINDER_H */