2 * Copyright © 2007 Intel Corporation
3 * Copyright © 2009 Intel Corporation
4 * Copyright © 2010 Intel Corporation
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:
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
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
26 * Eric Anholt <eric@anholt.net>
27 * Carl Worth <cworth@cworth.org>
28 * Chris Wilson <chris@chris-wilson.co.uk>
32 /** @file intel_decode.c
33 * This file contains code to print out batchbuffer contents in a
34 * human-readable format.
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.
53 #include <intel_bufmgr.h>
55 #include "intel_chipset.h"
58 #include "intel_reg.h"
61 print_head(unsigned int reg)
63 printf(" head = 0x%08x, wraps = %d\n", reg & (0x7ffff<<2), reg >> 21);
64 return reg & (0x7ffff<<2);
68 print_ctl(unsigned int reg)
70 uint32_t ring_length = (((reg & (0x1ff << 12)) >> 12) + 1) * 4096;
72 #define BIT_STR(reg, x, on, off) ((1 << (x)) & reg) ? on : off
74 printf(" len=%d%s%s%s\n", ring_length,
75 BIT_STR(reg, 0, ", enabled", ", disabled"),
76 BIT_STR(reg, 10, ", semaphore wait ", ""),
77 BIT_STR(reg, 11, ", rb wait ", "")
84 print_acthd(unsigned int reg, unsigned int ring_length)
86 if ((reg & (0x7ffff << 2)) < ring_length)
87 printf(" at ring: 0x%08x\n", reg & (0x7ffff << 2));
89 printf(" at batch: 0x%08x\n", reg);
93 print_instdone(uint32_t devid, unsigned int instdone, unsigned int instdone1)
99 init_instdone_definitions(devid);
103 for (i = 0; i < num_instdone_bits; i++) {
106 if (instdone_bits[i].reg == INSTDONE_1) {
107 if (!(instdone1 & instdone_bits[i].bit))
110 if (!(instdone & instdone_bits[i].bit))
115 printf(" busy: %s\n", instdone_bits[i].name);
120 print_i830_pgtbl_err(unsigned int reg)
124 switch((reg >> 3) & 0xf) {
125 case 0x1: str = "Overlay TLB"; break;
126 case 0x2: str = "Display A TLB"; break;
127 case 0x3: str = "Host TLB"; break;
128 case 0x4: str = "Render TLB"; break;
129 case 0x5: str = "Display C TLB"; break;
130 case 0x6: str = "Mapping TLB"; break;
131 case 0x7: str = "Command Stream TLB"; break;
132 case 0x8: str = "Vertex Buffer TLB"; break;
133 case 0x9: str = "Display B TLB"; break;
134 case 0xa: str = "Reserved System Memory"; break;
135 case 0xb: str = "Compressor TLB"; break;
136 case 0xc: str = "Binner TLB"; break;
137 default: str = "unknown"; break;
141 printf(" source = %s\n", str);
144 case 0x0: str = "Invalid GTT"; break;
145 case 0x1: str = "Invalid GTT PTE"; break;
146 case 0x2: str = "Invalid Memory"; break;
147 case 0x3: str = "Invalid TLB miss"; break;
148 case 0x4: str = "Invalid PTE data"; break;
149 case 0x5: str = "Invalid LocalMemory not present"; break;
150 case 0x6: str = "Invalid Tiling"; break;
151 case 0x7: str = "Host to CAM"; break;
153 printf(" error = %s\n", str);
157 print_i915_pgtbl_err(unsigned int reg)
160 printf(" Cursor A: Invalid GTT PTE\n");
162 printf(" Cursor B: Invalid GTT PTE\n");
164 printf(" MT: Invalid tiling\n");
166 printf(" MT: Invalid GTT PTE\n");
168 printf(" LC: Invalid tiling\n");
170 printf(" LC: Invalid GTT PTE\n");
172 printf(" BIN VertexData: Invalid GTT PTE\n");
174 printf(" BIN Instruction: Invalid GTT PTE\n");
176 printf(" CS VertexData: Invalid GTT PTE\n");
178 printf(" CS Instruction: Invalid GTT PTE\n");
180 printf(" CS: Invalid GTT\n");
182 printf(" Overlay: Invalid tiling\n");
184 printf(" Overlay: Invalid GTT PTE\n");
186 printf(" Display C: Invalid tiling\n");
188 printf(" Display C: Invalid GTT PTE\n");
190 printf(" Display B: Invalid tiling\n");
192 printf(" Display B: Invalid GTT PTE\n");
194 printf(" Display A: Invalid tiling\n");
196 printf(" Display A: Invalid GTT PTE\n");
198 printf(" Host Invalid PTE data\n");
200 printf(" Host Invalid GTT PTE\n");
204 print_i965_pgtbl_err(unsigned int reg)
207 printf(" Invalid Sampler Cache GTT entry\n");
209 printf(" Invalid Render Cache GTT entry\n");
211 printf(" Invalid Instruction/State Cache GTT entry\n");
213 printf(" There is no ROC, this cannot occur!\n");
215 printf(" Invalid GTT entry during Vertex Fetch\n");
217 printf(" Invalid GTT entry during Command Fetch\n");
219 printf(" Invalid GTT entry during CS\n");
221 printf(" Invalid GTT entry during Cursor Fetch\n");
223 printf(" Invalid GTT entry during Overlay Fetch\n");
225 printf(" Invalid GTT entry during Display B Fetch\n");
227 printf(" Invalid GTT entry during Display A Fetch\n");
229 printf(" Valid PTE references illegal memory\n");
231 printf(" Invalid GTT entry during fetch for host\n");
235 print_pgtbl_err(unsigned int reg, unsigned int devid)
238 return print_i965_pgtbl_err(reg);
239 } else if (IS_GEN3(devid)) {
240 return print_i915_pgtbl_err(reg);
242 return print_i830_pgtbl_err(reg);
247 print_snb_fence(unsigned int devid, uint64_t fence)
249 printf(" %svalid, %c-tiled, pitch: %i, start: 0x%08x, size: %u\n",
250 fence & 1 ? "" : "in",
251 fence & (1<<1) ? 'y' : 'x',
252 (int)(((fence>>32)&0xfff)+1)*128,
253 (uint32_t)fence & 0xfffff000,
254 (uint32_t)(((fence>>32)&0xfffff000) - (fence&0xfffff000) + 4096));
258 print_i965_fence(unsigned int devid, uint64_t fence)
260 printf(" %svalid, %c-tiled, pitch: %i, start: 0x%08x, size: %u\n",
261 fence & 1 ? "" : "in",
262 fence & (1<<1) ? 'y' : 'x',
263 (int)(((fence>>2)&0x1ff)+1)*128,
264 (uint32_t)fence & 0xfffff000,
265 (uint32_t)(((fence>>32)&0xfffff000) - (fence&0xfffff000) + 4096));
269 print_i915_fence(unsigned int devid, uint64_t fence)
272 if ((fence & 12) && !IS_915(devid))
277 printf(" %svalid, %c-tiled, pitch: %i, start: 0x%08x, size: %i\n",
278 fence & 1 ? "" : "in",
279 fence & (1<<12) ? 'y' : 'x',
280 (1<<((fence>>4)&0xf))*tile_width,
281 (uint32_t)fence & 0xff00000,
282 1<<(20 + ((fence>>8)&0xf)));
286 print_i830_fence(unsigned int devid, uint64_t fence)
288 printf(" %svalid, %c-tiled, pitch: %i, start: 0x%08x, size: %i\n",
289 fence & 1 ? "" : "in",
290 fence & (1<<12) ? 'y' : 'x',
291 (1<<((fence>>4)&0xf))*128,
292 (uint32_t)fence & 0x7f80000,
293 1<<(19 + ((fence>>8)&0xf)));
297 print_fence(unsigned int devid, uint64_t fence)
299 if (IS_GEN6(devid) || IS_GEN7(devid)) {
300 return print_snb_fence(devid, fence);
301 } else if (IS_GEN4(devid) || IS_GEN5(devid)) {
302 return print_i965_fence(devid, fence);
303 } else if (IS_GEN3(devid)) {
304 return print_i915_fence(devid, fence);
306 return print_i830_fence(devid, fence);
310 #define MAX_RINGS 10 /* I really hope this never... */
311 uint32_t head[MAX_RINGS];
314 static void print_batch(int is_batch, const char *ring_name, uint32_t gtt_offset)
316 const char *buffer_type[2] = { "ringbuffer", "batchbuffer" };
317 if (is_batch || !num_rings)
318 printf("%s (%s) at 0x%08x\n", buffer_type[is_batch], ring_name, gtt_offset);
320 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);
323 static void decode(struct drm_intel_decode *ctx, bool is_batch,
324 const char *ring_name, uint32_t gtt_offset, uint32_t *data,
330 print_batch(is_batch, ring_name, gtt_offset);
331 drm_intel_decode_set_batch_pointer(ctx, data, gtt_offset, *count);
332 drm_intel_decode(ctx);
337 read_data_file(FILE *file)
339 struct drm_intel_decode *decode_ctx = NULL;
340 uint32_t devid = PCI_CHIP_I855_GM;
341 uint32_t *data = NULL;
342 long long unsigned fence;
343 int data_size = 0, count = 0, line_number = 0, matched;
346 uint32_t offset, value, ring_length = 0;
347 uint32_t gtt_offset = 0, new_gtt_offset;
348 char *ring_name = NULL;
351 while (getline(&line, &line_size, file) > 0) {
355 dashes = strstr(line, "---");
357 char *new_ring_name = malloc(dashes - line);
358 strncpy(new_ring_name, line, dashes - line);
359 new_ring_name[dashes - line - 1] = '\0';
362 num_rings = head_ndx;
364 matched = sscanf(dashes, "--- gtt_offset = 0x%08x\n",
367 decode(decode_ctx, is_batch, ring_name,
368 gtt_offset, data, &count);
369 gtt_offset = new_gtt_offset;
372 ring_name = new_ring_name;
376 matched = sscanf(dashes, "--- ringbuffer = 0x%08x\n",
379 decode(decode_ctx, is_batch, ring_name,
380 gtt_offset, data, &count);
381 gtt_offset = new_gtt_offset;
384 ring_name = new_ring_name;
389 matched = sscanf(line, "%08x : %08x", &offset, &value);
393 /* display reg section is after the ringbuffers, don't mix them */
394 decode(decode_ctx, is_batch, ring_name, gtt_offset,
399 matched = sscanf(line, "PCI ID: 0x%04x\n", ®);
401 matched = sscanf(line, " PCI ID: 0x%04x\n", ®);
403 const char *pci_id_start = strstr(line, "PCI ID");
405 matched = sscanf(pci_id_start, "PCI ID: 0x%04x\n", ®);
409 printf("Detected GEN%i chipset\n",
412 decode_ctx = drm_intel_decode_context_alloc(devid);
415 matched = sscanf(line, " CTL: 0x%08x\n", ®);
417 ring_length = print_ctl(reg);
419 matched = sscanf(line, " HEAD: 0x%08x\n", ®);
421 head[num_rings++] = print_head(reg);
424 matched = sscanf(line, " ACTHD: 0x%08x\n", ®);
426 print_acthd(reg, ring_length);
427 drm_intel_decode_set_head_tail(decode_ctx, reg, 0xffffffff);
430 matched = sscanf(line, " PGTBL_ER: 0x%08x\n", ®);
431 if (matched == 1 && reg)
432 print_pgtbl_err(reg, devid);
434 matched = sscanf(line, " INSTDONE: 0x%08x\n", ®);
436 print_instdone(devid, reg, -1);
438 matched = sscanf(line, " INSTDONE1: 0x%08x\n", ®);
440 print_instdone(devid, -1, reg);
442 matched = sscanf(line, " fence[%i] = %Lx\n", ®, &fence);
444 print_fence(devid, fence);
451 if (count > data_size) {
452 data_size = data_size ? data_size * 2 : 1024;
453 data = realloc(data, data_size * sizeof (uint32_t));
455 fprintf(stderr, "Out of memory.\n");
460 data[count-1] = value;
463 decode(decode_ctx, is_batch, ring_name, gtt_offset, data, &count);
471 main(int argc, char *argv[])
475 char *filename = NULL;
481 "intel_gpu_decode: Parse an Intel GPU i915_error_state\n"
485 "With no arguments, debugfs-dri-directory is probed for in "
487 "/sys/kernel/debug. Otherwise, it may be "
488 "specified. If a file is given,\n"
489 "it is parsed as an GPU dump in the format of "
490 "/debug/dri/0/i915_error_state.\n",
497 path = "/sys/class/drm/card0/error";
498 error = stat(path, &st);
501 error = stat(path, &st);
504 path = "/sys/kernel/debug/dri";
505 error = stat(path, &st);
509 "Couldn't find i915 debugfs directory.\n\n"
510 "Is debugfs mounted? You might try mounting it with a command such as:\n\n"
511 "\tsudo mount -t debugfs debugfs /sys/kernel/debug\n");
514 read_data_file(stdin);
519 error = stat(path, &st);
521 fprintf(stderr, "Error opening %s: %s\n",
522 path, strerror(errno));
527 if (S_ISDIR(st.st_mode)) {
530 ret = asprintf(&filename, "%s/i915_error_state", path);
532 file = fopen(filename, "r");
535 for (minor = 0; minor < 64; minor++) {
537 ret = asprintf(&filename, "%s/%d/i915_error_state", path, minor);
540 file = fopen(filename, "r");
546 fprintf(stderr, "Failed to find i915_error_state beneath %s\n",
551 file = fopen(path, "r");
553 fprintf(stderr, "Failed to open %s: %s\n",
554 path, strerror(errno));
559 read_data_file(file);
562 if (filename != path)
568 /* vim: set ts=8 sw=8 tw=0 noet :*/