#include <asm/traps.h>
 #include <asm/cacheflush.h>
 
-/*
- * This undefined instruction must be unique and
- * reserved solely for kprobes' use.
- */
-#define KPROBE_BREAKPOINT_INSTRUCTION  0xe7f001f8
-
 #define MIN_STACK_SIZE(addr)                           \
        min((unsigned long)MAX_STACK_SIZE,              \
            (unsigned long)current_thread_info() + THREAD_START_SP - (addr))
        }
 }
 
-static int kprobe_trap_handler(struct pt_regs *regs, unsigned int instr)
+int kprobe_trap_handler(struct pt_regs *regs, unsigned int instr)
 {
        kprobe_handler(regs);
        return 0;
 
 #include <linux/kallsyms.h>
 #include <linux/delay.h>
 #include <linux/init.h>
+#include <linux/kprobes.h>
 
 #include <asm/atomic.h>
 #include <asm/cacheflush.h>
                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 &&
 
 #define MAX_INSN_SIZE                  2
 #define MAX_STACK_SIZE                 64      /* 32 would probably be OK */
 
+/*
+ * This undefined instruction must be unique and
+ * reserved solely for kprobes' use.
+ */
+#define KPROBE_BREAKPOINT_INSTRUCTION  0xe7f001f8
+
 #define regs_return_value(regs)                ((regs)->ARM_r0)
 #define flush_insn_slot(p)             do { } while (0)
 #define kretprobe_blacklist_size       0
 
 void arch_remove_kprobe(struct kprobe *);
 
+int kprobe_trap_handler(struct pt_regs *regs, unsigned int instr);
 int kprobe_fault_handler(struct pt_regs *regs, unsigned int fsr);
 int kprobe_exceptions_notify(struct notifier_block *self,
                             unsigned long val, void *data);