blob: 39177379a3b03cf43335b19b7e535a7f6f9b139e [file] [log] [blame]
Chris Wilson9eb4de12010-02-12 13:28:40 +00001/*
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 <eric@anholt.net>
27 * Carl Worth <cworth@cworth.org>
28 * Chris Wilson <chris@chris-wilson.co.uk>
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#define _GNU_SOURCE
42#include <stdio.h>
43#include <stdlib.h>
44#include <stdarg.h>
45#include <string.h>
Chris Wilsona3a78632010-12-01 21:51:59 +000046#include <unistd.h>
Chris Wilson9eb4de12010-02-12 13:28:40 +000047#include <inttypes.h>
48#include <errno.h>
49#include <sys/stat.h>
50#include <err.h>
Imre Deak5efd3d32012-10-10 16:04:39 +030051#include <assert.h>
Daniel Vetter7ee9f162012-01-09 23:38:17 +010052#include <intel_bufmgr.h>
Chris Wilson9eb4de12010-02-12 13:28:40 +000053
Chris Wilson9eb4de12010-02-12 13:28:40 +000054#include "intel_chipset.h"
55#include "intel_gpu_tools.h"
56#include "instdone.h"
57
Ben Widawskyafeb4312013-04-22 11:36:03 -070058static uint32_t
59print_head(unsigned int reg)
60{
61 printf(" head = 0x%08x, wraps = %d\n", reg & (0x7ffff<<2), reg >> 21);
62 return reg & (0x7ffff<<2);
63}
64
Mika Kuoppalaedee9522013-07-12 17:02:04 +030065static uint32_t
66print_ctl(unsigned int reg)
67{
68 uint32_t ring_length = (((reg & (0x1ff << 12)) >> 12) + 1) * 4096;
69
70#define BIT_STR(reg, x, on, off) ((1 << (x)) & reg) ? on : off
71
72 printf(" len=%d%s%s%s\n", ring_length,
73 BIT_STR(reg, 0, ", enabled", ", disabled"),
74 BIT_STR(reg, 10, ", semaphore wait ", ""),
75 BIT_STR(reg, 11, ", rb wait ", "")
76 );
77#undef BIT_STR
78 return ring_length;
79}
80
81static void
82print_acthd(unsigned int reg, unsigned int ring_length)
83{
84 if ((reg & (0x7ffff << 2)) < ring_length)
85 printf(" at ring: 0x%08x\n", reg & (0x7ffff << 2));
86 else
87 printf(" at batch: 0x%08x\n", reg);
88}
89
Chris Wilson9eb4de12010-02-12 13:28:40 +000090static void
Ben Widawsky155aa1e2013-04-22 11:07:35 -070091print_instdone(uint32_t devid, unsigned int instdone, unsigned int instdone1)
Chris Wilson9eb4de12010-02-12 13:28:40 +000092{
Ben Widawsky155aa1e2013-04-22 11:07:35 -070093 int i;
94 static int once;
Chris Wilson95374222010-04-08 11:56:57 +010095
Ben Widawsky155aa1e2013-04-22 11:07:35 -070096 if (!once) {
97 init_instdone_definitions(devid);
98 once = 1;
Chris Wilson9eb4de12010-02-12 13:28:40 +000099 }
100
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700101 for (i = 0; i < num_instdone_bits; i++) {
102 int busy = 0;
103
104 if (instdone_bits[i].reg == INST_DONE_1) {
105 if (!(instdone1 & instdone_bits[i].bit))
106 busy = 1;
107 } else {
108 if (!(instdone & instdone_bits[i].bit))
109 busy = 1;
110 }
111
112 if (busy)
113 printf(" busy: %s\n", instdone_bits[i].name);
114 }
Chris Wilson9eb4de12010-02-12 13:28:40 +0000115}
116
117static void
Chris Wilsonbfc2b532010-03-04 21:56:04 +0000118print_i830_pgtbl_err(unsigned int reg)
119{
120 const char *str;
121
122 switch((reg >> 3) & 0xf) {
123 case 0x1: str = "Overlay TLB"; break;
124 case 0x2: str = "Display A TLB"; break;
125 case 0x3: str = "Host TLB"; break;
126 case 0x4: str = "Render TLB"; break;
127 case 0x5: str = "Display C TLB"; break;
128 case 0x6: str = "Mapping TLB"; break;
129 case 0x7: str = "Command Stream TLB"; break;
130 case 0x8: str = "Vertex Buffer TLB"; break;
131 case 0x9: str = "Display B TLB"; break;
132 case 0xa: str = "Reserved System Memory"; break;
133 case 0xb: str = "Compressor TLB"; break;
134 case 0xc: str = "Binner TLB"; break;
135 default: str = "unknown"; break;
136 }
137
138 if (str)
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700139 printf(" source = %s\n", str);
Chris Wilsonbfc2b532010-03-04 21:56:04 +0000140
141 switch(reg & 0x7) {
142 case 0x0: str = "Invalid GTT"; break;
143 case 0x1: str = "Invalid GTT PTE"; break;
144 case 0x2: str = "Invalid Memory"; break;
145 case 0x3: str = "Invalid TLB miss"; break;
146 case 0x4: str = "Invalid PTE data"; break;
147 case 0x5: str = "Invalid LocalMemory not present"; break;
148 case 0x6: str = "Invalid Tiling"; break;
149 case 0x7: str = "Host to CAM"; break;
150 }
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700151 printf(" error = %s\n", str);
Chris Wilsonbfc2b532010-03-04 21:56:04 +0000152}
153
154static void
Chris Wilson2d1ad952010-07-15 19:18:39 +0100155print_i915_pgtbl_err(unsigned int reg)
156{
157 if (reg & (1 << 29))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700158 printf(" Cursor A: Invalid GTT PTE\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100159 if (reg & (1 << 28))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700160 printf(" Cursor B: Invalid GTT PTE\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100161 if (reg & (1 << 27))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700162 printf(" MT: Invalid tiling\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100163 if (reg & (1 << 26))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700164 printf(" MT: Invalid GTT PTE\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100165 if (reg & (1 << 25))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700166 printf(" LC: Invalid tiling\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100167 if (reg & (1 << 24))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700168 printf(" LC: Invalid GTT PTE\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100169 if (reg & (1 << 23))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700170 printf(" BIN VertexData: Invalid GTT PTE\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100171 if (reg & (1 << 22))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700172 printf(" BIN Instruction: Invalid GTT PTE\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100173 if (reg & (1 << 21))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700174 printf(" CS VertexData: Invalid GTT PTE\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100175 if (reg & (1 << 20))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700176 printf(" CS Instruction: Invalid GTT PTE\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100177 if (reg & (1 << 19))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700178 printf(" CS: Invalid GTT\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100179 if (reg & (1 << 18))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700180 printf(" Overlay: Invalid tiling\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100181 if (reg & (1 << 16))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700182 printf(" Overlay: Invalid GTT PTE\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100183 if (reg & (1 << 14))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700184 printf(" Display C: Invalid tiling\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100185 if (reg & (1 << 12))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700186 printf(" Display C: Invalid GTT PTE\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100187 if (reg & (1 << 10))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700188 printf(" Display B: Invalid tiling\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100189 if (reg & (1 << 8))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700190 printf(" Display B: Invalid GTT PTE\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100191 if (reg & (1 << 6))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700192 printf(" Display A: Invalid tiling\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100193 if (reg & (1 << 4))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700194 printf(" Display A: Invalid GTT PTE\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100195 if (reg & (1 << 1))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700196 printf(" Host Invalid PTE data\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100197 if (reg & (1 << 0))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700198 printf(" Host Invalid GTT PTE\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100199}
200
201static void
Chris Wilson89343952010-10-22 11:33:08 +0100202print_i965_pgtbl_err(unsigned int reg)
203{
204 if (reg & (1 << 26))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700205 printf(" Invalid Sampler Cache GTT entry\n");
Chris Wilson89343952010-10-22 11:33:08 +0100206 if (reg & (1 << 24))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700207 printf(" Invalid Render Cache GTT entry\n");
Chris Wilson89343952010-10-22 11:33:08 +0100208 if (reg & (1 << 23))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700209 printf(" Invalid Instruction/State Cache GTT entry\n");
Chris Wilson89343952010-10-22 11:33:08 +0100210 if (reg & (1 << 22))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700211 printf(" There is no ROC, this cannot occur!\n");
Chris Wilson89343952010-10-22 11:33:08 +0100212 if (reg & (1 << 21))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700213 printf(" Invalid GTT entry during Vertex Fetch\n");
Chris Wilson89343952010-10-22 11:33:08 +0100214 if (reg & (1 << 20))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700215 printf(" Invalid GTT entry during Command Fetch\n");
Chris Wilson89343952010-10-22 11:33:08 +0100216 if (reg & (1 << 19))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700217 printf(" Invalid GTT entry during CS\n");
Chris Wilson89343952010-10-22 11:33:08 +0100218 if (reg & (1 << 18))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700219 printf(" Invalid GTT entry during Cursor Fetch\n");
Chris Wilson89343952010-10-22 11:33:08 +0100220 if (reg & (1 << 17))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700221 printf(" Invalid GTT entry during Overlay Fetch\n");
Chris Wilson89343952010-10-22 11:33:08 +0100222 if (reg & (1 << 8))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700223 printf(" Invalid GTT entry during Display B Fetch\n");
Chris Wilson89343952010-10-22 11:33:08 +0100224 if (reg & (1 << 4))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700225 printf(" Invalid GTT entry during Display A Fetch\n");
Chris Wilson89343952010-10-22 11:33:08 +0100226 if (reg & (1 << 1))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700227 printf(" Valid PTE references illegal memory\n");
Chris Wilson89343952010-10-22 11:33:08 +0100228 if (reg & (1 << 0))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700229 printf(" Invalid GTT entry during fetch for host\n");
Chris Wilson89343952010-10-22 11:33:08 +0100230}
231
232static void
Chris Wilsonbfc2b532010-03-04 21:56:04 +0000233print_pgtbl_err(unsigned int reg, unsigned int devid)
234{
235 if (IS_965(devid)) {
Chris Wilson89343952010-10-22 11:33:08 +0100236 return print_i965_pgtbl_err(reg);
Chris Wilson41570d92011-02-14 15:56:14 +0000237 } else if (IS_GEN3(devid)) {
Chris Wilson2d1ad952010-07-15 19:18:39 +0100238 return print_i915_pgtbl_err(reg);
Chris Wilsonbfc2b532010-03-04 21:56:04 +0000239 } else {
240 return print_i830_pgtbl_err(reg);
241 }
242}
243
244static void
Daniel Vetterd5109532011-10-21 19:06:08 +0200245print_snb_fence(unsigned int devid, uint64_t fence)
246{
247 printf(" %svalid, %c-tiled, pitch: %i, start: 0x%08x, size: %u\n",
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700248 fence & 1 ? "" : "in",
249 fence & (1<<1) ? 'y' : 'x',
250 (int)(((fence>>32)&0xfff)+1)*128,
251 (uint32_t)fence & 0xfffff000,
252 (uint32_t)(((fence>>32)&0xfffff000) - (fence&0xfffff000) + 4096));
Daniel Vetterd5109532011-10-21 19:06:08 +0200253}
254
255static void
256print_i965_fence(unsigned int devid, uint64_t fence)
257{
258 printf(" %svalid, %c-tiled, pitch: %i, start: 0x%08x, size: %u\n",
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700259 fence & 1 ? "" : "in",
260 fence & (1<<1) ? 'y' : 'x',
261 (int)(((fence>>2)&0x1ff)+1)*128,
262 (uint32_t)fence & 0xfffff000,
263 (uint32_t)(((fence>>32)&0xfffff000) - (fence&0xfffff000) + 4096));
Daniel Vetterd5109532011-10-21 19:06:08 +0200264}
265
266static void
Daniel Vettercf5db112011-03-14 11:20:17 +0100267print_i915_fence(unsigned int devid, uint64_t fence)
268{
269 unsigned tile_width;
270 if ((fence & 12) && !IS_915(devid))
271 tile_width = 128;
272 else
273 tile_width = 512;
274
275 printf(" %svalid, %c-tiled, pitch: %i, start: 0x%08x, size: %i\n",
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700276 fence & 1 ? "" : "in",
277 fence & 12 ? 'y' : 'x',
278 (1<<((fence>>4)&0xf))*tile_width,
279 (uint32_t)fence & 0xff00000,
280 1<<(20 + ((fence>>8)&0xf)));
Daniel Vettercf5db112011-03-14 11:20:17 +0100281}
282
283static void
284print_i830_fence(unsigned int devid, uint64_t fence)
285{
286 printf(" %svalid, %c-tiled, pitch: %i, start: 0x%08x, size: %i\n",
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700287 fence & 1 ? "" : "in",
288 fence & 12 ? 'y' : 'x',
289 (1<<((fence>>4)&0xf))*128,
290 (uint32_t)fence & 0x7f80000,
291 1<<(19 + ((fence>>8)&0xf)));
Daniel Vettercf5db112011-03-14 11:20:17 +0100292}
293
294static void
295print_fence(unsigned int devid, uint64_t fence)
296{
Daniel Vetterd5109532011-10-21 19:06:08 +0200297 if (IS_GEN6(devid) || IS_GEN7(devid)) {
298 return print_snb_fence(devid, fence);
299 } else if (IS_GEN4(devid) || IS_GEN5(devid)) {
300 return print_i965_fence(devid, fence);
Daniel Vettercf5db112011-03-14 11:20:17 +0100301 } else if (IS_GEN3(devid)) {
302 return print_i915_fence(devid, fence);
303 } else {
304 return print_i830_fence(devid, fence);
305 }
306}
307
Ben Widawskyafeb4312013-04-22 11:36:03 -0700308#define MAX_RINGS 10 /* I really hope this never... */
309uint32_t head[MAX_RINGS];
310int head_ndx = 0;
311int num_rings = -1;
312static void print_batch(int is_batch, const char *ring_name, uint32_t gtt_offset)
313{
314 const char *buffer_type[2] = { "ringbuffer", "batchbuffer" };
315 if (is_batch) {
316 printf("%s (%s) at 0x%08x\n", buffer_type[is_batch], ring_name, gtt_offset);
317 } else {
318 printf("%s (%s) at 0x%08x; HEAD points to: 0x%08x\n", buffer_type[is_batch], ring_name, gtt_offset, head[head_ndx++ % num_rings] + gtt_offset);
319 }
320}
321
Daniel Vettercf5db112011-03-14 11:20:17 +0100322static void
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700323read_data_file(FILE *file)
Chris Wilson9eb4de12010-02-12 13:28:40 +0000324{
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700325 struct drm_intel_decode *decode_ctx = NULL;
326 uint32_t devid = PCI_CHIP_I855_GM;
327 uint32_t *data = NULL;
328 long long unsigned fence;
329 int data_size = 0, count = 0, line_number = 0, matched;
330 char *line = NULL;
331 size_t line_size;
Mika Kuoppalaedee9522013-07-12 17:02:04 +0300332 uint32_t offset, value, ring_length = 0;
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700333 uint32_t gtt_offset = 0, new_gtt_offset;
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700334 char *ring_name = NULL;
335 int is_batch = 1;
Chris Wilson9eb4de12010-02-12 13:28:40 +0000336
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700337 while (getline(&line, &line_size, file) > 0) {
338 char *dashes;
339 line_number++;
Chris Wilson9eb4de12010-02-12 13:28:40 +0000340
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700341 dashes = strstr(line, "---");
342 if (dashes) {
343 char *new_ring_name = malloc(dashes - line);
344 strncpy(new_ring_name, line, dashes - line);
345 new_ring_name[dashes - line - 1] = '\0';
Daniel Vetter73c21042011-10-11 13:14:02 +0200346
Ben Widawskyafeb4312013-04-22 11:36:03 -0700347 if (num_rings == -1)
348 num_rings = head_ndx;
349
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700350 matched = sscanf(dashes, "--- gtt_offset = 0x%08x\n",
351 &new_gtt_offset);
352 if (matched == 1) {
353 if (count) {
Ben Widawskyafeb4312013-04-22 11:36:03 -0700354 print_batch(is_batch, ring_name, gtt_offset);
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700355 drm_intel_decode_set_batch_pointer(decode_ctx,
356 data, gtt_offset,
357 count);
358 drm_intel_decode(decode_ctx);
359 count = 0;
360 }
361 gtt_offset = new_gtt_offset;
362 is_batch = 1;
363 free(ring_name);
364 ring_name = new_ring_name;
365 continue;
366 }
367
368 matched = sscanf(dashes, "--- ringbuffer = 0x%08x\n",
369 &new_gtt_offset);
370 if (matched == 1) {
371 if (count) {
Ben Widawskyafeb4312013-04-22 11:36:03 -0700372 print_batch(is_batch, ring_name, gtt_offset);
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700373 drm_intel_decode_set_batch_pointer(decode_ctx,
374 data, gtt_offset,
375 count);
376 drm_intel_decode(decode_ctx);
377 count = 0;
378 }
379 gtt_offset = new_gtt_offset;
380 is_batch = 0;
381 free(ring_name);
382 ring_name = new_ring_name;
383 continue;
384 }
385 }
386
387 matched = sscanf(line, "%08x : %08x", &offset, &value);
388 if (matched != 2) {
389 unsigned int reg;
390
391 /* display reg section is after the ringbuffers, don't mix them */
Chris Wilson98eb5a52011-01-09 13:26:50 +0000392 if (count) {
Ben Widawskyafeb4312013-04-22 11:36:03 -0700393 print_batch(is_batch, ring_name, gtt_offset);
Daniel Vetter7ee9f162012-01-09 23:38:17 +0100394 drm_intel_decode_set_batch_pointer(decode_ctx,
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700395 data, gtt_offset,
396 count);
Daniel Vetter7ee9f162012-01-09 23:38:17 +0100397 drm_intel_decode(decode_ctx);
Chris Wilson98eb5a52011-01-09 13:26:50 +0000398 count = 0;
399 }
Chris Wilson9eb4de12010-02-12 13:28:40 +0000400
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700401 printf("%s", line);
402
403 matched = sscanf(line, "PCI ID: 0x%04x\n", &reg);
404 if (matched == 0)
405 matched = sscanf(line, " PCI ID: 0x%04x\n", &reg);
406 if (matched == 0) {
407 const char *pci_id_start = strstr(line, "PCI ID");
408 if (pci_id_start)
409 matched = sscanf(pci_id_start, "PCI ID: 0x%04x\n", &reg);
Chris Wilson98eb5a52011-01-09 13:26:50 +0000410 }
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700411 if (matched == 1) {
412 devid = reg;
413 printf("Detected GEN%i chipset\n",
414 intel_gen(devid));
415
416 decode_ctx = drm_intel_decode_context_alloc(devid);
417 }
418
Mika Kuoppalaedee9522013-07-12 17:02:04 +0300419 matched = sscanf(line, " CTL: 0x%08x\n", &reg);
420 if (matched == 1)
421 ring_length = print_ctl(reg);
422
Ben Widawskyafeb4312013-04-22 11:36:03 -0700423 matched = sscanf(line, " HEAD: 0x%08x\n", &reg);
424 if (matched == 1) {
425 head[head_ndx++] = print_head(reg);
426 }
427
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700428 matched = sscanf(line, " ACTHD: 0x%08x\n", &reg);
Mika Kuoppalaedee9522013-07-12 17:02:04 +0300429 if (matched == 1) {
430 print_acthd(reg, ring_length);
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700431 drm_intel_decode_set_head_tail(decode_ctx, reg, 0xffffffff);
Mika Kuoppalaedee9522013-07-12 17:02:04 +0300432 }
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700433
434 matched = sscanf(line, " PGTBL_ER: 0x%08x\n", &reg);
435 if (matched == 1 && reg)
436 print_pgtbl_err(reg, devid);
437
438 matched = sscanf(line, " INSTDONE: 0x%08x\n", &reg);
439 if (matched == 1)
440 print_instdone(devid, reg, -1);
441
442 matched = sscanf(line, " INSTDONE1: 0x%08x\n", &reg);
443 if (matched == 1)
444 print_instdone(devid, -1, reg);
445
446 matched = sscanf(line, " fence[%i] = %Lx\n", &reg, &fence);
447 if (matched == 2)
448 print_fence(devid, fence);
449
Chris Wilson98eb5a52011-01-09 13:26:50 +0000450 continue;
451 }
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700452
453 count++;
454
455 if (count > data_size) {
456 data_size = data_size ? data_size * 2 : 1024;
457 data = realloc(data, data_size * sizeof (uint32_t));
458 if (data == NULL) {
459 fprintf(stderr, "Out of memory.\n");
460 exit(1);
461 }
462 }
463
464 data[count-1] = value;
Chris Wilson9eb4de12010-02-12 13:28:40 +0000465 }
466
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700467 if (count) {
Ben Widawskyafeb4312013-04-22 11:36:03 -0700468 print_batch(is_batch, ring_name, gtt_offset);
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700469 drm_intel_decode_set_batch_pointer(decode_ctx,
470 data, gtt_offset,
471 count);
472 drm_intel_decode(decode_ctx);
Chris Wilson9eb4de12010-02-12 13:28:40 +0000473 }
474
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700475 free(data);
476 free(line);
477 free(ring_name);
Chris Wilson9eb4de12010-02-12 13:28:40 +0000478}
479
480int
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700481main(int argc, char *argv[])
Chris Wilson9eb4de12010-02-12 13:28:40 +0000482{
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700483 FILE *file;
484 const char *path;
485 char *filename = NULL;
486 struct stat st;
487 int error;
Chris Wilson9eb4de12010-02-12 13:28:40 +0000488
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700489 if (argc > 2) {
490 fprintf(stderr,
491 "intel_gpu_decode: Parse an Intel GPU i915_error_state\n"
492 "Usage:\n"
493 "\t%s [<file>]\n"
494 "\n"
495 "With no arguments, debugfs-dri-directory is probed for in "
496 "/debug and \n"
497 "/sys/kernel/debug. Otherwise, it may be "
498 "specified. If a file is given,\n"
499 "it is parsed as an GPU dump in the format of "
500 "/debug/dri/0/i915_error_state.\n",
501 argv[0]);
502 return 1;
503 }
Chris Wilson9eb4de12010-02-12 13:28:40 +0000504
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700505 if (argc == 1) {
506 if (isatty(0)) {
Chris Wilsondbbf2e92013-08-07 23:41:54 +0100507 path = "/sys/class/drm/card0/error";
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700508 error = stat(path, &st);
509 if (error != 0) {
Chris Wilsondbbf2e92013-08-07 23:41:54 +0100510 path = "/debug/dri";
511 error = stat(path, &st);
512 }
513 if (error != 0) {
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700514 path = "/sys/kernel/debug/dri";
515 error = stat(path, &st);
Chris Wilsondbbf2e92013-08-07 23:41:54 +0100516 }
517 if (error != 0) {
518 errx(1,
519 "Couldn't find i915 debugfs directory.\n\n"
520 "Is debugfs mounted? You might try mounting it with a command such as:\n\n"
521 "\tsudo mount -t debugfs debugfs /sys/kernel/debug\n");
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700522 }
523 } else {
524 read_data_file(stdin);
525 exit(0);
Chris Wilsona3a78632010-12-01 21:51:59 +0000526 }
Chris Wilsona3a78632010-12-01 21:51:59 +0000527 } else {
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700528 path = argv[1];
529 error = stat(path, &st);
530 if (error != 0) {
531 fprintf(stderr, "Error opening %s: %s\n",
532 path, strerror(errno));
533 exit(1);
534 }
Chris Wilson9eb4de12010-02-12 13:28:40 +0000535 }
Chris Wilson9eb4de12010-02-12 13:28:40 +0000536
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700537 if (S_ISDIR(st.st_mode)) {
538 int ret;
Imre Deak5efd3d32012-10-10 16:04:39 +0300539
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700540 ret = asprintf(&filename, "%s/i915_error_state", path);
Imre Deak5efd3d32012-10-10 16:04:39 +0300541 assert(ret > 0);
Chris Wilson68a95f02011-01-25 16:34:08 +0000542 file = fopen(filename, "r");
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700543 if (!file) {
544 int minor;
545 for (minor = 0; minor < 64; minor++) {
546 free(filename);
547 ret = asprintf(&filename, "%s/%d/i915_error_state", path, minor);
548 assert(ret > 0);
Chris Wilson9eb4de12010-02-12 13:28:40 +0000549
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700550 file = fopen(filename, "r");
551 if (file)
552 break;
553 }
554 }
555 if (!file) {
556 fprintf(stderr, "Failed to find i915_error_state beneath %s\n",
557 path);
558 exit (1);
559 }
560 } else {
561 file = fopen(path, "r");
562 if (!file) {
563 fprintf(stderr, "Failed to open %s: %s\n",
564 path, strerror(errno));
565 exit (1);
566 }
567 }
Chris Wilson68a95f02011-01-25 16:34:08 +0000568
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700569 read_data_file(file);
570 fclose(file);
Chris Wilsona3a78632010-12-01 21:51:59 +0000571
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700572 if (filename != path)
573 free(filename);
574
575 return 0;
Chris Wilson9eb4de12010-02-12 13:28:40 +0000576}
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700577
578/* vim: set ts=8 sw=8 tw=0 noet :*/