All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH 0/9] arm64: Make the kprobes debug exception path noinstr
@ 2026-07-27 12:23 Hongyan Xia
  2026-07-27 12:25 ` [RFC PATCH 1/9] arm64/entry: Bound certain debug exception paths in instrumentation windows Hongyan Xia
                   ` (8 more replies)
  0 siblings, 9 replies; 10+ messages in thread
From: Hongyan Xia @ 2026-07-27 12:23 UTC (permalink / raw)
  To: Will Deacon, Masami Hiramatsu
  Cc: Jiazi Li, Pu Hu, linux-kernel@vger.kernel.org

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

Commit 879a6754d3d1 ("arm64: kprobes: Only handle faults originating
from XOL slot") and 23f851ac0078 ("arm64: kprobes: Allow reentering
kprobes while single-stepping") band-aided two corner cases in the arm64
kprobe path: Unrelated page faults inside Kprobe and nested Kprobe SS
handling. Although the two patches were taken, Will asked whether we
should keep patching things like this each time we find a corner case,
and whether making Kprobe noinstr is the correct answer [1].

This series attempts to do exactly that: Making the Kprobe path noinstr.
The kprobe handlers become noinstr end to end, and everything that is
inherently instrumentable is confined to instrumentation_begin/end()
windows, similar to the x86 side. After this series, the two
corner-cases mentioned above are also gone, hence the revert in 7/9 and
8/9. Some of the instrumentation_begin/end() sections are suggested by
AI, so they may need careful review.

Note that arm64 has no objtool to validate noinstr, so I wrote a small
script finding bl/blr and validated that their calls are confined within
noinstr. This is exactly what found the Clang outline compile problem
that motivated patch 9/9.

One question is whether other BRK paths get the same treatment.
Currently they stay instrumentable inside a big window.

[1] https://lore.kernel.org/all/alpuL10h7-OK2hFb@willie-the-truck/

Hongyan Xia (9):
  arm64/entry: Bound certain debug exception paths in instrumentation
    windows
  arm64/entry: Make debug_exception_enter/exit() noinstr
  arm64/debug-monitors: Make do_el1_brk64()/do_el1_softstep() noinstr
  arm64/kprobes: Make the single-step machinery noinstr
  arm64/kprobes: Invoke pre/post handlers inside instrumentation
  arm64/kprobes: Make kprobe_fault_handler() noinstr
  arm64/kprobes: Drop the KPROBE_HIT_SS reentry special case
  arm64/kprobes: Drop the XOL single-step fault PC check
  arm64/debug: Mark debug exception helpers __always_inline

 arch/arm64/include/asm/esr.h       |  2 +-
 arch/arm64/include/asm/kprobes.h   | 15 +----
 arch/arm64/include/asm/percpu.h    |  2 +-
 arch/arm64/include/asm/preempt.h   |  4 +-
 arch/arm64/include/asm/ptrace.h    |  4 +-
 arch/arm64/kernel/debug-monitors.c | 76 ++++++++++++-----------
 arch/arm64/kernel/entry-common.c   | 43 +++++++++----
 arch/arm64/kernel/probes/kprobes.c | 96 ++++++++++++++----------------
 include/linux/kprobes.h            |  8 +--
 9 files changed, 131 insertions(+), 119 deletions(-)

-- 
2.47.3


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [RFC PATCH 1/9] arm64/entry: Bound certain debug exception paths in instrumentation windows
  2026-07-27 12:23 [RFC PATCH 0/9] arm64: Make the kprobes debug exception path noinstr Hongyan Xia
@ 2026-07-27 12:25 ` Hongyan Xia
  2026-07-27 12:25 ` [RFC PATCH 2/9] arm64/entry: Make debug_exception_enter/exit() noinstr Hongyan Xia
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Hongyan Xia @ 2026-07-27 12:25 UTC (permalink / raw)
  To: Will Deacon, Masami Hiramatsu, Catalin Marinas
  Cc: Jiazi Li, Pu Hu, linux-kernel@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org

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

The el1 debug exception handlers are noinstr, but their payload calls
(do_breakpoint(), do_watchpoint(), try_step_suspended_breakpoints()
and the Cortex-A76 erratum handler) are ordinary instrumentable code.

Mark the boundaries explicitly with instrumentation_begin()/end(), in
the same style as x86 exception entries.

The BRK handlers (do_el1_brk64(), do_el1_softstep()) will be dealt with
in later patches.

Signed-off-by: Hongyan Xia <hongyan.xia@transsion.com>
---
 arch/arm64/kernel/entry-common.c | 19 +++++++++++++++++--
 1 file changed, 17 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/kernel/entry-common.c b/arch/arm64/kernel/entry-common.c
index ceb4eb11232a..466529cce1c3 100644
--- a/arch/arm64/kernel/entry-common.c
+++ b/arch/arm64/kernel/entry-common.c
@@ -6,6 +6,7 @@
  */
 
 #include <linux/context_tracking.h>
+#include <linux/instrumentation.h>
 #include <linux/irq-entry-common.h>
 #include <linux/kasan.h>
 #include <linux/linkage.h>
@@ -380,7 +381,9 @@ static void noinstr el1_breakpt(struct pt_regs *regs, unsigned long esr)
 
 	state = arm64_enter_el1_dbg(regs);
 	debug_exception_enter(regs);
+	instrumentation_begin();
 	do_breakpoint(esr, regs);
+	instrumentation_end();
 	debug_exception_exit(regs);
 	arm64_exit_el1_dbg(regs, state);
 }
@@ -388,9 +391,15 @@ static void noinstr el1_breakpt(struct pt_regs *regs, unsigned long esr)
 static void noinstr el1_softstp(struct pt_regs *regs, unsigned long esr)
 {
 	irqentry_state_t state;
+	bool handled;
 
 	state = arm64_enter_el1_dbg(regs);
-	if (!cortex_a76_erratum_1463225_debug_handler(regs)) {
+
+	instrumentation_begin();
+	handled = cortex_a76_erratum_1463225_debug_handler(regs);
+	instrumentation_end();
+
+	if (!handled) {
 		debug_exception_enter(regs);
 		/*
 		 * After handling a breakpoint, we suspend the breakpoint
@@ -398,7 +407,11 @@ static void noinstr el1_softstp(struct pt_regs *regs, unsigned long esr)
 		 * If we are stepping a suspended breakpoint there's nothing more to do:
 		 * the single-step is complete.
 		 */
-		if (!try_step_suspended_breakpoints(regs))
+		instrumentation_begin();
+		handled = try_step_suspended_breakpoints(regs);
+		instrumentation_end();
+
+		if (!handled)
 			do_el1_softstep(esr, regs);
 		debug_exception_exit(regs);
 	}
@@ -413,7 +426,9 @@ static void noinstr el1_watchpt(struct pt_regs *regs, unsigned long esr)
 
 	state = arm64_enter_el1_dbg(regs);
 	debug_exception_enter(regs);
+	instrumentation_begin();
 	do_watchpoint(far, esr, regs);
+	instrumentation_end();
 	debug_exception_exit(regs);
 	arm64_exit_el1_dbg(regs, state);
 }
-- 
2.47.3



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [RFC PATCH 2/9] arm64/entry: Make debug_exception_enter/exit() noinstr
  2026-07-27 12:23 [RFC PATCH 0/9] arm64: Make the kprobes debug exception path noinstr Hongyan Xia
  2026-07-27 12:25 ` [RFC PATCH 1/9] arm64/entry: Bound certain debug exception paths in instrumentation windows Hongyan Xia
@ 2026-07-27 12:25 ` Hongyan Xia
  2026-07-27 12:25 ` [RFC PATCH 3/9] arm64/debug-monitors: Make do_el1_brk64()/do_el1_softstep() noinstr Hongyan Xia
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Hongyan Xia @ 2026-07-27 12:25 UTC (permalink / raw)
  To: Will Deacon, Masami Hiramatsu, Catalin Marinas
  Cc: Jiazi Li, Pu Hu, linux-kernel@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org

From: Hongyan Xia <hongyan.xia@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@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



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [RFC PATCH 3/9] arm64/debug-monitors: Make do_el1_brk64()/do_el1_softstep() noinstr
  2026-07-27 12:23 [RFC PATCH 0/9] arm64: Make the kprobes debug exception path noinstr Hongyan Xia
  2026-07-27 12:25 ` [RFC PATCH 1/9] arm64/entry: Bound certain debug exception paths in instrumentation windows Hongyan Xia
  2026-07-27 12:25 ` [RFC PATCH 2/9] arm64/entry: Make debug_exception_enter/exit() noinstr Hongyan Xia
@ 2026-07-27 12:25 ` Hongyan Xia
  2026-07-27 12:25 ` [RFC PATCH 4/9] arm64/kprobes: Make the single-step machinery noinstr Hongyan Xia
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Hongyan Xia @ 2026-07-27 12:25 UTC (permalink / raw)
  To: Will Deacon, Masami Hiramatsu, Catalin Marinas
  Cc: Jiazi Li, Pu Hu, linux-kernel@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org

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

Convert do_el1_brk64(), do_el1_softstep() and call_el1_break_hook() to
noinstr. The kprobe and kretprobe BRK handlers (converted to noinstr in
the following patches) are dispatched directly. Every other BRK handler
are ordinary instrumentable code and now run bounded by
instrumentation_begin()/end().

With this, everything on the el1 debug exception path from the vectors
down to the kprobe handlers is noinstr, and instrumentation only runs
inside explicit instrumentation windows.

Signed-off-by: Hongyan Xia <hongyan.xia@transsion.com>
---
 arch/arm64/kernel/debug-monitors.c | 74 +++++++++++++++++-------------
 1 file changed, 41 insertions(+), 33 deletions(-)

diff --git a/arch/arm64/kernel/debug-monitors.c b/arch/arm64/kernel/debug-monitors.c
index 29307642f4c9..a970ab6327cd 100644
--- a/arch/arm64/kernel/debug-monitors.c
+++ b/arch/arm64/kernel/debug-monitors.c
@@ -11,6 +11,7 @@
 #include <linux/debugfs.h>
 #include <linux/hardirq.h>
 #include <linux/init.h>
+#include <linux/instrumentation.h>
 #include <linux/ptrace.h>
 #include <linux/kprobes.h>
 #include <linux/stat.h>
@@ -193,59 +194,65 @@ void do_el0_softstep(unsigned long esr, struct pt_regs *regs)
 	user_rewind_single_step(current);
 }
 
-void do_el1_softstep(unsigned long esr, struct pt_regs *regs)
+void noinstr do_el1_softstep(unsigned long esr, struct pt_regs *regs)
 {
-	if (kgdb_single_step_handler(regs, esr) == DBG_HOOK_HANDLED)
+	int handled;
+
+	instrumentation_begin();
+	handled = kgdb_single_step_handler(regs, esr);
+	instrumentation_end();
+
+	if (handled == DBG_HOOK_HANDLED)
 		return;
 
+	instrumentation_begin();
 	pr_warn("Unexpected kernel single-step exception at EL1\n");
+	instrumentation_end();
 	/*
 	 * Re-enable stepping since we know that we will be
 	 * returning to regs.
 	 */
 	set_regs_spsr_ss(regs);
 }
-NOKPROBE_SYMBOL(do_el1_softstep);
 
-static int call_el1_break_hook(struct pt_regs *regs, unsigned long esr)
+static int noinstr call_el1_break_hook(struct pt_regs *regs, unsigned long esr)
 {
-	if (esr_brk_comment(esr) == BUG_BRK_IMM)
-		return bug_brk_handler(regs, esr);
-
-	if (IS_ENABLED(CONFIG_CFI) && esr_is_cfi_brk(esr))
-		return cfi_brk_handler(regs, esr);
-
-	if (esr_brk_comment(esr) == FAULT_BRK_IMM)
-		return reserved_fault_brk_handler(regs, esr);
-
-	if (IS_ENABLED(CONFIG_KASAN_SW_TAGS) &&
-		(esr_brk_comment(esr) & ~KASAN_BRK_MASK) == KASAN_BRK_IMM)
-		return kasan_brk_handler(regs, esr);
-
-	if (IS_ENABLED(CONFIG_UBSAN_TRAP) && esr_is_ubsan_brk(esr))
-		return ubsan_brk_handler(regs, esr);
-
-	if (IS_ENABLED(CONFIG_KGDB)) {
-		if (esr_brk_comment(esr) == KGDB_DYN_DBG_BRK_IMM)
-			return kgdb_brk_handler(regs, esr);
-		if (esr_brk_comment(esr) == KGDB_COMPILED_DBG_BRK_IMM)
-			return kgdb_compiled_brk_handler(regs, esr);
-	}
+	unsigned long comment = esr_brk_comment(esr);
+	int ret = DBG_HOOK_ERROR;
 
 	if (IS_ENABLED(CONFIG_KPROBES)) {
-		if (esr_brk_comment(esr) == KPROBES_BRK_IMM)
+		if (comment == KPROBES_BRK_IMM)
 			return kprobe_brk_handler(regs, esr);
-		if (esr_brk_comment(esr) == KPROBES_BRK_SS_IMM)
+		if (comment == KPROBES_BRK_SS_IMM)
 			return kprobe_ss_brk_handler(regs, esr);
 	}
 
 	if (IS_ENABLED(CONFIG_KRETPROBES) &&
-		esr_brk_comment(esr) == KRETPROBES_BRK_IMM)
+	    comment == KRETPROBES_BRK_IMM)
 		return kretprobe_brk_handler(regs, esr);
 
-	return DBG_HOOK_ERROR;
+	instrumentation_begin();
+	if (comment == BUG_BRK_IMM)
+		ret = bug_brk_handler(regs, esr);
+	else if (IS_ENABLED(CONFIG_CFI) && esr_is_cfi_brk(esr))
+		ret = cfi_brk_handler(regs, esr);
+	else if (comment == FAULT_BRK_IMM)
+		ret = reserved_fault_brk_handler(regs, esr);
+	else if (IS_ENABLED(CONFIG_KASAN_SW_TAGS) &&
+		 (comment & ~KASAN_BRK_MASK) == KASAN_BRK_IMM)
+		ret = kasan_brk_handler(regs, esr);
+	else if (IS_ENABLED(CONFIG_UBSAN_TRAP) && esr_is_ubsan_brk(esr))
+		ret = ubsan_brk_handler(regs, esr);
+	else if (IS_ENABLED(CONFIG_KGDB)) {
+		if (comment == KGDB_DYN_DBG_BRK_IMM)
+			ret = kgdb_brk_handler(regs, esr);
+		else if (comment == KGDB_COMPILED_DBG_BRK_IMM)
+			ret = kgdb_compiled_brk_handler(regs, esr);
+	}
+	instrumentation_end();
+
+	return ret;
 }
-NOKPROBE_SYMBOL(call_el1_break_hook);
 
 /*
  * We have already unmasked interrupts and enabled preemption
@@ -261,14 +268,15 @@ void do_el0_brk64(unsigned long esr, struct pt_regs *regs)
 	send_user_sigtrap(TRAP_BRKPT);
 }
 
-void do_el1_brk64(unsigned long esr, struct pt_regs *regs)
+void noinstr do_el1_brk64(unsigned long esr, struct pt_regs *regs)
 {
 	if (call_el1_break_hook(regs, esr) == DBG_HOOK_HANDLED)
 		return;
 
+	instrumentation_begin();
 	die("Oops - BRK", regs, esr);
+	instrumentation_end();
 }
-NOKPROBE_SYMBOL(do_el1_brk64);
 
 #ifdef CONFIG_COMPAT
 void do_bkpt32(unsigned long esr, struct pt_regs *regs)
-- 
2.47.3



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [RFC PATCH 4/9] arm64/kprobes: Make the single-step machinery noinstr
  2026-07-27 12:23 [RFC PATCH 0/9] arm64: Make the kprobes debug exception path noinstr Hongyan Xia
                   ` (2 preceding siblings ...)
  2026-07-27 12:25 ` [RFC PATCH 3/9] arm64/debug-monitors: Make do_el1_brk64()/do_el1_softstep() noinstr Hongyan Xia
@ 2026-07-27 12:25 ` Hongyan Xia
  2026-07-27 12:25 ` [RFC PATCH 5/9] arm64/kprobes: Invoke pre/post handlers inside instrumentation Hongyan Xia
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Hongyan Xia @ 2026-07-27 12:25 UTC (permalink / raw)
  To: Will Deacon, Masami Hiramatsu, Catalin Marinas
  Cc: Jiazi Li, Pu Hu, linux-kernel@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org

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

Convert the core of the arm64 kprobe single-step flow to noinstr:
save_previous_kprobe(), restore_previous_kprobe(), set_current_kprobe(),
kprobes_save_local_irqflag(), kprobes_restore_local_irqflag(),
setup_singlestep(), reenter_kprobe() and post_kprobe_handler().

These functions only touch per-cpu state, pt_regs and DAIF, except for:

- kprobes_inc_nmissed_count(), which is generic and instrumentable; add
  an arm64-local wrapper that calls it bounded by
  instrumentation_begin()/end();
- the instruction simulation path in setup_singlestep(), whose decode
  handlers are instrumentable; bound arch_simulate_insn() with an
  instrumentation window;
- the unrecoverable-reentry pr_warn()/dump_kprobe()/BUG() path and the
  default WARN_ON(), both bounded with instrumentation windows.

The __kprobes attribute (notrace + .kprobes.text) is replaced by
noinstr, which is a strict superset for these functions.

Signed-off-by: Hongyan Xia <hongyan.xia@transsion.com>
---
 arch/arm64/kernel/probes/kprobes.c | 39 ++++++++++++++++++------------
 1 file changed, 24 insertions(+), 15 deletions(-)

diff --git a/arch/arm64/kernel/probes/kprobes.c b/arch/arm64/kernel/probes/kprobes.c
index 4e0efad5caf2..1b12341b2af3 100644
--- a/arch/arm64/kernel/probes/kprobes.c
+++ b/arch/arm64/kernel/probes/kprobes.c
@@ -14,6 +14,7 @@
 #include <linux/extable.h>
 #include <linux/kasan.h>
 #include <linux/kernel.h>
+#include <linux/instrumentation.h>
 #include <linux/kprobes.h>
 #include <linux/sched/debug.h>
 #include <linux/set_memory.h>
@@ -39,7 +40,7 @@
 DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL;
 DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
 
-static void __kprobes
+static void noinstr
 post_kprobe_handler(struct kprobe *, struct kprobe_ctlblk *, struct pt_regs *);
 
 void *alloc_insn_page(void)
@@ -170,7 +171,7 @@ void __kprobes arch_remove_kprobe(struct kprobe *p)
 	}
 }
 
-static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb)
+static void noinstr save_previous_kprobe(struct kprobe_ctlblk *kcb)
 {
 	kcb->prev_kprobe.kp = kprobe_running();
 	kcb->prev_kprobe.status = kcb->kprobe_status;
@@ -184,7 +185,7 @@ static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb)
 	kcb->prev_kprobe.saved_irqflag = kcb->saved_irqflag;
 }
 
-static void __kprobes restore_previous_kprobe(struct kprobe_ctlblk *kcb)
+static void noinstr restore_previous_kprobe(struct kprobe_ctlblk *kcb)
 {
 	__this_cpu_write(current_kprobe, kcb->prev_kprobe.kp);
 	kcb->kprobe_status = kcb->prev_kprobe.status;
@@ -197,7 +198,7 @@ static void __kprobes restore_previous_kprobe(struct kprobe_ctlblk *kcb)
 	kcb->saved_irqflag = kcb->prev_kprobe.saved_irqflag;
 }
 
-static void __kprobes set_current_kprobe(struct kprobe *p)
+static void noinstr set_current_kprobe(struct kprobe *p)
 {
 	__this_cpu_write(current_kprobe, p);
 }
@@ -207,23 +208,23 @@ static void __kprobes set_current_kprobe(struct kprobe *p)
  * simple and avoid nesting exceptions. Interrupts do have to be disabled since
  * the kprobe state is per-CPU and doesn't get migrated.
  */
-static void __kprobes kprobes_save_local_irqflag(struct kprobe_ctlblk *kcb,
-						struct pt_regs *regs)
+static void noinstr kprobes_save_local_irqflag(struct kprobe_ctlblk *kcb,
+					       struct pt_regs *regs)
 {
 	kcb->saved_irqflag = regs->pstate & DAIF_MASK;
 	regs->pstate |= DAIF_MASK;
 }
 
-static void __kprobes kprobes_restore_local_irqflag(struct kprobe_ctlblk *kcb,
-						struct pt_regs *regs)
+static void noinstr kprobes_restore_local_irqflag(struct kprobe_ctlblk *kcb,
+						  struct pt_regs *regs)
 {
 	regs->pstate &= ~DAIF_MASK;
 	regs->pstate |= kcb->saved_irqflag;
 }
 
-static void __kprobes setup_singlestep(struct kprobe *p,
-				       struct pt_regs *regs,
-				       struct kprobe_ctlblk *kcb, int reenter)
+static void noinstr setup_singlestep(struct kprobe *p,
+				     struct pt_regs *regs,
+				     struct kprobe_ctlblk *kcb, int reenter)
 {
 	unsigned long slot;
 
@@ -244,13 +245,15 @@ static void __kprobes setup_singlestep(struct kprobe *p,
 		instruction_pointer_set(regs, slot);
 	} else {
 		/* insn simulation */
+		instrumentation_begin();
 		arch_simulate_insn(p, regs);
+		instrumentation_end();
 	}
 }
 
-static int __kprobes reenter_kprobe(struct kprobe *p,
-				    struct pt_regs *regs,
-				    struct kprobe_ctlblk *kcb)
+static int noinstr reenter_kprobe(struct kprobe *p,
+				  struct pt_regs *regs,
+				  struct kprobe_ctlblk *kcb)
 {
 	switch (kcb->kprobe_status) {
 	case KPROBE_HIT_SSDONE:
@@ -262,23 +265,29 @@ static int __kprobes reenter_kprobe(struct kprobe *p,
 		 * recoverable one-level reentry, so handle it in the same way as
 		 * reentry from KPROBE_HIT_ACTIVE or KPROBE_HIT_SSDONE.
 		 */
+		instrumentation_begin();
 		kprobes_inc_nmissed_count(p);
+		instrumentation_end();
 		setup_singlestep(p, regs, kcb, 1);
 		break;
 	case KPROBE_REENTER:
+		instrumentation_begin();
 		pr_warn("Failed to recover from reentered kprobes.\n");
 		dump_kprobe(p);
 		BUG();
+		instrumentation_end();
 		break;
 	default:
+		instrumentation_begin();
 		WARN_ON(1);
+		instrumentation_end();
 		return 0;
 	}
 
 	return 1;
 }
 
-static void __kprobes
+static void noinstr
 post_kprobe_handler(struct kprobe *cur, struct kprobe_ctlblk *kcb, struct pt_regs *regs)
 {
 	/* return addr restore if non-branching insn */
-- 
2.47.3



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [RFC PATCH 5/9] arm64/kprobes: Invoke pre/post handlers inside instrumentation
  2026-07-27 12:23 [RFC PATCH 0/9] arm64: Make the kprobes debug exception path noinstr Hongyan Xia
                   ` (3 preceding siblings ...)
  2026-07-27 12:25 ` [RFC PATCH 4/9] arm64/kprobes: Make the single-step machinery noinstr Hongyan Xia
@ 2026-07-27 12:25 ` Hongyan Xia
  2026-07-27 12:25 ` [RFC PATCH 6/9] arm64/kprobes: Make kprobe_fault_handler() noinstr Hongyan Xia
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Hongyan Xia @ 2026-07-27 12:25 UTC (permalink / raw)
  To: Will Deacon, Masami Hiramatsu, Catalin Marinas
  Cc: Jiazi Li, Pu Hu, linux-kernel@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org

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

The kprobe pre_handler() and post_handler() are arbitrary instrumentable
code and can themselves trace, fault, or hit other kprobes. They are
the only parts of the kprobe debug exception flow that legitimately
need instrumentation.

Signed-off-by: Hongyan Xia <hongyan.xia@transsion.com>
---
 arch/arm64/include/asm/kprobes.h   |  9 +++------
 arch/arm64/kernel/probes/kprobes.c | 22 ++++++++++++++++++----
 2 files changed, 21 insertions(+), 10 deletions(-)

diff --git a/arch/arm64/include/asm/kprobes.h b/arch/arm64/include/asm/kprobes.h
index 35ce2c94040e..a694f7d34f45 100644
--- a/arch/arm64/include/asm/kprobes.h
+++ b/arch/arm64/include/asm/kprobes.h
@@ -48,11 +48,8 @@ void __kprobes *trampoline_probe_handler(struct pt_regs *regs);
 
 #endif /* CONFIG_KPROBES */
 
-int __kprobes kprobe_brk_handler(struct pt_regs *regs,
-				 unsigned long esr);
-int __kprobes kprobe_ss_brk_handler(struct pt_regs *regs,
-				 unsigned long esr);
-int __kprobes kretprobe_brk_handler(struct pt_regs *regs,
-				 unsigned long esr);
+int noinstr kprobe_brk_handler(struct pt_regs *regs, unsigned long esr);
+int noinstr kprobe_ss_brk_handler(struct pt_regs *regs, unsigned long esr);
+int noinstr kretprobe_brk_handler(struct pt_regs *regs, unsigned long esr);
 
 #endif /* _ARM_KPROBES_H */
diff --git a/arch/arm64/kernel/probes/kprobes.c b/arch/arm64/kernel/probes/kprobes.c
index 1b12341b2af3..e9fa66fa4217 100644
--- a/arch/arm64/kernel/probes/kprobes.c
+++ b/arch/arm64/kernel/probes/kprobes.c
@@ -301,8 +301,11 @@ post_kprobe_handler(struct kprobe *cur, struct kprobe_ctlblk *kcb, struct pt_reg
 	}
 	/* call post handler */
 	kcb->kprobe_status = KPROBE_HIT_SSDONE;
+
+	instrumentation_begin();
 	if (cur->post_handler)
 		cur->post_handler(cur, regs, 0);
+	instrumentation_end();
 
 	reset_current_kprobe();
 }
@@ -359,24 +362,28 @@ int __kprobes kprobe_fault_handler(struct pt_regs *regs, unsigned int fsr)
 	return 0;
 }
 
-int __kprobes
+int noinstr
 kprobe_brk_handler(struct pt_regs *regs, unsigned long esr)
 {
 	struct kprobe *p, *cur_kprobe;
 	struct kprobe_ctlblk *kcb;
 	unsigned long addr = instruction_pointer(regs);
+	bool handled;
 
 	kcb = get_kprobe_ctlblk();
 	cur_kprobe = kprobe_running();
 
+	instrumentation_begin();
 	p = get_kprobe((kprobe_opcode_t *) addr);
 	if (WARN_ON_ONCE(!p)) {
+		instrumentation_end();
 		/*
 		 * Something went wrong. This BRK used an immediate reserved
 		 * for kprobes, but we couldn't find any corresponding probe.
 		 */
 		return DBG_HOOK_ERROR;
 	}
+	instrumentation_end();
 
 	if (cur_kprobe) {
 		/* Hit a kprobe inside another kprobe */
@@ -387,6 +394,10 @@ kprobe_brk_handler(struct pt_regs *regs, unsigned long esr)
 		set_current_kprobe(p);
 		kcb->kprobe_status = KPROBE_HIT_ACTIVE;
 
+		instrumentation_begin();
+		handled = p->pre_handler && p->pre_handler(p, regs);
+		instrumentation_end();
+
 		/*
 		 * If we have no pre-handler or it returned 0, we
 		 * continue with normal processing.  If we have a
@@ -394,7 +405,7 @@ kprobe_brk_handler(struct pt_regs *regs, unsigned long esr)
 		 * modify the execution path and not need to single-step
 		 * Let's just reset current kprobe and exit.
 		 */
-		if (!p->pre_handler || !p->pre_handler(p, regs))
+		if (!handled)
 			setup_singlestep(p, regs, kcb, 0);
 		else
 			reset_current_kprobe();
@@ -403,7 +414,7 @@ kprobe_brk_handler(struct pt_regs *regs, unsigned long esr)
 	return DBG_HOOK_HANDLED;
 }
 
-int __kprobes
+int noinstr
 kprobe_ss_brk_handler(struct pt_regs *regs, unsigned long esr)
 {
 	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
@@ -422,13 +433,16 @@ kprobe_ss_brk_handler(struct pt_regs *regs, unsigned long esr)
 	return DBG_HOOK_ERROR;
 }
 
-int __kprobes
+int noinstr
 kretprobe_brk_handler(struct pt_regs *regs, unsigned long esr)
 {
 	if (regs->pc != (unsigned long)__kretprobe_trampoline)
 		return DBG_HOOK_ERROR;
 
+	instrumentation_begin();
 	regs->pc = kretprobe_trampoline_handler(regs, (void *)regs->regs[29]);
+	instrumentation_end();
+
 	return DBG_HOOK_HANDLED;
 }
 
-- 
2.47.3



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [RFC PATCH 6/9] arm64/kprobes: Make kprobe_fault_handler() noinstr
  2026-07-27 12:23 [RFC PATCH 0/9] arm64: Make the kprobes debug exception path noinstr Hongyan Xia
                   ` (4 preceding siblings ...)
  2026-07-27 12:25 ` [RFC PATCH 5/9] arm64/kprobes: Invoke pre/post handlers inside instrumentation Hongyan Xia
@ 2026-07-27 12:25 ` Hongyan Xia
  2026-07-27 12:25 ` [RFC PATCH 7/9] arm64/kprobes: Drop the KPROBE_HIT_SS reentry special case Hongyan Xia
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Hongyan Xia @ 2026-07-27 12:25 UTC (permalink / raw)
  To: Will Deacon, Masami Hiramatsu, Catalin Marinas
  Cc: Jiazi Li, Pu Hu, linux-kernel@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org

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

kprobe_fault_handler() is reached from do_page_fault() when a fault
happens while a kprobe single-step is armed. Everything it calls (the
save/restore helpers, kprobes_restore_local_irqflag(),
reset_current_kprobe(), register access) is noinstr after the previous
patch, and being called from an instrumentable caller into a noinstr
callee is fine.

Signed-off-by: Hongyan Xia <hongyan.xia@transsion.com>
---
 arch/arm64/kernel/probes/kprobes.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm64/kernel/probes/kprobes.c b/arch/arm64/kernel/probes/kprobes.c
index e9fa66fa4217..4172998d48d9 100644
--- a/arch/arm64/kernel/probes/kprobes.c
+++ b/arch/arm64/kernel/probes/kprobes.c
@@ -310,7 +310,7 @@ post_kprobe_handler(struct kprobe *cur, struct kprobe_ctlblk *kcb, struct pt_reg
 	reset_current_kprobe();
 }
 
-int __kprobes kprobe_fault_handler(struct pt_regs *regs, unsigned int fsr)
+int noinstr kprobe_fault_handler(struct pt_regs *regs, unsigned int fsr)
 {
 	struct kprobe *cur = kprobe_running();
 	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
-- 
2.47.3



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [RFC PATCH 7/9] arm64/kprobes: Drop the KPROBE_HIT_SS reentry special case
  2026-07-27 12:23 [RFC PATCH 0/9] arm64: Make the kprobes debug exception path noinstr Hongyan Xia
                   ` (5 preceding siblings ...)
  2026-07-27 12:25 ` [RFC PATCH 6/9] arm64/kprobes: Make kprobe_fault_handler() noinstr Hongyan Xia
@ 2026-07-27 12:25 ` Hongyan Xia
  2026-07-27 12:25 ` [RFC PATCH 8/9] arm64/kprobes: Drop the XOL single-step fault PC check Hongyan Xia
  2026-07-27 12:25 ` [RFC PATCH 9/9] arm64/debug: Mark debug exception helpers __always_inline Hongyan Xia
  8 siblings, 0 replies; 10+ messages in thread
From: Hongyan Xia @ 2026-07-27 12:25 UTC (permalink / raw)
  To: Will Deacon, Masami Hiramatsu, Catalin Marinas
  Cc: Jiazi Li, Pu Hu, linux-kernel@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org

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

With the debug exception path noinstr from the vectors down to the
kprobe handlers and the only instrumentable code in the flow confined to
instrumentation_begin()/end() windows, a kprobe hit while another probe
is in KPROBE_HIT_SS can no longer happen.

Signed-off-by: Hongyan Xia <hongyan.xia@transsion.com>
---
 arch/arm64/include/asm/kprobes.h   |  6 ------
 arch/arm64/kernel/probes/kprobes.c | 21 +--------------------
 2 files changed, 1 insertion(+), 26 deletions(-)

diff --git a/arch/arm64/include/asm/kprobes.h b/arch/arm64/include/asm/kprobes.h
index a694f7d34f45..bff8ba9c1689 100644
--- a/arch/arm64/include/asm/kprobes.h
+++ b/arch/arm64/include/asm/kprobes.h
@@ -26,12 +26,6 @@
 struct prev_kprobe {
 	struct kprobe *kp;
 	unsigned int status;
-
-	/*
-	 * The original DAIF state of the outer kprobe, saved here before
-	 * a nested kprobe overwrites kcb->saved_irqflag during reentry.
-	 */
-	unsigned long saved_irqflag;
 };
 
 /* per-cpu kprobe control block */
diff --git a/arch/arm64/kernel/probes/kprobes.c b/arch/arm64/kernel/probes/kprobes.c
index 4172998d48d9..1658b6acd803 100644
--- a/arch/arm64/kernel/probes/kprobes.c
+++ b/arch/arm64/kernel/probes/kprobes.c
@@ -176,13 +176,6 @@ static void noinstr save_previous_kprobe(struct kprobe_ctlblk *kcb)
 	kcb->prev_kprobe.kp = kprobe_running();
 	kcb->prev_kprobe.status = kcb->kprobe_status;
 
-	/*
-	 * Save the outer kprobe's original DAIF flags before the nested
-	 * kprobe calls kprobes_save_local_irqflag() and overwrites
-	 * kcb->saved_irqflag. Without this, the outer kprobe will restore
-	 * the wrong DAIF state and leave interrupts permanently masked.
-	 */
-	kcb->prev_kprobe.saved_irqflag = kcb->saved_irqflag;
 }
 
 static void noinstr restore_previous_kprobe(struct kprobe_ctlblk *kcb)
@@ -190,12 +183,6 @@ static void noinstr restore_previous_kprobe(struct kprobe_ctlblk *kcb)
 	__this_cpu_write(current_kprobe, kcb->prev_kprobe.kp);
 	kcb->kprobe_status = kcb->prev_kprobe.status;
 
-	/*
-	 * Restore the outer kprobe's saved_irqflag so that when its
-	 * single-step completes, kprobes_restore_local_irqflag() uses
-	 * the correct original DAIF value.
-	 */
-	kcb->saved_irqflag = kcb->prev_kprobe.saved_irqflag;
 }
 
 static void noinstr set_current_kprobe(struct kprobe *p)
@@ -258,18 +245,12 @@ static int noinstr reenter_kprobe(struct kprobe *p,
 	switch (kcb->kprobe_status) {
 	case KPROBE_HIT_SSDONE:
 	case KPROBE_HIT_ACTIVE:
-	case KPROBE_HIT_SS:
-		/*
-		 * A probe can be hit while another kprobe is preparing or
-		 * executing its XOL single-step instruction. This is still a
-		 * recoverable one-level reentry, so handle it in the same way as
-		 * reentry from KPROBE_HIT_ACTIVE or KPROBE_HIT_SSDONE.
-		 */
 		instrumentation_begin();
 		kprobes_inc_nmissed_count(p);
 		instrumentation_end();
 		setup_singlestep(p, regs, kcb, 1);
 		break;
+	case KPROBE_HIT_SS:
 	case KPROBE_REENTER:
 		instrumentation_begin();
 		pr_warn("Failed to recover from reentered kprobes.\n");
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [RFC PATCH 8/9] arm64/kprobes: Drop the XOL single-step fault PC check
  2026-07-27 12:23 [RFC PATCH 0/9] arm64: Make the kprobes debug exception path noinstr Hongyan Xia
                   ` (6 preceding siblings ...)
  2026-07-27 12:25 ` [RFC PATCH 7/9] arm64/kprobes: Drop the KPROBE_HIT_SS reentry special case Hongyan Xia
@ 2026-07-27 12:25 ` Hongyan Xia
  2026-07-27 12:25 ` [RFC PATCH 9/9] arm64/debug: Mark debug exception helpers __always_inline Hongyan Xia
  8 siblings, 0 replies; 10+ messages in thread
From: Hongyan Xia @ 2026-07-27 12:25 UTC (permalink / raw)
  To: Will Deacon, Masami Hiramatsu, Catalin Marinas
  Cc: Jiazi Li, Pu Hu, linux-kernel@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org

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

With the armed single-step window closed (the whole path noinstr, and
every piece of instrumentable code confined to instrumentation windows
that run in KPROBE_HIT_ACTIVE/HIT_SSDONE state), no code other than the
XOL instruction itself can execute while the state is KPROBE_HIT_SS or
KPROBE_REENTER. A page fault taken in those states therefore necessarily
originates from the XOL instruction, and the faulting-PC comparison is
redundant; revert to handling all such faults as single-step faults (as
before commit 879a6754d3d1).

The simulated-kprobe early bail is kept: simulated probes have no XOL
slot and execute (inside an instrumentation window) in debug trap
context, so a fault there can still come from the simulation handlers
and must not be treated as a single-step fault.

Signed-off-by: Hongyan Xia <hongyan.xia@transsion.com>
---
 arch/arm64/kernel/probes/kprobes.c | 12 ------------
 1 file changed, 12 deletions(-)

diff --git a/arch/arm64/kernel/probes/kprobes.c b/arch/arm64/kernel/probes/kprobes.c
index 1658b6acd803..73bbbcdbbfe5 100644
--- a/arch/arm64/kernel/probes/kprobes.c
+++ b/arch/arm64/kernel/probes/kprobes.c
@@ -309,18 +309,6 @@ int noinstr kprobe_fault_handler(struct pt_regs *regs, unsigned int fsr)
 	switch (kcb->kprobe_status) {
 	case KPROBE_HIT_SS:
 	case KPROBE_REENTER:
-		/*
-		 * A page fault taken while in KPROBE_HIT_SS or
-		 * KPROBE_REENTER state is only attributable to kprobe
-		 * single-stepping if the faulting PC points to the
-		 * current kprobe's XOL instruction. If the fault occurred
-		 * elsewhere (e.g. in perf or tracing code invoked from the
-		 * debug exception path), leave it for the normal page fault
-		 * handler to process.
-		 */
-		if (instruction_pointer(regs) != (unsigned long)cur->ainsn.xol_insn)
-			break;
-
 		/*
 		 * We are here because the instruction being single
 		 * stepped caused a page fault. We reset the current
-- 
2.47.3



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [RFC PATCH 9/9] arm64/debug: Mark debug exception helpers __always_inline
  2026-07-27 12:23 [RFC PATCH 0/9] arm64: Make the kprobes debug exception path noinstr Hongyan Xia
                   ` (7 preceding siblings ...)
  2026-07-27 12:25 ` [RFC PATCH 8/9] arm64/kprobes: Drop the XOL single-step fault PC check Hongyan Xia
@ 2026-07-27 12:25 ` Hongyan Xia
  8 siblings, 0 replies; 10+ messages in thread
From: Hongyan Xia @ 2026-07-27 12:25 UTC (permalink / raw)
  To: Will Deacon, Masami Hiramatsu, Catalin Marinas, Dennis Zhou,
	Tejun Heo, Christoph Lameter, Oleg Nesterov, Naveen N Rao,
	David S. Miller, Nathan Chancellor, Nick Desaulniers,
	Bill Wendling, Justin Stitt
  Cc: Jiazi Li, Pu Hu, linux-kernel@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org, linux-mm@kvack.org,
	linux-trace-kernel@vger.kernel.org, llvm@lists.linux.dev

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

Static inline should be enough to actually inline functions for most
compilers, but my Clang-19 somehow thinks it's better to outline them.
These tiny helpers then live in normal .text sections instead of
.noinstr sections, violating noinstr.

Mark them __always_inline so the compiler can never outline them.

Signed-off-by: Hongyan Xia <hongyan.xia@transsion.com>
---
 arch/arm64/include/asm/esr.h       | 2 +-
 arch/arm64/include/asm/percpu.h    | 2 +-
 arch/arm64/include/asm/preempt.h   | 4 ++--
 arch/arm64/include/asm/ptrace.h    | 4 ++--
 arch/arm64/kernel/debug-monitors.c | 2 +-
 include/linux/kprobes.h            | 8 ++++----
 6 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/arch/arm64/include/asm/esr.h b/arch/arm64/include/asm/esr.h
index f816f5d77f1a..a75bfdb7e5fe 100644
--- a/arch/arm64/include/asm/esr.h
+++ b/arch/arm64/include/asm/esr.h
@@ -437,7 +437,7 @@
 #ifndef __ASSEMBLER__
 #include <asm/types.h>
 
-static inline unsigned long esr_brk_comment(unsigned long esr)
+static __always_inline unsigned long esr_brk_comment(unsigned long esr)
 {
 	return esr & ESR_ELx_BRK64_ISS_COMMENT_MASK;
 }
diff --git a/arch/arm64/include/asm/percpu.h b/arch/arm64/include/asm/percpu.h
index b57b2bb00967..d4cae47fde8c 100644
--- a/arch/arm64/include/asm/percpu.h
+++ b/arch/arm64/include/asm/percpu.h
@@ -29,7 +29,7 @@ static inline unsigned long __hyp_my_cpu_offset(void)
 	return read_sysreg(tpidr_el2);
 }
 
-static inline unsigned long __kern_my_cpu_offset(void)
+static __always_inline unsigned long __kern_my_cpu_offset(void)
 {
 	unsigned long off;
 
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/include/asm/ptrace.h b/arch/arm64/include/asm/ptrace.h
index 39582511ad72..460726224299 100644
--- a/arch/arm64/include/asm/ptrace.h
+++ b/arch/arm64/include/asm/ptrace.h
@@ -336,11 +336,11 @@ static inline unsigned long regs_get_kernel_argument(struct pt_regs *regs,
 struct task_struct;
 int valid_user_regs(struct user_pt_regs *regs, struct task_struct *task);
 
-static inline unsigned long instruction_pointer(struct pt_regs *regs)
+static __always_inline unsigned long instruction_pointer(struct pt_regs *regs)
 {
 	return regs->pc;
 }
-static inline void instruction_pointer_set(struct pt_regs *regs,
+static __always_inline void instruction_pointer_set(struct pt_regs *regs,
 		unsigned long val)
 {
 	regs->pc = val;
diff --git a/arch/arm64/kernel/debug-monitors.c b/arch/arm64/kernel/debug-monitors.c
index a970ab6327cd..66cb8151f5df 100644
--- a/arch/arm64/kernel/debug-monitors.c
+++ b/arch/arm64/kernel/debug-monitors.c
@@ -146,7 +146,7 @@ postcore_initcall(debug_monitors_init);
 /*
  * Single step API and exception handling.
  */
-static void set_user_regs_spsr_ss(struct user_pt_regs *regs)
+static __always_inline void set_user_regs_spsr_ss(struct user_pt_regs *regs)
 {
 	regs->pstate |= DBG_SPSR_SS;
 }
diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h
index 8c4f3bb24429..5880445ed0f0 100644
--- a/include/linux/kprobes.h
+++ b/include/linux/kprobes.h
@@ -384,17 +384,17 @@ static inline void kprobe_ftrace_kill(void) {}
 struct kprobe *get_kprobe(void *addr);
 
 /* kprobe_running() will just return the current_kprobe on this CPU */
-static inline struct kprobe *kprobe_running(void)
+static __always_inline struct kprobe *kprobe_running(void)
 {
 	return __this_cpu_read(current_kprobe);
 }
 
-static inline void reset_current_kprobe(void)
+static __always_inline void reset_current_kprobe(void)
 {
 	__this_cpu_write(current_kprobe, NULL);
 }
 
-static inline struct kprobe_ctlblk *get_kprobe_ctlblk(void)
+static __always_inline struct kprobe_ctlblk *get_kprobe_ctlblk(void)
 {
 	return this_cpu_ptr(&kprobe_ctlblk);
 }
@@ -449,7 +449,7 @@ static inline struct kprobe *get_kprobe(void *addr)
 {
 	return NULL;
 }
-static inline struct kprobe *kprobe_running(void)
+static __always_inline struct kprobe *kprobe_running(void)
 {
 	return NULL;
 }
-- 
2.47.3



^ permalink raw reply related	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2026-07-27 12:26 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-27 12:23 [RFC PATCH 0/9] arm64: Make the kprobes debug exception path noinstr Hongyan Xia
2026-07-27 12:25 ` [RFC PATCH 1/9] arm64/entry: Bound certain debug exception paths in instrumentation windows Hongyan Xia
2026-07-27 12:25 ` [RFC PATCH 2/9] arm64/entry: Make debug_exception_enter/exit() noinstr Hongyan Xia
2026-07-27 12:25 ` [RFC PATCH 3/9] arm64/debug-monitors: Make do_el1_brk64()/do_el1_softstep() noinstr Hongyan Xia
2026-07-27 12:25 ` [RFC PATCH 4/9] arm64/kprobes: Make the single-step machinery noinstr Hongyan Xia
2026-07-27 12:25 ` [RFC PATCH 5/9] arm64/kprobes: Invoke pre/post handlers inside instrumentation Hongyan Xia
2026-07-27 12:25 ` [RFC PATCH 6/9] arm64/kprobes: Make kprobe_fault_handler() noinstr Hongyan Xia
2026-07-27 12:25 ` [RFC PATCH 7/9] arm64/kprobes: Drop the KPROBE_HIT_SS reentry special case Hongyan Xia
2026-07-27 12:25 ` [RFC PATCH 8/9] arm64/kprobes: Drop the XOL single-step fault PC check Hongyan Xia
2026-07-27 12:25 ` [RFC PATCH 9/9] arm64/debug: Mark debug exception helpers __always_inline Hongyan Xia

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.