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