2 * Copyright © 2007-2017 Intel Corporation
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:
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
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
34 #include <sys/types.h>
41 #include "common/gen_decoder.h"
42 #include "util/macros.h"
45 #define BLUE_HEADER CSI "0;44m"
46 #define GREEN_HEADER CSI "1;42m"
47 #define NORMAL CSI "0m"
51 static bool option_full_decode
= true;
52 static bool option_print_offsets
= true;
53 static enum { COLOR_AUTO
, COLOR_ALWAYS
, COLOR_NEVER
} option_color
;
54 static char *xml_path
= NULL
;
57 print_head(unsigned int reg
)
59 printf(" head = 0x%08x, wraps = %d\n", reg
& (0x7ffff<<2), reg
>> 21);
60 return reg
& (0x7ffff<<2);
64 print_register(struct gen_spec
*spec
, const char *name
, uint32_t reg
)
66 struct gen_group
*reg_spec
= gen_spec_find_register_by_name(spec
, name
);
69 gen_print_group(stdout
, reg_spec
, 0, ®
, option_color
== COLOR_ALWAYS
);
72 struct ring_register_mapping
{
73 const char *ring_name
;
74 const char *register_name
;
77 static const struct ring_register_mapping acthd_registers
[] = {
78 { "blt", "BCS_ACTHD_UDW" },
79 { "bsd", "VCS_ACTHD_UDW" },
80 { "bsd2", "VCS2_ACTHD_UDW" },
81 { "render", "ACTHD_UDW" },
82 { "vebox", "VECS_ACTHD_UDW" },
85 static const struct ring_register_mapping ctl_registers
[] = {
86 { "blt", "BCS_RING_BUFFER_CTL" },
87 { "bsd", "VCS_RING_BUFFER_CTL" },
88 { "bsd2", "VCS2_RING_BUFFER_CTL" },
89 { "render", "RCS_RING_BUFFER_CTL" },
90 { "vebox", "VECS_RING_BUFFER_CTL" },
93 static const struct ring_register_mapping fault_registers
[] = {
94 { "blt", "BCS_FAULT_REG" },
95 { "bsd", "VCS_FAULT_REG" },
96 { "render", "RCS_FAULT_REG" },
97 { "vebox", "VECS_FAULT_REG" },
101 register_name_from_ring(const struct ring_register_mapping
*mapping
,
103 const char *ring_name
)
105 for (unsigned i
= 0; i
< nb_mapping
; i
++) {
106 if (strcmp(mapping
[i
].ring_name
, ring_name
) == 0)
107 return mapping
[i
].register_name
;
113 instdone_register_for_ring(const struct gen_device_info
*devinfo
,
114 const char *ring_name
)
116 if (strcmp(ring_name
, "blt") == 0)
117 return "BCS_INSTDONE";
118 else if (strcmp(ring_name
, "vebox") == 0)
119 return "VECS_INSTDONE";
120 else if (strcmp(ring_name
, "bsd") == 0)
121 return "VCS_INSTDONE";
122 else if (strcmp(ring_name
, "render") == 0) {
123 if (devinfo
->gen
== 6)
132 print_pgtbl_err(unsigned int reg
, struct gen_device_info
*devinfo
)
135 printf(" Invalid Sampler Cache GTT entry\n");
137 printf(" Invalid Render Cache GTT entry\n");
139 printf(" Invalid Instruction/State Cache GTT entry\n");
141 printf(" There is no ROC, this cannot occur!\n");
143 printf(" Invalid GTT entry during Vertex Fetch\n");
145 printf(" Invalid GTT entry during Command Fetch\n");
147 printf(" Invalid GTT entry during CS\n");
149 printf(" Invalid GTT entry during Cursor Fetch\n");
151 printf(" Invalid GTT entry during Overlay Fetch\n");
153 printf(" Invalid GTT entry during Display B Fetch\n");
155 printf(" Invalid GTT entry during Display A Fetch\n");
157 printf(" Valid PTE references illegal memory\n");
159 printf(" Invalid GTT entry during fetch for host\n");
163 print_snb_fence(struct gen_device_info
*devinfo
, uint64_t fence
)
165 printf(" %svalid, %c-tiled, pitch: %i, start: 0x%08x, size: %u\n",
166 fence
& 1 ? "" : "in",
167 fence
& (1<<1) ? 'y' : 'x',
168 (int)(((fence
>>32)&0xfff)+1)*128,
169 (uint32_t)fence
& 0xfffff000,
170 (uint32_t)(((fence
>>32)&0xfffff000) - (fence
&0xfffff000) + 4096));
174 print_i965_fence(struct gen_device_info
*devinfo
, uint64_t fence
)
176 printf(" %svalid, %c-tiled, pitch: %i, start: 0x%08x, size: %u\n",
177 fence
& 1 ? "" : "in",
178 fence
& (1<<1) ? 'y' : 'x',
179 (int)(((fence
>>2)&0x1ff)+1)*128,
180 (uint32_t)fence
& 0xfffff000,
181 (uint32_t)(((fence
>>32)&0xfffff000) - (fence
&0xfffff000) + 4096));
185 print_fence(struct gen_device_info
*devinfo
, uint64_t fence
)
187 if (devinfo
->gen
== 6 || devinfo
->gen
== 7) {
188 return print_snb_fence(devinfo
, fence
);
189 } else if (devinfo
->gen
== 4 || devinfo
->gen
== 5) {
190 return print_i965_fence(devinfo
, fence
);
195 print_fault_data(struct gen_device_info
*devinfo
, uint32_t data1
, uint32_t data0
)
199 if (devinfo
->gen
< 8)
202 address
= ((uint64_t)(data0
) << 12) | ((uint64_t)data1
& 0xf) << 44;
203 printf(" Address 0x%016" PRIx64
" %s\n", address
,
204 data1
& (1 << 4) ? "GGTT" : "PPGTT");
207 #define MAX_RINGS 10 /* I really hope this never... */
210 #define NORMAL CSI "0m"
212 static void decode(struct gen_spec
*spec
,
213 const char *buffer_name
,
214 const char *ring_name
,
219 uint32_t *p
, *end
= (data
+ *count
);
221 struct gen_group
*inst
;
223 for (p
= data
; p
< end
; p
+= length
) {
224 const char *color
= option_full_decode
? BLUE_HEADER
: NORMAL
,
225 *reset_color
= NORMAL
;
226 uint64_t offset
= gtt_offset
+ 4 * (p
- data
);
228 inst
= gen_spec_find_instruction(spec
, p
);
229 length
= gen_group_get_length(inst
, p
);
230 assert(inst
== NULL
|| length
> 0);
231 length
= MAX2(1, length
);
233 printf("unknown instruction %08x\n", p
[0]);
236 if (option_color
== COLOR_NEVER
) {
241 printf("%s0x%08"PRIx64
": 0x%08x: %-80s%s\n",
242 color
, offset
, p
[0], gen_group_get_name(inst
), reset_color
);
244 gen_print_group(stdout
, inst
, offset
, p
,
245 option_color
== COLOR_ALWAYS
);
247 if (strcmp(inst
->name
, "MI_BATCH_BUFFER_END") == 0)
252 static int zlib_inflate(uint32_t **ptr
, int len
)
254 struct z_stream_s zstream
;
256 const uint32_t out_size
= 128*4096; /* approximate obj size */
258 memset(&zstream
, 0, sizeof(zstream
));
260 zstream
.next_in
= (unsigned char *)*ptr
;
261 zstream
.avail_in
= 4*len
;
263 if (inflateInit(&zstream
) != Z_OK
)
266 out
= malloc(out_size
);
267 zstream
.next_out
= out
;
268 zstream
.avail_out
= out_size
;
271 switch (inflate(&zstream
, Z_SYNC_FLUSH
)) {
277 inflateEnd(&zstream
);
281 if (zstream
.avail_out
)
284 out
= realloc(out
, 2*zstream
.total_out
);
286 inflateEnd(&zstream
);
290 zstream
.next_out
= (unsigned char *)out
+ zstream
.total_out
;
291 zstream
.avail_out
= zstream
.total_out
;
294 inflateEnd(&zstream
);
297 return zstream
.total_out
/ 4;
300 static int ascii85_decode(const char *in
, uint32_t **out
, bool inflate
)
302 int len
= 0, size
= 1024;
304 *out
= realloc(*out
, sizeof(uint32_t)*size
);
308 while (*in
>= '!' && *in
<= 'z') {
313 *out
= realloc(*out
, sizeof(uint32_t)*size
);
321 v
+= in
[0] - 33; v
*= 85;
322 v
+= in
[1] - 33; v
*= 85;
323 v
+= in
[2] - 33; v
*= 85;
324 v
+= in
[3] - 33; v
*= 85;
334 return zlib_inflate(out
, len
);
338 read_data_file(FILE *file
)
340 struct gen_spec
*spec
= NULL
;
341 uint32_t *data
= NULL
;
342 long long unsigned fence
;
343 int data_size
= 0, count
= 0, line_number
= 0, matched
;
346 uint32_t offset
, value
;
347 uint64_t gtt_offset
= 0, new_gtt_offset
;
348 const char *buffer_name
= "batch buffer";
349 char *ring_name
= NULL
;
350 struct gen_device_info devinfo
;
352 while (getline(&line
, &line_size
, file
) > 0) {
353 char *new_ring_name
= NULL
;
357 if (sscanf(line
, "%m[^ ] command stream\n", &new_ring_name
) > 0) {
359 ring_name
= new_ring_name
;
362 dashes
= strstr(line
, "---");
365 char *new_ring_name
= malloc(dashes
- line
);
366 strncpy(new_ring_name
, line
, dashes
- line
);
367 new_ring_name
[dashes
- line
- 1] = '\0';
371 matched
= sscanf(dashes
, "--- gtt_offset = 0x%08x %08x\n",
376 new_gtt_offset
<<= 32;
377 new_gtt_offset
|= lo
;
381 buffer_name
, ring_name
,
382 gtt_offset
, data
, &count
);
383 gtt_offset
= new_gtt_offset
;
385 ring_name
= new_ring_name
;
386 buffer_name
= "batch buffer";
390 matched
= sscanf(dashes
, "--- ringbuffer = 0x%08x %08x\n",
395 new_gtt_offset
<<= 32;
396 new_gtt_offset
|= lo
;
400 buffer_name
, ring_name
,
401 gtt_offset
, data
, &count
);
402 gtt_offset
= new_gtt_offset
;
404 ring_name
= new_ring_name
;
405 buffer_name
= "ring buffer";
409 matched
= sscanf(dashes
, "--- HW Context = 0x%08x %08x\n",
414 new_gtt_offset
<<= 32;
415 new_gtt_offset
|= lo
;
419 buffer_name
, ring_name
,
420 gtt_offset
, data
, &count
);
421 gtt_offset
= new_gtt_offset
;
423 ring_name
= new_ring_name
;
424 buffer_name
= "HW Context";
429 if (line
[0] == ':' || line
[0] == '~') {
430 count
= ascii85_decode(line
+1, &data
, line
[0] == ':');
432 fprintf(stderr
, "ASCII85 decode failed.\n");
436 buffer_name
, ring_name
,
437 gtt_offset
, data
, &count
);
441 matched
= sscanf(line
, "%08x : %08x", &offset
, &value
);
445 /* display reg section is after the ringbuffers, don't mix them */
447 buffer_name
, ring_name
,
448 gtt_offset
, data
, &count
);
452 matched
= sscanf(line
, "PCI ID: 0x%04x\n", ®
);
454 matched
= sscanf(line
, " PCI ID: 0x%04x\n", ®
);
456 const char *pci_id_start
= strstr(line
, "PCI ID");
458 matched
= sscanf(pci_id_start
, "PCI ID: 0x%04x\n", ®
);
461 if (!gen_get_device_info(reg
, &devinfo
)) {
462 printf("Unable to identify devid=%x\n", reg
);
466 printf("Detected GEN%i chipset\n", devinfo
.gen
);
468 if (xml_path
== NULL
)
469 spec
= gen_spec_load(&devinfo
);
471 spec
= gen_spec_load_from_path(&devinfo
, xml_path
);
474 matched
= sscanf(line
, " CTL: 0x%08x\n", ®
);
477 register_name_from_ring(ctl_registers
,
478 ARRAY_SIZE(ctl_registers
),
482 matched
= sscanf(line
, " HEAD: 0x%08x\n", ®
);
486 matched
= sscanf(line
, " ACTHD: 0x%08x\n", ®
);
489 register_name_from_ring(acthd_registers
,
490 ARRAY_SIZE(acthd_registers
),
494 matched
= sscanf(line
, " PGTBL_ER: 0x%08x\n", ®
);
495 if (matched
== 1 && reg
)
496 print_pgtbl_err(reg
, &devinfo
);
498 matched
= sscanf(line
, " ERROR: 0x%08x\n", ®
);
499 if (matched
== 1 && reg
) {
500 print_register(spec
, "GFX_ARB_ERROR_RPT", reg
);
503 matched
= sscanf(line
, " INSTDONE: 0x%08x\n", ®
);
505 const char *reg_name
=
506 instdone_register_for_ring(&devinfo
, ring_name
);
508 print_register(spec
, reg_name
, reg
);
511 matched
= sscanf(line
, " INSTDONE1: 0x%08x\n", ®
);
513 print_register(spec
, "INSTDONE_1", reg
);
515 matched
= sscanf(line
, " fence[%i] = %Lx\n", ®
, &fence
);
517 print_fence(&devinfo
, fence
);
519 matched
= sscanf(line
, " FAULT_REG: 0x%08x\n", ®
);
520 if (matched
== 1 && reg
) {
521 const char *reg_name
=
522 register_name_from_ring(fault_registers
,
523 ARRAY_SIZE(fault_registers
),
525 if (reg_name
== NULL
)
526 reg_name
= "FAULT_REG";
527 print_register(spec
, reg_name
, reg
);
530 matched
= sscanf(line
, " FAULT_TLB_DATA: 0x%08x 0x%08x\n", ®
, ®2
);
532 print_fault_data(&devinfo
, reg
, reg2
);
539 if (count
> data_size
) {
540 data_size
= data_size
? data_size
* 2 : 1024;
541 data
= realloc(data
, data_size
* sizeof (uint32_t));
543 fprintf(stderr
, "Out of memory.\n");
548 data
[count
-1] = value
;
552 buffer_name
, ring_name
,
553 gtt_offset
, data
, &count
);
579 execlp("less", "less", "-FRSi", NULL
);
588 print_help(const char *progname
, FILE *file
)
591 "Usage: %s [OPTION]... [FILE]\n"
592 "Parse an Intel GPU i915_error_state.\n"
593 "With no FILE, debugfs-dri-directory is probed for in /debug and \n"
594 "/sys/kernel/debug. Otherwise, it may be specified. If a file is given,\n"
595 "it is parsed as an GPU dump in the format of /debug/dri/0/i915_error_state.\n\n"
596 " --help display this help and exit\n"
597 " --headers decode only command headers\n"
598 " --color[=WHEN] colorize the output; WHEN can be 'auto' (default\n"
599 " if omitted), 'always', or 'never'\n"
600 " --no-pager don't launch pager\n"
601 " --no-offsets don't print instruction offsets\n"
602 " --xml=DIR load hardware xml description from directory DIR\n",
607 main(int argc
, char *argv
[])
613 bool help
= false, pager
= true;
614 const struct option aubinator_opts
[] = {
615 { "help", no_argument
, (int *) &help
, true },
616 { "no-pager", no_argument
, (int *) &pager
, false },
617 { "no-offsets", no_argument
, (int *) &option_print_offsets
, false },
618 { "headers", no_argument
, (int *) &option_full_decode
, false },
619 { "color", required_argument
, NULL
, 'c' },
620 { "xml", required_argument
, NULL
, 'x' },
625 while ((c
= getopt_long(argc
, argv
, "", aubinator_opts
, &i
)) != -1) {
628 if (optarg
== NULL
|| strcmp(optarg
, "always") == 0)
629 option_color
= COLOR_ALWAYS
;
630 else if (strcmp(optarg
, "never") == 0)
631 option_color
= COLOR_NEVER
;
632 else if (strcmp(optarg
, "auto") == 0)
633 option_color
= COLOR_AUTO
;
635 fprintf(stderr
, "invalid value for --color: %s", optarg
);
640 xml_path
= strdup(optarg
);
647 if (help
|| argc
== 1) {
648 print_help(argv
[0], stderr
);
652 if (optind
>= argc
) {
654 path
= "/sys/class/drm/card0/error";
655 error
= stat(path
, &st
);
658 error
= stat(path
, &st
);
661 path
= "/sys/kernel/debug/dri";
662 error
= stat(path
, &st
);
666 "Couldn't find i915 debugfs directory.\n\n"
667 "Is debugfs mounted? You might try mounting it with a command such as:\n\n"
668 "\tsudo mount -t debugfs debugfs /sys/kernel/debug\n");
671 read_data_file(stdin
);
676 error
= stat(path
, &st
);
678 fprintf(stderr
, "Error opening %s: %s\n",
679 path
, strerror(errno
));
684 if (option_color
== COLOR_AUTO
)
685 option_color
= isatty(1) ? COLOR_ALWAYS
: COLOR_NEVER
;
687 if (isatty(1) && pager
)
690 if (S_ISDIR(st
.st_mode
)) {
694 ret
= asprintf(&filename
, "%s/i915_error_state", path
);
696 file
= fopen(filename
, "r");
699 for (minor
= 0; minor
< 64; minor
++) {
701 ret
= asprintf(&filename
, "%s/%d/i915_error_state", path
, minor
);
704 file
= fopen(filename
, "r");
712 fprintf(stderr
, "Failed to find i915_error_state beneath %s\n",
717 file
= fopen(path
, "r");
719 fprintf(stderr
, "Failed to open %s: %s\n",
720 path
, strerror(errno
));
725 read_data_file(file
);
728 /* close the stdout which is opened to write the output */
739 /* vim: set ts=8 sw=8 tw=0 cino=:0,(0 noet :*/