diff options
| author | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-10-06 19:28:39 -0400 |
|---|---|---|
| committer | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-10-06 19:28:39 -0400 |
| commit | 6c3fd5df61ff2f5cb8833ead6c05eaff9fdc92bf (patch) | |
| tree | 3b3680902cd2223cbe60aaec0a0799cfc7b26be6 /debug/risc-v-gsp-rm-vm/docs/45-RM-RPC-CAPTURE-AND-REPLAY.md | |
| parent | a5473c91b8869b017385582ea969783b33553ded (diff) | |
| download | open-iov-6c3fd5df61ff2f5cb8833ead6c05eaff9fdc92bf.tar.gz open-iov-6c3fd5df61ff2f5cb8833ead6c05eaff9fdc92bf.zip | |
risc-v-gsp-rm-debugger: land docs 45-53 + harness/sim tool set with tests
rm_capture (chunked decode), launch_audit, state_seed/state_decode,
valprobe, rehost, contracts+run_contracts, host_traffic, gmmu_walk,
msgq_attach, libos_port, log_decode, server_snapshot; doc index updates
in the tool overview, operations pages and the repo README.
Diffstat (limited to 'debug/risc-v-gsp-rm-vm/docs/45-RM-RPC-CAPTURE-AND-REPLAY.md')
| -rw-r--r-- | debug/risc-v-gsp-rm-vm/docs/45-RM-RPC-CAPTURE-AND-REPLAY.md | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/debug/risc-v-gsp-rm-vm/docs/45-RM-RPC-CAPTURE-AND-REPLAY.md b/debug/risc-v-gsp-rm-vm/docs/45-RM-RPC-CAPTURE-AND-REPLAY.md new file mode 100644 index 0000000..023689a --- /dev/null +++ b/debug/risc-v-gsp-rm-vm/docs/45-RM-RPC-CAPTURE-AND-REPLAY.md @@ -0,0 +1,143 @@ +# 45 — GSP RPC capture ingestion and replay prep (in development) + +> **Status: in development (2026-10-06, capture-ingestion wave).** This page +> documents `harness/rm_capture.py`, a stdlib-only harness that turns the +> **supervised real-client GSP RPC capture** (the tag contract produced by the +> send-path instrumentation runbook) into structured, replayable artifacts: +> a decoded capture document, a per-record comparison report, and a replay +> **stimulus** document for the simulator's B4/B5 CSB/message-queue seam. +> +> Development-only: the tool reads files and writes reports. It never touches +> a GPU, kernel module, mdev, guest or network, and it never runs or schedules +> the capture itself. The capture is a supervised, human-run physical action +> (RUNBOOK P1/P7); the tool only ingests its log. +> +> **See also:** `06-ACCURACY.md` (fidelity levels, M1–M6), +> `17-RM-HARNESS.md` (read-only RM oracle policy), +> `36-GSP-DEVICE-MODEL.md` (the S1 device model and boot ladder), +> `38-GSP-EM-API.md` (TLV boundary), +> `44-GMMU-ORACLE-AND-WORKFLOW.md` (the same offline compare discipline for +> GMMU/FBIF registers). + +## 1. What this is and why + +The open GR question is *what the real host client actually sends* while it +creates and commits a GR context (the golden-image sequence and its promote +controls). The authored capture runbook obtains that sequence from an +instrumented reference kernel driver; this harness consumes the resulting log +and prepares it for two workflows: + +1. **Compare** — the real client's captured sequence vs. the open-iov host + ladder's replay (or two driver/firmware versions), per record, with explicit + unmatched lists. +2. **Replay** — an ordered stimulus document that the simulator's next rung + (B4/B5: host-traffic doorbell + first CSB/TRANSCOM poll served + one + scripted RM message end-to-end) can feed into the modelled firmware, so the + server side of the captured sequence can be observed off-hardware and + deterministically. + +The simulator consumes captured truth; it does not replace the capture. + +Known limitation up front: the capture runbook's hex helper currently caps a +payload dump at 192 bytes. Payloads larger than that (for example a 560-byte +`PROMOTE_CTX` control) decode as **`truncated`** and are **not replayable** +until the helper is extended to emit chunked blocks. The decoder flags this +per record and in the summary; it never pads a payload to look complete. + +## 2. The capture log contract + +Lines are matched anywhere in the line, so dmesg/NVRM/timestamp prefixes are +fine. Tags (exact grammar: `python3 harness/rm_capture.py --print-capture-hints`): + +``` +GE-GOLDEN-TRIGGER gspclient=<0|1> mig=<0|1> +GE-GOLDEN-BEGIN +GE-GOLDEN-END status=0x... +GE-SEND fn=0x... len=0x... ret=0x... +GE-CTRL cmd=0x... hClient=0x... hObject=0x... size=0x... paramp=0x... ret=0x... +GE-ALLOC cls=0x... hClient=0x... hParent=0x... hObject=0x... size=0x... paramp=0x... ret=0x... +GE-CTRL-DONE cmd=0x... rpc_status=0x... params_status=0x... +GE-<TAG> <offset-hex>: <hex bytes...> # attaches to the newest record of that tag +``` + +* Hex blocks attach to the most recent record **of their own tag**; an orphan + block is reported as a warning, never guessed onto another record. +* A `GE-SEND` payload's named id is derived when no named control line was + captured: function `76` (`GSP_RM_CONTROL`) carries the control id at payload + offset 8; function `103` (`GSP_RM_ALLOC`) carries the class id at offset 12. +* `ret=` is the caller return address: recorded as-is, capture-specific. + +## 3. Schemas + +* `greeneye-rm-rpc-capture/1` — `{format, source, sha256, records[], summary, + warnings, limits}`. Each record: `{index, kind, line, ts?, fn?, length?, + size?, cmd?, hclass?, hclient?, hobject?, hparent?, caller?, caller_raw?, + marker?, gspclient?, mig?, status?, rpc_status?, params_status?, + params_hex?, params_bytes, params_size_expected?, truncated?, anomalies?}`. +* `greeneye-rm-rpc-compare/1` — inputs + `summary` (matched / agree / + shape-agree / partial / mismatch / A-only / B-only / agreement % / + coverage % / mean byte agreement %), `rows[]` (per aligned record, with + byte agreement and first-difference offset), `a_only[]`, `b_only[]`, + `fidelity`, `limits`, `warnings`. +* `greeneye-rm-rpc-stimulus/1` — `markers[]` (golden slice boundaries) and + `messages[]` (`fn`/`cmd`/`hclass`/`wire_id`, `params_hex`, sizes, truncation + flag). Handles, physical addresses and caller addresses are **omitted** on + purpose: a replay must allocate/re-map them. + +## 4. Commands + +```bash +python3 harness/rm_capture.py --print-capture-hints # prints only +python3 harness/rm_capture.py decode --log capture.log --out dumps/rm-capture +python3 harness/rm_capture.py compare --a real.json --b replay.json --out dumps/rm-compare +python3 harness/rm_capture.py stimulus --capture real.json --out dumps/rm-stimulus.json +python3 harness/rm_capture.py demo --out /tmp/rm-capture-demo # synthetic, measured +``` + +Inputs to `compare`/`stimulus` may be decoded JSON documents or raw logs; the +loader auto-detects. A non-capture JSON format is a clean error. + +## 5. Simulator linkage (B4/B5) — not wired yet + +The stimulus document is the intended input for the simulator's +host-traffic rung: once the doorbell path and the first CSB/TRANSCOM poll are +served and a scripted message can be delivered end-to-end (handoff-simulator +§17.5), the captured golden-image sequence is the natural first real message +set. Until then this tool stays offline: `stimulus` states the pending wiring +in its `limits`, and nothing in `sim/` imports it yet. + +Ordering honesty: the capture is **send-side only**; server replies were not +captured by the probes. A replay therefore reproduces the stimulus, not the +reply sequence. + +## 6. Admission record (draft — pending maintainer filing) + +Per the project admission rule (`docs/eng-ops.md` §2): all five fields. This +record is a draft, like the simulator program's `gpgpu-sim/ADMISSION.md` +records; a maintainer files it. + +| Field | Value | +|---|---| +| Scenario | RE/porting loop: ingest a supervised real-client GSP RPC capture into the workflow — decode the golden-image sequence, compare it with the open-iov ladder's replay or another version, and prepare a replay stimulus for the simulator's message-loop rung. No hardware access. | +| Measurable outcome | Decode/compare/stimulus wall time vs. manual baseline; record and parameter integrity (no silent loss; truncation flagged); deterministic outputs (two runs byte-identical apart from timing). | +| Baseline | Manual decode-by-eye of one golden sequence from a capture log: grep tags, count records, walk each parameter blob against the RPC structs, transcribe a replay table. Conservative estimate **1800 s** (not measured on a human). | +| Evaluation threshold | Tool path ≤ **5%** of the baseline (≤90 s); demo `ok`; deterministic reports; new tests plus the full suite green. | +| Failure signal | Silent record/parameter loss; truncation unflagged; non-deterministic reports; demo above threshold; or any physical action executed/scheduled by the tool → disable the feature and record it as a failed experiment. | + +Measured proof (2026-10-06, synthetic demo on this host): 15/14 records, +13 agree + 1 shape-agree (flipped parameter byte) + 1 A-only (dropped alloc), +**wall ≈ 0.02 s** vs the 90 s threshold; artifacts under the `demo --out` +directory; 27 new tests, full suite 444 green (twice). + +## 7. Limits and deferrals + +* No hardware, module, mdev, guest or network action; the tool never runs the + capture. +* The 192-byte helper cap: extend the runbook helper to chunk before any large + payload (promote entries) is considered replayable. +* Handles/addresses are capture-specific and explicitly omitted from stimuli. +* Send-side only; no reply/event ordering. +* B4/B5 stimulus wiring, a captured-sequence vs. simulated-firmware accuracy + loop, and symbol/`addr2line` mapping of captured caller addresses are + deferred (the `gmmu_debug.py` static↔dynamic join is the pattern to reuse). +* L0/L1 fidelity only; no timing claim. |
