summaryrefslogtreecommitdiffstats
path: root/debug/risc-v-gsp-rm-vm/docs/43-GMMU-PTE-DECODER.md
diff options
context:
space:
mode:
authorArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-04 18:42:36 -0400
committerArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-04 18:42:36 -0400
commit1f2073d4fbb1d412d9bbf373312e3c51b83db92a (patch)
treea661537d7ec9510324e0a40a5a65e4b8c853f01b /debug/risc-v-gsp-rm-vm/docs/43-GMMU-PTE-DECODER.md
parentc1adf2727983f5cace8ca0f5d1119ac2256c348e (diff)
downloadopen-iov-1f2073d4fbb1d412d9bbf373312e3c51b83db92a.tar.gz
open-iov-1f2073d4fbb1d412d9bbf373312e3c51b83db92a.zip
greeneye: GMMU/FBIF observability, PTE decoder and oracle, MPU/libos simulator wave
Simulator development wave (docs 42-44): GMMU page-table entry decode with its oracle/workflow harness, FBIF observability, and MPU/LIBOS device surfaces in the device model, plus refreshed boot/machine/profile data (tu104-570.144), the qemu-line results, and the new unit tests. Docs 00/06/35-41 updated to match; harness helpers and .gitignore included.
Diffstat (limited to 'debug/risc-v-gsp-rm-vm/docs/43-GMMU-PTE-DECODER.md')
-rw-r--r--debug/risc-v-gsp-rm-vm/docs/43-GMMU-PTE-DECODER.md206
1 files changed, 206 insertions, 0 deletions
diff --git a/debug/risc-v-gsp-rm-vm/docs/43-GMMU-PTE-DECODER.md b/debug/risc-v-gsp-rm-vm/docs/43-GMMU-PTE-DECODER.md
new file mode 100644
index 0000000..ea6d3d4
--- /dev/null
+++ b/debug/risc-v-gsp-rm-vm/docs/43-GMMU-PTE-DECODER.md
@@ -0,0 +1,206 @@
+# 43 — GMMU PTE/PDE decoder for TU104 (in development)
+
+> **Status: in development (2026-10-03, G2 work package).** This page
+> documents `sim/gmmu_pte.py`: a clean-room decoder for captured Turing
+> (TU104) GMMU page-table entries. It is decode-only tooling — no hardware,
+> no kernel module, no mdev, no guest, no RM 610. Development-only, never
+> shipped.
+>
+> **Rule: decode captured data only; validate against a capture before
+> trusting.** Every field position below is a reverse-engineering result;
+> none of it is a silicon-accuracy or timing claim (`06-ACCURACY.md`
+> fidelity levels apply).
+
+
+## 1. What this is — and is not
+
+`sim/gmmu_pte.py` turns a captured page-table value or blob into named
+fields with exact bit positions. It is **not** a page-table walker: it never
+dereferences a decoded address, never reads a target table, and never fills
+a gap with a guess. Unsupported encodings and levels raise `E_UNSUPPORTED`;
+set bits that no named field covers are reported (`reserved_bits` /
+`reserved_mask`) and never dropped.
+
+The evidence base is the Turing GMMU entry-format definitions (field names,
+bit ranges, aperture/KIND numeric IDs) together with the driver's own
+page-table encoder/decoder behaviour, which is what proves which of the
+several described encodings Turing actually uses (VER2) and how the
+page-tree geometry maps to virtual-address bits.
+
+## 2. Encodings shipped
+
+| Encoding | Size | Used for |
+|---|---|---|
+| `ver2` | 8 bytes | VER2 leaf PTE and directory PDE — the encoding the Turing driver's page-tree path programs |
+| `ver2_dual` | 16 bytes | VER2 dual PDE0 slot for mixed 64K/4K page tables: BIG half (low 64 bits) + SMALL half (high 64 bits) |
+
+Known-but-unsupported encodings (explicit `E_UNSUPPORTED`): the older
+non-VER2 PTE/PDE encoding and the "NEW"/VER1 encodings also described by the
+same register definitions. They are not shipped because the Turing driver's
+page-tree path uses VER2; adding them without a capture to validate against
+would be unverified surface. See §8.
+
+## 3. VER2 leaf PTE (8 bytes)
+
+| Field (our name) | Bits | Meaning |
+|---|---|---|
+| `valid` | 0 | entry is present |
+| `aperture` / `aperture_name` | 2:1 | 0 video, 1 peer, 2 system coherent, 3 system non-coherent |
+| `volatile` | 3 | cache/volatility bit: 0 = cached, 1 = volatile (the format's cache-related field) |
+| `encrypted` | 4 | encrypted memory |
+| `privilege` | 5 | privileged access |
+| `read_only` (`writable`) | 6 | write protection |
+| `atomic_disable` | 7 | atomics disabled |
+| `address_sys` | 53:8 | system-aperture address bits (PA 53:12) |
+| `address_vid` | 32:8 | video/peer address bits (PA 36:12) |
+| `peer_id` | 35:33 | peer/fabric id (peer aperture) |
+| `comptagline` | 55:36 | compression tag; overloaded as high address bits for the documented 47-bit peer case |
+| `kind` / `kind_name` | 63:56 | memory kind id (see §6); unknown ids are reported, not guessed |
+
+## 4. VER2 directory PDE (8 bytes)
+
+| Field (our name) | Bits | Meaning |
+|---|---|---|
+| `is_pde_pointer` / `is_leaf` | 0 | 0 = pointer to a lower table, 1 = 2 MB leaf PTE stored at PDE0 |
+| `aperture` / `aperture_name` | 2:1 | 0 invalid, 1 video, 2 system coherent, 3 system non-coherent |
+| `volatile` | 3 | as PTE |
+| `no_ats` | 5 | skip the ATS lookup for the covered range (driver sets it at depth 2) |
+| `address_sys` | 53:8 | next-table address bits (system aperture) |
+| `address_vid` | 32:8 | next-table address bits (video aperture) |
+| `peer_id` | 35:33 | peer/fabric id |
+
+Note the aperture-id difference: for a leaf PTE aperture 0 is video memory;
+for a directory PDE aperture 0 is invalid.
+
+## 5. VER2 dual PDE0 (16 bytes)
+
+The BIG half is the low 64 bits, the SMALL half the high 64 bits. Bit 0
+applies to the whole slot.
+
+| Field (our name) | Bits | Meaning |
+|---|---|---|
+| `is_pde_pointer` / `is_leaf` | 0 | whole-slot discriminator |
+| `aperture_big` | 2:1 | 0 invalid, 1 video, 2 system coherent, 3 system non-coherent |
+| `volatile_big` | 3 | as PTE |
+| `no_ats` | 5 | ATS skip; lies inside the BIG address field (see §7) |
+| `address_big_sys` | 53:4 | BIG target address; stores address >> 8 (PA 57:8) |
+| `address_big_vid` | 32:4 | BIG target address, video aperture |
+| `peer_id_big` | 35:33 | BIG peer/fabric id |
+| `aperture_small` | 66:65 | as `aperture_big` |
+| `volatile_small` | 67 | as PTE |
+| `address_small_sys` | 117:72 | SMALL target address; stores address >> 12 (PA 57:12) |
+| `address_small_vid` | 96:72 | SMALL target address, video aperture |
+| `peer_id_small` | 99:97 | SMALL peer/fabric id |
+
+Bits 54–64, 68–71 and 118–127 are unnamed by the format definitions and are
+reported as reserved when set.
+
+## 6. Page-tree geometry and KIND ids
+
+Turing's page-tree path inherits the Pascal/Volta geometry and uses the VER2
+entry encoding. Depths are root (0) to leaf (4):
+
+| Depth | HW level | VA bits | Index bits | Entry size | Role |
+|---|---|---|---|---|---|
+| 0 | PDE3 | 48:47 | 2 | 8 | pointer PDE |
+| 1 | PDE2 | 46:38 | 9 | 8 | pointer PDE |
+| 2 | PDE1 | 37:29 | 9 | 8 | pointer PDE (NO_ATS here) |
+| 3 | PDE0 | 28:21 | 8 | 16 (dual) / 8 (2 MB leaf) | dual 64K/4K PDE, or a 2 MB leaf PTE |
+| 4 | PTE | 20:12 (4 KB) / 20:16 (64 KB) | 9 (4 KB) / 5 (64 KB) | 8 | leaf PTE |
+
+Supported page sizes: 2 MB (depth 3), 64 KB and 4 KB (depth 4); VA width 49
+bits. A leaf entry alone does not tell 4 KB from 64 KB — the table's depth
+and page-size context do, so the decoder reports `page_size` as
+`4k_or_64k` when the depth is pinned to 4.
+
+The PTE `kind` field carries numeric ids (243 named values re-derived from
+the format definitions). Common compute values: `0x00 PITCH`,
+`0x06 GENERIC_MEMORY`, `0x07 INVALID`, `0x0F SMSKED_MESSAGE`,
+`0xFE GENERIC_16BX2`. Unknown ids decode as `kind_name: null`,
+`kind_known: false` with the raw value preserved.
+
+## 7. Address decode and uncertainty
+
+* System apertures (`system_coherent_memory`, `system_non_coherent_memory`):
+ the reconstructed `address` is complete (`address_complete: true`).
+* Video/peer apertures: only the low address bits are unambiguous
+ (`address_complete: false`). `comptagline` is a compression tag in the
+ normal case and is documented as overloaded for 47-bit peer addresses; the
+ decoder therefore does not claim a complete video address.
+* Dual BIG address: the field stores `address >> 8`, so `address` is
+ reconstructed as `field << 8`. Bit 5 of the slot is named `no_ats` and also
+ lies inside the BIG address field (address bit 9). The decoder reports the
+ flag from bit 5 and excludes that bit from the reconstructed BIG address;
+ the raw `address_big_sys` / `address_big_vid` fields keep the bit visible.
+ This assumes the target table is 4 KB aligned, which is the normal GPU
+ allocation granularity — if a capture shows a non-aligned target, treat
+ that entry as an unexplained case, not as proof of a different format.
+* Reserved-bit policy: `reserved_bits` lists every set bit not covered by a
+ named field; `reserved_mask` is the same set as a mask. Nothing is
+ silently dropped.
+* The VER2 PTE has no separate cache field: `volatile` (bit 3) is the only
+ cache-related bit the format defines, so no cache encoding is invented.
+* `decode_table` is little-endian and never follows pointers; a blob whose
+ length is not a multiple of `entry_size` raises `E_TRUNCATED`, an empty
+ blob decodes to `[]`.
+
+## 8. Supported levels and explicit gaps
+
+`levels` may pin the page-tree depth (0–4) or a sequence of acceptable
+depths. `None` (default) uses the full supported set and lets each entry's
+bit-0 discriminator choose between the leaf-PTE and directory-PDE views,
+reporting `level: null` plus `level_candidates` instead of guessing a single
+depth. Any depth outside 0–4 raises `E_UNSUPPORTED`.
+
+Explicit gaps (never guessed):
+
+1. Pre-VER2 and "NEW"/VER1 encodings are not decoded (`E_UNSUPPORTED`).
+2. The decoder does not walk tables, resolve virtual addresses, or infer a
+ 4 KB vs 64 KB leaf page size from the entry alone.
+3. No capture has been validated yet: the golden vectors are constructed
+ field-by-field from the format definitions, not sampled from silicon.
+ **Validate against a real capture before trusting a decode.**
+4. No timing, device-environment, isolation or security claim is made; the
+ simulator fidelity levels in `06-ACCURACY.md` apply.
+
+## 9. Usage
+
+Python:
+
+```python
+from sim.gmmu_pte import decode_pte, decode_table
+
+pte = decode_pte(0x0600000000123456, pte_kind="ver2")
+entries = decode_table(blob, base_pa=0x2000, entry_size=8, levels=4)
+dual = decode_table(blob16, base_pa=0x2000, entry_size=16, kind="ver2_dual",
+ levels=3)
+```
+
+CLI:
+
+```bash
+# one entry (default role "auto": bit 0 picks leaf vs directory)
+python3 -m sim.gmmu_pte --value 0x0600000000123456 --role pte
+python3 -m sim.gmmu_pte --value 0x0600000000123456 --json
+
+# a captured table blob, with the blob's GPU physical base address
+python3 -m sim.gmmu_pte --blob table.bin --base-pa 0x2000
+python3 -m sim.gmmu_pte --blob table.bin --base-pa 0x2000 --levels 4 --json
+
+# a dual PDE0 slot
+python3 -m sim.gmmu_pte --blob dual.bin --base-pa 0x2000 \
+ --kind ver2_dual --entry-size 16 --levels 3 --json
+```
+
+Exit code 0 on success; 2 with an `E_*` code on stderr for unsupported
+kinds/levels, truncated blobs or bad values. JSON output is sorted-key and
+deterministic.
+
+## 10. Tests
+
+`tests/test_gmmu_pte.py` builds every vector field-by-field from the tables
+above, asserts field round-trips, reserved-bit reporting (including the
+unnamed dual bit 64 and the unnamed PDE bits 4, 6, 7, 54–63), the NO_ATS
+overlap behaviour, unknown-kind reporting, unsupported kind/level/entry-size
+errors, empty and truncated blobs, deterministic output, and CLI success and
+error paths. 44 constructed golden entry vectors across 43 tests.