intel: tools: split aub parsing from aubinator

v2: add parsing error callback (Lionel)

Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
Reviewed-by: Rafael Antognolli <rafael.antognolli@intel.com> (v1)
This commit is contained in:
Lionel Landwerlin 2018-07-28 19:13:04 +01:00
parent e15686567c
commit 4616639b49
5 changed files with 459 additions and 278 deletions

View file

@ -26,6 +26,8 @@ noinst_PROGRAMS += \
tools_aubinator_SOURCES = \
tools/aub_read.c \
tools/aub_read.h \
tools/aubinator.c \
tools/intel_aub.h

333
src/intel/tools/aub_read.c Normal file
View file

@ -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);
}

View file

@ -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 */

View file

@ -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)
handle_execlist_write(void *user_data, enum gen_engine engine, uint64_t context_descriptor)
{
/* 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)
{
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;
batch_ctx.get_bo = get_ggtt_batch_bo;
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;
}
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 */

View file

@ -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],