Path: blob/21.2-virgl/src/intel/tools/aub_read.c
4547 views
/*1* Copyright © 2016-2018 Intel Corporation2*3* Permission is hereby granted, free of charge, to any person obtaining a4* copy of this software and associated documentation files (the "Software"),5* to deal in the Software without restriction, including without limitation6* the rights to use, copy, modify, merge, publish, distribute, sublicense,7* and/or sell copies of the Software, and to permit persons to whom the8* Software is furnished to do so, subject to the following conditions:9*10* The above copyright notice and this permission notice (including the next11* paragraph) shall be included in all copies or substantial portions of the12* Software.13*14* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL17* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER18* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING19* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS20* IN THE SOFTWARE.21*22*/2324#include <stdio.h>25#include <stdlib.h>26#include <string.h>27#include <stdarg.h>2829#include "common/intel_gem.h"30#include "util/macros.h"3132#include "aub_read.h"33#include "intel_context.h"34#include "intel_aub.h"3536#define TYPE(dw) (((dw) >> 29) & 7)37#define OPCODE(dw) (((dw) >> 23) & 0x3f)38#define SUBOPCODE(dw) (((dw) >> 16) & 0x7f)3940#define MAKE_HEADER(type, opcode, subopcode) \41((((unsigned) (type)) << 29) | ((opcode) << 23) | ((subopcode) << 16))4243#define TYPE_AUB 0x74445/* Classic AUB opcodes */46#define OPCODE_AUB 0x0147#define SUBOPCODE_HEADER 0x0548#define SUBOPCODE_BLOCK 0x4149#define SUBOPCODE_BMP 0x1e5051/* Newer version AUB opcode */52#define OPCODE_NEW_AUB 0x2e53#define SUBOPCODE_REG_POLL 0x0254#define SUBOPCODE_REG_WRITE 0x0355#define SUBOPCODE_MEM_POLL 0x0556#define SUBOPCODE_MEM_WRITE 0x0657#define SUBOPCODE_VERSION 0x0e5859static PRINTFLIKE(3, 4) void60parse_error(struct aub_read *read, const uint32_t *p, const char *fmt, ...)61{62if (!read->error)63return;6465va_list ap;66va_start(ap, fmt);6768char msg[80];69vsnprintf(msg, sizeof(msg), fmt, ap);70read->error(read->user_data, p, msg);7172va_end(ap);73}7475static bool76handle_trace_header(struct aub_read *read, const uint32_t *p)77{78/* The intel_aubdump tool from IGT is kind enough to put a PCI-ID= tag in79* the AUB header comment. If the user hasn't specified a hardware80* generation, try to use the one from the AUB file.81*/82const uint32_t *end = p + (p[0] & 0xffff) + 2;83int aub_pci_id = 0;8485if (end > &p[12] && p[12] > 0) {86if (sscanf((char *)&p[13], "PCI-ID=%i", &aub_pci_id) > 0) {87if (!intel_get_device_info_from_pci_id(aub_pci_id, &read->devinfo)) {88parse_error(read, p,89"can't find device information: pci_id=0x%x\n", aub_pci_id);90return false;91}92}93}9495char app_name[33];96strncpy(app_name, (const char *)&p[2], 32);97app_name[32] = 0;9899if (read->info)100read->info(read->user_data, aub_pci_id, app_name);101102return true;103}104105static bool106handle_memtrace_version(struct aub_read *read, const uint32_t *p)107{108int header_length = p[0] & 0xffff;109char app_name[64];110int app_name_len = MIN2(4 * (header_length + 1 - 5), ARRAY_SIZE(app_name) - 1);111int pci_id_len = 0;112int aub_pci_id = 0;113114strncpy(app_name, (const char *)&p[5], app_name_len);115app_name[app_name_len] = 0;116117if (sscanf(app_name, "PCI-ID=%i %n", &aub_pci_id, &pci_id_len) > 0) {118if (!intel_get_device_info_from_pci_id(aub_pci_id, &read->devinfo)) {119parse_error(read, p, "can't find device information: pci_id=0x%x\n", aub_pci_id);120return false;121}122123if (read->info)124read->info(read->user_data, aub_pci_id, app_name + pci_id_len);125}126127return true;128}129130static bool131handle_trace_block(struct aub_read *read, const uint32_t *p)132{133int operation = p[1] & AUB_TRACE_OPERATION_MASK;134int type = p[1] & AUB_TRACE_TYPE_MASK;135int address_space = p[1] & AUB_TRACE_ADDRESS_SPACE_MASK;136int header_length = p[0] & 0xffff;137enum drm_i915_gem_engine_class engine = I915_ENGINE_CLASS_RENDER;138const void *data = p + header_length + 2;139uint64_t address = intel_48b_address((read->devinfo.ver >= 8 ? ((uint64_t) p[5] << 32) : 0) |140((uint64_t) p[3]));141uint32_t size = p[4];142143switch (operation) {144case AUB_TRACE_OP_DATA_WRITE:145if (address_space == AUB_TRACE_MEMTYPE_GTT) {146if (read->local_write)147read->local_write(read->user_data, address, data, size);148break;149case AUB_TRACE_OP_COMMAND_WRITE:150switch (type) {151case AUB_TRACE_TYPE_RING_PRB0:152engine = I915_ENGINE_CLASS_RENDER;153break;154case AUB_TRACE_TYPE_RING_PRB1:155engine = I915_ENGINE_CLASS_VIDEO;156break;157case AUB_TRACE_TYPE_RING_PRB2:158engine = I915_ENGINE_CLASS_COPY;159break;160default:161parse_error(read, p, "command write to unknown ring %d\n", type);162return false;163}164165if (read->ring_write)166read->ring_write(read->user_data, engine, data, size);167break;168}169}170171return true;172}173174static void175handle_memtrace_reg_write(struct aub_read *read, const uint32_t *p)176{177uint32_t offset = p[1];178uint32_t value = p[5];179180if (read->reg_write)181read->reg_write(read->user_data, offset, value);182183enum drm_i915_gem_engine_class engine;184uint64_t context_descriptor;185186switch (offset) {187case EXECLIST_SUBMITPORT_RCSUNIT: /* render elsp */188read->render_elsp[read->render_elsp_index++] = value;189if (read->render_elsp_index < 4)190return;191192read->render_elsp_index = 0;193engine = I915_ENGINE_CLASS_RENDER;194context_descriptor = (uint64_t)read->render_elsp[2] << 32 |195read->render_elsp[3];196break;197case EXECLIST_SUBMITPORT_VCSUNIT0: /* video elsp */198read->video_elsp[read->video_elsp_index++] = value;199if (read->video_elsp_index < 4)200return;201202read->video_elsp_index = 0;203engine = I915_ENGINE_CLASS_VIDEO;204context_descriptor = (uint64_t)read->video_elsp[2] << 32 |205read->video_elsp[3];206break;207case EXECLIST_SUBMITPORT_BCSUNIT: /* blitter elsp */208read->blitter_elsp[read->blitter_elsp_index++] = value;209if (read->blitter_elsp_index < 4)210return;211212read->blitter_elsp_index = 0;213engine = I915_ENGINE_CLASS_COPY;214context_descriptor = (uint64_t)read->blitter_elsp[2] << 32 |215read->blitter_elsp[3];216break;217case EXECLIST_SQ_CONTENTS0_RCSUNIT: /* render elsq0 lo */218read->render_elsp[3] = value;219return;220case (EXECLIST_SQ_CONTENTS0_RCSUNIT + 4): /* render elsq0 hi */221read->render_elsp[2] = value;222return;223case EXECLIST_SQ_CONTENTS0_VCSUNIT0: /* video elsq0 lo */224read->video_elsp[3] = value;225return;226case EXECLIST_SQ_CONTENTS0_VCSUNIT0 + 4: /* video elsq0 hi */227read->video_elsp[2] = value;228return;229case EXECLIST_SQ_CONTENTS0_BCSUNIT: /* blitter elsq0 lo */230read->blitter_elsp[3] = value;231return;232case (EXECLIST_SQ_CONTENTS0_BCSUNIT + 4): /* blitter elsq0 hi */233read->blitter_elsp[2] = value;234return;235case EXECLIST_CONTROL_RCSUNIT: /* render elsc */236engine = I915_ENGINE_CLASS_RENDER;237context_descriptor = (uint64_t)read->render_elsp[2] << 32 |238read->render_elsp[3];239break;240case EXECLIST_CONTROL_VCSUNIT0: /* video_elsc */241engine = I915_ENGINE_CLASS_VIDEO;242context_descriptor = (uint64_t)read->video_elsp[2] << 32 |243read->video_elsp[3];244break;245case EXECLIST_CONTROL_BCSUNIT: /* blitter elsc */246engine = I915_ENGINE_CLASS_COPY;247context_descriptor = (uint64_t)read->blitter_elsp[2] << 32 |248read->blitter_elsp[3];249break;250default:251return;252}253254if (read->execlist_write)255read->execlist_write(read->user_data, engine, context_descriptor);256}257258static void259handle_memtrace_mem_write(struct aub_read *read, const uint32_t *p)260{261const void *data = p + 5;262uint64_t addr = intel_48b_address(*(uint64_t*)&p[1]);263uint32_t size = p[4];264uint32_t address_space = p[3] >> 28;265266switch (address_space) {267case 0: /* GGTT */268if (read->ggtt_write)269read->ggtt_write(read->user_data, addr, data, size);270break;271case 1: /* Local */272if (read->local_write)273read->local_write(read->user_data, addr, data, size);274break;275case 2: /* Physical */276if (read->phys_write)277read->phys_write(read->user_data, addr, data, size);278break;279case 4: /* GGTT Entry */280if (read->ggtt_entry_write)281read->ggtt_entry_write(read->user_data, addr, data, size);282break;283}284}285286int287aub_read_command(struct aub_read *read, const void *data, uint32_t data_len)288{289const uint32_t *p = data, *next;290ASSERTED const uint32_t *end = data + data_len;291uint32_t h, header_length, bias;292293assert(data_len >= 4);294295h = *p;296header_length = h & 0xffff;297298switch (OPCODE(h)) {299case OPCODE_AUB:300bias = 2;301break;302case OPCODE_NEW_AUB:303bias = 1;304break;305default:306parse_error(read, data, "unknown opcode %d\n", OPCODE(h));307return -1;308}309310next = p + header_length + bias;311if ((h & 0xffff0000) == MAKE_HEADER(TYPE_AUB, OPCODE_AUB, SUBOPCODE_BLOCK)) {312assert(end - p >= 4);313next += p[4] / 4;314}315316if (next > end) {317parse_error(read, data,318"input ends unexpectedly (command length: %zu, remaining bytes: %zu)\n",319(uintptr_t)next - (uintptr_t)data,320(uintptr_t)end - (uintptr_t)data);321return -1;322}323324switch (h & 0xffff0000) {325case MAKE_HEADER(TYPE_AUB, OPCODE_AUB, SUBOPCODE_HEADER):326if (!handle_trace_header(read, p))327return -1;328break;329case MAKE_HEADER(TYPE_AUB, OPCODE_AUB, SUBOPCODE_BLOCK):330if (!handle_trace_block(read, p))331return -1;332break;333case MAKE_HEADER(TYPE_AUB, OPCODE_AUB, SUBOPCODE_BMP):334break;335case MAKE_HEADER(TYPE_AUB, OPCODE_NEW_AUB, SUBOPCODE_VERSION):336if (!handle_memtrace_version(read, p))337return -1;338break;339case MAKE_HEADER(TYPE_AUB, OPCODE_NEW_AUB, SUBOPCODE_REG_WRITE):340handle_memtrace_reg_write(read, p);341break;342case MAKE_HEADER(TYPE_AUB, OPCODE_NEW_AUB, SUBOPCODE_MEM_WRITE):343handle_memtrace_mem_write(read, p);344break;345case MAKE_HEADER(TYPE_AUB, OPCODE_NEW_AUB, SUBOPCODE_MEM_POLL):346/* fprintf(outfile, "memory poll block (dwords %d):\n", h & 0xffff); */347break;348case MAKE_HEADER(TYPE_AUB, OPCODE_NEW_AUB, SUBOPCODE_REG_POLL):349break;350default:351parse_error(read, p,352"unknown block type=0x%x, opcode=0x%x, subopcode=0x%x (%08x)\n",353TYPE(h), OPCODE(h), SUBOPCODE(h), h);354return -1;355}356357return (next - p) * sizeof(*p);358}359360361