# A working, non-destructive address-classification oracle on silicon Outcome of `STRATEGY-MEASUREMENT-FIRST.md` Prong 2, after the absent-address arm wedged the card and was dropped. ## The oracle `LOAD_TA` lets the host choose `app_phy_addr`; the PSP then reads and verifies that buffer. The returned status classifies what the PSP found: | source | status | | --- | --- | | a real, signed TA image | **`0x0`** (loads, session allocated) | | readable VRAM, invalid contents | **`0x34`** (52, signature verification failure) | | a range overlapping the **TMR** | **`0xA`** (10) | Two different junk buffers both return `0x34`, so the status is not noise; a real image returns `0x0`, so the path works. Both controls pass, and the PSP heartbeat stays alive through every probe — this is **non-destructive**, unlike the absent- address probing that cost a power cycle. `0xA` is the same code sOS's own gate uses for a rejected pointer (`GATE_BAD_PTR` in `pspemu/gate.py`), which suggests the refusal is a range check rather than a protection fault raised by hardware. For the oracle's purpose the distinction does not matter: the address is *classified*. ## Validated against independent ground truth The TMR is at PA `[0x300000, 0x1600000)` from the SMU/PSP fields (`tmr_paddr`/`tmr_size`), measured previously and by a completely different method. Sweeping the oracle across that boundary: 0x200000 0x34 outside expected outside agree 0x2ff000 0xa INSIDE expected outside MISMATCH 0x300000 0xa INSIDE expected INSIDE agree 0x301000 0xa INSIDE expected INSIDE agree 0x900000 0xa INSIDE expected INSIDE agree 0x15f0000 0xa INSIDE expected INSIDE agree 0x1600000 0x34 outside expected outside agree 0x1700000 0x34 outside expected outside agree 7/8 agree. PSP alive after sweep. **The one mismatch is the most useful row.** `0x2ff000` is a single page *below* the TMR base, but the probe's `app_len` is the whole TA blob, so the source *range* extends into the TMR. The refusal therefore covers `[start, start+len)`, not just the start address — and the upper edge confirms it: `0x15f0000` (extends past the end) reads INSIDE, while `0x1600000` (fully outside) reads outside. So the oracle answers *"does this range overlap a region the PSP refuses to read from?"*, and page-granular results are obtainable by shrinking `app_len`. ## Scope — what it does and does not reach * **Does:** classify **host-visible VRAM (MC) addresses**. It can map the TMR page-exactly and, more interestingly, **discover protected ranges we do not already know about**, by sweeping VRAM for regions that answer `0xA`. * **Does NOT:** reach PSP-internal physical space. `app_phy_addr` is an MC address, so this says nothing about Route C's window, which lives in PSP-internal space. That question remains open. ## Why this one survived when the others did not Every previous attempt needed a channel returning **data**, and none exists. This needs only a channel returning **status**, and status was always there — `0x34` had already been seen in `load_asd.py` for a bit-flipped image without anyone asking what *other* values the same field could take. Harnesses: `hw/psp_addr_classify.py` (the three-way probe with controls), `hw/psp_addr_classify_validate.py` (the ground-truth boundary sweep). --- # Sweep result: in the first ~1 GB of VRAM, the TMR is the ONLY refused range Swept PA `[0, 0x3ef00000)` at 1 MB granularity with `app_len = 0x1000` (`hw/vram_protect_sweep.py`), using the TMR as a live per-boot control — if `0x900000` does not come back refused, the oracle is not working on that boot and the sweep's negatives mean nothing. The control passed. 1006 addresses probed, 4 seconds, 19 refused refused range: 0x00300000 .. 0x01600000 <- exactly the known TMR **No protected range other than the TMR exists in the first ~1 GB**, at 1 MB resolution. That is a real negative with a validated instrument, and it also re-derives the TMR bounds independently, agreeing with the SMU/PSP fields. ## RETRACTED: there is no wall at PA 0x3ef00000 — it was ring exhaustion The first version of this section reported a "hard wall" at PA `0x3ef00000` above which the oracle stopped working, and concluded that its validated domain was `PA < 0x3ef00000`. **That was wrong, and the reasoning was a textbook confound.** The failures began at PA `0x3ef00000`, which was *also* probe **#1006**. The failing value was `(PA >> 16) + 0x101` — but since `PA = n * 0x100000`, that is identically `16*n + 257`. Address-derived and count-derived fit the same data exactly, and I picked the address explanation without testing the other. Two measurements settle it: * A **fresh process** probes `0x3ff00000` and `0x40000000` in 0.00 s with status `0x34` — no wall at those addresses at all. * Probing **one fixed address** (`0x20000000`) repeatedly deviates at probe **#998**, returning `0x3ff1` — the *same* value the sweep produced — while `(PA>>16)+0x101` for that address would be `0x2101`. The value has nothing to do with the address. `0x3ff1 = (1023 << 4) | 1`, and the latency jumps to exactly 10.00 s (a timeout). So the number is a **ring write pointer at 1023** on a 1024-entry ring: after ~1000 submits the ring is full and submissions stop being serviced. ## What this actually means * **The oracle has no known address limit.** Its real limit is **~998 probes per process**, after which the ring must be drained or the process restarted. * **The sweep's coverage was bounded by ring capacity, not by hardware.** It stopped at 1006 MB because that is where it ran out of ring, so "only the TMR is protected below 1 GB" stands, but the *reason* it stopped there was an artefact. * A full 24 GB sweep is feasible by restarting every ~900 probes (~28 restarts), or by finding the ring drain. The negative result above — TMR is the only refused range in the swept region — is unaffected, because every probe in it returned a fast, valid verdict with the live control passing.