[PATCH] Kprobes: preempt_disable/enable() simplification
[safe/jmp/linux-2.6] / arch / x86_64 / kernel / kprobes.c
index 9bef2c8..dddeb67 100644 (file)
@@ -286,16 +286,19 @@ void __kprobes arch_prepare_kretprobe(struct kretprobe *rp,
         }
 }
 
-/*
- * 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()) {
@@ -359,11 +362,6 @@ int __kprobes kprobe_handler(struct pt_regs *regs)
                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;
 
@@ -377,6 +375,7 @@ ss_probe:
        return 1;
 
 no_kprobe:
+       preempt_enable_no_resched();
        return ret;
 }
 
@@ -448,8 +447,8 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
 
         /*
          * 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;
 }
@@ -594,7 +593,6 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
        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))
@@ -606,14 +604,16 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
                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;
 }
 
@@ -675,6 +675,7 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
                *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;