2 * Copyright © 2016 Red Hat.
3 * Copyright © 2016 Bas Nieuwenhuizen
5 * based in part on anv driver which is:
6 * Copyright © 2015 Intel Corporation
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
15 * The above copyright notice and this permission notice (including the next
16 * paragraph) shall be included in all copies or substantial portions of the
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
34 #include "radv_debug.h"
35 #include "radv_shader.h"
37 #define TRACE_BO_SIZE 4096
39 #define COLOR_RESET "\033[0m"
40 #define COLOR_RED "\033[31m"
41 #define COLOR_GREEN "\033[1;32m"
42 #define COLOR_YELLOW "\033[1;33m"
43 #define COLOR_CYAN "\033[1;36m"
45 /* Trace BO layout (offsets are 4 bytes):
47 * [0]: primary trace ID
48 * [1]: secondary trace ID
49 * [2-3]: 64-bit GFX pipeline pointer
50 * [4-5]: 64-bit COMPUTE pipeline pointer
51 * [6-7]: 64-bit descriptor set #0 pointer
53 * [68-69]: 64-bit descriptor set #31 pointer
57 radv_init_trace(struct radv_device
*device
)
59 struct radeon_winsys
*ws
= device
->ws
;
61 device
->trace_bo
= ws
->buffer_create(ws
, TRACE_BO_SIZE
, 8,
63 RADEON_FLAG_CPU_ACCESS
);
64 if (!device
->trace_bo
)
67 device
->trace_id_ptr
= ws
->buffer_map(device
->trace_bo
);
68 if (!device
->trace_id_ptr
)
71 memset(device
->trace_id_ptr
, 0, TRACE_BO_SIZE
);
73 ac_vm_fault_occured(device
->physical_device
->rad_info
.chip_class
,
74 &device
->dmesg_timestamp
, NULL
);
80 radv_dump_trace(struct radv_device
*device
, struct radeon_winsys_cs
*cs
)
82 const char *filename
= getenv("RADV_TRACE_FILE");
83 FILE *f
= fopen(filename
, "w");
86 fprintf(stderr
, "Failed to write trace dump to %s\n", filename
);
90 fprintf(f
, "Trace ID: %x\n", *device
->trace_id_ptr
);
91 device
->ws
->cs_dump(cs
, f
, (const int*)device
->trace_id_ptr
, 2);
96 radv_dump_mmapped_reg(struct radv_device
*device
, FILE *f
, unsigned offset
)
98 struct radeon_winsys
*ws
= device
->ws
;
101 if (ws
->read_registers(ws
, offset
, 1, &value
))
102 ac_dump_reg(f
, device
->physical_device
->rad_info
.chip_class
,
107 radv_dump_debug_registers(struct radv_device
*device
, FILE *f
)
109 struct radeon_info
*info
= &device
->physical_device
->rad_info
;
111 if (info
->drm_major
== 2 && info
->drm_minor
< 42)
112 return; /* no radeon support */
114 fprintf(f
, "Memory-mapped registers:\n");
115 radv_dump_mmapped_reg(device
, f
, R_008010_GRBM_STATUS
);
117 /* No other registers can be read on DRM < 3.1.0. */
118 if (info
->drm_major
< 3 || info
->drm_minor
< 1) {
123 radv_dump_mmapped_reg(device
, f
, R_008008_GRBM_STATUS2
);
124 radv_dump_mmapped_reg(device
, f
, R_008014_GRBM_STATUS_SE0
);
125 radv_dump_mmapped_reg(device
, f
, R_008018_GRBM_STATUS_SE1
);
126 radv_dump_mmapped_reg(device
, f
, R_008038_GRBM_STATUS_SE2
);
127 radv_dump_mmapped_reg(device
, f
, R_00803C_GRBM_STATUS_SE3
);
128 radv_dump_mmapped_reg(device
, f
, R_00D034_SDMA0_STATUS_REG
);
129 radv_dump_mmapped_reg(device
, f
, R_00D834_SDMA1_STATUS_REG
);
130 if (info
->chip_class
<= VI
) {
131 radv_dump_mmapped_reg(device
, f
, R_000E50_SRBM_STATUS
);
132 radv_dump_mmapped_reg(device
, f
, R_000E4C_SRBM_STATUS2
);
133 radv_dump_mmapped_reg(device
, f
, R_000E54_SRBM_STATUS3
);
135 radv_dump_mmapped_reg(device
, f
, R_008680_CP_STAT
);
136 radv_dump_mmapped_reg(device
, f
, R_008674_CP_STALLED_STAT1
);
137 radv_dump_mmapped_reg(device
, f
, R_008678_CP_STALLED_STAT2
);
138 radv_dump_mmapped_reg(device
, f
, R_008670_CP_STALLED_STAT3
);
139 radv_dump_mmapped_reg(device
, f
, R_008210_CP_CPC_STATUS
);
140 radv_dump_mmapped_reg(device
, f
, R_008214_CP_CPC_BUSY_STAT
);
141 radv_dump_mmapped_reg(device
, f
, R_008218_CP_CPC_STALLED_STAT1
);
142 radv_dump_mmapped_reg(device
, f
, R_00821C_CP_CPF_STATUS
);
143 radv_dump_mmapped_reg(device
, f
, R_008220_CP_CPF_BUSY_STAT
);
144 radv_dump_mmapped_reg(device
, f
, R_008224_CP_CPF_STALLED_STAT1
);
148 struct radv_shader_inst
{
149 char text
[160]; /* one disasm line */
150 unsigned offset
; /* instruction offset */
151 unsigned size
; /* instruction size = 4 or 8 */
154 /* Split a disassembly string into lines and add them to the array pointed
155 * to by "instructions". */
156 static void si_add_split_disasm(const char *disasm
,
159 struct radv_shader_inst
*instructions
)
161 struct radv_shader_inst
*last_inst
= *num
? &instructions
[*num
- 1] : NULL
;
164 while ((next
= strchr(disasm
, '\n'))) {
165 struct radv_shader_inst
*inst
= &instructions
[*num
];
166 unsigned len
= next
- disasm
;
168 assert(len
< ARRAY_SIZE(inst
->text
));
169 memcpy(inst
->text
, disasm
, len
);
171 inst
->offset
= last_inst
? last_inst
->offset
+ last_inst
->size
: 0;
173 const char *semicolon
= strchr(disasm
, ';');
175 /* More than 16 chars after ";" means the instruction is 8 bytes long. */
176 inst
->size
= next
- semicolon
> 16 ? 8 : 4;
178 snprintf(inst
->text
+ len
, ARRAY_SIZE(inst
->text
) - len
,
179 " [PC=0x%"PRIx64
", off=%u, size=%u]",
180 start_addr
+ inst
->offset
, inst
->offset
, inst
->size
);
189 radv_dump_annotated_shader(struct radv_pipeline
*pipeline
,
190 struct radv_shader_variant
*shader
,
191 gl_shader_stage stage
,
192 struct ac_wave_info
*waves
, unsigned num_waves
,
195 struct radv_device
*device
= pipeline
->device
;
196 uint64_t start_addr
, end_addr
;
202 start_addr
= device
->ws
->buffer_get_va(shader
->bo
) + shader
->bo_offset
;
203 end_addr
= start_addr
+ shader
->code_size
;
205 /* See if any wave executes the shader. */
206 for (i
= 0; i
< num_waves
; i
++) {
207 if (start_addr
<= waves
[i
].pc
&& waves
[i
].pc
<= end_addr
)
212 return; /* the shader is not being executed */
214 /* Remember the first found wave. The waves are sorted according to PC. */
218 /* Get the list of instructions.
219 * Buffer size / 4 is the upper bound of the instruction count.
221 unsigned num_inst
= 0;
222 struct radv_shader_inst
*instructions
=
223 calloc(shader
->code_size
/ 4, sizeof(struct radv_shader_inst
));
225 si_add_split_disasm(shader
->disasm_string
,
226 start_addr
, &num_inst
, instructions
);
228 fprintf(f
, COLOR_YELLOW
"%s - annotated disassembly:" COLOR_RESET
"\n",
229 radv_get_shader_name(shader
, stage
));
231 /* Print instructions with annotations. */
232 for (i
= 0; i
< num_inst
; i
++) {
233 struct radv_shader_inst
*inst
= &instructions
[i
];
235 fprintf(f
, "%s\n", inst
->text
);
237 /* Print which waves execute the instruction right now. */
238 while (num_waves
&& start_addr
+ inst
->offset
== waves
->pc
) {
240 " " COLOR_GREEN
"^ SE%u SH%u CU%u "
241 "SIMD%u WAVE%u EXEC=%016"PRIx64
" ",
242 waves
->se
, waves
->sh
, waves
->cu
, waves
->simd
,
243 waves
->wave
, waves
->exec
);
245 if (inst
->size
== 4) {
246 fprintf(f
, "INST32=%08X" COLOR_RESET
"\n",
249 fprintf(f
, "INST64=%08X %08X" COLOR_RESET
"\n",
250 waves
->inst_dw0
, waves
->inst_dw1
);
253 waves
->matched
= true;
264 radv_dump_annotated_shaders(struct radv_pipeline
*pipeline
,
265 struct radv_shader_variant
*compute_shader
,
268 struct ac_wave_info waves
[AC_MAX_WAVES_PER_CHIP
];
269 unsigned num_waves
= ac_get_wave_info(waves
);
272 fprintf(f
, COLOR_CYAN
"The number of active waves = %u" COLOR_RESET
275 /* Dump annotated active graphics shaders. */
276 mask
= pipeline
->active_stages
;
278 int stage
= u_bit_scan(&mask
);
280 radv_dump_annotated_shader(pipeline
, pipeline
->shaders
[stage
],
281 stage
, waves
, num_waves
, f
);
284 radv_dump_annotated_shader(pipeline
, compute_shader
,
285 MESA_SHADER_COMPUTE
, waves
, num_waves
, f
);
287 /* Print waves executing shaders that are not currently bound. */
290 for (i
= 0; i
< num_waves
; i
++) {
291 if (waves
[i
].matched
)
295 fprintf(f
, COLOR_CYAN
296 "Waves not executing currently-bound shaders:"
300 fprintf(f
, " SE%u SH%u CU%u SIMD%u WAVE%u EXEC=%016"PRIx64
301 " INST=%08X %08X PC=%"PRIx64
"\n",
302 waves
[i
].se
, waves
[i
].sh
, waves
[i
].cu
, waves
[i
].simd
,
303 waves
[i
].wave
, waves
[i
].exec
, waves
[i
].inst_dw0
,
304 waves
[i
].inst_dw1
, waves
[i
].pc
);
311 radv_dump_shader(struct radv_pipeline
*pipeline
,
312 struct radv_shader_variant
*shader
, gl_shader_stage stage
,
318 fprintf(f
, "%s:\n%s\n\n", radv_get_shader_name(shader
, stage
),
319 shader
->disasm_string
);
321 radv_shader_dump_stats(pipeline
->device
, shader
, stage
, f
);
325 radv_dump_shaders(struct radv_pipeline
*pipeline
,
326 struct radv_shader_variant
*compute_shader
, FILE *f
)
330 /* Dump active graphics shaders. */
331 mask
= pipeline
->active_stages
;
333 int stage
= u_bit_scan(&mask
);
335 radv_dump_shader(pipeline
, pipeline
->shaders
[stage
], stage
, f
);
338 radv_dump_shader(pipeline
, compute_shader
, MESA_SHADER_COMPUTE
, f
);
342 radv_dump_graphics_state(struct radv_pipeline
*graphics_pipeline
,
343 struct radv_pipeline
*compute_pipeline
, FILE *f
)
345 struct radv_shader_variant
*compute_shader
=
346 compute_pipeline
? compute_pipeline
->shaders
[MESA_SHADER_COMPUTE
] : NULL
;
348 if (!graphics_pipeline
)
351 radv_dump_shaders(graphics_pipeline
, compute_shader
, f
);
352 radv_dump_annotated_shaders(graphics_pipeline
, compute_shader
, f
);
356 radv_dump_compute_state(struct radv_pipeline
*compute_pipeline
, FILE *f
)
358 if (!compute_pipeline
)
361 radv_dump_shaders(compute_pipeline
,
362 compute_pipeline
->shaders
[MESA_SHADER_COMPUTE
], f
);
363 radv_dump_annotated_shaders(compute_pipeline
,
364 compute_pipeline
->shaders
[MESA_SHADER_COMPUTE
],
368 static struct radv_pipeline
*
369 radv_get_saved_graphics_pipeline(struct radv_device
*device
)
371 uint64_t *ptr
= (uint64_t *)device
->trace_id_ptr
;
373 return (struct radv_pipeline
*)ptr
[1];
376 static struct radv_pipeline
*
377 radv_get_saved_compute_pipeline(struct radv_device
*device
)
379 uint64_t *ptr
= (uint64_t *)device
->trace_id_ptr
;
381 return (struct radv_pipeline
*)ptr
[2];
385 radv_gpu_hang_occured(struct radv_queue
*queue
, enum ring_type ring
)
387 struct radeon_winsys
*ws
= queue
->device
->ws
;
389 if (!ws
->ctx_wait_idle(queue
->hw_ctx
, ring
, queue
->queue_idx
))
396 radv_check_gpu_hangs(struct radv_queue
*queue
, struct radeon_winsys_cs
*cs
)
398 struct radv_pipeline
*graphics_pipeline
, *compute_pipeline
;
399 struct radv_device
*device
= queue
->device
;
403 ring
= radv_queue_family_to_ring(queue
->queue_family_index
);
405 bool hang_occurred
= radv_gpu_hang_occured(queue
, ring
);
406 bool vm_fault_occurred
= false;
407 if (queue
->device
->instance
->debug_flags
& RADV_DEBUG_VM_FAULTS
)
408 vm_fault_occurred
= ac_vm_fault_occured(device
->physical_device
->rad_info
.chip_class
,
409 &device
->dmesg_timestamp
, &addr
);
410 if (!hang_occurred
&& !vm_fault_occurred
)
413 graphics_pipeline
= radv_get_saved_graphics_pipeline(device
);
414 compute_pipeline
= radv_get_saved_compute_pipeline(device
);
416 if (vm_fault_occurred
) {
417 fprintf(stderr
, "VM fault report.\n\n");
418 fprintf(stderr
, "Failing VM page: 0x%08"PRIx64
"\n\n", addr
);
421 radv_dump_debug_registers(device
, stderr
);
425 radv_dump_graphics_state(graphics_pipeline
, compute_pipeline
,
429 radv_dump_compute_state(compute_pipeline
, stderr
);
436 radv_dump_trace(queue
->device
, cs
);
441 radv_print_spirv(struct radv_shader_module
*module
, FILE *fp
)
443 char path
[] = "/tmp/fileXXXXXX";
444 char line
[2048], command
[128];
448 /* Dump the binary into a temporary file. */
453 if (write(fd
, module
->data
, module
->size
) == -1)
456 sprintf(command
, "spirv-dis %s", path
);
458 /* Disassemble using spirv-dis if installed. */
459 p
= popen(command
, "r");
461 while (fgets(line
, sizeof(line
), p
))
462 fprintf(fp
, "%s", line
);