summaryrefslogtreecommitdiffstats
path: root/docs/07-developers
diff options
context:
space:
mode:
Diffstat (limited to 'docs/07-developers')
-rw-r--r--docs/07-developers/02-development-and-analysis-environment.md363
1 files changed, 363 insertions, 0 deletions
diff --git a/docs/07-developers/02-development-and-analysis-environment.md b/docs/07-developers/02-development-and-analysis-environment.md
new file mode 100644
index 0000000..370cefc
--- /dev/null
+++ b/docs/07-developers/02-development-and-analysis-environment.md
@@ -0,0 +1,363 @@
+# Development and analysis environment: Ghidra, green-eye and the Open-IOV toolchain
+
+> The single front door to the environment an Open-IOV developer works in:
+> the host stack, the guest diagnostics, the CUDA userspace and GSP firmware
+> Ghidra corpora, the host RM tooling, green-eye, CI and MCP. Each component
+> links to the document that specifies it; this page is the map, not a
+> duplicate of the manuals.
+
+## 1. Scope and benefit
+
+Open-IOV spans a host kernel module, a QEMU/KVM guest stack, a CUDA userspace
+binary, GSP firmware, a host resource manager and a growing analysis toolchain.
+The pieces were built by different workstreams and each has its own manual; the
+cost of a new contributor (or a returning one) has been re-learning where to
+start for a given question. This document exists to remove that cost: it is the
+**one map** of the environment — what every tool is for, when to use it, where
+it lives, and which document explains it — plus the two reverse-engineering
+loops that tie static and dynamic analysis together.
+
+In scope: the developer-facing analysis environment. Out of scope: end-user
+installation (see [`02-getting-started/01-install-and-first-run.md`](../02-getting-started/01-install-and-first-run.md)),
+the emulation architecture itself (see
+[`03-architecture/01-system-overview.md`](../03-architecture/01-system-overview.md))
+and product roadmaps. The green-eye toolchain is **in development and not
+ready yet** — status, limits and flag-removal criteria are in
+[`05-operations/03-risc-v-gsp-rm-vm.md`](../05-operations/03-risc-v-gsp-rm-vm.md)
+and the tool's own
+[`docs/00-OVERVIEW.md`](../../debug/risc-v-gsp-rm-vm/docs/00-OVERVIEW.md).
+
+## 2. The environment at a glance
+
+```mermaid
+flowchart TB
+ subgraph HOST["Lab host - x86_64 or aarch64"]
+ SM["scripts/stack_manager.sh<br/>build / load / status / test / unload"]
+ MOD["open-iov-vfio.ko<br/>virtual device + GSP-RM emulation + backend"]
+ QEMU["QEMU / KVM<br/>scripts/vgpu_vm.py, launch_qemu_*.sh"]
+ VFIO["VFIO mdev + IOMMU isolation"]
+ RMTOOLS["tools/rmtool, rmtop, rmq<br/>read-only host RM oracle"]
+ subgraph GUEST["Guest VM - stock driver, no Open-IOV code"]
+ WORK["CUDA workload + tools/cuda-ab"]
+ GDIAG["tools/guest-diag<br/>ioctl tracer, engines, pmap, probes"]
+ end
+ subgraph STATIC["Static analysis"]
+ GHFW["tools/ghidra + firmware/57X-GSP/&lt;ver&gt;<br/>GSP firmware Ghidra projects"]
+ GHCUDA["userspace/cuda Ghidra corpus<br/>+ analysis tools"]
+ end
+ subgraph DYN["Dynamic firmware analysis - green-eye"]
+ GE["Session: hooks, watchpoints, memory,<br/>call, run_until, record"]
+ GEB["Backends: QEMU-RSP + native RV64IMAC"]
+ GEH["harness/, injection SDK,<br/>Ghidra bridges, device maps"]
+ RMH["rmharness host captures"]
+ end
+ subgraph AUTO["Automation"]
+ CI[".github/workflows/ci.yml<br/>.github/workflows/greeneye.yml"]
+ MCP["plugins/mcp_server.py<br/>agent tool surface"]
+ end
+ end
+ SM --> MOD --> QEMU --> VFIO --> GUEST
+ MOD --> RMTOOLS
+ WORK --> GDIAG
+ RMTOOLS --> RMH
+ GHFW --> GE
+ GHCUDA --> GE
+ GE --> RMH
+ GE --> CI
+ GE --> MCP
+ GE -->|"export_hits + symbol DB"| GHFW
+ GHFW -->|"names + addresses"| GE
+```
+
+| Layer | What it answers | Entry point |
+|---|---|---|
+| Host stack | does the device load, boot and serve the guest? | `scripts/stack_manager.sh`, `scripts/vgpu_vm.py` |
+| Guest diagnostics | what did the stock driver request and receive? | `tools/guest-diag/` |
+| CUDA static corpus | what is `libcuda` doing, and what changed? | `userspace/cuda/READ-ME-FIRST.md` |
+| GSP firmware static | what does the firmware image contain? | `tools/ghidra/`, `firmware/57X-GSP/<ver>/` |
+| Host RM oracle | what does real RM report on this GPU? | `tools/rmtool`, `tools/rmtop`, `rmharness/` |
+| Dynamic firmware | what did the firmware server actually do? | `debug/risc-v-gsp-rm-vm/greeneye.sh` |
+| CI / agent | did the broad suite pass; can an agent drive it? | `.github/workflows/`, `plugins/mcp_server.py` |
+
+## 3. Host stack: KVM, QEMU, VFIO and the module
+
+The reference path is KVM + QEMU with the VFIO mdev transport. `open-iov-vfio.ko`
+emulates the device interface and GSP-RM behaviour (or drives the physical
+backend, per the chosen execution mode); the guest runs stock drivers only.
+
+```bash
+./install.sh deps nvidia firmware build # full host setup (stages selectable)
+make kernel # or: ./scripts/stack_manager.sh build-kernel
+./scripts/stack_manager.sh load-open-iov # load open-iov-vfio.ko
+./scripts/stack_manager.sh mdev-create # create the mediated device
+./scripts/vgpu_vm.py start vgpu-linux # guest lifecycle + guest-agent exec/shell
+./scripts/stack_manager.sh test # host test suite
+./scripts/stack_manager.sh dmesg # live filtered trace
+```
+
+Module load order matters on the optional OpenRM path: build `kernel/` first
+(it generates `kernel/Module.symvers`), then build the OpenRM modules with
+`KBUILD_EXTRA_SYMBOLS`, then load Open-IOV, then OpenRM, then firmware. On a
+typical single-GPU developer host the distribution driver owns the GPU and the
+emulated QEMU path runs without the OpenRM modules. The full contract is
+[`03-architecture/06-host-module-and-hybrid-model.md` §7](../03-architecture/06-host-module-and-hybrid-model.md).
+
+Guest virtual-memory inspection uses the QEMU gdbstub
+(`scripts/qemu_gdb_attach.sh`, `-gdb tcp::1234`); host-side guest-RAM scans and
+pokes use the module debug parameters (`scan_guest_ram`, `scan_seq`,
+`poke_guest`) documented in
+[`05-operations/02-debugging-and-maintenance-workflows.md`](../05-operations/02-debugging-and-maintenance-workflows.md) §3.1–3.3.
+VM access from tooling goes through `scripts/vgpu_vm.py`; scripts never reboot
+or change system state without explicit operator action (project hard rule).
+
+## 4. Guest diagnostics
+
+The stock guest driver is the best oracle for driver-side behaviour. These
+tools read it out without modifying it:
+
+| Tool | Purpose | Location |
+|---|---|---|
+| `ioctl_trace.c` | ptrace-based syscall/ioctl tracer (`LD_PRELOAD` cannot see `libcuda`'s raw syscalls) | `tools/guest-diag/ioctl_trace.c` |
+| `guest_engines.c` | guest engine/class inventory, virtualization mode, CE caps | `tools/guest-diag/guest_engines.c` |
+| `guest_pmap*.py`, `pmap_va.sh` | guest page-map walks (Linux and Windows samples) | `tools/guest-diag/` |
+| `push_guest_tools.sh` | stage diagnostics into the guest | `tools/guest-diag/push_guest_tools.sh` |
+| UVM debug prints | `echo 1 > /sys/module/nvidia_uvm/parameters/uvm_debug_prints` | guest sysfs |
+
+Standard captures for a bug report (host log, status, guest dmesg, `lspci -vvv`,
+`nvidia-smi -q`) are listed in
+[`05-operations/02` §2](../05-operations/02-debugging-and-maintenance-workflows.md).
+
+## 5. CUDA userspace: the Ghidra corpus and its tools
+
+`userspace/cuda/` holds the decompiled corpus and name map for the guest
+`libcuda` (570.144) plus reusable tooling. Start at
+[`userspace/cuda/READ-ME-FIRST.md`](../../userspace/cuda/READ-ME-FIRST.md); the
+five core documents are `docs/01-architecture.md` through
+`docs/05-570.144-decompilation.md`, with
+`docs/07-version-upgrade-playbook.md` for version bumps and
+`docs/06-tooling.md` for recipes.
+
+**Address convention (the one rule that bites):** public offsets are file
+virtual addresses (`libcuda+0x...`); Ghidra loads the library at image base
+`0x100000`, so decompilations produced without translation point 0x100000 too
+low. Current tooling translates; re-derive old conclusions
+([`docs/05` §1.1](../../userspace/cuda/docs/05-570.144-decompilation.md)).
+
+| Tool | Purpose |
+|---|---|
+| `tools/cudatool.py` | exports/FDEs/wrappers, `info`, `nearest`, `crash`, `delta`, `fdematch` |
+| `tools/callwalk.py` | callers/callees/chains over `callgraph.tsv` |
+| `tools/diff_corpus.py` | corpus diff across driver versions (match discipline reused by green-eye version diffs) |
+| `tools/name_candidates.py`, `subsystem_digest.py` | name candidates and per-subsystem call-tree digests |
+| `tools/ghidra_*.sh`, `tools/ghidra/` | headless analysis, decompile-at, index/name-map export, merge |
+| `tools/annotate_corpus.py` | apply the name map to the corpus |
+| `570.144/annotations/names.tsv`, `subsystems.tsv` | tracked name map (659 exports, verified internals) and subsystem index |
+| `tools/cuda-ab/ab.sh` + `vector_add.cu` | host-vs-guest A/B workload; `RESULT`/`STATUS` lines must match |
+| `tools/test/cuda_drv_test.c` | driver-API smoke test (prints `ALL OK`) |
+
+## 6. GSP firmware: Ghidra projects and images
+
+Firmware images are versioned and never overwritten:
+`firmware/<SERIES>-GSP/<VER>/gsp-<VER>.fwimage.bin` (currently 570.144). The
+firmware analysis pipeline is driven from `tools/ghidra/`:
+
+| Tool / artifact | Purpose |
+|---|---|
+| `tools/ghidra/analyze_fwimage.py` | headless project creation + analysis for a `.fwimage` |
+| `tools/ghidra/create_gsp_project.py` | build the GSP Ghidra project layout |
+| `tools/ghidra/diff_gsp_firmware.py`, `analyze_gsp_firmware.sh` | cross-version firmware diff / batch analysis |
+| `firmware/57X-GSP/570.144/analyze_firmware.py` | version-local extraction and reporting scripts |
+| `firmware/57X-GSP/570.144/decompiled*`, `RPC_HANDLER_MAP.md`, `FINAL_REPORT.md` | per-version decompiled handlers and maps |
+| `kernel/firmware_analyzer.c` (`known_signatures[]`) | runtime firmware identification used by the module |
+
+The upgrade procedure — acquire, version, decompile, diff the RPC dispatcher,
+update the version surface, validate, roll back safely — is
+[`05-operations/02` §4.1](../05-operations/02-debugging-and-maintenance-workflows.md);
+green-eye adds a runtime layer on top in
+[`debug/risc-v-gsp-rm-vm/docs/22-PORTING-CUDA-AND-DEVICES.md`](../../debug/risc-v-gsp-rm-vm/docs/22-PORTING-CUDA-AND-DEVICES.md).
+
+## 7. Host RM oracle: rmtool, rmtop, rmq and rmharness
+
+`tools/rmtool` and `tools/rmtop` are new, read-only host-RM clients sharing one
+ioctl layer (`tools/rmtool/src/rm_api.c`, `query.c`); `tools/rmq` is the
+pre-existing device-info oracle. They allocate only an RM client/device/
+subdevice handle and never create engine, channel or memory objects; write
+paths are refused in code. Green-eye's `rmharness/` wrappers locate, build and
+capture them into sessions.
+
+```bash
+make -C tools/rmtool && make -C tools/rmtop
+tools/rmtool/rmtool gpu list --format=json
+tools/rmtool/rmtool engine list && tools/rmtool/rmtool mem stats
+./rmharness/harness.sh --session dumps/real-rm -- rmtool engine list --format=json
+```
+
+Details: `tools/rmtool/` sources, [`rmharness/README.md`](../../debug/risc-v-gsp-rm-vm/rmharness/README.md),
+the tool doc [`17-RM-HARNESS.md`](../../debug/risc-v-gsp-rm-vm/docs/17-RM-HARNESS.md),
+and the metric use (M1/M6) in `docs/06-ACCURACY.md`.
+
+## 8. green-eye and its subsystems
+
+`debug/risc-v-gsp-rm-vm/` is the dynamic firmware environment. Its subsystem
+map: `greeneye/` (Session, memory, symbols, structs, probes, record, analyze,
+plugins, Ghidra bridges, injection, device map, native backend), `sim/`
+(deterministic RV64IMAC interpreter + trace), `sdk/` (injection ABI), `qemu/`
+(launch helper + TCG trace plugin), `ghidra/` (Java bridge scripts),
+`plugins/` (example, rmharness, MCP), `harness/` (automation), `rmharness/`,
+`firmware/uproc_demo/` and `tests/`.
+
+```bash
+cd debug/risc-v-gsp-rm-vm
+make demo sdk
+./greeneye.sh info && ./greeneye.sh demo
+./greeneye.sh probe # real fwimage: first divergence, honestly bounded
+./greeneye.sh analyze dumps/<session>
+```
+
+The full architecture and API surfaces are
+[`26-ARCHITECTURE.md`](../../debug/risc-v-gsp-rm-vm/docs/26-ARCHITECTURE.md);
+purpose/status is
+[`05-operations/03-risc-v-gsp-rm-vm.md`](../05-operations/03-risc-v-gsp-rm-vm.md);
+the long-term program is
+[`GREEN-EYE-ROADMAP.md`](../../debug/risc-v-gsp-rm-vm/GREEN-EYE-ROADMAP.md).
+
+## 9. CI and MCP
+
+* **Project CI**: `.github/workflows/ci.yml` builds the kernel module,
+ userspace and host tests on the main tree.
+* **Tool CI**: `.github/workflows/greeneye.yml` installs
+ `qemu-system-misc clang lld-18`, builds `sdk`/`demo`, and runs the tool unit
+ tests (`python3 -m unittest discover -s tests -t .`) on pushes/PRs touching
+ `debug/risc-v-gsp-rm-vm/**` or `tools/rm*/**`. No secrets, hardware or guest.
+* **Release pipelines**: `harness/version_diff.py` and `harness/ci_release.py`
+ produce a hashed evidence bundle; the RM 610 gate is enforced before any
+ target file is opened (`docs/21`, `docs/23`).
+* **MCP**: `plugins/mcp_server.py` exposes the active session as 24 JSON-RPC
+ tools over stdio for Claude Code/opencode; read/observe by default, writes
+ and injection explicitly gated, sessions as the audit trail (`docs/20`).
+
+## 10. Tool table
+
+| Tool | Purpose | When to use it | Where it lives | Doc |
+|---|---|---|---|---|
+| `stack_manager.sh` | build/load/status/test/unload with correct ordering | every host-stack change or bring-up | `scripts/stack_manager.sh` | [`03-architecture/06` §7](../03-architecture/06-host-module-and-hybrid-model.md) |
+| `vgpu_vm.py` | VM lifecycle + guest-agent exec/shell | booting/inspecting the guest | `scripts/vgpu_vm.py` | [`05-operations/02`](../05-operations/02-debugging-and-maintenance-workflows.md) |
+| QEMU launch/gdb helpers | direct QEMU launches, QMP/gdbstub access | gdbstub triage, direct QEMU runs | `scripts/launch_qemu_*.sh`, `qemu_*.sh/py` | [`05-operations/02` §3.3/§3.7](../05-operations/02-debugging-and-maintenance-workflows.md) |
+| module debug parameters | guest-RAM scan/poke, live trace | memory-state debugging in kernel context | `/sys/module/open_iov_vfio/parameters/` | [`05-operations/02` §3.1–3.2](../05-operations/02-debugging-and-maintenance-workflows.md) |
+| `guest-diag` | ioctl trace, engine list, pmap | driver-side oracle for a guest failure | `tools/guest-diag/` | [`05-operations/02` §3.4](../05-operations/02-debugging-and-maintenance-workflows.md) |
+| `cudatool.py` | CUDA binary info/delta/crash/fdematch | every `libcuda` version bump or crash | `userspace/cuda/tools/` | [`READ-ME-FIRST` §3](../../userspace/cuda/READ-ME-FIRST.md) |
+| `callwalk.py` | caller/callee/path walks | tracing a crash path through the corpus | `userspace/cuda/tools/` | [`READ-ME-FIRST` §3](../../userspace/cuda/READ-ME-FIRST.md) |
+| `diff_corpus.py` | corpus cross-version diff | deciding port class (patch/feature/reshuffle) | `userspace/cuda/tools/` | [`docs/07`](../../userspace/cuda/docs/07-version-upgrade-playbook.md) |
+| CUDA Ghidra scripts | headless analysis, decompile-at, name map | building/extending the corpus | `userspace/cuda/tools/ghidra*` | [`docs/06-tooling.md`](../../userspace/cuda/docs/06-tooling.md) |
+| `cuda-ab/ab.sh` | deterministic host-vs-guest workload A/B | validating an emulation change end-to-end | `tools/cuda-ab/` | [`05-operations/01`](../05-operations/01-performance-correctness-security.md) |
+| GSP Ghidra pipeline | firmware project creation + diff | new GSP version or new firmware question | `tools/ghidra/` | [`05-operations/02` §4.1](../05-operations/02-debugging-and-maintenance-workflows.md) |
+| `firmware_analyzer.c` | runtime firmware signatures | registering a new image for identification | `kernel/firmware_analyzer.c` | [`05-operations/02` §4.1](../05-operations/02-debugging-and-maintenance-workflows.md) |
+| `rmtool` | read-only RM inventory/mem/timer oracle | ground truth for M1/M6 metrics | `tools/rmtool/` | [`17`](../../debug/risc-v-gsp-rm-vm/docs/17-RM-HARNESS.md) |
+| `rmtop` | ncurses dashboard; `--once` for capture | human overview / session capture | `tools/rmtop/` | [`17`](../../debug/risc-v-gsp-rm-vm/docs/17-RM-HARNESS.md) |
+| `rmq` | device-info tables (unmodified) | TU104 static data queries | `tools/rmq/` | [`17`](../../debug/risc-v-gsp-rm-vm/docs/17-RM-HARNESS.md) |
+| `rmharness` | capture host oracle runs into sessions | pairing real RM data with a sim session | `debug/risc-v-gsp-rm-vm/rmharness/` | [`rmharness/README`](../../debug/risc-v-gsp-rm-vm/rmharness/README.md) |
+| green-eye CLI | session lifecycle, probe, record, analyze, compare, inject, Ghidra | all dynamic firmware questions | `debug/risc-v-gsp-rm-vm/greeneye.sh` | [`00`](../../debug/risc-v-gsp-rm-vm/docs/00-OVERVIEW.md), [`02`](../../debug/risc-v-gsp-rm-vm/docs/02-USAGE.md) |
+| green-eye Python API | scripted instrumentation and injection | repeatable/CI-able experiments | `greeneye/`, `examples/` | [`03`](../../debug/risc-v-gsp-rm-vm/docs/03-SCRIPTING.md) |
+| green-eye Ghidra bridge | run-until/breakpoints from the decompiler | static↔dynamic address joins | `ghidra/`, `greeneye/gdbridge.py` | [`05`](../../debug/risc-v-gsp-rm-vm/docs/05-GHIDRA-BRIDGE.md), [`13`](../../debug/risc-v-gsp-rm-vm/docs/13-GHIDRA-CONTROL.md) |
+| injection SDK | PIC RV64 service blobs + ABI | prototyping a service or engine | `sdk/`, `greeneye/inject.py` | [`12`](../../debug/risc-v-gsp-rm-vm/docs/12-INJECTION-SDK.md) |
+| green-eye harness | matrix, mutation, discovery, reach, version diff, release bundle, demos | porting, regression, evidence packs | `debug/risc-v-gsp-rm-vm/harness/` | [`18`](../../debug/risc-v-gsp-rm-vm/docs/18-HARNESS-AUTOMATION.md), [`19`](../../debug/risc-v-gsp-rm-vm/docs/19-CONTROL-DISCOVERY.md), [`21`](../../debug/risc-v-gsp-rm-vm/docs/21-CI-RELEASE-PIPELINE.md) |
+| native simulator + trace | deterministic RV64IMAC + exec/access trace | speed/determinism experiments | `sim/`, `greeneye/sim_backend.py` | [`16`](../../debug/risc-v-gsp-rm-vm/docs/16-CUSTOM-SIMULATOR.md) |
+| device map | first-touch MMIO data + lenient mode | device-model bring-up | `greeneye/device_map.py` | [`24`](../../debug/risc-v-gsp-rm-vm/docs/24-DEVICE-MAP.md) |
+| TCG trace plugin | full instruction/memory JSONL trace | coverage map when hooks are not enough | `qemu/greeneye_trace.c` | [`qemu/README.md`](../../debug/risc-v-gsp-rm-vm/qemu/README.md) |
+| MCP server | agent tool surface over a live session | agentic analysis/monitoring | `plugins/mcp_server.py` | [`20`](../../debug/risc-v-gsp-rm-vm/docs/20-MCP-SERVER.md) |
+| CI workflows | project and tool suites | every PR touching the covered paths | `.github/workflows/` | [`21` §5](../../debug/risc-v-gsp-rm-vm/docs/21-CI-RELEASE-PIPELINE.md) |
+
+## 11. The two reverse-engineering loops
+
+Static analysis answers *what is the code*; dynamic analysis answers *what did
+it do*. They interlock through addresses, symbols and recorded evidence.
+
+```mermaid
+flowchart LR
+ subgraph STATIC["Static loop (Ghidra)"]
+ A1["CUDA corpus + GSP firmware projects"] --> A2["name transfer, corpus diff,<br/>symbol inventory diff"]
+ A2 --> A3["hypothesis: dispatch tables,<br/>call paths, data layouts"]
+ end
+ subgraph DYN["Dynamic loop (green-eye)"]
+ B1["Session + injection on the firmware"] --> B2["observe, record, compare<br/>sessions"]
+ B2 --> B3["evidence: hits, watch PCs,<br/>written pages, reply values"]
+ end
+ A2 -->|"symbol DB with bias<br/>(symbols export)"| B1
+ B3 -->|"export_hits, fault PC,<br/>corpus bucket:line"| A1
+ A3 --> C["emulation change in open-iov-vfio"]
+ B3 --> C
+ C --> D["physical confirmation +<br/>regression with the same stimulus"]
+```
+
+* **Static loop**: import the binary/version into Ghidra, transfer the name
+ map (`cudatool.py delta`/`fdematch` for CUDA; `diff_gsp_firmware.py` and the
+ RPC map for firmware), diff the corpus, and read the changed functions.
+* **Dynamic loop**: boot the firmware in green-eye, instrument it, record a
+ session, compare against a reference, and attach the session as evidence.
+* **Interlock**: a Ghidra symbol/address is resolved into the runtime through a
+ symbol DB with the right bias; a runtime hit or fault PC is exported back
+ (`export_hits`) and annotated into the project
+ (`MarkGreenEyeHits.java`); `corpus_location()` maps a hit to its decompiled
+ body when the index carried `bucket:line`. See the green-eye
+ [`05`](../../debug/risc-v-gsp-rm-vm/docs/05-GHIDRA-BRIDGE.md),
+ [`13`](../../debug/risc-v-gsp-rm-vm/docs/13-GHIDRA-CONTROL.md) and
+ [`26` §7](../../debug/risc-v-gsp-rm-vm/docs/26-ARCHITECTURE.md).
+
+## 12. Porting workflows at a map level
+
+Three independent churn axes; a port is a claim with evidence, not a patch.
+Detailed procedures are not duplicated here.
+
+| Axis | Static triage | Dynamic confirmation | Full procedure |
+|---|---|---|---|
+| New CUDA userspace (`libcuda` bump) | `cudatool.py info/delta`, `fdematch`, `diff_corpus.py`, name-map apply | guest smoke (`cuda_drv_test.c`), `cuda-ab`, symbol spot-checks | [`userspace/cuda/docs/07`](../../userspace/cuda/docs/07-version-upgrade-playbook.md); green-eye [`22`](../../debug/risc-v-gsp-rm-vm/docs/22-PORTING-CUDA-AND-DEVICES.md) §2 |
+| New GSP/RM firmware version | decompile + diff RPC dispatcher/controls; Ghidra symbol inventory | `greeneye probe` first-touch, scripted/re-hosted `record`, `compare`, `version_diff.py` | [`05-operations/02` §4.1](../05-operations/02-debugging-and-maintenance-workflows.md) (upgrade runbook); green-eye [`07 P1`](../../debug/risc-v-gsp-rm-vm/docs/07-PORTABILITY-PLAYBOOKS.md), [`21`](../../debug/risc-v-gsp-rm-vm/docs/21-CI-RELEASE-PIPELINE.md), [`22`](../../debug/risc-v-gsp-rm-vm/docs/22-PORTING-CUDA-AND-DEVICES.md) §3 |
+| New device / architecture | device profile data, ISA/image shape, PMU/SOE deltas | portability matrix, probe first-touch on the new image | [`06-portability/hardware-software-matrix.md`](../06-portability/hardware-software-matrix.md); green-eye [`07 P2/P3`](../../debug/risc-v-gsp-rm-vm/docs/07-PORTABILITY-PLAYBOOKS.md), [`18`](../../debug/risc-v-gsp-rm-vm/docs/18-HARNESS-AUTOMATION.md) |
+| A/B accuracy ritual (real vs emulated) | M1–M6 metric definition | hardware/VFIO reference capture vs green-eye session | [`05-operations/01`](../05-operations/01-performance-correctness-security.md); green-eye [`06`](../../debug/risc-v-gsp-rm-vm/docs/06-ACCURACY.md), [`07 P4`](../../debug/risc-v-gsp-rm-vm/docs/07-PORTABILITY-PLAYBOOKS.md), [`25`](../../debug/risc-v-gsp-rm-vm/docs/25-VALUE-VALIDATION.md) |
+| RM 610 family | — | gate first; nothing opened before approval | green-eye [`23`](../../debug/risc-v-gsp-rm-vm/docs/23-RM610-READINESS.md) (hard gate), [`21` §3](../../debug/risc-v-gsp-rm-vm/docs/21-CI-RELEASE-PIPELINE.md) |
+
+The fast pipeline for a GSP version is: `harness/version_diff.py` →
+`harness/portability_matrix.py` → `harness/mutation_harness.py`, wrapped by
+`harness/ci_release.py --dry-run` first, with the resulting bundle attached to
+the change. The diagonal rule holds everywhere: static analysis proposes, the
+dynamic session disposes, and physical confirmation gates any product change.
+
+## 13. Environment invariants
+
+1. **The guest is stock**: no Open-IOV code, agent, driver patch or extra
+ kernel parameters in the guest, ever.
+2. **Tools are in-tree**: no tools in `/tmp`; artifacts survive reboots and are
+ reviewable.
+3. **Read-only host tools stay read-only**: `rmtool`/`rmtop`/`rmq`/`rmharness`
+ refuse write operations in code; no module load/unload, mdev churn or
+ `/sys/fs/pstore` access.
+4. **No unattended physical-GPU cycles**; physical confirmation is supervised
+ and explicit.
+5. **Simulator/re-hosted code is a study environment**: never shipped, never a
+ dependency, no confidentiality/isolation/timing claims.
+6. **Evidence or it did not happen**: sessions, hashes and the M1–M6 table
+ accompany any portability or accuracy claim.
+7. **Versioned, parallel directories**: firmware, CUDA versions and profiles
+ are added, never overwritten; rollback never destroys a working anchor.
+8. **Provenance discipline**: tracked docs describe components and
+ behaviour; conclusions cite recorded evidence.
+
+## 14. Reading paths
+
+* **New contributor**: [`onboarding-and-standards.md`](onboarding-and-standards.md)
+ → this document → the subsystem doc for what you will touch.
+* **CUDA bring-up**: [`../../userspace/cuda/READ-ME-FIRST.md`](../../userspace/cuda/READ-ME-FIRST.md)
+ → `docs/01`, `docs/03`, `docs/05` → `docs/22` for porting.
+* **Firmware/green-eye**: [`05-operations/03-risc-v-gsp-rm-vm.md`](../05-operations/03-risc-v-gsp-rm-vm.md)
+ → tool [`00`](../../debug/risc-v-gsp-rm-vm/docs/00-OVERVIEW.md),
+ [`26`](../../debug/risc-v-gsp-rm-vm/docs/26-ARCHITECTURE.md), then
+ [`03`](../../debug/risc-v-gsp-rm-vm/docs/03-SCRIPTING.md),
+ [`19`](../../debug/risc-v-gsp-rm-vm/docs/19-CONTROL-DISCOVERY.md) and
+ [`21`](../../debug/risc-v-gsp-rm-vm/docs/21-CI-RELEASE-PIPELINE.md) as needed.
+* **Host stack / VM**: [`03-architecture/06-host-module-and-hybrid-model.md`](../03-architecture/06-host-module-and-hybrid-model.md)
+ and [`05-operations/02-debugging-and-maintenance-workflows.md`](../05-operations/02-debugging-and-maintenance-workflows.md).
+* **Portability**: [`06-portability/hardware-software-matrix.md`](../06-portability/hardware-software-matrix.md)
+ plus green-eye `docs/07` and `docs/22`.
+
+Every path in this document was verified at the time of writing; when a tool
+moves, update this table first — it is the front door.