diff options
author | Matt Fleming <matt@console-pimps.org> | 2009-08-16 21:54:48 +0100 |
---|---|---|
committer | Matt Fleming <matt@console-pimps.org> | 2009-08-21 13:02:44 +0100 |
commit | b344e24a8e8ceda83d1285d22e3e5baf4f5e42d3 (patch) | |
tree | 4b9500264a797736b48b59c3f0977277ace53386 /arch/sh/include/asm/bug.h | |
parent | 97efbbd5886e27b61c19c77d41f6491f5d96fbd0 (diff) | |
download | linux-b344e24a8e8ceda83d1285d22e3e5baf4f5e42d3.tar.bz2 |
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/asm/bug.h')
-rw-r--r-- | arch/sh/include/asm/bug.h | 25 |
1 files changed, 25 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 @@ #ifndef __ASM_SH_BUG_H #define __ASM_SH_BUG_H +#define TRAPA_UNWINDER_BUG_OPCODE 0xc33b /* trapa #0x3b */ #define TRAPA_BUG_OPCODE 0xc33e /* trapa #0x3e */ #ifdef CONFIG_GENERIC_BUG @@ -72,6 +73,30 @@ do { \ unlikely(__ret_warn_on); \ }) +#define UNWINDER_BUG() \ +do { \ + __asm__ __volatile__ ( \ + "1:\t.short %O0\n" \ + _EMIT_BUG_ENTRY \ + : \ + : "n" (TRAPA_UNWINDER_BUG_OPCODE), \ + "i" (__FILE__), \ + "i" (__LINE__), "i" (0), \ + "i" (sizeof(struct bug_entry))); \ +} while (0) + +#define UNWINDER_BUG_ON(x) ({ \ + int __ret_unwinder_on = !!(x); \ + if (__builtin_constant_p(__ret_unwinder_on)) { \ + if (__ret_unwinder_on) \ + UNWINDER_BUG(); \ + } else { \ + if (unlikely(__ret_unwinder_on)) \ + UNWINDER_BUG(); \ + } \ + unlikely(__ret_unwinder_on); \ +}) + #endif /* CONFIG_GENERIC_BUG */ #include <asm-generic/bug.h> |