blob: f9e47eb60530d56ca79a30432f140280c5f9e174 [file] [log] [blame]
Chris Wilson9eb4de12010-02-12 13:28:40 +00001/* -*- c-basic-offset: 4 -*- */
2/*
3 * Copyright © 2007 Intel Corporation
4 * Copyright © 2009 Intel Corporation
5 * Copyright © 2010 Intel Corporation
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the next
15 * paragraph) shall be included in all copies or substantial portions of the
16 * Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24 * IN THE SOFTWARE.
25 *
26 * Authors:
27 * Eric Anholt <eric@anholt.net>
28 * Carl Worth <cworth@cworth.org>
29 * Chris Wilson <chris@chris-wilson.co.uk>
30 *
31 */
32
33/** @file intel_decode.c
34 * This file contains code to print out batchbuffer contents in a
35 * human-readable format.
36 *
37 * The current version only supports i915 packets, and only pretty-prints a
38 * subset of them. The intention is for it to make just a best attempt to
39 * decode, but never crash in the process.
40 */
41
42#define _GNU_SOURCE
43#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>
52
53#include "intel_decode.h"
54#include "intel_chipset.h"
55#include "intel_gpu_tools.h"
56#include "instdone.h"
57
58static void
Chris Wilson95374222010-04-08 11:56:57 +010059print_instdone (uint32_t devid, unsigned int instdone, unsigned int instdone1)
Chris Wilson9eb4de12010-02-12 13:28:40 +000060{
61 int i;
Chris Wilson95374222010-04-08 11:56:57 +010062 static int once;
63
64 if (!once) {
65 init_instdone_definitions(devid);
66 once = 1;
67 }
Chris Wilson9eb4de12010-02-12 13:28:40 +000068
69 for (i = 0; i < num_instdone_bits; i++) {
70 int busy = 0;
71
72 if (instdone_bits[i].reg == INST_DONE_1) {
73 if (!(instdone1 & instdone_bits[i].bit))
74 busy = 1;
75 } else {
76 if (!(instdone & instdone_bits[i].bit))
77 busy = 1;
78 }
79
80 if (busy)
81 printf(" busy: %s\n", instdone_bits[i].name);
82 }
83}
84
85static void
Chris Wilsonbfc2b532010-03-04 21:56:04 +000086print_i830_pgtbl_err(unsigned int reg)
87{
88 const char *str;
89
90 switch((reg >> 3) & 0xf) {
91 case 0x1: str = "Overlay TLB"; break;
92 case 0x2: str = "Display A TLB"; break;
93 case 0x3: str = "Host TLB"; break;
94 case 0x4: str = "Render TLB"; break;
95 case 0x5: str = "Display C TLB"; break;
96 case 0x6: str = "Mapping TLB"; break;
97 case 0x7: str = "Command Stream TLB"; break;
98 case 0x8: str = "Vertex Buffer TLB"; break;
99 case 0x9: str = "Display B TLB"; break;
100 case 0xa: str = "Reserved System Memory"; break;
101 case 0xb: str = "Compressor TLB"; break;
102 case 0xc: str = "Binner TLB"; break;
103 default: str = "unknown"; break;
104 }
105
106 if (str)
107 printf (" source = %s\n", str);
108
109 switch(reg & 0x7) {
110 case 0x0: str = "Invalid GTT"; break;
111 case 0x1: str = "Invalid GTT PTE"; break;
112 case 0x2: str = "Invalid Memory"; break;
113 case 0x3: str = "Invalid TLB miss"; break;
114 case 0x4: str = "Invalid PTE data"; break;
115 case 0x5: str = "Invalid LocalMemory not present"; break;
116 case 0x6: str = "Invalid Tiling"; break;
117 case 0x7: str = "Host to CAM"; break;
118 }
119 printf (" error = %s\n", str);
120}
121
122static void
Chris Wilson2d1ad952010-07-15 19:18:39 +0100123print_i915_pgtbl_err(unsigned int reg)
124{
125 if (reg & (1 << 29))
126 printf (" Cursor A: Invalid GTT PTE\n");
127 if (reg & (1 << 28))
128 printf (" Cursor B: Invalid GTT PTE\n");
129 if (reg & (1 << 27))
130 printf (" MT: Invalid tiling\n");
131 if (reg & (1 << 26))
132 printf (" MT: Invalid GTT PTE\n");
133 if (reg & (1 << 25))
134 printf (" LC: Invalid tiling\n");
135 if (reg & (1 << 24))
136 printf (" LC: Invalid GTT PTE\n");
137 if (reg & (1 << 23))
138 printf (" BIN VertexData: Invalid GTT PTE\n");
139 if (reg & (1 << 22))
140 printf (" BIN Instruction: Invalid GTT PTE\n");
141 if (reg & (1 << 21))
142 printf (" CS VertexData: Invalid GTT PTE\n");
143 if (reg & (1 << 20))
144 printf (" CS Instruction: Invalid GTT PTE\n");
145 if (reg & (1 << 19))
146 printf (" CS: Invalid GTT\n");
147 if (reg & (1 << 18))
148 printf (" Overlay: Invalid tiling\n");
149 if (reg & (1 << 16))
150 printf (" Overlay: Invalid GTT PTE\n");
151 if (reg & (1 << 14))
152 printf (" Display C: Invalid tiling\n");
153 if (reg & (1 << 12))
154 printf (" Display C: Invalid GTT PTE\n");
155 if (reg & (1 << 10))
156 printf (" Display B: Invalid tiling\n");
157 if (reg & (1 << 8))
158 printf (" Display B: Invalid GTT PTE\n");
159 if (reg & (1 << 6))
160 printf (" Display A: Invalid tiling\n");
161 if (reg & (1 << 4))
162 printf (" Display A: Invalid GTT PTE\n");
163 if (reg & (1 << 1))
164 printf (" Host Invalid PTE data\n");
165 if (reg & (1 << 0))
166 printf (" Host Invalid GTT PTE\n");
167}
168
169static void
Chris Wilson89343952010-10-22 11:33:08 +0100170print_i965_pgtbl_err(unsigned int reg)
171{
172 if (reg & (1 << 26))
173 printf (" Invalid Sampler Cache GTT entry\n");
174 if (reg & (1 << 24))
175 printf (" Invalid Render Cache GTT entry\n");
176 if (reg & (1 << 23))
177 printf (" Invalid Instruction/State Cache GTT entry\n");
178 if (reg & (1 << 22))
179 printf (" There is no ROC, this cannot occur!\n");
180 if (reg & (1 << 21))
181 printf (" Invalid GTT entry during Vertex Fetch\n");
182 if (reg & (1 << 20))
183 printf (" Invalid GTT entry during Command Fetch\n");
184 if (reg & (1 << 19))
185 printf (" Invalid GTT entry during CS\n");
186 if (reg & (1 << 18))
187 printf (" Invalid GTT entry during Cursor Fetch\n");
188 if (reg & (1 << 17))
189 printf (" Invalid GTT entry during Overlay Fetch\n");
190 if (reg & (1 << 8))
191 printf (" Invalid GTT entry during Display B Fetch\n");
192 if (reg & (1 << 4))
193 printf (" Invalid GTT entry during Display A Fetch\n");
194 if (reg & (1 << 1))
195 printf (" Valid PTE references illegal memory\n");
196 if (reg & (1 << 0))
197 printf (" Invalid GTT entry during fetch for host\n");
198}
199
200static void
Chris Wilsonbfc2b532010-03-04 21:56:04 +0000201print_pgtbl_err(unsigned int reg, unsigned int devid)
202{
203 if (IS_965(devid)) {
Chris Wilson89343952010-10-22 11:33:08 +0100204 return print_i965_pgtbl_err(reg);
Chris Wilson41570d92011-02-14 15:56:14 +0000205 } else if (IS_GEN3(devid)) {
Chris Wilson2d1ad952010-07-15 19:18:39 +0100206 return print_i915_pgtbl_err(reg);
Chris Wilsonbfc2b532010-03-04 21:56:04 +0000207 } else {
208 return print_i830_pgtbl_err(reg);
209 }
210}
211
212static void
Daniel Vettercf5db112011-03-14 11:20:17 +0100213print_i915_fence(unsigned int devid, uint64_t fence)
214{
215 unsigned tile_width;
216 if ((fence & 12) && !IS_915(devid))
217 tile_width = 128;
218 else
219 tile_width = 512;
220
221 printf(" %svalid, %c-tiled, pitch: %i, start: 0x%08x, size: %i\n",
222 fence & 1 ? "" : "in",
223 fence & 12 ? 'y' : 'x',
224 (1<<((fence>>4)&0xf))*tile_width,
225 (uint32_t)fence & 0x7f80000,
226 1<<(20 + ((fence>>8)&0xf)));
227}
228
229static void
230print_i830_fence(unsigned int devid, uint64_t fence)
231{
232 printf(" %svalid, %c-tiled, pitch: %i, start: 0x%08x, size: %i\n",
233 fence & 1 ? "" : "in",
234 fence & 12 ? 'y' : 'x',
235 (1<<((fence>>4)&0xf))*128,
236 (uint32_t)fence & 0x7f80000,
237 1<<(19 + ((fence>>8)&0xf)));
238}
239
240static void
241print_fence(unsigned int devid, uint64_t fence)
242{
243 if (IS_965(devid)) {
244 return;
245 } else if (IS_GEN3(devid)) {
246 return print_i915_fence(devid, fence);
247 } else {
248 return print_i830_fence(devid, fence);
249 }
250}
251
252static void
Chris Wilsona3a78632010-12-01 21:51:59 +0000253read_data_file (FILE *file)
Chris Wilson9eb4de12010-02-12 13:28:40 +0000254{
Chris Wilson9eb4de12010-02-12 13:28:40 +0000255 int devid = PCI_CHIP_I855_GM;
256 uint32_t *data = NULL;
Daniel Vettercf5db112011-03-14 11:20:17 +0100257 long long unsigned fence;
Chris Wilson9eb4de12010-02-12 13:28:40 +0000258 int data_size = 0, count = 0, line_number = 0, matched;
259 char *line = NULL;
260 size_t line_size;
261 uint32_t offset, value;
262 uint32_t gtt_offset = 0, new_gtt_offset;
263 char *buffer_type[2] = { "ringbuffer", "batchbuffer" };
Daniel Vetter73c21042011-10-11 13:14:02 +0200264 char *ring_name = NULL;
Chris Wilson9eb4de12010-02-12 13:28:40 +0000265 int is_batch = 1;
266
Chris Wilson9eb4de12010-02-12 13:28:40 +0000267 while (getline (&line, &line_size, file) > 0) {
Chris Wilson98eb5a52011-01-09 13:26:50 +0000268 char *dashes;
Chris Wilson9eb4de12010-02-12 13:28:40 +0000269 line_number++;
270
Chris Wilson98eb5a52011-01-09 13:26:50 +0000271 dashes = strstr(line, "---");
272 if (dashes) {
Daniel Vetter73c21042011-10-11 13:14:02 +0200273 char *new_ring_name = malloc(dashes - line);
274 strncpy(new_ring_name, line, dashes - line);
275 new_ring_name[dashes - line - 1] = '\0';
276
Chris Wilson98eb5a52011-01-09 13:26:50 +0000277 matched = sscanf (dashes, "--- gtt_offset = 0x%08x\n",
278 &new_gtt_offset);
279 if (matched == 1) {
280 if (count) {
Daniel Vetter73c21042011-10-11 13:14:02 +0200281 printf("%s (%s) at 0x%08x:\n",
282 buffer_type[is_batch],
283 ring_name,
284 gtt_offset);
Chris Wilson98eb5a52011-01-09 13:26:50 +0000285 intel_decode (data, count, gtt_offset, devid, 0);
286 count = 0;
287 }
288 gtt_offset = new_gtt_offset;
289 is_batch = 1;
Daniel Vetter73c21042011-10-11 13:14:02 +0200290 free(ring_name);
291 ring_name = new_ring_name;
Chris Wilson98eb5a52011-01-09 13:26:50 +0000292 continue;
293 }
Chris Wilson9eb4de12010-02-12 13:28:40 +0000294
Chris Wilson98eb5a52011-01-09 13:26:50 +0000295 matched = sscanf (dashes, "--- ringbuffer = 0x%08x\n",
296 &new_gtt_offset);
297 if (matched == 1) {
298 if (count) {
Daniel Vetter73c21042011-10-11 13:14:02 +0200299 printf("%s (%s) at 0x%08x:\n",
300 buffer_type[is_batch],
301 ring_name,
302 gtt_offset);
Chris Wilson98eb5a52011-01-09 13:26:50 +0000303 intel_decode (data, count, gtt_offset, devid, 0);
304 count = 0;
305 }
306 gtt_offset = new_gtt_offset;
307 is_batch = 0;
Daniel Vetter73c21042011-10-11 13:14:02 +0200308 free(ring_name);
309 ring_name = new_ring_name;
Chris Wilson98eb5a52011-01-09 13:26:50 +0000310 continue;
311 }
Chris Wilson9eb4de12010-02-12 13:28:40 +0000312 }
313
314 matched = sscanf (line, "%08x : %08x", &offset, &value);
315 if (matched != 2) {
316 unsigned int reg;
317
Daniel Vetter92b1f2c2011-10-18 15:54:31 +0200318 /* display reg section is after the ringbuffers, don't mix them */
319 if (count) {
320 printf("%s (%s) at 0x%08x:\n",
321 buffer_type[is_batch],
322 ring_name,
323 gtt_offset);
324 intel_decode (data, count, gtt_offset, devid, 0);
325 count = 0;
326 }
327
Chris Wilson9eb4de12010-02-12 13:28:40 +0000328 printf("%s", line);
329
330 matched = sscanf (line, "PCI ID: 0x%04x\n", &reg);
Chris Wilson4f208442010-12-23 19:44:14 +0000331 if (matched == 1) {
Chris Wilson9eb4de12010-02-12 13:28:40 +0000332 devid = reg;
Daniel Vetter5801e6b2011-10-18 16:30:56 +0200333 printf("Detected GEN%i chipset\n",
334 intel_gen(devid));
Chris Wilson4f208442010-12-23 19:44:14 +0000335 }
Chris Wilson9eb4de12010-02-12 13:28:40 +0000336
337 matched = sscanf (line, " ACTHD: 0x%08x\n", &reg);
Chris Wilson14618622010-08-25 11:55:25 +0100338 if (matched == 1)
Chris Wilson9eb4de12010-02-12 13:28:40 +0000339 intel_decode_context_set_head_tail(reg, 0xffffffff);
340
Chris Wilsonbfc2b532010-03-04 21:56:04 +0000341 matched = sscanf (line, " PGTBL_ER: 0x%08x\n", &reg);
Chris Wilson14618622010-08-25 11:55:25 +0100342 if (matched == 1 && reg)
Chris Wilsonbfc2b532010-03-04 21:56:04 +0000343 print_pgtbl_err(reg, devid);
344
Chris Wilson9eb4de12010-02-12 13:28:40 +0000345 matched = sscanf (line, " INSTDONE: 0x%08x\n", &reg);
Chris Wilson14618622010-08-25 11:55:25 +0100346 if (matched == 1)
Chris Wilson95374222010-04-08 11:56:57 +0100347 print_instdone (devid, reg, -1);
Chris Wilson9eb4de12010-02-12 13:28:40 +0000348
349 matched = sscanf (line, " INSTDONE1: 0x%08x\n", &reg);
Chris Wilson14618622010-08-25 11:55:25 +0100350 if (matched == 1)
Chris Wilson95374222010-04-08 11:56:57 +0100351 print_instdone (devid, -1, reg);
Chris Wilson9eb4de12010-02-12 13:28:40 +0000352
Daniel Vettercf5db112011-03-14 11:20:17 +0100353 matched = sscanf (line, " fence[%i] = %8Lx\n", &reg, &fence);
354 if (matched == 2)
355 print_fence (devid, fence);
356
Chris Wilson9eb4de12010-02-12 13:28:40 +0000357 continue;
358 }
359
360 count++;
361
362 if (count > data_size) {
363 data_size = data_size ? data_size * 2 : 1024;
364 data = realloc (data, data_size * sizeof (uint32_t));
365 if (data == NULL) {
366 fprintf (stderr, "Out of memory.\n");
367 exit (1);
368 }
369 }
370
371 data[count-1] = value;
372 }
373
374 if (count) {
Daniel Vetter6ed89f42011-10-18 15:49:41 +0200375 printf("%s (%s) at 0x%08x:\n",
376 buffer_type[is_batch],
377 ring_name,
378 gtt_offset);
Chris Wilson9eb4de12010-02-12 13:28:40 +0000379 intel_decode (data, count, gtt_offset, devid, 0);
380 }
381
382 free (data);
383 free (line);
Daniel Vetter73c21042011-10-11 13:14:02 +0200384 free (ring_name);
Chris Wilson9eb4de12010-02-12 13:28:40 +0000385}
386
387int
388main (int argc, char *argv[])
389{
Chris Wilsona3a78632010-12-01 21:51:59 +0000390 FILE *file;
Chris Wilson9eb4de12010-02-12 13:28:40 +0000391 const char *path;
Chris Wilsona3a78632010-12-01 21:51:59 +0000392 char *filename;
Chris Wilson9eb4de12010-02-12 13:28:40 +0000393 struct stat st;
394 int err;
395
396 if (argc > 2) {
397 fprintf (stderr,
398 "intel_gpu_decode: Parse an Intel GPU i915_error_state\n"
399 "Usage:\n"
400 "\t%s [<file>]\n"
401 "\n"
402 "With no arguments, debugfs-dri-directory is probed for in "
403 "/debug and \n"
404 "/sys/kernel/debug. Otherwise, it may be "
405 "specified. If a file is given,\n"
406 "it is parsed as an GPU dump in the format of "
407 "/debug/dri/0/i915_error_state.\n",
408 argv[0]);
409 return 1;
410 }
411
Chris Wilson9eb4de12010-02-12 13:28:40 +0000412 if (argc == 1) {
Chris Wilson292ae452010-12-10 15:31:59 +0000413 if (isatty(0)) {
Chris Wilson68a95f02011-01-25 16:34:08 +0000414 path = "/debug/dri";
Chris Wilson9eb4de12010-02-12 13:28:40 +0000415 err = stat (path, &st);
416 if (err != 0) {
Chris Wilson68a95f02011-01-25 16:34:08 +0000417 path = "/sys/kernel/debug/dri";
Chris Wilsona3a78632010-12-01 21:51:59 +0000418 err = stat (path, &st);
419 if (err != 0) {
420 errx(1,
421 "Couldn't find i915 debugfs directory.\n\n"
422 "Is debugfs mounted? You might try mounting it with a command such as:\n\n"
423 "\tsudo mount -t debugfs debugfs /sys/kernel/debug\n");
424 }
Chris Wilson9eb4de12010-02-12 13:28:40 +0000425 }
Chris Wilsona3a78632010-12-01 21:51:59 +0000426 } else {
427 read_data_file(stdin);
428 exit(0);
Chris Wilson9eb4de12010-02-12 13:28:40 +0000429 }
430 } else {
431 path = argv[1];
432 err = stat (path, &st);
433 if (err != 0) {
434 fprintf (stderr, "Error opening %s: %s\n",
435 path, strerror (errno));
436 exit (1);
437 }
438 }
439
Chris Wilson68a95f02011-01-25 16:34:08 +0000440 if (S_ISDIR (st.st_mode)) {
Chris Wilson9eb4de12010-02-12 13:28:40 +0000441 asprintf (&filename, "%s/i915_error_state", path);
Chris Wilson68a95f02011-01-25 16:34:08 +0000442 file = fopen(filename, "r");
443 if (!file) {
444 int minor;
445 for (minor = 0; minor < 64; minor++) {
446 free(filename);
447 asprintf(&filename, "%s/%d/i915_error_state", path, minor);
448 file = fopen(filename, "r");
449 if (file)
450 break;
451 }
452 }
453 if (!file) {
454 fprintf (stderr, "Failed to find i915_error_state beneath %s\n",
455 path);
456 exit (1);
457 }
Chris Wilson9eb4de12010-02-12 13:28:40 +0000458 } else {
Chris Wilson68a95f02011-01-25 16:34:08 +0000459 filename = (char *) path;
460 file = fopen(filename, "r");
461 if (!file) {
462 fprintf (stderr, "Failed to open %s: %s\n",
463 filename, strerror (errno));
464 exit (1);
465 }
Chris Wilson9eb4de12010-02-12 13:28:40 +0000466 }
467
Chris Wilson68a95f02011-01-25 16:34:08 +0000468 read_data_file (file);
469 fclose (file);
470
Chris Wilsona3a78632010-12-01 21:51:59 +0000471 if (filename != path)
472 free (filename);
473
Chris Wilson9eb4de12010-02-12 13:28:40 +0000474 return 0;
475}