Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: Ada Couprie Diaz <ada.coupriediaz@arm.com>
To: linux-arm-kernel@lists.infradead.org
Cc: Mark Rutland <mark.rutland@arm.com>,
	Rob Herring <robh@kernel.org>,
	Anshuman Khandual <anshuman.khandual@arm.com>,
	Catalin Marinas <catalin.marinas@arm.com>,
	Will Deacon <will@kernel.org>
Subject: [PATCH 1/2] arm64/debug: update perf slots in sync with BP registers
Date: Wed, 27 May 2026 17:15:52 +0100	[thread overview]
Message-ID: <20260527161553.97676-2-ada.coupriediaz@arm.com> (raw)
In-Reply-To: <20260527161553.97676-1-ada.coupriediaz@arm.com>

The current order of operations in `hw_breakpoint_control()` is unsound
and can lead to the kernel getting stuck on a hardware breakpoint in
some edge cases[0], as it can be called with debug exceptions unmasked.

As we search a relevant perf slot and update depending on the operation
directly in `hw_breakpoint_setup_slot()`, when uninstalling a breakpoint
it can still be triggered while its slot has been cleared, preventing
the debug handlers from handling it properly and getting stuck on it.

Hoist the perf slot updates out of `hw_breakpoint_setup_slot()` into
`hw_breakpoint_control()` : set up the slot before writing to the register
when installing (no change) but clear it after writing to the register
when uninstalling.
Rename `hw_breakpoint_setup_slot()` to `hw_breakpoint_find_slot()`, as
the slot setup is now done directly in `hw_breakpoint_control()`.

[0]: https://lore.kernel.org/linux-arm-kernel/adeE4MD0RgapI8aL@J2N7QTR9R3/

Signed-off-by: Ada Couprie Diaz <ada.coupriediaz@arm.com>
---
 arch/arm64/kernel/hw_breakpoint.c | 28 ++++++++++++++--------------
 1 file changed, 14 insertions(+), 14 deletions(-)

diff --git a/arch/arm64/kernel/hw_breakpoint.c b/arch/arm64/kernel/hw_breakpoint.c
index ab76b36dce82..ce99a00c8596 100644
--- a/arch/arm64/kernel/hw_breakpoint.c
+++ b/arch/arm64/kernel/hw_breakpoint.c
@@ -174,12 +174,11 @@ static int is_compat_bp(struct perf_event *bp)
 }
 
 /**
- * hw_breakpoint_slot_setup - Find and setup a perf slot according to
- *			      operations
+ * hw_breakpoint_find_slot - Find a perf slot according to operation
  *
  * @slots: pointer to array of slots
  * @max_slots: max number of slots
- * @bp: perf_event to setup
+ * @bp: perf_event to find, for uninstall and restore operations
  * @ops: operation to be carried out on the slot
  *
  * Return:
@@ -187,30 +186,26 @@ static int is_compat_bp(struct perf_event *bp)
  *	-ENOSPC if no slot is available/matches
  *	-EINVAL on wrong operations parameter
  */
-static int hw_breakpoint_slot_setup(struct perf_event **slots, int max_slots,
+static int hw_breakpoint_find_slot(struct perf_event **slots, int max_slots,
 				    struct perf_event *bp,
 				    enum hw_breakpoint_ops ops)
 {
 	int i;
-	struct perf_event **slot;
+	struct perf_event *slot;
 
 	for (i = 0; i < max_slots; ++i) {
-		slot = &slots[i];
+		slot = slots[i];
 		switch (ops) {
 		case HW_BREAKPOINT_INSTALL:
-			if (!*slot) {
-				*slot = bp;
+			if (!slot)
 				return i;
-			}
 			break;
 		case HW_BREAKPOINT_UNINSTALL:
-			if (*slot == bp) {
-				*slot = NULL;
+			if (slot == bp)
 				return i;
-			}
 			break;
 		case HW_BREAKPOINT_RESTORE:
-			if (*slot == bp)
+			if (slot == bp)
 				return i;
 			break;
 		default:
@@ -247,13 +242,15 @@ static int hw_breakpoint_control(struct perf_event *bp,
 		reg_enable = !debug_info->wps_disabled;
 	}
 
-	i = hw_breakpoint_slot_setup(slots, max_slots, bp, ops);
+	i = hw_breakpoint_find_slot(slots, max_slots, bp, ops);
 
 	if (WARN_ONCE(i < 0, "Can't find any breakpoint slot"))
 		return i;
 
 	switch (ops) {
 	case HW_BREAKPOINT_INSTALL:
+		slots[i] = bp;
+		barrier();
 		/*
 		 * Ensure debug monitors are enabled at the correct exception
 		 * level.
@@ -278,6 +275,9 @@ static int hw_breakpoint_control(struct perf_event *bp,
 		 * level.
 		 */
 		disable_debug_monitors(dbg_el);
+
+		barrier();
+		slots[i] = NULL;
 		break;
 	}
 
-- 
2.43.0



  reply	other threads:[~2026-05-27 16:16 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-05-27 16:15 [PATCH 0/2] arm64/debug: clean up some HW BP edge cases Ada Couprie Diaz
2026-05-27 16:15 ` Ada Couprie Diaz [this message]
2026-05-27 16:15 ` [PATCH 2/2] arm64/debug: mask exceptions when switching cpu-bound watchpoints Ada Couprie Diaz
2026-07-22 11:30 ` [PATCH 0/2] arm64/debug: clean up some HW BP edge cases Will Deacon
2026-07-22 12:56   ` Mark Rutland

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=20260527161553.97676-2-ada.coupriediaz@arm.com \
    --to=ada.coupriediaz@arm.com \
    --cc=anshuman.khandual@arm.com \
    --cc=catalin.marinas@arm.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=mark.rutland@arm.com \
    --cc=robh@kernel.org \
    --cc=will@kernel.org \
    /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