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
|
# 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.
|