[RFC PATCH 2/9] arm64/entry: Make debug_exception_enter/exit() noinstr

Hongyan Xia hongyan.xia at transsion.com
Mon Jul 27 05:25:36 PDT 2026


From: Hongyan Xia <hongyan.xia at transsion.com>

Commit 879a6754d3d11e30af24b7dc486f561510d62641 ran into a crash because
debug_exception_enter/exit() triggered page faults caused by perf dwarf
call graph tracing. That patch was a band-aid on top. Instead of trying
to band-aid all possible paths that can happen during instrumentation or
perf tracing, simply make both functions noinstr.

Drop the RCU_LOCKDEP_WARN(): arm64_enter_el1_dbg() runs first and
enters NMI context via ct_nmi_enter(), so RCU is always watching by the
time debug_exception_enter() runs.

Signed-off-by: Hongyan Xia <hongyan.xia at transsion.com>
---
 arch/arm64/kernel/entry-common.c | 24 +++++++++++++++---------
 1 file changed, 15 insertions(+), 9 deletions(-)

diff --git a/arch/arm64/kernel/entry-common.c b/arch/arm64/kernel/entry-common.c
index 466529cce1c3..f06b5e2437cd 100644
--- a/arch/arm64/kernel/entry-common.c
+++ b/arch/arm64/kernel/entry-common.c
@@ -293,20 +293,26 @@ static __always_inline void fpsimd_syscall_exit(void)
  * accidentally schedule in exception context and it will force a warning
  * if we somehow manage to schedule by accident.
  */
-static void debug_exception_enter(struct pt_regs *regs)
+static void noinstr debug_exception_enter(struct pt_regs *regs)
 {
-	preempt_disable();
-
-	/* This code is a bit fragile.  Test it. */
-	RCU_LOCKDEP_WARN(!rcu_is_watching(), "exception_enter didn't work");
+	/*
+	 * debug_exception_enter/exit() can be quite delicate. The normal
+	 * preempt_disable/enable() can be instrumented or traced by perf,
+	 * which leads to a can of worms including triggering page faults.
+	 *
+	 * Instead of trying to make all of them work properly here, just
+	 * open-code the simpler version of preempt_disable/enable() and make
+	 * enter/exit() both noinstr to avoid the entire complexity.
+	 */
+	__preempt_count_inc();
+	barrier();
 }
-NOKPROBE_SYMBOL(debug_exception_enter);
 
-static void debug_exception_exit(struct pt_regs *regs)
+static void noinstr debug_exception_exit(struct pt_regs *regs)
 {
-	preempt_enable_no_resched();
+	barrier();
+	__preempt_count_dec();
 }
-NOKPROBE_SYMBOL(debug_exception_exit);
 
 UNHANDLED(el1t, 64, sync)
 UNHANDLED(el1t, 64, irq)
-- 
2.47.3




More information about the linux-arm-kernel mailing list