<feed xmlns='http://www.w3.org/2005/Atom'>
<title>amd-psp-re.git/f32, branch main</title>
<subtitle>AMD PSP reverse engineering, emulator and vulnerability research</subtitle>
<id>https://git.sl0p.foo/amd-psp-re.git/atom/f32?h=main</id>
<link rel='self' href='https://git.sl0p.foo/amd-psp-re.git/atom/f32?h=main'/>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/amd-psp-re.git/'/>
<updated>2026-09-28T14:19:54Z</updated>
<entry>
<title>Synthesise the corpus: test the strongest compound, and reorder the targets</title>
<updated>2026-09-28T14:19:54Z</updated>
<author>
<name>user</name>
<email>user@clank</email>
</author>
<published>2026-09-28T14:19:54Z</published>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/amd-psp-re.git/commit/?id=2bac54abd7ea6f9fbaba4cffe54c252cbf61fa97'/>
<id>urn:sha1:2bac54abd7ea6f9fbaba4cffe54c252cbf61fa97</id>
<content type='text'>
A deliberate pass over all findings asking whether any two combine into
something neither is alone.

The strongest candidate is tested and falsified. FINDING-10 leaks memory with no
memory-safety bug -- it turns an unreadable value into measurable time -- and its
only real limitation is that the DMUB inbox is kernel-only. SDMA's POLL_REGMEM
has the identical shape on queues that ARE user-submittable, and since a poll
writes nothing, the gate covering SRBM_WRITE and POLL_REG_WRITE_MEM need not have
applied to it. On silicon the privileged control shows the oracle plainly (match
0.08 ms vs mismatch 3002 ms) and it vanishes at RB_PRIV=0, where both outcomes
become an indistinguishable hang. SDMA's register boundary is therefore
consistent across write, read-to-memory and read-by-timing -- a stronger claim
than any single probe made.

Recorded alongside it: an untested cross-engine question (SDMA's security is one
bit, DMCUB's types 1/3 are an intentional arbitrary register write -- can one
engine set another's privilege bit?); the systemic pattern that memory is
confined by hardware while registers are confined by firmware convention, which
is exactly what rollback undoes; and that DMUB rollback needs no power cycle,
unlike sOS rollback.

The useful output is a reordered target list. The only user-submittable surfaces
here are SDMA queues (audited, gated) and PM4 -&gt; MEC, which went unaudited only
because MEC was unreadable. It is RV64 and readable now, and the SDMA
methodology transfers directly, so MEC-PM4-FOOTHOLD.md becomes the
highest-expected-value target left.

Rejected compounds are kept too, including FINDING-10 against the HDCP canary
fence (no PSP memory aperture reachable from DMCUB) and FINDING-1 against the
PSR state machine (the host owns CW6 anyway, which lowers FINDING-1's severity).
</content>
</entry>
<entry>
<title>Read the F32 blobs: SDMA audited on hardware, RLC deprioritised</title>
<updated>2026-09-28T13:47:36Z</updated>
<author>
<name>user</name>
<email>user@clank</email>
</author>
<published>2026-09-28T13:47:36Z</published>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/amd-psp-re.git/commit/?id=5d6084877a10e1d7de2e09f9abccaa37ebf3de38'/>
<id>urn:sha1:5d6084877a10e1d7de2e09f9abccaa37ebf3de38</id>
<content type='text'>
Lifts the oldest blocker in this tree. fail0verflow's radeon-tools ships an F32
disassembler written for Sea Islands CP/RLC; it works on gfx11 once containers
are parsed and load bases recovered. Upstream is fetched, not vendored (no
LICENSE in that repo), with our one-hunk fix kept as a patch -- it makes
out-of-range branch targets print as addresses instead of the string "True",
which is what made RLC_G's load base (0x2000) discoverable.

Decode percentage is explicitly not the evidence: an RV64 image scores 78% on
this permissive decoder. ret count and call-target resolution are what
discriminate, and the selftest encodes that with CI-era positive controls.

SDMA, audited end to end with no finding:
  * the 52-packet dispatch table is recovered and validated against
    navi10_sdma_pkt_open.h
  * [HW] SRBM_WRITE writes an arbitrary register, but only with RB_CNTL.RB_PRIV
  * [HW] register reads (POLL_REG_WRITE_MEM) are gated the same way
  * [HW] PTEPDE is ungated and that is correct -- memory writes are confined by
    the queue's VMID page tables, proven by a GCVM L2 fault on a raw physical
    address
  * TH1 has no packet table; its computed register indices are firmware-bounded
  * the F32 register namespace is solved: 4*host_dword_offset + 0x4980,
    validated at 31/54 against a null whose maximum over 400 trials is 14

One lead is retracted with its hardware evidence: POLL_MEM_VERIFY appeared to
use its ABI-reserved 12th dword as a register index, which would have been an
unprivileged arbitrary register write. Two bl calls sit between the load and
the store and the screen was not call-clobber aware. The screen was rebuilt
with per-callee clobber sets, which kills the false positive and leaves exactly
one sink in TH0 -- itself gated.

RLC is read but ranked low: r1 is consumed once per blob versus 370 times in
SDMA TH0, so it has no host packet surface and every input is already
privileged. Its namespace is only ~17% mapped, and an attempt to fit per-block
bases produced 21 mutually inconsistent candidates -- recorded as overfitting.
</content>
</entry>
</feed>
