[PATCH 2/3] kernel: debug-monitors: Disable preemption

James Morse james.morse at arm.com
Thu Aug 3 08:15:32 PDT 2017


The helpers kernel_{en,dis}able_single_step check that interrupts
are disabled when they are called as they are setting the per-cpu
MDSCR_EL1 register.

But we don't expect single step to have an effect until we ERET with
SPSR.SS set. We may ERET to a context that has interrupts unmasked,
take an interrupt and switch CPU. This leaves MDSCR_EL1.SS set on
one CPU, and SPSR.SS set on another.

Stop this by wrapping the MDSCR_EL1 writes in preempt_{en,dis}able().

Signed-off-by: James Morse <james.morse at arm.com>
CC: Pratyush Anand <panand at redhat.com>
CC: AKASHI Takahiro <takahiro.akashi at linaro.org>

---
 arch/arm64/kernel/debug-monitors.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/kernel/debug-monitors.c b/arch/arm64/kernel/debug-monitors.c
index c7ef99904934..6ba315dc2935 100644
--- a/arch/arm64/kernel/debug-monitors.c
+++ b/arch/arm64/kernel/debug-monitors.c
@@ -22,6 +22,7 @@
 #include <linux/debugfs.h>
 #include <linux/hardirq.h>
 #include <linux/init.h>
+#include <linux/preempt.h>
 #include <linux/ptrace.h>
 #include <linux/kprobes.h>
 #include <linux/stat.h>
@@ -399,7 +400,7 @@ void user_fastforward_single_step(struct task_struct *task)
 /* Kernel API */
 void kernel_enable_single_step(struct pt_regs *regs)
 {
-	WARN_ON(!irqs_disabled());
+	preempt_disable();
 	set_regs_spsr_ss(regs);
 	mdscr_write(mdscr_read() | DBG_MDSCR_SS);
 	enable_debug_monitors(DBG_ACTIVE_EL1);
@@ -408,9 +409,9 @@ NOKPROBE_SYMBOL(kernel_enable_single_step);
 
 void kernel_disable_single_step(void)
 {
-	WARN_ON(!irqs_disabled());
 	mdscr_write(mdscr_read() & ~DBG_MDSCR_SS);
 	disable_debug_monitors(DBG_ACTIVE_EL1);
+	preempt_enable();
 }
 NOKPROBE_SYMBOL(kernel_disable_single_step);
 
-- 
2.13.3




More information about the linux-arm-kernel mailing list