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