x86: kprobes change kprobe_handler flow
Make the control flow of kprobe_handler more obvious. Collapse the separate if blocks/gotos with if/else blocks this unifies the duplication of the check for a breakpoint instruction race with another cpu. Create two jump targets: preempt_out: re-enables preemption before returning ret out: only returns ret Signed-off-by: Harvey Harrison <harvey.harrison@gmail.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
This commit is contained in:
parent
33cb524383
commit
b976015637
|
@ -494,32 +494,28 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
|
||||||
preempt_disable();
|
preempt_disable();
|
||||||
kcb = get_kprobe_ctlblk();
|
kcb = get_kprobe_ctlblk();
|
||||||
|
|
||||||
/* Check we're not actually recursing */
|
|
||||||
if (kprobe_running()) {
|
|
||||||
p = get_kprobe(addr);
|
p = get_kprobe(addr);
|
||||||
if (p) {
|
if (p) {
|
||||||
|
/* Check we're not actually recursing */
|
||||||
|
if (kprobe_running()) {
|
||||||
ret = reenter_kprobe(p, regs, kcb);
|
ret = reenter_kprobe(p, regs, kcb);
|
||||||
if (kcb->kprobe_status == KPROBE_REENTER)
|
if (kcb->kprobe_status == KPROBE_REENTER)
|
||||||
return 1;
|
{
|
||||||
} else {
|
|
||||||
if (*addr != BREAKPOINT_INSTRUCTION) {
|
|
||||||
/* The breakpoint instruction was removed by
|
|
||||||
* another cpu right after we hit, no further
|
|
||||||
* handling of this interrupt is appropriate
|
|
||||||
*/
|
|
||||||
regs->ip = (unsigned long)addr;
|
|
||||||
ret = 1;
|
ret = 1;
|
||||||
goto no_kprobe;
|
goto out;
|
||||||
}
|
}
|
||||||
p = __get_cpu_var(current_kprobe);
|
goto preempt_out;
|
||||||
if (p->break_handler && p->break_handler(p, regs))
|
} else {
|
||||||
goto ss_probe;
|
set_current_kprobe(p, regs, kcb);
|
||||||
|
kcb->kprobe_status = KPROBE_HIT_ACTIVE;
|
||||||
|
if (p->pre_handler && p->pre_handler(p, regs))
|
||||||
|
{
|
||||||
|
/* handler set things up, skip ss setup */
|
||||||
|
ret = 1;
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
goto no_kprobe;
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
p = get_kprobe(addr);
|
|
||||||
if (!p) {
|
|
||||||
if (*addr != BREAKPOINT_INSTRUCTION) {
|
if (*addr != BREAKPOINT_INSTRUCTION) {
|
||||||
/*
|
/*
|
||||||
* The breakpoint instruction was removed right
|
* The breakpoint instruction was removed right
|
||||||
|
@ -532,34 +528,34 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
|
||||||
*/
|
*/
|
||||||
regs->ip = (unsigned long)addr;
|
regs->ip = (unsigned long)addr;
|
||||||
ret = 1;
|
ret = 1;
|
||||||
|
goto preempt_out;
|
||||||
|
}
|
||||||
|
if (kprobe_running()) {
|
||||||
|
p = __get_cpu_var(current_kprobe);
|
||||||
|
if (p->break_handler && p->break_handler(p, regs))
|
||||||
|
goto ss_probe;
|
||||||
}
|
}
|
||||||
/* Not one of ours: let kernel handle it */
|
/* Not one of ours: let kernel handle it */
|
||||||
goto no_kprobe;
|
goto preempt_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
set_current_kprobe(p, regs, kcb);
|
|
||||||
kcb->kprobe_status = KPROBE_HIT_ACTIVE;
|
|
||||||
|
|
||||||
if (p->pre_handler && p->pre_handler(p, regs))
|
|
||||||
/* handler has already set things up, so skip ss setup */
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
ss_probe:
|
ss_probe:
|
||||||
|
ret = 1;
|
||||||
#if !defined(CONFIG_PREEMPT) || defined(CONFIG_PM)
|
#if !defined(CONFIG_PREEMPT) || defined(CONFIG_PM)
|
||||||
if (p->ainsn.boostable == 1 && !p->post_handler) {
|
if (p->ainsn.boostable == 1 && !p->post_handler) {
|
||||||
/* Boost up -- we can execute copied instructions directly */
|
/* Boost up -- we can execute copied instructions directly */
|
||||||
reset_current_kprobe();
|
reset_current_kprobe();
|
||||||
regs->ip = (unsigned long)p->ainsn.insn;
|
regs->ip = (unsigned long)p->ainsn.insn;
|
||||||
preempt_enable_no_resched();
|
goto preempt_out;
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
prepare_singlestep(p, regs);
|
prepare_singlestep(p, regs);
|
||||||
kcb->kprobe_status = KPROBE_HIT_SS;
|
kcb->kprobe_status = KPROBE_HIT_SS;
|
||||||
return 1;
|
goto out;
|
||||||
|
|
||||||
no_kprobe:
|
preempt_out:
|
||||||
preempt_enable_no_resched();
|
preempt_enable_no_resched();
|
||||||
|
out:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue