aub_read.c revision 01e04c3f
1/* 2 * Copyright © 2016-2018 Intel Corporation 3 * 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: 10 * 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 13 * Software. 14 * 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 21 * IN THE SOFTWARE. 22 * 23 */ 24 25#include <stdio.h> 26#include <stdlib.h> 27#include <string.h> 28#include <stdarg.h> 29 30#include "common/gen_gem.h" 31#include "util/macros.h" 32 33#include "aub_read.h" 34#include "intel_aub.h" 35 36#define TYPE(dw) (((dw) >> 29) & 7) 37#define OPCODE(dw) (((dw) >> 23) & 0x3f) 38#define SUBOPCODE(dw) (((dw) >> 16) & 0x7f) 39 40#define MAKE_HEADER(type, opcode, subopcode) \ 41 (((type) << 29) | ((opcode) << 23) | ((subopcode) << 16)) 42 43#define TYPE_AUB 0x7 44 45/* Classic AUB opcodes */ 46#define OPCODE_AUB 0x01 47#define SUBOPCODE_HEADER 0x05 48#define SUBOPCODE_BLOCK 0x41 49#define SUBOPCODE_BMP 0x1e 50 51/* Newer version AUB opcode */ 52#define OPCODE_NEW_AUB 0x2e 53#define SUBOPCODE_REG_POLL 0x02 54#define SUBOPCODE_REG_WRITE 0x03 55#define SUBOPCODE_MEM_POLL 0x05 56#define SUBOPCODE_MEM_WRITE 0x06 57#define SUBOPCODE_VERSION 0x0e 58 59#define MAKE_GEN(major, minor) (((major) << 8) | (minor)) 60 61static void 62parse_error(struct aub_read *read, const uint32_t *p, const char *fmt, ...) 63{ 64 if (!read->error) 65 return; 66 67 va_list ap; 68 va_start(ap, fmt); 69 70 char msg[80]; 71 vsnprintf(msg, sizeof(msg), fmt, ap); 72 read->error(read->user_data, p, msg); 73 74 va_end(ap); 75} 76 77static bool 78handle_trace_header(struct aub_read *read, const uint32_t *p) 79{ 80 /* The intel_aubdump tool from IGT is kind enough to put a PCI-ID= tag in 81 * the AUB header comment. If the user hasn't specified a hardware 82 * generation, try to use the one from the AUB file. 83 */ 84 const uint32_t *end = p + (p[0] & 0xffff) + 2; 85 int aub_pci_id = 0; 86 87 if (end > &p[12] && p[12] > 0) { 88 if (sscanf((char *)&p[13], "PCI-ID=%i", &aub_pci_id) > 0) { 89 if (!gen_get_device_info(aub_pci_id, &read->devinfo)) { 90 parse_error(read, p, 91 "can't find device information: pci_id=0x%x\n", aub_pci_id); 92 return false; 93 } 94 } 95 } 96 97 char app_name[33]; 98 strncpy(app_name, (const char *)&p[2], 32); 99 app_name[32] = 0; 100 101 if (read->info) 102 read->info(read->user_data, aub_pci_id, app_name); 103 104 return true; 105} 106 107static bool 108handle_memtrace_version(struct aub_read *read, const uint32_t *p) 109{ 110 int header_length = p[0] & 0xffff; 111 char app_name[64]; 112 int app_name_len = MIN2(4 * (header_length + 1 - 5), ARRAY_SIZE(app_name) - 1); 113 int pci_id_len = 0; 114 int aub_pci_id = 0; 115 116 strncpy(app_name, (const char *)&p[5], app_name_len); 117 app_name[app_name_len] = 0; 118 119 if (sscanf(app_name, "PCI-ID=%i %n", &aub_pci_id, &pci_id_len) > 0) { 120 if (!gen_get_device_info(aub_pci_id, &read->devinfo)) { 121 parse_error(read, p, "can't find device information: pci_id=0x%x\n", aub_pci_id); 122 return false; 123 } 124 125 if (read->info) 126 read->info(read->user_data, aub_pci_id, app_name + pci_id_len); 127 } 128 129 return true; 130} 131 132static bool 133handle_trace_block(struct aub_read *read, const uint32_t *p) 134{ 135 int operation = p[1] & AUB_TRACE_OPERATION_MASK; 136 int type = p[1] & AUB_TRACE_TYPE_MASK; 137 int address_space = p[1] & AUB_TRACE_ADDRESS_SPACE_MASK; 138 int header_length = p[0] & 0xffff; 139 int engine = GEN_ENGINE_RENDER; 140 const void *data = p + header_length + 2; 141 uint64_t address = gen_48b_address((read->devinfo.gen >= 8 ? ((uint64_t) p[5] << 32) : 0) | 142 ((uint64_t) p[3])); 143 uint32_t size = p[4]; 144 145 switch (operation) { 146 case AUB_TRACE_OP_DATA_WRITE: 147 if (address_space == AUB_TRACE_MEMTYPE_GTT) { 148 if (read->local_write) 149 read->local_write(read->user_data, address, data, size); 150 break; 151 case AUB_TRACE_OP_COMMAND_WRITE: 152 switch (type) { 153 case AUB_TRACE_TYPE_RING_PRB0: 154 engine = GEN_ENGINE_RENDER; 155 break; 156 case AUB_TRACE_TYPE_RING_PRB1: 157 engine = GEN_ENGINE_VIDEO; 158 break; 159 case AUB_TRACE_TYPE_RING_PRB2: 160 engine = GEN_ENGINE_BLITTER; 161 break; 162 default: 163 parse_error(read, p, "command write to unknown ring %d\n", type); 164 return false; 165 } 166 167 if (read->ring_write) 168 read->ring_write(read->user_data, engine, data, size); 169 break; 170 } 171 } 172 173 return true; 174} 175 176static void 177handle_memtrace_reg_write(struct aub_read *read, const uint32_t *p) 178{ 179 uint32_t offset = p[1]; 180 uint32_t value = p[5]; 181 182 if (read->reg_write) 183 read->reg_write(read->user_data, offset, value); 184 185 int engine; 186 uint64_t context_descriptor; 187 188 switch (offset) { 189 case 0x2230: /* render elsp */ 190 read->render_elsp[read->render_elsp_index++] = value; 191 if (read->render_elsp_index < 4) 192 return; 193 194 read->render_elsp_index = 0; 195 engine = GEN_ENGINE_RENDER; 196 context_descriptor = (uint64_t)read->render_elsp[2] << 32 | 197 read->render_elsp[3]; 198 break; 199 case 0x12230: /* video elsp */ 200 read->video_elsp[read->video_elsp_index++] = value; 201 if (read->video_elsp_index < 4) 202 return; 203 204 read->video_elsp_index = 0; 205 engine = GEN_ENGINE_VIDEO; 206 context_descriptor = (uint64_t)read->video_elsp[2] << 32 | 207 read->video_elsp[3]; 208 break; 209 case 0x22230: /* blitter elsp */ 210 read->blitter_elsp[read->blitter_elsp_index++] = value; 211 if (read->blitter_elsp_index < 4) 212 return; 213 214 read->blitter_elsp_index = 0; 215 engine = GEN_ENGINE_BLITTER; 216 context_descriptor = (uint64_t)read->blitter_elsp[2] << 32 | 217 read->blitter_elsp[3]; 218 break; 219 case 0x2510: /* render elsq0 lo */ 220 read->render_elsp[3] = value; 221 return; 222 break; 223 case 0x2514: /* render elsq0 hi */ 224 read->render_elsp[2] = value; 225 return; 226 break; 227 case 0x12510: /* video elsq0 lo */ 228 read->video_elsp[3] = value; 229 return; 230 break; 231 case 0x12514: /* video elsq0 hi */ 232 read->video_elsp[2] = value; 233 return; 234 break; 235 case 0x22510: /* blitter elsq0 lo */ 236 read->blitter_elsp[3] = value; 237 return; 238 break; 239 case 0x22514: /* blitter elsq0 hi */ 240 read->blitter_elsp[2] = value; 241 return; 242 break; 243 case 0x2550: /* render elsc */ 244 engine = GEN_ENGINE_RENDER; 245 context_descriptor = (uint64_t)read->render_elsp[2] << 32 | 246 read->render_elsp[3]; 247 break; 248 case 0x12550: /* video_elsc */ 249 engine = GEN_ENGINE_VIDEO; 250 context_descriptor = (uint64_t)read->video_elsp[2] << 32 | 251 read->video_elsp[3]; 252 break; 253 case 0x22550: /* blitter elsc */ 254 engine = GEN_ENGINE_BLITTER; 255 context_descriptor = (uint64_t)read->blitter_elsp[2] << 32 | 256 read->blitter_elsp[3]; 257 break; 258 default: 259 return; 260 } 261 262 if (read->execlist_write) 263 read->execlist_write(read->user_data, engine, context_descriptor); 264} 265 266static void 267handle_memtrace_mem_write(struct aub_read *read, const uint32_t *p) 268{ 269 const void *data = p + 5; 270 uint64_t addr = gen_48b_address(*(uint64_t*)&p[1]); 271 uint32_t size = p[4]; 272 uint32_t address_space = p[3] >> 28; 273 274 switch (address_space) { 275 case 0: /* GGTT */ 276 if (read->ggtt_write) 277 read->ggtt_write(read->user_data, addr, data, size); 278 break; 279 case 1: /* Local */ 280 if (read->local_write) 281 read->local_write(read->user_data, addr, data, size); 282 break; 283 case 2: /* Physical */ 284 if (read->phys_write) 285 read->phys_write(read->user_data, addr, data, size); 286 break; 287 case 4: /* GGTT Entry */ 288 if (read->ggtt_entry_write) 289 read->ggtt_entry_write(read->user_data, addr, data, size); 290 break; 291 } 292} 293 294int 295aub_read_command(struct aub_read *read, const void *data, uint32_t data_len) 296{ 297 const uint32_t *p = data, *end = data + data_len, *next; 298 uint32_t h, header_length, bias; 299 300 assert(data_len >= 4); 301 302 h = *p; 303 header_length = h & 0xffff; 304 305 switch (OPCODE(h)) { 306 case OPCODE_AUB: 307 bias = 2; 308 break; 309 case OPCODE_NEW_AUB: 310 bias = 1; 311 break; 312 default: 313 parse_error(read, data, "unknown opcode %d\n", OPCODE(h)); 314 return -1; 315 } 316 317 next = p + header_length + bias; 318 if ((h & 0xffff0000) == MAKE_HEADER(TYPE_AUB, OPCODE_AUB, SUBOPCODE_BLOCK)) { 319 assert(end - p >= 4); 320 next += p[4] / 4; 321 } 322 323 assert(next <= end); 324 325 switch (h & 0xffff0000) { 326 case MAKE_HEADER(TYPE_AUB, OPCODE_AUB, SUBOPCODE_HEADER): 327 if (!handle_trace_header(read, p)) 328 return -1; 329 break; 330 case MAKE_HEADER(TYPE_AUB, OPCODE_AUB, SUBOPCODE_BLOCK): 331 if (!handle_trace_block(read, p)) 332 return -1; 333 break; 334 case MAKE_HEADER(TYPE_AUB, OPCODE_AUB, SUBOPCODE_BMP): 335 break; 336 case MAKE_HEADER(TYPE_AUB, OPCODE_NEW_AUB, SUBOPCODE_VERSION): 337 if (!handle_memtrace_version(read, p)) 338 return -1; 339 break; 340 case MAKE_HEADER(TYPE_AUB, OPCODE_NEW_AUB, SUBOPCODE_REG_WRITE): 341 handle_memtrace_reg_write(read, p); 342 break; 343 case MAKE_HEADER(TYPE_AUB, OPCODE_NEW_AUB, SUBOPCODE_MEM_WRITE): 344 handle_memtrace_mem_write(read, p); 345 break; 346 case MAKE_HEADER(TYPE_AUB, OPCODE_NEW_AUB, SUBOPCODE_MEM_POLL): 347 /* fprintf(outfile, "memory poll block (dwords %d):\n", h & 0xffff); */ 348 break; 349 case MAKE_HEADER(TYPE_AUB, OPCODE_NEW_AUB, SUBOPCODE_REG_POLL): 350 break; 351 default: 352 parse_error(read, p, 353 "unknown block type=0x%x, opcode=0x%x, subopcode=0x%x (%08x)\n", 354 TYPE(h), OPCODE(h), SUBOPCODE(h), h); 355 return -1; 356 } 357 358 return (next - p) * sizeof(*p); 359} 360