Risc-v-gsp-rm-debugger

From Open-IOV
Revision as of 04:41, 12 October 2026 by WikiBot (talk | contribs) (Fix repository links: point to the cgit tree URLs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

An absence of critical technical documentation has historically slowed growth and adoption of developer ecosystems for GPU virtualization.

This CC-BY-4.0 licensed content can either be used with attribution, or used as inspiration for new documentation, created by GPU vendors for public commercial distribution as developer documentation.

Where possible, this documentation will clearly label dates and versions of observed-but-not-guaranteed behaviour vs. vendor-documented stable interfaces/behaviour with guarantees of forward or backward compatibility.

risc-v-gsp-rm-debugger

Scope. risc-v-gsp-rm-debugger runs GSP/uproc firmware off-hardware in a controllable RISC-V machine, instruments it with Frida-like primitives, and records durable sessions so firmware behaviour can be captured and compared with evidence instead of anecdotes. Canonical sources: ../docs/05-operations/03-risc-v-gsp-rm-vm.md and ../docs/05-operations/04-risc-v-gsp-rm-debugger-user-guide.md; if this page and the docs tree disagree, the docs tree wins.

Development-only. Host-side tooling that is never shipped, never a driver dependency and never present in a guest; interfaces and file formats may change without notice.

Status: 2026-10-12, tree master @ 2f066727. Tags: [live] recorded QEMU sessions; [design] device model and custom simulator are roadmap.

1. What it is

risc-v-gsp-rm-debugger makes the firmware's runtime behaviour inspectable. It boots GSP/uproc firmware in qemu-system-riscv64 (or a deterministic native interpreter) and offers Frida-like primitives on top:

  • breakpoints and enter/leave hooks (RV64 ABI aware); watchpoints on firmware variables;
  • memory read/write/hexdump/search, structure decoding, snapshot diffing;
  • recorded sessions: a replayable event stream plus memory dumps;
  • remote calls and run-to-cursor (execute until a chosen address);
  • injection: build a position-independent RV64 service, load it into the running firmware and dispatch to it;
  • declarative probe specs, a plugin API, and a Ghidra bridge for symbol export, hit annotation and decompiler-driven execution.

Its purpose is capturing how the firmware server behaves, repeatably and safely, so emulation changes can be measured against recorded evidence and can survive GSP version, device and architecture churn. The tooling lives under open-iov/debug/risc-v-gsp-rm-vm/, with its own documentation set (design, usage, scripting, plugins, bridges, accuracy, portability, roadmap).

2. What it is not

  • Not a GSP boot environment. QEMU virt has no falcon windows, WPR2, CSB/TRANSCOM, PMU, timers or FB DMA. probe reports exactly where the real image first diverges (for the TU104 570.144 image: a load-access fault at firmware vaddr 0x4009014 reading 0x2000000000000A00) — expected data, not a boot. A device model is a roadmap item, not a claim.
  • Not a timing model. Do not infer latency, jitter or concurrency behaviour from it; its in-scope conclusions are execution flow and memory side effects.
  • Not a replacement for Ghidra or the guest diagnostics. Ghidra answers what is the code; risc-v-gsp-rm-debugger answers what did it do; the guest driver remains the oracle for guest-side behaviour.
  • Not a hardware or security tool. It never attaches to a real GPU, a guest, a kernel module or an mdev, and it is never a security or confidentiality boundary.

3. Where it fits

Layer Tool Question answered
Static Ghidra and the decompilation corpus what is the code?
Guest driver guest diagnostics, ptrace tracing what did the driver request?
Firmware runtime risc-v-gsp-rm-debugger what does the firmware server do, repeatably and safely?
Physical backend supervised hardware sessions, module logs what did real silicon / the real GSP-RM do?

The intended measurement loop: capture the real backend's RPC behaviour, run the same stimulus in risc-v-gsp-rm-debugger, and compare the recorded sessions with the tool's accuracy metrics. A simulator observation is evidence about the firmware, not about silicon; anything that would change the product is reproduced on a physical reference first.

4. Quickstart

Requirements: Linux, Python 3.10+ (standard library only), qemu-system-riscv64 (Ubuntu package qemu-system-misc), clang and lld. No GPU, no driver and no kernel module are touched. From the repository root:

cd debug/risc-v-gsp-rm-vm
./risc-v-gsp-rm-debugger.sh info     # environment check: QEMU, toolchain, paths
make demo && make sdk                # build the bundled RV64 uproc demo and the injection SDK
./risc-v-gsp-rm-debugger.sh demo     # canned run: boot, hooks, watchpoints, session
./risc-v-gsp-rm-debugger.sh analyze dumps/<printed-session-dir>
./risc-v-gsp-rm-debugger.sh probe    # real GSP image: report the first divergence
./risc-v-gsp-rm-debugger.sh inject   # load and invoke a position-independent service

What "good" looks like: info reports QEMU and the demo paths; demo prints hook/branch lines and a session directory under dumps/; analyze renders hook/watch/breakpoint events and a coherent summary; probe reports a bounded first divergence (expected data, not a boot); inject returns matching values on the direct and firmware-dispatched invocation paths.

A large test suite (hundreds of tests) is run with make test, covering unit tests plus live-QEMU smoke runs.

5. The primitives

Primitive Use it for
breakpoint / hook did this function run? with what arguments and return value?
watch (w/r/a) when did this field change, and from which store PC?
run / run_until bounded observation; stop at a chosen address
call remote call to unit-test a function in isolation
step / note single-step with dispatch; annotate the event stream
Memory.read/write/hexdump/search/snapshot/diff inspect and diff memory regions
SymbolDB resolve file/program/runtime addresses across sources
Recorder write the durable session (events, snapshots, blobs)
injection SDK load, register and invoke your own position-independent RV64 service

Instructions between stops are invisible unless a trace is on (a TCG plugin on QEMU, or --trace on the native backend). Two backends — QEMU-RSP and the native interpreter — satisfy the same session API, so scripts, probes, plugins, recordings and comparisons survive a backend change.

6. Fidelity levels (what a result can mean)

Level Property risc-v-gsp-rm-debugger today
L0 instruction semantics high (QEMU TCG, same ISA family)
L1 memory behaviour high for RAM-resident code, conditional on mapping
L2 time / concurrency not modelled — never claim
L3 device environment (falcon, WPR2, CSB, PMU, timers, DMA, IRQ) absent — device model is roadmap

A simulator observation is evidence about the firmware, not about silicon. Never quote a session for timing, interrupt, security or confidentiality claims; zero hits in a run are a coverage fact, not proof that code is dead.

7. Sessions as evidence

Every run records a session directory (format greeneye-session/1):

dumps/<stamp>-<uuid>-<name>/
  session.json        format, name, counts, snapshot inventory, meta
  events.jsonl        append-only event stream (hooks, watches, memory, notes)
  snapshots/*.bin.z   zlib-compressed region captures with sha256
  blobs/*             QEMU logs, instruction/access traces, extra captures
  summary.md          rendered analysis

Rules that make a session usable as evidence:

  1. Record with a fixed stimulus. The same script, seed, budgets and image hash make runs comparable; a self-comparison must be empty.
  2. Annotate as you go. Explain inside the session what was asked and what was changed; a chat log is not evidence.
  3. Attach the provenance. Firmware SHA-256, version string, symbol DB source/hash/bias, and the exact command or script.
  4. Keep the directory together. session.json + events.jsonl + snapshots/ + blobs are one artifact; a copied event stream alone is not evidence.
  5. State the fidelity. Say which of L0/L1 was exercised and name the reference capture; do not silently waive L2/L3 gaps.
  6. Report deltas honestly. Every remaining delta between two runs is explained or listed as open; an empty unexplained-delta list is a claim that must be earned.
  7. Prefer an A/B pair. Static reading is a hypothesis; a recorded session is evidence; at least two comparable runs are a conclusion.

8. Safety and status

  • Simulator only. The tools launch their own QEMU or native machine against the bundled demo or an explicitly allowed re-hosted ELF; they never attach to hardware, a guest, a kernel module, an mdev or an existing debugger stub.
  • No guest, no hardware, no product. Nothing runs in a guest; injected services are prototypes, not shipped code; product changes go through the host module and a supervised physical confirmation.
  • Bounded everywhere. Runs have durations and stop caps; reads and snapshots have size caps; a wedged target is left stopped and restarted clean rather than poked.
  • Local only. The Ghidra bridge is a localhost transport, unauthenticated by design; never expose it on a network interface.
  • No confidentiality claims. The tool is a study environment; never use injection to defeat a hardware security boundary.
  • Status. The audited v0.1 surfaces are the CLI and the session format. Working and live-verified: hooks/watchpoints, memory tools, sessions, declarative probes, plugins, remote calls, run-to-cursor, the injection SDK, the Ghidra bridges, the first-fault probe and the instruction/access trace. The device model, the custom simulator and serving full host message traffic remain roadmap; porting and packaging scaffolds are pilot-status. Treat interface changes as reviewed events.

9. Related documentation