1 /*
2 * Copyright © 2007 Intel Corporation
3 * Copyright © 2009 Intel Corporation
4 * Copyright © 2010 Intel Corporation
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the next
14 * paragraph) shall be included in all copies or substantial portions of the
15 * Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
23 * IN THE SOFTWARE.
24 *
25 * Authors:
26 * Eric Anholt <[email protected]>
27 * Carl Worth <[email protected]>
28 * Chris Wilson <[email protected]>
29 *
30 */
31
32 /** @file intel_decode.c
33 * This file contains code to print out batchbuffer contents in a
34 * human-readable format.
35 *
36 * The current version only supports i915 packets, and only pretty-prints a
37 * subset of them. The intention is for it to make just a best attempt to
38 * decode, but never crash in the process.
39 */
40
41 #include <stdbool.h>
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <stdarg.h>
45 #include <string.h>
46 #include <unistd.h>
47 #include <inttypes.h>
48 #include <errno.h>
49 #include <sys/stat.h>
50 #include <err.h>
51 #include <assert.h>
52 #include <intel_bufmgr.h>
53 #include <zlib.h>
54 #include <ctype.h>
55
56 #include "intel_chipset.h"
57 #include "intel_io.h"
58 #include "instdone.h"
59 #include "intel_reg.h"
60 #include "drmtest.h"
61
62 static uint32_t
print_head(unsigned int reg)63 print_head(unsigned int reg)
64 {
65 printf(" head = 0x%08x, wraps = %d\n", reg & (0x7ffff<<2), reg >> 21);
66 return reg & (0x7ffff<<2);
67 }
68
69 static uint32_t
print_ctl(unsigned int reg)70 print_ctl(unsigned int reg)
71 {
72 uint32_t ring_length = (((reg & (0x1ff << 12)) >> 12) + 1) * 4096;
73
74 #define BIT_STR(reg, x, on, off) ((1 << (x)) & reg) ? on : off
75
76 printf(" len=%d%s%s%s\n", ring_length,
77 BIT_STR(reg, 0, ", enabled", ", disabled"),
78 BIT_STR(reg, 10, ", semaphore wait ", ""),
79 BIT_STR(reg, 11, ", rb wait ", "")
80 );
81 #undef BIT_STR
82 return ring_length;
83 }
84
85 static void
print_acthd(unsigned int reg,unsigned int ring_length)86 print_acthd(unsigned int reg, unsigned int ring_length)
87 {
88 if ((reg & (0x7ffff << 2)) < ring_length)
89 printf(" at ring: 0x%08x\n", reg & (0x7ffff << 2));
90 else
91 printf(" at batch: 0x%08x\n", reg);
92 }
93
94 static void
print_instdone(uint32_t devid,unsigned int instdone,unsigned int instdone1)95 print_instdone(uint32_t devid, unsigned int instdone, unsigned int instdone1)
96 {
97 int i;
98 static int once;
99
100 if (!once) {
101 if (!init_instdone_definitions(devid))
102 return;
103 once = 1;
104 }
105
106 for (i = 0; i < num_instdone_bits; i++) {
107 int busy = 0;
108
109 if (instdone_bits[i].reg == INSTDONE_1) {
110 if (!(instdone1 & instdone_bits[i].bit))
111 busy = 1;
112 } else {
113 if (!(instdone & instdone_bits[i].bit))
114 busy = 1;
115 }
116
117 if (busy)
118 printf(" busy: %s\n", instdone_bits[i].name);
119 }
120 }
121
122 static void
print_i830_pgtbl_err(unsigned int reg)123 print_i830_pgtbl_err(unsigned int reg)
124 {
125 const char *str;
126
127 switch((reg >> 3) & 0xf) {
128 case 0x1: str = "Overlay TLB"; break;
129 case 0x2: str = "Display A TLB"; break;
130 case 0x3: str = "Host TLB"; break;
131 case 0x4: str = "Render TLB"; break;
132 case 0x5: str = "Display C TLB"; break;
133 case 0x6: str = "Mapping TLB"; break;
134 case 0x7: str = "Command Stream TLB"; break;
135 case 0x8: str = "Vertex Buffer TLB"; break;
136 case 0x9: str = "Display B TLB"; break;
137 case 0xa: str = "Reserved System Memory"; break;
138 case 0xb: str = "Compressor TLB"; break;
139 case 0xc: str = "Binner TLB"; break;
140 default: str = "unknown"; break;
141 }
142
143 if (str)
144 printf(" source = %s\n", str);
145
146 switch(reg & 0x7) {
147 case 0x0: str = "Invalid GTT"; break;
148 case 0x1: str = "Invalid GTT PTE"; break;
149 case 0x2: str = "Invalid Memory"; break;
150 case 0x3: str = "Invalid TLB miss"; break;
151 case 0x4: str = "Invalid PTE data"; break;
152 case 0x5: str = "Invalid LocalMemory not present"; break;
153 case 0x6: str = "Invalid Tiling"; break;
154 case 0x7: str = "Host to CAM"; break;
155 }
156 printf(" error = %s\n", str);
157 }
158
159 static void
print_i915_pgtbl_err(unsigned int reg)160 print_i915_pgtbl_err(unsigned int reg)
161 {
162 if (reg & (1 << 29))
163 printf(" Cursor A: Invalid GTT PTE\n");
164 if (reg & (1 << 28))
165 printf(" Cursor B: Invalid GTT PTE\n");
166 if (reg & (1 << 27))
167 printf(" MT: Invalid tiling\n");
168 if (reg & (1 << 26))
169 printf(" MT: Invalid GTT PTE\n");
170 if (reg & (1 << 25))
171 printf(" LC: Invalid tiling\n");
172 if (reg & (1 << 24))
173 printf(" LC: Invalid GTT PTE\n");
174 if (reg & (1 << 23))
175 printf(" BIN VertexData: Invalid GTT PTE\n");
176 if (reg & (1 << 22))
177 printf(" BIN Instruction: Invalid GTT PTE\n");
178 if (reg & (1 << 21))
179 printf(" CS VertexData: Invalid GTT PTE\n");
180 if (reg & (1 << 20))
181 printf(" CS Instruction: Invalid GTT PTE\n");
182 if (reg & (1 << 19))
183 printf(" CS: Invalid GTT\n");
184 if (reg & (1 << 18))
185 printf(" Overlay: Invalid tiling\n");
186 if (reg & (1 << 16))
187 printf(" Overlay: Invalid GTT PTE\n");
188 if (reg & (1 << 14))
189 printf(" Display C: Invalid tiling\n");
190 if (reg & (1 << 12))
191 printf(" Display C: Invalid GTT PTE\n");
192 if (reg & (1 << 10))
193 printf(" Display B: Invalid tiling\n");
194 if (reg & (1 << 8))
195 printf(" Display B: Invalid GTT PTE\n");
196 if (reg & (1 << 6))
197 printf(" Display A: Invalid tiling\n");
198 if (reg & (1 << 4))
199 printf(" Display A: Invalid GTT PTE\n");
200 if (reg & (1 << 1))
201 printf(" Host Invalid PTE data\n");
202 if (reg & (1 << 0))
203 printf(" Host Invalid GTT PTE\n");
204 }
205
206 static void
print_i965_pgtbl_err(unsigned int reg)207 print_i965_pgtbl_err(unsigned int reg)
208 {
209 if (reg & (1 << 26))
210 printf(" Invalid Sampler Cache GTT entry\n");
211 if (reg & (1 << 24))
212 printf(" Invalid Render Cache GTT entry\n");
213 if (reg & (1 << 23))
214 printf(" Invalid Instruction/State Cache GTT entry\n");
215 if (reg & (1 << 22))
216 printf(" There is no ROC, this cannot occur!\n");
217 if (reg & (1 << 21))
218 printf(" Invalid GTT entry during Vertex Fetch\n");
219 if (reg & (1 << 20))
220 printf(" Invalid GTT entry during Command Fetch\n");
221 if (reg & (1 << 19))
222 printf(" Invalid GTT entry during CS\n");
223 if (reg & (1 << 18))
224 printf(" Invalid GTT entry during Cursor Fetch\n");
225 if (reg & (1 << 17))
226 printf(" Invalid GTT entry during Overlay Fetch\n");
227 if (reg & (1 << 8))
228 printf(" Invalid GTT entry during Display B Fetch\n");
229 if (reg & (1 << 4))
230 printf(" Invalid GTT entry during Display A Fetch\n");
231 if (reg & (1 << 1))
232 printf(" Valid PTE references illegal memory\n");
233 if (reg & (1 << 0))
234 printf(" Invalid GTT entry during fetch for host\n");
235 }
236
237 static void
print_pgtbl_err(unsigned int reg,unsigned int devid)238 print_pgtbl_err(unsigned int reg, unsigned int devid)
239 {
240 if (IS_965(devid)) {
241 return print_i965_pgtbl_err(reg);
242 } else if (IS_GEN3(devid)) {
243 return print_i915_pgtbl_err(reg);
244 } else {
245 return print_i830_pgtbl_err(reg);
246 }
247 }
248
print_ivb_error(unsigned int reg,unsigned int devid)249 static void print_ivb_error(unsigned int reg, unsigned int devid)
250 {
251 if (reg & (1 << 0))
252 printf(" TLB page fault error (GTT entry not valid)\n");
253 if (reg & (1 << 1))
254 printf(" Invalid physical address in RSTRM interface (PAVP)\n");
255 if (reg & (1 << 2))
256 printf(" Invalid page directory entry error\n");
257 if (reg & (1 << 3))
258 printf(" Invalid physical address in ROSTRM interface (PAVP)\n");
259 if (reg & (1 << 4))
260 printf(" TLB page VTD translation generated an error\n");
261 if (reg & (1 << 5))
262 printf(" Invalid physical address in WRITE interface (PAVP)\n");
263 if (reg & (1 << 6))
264 printf(" Page directory VTD translation generated error\n");
265 if (reg & (1 << 8))
266 printf(" Cacheline containing a PD was marked as invalid\n");
267 if (IS_HASWELL(devid) && (reg >> 10) & 0x1f)
268 printf(" %d pending page faults\n", (reg >> 10) & 0x1f);
269 }
270
print_snb_error(unsigned int reg)271 static void print_snb_error(unsigned int reg)
272 {
273 if (reg & (1 << 0))
274 printf(" TLB page fault error (GTT entry not valid)\n");
275 if (reg & (1 << 1))
276 printf(" Context page GTT translation generated a fault (GTT entry not valid)\n");
277 if (reg & (1 << 2))
278 printf(" Invalid page directory entry error\n");
279 if (reg & (1 << 3))
280 printf(" HWS page GTT translation generated a page fault (GTT entry not valid)\n");
281 if (reg & (1 << 4))
282 printf(" TLB page VTD translation generated an error\n");
283 if (reg & (1 << 5))
284 printf(" Context page VTD translation generated an error\n");
285 if (reg & (1 << 6))
286 printf(" Page directory VTD translation generated error\n");
287 if (reg & (1 << 7))
288 printf(" HWS page VTD translation generated an error\n");
289 if (reg & (1 << 8))
290 printf(" Cacheline containing a PD was marked as invalid\n");
291 }
292
print_bdw_error(unsigned int reg,unsigned int devid)293 static void print_bdw_error(unsigned int reg, unsigned int devid)
294 {
295 print_ivb_error(reg, devid);
296
297 if (reg & (1 << 10))
298 printf(" Non WB memory type for Advanced Context\n");
299 if (reg & (1 << 11))
300 printf(" PASID not enabled\n");
301 if (reg & (1 << 12))
302 printf(" PASID boundary violation\n");
303 if (reg & (1 << 13))
304 printf(" PASID not valid\n");
305 if (reg & (1 << 14))
306 printf(" PASID was zero for untranslated request\n");
307 if (reg & (1 << 15))
308 printf(" Context was not marked as present when doing DMA\n");
309 }
310
311 static void
print_error(unsigned int reg,unsigned int devid)312 print_error(unsigned int reg, unsigned int devid)
313 {
314 switch (intel_gen(devid)) {
315 case 8: return print_bdw_error(reg, devid);
316 case 7: return print_ivb_error(reg, devid);
317 case 6: return print_snb_error(reg);
318 }
319 }
320
321 static void
print_snb_fence(unsigned int devid,uint64_t fence)322 print_snb_fence(unsigned int devid, uint64_t fence)
323 {
324 printf(" %svalid, %c-tiled, pitch: %i, start: 0x%08x, size: %u\n",
325 fence & 1 ? "" : "in",
326 fence & (1<<1) ? 'y' : 'x',
327 (int)(((fence>>32)&0xfff)+1)*128,
328 (uint32_t)fence & 0xfffff000,
329 (uint32_t)(((fence>>32)&0xfffff000) - (fence&0xfffff000) + 4096));
330 }
331
332 static void
print_i965_fence(unsigned int devid,uint64_t fence)333 print_i965_fence(unsigned int devid, uint64_t fence)
334 {
335 printf(" %svalid, %c-tiled, pitch: %i, start: 0x%08x, size: %u\n",
336 fence & 1 ? "" : "in",
337 fence & (1<<1) ? 'y' : 'x',
338 (int)(((fence>>2)&0x1ff)+1)*128,
339 (uint32_t)fence & 0xfffff000,
340 (uint32_t)(((fence>>32)&0xfffff000) - (fence&0xfffff000) + 4096));
341 }
342
343 static void
print_i915_fence(unsigned int devid,uint64_t fence)344 print_i915_fence(unsigned int devid, uint64_t fence)
345 {
346 unsigned tile_width;
347 if ((fence & 12) && !IS_915(devid))
348 tile_width = 128;
349 else
350 tile_width = 512;
351
352 printf(" %svalid, %c-tiled, pitch: %i, start: 0x%08x, size: %i\n",
353 fence & 1 ? "" : "in",
354 fence & (1<<12) ? 'y' : 'x',
355 (1<<((fence>>4)&0xf))*tile_width,
356 (uint32_t)fence & 0xff00000,
357 1<<(20 + ((fence>>8)&0xf)));
358 }
359
360 static void
print_i830_fence(unsigned int devid,uint64_t fence)361 print_i830_fence(unsigned int devid, uint64_t fence)
362 {
363 printf(" %svalid, %c-tiled, pitch: %i, start: 0x%08x, size: %i\n",
364 fence & 1 ? "" : "in",
365 fence & (1<<12) ? 'y' : 'x',
366 (1<<((fence>>4)&0xf))*128,
367 (uint32_t)fence & 0x7f80000,
368 1<<(19 + ((fence>>8)&0xf)));
369 }
370
371 static void
print_fence(unsigned int devid,uint64_t fence)372 print_fence(unsigned int devid, uint64_t fence)
373 {
374 if (IS_GEN6(devid) || IS_GEN7(devid)) {
375 return print_snb_fence(devid, fence);
376 } else if (IS_GEN4(devid) || IS_GEN5(devid)) {
377 return print_i965_fence(devid, fence);
378 } else if (IS_GEN3(devid)) {
379 return print_i915_fence(devid, fence);
380 } else {
381 return print_i830_fence(devid, fence);
382 }
383 }
384
385 static void
print_fault_reg(unsigned devid,uint32_t reg)386 print_fault_reg(unsigned devid, uint32_t reg)
387 {
388 const char *gen7_types[] = { "Page",
389 "Invalid PD",
390 "Unloaded PD",
391 "Invalid and Unloaded PD" };
392
393 const char *gen8_types[] = { "PTE",
394 "PDE",
395 "PDPE",
396 "PML4E" };
397
398 const char *engine[] = { "GFX", "MFX0", "MFX1", "VEBX",
399 "BLT", "Unknown", "Unknown", "Unknown" };
400
401 if (intel_gen(devid) < 7)
402 return;
403
404 if (reg & (1 << 0))
405 printf(" Valid\n");
406 else
407 return;
408
409 if (intel_gen(devid) < 8)
410 printf(" %s Fault (%s)\n", gen7_types[reg >> 1 & 0x3],
411 reg & (1 << 11) ? "GGTT" : "PPGTT");
412 else
413 printf(" Invalid %s Fault\n", gen8_types[reg >> 1 & 0x3]);
414
415 if (intel_gen(devid) < 8)
416 printf(" Address 0x%08x\n", reg & ~((1 << 12)-1));
417 else
418 printf(" Engine %s\n", engine[reg >> 12 & 0x7]);
419
420 printf(" Source ID %d\n", reg >> 3 & 0xff);
421 }
422
423 static void
print_fault_data(unsigned devid,uint32_t data1,uint32_t data0)424 print_fault_data(unsigned devid, uint32_t data1, uint32_t data0)
425 {
426 uint64_t address;
427
428 if (intel_gen(devid) < 8)
429 return;
430
431 address = ((uint64_t)(data0) << 12) | ((uint64_t)data1 & 0xf) << 44;
432 printf(" Address 0x%016" PRIx64 " %s\n", address,
433 data1 & (1 << 4) ? "GGTT" : "PPGTT");
434 }
435
436 #define MAX_RINGS 10 /* I really hope this never... */
437
maybe_ascii(const void * data,int check)438 static bool maybe_ascii(const void *data, int check)
439 {
440 const char *c = data;
441 while (check--) {
442 if (!isprint(*c++))
443 return false;
444 }
445 return true;
446 }
447
decode(struct drm_intel_decode * ctx,const char * buffer_name,const char * ring_name,uint64_t gtt_offset,uint32_t head_offset,uint32_t * data,int * count,int decode)448 static void decode(struct drm_intel_decode *ctx,
449 const char *buffer_name,
450 const char *ring_name,
451 uint64_t gtt_offset,
452 uint32_t head_offset,
453 uint32_t *data, int *count,
454 int decode)
455 {
456 if (!*count)
457 return;
458
459 printf("%s (%s) at 0x%08x_%08x", buffer_name, ring_name,
460 (unsigned)(gtt_offset >> 32),
461 (unsigned)(gtt_offset & 0xffffffff));
462 if (head_offset != -1)
463 printf("; HEAD points to: 0x%08x_%08x",
464 (unsigned)((head_offset + gtt_offset) >> 32),
465 (unsigned)((head_offset + gtt_offset) & 0xffffffff));
466 printf("\n");
467
468 if (decode) {
469 drm_intel_decode_set_batch_pointer(ctx, data, gtt_offset,
470 *count);
471 drm_intel_decode(ctx);
472 } else if (maybe_ascii(data, 16)) {
473 printf("%*s\n", 4 * *count, (char *)data);
474 } else {
475 for (int i = 0; i + 4 <= *count; i += 4)
476 printf("[%04x] %08x %08x %08x %08x\n",
477 4*i, data[i], data[i+1], data[i+2], data[i+3]);
478 }
479 *count = 0;
480 }
481
zlib_inflate(uint32_t ** ptr,int len)482 static int zlib_inflate(uint32_t **ptr, int len)
483 {
484 struct z_stream_s zstream;
485 void *out;
486
487 memset(&zstream, 0, sizeof(zstream));
488
489 zstream.next_in = (unsigned char *)*ptr;
490 zstream.avail_in = 4*len;
491
492 if (inflateInit(&zstream) != Z_OK)
493 return 0;
494
495 out = malloc(128*4096); /* approximate obj size */
496 zstream.next_out = out;
497 zstream.avail_out = 128*4096;
498
499 do {
500 switch (inflate(&zstream, Z_SYNC_FLUSH)) {
501 case Z_STREAM_END:
502 goto end;
503 case Z_OK:
504 break;
505 default:
506 inflateEnd(&zstream);
507 return 0;
508 }
509
510 if (zstream.avail_out)
511 break;
512
513 out = realloc(out, 2*zstream.total_out);
514 if (out == NULL) {
515 inflateEnd(&zstream);
516 return 0;
517 }
518
519 zstream.next_out = (unsigned char *)out + zstream.total_out;
520 zstream.avail_out = zstream.total_out;
521 } while (1);
522 end:
523 inflateEnd(&zstream);
524 free(*ptr);
525 *ptr = out;
526 return zstream.total_out / 4;
527 }
528
ascii85_decode(const char * in,uint32_t ** out,bool inflate)529 static int ascii85_decode(const char *in, uint32_t **out, bool inflate)
530 {
531 int len = 0, size = 1024;
532
533 *out = realloc(*out, sizeof(uint32_t)*size);
534 if (*out == NULL)
535 return 0;
536
537 while (*in >= '!' && *in <= 'z') {
538 uint32_t v = 0;
539
540 if (len == size) {
541 size *= 2;
542 *out = realloc(*out, sizeof(uint32_t)*size);
543 if (*out == NULL)
544 return 0;
545 }
546
547 if (*in == 'z') {
548 in++;
549 } else {
550 v += in[0] - 33; v *= 85;
551 v += in[1] - 33; v *= 85;
552 v += in[2] - 33; v *= 85;
553 v += in[3] - 33; v *= 85;
554 v += in[4] - 33;
555 in += 5;
556 }
557 (*out)[len++] = v;
558 }
559
560 if (!inflate)
561 return len;
562
563 return zlib_inflate(out, len);
564 }
565
566 static void
read_data_file(FILE * file)567 read_data_file(FILE *file)
568 {
569 struct drm_intel_decode *decode_ctx = NULL;
570 uint32_t devid = PCI_CHIP_I855_GM;
571 uint32_t *data = NULL;
572 uint32_t head[MAX_RINGS];
573 int head_idx = 0;
574 int num_rings = 0;
575 long long unsigned fence;
576 int data_size = 0, count = 0, matched;
577 char *line = NULL;
578 size_t line_size;
579 uint32_t offset, value, ring_length = 0;
580 uint64_t gtt_offset = 0;
581 uint32_t head_offset = -1;
582 const char *buffer_name = "batch buffer";
583 char *ring_name = NULL;
584 int do_decode = 1;
585
586 while (getline(&line, &line_size, file) > 0) {
587 char *dashes;
588
589 if (line[0] == ':' || line[0] == '~') {
590 count = ascii85_decode(line+1, &data, line[0] == ':');
591 if (count == 0)
592 fprintf(stderr, "ASCII85 decode failed (%s - %s).\n",
593 ring_name, buffer_name);
594 decode(decode_ctx,
595 buffer_name, ring_name,
596 gtt_offset, head_offset,
597 data, &count, do_decode);
598 continue;
599 }
600
601 dashes = strstr(line, "---");
602 if (dashes) {
603 const struct {
604 const char *match;
605 const char *name;
606 int do_decode;
607 } buffers[] = {
608 { "ringbuffer", "ring", 1 },
609 { "gtt_offset", "batch", 1 },
610 { "hw context", "HW context", 1 },
611 { "hw status", "HW status", 0 },
612 { "wa context", "WA context", 1 },
613 { "wa batchbuffer", "WA batch", 1 },
614 { "user", "user", 0 },
615 { "semaphores", "semaphores", 0 },
616 { "guc log buffer", "GuC log", 0 },
617 { },
618 }, *b;
619 char *new_ring_name;
620
621 new_ring_name = malloc(dashes - line);
622 strncpy(new_ring_name, line, dashes - line);
623 new_ring_name[dashes - line - 1] = '\0';
624
625 decode(decode_ctx,
626 buffer_name, ring_name,
627 gtt_offset, head_offset,
628 data, &count, do_decode);
629 gtt_offset = 0;
630 head_offset = -1;
631
632 free(ring_name);
633 ring_name = new_ring_name;
634
635 dashes += 4;
636 for (b = buffers; b->match; b++) {
637 uint32_t lo, hi;
638
639 if (strncasecmp(dashes, b->match,
640 strlen(b->match)))
641 continue;
642
643 dashes = strchr(dashes, '=');
644 if (!dashes)
645 break;
646
647 matched = sscanf(dashes, "= 0x%08x %08x\n",
648 &hi, &lo);
649 if (matched > 0) {
650 gtt_offset = hi;
651 if (matched == 2) {
652 gtt_offset <<= 32;
653 gtt_offset |= lo;
654 }
655 }
656
657 do_decode = b->do_decode;
658 buffer_name = b->name;
659 if (b == buffers)
660 head_offset = head[head_idx++];
661 break;
662 }
663
664 continue;
665 }
666
667 matched = sscanf(line, "%08x : %08x", &offset, &value);
668 if (matched != 2) {
669 unsigned int reg, reg2;
670
671 /* display reg section is after the ringbuffers, don't mix them */
672 decode(decode_ctx,
673 buffer_name, ring_name,
674 gtt_offset, head_offset,
675 data, &count, do_decode);
676
677 printf("%s", line);
678
679 matched = sscanf(line, "PCI ID: 0x%04x\n", ®);
680 if (matched == 0)
681 matched = sscanf(line, " PCI ID: 0x%04x\n", ®);
682 if (matched == 0) {
683 const char *pci_id_start = strstr(line, "PCI ID");
684 if (pci_id_start)
685 matched = sscanf(pci_id_start, "PCI ID: 0x%04x\n", ®);
686 }
687 if (matched == 1) {
688 devid = reg;
689 printf("Detected GEN%i chipset\n",
690 intel_gen(devid));
691
692 decode_ctx = drm_intel_decode_context_alloc(devid);
693 }
694
695 matched = sscanf(line, " CTL: 0x%08x\n", ®);
696 if (matched == 1)
697 ring_length = print_ctl(reg);
698
699 matched = sscanf(line, " HEAD: 0x%08x\n", ®);
700 if (matched == 1) {
701 head[num_rings++] = print_head(reg);
702 }
703
704 matched = sscanf(line, " ACTHD: 0x%08x\n", ®);
705 if (matched == 1) {
706 print_acthd(reg, ring_length);
707 drm_intel_decode_set_head_tail(decode_ctx, reg, 0xffffffff);
708 }
709
710 matched = sscanf(line, " PGTBL_ER: 0x%08x\n", ®);
711 if (matched == 1 && reg)
712 print_pgtbl_err(reg, devid);
713
714 matched = sscanf(line, " ERROR: 0x%08x\n", ®);
715 if (matched == 1 && reg)
716 print_error(reg, devid);
717
718 matched = sscanf(line, " INSTDONE: 0x%08x\n", ®);
719 if (matched == 1)
720 print_instdone(devid, reg, -1);
721
722 matched = sscanf(line, " INSTDONE1: 0x%08x\n", ®);
723 if (matched == 1)
724 print_instdone(devid, -1, reg);
725
726 matched = sscanf(line, " fence[%i] = %Lx\n", ®, &fence);
727 if (matched == 2)
728 print_fence(devid, fence);
729
730 matched = sscanf(line, " FAULT_REG: 0x%08x\n", ®);
731 if (matched == 1 && reg)
732 print_fault_reg(devid, reg);
733
734 matched = sscanf(line, " FAULT_TLB_DATA: 0x%08x 0x%08x\n", ®, ®2);
735 if (matched == 2)
736 print_fault_data(devid, reg, reg2);
737
738 continue;
739 }
740
741 count++;
742
743 if (count > data_size) {
744 data_size = data_size ? data_size * 2 : 1024;
745 data = realloc(data, data_size * sizeof (uint32_t));
746 if (data == NULL) {
747 fprintf(stderr, "Out of memory.\n");
748 exit(1);
749 }
750 }
751
752 data[count-1] = value;
753 }
754
755 decode(decode_ctx,
756 buffer_name, ring_name,
757 gtt_offset, head_offset,
758 data, &count, do_decode);
759
760 free(data);
761 free(line);
762 free(ring_name);
763 }
764
setup_pager(void)765 static void setup_pager(void)
766 {
767 int fds[2];
768
769 if (pipe(fds) == -1)
770 return;
771
772 switch (fork()) {
773 case -1:
774 break;
775 case 0:
776 close(fds[1]);
777 dup2(fds[0], 0);
778 execlp("less", "less", "-FRSi", NULL);
779 break;
780
781 default:
782 close(fds[0]);
783 dup2(fds[1], 1);
784 close(fds[1]);
785 break;
786 }
787 }
788
789 int
main(int argc,char * argv[])790 main(int argc, char *argv[])
791 {
792 FILE *file;
793 const char *path;
794 char *filename = NULL;
795 struct stat st;
796 int error;
797
798 if (argc > 2) {
799 fprintf(stderr,
800 "intel_gpu_decode: Parse an Intel GPU i915_error_state\n"
801 "Usage:\n"
802 "\t%s [<file>]\n"
803 "\n"
804 "With no arguments, debugfs-dri-directory is probed for in "
805 "/debug and \n"
806 "/sys/kernel/debug. Otherwise, it may be "
807 "specified. If a file is given,\n"
808 "it is parsed as an GPU dump in the format of "
809 "/debug/dri/0/i915_error_state.\n",
810 argv[0]);
811 return 1;
812 }
813
814 if (isatty(1))
815 setup_pager();
816
817 if (argc == 1) {
818 if (isatty(0)) {
819 path = "/sys/class/drm/card0/error";
820 error = stat(path, &st);
821 if (error != 0) {
822 path = "/debug/dri";
823 error = stat(path, &st);
824 }
825 if (error != 0) {
826 path = "/sys/kernel/debug/dri";
827 error = stat(path, &st);
828 }
829 if (error != 0) {
830 errx(1,
831 "Couldn't find i915 debugfs directory.\n\n"
832 "Is debugfs mounted? You might try mounting it with a command such as:\n\n"
833 "\tsudo mount -t debugfs debugfs /sys/kernel/debug\n");
834 }
835 } else {
836 read_data_file(stdin);
837 exit(0);
838 }
839 } else {
840 path = argv[1];
841 error = stat(path, &st);
842 if (error != 0) {
843 fprintf(stderr, "Error opening %s: %s\n",
844 path, strerror(errno));
845 exit(1);
846 }
847 }
848
849 if (S_ISDIR(st.st_mode)) {
850 int ret;
851
852 ret = asprintf(&filename, "%s/i915_error_state", path);
853 assert(ret > 0);
854 file = fopen(filename, "r");
855 if (!file) {
856 int minor;
857 for (minor = 0; minor < 64; minor++) {
858 free(filename);
859 ret = asprintf(&filename, "%s/%d/i915_error_state", path, minor);
860 assert(ret > 0);
861
862 file = fopen(filename, "r");
863 if (file)
864 break;
865 }
866 }
867 if (!file) {
868 fprintf(stderr, "Failed to find i915_error_state beneath %s\n",
869 path);
870 exit (1);
871 }
872 } else {
873 file = fopen(path, "r");
874 if (!file) {
875 fprintf(stderr, "Failed to open %s: %s\n",
876 path, strerror(errno));
877 exit (1);
878 }
879 }
880
881 read_data_file(file);
882 fclose(file);
883
884 if (filename != path)
885 free(filename);
886
887 return 0;
888 }
889
890 /* vim: set ts=8 sw=8 tw=0 cino=:0,(0 noet :*/
891