freedreno/crashdec: Log IBs to snapshot

Signed-off-by: Rob Clark <rob.clark@oss.qualcomm.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/38450>
This commit is contained in:
Rob Clark 2025-10-15 08:33:51 -07:00 committed by Marge Bot
parent 8c372e8617
commit 74e77ce6a4
2 changed files with 98 additions and 3 deletions

View file

@ -422,6 +422,52 @@ valid_header(uint32_t pkt)
}
}
/**
* Simplified version of the parsing loop in dump_commands(), which simply
* looks for "IB" type packets and logs the target cmdstream buffers.
*/
static void
parse_ibs(uint32_t *dwords, uint32_t sizedwords)
{
int dwords_left = sizedwords;
uint32_t count = 0; /* dword count including packet header */
uint32_t val;
while (dwords_left > 0) {
if (pkt_is_regwrite(dwords[0], &val, &count)) {
/* ignore */
} else if (pkt_is_opcode(dwords[0], &val, &count)) {
const char *name = pktname(val);
if (!strcmp(name, "CP_INDIRECT_BUFFER")) {
uint64_t ibaddr;
uint32_t ibsize;
parse_cp_indirect(&dwords[1], count - 1, &ibaddr, &ibsize);
/* map gpuaddr back to hostptr: */
void *ptr = hostptr(ibaddr);
snapshot_ib(ibaddr, ptr, ibsize);
}
// TODO CP_SET_DRAW_STATE and others?
} else if (pkt_is_type2(dwords[0])) {
/* no-op */
count = 1;
} else {
printf("bad type! %08x\n", dwords[0]);
/* for 5xx+ we can do a passable job of looking for start of next valid
* packet: */
if (options.info->chip >= 5) {
count = find_next_packet(dwords, dwords_left);
} else {
return;
}
}
dwords += count;
dwords_left -= count;
}
}
static void
dump_cmdstream(void)
{
@ -522,7 +568,13 @@ dump_cmdstream(void)
options.ibs[0].size = cmdszdw;
handle_prefetch(buf, cmdszdw);
dump_commands(buf, cmdszdw, 0);
if (snapshot) {
parse_ibs(buf, cmdszdw);
} else {
dump_commands(buf, cmdszdw, 0);
}
free(buf);
}
}
@ -1136,11 +1188,12 @@ decode(void)
static void
decode_finalize(void)
{
snapshot_linux.ptbase = ptbase;
/* Dump cmdstream at the end after we know we've decoded all sections that might
* contain reg vals needed for locating the cmdstream:
*/
if (!snapshot)
dump_cmdstream();
dump_cmdstream();
/* If we are exporting snapshot, finalize it now: */
do_snapshot();
@ -1249,6 +1302,7 @@ main(int argc, char **argv)
if (snapshot) {
freopen("/dev/null", "w", stdout);
verbose = false;
} else if (interactive) {
pager_open();
}

View file

@ -327,6 +327,7 @@ struct snapshot_gmu_version {
*/
static FILE *snapshot;
static uint64_t ptbase = 0x43210000; /* We don't always have a real ttbr0, so fake it */
static inline void
snapshot_write(void *data, size_t sz)
@ -556,6 +557,36 @@ snapshot_gpu_object(uint64_t gpuaddr, uint32_t size, uint32_t *buf)
snapshot_write(buf, size);
}
static struct {
struct snapshot_ib_v2 ib;
uint32_t *dwords;
} ibs[512];
static unsigned nibs;
static inline void
snapshot_ib(uint64_t gpuaddr, uint32_t *dwords, uint32_t sizedwords)
{
int idx;
if (!snapshot || !dwords)
return;
for (idx = 0; idx < nibs; idx++) {
if (ibs[idx].ib.gpuaddr == gpuaddr) {
ibs[idx].ib.size = MAX2(ibs[idx].ib.size, sizedwords);
return;
}
}
assert(idx < ARRAY_SIZE(ibs));
ibs[idx].ib.gpuaddr = gpuaddr;
ibs[idx].ib.size = sizedwords;
ibs[idx].ib.ptbase = ptbase;
ibs[idx].dwords = dwords;
nibs++;
}
static inline void
do_snapshot(void)
{
@ -582,6 +613,16 @@ do_snapshot(void)
snapshot_write(buf, snapshot_rb[i].rbsize * 4);
}
for (unsigned i = 0; i < nibs; i++) {
snapshot_write_sect_header(
SNAPSHOT_SECTION_IB_V2,
sizeof(ibs[i].ib) + (4 * ibs[i].ib.size)
);
snapshot_write(&ibs[i].ib, sizeof(ibs[i].ib));
snapshot_write(ibs[i].dwords, ibs[i].ib.size * 4);
}
snapshot_write_sect_header(SNAPSHOT_SECTION_END, 0);
}