1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright © 2016 Red Hat.
3bf215546Sopenharmony_ci * Copyright © 2016 Bas Nieuwenhuizen
4bf215546Sopenharmony_ci *
5bf215546Sopenharmony_ci * based in part on anv driver which is:
6bf215546Sopenharmony_ci * Copyright © 2015 Intel Corporation
7bf215546Sopenharmony_ci *
8bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
9bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
10bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
11bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
13bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
14bf215546Sopenharmony_ci *
15bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next
16bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
17bf215546Sopenharmony_ci * Software.
18bf215546Sopenharmony_ci *
19bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
22bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
25bf215546Sopenharmony_ci * IN THE SOFTWARE.
26bf215546Sopenharmony_ci */
27bf215546Sopenharmony_ci
28bf215546Sopenharmony_ci#include <stdio.h>
29bf215546Sopenharmony_ci#include <stdlib.h>
30bf215546Sopenharmony_ci#ifndef _WIN32
31bf215546Sopenharmony_ci#include <sys/utsname.h>
32bf215546Sopenharmony_ci#endif
33bf215546Sopenharmony_ci#include <sys/stat.h>
34bf215546Sopenharmony_ci
35bf215546Sopenharmony_ci#include "util/mesa-sha1.h"
36bf215546Sopenharmony_ci#include "util/os_time.h"
37bf215546Sopenharmony_ci#include "ac_debug.h"
38bf215546Sopenharmony_ci#include "radv_debug.h"
39bf215546Sopenharmony_ci#include "radv_shader.h"
40bf215546Sopenharmony_ci#include "sid.h"
41bf215546Sopenharmony_ci
42bf215546Sopenharmony_ci#define TRACE_BO_SIZE 4096
43bf215546Sopenharmony_ci#define TMA_BO_SIZE   4096
44bf215546Sopenharmony_ci
45bf215546Sopenharmony_ci#define COLOR_RESET  "\033[0m"
46bf215546Sopenharmony_ci#define COLOR_RED    "\033[31m"
47bf215546Sopenharmony_ci#define COLOR_GREEN  "\033[1;32m"
48bf215546Sopenharmony_ci#define COLOR_YELLOW "\033[1;33m"
49bf215546Sopenharmony_ci#define COLOR_CYAN   "\033[1;36m"
50bf215546Sopenharmony_ci
51bf215546Sopenharmony_ci#define RADV_DUMP_DIR "radv_dumps"
52bf215546Sopenharmony_ci
53bf215546Sopenharmony_ci/* Trace BO layout (offsets are 4 bytes):
54bf215546Sopenharmony_ci *
55bf215546Sopenharmony_ci * [0]: primary trace ID
56bf215546Sopenharmony_ci * [1]: secondary trace ID
57bf215546Sopenharmony_ci * [2-3]: 64-bit GFX ring pipeline pointer
58bf215546Sopenharmony_ci * [4-5]: 64-bit COMPUTE ring pipeline pointer
59bf215546Sopenharmony_ci * [6-7]: Vertex descriptors pointer
60bf215546Sopenharmony_ci * [8-9]: 64-bit Vertex prolog pointer
61bf215546Sopenharmony_ci * [10-11]: 64-bit descriptor set #0 pointer
62bf215546Sopenharmony_ci * ...
63bf215546Sopenharmony_ci * [72-73]: 64-bit descriptor set #31 pointer
64bf215546Sopenharmony_ci */
65bf215546Sopenharmony_ci
66bf215546Sopenharmony_cibool
67bf215546Sopenharmony_ciradv_init_trace(struct radv_device *device)
68bf215546Sopenharmony_ci{
69bf215546Sopenharmony_ci   struct radeon_winsys *ws = device->ws;
70bf215546Sopenharmony_ci   VkResult result;
71bf215546Sopenharmony_ci
72bf215546Sopenharmony_ci   result = ws->buffer_create(
73bf215546Sopenharmony_ci      ws, TRACE_BO_SIZE, 8, RADEON_DOMAIN_VRAM,
74bf215546Sopenharmony_ci      RADEON_FLAG_CPU_ACCESS | RADEON_FLAG_NO_INTERPROCESS_SHARING | RADEON_FLAG_ZERO_VRAM |
75bf215546Sopenharmony_ci      RADEON_FLAG_VA_UNCACHED, RADV_BO_PRIORITY_UPLOAD_BUFFER, 0, &device->trace_bo);
76bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
77bf215546Sopenharmony_ci      return false;
78bf215546Sopenharmony_ci
79bf215546Sopenharmony_ci   result = ws->buffer_make_resident(ws, device->trace_bo, true);
80bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
81bf215546Sopenharmony_ci      return false;
82bf215546Sopenharmony_ci
83bf215546Sopenharmony_ci   device->trace_id_ptr = ws->buffer_map(device->trace_bo);
84bf215546Sopenharmony_ci   if (!device->trace_id_ptr)
85bf215546Sopenharmony_ci      return false;
86bf215546Sopenharmony_ci
87bf215546Sopenharmony_ci   ac_vm_fault_occured(device->physical_device->rad_info.gfx_level, &device->dmesg_timestamp, NULL);
88bf215546Sopenharmony_ci
89bf215546Sopenharmony_ci   return true;
90bf215546Sopenharmony_ci}
91bf215546Sopenharmony_ci
92bf215546Sopenharmony_civoid
93bf215546Sopenharmony_ciradv_finish_trace(struct radv_device *device)
94bf215546Sopenharmony_ci{
95bf215546Sopenharmony_ci   struct radeon_winsys *ws = device->ws;
96bf215546Sopenharmony_ci
97bf215546Sopenharmony_ci   if (unlikely(device->trace_bo)) {
98bf215546Sopenharmony_ci      ws->buffer_make_resident(ws, device->trace_bo, false);
99bf215546Sopenharmony_ci      ws->buffer_destroy(ws, device->trace_bo);
100bf215546Sopenharmony_ci   }
101bf215546Sopenharmony_ci}
102bf215546Sopenharmony_ci
103bf215546Sopenharmony_cistatic void
104bf215546Sopenharmony_ciradv_dump_trace(struct radv_device *device, struct radeon_cmdbuf *cs, FILE *f)
105bf215546Sopenharmony_ci{
106bf215546Sopenharmony_ci   fprintf(f, "Trace ID: %x\n", *device->trace_id_ptr);
107bf215546Sopenharmony_ci   device->ws->cs_dump(cs, f, (const int *)device->trace_id_ptr, 2);
108bf215546Sopenharmony_ci}
109bf215546Sopenharmony_ci
110bf215546Sopenharmony_cistatic void
111bf215546Sopenharmony_ciradv_dump_mmapped_reg(struct radv_device *device, FILE *f, unsigned offset)
112bf215546Sopenharmony_ci{
113bf215546Sopenharmony_ci   struct radeon_winsys *ws = device->ws;
114bf215546Sopenharmony_ci   uint32_t value;
115bf215546Sopenharmony_ci
116bf215546Sopenharmony_ci   if (ws->read_registers(ws, offset, 1, &value))
117bf215546Sopenharmony_ci      ac_dump_reg(f, device->physical_device->rad_info.gfx_level, offset, value, ~0);
118bf215546Sopenharmony_ci}
119bf215546Sopenharmony_ci
120bf215546Sopenharmony_cistatic void
121bf215546Sopenharmony_ciradv_dump_debug_registers(struct radv_device *device, FILE *f)
122bf215546Sopenharmony_ci{
123bf215546Sopenharmony_ci   struct radeon_info *info = &device->physical_device->rad_info;
124bf215546Sopenharmony_ci
125bf215546Sopenharmony_ci   fprintf(f, "Memory-mapped registers:\n");
126bf215546Sopenharmony_ci   radv_dump_mmapped_reg(device, f, R_008010_GRBM_STATUS);
127bf215546Sopenharmony_ci
128bf215546Sopenharmony_ci   radv_dump_mmapped_reg(device, f, R_008008_GRBM_STATUS2);
129bf215546Sopenharmony_ci   radv_dump_mmapped_reg(device, f, R_008014_GRBM_STATUS_SE0);
130bf215546Sopenharmony_ci   radv_dump_mmapped_reg(device, f, R_008018_GRBM_STATUS_SE1);
131bf215546Sopenharmony_ci   radv_dump_mmapped_reg(device, f, R_008038_GRBM_STATUS_SE2);
132bf215546Sopenharmony_ci   radv_dump_mmapped_reg(device, f, R_00803C_GRBM_STATUS_SE3);
133bf215546Sopenharmony_ci   radv_dump_mmapped_reg(device, f, R_00D034_SDMA0_STATUS_REG);
134bf215546Sopenharmony_ci   radv_dump_mmapped_reg(device, f, R_00D834_SDMA1_STATUS_REG);
135bf215546Sopenharmony_ci   if (info->gfx_level <= GFX8) {
136bf215546Sopenharmony_ci      radv_dump_mmapped_reg(device, f, R_000E50_SRBM_STATUS);
137bf215546Sopenharmony_ci      radv_dump_mmapped_reg(device, f, R_000E4C_SRBM_STATUS2);
138bf215546Sopenharmony_ci      radv_dump_mmapped_reg(device, f, R_000E54_SRBM_STATUS3);
139bf215546Sopenharmony_ci   }
140bf215546Sopenharmony_ci   radv_dump_mmapped_reg(device, f, R_008680_CP_STAT);
141bf215546Sopenharmony_ci   radv_dump_mmapped_reg(device, f, R_008674_CP_STALLED_STAT1);
142bf215546Sopenharmony_ci   radv_dump_mmapped_reg(device, f, R_008678_CP_STALLED_STAT2);
143bf215546Sopenharmony_ci   radv_dump_mmapped_reg(device, f, R_008670_CP_STALLED_STAT3);
144bf215546Sopenharmony_ci   radv_dump_mmapped_reg(device, f, R_008210_CP_CPC_STATUS);
145bf215546Sopenharmony_ci   radv_dump_mmapped_reg(device, f, R_008214_CP_CPC_BUSY_STAT);
146bf215546Sopenharmony_ci   radv_dump_mmapped_reg(device, f, R_008218_CP_CPC_STALLED_STAT1);
147bf215546Sopenharmony_ci   radv_dump_mmapped_reg(device, f, R_00821C_CP_CPF_STATUS);
148bf215546Sopenharmony_ci   radv_dump_mmapped_reg(device, f, R_008220_CP_CPF_BUSY_STAT);
149bf215546Sopenharmony_ci   radv_dump_mmapped_reg(device, f, R_008224_CP_CPF_STALLED_STAT1);
150bf215546Sopenharmony_ci   fprintf(f, "\n");
151bf215546Sopenharmony_ci}
152bf215546Sopenharmony_ci
153bf215546Sopenharmony_cistatic void
154bf215546Sopenharmony_ciradv_dump_buffer_descriptor(enum amd_gfx_level gfx_level, const uint32_t *desc, FILE *f)
155bf215546Sopenharmony_ci{
156bf215546Sopenharmony_ci   fprintf(f, COLOR_CYAN "    Buffer:" COLOR_RESET "\n");
157bf215546Sopenharmony_ci   for (unsigned j = 0; j < 4; j++)
158bf215546Sopenharmony_ci      ac_dump_reg(f, gfx_level, R_008F00_SQ_BUF_RSRC_WORD0 + j * 4, desc[j], 0xffffffff);
159bf215546Sopenharmony_ci}
160bf215546Sopenharmony_ci
161bf215546Sopenharmony_cistatic void
162bf215546Sopenharmony_ciradv_dump_image_descriptor(enum amd_gfx_level gfx_level, const uint32_t *desc, FILE *f)
163bf215546Sopenharmony_ci{
164bf215546Sopenharmony_ci   unsigned sq_img_rsrc_word0 =
165bf215546Sopenharmony_ci      gfx_level >= GFX10 ? R_00A000_SQ_IMG_RSRC_WORD0 : R_008F10_SQ_IMG_RSRC_WORD0;
166bf215546Sopenharmony_ci
167bf215546Sopenharmony_ci   fprintf(f, COLOR_CYAN "    Image:" COLOR_RESET "\n");
168bf215546Sopenharmony_ci   for (unsigned j = 0; j < 8; j++)
169bf215546Sopenharmony_ci      ac_dump_reg(f, gfx_level, sq_img_rsrc_word0 + j * 4, desc[j], 0xffffffff);
170bf215546Sopenharmony_ci
171bf215546Sopenharmony_ci   fprintf(f, COLOR_CYAN "    FMASK:" COLOR_RESET "\n");
172bf215546Sopenharmony_ci   for (unsigned j = 0; j < 8; j++)
173bf215546Sopenharmony_ci      ac_dump_reg(f, gfx_level, sq_img_rsrc_word0 + j * 4, desc[8 + j], 0xffffffff);
174bf215546Sopenharmony_ci}
175bf215546Sopenharmony_ci
176bf215546Sopenharmony_cistatic void
177bf215546Sopenharmony_ciradv_dump_sampler_descriptor(enum amd_gfx_level gfx_level, const uint32_t *desc, FILE *f)
178bf215546Sopenharmony_ci{
179bf215546Sopenharmony_ci   fprintf(f, COLOR_CYAN "    Sampler state:" COLOR_RESET "\n");
180bf215546Sopenharmony_ci   for (unsigned j = 0; j < 4; j++) {
181bf215546Sopenharmony_ci      ac_dump_reg(f, gfx_level, R_008F30_SQ_IMG_SAMP_WORD0 + j * 4, desc[j], 0xffffffff);
182bf215546Sopenharmony_ci   }
183bf215546Sopenharmony_ci}
184bf215546Sopenharmony_ci
185bf215546Sopenharmony_cistatic void
186bf215546Sopenharmony_ciradv_dump_combined_image_sampler_descriptor(enum amd_gfx_level gfx_level, const uint32_t *desc,
187bf215546Sopenharmony_ci                                            FILE *f)
188bf215546Sopenharmony_ci{
189bf215546Sopenharmony_ci   radv_dump_image_descriptor(gfx_level, desc, f);
190bf215546Sopenharmony_ci   radv_dump_sampler_descriptor(gfx_level, desc + 16, f);
191bf215546Sopenharmony_ci}
192bf215546Sopenharmony_ci
193bf215546Sopenharmony_cistatic void
194bf215546Sopenharmony_ciradv_dump_descriptor_set(struct radv_device *device, struct radv_descriptor_set *set, unsigned id,
195bf215546Sopenharmony_ci                         FILE *f)
196bf215546Sopenharmony_ci{
197bf215546Sopenharmony_ci   enum amd_gfx_level gfx_level = device->physical_device->rad_info.gfx_level;
198bf215546Sopenharmony_ci   const struct radv_descriptor_set_layout *layout;
199bf215546Sopenharmony_ci   int i;
200bf215546Sopenharmony_ci
201bf215546Sopenharmony_ci   if (!set)
202bf215546Sopenharmony_ci      return;
203bf215546Sopenharmony_ci   layout = set->header.layout;
204bf215546Sopenharmony_ci
205bf215546Sopenharmony_ci   for (i = 0; i < set->header.layout->binding_count; i++) {
206bf215546Sopenharmony_ci      uint32_t *desc = set->header.mapped_ptr + layout->binding[i].offset / 4;
207bf215546Sopenharmony_ci
208bf215546Sopenharmony_ci      switch (layout->binding[i].type) {
209bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
210bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
211bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
212bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
213bf215546Sopenharmony_ci         radv_dump_buffer_descriptor(gfx_level, desc, f);
214bf215546Sopenharmony_ci         break;
215bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
216bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
217bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
218bf215546Sopenharmony_ci         radv_dump_image_descriptor(gfx_level, desc, f);
219bf215546Sopenharmony_ci         break;
220bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
221bf215546Sopenharmony_ci         radv_dump_combined_image_sampler_descriptor(gfx_level, desc, f);
222bf215546Sopenharmony_ci         break;
223bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_SAMPLER:
224bf215546Sopenharmony_ci         radv_dump_sampler_descriptor(gfx_level, desc, f);
225bf215546Sopenharmony_ci         break;
226bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
227bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
228bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_MUTABLE_VALVE:
229bf215546Sopenharmony_ci      case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR:
230bf215546Sopenharmony_ci         /* todo */
231bf215546Sopenharmony_ci         break;
232bf215546Sopenharmony_ci      default:
233bf215546Sopenharmony_ci         assert(!"unknown descriptor type");
234bf215546Sopenharmony_ci         break;
235bf215546Sopenharmony_ci      }
236bf215546Sopenharmony_ci      fprintf(f, "\n");
237bf215546Sopenharmony_ci   }
238bf215546Sopenharmony_ci   fprintf(f, "\n\n");
239bf215546Sopenharmony_ci}
240bf215546Sopenharmony_ci
241bf215546Sopenharmony_cistatic void
242bf215546Sopenharmony_ciradv_dump_descriptors(struct radv_device *device, FILE *f)
243bf215546Sopenharmony_ci{
244bf215546Sopenharmony_ci   uint64_t *ptr = (uint64_t *)device->trace_id_ptr;
245bf215546Sopenharmony_ci   int i;
246bf215546Sopenharmony_ci
247bf215546Sopenharmony_ci   fprintf(f, "Descriptors:\n");
248bf215546Sopenharmony_ci   for (i = 0; i < MAX_SETS; i++) {
249bf215546Sopenharmony_ci      struct radv_descriptor_set *set = *(struct radv_descriptor_set **)(ptr + i + 5);
250bf215546Sopenharmony_ci
251bf215546Sopenharmony_ci      radv_dump_descriptor_set(device, set, i, f);
252bf215546Sopenharmony_ci   }
253bf215546Sopenharmony_ci}
254bf215546Sopenharmony_ci
255bf215546Sopenharmony_cistruct radv_shader_inst {
256bf215546Sopenharmony_ci   char text[160];  /* one disasm line */
257bf215546Sopenharmony_ci   unsigned offset; /* instruction offset */
258bf215546Sopenharmony_ci   unsigned size;   /* instruction size = 4 or 8 */
259bf215546Sopenharmony_ci};
260bf215546Sopenharmony_ci
261bf215546Sopenharmony_ci/* Split a disassembly string into lines and add them to the array pointed
262bf215546Sopenharmony_ci * to by "instructions". */
263bf215546Sopenharmony_cistatic void
264bf215546Sopenharmony_cisi_add_split_disasm(const char *disasm, uint64_t start_addr, unsigned *num,
265bf215546Sopenharmony_ci                    struct radv_shader_inst *instructions)
266bf215546Sopenharmony_ci{
267bf215546Sopenharmony_ci   struct radv_shader_inst *last_inst = *num ? &instructions[*num - 1] : NULL;
268bf215546Sopenharmony_ci   char *next;
269bf215546Sopenharmony_ci
270bf215546Sopenharmony_ci   while ((next = strchr(disasm, '\n'))) {
271bf215546Sopenharmony_ci      struct radv_shader_inst *inst = &instructions[*num];
272bf215546Sopenharmony_ci      unsigned len = next - disasm;
273bf215546Sopenharmony_ci
274bf215546Sopenharmony_ci      if (!memchr(disasm, ';', len)) {
275bf215546Sopenharmony_ci         /* Ignore everything that is not an instruction. */
276bf215546Sopenharmony_ci         disasm = next + 1;
277bf215546Sopenharmony_ci         continue;
278bf215546Sopenharmony_ci      }
279bf215546Sopenharmony_ci
280bf215546Sopenharmony_ci      assert(len < ARRAY_SIZE(inst->text));
281bf215546Sopenharmony_ci      memcpy(inst->text, disasm, len);
282bf215546Sopenharmony_ci      inst->text[len] = 0;
283bf215546Sopenharmony_ci      inst->offset = last_inst ? last_inst->offset + last_inst->size : 0;
284bf215546Sopenharmony_ci
285bf215546Sopenharmony_ci      const char *semicolon = strchr(disasm, ';');
286bf215546Sopenharmony_ci      assert(semicolon);
287bf215546Sopenharmony_ci      /* More than 16 chars after ";" means the instruction is 8 bytes long. */
288bf215546Sopenharmony_ci      inst->size = next - semicolon > 16 ? 8 : 4;
289bf215546Sopenharmony_ci
290bf215546Sopenharmony_ci      snprintf(inst->text + len, ARRAY_SIZE(inst->text) - len,
291bf215546Sopenharmony_ci               " [PC=0x%" PRIx64 ", off=%u, size=%u]", start_addr + inst->offset, inst->offset,
292bf215546Sopenharmony_ci               inst->size);
293bf215546Sopenharmony_ci
294bf215546Sopenharmony_ci      last_inst = inst;
295bf215546Sopenharmony_ci      (*num)++;
296bf215546Sopenharmony_ci      disasm = next + 1;
297bf215546Sopenharmony_ci   }
298bf215546Sopenharmony_ci}
299bf215546Sopenharmony_ci
300bf215546Sopenharmony_cistatic void
301bf215546Sopenharmony_ciradv_dump_annotated_shader(struct radv_shader *shader, gl_shader_stage stage,
302bf215546Sopenharmony_ci                           struct ac_wave_info *waves, unsigned num_waves, FILE *f)
303bf215546Sopenharmony_ci{
304bf215546Sopenharmony_ci   uint64_t start_addr, end_addr;
305bf215546Sopenharmony_ci   unsigned i;
306bf215546Sopenharmony_ci
307bf215546Sopenharmony_ci   if (!shader)
308bf215546Sopenharmony_ci      return;
309bf215546Sopenharmony_ci
310bf215546Sopenharmony_ci   start_addr = radv_shader_get_va(shader);
311bf215546Sopenharmony_ci   end_addr = start_addr + shader->code_size;
312bf215546Sopenharmony_ci
313bf215546Sopenharmony_ci   /* See if any wave executes the shader. */
314bf215546Sopenharmony_ci   for (i = 0; i < num_waves; i++) {
315bf215546Sopenharmony_ci      if (start_addr <= waves[i].pc && waves[i].pc <= end_addr)
316bf215546Sopenharmony_ci         break;
317bf215546Sopenharmony_ci   }
318bf215546Sopenharmony_ci
319bf215546Sopenharmony_ci   if (i == num_waves)
320bf215546Sopenharmony_ci      return; /* the shader is not being executed */
321bf215546Sopenharmony_ci
322bf215546Sopenharmony_ci   /* Remember the first found wave. The waves are sorted according to PC. */
323bf215546Sopenharmony_ci   waves = &waves[i];
324bf215546Sopenharmony_ci   num_waves -= i;
325bf215546Sopenharmony_ci
326bf215546Sopenharmony_ci   /* Get the list of instructions.
327bf215546Sopenharmony_ci    * Buffer size / 4 is the upper bound of the instruction count.
328bf215546Sopenharmony_ci    */
329bf215546Sopenharmony_ci   unsigned num_inst = 0;
330bf215546Sopenharmony_ci   struct radv_shader_inst *instructions =
331bf215546Sopenharmony_ci      calloc(shader->code_size / 4, sizeof(struct radv_shader_inst));
332bf215546Sopenharmony_ci
333bf215546Sopenharmony_ci   si_add_split_disasm(shader->disasm_string, start_addr, &num_inst, instructions);
334bf215546Sopenharmony_ci
335bf215546Sopenharmony_ci   fprintf(f, COLOR_YELLOW "%s - annotated disassembly:" COLOR_RESET "\n",
336bf215546Sopenharmony_ci           radv_get_shader_name(&shader->info, stage));
337bf215546Sopenharmony_ci
338bf215546Sopenharmony_ci   /* Print instructions with annotations. */
339bf215546Sopenharmony_ci   for (i = 0; i < num_inst; i++) {
340bf215546Sopenharmony_ci      struct radv_shader_inst *inst = &instructions[i];
341bf215546Sopenharmony_ci
342bf215546Sopenharmony_ci      fprintf(f, "%s\n", inst->text);
343bf215546Sopenharmony_ci
344bf215546Sopenharmony_ci      /* Print which waves execute the instruction right now. */
345bf215546Sopenharmony_ci      while (num_waves && start_addr + inst->offset == waves->pc) {
346bf215546Sopenharmony_ci         fprintf(f,
347bf215546Sopenharmony_ci                 "          " COLOR_GREEN "^ SE%u SH%u CU%u "
348bf215546Sopenharmony_ci                 "SIMD%u WAVE%u  EXEC=%016" PRIx64 "  ",
349bf215546Sopenharmony_ci                 waves->se, waves->sh, waves->cu, waves->simd, waves->wave, waves->exec);
350bf215546Sopenharmony_ci
351bf215546Sopenharmony_ci         if (inst->size == 4) {
352bf215546Sopenharmony_ci            fprintf(f, "INST32=%08X" COLOR_RESET "\n", waves->inst_dw0);
353bf215546Sopenharmony_ci         } else {
354bf215546Sopenharmony_ci            fprintf(f, "INST64=%08X %08X" COLOR_RESET "\n", waves->inst_dw0, waves->inst_dw1);
355bf215546Sopenharmony_ci         }
356bf215546Sopenharmony_ci
357bf215546Sopenharmony_ci         waves->matched = true;
358bf215546Sopenharmony_ci         waves = &waves[1];
359bf215546Sopenharmony_ci         num_waves--;
360bf215546Sopenharmony_ci      }
361bf215546Sopenharmony_ci   }
362bf215546Sopenharmony_ci
363bf215546Sopenharmony_ci   fprintf(f, "\n\n");
364bf215546Sopenharmony_ci   free(instructions);
365bf215546Sopenharmony_ci}
366bf215546Sopenharmony_ci
367bf215546Sopenharmony_cistatic void
368bf215546Sopenharmony_ciradv_dump_annotated_shaders(struct radv_pipeline *pipeline, VkShaderStageFlagBits active_stages,
369bf215546Sopenharmony_ci                            FILE *f)
370bf215546Sopenharmony_ci{
371bf215546Sopenharmony_ci   struct ac_wave_info waves[AC_MAX_WAVES_PER_CHIP];
372bf215546Sopenharmony_ci   enum amd_gfx_level gfx_level = pipeline->device->physical_device->rad_info.gfx_level;
373bf215546Sopenharmony_ci   unsigned num_waves = ac_get_wave_info(gfx_level, waves);
374bf215546Sopenharmony_ci
375bf215546Sopenharmony_ci   fprintf(f, COLOR_CYAN "The number of active waves = %u" COLOR_RESET "\n\n", num_waves);
376bf215546Sopenharmony_ci
377bf215546Sopenharmony_ci   /* Dump annotated active graphics shaders. */
378bf215546Sopenharmony_ci   unsigned stages = active_stages;
379bf215546Sopenharmony_ci   while (stages) {
380bf215546Sopenharmony_ci      int stage = u_bit_scan(&stages);
381bf215546Sopenharmony_ci
382bf215546Sopenharmony_ci      radv_dump_annotated_shader(pipeline->shaders[stage], stage, waves, num_waves, f);
383bf215546Sopenharmony_ci   }
384bf215546Sopenharmony_ci
385bf215546Sopenharmony_ci   /* Print waves executing shaders that are not currently bound. */
386bf215546Sopenharmony_ci   unsigned i;
387bf215546Sopenharmony_ci   bool found = false;
388bf215546Sopenharmony_ci   for (i = 0; i < num_waves; i++) {
389bf215546Sopenharmony_ci      if (waves[i].matched)
390bf215546Sopenharmony_ci         continue;
391bf215546Sopenharmony_ci
392bf215546Sopenharmony_ci      if (!found) {
393bf215546Sopenharmony_ci         fprintf(f, COLOR_CYAN "Waves not executing currently-bound shaders:" COLOR_RESET "\n");
394bf215546Sopenharmony_ci         found = true;
395bf215546Sopenharmony_ci      }
396bf215546Sopenharmony_ci      fprintf(f,
397bf215546Sopenharmony_ci              "    SE%u SH%u CU%u SIMD%u WAVE%u  EXEC=%016" PRIx64 "  INST=%08X %08X  PC=%" PRIx64
398bf215546Sopenharmony_ci              "\n",
399bf215546Sopenharmony_ci              waves[i].se, waves[i].sh, waves[i].cu, waves[i].simd, waves[i].wave, waves[i].exec,
400bf215546Sopenharmony_ci              waves[i].inst_dw0, waves[i].inst_dw1, waves[i].pc);
401bf215546Sopenharmony_ci   }
402bf215546Sopenharmony_ci   if (found)
403bf215546Sopenharmony_ci      fprintf(f, "\n\n");
404bf215546Sopenharmony_ci}
405bf215546Sopenharmony_ci
406bf215546Sopenharmony_cistatic void
407bf215546Sopenharmony_ciradv_dump_spirv(struct radv_shader *shader, const char *sha1, const char *dump_dir)
408bf215546Sopenharmony_ci{
409bf215546Sopenharmony_ci   char dump_path[512];
410bf215546Sopenharmony_ci   FILE *f;
411bf215546Sopenharmony_ci
412bf215546Sopenharmony_ci   snprintf(dump_path, sizeof(dump_path), "%s/%s.spv", dump_dir, sha1);
413bf215546Sopenharmony_ci
414bf215546Sopenharmony_ci   f = fopen(dump_path, "w+");
415bf215546Sopenharmony_ci   if (f) {
416bf215546Sopenharmony_ci      fwrite(shader->spirv, shader->spirv_size, 1, f);
417bf215546Sopenharmony_ci      fclose(f);
418bf215546Sopenharmony_ci   }
419bf215546Sopenharmony_ci}
420bf215546Sopenharmony_ci
421bf215546Sopenharmony_cistatic void
422bf215546Sopenharmony_ciradv_dump_shader(struct radv_pipeline *pipeline, struct radv_shader *shader,
423bf215546Sopenharmony_ci                 gl_shader_stage stage, const char *dump_dir, FILE *f)
424bf215546Sopenharmony_ci{
425bf215546Sopenharmony_ci   if (!shader)
426bf215546Sopenharmony_ci      return;
427bf215546Sopenharmony_ci
428bf215546Sopenharmony_ci   fprintf(f, "%s:\n\n", radv_get_shader_name(&shader->info, stage));
429bf215546Sopenharmony_ci
430bf215546Sopenharmony_ci   if (shader->spirv) {
431bf215546Sopenharmony_ci      unsigned char sha1[21];
432bf215546Sopenharmony_ci      char sha1buf[41];
433bf215546Sopenharmony_ci
434bf215546Sopenharmony_ci      _mesa_sha1_compute(shader->spirv, shader->spirv_size, sha1);
435bf215546Sopenharmony_ci      _mesa_sha1_format(sha1buf, sha1);
436bf215546Sopenharmony_ci
437bf215546Sopenharmony_ci      fprintf(f, "SPIRV (see %s.spv)\n\n", sha1buf);
438bf215546Sopenharmony_ci      radv_dump_spirv(shader, sha1buf, dump_dir);
439bf215546Sopenharmony_ci   }
440bf215546Sopenharmony_ci
441bf215546Sopenharmony_ci   if (shader->nir_string) {
442bf215546Sopenharmony_ci      fprintf(f, "NIR:\n%s\n", shader->nir_string);
443bf215546Sopenharmony_ci   }
444bf215546Sopenharmony_ci
445bf215546Sopenharmony_ci   fprintf(f, "%s IR:\n%s\n", pipeline->device->physical_device->use_llvm ? "LLVM" : "ACO",
446bf215546Sopenharmony_ci           shader->ir_string);
447bf215546Sopenharmony_ci   fprintf(f, "DISASM:\n%s\n", shader->disasm_string);
448bf215546Sopenharmony_ci
449bf215546Sopenharmony_ci   radv_dump_shader_stats(pipeline->device, pipeline, stage, f);
450bf215546Sopenharmony_ci}
451bf215546Sopenharmony_ci
452bf215546Sopenharmony_cistatic void
453bf215546Sopenharmony_ciradv_dump_shaders(struct radv_pipeline *pipeline, VkShaderStageFlagBits active_stages,
454bf215546Sopenharmony_ci                  const char *dump_dir, FILE *f)
455bf215546Sopenharmony_ci{
456bf215546Sopenharmony_ci   /* Dump active graphics shaders. */
457bf215546Sopenharmony_ci   unsigned stages = active_stages;
458bf215546Sopenharmony_ci   while (stages) {
459bf215546Sopenharmony_ci      int stage = u_bit_scan(&stages);
460bf215546Sopenharmony_ci
461bf215546Sopenharmony_ci      radv_dump_shader(pipeline, pipeline->shaders[stage], stage, dump_dir, f);
462bf215546Sopenharmony_ci   }
463bf215546Sopenharmony_ci}
464bf215546Sopenharmony_ci
465bf215546Sopenharmony_cistatic void
466bf215546Sopenharmony_ciradv_dump_vertex_descriptors(struct radv_graphics_pipeline *pipeline, FILE *f)
467bf215546Sopenharmony_ci{
468bf215546Sopenharmony_ci   void *ptr = (uint64_t *)pipeline->base.device->trace_id_ptr;
469bf215546Sopenharmony_ci   uint32_t count = util_bitcount(pipeline->vb_desc_usage_mask);
470bf215546Sopenharmony_ci   uint32_t *vb_ptr = &((uint32_t *)ptr)[3];
471bf215546Sopenharmony_ci
472bf215546Sopenharmony_ci   if (!count)
473bf215546Sopenharmony_ci      return;
474bf215546Sopenharmony_ci
475bf215546Sopenharmony_ci   fprintf(f, "Num vertex %s: %d\n",
476bf215546Sopenharmony_ci           pipeline->use_per_attribute_vb_descs ? "attributes" : "bindings", count);
477bf215546Sopenharmony_ci   for (uint32_t i = 0; i < count; i++) {
478bf215546Sopenharmony_ci      uint32_t *desc = &((uint32_t *)vb_ptr)[i * 4];
479bf215546Sopenharmony_ci      uint64_t va = 0;
480bf215546Sopenharmony_ci
481bf215546Sopenharmony_ci      va |= desc[0];
482bf215546Sopenharmony_ci      va |= (uint64_t)G_008F04_BASE_ADDRESS_HI(desc[1]) << 32;
483bf215546Sopenharmony_ci
484bf215546Sopenharmony_ci      fprintf(f, "VBO#%d:\n", i);
485bf215546Sopenharmony_ci      fprintf(f, "\tVA: 0x%" PRIx64 "\n", va);
486bf215546Sopenharmony_ci      fprintf(f, "\tStride: %d\n", G_008F04_STRIDE(desc[1]));
487bf215546Sopenharmony_ci      fprintf(f, "\tNum records: %d (0x%x)\n", desc[2], desc[2]);
488bf215546Sopenharmony_ci   }
489bf215546Sopenharmony_ci}
490bf215546Sopenharmony_ci
491bf215546Sopenharmony_cistatic struct radv_shader_part *
492bf215546Sopenharmony_ciradv_get_saved_vs_prolog(struct radv_device *device)
493bf215546Sopenharmony_ci{
494bf215546Sopenharmony_ci   uint64_t *ptr = (uint64_t *)device->trace_id_ptr;
495bf215546Sopenharmony_ci   return *(struct radv_shader_part **)(ptr + 4);
496bf215546Sopenharmony_ci}
497bf215546Sopenharmony_ci
498bf215546Sopenharmony_cistatic void
499bf215546Sopenharmony_ciradv_dump_vs_prolog(struct radv_pipeline *pipeline, FILE *f)
500bf215546Sopenharmony_ci{
501bf215546Sopenharmony_ci   struct radv_shader_part *vs_prolog = radv_get_saved_vs_prolog(pipeline->device);
502bf215546Sopenharmony_ci   struct radv_shader *vs_shader = radv_get_shader(pipeline, MESA_SHADER_VERTEX);
503bf215546Sopenharmony_ci
504bf215546Sopenharmony_ci   if (!vs_prolog || !vs_shader || !vs_shader->info.vs.has_prolog)
505bf215546Sopenharmony_ci      return;
506bf215546Sopenharmony_ci
507bf215546Sopenharmony_ci   fprintf(f, "Vertex prolog:\n\n");
508bf215546Sopenharmony_ci   fprintf(f, "DISASM:\n%s\n", vs_prolog->disasm_string);
509bf215546Sopenharmony_ci}
510bf215546Sopenharmony_ci
511bf215546Sopenharmony_cistatic struct radv_pipeline *
512bf215546Sopenharmony_ciradv_get_saved_pipeline(struct radv_device *device, enum amd_ip_type ring)
513bf215546Sopenharmony_ci{
514bf215546Sopenharmony_ci   uint64_t *ptr = (uint64_t *)device->trace_id_ptr;
515bf215546Sopenharmony_ci   int offset = ring == AMD_IP_GFX ? 1 : 2;
516bf215546Sopenharmony_ci
517bf215546Sopenharmony_ci   return *(struct radv_pipeline **)(ptr + offset);
518bf215546Sopenharmony_ci}
519bf215546Sopenharmony_ci
520bf215546Sopenharmony_cistatic void
521bf215546Sopenharmony_ciradv_dump_queue_state(struct radv_queue *queue, const char *dump_dir, FILE *f)
522bf215546Sopenharmony_ci{
523bf215546Sopenharmony_ci   enum amd_ip_type ring = radv_queue_ring(queue);
524bf215546Sopenharmony_ci   struct radv_pipeline *pipeline;
525bf215546Sopenharmony_ci
526bf215546Sopenharmony_ci   fprintf(f, "AMD_IP_%s:\n", ring == AMD_IP_GFX ? "GFX" : "COMPUTE");
527bf215546Sopenharmony_ci
528bf215546Sopenharmony_ci   pipeline = radv_get_saved_pipeline(queue->device, ring);
529bf215546Sopenharmony_ci   if (pipeline) {
530bf215546Sopenharmony_ci      struct radv_graphics_pipeline *graphics_pipeline = radv_pipeline_to_graphics(pipeline);
531bf215546Sopenharmony_ci      VkShaderStageFlags active_stages;
532bf215546Sopenharmony_ci
533bf215546Sopenharmony_ci      if (pipeline->type == RADV_PIPELINE_GRAPHICS) {
534bf215546Sopenharmony_ci         active_stages = graphics_pipeline->active_stages;
535bf215546Sopenharmony_ci      } else {
536bf215546Sopenharmony_ci         active_stages = VK_SHADER_STAGE_COMPUTE_BIT;
537bf215546Sopenharmony_ci      }
538bf215546Sopenharmony_ci
539bf215546Sopenharmony_ci      radv_dump_vs_prolog(pipeline, f);
540bf215546Sopenharmony_ci      radv_dump_shaders(pipeline, active_stages, dump_dir, f);
541bf215546Sopenharmony_ci      if (!(queue->device->instance->debug_flags & RADV_DEBUG_NO_UMR))
542bf215546Sopenharmony_ci         radv_dump_annotated_shaders(pipeline, active_stages, f);
543bf215546Sopenharmony_ci      radv_dump_vertex_descriptors(graphics_pipeline, f);
544bf215546Sopenharmony_ci      radv_dump_descriptors(queue->device, f);
545bf215546Sopenharmony_ci   }
546bf215546Sopenharmony_ci}
547bf215546Sopenharmony_ci
548bf215546Sopenharmony_cistatic void
549bf215546Sopenharmony_ciradv_dump_cmd(const char *cmd, FILE *f)
550bf215546Sopenharmony_ci{
551bf215546Sopenharmony_ci#ifndef _WIN32
552bf215546Sopenharmony_ci   char line[2048];
553bf215546Sopenharmony_ci   FILE *p;
554bf215546Sopenharmony_ci
555bf215546Sopenharmony_ci   p = popen(cmd, "r");
556bf215546Sopenharmony_ci   if (p) {
557bf215546Sopenharmony_ci      while (fgets(line, sizeof(line), p))
558bf215546Sopenharmony_ci         fputs(line, f);
559bf215546Sopenharmony_ci      fprintf(f, "\n");
560bf215546Sopenharmony_ci      pclose(p);
561bf215546Sopenharmony_ci   }
562bf215546Sopenharmony_ci#endif
563bf215546Sopenharmony_ci}
564bf215546Sopenharmony_ci
565bf215546Sopenharmony_cistatic void
566bf215546Sopenharmony_ciradv_dump_dmesg(FILE *f)
567bf215546Sopenharmony_ci{
568bf215546Sopenharmony_ci   fprintf(f, "\nLast 60 lines of dmesg:\n\n");
569bf215546Sopenharmony_ci   radv_dump_cmd("dmesg | tail -n60", f);
570bf215546Sopenharmony_ci}
571bf215546Sopenharmony_ci
572bf215546Sopenharmony_civoid
573bf215546Sopenharmony_ciradv_dump_enabled_options(struct radv_device *device, FILE *f)
574bf215546Sopenharmony_ci{
575bf215546Sopenharmony_ci   uint64_t mask;
576bf215546Sopenharmony_ci
577bf215546Sopenharmony_ci   if (device->instance->debug_flags) {
578bf215546Sopenharmony_ci      fprintf(f, "Enabled debug options: ");
579bf215546Sopenharmony_ci
580bf215546Sopenharmony_ci      mask = device->instance->debug_flags;
581bf215546Sopenharmony_ci      while (mask) {
582bf215546Sopenharmony_ci         int i = u_bit_scan64(&mask);
583bf215546Sopenharmony_ci         fprintf(f, "%s, ", radv_get_debug_option_name(i));
584bf215546Sopenharmony_ci      }
585bf215546Sopenharmony_ci      fprintf(f, "\n");
586bf215546Sopenharmony_ci   }
587bf215546Sopenharmony_ci
588bf215546Sopenharmony_ci   if (device->instance->perftest_flags) {
589bf215546Sopenharmony_ci      fprintf(f, "Enabled perftest options: ");
590bf215546Sopenharmony_ci
591bf215546Sopenharmony_ci      mask = device->instance->perftest_flags;
592bf215546Sopenharmony_ci      while (mask) {
593bf215546Sopenharmony_ci         int i = u_bit_scan64(&mask);
594bf215546Sopenharmony_ci         fprintf(f, "%s, ", radv_get_perftest_option_name(i));
595bf215546Sopenharmony_ci      }
596bf215546Sopenharmony_ci      fprintf(f, "\n");
597bf215546Sopenharmony_ci   }
598bf215546Sopenharmony_ci}
599bf215546Sopenharmony_ci
600bf215546Sopenharmony_cistatic void
601bf215546Sopenharmony_ciradv_dump_app_info(struct radv_device *device, FILE *f)
602bf215546Sopenharmony_ci{
603bf215546Sopenharmony_ci   struct radv_instance *instance = device->instance;
604bf215546Sopenharmony_ci
605bf215546Sopenharmony_ci   fprintf(f, "Application name: %s\n", instance->vk.app_info.app_name);
606bf215546Sopenharmony_ci   fprintf(f, "Application version: %d\n", instance->vk.app_info.app_version);
607bf215546Sopenharmony_ci   fprintf(f, "Engine name: %s\n", instance->vk.app_info.engine_name);
608bf215546Sopenharmony_ci   fprintf(f, "Engine version: %d\n", instance->vk.app_info.engine_version);
609bf215546Sopenharmony_ci   fprintf(f, "API version: %d.%d.%d\n", VK_VERSION_MAJOR(instance->vk.app_info.api_version),
610bf215546Sopenharmony_ci           VK_VERSION_MINOR(instance->vk.app_info.api_version),
611bf215546Sopenharmony_ci           VK_VERSION_PATCH(instance->vk.app_info.api_version));
612bf215546Sopenharmony_ci
613bf215546Sopenharmony_ci   radv_dump_enabled_options(device, f);
614bf215546Sopenharmony_ci}
615bf215546Sopenharmony_ci
616bf215546Sopenharmony_cistatic void
617bf215546Sopenharmony_ciradv_dump_device_name(struct radv_device *device, FILE *f)
618bf215546Sopenharmony_ci{
619bf215546Sopenharmony_ci   struct radeon_info *info = &device->physical_device->rad_info;
620bf215546Sopenharmony_ci#ifndef _WIN32
621bf215546Sopenharmony_ci   char kernel_version[128] = {0};
622bf215546Sopenharmony_ci   struct utsname uname_data;
623bf215546Sopenharmony_ci#endif
624bf215546Sopenharmony_ci
625bf215546Sopenharmony_ci#ifdef _WIN32
626bf215546Sopenharmony_ci   fprintf(f, "Device name: %s (DRM %i.%i.%i)\n\n", device->physical_device->marketing_name,
627bf215546Sopenharmony_ci           info->drm_major, info->drm_minor, info->drm_patchlevel);
628bf215546Sopenharmony_ci#else
629bf215546Sopenharmony_ci   if (uname(&uname_data) == 0)
630bf215546Sopenharmony_ci      snprintf(kernel_version, sizeof(kernel_version), " / %s", uname_data.release);
631bf215546Sopenharmony_ci
632bf215546Sopenharmony_ci   fprintf(f, "Device name: %s (DRM %i.%i.%i%s)\n\n", device->physical_device->marketing_name,
633bf215546Sopenharmony_ci           info->drm_major, info->drm_minor, info->drm_patchlevel, kernel_version);
634bf215546Sopenharmony_ci#endif
635bf215546Sopenharmony_ci}
636bf215546Sopenharmony_ci
637bf215546Sopenharmony_cistatic void
638bf215546Sopenharmony_ciradv_dump_umr_ring(struct radv_queue *queue, FILE *f)
639bf215546Sopenharmony_ci{
640bf215546Sopenharmony_ci   enum amd_ip_type ring = radv_queue_ring(queue);
641bf215546Sopenharmony_ci   struct radv_device *device = queue->device;
642bf215546Sopenharmony_ci   char cmd[128];
643bf215546Sopenharmony_ci
644bf215546Sopenharmony_ci   /* TODO: Dump compute ring. */
645bf215546Sopenharmony_ci   if (ring != AMD_IP_GFX)
646bf215546Sopenharmony_ci      return;
647bf215546Sopenharmony_ci
648bf215546Sopenharmony_ci   sprintf(cmd, "umr -R %s 2>&1",
649bf215546Sopenharmony_ci           device->physical_device->rad_info.gfx_level >= GFX10 ? "gfx_0.0.0" : "gfx");
650bf215546Sopenharmony_ci
651bf215546Sopenharmony_ci   fprintf(f, "\nUMR GFX ring:\n\n");
652bf215546Sopenharmony_ci   radv_dump_cmd(cmd, f);
653bf215546Sopenharmony_ci}
654bf215546Sopenharmony_ci
655bf215546Sopenharmony_cistatic void
656bf215546Sopenharmony_ciradv_dump_umr_waves(struct radv_queue *queue, FILE *f)
657bf215546Sopenharmony_ci{
658bf215546Sopenharmony_ci   enum amd_ip_type ring = radv_queue_ring(queue);
659bf215546Sopenharmony_ci   struct radv_device *device = queue->device;
660bf215546Sopenharmony_ci   char cmd[128];
661bf215546Sopenharmony_ci
662bf215546Sopenharmony_ci   /* TODO: Dump compute ring. */
663bf215546Sopenharmony_ci   if (ring != AMD_IP_GFX)
664bf215546Sopenharmony_ci      return;
665bf215546Sopenharmony_ci
666bf215546Sopenharmony_ci   sprintf(cmd, "umr -O bits,halt_waves -go 0 -wa %s -go 1 2>&1",
667bf215546Sopenharmony_ci           device->physical_device->rad_info.gfx_level >= GFX10 ? "gfx_0.0.0" : "gfx");
668bf215546Sopenharmony_ci
669bf215546Sopenharmony_ci   fprintf(f, "\nUMR GFX waves:\n\n");
670bf215546Sopenharmony_ci   radv_dump_cmd(cmd, f);
671bf215546Sopenharmony_ci}
672bf215546Sopenharmony_ci
673bf215546Sopenharmony_cistatic bool
674bf215546Sopenharmony_ciradv_gpu_hang_occured(struct radv_queue *queue, enum amd_ip_type ring)
675bf215546Sopenharmony_ci{
676bf215546Sopenharmony_ci   struct radeon_winsys *ws = queue->device->ws;
677bf215546Sopenharmony_ci
678bf215546Sopenharmony_ci   if (!ws->ctx_wait_idle(queue->hw_ctx, ring, queue->vk.index_in_family))
679bf215546Sopenharmony_ci      return true;
680bf215546Sopenharmony_ci
681bf215546Sopenharmony_ci   return false;
682bf215546Sopenharmony_ci}
683bf215546Sopenharmony_ci
684bf215546Sopenharmony_civoid
685bf215546Sopenharmony_ciradv_check_gpu_hangs(struct radv_queue *queue, struct radeon_cmdbuf *cs)
686bf215546Sopenharmony_ci{
687bf215546Sopenharmony_ci   struct radv_device *device = queue->device;
688bf215546Sopenharmony_ci   enum amd_ip_type ring;
689bf215546Sopenharmony_ci   uint64_t addr;
690bf215546Sopenharmony_ci
691bf215546Sopenharmony_ci   ring = radv_queue_ring(queue);
692bf215546Sopenharmony_ci
693bf215546Sopenharmony_ci   bool hang_occurred = radv_gpu_hang_occured(queue, ring);
694bf215546Sopenharmony_ci   bool vm_fault_occurred = false;
695bf215546Sopenharmony_ci   if (queue->device->instance->debug_flags & RADV_DEBUG_VM_FAULTS)
696bf215546Sopenharmony_ci      vm_fault_occurred = ac_vm_fault_occured(device->physical_device->rad_info.gfx_level,
697bf215546Sopenharmony_ci                                              &device->dmesg_timestamp, &addr);
698bf215546Sopenharmony_ci   if (!hang_occurred && !vm_fault_occurred)
699bf215546Sopenharmony_ci      return;
700bf215546Sopenharmony_ci
701bf215546Sopenharmony_ci   fprintf(stderr, "radv: GPU hang detected...\n");
702bf215546Sopenharmony_ci
703bf215546Sopenharmony_ci#ifndef _WIN32
704bf215546Sopenharmony_ci   /* Create a directory into $HOME/radv_dumps_<pid>_<time> to save
705bf215546Sopenharmony_ci    * various debugging info about that GPU hang.
706bf215546Sopenharmony_ci    */
707bf215546Sopenharmony_ci   struct tm *timep, result;
708bf215546Sopenharmony_ci   time_t raw_time;
709bf215546Sopenharmony_ci   FILE *f;
710bf215546Sopenharmony_ci   char dump_dir[256], dump_path[512], buf_time[128];
711bf215546Sopenharmony_ci
712bf215546Sopenharmony_ci   time(&raw_time);
713bf215546Sopenharmony_ci   timep = os_localtime(&raw_time, &result);
714bf215546Sopenharmony_ci   strftime(buf_time, sizeof(buf_time), "%Y.%m.%d_%H.%M.%S", timep);
715bf215546Sopenharmony_ci
716bf215546Sopenharmony_ci   snprintf(dump_dir, sizeof(dump_dir), "%s/" RADV_DUMP_DIR "_%d_%s", debug_get_option("HOME", "."),
717bf215546Sopenharmony_ci            getpid(), buf_time);
718bf215546Sopenharmony_ci   if (mkdir(dump_dir, 0774) && errno != EEXIST) {
719bf215546Sopenharmony_ci      fprintf(stderr, "radv: can't create directory '%s' (%i).\n", dump_dir, errno);
720bf215546Sopenharmony_ci      abort();
721bf215546Sopenharmony_ci   }
722bf215546Sopenharmony_ci
723bf215546Sopenharmony_ci   fprintf(stderr, "radv: GPU hang report will be saved to '%s'!\n", dump_dir);
724bf215546Sopenharmony_ci
725bf215546Sopenharmony_ci   /* Dump trace file. */
726bf215546Sopenharmony_ci   snprintf(dump_path, sizeof(dump_path), "%s/%s", dump_dir, "trace.log");
727bf215546Sopenharmony_ci   f = fopen(dump_path, "w+");
728bf215546Sopenharmony_ci   if (f) {
729bf215546Sopenharmony_ci      radv_dump_trace(queue->device, cs, f);
730bf215546Sopenharmony_ci      fclose(f);
731bf215546Sopenharmony_ci   }
732bf215546Sopenharmony_ci
733bf215546Sopenharmony_ci   /* Dump pipeline state. */
734bf215546Sopenharmony_ci   snprintf(dump_path, sizeof(dump_path), "%s/%s", dump_dir, "pipeline.log");
735bf215546Sopenharmony_ci   f = fopen(dump_path, "w+");
736bf215546Sopenharmony_ci   if (f) {
737bf215546Sopenharmony_ci      radv_dump_queue_state(queue, dump_dir, f);
738bf215546Sopenharmony_ci      fclose(f);
739bf215546Sopenharmony_ci   }
740bf215546Sopenharmony_ci
741bf215546Sopenharmony_ci   if (!(device->instance->debug_flags & RADV_DEBUG_NO_UMR)) {
742bf215546Sopenharmony_ci      /* Dump UMR waves. */
743bf215546Sopenharmony_ci      snprintf(dump_path, sizeof(dump_path), "%s/%s", dump_dir, "umr_waves.log");
744bf215546Sopenharmony_ci      f = fopen(dump_path, "w+");
745bf215546Sopenharmony_ci      if (f) {
746bf215546Sopenharmony_ci         radv_dump_umr_waves(queue, f);
747bf215546Sopenharmony_ci         fclose(f);
748bf215546Sopenharmony_ci      }
749bf215546Sopenharmony_ci
750bf215546Sopenharmony_ci      /* Dump UMR ring. */
751bf215546Sopenharmony_ci      snprintf(dump_path, sizeof(dump_path), "%s/%s", dump_dir, "umr_ring.log");
752bf215546Sopenharmony_ci      f = fopen(dump_path, "w+");
753bf215546Sopenharmony_ci      if (f) {
754bf215546Sopenharmony_ci         radv_dump_umr_ring(queue, f);
755bf215546Sopenharmony_ci         fclose(f);
756bf215546Sopenharmony_ci      }
757bf215546Sopenharmony_ci   }
758bf215546Sopenharmony_ci
759bf215546Sopenharmony_ci   /* Dump debug registers. */
760bf215546Sopenharmony_ci   snprintf(dump_path, sizeof(dump_path), "%s/%s", dump_dir, "registers.log");
761bf215546Sopenharmony_ci   f = fopen(dump_path, "w+");
762bf215546Sopenharmony_ci   if (f) {
763bf215546Sopenharmony_ci      radv_dump_debug_registers(device, f);
764bf215546Sopenharmony_ci      fclose(f);
765bf215546Sopenharmony_ci   }
766bf215546Sopenharmony_ci
767bf215546Sopenharmony_ci   /* Dump BO ranges. */
768bf215546Sopenharmony_ci   snprintf(dump_path, sizeof(dump_path), "%s/%s", dump_dir, "bo_ranges.log");
769bf215546Sopenharmony_ci   f = fopen(dump_path, "w+");
770bf215546Sopenharmony_ci   if (f) {
771bf215546Sopenharmony_ci      device->ws->dump_bo_ranges(device->ws, f);
772bf215546Sopenharmony_ci      fclose(f);
773bf215546Sopenharmony_ci   }
774bf215546Sopenharmony_ci
775bf215546Sopenharmony_ci   /* Dump BO log. */
776bf215546Sopenharmony_ci   snprintf(dump_path, sizeof(dump_path), "%s/%s", dump_dir, "bo_history.log");
777bf215546Sopenharmony_ci   f = fopen(dump_path, "w+");
778bf215546Sopenharmony_ci   if (f) {
779bf215546Sopenharmony_ci      device->ws->dump_bo_log(device->ws, f);
780bf215546Sopenharmony_ci      fclose(f);
781bf215546Sopenharmony_ci   }
782bf215546Sopenharmony_ci
783bf215546Sopenharmony_ci   /* Dump VM fault info. */
784bf215546Sopenharmony_ci   if (vm_fault_occurred) {
785bf215546Sopenharmony_ci      snprintf(dump_path, sizeof(dump_path), "%s/%s", dump_dir, "vm_fault.log");
786bf215546Sopenharmony_ci      f = fopen(dump_path, "w+");
787bf215546Sopenharmony_ci      if (f) {
788bf215546Sopenharmony_ci         fprintf(f, "VM fault report.\n\n");
789bf215546Sopenharmony_ci         fprintf(f, "Failing VM page: 0x%08" PRIx64 "\n\n", addr);
790bf215546Sopenharmony_ci         fclose(f);
791bf215546Sopenharmony_ci      }
792bf215546Sopenharmony_ci   }
793bf215546Sopenharmony_ci
794bf215546Sopenharmony_ci   /* Dump app info. */
795bf215546Sopenharmony_ci   snprintf(dump_path, sizeof(dump_path), "%s/%s", dump_dir, "app_info.log");
796bf215546Sopenharmony_ci   f = fopen(dump_path, "w+");
797bf215546Sopenharmony_ci   if (f) {
798bf215546Sopenharmony_ci      radv_dump_app_info(device, f);
799bf215546Sopenharmony_ci      fclose(f);
800bf215546Sopenharmony_ci   }
801bf215546Sopenharmony_ci
802bf215546Sopenharmony_ci   /* Dump GPU info. */
803bf215546Sopenharmony_ci   snprintf(dump_path, sizeof(dump_path), "%s/%s", dump_dir, "gpu_info.log");
804bf215546Sopenharmony_ci   f = fopen(dump_path, "w+");
805bf215546Sopenharmony_ci   if (f) {
806bf215546Sopenharmony_ci      radv_dump_device_name(device, f);
807bf215546Sopenharmony_ci      ac_print_gpu_info(&device->physical_device->rad_info, f);
808bf215546Sopenharmony_ci      fclose(f);
809bf215546Sopenharmony_ci   }
810bf215546Sopenharmony_ci
811bf215546Sopenharmony_ci   /* Dump dmesg. */
812bf215546Sopenharmony_ci   snprintf(dump_path, sizeof(dump_path), "%s/%s", dump_dir, "dmesg.log");
813bf215546Sopenharmony_ci   f = fopen(dump_path, "w+");
814bf215546Sopenharmony_ci   if (f) {
815bf215546Sopenharmony_ci      radv_dump_dmesg(f);
816bf215546Sopenharmony_ci      fclose(f);
817bf215546Sopenharmony_ci   }
818bf215546Sopenharmony_ci#endif
819bf215546Sopenharmony_ci
820bf215546Sopenharmony_ci   fprintf(stderr, "radv: GPU hang report saved successfully!\n");
821bf215546Sopenharmony_ci   abort();
822bf215546Sopenharmony_ci}
823bf215546Sopenharmony_ci
824bf215546Sopenharmony_civoid
825bf215546Sopenharmony_ciradv_print_spirv(const char *data, uint32_t size, FILE *fp)
826bf215546Sopenharmony_ci{
827bf215546Sopenharmony_ci#ifndef _WIN32
828bf215546Sopenharmony_ci   char path[] = "/tmp/fileXXXXXX";
829bf215546Sopenharmony_ci   char command[128];
830bf215546Sopenharmony_ci   int fd;
831bf215546Sopenharmony_ci
832bf215546Sopenharmony_ci   /* Dump the binary into a temporary file. */
833bf215546Sopenharmony_ci   fd = mkstemp(path);
834bf215546Sopenharmony_ci   if (fd < 0)
835bf215546Sopenharmony_ci      return;
836bf215546Sopenharmony_ci
837bf215546Sopenharmony_ci   if (write(fd, data, size) == -1)
838bf215546Sopenharmony_ci      goto fail;
839bf215546Sopenharmony_ci
840bf215546Sopenharmony_ci   /* Disassemble using spirv-dis if installed. */
841bf215546Sopenharmony_ci   sprintf(command, "spirv-dis %s", path);
842bf215546Sopenharmony_ci   radv_dump_cmd(command, fp);
843bf215546Sopenharmony_ci
844bf215546Sopenharmony_cifail:
845bf215546Sopenharmony_ci   close(fd);
846bf215546Sopenharmony_ci   unlink(path);
847bf215546Sopenharmony_ci#endif
848bf215546Sopenharmony_ci}
849bf215546Sopenharmony_ci
850bf215546Sopenharmony_cibool
851bf215546Sopenharmony_ciradv_trap_handler_init(struct radv_device *device)
852bf215546Sopenharmony_ci{
853bf215546Sopenharmony_ci   struct radeon_winsys *ws = device->ws;
854bf215546Sopenharmony_ci   VkResult result;
855bf215546Sopenharmony_ci
856bf215546Sopenharmony_ci   /* Create the trap handler shader and upload it like other shaders. */
857bf215546Sopenharmony_ci   device->trap_handler_shader = radv_create_trap_handler_shader(device);
858bf215546Sopenharmony_ci   if (!device->trap_handler_shader) {
859bf215546Sopenharmony_ci      fprintf(stderr, "radv: failed to create the trap handler shader.\n");
860bf215546Sopenharmony_ci      return false;
861bf215546Sopenharmony_ci   }
862bf215546Sopenharmony_ci
863bf215546Sopenharmony_ci   result = ws->buffer_make_resident(ws, device->trap_handler_shader->alloc->arena->bo, true);
864bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
865bf215546Sopenharmony_ci      return false;
866bf215546Sopenharmony_ci
867bf215546Sopenharmony_ci   result = ws->buffer_create(ws, TMA_BO_SIZE, 256, RADEON_DOMAIN_VRAM,
868bf215546Sopenharmony_ci                              RADEON_FLAG_CPU_ACCESS | RADEON_FLAG_NO_INTERPROCESS_SHARING |
869bf215546Sopenharmony_ci                                 RADEON_FLAG_ZERO_VRAM | RADEON_FLAG_32BIT,
870bf215546Sopenharmony_ci                              RADV_BO_PRIORITY_SCRATCH, 0, &device->tma_bo);
871bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
872bf215546Sopenharmony_ci      return false;
873bf215546Sopenharmony_ci
874bf215546Sopenharmony_ci   result = ws->buffer_make_resident(ws, device->tma_bo, true);
875bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
876bf215546Sopenharmony_ci      return false;
877bf215546Sopenharmony_ci
878bf215546Sopenharmony_ci   device->tma_ptr = ws->buffer_map(device->tma_bo);
879bf215546Sopenharmony_ci   if (!device->tma_ptr)
880bf215546Sopenharmony_ci      return false;
881bf215546Sopenharmony_ci
882bf215546Sopenharmony_ci   /* Upload a buffer descriptor to store various info from the trap. */
883bf215546Sopenharmony_ci   uint64_t tma_va = radv_buffer_get_va(device->tma_bo) + 16;
884bf215546Sopenharmony_ci   uint32_t desc[4];
885bf215546Sopenharmony_ci
886bf215546Sopenharmony_ci   desc[0] = tma_va;
887bf215546Sopenharmony_ci   desc[1] = S_008F04_BASE_ADDRESS_HI(tma_va >> 32);
888bf215546Sopenharmony_ci   desc[2] = TMA_BO_SIZE;
889bf215546Sopenharmony_ci   desc[3] = S_008F0C_DST_SEL_X(V_008F0C_SQ_SEL_X) | S_008F0C_DST_SEL_Y(V_008F0C_SQ_SEL_Y) |
890bf215546Sopenharmony_ci             S_008F0C_DST_SEL_Z(V_008F0C_SQ_SEL_Z) | S_008F0C_DST_SEL_W(V_008F0C_SQ_SEL_W) |
891bf215546Sopenharmony_ci             S_008F0C_DATA_FORMAT(V_008F0C_BUF_DATA_FORMAT_32);
892bf215546Sopenharmony_ci
893bf215546Sopenharmony_ci   memcpy(device->tma_ptr, desc, sizeof(desc));
894bf215546Sopenharmony_ci
895bf215546Sopenharmony_ci   return true;
896bf215546Sopenharmony_ci}
897bf215546Sopenharmony_ci
898bf215546Sopenharmony_civoid
899bf215546Sopenharmony_ciradv_trap_handler_finish(struct radv_device *device)
900bf215546Sopenharmony_ci{
901bf215546Sopenharmony_ci   struct radeon_winsys *ws = device->ws;
902bf215546Sopenharmony_ci
903bf215546Sopenharmony_ci   if (unlikely(device->trap_handler_shader)) {
904bf215546Sopenharmony_ci      ws->buffer_make_resident(ws, device->trap_handler_shader->alloc->arena->bo, false);
905bf215546Sopenharmony_ci      radv_trap_handler_shader_destroy(device, device->trap_handler_shader);
906bf215546Sopenharmony_ci   }
907bf215546Sopenharmony_ci
908bf215546Sopenharmony_ci   if (unlikely(device->tma_bo)) {
909bf215546Sopenharmony_ci      ws->buffer_make_resident(ws, device->tma_bo, false);
910bf215546Sopenharmony_ci      ws->buffer_destroy(ws, device->tma_bo);
911bf215546Sopenharmony_ci   }
912bf215546Sopenharmony_ci}
913bf215546Sopenharmony_ci
914bf215546Sopenharmony_cistatic void
915bf215546Sopenharmony_ciradv_dump_faulty_shader(struct radv_device *device, uint64_t faulty_pc)
916bf215546Sopenharmony_ci{
917bf215546Sopenharmony_ci   struct radv_shader *shader;
918bf215546Sopenharmony_ci   uint64_t start_addr, end_addr;
919bf215546Sopenharmony_ci   uint32_t instr_offset;
920bf215546Sopenharmony_ci
921bf215546Sopenharmony_ci   shader = radv_find_shader(device, faulty_pc);
922bf215546Sopenharmony_ci   if (!shader)
923bf215546Sopenharmony_ci      return;
924bf215546Sopenharmony_ci
925bf215546Sopenharmony_ci   start_addr = radv_shader_get_va(shader);
926bf215546Sopenharmony_ci   end_addr = start_addr + shader->code_size;
927bf215546Sopenharmony_ci   instr_offset = faulty_pc - start_addr;
928bf215546Sopenharmony_ci
929bf215546Sopenharmony_ci   fprintf(stderr,
930bf215546Sopenharmony_ci           "Faulty shader found "
931bf215546Sopenharmony_ci           "VA=[0x%" PRIx64 "-0x%" PRIx64 "], instr_offset=%d\n",
932bf215546Sopenharmony_ci           start_addr, end_addr, instr_offset);
933bf215546Sopenharmony_ci
934bf215546Sopenharmony_ci   /* Get the list of instructions.
935bf215546Sopenharmony_ci    * Buffer size / 4 is the upper bound of the instruction count.
936bf215546Sopenharmony_ci    */
937bf215546Sopenharmony_ci   unsigned num_inst = 0;
938bf215546Sopenharmony_ci   struct radv_shader_inst *instructions =
939bf215546Sopenharmony_ci      calloc(shader->code_size / 4, sizeof(struct radv_shader_inst));
940bf215546Sopenharmony_ci
941bf215546Sopenharmony_ci   /* Split the disassembly string into instructions. */
942bf215546Sopenharmony_ci   si_add_split_disasm(shader->disasm_string, start_addr, &num_inst, instructions);
943bf215546Sopenharmony_ci
944bf215546Sopenharmony_ci   /* Print instructions with annotations. */
945bf215546Sopenharmony_ci   for (unsigned i = 0; i < num_inst; i++) {
946bf215546Sopenharmony_ci      struct radv_shader_inst *inst = &instructions[i];
947bf215546Sopenharmony_ci
948bf215546Sopenharmony_ci      if (start_addr + inst->offset == faulty_pc) {
949bf215546Sopenharmony_ci         fprintf(stderr, "\n!!! Faulty instruction below !!!\n");
950bf215546Sopenharmony_ci         fprintf(stderr, "%s\n", inst->text);
951bf215546Sopenharmony_ci         fprintf(stderr, "\n");
952bf215546Sopenharmony_ci      } else {
953bf215546Sopenharmony_ci         fprintf(stderr, "%s\n", inst->text);
954bf215546Sopenharmony_ci      }
955bf215546Sopenharmony_ci   }
956bf215546Sopenharmony_ci
957bf215546Sopenharmony_ci   free(instructions);
958bf215546Sopenharmony_ci}
959bf215546Sopenharmony_ci
960bf215546Sopenharmony_cistruct radv_sq_hw_reg {
961bf215546Sopenharmony_ci   uint32_t status;
962bf215546Sopenharmony_ci   uint32_t trap_sts;
963bf215546Sopenharmony_ci   uint32_t hw_id;
964bf215546Sopenharmony_ci   uint32_t ib_sts;
965bf215546Sopenharmony_ci};
966bf215546Sopenharmony_ci
967bf215546Sopenharmony_cistatic void
968bf215546Sopenharmony_ciradv_dump_sq_hw_regs(struct radv_device *device)
969bf215546Sopenharmony_ci{
970bf215546Sopenharmony_ci   struct radv_sq_hw_reg *regs = (struct radv_sq_hw_reg *)&device->tma_ptr[6];
971bf215546Sopenharmony_ci
972bf215546Sopenharmony_ci   fprintf(stderr, "\nHardware registers:\n");
973bf215546Sopenharmony_ci   if (device->physical_device->rad_info.gfx_level >= GFX10) {
974bf215546Sopenharmony_ci      ac_dump_reg(stderr, device->physical_device->rad_info.gfx_level, R_000408_SQ_WAVE_STATUS,
975bf215546Sopenharmony_ci                  regs->status, ~0);
976bf215546Sopenharmony_ci      ac_dump_reg(stderr, device->physical_device->rad_info.gfx_level, R_00040C_SQ_WAVE_TRAPSTS,
977bf215546Sopenharmony_ci                  regs->trap_sts, ~0);
978bf215546Sopenharmony_ci      ac_dump_reg(stderr, device->physical_device->rad_info.gfx_level, R_00045C_SQ_WAVE_HW_ID1,
979bf215546Sopenharmony_ci                  regs->hw_id, ~0);
980bf215546Sopenharmony_ci      ac_dump_reg(stderr, device->physical_device->rad_info.gfx_level, R_00041C_SQ_WAVE_IB_STS,
981bf215546Sopenharmony_ci                  regs->ib_sts, ~0);
982bf215546Sopenharmony_ci   } else {
983bf215546Sopenharmony_ci      ac_dump_reg(stderr, device->physical_device->rad_info.gfx_level, R_000048_SQ_WAVE_STATUS,
984bf215546Sopenharmony_ci                  regs->status, ~0);
985bf215546Sopenharmony_ci      ac_dump_reg(stderr, device->physical_device->rad_info.gfx_level, R_00004C_SQ_WAVE_TRAPSTS,
986bf215546Sopenharmony_ci                  regs->trap_sts, ~0);
987bf215546Sopenharmony_ci      ac_dump_reg(stderr, device->physical_device->rad_info.gfx_level, R_000050_SQ_WAVE_HW_ID,
988bf215546Sopenharmony_ci                  regs->hw_id, ~0);
989bf215546Sopenharmony_ci      ac_dump_reg(stderr, device->physical_device->rad_info.gfx_level, R_00005C_SQ_WAVE_IB_STS,
990bf215546Sopenharmony_ci                  regs->ib_sts, ~0);
991bf215546Sopenharmony_ci   }
992bf215546Sopenharmony_ci   fprintf(stderr, "\n\n");
993bf215546Sopenharmony_ci}
994bf215546Sopenharmony_ci
995bf215546Sopenharmony_civoid
996bf215546Sopenharmony_ciradv_check_trap_handler(struct radv_queue *queue)
997bf215546Sopenharmony_ci{
998bf215546Sopenharmony_ci   enum amd_ip_type ring = radv_queue_ring(queue);
999bf215546Sopenharmony_ci   struct radv_device *device = queue->device;
1000bf215546Sopenharmony_ci   struct radeon_winsys *ws = device->ws;
1001bf215546Sopenharmony_ci
1002bf215546Sopenharmony_ci   /* Wait for the context to be idle in a finite time. */
1003bf215546Sopenharmony_ci   ws->ctx_wait_idle(queue->hw_ctx, ring, queue->vk.index_in_family);
1004bf215546Sopenharmony_ci
1005bf215546Sopenharmony_ci   /* Try to detect if the trap handler has been reached by the hw by
1006bf215546Sopenharmony_ci    * looking at ttmp0 which should be non-zero if a shader exception
1007bf215546Sopenharmony_ci    * happened.
1008bf215546Sopenharmony_ci    */
1009bf215546Sopenharmony_ci   if (!device->tma_ptr[4])
1010bf215546Sopenharmony_ci      return;
1011bf215546Sopenharmony_ci
1012bf215546Sopenharmony_ci#if 0
1013bf215546Sopenharmony_ci	fprintf(stderr, "tma_ptr:\n");
1014bf215546Sopenharmony_ci	for (unsigned i = 0; i < 10; i++)
1015bf215546Sopenharmony_ci		fprintf(stderr, "tma_ptr[%d]=0x%x\n", i, device->tma_ptr[i]);
1016bf215546Sopenharmony_ci#endif
1017bf215546Sopenharmony_ci
1018bf215546Sopenharmony_ci   radv_dump_sq_hw_regs(device);
1019bf215546Sopenharmony_ci
1020bf215546Sopenharmony_ci   uint32_t ttmp0 = device->tma_ptr[4];
1021bf215546Sopenharmony_ci   uint32_t ttmp1 = device->tma_ptr[5];
1022bf215546Sopenharmony_ci
1023bf215546Sopenharmony_ci   /* According to the ISA docs, 3.10 Trap and Exception Registers:
1024bf215546Sopenharmony_ci    *
1025bf215546Sopenharmony_ci    * "{ttmp1, ttmp0} = {3'h0, pc_rewind[3:0], HT[0], trapID[7:0], PC[47:0]}"
1026bf215546Sopenharmony_ci    *
1027bf215546Sopenharmony_ci    * "When the trap handler is entered, the PC of the faulting
1028bf215546Sopenharmony_ci    *  instruction is: (PC - PC_rewind * 4)."
1029bf215546Sopenharmony_ci    * */
1030bf215546Sopenharmony_ci   uint8_t trap_id = (ttmp1 >> 16) & 0xff;
1031bf215546Sopenharmony_ci   uint8_t ht = (ttmp1 >> 24) & 0x1;
1032bf215546Sopenharmony_ci   uint8_t pc_rewind = (ttmp1 >> 25) & 0xf;
1033bf215546Sopenharmony_ci   uint64_t pc = (ttmp0 | ((ttmp1 & 0x0000ffffull) << 32)) - (pc_rewind * 4);
1034bf215546Sopenharmony_ci
1035bf215546Sopenharmony_ci   fprintf(stderr, "PC=0x%" PRIx64 ", trapID=%d, HT=%d, PC_rewind=%d\n", pc, trap_id, ht,
1036bf215546Sopenharmony_ci           pc_rewind);
1037bf215546Sopenharmony_ci
1038bf215546Sopenharmony_ci   radv_dump_faulty_shader(device, pc);
1039bf215546Sopenharmony_ci
1040bf215546Sopenharmony_ci   abort();
1041bf215546Sopenharmony_ci}
1042