summaryrefslogtreecommitdiff
path: root/arch/arm/kernel/hw_breakpoint.c
diff options
context:
space:
mode:
authorWill Deacon <will.deacon@arm.com>2010-12-01 17:05:24 +0000
committerWill Deacon <will.deacon@arm.com>2010-12-06 11:55:57 +0000
commit3ce70b2e24cd35cc9f2df8cf5205b8ab4e6178e1 (patch)
tree2f0939d5d8f2ac9d97932905f0b147b5a5e1891e /arch/arm/kernel/hw_breakpoint.c
parent9ebb3cbcc39d4e61ae6751167086acfb5c201e6f (diff)
ARM: hw_breakpoint: disallow per-cpu breakpoints without overflow handler
Single-stepping a breakpoint requires us to disable it temporarily so that we don't get stuck in a recursive debug trap. With per-cpu breakpoints this presents a problem where an interrupt can be taken before the single-step has completed and a new task is eventually scheduled. This new task will not hit the breakpoint because it will have been disabled during the previous handling code. This patch disallows per-cpu breakpoints on ARM when an overflow handler is not present. A similar effect can be created by placing breakpoints on a shell and then running applications there. Signed-off-by: Will Deacon <will.deacon@arm.com>
Diffstat (limited to 'arch/arm/kernel/hw_breakpoint.c')
-rw-r--r--arch/arm/kernel/hw_breakpoint.c6
1 files changed, 4 insertions, 2 deletions
diff --git a/arch/arm/kernel/hw_breakpoint.c b/arch/arm/kernel/hw_breakpoint.c
index 36cd7680d3d2..eef1b1e235a7 100644
--- a/arch/arm/kernel/hw_breakpoint.c
+++ b/arch/arm/kernel/hw_breakpoint.c
@@ -622,10 +622,12 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp)
* Currently we rely on an overflow handler to take
* care of single-stepping the breakpoint when it fires.
* In the case of userspace breakpoints on a core with V7 debug,
- * we can use the mismatch feature as a poor-man's hardware single-step.
+ * we can use the mismatch feature as a poor-man's hardware
+ * single-step, but this only works for per-task breakpoints.
*/
if (WARN_ONCE(!bp->overflow_handler &&
- (arch_check_bp_in_kernelspace(bp) || !core_has_mismatch_brps()),
+ (arch_check_bp_in_kernelspace(bp) || !core_has_mismatch_brps()
+ || !bp->hw.bp_target),
"overflow handler required but none found")) {
ret = -EINVAL;
}