DF-4031 / strmout_wrap_sim.c
/* * strmout_wrap_sim.c โ host-runnable proof for DF-4031. * * Replicates r600_cs_check_reg() VGT_STRMOUT_BUFFER_SIZE_n handling * (sys/dev/drm/radeon/r600_cs.c:1090-1098) and the streamout check in * r600_cs_track_check() (r600_cs.c:717-736), plus the <<8 offset * truncation family (r600_cs.c:1084, 1281, 1295, 1308). */ #include <stdio.h> #include <stdint.h> int main(void) { uint32_t raw = 0x40000000u; /* VGT_STRMOUT_BUFFER_SIZE_0 value (DWs) */ uint32_t bo_size = 4096; /* r600_cs.c:1096 โ u32 multiply */ uint32_t vgt_strmout_size = raw * 4; /* wraps to 0 */ /* r600_cs.c:721-728 โ the kernel-side bound check */ uint64_t bo_offset = 0; /* base raw = 0 -> <<8 = 0 */ uint64_t offset = (uint64_t)bo_offset + (uint64_t)vgt_strmout_size; printf("VGT_STRMOUT_BUFFER_SIZE_0 = 0x%08x DWs\n", raw); printf("kernel track->vgt_strmout_size = raw*4 (u32) = 0x%08x\n", vgt_strmout_size); printf("kernel check: offset (%llu) > bo_size (%u)? %s -> CS %s\n\n", (unsigned long long)offset, bo_size, offset > bo_size ? "YES" : "NO", offset > bo_size ? "rejected" : "ACCEPTED"); printf("GPU executes the register verbatim: streamout bound = raw*4 = " "%llu bytes = 4 GiB of write space past the 4 KiB BO.\n\n", (unsigned long long)raw * 4ull); /* <<8 truncation family: r600_cs.c:1084,1281,1295,1308 */ uint32_t regval = 0x01000000u; /* CB_COLOR0_BASE / DB_DEPTH_BASE raw */ uint64_t kernel_offset = (uint64_t)(regval << 8); /* u32 shift -> wraps */ uint64_t gpu_offset = (uint64_t)regval << 8; /* 40-bit, no wrap */ printf("<<8 truncation: reg raw = 0x%08x\n", regval); printf(" kernel-tracked offset = (u32)(raw<<8) = 0x%010llx\n", (unsigned long long)kernel_offset); printf(" GPU base offset = (u64)raw<<8 = 0x%010llx\n", (unsigned long long)gpu_offset); printf(" -> every CB/DB/htile/streamout BO-size check validates the\n" " WRONG offset; the GPU addresses %llu bytes away from where\n" " the kernel believes.\n", (unsigned long long)(gpu_offset - kernel_offset)); return 0; } |