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 "gen_context.h"
35 #include "intel_aub.h"
37 #define TYPE(dw) (((dw) >> 29) & 7)
38 #define OPCODE(dw) (((dw) >> 23) & 0x3f)
39 #define SUBOPCODE(dw) (((dw) >> 16) & 0x7f)
41 #define MAKE_HEADER(type, opcode, subopcode) \
42 ((((unsigned) (type)) << 29) | ((opcode) << 23) | ((subopcode) << 16))
46 /* Classic AUB opcodes */
47 #define OPCODE_AUB 0x01
48 #define SUBOPCODE_HEADER 0x05
49 #define SUBOPCODE_BLOCK 0x41
50 #define SUBOPCODE_BMP 0x1e
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
60 #define MAKE_GEN(major, minor) (((major) << 8) | (minor))
63 parse_error(struct aub_read
*read
, const uint32_t *p
, const char *fmt
, ...)
72 vsnprintf(msg
, sizeof(msg
), fmt
, ap
);
73 read
->error(read
->user_data
, p
, msg
);
79 handle_trace_header(struct aub_read
*read
, const uint32_t *p
)
81 /* The intel_aubdump tool from IGT is kind enough to put a PCI-ID= tag in
82 * the AUB header comment. If the user hasn't specified a hardware
83 * generation, try to use the one from the AUB file.
85 const uint32_t *end
= p
+ (p
[0] & 0xffff) + 2;
88 if (end
> &p
[12] && p
[12] > 0) {
89 if (sscanf((char *)&p
[13], "PCI-ID=%i", &aub_pci_id
) > 0) {
90 if (!gen_get_device_info_from_pci_id(aub_pci_id
, &read
->devinfo
)) {
92 "can't find device information: pci_id=0x%x\n", aub_pci_id
);
99 strncpy(app_name
, (const char *)&p
[2], 32);
103 read
->info(read
->user_data
, aub_pci_id
, app_name
);
109 handle_memtrace_version(struct aub_read
*read
, const uint32_t *p
)
111 int header_length
= p
[0] & 0xffff;
113 int app_name_len
= MIN2(4 * (header_length
+ 1 - 5), ARRAY_SIZE(app_name
) - 1);
117 strncpy(app_name
, (const char *)&p
[5], app_name_len
);
118 app_name
[app_name_len
] = 0;
120 if (sscanf(app_name
, "PCI-ID=%i %n", &aub_pci_id
, &pci_id_len
) > 0) {
121 if (!gen_get_device_info_from_pci_id(aub_pci_id
, &read
->devinfo
)) {
122 parse_error(read
, p
, "can't find device information: pci_id=0x%x\n", aub_pci_id
);
127 read
->info(read
->user_data
, aub_pci_id
, app_name
+ pci_id_len
);
134 handle_trace_block(struct aub_read
*read
, const uint32_t *p
)
136 int operation
= p
[1] & AUB_TRACE_OPERATION_MASK
;
137 int type
= p
[1] & AUB_TRACE_TYPE_MASK
;
138 int address_space
= p
[1] & AUB_TRACE_ADDRESS_SPACE_MASK
;
139 int header_length
= p
[0] & 0xffff;
140 enum drm_i915_gem_engine_class engine
= I915_ENGINE_CLASS_RENDER
;
141 const void *data
= p
+ header_length
+ 2;
142 uint64_t address
= gen_48b_address((read
->devinfo
.gen
>= 8 ? ((uint64_t) p
[5] << 32) : 0) |
144 uint32_t size
= p
[4];
147 case AUB_TRACE_OP_DATA_WRITE
:
148 if (address_space
== AUB_TRACE_MEMTYPE_GTT
) {
149 if (read
->local_write
)
150 read
->local_write(read
->user_data
, address
, data
, size
);
152 case AUB_TRACE_OP_COMMAND_WRITE
:
154 case AUB_TRACE_TYPE_RING_PRB0
:
155 engine
= I915_ENGINE_CLASS_RENDER
;
157 case AUB_TRACE_TYPE_RING_PRB1
:
158 engine
= I915_ENGINE_CLASS_VIDEO
;
160 case AUB_TRACE_TYPE_RING_PRB2
:
161 engine
= I915_ENGINE_CLASS_COPY
;
164 parse_error(read
, p
, "command write to unknown ring %d\n", type
);
168 if (read
->ring_write
)
169 read
->ring_write(read
->user_data
, engine
, data
, size
);
178 handle_memtrace_reg_write(struct aub_read
*read
, const uint32_t *p
)
180 uint32_t offset
= p
[1];
181 uint32_t value
= p
[5];
184 read
->reg_write(read
->user_data
, offset
, value
);
186 enum drm_i915_gem_engine_class engine
;
187 uint64_t context_descriptor
;
190 case EXECLIST_SUBMITPORT_RCSUNIT
: /* render elsp */
191 read
->render_elsp
[read
->render_elsp_index
++] = value
;
192 if (read
->render_elsp_index
< 4)
195 read
->render_elsp_index
= 0;
196 engine
= I915_ENGINE_CLASS_RENDER
;
197 context_descriptor
= (uint64_t)read
->render_elsp
[2] << 32 |
198 read
->render_elsp
[3];
200 case EXECLIST_SUBMITPORT_VCSUNIT0
: /* video elsp */
201 read
->video_elsp
[read
->video_elsp_index
++] = value
;
202 if (read
->video_elsp_index
< 4)
205 read
->video_elsp_index
= 0;
206 engine
= I915_ENGINE_CLASS_VIDEO
;
207 context_descriptor
= (uint64_t)read
->video_elsp
[2] << 32 |
210 case EXECLIST_SUBMITPORT_BCSUNIT
: /* blitter elsp */
211 read
->blitter_elsp
[read
->blitter_elsp_index
++] = value
;
212 if (read
->blitter_elsp_index
< 4)
215 read
->blitter_elsp_index
= 0;
216 engine
= I915_ENGINE_CLASS_COPY
;
217 context_descriptor
= (uint64_t)read
->blitter_elsp
[2] << 32 |
218 read
->blitter_elsp
[3];
220 case EXECLIST_SQ_CONTENTS0_RCSUNIT
: /* render elsq0 lo */
221 read
->render_elsp
[3] = value
;
223 case (EXECLIST_SQ_CONTENTS0_RCSUNIT
+ 4): /* render elsq0 hi */
224 read
->render_elsp
[2] = value
;
226 case EXECLIST_SQ_CONTENTS0_VCSUNIT0
: /* video elsq0 lo */
227 read
->video_elsp
[3] = value
;
229 case EXECLIST_SQ_CONTENTS0_VCSUNIT0
+ 4: /* video elsq0 hi */
230 read
->video_elsp
[2] = value
;
232 case EXECLIST_SQ_CONTENTS0_BCSUNIT
: /* blitter elsq0 lo */
233 read
->blitter_elsp
[3] = value
;
235 case (EXECLIST_SQ_CONTENTS0_BCSUNIT
+ 4): /* blitter elsq0 hi */
236 read
->blitter_elsp
[2] = value
;
238 case EXECLIST_CONTROL_RCSUNIT
: /* render elsc */
239 engine
= I915_ENGINE_CLASS_RENDER
;
240 context_descriptor
= (uint64_t)read
->render_elsp
[2] << 32 |
241 read
->render_elsp
[3];
243 case EXECLIST_CONTROL_VCSUNIT0
: /* video_elsc */
244 engine
= I915_ENGINE_CLASS_VIDEO
;
245 context_descriptor
= (uint64_t)read
->video_elsp
[2] << 32 |
248 case EXECLIST_CONTROL_BCSUNIT
: /* blitter elsc */
249 engine
= I915_ENGINE_CLASS_COPY
;
250 context_descriptor
= (uint64_t)read
->blitter_elsp
[2] << 32 |
251 read
->blitter_elsp
[3];
257 if (read
->execlist_write
)
258 read
->execlist_write(read
->user_data
, engine
, context_descriptor
);
262 handle_memtrace_mem_write(struct aub_read
*read
, const uint32_t *p
)
264 const void *data
= p
+ 5;
265 uint64_t addr
= gen_48b_address(*(uint64_t*)&p
[1]);
266 uint32_t size
= p
[4];
267 uint32_t address_space
= p
[3] >> 28;
269 switch (address_space
) {
271 if (read
->ggtt_write
)
272 read
->ggtt_write(read
->user_data
, addr
, data
, size
);
275 if (read
->local_write
)
276 read
->local_write(read
->user_data
, addr
, data
, size
);
278 case 2: /* Physical */
279 if (read
->phys_write
)
280 read
->phys_write(read
->user_data
, addr
, data
, size
);
282 case 4: /* GGTT Entry */
283 if (read
->ggtt_entry_write
)
284 read
->ggtt_entry_write(read
->user_data
, addr
, data
, size
);
290 aub_read_command(struct aub_read
*read
, const void *data
, uint32_t data_len
)
292 const uint32_t *p
= data
, *next
;
293 ASSERTED
const uint32_t *end
= data
+ data_len
;
294 uint32_t h
, header_length
, bias
;
296 assert(data_len
>= 4);
299 header_length
= h
& 0xffff;
309 parse_error(read
, data
, "unknown opcode %d\n", OPCODE(h
));
313 next
= p
+ header_length
+ bias
;
314 if ((h
& 0xffff0000) == MAKE_HEADER(TYPE_AUB
, OPCODE_AUB
, SUBOPCODE_BLOCK
)) {
315 assert(end
- p
>= 4);
321 switch (h
& 0xffff0000) {
322 case MAKE_HEADER(TYPE_AUB
, OPCODE_AUB
, SUBOPCODE_HEADER
):
323 if (!handle_trace_header(read
, p
))
326 case MAKE_HEADER(TYPE_AUB
, OPCODE_AUB
, SUBOPCODE_BLOCK
):
327 if (!handle_trace_block(read
, p
))
330 case MAKE_HEADER(TYPE_AUB
, OPCODE_AUB
, SUBOPCODE_BMP
):
332 case MAKE_HEADER(TYPE_AUB
, OPCODE_NEW_AUB
, SUBOPCODE_VERSION
):
333 if (!handle_memtrace_version(read
, p
))
336 case MAKE_HEADER(TYPE_AUB
, OPCODE_NEW_AUB
, SUBOPCODE_REG_WRITE
):
337 handle_memtrace_reg_write(read
, p
);
339 case MAKE_HEADER(TYPE_AUB
, OPCODE_NEW_AUB
, SUBOPCODE_MEM_WRITE
):
340 handle_memtrace_mem_write(read
, p
);
342 case MAKE_HEADER(TYPE_AUB
, OPCODE_NEW_AUB
, SUBOPCODE_MEM_POLL
):
343 /* fprintf(outfile, "memory poll block (dwords %d):\n", h & 0xffff); */
345 case MAKE_HEADER(TYPE_AUB
, OPCODE_NEW_AUB
, SUBOPCODE_REG_POLL
):
349 "unknown block type=0x%x, opcode=0x%x, subopcode=0x%x (%08x)\n",
350 TYPE(h
), OPCODE(h
), SUBOPCODE(h
), h
);
354 return (next
- p
) * sizeof(*p
);