Message ID | 20220420065013.222816-32-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: > > Rework poll() and the stop reason code to support multi-threaded > debugging. > > - Make poll() iterate over all target threads to check whether any > are stopped. > > - If any are found stopped, stop the rest. Poll SPATTN for all > target threads. > > This provides the basis for "all-stop" threaded debugging mode, > which is what seems to work best for bare metal debugging. > > Signed-off-by: Nicholas Piggin <npiggin@gmail.com> Reviewed-by: Joel Stanley <joel@jms.id.au> > --- > src/pdbgproxy.c | 75 +++++++++++++++++++++++++++++-------------------- > 1 file changed, 44 insertions(+), 31 deletions(-) > > diff --git a/src/pdbgproxy.c b/src/pdbgproxy.c > index c5870091..735615c6 100644 > --- a/src/pdbgproxy.c > +++ b/src/pdbgproxy.c > @@ -683,60 +683,73 @@ static void stop_all(void) > PR_ERROR("Could not quiesce thread\n"); > /* How to fix? */ > } > + > + if (thread_check_attn(target)) { > + struct thread *thread = target_to_thread(target); > + struct gdb_thread *gdb_thread = thread->gdbserver_priv; > + uint64_t nia; > + > + PR_INFO("thread pir=%"PRIx64" hit attn\n", gdb_thread->pir); > + > + if (!(status.active)) > + PR_ERROR("Error thread inactive after trap\n"); > + /* Restore NIA to before break */ > + if (thread_getnia(target, &nia)) > + PR_ERROR("Error during getnia\n"); > + if (thread_putnia(target, nia - 4)) > + PR_ERROR("Error during putnia\n"); > + } > } > } > > static void interrupt(uint64_t *stack, void *priv) > { > - struct thread_state status; > - > PR_INFO("Interrupt from gdb client\n"); > + if (state != IDLE) { > + stop_all(); > > - stop_all(); > - > - status = thread_status(thread_target); > - if (!(status.quiesced)) { > - PR_ERROR("Could not quiesce thread\n"); > - return; > + state = IDLE; > + poll_interval = VCONT_POLL_DELAY; > } > - state = IDLE; > - poll_interval = VCONT_POLL_DELAY; > + > send_response(fd, TRAP); > } > > -static void poll(void) > +static bool poll_threads(void) > { > - struct thread_state status; > + struct pdbg_target *target; > + > + for_each_path_target_class("thread", target) { > + struct thread_state status; > + > + if (pdbg_target_status(target) != PDBG_TARGET_ENABLED) > + continue; > > + target->probe(target); > + status = thread_status(target); > + if (status.quiesced) > + return true; > + } > + return false; > +} > + > +static void poll(void) > +{ > if (state != SIGNAL_WAIT) > return; > > - thread_target->probe(thread_target); > - status = thread_status(thread_target); > - > - if (!(status.quiesced)) > + if (!poll_threads()) > return; > > + /* Something hit a breakpoint */ > + > + stop_all(); > + > set_attn(false); > > state = IDLE; > poll_interval = VCONT_POLL_DELAY; > > - if (thread_check_attn(thread_target)) { > - uint64_t nia; > - > - if (!(status.active)) { > - PR_ERROR("Thread inactive after trap\n"); > - send_response(fd, ERROR(EPERM)); > - return; > - } > - > - /* Restore NIA */ > - if (thread_getnia(thread_target, &nia)) > - PR_ERROR("Error during getnia\n"); > - if (thread_putnia(thread_target, nia - 4)) > - PR_ERROR("Error during putnia\n"); > - } > send_response(fd, TRAP); > } > > -- > 2.35.1 > > -- > Pdbg mailing list > Pdbg@lists.ozlabs.org > https://lists.ozlabs.org/listinfo/pdbg
diff --git a/src/pdbgproxy.c b/src/pdbgproxy.c index c5870091..735615c6 100644 --- a/src/pdbgproxy.c +++ b/src/pdbgproxy.c @@ -683,60 +683,73 @@ static void stop_all(void) PR_ERROR("Could not quiesce thread\n"); /* How to fix? */ } + + if (thread_check_attn(target)) { + struct thread *thread = target_to_thread(target); + struct gdb_thread *gdb_thread = thread->gdbserver_priv; + uint64_t nia; + + PR_INFO("thread pir=%"PRIx64" hit attn\n", gdb_thread->pir); + + if (!(status.active)) + PR_ERROR("Error thread inactive after trap\n"); + /* Restore NIA to before break */ + if (thread_getnia(target, &nia)) + PR_ERROR("Error during getnia\n"); + if (thread_putnia(target, nia - 4)) + PR_ERROR("Error during putnia\n"); + } } } static void interrupt(uint64_t *stack, void *priv) { - struct thread_state status; - PR_INFO("Interrupt from gdb client\n"); + if (state != IDLE) { + stop_all(); - stop_all(); - - status = thread_status(thread_target); - if (!(status.quiesced)) { - PR_ERROR("Could not quiesce thread\n"); - return; + state = IDLE; + poll_interval = VCONT_POLL_DELAY; } - state = IDLE; - poll_interval = VCONT_POLL_DELAY; + send_response(fd, TRAP); } -static void poll(void) +static bool poll_threads(void) { - struct thread_state status; + struct pdbg_target *target; + + for_each_path_target_class("thread", target) { + struct thread_state status; + + if (pdbg_target_status(target) != PDBG_TARGET_ENABLED) + continue; + target->probe(target); + status = thread_status(target); + if (status.quiesced) + return true; + } + return false; +} + +static void poll(void) +{ if (state != SIGNAL_WAIT) return; - thread_target->probe(thread_target); - status = thread_status(thread_target); - - if (!(status.quiesced)) + if (!poll_threads()) return; + /* Something hit a breakpoint */ + + stop_all(); + set_attn(false); state = IDLE; poll_interval = VCONT_POLL_DELAY; - if (thread_check_attn(thread_target)) { - uint64_t nia; - - if (!(status.active)) { - PR_ERROR("Thread inactive after trap\n"); - send_response(fd, ERROR(EPERM)); - return; - } - - /* Restore NIA */ - if (thread_getnia(thread_target, &nia)) - PR_ERROR("Error during getnia\n"); - if (thread_putnia(thread_target, nia - 4)) - PR_ERROR("Error during putnia\n"); - } send_response(fd, TRAP); }
Rework poll() and the stop reason code to support multi-threaded debugging. - Make poll() iterate over all target threads to check whether any are stopped. - If any are found stopped, stop the rest. Poll SPATTN for all target threads. This provides the basis for "all-stop" threaded debugging mode, which is what seems to work best for bare metal debugging. Signed-off-by: Nicholas Piggin <npiggin@gmail.com> --- src/pdbgproxy.c | 75 +++++++++++++++++++++++++++++-------------------- 1 file changed, 44 insertions(+), 31 deletions(-)