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


Reply via email to