blob: e6c3a7637ab21c801b534e53a26614fdd6dc5668 [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>
47#include <inttypes.h>
48#include <errno.h>
49#include <sys/stat.h>
50#include <err.h>
51
52#include "intel_decode.h"
53#include "intel_chipset.h"
54#include "intel_gpu_tools.h"
55#include "instdone.h"
56
57static void
Chris Wilson95374222010-04-08 11:56:57 +010058print_instdone (uint32_t devid, unsigned int instdone, unsigned int instdone1)
Chris Wilson9eb4de12010-02-12 13:28:40 +000059{
60 int i;
Chris Wilson95374222010-04-08 11:56:57 +010061 static int once;
62
63 if (!once) {
64 init_instdone_definitions(devid);
65 once = 1;
66 }
Chris Wilson9eb4de12010-02-12 13:28:40 +000067
68 for (i = 0; i < num_instdone_bits; i++) {
69 int busy = 0;
70
71 if (instdone_bits[i].reg == INST_DONE_1) {
72 if (!(instdone1 & instdone_bits[i].bit))
73 busy = 1;
74 } else {
75 if (!(instdone & instdone_bits[i].bit))
76 busy = 1;
77 }
78
79 if (busy)
80 printf(" busy: %s\n", instdone_bits[i].name);
81 }
82}
83
84static void
Chris Wilsonbfc2b532010-03-04 21:56:04 +000085print_i830_pgtbl_err(unsigned int reg)
86{
87 const char *str;
88
89 switch((reg >> 3) & 0xf) {
90 case 0x1: str = "Overlay TLB"; break;
91 case 0x2: str = "Display A TLB"; break;
92 case 0x3: str = "Host TLB"; break;
93 case 0x4: str = "Render TLB"; break;
94 case 0x5: str = "Display C TLB"; break;
95 case 0x6: str = "Mapping TLB"; break;
96 case 0x7: str = "Command Stream TLB"; break;
97 case 0x8: str = "Vertex Buffer TLB"; break;
98 case 0x9: str = "Display B TLB"; break;
99 case 0xa: str = "Reserved System Memory"; break;
100 case 0xb: str = "Compressor TLB"; break;
101 case 0xc: str = "Binner TLB"; break;
102 default: str = "unknown"; break;
103 }
104
105 if (str)
106 printf (" source = %s\n", str);
107
108 switch(reg & 0x7) {
109 case 0x0: str = "Invalid GTT"; break;
110 case 0x1: str = "Invalid GTT PTE"; break;
111 case 0x2: str = "Invalid Memory"; break;
112 case 0x3: str = "Invalid TLB miss"; break;
113 case 0x4: str = "Invalid PTE data"; break;
114 case 0x5: str = "Invalid LocalMemory not present"; break;
115 case 0x6: str = "Invalid Tiling"; break;
116 case 0x7: str = "Host to CAM"; break;
117 }
118 printf (" error = %s\n", str);
119}
120
121static void
Chris Wilson2d1ad952010-07-15 19:18:39 +0100122print_i915_pgtbl_err(unsigned int reg)
123{
124 if (reg & (1 << 29))
125 printf (" Cursor A: Invalid GTT PTE\n");
126 if (reg & (1 << 28))
127 printf (" Cursor B: Invalid GTT PTE\n");
128 if (reg & (1 << 27))
129 printf (" MT: Invalid tiling\n");
130 if (reg & (1 << 26))
131 printf (" MT: Invalid GTT PTE\n");
132 if (reg & (1 << 25))
133 printf (" LC: Invalid tiling\n");
134 if (reg & (1 << 24))
135 printf (" LC: Invalid GTT PTE\n");
136 if (reg & (1 << 23))
137 printf (" BIN VertexData: Invalid GTT PTE\n");
138 if (reg & (1 << 22))
139 printf (" BIN Instruction: Invalid GTT PTE\n");
140 if (reg & (1 << 21))
141 printf (" CS VertexData: Invalid GTT PTE\n");
142 if (reg & (1 << 20))
143 printf (" CS Instruction: Invalid GTT PTE\n");
144 if (reg & (1 << 19))
145 printf (" CS: Invalid GTT\n");
146 if (reg & (1 << 18))
147 printf (" Overlay: Invalid tiling\n");
148 if (reg & (1 << 16))
149 printf (" Overlay: Invalid GTT PTE\n");
150 if (reg & (1 << 14))
151 printf (" Display C: Invalid tiling\n");
152 if (reg & (1 << 12))
153 printf (" Display C: Invalid GTT PTE\n");
154 if (reg & (1 << 10))
155 printf (" Display B: Invalid tiling\n");
156 if (reg & (1 << 8))
157 printf (" Display B: Invalid GTT PTE\n");
158 if (reg & (1 << 6))
159 printf (" Display A: Invalid tiling\n");
160 if (reg & (1 << 4))
161 printf (" Display A: Invalid GTT PTE\n");
162 if (reg & (1 << 1))
163 printf (" Host Invalid PTE data\n");
164 if (reg & (1 << 0))
165 printf (" Host Invalid GTT PTE\n");
166}
167
168static void
Chris Wilson89343952010-10-22 11:33:08 +0100169print_i965_pgtbl_err(unsigned int reg)
170{
171 if (reg & (1 << 26))
172 printf (" Invalid Sampler Cache GTT entry\n");
173 if (reg & (1 << 24))
174 printf (" Invalid Render Cache GTT entry\n");
175 if (reg & (1 << 23))
176 printf (" Invalid Instruction/State Cache GTT entry\n");
177 if (reg & (1 << 22))
178 printf (" There is no ROC, this cannot occur!\n");
179 if (reg & (1 << 21))
180 printf (" Invalid GTT entry during Vertex Fetch\n");
181 if (reg & (1 << 20))
182 printf (" Invalid GTT entry during Command Fetch\n");
183 if (reg & (1 << 19))
184 printf (" Invalid GTT entry during CS\n");
185 if (reg & (1 << 18))
186 printf (" Invalid GTT entry during Cursor Fetch\n");
187 if (reg & (1 << 17))
188 printf (" Invalid GTT entry during Overlay Fetch\n");
189 if (reg & (1 << 8))
190 printf (" Invalid GTT entry during Display B Fetch\n");
191 if (reg & (1 << 4))
192 printf (" Invalid GTT entry during Display A Fetch\n");
193 if (reg & (1 << 1))
194 printf (" Valid PTE references illegal memory\n");
195 if (reg & (1 << 0))
196 printf (" Invalid GTT entry during fetch for host\n");
197}
198
199static void
Chris Wilsonbfc2b532010-03-04 21:56:04 +0000200print_pgtbl_err(unsigned int reg, unsigned int devid)
201{
202 if (IS_965(devid)) {
Chris Wilson89343952010-10-22 11:33:08 +0100203 return print_i965_pgtbl_err(reg);
Chris Wilsonbfc2b532010-03-04 21:56:04 +0000204 } else if (IS_9XX(devid)) {
Chris Wilson2d1ad952010-07-15 19:18:39 +0100205 return print_i915_pgtbl_err(reg);
Chris Wilsonbfc2b532010-03-04 21:56:04 +0000206 } else {
207 return print_i830_pgtbl_err(reg);
208 }
209}
210
211static void
Chris Wilson9eb4de12010-02-12 13:28:40 +0000212read_data_file (const char * filename)
213{
214 FILE *file;
215 int devid = PCI_CHIP_I855_GM;
216 uint32_t *data = NULL;
217 int data_size = 0, count = 0, line_number = 0, matched;
218 char *line = NULL;
219 size_t line_size;
220 uint32_t offset, value;
221 uint32_t gtt_offset = 0, new_gtt_offset;
222 char *buffer_type[2] = { "ringbuffer", "batchbuffer" };
223 int is_batch = 1;
224
225 file = fopen (filename, "r");
226 if (file == NULL) {
227 fprintf (stderr, "Failed to open %s: %s\n",
228 filename, strerror (errno));
229 exit (1);
230 }
231
232 while (getline (&line, &line_size, file) > 0) {
233 line_number++;
234
235 matched = sscanf (line, "--- gtt_offset = 0x%08x\n", &new_gtt_offset);
236 if (matched == 1) {
237 if (count) {
238 printf("%s at 0x%08x:\n", buffer_type[is_batch], gtt_offset);
239 intel_decode (data, count, gtt_offset, devid, 0);
240 count = 0;
241 }
242 gtt_offset = new_gtt_offset;
243 is_batch = 1;
244 continue;
245 }
246
247 matched = sscanf (line, "--- ringbuffer = 0x%08x\n", &new_gtt_offset);
248 if (matched == 1) {
249 if (count) {
250 printf("%s at 0x%08x:\n", buffer_type[is_batch], gtt_offset);
251 intel_decode (data, count, gtt_offset, devid, 0);
252 count = 0;
253 }
254 gtt_offset = new_gtt_offset;
255 is_batch = 0;
256 continue;
257 }
258
259 matched = sscanf (line, "%08x : %08x", &offset, &value);
260 if (matched != 2) {
261 unsigned int reg;
262
263 printf("%s", line);
264
265 matched = sscanf (line, "PCI ID: 0x%04x\n", &reg);
Chris Wilson14618622010-08-25 11:55:25 +0100266 if (matched == 1)
Chris Wilson9eb4de12010-02-12 13:28:40 +0000267 devid = reg;
268
269 matched = sscanf (line, " ACTHD: 0x%08x\n", &reg);
Chris Wilson14618622010-08-25 11:55:25 +0100270 if (matched == 1)
Chris Wilson9eb4de12010-02-12 13:28:40 +0000271 intel_decode_context_set_head_tail(reg, 0xffffffff);
272
Chris Wilsonbfc2b532010-03-04 21:56:04 +0000273 matched = sscanf (line, " PGTBL_ER: 0x%08x\n", &reg);
Chris Wilson14618622010-08-25 11:55:25 +0100274 if (matched == 1 && reg)
Chris Wilsonbfc2b532010-03-04 21:56:04 +0000275 print_pgtbl_err(reg, devid);
276
Chris Wilson9eb4de12010-02-12 13:28:40 +0000277 matched = sscanf (line, " INSTDONE: 0x%08x\n", &reg);
Chris Wilson14618622010-08-25 11:55:25 +0100278 if (matched == 1)
Chris Wilson95374222010-04-08 11:56:57 +0100279 print_instdone (devid, reg, -1);
Chris Wilson9eb4de12010-02-12 13:28:40 +0000280
281 matched = sscanf (line, " INSTDONE1: 0x%08x\n", &reg);
Chris Wilson14618622010-08-25 11:55:25 +0100282 if (matched == 1)
Chris Wilson95374222010-04-08 11:56:57 +0100283 print_instdone (devid, -1, reg);
Chris Wilson9eb4de12010-02-12 13:28:40 +0000284
285 continue;
286 }
287
288 count++;
289
290 if (count > data_size) {
291 data_size = data_size ? data_size * 2 : 1024;
292 data = realloc (data, data_size * sizeof (uint32_t));
293 if (data == NULL) {
294 fprintf (stderr, "Out of memory.\n");
295 exit (1);
296 }
297 }
298
299 data[count-1] = value;
300 }
301
302 if (count) {
303 printf("%s at 0x%08x:\n", buffer_type[is_batch], gtt_offset);
304 intel_decode (data, count, gtt_offset, devid, 0);
305 }
306
307 free (data);
308 free (line);
309
310 fclose (file);
311}
312
313int
314main (int argc, char *argv[])
315{
316 const char *path;
317 struct stat st;
318 int err;
319
320 if (argc > 2) {
321 fprintf (stderr,
322 "intel_gpu_decode: Parse an Intel GPU i915_error_state\n"
323 "Usage:\n"
324 "\t%s [<file>]\n"
325 "\n"
326 "With no arguments, debugfs-dri-directory is probed for in "
327 "/debug and \n"
328 "/sys/kernel/debug. Otherwise, it may be "
329 "specified. If a file is given,\n"
330 "it is parsed as an GPU dump in the format of "
331 "/debug/dri/0/i915_error_state.\n",
332 argv[0]);
333 return 1;
334 }
335
Chris Wilson9eb4de12010-02-12 13:28:40 +0000336 if (argc == 1) {
337 path = "/debug/dri/0";
338 err = stat (path, &st);
339 if (err != 0) {
340 path = "/sys/kernel/debug/dri/0";
341 err = stat (path, &st);
342 if (err != 0) {
343 errx(1,
344 "Couldn't find i915 debugfs directory.\n\n"
345 "Is debugfs mounted? You might try mounting it with a command such as:\n\n"
346 "\tsudo mount -t debugfs debugfs /sys/kernel/debug\n");
347 }
348 }
349 } else {
350 path = argv[1];
351 err = stat (path, &st);
352 if (err != 0) {
353 fprintf (stderr, "Error opening %s: %s\n",
354 path, strerror (errno));
355 exit (1);
356 }
357 }
358
359 if (S_ISDIR (st.st_mode)) {
360 char *filename;
361
362 asprintf (&filename, "%s/i915_error_state", path);
363 read_data_file (filename);
364 free (filename);
365 } else {
366 read_data_file (path);
367 }
368
369 return 0;
370}