Merge branch 'x86-geode-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[pandora-kernel.git] / arch / arm / kernel / traps.c
index bc9f9da..99a5727 100644 (file)
 #include <linux/kdebug.h>
 #include <linux/module.h>
 #include <linux/kexec.h>
+#include <linux/bug.h>
 #include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/sched.h>
 
 #include <linux/atomic.h>
 #include <asm/cacheflush.h>
+#include <asm/exception.h>
 #include <asm/system.h>
 #include <asm/unistd.h>
 #include <asm/traps.h>
@@ -255,7 +257,7 @@ static int __die(const char *str, int err, struct thread_info *thread, struct pt
        return ret;
 }
 
-static DEFINE_SPINLOCK(die_lock);
+static DEFINE_RAW_SPINLOCK(die_lock);
 
 /*
  * This function is protected against re-entrancy.
@@ -267,9 +269,11 @@ void die(const char *str, struct pt_regs *regs, int err)
 
        oops_enter();
 
-       spin_lock_irq(&die_lock);
+       raw_spin_lock_irq(&die_lock);
        console_verbose();
        bust_spinlocks(1);
+       if (!user_mode(regs))
+               report_bug(regs->ARM_pc, regs);
        ret = __die(str, err, thread, regs);
 
        if (regs && kexec_should_crash(thread->task))
@@ -277,7 +281,7 @@ void die(const char *str, struct pt_regs *regs, int err)
 
        bust_spinlocks(0);
        add_taint(TAINT_DIE);
-       spin_unlock_irq(&die_lock);
+       raw_spin_unlock_irq(&die_lock);
        oops_exit();
 
        if (in_interrupt())
@@ -301,25 +305,43 @@ void arm_notify_die(const char *str, struct pt_regs *regs,
        }
 }
 
+#ifdef CONFIG_GENERIC_BUG
+
+int is_valid_bugaddr(unsigned long pc)
+{
+#ifdef CONFIG_THUMB2_KERNEL
+       unsigned short bkpt;
+#else
+       unsigned long bkpt;
+#endif
+
+       if (probe_kernel_address((unsigned *)pc, bkpt))
+               return 0;
+
+       return bkpt == BUG_INSTR_VALUE;
+}
+
+#endif
+
 static LIST_HEAD(undef_hook);
-static DEFINE_SPINLOCK(undef_lock);
+static DEFINE_RAW_SPINLOCK(undef_lock);
 
 void register_undef_hook(struct undef_hook *hook)
 {
        unsigned long flags;
 
-       spin_lock_irqsave(&undef_lock, flags);
+       raw_spin_lock_irqsave(&undef_lock, flags);
        list_add(&hook->node, &undef_hook);
-       spin_unlock_irqrestore(&undef_lock, flags);
+       raw_spin_unlock_irqrestore(&undef_lock, flags);
 }
 
 void unregister_undef_hook(struct undef_hook *hook)
 {
        unsigned long flags;
 
-       spin_lock_irqsave(&undef_lock, flags);
+       raw_spin_lock_irqsave(&undef_lock, flags);
        list_del(&hook->node);
-       spin_unlock_irqrestore(&undef_lock, flags);
+       raw_spin_unlock_irqrestore(&undef_lock, flags);
 }
 
 static int call_undef_hook(struct pt_regs *regs, unsigned int instr)
@@ -328,12 +350,12 @@ static int call_undef_hook(struct pt_regs *regs, unsigned int instr)
        unsigned long flags;
        int (*fn)(struct pt_regs *regs, unsigned int instr) = NULL;
 
-       spin_lock_irqsave(&undef_lock, flags);
+       raw_spin_lock_irqsave(&undef_lock, flags);
        list_for_each_entry(hook, &undef_hook, node)
                if ((instr & hook->instr_mask) == hook->instr_val &&
                    (regs->ARM_cpsr & hook->cpsr_mask) == hook->cpsr_val)
                        fn = hook->fn;
-       spin_unlock_irqrestore(&undef_lock, flags);
+       raw_spin_unlock_irqrestore(&undef_lock, flags);
 
        return fn ? fn(regs, instr) : 1;
 }
@@ -706,16 +728,6 @@ baddataabort(int code, unsigned long instr, struct pt_regs *regs)
        arm_notify_die("unknown data abort code", regs, &info, instr, 0);
 }
 
-void __attribute__((noreturn)) __bug(const char *file, int line)
-{
-       printk(KERN_CRIT"kernel BUG at %s:%d!\n", file, line);
-       *(int *)0 = 0;
-
-       /* Avoid "noreturn function does return" */
-       for (;;);
-}
-EXPORT_SYMBOL(__bug);
-
 void __readwrite_bug(const char *fn)
 {
        printk("%s called, but not implemented\n", fn);