# risc-v-gsp-rm-debugger value-validation demos Runnable demonstrations that tie risc-v-gsp-rm-debugger tool capabilities to **real** Open-IOV scenarios (cited from `Handoff-vGPU-IO.md` and the project docs) and measure the time-to-value against the static/Ghidra-only baseline. Each demo: * names the real scenario (handoff PART/addendum + date) and what it cost; * prints the question, the risc-v-gsp-rm-debugger commands used, the answer, the evidence artifact and the elapsed wall-clock; * writes a machine-readable `result.json` under `artifacts//`; * labels what is **measured on the analog** vs **projected for the real case**; device-model-blocked scenarios say so explicitly. > risc-v-gsp-rm-debugger is development-only tooling (docs/00); these demos never touch > hardware, a guest or a kernel module. The real `.fwimage` cannot boot > without the H2 device model (docs/06 §3), so every demo is honest about > being a *shape* reproduction on the bundled `uproc_demo` firmware + native > RV64 simulator / QEMU. ## Run From the tool root (`open-iov/debug/risc-v-gsp-rm-vm`): ```bash make demo # once: build firmware/uproc_demo/build/uproc_demo.elf make sdk # optional (s06): builds sdk/build/injected_demo.elf python3 harness/value_demos/run_all.py # all 10, results JSON python3 harness/value_demos/run_all.py --only s01,s04,s05 # subset python3 harness/value_demos/s01_reply_consumer.py # one demo, verbose VALUE_DEMO_BACKEND=qemu python3 harness/value_demos/run_all.py # force QEMU ``` Defaults: native backend (deterministic, in-process) for s01–s08; QEMU for s09/s10 (with a native fallback if QEMU is absent). `VALUE_DEMO_BACKEND` overrides all of them. No hardware is required. The aggregate lands in `artifacts/results.json`; each demo writes under `artifacts//` (results, sessions, TSVs, reports). The runner enforces a per-demo timeout and the full suite runs in ~18 s on the reference host (budget: each demo < ~30 s, suite < ~3 min). ## Demos | # | Script | Real scenario (source, date) | Static/Ghidra-only baseline | Analog answer | |---|---|---|---|---| | s01 | `s01_reply_consumer.py` | 0x59 RM-init chase; fn72/fn73 hidden error (PART 91 + ADDENDA 2–7, 2026-10-01) | cycles 2–13, ~5 h, 10+ supervised boots; reply was a generic `0x59` | hook dispatcher + watch `result`: every command consumed and its exact reply decoded (1.14 s) | | s02 | `s02_counter_publication.py` | 20 GR per-channel counters; only 4/20 moved (PARTs 46–64, 2026-09-24…29) | ~5 days; slot layout re-derived per boot; ~2–3 s pin vs ~2 s deadline | 20/20 slots published, each store PC captured (1.34 s) | | s03 | `s03_unknown_command.py` | unknown/new control discovery; injected slots 16–23 (docs/19, 2026-10-02) | read the indirect dispatch table per stripped image | 24 IDs swept + classified: 6 known, 8 injected-slot, 10 default (5.96 s) | | s04 | `s04_run_until_function.py` | RM-client ladder reachability per rung (PART 91 ADDENDUM 9 cycles 18–25, 2026-10-01) | ~1 h 41 m / 8 supervised cycles | natural run / timeout / trigger / direct call in one session (0.24 s) | | s05 | `s05_snapshot_diff.py` | fn72 identity fix + 1656-B static-config reply (PART 91 ADDENDUM 6/7, 2026-10-01) | malformed field suspected statically; a live boot per fix iteration | every changed byte attributed to a named schema field (0.50 s) | | s06 | `s06_inject_service.py` | P6 service wiring / guest CE copies (PART 92 ADDENDA 5–11, 2026-10-02) | kernel rebuild + supervised cycle (~5–8 min) per rung | service blob loaded, registered, invoked both routes (0.63 s) | | s07 | `s07_version_diff.py` | 570.144 vs 570.211 pairing disproof; semantic diff (PART 91 cycles 2–3, 2026-10-01) | one full boot per version + manual log compare | same stimulus on two builds; exactly one reply field moved (1.14 s) | | s08 | `s08_mutation_triage.py` | error-path corpus / fail-closed rules (R5; docs/19 §3.4, docs/18 §2) | hand-derived asserts and NOCAT records across cycles | 7 seeded mutations classified ok/fault/no-progress (1.82 s) | | s09 | `s09_grabbing_a_ghidra_address.py` | static/dynamic join; GPFIFO GET fault `0x40000` vs `0x101000` (PART 91 ADDENDUM 9 cycle 24) | hypothesis unproven until the decoded status-queue fault (8 cycles) | Ghidra addr + bias = runtime; hook hit + `greeneye_hits.tsv` (0.72 s) | | s10 | `s10_full_session_evidence.py` | evidence pack for a milestone (docs/14 §6; cycles 11–13, 2026-10-01) | hashes/sessions/logs/compare gathered by hand per cycle | one run → analyze + compare + hits + manifest + M1–M6 (4.92 s) | Times are the measured risc-v-gsp-rm-debugger path on the reference host (native for s01–s08, QEMU for s09/s10); see `artifacts/results.json` for a fresh run. ## Projected vs measured * **Measured:** every analog result, elapsed time, session size, trace slowdown and slot/reply count in `result.json`. * **Projected (labelled `projected` in each result):** the real-case time saving. No demo claims a real-GSP result the simulator cannot reach. * **Blocked (`blocked_on_device_model: true`):** all real-firmware claims wait on the H2.2 device model; the workflow is demonstrated on the analog. ## Tests ```bash python3 -m unittest tests.test_value_demos -v # 5 tests, ~5 s ``` The suite runs the fastest demos end-to-end as subprocesses, asserts their answers and checks `run_all.py` emits `artifacts/results.json`. It skips cleanly when QEMU or the demo firmware is absent. See [`docs/25-VALUE-VALIDATION.md`](../../docs/25-VALUE-VALIDATION.md) for the methodology, overhead analysis and scenario representativeness argument.