> On 7. Jul 2026, at 19:27, Richard Henderson <[email protected]>
> wrote:
>
> On 7/6/26 02:21, Peter Maydell wrote:
>> On Sun, 5 Jul 2026 at 23:44, Gilles Grimaud
>> <[email protected]> wrote:
>>>
>>> While working on Raspberry Pi Pico/RP2040 support, I noticed that Pico SDK
>>> programs deliberately execute BKPT from _exit(). On real hardware this is
>>> useful when a debug probe is attached: returning from main() stops the
>>> debugger at the program exit point.
>>>
>>> Under QEMU this currently does not behave like the debug-probe case. For
>>> M-profile guests, the BKPT instruction is routed through the architectural
>>> guest debug exception path. Without halting debug, that path should remain a
>>> guest-visible DebugMonitor exception when DebugMonitor is enabled, or
>>> escalate
>>> towards HardFault otherwise. This patch deliberately leaves that no-debugger
>>> architectural path unchanged.
>>>
>>> The problem addressed here is the case where GDB is connected to QEMU's
>>> gdbstub. In that situation, firmware that uses BKPT as a debugger stop point
>>> should stop in the attached debugger. Instead, the M-profile guest currently
>>> continues down the guest exception path and may end in HardFault/lockup
>>> rather
>>> than reporting a clean trap to GDB.
>>>
>>> This is not specific to the RP2040 machine model. It is a generic
>>> Cortex-M/gdbstub interaction: firmware that uses BKPT as a debugger stop
>>> point
>>> should be reported to the attached debugger, while keeping the guest
>>> architectural exception path when no debugger is attached.
>>>
>>> Expose a small gdbstub helper to test whether a CPU is visible to an
>>> attached
>>> debugger. When an M-profile BKPT instruction is executed with such a
>>> debugger
>>> attached, leave the translated block with EXCP_DEBUG so the existing gdbstub
>>> stop path reports a trap to GDB.
>>>
>>> Signed-off-by: Gilles Grimaud <[email protected]>
>>> ---
>>> gdbstub/gdbstub.c | 13 ++++++++++++-
>>> include/exec/gdbstub.h | 6 ++++++
>>> target/arm/tcg/debug.c | 9 +++++++++
>>> 3 files changed, 27 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/gdbstub/gdbstub.c b/gdbstub/gdbstub.c
>>> index c3c944e965..9f259fc005 100644
>>> --- a/gdbstub/gdbstub.c
>>> +++ b/gdbstub/gdbstub.c
>>> @@ -237,6 +237,18 @@ static GDBProcess *gdb_get_cpu_process(CPUState *cpu)
>>> return gdb_get_process(gdb_get_cpu_pid(cpu));
>>> }
>>>
>>> +bool gdb_cpu_is_attached(CPUState *cpu)
>>> +{
>>> + GDBProcess *process;
>>> +
>>> + if (!gdbserver_state.init || !cpu) {
>>> + return false;
>>> + }
>>> +
>>> + process = gdb_get_cpu_process(cpu);
>>> + return process && process->attached;
>>> +}
>> No other architecture, CPU or board in QEMU needs to do this,
>> so my instinct is to say that M-profile should not be special here.
>> Richard, Alex: how do we usually handle breakpoint insns for the
>> gdbstub ?
>
> We handle them via CPUBreakpoint structures; we never inject code changes.
>
> The patch description explains the confusion: this is attempting to replicate
> a feature of the Raspberry Pi Pico SDK, wherein a guest BPKT really is
> trapped by an external debugger.
>
> The only question is whether we want to follow that, and I suspect the answer
> is no.
>
>
> r~
Hi,
It’s a typical debugging pattern on Cortex-M platforms.
Especially as quite some designs around of Arm M profile are with no HW
breakpoints at all.
The Armv8-M TRM says:
(B13.4.4)
> When DHCSR.C_DEBUGEN == 0 or when the PE is in a state in which halting is
> prohibited,
> the BKPT instruction does not generate an entry to Debug state. If no
> DebugMonitor
> exception is generated, the BKPT instruction generates a HardFault exception
> or enters
> Lockup state.
With UDE added as an additional control in Armv8.1-M
(C2.4.25)
> BKPT
> Breakpoint. Breakpoint causes a DebugMonitor exception or a debug halt to
> occur
> depending on the configuration of the debug support.
with DebugMonitor being fairly new and not really used all that much because
self-hosting debug on Cortex-M is/was quite rare
Quite a number of Cortex-M platforms don’t have hardware breakpoints at all,
relying fully on BKPT. While there are other options when QEMU is around, I
think
it’s still a good idea to be able to replicate the hardware behaviour.
Which in this case would mean having QEMU’s gdbstub match the behaviour
that can be obtained from OpenOCD providing a GDB stub.