# The TMR fence ignores the access tag too, not just the requester `FINDING-SMU-MAILBOX-HOST-REACHABLE.md` established the PSP's TMR fence is "**requester-agnostic** — it blocks the trusted SMU requester, not just the host BAR path". That conclusion came from one alternative requester (SMU DMA) and from host BAR reads. Two gaps in that: host BAR reads are **PA-based and bypass the GPU VM entirely**, so they say nothing about VM-mediated access; and the SMU is a microcontroller, not one of the GPU's own engines. Nobody had tried changing the **tag** on the access, which matters because the host driver owns the GPU page tables and those carry `AMDGPU_PTE_TMZ` (bit 3) — the trusted-memory-zone bit. If the fence keyed on the TMZ tag rather than on physical address, a host that forges that bit in its own PTEs would read PSP-trusted memory. That would be the disclosure primitive this project has never had. ## Method Point a GPU buffer's VA at TMR physical memory and have a **GPU kernel** read it, with and without TMZ set on the PTE. TMR range is 0x300000..0x1600000 (from the SMU finding); target PA 0x900000. ## Result: refuted, with every control passing | step | first 16 bytes read | verdict | | --- | --- | --- | | host BAR read of PA 0x900000 | `ffffffffffcfffffffffffffffffffff` | fence, as documented | | **control** — VA remapped to our own scratch page (0x3C fill) | `3c3c…3c` (1 unique byte) | **remap + kernel + TLB path VALID** | | control — same scratch page **with TMZ set** | `3c3c…3c` | TMZ does not break a normal read | | TMR PA, no TMZ | `ffffffffffcfffffffffffffffffffff` | blocked | | **TMR PA, with TMZ** | `ffffffffffcfffffffffffffffffffff` | **blocked — identical** | The GPU engine read returns **byte-for-byte what the host BAR returns** for the same physical address, and setting the TMZ bit changes nothing. So the fence is not merely requester-agnostic; it is **tag-agnostic** and applies to VM-mediated GPU engine accesses exactly as it does to the host BAR path. It is a physical-address fence, enforced below both the VM and the requester ID. ## Why the controls matter here The scratch-page control is what makes this a real negative rather than another broken detector: the same VA, the same kernel, the same TLB flush, reading a page we own, returns our 0x3C fill cleanly. So the machinery demonstrably works and the TMR result is the fence, not a broken read path. The TMZ-on-our-own-page control further shows that setting the bit does not simply invalidate the mapping. ## Incidental The fence pattern is not pure `0xFF` — 12 distinct byte values across the page, with `0xCF` recurring at a fixed offset. Identical from both access paths, so it is the fence's response and not leaked content, but it is a slightly more structured response than "reads return 0xFF" implies. ## Status Negative, and it closes the tag-forging angle. Combined with the prior SMU result, three distinct initiators (host BAR, SMU DMA, GPU compute engine) and two tag states have now failed to read TMR memory. The remaining untried initiator class is the PSP itself, which `ANGLE-PSP-AS-CONFUSED-DEPUTY-WRITER.md` already tried and refuted from the other direction. --- # Follow-ups: PTE attributes closed, DF config port closed, fence shape questioned ## PTE cacheability attributes — no effect (closed) If the fence were expressed at a cache/coherence level rather than as a hard physical block, cacheability attributes might change it. They do not. Same validated harness, control page passing first: | PTE attributes on the TMR mapping | GPU read | | --- | --- | | default | `ffffffffffcfffffffffffff` | | MTYPE cleared | identical | | MTYPE = 1/2/3 << 48 | identical | | NOALLOC | identical | | NOALLOC + MTYPE cleared | identical | Together with TMZ, **no PTE attribute we can set changes what a GPU engine reads from the TMR.** ## DF FabricIndirectConfigAccess — does not decode (closed) `DF.FabricConfigAccessControl` (0x1D040), `FabricIndirectConfigAccessAddress` (0x1D050) and `DataLo/Hi` (0x1D080/84) are an index/data port into the Data Fabric's *configuration* space — where address-map routing lives, and never used in this project. On this card all four **mirror**, with the C2PMSG control decoding. The probe stopped there by design and wrote nothing. Another instance of NV22 addresses not transferring to NV31. ## The fence's shape does not match the documented range Probing physical addresses through the GPU path, against the documented TMR range 0x300000..0x1600000: | PA | first 12 bytes | | | --- | --- | --- | | 0x0200000 | `ffffffffffffffffffffffff` | below range | | 0x02FF000 | `ffffffffffffffffffffffff` | below range | | **0x0300000** | `000000000000000000000000` | **in range, reads ZEROS** | | **0x0400000** | `000000000000000000000000` | **in range, reads ZEROS** | | 0x0900000 | `ffffffffffcfffffffffffff` | in range | | 0x15FF000 | `ffffffffffff...7fffff` | in range | | 0x1600000 | `003f02c00030080000200000` | just past — real-looking data | | 0x1700000 | `000000000000000000000000` | above | | 0x2000000 | `000000000000000000000000` | above | This does not fit "everything in 0x300000..0x1600000 is fenced and returns 0xFF". Addresses *below* the range return 0xFF; two addresses *inside* it return clean zeros. **The right conclusion is that `0xFF` is not a reliable fence signature.** It is equally consistent with unpopulated or uninitialised memory, and zeros are equally consistent with genuinely-zero RAM. Nothing here is a disclosure — reading zeros discloses nothing, and 0x1600000 is ordinary VRAM outside the protected range. What it does mean is that **this probe cannot distinguish "fenced" from "empty"**, so it should not be used to map the fence. A sound version needs a positive discriminator: get the PSP to write a known value to a TMR address (it is the one initiator that can), then read that address back through each path. Without that, every 0xFF here is ambiguous. The SMU experiment remains the better evidence on the fence, because it had one: the *same* DMA succeeded at 0x9A000 and 0x1600000 and failed at TMR+0x980000, which is a controlled comparison rather than a pattern-read.