diff mbox series

[v2,26/38] gdbserver: track attn enablement by breakpoints

Message ID 20220329154931.493851-27-npiggin@gmail.com
State New
Headers show
Series gdbserver multi-threaded debugging and POWER9/10 support | expand

Commit Message

Nicholas Piggin March 29, 2022, 3:49 p.m. UTC
attn-enabled is a per-core property that host software (e.g.,
skiboot) may change. gdbserver should not disable attn if it
was found to be enabled.

There are still unavoidable races where the host could change
between gdbserver wanting it enabled and disabled.

This also moves set_attn to iterate all targets in preparation
for multi-threaded debugging.

Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
 src/pdbgproxy.c | 40 ++++++++++++++++++++++++++++++++++------
 1 file changed, 34 insertions(+), 6 deletions(-)
diff mbox series

Patch

diff --git a/src/pdbgproxy.c b/src/pdbgproxy.c
index c5e439d..756feb5 100644
--- a/src/pdbgproxy.c
+++ b/src/pdbgproxy.c
@@ -54,6 +54,7 @@  static enum client_state state = IDLE;
 /* Attached to thread->gdbserver_priv */
 struct gdb_thread {
 	uint64_t pir;
+	bool attn_set;
 };
 
 static void destroy_client(int dead_fd);
@@ -116,39 +117,49 @@  static void detach(uint64_t *stack, void *priv)
 #define POWER10_HID_ENABLE_ATTN			PPC_BIT(3)
 #define POWER10_HID_FLUSH_ICACHE		PPC_BIT(2)
 
-static int set_attn(bool enable)
+static int thread_set_attn(struct pdbg_target *target, bool enable)
 {
+	struct thread *thread = target_to_thread(target);
+	struct gdb_thread *gdb_thread = thread->gdbserver_priv;
 	uint64_t hid;
 
-	if (thread_getspr(thread_target, SPR_HID, &hid))
+	if (!enable && !gdb_thread->attn_set) {
+		/* Don't clear attn if we didn't enable it */
+		return 0;
+	}
+
+	if (thread_getspr(target, SPR_HID, &hid))
 		return -1;
 
-	if (pdbg_target_compatible(thread_target, "ibm,power8-thread")) {
+	if (pdbg_target_compatible(target, "ibm,power8-thread")) {
 		if (enable) {
 			if (hid & POWER8_HID_ENABLE_ATTN)
 				return 0;
 			hid |= POWER8_HID_ENABLE_ATTN;
+			gdb_thread->attn_set = true;
 		} else {
 			if (!(hid & POWER8_HID_ENABLE_ATTN))
 				return 0;
 			hid &= ~POWER8_HID_ENABLE_ATTN;
 		}
-	} else if (pdbg_target_compatible(thread_target, "ibm,power9-thread")) {
+	} else if (pdbg_target_compatible(target, "ibm,power9-thread")) {
 		if (enable) {
 			if (hid & POWER9_HID_ENABLE_ATTN)
 				return 0;
 			hid |= POWER9_HID_ENABLE_ATTN;
+			gdb_thread->attn_set = true;
 		} else {
 			if (!(hid & POWER9_HID_ENABLE_ATTN))
 				return 0;
 			hid &= ~POWER9_HID_ENABLE_ATTN;
 		}
 		hid |= POWER9_HID_FLUSH_ICACHE;
-	} else if (pdbg_target_compatible(thread_target, "ibm,power10-thread")) {
+	} else if (pdbg_target_compatible(target, "ibm,power10-thread")) {
 		if (enable) {
 			if (hid & POWER10_HID_ENABLE_ATTN)
 				return 0;
 			hid |= POWER10_HID_ENABLE_ATTN;
+			gdb_thread->attn_set = true;
 		} else {
 			if (!(hid & POWER10_HID_ENABLE_ATTN))
 				return 0;
@@ -159,12 +170,29 @@  static int set_attn(bool enable)
 		return -1;
 	}
 
-	if (thread_putspr(thread_target, SPR_HID, hid))
+	if (thread_putspr(target, SPR_HID, hid))
 		return -1;
 
 	return 0;
 }
 
+static int set_attn(bool enable)
+{
+	struct pdbg_target *target;
+	int err = 0;
+
+	for_each_path_target_class("thread", target) {
+		if (pdbg_target_status(target) != PDBG_TARGET_ENABLED)
+			continue;
+
+		err = thread_set_attn(target, enable);
+		if (err)
+			break;
+	}
+
+	return err;
+}
+
 /* 32 registers represented as 16 char hex numbers with null-termination */
 #define REG_DATA_SIZE (32*16+1)
 static void get_gprs(uint64_t *stack, void *priv)