intel/tools: avoid 'unused variable' warnings
[mesa.git] / src / intel / tools / aub_read.c
1 /*
2 * Copyright © 2016-2018 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 *
23 */
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <stdarg.h>
29
30 #include "common/gen_gem.h"
31 #include "util/macros.h"
32
33 #include "aub_read.h"
34 #include "intel_aub.h"
35
36 #define TYPE(dw) (((dw) >> 29) & 7)
37 #define OPCODE(dw) (((dw) >> 23) & 0x3f)
38 #define SUBOPCODE(dw) (((dw) >> 16) & 0x7f)
39
40 #define MAKE_HEADER(type, opcode, subopcode) \
41 (((type) << 29) | ((opcode) << 23) | ((subopcode) << 16))
42
43 #define TYPE_AUB 0x7
44
45 /* Classic AUB opcodes */
46 #define OPCODE_AUB 0x01
47 #define SUBOPCODE_HEADER 0x05
48 #define SUBOPCODE_BLOCK 0x41
49 #define SUBOPCODE_BMP 0x1e
50
51 /* Newer version AUB opcode */
52 #define OPCODE_NEW_AUB 0x2e
53 #define SUBOPCODE_REG_POLL 0x02
54 #define SUBOPCODE_REG_WRITE 0x03
55 #define SUBOPCODE_MEM_POLL 0x05
56 #define SUBOPCODE_MEM_WRITE 0x06
57 #define SUBOPCODE_VERSION 0x0e
58
59 #define MAKE_GEN(major, minor) (((major) << 8) | (minor))
60
61 static void
62 parse_error(struct aub_read *read, const uint32_t *p, const char *fmt, ...)
63 {
64 if (!read->error)
65 return;
66
67 va_list ap;
68 va_start(ap, fmt);
69
70 char msg[80];
71 vsnprintf(msg, sizeof(msg), fmt, ap);
72 read->error(read->user_data, p, msg);
73
74 va_end(ap);
75 }
76
77 static bool
78 handle_trace_header(struct aub_read *read, const uint32_t *p)
79 {
80 /* The intel_aubdump tool from IGT is kind enough to put a PCI-ID= tag in
81 * the AUB header comment. If the user hasn't specified a hardware
82 * generation, try to use the one from the AUB file.
83 */
84 const uint32_t *end = p + (p[0] & 0xffff) + 2;
85 int aub_pci_id = 0;
86
87 if (end > &p[12] && p[12] > 0) {
88 if (sscanf((char *)&p[13], "PCI-ID=%i", &aub_pci_id) > 0) {
89 if (!gen_get_device_info(aub_pci_id, &read->devinfo)) {
90 parse_error(read, p,
91 "can't find device information: pci_id=0x%x\n", aub_pci_id);
92 return false;
93 }
94 }
95 }
96
97 char app_name[33];
98 strncpy(app_name, (const char *)&p[2], 32);
99 app_name[32] = 0;
100
101 if (read->info)
102 read->info(read->user_data, aub_pci_id, app_name);
103
104 return true;
105 }
106
107 static bool
108 handle_memtrace_version(struct aub_read *read, const uint32_t *p)
109 {
110 int header_length = p[0] & 0xffff;
111 char app_name[64];
112 int app_name_len = MIN2(4 * (header_length + 1 - 5), ARRAY_SIZE(app_name) - 1);
113 int pci_id_len = 0;
114 int aub_pci_id = 0;
115
116 strncpy(app_name, (const char *)&p[5], app_name_len);
117 app_name[app_name_len] = 0;
118
119 if (sscanf(app_name, "PCI-ID=%i %n", &aub_pci_id, &pci_id_len) > 0) {
120 if (!gen_get_device_info(aub_pci_id, &read->devinfo)) {
121 parse_error(read, p, "can't find device information: pci_id=0x%x\n", aub_pci_id);
122 return false;
123 }
124
125 if (read->info)
126 read->info(read->user_data, aub_pci_id, app_name + pci_id_len);
127 }
128
129 return true;
130 }
131
132 static bool
133 handle_trace_block(struct aub_read *read, const uint32_t *p)
134 {
135 int operation = p[1] & AUB_TRACE_OPERATION_MASK;
136 int type = p[1] & AUB_TRACE_TYPE_MASK;
137 int address_space = p[1] & AUB_TRACE_ADDRESS_SPACE_MASK;
138 int header_length = p[0] & 0xffff;
139 enum drm_i915_gem_engine_class engine = I915_ENGINE_CLASS_RENDER;
140 const void *data = p + header_length + 2;
141 uint64_t address = gen_48b_address((read->devinfo.gen >= 8 ? ((uint64_t) p[5] << 32) : 0) |
142 ((uint64_t) p[3]));
143 uint32_t size = p[4];
144
145 switch (operation) {
146 case AUB_TRACE_OP_DATA_WRITE:
147 if (address_space == AUB_TRACE_MEMTYPE_GTT) {
148 if (read->local_write)
149 read->local_write(read->user_data, address, data, size);
150 break;
151 case AUB_TRACE_OP_COMMAND_WRITE:
152 switch (type) {
153 case AUB_TRACE_TYPE_RING_PRB0:
154 engine = I915_ENGINE_CLASS_RENDER;
155 break;
156 case AUB_TRACE_TYPE_RING_PRB1:
157 engine = I915_ENGINE_CLASS_VIDEO;
158 break;
159 case AUB_TRACE_TYPE_RING_PRB2:
160 engine = I915_ENGINE_CLASS_COPY;
161 break;
162 default:
163 parse_error(read, p, "command write to unknown ring %d\n", type);
164 return false;
165 }
166
167 if (read->ring_write)
168 read->ring_write(read->user_data, engine, data, size);
169 break;
170 }
171 }
172
173 return true;
174 }
175
176 static void
177 handle_memtrace_reg_write(struct aub_read *read, const uint32_t *p)
178 {
179 uint32_t offset = p[1];
180 uint32_t value = p[5];
181
182 if (read->reg_write)
183 read->reg_write(read->user_data, offset, value);
184
185 enum drm_i915_gem_engine_class engine;
186 uint64_t context_descriptor;
187
188 switch (offset) {
189 case 0x2230: /* render elsp */
190 read->render_elsp[read->render_elsp_index++] = value;
191 if (read->render_elsp_index < 4)
192 return;
193
194 read->render_elsp_index = 0;
195 engine = I915_ENGINE_CLASS_RENDER;
196 context_descriptor = (uint64_t)read->render_elsp[2] << 32 |
197 read->render_elsp[3];
198 break;
199 case 0x12230: /* video elsp */
200 read->video_elsp[read->video_elsp_index++] = value;
201 if (read->video_elsp_index < 4)
202 return;
203
204 read->video_elsp_index = 0;
205 engine = I915_ENGINE_CLASS_VIDEO;
206 context_descriptor = (uint64_t)read->video_elsp[2] << 32 |
207 read->video_elsp[3];
208 break;
209 case 0x22230: /* blitter elsp */
210 read->blitter_elsp[read->blitter_elsp_index++] = value;
211 if (read->blitter_elsp_index < 4)
212 return;
213
214 read->blitter_elsp_index = 0;
215 engine = I915_ENGINE_CLASS_COPY;
216 context_descriptor = (uint64_t)read->blitter_elsp[2] << 32 |
217 read->blitter_elsp[3];
218 break;
219 case 0x2510: /* render elsq0 lo */
220 read->render_elsp[3] = value;
221 return;
222 case 0x2514: /* render elsq0 hi */
223 read->render_elsp[2] = value;
224 return;
225 case 0x12510: /* video elsq0 lo */
226 read->video_elsp[3] = value;
227 return;
228 case 0x12514: /* video elsq0 hi */
229 read->video_elsp[2] = value;
230 return;
231 case 0x22510: /* blitter elsq0 lo */
232 read->blitter_elsp[3] = value;
233 return;
234 case 0x22514: /* blitter elsq0 hi */
235 read->blitter_elsp[2] = value;
236 return;
237 case 0x2550: /* render elsc */
238 engine = I915_ENGINE_CLASS_RENDER;
239 context_descriptor = (uint64_t)read->render_elsp[2] << 32 |
240 read->render_elsp[3];
241 break;
242 case 0x12550: /* video_elsc */
243 engine = I915_ENGINE_CLASS_VIDEO;
244 context_descriptor = (uint64_t)read->video_elsp[2] << 32 |
245 read->video_elsp[3];
246 break;
247 case 0x22550: /* blitter elsc */
248 engine = I915_ENGINE_CLASS_COPY;
249 context_descriptor = (uint64_t)read->blitter_elsp[2] << 32 |
250 read->blitter_elsp[3];
251 break;
252 default:
253 return;
254 }
255
256 if (read->execlist_write)
257 read->execlist_write(read->user_data, engine, context_descriptor);
258 }
259
260 static void
261 handle_memtrace_mem_write(struct aub_read *read, const uint32_t *p)
262 {
263 const void *data = p + 5;
264 uint64_t addr = gen_48b_address(*(uint64_t*)&p[1]);
265 uint32_t size = p[4];
266 uint32_t address_space = p[3] >> 28;
267
268 switch (address_space) {
269 case 0: /* GGTT */
270 if (read->ggtt_write)
271 read->ggtt_write(read->user_data, addr, data, size);
272 break;
273 case 1: /* Local */
274 if (read->local_write)
275 read->local_write(read->user_data, addr, data, size);
276 break;
277 case 2: /* Physical */
278 if (read->phys_write)
279 read->phys_write(read->user_data, addr, data, size);
280 break;
281 case 4: /* GGTT Entry */
282 if (read->ggtt_entry_write)
283 read->ggtt_entry_write(read->user_data, addr, data, size);
284 break;
285 }
286 }
287
288 int
289 aub_read_command(struct aub_read *read, const void *data, uint32_t data_len)
290 {
291 const uint32_t *p = data, *next;
292 MAYBE_UNUSED const uint32_t *end = data + data_len;
293 uint32_t h, header_length, bias;
294
295 assert(data_len >= 4);
296
297 h = *p;
298 header_length = h & 0xffff;
299
300 switch (OPCODE(h)) {
301 case OPCODE_AUB:
302 bias = 2;
303 break;
304 case OPCODE_NEW_AUB:
305 bias = 1;
306 break;
307 default:
308 parse_error(read, data, "unknown opcode %d\n", OPCODE(h));
309 return -1;
310 }
311
312 next = p + header_length + bias;
313 if ((h & 0xffff0000) == MAKE_HEADER(TYPE_AUB, OPCODE_AUB, SUBOPCODE_BLOCK)) {
314 assert(end - p >= 4);
315 next += p[4] / 4;
316 }
317
318 assert(next <= end);
319
320 switch (h & 0xffff0000) {
321 case MAKE_HEADER(TYPE_AUB, OPCODE_AUB, SUBOPCODE_HEADER):
322 if (!handle_trace_header(read, p))
323 return -1;
324 break;
325 case MAKE_HEADER(TYPE_AUB, OPCODE_AUB, SUBOPCODE_BLOCK):
326 if (!handle_trace_block(read, p))
327 return -1;
328 break;
329 case MAKE_HEADER(TYPE_AUB, OPCODE_AUB, SUBOPCODE_BMP):
330 break;
331 case MAKE_HEADER(TYPE_AUB, OPCODE_NEW_AUB, SUBOPCODE_VERSION):
332 if (!handle_memtrace_version(read, p))
333 return -1;
334 break;
335 case MAKE_HEADER(TYPE_AUB, OPCODE_NEW_AUB, SUBOPCODE_REG_WRITE):
336 handle_memtrace_reg_write(read, p);
337 break;
338 case MAKE_HEADER(TYPE_AUB, OPCODE_NEW_AUB, SUBOPCODE_MEM_WRITE):
339 handle_memtrace_mem_write(read, p);
340 break;
341 case MAKE_HEADER(TYPE_AUB, OPCODE_NEW_AUB, SUBOPCODE_MEM_POLL):
342 /* fprintf(outfile, "memory poll block (dwords %d):\n", h & 0xffff); */
343 break;
344 case MAKE_HEADER(TYPE_AUB, OPCODE_NEW_AUB, SUBOPCODE_REG_POLL):
345 break;
346 default:
347 parse_error(read, p,
348 "unknown block type=0x%x, opcode=0x%x, subopcode=0x%x (%08x)\n",
349 TYPE(h), OPCODE(h), SUBOPCODE(h), h);
350 return -1;
351 }
352
353 return (next - p) * sizeof(*p);
354 }