Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: Will Deacon <will@kernel.org>
To: Ada Couprie Diaz <ada.coupriediaz@arm.com>
Cc: linux-arm-kernel@lists.infradead.org,
	Catalin Marinas <catalin.marinas@arm.com>,
	Mark Rutland <mark.rutland@arm.com>,
	"Luis Claudio R. Goncalves" <lgoncalv@redhat.com>,
	Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Subject: Re: [PATCH v2 02/11] arm64: debug: call software break handlers statically
Date: Tue, 20 May 2025 16:35:46 +0100	[thread overview]
Message-ID: <20250520153545.GB18901@willie-the-truck> (raw)
In-Reply-To: <20250512174326.133905-3-ada.coupriediaz@arm.com>

On Mon, May 12, 2025 at 06:43:17PM +0100, Ada Couprie Diaz wrote:
> Software breakpoints pass an immediate value in ESR ("comment") that can
> be used to call a specialized handler (KGDB, KASAN...).
> We do so in two different ways :
>  - During early boot, `early_brk64` statically checks against known
>    immediates and calls the corresponding handler,
>  - During init, handlers are dynamically registered into a list. When
>    called, the generic software breakpoint handler will iterate over
>    the list to find the appropriate handler.
> 
> The dynamic registration does not provide any benefit here as it is not
> exported and all its uses are within the arm64 tree. It also depends on an
> RCU list, whose safe access currently relies on the non-preemptible state
> of `do_debug_exception`.
> 
> Replace the list iteration logic in `call_break_hooks` to call
> the breakpoint handlers statically if they are enabled, like in
> `early_brk64`.
> Expose the handlers in their respective headers to be reachable from
> `arch/arm64/kernel/debug-monitors.c` at link time.
> 
> Unify the naming of the software breakpoint handlers to XXX_brk_handler(),
> making it clear they are related and to differentiate from the
> hardware breakpoints.
> 
> Signed-off-by: Ada Couprie Diaz <ada.coupriediaz@arm.com>
> ---
>  arch/arm64/include/asm/kgdb.h                 |  3 +
>  arch/arm64/include/asm/kprobes.h              |  6 ++
>  arch/arm64/include/asm/traps.h                |  6 ++
>  arch/arm64/include/asm/uprobes.h              |  2 +
>  arch/arm64/kernel/debug-monitors.c            | 57 ++++++++++++++----
>  arch/arm64/kernel/kgdb.c                      | 22 ++-----
>  arch/arm64/kernel/probes/kprobes.c            | 31 ++--------
>  arch/arm64/kernel/probes/kprobes_trampoline.S |  2 +-
>  arch/arm64/kernel/probes/uprobes.c            |  9 +--
>  arch/arm64/kernel/traps.c                     | 59 ++++---------------
>  10 files changed, 84 insertions(+), 113 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/kgdb.h b/arch/arm64/include/asm/kgdb.h
> index 21fc85e9d2be..82a76b2102fb 100644
> --- a/arch/arm64/include/asm/kgdb.h
> +++ b/arch/arm64/include/asm/kgdb.h
> @@ -24,6 +24,9 @@ static inline void arch_kgdb_breakpoint(void)
>  extern void kgdb_handle_bus_error(void);
>  extern int kgdb_fault_expected;
>  
> +int kgdb_brk_handler(struct pt_regs *regs, unsigned long esr);
> +int kgdb_compiled_brk_handler(struct pt_regs *regs, unsigned long esr);
> +
>  #endif /* !__ASSEMBLY__ */
>  
>  /*
> diff --git a/arch/arm64/include/asm/kprobes.h b/arch/arm64/include/asm/kprobes.h
> index be7a3680dadf..b27dd6028e6a 100644
> --- a/arch/arm64/include/asm/kprobes.h
> +++ b/arch/arm64/include/asm/kprobes.h
> @@ -38,6 +38,12 @@ struct kprobe_ctlblk {
>  void arch_remove_kprobe(struct kprobe *);
>  int kprobe_fault_handler(struct pt_regs *regs, unsigned int fsr);
>  void __kretprobe_trampoline(void);
> +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);
>  void __kprobes *trampoline_probe_handler(struct pt_regs *regs);
>  
>  #endif /* CONFIG_KPROBES */

If you add these _after_ the #endif...

> diff --git a/arch/arm64/kernel/debug-monitors.c b/arch/arm64/kernel/debug-monitors.c
> index 676fa0231935..4ece4a93b872 100644
> --- a/arch/arm64/kernel/debug-monitors.c
> +++ b/arch/arm64/kernel/debug-monitors.c
> @@ -21,8 +21,11 @@
>  #include <asm/cputype.h>
>  #include <asm/daifflags.h>
>  #include <asm/debug-monitors.h>
> +#include <asm/kgdb.h>
> +#include <asm/kprobes.h>
>  #include <asm/system_misc.h>
>  #include <asm/traps.h>
> +#include <asm/uprobes.h>
>  
>  /* Determine debug architecture. */
>  u8 debug_monitors_arch(void)
> @@ -299,20 +302,50 @@ void unregister_kernel_break_hook(struct break_hook *hook)
>  
>  static int call_break_hook(struct pt_regs *regs, unsigned long esr)
>  {
> -	struct break_hook *hook;
> -	struct list_head *list;
> -
> -	list = user_mode(regs) ? &user_break_hook : &kernel_break_hook;
> -
> -	/*
> -	 * Since brk exception disables interrupt, this function is
> -	 * entirely not preemptible, and we can use rcu list safely here.
> -	 */
> -	list_for_each_entry_rcu(hook, list, node) {
> -		if ((esr_brk_comment(esr) & ~hook->mask) == hook->imm)
> -			return hook->fn(regs, esr);
> +	if (user_mode(regs)) {
> +#ifdef CONFIG_UPROBES
> +		if (esr_brk_comment(esr) == UPROBES_BRK_IMM)
> +			return uprobe_brk_handler(regs, esr);
> +#endif
> +		return DBG_HOOK_ERROR;
>  	}
>  
> +	if (esr_brk_comment(esr) == BUG_BRK_IMM)
> +		return bug_brk_handler(regs, esr);
> +
> +#ifdef CONFIG_CFI_CLANG
> +	if (esr_is_cfi_brk(esr))
> +		return cfi_brk_handler(regs, esr);
> +#endif
> +
> +	if (esr_brk_comment(esr) == FAULT_BRK_IMM)
> +		return reserved_fault_brk_handler(regs, esr);
> +
> +#ifdef CONFIG_KASAN_SW_TAGS
> +	if ((esr_brk_comment(esr) & ~KASAN_BRK_MASK) == KASAN_BRK_IMM)
> +		return kasan_brk_handler(regs, esr);
> +#endif
> +#ifdef CONFIG_UBSAN_TRAP
> +	if ((esr_brk_comment(esr) & ~UBSAN_BRK_MASK) == UBSAN_BRK_IMM)
> +		return ubsan_brk_handler(regs, esr);
> +#endif
> +#ifdef 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);
> +#endif
> +#ifdef CONFIG_KPROBES
> +	if (esr_brk_comment(esr) == KPROBES_BRK_IMM)
> +		return kprobe_brk_handler(regs, esr);
> +	if (esr_brk_comment(esr) == KPROBES_BRK_SS_IMM)
> +		return kprobe_ss_brk_handler(regs, esr);
> +#endif
> +#ifdef CONFIG_KRETPROBES
> +	if (esr_brk_comment(esr) == KRETPROBES_BRK_IMM)
> +		return kretprobe_brk_handler(regs, esr);
> +#endif

... then I think you can use IS_ENABLED() here instead of the #ifdefs.
I didn't check everything, but the diff I was hacking on is below.

Will

--->8

diff --git a/arch/arm64/include/asm/kprobes.h b/arch/arm64/include/asm/kprobes.h
index b27dd6028e6a..0d41fbbffb06 100644
--- a/arch/arm64/include/asm/kprobes.h
+++ b/arch/arm64/include/asm/kprobes.h
@@ -38,13 +38,14 @@ struct kprobe_ctlblk {
 void arch_remove_kprobe(struct kprobe *);
 int kprobe_fault_handler(struct pt_regs *regs, unsigned int fsr);
 void __kretprobe_trampoline(void);
+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);
-void __kprobes *trampoline_probe_handler(struct pt_regs *regs);
 
-#endif /* CONFIG_KPROBES */
 #endif /* _ARM_KPROBES_H */
diff --git a/arch/arm64/kernel/debug-monitors.c b/arch/arm64/kernel/debug-monitors.c
index a5f344e556df..5b199ac70476 100644
--- a/arch/arm64/kernel/debug-monitors.c
+++ b/arch/arm64/kernel/debug-monitors.c
@@ -227,48 +227,50 @@ NOKPROBE_SYMBOL(do_softstep);
 static int call_break_hook(struct pt_regs *regs, unsigned long esr)
 {
 	if (user_mode(regs)) {
-#ifdef CONFIG_UPROBES
-		if (esr_brk_comment(esr) == UPROBES_BRK_IMM)
+		if (IS_ENABLED(CONFIG_UPROBES) &&
+		    esr_brk_comment(esr) == UPROBES_BRK_IMM) {
 			return uprobe_brk_handler(regs, esr);
-#endif
+		}
+
 		return DBG_HOOK_ERROR;
 	}
 
 	if (esr_brk_comment(esr) == BUG_BRK_IMM)
 		return bug_brk_handler(regs, esr);
 
-#ifdef CONFIG_CFI_CLANG
-	if (esr_is_cfi_brk(esr))
+	if (IS_ENABLED(CONFIG_CFI_CLANG) && esr_is_cfi_brk(esr))
 		return cfi_brk_handler(regs, esr);
-#endif
 
 	if (esr_brk_comment(esr) == FAULT_BRK_IMM)
 		return reserved_fault_brk_handler(regs, esr);
 
-#ifdef CONFIG_KASAN_SW_TAGS
-	if ((esr_brk_comment(esr) & ~KASAN_BRK_MASK) == KASAN_BRK_IMM)
+	if (IS_ENABLED(CONFIG_KASAN_SW_TAGS) &&
+	    (esr_brk_comment(esr) & ~KASAN_BRK_MASK) == KASAN_BRK_IMM) {
 		return kasan_brk_handler(regs, esr);
-#endif
-#ifdef CONFIG_UBSAN_TRAP
-	if ((esr_brk_comment(esr) & ~UBSAN_BRK_MASK) == UBSAN_BRK_IMM)
+	}
+
+	if (IS_ENABLED(CONFIG_UBSAN_TRAP) &&
+	    (esr_brk_comment(esr) & ~UBSAN_BRK_MASK) == UBSAN_BRK_IMM) {
 		return ubsan_brk_handler(regs, esr);
-#endif
-#ifdef 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);
-#endif
-#ifdef CONFIG_KPROBES
-	if (esr_brk_comment(esr) == KPROBES_BRK_IMM)
-		return kprobe_brk_handler(regs, esr);
-	if (esr_brk_comment(esr) == KPROBES_BRK_SS_IMM)
-		return kprobe_ss_brk_handler(regs, esr);
-#endif
-#ifdef CONFIG_KRETPROBES
-	if (esr_brk_comment(esr) == KRETPROBES_BRK_IMM)
+	}
+
+	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);
+	}
+
+	if (IS_ENABLED(CONFIG_KPROBES)) {
+		if (esr_brk_comment(esr) == KPROBES_BRK_IMM)
+			return kprobe_brk_handler(regs, esr);
+		if (esr_brk_comment(esr) == KPROBES_BRK_SS_IMM)
+			return kprobe_ss_brk_handler(regs, esr);
+	}
+
+	if (IS_ENABLED(CONFIG_KRETPROBES) &&
+	    esr_brk_comment(esr) == KRETPROBES_BRK_IMM)
 		return kretprobe_brk_handler(regs, esr);
-#endif
 
 	return DBG_HOOK_ERROR;
 }


  reply	other threads:[~2025-05-20 16:08 UTC|newest]

Thread overview: 42+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-05-12 17:43 [PATCH v2 00/11] arm64: debug: remove hook registration, split exception entry Ada Couprie Diaz
2025-05-12 17:43 ` [PATCH v2 01/11] arm64: debug: clean up single_step_handler logic Ada Couprie Diaz
2025-05-20 15:35   ` Will Deacon
2025-05-12 17:43 ` [PATCH v2 02/11] arm64: debug: call software break handlers statically Ada Couprie Diaz
2025-05-20 15:35   ` Will Deacon [this message]
2025-06-02 16:39     ` Ada Couprie Diaz
2025-05-12 17:43 ` [PATCH v2 03/11] arm64: debug: call step " Ada Couprie Diaz
2025-05-20 15:35   ` Will Deacon
2025-05-28 16:02     ` Ada Couprie Diaz
2025-05-12 17:43 ` [PATCH v2 04/11] arm64: debug: remove break/step handler registration infrastructure Ada Couprie Diaz
2025-05-20 15:36   ` Will Deacon
2025-05-12 17:43 ` [PATCH v2 05/11] arm64: entry: Add entry and exit functions for debug exceptions Ada Couprie Diaz
2025-05-20 15:36   ` Will Deacon
2025-05-28 14:08     ` Ada Couprie Diaz
2025-05-29 10:11       ` Will Deacon
2025-05-12 17:43 ` [PATCH v2 06/11] arm64: debug: split hardware breakpoint exeception entry Ada Couprie Diaz
2025-05-20 15:36   ` Will Deacon
2025-05-28 15:17     ` Mark Rutland
2025-05-28 16:10       ` Ada Couprie Diaz
2025-05-12 17:43 ` [PATCH v2 07/11] arm64: debug: split single stepping exception entry Ada Couprie Diaz
2025-05-20 16:29   ` Will Deacon
2025-05-28 15:22     ` Mark Rutland
2025-05-29 10:10       ` Will Deacon
2025-05-29 10:48         ` Ada Couprie Diaz
2025-05-12 17:43 ` [PATCH v2 08/11] arm64: debug: split hardware watchpoint " Ada Couprie Diaz
2025-05-20 16:59   ` Will Deacon
2025-05-28 13:47     ` Ada Couprie Diaz
2025-05-28 15:42       ` Mark Rutland
2025-05-29 10:13         ` Will Deacon
2025-05-12 17:43 ` [PATCH v2 09/11] arm64: debug: split brk64 " Ada Couprie Diaz
2025-05-12 17:43 ` [PATCH v2 10/11] arm64: debug: split bkpt32 " Ada Couprie Diaz
2025-05-21  9:07   ` Will Deacon
2025-05-29 10:43     ` Ada Couprie Diaz
2025-05-12 17:43 ` [PATCH v2 11/11] arm64: debug: remove debug exception registration infrastructure Ada Couprie Diaz
2025-05-21  9:38   ` Will Deacon
2025-05-28 16:41     ` Ada Couprie Diaz
2025-05-29 10:15       ` Will Deacon
2025-05-13 12:25 ` [PATCH v2 00/11] arm64: debug: remove hook registration, split exception entry Luis Claudio R. Goncalves
2025-05-13 15:19   ` Ada Couprie Diaz
2025-05-16 11:57     ` Luis Claudio R. Goncalves
2025-05-28 10:38       ` Ada Couprie Diaz
2025-06-03 16:10         ` Ada Couprie Diaz

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20250520153545.GB18901@willie-the-truck \
    --to=will@kernel.org \
    --cc=ada.coupriediaz@arm.com \
    --cc=bigeasy@linutronix.de \
    --cc=catalin.marinas@arm.com \
    --cc=lgoncalv@redhat.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=mark.rutland@arm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox