forked from Minki/linux
sh: generic BUG() support.
Wire up GENERIC_BUG for SH. This moves off of the special bug frame and on to the generic struct bug_entry. Roughly the same semantics are retained, and we can kill off some of the verbose BUG() reporting code. Signed-off-by: Paul Mundt <lethal@linux-sh.org>
This commit is contained in:
parent
45ed285b54
commit
fa69151173
@ -22,6 +22,10 @@ config RWSEM_GENERIC_SPINLOCK
|
||||
config RWSEM_XCHGADD_ALGORITHM
|
||||
bool
|
||||
|
||||
config GENERIC_BUG
|
||||
def_bool y
|
||||
depends on BUG
|
||||
|
||||
config GENERIC_FIND_NEXT_BIT
|
||||
bool
|
||||
default y
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/kallsyms.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/bug.h>
|
||||
#include <linux/debug_locks.h>
|
||||
#include <linux/limits.h>
|
||||
#include <asm/system.h>
|
||||
@ -130,40 +131,6 @@ 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 */
|
||||
|
||||
void handle_BUG(struct pt_regs *regs)
|
||||
{
|
||||
do_bug_verbose(regs);
|
||||
die("Kernel BUG", regs, TRAPA_BUG_OPCODE & 0xff);
|
||||
}
|
||||
#endif /* CONFIG_BUG */
|
||||
|
||||
/*
|
||||
* handle an instruction that does an unaligned memory access by emulating the
|
||||
* desired behaviour
|
||||
@ -888,6 +855,25 @@ void __init trap_init(void)
|
||||
per_cpu_trap_init();
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BUG
|
||||
void handle_BUG(struct pt_regs *regs)
|
||||
{
|
||||
enum bug_trap_type tt;
|
||||
tt = report_bug(regs->pc);
|
||||
if (tt == BUG_TRAP_TYPE_WARN) {
|
||||
regs->pc += 2;
|
||||
return;
|
||||
}
|
||||
|
||||
die("Kernel BUG", regs, TRAPA_BUG_OPCODE & 0xff);
|
||||
}
|
||||
|
||||
int is_valid_bugaddr(unsigned long addr)
|
||||
{
|
||||
return addr >= PAGE_OFFSET;
|
||||
}
|
||||
#endif
|
||||
|
||||
void show_trace(struct task_struct *tsk, unsigned long *sp,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
|
@ -34,9 +34,11 @@ SECTIONS
|
||||
__ex_table : { *(__ex_table) }
|
||||
__stop___ex_table = .;
|
||||
|
||||
_etext = .; /* End of text section */
|
||||
|
||||
RODATA
|
||||
|
||||
_etext = .; /* End of text section */
|
||||
BUG_TABLE
|
||||
|
||||
.data : { /* Data */
|
||||
*(.data)
|
||||
@ -53,6 +55,10 @@ SECTIONS
|
||||
|
||||
. = ALIGN(PAGE_SIZE);
|
||||
.data.page_aligned : { *(.data.page_aligned) }
|
||||
__nosave_begin = .;
|
||||
.data_nosave : { *(.data.nosave) }
|
||||
. = ALIGN(PAGE_SIZE);
|
||||
__nosave_end = .;
|
||||
|
||||
. = ALIGN(PAGE_SIZE);
|
||||
__per_cpu_start = .;
|
||||
@ -110,43 +116,10 @@ SECTIONS
|
||||
* it's a module.
|
||||
*/
|
||||
/DISCARD/ : {
|
||||
*(.exit.text)
|
||||
*(.exit.data)
|
||||
*(.exitcall.exit)
|
||||
}
|
||||
|
||||
/* Stabs debugging sections. */
|
||||
.stab 0 : { *(.stab) }
|
||||
.stabstr 0 : { *(.stabstr) }
|
||||
.stab.excl 0 : { *(.stab.excl) }
|
||||
.stab.exclstr 0 : { *(.stab.exclstr) }
|
||||
.stab.index 0 : { *(.stab.index) }
|
||||
.stab.indexstr 0 : { *(.stab.indexstr) }
|
||||
.comment 0 : { *(.comment) }
|
||||
/* DWARF debug sections.
|
||||
Symbols in the DWARF debugging section are relative to the beginning
|
||||
of the section so we begin .debug at 0. */
|
||||
/* DWARF 1 */
|
||||
.debug 0 : { *(.debug) }
|
||||
.line 0 : { *(.line) }
|
||||
/* GNU DWARF 1 extensions */
|
||||
.debug_srcinfo 0 : { *(.debug_srcinfo) }
|
||||
.debug_sfnames 0 : { *(.debug_sfnames) }
|
||||
/* DWARF 1.1 and DWARF 2 */
|
||||
.debug_aranges 0 : { *(.debug_aranges) }
|
||||
.debug_pubnames 0 : { *(.debug_pubnames) }
|
||||
/* DWARF 2 */
|
||||
.debug_info 0 : { *(.debug_info) }
|
||||
.debug_abbrev 0 : { *(.debug_abbrev) }
|
||||
.debug_line 0 : { *(.debug_line) }
|
||||
.debug_frame 0 : { *(.debug_frame) }
|
||||
.debug_str 0 : { *(.debug_str) }
|
||||
.debug_loc 0 : { *(.debug_loc) }
|
||||
.debug_macinfo 0 : { *(.debug_macinfo) }
|
||||
/* SGI/MIPS DWARF 2 extensions */
|
||||
.debug_weaknames 0 : { *(.debug_weaknames) }
|
||||
.debug_funcnames 0 : { *(.debug_funcnames) }
|
||||
.debug_typenames 0 : { *(.debug_typenames) }
|
||||
.debug_varnames 0 : { *(.debug_varnames) }
|
||||
/* These must appear regardless of . */
|
||||
STABS_DEBUG
|
||||
|
||||
DWARF_DEBUG
|
||||
}
|
||||
|
@ -2,50 +2,80 @@
|
||||
#define __ASM_SH_BUG_H
|
||||
|
||||
#ifdef CONFIG_BUG
|
||||
|
||||
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 HAVE_ARCH_BUG
|
||||
#define HAVE_ARCH_WARN_ON
|
||||
|
||||
#define TRAPA_BUG_OPCODE 0xc33e /* trapa #0x3e */
|
||||
|
||||
/**
|
||||
* _EMIT_BUG_ENTRY
|
||||
* %1 - __FILE__
|
||||
* %2 - __LINE__
|
||||
* %3 - trap type
|
||||
* %4 - sizeof(struct bug_entry)
|
||||
*
|
||||
* The trapa opcode itself sits in %0.
|
||||
* The %O notation is used to avoid # generation.
|
||||
*
|
||||
* The offending file and line are encoded in the __bug_table section.
|
||||
*/
|
||||
#ifdef CONFIG_DEBUG_BUGVERBOSE
|
||||
#define _EMIT_BUG_ENTRY \
|
||||
"\t.pushsection __bug_table,\"a\"\n" \
|
||||
"2:\t.long 1b, %O1\n" \
|
||||
"\t.short %O2, %O3\n" \
|
||||
"\t.org 2b+%O4\n" \
|
||||
"\t.popsection\n"
|
||||
#else
|
||||
#define _EMIT_BUG_ENTRY \
|
||||
"\t.pushsection __bug_table,\"a\"\n" \
|
||||
"2:\t.long 1b\n" \
|
||||
"\t.short %O3\n" \
|
||||
"\t.org 2b+%O4\n" \
|
||||
"\t.popsection\n"
|
||||
#endif
|
||||
|
||||
#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__)); \
|
||||
"1:\t.short %O0\n" \
|
||||
_EMIT_BUG_ENTRY \
|
||||
: \
|
||||
: "n" (TRAPA_BUG_OPCODE), \
|
||||
"i" (__FILE__), \
|
||||
"i" (__LINE__), "i" (0), \
|
||||
"i" (sizeof(struct bug_entry))); \
|
||||
} while (0)
|
||||
|
||||
#else
|
||||
|
||||
#define BUG() \
|
||||
do { \
|
||||
__asm__ __volatile__ ( \
|
||||
".align 2\n\t" \
|
||||
".short %O0\n\t" \
|
||||
: \
|
||||
: "n" (TRAPA_BUG_OPCODE)); \
|
||||
#define __WARN() \
|
||||
do { \
|
||||
__asm__ __volatile__ ( \
|
||||
"1:\t.short %O0\n" \
|
||||
_EMIT_BUG_ENTRY \
|
||||
: \
|
||||
: "n" (TRAPA_BUG_OPCODE), \
|
||||
"i" (__FILE__), \
|
||||
"i" (__LINE__), \
|
||||
"i" (BUGFLAG_WARNING), \
|
||||
"i" (sizeof(struct bug_entry))); \
|
||||
} while (0)
|
||||
|
||||
#endif /* CONFIG_DEBUG_BUGVERBOSE */
|
||||
#define WARN_ON(x) ({ \
|
||||
typeof(x) __ret_warn_on = (x); \
|
||||
if (__builtin_constant_p(__ret_warn_on)) { \
|
||||
if (__ret_warn_on) \
|
||||
__WARN(); \
|
||||
} else { \
|
||||
if (unlikely(__ret_warn_on)) \
|
||||
__WARN(); \
|
||||
} \
|
||||
unlikely(__ret_warn_on); \
|
||||
})
|
||||
|
||||
#define HAVE_ARCH_BUG
|
||||
struct pt_regs;
|
||||
|
||||
/* arch/sh/kernel/traps.c */
|
||||
void handle_BUG(struct pt_regs *);
|
||||
|
||||
#endif /* CONFIG_BUG */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user