Re: [RFC PATCH v2 1/4] arm64/entry: Make debug_exception_enter/exit() noinstr
Masami Hiramatsu (Google) <[email protected]>
| Newsgroups | org.infradead.lists.linux-arm-kernel,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
On Thu, 13 Aug 2026 06:49:27 +0000 Hongyan Xia <[email protected]> wrote: > 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. Looks good to me as a kprobe maintainer. Reviewed-by: Masami Hiramatsu (Google) <[email protected]> Thanks, > > 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 > -- Masami Hiramatsu (Google) <[email protected]>