[RFC PATCH v2 1/4] arm64/entry: Make debug_exception_enter/exit() noinstr
Hongyan Xia <[email protected]>
| Newsgroups | org.infradead.lists.linux-arm-kernel,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <c3a90368dd6c096af9d918e036a27728696fb8a4.1786603168.git.hongyan.xia@transsion.com> |
From: Hongyan Xia <[email protected]> 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 force-inline these functions and use the notrace variant of preempt handling to avoid all the complexity. 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. Also mark __preempt_count_add/sub() __always_inline so the preempt count updates fold into the noinstr callers instead of becoming outlined calls to instrumentable text. Signed-off-by: Hongyan Xia <[email protected]> --- arch/arm64/include/asm/preempt.h | 4 ++-- arch/arm64/kernel/entry-common.c | 13 ++++--------- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/arch/arm64/include/asm/preempt.h b/arch/arm64/include/asm/preempt.h index 932ea4b62042..326f221c3f56 100644 --- a/arch/arm64/include/asm/preempt.h +++ b/arch/arm64/include/asm/preempt.h @@ -41,14 +41,14 @@ static inline bool test_preempt_need_resched(void) return !current_thread_info()->preempt.need_resched; } -static inline void __preempt_count_add(int val) +static __always_inline void __preempt_count_add(int val) { u32 pc = READ_ONCE(current_thread_info()->preempt.count); pc += val; WRITE_ONCE(current_thread_info()->preempt.count, pc); } -static inline void __preempt_count_sub(int val) +static __always_inline void __preempt_count_sub(int val) { u32 pc = READ_ONCE(current_thread_info()->preempt.count); pc -= val; diff --git a/arch/arm64/kernel/entry-common.c b/arch/arm64/kernel/entry-common.c index ceb4eb11232a..d5c1d6defe29 100644 --- a/arch/arm64/kernel/entry-common.c +++ b/arch/arm64/kernel/entry-common.c @@ -292,20 +292,15 @@ 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 __always_inline void 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"); + preempt_disable_notrace(); } -NOKPROBE_SYMBOL(debug_exception_enter); -static void debug_exception_exit(struct pt_regs *regs) +static __always_inline void debug_exception_exit(struct pt_regs *regs) { - preempt_enable_no_resched(); + preempt_enable_no_resched_notrace(); } -NOKPROBE_SYMBOL(debug_exception_exit); UNHANDLED(el1t, 64, sync) UNHANDLED(el1t, 64, irq) -- 2.47.3