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.