Message ID | 20220420065013.222816-27-npiggin@gmail.com |
---|---|
State | New |
Headers | show |
Series | gdbserver multi-threaded debugging and POWER9/10 support | expand |
On Wed, 20 Apr 2022 at 06:51, Nicholas Piggin <npiggin@gmail.com> wrote: > > Add a command-specific pointer to the struct thread that gdbserver > can use, so it doesn't have to build its own structure of threads. > > Initially keep the PIR value in here, as a demonstration. > > Later PIR will be used to identify threads to the gdb client, and > more data will be added to the gdb_thread structure to support > debugging multiple threads. > > Signed-off-by: Nicholas Piggin <npiggin@gmail.com> Reviewed-by: Joel Stanley <joel@jms.id.au> > --- > libpdbg/hwunit.h | 1 + > src/pdbgproxy.c | 66 ++++++++++++++++++++++++++++++++++++------------ > 2 files changed, 51 insertions(+), 16 deletions(-) > > diff --git a/libpdbg/hwunit.h b/libpdbg/hwunit.h > index 2ce41db8..563b5812 100644 > --- a/libpdbg/hwunit.h > +++ b/libpdbg/hwunit.h > @@ -139,6 +139,7 @@ struct core { > struct thread { > struct pdbg_target target; > struct thread_state status; > + void *gdbserver_priv; > int id; > struct thread_state (*state)(struct thread *); > int (*step)(struct thread *, int); > diff --git a/src/pdbgproxy.c b/src/pdbgproxy.c > index 393b37bf..b8ee2a06 100644 > --- a/src/pdbgproxy.c > +++ b/src/pdbgproxy.c > @@ -51,6 +51,11 @@ static int fd = -1; > enum client_state {IDLE, SIGNAL_WAIT}; > static enum client_state state = IDLE; > > +/* Attached to thread->gdbserver_priv */ > +struct gdb_thread { > + uint64_t pir; > +}; > + > static void destroy_client(int dead_fd); > > static uint8_t gdbcrc(char *data) > @@ -666,7 +671,7 @@ static void SIGINT_handler(int sig) > gdbserver_running = false; > } > > -static int gdbserver_start(struct pdbg_target *thread, struct pdbg_target *adu, uint16_t port) > +static int gdbserver_start(struct pdbg_target *adu, uint16_t port) > { > int sock, i; > struct sigaction sa; > @@ -682,7 +687,6 @@ static int gdbserver_start(struct pdbg_target *thread, struct pdbg_target *adu, > } > > parser_init(callbacks); > - thread_target = thread; > adu_target = adu; > > sock = socket(PF_INET, SOCK_STREAM, 0); > @@ -767,33 +771,40 @@ static int gdbserver_start(struct pdbg_target *thread, struct pdbg_target *adu, > > static int gdbserver(uint16_t port) > { > - struct pdbg_target *target, *adu, *thread = NULL; > + struct pdbg_target *target, *adu, *first_target = NULL; > > for_each_path_target_class("thread", target) { > - if (pdbg_target_probe(target) != PDBG_TARGET_ENABLED) > + struct thread *thread = target_to_thread(target); > + struct gdb_thread *gdb_thread; > + > + if (pdbg_target_status(target) != PDBG_TARGET_ENABLED) > continue; > > - if (!thread) { > - thread = target; > + if (!pdbg_target_compatible(target, "ibm,power8-thread") && > + !pdbg_target_compatible(target, "ibm,power9-thread") && > + !pdbg_target_compatible(target, "ibm,power10-thread")) { > + PR_ERROR("GDBSERVER is only available on POWER8,9,10\n"); > + return -1; > + } > + > + gdb_thread = malloc(sizeof(struct gdb_thread)); > + memset(gdb_thread, 0, sizeof(*gdb_thread)); > + thread->gdbserver_priv = gdb_thread; > + > + if (!first_target) { > + first_target = target; > } else { > fprintf(stderr, "GDB server cannot be run on multiple threads at once.\n"); > return 0; > } > } > > - if (!thread) { > + if (!first_target) { > fprintf(stderr, "No thread selected\n"); > return 0; > } > > - if (!pdbg_target_compatible(thread, "ibm,power8-thread") && > - !pdbg_target_compatible(thread, "ibm,power9-thread") && > - !pdbg_target_compatible(thread, "ibm,power10-thread")) { > - PR_ERROR("GDBSERVER is only available on POWER8,9,10\n"); > - return -1; > - } > - > - if (pdbg_target_compatible(thread, "ibm,power9-thread")) { > + if (pdbg_target_compatible(first_target, "ibm,power9-thread")) { > /* > * XXX: If we advertise no swbreak support on POWER9 does > * that prevent the client using them? > @@ -801,6 +812,29 @@ static int gdbserver(uint16_t port) > PR_WARNING("Breakpoints may cause host crashes on POWER9 and should not be used\n"); > } > > + thread_target = first_target; > + > + for_each_path_target_class("thread", target) { > + struct thread *thread = target_to_thread(target); > + struct gdb_thread *gdb_thread; > + > + 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; > + } > + > + if (gdb_thread->pir & ~0xffffULL) { > + /* This limit is just due to some string array sizes */ > + PR_ERROR("PIR exceeds 16-bits."); > + return 0; > + } > + } > + > /* Select ADU target */ > pdbg_for_each_class_target("mem", adu) { > if (pdbg_target_probe(adu) == PDBG_TARGET_ENABLED) > @@ -812,7 +846,7 @@ static int gdbserver(uint16_t port) > return 0; > } > > - gdbserver_start(thread, adu, port); > + gdbserver_start(adu, port); > > return 0; > } > -- > 2.35.1 > > -- > Pdbg mailing list > Pdbg@lists.ozlabs.org > https://lists.ozlabs.org/listinfo/pdbg
diff --git a/libpdbg/hwunit.h b/libpdbg/hwunit.h index 2ce41db8..563b5812 100644 --- a/libpdbg/hwunit.h +++ b/libpdbg/hwunit.h @@ -139,6 +139,7 @@ struct core { struct thread { struct pdbg_target target; struct thread_state status; + void *gdbserver_priv; int id; struct thread_state (*state)(struct thread *); int (*step)(struct thread *, int); diff --git a/src/pdbgproxy.c b/src/pdbgproxy.c index 393b37bf..b8ee2a06 100644 --- a/src/pdbgproxy.c +++ b/src/pdbgproxy.c @@ -51,6 +51,11 @@ static int fd = -1; enum client_state {IDLE, SIGNAL_WAIT}; static enum client_state state = IDLE; +/* Attached to thread->gdbserver_priv */ +struct gdb_thread { + uint64_t pir; +}; + static void destroy_client(int dead_fd); static uint8_t gdbcrc(char *data) @@ -666,7 +671,7 @@ static void SIGINT_handler(int sig) gdbserver_running = false; } -static int gdbserver_start(struct pdbg_target *thread, struct pdbg_target *adu, uint16_t port) +static int gdbserver_start(struct pdbg_target *adu, uint16_t port) { int sock, i; struct sigaction sa; @@ -682,7 +687,6 @@ static int gdbserver_start(struct pdbg_target *thread, struct pdbg_target *adu, } parser_init(callbacks); - thread_target = thread; adu_target = adu; sock = socket(PF_INET, SOCK_STREAM, 0); @@ -767,33 +771,40 @@ static int gdbserver_start(struct pdbg_target *thread, struct pdbg_target *adu, static int gdbserver(uint16_t port) { - struct pdbg_target *target, *adu, *thread = NULL; + struct pdbg_target *target, *adu, *first_target = NULL; for_each_path_target_class("thread", target) { - if (pdbg_target_probe(target) != PDBG_TARGET_ENABLED) + struct thread *thread = target_to_thread(target); + struct gdb_thread *gdb_thread; + + if (pdbg_target_status(target) != PDBG_TARGET_ENABLED) continue; - if (!thread) { - thread = target; + if (!pdbg_target_compatible(target, "ibm,power8-thread") && + !pdbg_target_compatible(target, "ibm,power9-thread") && + !pdbg_target_compatible(target, "ibm,power10-thread")) { + PR_ERROR("GDBSERVER is only available on POWER8,9,10\n"); + return -1; + } + + gdb_thread = malloc(sizeof(struct gdb_thread)); + memset(gdb_thread, 0, sizeof(*gdb_thread)); + thread->gdbserver_priv = gdb_thread; + + if (!first_target) { + first_target = target; } else { fprintf(stderr, "GDB server cannot be run on multiple threads at once.\n"); return 0; } } - if (!thread) { + if (!first_target) { fprintf(stderr, "No thread selected\n"); return 0; } - if (!pdbg_target_compatible(thread, "ibm,power8-thread") && - !pdbg_target_compatible(thread, "ibm,power9-thread") && - !pdbg_target_compatible(thread, "ibm,power10-thread")) { - PR_ERROR("GDBSERVER is only available on POWER8,9,10\n"); - return -1; - } - - if (pdbg_target_compatible(thread, "ibm,power9-thread")) { + if (pdbg_target_compatible(first_target, "ibm,power9-thread")) { /* * XXX: If we advertise no swbreak support on POWER9 does * that prevent the client using them? @@ -801,6 +812,29 @@ static int gdbserver(uint16_t port) PR_WARNING("Breakpoints may cause host crashes on POWER9 and should not be used\n"); } + thread_target = first_target; + + for_each_path_target_class("thread", target) { + struct thread *thread = target_to_thread(target); + struct gdb_thread *gdb_thread; + + 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; + } + + if (gdb_thread->pir & ~0xffffULL) { + /* This limit is just due to some string array sizes */ + PR_ERROR("PIR exceeds 16-bits."); + return 0; + } + } + /* Select ADU target */ pdbg_for_each_class_target("mem", adu) { if (pdbg_target_probe(adu) == PDBG_TARGET_ENABLED) @@ -812,7 +846,7 @@ static int gdbserver(uint16_t port) return 0; } - gdbserver_start(thread, adu, port); + gdbserver_start(adu, port); return 0; }
Add a command-specific pointer to the struct thread that gdbserver can use, so it doesn't have to build its own structure of threads. Initially keep the PIR value in here, as a demonstration. Later PIR will be used to identify threads to the gdb client, and more data will be added to the gdb_thread structure to support debugging multiple threads. Signed-off-by: Nicholas Piggin <npiggin@gmail.com> --- libpdbg/hwunit.h | 1 + src/pdbgproxy.c | 66 ++++++++++++++++++++++++++++++++++++------------ 2 files changed, 51 insertions(+), 16 deletions(-)