blob: 371aa423398dbca9ddc74ef61a1fef3fa985365f [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
Damien Lespiau1d2ef952013-12-16 11:28:39 +000042#include <stdbool.h>
Chris Wilson9eb4de12010-02-12 13:28:40 +000043#include <stdio.h>
44#include <stdlib.h>
45#include <stdarg.h>
46#include <string.h>
Chris Wilsona3a78632010-12-01 21:51:59 +000047#include <unistd.h>
Chris Wilson9eb4de12010-02-12 13:28:40 +000048#include <inttypes.h>
49#include <errno.h>
50#include <sys/stat.h>
51#include <err.h>
Imre Deak5efd3d32012-10-10 16:04:39 +030052#include <assert.h>
Daniel Vetter7ee9f162012-01-09 23:38:17 +010053#include <intel_bufmgr.h>
Chris Wilsond4c3cd42014-10-31 11:27:21 +000054#include <zlib.h>
Chris Wilson9eb4de12010-02-12 13:28:40 +000055
Chris Wilson9eb4de12010-02-12 13:28:40 +000056#include "intel_chipset.h"
Daniel Vetterc03c6ce2014-03-22 21:34:29 +010057#include "intel_io.h"
Chris Wilson9eb4de12010-02-12 13:28:40 +000058#include "instdone.h"
Daniel Vetter6cfcd712014-03-22 20:07:35 +010059#include "intel_reg.h"
Zhao Yakuif04bf002014-01-22 09:37:20 +080060#include "drmtest.h"
Chris Wilson9eb4de12010-02-12 13:28:40 +000061
Ben Widawskyafeb4312013-04-22 11:36:03 -070062static uint32_t
63print_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
Mika Kuoppalaedee9522013-07-12 17:02:04 +030069static uint32_t
70print_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
85static void
86print_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
Chris Wilson9eb4de12010-02-12 13:28:40 +000094static void
Ben Widawsky155aa1e2013-04-22 11:07:35 -070095print_instdone(uint32_t devid, unsigned int instdone, unsigned int instdone1)
Chris Wilson9eb4de12010-02-12 13:28:40 +000096{
Ben Widawsky155aa1e2013-04-22 11:07:35 -070097 int i;
98 static int once;
Chris Wilson95374222010-04-08 11:56:57 +010099
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700100 if (!once) {
Chris Wilson70ee5082015-11-09 08:58:59 +0000101 if (!init_instdone_definitions(devid))
102 return;
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700103 once = 1;
Chris Wilson9eb4de12010-02-12 13:28:40 +0000104 }
105
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700106 for (i = 0; i < num_instdone_bits; i++) {
107 int busy = 0;
108
Damien Lespiaud8b1dee2013-06-04 05:41:36 +0100109 if (instdone_bits[i].reg == INSTDONE_1) {
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700110 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 }
Chris Wilson9eb4de12010-02-12 13:28:40 +0000120}
121
122static void
Chris Wilsonbfc2b532010-03-04 21:56:04 +0000123print_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)
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700144 printf(" source = %s\n", str);
Chris Wilsonbfc2b532010-03-04 21:56:04 +0000145
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 }
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700156 printf(" error = %s\n", str);
Chris Wilsonbfc2b532010-03-04 21:56:04 +0000157}
158
159static void
Chris Wilson2d1ad952010-07-15 19:18:39 +0100160print_i915_pgtbl_err(unsigned int reg)
161{
162 if (reg & (1 << 29))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700163 printf(" Cursor A: Invalid GTT PTE\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100164 if (reg & (1 << 28))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700165 printf(" Cursor B: Invalid GTT PTE\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100166 if (reg & (1 << 27))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700167 printf(" MT: Invalid tiling\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100168 if (reg & (1 << 26))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700169 printf(" MT: Invalid GTT PTE\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100170 if (reg & (1 << 25))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700171 printf(" LC: Invalid tiling\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100172 if (reg & (1 << 24))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700173 printf(" LC: Invalid GTT PTE\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100174 if (reg & (1 << 23))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700175 printf(" BIN VertexData: Invalid GTT PTE\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100176 if (reg & (1 << 22))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700177 printf(" BIN Instruction: Invalid GTT PTE\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100178 if (reg & (1 << 21))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700179 printf(" CS VertexData: Invalid GTT PTE\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100180 if (reg & (1 << 20))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700181 printf(" CS Instruction: Invalid GTT PTE\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100182 if (reg & (1 << 19))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700183 printf(" CS: Invalid GTT\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100184 if (reg & (1 << 18))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700185 printf(" Overlay: Invalid tiling\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100186 if (reg & (1 << 16))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700187 printf(" Overlay: Invalid GTT PTE\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100188 if (reg & (1 << 14))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700189 printf(" Display C: Invalid tiling\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100190 if (reg & (1 << 12))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700191 printf(" Display C: Invalid GTT PTE\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100192 if (reg & (1 << 10))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700193 printf(" Display B: Invalid tiling\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100194 if (reg & (1 << 8))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700195 printf(" Display B: Invalid GTT PTE\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100196 if (reg & (1 << 6))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700197 printf(" Display A: Invalid tiling\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100198 if (reg & (1 << 4))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700199 printf(" Display A: Invalid GTT PTE\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100200 if (reg & (1 << 1))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700201 printf(" Host Invalid PTE data\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100202 if (reg & (1 << 0))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700203 printf(" Host Invalid GTT PTE\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100204}
205
206static void
Chris Wilson89343952010-10-22 11:33:08 +0100207print_i965_pgtbl_err(unsigned int reg)
208{
209 if (reg & (1 << 26))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700210 printf(" Invalid Sampler Cache GTT entry\n");
Chris Wilson89343952010-10-22 11:33:08 +0100211 if (reg & (1 << 24))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700212 printf(" Invalid Render Cache GTT entry\n");
Chris Wilson89343952010-10-22 11:33:08 +0100213 if (reg & (1 << 23))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700214 printf(" Invalid Instruction/State Cache GTT entry\n");
Chris Wilson89343952010-10-22 11:33:08 +0100215 if (reg & (1 << 22))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700216 printf(" There is no ROC, this cannot occur!\n");
Chris Wilson89343952010-10-22 11:33:08 +0100217 if (reg & (1 << 21))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700218 printf(" Invalid GTT entry during Vertex Fetch\n");
Chris Wilson89343952010-10-22 11:33:08 +0100219 if (reg & (1 << 20))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700220 printf(" Invalid GTT entry during Command Fetch\n");
Chris Wilson89343952010-10-22 11:33:08 +0100221 if (reg & (1 << 19))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700222 printf(" Invalid GTT entry during CS\n");
Chris Wilson89343952010-10-22 11:33:08 +0100223 if (reg & (1 << 18))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700224 printf(" Invalid GTT entry during Cursor Fetch\n");
Chris Wilson89343952010-10-22 11:33:08 +0100225 if (reg & (1 << 17))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700226 printf(" Invalid GTT entry during Overlay Fetch\n");
Chris Wilson89343952010-10-22 11:33:08 +0100227 if (reg & (1 << 8))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700228 printf(" Invalid GTT entry during Display B Fetch\n");
Chris Wilson89343952010-10-22 11:33:08 +0100229 if (reg & (1 << 4))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700230 printf(" Invalid GTT entry during Display A Fetch\n");
Chris Wilson89343952010-10-22 11:33:08 +0100231 if (reg & (1 << 1))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700232 printf(" Valid PTE references illegal memory\n");
Chris Wilson89343952010-10-22 11:33:08 +0100233 if (reg & (1 << 0))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700234 printf(" Invalid GTT entry during fetch for host\n");
Chris Wilson89343952010-10-22 11:33:08 +0100235}
236
237static void
Chris Wilsonbfc2b532010-03-04 21:56:04 +0000238print_pgtbl_err(unsigned int reg, unsigned int devid)
239{
240 if (IS_965(devid)) {
Chris Wilson89343952010-10-22 11:33:08 +0100241 return print_i965_pgtbl_err(reg);
Chris Wilson41570d92011-02-14 15:56:14 +0000242 } else if (IS_GEN3(devid)) {
Chris Wilson2d1ad952010-07-15 19:18:39 +0100243 return print_i915_pgtbl_err(reg);
Chris Wilsonbfc2b532010-03-04 21:56:04 +0000244 } else {
245 return print_i830_pgtbl_err(reg);
246 }
247}
248
Chris Wilsonb6470462014-12-05 11:04:42 +0000249static 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
271static 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
Mika Kuoppala0a2ef9c2015-03-23 11:35:14 +0200293static 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
Chris Wilsonb6470462014-12-05 11:04:42 +0000311static void
312print_error(unsigned int reg, unsigned int devid)
313{
314 switch (intel_gen(devid)) {
Mika Kuoppala0a2ef9c2015-03-23 11:35:14 +0200315 case 8: return print_bdw_error(reg, devid);
Chris Wilsonb6470462014-12-05 11:04:42 +0000316 case 7: return print_ivb_error(reg, devid);
317 case 6: return print_snb_error(reg);
318 }
319}
320
Chris Wilsonbfc2b532010-03-04 21:56:04 +0000321static void
Daniel Vetterd5109532011-10-21 19:06:08 +0200322print_snb_fence(unsigned int devid, uint64_t fence)
323{
324 printf(" %svalid, %c-tiled, pitch: %i, start: 0x%08x, size: %u\n",
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700325 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));
Daniel Vetterd5109532011-10-21 19:06:08 +0200330}
331
332static void
333print_i965_fence(unsigned int devid, uint64_t fence)
334{
335 printf(" %svalid, %c-tiled, pitch: %i, start: 0x%08x, size: %u\n",
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700336 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));
Daniel Vetterd5109532011-10-21 19:06:08 +0200341}
342
343static void
Daniel Vettercf5db112011-03-14 11:20:17 +0100344print_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",
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700353 fence & 1 ? "" : "in",
Chris Wilson58ac17d2013-10-21 09:31:18 +0100354 fence & (1<<12) ? 'y' : 'x',
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700355 (1<<((fence>>4)&0xf))*tile_width,
356 (uint32_t)fence & 0xff00000,
357 1<<(20 + ((fence>>8)&0xf)));
Daniel Vettercf5db112011-03-14 11:20:17 +0100358}
359
360static void
361print_i830_fence(unsigned int devid, uint64_t fence)
362{
363 printf(" %svalid, %c-tiled, pitch: %i, start: 0x%08x, size: %i\n",
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700364 fence & 1 ? "" : "in",
Chris Wilson58ac17d2013-10-21 09:31:18 +0100365 fence & (1<<12) ? 'y' : 'x',
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700366 (1<<((fence>>4)&0xf))*128,
367 (uint32_t)fence & 0x7f80000,
368 1<<(19 + ((fence>>8)&0xf)));
Daniel Vettercf5db112011-03-14 11:20:17 +0100369}
370
371static void
372print_fence(unsigned int devid, uint64_t fence)
373{
Daniel Vetterd5109532011-10-21 19:06:08 +0200374 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);
Daniel Vettercf5db112011-03-14 11:20:17 +0100378 } else if (IS_GEN3(devid)) {
379 return print_i915_fence(devid, fence);
380 } else {
381 return print_i830_fence(devid, fence);
382 }
383}
384
Mika Kuoppalaf96bfb82015-03-23 11:33:37 +0200385static void
386print_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
Mika Kuoppala559987f2015-03-24 13:03:26 +0200423static void
424print_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
Ben Widawskyafeb4312013-04-22 11:36:03 -0700436#define MAX_RINGS 10 /* I really hope this never... */
Ben Widawskyafeb4312013-04-22 11:36:03 -0700437
Chris Wilson8f9df282014-11-05 11:24:49 +0000438static void decode(struct drm_intel_decode *ctx,
439 const char *buffer_name,
440 const char *ring_name,
Chris Wilsonbb357162015-12-31 21:34:27 +0000441 uint64_t gtt_offset,
Chris Wilson8f9df282014-11-05 11:24:49 +0000442 uint32_t head_offset,
443 uint32_t *data,
Damien Lespiau1d2ef952013-12-16 11:28:39 +0000444 int *count)
445{
446 if (!*count)
447 return;
448
Chris Wilsonbb357162015-12-31 21:34:27 +0000449 printf("%s (%s) at 0x%08x_%08x", buffer_name, ring_name,
450 (unsigned)(gtt_offset >> 32),
451 (unsigned)(gtt_offset & 0xffffffff));
Chris Wilson8f9df282014-11-05 11:24:49 +0000452 if (head_offset != -1)
Chris Wilsonbb357162015-12-31 21:34:27 +0000453 printf("; HEAD points to: 0x%08x_%08x",
454 (unsigned)((head_offset + gtt_offset) >> 32),
455 (unsigned)((head_offset + gtt_offset) & 0xffffffff));
Chris Wilson8f9df282014-11-05 11:24:49 +0000456 printf("\n");
457
Damien Lespiau1d2ef952013-12-16 11:28:39 +0000458 drm_intel_decode_set_batch_pointer(ctx, data, gtt_offset, *count);
459 drm_intel_decode(ctx);
460 *count = 0;
461}
462
Chris Wilsond4c3cd42014-10-31 11:27:21 +0000463static int zlib_inflate(uint32_t **ptr, int len)
464{
465 struct z_stream_s zstream;
466 void *out;
467
468 memset(&zstream, 0, sizeof(zstream));
469
470 zstream.next_in = (unsigned char *)*ptr;
471 zstream.avail_in = 4*len;
472
473 if (inflateInit(&zstream) != Z_OK)
474 return 0;
475
476 out = malloc(128*4096); /* approximate obj size */
477 zstream.next_out = out;
478 zstream.avail_out = 40*len;
479
480 do {
481 switch (inflate(&zstream, Z_SYNC_FLUSH)) {
482 case Z_STREAM_END:
483 goto end;
484 case Z_OK:
485 break;
486 default:
487 inflateEnd(&zstream);
488 return 0;
489 }
490
491 if (zstream.avail_out)
492 break;
493
494 out = realloc(out, 2*zstream.total_out);
495 if (out == NULL) {
496 inflateEnd(&zstream);
497 return 0;
498 }
499
500 zstream.next_out = (unsigned char *)out + zstream.total_out;
501 zstream.avail_out = zstream.total_out;
502 } while (1);
503end:
504 inflateEnd(&zstream);
505 free(*ptr);
506 *ptr = out;
507 return zstream.total_out / 4;
508}
509
510static int ascii85_decode(const char *in, uint32_t **out)
511{
512 int len = 0, size = 1024;
513
514 *out = realloc(*out, sizeof(uint32_t)*size);
515 if (*out == NULL)
516 return 0;
517
518 while (*in >= '!' && *in <= 'z') {
519 uint32_t v = 0;
520
521 if (len == size) {
522 size *= 2;
523 *out = realloc(*out, sizeof(uint32_t)*size);
524 if (*out == NULL)
525 return 0;
526 }
527
528 if (*in == 'z') {
529 in++;
530 } else {
531 v += in[0] - 33; v *= 85;
532 v += in[1] - 33; v *= 85;
533 v += in[2] - 33; v *= 85;
534 v += in[3] - 33; v *= 85;
535 v += in[4] - 33;
536 in += 5;
537 }
538 (*out)[len++] = v;
539 }
540
541 return zlib_inflate(out, len);
542}
543
Daniel Vettercf5db112011-03-14 11:20:17 +0100544static void
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700545read_data_file(FILE *file)
Chris Wilson9eb4de12010-02-12 13:28:40 +0000546{
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700547 struct drm_intel_decode *decode_ctx = NULL;
548 uint32_t devid = PCI_CHIP_I855_GM;
549 uint32_t *data = NULL;
Chris Wilson8f9df282014-11-05 11:24:49 +0000550 uint32_t head[MAX_RINGS];
551 int head_idx = 0;
552 int num_rings = 0;
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700553 long long unsigned fence;
554 int data_size = 0, count = 0, line_number = 0, matched;
555 char *line = NULL;
556 size_t line_size;
Mika Kuoppalaedee9522013-07-12 17:02:04 +0300557 uint32_t offset, value, ring_length = 0;
Chris Wilsonbb357162015-12-31 21:34:27 +0000558 uint64_t gtt_offset = 0, new_gtt_offset;
Chris Wilson8f9df282014-11-05 11:24:49 +0000559 uint32_t head_offset = -1;
560 const char *buffer_name = "batch buffer";
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700561 char *ring_name = NULL;
Chris Wilson9eb4de12010-02-12 13:28:40 +0000562
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700563 while (getline(&line, &line_size, file) > 0) {
564 char *dashes;
565 line_number++;
Chris Wilson9eb4de12010-02-12 13:28:40 +0000566
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700567 dashes = strstr(line, "---");
568 if (dashes) {
Chris Wilsonbb357162015-12-31 21:34:27 +0000569 uint32_t lo, hi;
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700570 char *new_ring_name = malloc(dashes - line);
571 strncpy(new_ring_name, line, dashes - line);
572 new_ring_name[dashes - line - 1] = '\0';
Daniel Vetter73c21042011-10-11 13:14:02 +0200573
Chris Wilsonbb357162015-12-31 21:34:27 +0000574 matched = sscanf(dashes, "--- gtt_offset = 0x%08x %08x\n",
575 &hi, &lo);
576 if (matched > 0) {
577 new_gtt_offset = hi;
578 if (matched == 2) {
579 new_gtt_offset <<= 32;
580 new_gtt_offset |= lo;
581 }
582
Chris Wilson8f9df282014-11-05 11:24:49 +0000583 decode(decode_ctx,
584 buffer_name, ring_name,
585 gtt_offset, head_offset,
586 data, &count);
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700587 gtt_offset = new_gtt_offset;
Chris Wilson8f9df282014-11-05 11:24:49 +0000588 head_offset = -1;
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700589 free(ring_name);
590 ring_name = new_ring_name;
Chris Wilson8f9df282014-11-05 11:24:49 +0000591 buffer_name = "batch buffer";
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700592 continue;
593 }
594
Chris Wilsonbb357162015-12-31 21:34:27 +0000595 matched = sscanf(dashes, "--- ringbuffer = 0x%08x %08x\n",
596 &hi, &lo);
597 if (matched > 0) {
598 new_gtt_offset = hi;
599 if (matched == 2) {
600 new_gtt_offset <<= 32;
601 new_gtt_offset |= lo;
602 }
603
Chris Wilson8f9df282014-11-05 11:24:49 +0000604 decode(decode_ctx,
605 buffer_name, ring_name,
606 gtt_offset, head_offset,
607 data, &count);
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700608 gtt_offset = new_gtt_offset;
Chris Wilson8f9df282014-11-05 11:24:49 +0000609 if (head_idx < num_rings)
610 head_offset = head[head_idx++];
611 else
612 head_offset = -1;
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700613 free(ring_name);
614 ring_name = new_ring_name;
Chris Wilson8f9df282014-11-05 11:24:49 +0000615 buffer_name = "ring buffer";
616 continue;
617 }
618
Chris Wilsonbb357162015-12-31 21:34:27 +0000619 matched = sscanf(dashes, "--- HW Context = 0x%08x %08x\n",
620 &hi, &lo);
621 if (matched > 0) {
622 new_gtt_offset = hi;
623 if (matched == 2) {
624 new_gtt_offset <<= 32;
625 new_gtt_offset |= lo;
626 }
627
Chris Wilson8f9df282014-11-05 11:24:49 +0000628 decode(decode_ctx,
629 buffer_name, ring_name,
630 gtt_offset, head_offset,
631 data, &count);
632 gtt_offset = new_gtt_offset;
633 head_offset = -1;
634 free(ring_name);
635 ring_name = new_ring_name;
636 buffer_name = "HW Context";
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700637 continue;
638 }
639 }
640
Chris Wilsond4c3cd42014-10-31 11:27:21 +0000641 if (line[0] == ':') {
642 count = ascii85_decode(line+1, &data);
643 if (count == 0) {
644 fprintf(stderr, "ASCII85 decode failed.\n");
645 exit(1);
646 }
Chris Wilson8f9df282014-11-05 11:24:49 +0000647 decode(decode_ctx,
648 buffer_name, ring_name,
649 gtt_offset, head_offset,
Chris Wilsond4c3cd42014-10-31 11:27:21 +0000650 data, &count);
651 continue;
652 }
653
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700654 matched = sscanf(line, "%08x : %08x", &offset, &value);
655 if (matched != 2) {
Mika Kuoppala559987f2015-03-24 13:03:26 +0200656 unsigned int reg, reg2;
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700657
658 /* display reg section is after the ringbuffers, don't mix them */
Chris Wilson8f9df282014-11-05 11:24:49 +0000659 decode(decode_ctx,
660 buffer_name, ring_name,
661 gtt_offset, head_offset,
Damien Lespiau1d2ef952013-12-16 11:28:39 +0000662 data, &count);
Chris Wilson9eb4de12010-02-12 13:28:40 +0000663
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700664 printf("%s", line);
665
666 matched = sscanf(line, "PCI ID: 0x%04x\n", &reg);
667 if (matched == 0)
668 matched = sscanf(line, " PCI ID: 0x%04x\n", &reg);
669 if (matched == 0) {
670 const char *pci_id_start = strstr(line, "PCI ID");
671 if (pci_id_start)
672 matched = sscanf(pci_id_start, "PCI ID: 0x%04x\n", &reg);
Chris Wilson98eb5a52011-01-09 13:26:50 +0000673 }
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700674 if (matched == 1) {
675 devid = reg;
676 printf("Detected GEN%i chipset\n",
677 intel_gen(devid));
678
679 decode_ctx = drm_intel_decode_context_alloc(devid);
680 }
681
Mika Kuoppalaedee9522013-07-12 17:02:04 +0300682 matched = sscanf(line, " CTL: 0x%08x\n", &reg);
683 if (matched == 1)
684 ring_length = print_ctl(reg);
685
Ben Widawskyafeb4312013-04-22 11:36:03 -0700686 matched = sscanf(line, " HEAD: 0x%08x\n", &reg);
687 if (matched == 1) {
Chris Wilsonb5109e62014-01-23 21:50:36 +0000688 head[num_rings++] = print_head(reg);
Ben Widawskyafeb4312013-04-22 11:36:03 -0700689 }
690
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700691 matched = sscanf(line, " ACTHD: 0x%08x\n", &reg);
Mika Kuoppalaedee9522013-07-12 17:02:04 +0300692 if (matched == 1) {
693 print_acthd(reg, ring_length);
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700694 drm_intel_decode_set_head_tail(decode_ctx, reg, 0xffffffff);
Mika Kuoppalaedee9522013-07-12 17:02:04 +0300695 }
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700696
697 matched = sscanf(line, " PGTBL_ER: 0x%08x\n", &reg);
698 if (matched == 1 && reg)
699 print_pgtbl_err(reg, devid);
700
Chris Wilsonb6470462014-12-05 11:04:42 +0000701 matched = sscanf(line, " ERROR: 0x%08x\n", &reg);
702 if (matched == 1 && reg)
703 print_error(reg, devid);
704
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700705 matched = sscanf(line, " INSTDONE: 0x%08x\n", &reg);
706 if (matched == 1)
707 print_instdone(devid, reg, -1);
708
709 matched = sscanf(line, " INSTDONE1: 0x%08x\n", &reg);
710 if (matched == 1)
711 print_instdone(devid, -1, reg);
712
713 matched = sscanf(line, " fence[%i] = %Lx\n", &reg, &fence);
714 if (matched == 2)
715 print_fence(devid, fence);
716
Mika Kuoppalaf96bfb82015-03-23 11:33:37 +0200717 matched = sscanf(line, " FAULT_REG: 0x%08x\n", &reg);
718 if (matched == 1 && reg)
719 print_fault_reg(devid, reg);
720
Mika Kuoppala559987f2015-03-24 13:03:26 +0200721 matched = sscanf(line, " FAULT_TLB_DATA: 0x%08x 0x%08x\n", &reg, &reg2);
722 if (matched == 2)
723 print_fault_data(devid, reg, reg2);
724
Chris Wilson98eb5a52011-01-09 13:26:50 +0000725 continue;
726 }
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700727
728 count++;
729
730 if (count > data_size) {
731 data_size = data_size ? data_size * 2 : 1024;
732 data = realloc(data, data_size * sizeof (uint32_t));
733 if (data == NULL) {
734 fprintf(stderr, "Out of memory.\n");
735 exit(1);
736 }
737 }
738
739 data[count-1] = value;
Chris Wilson9eb4de12010-02-12 13:28:40 +0000740 }
741
Chris Wilson8f9df282014-11-05 11:24:49 +0000742 decode(decode_ctx,
743 buffer_name, ring_name,
744 gtt_offset, head_offset,
745 data, &count);
Chris Wilson9eb4de12010-02-12 13:28:40 +0000746
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700747 free(data);
748 free(line);
749 free(ring_name);
Chris Wilson9eb4de12010-02-12 13:28:40 +0000750}
751
752int
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700753main(int argc, char *argv[])
Chris Wilson9eb4de12010-02-12 13:28:40 +0000754{
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700755 FILE *file;
756 const char *path;
757 char *filename = NULL;
758 struct stat st;
759 int error;
Chris Wilson9eb4de12010-02-12 13:28:40 +0000760
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700761 if (argc > 2) {
762 fprintf(stderr,
763 "intel_gpu_decode: Parse an Intel GPU i915_error_state\n"
764 "Usage:\n"
765 "\t%s [<file>]\n"
766 "\n"
767 "With no arguments, debugfs-dri-directory is probed for in "
768 "/debug and \n"
769 "/sys/kernel/debug. Otherwise, it may be "
770 "specified. If a file is given,\n"
771 "it is parsed as an GPU dump in the format of "
772 "/debug/dri/0/i915_error_state.\n",
773 argv[0]);
774 return 1;
775 }
Chris Wilson9eb4de12010-02-12 13:28:40 +0000776
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700777 if (argc == 1) {
778 if (isatty(0)) {
Chris Wilsondbbf2e92013-08-07 23:41:54 +0100779 path = "/sys/class/drm/card0/error";
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700780 error = stat(path, &st);
781 if (error != 0) {
Chris Wilsondbbf2e92013-08-07 23:41:54 +0100782 path = "/debug/dri";
783 error = stat(path, &st);
784 }
785 if (error != 0) {
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700786 path = "/sys/kernel/debug/dri";
787 error = stat(path, &st);
Chris Wilsondbbf2e92013-08-07 23:41:54 +0100788 }
789 if (error != 0) {
790 errx(1,
791 "Couldn't find i915 debugfs directory.\n\n"
792 "Is debugfs mounted? You might try mounting it with a command such as:\n\n"
793 "\tsudo mount -t debugfs debugfs /sys/kernel/debug\n");
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700794 }
795 } else {
796 read_data_file(stdin);
797 exit(0);
Chris Wilsona3a78632010-12-01 21:51:59 +0000798 }
Chris Wilsona3a78632010-12-01 21:51:59 +0000799 } else {
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700800 path = argv[1];
801 error = stat(path, &st);
802 if (error != 0) {
803 fprintf(stderr, "Error opening %s: %s\n",
804 path, strerror(errno));
805 exit(1);
806 }
Chris Wilson9eb4de12010-02-12 13:28:40 +0000807 }
Chris Wilson9eb4de12010-02-12 13:28:40 +0000808
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700809 if (S_ISDIR(st.st_mode)) {
810 int ret;
Imre Deak5efd3d32012-10-10 16:04:39 +0300811
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700812 ret = asprintf(&filename, "%s/i915_error_state", path);
Imre Deak5efd3d32012-10-10 16:04:39 +0300813 assert(ret > 0);
Chris Wilson68a95f02011-01-25 16:34:08 +0000814 file = fopen(filename, "r");
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700815 if (!file) {
816 int minor;
817 for (minor = 0; minor < 64; minor++) {
818 free(filename);
819 ret = asprintf(&filename, "%s/%d/i915_error_state", path, minor);
820 assert(ret > 0);
Chris Wilson9eb4de12010-02-12 13:28:40 +0000821
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700822 file = fopen(filename, "r");
823 if (file)
824 break;
825 }
826 }
827 if (!file) {
828 fprintf(stderr, "Failed to find i915_error_state beneath %s\n",
829 path);
830 exit (1);
831 }
832 } else {
833 file = fopen(path, "r");
834 if (!file) {
835 fprintf(stderr, "Failed to open %s: %s\n",
836 path, strerror(errno));
837 exit (1);
838 }
839 }
Chris Wilson68a95f02011-01-25 16:34:08 +0000840
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700841 read_data_file(file);
842 fclose(file);
Chris Wilsona3a78632010-12-01 21:51:59 +0000843
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700844 if (filename != path)
845 free(filename);
846
847 return 0;
Chris Wilson9eb4de12010-02-12 13:28:40 +0000848}
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700849
850/* vim: set ts=8 sw=8 tw=0 noet :*/