bool
default y
+config GENERIC_BUG
+ bool
+ default y
+ depends on BUG
+
config DEFAULT_UIMAGE
bool
help
#include <linux/string.h>
#include <linux/kernel.h>
#include <linux/cache.h>
+#include <linux/bug.h>
#include "setup.h"
struct module *me)
{
const Elf_Shdr *sect;
+ int err;
- me->arch.bug_table = NULL;
- me->arch.num_bugs = 0;
-
- /* Find the __bug_table section, if present */
- sect = find_section(hdr, sechdrs, "__bug_table");
- if (sect != NULL) {
- me->arch.bug_table = (void *) sect->sh_addr;
- me->arch.num_bugs = sect->sh_size / sizeof(struct bug_entry);
- }
-
- /*
- * Strictly speaking this should have a spinlock to protect against
- * traversals, but since we only traverse on BUG()s, a spinlock
- * could potentially lead to deadlock and thus be counter-productive.
- */
- list_add(&me->arch.bug_list, &module_bug_list);
+ err = module_bug_finalize(hdr, sechdrs, me);
+ if (err) /* never true, currently */
+ return err;
/* Apply feature fixups */
sect = find_section(hdr, sechdrs, "__ftr_fixup");
void module_arch_cleanup(struct module *mod)
{
- list_del(&mod->arch.bug_list);
+ module_bug_cleanup(mod);
}
struct bug_entry *module_find_bug(unsigned long bugaddr)
#include <linux/moduleloader.h>
#include <linux/err.h>
#include <linux/vmalloc.h>
+#include <linux/bug.h>
#include <asm/module.h>
#include <asm/uaccess.h>
#include <asm/firmware.h>
const Elf_Shdr *sechdrs, struct module *me)
{
const Elf_Shdr *sect;
+ int err;
- me->arch.bug_table = NULL;
- me->arch.num_bugs = 0;
-
- /* Find the __bug_table section, if present */
- sect = find_section(hdr, sechdrs, "__bug_table");
- if (sect != NULL) {
- me->arch.bug_table = (void *) sect->sh_addr;
- me->arch.num_bugs = sect->sh_size / sizeof(struct bug_entry);
- }
-
- /*
- * Strictly speaking this should have a spinlock to protect against
- * traversals, but since we only traverse on BUG()s, a spinlock
- * could potentially lead to deadlock and thus be counter-productive.
- */
- list_add(&me->arch.bug_list, &module_bug_list);
+ err = module_bug_finalize(hdr, sechdrs, me);
+ if (err)
+ return err;
/* Apply feature fixups */
sect = find_section(hdr, sechdrs, "__ftr_fixup");
void module_arch_cleanup(struct module *mod)
{
- list_del(&mod->arch.bug_list);
+ module_bug_cleanup(mod);
}
struct bug_entry *module_find_bug(unsigned long bugaddr)
#include <linux/kprobes.h>
#include <linux/kexec.h>
#include <linux/backlight.h>
+#include <linux/bug.h>
#include <asm/kdebug.h>
#include <asm/pgtable.h>
return -EINVAL;
}
-/*
- * Look through the list of trap instructions that are used for BUG(),
- * BUG_ON() and WARN_ON() and see if we hit one. At this point we know
- * that the exception was caused by a trap instruction of some kind.
- * Returns 1 if we should continue (i.e. it was a WARN_ON) or 0
- * otherwise.
- */
-extern struct bug_entry __start___bug_table[], __stop___bug_table[];
-
-#ifndef CONFIG_MODULES
-#define module_find_bug(x) NULL
-#endif
-
-struct bug_entry *find_bug(unsigned long bugaddr)
+int is_valid_bugaddr(unsigned long addr)
{
- struct bug_entry *bug;
-
- for (bug = __start___bug_table; bug < __stop___bug_table; ++bug)
- if (bugaddr == bug->bug_addr)
- return bug;
- return module_find_bug(bugaddr);
-}
-
-static int check_bug_trap(struct pt_regs *regs)
-{
- struct bug_entry *bug;
- unsigned long addr;
-
- if (regs->msr & MSR_PR)
- return 0; /* not in kernel */
- addr = regs->nip; /* address of trap instruction */
- if (addr < PAGE_OFFSET)
- return 0;
- bug = find_bug(regs->nip);
- if (bug == NULL)
- return 0;
- if (bug->line & BUG_WARNING_TRAP) {
- /* this is a WARN_ON rather than BUG/BUG_ON */
- printk(KERN_ERR "Badness in %s at %s:%ld\n",
- bug->function, bug->file,
- bug->line & ~BUG_WARNING_TRAP);
- dump_stack();
- return 1;
- }
- printk(KERN_CRIT "kernel BUG in %s at %s:%ld!\n",
- bug->function, bug->file, bug->line);
-
- return 0;
+ return is_kernel_addr(addr);
}
void __kprobes program_check_exception(struct pt_regs *regs)
return;
if (debugger_bpt(regs))
return;
- if (check_bug_trap(regs)) {
+
+ if (!(regs->msr & MSR_PR) && /* not user-mode */
+ report_bug(regs->nip) == BUG_TRAP_TYPE_WARN) {
regs->nip += 4;
return;
}
__stop___ex_table = .;
}
- __bug_table : {
- __start___bug_table = .;
- *(__bug_table)
- __stop___bug_table = .;
- }
+ BUG_TABLE
/*
* Init sections discarded at runtime
#include <linux/sysrq.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
+#include <linux/bug.h>
#include <asm/ptrace.h>
#include <asm/string.h>
#include <asm/cputable.h>
#include <asm/rtas.h>
#include <asm/sstep.h>
-#include <asm/bug.h>
#include <asm/irq_regs.h>
#include <asm/spu.h>
#include <asm/spu_priv1.h>
static void print_bug_trap(struct pt_regs *regs)
{
- struct bug_entry *bug;
+ const struct bug_entry *bug;
unsigned long addr;
if (regs->msr & MSR_PR)
bug = find_bug(regs->nip);
if (bug == NULL)
return;
- if (bug->line & BUG_WARNING_TRAP)
+ if (is_warning_bug(bug))
return;
- printf("kernel BUG in %s at %s:%d!\n",
- bug->function, bug->file, (unsigned int)bug->line);
+ printf("kernel BUG at %s:%u!\n",
+ bug->file, bug->line);
}
void excprint(struct pt_regs *fp)
#ifndef __ASSEMBLY__
-struct bug_entry {
- unsigned long bug_addr;
- long line;
- const char *file;
- const char *function;
-};
-
-struct bug_entry *find_bug(unsigned long bugaddr);
-
-/*
- * If this bit is set in the line number it means that the trap
- * is for WARN_ON rather than BUG or BUG_ON.
- */
-#define BUG_WARNING_TRAP 0x1000000
-
#ifdef CONFIG_BUG
+/* _EMIT_BUG_ENTRY expects args %0,%1,%2,%3 to be FILE, LINE, flags and
+ sizeof(struct bug_entry), respectively */
+#ifdef CONFIG_DEBUG_BUGVERBOSE
+#define _EMIT_BUG_ENTRY \
+ ".section __bug_table,\"a\"\n" \
+ "2:\t" PPC_LONG "1b, %0\n" \
+ "\t.short %1, %2\n" \
+ ".org 2b+%3\n" \
+ ".previous\n"
+#else
+#define _EMIT_BUG_ENTRY \
+ ".section __bug_table,\"a\"\n" \
+ "2:\t" PPC_LONG "1b\n" \
+ "\t.short %2\n" \
+ ".org 2b+%3\n" \
+ ".previous\n"
+#endif
+
/*
* BUG_ON() and WARN_ON() do their best to cooperate with compile-time
* optimisations. However depending on the complexity of the condition
* some compiler versions may not produce optimal results.
*/
-#define BUG() do { \
- __asm__ __volatile__( \
- "1: twi 31,0,0\n" \
- ".section __bug_table,\"a\"\n" \
- "\t"PPC_LONG" 1b,%0,%1,%2\n" \
- ".previous" \
- : : "i" (__LINE__), "i" (__FILE__), "i" (__FUNCTION__)); \
+#define BUG() do { \
+ __asm__ __volatile__( \
+ "1: twi 31,0,0\n" \
+ _EMIT_BUG_ENTRY \
+ : : "i" (__FILE__), "i" (__LINE__), \
+ "i" (0), "i" (sizeof(struct bug_entry))); \
+ for(;;) ; \
} while (0)
#define BUG_ON(x) do { \
BUG(); \
} else { \
__asm__ __volatile__( \
- "1: "PPC_TLNEI" %0,0\n" \
- ".section __bug_table,\"a\"\n" \
- "\t"PPC_LONG" 1b,%1,%2,%3\n" \
- ".previous" \
- : : "r" ((long)(x)), "i" (__LINE__), \
- "i" (__FILE__), "i" (__FUNCTION__)); \
+ "1: "PPC_TLNEI" %4,0\n" \
+ _EMIT_BUG_ENTRY \
+ : : "i" (__FILE__), "i" (__LINE__), "i" (0), \
+ "i" (sizeof(struct bug_entry)), \
+ "r" ((long)(x))); \
} \
} while (0)
#define __WARN() do { \
__asm__ __volatile__( \
"1: twi 31,0,0\n" \
- ".section __bug_table,\"a\"\n" \
- "\t"PPC_LONG" 1b,%0,%1,%2\n" \
- ".previous" \
- : : "i" (__LINE__ + BUG_WARNING_TRAP), \
- "i" (__FILE__), "i" (__FUNCTION__)); \
+ _EMIT_BUG_ENTRY \
+ : : "i" (__FILE__), "i" (__LINE__), \
+ "i" (BUGFLAG_WARNING), \
+ "i" (sizeof(struct bug_entry))); \
} while (0)
#define WARN_ON(x) ({ \
__WARN(); \
} else { \
__asm__ __volatile__( \
- "1: "PPC_TLNEI" %0,0\n" \
- ".section __bug_table,\"a\"\n" \
- "\t"PPC_LONG" 1b,%1,%2,%3\n" \
- ".previous" \
- : : "r" (__ret_warn_on), \
- "i" (__LINE__ + BUG_WARNING_TRAP), \
- "i" (__FILE__), "i" (__FUNCTION__)); \
+ "1: "PPC_TLNEI" %4,0\n" \
+ _EMIT_BUG_ENTRY \
+ : : "i" (__FILE__), "i" (__LINE__), \
+ "i" (BUGFLAG_WARNING), \
+ "i" (sizeof(struct bug_entry)), \
+ "r" (__ret_warn_on)); \
} \
unlikely(__ret_warn_on); \
})
unsigned int num_bugs;
};
-extern struct bug_entry *module_find_bug(unsigned long bugaddr);
-
/*
* Select ELF headers.
* Make empty section for module_frob_arch_sections to expand.