DF-4029 / resource_index_sim.c
/* * resource_index_sim.c — host-runnable index/pairing proof for DF-4029 * (and the u32 wrap for DF-4030). * * Replicates the SET_RESOURCE loop in r600_packet3_check() * (sys/dev/drm/radeon/r600_cs.c:1953-2013): * reads at idx+1+(i*7)+n (7-dword resource slots, count%7==0) * writes at idx+1+(i*8)+0 and idx+1+(i*8)+2 <-- 8-dword stride (bug) * * Shows, for k slots: * 1. which resource slot / trailing NOP each write lands in; * 2. that the mandatory trailing reloc NOPs (2 dwords each, one per * resource) keep the writes inside the IB (honest scoping: this is a * validated-vs-executed desync inside the IB, not a past-IB write); * 3. the DF-4030 u32 wrap: (size + offset) computed in u32. */ #include <stdio.h> #include <stdint.h> int main(void) { int k = 6; /* 6 VALID_BUFFER resources */ unsigned idx = 2; /* packet body starts after header+offset word */ unsigned body_last = idx + 7 * k; /* last resource dword */ unsigned ib_len_min = body_last + 1 + 2 * k; /* +1 offset word region end + 2 dw per NOP */ printf("SET_RESOURCE: %d buffer slots, idx=%u, body_last=%u, " "min IB length (with %d trailing 2-dw NOP relocs) = %u\n\n", k, idx, body_last, k, ib_len_min); printf(" slot | reads at (i*7) | writes at (i*8) | write lands in\n"); printf("------+---------------------+----------------------+---------------------------\n"); for (int i = 0; i < k; i++) { unsigned r0 = idx + 1 + 7 * i; unsigned w0 = idx + 1 + 8 * i, w2 = w0 + 2; const char *where; if (w2 <= idx + 7 * (i + 1)) where = "own/later slot body (validated as data)"; else if (w2 < ib_len_min) where = "trailing reloc NOP region"; else where = "*** PAST IB END ***"; printf(" %4d | %3u..%3u | %3u, %3u | %s\n", i, r0, r0 + 6, w0, w2, where); } printf("\nmax write index = %u < min IB length %u -> writes stay inside the\n" "IB, but clobber resource words the validator ALREADY checked with\n" "different values (validated/executed desync) and reloc-NOP words.\n", idx + 1 + 8 * (k - 1) + 2, ib_len_min); /* DF-4030 wrap */ uint32_t offset = 0xFFFFFF00u, size = 0x100u; uint32_t sum = size + offset; /* r600_cs.c:2002 — u32 add */ printf("\nDF-4030: offset=0x%08x size=0x%08x -> (size+offset) as u32 = " "0x%08x -> bound check `(sum > bo_size)' %s for bo_size >= 0x1000\n", offset, size, sum, (sum > 0x1000) ? "FAILS" : "PASSES (wrap)"); return 0; } |