diff options
-rw-r--r-- | configure.ac | 5 | ||||
-rw-r--r-- | tools/.gitignore | 1 | ||||
-rw-r--r-- | tools/Makefile.am | 12 | ||||
-rw-r--r-- | tools/aubdump.c | 518 | ||||
-rw-r--r-- | tools/intel_aub.h | 153 | ||||
-rw-r--r-- | tools/intel_aubdump.in | 70 |
6 files changed, 758 insertions, 1 deletions
diff --git a/configure.ac b/configure.ac index 3770b2fc..6fc63e4c 100644 --- a/configure.ac +++ b/configure.ac @@ -255,6 +255,7 @@ AC_CONFIG_FILES([ scripts/Makefile tests/Makefile tools/Makefile + tools/intel_aubdump tools/quick_dump/Makefile tools/null_state_gen/Makefile debugger/Makefile @@ -264,7 +265,9 @@ AC_CONFIG_FILES([ assembler/test/Makefile assembler/intel-gen4asm.pc overlay/Makefile - ]) + ], + [chmod +x tools/intel_aubdump]) + AC_OUTPUT # Print a summary of the compilation diff --git a/tools/.gitignore b/tools/.gitignore index a09d9e82..49bd24f3 100644 --- a/tools/.gitignore +++ b/tools/.gitignore @@ -1,6 +1,7 @@ # Please keep sorted alphabetically hsw_compute_wrpll igt_stats +intel_aubdump intel_audio_dump intel_backlight intel_bios_dumper diff --git a/tools/Makefile.am b/tools/Makefile.am index da971c37..95f13f90 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -10,3 +10,15 @@ AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/lib AM_CFLAGS = $(DEBUG_CFLAGS) $(DRM_CFLAGS) $(PCIACCESS_CFLAGS) $(CWARNFLAGS) $(CAIRO_CFLAGS) $(LIBUNWIND_CFLAGS) LDADD = $(top_builddir)/lib/libintel_tools.la $(DRM_LIBS) $(PCIACCESS_LIBS) $(CAIRO_LIBS) $(LIBUDEV_LIBS) $(LIBUNWIND_LIBS) -lm + +# aubdumper + +module_LTLIBRARIES = intel_aubdump.la +moduledir = $(libdir) +intel_aubdump_la_LDFLAGS = -module -avoid-version -no-undefined +intel_aubdump_la_SOURCES = aubdump.c intel_aub.h +intel_aubdump_la_LIBADD = $(top_builddir)/lib/libintel_tools.la + +bin_SCRIPTS = intel_aubdump +CLEANFILES = $(bin_SCRIPTS) + diff --git a/tools/aubdump.c b/tools/aubdump.c new file mode 100644 index 00000000..bf128531 --- /dev/null +++ b/tools/aubdump.c @@ -0,0 +1,518 @@ +/* + * Copyright © 2015 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. + */ + +#define _GNU_SOURCE /* for RTLD_NEXT */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <stdint.h> +#include <stdbool.h> +#include <stdarg.h> +#include <fcntl.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/ioctl.h> +#include <unistd.h> +#include <errno.h> +#include <sys/mman.h> +#include <dlfcn.h> +#include <drm/i915_drm.h> + +#include "intel_aub.h" +#include "intel_chipset.h" + +static int (*libc_open)(const char *pathname, int flags, mode_t mode); +static int (*libc_close)(int fd); +static int (*libc_ioctl)(int fd, unsigned long request, void *argp); + +static int drm_fd = -1; +static char *filename; +static FILE *file; +static int gen = 0; +static int verbose = 0; +static const uint32_t gtt_size = 0x10000; + +#define MAX_BO_COUNT 64 * 1024 + +struct bo { + uint32_t size; + uint32_t offset; + void *map; +}; + +static struct bo *bos; + +#define DRM_MAJOR 226 + +/* We set bit 0 in the map pointer for userptr BOs so we know not to + * munmap them on DRM_IOCTL_GEM_CLOSE. + */ +#define USERPTR_FLAG 1 +#define IS_USERPTR(p) ((uintptr_t) (p) & USERPTR_FLAG) +#define GET_PTR(p) ( (void *) ((uintptr_t) p & ~(uintptr_t) 1) ) + +static void __attribute__ ((format(__printf__, 2, 3))) +fail_if(int cond, const char *format, ...) +{ + va_list args; + + if (!cond) + return; + + va_start(args, format); + vfprintf(stderr, format, args); + va_end(args); + + exit(1); +} + +static inline uint32_t +align_u32(uint32_t v, uint32_t a) +{ + return (v + a - 1) & ~(a - 1); +} + +static void +dword_out(uint32_t data) +{ + fwrite(&data, 1, 4, file); +} + +static void +data_out(const void *data, size_t size) +{ + fwrite(data, 1, size, file); +} + +static void +write_header(void) +{ + uint32_t entry = 0x200003; + + /* Start with a (required) version packet. */ + dword_out(CMD_AUB_HEADER | (13 - 2)); + dword_out((4 << AUB_HEADER_MAJOR_SHIFT) | + (0 << AUB_HEADER_MINOR_SHIFT)); + for (int i = 0; i < 8; i++) + dword_out(0); /* app name */ + + dword_out(0); /* timestamp */ + dword_out(0); /* timestamp */ + dword_out(0); /* comment len */ + + /* Set up the GTT. The max we can handle is 256M */ + dword_out(CMD_AUB_TRACE_HEADER_BLOCK | ((gen >= 8 ? 6 : 5) - 2)); + dword_out(AUB_TRACE_MEMTYPE_GTT_ENTRY | + AUB_TRACE_TYPE_NOTYPE | AUB_TRACE_OP_DATA_WRITE); + dword_out(0); /* subtype */ + dword_out(0); /* offset */ + dword_out(gtt_size); /* size */ + if (gen >= 8) + dword_out(0); + for (uint32_t i = 0; i < gtt_size; i += 4, entry += 0x1000) + dword_out(entry); +} + +/** + * Break up large objects into multiple writes. Otherwise a 128kb VBO + * would overflow the 16 bits of size field in the packet header and + * everything goes badly after that. + */ +static void +aub_write_trace_block(uint32_t type, void *virtual, uint32_t size, uint32_t gtt_offset) +{ + uint32_t block_size; + uint32_t subtype = 0; + static const char null_block[8 * 4096]; + + for (uint32_t offset = 0; offset < size; offset += block_size) { + block_size = size - offset; + + if (block_size > 8 * 4096) + block_size = 8 * 4096; + + dword_out(CMD_AUB_TRACE_HEADER_BLOCK | + ((gen >= 8 ? 6 : 5) - 2)); + dword_out(AUB_TRACE_MEMTYPE_GTT | + type | AUB_TRACE_OP_DATA_WRITE); + dword_out(subtype); + dword_out(gtt_offset + offset); + dword_out(align_u32(block_size, 4)); + if (gen >= 8) + dword_out(0); + + if (virtual) + data_out(GET_PTR(virtual) + offset, block_size); + else + data_out(null_block, block_size); + + /* Pad to a multiple of 4 bytes. */ + data_out(null_block, -block_size & 3); + } +} + +static void +aub_dump_ringbuffer(uint32_t batch_offset, uint32_t offset, int ring_flag) +{ + uint32_t ringbuffer[4096]; + int ring = AUB_TRACE_TYPE_RING_PRB0; /* The default ring */ + int ring_count = 0; + + if (ring_flag == I915_EXEC_BSD) + ring = AUB_TRACE_TYPE_RING_PRB1; + else if (ring_flag == I915_EXEC_BLT) + ring = AUB_TRACE_TYPE_RING_PRB2; + + /* Make a ring buffer to execute our batchbuffer. */ + memset(ringbuffer, 0, sizeof(ringbuffer)); + if (gen >= 8) { + ringbuffer[ring_count++] = AUB_MI_BATCH_BUFFER_START | (3 - 2); + ringbuffer[ring_count++] = batch_offset; + ringbuffer[ring_count++] = 0; + } else { + ringbuffer[ring_count++] = AUB_MI_BATCH_BUFFER_START; + ringbuffer[ring_count++] = batch_offset; + } + + /* Write out the ring. This appears to trigger execution of + * the ring in the simulator. + */ + dword_out(CMD_AUB_TRACE_HEADER_BLOCK | + ((gen >= 8 ? 6 : 5) - 2)); + dword_out(AUB_TRACE_MEMTYPE_GTT | ring | AUB_TRACE_OP_COMMAND_WRITE); + dword_out(0); /* general/surface subtype */ + dword_out(offset); + dword_out(ring_count * 4); + if (gen >= 8) + dword_out(0); + + data_out(ringbuffer, ring_count * 4); +} + +static void * +relocate_bo(struct bo *bo, const struct drm_i915_gem_execbuffer2 *execbuffer2, + const struct drm_i915_gem_exec_object2 *obj) +{ + const struct drm_i915_gem_exec_object2 *exec_objects = + (struct drm_i915_gem_exec_object2 *) (uintptr_t) execbuffer2->buffers_ptr; + const struct drm_i915_gem_relocation_entry *relocs = + (const struct drm_i915_gem_relocation_entry *) (uintptr_t) obj->relocs_ptr; + void *relocated; + uint32_t *dw; + int handle; + + relocated = malloc(bo->size); + fail_if(relocated == NULL, "intel_aubdump: out of memory\n"); + memcpy(relocated, GET_PTR(bo->map), bo->size); + for (size_t i = 0; i < obj->relocation_count; i++) { + fail_if(relocs[i].offset >= bo->size, "intel_aubdump: reloc outside bo\n"); + + if (execbuffer2->flags & I915_EXEC_HANDLE_LUT) + handle = exec_objects[relocs[i].target_handle].handle; + else + handle = relocs[i].target_handle; + + dw = relocated + relocs[i].offset; + *dw = bos[handle].offset + relocs[i].delta; + } + + return relocated; +} + +static int +gem_ioctl(int fd, unsigned long request, void *argp) +{ + int ret; + + do { + ret = libc_ioctl(fd, request, argp); + } while (ret == -1 && (errno == EINTR || errno == EAGAIN)); + + return ret; +} + +static void * +gem_mmap(int fd, uint32_t handle, uint64_t offset, uint64_t size) +{ + struct drm_i915_gem_mmap mmap = { + .handle = handle, + .offset = offset, + .size = size + }; + + if (gem_ioctl(fd, DRM_IOCTL_I915_GEM_MMAP, &mmap) == -1) + return MAP_FAILED; + + return (void *)(uintptr_t) mmap.addr_ptr; +} + +static int +gem_get_param(int fd, uint32_t param) +{ + int value; + drm_i915_getparam_t gp = { + .param = param, + .value = &value + }; + + if (gem_ioctl(fd, DRM_IOCTL_I915_GETPARAM, &gp) == -1) + return 0; + + return value; +} + +static void +dump_execbuffer2(int fd, struct drm_i915_gem_execbuffer2 *execbuffer2) +{ + struct drm_i915_gem_exec_object2 *exec_objects = + (struct drm_i915_gem_exec_object2 *) (uintptr_t) execbuffer2->buffers_ptr; + uint32_t ring_flag = 0; + uint32_t offset = gtt_size; + struct drm_i915_gem_exec_object2 *obj; + struct bo *bo, *batch_bo; + void *data; + + /* We can't do this at open time as we're not yet authenticated. */ + if (gen == 0) { + uint32_t chipset_id = gem_get_param(fd, I915_PARAM_CHIPSET_ID); + gen = intel_gen(chipset_id); + + fail_if(chipset_id == 0 || gen == -1, "failed to identify chipset\n"); + if (verbose) + printf("[intel_aubdump active: " + "output file %s, chipset id 0x%04x, gen %d]\n", + filename, chipset_id, gen); + } + + for (uint32_t i = 0; i < execbuffer2->buffer_count; i++) { + obj = &exec_objects[i]; + bo = &bos[obj->handle]; + + bo->offset = offset; + offset = align_u32(offset + bo->size + 4095, 4096); + + if (bo->map == NULL) + bo->map = gem_mmap(fd, obj->handle, 0, bo->size); + fail_if(bo->map == MAP_FAILED, "intel_aubdump: bo mmap failed\n"); + } + + batch_bo = &bos[exec_objects[execbuffer2->buffer_count - 1].handle]; + for (uint32_t i = 0; i < execbuffer2->buffer_count; i++) { + obj = &exec_objects[i]; + bo = &bos[obj->handle]; + + if (obj->relocation_count > 0) + data = relocate_bo(bo, execbuffer2, obj); + else + data = bo->map; + + if (bo == batch_bo) { + aub_write_trace_block(AUB_TRACE_TYPE_BATCH, + data, bo->size, bo->offset); + } else { + aub_write_trace_block(AUB_TRACE_TYPE_NOTYPE, + data, bo->size, bo->offset); + } + if (data != bo->map) + free(data); + } + + /* Dump ring buffer */ + aub_dump_ringbuffer(batch_bo->offset + execbuffer2->batch_start_offset, + offset, ring_flag); + + fflush(file); +} + +static void +add_new_bo(int handle, uint64_t size, void *map) +{ + struct bo *bo = &bos[handle]; + + fail_if(handle >= MAX_BO_COUNT, "intel_aubdump: bo handle out of range\n"); + + bo->size = size; + bo->map = map; +} + +static void +remove_bo(int handle) +{ + struct bo *bo = &bos[handle]; + + if (bo->map && !IS_USERPTR(bo->map)) + munmap(bo->map, bo->size); + bo->map = NULL; +} + +int +open(const char *pathname, int flags, ...) +{ + va_list args; + struct stat buf; + mode_t mode; + int fd; + + va_start(args, flags); + mode = va_arg(args, int); + va_end(args); + + fd = libc_open(pathname, flags, mode); + + if (fd >= 0 && fstat(fd, &buf) == 0 && + (buf.st_mode & S_IFMT) == S_IFCHR && major(buf.st_rdev) == DRM_MAJOR) + drm_fd = fd; + + return fd; +} + +int +close(int fd) +{ + if (fd == drm_fd) + drm_fd = -1; + + return libc_close(fd); +} + +int +ioctl(int fd, unsigned long request, ...) +{ + va_list args; + void *argp; + int ret; + + va_start(args, request); + argp = va_arg(args, void *); + va_end(args); + + if (fd == drm_fd) { + switch (request) { + case DRM_IOCTL_I915_GEM_EXECBUFFER: { + static bool once; + if (!once) { + fprintf(stderr, "intel_aubdump: " + "application uses DRM_IOCTL_I915_GEM_EXECBUFFER, not handled\n"); + once = true; + } + return libc_ioctl(fd, request, argp); + } + + case DRM_IOCTL_I915_GEM_EXECBUFFER2: { + dump_execbuffer2(fd, argp); + return libc_ioctl(fd, request, argp); + } + + case DRM_IOCTL_I915_GEM_CREATE: { + struct drm_i915_gem_create *create = argp; + + ret = libc_ioctl(fd, request, argp); + if (ret == 0) + add_new_bo(create->handle, create->size, NULL); + + return ret; + } + + case DRM_IOCTL_I915_GEM_USERPTR: { + struct drm_i915_gem_userptr *userptr = argp; + + ret = libc_ioctl(fd, request, argp); + if (ret == 0) + add_new_bo(userptr->handle, userptr->user_size, + (void *) (uintptr_t) (userptr->user_ptr | USERPTR_FLAG)); + return ret; + } + + case DRM_IOCTL_GEM_CLOSE: { + struct drm_gem_close *close = argp; + + remove_bo(close->handle); + + return libc_ioctl(fd, request, argp); + } + + case DRM_IOCTL_GEM_OPEN: { + struct drm_gem_open *open = argp; + + ret = libc_ioctl(fd, request, argp); + if (ret == 0) + add_new_bo(open->handle, open->size, NULL); + + return ret; + } + + case DRM_IOCTL_PRIME_FD_TO_HANDLE: { + struct drm_prime_handle *prime = argp; + + ret = libc_ioctl(fd, request, argp); + if (ret == 0) { + off_t size; + + size = lseek(prime->fd, 0, SEEK_END); + fail_if(size == -1, "intel_aubdump: failed to get prime bo size\n"); + add_new_bo(prime->handle, size, NULL); + } + + return ret; + } + + default: + return libc_ioctl(fd, request, argp); + } + } else { + return libc_ioctl(fd, request, argp); + } +} + +static void __attribute__ ((constructor)) +init(void) +{ + const char *args = getenv("INTEL_AUBDUMP_ARGS"); + + libc_open = dlsym(RTLD_NEXT, "open"); + libc_close = dlsym(RTLD_NEXT, "close"); + libc_ioctl = dlsym(RTLD_NEXT, "ioctl"); + fail_if(libc_open == NULL || libc_close == NULL || libc_ioctl == NULL, + "intel_aubdump: failed to get libc open or ioctl\n"); + + if (sscanf(args, "verbose=%d;file=%m[^;]", &verbose, &filename) != 2) + filename = strdup("intel.aub"); + fail_if(filename == NULL, "intel_aubdump: out of memory\n"); + + bos = malloc(MAX_BO_COUNT * sizeof(bos[0])); + fail_if(bos == NULL, "intel_aubdump: out of memory\n"); + + file = fopen(filename, "w+"); + fail_if(file == NULL, "intel_aubdump: failed to open file '%s'\n", filename); + + write_header(); +} + +static void __attribute__ ((destructor)) +fini(void) +{ + free(filename); + fclose(file); + free(bos); +} diff --git a/tools/intel_aub.h b/tools/intel_aub.h new file mode 100644 index 00000000..5f0aba8e --- /dev/null +++ b/tools/intel_aub.h @@ -0,0 +1,153 @@ +/* + * Copyright © 2010 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. + * + * Authors: + * Eric Anholt <eric@anholt.net> + * + */ + +/** @file intel_aub.h + * + * The AUB file is a file format used by Intel's internal simulation + * and other validation tools. It can be used at various levels by a + * driver to input state to the simulated hardware or a replaying + * debugger. + * + * We choose to dump AUB files using the trace block format for ease + * of implementation -- dump out the blocks of memory as plain blobs + * and insert ring commands to execute the batchbuffer blob. + */ + +#ifndef _INTEL_AUB_H +#define _INTEL_AUB_H + +#define AUB_MI_NOOP (0) +#define AUB_MI_BATCH_BUFFER_START (0x31 << 23) +#define AUB_PIPE_CONTROL (0x7a000002) + +/* DW0: instruction type. */ + +#define CMD_AUB (7 << 29) + +#define CMD_AUB_HEADER (CMD_AUB | (1 << 23) | (0x05 << 16)) +/* DW1 */ +# define AUB_HEADER_MAJOR_SHIFT 24 +# define AUB_HEADER_MINOR_SHIFT 16 + +#define CMD_AUB_TRACE_HEADER_BLOCK (CMD_AUB | (1 << 23) | (0x41 << 16)) +#define CMD_AUB_DUMP_BMP (CMD_AUB | (1 << 23) | (0x9e << 16)) + +/* DW1 */ +#define AUB_TRACE_OPERATION_MASK 0x000000ff +#define AUB_TRACE_OP_COMMENT 0x00000000 +#define AUB_TRACE_OP_DATA_WRITE 0x00000001 +#define AUB_TRACE_OP_COMMAND_WRITE 0x00000002 +#define AUB_TRACE_OP_MMIO_WRITE 0x00000003 +// operation = TRACE_DATA_WRITE, Type +#define AUB_TRACE_TYPE_MASK 0x0000ff00 +#define AUB_TRACE_TYPE_NOTYPE (0 << 8) +#define AUB_TRACE_TYPE_BATCH (1 << 8) +#define AUB_TRACE_TYPE_VERTEX_BUFFER (5 << 8) +#define AUB_TRACE_TYPE_2D_MAP (6 << 8) +#define AUB_TRACE_TYPE_CUBE_MAP (7 << 8) +#define AUB_TRACE_TYPE_VOLUME_MAP (9 << 8) +#define AUB_TRACE_TYPE_1D_MAP (10 << 8) +#define AUB_TRACE_TYPE_CONSTANT_BUFFER (11 << 8) +#define AUB_TRACE_TYPE_CONSTANT_URB (12 << 8) +#define AUB_TRACE_TYPE_INDEX_BUFFER (13 << 8) +#define AUB_TRACE_TYPE_GENERAL (14 << 8) +#define AUB_TRACE_TYPE_SURFACE (15 << 8) + + +// operation = TRACE_COMMAND_WRITE, Type = +#define AUB_TRACE_TYPE_RING_HWB (1 << 8) +#define AUB_TRACE_TYPE_RING_PRB0 (2 << 8) +#define AUB_TRACE_TYPE_RING_PRB1 (3 << 8) +#define AUB_TRACE_TYPE_RING_PRB2 (4 << 8) + +// Address space +#define AUB_TRACE_ADDRESS_SPACE_MASK 0x00ff0000 +#define AUB_TRACE_MEMTYPE_GTT (0 << 16) +#define AUB_TRACE_MEMTYPE_LOCAL (1 << 16) +#define AUB_TRACE_MEMTYPE_NONLOCAL (2 << 16) +#define AUB_TRACE_MEMTYPE_PCI (3 << 16) +#define AUB_TRACE_MEMTYPE_GTT_ENTRY (4 << 16) + +/* DW2 */ + +/** + * aub_state_struct_type enum values are encoded with the top 16 bits + * representing the type to be delivered to the .aub file, and the bottom 16 + * bits representing the subtype. This macro performs the encoding. + */ +#define ENCODE_SS_TYPE(type, subtype) (((type) << 16) | (subtype)) + +enum aub_state_struct_type { + AUB_TRACE_VS_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 1), + AUB_TRACE_GS_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 2), + AUB_TRACE_CLIP_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 3), + AUB_TRACE_SF_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 4), + AUB_TRACE_WM_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 5), + AUB_TRACE_CC_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 6), + AUB_TRACE_CLIP_VP_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 7), + AUB_TRACE_SF_VP_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 8), + AUB_TRACE_CC_VP_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 0x9), + AUB_TRACE_SAMPLER_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 0xa), + AUB_TRACE_KERNEL_INSTRUCTIONS = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 0xb), + AUB_TRACE_SCRATCH_SPACE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 0xc), + AUB_TRACE_SAMPLER_DEFAULT_COLOR = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 0xd), + + AUB_TRACE_SCISSOR_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 0x15), + AUB_TRACE_BLEND_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 0x16), + AUB_TRACE_DEPTH_STENCIL_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 0x17), + + AUB_TRACE_VERTEX_BUFFER = ENCODE_SS_TYPE(AUB_TRACE_TYPE_VERTEX_BUFFER, 0), + AUB_TRACE_BINDING_TABLE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_SURFACE, 0x100), + AUB_TRACE_SURFACE_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_SURFACE, 0x200), + AUB_TRACE_VS_CONSTANTS = ENCODE_SS_TYPE(AUB_TRACE_TYPE_CONSTANT_BUFFER, 0), + AUB_TRACE_WM_CONSTANTS = ENCODE_SS_TYPE(AUB_TRACE_TYPE_CONSTANT_BUFFER, 1), +}; + +#undef ENCODE_SS_TYPE + +/** + * Decode a aub_state_struct_type value to determine the type that should be + * stored in the .aub file. + */ +static inline uint32_t AUB_TRACE_TYPE(enum aub_state_struct_type ss_type) +{ + return (ss_type & 0xFFFF0000) >> 16; +} + +/** + * Decode a state_struct_type value to determine the subtype that should be + * stored in the .aub file. + */ +static inline uint32_t AUB_TRACE_SUBTYPE(enum aub_state_struct_type ss_type) +{ + return ss_type & 0xFFFF; +} + +/* DW3: address */ +/* DW4: len */ + +#endif /* _INTEL_AUB_H */ diff --git a/tools/intel_aubdump.in b/tools/intel_aubdump.in new file mode 100644 index 00000000..7b5a0a1c --- /dev/null +++ b/tools/intel_aubdump.in @@ -0,0 +1,70 @@ +#!/bin/bash +# -*- mode: sh -*- + +function show_help() { + cat <<EOF +Usage: intel_aubdump [OPTION]... [--] COMMAND ARGUMENTS + +Run COMMAND with ARGUMENTS and dump an AUB file that captures buffer +contents and execution of the GEM application. + + -o, --output=FILE Name of AUB file. Defaults to COMMAND.aub + + -v Enable verbose output + + --help Display this help message and exit + +EOF + + exit 0 +} + +verbose=0 + +while true; do + case "$1" in + -o) + file=$2 + shift 2 + ;; + -v) + verbose=1 + shift 1 + ;; + -o*) + file=${1##-o} + shift + ;; + --output=*) + file=${1##--output=} + shift + ;; + --help) + show_help + ;; + --) + shift + break + ;; + -*) + echo "intel_aubdump: invalid option: $1" + echo + show_help + ;; + *) + break + ;; + esac +done + +[ -z $1 ] && show_help + +file=${file:-$(basename $1).aub} + +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ + +LD_PRELOAD=${libdir}/intel_aubdump.so${LD_PPRELOAD:+:${LD_PRELOAD}} \ + INTEL_AUBDUMP_ARGS="verbose=$verbose;file=$file" \ + exec -- "$@" |