blob: d4bf8bcfe410af640d8088b6e31501a8ddd7429d [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
58print_instdone (unsigned int instdone, unsigned int instdone1)
59{
60 int i;
61
62 for (i = 0; i < num_instdone_bits; i++) {
63 int busy = 0;
64
65 if (instdone_bits[i].reg == INST_DONE_1) {
66 if (!(instdone1 & instdone_bits[i].bit))
67 busy = 1;
68 } else {
69 if (!(instdone & instdone_bits[i].bit))
70 busy = 1;
71 }
72
73 if (busy)
74 printf(" busy: %s\n", instdone_bits[i].name);
75 }
76}
77
78static void
Chris Wilsonbfc2b532010-03-04 21:56:04 +000079print_i830_pgtbl_err(unsigned int reg)
80{
81 const char *str;
82
83 switch((reg >> 3) & 0xf) {
84 case 0x1: str = "Overlay TLB"; break;
85 case 0x2: str = "Display A TLB"; break;
86 case 0x3: str = "Host TLB"; break;
87 case 0x4: str = "Render TLB"; break;
88 case 0x5: str = "Display C TLB"; break;
89 case 0x6: str = "Mapping TLB"; break;
90 case 0x7: str = "Command Stream TLB"; break;
91 case 0x8: str = "Vertex Buffer TLB"; break;
92 case 0x9: str = "Display B TLB"; break;
93 case 0xa: str = "Reserved System Memory"; break;
94 case 0xb: str = "Compressor TLB"; break;
95 case 0xc: str = "Binner TLB"; break;
96 default: str = "unknown"; break;
97 }
98
99 if (str)
100 printf (" source = %s\n", str);
101
102 switch(reg & 0x7) {
103 case 0x0: str = "Invalid GTT"; break;
104 case 0x1: str = "Invalid GTT PTE"; break;
105 case 0x2: str = "Invalid Memory"; break;
106 case 0x3: str = "Invalid TLB miss"; break;
107 case 0x4: str = "Invalid PTE data"; break;
108 case 0x5: str = "Invalid LocalMemory not present"; break;
109 case 0x6: str = "Invalid Tiling"; break;
110 case 0x7: str = "Host to CAM"; break;
111 }
112 printf (" error = %s\n", str);
113}
114
115static void
116print_pgtbl_err(unsigned int reg, unsigned int devid)
117{
118 if (IS_965(devid)) {
119 } else if (IS_9XX(devid)) {
120 } else {
121 return print_i830_pgtbl_err(reg);
122 }
123}
124
125static void
Chris Wilson9eb4de12010-02-12 13:28:40 +0000126read_data_file (const char * filename)
127{
128 FILE *file;
129 int devid = PCI_CHIP_I855_GM;
130 uint32_t *data = NULL;
131 int data_size = 0, count = 0, line_number = 0, matched;
132 char *line = NULL;
133 size_t line_size;
134 uint32_t offset, value;
135 uint32_t gtt_offset = 0, new_gtt_offset;
136 char *buffer_type[2] = { "ringbuffer", "batchbuffer" };
137 int is_batch = 1;
138
139 file = fopen (filename, "r");
140 if (file == NULL) {
141 fprintf (stderr, "Failed to open %s: %s\n",
142 filename, strerror (errno));
143 exit (1);
144 }
145
146 while (getline (&line, &line_size, file) > 0) {
147 line_number++;
148
149 matched = sscanf (line, "--- gtt_offset = 0x%08x\n", &new_gtt_offset);
150 if (matched == 1) {
151 if (count) {
152 printf("%s at 0x%08x:\n", buffer_type[is_batch], gtt_offset);
153 intel_decode (data, count, gtt_offset, devid, 0);
154 count = 0;
155 }
156 gtt_offset = new_gtt_offset;
157 is_batch = 1;
158 continue;
159 }
160
161 matched = sscanf (line, "--- ringbuffer = 0x%08x\n", &new_gtt_offset);
162 if (matched == 1) {
163 if (count) {
164 printf("%s at 0x%08x:\n", buffer_type[is_batch], gtt_offset);
165 intel_decode (data, count, gtt_offset, devid, 0);
166 count = 0;
167 }
168 gtt_offset = new_gtt_offset;
169 is_batch = 0;
170 continue;
171 }
172
173 matched = sscanf (line, "%08x : %08x", &offset, &value);
174 if (matched != 2) {
175 unsigned int reg;
176
177 printf("%s", line);
178
179 matched = sscanf (line, "PCI ID: 0x%04x\n", &reg);
180 if (matched)
181 devid = reg;
182
183 matched = sscanf (line, " ACTHD: 0x%08x\n", &reg);
184 if (matched)
185 intel_decode_context_set_head_tail(reg, 0xffffffff);
186
Chris Wilsonbfc2b532010-03-04 21:56:04 +0000187 matched = sscanf (line, " PGTBL_ER: 0x%08x\n", &reg);
188 if (matched && reg)
189 print_pgtbl_err(reg, devid);
190
Chris Wilson9eb4de12010-02-12 13:28:40 +0000191 matched = sscanf (line, " INSTDONE: 0x%08x\n", &reg);
192 if (matched)
193 print_instdone (reg, -1);
194
195 matched = sscanf (line, " INSTDONE1: 0x%08x\n", &reg);
196 if (matched)
197 print_instdone (-1, reg);
198
199 continue;
200 }
201
202 count++;
203
204 if (count > data_size) {
205 data_size = data_size ? data_size * 2 : 1024;
206 data = realloc (data, data_size * sizeof (uint32_t));
207 if (data == NULL) {
208 fprintf (stderr, "Out of memory.\n");
209 exit (1);
210 }
211 }
212
213 data[count-1] = value;
214 }
215
216 if (count) {
217 printf("%s at 0x%08x:\n", buffer_type[is_batch], gtt_offset);
218 intel_decode (data, count, gtt_offset, devid, 0);
219 }
220
221 free (data);
222 free (line);
223
224 fclose (file);
225}
226
227int
228main (int argc, char *argv[])
229{
230 const char *path;
231 struct stat st;
232 int err;
233
234 if (argc > 2) {
235 fprintf (stderr,
236 "intel_gpu_decode: Parse an Intel GPU i915_error_state\n"
237 "Usage:\n"
238 "\t%s [<file>]\n"
239 "\n"
240 "With no arguments, debugfs-dri-directory is probed for in "
241 "/debug and \n"
242 "/sys/kernel/debug. Otherwise, it may be "
243 "specified. If a file is given,\n"
244 "it is parsed as an GPU dump in the format of "
245 "/debug/dri/0/i915_error_state.\n",
246 argv[0]);
247 return 1;
248 }
249
250 init_instdone_definitions();
251
252 if (argc == 1) {
253 path = "/debug/dri/0";
254 err = stat (path, &st);
255 if (err != 0) {
256 path = "/sys/kernel/debug/dri/0";
257 err = stat (path, &st);
258 if (err != 0) {
259 errx(1,
260 "Couldn't find i915 debugfs directory.\n\n"
261 "Is debugfs mounted? You might try mounting it with a command such as:\n\n"
262 "\tsudo mount -t debugfs debugfs /sys/kernel/debug\n");
263 }
264 }
265 } else {
266 path = argv[1];
267 err = stat (path, &st);
268 if (err != 0) {
269 fprintf (stderr, "Error opening %s: %s\n",
270 path, strerror (errno));
271 exit (1);
272 }
273 }
274
275 if (S_ISDIR (st.st_mode)) {
276 char *filename;
277
278 asprintf (&filename, "%s/i915_error_state", path);
279 read_data_file (filename);
280 free (filename);
281 } else {
282 read_data_file (path);
283 }
284
285 return 0;
286}