2 * Copyright © 2016-2018 Intel Corporation
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:
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
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
30 #include "common/gen_gem.h"
31 #include "util/macros.h"
34 #include "intel_aub.h"
36 #define TYPE(dw) (((dw) >> 29) & 7)
37 #define OPCODE(dw) (((dw) >> 23) & 0x3f)
38 #define SUBOPCODE(dw) (((dw) >> 16) & 0x7f)
40 #define MAKE_HEADER(type, opcode, subopcode) \
41 (((type) << 29) | ((opcode) << 23) | ((subopcode) << 16))
45 /* Classic AUB opcodes */
46 #define OPCODE_AUB 0x01
47 #define SUBOPCODE_HEADER 0x05
48 #define SUBOPCODE_BLOCK 0x41
49 #define SUBOPCODE_BMP 0x1e
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
59 #define MAKE_GEN(major, minor) (((major) << 8) | (minor))
62 parse_error(struct aub_read
*read
, const uint32_t *p
, const char *fmt
, ...)
71 vsnprintf(msg
, sizeof(msg
), fmt
, ap
);
72 read
->error(read
->user_data
, p
, msg
);
78 handle_trace_header(struct aub_read
*read
, const uint32_t *p
)
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.
84 const uint32_t *end
= p
+ (p
[0] & 0xffff) + 2;
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
)) {
91 "can't find device information: pci_id=0x%x\n", aub_pci_id
);
98 strncpy(app_name
, (const char *)&p
[2], 32);
102 read
->info(read
->user_data
, aub_pci_id
, app_name
);
108 handle_memtrace_version(struct aub_read
*read
, const uint32_t *p
)
110 int header_length
= p
[0] & 0xffff;
112 int app_name_len
= MIN2(4 * (header_length
+ 1 - 5), ARRAY_SIZE(app_name
) - 1);
116 strncpy(app_name
, (const char *)&p
[5], app_name_len
);
117 app_name
[app_name_len
] = 0;
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
);
126 read
->info(read
->user_data
, aub_pci_id
, app_name
+ pci_id_len
);
133 handle_trace_block(struct aub_read
*read
, const uint32_t *p
)
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) |
143 uint32_t size
= p
[4];
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
);
151 case AUB_TRACE_OP_COMMAND_WRITE
:
153 case AUB_TRACE_TYPE_RING_PRB0
:
154 engine
= I915_ENGINE_CLASS_RENDER
;
156 case AUB_TRACE_TYPE_RING_PRB1
:
157 engine
= I915_ENGINE_CLASS_VIDEO
;
159 case AUB_TRACE_TYPE_RING_PRB2
:
160 engine
= I915_ENGINE_CLASS_COPY
;
163 parse_error(read
, p
, "command write to unknown ring %d\n", type
);
167 if (read
->ring_write
)
168 read
->ring_write(read
->user_data
, engine
, data
, size
);
177 handle_memtrace_reg_write(struct aub_read
*read
, const uint32_t *p
)
179 uint32_t offset
= p
[1];
180 uint32_t value
= p
[5];
183 read
->reg_write(read
->user_data
, offset
, value
);
185 enum drm_i915_gem_engine_class engine
;
186 uint64_t context_descriptor
;
189 case 0x2230: /* render elsp */
190 read
->render_elsp
[read
->render_elsp_index
++] = value
;
191 if (read
->render_elsp_index
< 4)
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];
199 case 0x12230: /* video elsp */
200 read
->video_elsp
[read
->video_elsp_index
++] = value
;
201 if (read
->video_elsp_index
< 4)
204 read
->video_elsp_index
= 0;
205 engine
= I915_ENGINE_CLASS_VIDEO
;
206 context_descriptor
= (uint64_t)read
->video_elsp
[2] << 32 |
209 case 0x22230: /* blitter elsp */
210 read
->blitter_elsp
[read
->blitter_elsp_index
++] = value
;
211 if (read
->blitter_elsp_index
< 4)
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];
219 case 0x2510: /* render elsq0 lo */
220 read
->render_elsp
[3] = value
;
222 case 0x2514: /* render elsq0 hi */
223 read
->render_elsp
[2] = value
;
225 case 0x12510: /* video elsq0 lo */
226 read
->video_elsp
[3] = value
;
228 case 0x12514: /* video elsq0 hi */
229 read
->video_elsp
[2] = value
;
231 case 0x22510: /* blitter elsq0 lo */
232 read
->blitter_elsp
[3] = value
;
234 case 0x22514: /* blitter elsq0 hi */
235 read
->blitter_elsp
[2] = value
;
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];
242 case 0x12550: /* video_elsc */
243 engine
= I915_ENGINE_CLASS_VIDEO
;
244 context_descriptor
= (uint64_t)read
->video_elsp
[2] << 32 |
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];
256 if (read
->execlist_write
)
257 read
->execlist_write(read
->user_data
, engine
, context_descriptor
);
261 handle_memtrace_mem_write(struct aub_read
*read
, const uint32_t *p
)
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;
268 switch (address_space
) {
270 if (read
->ggtt_write
)
271 read
->ggtt_write(read
->user_data
, addr
, data
, size
);
274 if (read
->local_write
)
275 read
->local_write(read
->user_data
, addr
, data
, size
);
277 case 2: /* Physical */
278 if (read
->phys_write
)
279 read
->phys_write(read
->user_data
, addr
, data
, size
);
281 case 4: /* GGTT Entry */
282 if (read
->ggtt_entry_write
)
283 read
->ggtt_entry_write(read
->user_data
, addr
, data
, size
);
289 aub_read_command(struct aub_read
*read
, const void *data
, uint32_t data_len
)
291 const uint32_t *p
= data
, *next
;
292 MAYBE_UNUSED
const uint32_t *end
= data
+ data_len
;
293 uint32_t h
, header_length
, bias
;
295 assert(data_len
>= 4);
298 header_length
= h
& 0xffff;
308 parse_error(read
, data
, "unknown opcode %d\n", OPCODE(h
));
312 next
= p
+ header_length
+ bias
;
313 if ((h
& 0xffff0000) == MAKE_HEADER(TYPE_AUB
, OPCODE_AUB
, SUBOPCODE_BLOCK
)) {
314 assert(end
- p
>= 4);
320 switch (h
& 0xffff0000) {
321 case MAKE_HEADER(TYPE_AUB
, OPCODE_AUB
, SUBOPCODE_HEADER
):
322 if (!handle_trace_header(read
, p
))
325 case MAKE_HEADER(TYPE_AUB
, OPCODE_AUB
, SUBOPCODE_BLOCK
):
326 if (!handle_trace_block(read
, p
))
329 case MAKE_HEADER(TYPE_AUB
, OPCODE_AUB
, SUBOPCODE_BMP
):
331 case MAKE_HEADER(TYPE_AUB
, OPCODE_NEW_AUB
, SUBOPCODE_VERSION
):
332 if (!handle_memtrace_version(read
, p
))
335 case MAKE_HEADER(TYPE_AUB
, OPCODE_NEW_AUB
, SUBOPCODE_REG_WRITE
):
336 handle_memtrace_reg_write(read
, p
);
338 case MAKE_HEADER(TYPE_AUB
, OPCODE_NEW_AUB
, SUBOPCODE_MEM_WRITE
):
339 handle_memtrace_mem_write(read
, p
);
341 case MAKE_HEADER(TYPE_AUB
, OPCODE_NEW_AUB
, SUBOPCODE_MEM_POLL
):
342 /* fprintf(outfile, "memory poll block (dwords %d):\n", h & 0xffff); */
344 case MAKE_HEADER(TYPE_AUB
, OPCODE_NEW_AUB
, SUBOPCODE_REG_POLL
):
348 "unknown block type=0x%x, opcode=0x%x, subopcode=0x%x (%08x)\n",
349 TYPE(h
), OPCODE(h
), SUBOPCODE(h
), h
);
353 return (next
- p
) * sizeof(*p
);