# risc-v-gsp-rm-debugger User Guide (experimental) > Status: implemented, documented and tested (audit: [docs/27](../../debug/risc-v-gsp-rm-vm/docs/27-TOOL-AUDIT.md); value demos: [docs/25](../../debug/risc-v-gsp-rm-vm/docs/25-VALUE-VALIDATION.md)). > risc-v-gsp-rm-debugger is the development environment for running GSP/uproc firmware > off-hardware, observing it, injecting into it and comparing runs as evidence. > It is never shipped, never a driver dependency and never present in a guest; > interfaces and file formats may change without notice. For incident response > procedures see the [Open-IOV Defensive Operations Runbook](../RUNBOOK.md). This guide is the single front door for a new user: what risc-v-gsp-rm-debugger is, how to get a first recorded run in ten minutes, which tool to use for which task, how to treat sessions as evidence, and what to do when something is wrong. The authoritative details live in the tool's own documentation set ([documentation map](#10-documentation-map)). ## 1. What risc-v-gsp-rm-debugger is risc-v-gsp-rm-debugger runs GSP/uproc firmware in a controllable machine, instruments it with Frida-like primitives, records a durable session, changes the machine's inputs (including injected code), and compares runs so that emulation changes in `vgsp` land with evidence instead of anecdotes. | It is | It is not | |---|---| | A firmware runtime microscope (execution + memory: L0/L1) | A timing, interrupt or device model (L2/L3 absent) | | A scriptable `Session` API with two backends (QEMU-RSP and native) | A GDB wrapper; there is no GDB dependency | | A recorded-evidence system with a versioned session format | A product component, a guest agent or a shipped dependency | | A static/dynamic join for Ghidra | A decompiler or a CUDA-corpus replacement | | An automation layer (harnesses, MCP, CI) | A fuzzing service against hardware; simulator/re-hosted code only | Ghidra answers *what is the code*; risc-v-gsp-rm-debugger answers *what did it do*. Guest diagnostics answer *what did the driver request*; a supervised physical cycle answers *what does silicon do*. risc-v-gsp-rm-debugger makes the middle question repeatable and safe. ## 2. Ten-minute quickstart Requirements: Linux, Python 3.10+ (stdlib only), `qemu-system-riscv64` (Ubuntu `qemu-system-misc`), `clang` and `lld`. No GPU, no driver and no kernel module are touched. ```bash cd open-iov/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 injection SDK ./risc-v-gsp-rm-debugger.sh demo # canned run: boot, hooks, watchpoints, session ./risc-v-gsp-rm-debugger.sh analyze dumps/ ./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: 1. `info` reports QEMU and the demo paths; 2. `demo` prints hook/branch lines and a session directory under `dumps/`; 3. `analyze` renders hook/watch/breakpoint events and a coherent summary; 4. `probe` reports a bounded first divergence (for the TU104 570.144 image, a load-access fault at firmware vaddr `0x4009014` reading `0x2000000000000A00`) — that is expected data, not a boot; 5. `inject` returns matching values on the direct and firmware-dispatched paths. Next steps: [choose a tool](#5-choosing-the-right-tool) for your task and read [Common recipes](#7-common-recipes). ## 3. Mental model ### 3.1 Two backends, one session API ```text CLI / REPL / Python ─┐ MCP (stdio) ────────┼─► GreenEyeAPI ─► Session ─┬─► QEMU-RSP backend (qemu-system-riscv64) Ghidra bridge ──────┤ hooks, watchpoints, └─► native backend (sim/machine.py) harness/ + rmharness┘ memory, symbols, recorder ──► session directory ``` * **QEMU-RSP** is the default: full RV64 execution, gdbstub transport without GDB, TCG trace plugin optional. * **native** (`--backend native`) is the in-process interpreter: deterministic virtual time (instruction counts), fast startup, an exec/access trace, and lenient MMIO for first-touch exploration. * Both satisfy the same `Session` primitives (registers/memory, breakpoints, watchpoints, step/continue, snapshots), so scripts, probes, plugins, recordings and comparisons survive a backend change. ### 3.2 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, from which store PC? | | `run` / `run_until` | bounded observation; stop at a chosen address | | `call` | Frida-like 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 PIC RV64 service | Instructions between stops are invisible unless a trace is on: the TCG plugin (`-plugin qemu/greeneye-trace.so`) on QEMU, or `--trace` on the native backend. ### 3.3 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** (do not 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; anything that would change the product is reproduced on a physical/vfio-mdev reference first. Never quote a risc-v-gsp-rm-debugger session for timing, interrupt or security claims. ### 3.4 A session is the unit of work Every run records a `greeneye-session/1` directory: ```text dumps/--/ 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, trace.jsonl, host-oracle stdout summary.md rendered analysis ``` Partial sessions stay readable; the format evolves additively. A copied `events.jsonl` without its `session.json`, snapshots and metadata is not evidence. ## 4. Tool inventory Run everything from `open-iov/debug/risc-v-gsp-rm-vm/` unless stated. ### 4.1 CLI (`./risc-v-gsp-rm-debugger.sh`) | Command | One-line purpose | |---|---| | `info` | environment/tooling check (QEMU, paths, capabilities) | | `demo` | canned boot + hooks + watchpoints + recording on the bundled uproc | | `run ` | run a Python instrumentation session against the demo/ELF | | `attach` / `launch` | interactive REPL; keep a target alive and print its gdbstub port | | `record` | boot and record with watches/snapshots (and `--trace` on native) | | `probe ` | bounded run of a raw image; first-divergence report | | `analyze ` | session to symbol-annotated Markdown report | | `compare ` | symbolic A/B delta of two recorded sessions | | `symbols export\|resolve` | build/inspect a runtime-address symbol DB | | `inject` | load, register and invoke an SDK service (direct + mailbox) | | `ghidra` | serve the live session to GhidraScripts over localhost | | `plugins` | list discoverable plugins | ### 4.2 Harnesses (`harness/`) | Tool | One-line purpose | |---|---| | `portability_matrix.py` | probe + fixed scenario + compare across targets, with an M1–M6 skeleton | | `mutation_harness.py` | seeded one-input mutations with outcome classes and per-attempt sessions | | `control_discovery.py` | sweep a call surface to find known/unknown/injected handler IDs | | `reach.py` | is one symbol reachable, what triggers it, with what arguments and effects | | `version_diff.py` | old vs new image: shape, symbols, corpus hints, probe, behavior | | `ci_release.py` | version_diff → matrix → mutation smoke, hashed into one bundle | | `port_driver_versions.py`, `port_new_device.py`, `package_sim.py` | porting/packaging scaffolds (dry-run default; pilot status and evaluation in [docs/28](../../debug/risc-v-gsp-rm-vm/docs/28-PORTING-AUTOMATION.md), [docs/29](../../debug/risc-v-gsp-rm-vm/docs/29-PACKAGING-AND-TRIALING.md)) | | `value_demos/run_all.py` | ten fixed scenarios s01–s10 with measured time-to-value | | `rm_capture.py` | real-client GSP RPC capture: decode, compare, replay prep ([docs/45](../../debug/risc-v-gsp-rm-vm/docs/45-RM-RPC-CAPTURE-AND-REPLAY.md)) | | `rehost.py` | run one bounded firmware function with crafted state and before/after snapshots ([docs/46](../../debug/risc-v-gsp-rm-vm/docs/46-SURGICAL-REHOST.md)) | | `valprobe.py` | run one firmware validation branch with crafted state and labelled outcome addresses (offline predicate probe; [docs/47](../../debug/risc-v-gsp-rm-vm/docs/47-VALIDATION-PREDICATE-PROBE.md)) | | `launch_audit.py` | audit a submission's engine-visible memory contract against captured page tables: `ok`/`pa_mismatch`/`unmapped`/`access_denied` per leg ([docs/48](../../debug/risc-v-gsp-rm-vm/docs/48-GMMU-WALK-AND-LAUNCH-AUDIT.md)) | | `common.py` | shared helpers (flat relocation, sessions, bounded log reads) | ### 4.3 Native simulator, plugins, host oracle, bridges | Tool | One-line purpose | |---|---| | `sim/` (`--backend native`, `--trace`) | deterministic RV64IMAC interpreter with exec/access trace and lenient MMIO | | `sim/gmmu_walk.py` | functional GMMU page-table walker over captured/constructed tables (VER2 4K/2M validated; 64K modelled) | | `python3 -m greeneye.device_map harvest\|show\|merge\|demo` | first-touch MMIO map: authoring, inspection, merge | | `qemu/greeneye_trace.c` (`make -C qemu`) | full TCG exec/access JSONL trace with `start=`/`end=` filters | | `plugins/example_plugin.py` | plugin authoring reference | | `plugins/mcp_server.py` | MCP server for agents (stdio or loopback; read-only by default) | | `plugins/rmharness_plugin.py` | REPL commands for the host RM oracle | | `rmharness/harness.sh` + `rmtool`/`rmtop`/`rmq` | read-only host oracle captures appended into a session | | `ghidra/ExportForGreenEye.java`, `MarkGreenEyeHits.java`, `GreenEyeControl.java` | symbol export, hit annotation and decompiler-driven execution | | `sdk/` + `./risc-v-gsp-rm-debugger.sh inject` | position-independent service ABI v1 | ## 5. Choosing the right tool | Task | Tool | Notes | |---|---|---| | "Does this run?" / first divergence of a raw image | `./risc-v-gsp-rm-debugger.sh probe` | no device model: expected early fault is data | | "What does this firmware do on this stimulus?" | `record` / `run` + `analyze` | fixed stimulus, bounded budgets, hooks/watchpoints | | "Which command IDs exist / what is undiscovered?" | `harness/control_discovery.py` | fresh session per probe; deterministic seed | | "Is this function reachable, and how?" | `harness/reach.py` | `auto|stimulus|trigger|run|call`; emits a replayable probe spec | | "What changed between two firmware versions?" | `harness/version_diff.py`, `./risc-v-gsp-rm-debugger.sh compare` | static inventory + dynamic profile | | "Does the new firmware move behaviour or code?" | `harness/version_diff.py` + docs/14 decision table | code vs behaviour classification | | "Prove an error path / fail-closed rule" | `harness/mutation_harness.py` | simulator only; seeded and replayable | | "Prototype an RM service before product code" | `sdk/` + `./risc-v-gsp-rm-debugger.sh inject` | PIC blob; direct and mailbox paths | | "Join Ghidra static addresses to runtime hits" | `./risc-v-gsp-rm-debugger.sh ghidra` + Java bridges | localhost only; no auth | | "What does a control reply look like on real RM?" | `rmharness/harness.sh … rmtool` | read-only host oracle; safe beside a CUDA job | | "Explore MMIO the firmware touches first" | `probe` → `python3 -m greeneye.device_map` | versioned JSON; feeds the device model | | "Triage a release end to end" | `harness/ci_release.py` | always `--dry-run` first | | "Let an agent monitor a run" | `plugins/mcp_server.py` | read/observe by default; writes gated | | **"Which control/entry shape does the firmware accept, and why?"** | `harness/valprobe.py` | offline predicate branch with crafted state + labelled outcomes; deterministic, seconds; [docs/47](../../debug/risc-v-gsp-rm-vm/docs/47-VALIDATION-PREDICATE-PROBE.md) | | **"A handler/function early-outs on state we don't have"** | `harness/rehost.py` | bounded call with crafted state; the first missing state is the finding; [docs/46](../../debug/risc-v-gsp-rm-vm/docs/46-SURGICAL-REHOST.md) | | "Decode/compare the real client's GSP RPCs" | `harness/rm_capture.py` | offline decode/stimulus; consumption awaits the message-injection rung; [docs/45](../../debug/risc-v-gsp-rm-vm/docs/45-RM-RPC-CAPTURE-AND-REPLAY.md) | | **"Where would the engine read/write this VA?"** | `sim/gmmu_walk.py`, `harness/launch_audit.py` | walk captured/constructed page tables offline; per-leg `ok`/`pa_mismatch`/`unmapped`/`access_denied`; [docs/48](../../debug/risc-v-gsp-rm-vm/docs/48-GMMU-WALK-AND-LAUNCH-AUDIT.md) | Decision rule: static reading is a hypothesis; a recorded session is evidence; at least an A/B pair is a conclusion. If the question is "what will this firmware branch do with input/state X?", probe it offline first (`valprobe`/`rehost`, seconds, deterministic) and spend supervised cycles only on what the probe cannot see (engine/silicon behaviour); if it is "what does the silicon do?" or "does the run survive?", it is a hardware question and the simulator makes no L2/L3 claims. ## 6. Sessions 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.** `s.note(...)` inside the session explains what was asked and what was mutated; a chat log is not evidence. 3. **Attach the provenance.** Firmware SHA-256, version string, pairing notes, 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; publish a SHA-256 list when moving it. 5. **State the fidelity.** L0/L1 exercised; L2/L3 not claimed; reference capture named (hardware, vfio-mdev, host oracle or none). 6. **Report deltas honestly.** `compare` marks non-semantic fields (time, host paths, backend identity) as such; every remaining delta is explained or listed as open. An empty unexplained-delta list is a claim that must be earned. 7. **Bundle for triage.** A release bundle is `bundle-manifest.json` + `release-report.json` + version-diff + portability matrix + mutation smoke; see [docs/21](../../debug/risc-v-gsp-rm-vm/docs/21-CI-RELEASE-PIPELINE.md) §4.3. The M1–M6 metric contract (inventory, reply, ordering, state, error-path and memory-side-effect agreement) is defined in [docs/06-ACCURACY](../../debug/risc-v-gsp-rm-vm/docs/06-ACCURACY.md) §5 and is authoritative for every claim. ## 7. Common recipes ### 7.1 First record and analyze ```bash cd debug/risc-v-gsp-rm-vm make demo ./risc-v-gsp-rm-debugger.sh demo # prints the session directory ./risc-v-gsp-rm-debugger.sh analyze dumps/ # symbol-annotated report ``` ### 7.2 Probe a new firmware image ```bash ./risc-v-gsp-rm-debugger.sh symbols export --index --bias 0 -o symbols-.json ./risc-v-gsp-rm-debugger.sh probe .fwimage.bin> --symbols symbols-.json --record python3 harness/version_diff.py --old --new --out dumps/vdiff- \ --old-symbols symbols-.json --new-symbols symbols-.json ``` ### 7.3 Discover controls and prove reachability ```bash python3 harness/control_discovery.py --out dumps/discovery --max-id 32 \ --patterns zero --seed 5 python3 harness/reach.py --target rpc_ping --method call --args 0x41 \ --out dumps/reach-ping ``` ### 7.4 Mutate an input surface (simulator only) ```bash python3 harness/mutation_harness.py --out dumps/mutation-7 \ --iterations 64 --seed 7 --timeout 0.25 --settle 0.2 ``` ### 7.5 Portability pipeline across targets ```bash python3 harness/portability_matrix.py \ --target --target \ --out dumps/matrix-candidate --probe-instructions 200 --scenario-duration 0.2 ``` ### 7.6 Inject and debug a service ```bash make -C sdk make -C sdk relocs ./risc-v-gsp-rm-debugger.sh inject --service sdk/build/injected_demo.elf --cmd 1 --arg0 0x41 --arg1 0x42 ``` The direct call is the unit test; the mailbox call is the integration test. Both are recorded. ### 7.7 Drive execution from Ghidra ```bash # terminal 1 ./risc-v-gsp-rm-debugger.sh ghidra --kernel --bridge-port 7000 # terminal 2 (Ghidra headless) $GHIDRA/support/analyzeHeadless -process -noanalysis \ -scriptPath open-iov/debug/risc-v-gsp-rm-vm/ghidra \ -postScript GreenEyeControl.java 7000 0x
``` ### 7.8 Host oracle capture (read-only) ```bash ./rmharness/harness.sh --session dumps/real- --name before \ -- rmtool engine list --format=json ./rmharness/harness.sh --session dumps/real- -- rmtop --once ``` ### 7.9 Release rehearsal ```bash python3 harness/ci_release.py --old --new --out dumps/release- \ --old-label --new-label --dry-run ``` `--dry-run` prints the plan and creates nothing; the RM 610 gate refuses 610 labels (exit 3) until a human approves in writing. ### 7.10 Let an agent monitor ```bash python3 plugins/mcp_server.py --stdio --backend native --record # read/observe by default; --allow-write and --allow-inject are explicit opt-ins ``` ### 7.11 First-touch device map ```bash ./risc-v-gsp-rm-debugger.sh probe --record python3 -m greeneye.device_map harvest dumps/ --out dumps/-device-map.json python3 -m greeneye.device_map show dumps/-device-map.json ``` ## 8. Troubleshooting | Symptom | Likely cause | Fix | |---|---|---| | `qemu-system-riscv64 not found` | QEMU absent or not on `PATH` | install `qemu-system-misc` or point `GREENEYE_QEMU` at the binary | | QEMU starts but the script cannot attach | wrong port / target exited | use the port `launch`/`demo` printed; re-run `launch` and `attach --port ` | | `Address already in use` on a bridge/trace port | stale bridge or another session | choose another `--bridge-port`; check `pgrep -fa greeneye` and `pgrep -fa qemu-system-riscv64` | | QEMU survives Ctrl-C of a script | `launch` keeps the target alive by design | close the session or stop the reported PID; do not kill an unrelated QEMU | | Session analyzer shows no hits/events | recording off, or the stimulus never ran | use the CLI (records by default); check hooks/watchpoints with a known symbol (`rpc_sum`) | | `NameError: __file__` in `run` scripts | script invoked outside `risc-v-gsp-rm-debugger.sh run` | run through `./risc-v-gsp-rm-debugger.sh run`, keep scripts inside the tool tree | | Empty TCG trace blob | plugin window missed or target never resumed | `make -C qemu`; widen `start=`/`end=`, set `exec=on`, resume the target | | MCP writes refused / no tools | server read-only by default; stdout polluted | pass `--allow-write`/`--allow-inject` deliberately; keep stdout protocol-only | | `risc-v-gsp-rm-debugger error:` on a valid path | wrong relative path or `--db` file | `./risc-v-gsp-rm-debugger.sh info` shows resolved paths; bad symbol DBs fail with a clear error | | Harness findings not reproducible | seed/budget changed | pin `--seed` and budgets; compare `findings.jsonl` byte-for-byte | | Everything "unreachable" | wrong surface/timeouts | run `--surface demo` on the built demo first; raise `--settle`/`--timeout` | | `Unknown symbol` in the optional OpenRM build | module-tag drift | re-pin build glue; see the [RUNBOOK](../RUNBOOK.md) S2 | Marker status: the in-development notices were removed on 2026-10-02 after the tool audit ([docs/27](../../debug/risc-v-gsp-rm-vm/docs/27-TOOL-AUDIT.md)), the 194-test green suite, and the end-to-end s01–s10 value demonstrations ([docs/25](../../debug/risc-v-gsp-rm-vm/docs/25-VALUE-VALIDATION.md)). Open items stay listed honestly: docs 28/29 are unadmitted pilots and the device model/custom simulator M2+ remain roadmap. The session format and CLI are the audited v0.1 surfaces; treat changes to them as reviewed events. ## 9. Safety * **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 gdbstub. * **No guest, no hardware, no product.** Nothing runs in a guest; injected services are prototypes, not shipped code; product changes go through `vgsp` with physical confirmation. * **Read by default; writes gated.** MCP `write_mem`/`call_function` need `--allow-write`, injection needs `--allow-inject`, and every write is recorded in the session. * **Bounded everywhere.** Runs have durations/stop caps; reads and snapshots have size caps; harness subprocesses have timeouts; a wedged target is left stopped and restarted clean rather than poked. * **Local only.** Ghidra and MCP transports are localhost/stdio; the bridge is unauthenticated by design, so never expose it on a network interface. * **No confidentiality claims.** The simulator is a study environment, never a security or confidentiality boundary; never use injection to defeat a hardware security boundary. * **Fuzzing is gated.** Mutation runs only against the simulator or re-hosted code, behind explicit harnesses, with recorded evidence. * **RM 610 is a hard human gate.** No acquisition, analysis, emulation edit, physical work or support claim before written approval; the gate is enforced by the CLIs. ## 10. Documentation map Tool documentation (`debug/risc-v-gsp-rm-vm/docs/`): [00 overview](../../debug/risc-v-gsp-rm-vm/docs/00-OVERVIEW.md), [01 design](../../debug/risc-v-gsp-rm-vm/docs/01-DESIGN.md), [02 usage](../../debug/risc-v-gsp-rm-vm/docs/02-USAGE.md), [03 scripting](../../debug/risc-v-gsp-rm-vm/docs/03-SCRIPTING.md), [04 plugins](../../debug/risc-v-gsp-rm-vm/docs/04-PLUGINS.md), [05 Ghidra bridge](../../debug/risc-v-gsp-rm-vm/docs/05-GHIDRA-BRIDGE.md), [06 accuracy](../../debug/risc-v-gsp-rm-vm/docs/06-ACCURACY.md), [07 portability playbooks](../../debug/risc-v-gsp-rm-vm/docs/07-PORTABILITY-PLAYBOOKS.md), [08 roadmap](../../debug/risc-v-gsp-rm-vm/docs/08-ROADMAP.md), [09 firmware notes](../../debug/risc-v-gsp-rm-vm/docs/09-GSP-FIRMWARE-NOTES.md), [10 related work](../../debug/risc-v-gsp-rm-vm/docs/10-RELATED-WORK.md), [11 RM service guide](../../debug/risc-v-gsp-rm-vm/docs/11-GSP-RM-SERVICE-DEVELOPER-GUIDE.md), [12 injection SDK](../../debug/risc-v-gsp-rm-vm/docs/12-INJECTION-SDK.md), [13 Ghidra control](../../debug/risc-v-gsp-rm-vm/docs/13-GHIDRA-CONTROL.md), [14 adversarial interop](../../debug/risc-v-gsp-rm-vm/docs/14-ADVERSARIAL-INTEROP-GUIDE.md), [15 agentic GSP IDE](../../debug/risc-v-gsp-rm-vm/docs/15-AGENTIC-GSP-IDE.md), [16 custom simulator](../../debug/risc-v-gsp-rm-vm/docs/16-CUSTOM-SIMULATOR.md), [17 RM harness](../../debug/risc-v-gsp-rm-vm/docs/17-RM-HARNESS.md), [18 harness automation](../../debug/risc-v-gsp-rm-vm/docs/18-HARNESS-AUTOMATION.md), [19 control discovery](../../debug/risc-v-gsp-rm-vm/docs/19-CONTROL-DISCOVERY.md), [20 MCP server](../../debug/risc-v-gsp-rm-vm/docs/20-MCP-SERVER.md), [21 CI/release pipeline](../../debug/risc-v-gsp-rm-vm/docs/21-CI-RELEASE-PIPELINE.md), [22 porting CUDA and devices](../../debug/risc-v-gsp-rm-vm/docs/22-PORTING-CUDA-AND-DEVICES.md), [23 RM 610 readiness](../../debug/risc-v-gsp-rm-vm/docs/23-RM610-READINESS.md), [24 device map](../../debug/risc-v-gsp-rm-vm/docs/24-DEVICE-MAP.md), [25 value validation](../../debug/risc-v-gsp-rm-vm/docs/25-VALUE-VALIDATION.md), [26 architecture](../../debug/risc-v-gsp-rm-vm/docs/26-ARCHITECTURE.md), [27 tool audit](../../debug/risc-v-gsp-rm-vm/docs/27-TOOL-AUDIT.md), [28 porting automation](../../debug/risc-v-gsp-rm-vm/docs/28-PORTING-AUTOMATION.md), [29 packaging and trialing](../../debug/risc-v-gsp-rm-vm/docs/29-PACKAGING-AND-TRIALING.md), and the [long-term roadmap](../../debug/risc-v-gsp-rm-vm/RISC-V-GSP-RM-DEBUGGER-ROADMAP.md). Project documentation: * [Open-IOV Defensive Operations Runbook](../RUNBOOK.md) — incident scenarios S1–S10, evidence bundles, escalation tree; * [GSP in a RISC-V VM](03-risc-v-gsp-rm-vm.md) — project-level purpose, status and limits; * [Debugging and maintenance workflows](02-debugging-and-maintenance-workflows.md) — captures, failure taxonomy and the upgrade runbook; * [Hardware and software matrix](../06-portability/hardware-software-matrix.md) — support ladder and the portability pipeline; * [Adversarial interoperability](../04-implementation/02-practical-challenges-and-adversarial-interop.md) — the no-patch rule; * [Engineering operations](../eng-ops.md) — tool admission, workflows and retirement (the cross-cutting engineering-operations document); * CUDA playbook: [`userspace/cuda/docs/07-version-upgrade-playbook.md`](../../userspace/cuda/docs/07-version-upgrade-playbook.md) and [`userspace/cuda/READ-ME-FIRST.md`](../../userspace/cuda/READ-ME-FIRST.md); * [Documentation front door](../README.md) — the full reading order.