Blackfin: add support for GENERIC_BUG
authorMike Frysinger <vapier@gentoo.org>
Sun, 7 Jun 2009 21:18:25 +0000 (17:18 -0400)
committerMike Frysinger <vapier@gentoo.org>
Sat, 13 Jun 2009 11:20:07 +0000 (07:20 -0400)
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
arch/blackfin/Kconfig
arch/blackfin/include/asm/bug.h
arch/blackfin/kernel/traps.c
arch/blackfin/kernel/vmlinux.lds.S

index c56fd3e..74cdcf3 100644 (file)
@@ -28,6 +28,10 @@ config BLACKFIN
        select HAVE_OPROFILE
        select ARCH_WANT_OPTIONAL_GPIOLIB
 
+config GENERIC_BUG
+       def_bool y
+       depends on BUG
+
 config ZONE_DMA
        bool
        default y
index 6d3e11b..655e495 100644 (file)
@@ -2,13 +2,58 @@
 #define _BLACKFIN_BUG_H
 
 #ifdef CONFIG_BUG
-#define HAVE_ARCH_BUG
 
-#define BUG() do { \
-       dump_bfin_trace_buffer(); \
-       printk(KERN_EMERG "BUG: failure at %s:%d/%s()!\n", __FILE__, __LINE__, __func__); \
-       panic("BUG!"); \
-} while (0)
+#define BFIN_BUG_OPCODE        0xefcd
+
+#ifdef CONFIG_DEBUG_BUGVERBOSE
+
+#define _BUG_OR_WARN(flags)                                            \
+       asm volatile(                                                   \
+               "1:     .hword  %0\n"                                   \
+               "       .section __bug_table,\"a\",@progbits\n"         \
+               "2:     .long   1b\n"                                   \
+               "       .long   %1\n"                                   \
+               "       .short  %2\n"                                   \
+               "       .short  %3\n"                                   \
+               "       .org    2b + %4\n"                              \
+               "       .previous"                                      \
+               :                                                       \
+               : "i"(BFIN_BUG_OPCODE), "i"(__FILE__),                  \
+                 "i"(__LINE__), "i"(flags),                            \
+                 "i"(sizeof(struct bug_entry)))
+
+#else
+
+#define _BUG_OR_WARN(flags)                                            \
+       asm volatile(                                                   \
+               "1:     .hword  %0\n"                                   \
+               "       .section __bug_table,\"a\",@progbits\n"         \
+               "2:     .long   1b\n"                                   \
+               "       .short  %1\n"                                   \
+               "       .org    2b + %2\n"                              \
+               "       .previous"                                      \
+               :                                                       \
+               : "i"(BFIN_BUG_OPCODE), "i"(flags),                     \
+                 "i"(sizeof(struct bug_entry)))
+
+#endif /* CONFIG_DEBUG_BUGVERBOSE */
+
+#define BUG()                                                          \
+       do {                                                            \
+               _BUG_OR_WARN(0);                                        \
+               for (;;);                                               \
+       } while (0)
+
+#define WARN_ON(condition)                                                     \
+       ({                                                              \
+               int __ret_warn_on = !!(condition);                      \
+               if (unlikely(__ret_warn_on))                            \
+                       _BUG_OR_WARN(BUGFLAG_WARNING);                  \
+               unlikely(__ret_warn_on);                                \
+       })
+
+#define HAVE_ARCH_BUG
+#define HAVE_ARCH_WARN_ON
 
 #endif
 
index aa76dfb..2405f19 100644 (file)
@@ -27,6 +27,7 @@
  * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
+#include <linux/bug.h>
 #include <linux/uaccess.h>
 #include <linux/interrupt.h>
 #include <linux/module.h>
@@ -381,6 +382,23 @@ asmlinkage void trap_c(struct pt_regs *fp)
        /* 0x20 - Reserved, Caught by default */
        /* 0x21 - Undefined Instruction, handled here */
        case VEC_UNDEF_I:
+#ifdef CONFIG_BUG
+               if (kernel_mode_regs(fp)) {
+                       switch (report_bug(fp->pc, fp)) {
+                       case BUG_TRAP_TYPE_NONE:
+                               break;
+                       case BUG_TRAP_TYPE_WARN:
+                               dump_bfin_trace_buffer();
+                               fp->pc += 2;
+                               goto traps_done;
+                       case BUG_TRAP_TYPE_BUG:
+                               /* call to panic() will dump trace, and it is
+                                * off at this point, so it won't be clobbered
+                                */
+                               panic("BUG()");
+                       }
+               }
+#endif
                info.si_code = ILL_ILLOPC;
                sig = SIGILL;
                verbose_printk(KERN_NOTICE EXC_0x21(KERN_NOTICE));
@@ -792,6 +810,18 @@ void dump_bfin_trace_buffer(void)
 }
 EXPORT_SYMBOL(dump_bfin_trace_buffer);
 
+#ifdef CONFIG_BUG
+int is_valid_bugaddr(unsigned long addr)
+{
+       unsigned short opcode;
+
+       if (!get_instruction(&opcode, (unsigned short *)addr))
+               return 0;
+
+       return opcode == BFIN_BUG_OPCODE;
+}
+#endif
+
 /*
  * Checks to see if the address pointed to is either a
  * 16-bit CALL instruction, or a 32-bit CALL instruction
index 8b67167..119fbdb 100644 (file)
@@ -166,6 +166,20 @@ SECTIONS
        }
        PERCPU(4)
        SECURITY_INIT
+
+       /* we have to discard exit text and such at runtime, not link time, to
+        * handle embedded cross-section references (alt instructions, bug
+        * table, eh_frame, etc...)
+        */
+       .exit.text :
+       {
+               EXIT_TEXT
+       }
+       .exit.data :
+       {
+               EXIT_DATA
+       }
+
        .init.ramfs :
        {
                . = ALIGN(4);
@@ -264,8 +278,6 @@ SECTIONS
 
        /DISCARD/ :
        {
-               EXIT_TEXT
-               EXIT_DATA
                *(.exitcall.exit)
        }
 }