diff options
author | Lionel Landwerlin <[email protected]> | 2018-07-28 19:13:04 +0100 |
---|---|---|
committer | Lionel Landwerlin <[email protected]> | 2018-08-22 17:49:36 +0100 |
commit | 4616639b49b4bbc91e503c1c27632dccc1c2b5be (patch) | |
tree | d3197a080693a1f0a04dd4add91a5607636a4e42 /src/intel | |
parent | e15686567c9481de86dc5088b41e480085d4fe0c (diff) |
intel: tools: split aub parsing from aubinator
v2: add parsing error callback (Lionel)
Signed-off-by: Lionel Landwerlin <[email protected]>
Reviewed-by: Rafael Antognolli <[email protected]> (v1)
Diffstat (limited to 'src/intel')
-rw-r--r-- | src/intel/Makefile.tools.am | 2 | ||||
-rw-r--r-- | src/intel/tools/aub_read.c | 333 | ||||
-rw-r--r-- | src/intel/tools/aub_read.h | 77 | ||||
-rw-r--r-- | src/intel/tools/aubinator.c | 325 | ||||
-rw-r--r-- | src/intel/tools/meson.build | 2 |
5 files changed, 460 insertions, 279 deletions
diff --git a/src/intel/Makefile.tools.am b/src/intel/Makefile.tools.am index 00624084e6f..9dc89ad6f6e 100644 --- a/src/intel/Makefile.tools.am +++ b/src/intel/Makefile.tools.am @@ -26,6 +26,8 @@ noinst_PROGRAMS += \ tools_aubinator_SOURCES = \ + tools/aub_read.c \ + tools/aub_read.h \ tools/aubinator.c \ tools/intel_aub.h diff --git a/src/intel/tools/aub_read.c b/src/intel/tools/aub_read.c new file mode 100644 index 00000000000..5b704e8f78b --- /dev/null +++ b/src/intel/tools/aub_read.c @@ -0,0 +1,333 @@ +/* + * Copyright © 2016-2018 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdarg.h> + +#include "common/gen_gem.h" +#include "util/macros.h" + +#include "aub_read.h" +#include "intel_aub.h" + +#define TYPE(dw) (((dw) >> 29) & 7) +#define OPCODE(dw) (((dw) >> 23) & 0x3f) +#define SUBOPCODE(dw) (((dw) >> 16) & 0x7f) + +#define MAKE_HEADER(type, opcode, subopcode) \ + (((type) << 29) | ((opcode) << 23) | ((subopcode) << 16)) + +#define TYPE_AUB 0x7 + +/* Classic AUB opcodes */ +#define OPCODE_AUB 0x01 +#define SUBOPCODE_HEADER 0x05 +#define SUBOPCODE_BLOCK 0x41 +#define SUBOPCODE_BMP 0x1e + +/* Newer version AUB opcode */ +#define OPCODE_NEW_AUB 0x2e +#define SUBOPCODE_REG_POLL 0x02 +#define SUBOPCODE_REG_WRITE 0x03 +#define SUBOPCODE_MEM_POLL 0x05 +#define SUBOPCODE_MEM_WRITE 0x06 +#define SUBOPCODE_VERSION 0x0e + +#define MAKE_GEN(major, minor) (((major) << 8) | (minor)) + +static void +parse_error(struct aub_read *read, const uint32_t *p, const char *fmt, ...) +{ + if (!read->error) + return; + + va_list ap; + va_start(ap, fmt); + + char msg[80]; + vsnprintf(msg, sizeof(msg), fmt, ap); + read->error(read->user_data, p, msg); + + va_end(ap); +} + +static bool +handle_trace_header(struct aub_read *read, const uint32_t *p) +{ + /* The intel_aubdump tool from IGT is kind enough to put a PCI-ID= tag in + * the AUB header comment. If the user hasn't specified a hardware + * generation, try to use the one from the AUB file. + */ + const uint32_t *end = p + (p[0] & 0xffff) + 2; + int aub_pci_id = 0; + + if (end > &p[12] && p[12] > 0) { + if (sscanf((char *)&p[13], "PCI-ID=%i", &aub_pci_id) > 0) { + if (!gen_get_device_info(aub_pci_id, &read->devinfo)) { + parse_error(read, p, + "can't find device information: pci_id=0x%x\n", aub_pci_id); + return false; + } + } + } + + char app_name[33]; + strncpy(app_name, (const char *)&p[2], 32); + app_name[32] = 0; + + if (read->info) + read->info(read->user_data, aub_pci_id, app_name); + + return true; +} + +static bool +handle_memtrace_version(struct aub_read *read, const uint32_t *p) +{ + int header_length = p[0] & 0xffff; + char app_name[64]; + int app_name_len = MIN2(4 * (header_length + 1 - 5), ARRAY_SIZE(app_name) - 1); + int pci_id_len = 0; + int aub_pci_id = 0; + + strncpy(app_name, (const char *)&p[5], app_name_len); + app_name[app_name_len] = 0; + + if (sscanf(app_name, "PCI-ID=%i %n", &aub_pci_id, &pci_id_len) > 0) { + if (!gen_get_device_info(aub_pci_id, &read->devinfo)) { + parse_error(read, p, "can't find device information: pci_id=0x%x\n", aub_pci_id); + return false; + } + + if (read->info) + read->info(read->user_data, aub_pci_id, app_name + pci_id_len); + } + + return true; +} + +static bool +handle_trace_block(struct aub_read *read, const uint32_t *p) +{ + int operation = p[1] & AUB_TRACE_OPERATION_MASK; + int type = p[1] & AUB_TRACE_TYPE_MASK; + int address_space = p[1] & AUB_TRACE_ADDRESS_SPACE_MASK; + int header_length = p[0] & 0xffff; + int engine = GEN_ENGINE_RENDER; + const void *data = p + header_length + 2; + uint64_t address = gen_48b_address((read->devinfo.gen >= 8 ? ((uint64_t) p[5] << 32) : 0) | + ((uint64_t) p[3])); + uint32_t size = p[4]; + + switch (operation) { + case AUB_TRACE_OP_DATA_WRITE: + if (address_space == AUB_TRACE_MEMTYPE_GTT) { + if (read->local_write) + read->local_write(read->user_data, address, data, size); + break; + case AUB_TRACE_OP_COMMAND_WRITE: + switch (type) { + case AUB_TRACE_TYPE_RING_PRB0: + engine = GEN_ENGINE_RENDER; + break; + case AUB_TRACE_TYPE_RING_PRB2: + engine = GEN_ENGINE_BLITTER; + break; + default: + parse_error(read, p, "command write to unknown ring %d\n", type); + return false; + } + + if (read->ring_write) + read->ring_write(read->user_data, engine, data, size); + break; + } + } + + return true; +} + +static void +handle_memtrace_reg_write(struct aub_read *read, const uint32_t *p) +{ + uint32_t offset = p[1]; + uint32_t value = p[5]; + + if (read->reg_write) + read->reg_write(read->user_data, offset, value); + + int engine; + uint64_t context_descriptor; + + switch (offset) { + case 0x2230: /* render elsp */ + read->render_elsp[read->render_elsp_index++] = value; + if (read->render_elsp_index < 4) + return; + + read->render_elsp_index = 0; + engine = GEN_ENGINE_RENDER; + context_descriptor = (uint64_t)read->render_elsp[2] << 32 | + read->render_elsp[3]; + break; + case 0x22230: /* blitter elsp */ + read->blitter_elsp[read->blitter_elsp_index++] = value; + if (read->blitter_elsp_index < 4) + return; + + read->blitter_elsp_index = 0; + engine = GEN_ENGINE_BLITTER; + context_descriptor = (uint64_t)read->blitter_elsp[2] << 32 | + read->blitter_elsp[3]; + break; + case 0x2510: /* render elsq0 lo */ + read->render_elsp[3] = value; + return; + break; + case 0x2514: /* render elsq0 hi */ + read->render_elsp[2] = value; + return; + break; + case 0x22510: /* blitter elsq0 lo */ + read->blitter_elsp[3] = value; + return; + break; + case 0x22514: /* blitter elsq0 hi */ + read->blitter_elsp[2] = value; + return; + break; + case 0x2550: /* render elsc */ + engine = GEN_ENGINE_RENDER; + context_descriptor = (uint64_t)read->render_elsp[2] << 32 | + read->render_elsp[3]; + break; + case 0x22550: /* blitter elsc */ + engine = GEN_ENGINE_BLITTER; + context_descriptor = (uint64_t)read->blitter_elsp[2] << 32 | + read->blitter_elsp[3]; + break; + default: + return; + } + + if (read->execlist_write) + read->execlist_write(read->user_data, engine, context_descriptor); +} + +static void +handle_memtrace_mem_write(struct aub_read *read, const uint32_t *p) +{ + const void *data = p + 5; + uint64_t addr = gen_48b_address(*(uint64_t*)&p[1]); + uint32_t size = p[4]; + uint32_t address_space = p[3] >> 28; + + switch (address_space) { + case 0: /* GGTT */ + if (read->ggtt_write) + read->ggtt_write(read->user_data, addr, data, size); + break; + case 1: /* Local */ + if (read->local_write) + read->local_write(read->user_data, addr, data, size); + break; + case 2: /* Physical */ + if (read->phys_write) + read->phys_write(read->user_data, addr, data, size); + break; + case 4: /* GGTT Entry */ + if (read->ggtt_entry_write) + read->ggtt_entry_write(read->user_data, addr, data, size); + break; + } +} + +int +aub_read_command(struct aub_read *read, const void *data, uint32_t data_len) +{ + const uint32_t *p = data, *end = data + data_len, *next; + uint32_t h, header_length, bias; + + assert(data_len >= 4); + + h = *p; + header_length = h & 0xffff; + + switch (OPCODE(h)) { + case OPCODE_AUB: + bias = 2; + break; + case OPCODE_NEW_AUB: + bias = 1; + break; + default: + parse_error(read, data, "unknown opcode %d\n", OPCODE(h)); + return -1; + } + + next = p + header_length + bias; + if ((h & 0xffff0000) == MAKE_HEADER(TYPE_AUB, OPCODE_AUB, SUBOPCODE_BLOCK)) { + assert(end - p >= 4); + next += p[4] / 4; + } + + assert(next <= end); + + switch (h & 0xffff0000) { + case MAKE_HEADER(TYPE_AUB, OPCODE_AUB, SUBOPCODE_HEADER): + if (!handle_trace_header(read, p)) + return -1; + break; + case MAKE_HEADER(TYPE_AUB, OPCODE_AUB, SUBOPCODE_BLOCK): + if (!handle_trace_block(read, p)) + return -1; + break; + case MAKE_HEADER(TYPE_AUB, OPCODE_AUB, SUBOPCODE_BMP): + break; + case MAKE_HEADER(TYPE_AUB, OPCODE_NEW_AUB, SUBOPCODE_VERSION): + if (!handle_memtrace_version(read, p)) + return -1; + break; + case MAKE_HEADER(TYPE_AUB, OPCODE_NEW_AUB, SUBOPCODE_REG_WRITE): + handle_memtrace_reg_write(read, p); + break; + case MAKE_HEADER(TYPE_AUB, OPCODE_NEW_AUB, SUBOPCODE_MEM_WRITE): + handle_memtrace_mem_write(read, p); + break; + case MAKE_HEADER(TYPE_AUB, OPCODE_NEW_AUB, SUBOPCODE_MEM_POLL): + /* fprintf(outfile, "memory poll block (dwords %d):\n", h & 0xffff); */ + break; + case MAKE_HEADER(TYPE_AUB, OPCODE_NEW_AUB, SUBOPCODE_REG_POLL): + break; + default: + parse_error(read, p, + "unknown block type=0x%x, opcode=0x%x, subopcode=0x%x (%08x)\n", + TYPE(h), OPCODE(h), SUBOPCODE(h), h); + return -1; + } + + return (next - p) * sizeof(*p); +} diff --git a/src/intel/tools/aub_read.h b/src/intel/tools/aub_read.h new file mode 100644 index 00000000000..3502c0887bb --- /dev/null +++ b/src/intel/tools/aub_read.h @@ -0,0 +1,77 @@ +/* + * Copyright © 2018 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + */ + +#ifndef INTEL_AUB_READ +#define INTEL_AUB_READ + +#include <stdint.h> + +#include "dev/gen_device_info.h" + +#ifdef __cplusplus +extern "C" { +#endif + +enum gen_engine { + GEN_ENGINE_RENDER = 1, + GEN_ENGINE_BLITTER = 2, +}; + +struct aub_read { + /* Caller's data */ + void *user_data; + + void (*error)(void *user_data, const void *aub_data, const char *msg); + + void (*info)(void *user_data, int pci_id, const char *app_name); + + void (*local_write)(void *user_data, uint64_t phys_addr, const void *data, uint32_t data_len); + void (*phys_write)(void *user_data, uint64_t phys_addr, const void *data, uint32_t data_len); + void (*ggtt_write)(void *user_data, uint64_t phys_addr, const void *data, uint32_t data_len); + void (*ggtt_entry_write)(void *user_data, uint64_t phys_addr, + const void *data, uint32_t data_len); + + void (*reg_write)(void *user_data, uint32_t reg_offset, uint32_t reg_value); + + void (*ring_write)(void *user_data, enum gen_engine engine, + const void *data, uint32_t data_len); + void (*execlist_write)(void *user_data, enum gen_engine engine, + uint64_t context_descriptor); + + /* Reader's data */ + uint32_t render_elsp[4]; + int render_elsp_index; + uint32_t blitter_elsp[4]; + int blitter_elsp_index; + + struct gen_device_info devinfo; +}; + +int aub_read_command(struct aub_read *read, const void *data, uint32_t data_len); + +#ifdef __cplusplus +} +#endif + +#endif /* INTEL_AUB_READ */ diff --git a/src/intel/tools/aubinator.c b/src/intel/tools/aubinator.c index 66a7db1043b..27ce0cef4dc 100644 --- a/src/intel/tools/aubinator.c +++ b/src/intel/tools/aubinator.c @@ -43,9 +43,8 @@ #include "util/rb_tree.h" #include "common/gen_decoder.h" -#include "common/gen_disasm.h" -#include "common/gen_gem.h" #include "intel_aub.h" +#include "aub_read.h" #ifndef HAVE_MEMFD_CREATE #include <sys/syscall.h> @@ -234,7 +233,18 @@ search_phys_mem(uint64_t phys_addr) } static void -handle_ggtt_entry_write(uint64_t address, const void *_data, uint32_t _size) +handle_local_write(void *user_data, uint64_t address, const void *data, uint32_t size) +{ + struct gen_batch_decode_bo bo = { + .map = data, + .addr = address, + .size = size, + }; + add_gtt_bo_map(bo, false); +} + +static void +handle_ggtt_entry_write(void *user_data, uint64_t address, const void *_data, uint32_t _size) { uint64_t virt_addr = (address / sizeof(uint64_t)) << 12; const uint64_t *data = _data; @@ -248,7 +258,7 @@ handle_ggtt_entry_write(uint64_t address, const void *_data, uint32_t _size) } static void -handle_physical_write(uint64_t phys_address, const void *data, uint32_t size) +handle_physical_write(void *user_data, uint64_t phys_address, const void *data, uint32_t size) { uint32_t to_write = size; for (uint64_t page = phys_address & ~0xfff; page < phys_address + size; page += 4096) { @@ -262,7 +272,7 @@ handle_physical_write(uint64_t phys_address, const void *data, uint32_t size) } static void -handle_ggtt_write(uint64_t virt_address, const void *data, uint32_t size) +handle_ggtt_write(void *user_data, uint64_t virt_address, const void *data, uint32_t size) { uint32_t to_write = size; for (uint64_t page = virt_address & ~0xfff; page < virt_address + size; page += 4096) { @@ -274,7 +284,7 @@ handle_ggtt_write(uint64_t virt_address, const void *data, uint32_t size) to_write -= size_this_page; uint64_t phys_page = entry->phys_addr & ~0xfff; /* Clear the validity bits. */ - handle_physical_write(phys_page + offset, data, size_this_page); + handle_physical_write(user_data, phys_page + offset, data, size_this_page); data = (const uint8_t *)data + size_this_page; } } @@ -390,58 +400,17 @@ get_ppgtt_batch_bo(void *user_data, uint64_t address) return bo; } -#define GEN_ENGINE_RENDER 1 -#define GEN_ENGINE_BLITTER 2 - static void -handle_trace_block(uint32_t *p) +aubinator_error(void *user_data, const void *aub_data, const char *msg) { - int operation = p[1] & AUB_TRACE_OPERATION_MASK; - int type = p[1] & AUB_TRACE_TYPE_MASK; - int address_space = p[1] & AUB_TRACE_ADDRESS_SPACE_MASK; - int header_length = p[0] & 0xffff; - int engine = GEN_ENGINE_RENDER; - struct gen_batch_decode_bo bo = { - .map = p + header_length + 2, - /* Addresses written by aubdump here are in canonical form but the batch - * decoder always gives us addresses with the top 16bits zeroed, so do - * the same here. - */ - .addr = gen_48b_address((devinfo.gen >= 8 ? ((uint64_t) p[5] << 32) : 0) | - ((uint64_t) p[3])), - .size = p[4], - }; - - switch (operation) { - case AUB_TRACE_OP_DATA_WRITE: - if (address_space == AUB_TRACE_MEMTYPE_GTT) - add_gtt_bo_map(bo, false); - break; - case AUB_TRACE_OP_COMMAND_WRITE: - switch (type) { - case AUB_TRACE_TYPE_RING_PRB0: - engine = GEN_ENGINE_RENDER; - break; - case AUB_TRACE_TYPE_RING_PRB2: - engine = GEN_ENGINE_BLITTER; - break; - default: - fprintf(outfile, "command write to unknown ring %d\n", type); - break; - } - - (void)engine; /* TODO */ - batch_ctx.get_bo = get_ggtt_batch_bo; - gen_print_batch(&batch_ctx, bo.map, bo.size, 0); - - clear_bo_maps(); - break; - } + fprintf(stderr, msg); } static void -aubinator_init(uint16_t aub_pci_id, const char *app_name) +aubinator_init(void *user_data, int aub_pci_id, const char *app_name) { + pci_id = aub_pci_id; + if (!gen_get_device_info(pci_id, &devinfo)) { fprintf(stderr, "can't find device information: pci_id=0x%x\n", pci_id); exit(EXIT_FAILURE); @@ -482,111 +451,8 @@ aubinator_init(uint16_t aub_pci_id, const char *app_name) } static void -handle_trace_header(uint32_t *p) -{ - /* The intel_aubdump tool from IGT is kind enough to put a PCI-ID= tag in - * the AUB header comment. If the user hasn't specified a hardware - * generation, try to use the one from the AUB file. - */ - uint32_t *end = p + (p[0] & 0xffff) + 2; - int aub_pci_id = 0; - if (end > &p[12] && p[12] > 0) - sscanf((char *)&p[13], "PCI-ID=%i", &aub_pci_id); - - if (pci_id == 0) - pci_id = aub_pci_id; - - char app_name[33]; - strncpy(app_name, (char *)&p[2], 32); - app_name[32] = 0; - - aubinator_init(aub_pci_id, app_name); -} - -static void -handle_memtrace_version(uint32_t *p) -{ - int header_length = p[0] & 0xffff; - char app_name[64]; - int app_name_len = MIN2(4 * (header_length + 1 - 5), ARRAY_SIZE(app_name) - 1); - int pci_id_len = 0; - int aub_pci_id = 0; - - strncpy(app_name, (char *)&p[5], app_name_len); - app_name[app_name_len] = 0; - sscanf(app_name, "PCI-ID=%i %n", &aub_pci_id, &pci_id_len); - if (pci_id == 0) - pci_id = aub_pci_id; - aubinator_init(aub_pci_id, app_name + pci_id_len); -} - -static void -handle_memtrace_reg_write(uint32_t *p) +handle_execlist_write(void *user_data, enum gen_engine engine, uint64_t context_descriptor) { - static struct execlist_regs { - uint32_t render_elsp[4]; - int render_elsp_index; - uint32_t blitter_elsp[4]; - int blitter_elsp_index; - } state = {}; - - uint32_t offset = p[1]; - uint32_t value = p[5]; - - int engine; - uint64_t context_descriptor; - - switch (offset) { - case 0x2230: /* render elsp */ - state.render_elsp[state.render_elsp_index++] = value; - if (state.render_elsp_index < 4) - return; - - state.render_elsp_index = 0; - engine = GEN_ENGINE_RENDER; - context_descriptor = (uint64_t)state.render_elsp[2] << 32 | - state.render_elsp[3]; - break; - case 0x22230: /* blitter elsp */ - state.blitter_elsp[state.blitter_elsp_index++] = value; - if (state.blitter_elsp_index < 4) - return; - - state.blitter_elsp_index = 0; - engine = GEN_ENGINE_BLITTER; - context_descriptor = (uint64_t)state.blitter_elsp[2] << 32 | - state.blitter_elsp[3]; - break; - case 0x2510: /* render elsq0 lo */ - state.render_elsp[3] = value; - return; - break; - case 0x2514: /* render elsq0 hi */ - state.render_elsp[2] = value; - return; - break; - case 0x22510: /* blitter elsq0 lo */ - state.blitter_elsp[3] = value; - return; - break; - case 0x22514: /* blitter elsq0 hi */ - state.blitter_elsp[2] = value; - return; - break; - case 0x2550: /* render elsc */ - engine = GEN_ENGINE_RENDER; - context_descriptor = (uint64_t)state.render_elsp[2] << 32 | - state.render_elsp[3]; - break; - case 0x22550: /* blitter elsc */ - engine = GEN_ENGINE_BLITTER; - context_descriptor = (uint64_t)state.blitter_elsp[2] << 32 | - state.blitter_elsp[3]; - break; - default: - return; - } - const uint32_t pphwsp_size = 4096; uint32_t pphwsp_addr = context_descriptor & 0xfffff000; struct gen_batch_decode_bo pphwsp_bo = get_ggtt_batch_bo(NULL, pphwsp_addr); @@ -618,40 +484,20 @@ handle_memtrace_reg_write(uint32_t *p) } static void -handle_memtrace_mem_write(uint32_t *p) +handle_ring_write(void *user_data, enum gen_engine engine, + const void *data, uint32_t data_len) { - struct gen_batch_decode_bo bo = { - .map = p + 5, - /* Addresses written by aubdump here are in canonical form but the batch - * decoder always gives us addresses with the top 16bits zeroed, so do - * the same here. - */ - .addr = gen_48b_address(*(uint64_t*)&p[1]), - .size = p[4], - }; - uint32_t address_space = p[3] >> 28; - - switch (address_space) { - case 0: /* GGTT */ - handle_ggtt_write(bo.addr, bo.map, bo.size); - break; - case 1: /* Local */ - add_gtt_bo_map(bo, false); - break; - case 2: /* Physical */ - handle_physical_write(bo.addr, bo.map, bo.size); - break; - case 4: /* GGTT Entry */ - handle_ggtt_entry_write(bo.addr, bo.map, bo.size); - break; - } + batch_ctx.get_bo = get_ggtt_batch_bo; + + gen_print_batch(&batch_ctx, data, data_len, 0); + + clear_bo_maps(); } struct aub_file { FILE *stream; - uint32_t *map, *end, *cursor; - uint32_t *mem_end; + void *map, *end, *cursor; }; static struct aub_file * @@ -683,103 +529,11 @@ aub_file_open(const char *filename) close(fd); file->cursor = file->map; - file->end = file->map + sb.st_size / 4; + file->end = file->map + sb.st_size; return file; } -#define TYPE(dw) (((dw) >> 29) & 7) -#define OPCODE(dw) (((dw) >> 23) & 0x3f) -#define SUBOPCODE(dw) (((dw) >> 16) & 0x7f) - -#define MAKE_HEADER(type, opcode, subopcode) \ - (((type) << 29) | ((opcode) << 23) | ((subopcode) << 16)) - -#define TYPE_AUB 0x7 - -/* Classic AUB opcodes */ -#define OPCODE_AUB 0x01 -#define SUBOPCODE_HEADER 0x05 -#define SUBOPCODE_BLOCK 0x41 -#define SUBOPCODE_BMP 0x1e - -/* Newer version AUB opcode */ -#define OPCODE_NEW_AUB 0x2e -#define SUBOPCODE_REG_POLL 0x02 -#define SUBOPCODE_REG_WRITE 0x03 -#define SUBOPCODE_MEM_POLL 0x05 -#define SUBOPCODE_MEM_WRITE 0x06 -#define SUBOPCODE_VERSION 0x0e - -#define MAKE_GEN(major, minor) ( ((major) << 8) | (minor) ) - -static bool -aub_file_decode_batch(struct aub_file *file) -{ - uint32_t *p, h, *new_cursor; - int header_length, bias; - - assert(file->cursor < file->end); - - p = file->cursor; - h = *p; - header_length = h & 0xffff; - - switch (OPCODE(h)) { - case OPCODE_AUB: - bias = 2; - break; - case OPCODE_NEW_AUB: - bias = 1; - break; - default: - fprintf(outfile, "unknown opcode %d at %td/%td\n", - OPCODE(h), file->cursor - file->map, - file->end - file->map); - return false; - } - - new_cursor = p + header_length + bias; - if ((h & 0xffff0000) == MAKE_HEADER(TYPE_AUB, OPCODE_AUB, SUBOPCODE_BLOCK)) { - assert(file->end - file->cursor >= 4); - new_cursor += p[4] / 4; - } - - assert(new_cursor <= file->end); - - switch (h & 0xffff0000) { - case MAKE_HEADER(TYPE_AUB, OPCODE_AUB, SUBOPCODE_HEADER): - handle_trace_header(p); - break; - case MAKE_HEADER(TYPE_AUB, OPCODE_AUB, SUBOPCODE_BLOCK): - handle_trace_block(p); - break; - case MAKE_HEADER(TYPE_AUB, OPCODE_AUB, SUBOPCODE_BMP): - break; - case MAKE_HEADER(TYPE_AUB, OPCODE_NEW_AUB, SUBOPCODE_VERSION): - handle_memtrace_version(p); - break; - case MAKE_HEADER(TYPE_AUB, OPCODE_NEW_AUB, SUBOPCODE_REG_WRITE): - handle_memtrace_reg_write(p); - break; - case MAKE_HEADER(TYPE_AUB, OPCODE_NEW_AUB, SUBOPCODE_MEM_WRITE): - handle_memtrace_mem_write(p); - break; - case MAKE_HEADER(TYPE_AUB, OPCODE_NEW_AUB, SUBOPCODE_MEM_POLL): - fprintf(outfile, "memory poll block (dwords %d):\n", h & 0xffff); - break; - case MAKE_HEADER(TYPE_AUB, OPCODE_NEW_AUB, SUBOPCODE_REG_POLL): - break; - default: - fprintf(outfile, "unknown block type=0x%x, opcode=0x%x, " - "subopcode=0x%x (%08x)\n", TYPE(h), OPCODE(h), SUBOPCODE(h), h); - break; - } - file->cursor = new_cursor; - - return true; -} - static int aub_file_more_stuff(struct aub_file *file) { @@ -908,8 +662,23 @@ int main(int argc, char *argv[]) file = aub_file_open(input_file); + struct aub_read aub_read = { + .user_data = NULL, + .error = aubinator_error, + .info = aubinator_init, + .local_write = handle_local_write, + .phys_write = handle_physical_write, + .ggtt_write = handle_ggtt_write, + .ggtt_entry_write = handle_ggtt_entry_write, + .execlist_write = handle_execlist_write, + .ring_write = handle_ring_write, + }; + int consumed; while (aub_file_more_stuff(file) && - aub_file_decode_batch(file)); + (consumed = aub_read_command(&aub_read, file->cursor, + file->end - file->cursor)) > 0) { + file->cursor += consumed; + } fflush(stdout); /* close the stdout which is opened to write the output */ diff --git a/src/intel/tools/meson.build b/src/intel/tools/meson.build index cef0f2e956a..660d87f455d 100644 --- a/src/intel/tools/meson.build +++ b/src/intel/tools/meson.build @@ -20,7 +20,7 @@ aubinator = executable( 'aubinator', - files('aubinator.c', 'intel_aub.h'), + files('aubinator.c', 'intel_aub.h', 'aub_read.h', 'aub_read.c'), dependencies : [dep_expat, dep_zlib, dep_dl, dep_thread, dep_m], include_directories : [inc_common, inc_intel], link_with : [libintel_common, libintel_compiler, libintel_dev, libmesa_util], |