From 2a681c4f8b56b6f1eb70fbd7ab353be0068867eb Mon Sep 17 00:00:00 2001 From: Jianxun Zhang Date: Tue, 17 Mar 2026 12:42:13 -0700 Subject: [PATCH] intel/decoder: Print more information in shader's headline Print out the kernel start pointer (KSP) and the hash of referenced shader in its headline. This saves some search in GPU hang dumps, base on the work of 72bc74f0be5f4df28b0805f2d501dcc7339e159d and fd11e4b4d31adde062b9f19a8eec82f06f832f00 An example from a decoded GPU hang dump: 0xeffeffefe19c: 0x10000002: MI_STORE_DATA_IMM 0xeffeffefe19c: 0x10000002 : Dword 0 DWord Length: 2 Force Write Completion Check : false Store Qword: 0 Use Global GTT: false 0xeffeffefe1a0: 0xffe000c0 : Dword 1 Core Mode Enable: 0 0xeffeffefe1a4: 0x0000effe : Dword 2 Address: 0xeffeffe000c0 0xeffeffefe1a8: 0x82f94895 : Dword 3 <--- No need to search here 0xeffeffefe1ac: 0x72080025 : Dword 4 Immediate Data: 2197375125 0xeffeffefe1ac: 0x72080025: COMPUTE_WALKER 0xeffeffefe1ac: 0x72080025 : Dword 0 ... body: ... Interface Descriptor: ... 0xeffeffefe1f4: 0x00001f40 : Dword 0 Kernel Start Pointer: 0x00001f40 <--- No need to search here ... 0xeffeffefe244: 0x00000000 : Dword 37 Inline Data[7]: 0 Referenced compute shader (ksp: 0x1f40 hash: 0x7208002582f94895): <- ksp & hash printed here send(1) g3UD g2UD nullUD ... ugm MsgDesc: ( load, a64, d32, V64, ... add(1) g16<2>UD g2<0,1,0>UD 0x00000100UD Note: Shader hash output rquires 'ANV_DEBUG=shader-hash' when running the workload. Signed-off-by: Jianxun Zhang Reviewed-by: Lionel Landwerlin Part-of: --- src/intel/decoder/intel_batch_decoder.c | 24 +++++++++++++++++++++ src/intel/decoder/intel_batch_decoder_gen.c | 20 ++++++++++++++++- src/intel/decoder/intel_decoder.h | 8 +++++++ 3 files changed, 51 insertions(+), 1 deletion(-) diff --git a/src/intel/decoder/intel_batch_decoder.c b/src/intel/decoder/intel_batch_decoder.c index 1296939dbc4..07e9bcb7b98 100644 --- a/src/intel/decoder/intel_batch_decoder.c +++ b/src/intel/decoder/intel_batch_decoder.c @@ -1231,6 +1231,27 @@ decode_load_register_imm(struct intel_batch_decode_ctx *ctx, const uint32_t *p) } } +static void +decode_store_data_imm(struct intel_batch_decode_ctx *ctx, const uint32_t *p) +{ + /* Record a _potential_ shader hash. (We won't know if the data is a hash + * from a dummy MI_STORE_DATA_IMM or a real case of the same command until + * the next command gets parsed.) + * + * Since shader hash injection is supported, a hash was 32 bit and then + * is extended to 64 bit. There is a chance that a decoder supporting 64 + * bit hash is used to parse an older dump generated with 32 bit hash. We + * have to look into the dword length field (bits 9:0 of BG 0) to + * determine the width of the hash. + * + * So far, dword 3 and 4 of MI_STORE_DATA_IMM are defined same way among + * all GFX generations, so we simply use the hard-coded indexes to get + * their values. + */ + uint64_t hash_hi = (*p & 0x3ff) == 2 ? 0 : p[4]; + ctx->shader_hash.hash = (hash_hi << 32) + p[3]; +} + static void disasm_program_from_group(struct intel_batch_decode_ctx *ctx, struct intel_group *strct, const void *map, @@ -1515,6 +1536,7 @@ struct custom_decoder custom_decoders[] = { { "3DSTATE_SCISSOR_STATE_POINTERS", decode_3dstate_scissor_state_pointers }, { "3DSTATE_SLICE_TABLE_STATE_POINTERS", decode_3dstate_slice_table_state_pointers }, { "MI_LOAD_REGISTER_IMM", decode_load_register_imm }, + { "MI_STORE_DATA_IMM", decode_store_data_imm }, { "3DSTATE_PIPELINED_POINTERS", decode_pipelined_pointers }, { "3DSTATE_CPS_POINTERS", decode_cps_pointers }, { "CONSTANT_BUFFER", decode_gfx4_constant_buffer }, @@ -1745,6 +1767,8 @@ intel_print_batch(struct intel_batch_decode_ctx *ctx, } else if (strcmp(inst->name, "MI_BATCH_BUFFER_END") == 0) { break; } + + ctx->shader_hash.last_inst = inst; } ctx->n_batch_buffer_start--; diff --git a/src/intel/decoder/intel_batch_decoder_gen.c b/src/intel/decoder/intel_batch_decoder_gen.c index 6ae50ffb705..6efb230b7b6 100644 --- a/src/intel/decoder/intel_batch_decoder_gen.c +++ b/src/intel/decoder/intel_batch_decoder_gen.c @@ -21,7 +21,25 @@ ctx_disassemble_program_gen(struct intel_batch_decode_ctx *ctx, if (!bo.map) return; - fprintf(ctx->fp, "\nReferenced %s:\n", name); + fprintf(ctx->fp, "\nReferenced %s (ksp: 0x%" PRIx32, name, ksp); + if (ctx->shader_hash.last_inst && + !strcmp(ctx->shader_hash.last_inst->name, "MI_STORE_DATA_IMM")) { + /* We only consider a recorded hash valid when the previously parsed + * instruction is the token. + */ + fprintf(ctx->fp, " hash: 0x%" PRIx64 "): \n", ctx->shader_hash.hash); + /* FIXME: Only the hash of the first shader is available now. + * + * For a targeted shader submission command which can have more than + * one shader, the dummy MI_STORE_DATA_IMM token instruction only + * contains the hash of the first shader. In this case, we invalidate + * the last instruction here so that the following shaders won't be + * printed out with the hash of the first. + */ + ctx->shader_hash.last_inst = NULL; + } else { + fprintf(ctx->fp, "):\n"); + } const int size = gen_find_shader_size(&ctx->devinfo, bo.map, 0, bo.size); if (size > 0) { diff --git a/src/intel/decoder/intel_decoder.h b/src/intel/decoder/intel_decoder.h index 28d29757cdb..402b4092db1 100644 --- a/src/intel/decoder/intel_decoder.h +++ b/src/intel/decoder/intel_decoder.h @@ -255,6 +255,13 @@ struct intel_batch_decode_bo { const void *map; }; +struct intel_batch_decode_hash { + /* Record the previous parsed command for cross-instruction tracking. + */ + const struct intel_group *last_inst; + uint64_t hash; +}; + struct intel_batch_decode_ctx { /** * Return information about the buffer containing the given address. @@ -297,6 +304,7 @@ struct intel_batch_decode_ctx { struct hash_table *commands; struct hash_table *filters; struct hash_table *stats; + struct intel_batch_decode_hash shader_hash; void (*disassemble_program)(struct intel_batch_decode_ctx *ctx, uint32_t ksp,