return 1;
 }
 
+static void __kprobes skip_singlestep(struct kprobe *p, struct pt_regs *regs,
+                                     struct kprobe_ctlblk *kcb);
 /*
  * Interrupts are disabled on entry as trap3 is an interrupt gate and they
  * remain disabled throughout this function.
        } else if (kprobe_running()) {
                p = __this_cpu_read(current_kprobe);
                if (p->break_handler && p->break_handler(p, regs)) {
+#ifdef KPROBES_CAN_USE_FTRACE
+                       if (kprobe_ftrace(p)) {
+                               skip_singlestep(p, regs, kcb);
+                               return 1;
+                       }
+#endif
                        setup_singlestep(p, regs, kcb, 0);
                        return 1;
                }
 }
 
 #ifdef KPROBES_CAN_USE_FTRACE
+static void __kprobes skip_singlestep(struct kprobe *p, struct pt_regs *regs,
+                                     struct kprobe_ctlblk *kcb)
+{
+       /*
+        * Emulate singlestep (and also recover regs->ip)
+        * as if there is a 5byte nop
+        */
+       regs->ip = (unsigned long)p->addr + MCOUNT_INSN_SIZE;
+       if (unlikely(p->post_handler)) {
+               kcb->kprobe_status = KPROBE_HIT_SSDONE;
+               p->post_handler(p, regs, 0);
+       }
+       __this_cpu_write(current_kprobe, NULL);
+}
+
 /* Ftrace callback handler for kprobes */
 void __kprobes kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip,
                                     struct ftrace_ops *ops, struct pt_regs *regs)
 
                __this_cpu_write(current_kprobe, p);
                kcb->kprobe_status = KPROBE_HIT_ACTIVE;
-               if (p->pre_handler)
-                       p->pre_handler(p, regs);
-
-               if (unlikely(p->post_handler)) {
-                       /*
-                        * Emulate singlestep (and also recover regs->ip)
-                        * as if there is a 5byte nop
-                        */
-                       regs->ip = ip + MCOUNT_INSN_SIZE;
-                       kcb->kprobe_status = KPROBE_HIT_SSDONE;
-                       p->post_handler(p, regs, 0);
-               }
-               __this_cpu_write(current_kprobe, NULL);
+               if (!p->pre_handler || !p->pre_handler(p, regs))
+                       skip_singlestep(p, regs, kcb);
+               /*
+                * If pre_handler returns !0, it sets regs->ip and
+                * resets current kprobe.
+                */
        }
 end:
        local_irq_restore(flags);