intel/aubinator: Free section data last
[mesa.git] / src / intel / tools / aubinator_error_decode.c
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/gen_decoder.h"
42 #include "util/macros.h"
43
44 #define CSI "\e["
45 #define BLUE_HEADER CSI "0;44m"
46 #define GREEN_HEADER CSI "1;42m"
47 #define NORMAL CSI "0m"
48
49 #define MIN(a, b) ((a) < (b) ? (a) : (b))
50
51 /* options */
52
53 static bool option_full_decode = true;
54 static bool option_print_offsets = true;
55 static enum { COLOR_AUTO, COLOR_ALWAYS, COLOR_NEVER } option_color;
56 static char *xml_path = NULL;
57
58 static uint32_t
59 print_head(unsigned int reg)
60 {
61 printf(" head = 0x%08x, wraps = %d\n", reg & (0x7ffff<<2), reg >> 21);
62 return reg & (0x7ffff<<2);
63 }
64
65 static void
66 print_register(struct gen_spec *spec, const char *name, uint32_t reg)
67 {
68 struct gen_group *reg_spec = gen_spec_find_register_by_name(spec, name);
69
70 if (reg_spec) {
71 gen_print_group(stdout, reg_spec, 0, &reg, 0,
72 option_color == COLOR_ALWAYS);
73 }
74 }
75
76 struct ring_register_mapping {
77 const char *ring_name;
78 const char *register_name;
79 };
80
81 static const struct ring_register_mapping acthd_registers[] = {
82 { "blt", "BCS_ACTHD_UDW" },
83 { "bsd", "VCS_ACTHD_UDW" },
84 { "bsd2", "VCS2_ACTHD_UDW" },
85 { "render", "ACTHD_UDW" },
86 { "vebox", "VECS_ACTHD_UDW" },
87 };
88
89 static const struct ring_register_mapping ctl_registers[] = {
90 { "blt", "BCS_RING_BUFFER_CTL" },
91 { "bsd", "VCS_RING_BUFFER_CTL" },
92 { "bsd2", "VCS2_RING_BUFFER_CTL" },
93 { "render", "RCS_RING_BUFFER_CTL" },
94 { "vebox", "VECS_RING_BUFFER_CTL" },
95 };
96
97 static const struct ring_register_mapping fault_registers[] = {
98 { "blt", "BCS_FAULT_REG" },
99 { "bsd", "VCS_FAULT_REG" },
100 { "render", "RCS_FAULT_REG" },
101 { "vebox", "VECS_FAULT_REG" },
102 };
103
104 static const char *
105 register_name_from_ring(const struct ring_register_mapping *mapping,
106 unsigned nb_mapping,
107 const char *ring_name)
108 {
109 for (unsigned i = 0; i < nb_mapping; i++) {
110 if (strcmp(mapping[i].ring_name, ring_name) == 0)
111 return mapping[i].register_name;
112 }
113 return NULL;
114 }
115
116 static const char *
117 instdone_register_for_ring(const struct gen_device_info *devinfo,
118 const char *ring_name)
119 {
120 if (strcmp(ring_name, "blt") == 0)
121 return "BCS_INSTDONE";
122 else if (strcmp(ring_name, "vebox") == 0)
123 return "VECS_INSTDONE";
124 else if (strcmp(ring_name, "bsd") == 0)
125 return "VCS_INSTDONE";
126 else if (strcmp(ring_name, "render") == 0) {
127 if (devinfo->gen == 6)
128 return "INSTDONE_2";
129 return "INSTDONE_1";
130 }
131
132 return NULL;
133 }
134
135 static void
136 print_pgtbl_err(unsigned int reg, struct gen_device_info *devinfo)
137 {
138 if (reg & (1 << 26))
139 printf(" Invalid Sampler Cache GTT entry\n");
140 if (reg & (1 << 24))
141 printf(" Invalid Render Cache GTT entry\n");
142 if (reg & (1 << 23))
143 printf(" Invalid Instruction/State Cache GTT entry\n");
144 if (reg & (1 << 22))
145 printf(" There is no ROC, this cannot occur!\n");
146 if (reg & (1 << 21))
147 printf(" Invalid GTT entry during Vertex Fetch\n");
148 if (reg & (1 << 20))
149 printf(" Invalid GTT entry during Command Fetch\n");
150 if (reg & (1 << 19))
151 printf(" Invalid GTT entry during CS\n");
152 if (reg & (1 << 18))
153 printf(" Invalid GTT entry during Cursor Fetch\n");
154 if (reg & (1 << 17))
155 printf(" Invalid GTT entry during Overlay Fetch\n");
156 if (reg & (1 << 8))
157 printf(" Invalid GTT entry during Display B Fetch\n");
158 if (reg & (1 << 4))
159 printf(" Invalid GTT entry during Display A Fetch\n");
160 if (reg & (1 << 1))
161 printf(" Valid PTE references illegal memory\n");
162 if (reg & (1 << 0))
163 printf(" Invalid GTT entry during fetch for host\n");
164 }
165
166 static void
167 print_snb_fence(struct gen_device_info *devinfo, uint64_t fence)
168 {
169 printf(" %svalid, %c-tiled, pitch: %i, start: 0x%08x, size: %u\n",
170 fence & 1 ? "" : "in",
171 fence & (1<<1) ? 'y' : 'x',
172 (int)(((fence>>32)&0xfff)+1)*128,
173 (uint32_t)fence & 0xfffff000,
174 (uint32_t)(((fence>>32)&0xfffff000) - (fence&0xfffff000) + 4096));
175 }
176
177 static void
178 print_i965_fence(struct gen_device_info *devinfo, uint64_t fence)
179 {
180 printf(" %svalid, %c-tiled, pitch: %i, start: 0x%08x, size: %u\n",
181 fence & 1 ? "" : "in",
182 fence & (1<<1) ? 'y' : 'x',
183 (int)(((fence>>2)&0x1ff)+1)*128,
184 (uint32_t)fence & 0xfffff000,
185 (uint32_t)(((fence>>32)&0xfffff000) - (fence&0xfffff000) + 4096));
186 }
187
188 static void
189 print_fence(struct gen_device_info *devinfo, uint64_t fence)
190 {
191 if (devinfo->gen == 6 || devinfo->gen == 7) {
192 return print_snb_fence(devinfo, fence);
193 } else if (devinfo->gen == 4 || devinfo->gen == 5) {
194 return print_i965_fence(devinfo, fence);
195 }
196 }
197
198 static void
199 print_fault_data(struct gen_device_info *devinfo, uint32_t data1, uint32_t data0)
200 {
201 uint64_t address;
202
203 if (devinfo->gen < 8)
204 return;
205
206 address = ((uint64_t)(data0) << 12) | ((uint64_t)data1 & 0xf) << 44;
207 printf(" Address 0x%016" PRIx64 " %s\n", address,
208 data1 & (1 << 4) ? "GGTT" : "PPGTT");
209 }
210
211 #define CSI "\e["
212 #define NORMAL CSI "0m"
213
214 struct section {
215 uint64_t gtt_offset;
216 char *ring_name;
217 const char *buffer_name;
218 uint32_t *data;
219 int count;
220 };
221
222 #define MAX_SECTIONS 30
223 static struct section sections[MAX_SECTIONS];
224
225 static int zlib_inflate(uint32_t **ptr, int len)
226 {
227 struct z_stream_s zstream;
228 void *out;
229 const uint32_t out_size = 128*4096; /* approximate obj size */
230
231 memset(&zstream, 0, sizeof(zstream));
232
233 zstream.next_in = (unsigned char *)*ptr;
234 zstream.avail_in = 4*len;
235
236 if (inflateInit(&zstream) != Z_OK)
237 return 0;
238
239 out = malloc(out_size);
240 zstream.next_out = out;
241 zstream.avail_out = out_size;
242
243 do {
244 switch (inflate(&zstream, Z_SYNC_FLUSH)) {
245 case Z_STREAM_END:
246 goto end;
247 case Z_OK:
248 break;
249 default:
250 inflateEnd(&zstream);
251 return 0;
252 }
253
254 if (zstream.avail_out)
255 break;
256
257 out = realloc(out, 2*zstream.total_out);
258 if (out == NULL) {
259 inflateEnd(&zstream);
260 return 0;
261 }
262
263 zstream.next_out = (unsigned char *)out + zstream.total_out;
264 zstream.avail_out = zstream.total_out;
265 } while (1);
266 end:
267 inflateEnd(&zstream);
268 free(*ptr);
269 *ptr = out;
270 return zstream.total_out / 4;
271 }
272
273 static int ascii85_decode(const char *in, uint32_t **out, bool inflate)
274 {
275 int len = 0, size = 1024;
276
277 *out = realloc(*out, sizeof(uint32_t)*size);
278 if (*out == NULL)
279 return 0;
280
281 while (*in >= '!' && *in <= 'z') {
282 uint32_t v = 0;
283
284 if (len == size) {
285 size *= 2;
286 *out = realloc(*out, sizeof(uint32_t)*size);
287 if (*out == NULL)
288 return 0;
289 }
290
291 if (*in == 'z') {
292 in++;
293 } else {
294 v += in[0] - 33; v *= 85;
295 v += in[1] - 33; v *= 85;
296 v += in[2] - 33; v *= 85;
297 v += in[3] - 33; v *= 85;
298 v += in[4] - 33;
299 in += 5;
300 }
301 (*out)[len++] = v;
302 }
303
304 if (!inflate)
305 return len;
306
307 return zlib_inflate(out, len);
308 }
309
310 static struct gen_batch_decode_bo
311 get_gen_batch_bo(void *user_data, uint64_t address)
312 {
313 for (int s = 0; s < MAX_SECTIONS; s++) {
314 if (sections[s].gtt_offset <= address &&
315 address < sections[s].gtt_offset + sections[s].count) {
316 return (struct gen_batch_decode_bo) {
317 .addr = sections[s].gtt_offset,
318 .map = sections[s].data,
319 .size = sections[s].count,
320 };
321 }
322 }
323
324 return (struct gen_batch_decode_bo) { .map = NULL };
325 }
326
327 static void
328 read_data_file(FILE *file)
329 {
330 struct gen_spec *spec = NULL;
331 long long unsigned fence;
332 int matched;
333 char *line = NULL;
334 size_t line_size;
335 uint32_t offset, value;
336 char *ring_name = NULL;
337 struct gen_device_info devinfo;
338 int sect_num = 0;
339
340 while (getline(&line, &line_size, file) > 0) {
341 char *new_ring_name = NULL;
342 char *dashes;
343
344 if (sscanf(line, "%m[^ ] command stream\n", &new_ring_name) > 0) {
345 free(ring_name);
346 ring_name = new_ring_name;
347 }
348
349 if (line[0] == ':' || line[0] == '~') {
350 uint32_t *data = NULL;
351 int count = ascii85_decode(line+1, &data, line[0] == ':');
352 if (count == 0) {
353 fprintf(stderr, "ASCII85 decode failed.\n");
354 exit(EXIT_FAILURE);
355 }
356 sections[sect_num].data = data;
357 sections[sect_num].count = count;
358 sect_num++;
359 continue;
360 }
361
362 dashes = strstr(line, "---");
363 if (dashes) {
364 const struct {
365 const char *match;
366 const char *name;
367 } buffers[] = {
368 { "ringbuffer", "ring buffer" },
369 { "gtt_offset", "batch buffer" },
370 { "hw context", "HW Context" },
371 { "hw status", "HW status" },
372 { "wa context", "WA context" },
373 { "wa batchbuffer", "WA batch" },
374 { "user", "user" },
375 { "semaphores", "semaphores", },
376 { "guc log buffer", "GuC log", },
377 { NULL, "unknown" },
378 }, *b;
379
380 free(ring_name);
381 ring_name = malloc(dashes - line);
382 strncpy(ring_name, line, dashes - line);
383 ring_name[dashes - line - 1] = '\0';
384
385 dashes += 4;
386 for (b = buffers; b->match; b++) {
387 if (strncasecmp(dashes, b->match, strlen(b->match)) == 0)
388 break;
389 }
390
391 sections[sect_num].buffer_name = b->name;
392 sections[sect_num].ring_name = strdup(ring_name);
393
394 uint32_t hi, lo;
395 dashes = strchr(dashes, '=');
396 if (dashes && sscanf(dashes, "= 0x%08x %08x\n", &hi, &lo))
397 sections[sect_num].gtt_offset = ((uint64_t) hi) << 32 | lo;
398
399 continue;
400 }
401
402 matched = sscanf(line, "%08x : %08x", &offset, &value);
403 if (matched != 2) {
404 uint32_t reg, reg2;
405
406 /* display reg section is after the ringbuffers, don't mix them */
407 printf("%s", line);
408
409 matched = sscanf(line, "PCI ID: 0x%04x\n", &reg);
410 if (matched == 0)
411 matched = sscanf(line, " PCI ID: 0x%04x\n", &reg);
412 if (matched == 0) {
413 const char *pci_id_start = strstr(line, "PCI ID");
414 if (pci_id_start)
415 matched = sscanf(pci_id_start, "PCI ID: 0x%04x\n", &reg);
416 }
417 if (matched == 1) {
418 if (!gen_get_device_info(reg, &devinfo)) {
419 printf("Unable to identify devid=%x\n", reg);
420 exit(EXIT_FAILURE);
421 }
422
423 printf("Detected GEN%i chipset\n", devinfo.gen);
424
425 if (xml_path == NULL)
426 spec = gen_spec_load(&devinfo);
427 else
428 spec = gen_spec_load_from_path(&devinfo, xml_path);
429 }
430
431 matched = sscanf(line, " CTL: 0x%08x\n", &reg);
432 if (matched == 1) {
433 print_register(spec,
434 register_name_from_ring(ctl_registers,
435 ARRAY_SIZE(ctl_registers),
436 ring_name), reg);
437 }
438
439 matched = sscanf(line, " HEAD: 0x%08x\n", &reg);
440 if (matched == 1)
441 print_head(reg);
442
443 matched = sscanf(line, " ACTHD: 0x%08x\n", &reg);
444 if (matched == 1) {
445 print_register(spec,
446 register_name_from_ring(acthd_registers,
447 ARRAY_SIZE(acthd_registers),
448 ring_name), reg);
449 }
450
451 matched = sscanf(line, " PGTBL_ER: 0x%08x\n", &reg);
452 if (matched == 1 && reg)
453 print_pgtbl_err(reg, &devinfo);
454
455 matched = sscanf(line, " ERROR: 0x%08x\n", &reg);
456 if (matched == 1 && reg) {
457 print_register(spec, "GFX_ARB_ERROR_RPT", reg);
458 }
459
460 matched = sscanf(line, " INSTDONE: 0x%08x\n", &reg);
461 if (matched == 1) {
462 const char *reg_name =
463 instdone_register_for_ring(&devinfo, ring_name);
464 if (reg_name)
465 print_register(spec, reg_name, reg);
466 }
467
468 matched = sscanf(line, " INSTDONE1: 0x%08x\n", &reg);
469 if (matched == 1)
470 print_register(spec, "INSTDONE_1", reg);
471
472 matched = sscanf(line, " fence[%i] = %Lx\n", &reg, &fence);
473 if (matched == 2)
474 print_fence(&devinfo, fence);
475
476 matched = sscanf(line, " FAULT_REG: 0x%08x\n", &reg);
477 if (matched == 1 && reg) {
478 const char *reg_name =
479 register_name_from_ring(fault_registers,
480 ARRAY_SIZE(fault_registers),
481 ring_name);
482 if (reg_name == NULL)
483 reg_name = "FAULT_REG";
484 print_register(spec, reg_name, reg);
485 }
486
487 matched = sscanf(line, " FAULT_TLB_DATA: 0x%08x 0x%08x\n", &reg, &reg2);
488 if (matched == 2)
489 print_fault_data(&devinfo, reg, reg2);
490
491 continue;
492 }
493 }
494
495 free(line);
496 free(ring_name);
497
498 enum gen_batch_decode_flags batch_flags = 0;
499 if (option_color == COLOR_ALWAYS)
500 batch_flags |= GEN_BATCH_DECODE_IN_COLOR;
501 if (option_full_decode)
502 batch_flags |= GEN_BATCH_DECODE_FULL;
503 if (option_print_offsets)
504 batch_flags |= GEN_BATCH_DECODE_OFFSETS;
505 batch_flags |= GEN_BATCH_DECODE_FLOATS;
506
507 struct gen_batch_decode_ctx batch_ctx;
508 gen_batch_decode_ctx_init(&batch_ctx, &devinfo, stdout, batch_flags,
509 xml_path, get_gen_batch_bo, NULL);
510
511
512 for (int s = 0; s < sect_num; s++) {
513 printf("--- %s (%s) at 0x%08x %08x\n",
514 sections[s].buffer_name, sections[s].ring_name,
515 (unsigned) (sections[s].gtt_offset >> 32),
516 (unsigned) sections[s].gtt_offset);
517
518 if (strcmp(sections[s].buffer_name, "batch buffer") == 0 ||
519 strcmp(sections[s].buffer_name, "ring buffer") == 0 ||
520 strcmp(sections[s].buffer_name, "HW Context") == 0) {
521 gen_print_batch(&batch_ctx, sections[s].data, sections[s].count,
522 sections[s].gtt_offset);
523 }
524 }
525
526 gen_batch_decode_ctx_finish(&batch_ctx);
527
528 for (int s = 0; s < sect_num; s++) {
529 free(sections[s].ring_name);
530 free(sections[s].data);
531 }
532 }
533
534 static void
535 setup_pager(void)
536 {
537 int fds[2];
538 pid_t pid;
539
540 if (!isatty(1))
541 return;
542
543 if (pipe(fds) == -1)
544 return;
545
546 pid = fork();
547 if (pid == -1)
548 return;
549
550 if (pid == 0) {
551 close(fds[1]);
552 dup2(fds[0], 0);
553 execlp("less", "less", "-FRSi", NULL);
554 }
555
556 close(fds[0]);
557 dup2(fds[1], 1);
558 close(fds[1]);
559 }
560
561 static void
562 print_help(const char *progname, FILE *file)
563 {
564 fprintf(file,
565 "Usage: %s [OPTION]... [FILE]\n"
566 "Parse an Intel GPU i915_error_state.\n"
567 "With no FILE, debugfs-dri-directory is probed for in /debug and \n"
568 "/sys/kernel/debug. Otherwise, it may be specified. If a file is given,\n"
569 "it is parsed as an GPU dump in the format of /debug/dri/0/i915_error_state.\n\n"
570 " --help display this help and exit\n"
571 " --headers decode only command headers\n"
572 " --color[=WHEN] colorize the output; WHEN can be 'auto' (default\n"
573 " if omitted), 'always', or 'never'\n"
574 " --no-pager don't launch pager\n"
575 " --no-offsets don't print instruction offsets\n"
576 " --xml=DIR load hardware xml description from directory DIR\n",
577 progname);
578 }
579
580 int
581 main(int argc, char *argv[])
582 {
583 FILE *file;
584 const char *path;
585 struct stat st;
586 int c, i, error;
587 bool help = false, pager = true;
588 const struct option aubinator_opts[] = {
589 { "help", no_argument, (int *) &help, true },
590 { "no-pager", no_argument, (int *) &pager, false },
591 { "no-offsets", no_argument, (int *) &option_print_offsets, false },
592 { "headers", no_argument, (int *) &option_full_decode, false },
593 { "color", required_argument, NULL, 'c' },
594 { "xml", required_argument, NULL, 'x' },
595 { NULL, 0, NULL, 0 }
596 };
597
598 i = 0;
599 while ((c = getopt_long(argc, argv, "", aubinator_opts, &i)) != -1) {
600 switch (c) {
601 case 'c':
602 if (optarg == NULL || strcmp(optarg, "always") == 0)
603 option_color = COLOR_ALWAYS;
604 else if (strcmp(optarg, "never") == 0)
605 option_color = COLOR_NEVER;
606 else if (strcmp(optarg, "auto") == 0)
607 option_color = COLOR_AUTO;
608 else {
609 fprintf(stderr, "invalid value for --color: %s", optarg);
610 exit(EXIT_FAILURE);
611 }
612 break;
613 case 'x':
614 xml_path = strdup(optarg);
615 break;
616 default:
617 break;
618 }
619 }
620
621 if (help || argc == 1) {
622 print_help(argv[0], stderr);
623 exit(EXIT_SUCCESS);
624 }
625
626 if (optind >= argc) {
627 if (isatty(0)) {
628 path = "/sys/class/drm/card0/error";
629 error = stat(path, &st);
630 if (error != 0) {
631 path = "/debug/dri";
632 error = stat(path, &st);
633 }
634 if (error != 0) {
635 path = "/sys/kernel/debug/dri";
636 error = stat(path, &st);
637 }
638 if (error != 0) {
639 errx(1,
640 "Couldn't find i915 debugfs directory.\n\n"
641 "Is debugfs mounted? You might try mounting it with a command such as:\n\n"
642 "\tsudo mount -t debugfs debugfs /sys/kernel/debug\n");
643 }
644 } else {
645 read_data_file(stdin);
646 exit(EXIT_SUCCESS);
647 }
648 } else {
649 path = argv[optind];
650 error = stat(path, &st);
651 if (error != 0) {
652 fprintf(stderr, "Error opening %s: %s\n",
653 path, strerror(errno));
654 exit(EXIT_FAILURE);
655 }
656 }
657
658 if (option_color == COLOR_AUTO)
659 option_color = isatty(1) ? COLOR_ALWAYS : COLOR_NEVER;
660
661 if (isatty(1) && pager)
662 setup_pager();
663
664 if (S_ISDIR(st.st_mode)) {
665 int ret;
666 char *filename;
667
668 ret = asprintf(&filename, "%s/i915_error_state", path);
669 assert(ret > 0);
670 file = fopen(filename, "r");
671 if (!file) {
672 int minor;
673 free(filename);
674 for (minor = 0; minor < 64; minor++) {
675 ret = asprintf(&filename, "%s/%d/i915_error_state", path, minor);
676 assert(ret > 0);
677
678 file = fopen(filename, "r");
679 if (file)
680 break;
681
682 free(filename);
683 }
684 }
685 if (!file) {
686 fprintf(stderr, "Failed to find i915_error_state beneath %s\n",
687 path);
688 return EXIT_FAILURE;
689 }
690 } else {
691 file = fopen(path, "r");
692 if (!file) {
693 fprintf(stderr, "Failed to open %s: %s\n",
694 path, strerror(errno));
695 return EXIT_FAILURE;
696 }
697 }
698
699 read_data_file(file);
700 fclose(file);
701
702 /* close the stdout which is opened to write the output */
703 fflush(stdout);
704 close(1);
705 wait(NULL);
706
707 if (xml_path)
708 free(xml_path);
709
710 return EXIT_SUCCESS;
711 }
712
713 /* vim: set ts=8 sw=8 tw=0 cino=:0,(0 noet :*/