Merge git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
[cascardo/linux.git] / arch / sh / kernel / traps.c
index ec11015..7b40f0f 100644 (file)
@@ -5,7 +5,7 @@
  *  SuperH version: Copyright (C) 1999 Niibe Yutaka
  *                  Copyright (C) 2000 Philipp Rumpf
  *                  Copyright (C) 2000 David Howells
- *                  Copyright (C) 2002 - 2006 Paul Mundt
+ *                  Copyright (C) 2002 - 2007 Paul Mundt
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
 #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>
 #include <asm/uaccess.h>
+#include <asm/kdebug.h>
 
 #ifdef CONFIG_SH_KGDB
 #include <asm/kgdb.h>
@@ -74,7 +76,21 @@ static void dump_mem(const char *str, unsigned long bottom, unsigned long top)
        }
 }
 
-DEFINE_SPINLOCK(die_lock);
+ATOMIC_NOTIFIER_HEAD(shdie_chain);
+
+int register_die_notifier(struct notifier_block *nb)
+{
+       return atomic_notifier_chain_register(&shdie_chain, nb);
+}
+EXPORT_SYMBOL(register_die_notifier);
+
+int unregister_die_notifier(struct notifier_block *nb)
+{
+       return atomic_notifier_chain_unregister(&shdie_chain, nb);
+}
+EXPORT_SYMBOL(unregister_die_notifier);
+
+static DEFINE_SPINLOCK(die_lock);
 
 void die(const char * str, struct pt_regs * regs, long err)
 {
@@ -130,40 +146,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 */
-#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
@@ -641,7 +623,7 @@ int is_dsp_inst(struct pt_regs *regs)
         * Safe guard if DSP mode is already enabled or we're lacking
         * the DSP altogether.
         */
-       if (!(cpu_data->flags & CPU_HAS_DSP) || (regs->sr & SR_DSP))
+       if (!(current_cpu_data.flags & CPU_HAS_DSP) || (regs->sr & SR_DSP))
                return 0;
 
        get_user(inst, ((unsigned short *) regs->pc));
@@ -888,6 +870,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)
 {