Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/cooloney...
[pandora-kernel.git] / arch / arm / kernel / traps.c
index 4764bd9..7277aef 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/kallsyms.h>
 #include <linux/delay.h>
 #include <linux/init.h>
+#include <linux/kprobes.h>
 
 #include <asm/atomic.h>
 #include <asm/cacheflush.h>
@@ -46,15 +47,6 @@ __setup("user_debug=", user_debug_setup);
 
 static void dump_mem(const char *str, unsigned long bottom, unsigned long top);
 
-static inline int in_exception_text(unsigned long ptr)
-{
-       extern char __exception_text_start[];
-       extern char __exception_text_end[];
-
-       return ptr >= (unsigned long)&__exception_text_start &&
-              ptr < (unsigned long)&__exception_text_end;
-}
-
 void dump_backtrace_entry(unsigned long where, unsigned long from, unsigned long frame)
 {
 #ifdef CONFIG_KALLSYMS
@@ -322,12 +314,23 @@ asmlinkage void __exception do_undefinstr(struct pt_regs *regs)
                get_user(instr, (u32 __user *)pc);
        }
 
+#ifdef CONFIG_KPROBES
+       /*
+        * It is possible to have recursive kprobes, so we can't call
+        * the kprobe trap handler with the undef_lock held.
+        */
+       if (instr == KPROBE_BREAKPOINT_INSTRUCTION && !user_mode(regs)) {
+               kprobe_trap_handler(regs, instr);
+               return;
+       }
+#endif
+
        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) {
                        if (hook->fn(regs, instr) == 0) {
-                               spin_unlock_irq(&undef_lock);
+                               spin_unlock_irqrestore(&undef_lock, flags);
                                return;
                        }
                }
@@ -509,7 +512,7 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs)
         * existence.  Don't ever use this from user code.
         */
        case 0xfff0:
-       {
+       for (;;) {
                extern void do_DataAbort(unsigned long addr, unsigned int fsr,
                                         struct pt_regs *regs);
                unsigned long val;
@@ -545,7 +548,6 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs)
                up_read(&mm->mmap_sem);
                /* simulate a write access fault */
                do_DataAbort(addr, 15 + (1 << 11), regs);
-               return -1;
        }
 #endif
 
@@ -705,6 +707,11 @@ void abort(void)
 EXPORT_SYMBOL(abort);
 
 void __init trap_init(void)
+{
+       return;
+}
+
+void __init early_trap_init(void)
 {
        unsigned long vectors = CONFIG_VECTORS_BASE;
        extern char __stubs_start[], __stubs_end[];