Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/intel/tools/aub_read.c
4547 views
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/intel_gem.h"
31
#include "util/macros.h"
32
33
#include "aub_read.h"
34
#include "intel_context.h"
35
#include "intel_aub.h"
36
37
#define TYPE(dw) (((dw) >> 29) & 7)
38
#define OPCODE(dw) (((dw) >> 23) & 0x3f)
39
#define SUBOPCODE(dw) (((dw) >> 16) & 0x7f)
40
41
#define MAKE_HEADER(type, opcode, subopcode) \
42
((((unsigned) (type)) << 29) | ((opcode) << 23) | ((subopcode) << 16))
43
44
#define TYPE_AUB 0x7
45
46
/* Classic AUB opcodes */
47
#define OPCODE_AUB 0x01
48
#define SUBOPCODE_HEADER 0x05
49
#define SUBOPCODE_BLOCK 0x41
50
#define SUBOPCODE_BMP 0x1e
51
52
/* Newer version AUB opcode */
53
#define OPCODE_NEW_AUB 0x2e
54
#define SUBOPCODE_REG_POLL 0x02
55
#define SUBOPCODE_REG_WRITE 0x03
56
#define SUBOPCODE_MEM_POLL 0x05
57
#define SUBOPCODE_MEM_WRITE 0x06
58
#define SUBOPCODE_VERSION 0x0e
59
60
static PRINTFLIKE(3, 4) void
61
parse_error(struct aub_read *read, const uint32_t *p, const char *fmt, ...)
62
{
63
if (!read->error)
64
return;
65
66
va_list ap;
67
va_start(ap, fmt);
68
69
char msg[80];
70
vsnprintf(msg, sizeof(msg), fmt, ap);
71
read->error(read->user_data, p, msg);
72
73
va_end(ap);
74
}
75
76
static bool
77
handle_trace_header(struct aub_read *read, const uint32_t *p)
78
{
79
/* The intel_aubdump tool from IGT is kind enough to put a PCI-ID= tag in
80
* the AUB header comment. If the user hasn't specified a hardware
81
* generation, try to use the one from the AUB file.
82
*/
83
const uint32_t *end = p + (p[0] & 0xffff) + 2;
84
int aub_pci_id = 0;
85
86
if (end > &p[12] && p[12] > 0) {
87
if (sscanf((char *)&p[13], "PCI-ID=%i", &aub_pci_id) > 0) {
88
if (!intel_get_device_info_from_pci_id(aub_pci_id, &read->devinfo)) {
89
parse_error(read, p,
90
"can't find device information: pci_id=0x%x\n", aub_pci_id);
91
return false;
92
}
93
}
94
}
95
96
char app_name[33];
97
strncpy(app_name, (const char *)&p[2], 32);
98
app_name[32] = 0;
99
100
if (read->info)
101
read->info(read->user_data, aub_pci_id, app_name);
102
103
return true;
104
}
105
106
static bool
107
handle_memtrace_version(struct aub_read *read, const uint32_t *p)
108
{
109
int header_length = p[0] & 0xffff;
110
char app_name[64];
111
int app_name_len = MIN2(4 * (header_length + 1 - 5), ARRAY_SIZE(app_name) - 1);
112
int pci_id_len = 0;
113
int aub_pci_id = 0;
114
115
strncpy(app_name, (const char *)&p[5], app_name_len);
116
app_name[app_name_len] = 0;
117
118
if (sscanf(app_name, "PCI-ID=%i %n", &aub_pci_id, &pci_id_len) > 0) {
119
if (!intel_get_device_info_from_pci_id(aub_pci_id, &read->devinfo)) {
120
parse_error(read, p, "can't find device information: pci_id=0x%x\n", aub_pci_id);
121
return false;
122
}
123
124
if (read->info)
125
read->info(read->user_data, aub_pci_id, app_name + pci_id_len);
126
}
127
128
return true;
129
}
130
131
static bool
132
handle_trace_block(struct aub_read *read, const uint32_t *p)
133
{
134
int operation = p[1] & AUB_TRACE_OPERATION_MASK;
135
int type = p[1] & AUB_TRACE_TYPE_MASK;
136
int address_space = p[1] & AUB_TRACE_ADDRESS_SPACE_MASK;
137
int header_length = p[0] & 0xffff;
138
enum drm_i915_gem_engine_class engine = I915_ENGINE_CLASS_RENDER;
139
const void *data = p + header_length + 2;
140
uint64_t address = intel_48b_address((read->devinfo.ver >= 8 ? ((uint64_t) p[5] << 32) : 0) |
141
((uint64_t) p[3]));
142
uint32_t size = p[4];
143
144
switch (operation) {
145
case AUB_TRACE_OP_DATA_WRITE:
146
if (address_space == AUB_TRACE_MEMTYPE_GTT) {
147
if (read->local_write)
148
read->local_write(read->user_data, address, data, size);
149
break;
150
case AUB_TRACE_OP_COMMAND_WRITE:
151
switch (type) {
152
case AUB_TRACE_TYPE_RING_PRB0:
153
engine = I915_ENGINE_CLASS_RENDER;
154
break;
155
case AUB_TRACE_TYPE_RING_PRB1:
156
engine = I915_ENGINE_CLASS_VIDEO;
157
break;
158
case AUB_TRACE_TYPE_RING_PRB2:
159
engine = I915_ENGINE_CLASS_COPY;
160
break;
161
default:
162
parse_error(read, p, "command write to unknown ring %d\n", type);
163
return false;
164
}
165
166
if (read->ring_write)
167
read->ring_write(read->user_data, engine, data, size);
168
break;
169
}
170
}
171
172
return true;
173
}
174
175
static void
176
handle_memtrace_reg_write(struct aub_read *read, const uint32_t *p)
177
{
178
uint32_t offset = p[1];
179
uint32_t value = p[5];
180
181
if (read->reg_write)
182
read->reg_write(read->user_data, offset, value);
183
184
enum drm_i915_gem_engine_class engine;
185
uint64_t context_descriptor;
186
187
switch (offset) {
188
case EXECLIST_SUBMITPORT_RCSUNIT: /* render elsp */
189
read->render_elsp[read->render_elsp_index++] = value;
190
if (read->render_elsp_index < 4)
191
return;
192
193
read->render_elsp_index = 0;
194
engine = I915_ENGINE_CLASS_RENDER;
195
context_descriptor = (uint64_t)read->render_elsp[2] << 32 |
196
read->render_elsp[3];
197
break;
198
case EXECLIST_SUBMITPORT_VCSUNIT0: /* video elsp */
199
read->video_elsp[read->video_elsp_index++] = value;
200
if (read->video_elsp_index < 4)
201
return;
202
203
read->video_elsp_index = 0;
204
engine = I915_ENGINE_CLASS_VIDEO;
205
context_descriptor = (uint64_t)read->video_elsp[2] << 32 |
206
read->video_elsp[3];
207
break;
208
case EXECLIST_SUBMITPORT_BCSUNIT: /* blitter elsp */
209
read->blitter_elsp[read->blitter_elsp_index++] = value;
210
if (read->blitter_elsp_index < 4)
211
return;
212
213
read->blitter_elsp_index = 0;
214
engine = I915_ENGINE_CLASS_COPY;
215
context_descriptor = (uint64_t)read->blitter_elsp[2] << 32 |
216
read->blitter_elsp[3];
217
break;
218
case EXECLIST_SQ_CONTENTS0_RCSUNIT: /* render elsq0 lo */
219
read->render_elsp[3] = value;
220
return;
221
case (EXECLIST_SQ_CONTENTS0_RCSUNIT + 4): /* render elsq0 hi */
222
read->render_elsp[2] = value;
223
return;
224
case EXECLIST_SQ_CONTENTS0_VCSUNIT0: /* video elsq0 lo */
225
read->video_elsp[3] = value;
226
return;
227
case EXECLIST_SQ_CONTENTS0_VCSUNIT0 + 4: /* video elsq0 hi */
228
read->video_elsp[2] = value;
229
return;
230
case EXECLIST_SQ_CONTENTS0_BCSUNIT: /* blitter elsq0 lo */
231
read->blitter_elsp[3] = value;
232
return;
233
case (EXECLIST_SQ_CONTENTS0_BCSUNIT + 4): /* blitter elsq0 hi */
234
read->blitter_elsp[2] = value;
235
return;
236
case EXECLIST_CONTROL_RCSUNIT: /* render elsc */
237
engine = I915_ENGINE_CLASS_RENDER;
238
context_descriptor = (uint64_t)read->render_elsp[2] << 32 |
239
read->render_elsp[3];
240
break;
241
case EXECLIST_CONTROL_VCSUNIT0: /* video_elsc */
242
engine = I915_ENGINE_CLASS_VIDEO;
243
context_descriptor = (uint64_t)read->video_elsp[2] << 32 |
244
read->video_elsp[3];
245
break;
246
case EXECLIST_CONTROL_BCSUNIT: /* blitter elsc */
247
engine = I915_ENGINE_CLASS_COPY;
248
context_descriptor = (uint64_t)read->blitter_elsp[2] << 32 |
249
read->blitter_elsp[3];
250
break;
251
default:
252
return;
253
}
254
255
if (read->execlist_write)
256
read->execlist_write(read->user_data, engine, context_descriptor);
257
}
258
259
static void
260
handle_memtrace_mem_write(struct aub_read *read, const uint32_t *p)
261
{
262
const void *data = p + 5;
263
uint64_t addr = intel_48b_address(*(uint64_t*)&p[1]);
264
uint32_t size = p[4];
265
uint32_t address_space = p[3] >> 28;
266
267
switch (address_space) {
268
case 0: /* GGTT */
269
if (read->ggtt_write)
270
read->ggtt_write(read->user_data, addr, data, size);
271
break;
272
case 1: /* Local */
273
if (read->local_write)
274
read->local_write(read->user_data, addr, data, size);
275
break;
276
case 2: /* Physical */
277
if (read->phys_write)
278
read->phys_write(read->user_data, addr, data, size);
279
break;
280
case 4: /* GGTT Entry */
281
if (read->ggtt_entry_write)
282
read->ggtt_entry_write(read->user_data, addr, data, size);
283
break;
284
}
285
}
286
287
int
288
aub_read_command(struct aub_read *read, const void *data, uint32_t data_len)
289
{
290
const uint32_t *p = data, *next;
291
ASSERTED const uint32_t *end = data + data_len;
292
uint32_t h, header_length, bias;
293
294
assert(data_len >= 4);
295
296
h = *p;
297
header_length = h & 0xffff;
298
299
switch (OPCODE(h)) {
300
case OPCODE_AUB:
301
bias = 2;
302
break;
303
case OPCODE_NEW_AUB:
304
bias = 1;
305
break;
306
default:
307
parse_error(read, data, "unknown opcode %d\n", OPCODE(h));
308
return -1;
309
}
310
311
next = p + header_length + bias;
312
if ((h & 0xffff0000) == MAKE_HEADER(TYPE_AUB, OPCODE_AUB, SUBOPCODE_BLOCK)) {
313
assert(end - p >= 4);
314
next += p[4] / 4;
315
}
316
317
if (next > end) {
318
parse_error(read, data,
319
"input ends unexpectedly (command length: %zu, remaining bytes: %zu)\n",
320
(uintptr_t)next - (uintptr_t)data,
321
(uintptr_t)end - (uintptr_t)data);
322
return -1;
323
}
324
325
switch (h & 0xffff0000) {
326
case MAKE_HEADER(TYPE_AUB, OPCODE_AUB, SUBOPCODE_HEADER):
327
if (!handle_trace_header(read, p))
328
return -1;
329
break;
330
case MAKE_HEADER(TYPE_AUB, OPCODE_AUB, SUBOPCODE_BLOCK):
331
if (!handle_trace_block(read, p))
332
return -1;
333
break;
334
case MAKE_HEADER(TYPE_AUB, OPCODE_AUB, SUBOPCODE_BMP):
335
break;
336
case MAKE_HEADER(TYPE_AUB, OPCODE_NEW_AUB, SUBOPCODE_VERSION):
337
if (!handle_memtrace_version(read, p))
338
return -1;
339
break;
340
case MAKE_HEADER(TYPE_AUB, OPCODE_NEW_AUB, SUBOPCODE_REG_WRITE):
341
handle_memtrace_reg_write(read, p);
342
break;
343
case MAKE_HEADER(TYPE_AUB, OPCODE_NEW_AUB, SUBOPCODE_MEM_WRITE):
344
handle_memtrace_mem_write(read, p);
345
break;
346
case MAKE_HEADER(TYPE_AUB, OPCODE_NEW_AUB, SUBOPCODE_MEM_POLL):
347
/* fprintf(outfile, "memory poll block (dwords %d):\n", h & 0xffff); */
348
break;
349
case MAKE_HEADER(TYPE_AUB, OPCODE_NEW_AUB, SUBOPCODE_REG_POLL):
350
break;
351
default:
352
parse_error(read, p,
353
"unknown block type=0x%x, opcode=0x%x, subopcode=0x%x (%08x)\n",
354
TYPE(h), OPCODE(h), SUBOPCODE(h), h);
355
return -1;
356
}
357
358
return (next - p) * sizeof(*p);
359
}
360
361