diff mbox series

[v2,33/38] gdbserver: allow gdbserver to start with targets running

Message ID 20220329154931.493851-34-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
Rather than having to stop and start threads independently,
allow gdbserver to stop and start its targets as necessary.

Manually quiesced targets may still be debugged. This just
makes it a bit more user friendly.

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

Patch

diff --git a/src/pdbgproxy.c b/src/pdbgproxy.c
index e9d11af..3ffa9e2 100644
--- a/src/pdbgproxy.c
+++ b/src/pdbgproxy.c
@@ -51,7 +51,7 @@ 
 
 #define TEST_SKIBOOT_ADDR 0x40000000
 
-static bool all_stopped = true; /* must be started with targets stopped */
+static bool all_stopped = false;
 static struct pdbg_target *thread_target = NULL;
 static struct pdbg_target *adu_target;
 static struct timeval timeout;
@@ -222,9 +222,13 @@  static void stop_reason(uint64_t *stack, void *priv)
 	send_stop_for_thread(thread_target);
 }
 
+static void start_all(void);
+
 static void detach(uint64_t *stack, void *priv)
 {
 	PR_INFO("Detach debug session with client. pid %16" PRIi64 "\n", stack[0]);
+	start_all();
+
 	send_response(fd, OK);
 }
 
@@ -891,6 +895,8 @@  static void create_client(int new_fd)
 {
 	PR_INFO("Client connected\n");
 	fd = new_fd;
+	if (!all_stopped)
+		stop_all();
 }
 
 static void destroy_client(int dead_fd)
@@ -1095,27 +1101,38 @@  static int gdbserver(uint16_t port)
 
 	thread_target = first_target;
 
+	for_each_path_target_class("thread", target) {
+		if (pdbg_target_status(target) != PDBG_TARGET_ENABLED)
+			continue;
+
+		if (thread_stop(target)) {
+			PR_ERROR("Could not stop thread %s\n",
+				 pdbg_target_path(target));
+			return -1;
+		}
+	}
+
 	for_each_path_target_class("thread", target) {
 		struct thread *thread = target_to_thread(target);
-		struct gdb_thread *gdb_thread;
+		struct gdb_thread *gdb_thread = thread->gdbserver_priv;
 
 		if (pdbg_target_status(target) != PDBG_TARGET_ENABLED)
 			continue;
 
-		gdb_thread = thread->gdbserver_priv;
-
 		if (thread_getspr(target, SPR_PIR, &gdb_thread->pir)) {
 			PR_ERROR("Error reading PIR. Are all thread in the target cores quiesced?\n");
-			return 0;
+			goto out;
 		}
 
 		if (gdb_thread->pir & ~0xffffULL) {
 			/* This limit is just due to some string array sizes */
 			PR_ERROR("PIR exceeds 16-bits.");
-			return 0;
+			goto out;
 		}
 	}
 
+	start_all();
+
 	/* Select ADU target */
 	pdbg_for_each_class_target("mem", adu) {
 		if (pdbg_target_probe(adu) == PDBG_TARGET_ENABLED)
@@ -1124,11 +1141,15 @@  static int gdbserver(uint16_t port)
 
 	if (!adu) {
 		fprintf(stderr, "No ADU found\n");
-		return 0;
+		goto out;
 	}
 
 	gdbserver_start(adu, port);
 
+out:
+	if (all_stopped)
+		__start_all();
+
 	return 0;
 }
 #else