summaryrefslogtreecommitdiffstats
path: root/debug/risc-v-gsp-rm-vm/docs/42-GMMU-FBIF-OBSERVABILITY.md
diff options
context:
space:
mode:
Diffstat (limited to 'debug/risc-v-gsp-rm-vm/docs/42-GMMU-FBIF-OBSERVABILITY.md')
-rw-r--r--debug/risc-v-gsp-rm-vm/docs/42-GMMU-FBIF-OBSERVABILITY.md203
1 files changed, 203 insertions, 0 deletions
diff --git a/debug/risc-v-gsp-rm-vm/docs/42-GMMU-FBIF-OBSERVABILITY.md b/debug/risc-v-gsp-rm-vm/docs/42-GMMU-FBIF-OBSERVABILITY.md
new file mode 100644
index 0000000..4a2d6ee
--- /dev/null
+++ b/debug/risc-v-gsp-rm-vm/docs/42-GMMU-FBIF-OBSERVABILITY.md
@@ -0,0 +1,203 @@
+# 42 — GMMU/FBIF observability (in development)
+
+> **Status: in development (2026-10-03, G1 work package).** This page
+> documents the observe-only GMMU and FBIF/FBPA register windows added to the
+> device model, the `greeneye-gmmu-fbif-trace/1` document and the boot-runner
+> flags that produce it. Development-only: nothing here authorises GPU
+> hardware, kernel modules, mdev, guest access or reboots, and nothing here is
+> a silicon-accuracy claim.
+>
+> **See also:** `36-GSP-DEVICE-MODEL.md` (the device model this plugs into),
+> `06-ACCURACY.md` (fidelity levels), `24-DEVICE-MAP.md` (harvested access
+> maps), `35-GREENEYE-SIMULATOR-DESIGN.md` §4.1 (the Phase G inventory this
+> observability de-risks).
+
+## 1. What this is
+
+The Phase G board model needs the GMMU and the FB interface eventually. Before
+modelling either, we need to know **what the firmware actually touches** in
+those register windows, with which width and direction, from which PC, and
+without pretending to know register behaviour we have not established.
+
+`sim/devices/observe.py` adds **observer windows**: device-model windows that
+record every access and then **decline** it, so execution follows the existing
+device-map / lenient / unknown path exactly as it did before the window
+existed. They never invent a read value.
+
+## 2. What is observed
+
+The TU104 profile (`sim/profiles/tu104-570.144.json`) declares 23 observer
+windows, all `observe-only`. Bases are runtime addresses in the GSP RISC-V
+PRIV aperture (`0x2000_0000_0000_0000` + BAR0 offset); offsets/names come from
+the hardware register/field headers (evidence kind: **header**). The B0–B2
+runs did not touch any of them; the B3 wave reaches the WPR2 read pair
+(`0x1FA824/0x1FA828`), which falls inside the `gmmu-wpr-lock` window and is
+recorded observe-only (2 accesses, 0 served; the fwsec device answers).
+
+| Window label | Runtime base | Size | Covers |
+|---|---|---|---|
+| `gmmu-pri-mmu` | `0x2000000000100C80` | `0x280` | `NV_PFB_PRI_MMU_*` cluster (`NV_PFB_PRI_MMU_CTRL` first) |
+| `gmmu-wpr-lock` | `0x20000000001FA7D8` | `0x5C` | MMU per-engine PRIV_LEVEL masks + VPR/WPR/lock address pair |
+| `gmmu-hsmmu` | `0x20000000001FAC00` | `0x400` | `NV_PFB_HSMMU_PRI_MMU_*` (secondary MMU block) |
+| `fbpa` | `0x20000000009A0000` | `0x4000` | main FBPA block (`NV_PFB_FBPA_*`) |
+| `fbpa-partition-0..15` | `0x2000000000900000` + i·`0x4000` | `0x4000` | per-partition FBPA instances |
+| `fbpa-mc-0..2` | `0x2000000000980000` + i·`0x4000` | `0x4000` | FBPA MC instances |
+
+Register names (and, for a few control/status registers, header field names
+with bit positions) are declared per window so traces are readable; offsets
+inside a window that the profile does not name are still recorded and land
+under `unclassified`. `gmmu-pri-mmu` spans the `NV_PFB_PRI_MMU_*` cluster
+`0x100C80–0x100EFC`; the few non-MMU PFB registers interleaved in that span
+(e.g. the PRI_FB clock/power-gating registers) are recorded as unclassified,
+never renamed.
+
+## 3. Mechanism: record, then decline
+
+Each `ObservedWindow` is a normal device-model window and is consulted by the
+registry like any other. Its `read`/`write` always record:
+
+```text
+addr, offset, size, rw, value-if-known, pc, vt, window, register, served
+```
+
+and then return `None`/`False` unless the window is declared `storage` **and**
+the accessed offset is a declared plain read/write register **and** (for
+reads) that register has been written before. Declining means the registry
+falls through to the next matching window and the machine's existing path
+applies unchanged:
+
+* lenient mode: the access is logged/counted as before and reads 0;
+* fault mode: the same `Fault(cause, tval)` as without the window;
+* a modelled window underneath (e.g. the PMC block) is consulted exactly as
+ before and serves the access if it models it, and the observer records that
+ it happened. (The `gmmu-wpr-lock` window overlaps the fwsec WPR2 window, so
+ it exercises this fall-through; it asserts nothing about whether the
+ underlying WPR2 path serves — that path is unchanged by the observer and
+ currently serves nothing through the registry, a pre-existing condition.)
+
+**No-fake-read guarantee.** An observe-only read records `"value": null` and
+returns `None`; a storage read before any write is declined the same way; no
+reset value is synthesised. The only read value a storage window can return
+is one this same run wrote to that register. All profile windows for
+GMMU/FBIF are `observe-only`; the `storage` mode exists for surfaces whose
+header proves plain read/write behaviour and is exercised by tests.
+
+`pc` is the faulting instruction address (the registry forwards it only to
+devices that opt in). `vt` is the machine instruction counter at the access;
+it advances at `Machine.run` boundaries, so accesses inside one bounded run
+share the run-start value — a documented granularity, not a timing claim
+(fidelity L2 is not modelled).
+
+**Size limit.** Each window's access log is capped (`max_access_log`, default
+65536 entries); accesses beyond the cap are counted, not written. The trace
+document reports `dropped_accesses` per window and in the summary and
+separates `accesses` (total observed) from `retained_accesses` (present in
+the document), so truncation is never silent.
+
+## 4. Trace document: `greeneye-gmmu-fbif-trace/1`
+
+`--trace-out <path>` writes a trace file: a path that is an existing
+directory (or ends in `/`, which makes that directory) gets the canonical
+filename `gmmu-fbif-trace.json` inside; anything else is used as the file
+name. Accesses are grouped per window and per declared register; undeclared
+offsets go to `unclassified`. Shape:
+
+```json
+{
+ "schema": "greeneye-gmmu-fbif-trace/1",
+ "image_sha256": "…",
+ "profile": "tu104-570.144.json",
+ "profile_name": "tu104-570.144",
+ "symbols": "symbols.json",
+ "summary": {"windows": 23, "windows_touched": 0, "accesses": 0,
+ "retained_accesses": 0, "dropped_accesses": 0,
+ "reads": 0, "writes": 0, "served": 0, "registers_touched": 0},
+ "windows": [
+ {"label": "gmmu-pri-mmu", "base": "0x2000000000100c80", "size": "0x280",
+ "mode": "observe-only", "evidence": "…",
+ "counts": {"r": 0, "w": 0, "served": 0, "declined": 0},
+ "retained_accesses": 0, "dropped_accesses": 0,
+ "registers": [
+ {"offset": "0x0", "name": "NV_PFB_PRI_MMU_CTRL", "access": "rw",
+ "counts": {"r": 0, "w": 1, "served": 0},
+ "accesses": [
+ {"addr": "0x2000000000100c80", "offset": "0x0", "size": 4,
+ "rw": "w", "value": "0x1", "pc": "0x4001234",
+ "pc_symbol": "rm_init+0x20", "vt": 0,
+ "window": "gmmu-pri-mmu", "register": "NV_PFB_PRI_MMU_CTRL",
+ "served": false, "decoded": {"VM_PG_SIZE": 1}}
+ ]}
+ ],
+ "unclassified": {"counts": {"r": 0, "w": 0, "served": 0},
+ "accesses": []}}
+ ]
+}
+```
+
+`pc_symbol` is `null` unless `--symbols <greeneye-symbols/1 JSON>` is given;
+`decoded` is present only when a value is known and the register declares
+fields (bit positions from the header). `value`/`addr`/`offset`/`pc` are hex
+strings; `vt` is an integer. The document is deterministic for a fixed image,
+profile, flags and stimulus.
+
+The **count summary is always in the boot report** (and session metadata under
+`gmmu_fbif`) even when `--trace-out` is off; the trace blob is added to the
+recorded session only when the flag is on.
+
+## 5. Commands
+
+```bash
+cd open-iov/debug/risc-v-gsp-rm-vm
+
+# B2 run with the observer summary, trace written to a directory:
+python3 -m sim.gsp_boot --instructions 20000 --record dumps/gsp-boot-b2-observe \
+ --trace-out dumps/gsp-boot-b2-observe
+
+# Resolve recorded PCs through a symbol database:
+python3 -m sim.gsp_boot --trace-out /tmp/trace.json --symbols symbols.json
+
+# Ad-hoc window whose base is not established yet (repeatable, no guessing):
+python3 -m sim.gsp_boot --observe-window 0x20000000009A0000:0x4000:fbpa \
+ --observe-window 0x2000000000100C80:0x280:gmmu
+```
+
+`--observe-window BASE:SIZE[:LABEL[:MODE]]` is the escape hatch: the trace
+accepts a runtime window list, so an unknown surface can be observed before
+any profile entry exists. A runtime window is `observe-only` unless
+`MODE=storage` is given (storage without declared registers still records and
+declines).
+
+## 6. What is NOT modelled
+
+* **No GMMU page walk, no PTE/PDE decode, no TLB, no fault handling, no ATS.**
+ Window accesses are recorded; their semantics are not interpreted.
+* **No FBIF transaction semantics, compression, ECC or partition hashing.**
+ FBPA register offsets/names are labels, not behaviour.
+* **No interrupt or timing (L2) claims.** `vt` is the modeled instruction
+ counter, not cycles.
+* **No device-environment (L3) claims.** The windows exist because the
+ simulator serves them; silicon behaviour is not asserted.
+* **Storage is not semantics.** A storage window only echoes values written in
+ the same run; it is not evidence that the real register stores them.
+* **No product or hardware action.** Nothing in this workstream touches
+ `vgsp`, a GPU, a module, mdev, or a guest.
+
+## 7. Evidence, limits and tests
+
+* Evidence kind for every window/offset is the hardware register/field header
+ (block ranges and register offsets); observed firmware use in B0–B2 was
+ **zero accesses** (measured at the B2 stop: 14 682 instructions, 0 unknown
+ MMIO, 1 device access — the PMC chip-ID read). The B3 wave's WPR2 reads are
+ the first observed accesses (2 reads inside `gmmu-wpr-lock`, observe-only,
+ 0 served). The mechanism is still tested end-to-end with runtime windows.
+* Boot numbers are unchanged by the observer windows (instructions, stop
+ PC/reason, unknown MMIO, unhandled-in-window, served accesses); the only
+ session difference is the added device-state entries for the observers.
+* Tests: `tests/test_gmmu_fbif_trace.py` — no-semantic-change (lenient and
+ fault paths match a registry without the window), storage read-back,
+ field decode, profile expansion, trace schema, access-log-cap reporting,
+ WPR2-overlap pass-through, B2 invariance, symbol resolution, runtime
+ windows.
+* Public artifacts carry only component register names/offsets and behaviour;
+ the window/register tables come from the tracked analysis and recorded
+ sessions.