summaryrefslogtreecommitdiffstats
path: root/debug/risc-v-gsp-rm-vm/docs/45-RM-RPC-CAPTURE-AND-REPLAY.md
diff options
context:
space:
mode:
authorArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-06 19:28:39 -0400
committerArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-06 19:28:39 -0400
commit6c3fd5df61ff2f5cb8833ead6c05eaff9fdc92bf (patch)
tree3b3680902cd2223cbe60aaec0a0799cfc7b26be6 /debug/risc-v-gsp-rm-vm/docs/45-RM-RPC-CAPTURE-AND-REPLAY.md
parenta5473c91b8869b017385582ea969783b33553ded (diff)
downloadopen-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.md143
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.