blob: a7a65e85e57236029b17644eefbf40a7452db8e9 [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 Wilson9eb4de12010-02-12 13:28:40 +000054
Chris Wilson9eb4de12010-02-12 13:28:40 +000055#include "intel_chipset.h"
Daniel Vetterc03c6ce2014-03-22 21:34:29 +010056#include "intel_io.h"
Chris Wilson9eb4de12010-02-12 13:28:40 +000057#include "instdone.h"
Daniel Vetter6cfcd712014-03-22 20:07:35 +010058#include "intel_reg.h"
Zhao Yakuif04bf002014-01-22 09:37:20 +080059#include "drmtest.h"
Chris Wilson9eb4de12010-02-12 13:28:40 +000060
Ben Widawskyafeb4312013-04-22 11:36:03 -070061static uint32_t
62print_head(unsigned int reg)
63{
64 printf(" head = 0x%08x, wraps = %d\n", reg & (0x7ffff<<2), reg >> 21);
65 return reg & (0x7ffff<<2);
66}
67
Mika Kuoppalaedee9522013-07-12 17:02:04 +030068static uint32_t
69print_ctl(unsigned int reg)
70{
71 uint32_t ring_length = (((reg & (0x1ff << 12)) >> 12) + 1) * 4096;
72
73#define BIT_STR(reg, x, on, off) ((1 << (x)) & reg) ? on : off
74
75 printf(" len=%d%s%s%s\n", ring_length,
76 BIT_STR(reg, 0, ", enabled", ", disabled"),
77 BIT_STR(reg, 10, ", semaphore wait ", ""),
78 BIT_STR(reg, 11, ", rb wait ", "")
79 );
80#undef BIT_STR
81 return ring_length;
82}
83
84static void
85print_acthd(unsigned int reg, unsigned int ring_length)
86{
87 if ((reg & (0x7ffff << 2)) < ring_length)
88 printf(" at ring: 0x%08x\n", reg & (0x7ffff << 2));
89 else
90 printf(" at batch: 0x%08x\n", reg);
91}
92
Chris Wilson9eb4de12010-02-12 13:28:40 +000093static void
Ben Widawsky155aa1e2013-04-22 11:07:35 -070094print_instdone(uint32_t devid, unsigned int instdone, unsigned int instdone1)
Chris Wilson9eb4de12010-02-12 13:28:40 +000095{
Ben Widawsky155aa1e2013-04-22 11:07:35 -070096 int i;
97 static int once;
Chris Wilson95374222010-04-08 11:56:57 +010098
Ben Widawsky155aa1e2013-04-22 11:07:35 -070099 if (!once) {
Chris Wilson70ee5082015-11-09 08:58:59 +0000100 if (!init_instdone_definitions(devid))
101 return;
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700102 once = 1;
Chris Wilson9eb4de12010-02-12 13:28:40 +0000103 }
104
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700105 for (i = 0; i < num_instdone_bits; i++) {
106 int busy = 0;
107
Damien Lespiaud8b1dee2013-06-04 05:41:36 +0100108 if (instdone_bits[i].reg == INSTDONE_1) {
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700109 if (!(instdone1 & instdone_bits[i].bit))
110 busy = 1;
111 } else {
112 if (!(instdone & instdone_bits[i].bit))
113 busy = 1;
114 }
115
116 if (busy)
117 printf(" busy: %s\n", instdone_bits[i].name);
118 }
Chris Wilson9eb4de12010-02-12 13:28:40 +0000119}
120
121static void
Chris Wilsonbfc2b532010-03-04 21:56:04 +0000122print_i830_pgtbl_err(unsigned int reg)
123{
124 const char *str;
125
126 switch((reg >> 3) & 0xf) {
127 case 0x1: str = "Overlay TLB"; break;
128 case 0x2: str = "Display A TLB"; break;
129 case 0x3: str = "Host TLB"; break;
130 case 0x4: str = "Render TLB"; break;
131 case 0x5: str = "Display C TLB"; break;
132 case 0x6: str = "Mapping TLB"; break;
133 case 0x7: str = "Command Stream TLB"; break;
134 case 0x8: str = "Vertex Buffer TLB"; break;
135 case 0x9: str = "Display B TLB"; break;
136 case 0xa: str = "Reserved System Memory"; break;
137 case 0xb: str = "Compressor TLB"; break;
138 case 0xc: str = "Binner TLB"; break;
139 default: str = "unknown"; break;
140 }
141
142 if (str)
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700143 printf(" source = %s\n", str);
Chris Wilsonbfc2b532010-03-04 21:56:04 +0000144
145 switch(reg & 0x7) {
146 case 0x0: str = "Invalid GTT"; break;
147 case 0x1: str = "Invalid GTT PTE"; break;
148 case 0x2: str = "Invalid Memory"; break;
149 case 0x3: str = "Invalid TLB miss"; break;
150 case 0x4: str = "Invalid PTE data"; break;
151 case 0x5: str = "Invalid LocalMemory not present"; break;
152 case 0x6: str = "Invalid Tiling"; break;
153 case 0x7: str = "Host to CAM"; break;
154 }
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700155 printf(" error = %s\n", str);
Chris Wilsonbfc2b532010-03-04 21:56:04 +0000156}
157
158static void
Chris Wilson2d1ad952010-07-15 19:18:39 +0100159print_i915_pgtbl_err(unsigned int reg)
160{
161 if (reg & (1 << 29))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700162 printf(" Cursor A: Invalid GTT PTE\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100163 if (reg & (1 << 28))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700164 printf(" Cursor B: Invalid GTT PTE\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100165 if (reg & (1 << 27))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700166 printf(" MT: Invalid tiling\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100167 if (reg & (1 << 26))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700168 printf(" MT: Invalid GTT PTE\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100169 if (reg & (1 << 25))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700170 printf(" LC: Invalid tiling\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100171 if (reg & (1 << 24))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700172 printf(" LC: Invalid GTT PTE\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100173 if (reg & (1 << 23))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700174 printf(" BIN VertexData: Invalid GTT PTE\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100175 if (reg & (1 << 22))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700176 printf(" BIN Instruction: Invalid GTT PTE\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100177 if (reg & (1 << 21))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700178 printf(" CS VertexData: Invalid GTT PTE\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100179 if (reg & (1 << 20))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700180 printf(" CS Instruction: Invalid GTT PTE\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100181 if (reg & (1 << 19))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700182 printf(" CS: Invalid GTT\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100183 if (reg & (1 << 18))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700184 printf(" Overlay: Invalid tiling\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100185 if (reg & (1 << 16))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700186 printf(" Overlay: Invalid GTT PTE\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100187 if (reg & (1 << 14))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700188 printf(" Display C: Invalid tiling\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100189 if (reg & (1 << 12))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700190 printf(" Display C: Invalid GTT PTE\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100191 if (reg & (1 << 10))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700192 printf(" Display B: Invalid tiling\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100193 if (reg & (1 << 8))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700194 printf(" Display B: Invalid GTT PTE\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100195 if (reg & (1 << 6))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700196 printf(" Display A: Invalid tiling\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100197 if (reg & (1 << 4))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700198 printf(" Display A: Invalid GTT PTE\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100199 if (reg & (1 << 1))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700200 printf(" Host Invalid PTE data\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100201 if (reg & (1 << 0))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700202 printf(" Host Invalid GTT PTE\n");
Chris Wilson2d1ad952010-07-15 19:18:39 +0100203}
204
205static void
Chris Wilson89343952010-10-22 11:33:08 +0100206print_i965_pgtbl_err(unsigned int reg)
207{
208 if (reg & (1 << 26))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700209 printf(" Invalid Sampler Cache GTT entry\n");
Chris Wilson89343952010-10-22 11:33:08 +0100210 if (reg & (1 << 24))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700211 printf(" Invalid Render Cache GTT entry\n");
Chris Wilson89343952010-10-22 11:33:08 +0100212 if (reg & (1 << 23))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700213 printf(" Invalid Instruction/State Cache GTT entry\n");
Chris Wilson89343952010-10-22 11:33:08 +0100214 if (reg & (1 << 22))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700215 printf(" There is no ROC, this cannot occur!\n");
Chris Wilson89343952010-10-22 11:33:08 +0100216 if (reg & (1 << 21))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700217 printf(" Invalid GTT entry during Vertex Fetch\n");
Chris Wilson89343952010-10-22 11:33:08 +0100218 if (reg & (1 << 20))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700219 printf(" Invalid GTT entry during Command Fetch\n");
Chris Wilson89343952010-10-22 11:33:08 +0100220 if (reg & (1 << 19))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700221 printf(" Invalid GTT entry during CS\n");
Chris Wilson89343952010-10-22 11:33:08 +0100222 if (reg & (1 << 18))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700223 printf(" Invalid GTT entry during Cursor Fetch\n");
Chris Wilson89343952010-10-22 11:33:08 +0100224 if (reg & (1 << 17))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700225 printf(" Invalid GTT entry during Overlay Fetch\n");
Chris Wilson89343952010-10-22 11:33:08 +0100226 if (reg & (1 << 8))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700227 printf(" Invalid GTT entry during Display B Fetch\n");
Chris Wilson89343952010-10-22 11:33:08 +0100228 if (reg & (1 << 4))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700229 printf(" Invalid GTT entry during Display A Fetch\n");
Chris Wilson89343952010-10-22 11:33:08 +0100230 if (reg & (1 << 1))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700231 printf(" Valid PTE references illegal memory\n");
Chris Wilson89343952010-10-22 11:33:08 +0100232 if (reg & (1 << 0))
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700233 printf(" Invalid GTT entry during fetch for host\n");
Chris Wilson89343952010-10-22 11:33:08 +0100234}
235
236static void
Chris Wilsonbfc2b532010-03-04 21:56:04 +0000237print_pgtbl_err(unsigned int reg, unsigned int devid)
238{
239 if (IS_965(devid)) {
Chris Wilson89343952010-10-22 11:33:08 +0100240 return print_i965_pgtbl_err(reg);
Chris Wilson41570d92011-02-14 15:56:14 +0000241 } else if (IS_GEN3(devid)) {
Chris Wilson2d1ad952010-07-15 19:18:39 +0100242 return print_i915_pgtbl_err(reg);
Chris Wilsonbfc2b532010-03-04 21:56:04 +0000243 } else {
244 return print_i830_pgtbl_err(reg);
245 }
246}
247
Chris Wilsonb6470462014-12-05 11:04:42 +0000248static void print_ivb_error(unsigned int reg, unsigned int devid)
249{
250 if (reg & (1 << 0))
251 printf(" TLB page fault error (GTT entry not valid)\n");
252 if (reg & (1 << 1))
253 printf(" Invalid physical address in RSTRM interface (PAVP)\n");
254 if (reg & (1 << 2))
255 printf(" Invalid page directory entry error\n");
256 if (reg & (1 << 3))
257 printf(" Invalid physical address in ROSTRM interface (PAVP)\n");
258 if (reg & (1 << 4))
259 printf(" TLB page VTD translation generated an error\n");
260 if (reg & (1 << 5))
261 printf(" Invalid physical address in WRITE interface (PAVP)\n");
262 if (reg & (1 << 6))
263 printf(" Page directory VTD translation generated error\n");
264 if (reg & (1 << 8))
265 printf(" Cacheline containing a PD was marked as invalid\n");
266 if (IS_HASWELL(devid) && (reg >> 10) & 0x1f)
267 printf(" %d pending page faults\n", (reg >> 10) & 0x1f);
268}
269
270static void print_snb_error(unsigned int reg)
271{
272 if (reg & (1 << 0))
273 printf(" TLB page fault error (GTT entry not valid)\n");
274 if (reg & (1 << 1))
275 printf(" Context page GTT translation generated a fault (GTT entry not valid)\n");
276 if (reg & (1 << 2))
277 printf(" Invalid page directory entry error\n");
278 if (reg & (1 << 3))
279 printf(" HWS page GTT translation generated a page fault (GTT entry not valid)\n");
280 if (reg & (1 << 4))
281 printf(" TLB page VTD translation generated an error\n");
282 if (reg & (1 << 5))
283 printf(" Context page VTD translation generated an error\n");
284 if (reg & (1 << 6))
285 printf(" Page directory VTD translation generated error\n");
286 if (reg & (1 << 7))
287 printf(" HWS page VTD translation generated an error\n");
288 if (reg & (1 << 8))
289 printf(" Cacheline containing a PD was marked as invalid\n");
290}
291
Mika Kuoppala0a2ef9c2015-03-23 11:35:14 +0200292static void print_bdw_error(unsigned int reg, unsigned int devid)
293{
294 print_ivb_error(reg, devid);
295
296 if (reg & (1 << 10))
297 printf(" Non WB memory type for Advanced Context\n");
298 if (reg & (1 << 11))
299 printf(" PASID not enabled\n");
300 if (reg & (1 << 12))
301 printf(" PASID boundary violation\n");
302 if (reg & (1 << 13))
303 printf(" PASID not valid\n");
304 if (reg & (1 << 14))
305 printf(" PASID was zero for untranslated request\n");
306 if (reg & (1 << 15))
307 printf(" Context was not marked as present when doing DMA\n");
308}
309
Chris Wilsonb6470462014-12-05 11:04:42 +0000310static void
311print_error(unsigned int reg, unsigned int devid)
312{
313 switch (intel_gen(devid)) {
Mika Kuoppala0a2ef9c2015-03-23 11:35:14 +0200314 case 8: return print_bdw_error(reg, devid);
Chris Wilsonb6470462014-12-05 11:04:42 +0000315 case 7: return print_ivb_error(reg, devid);
316 case 6: return print_snb_error(reg);
317 }
318}
319
Chris Wilsonbfc2b532010-03-04 21:56:04 +0000320static void
Daniel Vetterd5109532011-10-21 19:06:08 +0200321print_snb_fence(unsigned int devid, uint64_t fence)
322{
323 printf(" %svalid, %c-tiled, pitch: %i, start: 0x%08x, size: %u\n",
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700324 fence & 1 ? "" : "in",
325 fence & (1<<1) ? 'y' : 'x',
326 (int)(((fence>>32)&0xfff)+1)*128,
327 (uint32_t)fence & 0xfffff000,
328 (uint32_t)(((fence>>32)&0xfffff000) - (fence&0xfffff000) + 4096));
Daniel Vetterd5109532011-10-21 19:06:08 +0200329}
330
331static void
332print_i965_fence(unsigned int devid, uint64_t fence)
333{
334 printf(" %svalid, %c-tiled, pitch: %i, start: 0x%08x, size: %u\n",
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700335 fence & 1 ? "" : "in",
336 fence & (1<<1) ? 'y' : 'x',
337 (int)(((fence>>2)&0x1ff)+1)*128,
338 (uint32_t)fence & 0xfffff000,
339 (uint32_t)(((fence>>32)&0xfffff000) - (fence&0xfffff000) + 4096));
Daniel Vetterd5109532011-10-21 19:06:08 +0200340}
341
342static void
Daniel Vettercf5db112011-03-14 11:20:17 +0100343print_i915_fence(unsigned int devid, uint64_t fence)
344{
345 unsigned tile_width;
346 if ((fence & 12) && !IS_915(devid))
347 tile_width = 128;
348 else
349 tile_width = 512;
350
351 printf(" %svalid, %c-tiled, pitch: %i, start: 0x%08x, size: %i\n",
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700352 fence & 1 ? "" : "in",
Chris Wilson58ac17d2013-10-21 09:31:18 +0100353 fence & (1<<12) ? 'y' : 'x',
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700354 (1<<((fence>>4)&0xf))*tile_width,
355 (uint32_t)fence & 0xff00000,
356 1<<(20 + ((fence>>8)&0xf)));
Daniel Vettercf5db112011-03-14 11:20:17 +0100357}
358
359static void
360print_i830_fence(unsigned int devid, uint64_t fence)
361{
362 printf(" %svalid, %c-tiled, pitch: %i, start: 0x%08x, size: %i\n",
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700363 fence & 1 ? "" : "in",
Chris Wilson58ac17d2013-10-21 09:31:18 +0100364 fence & (1<<12) ? 'y' : 'x',
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700365 (1<<((fence>>4)&0xf))*128,
366 (uint32_t)fence & 0x7f80000,
367 1<<(19 + ((fence>>8)&0xf)));
Daniel Vettercf5db112011-03-14 11:20:17 +0100368}
369
370static void
371print_fence(unsigned int devid, uint64_t fence)
372{
Daniel Vetterd5109532011-10-21 19:06:08 +0200373 if (IS_GEN6(devid) || IS_GEN7(devid)) {
374 return print_snb_fence(devid, fence);
375 } else if (IS_GEN4(devid) || IS_GEN5(devid)) {
376 return print_i965_fence(devid, fence);
Daniel Vettercf5db112011-03-14 11:20:17 +0100377 } else if (IS_GEN3(devid)) {
378 return print_i915_fence(devid, fence);
379 } else {
380 return print_i830_fence(devid, fence);
381 }
382}
383
Mika Kuoppalaf96bfb82015-03-23 11:33:37 +0200384static void
385print_fault_reg(unsigned devid, uint32_t reg)
386{
387 const char *gen7_types[] = { "Page",
388 "Invalid PD",
389 "Unloaded PD",
390 "Invalid and Unloaded PD" };
391
392 const char *gen8_types[] = { "PTE",
393 "PDE",
394 "PDPE",
395 "PML4E" };
396
397 const char *engine[] = { "GFX", "MFX0", "MFX1", "VEBX",
398 "BLT", "Unknown", "Unknown", "Unknown" };
399
400 if (intel_gen(devid) < 7)
401 return;
402
403 if (reg & (1 << 0))
404 printf(" Valid\n");
405 else
406 return;
407
408 if (intel_gen(devid) < 8)
409 printf(" %s Fault (%s)\n", gen7_types[reg >> 1 & 0x3],
410 reg & (1 << 11) ? "GGTT" : "PPGTT");
411 else
412 printf(" Invalid %s Fault\n", gen8_types[reg >> 1 & 0x3]);
413
414 if (intel_gen(devid) < 8)
415 printf(" Address 0x%08x\n", reg & ~((1 << 12)-1));
416 else
417 printf(" Engine %s\n", engine[reg >> 12 & 0x7]);
418
419 printf(" Source ID %d\n", reg >> 3 & 0xff);
420}
421
Mika Kuoppala559987f2015-03-24 13:03:26 +0200422static void
423print_fault_data(unsigned devid, uint32_t data1, uint32_t data0)
424{
425 uint64_t address;
426
427 if (intel_gen(devid) < 8)
428 return;
429
430 address = ((uint64_t)(data0) << 12) | ((uint64_t)data1 & 0xf) << 44;
431 printf(" Address 0x%016" PRIx64 " %s\n", address,
432 data1 & (1 << 4) ? "GGTT" : "PPGTT");
433}
434
Ben Widawskyafeb4312013-04-22 11:36:03 -0700435#define MAX_RINGS 10 /* I really hope this never... */
436uint32_t head[MAX_RINGS];
437int head_ndx = 0;
Chris Wilsonb5109e62014-01-23 21:50:36 +0000438int num_rings = 0;
Ben Widawskyafeb4312013-04-22 11:36:03 -0700439static void print_batch(int is_batch, const char *ring_name, uint32_t gtt_offset)
440{
441 const char *buffer_type[2] = { "ringbuffer", "batchbuffer" };
Chris Wilsonb5109e62014-01-23 21:50:36 +0000442 if (is_batch || !num_rings)
Ben Widawskyafeb4312013-04-22 11:36:03 -0700443 printf("%s (%s) at 0x%08x\n", buffer_type[is_batch], ring_name, gtt_offset);
Chris Wilsonb5109e62014-01-23 21:50:36 +0000444 else
Ben Widawskyafeb4312013-04-22 11:36:03 -0700445 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);
Ben Widawskyafeb4312013-04-22 11:36:03 -0700446}
447
Damien Lespiau1d2ef952013-12-16 11:28:39 +0000448static void decode(struct drm_intel_decode *ctx, bool is_batch,
449 const char *ring_name, uint32_t gtt_offset, uint32_t *data,
450 int *count)
451{
452 if (!*count)
453 return;
454
455 print_batch(is_batch, ring_name, gtt_offset);
456 drm_intel_decode_set_batch_pointer(ctx, data, gtt_offset, *count);
457 drm_intel_decode(ctx);
458 *count = 0;
459}
460
Daniel Vettercf5db112011-03-14 11:20:17 +0100461static void
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700462read_data_file(FILE *file)
Chris Wilson9eb4de12010-02-12 13:28:40 +0000463{
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700464 struct drm_intel_decode *decode_ctx = NULL;
465 uint32_t devid = PCI_CHIP_I855_GM;
466 uint32_t *data = NULL;
467 long long unsigned fence;
468 int data_size = 0, count = 0, line_number = 0, matched;
469 char *line = NULL;
470 size_t line_size;
Mika Kuoppalaedee9522013-07-12 17:02:04 +0300471 uint32_t offset, value, ring_length = 0;
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700472 uint32_t gtt_offset = 0, new_gtt_offset;
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700473 char *ring_name = NULL;
474 int is_batch = 1;
Chris Wilson9eb4de12010-02-12 13:28:40 +0000475
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700476 while (getline(&line, &line_size, file) > 0) {
477 char *dashes;
478 line_number++;
Chris Wilson9eb4de12010-02-12 13:28:40 +0000479
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700480 dashes = strstr(line, "---");
481 if (dashes) {
482 char *new_ring_name = malloc(dashes - line);
483 strncpy(new_ring_name, line, dashes - line);
484 new_ring_name[dashes - line - 1] = '\0';
Daniel Vetter73c21042011-10-11 13:14:02 +0200485
Ben Widawskyafeb4312013-04-22 11:36:03 -0700486 if (num_rings == -1)
487 num_rings = head_ndx;
488
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700489 matched = sscanf(dashes, "--- gtt_offset = 0x%08x\n",
490 &new_gtt_offset);
491 if (matched == 1) {
Damien Lespiau1d2ef952013-12-16 11:28:39 +0000492 decode(decode_ctx, is_batch, ring_name,
493 gtt_offset, data, &count);
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700494 gtt_offset = new_gtt_offset;
495 is_batch = 1;
496 free(ring_name);
497 ring_name = new_ring_name;
498 continue;
499 }
500
501 matched = sscanf(dashes, "--- ringbuffer = 0x%08x\n",
502 &new_gtt_offset);
503 if (matched == 1) {
Damien Lespiau1d2ef952013-12-16 11:28:39 +0000504 decode(decode_ctx, is_batch, ring_name,
505 gtt_offset, data, &count);
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700506 gtt_offset = new_gtt_offset;
507 is_batch = 0;
508 free(ring_name);
509 ring_name = new_ring_name;
510 continue;
511 }
512 }
513
514 matched = sscanf(line, "%08x : %08x", &offset, &value);
515 if (matched != 2) {
Mika Kuoppala559987f2015-03-24 13:03:26 +0200516 unsigned int reg, reg2;
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700517
518 /* display reg section is after the ringbuffers, don't mix them */
Damien Lespiau1d2ef952013-12-16 11:28:39 +0000519 decode(decode_ctx, is_batch, ring_name, gtt_offset,
520 data, &count);
Chris Wilson9eb4de12010-02-12 13:28:40 +0000521
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700522 printf("%s", line);
523
524 matched = sscanf(line, "PCI ID: 0x%04x\n", &reg);
525 if (matched == 0)
526 matched = sscanf(line, " PCI ID: 0x%04x\n", &reg);
527 if (matched == 0) {
528 const char *pci_id_start = strstr(line, "PCI ID");
529 if (pci_id_start)
530 matched = sscanf(pci_id_start, "PCI ID: 0x%04x\n", &reg);
Chris Wilson98eb5a52011-01-09 13:26:50 +0000531 }
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700532 if (matched == 1) {
533 devid = reg;
534 printf("Detected GEN%i chipset\n",
535 intel_gen(devid));
536
537 decode_ctx = drm_intel_decode_context_alloc(devid);
538 }
539
Mika Kuoppalaedee9522013-07-12 17:02:04 +0300540 matched = sscanf(line, " CTL: 0x%08x\n", &reg);
541 if (matched == 1)
542 ring_length = print_ctl(reg);
543
Ben Widawskyafeb4312013-04-22 11:36:03 -0700544 matched = sscanf(line, " HEAD: 0x%08x\n", &reg);
545 if (matched == 1) {
Chris Wilsonb5109e62014-01-23 21:50:36 +0000546 head[num_rings++] = print_head(reg);
Ben Widawskyafeb4312013-04-22 11:36:03 -0700547 }
548
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700549 matched = sscanf(line, " ACTHD: 0x%08x\n", &reg);
Mika Kuoppalaedee9522013-07-12 17:02:04 +0300550 if (matched == 1) {
551 print_acthd(reg, ring_length);
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700552 drm_intel_decode_set_head_tail(decode_ctx, reg, 0xffffffff);
Mika Kuoppalaedee9522013-07-12 17:02:04 +0300553 }
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700554
555 matched = sscanf(line, " PGTBL_ER: 0x%08x\n", &reg);
556 if (matched == 1 && reg)
557 print_pgtbl_err(reg, devid);
558
Chris Wilsonb6470462014-12-05 11:04:42 +0000559 matched = sscanf(line, " ERROR: 0x%08x\n", &reg);
560 if (matched == 1 && reg)
561 print_error(reg, devid);
562
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700563 matched = sscanf(line, " INSTDONE: 0x%08x\n", &reg);
564 if (matched == 1)
565 print_instdone(devid, reg, -1);
566
567 matched = sscanf(line, " INSTDONE1: 0x%08x\n", &reg);
568 if (matched == 1)
569 print_instdone(devid, -1, reg);
570
571 matched = sscanf(line, " fence[%i] = %Lx\n", &reg, &fence);
572 if (matched == 2)
573 print_fence(devid, fence);
574
Mika Kuoppalaf96bfb82015-03-23 11:33:37 +0200575 matched = sscanf(line, " FAULT_REG: 0x%08x\n", &reg);
576 if (matched == 1 && reg)
577 print_fault_reg(devid, reg);
578
Mika Kuoppala559987f2015-03-24 13:03:26 +0200579 matched = sscanf(line, " FAULT_TLB_DATA: 0x%08x 0x%08x\n", &reg, &reg2);
580 if (matched == 2)
581 print_fault_data(devid, reg, reg2);
582
Chris Wilson98eb5a52011-01-09 13:26:50 +0000583 continue;
584 }
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700585
586 count++;
587
588 if (count > data_size) {
589 data_size = data_size ? data_size * 2 : 1024;
590 data = realloc(data, data_size * sizeof (uint32_t));
591 if (data == NULL) {
592 fprintf(stderr, "Out of memory.\n");
593 exit(1);
594 }
595 }
596
597 data[count-1] = value;
Chris Wilson9eb4de12010-02-12 13:28:40 +0000598 }
599
Damien Lespiau1d2ef952013-12-16 11:28:39 +0000600 decode(decode_ctx, is_batch, ring_name, gtt_offset, data, &count);
Chris Wilson9eb4de12010-02-12 13:28:40 +0000601
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700602 free(data);
603 free(line);
604 free(ring_name);
Chris Wilson9eb4de12010-02-12 13:28:40 +0000605}
606
607int
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700608main(int argc, char *argv[])
Chris Wilson9eb4de12010-02-12 13:28:40 +0000609{
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700610 FILE *file;
611 const char *path;
612 char *filename = NULL;
613 struct stat st;
614 int error;
Chris Wilson9eb4de12010-02-12 13:28:40 +0000615
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700616 if (argc > 2) {
617 fprintf(stderr,
618 "intel_gpu_decode: Parse an Intel GPU i915_error_state\n"
619 "Usage:\n"
620 "\t%s [<file>]\n"
621 "\n"
622 "With no arguments, debugfs-dri-directory is probed for in "
623 "/debug and \n"
624 "/sys/kernel/debug. Otherwise, it may be "
625 "specified. If a file is given,\n"
626 "it is parsed as an GPU dump in the format of "
627 "/debug/dri/0/i915_error_state.\n",
628 argv[0]);
629 return 1;
630 }
Chris Wilson9eb4de12010-02-12 13:28:40 +0000631
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700632 if (argc == 1) {
633 if (isatty(0)) {
Chris Wilsondbbf2e92013-08-07 23:41:54 +0100634 path = "/sys/class/drm/card0/error";
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700635 error = stat(path, &st);
636 if (error != 0) {
Chris Wilsondbbf2e92013-08-07 23:41:54 +0100637 path = "/debug/dri";
638 error = stat(path, &st);
639 }
640 if (error != 0) {
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700641 path = "/sys/kernel/debug/dri";
642 error = stat(path, &st);
Chris Wilsondbbf2e92013-08-07 23:41:54 +0100643 }
644 if (error != 0) {
645 errx(1,
646 "Couldn't find i915 debugfs directory.\n\n"
647 "Is debugfs mounted? You might try mounting it with a command such as:\n\n"
648 "\tsudo mount -t debugfs debugfs /sys/kernel/debug\n");
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700649 }
650 } else {
651 read_data_file(stdin);
652 exit(0);
Chris Wilsona3a78632010-12-01 21:51:59 +0000653 }
Chris Wilsona3a78632010-12-01 21:51:59 +0000654 } else {
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700655 path = argv[1];
656 error = stat(path, &st);
657 if (error != 0) {
658 fprintf(stderr, "Error opening %s: %s\n",
659 path, strerror(errno));
660 exit(1);
661 }
Chris Wilson9eb4de12010-02-12 13:28:40 +0000662 }
Chris Wilson9eb4de12010-02-12 13:28:40 +0000663
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700664 if (S_ISDIR(st.st_mode)) {
665 int ret;
Imre Deak5efd3d32012-10-10 16:04:39 +0300666
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700667 ret = asprintf(&filename, "%s/i915_error_state", path);
Imre Deak5efd3d32012-10-10 16:04:39 +0300668 assert(ret > 0);
Chris Wilson68a95f02011-01-25 16:34:08 +0000669 file = fopen(filename, "r");
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700670 if (!file) {
671 int minor;
672 for (minor = 0; minor < 64; minor++) {
673 free(filename);
674 ret = asprintf(&filename, "%s/%d/i915_error_state", path, minor);
675 assert(ret > 0);
Chris Wilson9eb4de12010-02-12 13:28:40 +0000676
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700677 file = fopen(filename, "r");
678 if (file)
679 break;
680 }
681 }
682 if (!file) {
683 fprintf(stderr, "Failed to find i915_error_state beneath %s\n",
684 path);
685 exit (1);
686 }
687 } else {
688 file = fopen(path, "r");
689 if (!file) {
690 fprintf(stderr, "Failed to open %s: %s\n",
691 path, strerror(errno));
692 exit (1);
693 }
694 }
Chris Wilson68a95f02011-01-25 16:34:08 +0000695
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700696 read_data_file(file);
697 fclose(file);
Chris Wilsona3a78632010-12-01 21:51:59 +0000698
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700699 if (filename != path)
700 free(filename);
701
702 return 0;
Chris Wilson9eb4de12010-02-12 13:28:40 +0000703}
Ben Widawsky155aa1e2013-04-22 11:07:35 -0700704
705/* vim: set ts=8 sw=8 tw=0 noet :*/