mirror of https://gitee.com/openkylin/linux.git
kprobes/x86: Do not disable preempt on int3 path
Since int3 and debug exception(for singlestep) are run with IRQ disabled and while running single stepping we drop IF from regs->flags, that path must not be preemptible. So we can remove the preempt disable/enable calls from that path. Suggested-by: Ingo Molnar <mingo@kernel.org> Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org> Acked-by: Thomas Gleixner <tglx@linutronix.de> Cc: Ananth N Mavinakayanahalli <ananth@linux.vnet.ibm.com> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Steven Rostedt <rostedt@goodmis.org> Cc: linux-arch@vger.kernel.org Cc: linux-doc@vger.kernel.org Link: https://lore.kernel.org/lkml/152942497779.15209.2879580696589868291.stgit@devbox Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
parent
cce188bd58
commit
2bbda764d7
|
@ -566,12 +566,11 @@ the same handler) may run concurrently on different CPUs.
|
||||||
Kprobes does not use mutexes or allocate memory except during
|
Kprobes does not use mutexes or allocate memory except during
|
||||||
registration and unregistration.
|
registration and unregistration.
|
||||||
|
|
||||||
Probe handlers are run with preemption disabled. Depending on the
|
Probe handlers are run with preemption disabled or interrupt disabled,
|
||||||
architecture and optimization state, handlers may also run with
|
which depends on the architecture and optimization state. (e.g.,
|
||||||
interrupts disabled (e.g., kretprobe handlers and optimized kprobe
|
kretprobe handlers and optimized kprobe handlers run without interrupt
|
||||||
handlers run without interrupt disabled on x86/x86-64). In any case,
|
disabled on x86/x86-64). In any case, your handler should not yield
|
||||||
your handler should not yield the CPU (e.g., by attempting to acquire
|
the CPU (e.g., by attempting to acquire a semaphore, or waiting I/O).
|
||||||
a semaphore).
|
|
||||||
|
|
||||||
Since a return probe is implemented by replacing the return
|
Since a return probe is implemented by replacing the return
|
||||||
address with the trampoline's address, stack backtraces and calls
|
address with the trampoline's address, stack backtraces and calls
|
||||||
|
|
|
@ -594,7 +594,6 @@ static void setup_singlestep(struct kprobe *p, struct pt_regs *regs,
|
||||||
* stepping.
|
* stepping.
|
||||||
*/
|
*/
|
||||||
regs->ip = (unsigned long)p->ainsn.insn;
|
regs->ip = (unsigned long)p->ainsn.insn;
|
||||||
preempt_enable_no_resched();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -667,12 +666,10 @@ int kprobe_int3_handler(struct pt_regs *regs)
|
||||||
|
|
||||||
addr = (kprobe_opcode_t *)(regs->ip - sizeof(kprobe_opcode_t));
|
addr = (kprobe_opcode_t *)(regs->ip - sizeof(kprobe_opcode_t));
|
||||||
/*
|
/*
|
||||||
* We don't want to be preempted for the entire
|
* We don't want to be preempted for the entire duration of kprobe
|
||||||
* duration of kprobe processing. We conditionally
|
* processing. Since int3 and debug trap disables irqs and we clear
|
||||||
* re-enable preemption at the end of this function,
|
* IF while singlestepping, it must be no preemptible.
|
||||||
* and also in reenter_kprobe() and setup_singlestep().
|
|
||||||
*/
|
*/
|
||||||
preempt_disable();
|
|
||||||
|
|
||||||
kcb = get_kprobe_ctlblk();
|
kcb = get_kprobe_ctlblk();
|
||||||
p = get_kprobe(addr);
|
p = get_kprobe(addr);
|
||||||
|
@ -694,10 +691,8 @@ int kprobe_int3_handler(struct pt_regs *regs)
|
||||||
*/
|
*/
|
||||||
if (!p->pre_handler || !p->pre_handler(p, regs))
|
if (!p->pre_handler || !p->pre_handler(p, regs))
|
||||||
setup_singlestep(p, regs, kcb, 0);
|
setup_singlestep(p, regs, kcb, 0);
|
||||||
else {
|
else
|
||||||
reset_current_kprobe();
|
reset_current_kprobe();
|
||||||
preempt_enable_no_resched();
|
|
||||||
}
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
} else if (*addr != BREAKPOINT_INSTRUCTION) {
|
} else if (*addr != BREAKPOINT_INSTRUCTION) {
|
||||||
|
@ -711,11 +706,9 @@ int kprobe_int3_handler(struct pt_regs *regs)
|
||||||
* the original instruction.
|
* the original instruction.
|
||||||
*/
|
*/
|
||||||
regs->ip = (unsigned long)addr;
|
regs->ip = (unsigned long)addr;
|
||||||
preempt_enable_no_resched();
|
|
||||||
return 1;
|
return 1;
|
||||||
} /* else: not a kprobe fault; let the kernel handle it */
|
} /* else: not a kprobe fault; let the kernel handle it */
|
||||||
|
|
||||||
preempt_enable_no_resched();
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
NOKPROBE_SYMBOL(kprobe_int3_handler);
|
NOKPROBE_SYMBOL(kprobe_int3_handler);
|
||||||
|
@ -966,8 +959,6 @@ int kprobe_debug_handler(struct pt_regs *regs)
|
||||||
}
|
}
|
||||||
reset_current_kprobe();
|
reset_current_kprobe();
|
||||||
out:
|
out:
|
||||||
preempt_enable_no_resched();
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* if somebody else is singlestepping across a probe point, flags
|
* if somebody else is singlestepping across a probe point, flags
|
||||||
* will have TF set, in which case, continue the remaining processing
|
* will have TF set, in which case, continue the remaining processing
|
||||||
|
@ -1014,7 +1005,6 @@ int kprobe_fault_handler(struct pt_regs *regs, int trapnr)
|
||||||
restore_previous_kprobe(kcb);
|
restore_previous_kprobe(kcb);
|
||||||
else
|
else
|
||||||
reset_current_kprobe();
|
reset_current_kprobe();
|
||||||
preempt_enable_no_resched();
|
|
||||||
} else if (kcb->kprobe_status == KPROBE_HIT_ACTIVE ||
|
} else if (kcb->kprobe_status == KPROBE_HIT_ACTIVE ||
|
||||||
kcb->kprobe_status == KPROBE_HIT_SSDONE) {
|
kcb->kprobe_status == KPROBE_HIT_SSDONE) {
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -491,7 +491,6 @@ int setup_detour_execution(struct kprobe *p, struct pt_regs *regs, int reenter)
|
||||||
regs->ip = (unsigned long)op->optinsn.insn + TMPL_END_IDX;
|
regs->ip = (unsigned long)op->optinsn.insn + TMPL_END_IDX;
|
||||||
if (!reenter)
|
if (!reenter)
|
||||||
reset_current_kprobe();
|
reset_current_kprobe();
|
||||||
preempt_enable_no_resched();
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
Loading…
Reference in New Issue