This series adds a RISC-V Debug Module model and wires it into target/riscv and the virt machine.
It depends on two earlier patch sets: - Max's Zvfbfa v5 series, which introduces the EXT_TB flags mechanism reused here; - the Sdext debug extension v5 series, which adds the base debug-mode support that this series builds on. The architectural reference for this work is the RISC-V Debug Specification v1.0 (ratified 2025-02-21): https://github.com/riscv/riscv-debug-spec/releases/tag/1.0 The implementation takes design cues from spike's debug module. The focus is the Debug Module itself and the execution-based debug flow around it. In practice, this means: - target/riscv gains the plumbing needed to keep a hart in Debug Mode while it executes from a DM ROM, and to route haltreq, reset-haltreq, single-step completion, ebreak, exceptions, and trigger-based debug entry through that ROM flow; - hw/riscv gains a QOM Debug Module device with a DMI-style MMIO window, a ROM work area, per-hart state tracking, run-control, abstract register access, and system bus access; - virt wires CPUs to the DM and exposes a stable layout for the DMI window and ROM alias; - qtest adds both protocol-level coverage and TCG-backed execution tests for the full bring-up path on rv32 and rv64. The series intentionally focuses on board-visible DM behavior. It does not add a JTAG DTM frontend, authentication, or other transport-side pieces. The result is a usable DM model for virt, with enough target-side support to exercise the main spec-driven debug flows and enough qtest coverage to keep the behavior regression-resistant. Current implementation status: +-------------------+---------+---------+---------------------------+ | Area | Req/Opt | Status | Notes | +-------------------+---------+---------+---------------------------+ | Debug entry | req | done | haltreq, reset-haltreq, | | | | | ebreak, step, exceptions, | | | | | triggers | +-------------------+---------+---------+---------------------------+ | DM device | req | done | riscv-dm QOM, DMI MMIO, | | | | | ROM work area, reset | +-------------------+---------+---------+---------------------------+ | Hart state | req | done | halted, resumeack, | | | | | havereset, haltsum0/1, | | | | | hart selection | +-------------------+---------+---------+---------------------------+ | Run-control | req | done | haltreq, resumereq, | | | | | hartreset, ndmreset, | | | | | reset-haltreq | +-------------------+---------+---------+---------------------------+ | Abstract cmds | req | done | Access Register | | | | | (GPR/CSR/FPR), DATA, | | | | | PROGBUF, ABSTRACTAUTO | +-------------------+---------+---------+---------------------------+ | SBA | opt | done | SBCS, SBADDRESS, SBDATA, | | | | | sticky errors, auto-inc | +-------------------+---------+---------+---------------------------+ | virt wiring | -- | done | DM address map, CPU | | | | | hookup, ROM propagation | +-------------------+---------+---------+---------------------------+ | ndmreset scope | req | partial | resets harts only, not | | | | | other devices | +-------------------+---------+---------+---------------------------+ | haltsum2/3 | opt | stub | present but read zero; | | | | | only for >1024 harts | +-------------------+---------+---------+---------------------------+ | Quick Access | opt | no | cmdtype=1 | +-------------------+---------+---------+---------------------------+ | Access Memory | opt | no | cmdtype=2 | +-------------------+---------+---------+---------------------------+ | DTM / JTAG | opt | no | transport-side, outside | | | | | this series | +-------------------+---------+---------+---------------------------+ | Authentication | opt | no | authdata absent; | | | | | authenticated=1 | +-------------------+---------+---------+---------------------------+ | Hart/resume | opt | no | dmcs2 absent, no group | | groups | | | halt/resume | +-------------------+---------+---------+---------------------------+ | External triggers | opt | no | DM ext-trigger I/O not | | | | | wired | +-------------------+---------+---------+---------------------------+ | keepalive | opt | no | set/clrkeepalive ignored | +-------------------+---------+---------+---------------------------+ | ackunavail / | opt | no | sticky unavail not | | stickyunavail | | | tracked | +-------------------+---------+---------+---------------------------+ | confstrptr | opt | stub | always 0 | +-------------------+---------+---------+---------------------------+ | Multi-DM/nextdm | opt | stub | always 0, single DM only | +-------------------+---------+---------+---------------------------+ | 128-bit access | opt | no | aarsize=4, sbaccess128 | +-------------------+---------+---------+---------------------------+ | Custom registers | opt | no | regno 0xC000-0xFFFF | +-------------------+---------+---------+---------------------------+ | Cmds on running | opt | no | abstract cmds require | | harts | | | halted hart | +-------------------+---------+---------+---------------------------+ | Sub-word reg | opt | no | aarsize 8/16-bit not | | access | | | supported | +-------------------+---------+---------+---------------------------+ The main design choice is to follow the execution-based Debug Module model described by the spec: the hart stays in Debug Mode, enters a ROM park loop, and the DM coordinates state changes and abstract command execution through mailbox words and generated ROM snippets. This keeps the DM behavior explicit in the machine model and avoids inventing a separate QEMU-only debug protocol. The patches are split into three layers: - patches 1-14 build the target/riscv side of the ROM-based Debug Mode flow and make trigger-driven stops preserve the right cause information; - patches 15-23 add the Debug Module device model, per-hart state tracking, run-control, register infrastructure, abstract commands, system bus access, and virt integration; - patches 24-28 add qtest coverage for the DMI register surface and the TCG execution paths. This series is also expected to help advance rvsp-ref machine support, since Sdext is a required instruction extension for rvsp-soc. Thanks Tao Tang for running CI on this series: https://gitlab.com/TaoTang/qemu/-/pipelines/2370872174 The resulting series has been validated with: - `TMPDIR=/tmp QTEST_QEMU_BINARY=./build/qemu-system-riscv32 \ ./build/tests/qtest/riscv-dm-test` - `TMPDIR=/tmp QTEST_QEMU_BINARY=./build/qemu-system-riscv64 \ ./build/tests/qtest/riscv-dm-test` Thanks, Chao Chao Liu (28): target/riscv: track pending Debug Module halt requests target/riscv: keep Debug Mode active when a DM ROM is present target/riscv: enter Debug Mode from pending DM halt requests target/riscv: route in-debug exceptions back to the DM ROM target/riscv: re-enter the DM ROM after single-step completion target/riscv: let ebreak enter the DM ROM target/riscv: restart the DM ROM on debug-mode ebreak target/riscv: track the exact breakpoint trigger hit target/riscv: track the exact watchpoint trigger hit target/riscv: send trigger debug-mode actions to the DM ROM target/riscv: suppress itrigger TB state in Debug Mode target/riscv: tighten itrigger privilege and count checks target/riscv: allow debug-mode actions for itrigger target/riscv: stop consuming itrigger counts in Debug Mode hw/riscv: add an initial Debug Module device model hw/riscv/dm: track per-hart debug state hw/riscv/dm: add hart run-control operations hw/riscv/dm: queue reset halts from the reset work item hw/riscv/dm: add DMI register declarations and ROM entry program hw/riscv/dm: add register handlers and update state management hw/riscv/dm: add abstract command execution hw/riscv/dm: add system bus access hw/riscv/virt: integrate the Debug Module tests/qtest: add initial RISC-V Debug Module tests tests/qtest: extend DM register semantics coverage tests/qtest: add DM abstract command and halt/resume tests tests/qtest: add DM TCG halt and register access tests tests/qtest: add DM TCG single-step and trigger tests MAINTAINERS | 1 + hw/riscv/Kconfig | 5 + hw/riscv/dm.c | 2017 +++++++++++++++++++++++++++++++++++ hw/riscv/meson.build | 2 + hw/riscv/trace-events | 14 + hw/riscv/virt.c | 21 +- include/hw/riscv/dm.h | 139 +++ target/riscv/cpu.c | 68 ++ target/riscv/cpu.h | 8 + target/riscv/cpu_bits.h | 1 + target/riscv/cpu_helper.c | 60 +- target/riscv/debug.c | 249 ++--- target/riscv/machine.c | 2 + target/riscv/op_helper.c | 15 + target/riscv/tcg/tcg-cpu.c | 12 +- tests/qtest/meson.build | 7 +- tests/qtest/riscv-dm-test.c | 1914 +++++++++++++++++++++++++++++++++ 17 files changed, 4410 insertions(+), 125 deletions(-) create mode 100644 hw/riscv/dm.c create mode 100644 include/hw/riscv/dm.h create mode 100644 tests/qtest/riscv-dm-test.c -- 2.53.0
