Home | History | Annotate | Line # | Download | only in tools
      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 
     49 static bool option_full_decode = true;
     50 static bool option_print_all_bb = false;
     51 static bool option_print_offsets = true;
     52 static enum { COLOR_AUTO, COLOR_ALWAYS, COLOR_NEVER } option_color;
     53 static char *xml_path = NULL;
     54 
     55 static uint32_t
     56 print_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 
     62 static void
     63 print_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, &reg, 0,
     70                         option_color == COLOR_ALWAYS);
     71    }
     72 }
     73 
     74 struct ring_register_mapping {
     75    enum drm_i915_gem_engine_class ring_class;
     76    unsigned ring_instance;
     77    const char *register_name;
     78 };
     79 
     80 static 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 
     88 static 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 
     96 static 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 
    103 static 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 
    142 static const char *
    143 register_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 
    162 static const char *
    163 instdone_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 
    203 static void
    204 print_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 
    234 static void
    235 print_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 
    245 static void
    246 print_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 
    256 static void
    257 print_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 
    266 static void
    267 print_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 
    282 struct 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
    292 static unsigned num_sections;
    293 static struct section sections[MAX_SECTIONS];
    294 
    295 static 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 
    343 static 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 
    380 static 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 
    391 static struct intel_batch_decode_bo
    392 get_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 
    408 static void
    409 read_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", &reg);
    498          if (matched == 0)
    499             matched = sscanf(line, " PCI ID: 0x%04x\n", &reg);
    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", &reg);
    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", &reg);
    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", &reg);
    528          if (matched == 1)
    529             print_head(reg);
    530 
    531          sscanf(line, "  HEAD: 0x%08x [0x%08X]\n", &reg, &ring_head);
    532          sscanf(line, "  TAIL: 0x%08x\n", &ring_tail);
    533 
    534          matched = sscanf(line, "  ACTHD: 0x%08x\n", &reg);
    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", &reg, &reg2);
    543          if (matched == 2)
    544             acthd = ((uint64_t)reg << 32) | reg2;
    545 
    546          matched = sscanf(line, "  PGTBL_ER: 0x%08x\n", &reg);
    547          if (matched == 1 && reg)
    548             print_pgtbl_err(reg, &devinfo);
    549 
    550          matched = sscanf(line, "  ERROR: 0x%08x\n", &reg);
    551          if (matched == 1 && reg) {
    552             print_register(spec, "GFX_ARB_ERROR_RPT", reg);
    553          }
    554 
    555          matched = sscanf(line, "  INSTDONE: 0x%08x\n", &reg);
    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", &reg);
    564          if (matched == 1)
    565             print_register(spec, "SC_INSTDONE", reg);
    566 
    567          matched = sscanf(line, "  SC_INSTDONE_EXTRA: 0x%08x\n", &reg);
    568          if (matched == 1)
    569             print_register(spec, "SC_INSTDONE_EXTRA", reg);
    570 
    571          matched = sscanf(line, "  SC_INSTDONE_EXTRA2: 0x%08x\n", &reg);
    572          if (matched == 1)
    573             print_register(spec, "SC_INSTDONE_EXTRA2", reg);
    574 
    575          matched = sscanf(line, "  SAMPLER_INSTDONE[%*d][%*d]: 0x%08x\n", &reg);
    576          if (matched == 1)
    577             print_register(spec, "SAMPLER_INSTDONE", reg);
    578 
    579          matched = sscanf(line, "  ROW_INSTDONE[%*d][%*d]: 0x%08x\n", &reg);
    580          if (matched == 1)
    581             print_register(spec, "ROW_INSTDONE", reg);
    582 
    583          matched = sscanf(line, "  GEOM_SVGUNIT_INSTDONE[%*d][%*d]: 0x%08x\n", &reg);
    584          if (matched == 1)
    585             print_register(spec, "INSTDONE_GEOM", reg);
    586 
    587          matched = sscanf(line, "  INSTDONE1: 0x%08x\n", &reg);
    588          if (matched == 1)
    589             print_register(spec, "INSTDONE_1", reg);
    590 
    591          matched = sscanf(line, "  fence[%i] = %Lx\n", &reg, &fence);
    592          if (matched == 2)
    593             print_fence(&devinfo, fence);
    594 
    595          matched = sscanf(line, "  FAULT_REG: 0x%08x\n", &reg);
    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", &reg, &reg2);
    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 
    715 static void
    716 setup_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 
    742 static void
    743 print_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 
    762 static FILE *
    763 open_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 
    807 int
    808 main(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