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