|
|
Acting on the synthesis, which put PM4 at the top because it is the only
user-submittable surface left unaudited.
Round 1's table base was 0x100 low -- the same nested-$PS1 error that shifted
every DMCUB address in this tree. At the corrected base 0x415d8 all five of
Round 1's anchor opcodes verify, and 5 of 7 populated slots carry published
PACKET3_* names (MAP_QUEUES, UNMAP_QUEUES, QUERY_STATUS, RUN_LIST,
MAP_PROCESS_VM). At the old base, zero did, which is what makes the naming a
validation rather than a decoration.
That table covers queue management only. Two scans found no second dispatch
structure -- no further (handler, flags) pairs and no plain pointer table that
opcode-indexes onto the enum -- so the remaining packets are dispatched by
compare chains, matching Round 2's reading.
Round 1's suspected per-packet length bound is refuted: MAP_QUEUES carries 2241
where UNMAP/QUERY/RUN_LIST carry 2 and MAP_PROCESS_VM carries 1. Those are not
dword counts for those packets, so the low half is a flags field and the parser's
length validation lives in code.
New tooling (mes/mec_audit.py: table/bounds/taint) taints from the packet data
port 0x6F8(tp) with dataflow that respects both calls and basic blocks. The
block rule was added after the pass produced a striking false lead: a raw packet
dword shifted left 36 into MMIO-aperture bits and used as a store address, which
would have been a host-controlled register write. An unconditional j sits just
before that block, so the base comes from elsewhere; block-awareness removed it
and 16 other sinks. Of the 75 survivors, 27 assemble a 64-bit GPU VA from two
packet dwords and are VM-confined as proven for SDMA.
Still no finding.
|