#include <linux/config.h>
 #include <linux/kprobes.h>
 #include <linux/ptrace.h>
-#include <linux/spinlock.h>
 #include <linux/preempt.h>
 #include <asm/cacheflush.h>
 #include <asm/kdebug.h>
                regs->eip = (unsigned long)&p->ainsn.insn;
 }
 
+/* Called with kretprobe_lock held */
 void __kprobes arch_prepare_kretprobe(struct kretprobe *rp,
                                      struct pt_regs *regs)
 {
        }
        /* Check we're not actually recursing */
        if (kprobe_running()) {
-               /* We *are* holding lock here, so this is safe.
-                  Disarm the probe we just hit, and ignore it. */
                p = get_kprobe(addr);
                if (p) {
                        if (kcb->kprobe_status == KPROBE_HIT_SS &&
                                *p->ainsn.insn == BREAKPOINT_INSTRUCTION) {
                                regs->eflags &= ~TF_MASK;
                                regs->eflags |= kcb->kprobe_saved_eflags;
-                               unlock_kprobes();
                                goto no_kprobe;
                        }
                        /* We have reentered the kprobe_handler(), since
                                goto ss_probe;
                        }
                }
-               /* If it's not ours, can't be delete race, (we hold lock). */
                goto no_kprobe;
        }
 
-       lock_kprobes();
        p = get_kprobe(addr);
        if (!p) {
-               unlock_kprobes();
                if (regs->eflags & VM_MASK) {
                        /* We are in virtual-8086 mode. Return 0 */
                        goto no_kprobe;
         struct kretprobe_instance *ri = NULL;
         struct hlist_head *head;
         struct hlist_node *node, *tmp;
-       unsigned long orig_ret_address = 0;
+       unsigned long flags, orig_ret_address = 0;
        unsigned long trampoline_address =(unsigned long)&kretprobe_trampoline;
 
+       spin_lock_irqsave(&kretprobe_lock, flags);
         head = kretprobe_inst_table_head(current);
 
        /*
        regs->eip = orig_ret_address;
 
        reset_current_kprobe();
-       unlock_kprobes();
+       spin_unlock_irqrestore(&kretprobe_lock, flags);
        preempt_enable_no_resched();
 
        /*
 
 /*
  * Interrupts are disabled on entry as trap1 is an interrupt gate and they
- * remain disabled thoroughout this function.  And we hold kprobe lock.
+ * remain disabled thoroughout this function.
  */
 static inline int post_kprobe_handler(struct pt_regs *regs)
 {
                goto out;
        }
        reset_current_kprobe();
-       unlock_kprobes();
 out:
        preempt_enable_no_resched();
 
        return 1;
 }
 
-/* Interrupts disabled, kprobe_lock held. */
 static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr)
 {
        struct kprobe *cur = kprobe_running();
                regs->eflags |= kcb->kprobe_old_eflags;
 
                reset_current_kprobe();
-               unlock_kprobes();
                preempt_enable_no_resched();
        }
        return 0;
        struct die_args *args = (struct die_args *)data;
        int ret = NOTIFY_DONE;
 
-       preempt_disable();
+       rcu_read_lock();
        switch (val) {
        case DIE_INT3:
                if (kprobe_handler(args->regs))
        default:
                break;
        }
-       preempt_enable();
+       rcu_read_unlock();
        return ret;
 }
 
 
 #include <linux/config.h>
 #include <linux/kprobes.h>
 #include <linux/ptrace.h>
-#include <linux/spinlock.h>
 #include <linux/string.h>
 #include <linux/slab.h>
 #include <linux/preempt.h>
        struct kretprobe_instance *ri = NULL;
        struct hlist_head *head;
        struct hlist_node *node, *tmp;
-       unsigned long orig_ret_address = 0;
+       unsigned long flags, orig_ret_address = 0;
        unsigned long trampoline_address =
                ((struct fnptr *)kretprobe_trampoline)->ip;
 
+       spin_lock_irqsave(&kretprobe_lock, flags);
         head = kretprobe_inst_table_head(current);
 
        /*
        regs->cr_iip = orig_ret_address;
 
        reset_current_kprobe();
-       unlock_kprobes();
+       spin_unlock_irqrestore(&kretprobe_lock, flags);
        preempt_enable_no_resched();
 
         /*
         return 1;
 }
 
+/* Called with kretprobe_lock held */
 void __kprobes arch_prepare_kretprobe(struct kretprobe *rp,
                                      struct pt_regs *regs)
 {
                        if ((kcb->kprobe_status == KPROBE_HIT_SS) &&
                             (p->ainsn.inst_flag == INST_FLAG_BREAK_INST)) {
                                ia64_psr(regs)->ss = 0;
-                               unlock_kprobes();
                                goto no_kprobe;
                        }
                        /* We have reentered the pre_kprobe_handler(), since
                }
        }
 
-       lock_kprobes();
        p = get_kprobe(addr);
        if (!p) {
-               unlock_kprobes();
                if (!is_ia64_break_inst(regs)) {
                        /*
                         * The breakpoint instruction was removed right
                goto out;
        }
        reset_current_kprobe();
-       unlock_kprobes();
 
 out:
        preempt_enable_no_resched();
        if (kcb->kprobe_status & KPROBE_HIT_SS) {
                resume_execution(cur, regs);
                reset_current_kprobe();
-               unlock_kprobes();
                preempt_enable_no_resched();
        }
 
        struct die_args *args = (struct die_args *)data;
        int ret = NOTIFY_DONE;
 
-       preempt_disable();
+       rcu_read_lock();
        switch(val) {
        case DIE_BREAK:
                if (pre_kprobes_handler(args))
        default:
                break;
        }
-       preempt_enable();
+       rcu_read_unlock();
        return ret;
 }
 
 
 #include <linux/config.h>
 #include <linux/kprobes.h>
 #include <linux/ptrace.h>
-#include <linux/spinlock.h>
 #include <linux/preempt.h>
 #include <asm/cacheflush.h>
 #include <asm/kdebug.h>
        kcb->kprobe_saved_msr = regs->msr;
 }
 
+/* Called with kretprobe_lock held */
 void __kprobes arch_prepare_kretprobe(struct kretprobe *rp,
                                      struct pt_regs *regs)
 {
 
        /* Check we're not actually recursing */
        if (kprobe_running()) {
-               /* We *are* holding lock here, so this is safe.
-                  Disarm the probe we just hit, and ignore it. */
                p = get_kprobe(addr);
                if (p) {
                        kprobe_opcode_t insn = *p->ainsn.insn;
                                        is_trap(insn)) {
                                regs->msr &= ~MSR_SE;
                                regs->msr |= kcb->kprobe_saved_msr;
-                               unlock_kprobes();
                                goto no_kprobe;
                        }
                        /* We have reentered the kprobe_handler(), since
                                goto ss_probe;
                        }
                }
-               /* If it's not ours, can't be delete race, (we hold lock). */
                goto no_kprobe;
        }
 
-       lock_kprobes();
        p = get_kprobe(addr);
        if (!p) {
-               unlock_kprobes();
                if (*addr != BREAKPOINT_INSTRUCTION) {
                        /*
                         * PowerPC has multiple variants of the "trap"
         struct kretprobe_instance *ri = NULL;
         struct hlist_head *head;
         struct hlist_node *node, *tmp;
-       unsigned long orig_ret_address = 0;
+       unsigned long flags, orig_ret_address = 0;
        unsigned long trampoline_address =(unsigned long)&kretprobe_trampoline;
 
+       spin_lock_irqsave(&kretprobe_lock, flags);
         head = kretprobe_inst_table_head(current);
 
        /*
        regs->nip = orig_ret_address;
 
        reset_current_kprobe();
-       unlock_kprobes();
+       spin_unlock_irqrestore(&kretprobe_lock, flags);
        preempt_enable_no_resched();
 
         /*
                goto out;
        }
        reset_current_kprobe();
-       unlock_kprobes();
 out:
        preempt_enable_no_resched();
 
        return 1;
 }
 
-/* Interrupts disabled, kprobe_lock held. */
 static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr)
 {
        struct kprobe *cur = kprobe_running();
                regs->msr |= kcb->kprobe_saved_msr;
 
                reset_current_kprobe();
-               unlock_kprobes();
                preempt_enable_no_resched();
        }
        return 0;
        struct die_args *args = (struct die_args *)data;
        int ret = NOTIFY_DONE;
 
-       /*
-        * Interrupts are not disabled here.  We need to disable
-        * preemption, because kprobe_running() uses smp_processor_id().
-        */
-       preempt_disable();
+       rcu_read_lock();
        switch (val) {
        case DIE_BPT:
                if (kprobe_handler(args->regs))
        default:
                break;
        }
-       preempt_enable_no_resched();
+       rcu_read_unlock();
        return ret;
 }
 
 
        struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
 
        if (kprobe_running()) {
-               /* We *are* holding lock here, so this is safe.
-                * Disarm the probe we just hit, and ignore it.
-                */
                p = get_kprobe(addr);
                if (p) {
                        if (kcb->kprobe_status == KPROBE_HIT_SS) {
                                regs->tstate = ((regs->tstate & ~TSTATE_PIL) |
                                        kcb->kprobe_orig_tstate_pil);
-                               unlock_kprobes();
                                goto no_kprobe;
                        }
                        /* We have reentered the kprobe_handler(), since
                        if (p->break_handler && p->break_handler(p, regs))
                                goto ss_probe;
                }
-               /* If it's not ours, can't be delete race, (we hold lock). */
                goto no_kprobe;
        }
 
-       lock_kprobes();
        p = get_kprobe(addr);
        if (!p) {
-               unlock_kprobes();
                if (*(u32 *)addr != BREAKPOINT_INSTRUCTION) {
                        /*
                         * The breakpoint instruction was removed right
                goto out;
        }
        reset_current_kprobe();
-       unlock_kprobes();
 out:
        preempt_enable_no_resched();
 
        return 1;
 }
 
-/* Interrupts disabled, kprobe_lock held. */
 static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr)
 {
        struct kprobe *cur = kprobe_running();
                resume_execution(cur, regs, kcb);
 
                reset_current_kprobe();
-               unlock_kprobes();
                preempt_enable_no_resched();
        }
        return 0;
        struct die_args *args = (struct die_args *)data;
        int ret = NOTIFY_DONE;
 
-       preempt_disable();
+       rcu_read_lock();
        switch (val) {
        case DIE_DEBUG:
                if (kprobe_handler(args->regs))
        default:
                break;
        }
-       preempt_enable();
+       rcu_read_unlock();
        return ret;
 }
 
 
 #include <linux/config.h>
 #include <linux/kprobes.h>
 #include <linux/ptrace.h>
-#include <linux/spinlock.h>
 #include <linux/string.h>
 #include <linux/slab.h>
 #include <linux/preempt.h>
                regs->rip = (unsigned long)p->ainsn.insn;
 }
 
+/* Called with kretprobe_lock held */
 void __kprobes arch_prepare_kretprobe(struct kretprobe *rp,
                                      struct pt_regs *regs)
 {
 
        /* Check we're not actually recursing */
        if (kprobe_running()) {
-               /* We *are* holding lock here, so this is safe.
-                  Disarm the probe we just hit, and ignore it. */
                p = get_kprobe(addr);
                if (p) {
                        if (kcb->kprobe_status == KPROBE_HIT_SS &&
                                *p->ainsn.insn == BREAKPOINT_INSTRUCTION) {
                                regs->eflags &= ~TF_MASK;
                                regs->eflags |= kcb->kprobe_saved_rflags;
-                               unlock_kprobes();
                                goto no_kprobe;
                        } else if (kcb->kprobe_status == KPROBE_HIT_SSDONE) {
                                /* TODO: Provide re-entrancy from
                                goto ss_probe;
                        }
                }
-               /* If it's not ours, can't be delete race, (we hold lock). */
                goto no_kprobe;
        }
 
-       lock_kprobes();
        p = get_kprobe(addr);
        if (!p) {
-               unlock_kprobes();
                if (*addr != BREAKPOINT_INSTRUCTION) {
                        /*
                         * The breakpoint instruction was removed right
         struct kretprobe_instance *ri = NULL;
         struct hlist_head *head;
         struct hlist_node *node, *tmp;
-       unsigned long orig_ret_address = 0;
+       unsigned long flags, orig_ret_address = 0;
        unsigned long trampoline_address =(unsigned long)&kretprobe_trampoline;
 
+       spin_lock_irqsave(&kretprobe_lock, flags);
         head = kretprobe_inst_table_head(current);
 
        /*
        regs->rip = orig_ret_address;
 
        reset_current_kprobe();
-       unlock_kprobes();
+       spin_unlock_irqrestore(&kretprobe_lock, flags);
        preempt_enable_no_resched();
 
         /*
        }
 }
 
-/*
- * Interrupts are disabled on entry as trap1 is an interrupt gate and they
- * remain disabled thoroughout this function.  And we hold kprobe lock.
- */
 int __kprobes post_kprobe_handler(struct pt_regs *regs)
 {
        struct kprobe *cur = kprobe_running();
        if (kcb->kprobe_status == KPROBE_REENTER) {
                restore_previous_kprobe(kcb);
                goto out;
-       } else {
-               unlock_kprobes();
        }
        reset_current_kprobe();
 out:
        return 1;
 }
 
-/* Interrupts disabled, kprobe_lock held. */
 int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
 {
        struct kprobe *cur = kprobe_running();
                regs->eflags |= kcb->kprobe_old_rflags;
 
                reset_current_kprobe();
-               unlock_kprobes();
                preempt_enable_no_resched();
        }
        return 0;
        struct die_args *args = (struct die_args *)data;
        int ret = NOTIFY_DONE;
 
-       preempt_disable();
+       rcu_read_lock();
        switch (val) {
        case DIE_INT3:
                if (kprobe_handler(args->regs))
        default:
                break;
        }
-       preempt_enable();
+       rcu_read_unlock();
        return ret;
 }