Skip to content

Commit

Permalink
sh: BUG() handling through trapa vector.
Browse files Browse the repository at this point in the history
Previously we haven't been doing anything with verbose BUG() reporting,
and we've been relying on the oops path for handling BUG()'s, which is
rather sub-optimal.

This switches BUG handling to use a fixed trapa vector (#0x3e) where we
construct a small bug frame post trapa instruction to get the context
right. This also makes it trivial to wire up a DIE_BUG for the atomic
die chain, which we couldn't really do before.

Signed-off-by: Paul Mundt <lethal@linux-sh.org>
  • Loading branch information
Paul Mundt committed Dec 11, 2006
1 parent 1b73e6a commit dc34d31
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 9 deletions.
10 changes: 10 additions & 0 deletions arch/sh/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -498,6 +498,16 @@ asmlinkage void break_point_trap_software(unsigned long r4, unsigned long r5,
{
struct pt_regs *regs = RELOC_HIDE(&__regs, 0);

/* Rewind */
regs->pc -= 2;

#ifdef CONFIG_BUG
if (__kernel_text_address(instruction_pointer(regs))) {
u16 insn = *(u16 *)instruction_pointer(regs);
if (insn == TRAPA_BUG_OPCODE)
handle_BUG(regs);
}
#endif

force_sig(SIGTRAP, current);
}
35 changes: 35 additions & 0 deletions arch/sh/kernel/traps.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include <linux/kallsyms.h>
#include <linux/io.h>
#include <linux/debug_locks.h>
#include <linux/limits.h>
#include <asm/system.h>
#include <asm/uaccess.h>

Expand Down Expand Up @@ -129,6 +130,40 @@ static int die_if_no_fixup(const char * str, struct pt_regs * regs, long err)
return -EFAULT;
}

#ifdef CONFIG_BUG
#ifdef CONFIG_DEBUG_BUGVERBOSE
static inline void do_bug_verbose(struct pt_regs *regs)
{
struct bug_frame f;
long len;

if (__copy_from_user(&f, (const void __user *)regs->pc,
sizeof(struct bug_frame)))
return;

len = __strnlen_user(f.file, PATH_MAX) - 1;
if (unlikely(len < 0 || len >= PATH_MAX))
f.file = "<bad filename>";
len = __strnlen_user(f.func, PATH_MAX) - 1;
if (unlikely(len < 0 || len >= PATH_MAX))
f.func = "<bad function>";

printk(KERN_ALERT "kernel BUG in %s() at %s:%d!\n",
f.func, f.file, f.line);
}
#else
static inline void do_bug_verbose(struct pt_regs *regs)
{
}
#endif /* CONFIG_DEBUG_BUGVERBOSE */
#endif /* CONFIG_BUG */

void handle_BUG(struct pt_regs *regs)
{
do_bug_verbose(regs);
die("Kernel BUG", regs, TRAPA_BUG_OPCODE & 0xff);
}

/*
* handle an instruction that does an unaligned memory access by emulating the
* desired behaviour
Expand Down
53 changes: 44 additions & 9 deletions include/asm-sh/bug.h
Original file line number Diff line number Diff line change
@@ -1,19 +1,54 @@
#ifndef __ASM_SH_BUG_H
#define __ASM_SH_BUG_H


#ifdef CONFIG_BUG
/*
* Tell the user there is some problem.
*/
#define BUG() do { \
printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \
*(volatile int *)0 = 0; \

struct bug_frame {
unsigned short opcode;
unsigned short line;
const char *file;
const char *func;
};

struct pt_regs;

extern void handle_BUG(struct pt_regs *);

#define TRAPA_BUG_OPCODE 0xc33e /* trapa #0x3e */

#ifdef CONFIG_DEBUG_BUGVERBOSE

#define BUG() \
do { \
__asm__ __volatile__ ( \
".align 2\n\t" \
".short %O0\n\t" \
".short %O1\n\t" \
".long %O2\n\t" \
".long %O3\n\t" \
: \
: "n" (TRAPA_BUG_OPCODE), \
"i" (__LINE__), "X" (__FILE__), \
"X" (__FUNCTION__)); \
} while (0)

#else

#define BUG() \
do { \
__asm__ __volatile__ ( \
".align 2\n\t" \
".short %O0\n\t" \
: \
: "n" (TRAPA_BUG_OPCODE)); \
} while (0)

#endif /* CONFIG_DEBUG_BUGVERBOSE */

#define HAVE_ARCH_BUG
#endif

#endif /* CONFIG_BUG */

#include <asm-generic/bug.h>

#endif
#endif /* __ASM_SH_BUG_H */

0 comments on commit dc34d31

Please sign in to comment.