xref: /aosp_15_r20/external/mesa3d/src/intel/tools/aubinator_error_decode.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright © 2007-2017 Intel Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21  * IN THE SOFTWARE.
22  *
23  */
24 
25 #include <stdbool.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <stdarg.h>
29 #include <string.h>
30 #include <unistd.h>
31 #include <inttypes.h>
32 #include <errno.h>
33 #include <sys/stat.h>
34 #include <sys/types.h>
35 #include <sys/wait.h>
36 #include <err.h>
37 #include <assert.h>
38 #include <getopt.h>
39 #include <zlib.h>
40 
41 #include "aubinator_error_decode_lib.h"
42 #include "aubinator_error_decode_xe.h"
43 #include "common/intel_debug_identifier.h"
44 #include "compiler/brw_compiler.h"
45 #include "compiler/elk/elk_compiler.h"
46 #include "decoder/intel_decoder.h"
47 #include "dev/intel_debug.h"
48 #include "error_decode_lib.h"
49 #include "util/macros.h"
50 
51 #define MIN(a, b) ((a) < (b) ? (a) : (b))
52 
53 #define XE_KMD_ERROR_DUMP_IDENTIFIER "**** Xe Device Coredump ****"
54 
55 /* options */
56 
57 static bool option_full_decode = true;
58 static bool option_print_all_bb = false;
59 static bool option_print_offsets = true;
60 static bool option_dump_kernels = false;
61 static enum decode_color option_color;
62 static char *xml_path = NULL;
63 
64 static uint32_t
print_head(unsigned int reg)65 print_head(unsigned int reg)
66 {
67    printf("    head = 0x%08x, wraps = %d\n", reg & (0x7ffff<<2), reg >> 21);
68    return reg & (0x7ffff<<2);
69 }
70 
71 static void
print_register(struct intel_spec * spec,const char * name,uint32_t reg)72 print_register(struct intel_spec *spec, const char *name, uint32_t reg)
73 {
74    struct intel_group *reg_spec =
75       name ? intel_spec_find_register_by_name(spec, name) : NULL;
76 
77    if (reg_spec) {
78       intel_print_group(stdout, reg_spec, 0, &reg, 0,
79                         option_color == DECODE_COLOR_ALWAYS);
80    }
81 }
82 
83 struct ring_register_mapping {
84    enum intel_engine_class ring_class;
85    unsigned ring_instance;
86    const char *register_name;
87 };
88 
89 static const struct ring_register_mapping acthd_registers[] = {
90    { INTEL_ENGINE_CLASS_COPY, 0, "BCS_ACTHD_UDW" },
91    { INTEL_ENGINE_CLASS_VIDEO, 0, "VCS_ACTHD_UDW" },
92    { INTEL_ENGINE_CLASS_VIDEO, 1, "VCS2_ACTHD_UDW" },
93    { INTEL_ENGINE_CLASS_RENDER, 0, "ACTHD_UDW" },
94    { INTEL_ENGINE_CLASS_VIDEO_ENHANCE, 0, "VECS_ACTHD_UDW" },
95 };
96 
97 static const struct ring_register_mapping ctl_registers[] = {
98    { INTEL_ENGINE_CLASS_COPY, 0, "BCS_RING_BUFFER_CTL" },
99    { INTEL_ENGINE_CLASS_VIDEO, 0, "VCS_RING_BUFFER_CTL" },
100    { INTEL_ENGINE_CLASS_VIDEO, 1, "VCS2_RING_BUFFER_CTL" },
101    { INTEL_ENGINE_CLASS_RENDER, 0, "RCS_RING_BUFFER_CTL" },
102    { INTEL_ENGINE_CLASS_VIDEO_ENHANCE, 0,  "VECS_RING_BUFFER_CTL" },
103 };
104 
105 static const struct ring_register_mapping fault_registers[] = {
106    { INTEL_ENGINE_CLASS_COPY, 0, "BCS_FAULT_REG" },
107    { INTEL_ENGINE_CLASS_VIDEO, 0, "VCS_FAULT_REG" },
108    { INTEL_ENGINE_CLASS_RENDER, 0, "RCS_FAULT_REG" },
109    { INTEL_ENGINE_CLASS_VIDEO_ENHANCE, 0, "VECS_FAULT_REG" },
110 };
111 
112 static const char *
register_name_from_ring(const struct ring_register_mapping * mapping,unsigned nb_mapping,const char * ring_name)113 register_name_from_ring(const struct ring_register_mapping *mapping,
114                         unsigned nb_mapping,
115                         const char *ring_name)
116 {
117    enum intel_engine_class class;
118    int instance;
119 
120    instance = ring_name_to_class(ring_name, &class);
121    if (instance < 0)
122       return NULL;
123 
124    for (unsigned i = 0; i < nb_mapping; i++) {
125       if (mapping[i].ring_class == class &&
126           mapping[i].ring_instance == instance)
127          return mapping[i].register_name;
128    }
129    return NULL;
130 }
131 
132 static const char *
instdone_register_for_ring(const struct intel_device_info * devinfo,const char * ring_name)133 instdone_register_for_ring(const struct intel_device_info *devinfo,
134                            const char *ring_name)
135 {
136    enum intel_engine_class class;
137    int instance;
138 
139    instance = ring_name_to_class(ring_name, &class);
140    if (instance < 0)
141       return NULL;
142 
143    switch (class) {
144    case INTEL_ENGINE_CLASS_RENDER:
145       if (devinfo->ver == 6)
146          return "INSTDONE_2";
147       else
148          return "INSTDONE_1";
149 
150    case INTEL_ENGINE_CLASS_COPY:
151       return "BCS_INSTDONE";
152 
153    case INTEL_ENGINE_CLASS_VIDEO:
154       switch (instance) {
155       case 0:
156          return "VCS_INSTDONE";
157       case 1:
158          return "VCS2_INSTDONE";
159       default:
160          return NULL;
161       }
162 
163    case INTEL_ENGINE_CLASS_VIDEO_ENHANCE:
164       return "VECS_INSTDONE";
165 
166    default:
167       return NULL;
168    }
169 
170    return NULL;
171 }
172 
173 static void
print_pgtbl_err(unsigned int reg,struct intel_device_info * devinfo)174 print_pgtbl_err(unsigned int reg, struct intel_device_info *devinfo)
175 {
176    if (reg & (1 << 26))
177       printf("    Invalid Sampler Cache GTT entry\n");
178    if (reg & (1 << 24))
179       printf("    Invalid Render Cache GTT entry\n");
180    if (reg & (1 << 23))
181       printf("    Invalid Instruction/State Cache GTT entry\n");
182    if (reg & (1 << 22))
183       printf("    There is no ROC, this cannot occur!\n");
184    if (reg & (1 << 21))
185       printf("    Invalid GTT entry during Vertex Fetch\n");
186    if (reg & (1 << 20))
187       printf("    Invalid GTT entry during Command Fetch\n");
188    if (reg & (1 << 19))
189       printf("    Invalid GTT entry during CS\n");
190    if (reg & (1 << 18))
191       printf("    Invalid GTT entry during Cursor Fetch\n");
192    if (reg & (1 << 17))
193       printf("    Invalid GTT entry during Overlay Fetch\n");
194    if (reg & (1 << 8))
195       printf("    Invalid GTT entry during Display B Fetch\n");
196    if (reg & (1 << 4))
197       printf("    Invalid GTT entry during Display A Fetch\n");
198    if (reg & (1 << 1))
199       printf("    Valid PTE references illegal memory\n");
200    if (reg & (1 << 0))
201       printf("    Invalid GTT entry during fetch for host\n");
202 }
203 
204 static void
print_snb_fence(struct intel_device_info * devinfo,uint64_t fence)205 print_snb_fence(struct intel_device_info *devinfo, uint64_t fence)
206 {
207    printf("    %svalid, %c-tiled, pitch: %i, start: 0x%08x, size: %u\n",
208           fence & 1 ? "" : "in",
209           fence & (1<<1) ? 'y' : 'x',
210           (int)(((fence>>32)&0xfff)+1)*128,
211           (uint32_t)fence & 0xfffff000,
212           (uint32_t)(((fence>>32)&0xfffff000) - (fence&0xfffff000) + 4096));
213 }
214 
215 static void
print_i965_fence(struct intel_device_info * devinfo,uint64_t fence)216 print_i965_fence(struct intel_device_info *devinfo, uint64_t fence)
217 {
218    printf("    %svalid, %c-tiled, pitch: %i, start: 0x%08x, size: %u\n",
219           fence & 1 ? "" : "in",
220           fence & (1<<1) ? 'y' : 'x',
221           (int)(((fence>>2)&0x1ff)+1)*128,
222           (uint32_t)fence & 0xfffff000,
223           (uint32_t)(((fence>>32)&0xfffff000) - (fence&0xfffff000) + 4096));
224 }
225 
226 static void
print_fence(struct intel_device_info * devinfo,uint64_t fence)227 print_fence(struct intel_device_info *devinfo, uint64_t fence)
228 {
229    if (devinfo->ver == 6 || devinfo->ver == 7) {
230       return print_snb_fence(devinfo, fence);
231    } else if (devinfo->ver == 4 || devinfo->ver == 5) {
232       return print_i965_fence(devinfo, fence);
233    }
234 }
235 
236 static void
print_fault_data(struct intel_device_info * devinfo,uint32_t data1,uint32_t data0)237 print_fault_data(struct intel_device_info *devinfo, uint32_t data1, uint32_t data0)
238 {
239    uint64_t address;
240 
241    if (devinfo->ver < 8)
242       return;
243 
244    address = ((uint64_t)(data0) << 12) | ((uint64_t)data1 & 0xf) << 44;
245    printf("    Address 0x%016" PRIx64 " %s\n", address,
246           data1 & (1 << 4) ? "GGTT" : "PPGTT");
247 }
248 
249 #define CSI "\e["
250 #define NORMAL       CSI "0m"
251 
252 struct section {
253    uint64_t gtt_offset;
254    char *ring_name;
255    const char *buffer_name;
256    uint32_t *data;
257    int dword_count;
258    size_t data_offset;
259 };
260 
261 #define MAX_SECTIONS 1024
262 static unsigned num_sections;
263 static struct section sections[MAX_SECTIONS];
264 
zlib_inflate(uint32_t ** ptr,int len)265 static int zlib_inflate(uint32_t **ptr, int len)
266 {
267    struct z_stream_s zstream;
268    void *out;
269    const uint32_t out_size = 128*4096;  /* approximate obj size */
270 
271    memset(&zstream, 0, sizeof(zstream));
272 
273    zstream.next_in = (unsigned char *)*ptr;
274    zstream.avail_in = 4*len;
275 
276    if (inflateInit(&zstream) != Z_OK)
277       return 0;
278 
279    out = malloc(out_size);
280    zstream.next_out = out;
281    zstream.avail_out = out_size;
282 
283    do {
284       switch (inflate(&zstream, Z_SYNC_FLUSH)) {
285       case Z_STREAM_END:
286          goto end;
287       case Z_OK:
288          break;
289       default:
290          inflateEnd(&zstream);
291          return 0;
292       }
293 
294       if (zstream.avail_out)
295          break;
296 
297       out = realloc(out, 2*zstream.total_out);
298       if (out == NULL) {
299          inflateEnd(&zstream);
300          return 0;
301       }
302 
303       zstream.next_out = (unsigned char *)out + zstream.total_out;
304       zstream.avail_out = zstream.total_out;
305    } while (1);
306  end:
307    inflateEnd(&zstream);
308    free(*ptr);
309    *ptr = out;
310    return zstream.total_out / 4;
311 }
312 
ascii85_decode(const char * in,uint32_t ** out,bool inflate)313 static int ascii85_decode(const char *in, uint32_t **out, bool inflate)
314 {
315    int len = 0, size = 1024;
316 
317    *out = realloc(*out, sizeof(uint32_t)*size);
318    if (*out == NULL)
319       return 0;
320 
321    while (*in >= '!' && *in <= 'z') {
322       uint32_t v = 0;
323 
324       if (len == size) {
325          size *= 2;
326          *out = realloc(*out, sizeof(uint32_t)*size);
327          if (*out == NULL)
328             return 0;
329       }
330 
331       in = ascii85_decode_char(in, &v);
332       (*out)[len++] = v;
333    }
334 
335    if (!inflate)
336       return len;
337 
338    return zlib_inflate(out, len);
339 }
340 
qsort_hw_context_first(const void * a,const void * b)341 static int qsort_hw_context_first(const void *a, const void *b)
342 {
343    const struct section *sa = a, *sb = b;
344    if (strcmp(sa->buffer_name, "HW Context") == 0)
345       return -1;
346    if (strcmp(sb->buffer_name, "HW Context") == 0)
347       return 1;
348    else
349       return 0;
350 }
351 
352 static struct intel_batch_decode_bo
get_intel_batch_bo(void * user_data,bool ppgtt,uint64_t address)353 get_intel_batch_bo(void *user_data, bool ppgtt, uint64_t address)
354 {
355    for (int s = 0; s < num_sections; s++) {
356       if (sections[s].gtt_offset <= address &&
357           address < sections[s].gtt_offset + sections[s].dword_count * 4) {
358          return (struct intel_batch_decode_bo) {
359             .addr = sections[s].gtt_offset,
360             .map = sections[s].data,
361             .size = sections[s].dword_count * 4,
362          };
363       }
364    }
365 
366    return (struct intel_batch_decode_bo) { .map = NULL };
367 }
368 
369 static void
read_i915_data_file(FILE * file,enum intel_batch_decode_flags batch_flags)370 read_i915_data_file(FILE *file, enum intel_batch_decode_flags batch_flags)
371 {
372    struct intel_spec *spec = NULL;
373    long long unsigned fence;
374    int matched;
375    char *line = NULL;
376    size_t line_size;
377    uint32_t offset, value;
378    uint32_t ring_head = UINT32_MAX, ring_tail = UINT32_MAX;
379    bool ring_wraps = false;
380    char *ring_name = NULL;
381    struct intel_device_info devinfo;
382    struct brw_isa_info brw;
383    struct elk_isa_info elk;
384    uint64_t acthd = 0;
385 
386    while (getline(&line, &line_size, file) > 0) {
387       char *new_ring_name = NULL;
388       char *dashes;
389 
390       if (sscanf(line, "%m[^ ] command stream\n", &new_ring_name) > 0) {
391          free(ring_name);
392          ring_name = new_ring_name;
393       }
394 
395       if (line[0] == ':' || line[0] == '~') {
396          uint32_t *data = NULL;
397          int dword_count = ascii85_decode(line+1, &data, line[0] == ':');
398          if (dword_count == 0) {
399             fprintf(stderr, "ASCII85 decode failed.\n");
400             exit(EXIT_FAILURE);
401          }
402          assert(num_sections < MAX_SECTIONS);
403          sections[num_sections].data = data;
404          sections[num_sections].dword_count = dword_count;
405          num_sections++;
406          continue;
407       }
408 
409       dashes = strstr(line, "---");
410       if (dashes) {
411          const struct {
412             const char *match;
413             const char *name;
414          } buffers[] = {
415             { "ringbuffer", "ring buffer" },
416             { "ring", "ring buffer" },
417             { "gtt_offset", "batch buffer" },
418             { "batch", "batch buffer" },
419             { "hw context", "HW Context" },
420             { "hw status", "HW status" },
421             { "wa context", "WA context" },
422             { "wa batchbuffer", "WA batch" },
423             { "NULL context", "Kernel context" },
424             { "user", "user" },
425             { "semaphores", "semaphores", },
426             { "guc log buffer", "GuC log", },
427             { NULL, "unknown" },
428          }, *b;
429 
430          free(ring_name);
431          ring_name = malloc(dashes - line);
432          strncpy(ring_name, line, dashes - line);
433          ring_name[dashes - line - 1] = '\0';
434 
435          dashes += 4;
436          for (b = buffers; b->match; b++) {
437             if (strncasecmp(dashes, b->match, strlen(b->match)) == 0)
438                break;
439          }
440 
441          assert(num_sections < MAX_SECTIONS);
442          sections[num_sections].buffer_name = b->name;
443          sections[num_sections].ring_name = strdup(ring_name);
444 
445          uint32_t hi, lo;
446          dashes = strchr(dashes, '=');
447          if (dashes && sscanf(dashes, "= 0x%08x %08x\n", &hi, &lo))
448             sections[num_sections].gtt_offset = ((uint64_t) hi) << 32 | lo;
449 
450          continue;
451       }
452 
453       matched = sscanf(line, "%08x : %08x", &offset, &value);
454       if (matched != 2) {
455          uint32_t reg, reg2;
456 
457          /* display reg section is after the ringbuffers, don't mix them */
458          printf("%s", line);
459 
460          matched = sscanf(line, "PCI ID: 0x%04x\n", &reg);
461          if (matched == 0)
462             matched = sscanf(line, " PCI ID: 0x%04x\n", &reg);
463          if (matched == 0) {
464             const char *pci_id_start = strstr(line, "PCI ID");
465             if (pci_id_start)
466                matched = sscanf(pci_id_start, "PCI ID: 0x%04x\n", &reg);
467          }
468          if (matched == 1) {
469             if (!intel_get_device_info_from_pci_id(reg, &devinfo)) {
470                printf("Unable to identify devid=%x\n", reg);
471                exit(EXIT_FAILURE);
472             }
473 
474             printf("Detected GEN%i chipset\n", devinfo.ver);
475 
476             if (devinfo.ver >= 9)
477                brw_init_isa_info(&brw, &devinfo);
478             else
479                elk_init_isa_info(&elk, &devinfo);
480 
481             if (xml_path == NULL)
482                spec = intel_spec_load(&devinfo);
483             else
484                spec = intel_spec_load_from_path(&devinfo, xml_path);
485          }
486 
487          matched = sscanf(line, "  CTL: 0x%08x\n", &reg);
488          if (matched == 1) {
489             print_register(spec,
490                            register_name_from_ring(ctl_registers,
491                                                    ARRAY_SIZE(ctl_registers),
492                                                    ring_name), reg);
493          }
494 
495          matched = sscanf(line, "  HEAD: 0x%08x\n", &reg);
496          if (matched == 1)
497             print_head(reg);
498 
499          sscanf(line, "  HEAD: 0x%08x [0x%08X]\n", &reg, &ring_head);
500          sscanf(line, "  TAIL: 0x%08x\n", &ring_tail);
501 
502          matched = sscanf(line, "  ACTHD: 0x%08x\n", &reg);
503          if (matched == 1) {
504             print_register(spec,
505                            register_name_from_ring(acthd_registers,
506                                                    ARRAY_SIZE(acthd_registers),
507                                                    ring_name), reg);
508          }
509 
510          matched = sscanf(line, "  ACTHD: 0x%08x %08x\n", &reg, &reg2);
511          if (matched == 2)
512             acthd = ((uint64_t)reg << 32) | reg2;
513 
514          matched = sscanf(line, "  ACTHD_LDW: 0x%08x\n", &reg);
515          if (matched == 1)
516             acthd = reg;
517 
518          matched = sscanf(line, "  ACTHD_UDW: 0x%08x\n", &reg);
519          if (matched == 1)
520             acthd |= (uint64_t)reg << 32;
521 
522          matched = sscanf(line, "  PGTBL_ER: 0x%08x\n", &reg);
523          if (matched == 1 && reg)
524             print_pgtbl_err(reg, &devinfo);
525 
526          matched = sscanf(line, "  ERROR: 0x%08x\n", &reg);
527          if (matched == 1 && reg) {
528             print_register(spec, "GFX_ARB_ERROR_RPT", reg);
529          }
530 
531          matched = sscanf(line, "  INSTDONE: 0x%08x\n", &reg);
532          if (matched == 1) {
533             const char *reg_name =
534                instdone_register_for_ring(&devinfo, ring_name);
535             if (reg_name)
536                print_register(spec, reg_name, reg);
537          }
538 
539          matched = sscanf(line, "  GAM_DONE: 0x%08x\n", &reg);
540          if (matched == 1)
541             print_register(spec, "GAM_DONE", reg);
542 
543          matched = sscanf(line, "  SC_INSTDONE: 0x%08x\n", &reg);
544          if (matched == 1)
545             print_register(spec, "SC_INSTDONE", reg);
546 
547          matched = sscanf(line, "  GEN7_SC_INSTDONE: 0x%08x\n", &reg);
548          if (matched == 1)
549             print_register(spec, "SC_INSTDONE", reg);
550 
551          matched = sscanf(line, "  SC_INSTDONE_EXTRA: 0x%08x\n", &reg);
552          if (matched == 1)
553             print_register(spec, "SC_INSTDONE_EXTRA", reg);
554 
555          matched = sscanf(line, "  GEN12_SC_INSTDONE_EXTRA: 0x%08x\n", &reg);
556          if (matched == 1)
557             print_register(spec, "SC_INSTDONE_EXTRA", reg);
558 
559          matched = sscanf(line, "  SC_INSTDONE_EXTRA2: 0x%08x\n", &reg);
560          if (matched == 1)
561             print_register(spec, "SC_INSTDONE_EXTRA2", reg);
562 
563          matched = sscanf(line, "  GEN12_SC_INSTDONE_EXTRA2: 0x%08x\n", &reg);
564          if (matched == 1)
565             print_register(spec, "SC_INSTDONE_EXTRA2", reg);
566 
567          matched = sscanf(line, "  SAMPLER_INSTDONE[%*d][%*d]: 0x%08x\n", &reg);
568          if (matched == 1)
569             print_register(spec, "SAMPLER_INSTDONE", reg);
570 
571          matched = sscanf(line, "  GEN8_SAMPLER_INSTDONE[%*d][%*d]: 0x%08x\n", &reg);
572          if (matched == 1)
573             print_register(spec, "SAMPLER_INSTDONE", reg);
574 
575          matched = sscanf(line, "  ROW_INSTDONE[%*d][%*d]: 0x%08x\n", &reg);
576          if (matched == 1)
577             print_register(spec, "ROW_INSTDONE", reg);
578 
579          matched = sscanf(line, "  GEN8_ROW_INSTDONE[%*d][%*d]: 0x%08x\n", &reg);
580          if (matched == 1)
581             print_register(spec, "ROW_INSTDONE", reg);
582 
583          matched = sscanf(line, "  GEOM_SVGUNIT_INSTDONE[%*d][%*d]: 0x%08x\n", &reg);
584          if (matched == 1)
585             print_register(spec, "INSTDONE_GEOM", reg);
586 
587          matched = sscanf(line, "  XEHPG_INSTDONE_GEOM_SVG[%*d][%*d]: 0x%08x\n", &reg);
588          if (matched == 1)
589             print_register(spec, "INSTDONE_GEOM", reg);
590 
591          matched = sscanf(line, "  INSTDONE1: 0x%08x\n", &reg);
592          if (matched == 1)
593             print_register(spec, "INSTDONE_1", reg);
594 
595          matched = sscanf(line, "  fence[%i] = %Lx\n", &reg, &fence);
596          if (matched == 2)
597             print_fence(&devinfo, fence);
598 
599          matched = sscanf(line, "  FAULT_REG: 0x%08x\n", &reg);
600          if (matched == 1 && reg) {
601             const char *reg_name =
602                register_name_from_ring(fault_registers,
603                                        ARRAY_SIZE(fault_registers),
604                                        ring_name);
605             if (reg_name == NULL)
606                reg_name = "FAULT_REG";
607             print_register(spec, reg_name, reg);
608          }
609 
610          matched = sscanf(line, "  FAULT_TLB_DATA: 0x%08x 0x%08x\n", &reg, &reg2);
611          if (matched == 2)
612             print_fault_data(&devinfo, reg, reg2);
613 
614          continue;
615       }
616    }
617 
618    free(line);
619    free(ring_name);
620 
621    /*
622     * Order sections so that the hardware context section is visited by the
623     * decoder before other command buffers. This will allow the decoder to see
624     * persistent state that was set before the current batch.
625     */
626    qsort(sections, num_sections, sizeof(sections[0]), qsort_hw_context_first);
627 
628    for (int s = 0; s < num_sections; s++) {
629       if (strcmp(sections[s].buffer_name, "ring buffer") != 0)
630          continue;
631       if (ring_head == UINT32_MAX) {
632          ring_head = 0;
633          ring_tail = UINT32_MAX;
634       }
635       if (ring_tail == UINT32_MAX)
636          ring_tail = (ring_head - sizeof(uint32_t)) %
637             (sections[s].dword_count * sizeof(uint32_t));
638       if (ring_head > ring_tail) {
639          size_t total_size = sections[s].dword_count * sizeof(uint32_t) -
640             ring_head + ring_tail;
641          size_t size1 = total_size - ring_tail;
642          uint32_t *new_data = calloc(total_size, 1);
643          memcpy(new_data, (uint8_t *)sections[s].data + ring_head, size1);
644          memcpy((uint8_t *)new_data + size1, sections[s].data, ring_tail);
645          free(sections[s].data);
646          sections[s].data = new_data;
647          ring_head = 0;
648          ring_tail = total_size;
649          ring_wraps = true;
650       }
651       sections[s].data_offset = ring_head;
652       sections[s].dword_count = (ring_tail - ring_head) / sizeof(uint32_t);
653    }
654 
655    for (int s = 0; s < num_sections; s++) {
656       if (sections[s].dword_count * 4 > intel_debug_identifier_size() &&
657           memcmp(sections[s].data, intel_debug_identifier(),
658                  intel_debug_identifier_size()) == 0) {
659          const struct intel_debug_block_driver *driver_desc =
660             intel_debug_get_identifier_block(sections[s].data,
661                                              sections[s].dword_count * 4,
662                                              INTEL_DEBUG_BLOCK_TYPE_DRIVER);
663          if (driver_desc) {
664             printf("Driver identifier: %s\n",
665                    (const char *) driver_desc->description);
666          }
667          break;
668       }
669    }
670 
671    struct intel_batch_decode_ctx batch_ctx;
672    if (devinfo.ver >= 9) {
673       intel_batch_decode_ctx_init_brw(&batch_ctx, &brw, &devinfo, stdout,
674                                       batch_flags, xml_path, get_intel_batch_bo,
675                                       NULL, NULL);
676    } else {
677       intel_batch_decode_ctx_init_elk(&batch_ctx, &elk, &devinfo, stdout,
678                                       batch_flags, xml_path, get_intel_batch_bo,
679                                       NULL, NULL);
680    }
681    batch_ctx.acthd = acthd;
682 
683    if (option_dump_kernels)
684       batch_ctx.shader_binary = dump_shader_binary;
685 
686    for (int s = 0; s < num_sections; s++) {
687       enum intel_engine_class class;
688       ring_name_to_class(sections[s].ring_name, &class);
689 
690       printf("--- %s (%s) at 0x%08x %08x\n",
691              sections[s].buffer_name, sections[s].ring_name,
692              (unsigned) (sections[s].gtt_offset >> 32),
693              (unsigned) sections[s].gtt_offset);
694 
695       bool is_ring_buffer = strcmp(sections[s].buffer_name, "ring buffer") == 0;
696       if (option_print_all_bb || is_ring_buffer ||
697           strcmp(sections[s].buffer_name, "batch buffer") == 0 ||
698           strcmp(sections[s].buffer_name, "HW Context") == 0) {
699          if (is_ring_buffer && ring_wraps)
700             batch_ctx.flags &= ~INTEL_BATCH_DECODE_OFFSETS;
701          batch_ctx.engine = class;
702          uint8_t *data = (uint8_t *)sections[s].data + sections[s].data_offset;
703          uint64_t batch_addr = sections[s].gtt_offset + sections[s].data_offset;
704          intel_print_batch(&batch_ctx, (uint32_t *)data,
705                            sections[s].dword_count * 4, batch_addr,
706                            is_ring_buffer);
707          batch_ctx.flags = batch_flags;
708       }
709    }
710 
711    intel_batch_decode_ctx_finish(&batch_ctx);
712 
713    for (int s = 0; s < num_sections; s++) {
714       free(sections[s].ring_name);
715       free(sections[s].data);
716    }
717 }
718 
719 static void
setup_pager(void)720 setup_pager(void)
721 {
722    int fds[2];
723    pid_t pid;
724 
725    if (!isatty(1))
726       return;
727 
728    if (pipe(fds) == -1)
729       return;
730 
731    pid = fork();
732    if (pid == -1)
733       return;
734 
735    if (pid == 0) {
736       close(fds[1]);
737       dup2(fds[0], 0);
738       execlp("less", "less", "-FRSi", NULL);
739    }
740 
741    close(fds[0]);
742    dup2(fds[1], 1);
743    close(fds[1]);
744 }
745 
746 static void
print_help(const char * progname,FILE * file)747 print_help(const char *progname, FILE *file)
748 {
749    fprintf(file,
750            "Usage: %s [OPTION]... [FILE]\n"
751            "Parse an Intel GPU i915_error_state.\n"
752            "With no FILE, debugfs-dri-directory is probed for in /debug and \n"
753            "/sys/kernel/debug.  Otherwise, it may be specified. If a file is given,\n"
754            "it is parsed as an GPU dump in the format of /debug/dri/0/i915_error_state.\n\n"
755            "      --help          display this help and exit\n"
756            "      --headers       decode only command headers\n"
757            "      --color[=WHEN]  colorize the output; WHEN can be 'auto' (default\n"
758            "                        if omitted), 'always', or 'never'\n"
759            "      --no-pager      don't launch pager\n"
760            "      --no-offsets    don't print instruction offsets\n"
761            "      --xml=DIR       load hardware xml description from directory DIR\n"
762            "      --all-bb        print out all batchbuffers\n"
763            "      --kernels       dump out all kernels (in current directory)\n",
764            progname);
765 }
766 
767 static FILE *
try_open_file(const char * format,...)768 try_open_file(const char *format, ...)
769 {
770    ASSERTED int ret;
771    char *filename;
772    FILE *file;
773    va_list args;
774 
775    va_start(args, format);
776    ret = vasprintf(&filename, format, args);
777    va_end(args);
778 
779    assert(ret > 0);
780    file = fopen(filename, "r");
781    free(filename);
782 
783    return file;
784 }
785 
786 static FILE *
open_xe_error_state_file(const char * path)787 open_xe_error_state_file(const char *path)
788 {
789    FILE *file = NULL;
790 
791    if (path) {
792       struct stat st;
793 
794       if (stat(path, &st))
795          return NULL;
796 
797       if (S_ISDIR(st.st_mode)) {
798          file = try_open_file("%s/data", path);
799       } else {
800          file = fopen(path, "r");
801       }
802    } else {
803       for (int minor = 0; minor < 64; minor++) {
804          file = try_open_file("/sys/class/drm/card%i/device/devcoredump/data", minor);
805          if (file)
806             break;
807       }
808    }
809 
810    return file;
811 }
812 
813 static FILE *
open_i915_error_state_file(const char * path)814 open_i915_error_state_file(const char *path)
815 {
816    FILE *file = NULL;
817    struct stat st;
818 
819    if (stat(path, &st))
820       return NULL;
821 
822    if (S_ISDIR(st.st_mode)) {
823       file = try_open_file("%s/i915_error_state", path);
824       if (!file) {
825          int minor;
826          for (minor = 0; minor < 64; minor++) {
827             file = try_open_file("%s/%d/i915_error_state", path, minor);
828             if (file)
829                break;
830          }
831       }
832    } else {
833       file = fopen(path, "r");
834    }
835 
836    return file;
837 }
838 
839 int
main(int argc,char * argv[])840 main(int argc, char *argv[])
841 {
842    enum intel_batch_decode_flags batch_flags = 0;
843    FILE *file;
844    int c, i;
845    bool help = false, pager = true;
846    char *line = NULL;
847    size_t line_size;
848 
849    const struct option aubinator_opts[] = {
850       { "help",       no_argument,       (int *) &help,                 true },
851       { "no-pager",   no_argument,       (int *) &pager,                false },
852       { "no-offsets", no_argument,       (int *) &option_print_offsets, false },
853       { "headers",    no_argument,       (int *) &option_full_decode,   false },
854       { "color",      optional_argument, NULL,                          'c' },
855       { "xml",        required_argument, NULL,                          'x' },
856       { "all-bb",     no_argument,       (int *) &option_print_all_bb,  true },
857       { "kernels",    no_argument,       (int *) &option_dump_kernels,  true },
858       { NULL,         0,                 NULL,                          0 }
859    };
860 
861    i = 0;
862    while ((c = getopt_long(argc, argv, "", aubinator_opts, &i)) != -1) {
863       switch (c) {
864       case 'c':
865          if (optarg == NULL || strcmp(optarg, "always") == 0)
866             option_color = DECODE_COLOR_ALWAYS;
867          else if (strcmp(optarg, "never") == 0)
868             option_color = DECODE_COLOR_NEVER;
869          else if (strcmp(optarg, "auto") == 0)
870             option_color = DECODE_COLOR_AUTO;
871          else {
872             fprintf(stderr, "invalid value for --color: %s", optarg);
873             exit(EXIT_FAILURE);
874          }
875          break;
876       case 'x':
877          xml_path = strdup(optarg);
878          break;
879       case '?':
880          print_help(argv[0], stderr);
881          exit(EXIT_FAILURE);
882       default:
883          break;
884       }
885    }
886 
887    if (help) {
888       print_help(argv[0], stderr);
889       exit(EXIT_SUCCESS);
890    }
891 
892    if (optind >= argc) {
893       if (isatty(0)) {
894          file = open_i915_error_state_file("/sys/class/drm/card0/error");
895          if (!file)
896             file = open_i915_error_state_file("/debug/dri");
897          if (!file)
898             file = open_i915_error_state_file("/sys/kernel/debug/dri");
899          if (!file)
900             file = open_xe_error_state_file(NULL);
901          if (file == NULL) {
902             errx(1,
903                  "Couldn't find i915 or Xe error dump.\n\n"
904                  "Is debugfs mounted? You might try mounting it with a command such as:\n\n"
905                  "\tsudo mount -t debugfs debugfs /sys/kernel/debug\n");
906          }
907       } else {
908          file = stdin;
909       }
910    } else {
911       const char *path = argv[optind];
912       if (strcmp(path, "-") == 0) {
913          file = stdin;
914       } else {
915          FILE *i915, *xe;
916 
917          i915 = open_i915_error_state_file(path);
918          xe = open_xe_error_state_file(path);
919 
920          if (i915 == NULL && xe == NULL) {
921             fprintf(stderr, "Error opening %s: %s\n", path, strerror(errno));
922             exit(EXIT_FAILURE);
923          }
924 
925          file = i915 ? i915 : xe;
926       }
927    }
928 
929    if (option_color == DECODE_COLOR_AUTO)
930       option_color = isatty(1) ? DECODE_COLOR_ALWAYS : DECODE_COLOR_NEVER;
931 
932    if (isatty(1) && pager)
933       setup_pager();
934 
935    if (option_color == DECODE_COLOR_ALWAYS)
936       batch_flags |= INTEL_BATCH_DECODE_IN_COLOR;
937    if (option_full_decode)
938       batch_flags |= INTEL_BATCH_DECODE_FULL;
939    if (option_print_offsets)
940       batch_flags |= INTEL_BATCH_DECODE_OFFSETS;
941    batch_flags |= INTEL_BATCH_DECODE_FLOATS;
942 
943    getline(&line, &line_size, file);
944    rewind(file);
945    if (strncmp(line, XE_KMD_ERROR_DUMP_IDENTIFIER, strlen(XE_KMD_ERROR_DUMP_IDENTIFIER)) == 0)
946       read_xe_data_file(file, batch_flags, xml_path, option_dump_kernels,
947                         option_print_all_bb, option_color);
948    else
949       read_i915_data_file(file, batch_flags);
950    free(line);
951    fclose(file);
952 
953    /* close the stdout which is opened to write the output */
954    fflush(stdout);
955    close(1);
956    wait(NULL);
957 
958    if (xml_path)
959       free(xml_path);
960 
961    return EXIT_SUCCESS;
962 }
963 
964 /* vim: set ts=8 sw=8 tw=0 cino=:0,(0 noet :*/
965