blob: 4dc3d43ce4f6bd2562a01eb4b63933f414e8c25d [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
79read_data_file (const char * filename)
80{
81 FILE *file;
82 int devid = PCI_CHIP_I855_GM;
83 uint32_t *data = NULL;
84 int data_size = 0, count = 0, line_number = 0, matched;
85 char *line = NULL;
86 size_t line_size;
87 uint32_t offset, value;
88 uint32_t gtt_offset = 0, new_gtt_offset;
89 char *buffer_type[2] = { "ringbuffer", "batchbuffer" };
90 int is_batch = 1;
91
92 file = fopen (filename, "r");
93 if (file == NULL) {
94 fprintf (stderr, "Failed to open %s: %s\n",
95 filename, strerror (errno));
96 exit (1);
97 }
98
99 while (getline (&line, &line_size, file) > 0) {
100 line_number++;
101
102 matched = sscanf (line, "--- gtt_offset = 0x%08x\n", &new_gtt_offset);
103 if (matched == 1) {
104 if (count) {
105 printf("%s at 0x%08x:\n", buffer_type[is_batch], gtt_offset);
106 intel_decode (data, count, gtt_offset, devid, 0);
107 count = 0;
108 }
109 gtt_offset = new_gtt_offset;
110 is_batch = 1;
111 continue;
112 }
113
114 matched = sscanf (line, "--- ringbuffer = 0x%08x\n", &new_gtt_offset);
115 if (matched == 1) {
116 if (count) {
117 printf("%s at 0x%08x:\n", buffer_type[is_batch], gtt_offset);
118 intel_decode (data, count, gtt_offset, devid, 0);
119 count = 0;
120 }
121 gtt_offset = new_gtt_offset;
122 is_batch = 0;
123 continue;
124 }
125
126 matched = sscanf (line, "%08x : %08x", &offset, &value);
127 if (matched != 2) {
128 unsigned int reg;
129
130 printf("%s", line);
131
132 matched = sscanf (line, "PCI ID: 0x%04x\n", &reg);
133 if (matched)
134 devid = reg;
135
136 matched = sscanf (line, " ACTHD: 0x%08x\n", &reg);
137 if (matched)
138 intel_decode_context_set_head_tail(reg, 0xffffffff);
139
140 matched = sscanf (line, " INSTDONE: 0x%08x\n", &reg);
141 if (matched)
142 print_instdone (reg, -1);
143
144 matched = sscanf (line, " INSTDONE1: 0x%08x\n", &reg);
145 if (matched)
146 print_instdone (-1, reg);
147
148 continue;
149 }
150
151 count++;
152
153 if (count > data_size) {
154 data_size = data_size ? data_size * 2 : 1024;
155 data = realloc (data, data_size * sizeof (uint32_t));
156 if (data == NULL) {
157 fprintf (stderr, "Out of memory.\n");
158 exit (1);
159 }
160 }
161
162 data[count-1] = value;
163 }
164
165 if (count) {
166 printf("%s at 0x%08x:\n", buffer_type[is_batch], gtt_offset);
167 intel_decode (data, count, gtt_offset, devid, 0);
168 }
169
170 free (data);
171 free (line);
172
173 fclose (file);
174}
175
176int
177main (int argc, char *argv[])
178{
179 const char *path;
180 struct stat st;
181 int err;
182
183 if (argc > 2) {
184 fprintf (stderr,
185 "intel_gpu_decode: Parse an Intel GPU i915_error_state\n"
186 "Usage:\n"
187 "\t%s [<file>]\n"
188 "\n"
189 "With no arguments, debugfs-dri-directory is probed for in "
190 "/debug and \n"
191 "/sys/kernel/debug. Otherwise, it may be "
192 "specified. If a file is given,\n"
193 "it is parsed as an GPU dump in the format of "
194 "/debug/dri/0/i915_error_state.\n",
195 argv[0]);
196 return 1;
197 }
198
199 init_instdone_definitions();
200
201 if (argc == 1) {
202 path = "/debug/dri/0";
203 err = stat (path, &st);
204 if (err != 0) {
205 path = "/sys/kernel/debug/dri/0";
206 err = stat (path, &st);
207 if (err != 0) {
208 errx(1,
209 "Couldn't find i915 debugfs directory.\n\n"
210 "Is debugfs mounted? You might try mounting it with a command such as:\n\n"
211 "\tsudo mount -t debugfs debugfs /sys/kernel/debug\n");
212 }
213 }
214 } else {
215 path = argv[1];
216 err = stat (path, &st);
217 if (err != 0) {
218 fprintf (stderr, "Error opening %s: %s\n",
219 path, strerror (errno));
220 exit (1);
221 }
222 }
223
224 if (S_ISDIR (st.st_mode)) {
225 char *filename;
226
227 asprintf (&filename, "%s/i915_error_state", path);
228 read_data_file (filename);
229 free (filename);
230 } else {
231 read_data_file (path);
232 }
233
234 return 0;
235}