int ret = 0;
        kprobe_opcode_t *addr = NULL;
        unsigned long *lp;
-       struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+       struct kprobe_ctlblk *kcb;
+
+       /*
+        * We don't want to be preempted for the entire
+        * duration of kprobe processing
+        */
+       preempt_disable();
+       kcb = get_kprobe_ctlblk();
 
        /* Check if the application is using LDT entry for its code segment and
         * calculate the address by reading the base address from the LDT entry.
                goto no_kprobe;
        }
 
-       /*
-        * This preempt_disable() matches the preempt_enable_no_resched()
-        * in post_kprobe_handler()
-        */
-       preempt_disable();
        set_current_kprobe(p, regs, kcb);
        kcb->kprobe_status = KPROBE_HIT_ACTIVE;
 
        return 1;
 
 no_kprobe:
+       preempt_enable_no_resched();
        return ret;
 }
 
 
        /*
         * By returning a non-zero value, we are telling
-        * kprobe_handler() that we have handled unlocking
-        * and re-enabling preemption
+        * kprobe_handler() that we don't want the post_handler
+        * to run (and have re-enabled preemption)
         */
         return 1;
 }
        struct die_args *args = (struct die_args *)data;
        int ret = NOTIFY_DONE;
 
-       rcu_read_lock();
        switch (val) {
        case DIE_INT3:
                if (kprobe_handler(args->regs))
                break;
        case DIE_GPF:
        case DIE_PAGE_FAULT:
+               /* kprobe_running() needs smp_processor_id() */
+               preempt_disable();
                if (kprobe_running() &&
                    kprobe_fault_handler(args->regs, args->trapnr))
                        ret = NOTIFY_STOP;
+               preempt_enable();
                break;
        default:
                break;
        }
-       rcu_read_unlock();
        return ret;
 }
 
                *regs = kcb->jprobe_saved_regs;
                memcpy((kprobe_opcode_t *) stack_addr, kcb->jprobes_stack,
                       MIN_STACK_SIZE(stack_addr));
+               preempt_enable_no_resched();
                return 1;
        }
        return 0;
 
        spin_unlock_irqrestore(&kretprobe_lock, flags);
        preempt_enable_no_resched();
 
-        /*
-         * By returning a non-zero value, we are telling
-         * kprobe_handler() that we have handled unlocking
-        * and re-enabling preemption
-         */
+       /*
+        * By returning a non-zero value, we are telling
+        * kprobe_handler() that we don't want the post_handler
+        * to run (and have re-enabled preemption)
+        */
         return 1;
 }
 
        int ret = 0;
        struct pt_regs *regs = args->regs;
        kprobe_opcode_t *addr = (kprobe_opcode_t *)instruction_pointer(regs);
-       struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+       struct kprobe_ctlblk *kcb;
+
+       /*
+        * We don't want to be preempted for the entire
+        * duration of kprobe processing
+        */
+       preempt_disable();
+       kcb = get_kprobe_ctlblk();
 
        /* Handle recursion cases */
        if (kprobe_running()) {
                goto no_kprobe;
        }
 
-       /*
-        * This preempt_disable() matches the preempt_enable_no_resched()
-        * in post_kprobes_handler()
-        */
-       preempt_disable();
        set_current_kprobe(p, kcb);
        kcb->kprobe_status = KPROBE_HIT_ACTIVE;
 
        return 1;
 
 no_kprobe:
+       preempt_enable_no_resched();
        return ret;
 }
 
        struct kprobe *cur = kprobe_running();
        struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
 
-       if (!cur)
-               return 0;
-
        if (cur->fault_handler && cur->fault_handler(cur, regs, trapnr))
                return 1;
 
        struct die_args *args = (struct die_args *)data;
        int ret = NOTIFY_DONE;
 
-       rcu_read_lock();
        switch(val) {
        case DIE_BREAK:
                if (pre_kprobes_handler(args))
                        ret = NOTIFY_STOP;
                break;
        case DIE_PAGE_FAULT:
-               if (kprobes_fault_handler(args->regs, args->trapnr))
+               /* kprobe_running() needs smp_processor_id() */
+               preempt_disable();
+               if (kprobe_running() &&
+                       kprobes_fault_handler(args->regs, args->trapnr))
                        ret = NOTIFY_STOP;
+               preempt_enable();
        default:
                break;
        }
-       rcu_read_unlock();
        return ret;
 }
 
        struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
 
        *regs = kcb->jprobe_saved_regs;
+       preempt_enable_no_resched();
        return 1;
 }
 
 
        struct kprobe *p;
        int ret = 0;
        unsigned int *addr = (unsigned int *)regs->nip;
-       struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+       struct kprobe_ctlblk *kcb;
+
+       /*
+        * We don't want to be preempted for the entire
+        * duration of kprobe processing
+        */
+       preempt_disable();
+       kcb = get_kprobe_ctlblk();
 
        /* Check we're not actually recursing */
        if (kprobe_running()) {
                goto no_kprobe;
        }
 
-       /*
-        * This preempt_disable() matches the preempt_enable_no_resched()
-        * in post_kprobe_handler().
-        */
-       preempt_disable();
        kcb->kprobe_status = KPROBE_HIT_ACTIVE;
        set_current_kprobe(p, regs, kcb);
        if (p->pre_handler && p->pre_handler(p, regs))
        return 1;
 
 no_kprobe:
+       preempt_enable_no_resched();
        return ret;
 }
 
 
         /*
          * By returning a non-zero value, we are telling
-         * kprobe_handler() that we have handled unlocking
-         * and re-enabling preemption.
+         * kprobe_handler() that we don't want the post_handler
+         * to run (and have re-enabled preemption)
          */
         return 1;
 }
        struct die_args *args = (struct die_args *)data;
        int ret = NOTIFY_DONE;
 
-       rcu_read_lock();
        switch (val) {
        case DIE_BPT:
                if (kprobe_handler(args->regs))
                        ret = NOTIFY_STOP;
                break;
        case DIE_PAGE_FAULT:
+               /* kprobe_running() needs smp_processor_id() */
+               preempt_disable();
                if (kprobe_running() &&
                    kprobe_fault_handler(args->regs, args->trapnr))
                        ret = NOTIFY_STOP;
+               preempt_enable();
                break;
        default:
                break;
        }
-       rcu_read_unlock();
        return ret;
 }
 
         * saved regs...
         */
        memcpy(regs, &kcb->jprobe_saved_regs, sizeof(struct pt_regs));
+       preempt_enable_no_resched();
        return 1;
 }
 
 
        struct kprobe *p;
        void *addr = (void *) regs->tpc;
        int ret = 0;
-       struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+       struct kprobe_ctlblk *kcb;
+
+       /*
+        * We don't want to be preempted for the entire
+        * duration of kprobe processing
+        */
+       preempt_disable();
+       kcb = get_kprobe_ctlblk();
 
        if (kprobe_running()) {
                p = get_kprobe(addr);
                goto no_kprobe;
        }
 
-       /*
-        * This preempt_disable() matches the preempt_enable_no_resched()
-        * in post_kprobes_handler()
-        */
-       preempt_disable();
        set_current_kprobe(p, regs, kcb);
        kcb->kprobe_status = KPROBE_HIT_ACTIVE;
        if (p->pre_handler && p->pre_handler(p, regs))
        return 1;
 
 no_kprobe:
+       preempt_enable_no_resched();
        return ret;
 }
 
        struct die_args *args = (struct die_args *)data;
        int ret = NOTIFY_DONE;
 
-       rcu_read_lock();
        switch (val) {
        case DIE_DEBUG:
                if (kprobe_handler(args->regs))
                break;
        case DIE_GPF:
        case DIE_PAGE_FAULT:
+               /* kprobe_running() needs smp_processor_id() */
+               preempt_disable();
                if (kprobe_running() &&
                    kprobe_fault_handler(args->regs, args->trapnr))
                        ret = NOTIFY_STOP;
+               preempt_enable();
                break;
        default:
                break;
        }
-       rcu_read_unlock();
        return ret;
 }
 
                       &(kcb->jprobe_saved_stack),
                       sizeof(kcb->jprobe_saved_stack));
 
+               preempt_enable_no_resched();
                return 1;
        }
        return 0;
 
         }
 }
 
-/*
- * Interrupts are disabled on entry as trap3 is an interrupt gate and they
- * remain disabled thorough out this function.
- */
 int __kprobes kprobe_handler(struct pt_regs *regs)
 {
        struct kprobe *p;
        int ret = 0;
        kprobe_opcode_t *addr = (kprobe_opcode_t *)(regs->rip - sizeof(kprobe_opcode_t));
-       struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+       struct kprobe_ctlblk *kcb;
+
+       /*
+        * We don't want to be preempted for the entire
+        * duration of kprobe processing
+        */
+       preempt_disable();
+       kcb = get_kprobe_ctlblk();
 
        /* Check we're not actually recursing */
        if (kprobe_running()) {
                goto no_kprobe;
        }
 
-       /*
-        * This preempt_disable() matches the preempt_enable_no_resched()
-        * in post_kprobe_handler()
-        */
-       preempt_disable();
        set_current_kprobe(p, regs, kcb);
        kcb->kprobe_status = KPROBE_HIT_ACTIVE;
 
        return 1;
 
 no_kprobe:
+       preempt_enable_no_resched();
        return ret;
 }
 
 
         /*
          * By returning a non-zero value, we are telling
-         * kprobe_handler() that we have handled unlocking
-        * and re-enabling preemption
+         * kprobe_handler() that we don't want the post_handler
+        * to run (and have re-enabled preemption)
          */
         return 1;
 }
        struct die_args *args = (struct die_args *)data;
        int ret = NOTIFY_DONE;
 
-       rcu_read_lock();
        switch (val) {
        case DIE_INT3:
                if (kprobe_handler(args->regs))
                break;
        case DIE_GPF:
        case DIE_PAGE_FAULT:
+               /* kprobe_running() needs smp_processor_id() */
+               preempt_disable();
                if (kprobe_running() &&
                    kprobe_fault_handler(args->regs, args->trapnr))
                        ret = NOTIFY_STOP;
+               preempt_enable();
                break;
        default:
                break;
        }
-       rcu_read_unlock();
        return ret;
 }
 
                *regs = kcb->jprobe_saved_regs;
                memcpy((kprobe_opcode_t *) stack_addr, kcb->jprobes_stack,
                       MIN_STACK_SIZE(stack_addr));
+               preempt_enable_no_resched();
                return 1;
        }
        return 0;
 
 extern kprobe_opcode_t *get_insn_slot(void);
 extern void free_insn_slot(kprobe_opcode_t *slot);
 
-/* Get the kprobe at this addr (if any) - called under a rcu_read_lock() */
+/* Get the kprobe at this addr (if any) - called with preemption disabled */
 struct kprobe *get_kprobe(void *addr);
 struct hlist_head * kretprobe_inst_table_head(struct task_struct *tsk);
 
 
  * This routine is called either:
  *     - under the kprobe_lock spinlock - during kprobe_[un]register()
  *                             OR
- *     - under an rcu_read_lock() - from arch/xxx/kernel/kprobes.c
+ *     - with preemption disabled - from arch/xxx/kernel/kprobes.c
  */
 struct kprobe __kprobes *get_kprobe(void *addr)
 {