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, ®, 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", ®);
461 if (matched == 0)
462 matched = sscanf(line, " PCI ID: 0x%04x\n", ®);
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", ®);
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", ®);
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", ®);
496 if (matched == 1)
497 print_head(reg);
498
499 sscanf(line, " HEAD: 0x%08x [0x%08X]\n", ®, &ring_head);
500 sscanf(line, " TAIL: 0x%08x\n", &ring_tail);
501
502 matched = sscanf(line, " ACTHD: 0x%08x\n", ®);
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", ®, ®2);
511 if (matched == 2)
512 acthd = ((uint64_t)reg << 32) | reg2;
513
514 matched = sscanf(line, " ACTHD_LDW: 0x%08x\n", ®);
515 if (matched == 1)
516 acthd = reg;
517
518 matched = sscanf(line, " ACTHD_UDW: 0x%08x\n", ®);
519 if (matched == 1)
520 acthd |= (uint64_t)reg << 32;
521
522 matched = sscanf(line, " PGTBL_ER: 0x%08x\n", ®);
523 if (matched == 1 && reg)
524 print_pgtbl_err(reg, &devinfo);
525
526 matched = sscanf(line, " ERROR: 0x%08x\n", ®);
527 if (matched == 1 && reg) {
528 print_register(spec, "GFX_ARB_ERROR_RPT", reg);
529 }
530
531 matched = sscanf(line, " INSTDONE: 0x%08x\n", ®);
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", ®);
540 if (matched == 1)
541 print_register(spec, "GAM_DONE", reg);
542
543 matched = sscanf(line, " SC_INSTDONE: 0x%08x\n", ®);
544 if (matched == 1)
545 print_register(spec, "SC_INSTDONE", reg);
546
547 matched = sscanf(line, " GEN7_SC_INSTDONE: 0x%08x\n", ®);
548 if (matched == 1)
549 print_register(spec, "SC_INSTDONE", reg);
550
551 matched = sscanf(line, " SC_INSTDONE_EXTRA: 0x%08x\n", ®);
552 if (matched == 1)
553 print_register(spec, "SC_INSTDONE_EXTRA", reg);
554
555 matched = sscanf(line, " GEN12_SC_INSTDONE_EXTRA: 0x%08x\n", ®);
556 if (matched == 1)
557 print_register(spec, "SC_INSTDONE_EXTRA", reg);
558
559 matched = sscanf(line, " SC_INSTDONE_EXTRA2: 0x%08x\n", ®);
560 if (matched == 1)
561 print_register(spec, "SC_INSTDONE_EXTRA2", reg);
562
563 matched = sscanf(line, " GEN12_SC_INSTDONE_EXTRA2: 0x%08x\n", ®);
564 if (matched == 1)
565 print_register(spec, "SC_INSTDONE_EXTRA2", reg);
566
567 matched = sscanf(line, " SAMPLER_INSTDONE[%*d][%*d]: 0x%08x\n", ®);
568 if (matched == 1)
569 print_register(spec, "SAMPLER_INSTDONE", reg);
570
571 matched = sscanf(line, " GEN8_SAMPLER_INSTDONE[%*d][%*d]: 0x%08x\n", ®);
572 if (matched == 1)
573 print_register(spec, "SAMPLER_INSTDONE", reg);
574
575 matched = sscanf(line, " ROW_INSTDONE[%*d][%*d]: 0x%08x\n", ®);
576 if (matched == 1)
577 print_register(spec, "ROW_INSTDONE", reg);
578
579 matched = sscanf(line, " GEN8_ROW_INSTDONE[%*d][%*d]: 0x%08x\n", ®);
580 if (matched == 1)
581 print_register(spec, "ROW_INSTDONE", reg);
582
583 matched = sscanf(line, " GEOM_SVGUNIT_INSTDONE[%*d][%*d]: 0x%08x\n", ®);
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", ®);
588 if (matched == 1)
589 print_register(spec, "INSTDONE_GEOM", reg);
590
591 matched = sscanf(line, " INSTDONE1: 0x%08x\n", ®);
592 if (matched == 1)
593 print_register(spec, "INSTDONE_1", reg);
594
595 matched = sscanf(line, " fence[%i] = %Lx\n", ®, &fence);
596 if (matched == 2)
597 print_fence(&devinfo, fence);
598
599 matched = sscanf(line, " FAULT_REG: 0x%08x\n", ®);
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", ®, ®2);
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