summaryrefslogtreecommitdiffstats
path: root/docs/05-operations/04-green-eye-user-guide.md
blob: a9bf1dc5176831dd2868863e81cb063a1160ebe4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
# green-eye User Guide (experimental)

> **# TOOL IN DEVELOPMENT - NOT READY YET!**
> green-eye 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 green-eye 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 green-eye is

green-eye 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 `open-iov-vfio` 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*; green-eye answers *what did it do*. Guest
diagnostics answer *what did the driver request*; a supervised physical cycle
answers *what does silicon do*. green-eye 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

./greeneye.sh info          # environment check: QEMU, toolchain, paths
make demo && make sdk       # build the bundled RV64 uproc demo and injection SDK

./greeneye.sh demo          # canned run: boot, hooks, watchpoints, session
./greeneye.sh analyze dumps/<printed-session-dir>

./greeneye.sh probe         # real GSP image: report the first divergence
./greeneye.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 | green-eye 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 green-eye 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/<stamp>-<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, 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 (`./greeneye.sh`)

| Command | One-line purpose |
|---|---|
| `info` | environment/tooling check (QEMU, paths, capabilities) |
| `demo` | canned boot + hooks + watchpoints + recording on the bundled uproc |
| `run <script.py>` | 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 <image>` | bounded run of a raw image; first-divergence report |
| `analyze <session>` | session to symbol-annotated Markdown report |
| `compare <a> <b>` | 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 |
| `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 |
| `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/` + `greeneye inject` | position-independent service ABI v1 |

## 5. Choosing the right tool

| Task | Tool | Notes |
|---|---|---|
| "Does this run?" / first divergence of a raw image | `./greeneye.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`, `./greeneye.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/` + `./greeneye.sh inject` | PIC blob; direct and mailbox paths |
| "Join Ghidra static addresses to runtime hits" | `./greeneye.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 |

Decision rule: static reading is a hypothesis; a recorded session is evidence;
at least an A/B pair is a conclusion.

## 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
./greeneye.sh demo                       # prints the session directory
./greeneye.sh analyze dumps/<session>    # symbol-annotated report
```

### 7.2 Probe a new firmware image

```bash
./greeneye.sh symbols export --index <export.tsv> --bias 0 -o symbols-<ver>.json
./greeneye.sh probe <gsp-<VER>.fwimage.bin> --symbols symbols-<ver>.json --record
python3 harness/version_diff.py --old <old> --new <new> --out dumps/vdiff-<ver> \
    --old-symbols symbols-<old>.json --new-symbols symbols-<new>.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 <reference-fwimage> --target <candidate-fwimage> \
    --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
./greeneye.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
./greeneye.sh ghidra --kernel <elf> --bridge-port 7000
# terminal 2 (Ghidra headless)
$GHIDRA/support/analyzeHeadless <proj> <name> -process <program> -noanalysis \
    -scriptPath open-iov/debug/risc-v-gsp-rm-vm/ghidra \
    -postScript GreenEyeControl.java 7000 0x<address>
```

### 7.8 Host oracle capture (read-only)

```bash
./rmharness/harness.sh --session dumps/real-<anchor> --name before \
    -- rmtool engine list --format=json
./rmharness/harness.sh --session dumps/real-<anchor> -- rmtop --once
```

### 7.9 Release rehearsal

```bash
python3 harness/ci_release.py --old <old> --new <new> --out dumps/release-<ver> \
    --old-label <OLD> --new-label <NEW> --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
./greeneye.sh probe <fwimage> --record
python3 -m greeneye.device_map harvest dumps/<probe-session> --out dumps/<ver>-device-map.json
python3 -m greeneye.device_map show dumps/<ver>-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 <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 `greeneye.sh run` | run through `./greeneye.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 |
| `greeneye error:` on a valid path | wrong relative path or `--db` file | `./greeneye.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: every tool document carries the
**# TOOL IN DEVELOPMENT - NOT READY YET!** banner. The marker is removed only
when the acceptance list in
[docs/00-OVERVIEW](../../debug/risc-v-gsp-rm-vm/docs/00-OVERVIEW.md) passes on a
clean checkout, the usage recipes verify end-to-end, a second person can run
the quickstart unaided, and the session format and CLI are declared stable.

## 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
  `open-iov-vfio` 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/GREEN-EYE-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.

<!-- change (2026-10-02): correct the TCG plugin filename to the actual
qemu/greeneye_trace.c, list the docs 28/29 scaffolds in the tool inventory and
documentation map; scope: §4.2, §4.3, §10 only; benefit: copied commands and
doc-map navigation match the tool tree. -->