Skip to content

Commit

Permalink
sh: unwinder: Use a special bug flag for unwinder traps.
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Paul Mundt committed Aug 21, 2009
1 parent c153a58 commit e115f2c
Show file tree
Hide file tree
Showing 4 changed files with 24 additions and 35 deletions.
11 changes: 6 additions & 5 deletions arch/sh/include/asm/bug.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
#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 */
#define BUGFLAG_UNWINDER (1 << 1)

#ifdef CONFIG_GENERIC_BUG
#define HAVE_ARCH_BUG
Expand Down Expand Up @@ -73,15 +73,16 @@ do { \
unlikely(__ret_warn_on); \
})

#define UNWINDER_BUG() \
#define UNWINDER_BUG() \
do { \
__asm__ __volatile__ ( \
"1:\t.short %O0\n" \
_EMIT_BUG_ENTRY \
_EMIT_BUG_ENTRY \
: \
: "n" (TRAPA_UNWINDER_BUG_OPCODE), \
: "n" (TRAPA_BUG_OPCODE), \
"i" (__FILE__), \
"i" (__LINE__), "i" (0), \
"i" (__LINE__), \
"i" (BUGFLAG_UNWINDER), \
"i" (sizeof(struct bug_entry))); \
} while (0)

Expand Down
6 changes: 1 addition & 5 deletions arch/sh/kernel/debugtraps.S
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,6 @@

#if !defined(CONFIG_SH_STANDARD_BIOS)
#define sh_bios_handler debug_trap_handler
#endif

#if !defined(CONFIG_DWARF_UNWINDER)
#define unwinder_trap_handler debug_trap_handler
#endif

.data
Expand All @@ -39,7 +35,7 @@ ENTRY(debug_trap_table)
.long debug_trap_handler /* 0x38 */
.long debug_trap_handler /* 0x39 */
.long debug_trap_handler /* 0x3a */
.long unwinder_trap_handler /* 0x3b */
.long debug_trap_handler /* 0x3b */
.long breakpoint_trap_handler /* 0x3c */
.long singlestep_trap_handler /* 0x3d */
.long bug_trap_handler /* 0x3e */
Expand Down
21 changes: 17 additions & 4 deletions arch/sh/kernel/traps.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,32 @@
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/uaccess.h>
#include <asm/unwinder.h>
#include <asm/system.h>

#ifdef CONFIG_BUG
void handle_BUG(struct pt_regs *regs)
{
const struct bug_entry *bug;
unsigned long bugaddr = regs->pc;
enum bug_trap_type tt;
tt = report_bug(regs->pc, regs);

if (!is_valid_bugaddr(bugaddr))
goto invalid;

bug = find_bug(bugaddr);

/* Switch unwinders when unwind_stack() is called */
if (bug->flags & BUGFLAG_UNWINDER)
unwinder_faulted = 1;

tt = report_bug(bugaddr, regs);
if (tt == BUG_TRAP_TYPE_WARN) {
regs->pc += instruction_size(regs->pc);
regs->pc += instruction_size(bugaddr);
return;
}

invalid:
die("Kernel BUG", regs, TRAPA_BUG_OPCODE & 0xff);
}

Expand All @@ -28,8 +42,7 @@ int is_valid_bugaddr(unsigned long addr)
return 0;
if (probe_kernel_address((insn_size_t *)addr, opcode))
return 0;

if (opcode == TRAPA_BUG_OPCODE || opcode == TRAPA_UNWINDER_BUG_OPCODE)
if (opcode == TRAPA_BUG_OPCODE)
return 1;

return 0;
Expand Down
21 changes: 0 additions & 21 deletions arch/sh/kernel/unwinder.c
Original file line number Diff line number Diff line change
Expand Up @@ -161,25 +161,4 @@ void unwind_stack(struct task_struct *task, struct pt_regs *regs,

curr_unwinder->dump(task, regs, sp, ops, data);
}

/*
* Trap handler for UWINDER_BUG() statements. We must switch to the
* unwinder with the next highest rating.
*/
BUILD_TRAP_HANDLER(unwinder)
{
insn_size_t insn;
TRAP_HANDLER_DECL;

/* Rewind */
regs->pc -= instruction_size(ctrl_inw(regs->pc - 4));
insn = *(insn_size_t *)instruction_pointer(regs);

/* Switch unwinders when unwind_stack() is called */
unwinder_faulted = 1;

#ifdef CONFIG_BUG
handle_BUG(regs);
#endif
}
EXPORT_SYMBOL_GPL(unwind_stack);

0 comments on commit e115f2c

Please sign in to comment.