ac_debug.c revision ed98bd31
1/* 2 * Copyright 2015 Advanced Micro Devices, Inc. 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 * on the rights to use, copy, modify, merge, publish, distribute, sub 8 * license, and/or sell copies of the Software, and to permit persons to whom 9 * the 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 NON-INFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 21 * USE OR OTHER DEALINGS IN THE SOFTWARE. 22 */ 23 24#include "ac_debug.h" 25 26#ifdef HAVE_VALGRIND 27#include <valgrind.h> 28#include <memcheck.h> 29#define VG(x) x 30#else 31#define VG(x) 32#endif 33 34#include <inttypes.h> 35 36#include "sid.h" 37#include "gfx9d.h" 38#include "sid_tables.h" 39#include "util/u_math.h" 40#include "util/u_memory.h" 41#include "util/u_string.h" 42 43#include <assert.h> 44 45/* Parsed IBs are difficult to read without colors. Use "less -R file" to 46 * read them, or use "aha -b -f file" to convert them to html. 47 */ 48#define COLOR_RESET "\033[0m" 49#define COLOR_RED "\033[31m" 50#define COLOR_GREEN "\033[1;32m" 51#define COLOR_YELLOW "\033[1;33m" 52#define COLOR_CYAN "\033[1;36m" 53 54#define INDENT_PKT 8 55 56struct ac_ib_parser { 57 FILE *f; 58 uint32_t *ib; 59 unsigned num_dw; 60 const int *trace_ids; 61 unsigned trace_id_count; 62 enum chip_class chip_class; 63 ac_debug_addr_callback addr_callback; 64 void *addr_callback_data; 65 66 unsigned cur_dw; 67}; 68 69static void ac_do_parse_ib(FILE *f, struct ac_ib_parser *ib); 70 71static void print_spaces(FILE *f, unsigned num) 72{ 73 fprintf(f, "%*s", num, ""); 74} 75 76static void print_value(FILE *file, uint32_t value, int bits) 77{ 78 /* Guess if it's int or float */ 79 if (value <= (1 << 15)) { 80 if (value <= 9) 81 fprintf(file, "%u\n", value); 82 else 83 fprintf(file, "%u (0x%0*x)\n", value, bits / 4, value); 84 } else { 85 float f = uif(value); 86 87 if (fabs(f) < 100000 && f*10 == floor(f*10)) 88 fprintf(file, "%.1ff (0x%0*x)\n", f, bits / 4, value); 89 else 90 /* Don't print more leading zeros than there are bits. */ 91 fprintf(file, "0x%0*x\n", bits / 4, value); 92 } 93} 94 95static void print_named_value(FILE *file, const char *name, uint32_t value, 96 int bits) 97{ 98 print_spaces(file, INDENT_PKT); 99 fprintf(file, COLOR_YELLOW "%s" COLOR_RESET " <- ", name); 100 print_value(file, value, bits); 101} 102 103static const struct si_reg *find_register(const struct si_reg *table, 104 unsigned table_size, 105 unsigned offset) 106{ 107 for (unsigned i = 0; i < table_size; i++) { 108 const struct si_reg *reg = &table[i]; 109 110 if (reg->offset == offset) 111 return reg; 112 } 113 114 return NULL; 115} 116 117void ac_dump_reg(FILE *file, enum chip_class chip_class, unsigned offset, 118 uint32_t value, uint32_t field_mask) 119{ 120 const struct si_reg *reg = NULL; 121 122 if (chip_class >= GFX9) 123 reg = find_register(gfx9d_reg_table, ARRAY_SIZE(gfx9d_reg_table), offset); 124 if (!reg) 125 reg = find_register(sid_reg_table, ARRAY_SIZE(sid_reg_table), offset); 126 127 if (reg) { 128 const char *reg_name = sid_strings + reg->name_offset; 129 bool first_field = true; 130 131 print_spaces(file, INDENT_PKT); 132 fprintf(file, COLOR_YELLOW "%s" COLOR_RESET " <- ", 133 reg_name); 134 135 if (!reg->num_fields) { 136 print_value(file, value, 32); 137 return; 138 } 139 140 for (unsigned f = 0; f < reg->num_fields; f++) { 141 const struct si_field *field = sid_fields_table + reg->fields_offset + f; 142 const int *values_offsets = sid_strings_offsets + field->values_offset; 143 uint32_t val = (value & field->mask) >> 144 (ffs(field->mask) - 1); 145 146 if (!(field->mask & field_mask)) 147 continue; 148 149 /* Indent the field. */ 150 if (!first_field) 151 print_spaces(file, 152 INDENT_PKT + strlen(reg_name) + 4); 153 154 /* Print the field. */ 155 fprintf(file, "%s = ", sid_strings + field->name_offset); 156 157 if (val < field->num_values && values_offsets[val] >= 0) 158 fprintf(file, "%s\n", sid_strings + values_offsets[val]); 159 else 160 print_value(file, val, 161 util_bitcount(field->mask)); 162 163 first_field = false; 164 } 165 return; 166 } 167 168 print_spaces(file, INDENT_PKT); 169 fprintf(file, COLOR_YELLOW "0x%05x" COLOR_RESET " <- 0x%08x\n", offset, value); 170} 171 172static uint32_t ac_ib_get(struct ac_ib_parser *ib) 173{ 174 uint32_t v = 0; 175 176 if (ib->cur_dw < ib->num_dw) { 177 v = ib->ib[ib->cur_dw]; 178#ifdef HAVE_VALGRIND 179 /* Help figure out where garbage data is written to IBs. 180 * 181 * Arguably we should do this already when the IBs are written, 182 * see RADEON_VALGRIND. The problem is that client-requests to 183 * Valgrind have an overhead even when Valgrind isn't running, 184 * and radeon_emit is performance sensitive... 185 */ 186 if (VALGRIND_CHECK_VALUE_IS_DEFINED(v)) 187 fprintf(ib->f, COLOR_RED "Valgrind: The next DWORD is garbage" 188 COLOR_RESET "\n"); 189#endif 190 fprintf(ib->f, "\n\035#%08x ", v); 191 } else { 192 fprintf(ib->f, "\n\035#???????? "); 193 } 194 195 ib->cur_dw++; 196 return v; 197} 198 199static void ac_parse_set_reg_packet(FILE *f, unsigned count, unsigned reg_offset, 200 struct ac_ib_parser *ib) 201{ 202 unsigned reg_dw = ac_ib_get(ib); 203 unsigned reg = ((reg_dw & 0xFFFF) << 2) + reg_offset; 204 unsigned index = reg_dw >> 28; 205 int i; 206 207 if (index != 0) { 208 print_spaces(f, INDENT_PKT); 209 fprintf(f, "INDEX = %u\n", index); 210 } 211 212 for (i = 0; i < count; i++) 213 ac_dump_reg(f, ib->chip_class, reg + i*4, ac_ib_get(ib), ~0); 214} 215 216static void ac_parse_packet3(FILE *f, uint32_t header, struct ac_ib_parser *ib, 217 int *current_trace_id) 218{ 219 unsigned first_dw = ib->cur_dw; 220 int count = PKT_COUNT_G(header); 221 unsigned op = PKT3_IT_OPCODE_G(header); 222 const char *predicate = PKT3_PREDICATE(header) ? "(predicate)" : ""; 223 int i; 224 225 /* Print the name first. */ 226 for (i = 0; i < ARRAY_SIZE(packet3_table); i++) 227 if (packet3_table[i].op == op) 228 break; 229 230 if (i < ARRAY_SIZE(packet3_table)) { 231 const char *name = sid_strings + packet3_table[i].name_offset; 232 233 if (op == PKT3_SET_CONTEXT_REG || 234 op == PKT3_SET_CONFIG_REG || 235 op == PKT3_SET_UCONFIG_REG || 236 op == PKT3_SET_UCONFIG_REG_INDEX || 237 op == PKT3_SET_SH_REG) 238 fprintf(f, COLOR_CYAN "%s%s" COLOR_CYAN ":\n", 239 name, predicate); 240 else 241 fprintf(f, COLOR_GREEN "%s%s" COLOR_RESET ":\n", 242 name, predicate); 243 } else 244 fprintf(f, COLOR_RED "PKT3_UNKNOWN 0x%x%s" COLOR_RESET ":\n", 245 op, predicate); 246 247 /* Print the contents. */ 248 switch (op) { 249 case PKT3_SET_CONTEXT_REG: 250 ac_parse_set_reg_packet(f, count, SI_CONTEXT_REG_OFFSET, ib); 251 break; 252 case PKT3_SET_CONFIG_REG: 253 ac_parse_set_reg_packet(f, count, SI_CONFIG_REG_OFFSET, ib); 254 break; 255 case PKT3_SET_UCONFIG_REG: 256 case PKT3_SET_UCONFIG_REG_INDEX: 257 ac_parse_set_reg_packet(f, count, CIK_UCONFIG_REG_OFFSET, ib); 258 break; 259 case PKT3_SET_SH_REG: 260 ac_parse_set_reg_packet(f, count, SI_SH_REG_OFFSET, ib); 261 break; 262 case PKT3_ACQUIRE_MEM: 263 ac_dump_reg(f, ib->chip_class, R_0301F0_CP_COHER_CNTL, ac_ib_get(ib), ~0); 264 ac_dump_reg(f, ib->chip_class, R_0301F4_CP_COHER_SIZE, ac_ib_get(ib), ~0); 265 ac_dump_reg(f, ib->chip_class, R_030230_CP_COHER_SIZE_HI, ac_ib_get(ib), ~0); 266 ac_dump_reg(f, ib->chip_class, R_0301F8_CP_COHER_BASE, ac_ib_get(ib), ~0); 267 ac_dump_reg(f, ib->chip_class, R_0301E4_CP_COHER_BASE_HI, ac_ib_get(ib), ~0); 268 print_named_value(f, "POLL_INTERVAL", ac_ib_get(ib), 16); 269 break; 270 case PKT3_SURFACE_SYNC: 271 if (ib->chip_class >= CIK) { 272 ac_dump_reg(f, ib->chip_class, R_0301F0_CP_COHER_CNTL, ac_ib_get(ib), ~0); 273 ac_dump_reg(f, ib->chip_class, R_0301F4_CP_COHER_SIZE, ac_ib_get(ib), ~0); 274 ac_dump_reg(f, ib->chip_class, R_0301F8_CP_COHER_BASE, ac_ib_get(ib), ~0); 275 } else { 276 ac_dump_reg(f, ib->chip_class, R_0085F0_CP_COHER_CNTL, ac_ib_get(ib), ~0); 277 ac_dump_reg(f, ib->chip_class, R_0085F4_CP_COHER_SIZE, ac_ib_get(ib), ~0); 278 ac_dump_reg(f, ib->chip_class, R_0085F8_CP_COHER_BASE, ac_ib_get(ib), ~0); 279 } 280 print_named_value(f, "POLL_INTERVAL", ac_ib_get(ib), 16); 281 break; 282 case PKT3_EVENT_WRITE: { 283 uint32_t event_dw = ac_ib_get(ib); 284 ac_dump_reg(f, ib->chip_class, R_028A90_VGT_EVENT_INITIATOR, event_dw, 285 S_028A90_EVENT_TYPE(~0)); 286 print_named_value(f, "EVENT_INDEX", (event_dw >> 8) & 0xf, 4); 287 print_named_value(f, "INV_L2", (event_dw >> 20) & 0x1, 1); 288 if (count > 0) { 289 print_named_value(f, "ADDRESS_LO", ac_ib_get(ib), 32); 290 print_named_value(f, "ADDRESS_HI", ac_ib_get(ib), 16); 291 } 292 break; 293 } 294 case PKT3_EVENT_WRITE_EOP: { 295 uint32_t event_dw = ac_ib_get(ib); 296 ac_dump_reg(f, ib->chip_class, R_028A90_VGT_EVENT_INITIATOR, event_dw, 297 S_028A90_EVENT_TYPE(~0)); 298 print_named_value(f, "EVENT_INDEX", (event_dw >> 8) & 0xf, 4); 299 print_named_value(f, "TCL1_VOL_ACTION_ENA", (event_dw >> 12) & 0x1, 1); 300 print_named_value(f, "TC_VOL_ACTION_ENA", (event_dw >> 13) & 0x1, 1); 301 print_named_value(f, "TC_WB_ACTION_ENA", (event_dw >> 15) & 0x1, 1); 302 print_named_value(f, "TCL1_ACTION_ENA", (event_dw >> 16) & 0x1, 1); 303 print_named_value(f, "TC_ACTION_ENA", (event_dw >> 17) & 0x1, 1); 304 print_named_value(f, "ADDRESS_LO", ac_ib_get(ib), 32); 305 uint32_t addr_hi_dw = ac_ib_get(ib); 306 print_named_value(f, "ADDRESS_HI", addr_hi_dw, 16); 307 print_named_value(f, "DST_SEL", (addr_hi_dw >> 16) & 0x3, 2); 308 print_named_value(f, "INT_SEL", (addr_hi_dw >> 24) & 0x7, 3); 309 print_named_value(f, "DATA_SEL", addr_hi_dw >> 29, 3); 310 print_named_value(f, "DATA_LO", ac_ib_get(ib), 32); 311 print_named_value(f, "DATA_HI", ac_ib_get(ib), 32); 312 break; 313 } 314 case PKT3_RELEASE_MEM: { 315 uint32_t event_dw = ac_ib_get(ib); 316 ac_dump_reg(f, ib->chip_class, R_028A90_VGT_EVENT_INITIATOR, event_dw, 317 S_028A90_EVENT_TYPE(~0)); 318 print_named_value(f, "EVENT_INDEX", (event_dw >> 8) & 0xf, 4); 319 print_named_value(f, "TCL1_VOL_ACTION_ENA", (event_dw >> 12) & 0x1, 1); 320 print_named_value(f, "TC_VOL_ACTION_ENA", (event_dw >> 13) & 0x1, 1); 321 print_named_value(f, "TC_WB_ACTION_ENA", (event_dw >> 15) & 0x1, 1); 322 print_named_value(f, "TCL1_ACTION_ENA", (event_dw >> 16) & 0x1, 1); 323 print_named_value(f, "TC_ACTION_ENA", (event_dw >> 17) & 0x1, 1); 324 print_named_value(f, "TC_NC_ACTION_ENA", (event_dw >> 19) & 0x1, 1); 325 print_named_value(f, "TC_WC_ACTION_ENA", (event_dw >> 20) & 0x1, 1); 326 print_named_value(f, "TC_MD_ACTION_ENA", (event_dw >> 21) & 0x1, 1); 327 uint32_t sel_dw = ac_ib_get(ib); 328 print_named_value(f, "DST_SEL", (sel_dw >> 16) & 0x3, 2); 329 print_named_value(f, "INT_SEL", (sel_dw >> 24) & 0x7, 3); 330 print_named_value(f, "DATA_SEL", sel_dw >> 29, 3); 331 print_named_value(f, "ADDRESS_LO", ac_ib_get(ib), 32); 332 print_named_value(f, "ADDRESS_HI", ac_ib_get(ib), 32); 333 print_named_value(f, "DATA_LO", ac_ib_get(ib), 32); 334 print_named_value(f, "DATA_HI", ac_ib_get(ib), 32); 335 print_named_value(f, "CTXID", ac_ib_get(ib), 32); 336 break; 337 } 338 case PKT3_WAIT_REG_MEM: 339 print_named_value(f, "OP", ac_ib_get(ib), 32); 340 print_named_value(f, "ADDRESS_LO", ac_ib_get(ib), 32); 341 print_named_value(f, "ADDRESS_HI", ac_ib_get(ib), 32); 342 print_named_value(f, "REF", ac_ib_get(ib), 32); 343 print_named_value(f, "MASK", ac_ib_get(ib), 32); 344 print_named_value(f, "POLL_INTERVAL", ac_ib_get(ib), 16); 345 break; 346 case PKT3_DRAW_INDEX_AUTO: 347 ac_dump_reg(f, ib->chip_class, R_030930_VGT_NUM_INDICES, ac_ib_get(ib), ~0); 348 ac_dump_reg(f, ib->chip_class, R_0287F0_VGT_DRAW_INITIATOR, ac_ib_get(ib), ~0); 349 break; 350 case PKT3_DRAW_INDEX_2: 351 ac_dump_reg(f, ib->chip_class, R_028A78_VGT_DMA_MAX_SIZE, ac_ib_get(ib), ~0); 352 ac_dump_reg(f, ib->chip_class, R_0287E8_VGT_DMA_BASE, ac_ib_get(ib), ~0); 353 ac_dump_reg(f, ib->chip_class, R_0287E4_VGT_DMA_BASE_HI, ac_ib_get(ib), ~0); 354 ac_dump_reg(f, ib->chip_class, R_030930_VGT_NUM_INDICES, ac_ib_get(ib), ~0); 355 ac_dump_reg(f, ib->chip_class, R_0287F0_VGT_DRAW_INITIATOR, ac_ib_get(ib), ~0); 356 break; 357 case PKT3_INDEX_TYPE: 358 ac_dump_reg(f, ib->chip_class, R_028A7C_VGT_DMA_INDEX_TYPE, ac_ib_get(ib), ~0); 359 break; 360 case PKT3_NUM_INSTANCES: 361 ac_dump_reg(f, ib->chip_class, R_030934_VGT_NUM_INSTANCES, ac_ib_get(ib), ~0); 362 break; 363 case PKT3_WRITE_DATA: 364 ac_dump_reg(f, ib->chip_class, R_370_CONTROL, ac_ib_get(ib), ~0); 365 ac_dump_reg(f, ib->chip_class, R_371_DST_ADDR_LO, ac_ib_get(ib), ~0); 366 ac_dump_reg(f, ib->chip_class, R_372_DST_ADDR_HI, ac_ib_get(ib), ~0); 367 /* The payload is written automatically */ 368 break; 369 case PKT3_CP_DMA: 370 ac_dump_reg(f, ib->chip_class, R_410_CP_DMA_WORD0, ac_ib_get(ib), ~0); 371 ac_dump_reg(f, ib->chip_class, R_411_CP_DMA_WORD1, ac_ib_get(ib), ~0); 372 ac_dump_reg(f, ib->chip_class, R_412_CP_DMA_WORD2, ac_ib_get(ib), ~0); 373 ac_dump_reg(f, ib->chip_class, R_413_CP_DMA_WORD3, ac_ib_get(ib), ~0); 374 ac_dump_reg(f, ib->chip_class, R_414_COMMAND, ac_ib_get(ib), ~0); 375 break; 376 case PKT3_DMA_DATA: 377 ac_dump_reg(f, ib->chip_class, R_500_DMA_DATA_WORD0, ac_ib_get(ib), ~0); 378 ac_dump_reg(f, ib->chip_class, R_501_SRC_ADDR_LO, ac_ib_get(ib), ~0); 379 ac_dump_reg(f, ib->chip_class, R_502_SRC_ADDR_HI, ac_ib_get(ib), ~0); 380 ac_dump_reg(f, ib->chip_class, R_503_DST_ADDR_LO, ac_ib_get(ib), ~0); 381 ac_dump_reg(f, ib->chip_class, R_504_DST_ADDR_HI, ac_ib_get(ib), ~0); 382 ac_dump_reg(f, ib->chip_class, R_414_COMMAND, ac_ib_get(ib), ~0); 383 break; 384 case PKT3_INDIRECT_BUFFER_SI: 385 case PKT3_INDIRECT_BUFFER_CONST: 386 case PKT3_INDIRECT_BUFFER_CIK: { 387 uint32_t base_lo_dw = ac_ib_get(ib); 388 ac_dump_reg(f, ib->chip_class, R_3F0_IB_BASE_LO, base_lo_dw, ~0); 389 uint32_t base_hi_dw = ac_ib_get(ib); 390 ac_dump_reg(f, ib->chip_class, R_3F1_IB_BASE_HI, base_hi_dw, ~0); 391 uint32_t control_dw = ac_ib_get(ib); 392 ac_dump_reg(f, ib->chip_class, R_3F2_CONTROL, control_dw, ~0); 393 394 if (!ib->addr_callback) 395 break; 396 397 uint64_t addr = ((uint64_t)base_hi_dw << 32) | base_lo_dw; 398 void *data = ib->addr_callback(ib->addr_callback_data, addr); 399 if (!data) 400 break; 401 402 if (G_3F2_CHAIN(control_dw)) { 403 ib->ib = data; 404 ib->num_dw = G_3F2_IB_SIZE(control_dw); 405 ib->cur_dw = 0; 406 return; 407 } 408 409 struct ac_ib_parser ib_recurse; 410 memcpy(&ib_recurse, ib, sizeof(ib_recurse)); 411 ib_recurse.ib = data; 412 ib_recurse.num_dw = G_3F2_IB_SIZE(control_dw); 413 ib_recurse.cur_dw = 0; 414 if(ib_recurse.trace_id_count) { 415 if (*current_trace_id == *ib->trace_ids) { 416 ++ib_recurse.trace_ids; 417 --ib_recurse.trace_id_count; 418 } else { 419 ib_recurse.trace_id_count = 0; 420 } 421 } 422 423 fprintf(f, "\n\035>------------------ nested begin ------------------\n"); 424 ac_do_parse_ib(f, &ib_recurse); 425 fprintf(f, "\n\035<------------------- nested end -------------------\n"); 426 break; 427 } 428 case PKT3_CLEAR_STATE: 429 case PKT3_INCREMENT_DE_COUNTER: 430 case PKT3_PFP_SYNC_ME: 431 break; 432 case PKT3_NOP: 433 if (header == 0xffff1000) { 434 count = -1; /* One dword NOP. */ 435 } else if (count == 0 && ib->cur_dw < ib->num_dw && 436 AC_IS_TRACE_POINT(ib->ib[ib->cur_dw])) { 437 unsigned packet_id = AC_GET_TRACE_POINT_ID(ib->ib[ib->cur_dw]); 438 439 print_spaces(f, INDENT_PKT); 440 fprintf(f, COLOR_RED "Trace point ID: %u\n", packet_id); 441 442 if (!ib->trace_id_count) 443 break; /* tracing was disabled */ 444 445 *current_trace_id = packet_id; 446 447 print_spaces(f, INDENT_PKT); 448 if (packet_id < *ib->trace_ids) 449 fprintf(f, COLOR_RED 450 "This trace point was reached by the CP." 451 COLOR_RESET "\n"); 452 else if (packet_id == *ib->trace_ids) 453 fprintf(f, COLOR_RED 454 "!!!!! This is the last trace point that " 455 "was reached by the CP !!!!!" 456 COLOR_RESET "\n"); 457 else if (packet_id+1 == *ib->trace_ids) 458 fprintf(f, COLOR_RED 459 "!!!!! This is the first trace point that " 460 "was NOT been reached by the CP !!!!!" 461 COLOR_RESET "\n"); 462 else 463 fprintf(f, COLOR_RED 464 "!!!!! This trace point was NOT reached " 465 "by the CP !!!!!" 466 COLOR_RESET "\n"); 467 break; 468 } 469 break; 470 } 471 472 /* print additional dwords */ 473 while (ib->cur_dw <= first_dw + count) 474 ac_ib_get(ib); 475 476 if (ib->cur_dw > first_dw + count + 1) 477 fprintf(f, COLOR_RED "\n!!!!! count in header too low !!!!!" 478 COLOR_RESET "\n"); 479} 480 481/** 482 * Parse and print an IB into a file. 483 */ 484static void ac_do_parse_ib(FILE *f, struct ac_ib_parser *ib) 485{ 486 int current_trace_id = -1; 487 488 while (ib->cur_dw < ib->num_dw) { 489 uint32_t header = ac_ib_get(ib); 490 unsigned type = PKT_TYPE_G(header); 491 492 switch (type) { 493 case 3: 494 ac_parse_packet3(f, header, ib, ¤t_trace_id); 495 break; 496 case 2: 497 /* type-2 nop */ 498 if (header == 0x80000000) { 499 fprintf(f, COLOR_GREEN "NOP (type 2)" COLOR_RESET "\n"); 500 break; 501 } 502 /* fall through */ 503 default: 504 fprintf(f, "Unknown packet type %i\n", type); 505 break; 506 } 507 } 508} 509 510static void format_ib_output(FILE *f, char *out) 511{ 512 unsigned depth = 0; 513 514 for (;;) { 515 char op = 0; 516 517 if (out[0] == '\n' && out[1] == '\035') 518 out++; 519 if (out[0] == '\035') { 520 op = out[1]; 521 out += 2; 522 } 523 524 if (op == '<') 525 depth--; 526 527 unsigned indent = 4 * depth; 528 if (op != '#') 529 indent += 9; 530 531 if (indent) 532 print_spaces(f, indent); 533 534 char *end = util_strchrnul(out, '\n'); 535 fwrite(out, end - out, 1, f); 536 fputc('\n', f); /* always end with a new line */ 537 if (!*end) 538 break; 539 540 out = end + 1; 541 542 if (op == '>') 543 depth++; 544 } 545} 546 547/** 548 * Parse and print an IB into a file. 549 * 550 * \param f file 551 * \param ib_ptr IB 552 * \param num_dw size of the IB 553 * \param chip_class chip class 554 * \param trace_ids the last trace IDs that are known to have been reached 555 * and executed by the CP, typically read from a buffer 556 * \param trace_id_count The number of entries in the trace_ids array. 557 * \param addr_callback Get a mapped pointer of the IB at a given address. Can 558 * be NULL. 559 * \param addr_callback_data user data for addr_callback 560 */ 561void ac_parse_ib_chunk(FILE *f, uint32_t *ib_ptr, int num_dw, const int *trace_ids, 562 unsigned trace_id_count, enum chip_class chip_class, 563 ac_debug_addr_callback addr_callback, void *addr_callback_data) 564{ 565 struct ac_ib_parser ib = {}; 566 ib.ib = ib_ptr; 567 ib.num_dw = num_dw; 568 ib.trace_ids = trace_ids; 569 ib.trace_id_count = trace_id_count; 570 ib.chip_class = chip_class; 571 ib.addr_callback = addr_callback; 572 ib.addr_callback_data = addr_callback_data; 573 574 char *out; 575 size_t outsize; 576 FILE *memf = open_memstream(&out, &outsize); 577 ib.f = memf; 578 ac_do_parse_ib(memf, &ib); 579 fclose(memf); 580 581 if (out) { 582 format_ib_output(f, out); 583 free(out); 584 } 585 586 if (ib.cur_dw > ib.num_dw) { 587 printf("\nPacket ends after the end of IB.\n"); 588 exit(1); 589 } 590} 591 592/** 593 * Parse and print an IB into a file. 594 * 595 * \param f file 596 * \param ib IB 597 * \param num_dw size of the IB 598 * \param chip_class chip class 599 * \param trace_ids the last trace IDs that are known to have been reached 600 * and executed by the CP, typically read from a buffer 601 * \param trace_id_count The number of entries in the trace_ids array. 602 * \param addr_callback Get a mapped pointer of the IB at a given address. Can 603 * be NULL. 604 * \param addr_callback_data user data for addr_callback 605 */ 606void ac_parse_ib(FILE *f, uint32_t *ib, int num_dw, const int *trace_ids, 607 unsigned trace_id_count, const char *name, 608 enum chip_class chip_class, ac_debug_addr_callback addr_callback, 609 void *addr_callback_data) 610{ 611 fprintf(f, "------------------ %s begin ------------------\n", name); 612 613 ac_parse_ib_chunk(f, ib, num_dw, trace_ids, trace_id_count, 614 chip_class, addr_callback, addr_callback_data); 615 616 fprintf(f, "------------------- %s end -------------------\n\n", name); 617} 618 619/** 620 * Parse dmesg and return TRUE if a VM fault has been detected. 621 * 622 * \param chip_class chip class 623 * \param old_dmesg_timestamp previous dmesg timestamp parsed at init time 624 * \param out_addr detected VM fault addr 625 */ 626bool ac_vm_fault_occured(enum chip_class chip_class, 627 uint64_t *old_dmesg_timestamp, uint64_t *out_addr) 628{ 629 char line[2000]; 630 unsigned sec, usec; 631 int progress = 0; 632 uint64_t dmesg_timestamp = 0; 633 bool fault = false; 634 635 FILE *p = popen("dmesg", "r"); 636 if (!p) 637 return false; 638 639 while (fgets(line, sizeof(line), p)) { 640 char *msg, len; 641 642 if (!line[0] || line[0] == '\n') 643 continue; 644 645 /* Get the timestamp. */ 646 if (sscanf(line, "[%u.%u]", &sec, &usec) != 2) { 647 static bool hit = false; 648 if (!hit) { 649 fprintf(stderr, "%s: failed to parse line '%s'\n", 650 __func__, line); 651 hit = true; 652 } 653 continue; 654 } 655 dmesg_timestamp = sec * 1000000ull + usec; 656 657 /* If just updating the timestamp. */ 658 if (!out_addr) 659 continue; 660 661 /* Process messages only if the timestamp is newer. */ 662 if (dmesg_timestamp <= *old_dmesg_timestamp) 663 continue; 664 665 /* Only process the first VM fault. */ 666 if (fault) 667 continue; 668 669 /* Remove trailing \n */ 670 len = strlen(line); 671 if (len && line[len-1] == '\n') 672 line[len-1] = 0; 673 674 /* Get the message part. */ 675 msg = strchr(line, ']'); 676 if (!msg) 677 continue; 678 msg++; 679 680 const char *header_line, *addr_line_prefix, *addr_line_format; 681 682 if (chip_class >= GFX9) { 683 /* Match this: 684 * ..: [gfxhub] VMC page fault (src_id:0 ring:158 vm_id:2 pas_id:0) 685 * ..: at page 0x0000000219f8f000 from 27 686 * ..: VM_L2_PROTECTION_FAULT_STATUS:0x0020113C 687 */ 688 header_line = "VMC page fault"; 689 addr_line_prefix = " at page"; 690 addr_line_format = "%"PRIx64; 691 } else { 692 header_line = "GPU fault detected:"; 693 addr_line_prefix = "VM_CONTEXT1_PROTECTION_FAULT_ADDR"; 694 addr_line_format = "%"PRIX64; 695 } 696 697 switch (progress) { 698 case 0: 699 if (strstr(msg, header_line)) 700 progress = 1; 701 break; 702 case 1: 703 msg = strstr(msg, addr_line_prefix); 704 if (msg) { 705 msg = strstr(msg, "0x"); 706 if (msg) { 707 msg += 2; 708 if (sscanf(msg, addr_line_format, out_addr) == 1) 709 fault = true; 710 } 711 } 712 progress = 0; 713 break; 714 default: 715 progress = 0; 716 } 717 } 718 pclose(p); 719 720 if (dmesg_timestamp > *old_dmesg_timestamp) 721 *old_dmesg_timestamp = dmesg_timestamp; 722 723 return fault; 724} 725 726static int compare_wave(const void *p1, const void *p2) 727{ 728 struct ac_wave_info *w1 = (struct ac_wave_info *)p1; 729 struct ac_wave_info *w2 = (struct ac_wave_info *)p2; 730 731 /* Sort waves according to PC and then SE, SH, CU, etc. */ 732 if (w1->pc < w2->pc) 733 return -1; 734 if (w1->pc > w2->pc) 735 return 1; 736 if (w1->se < w2->se) 737 return -1; 738 if (w1->se > w2->se) 739 return 1; 740 if (w1->sh < w2->sh) 741 return -1; 742 if (w1->sh > w2->sh) 743 return 1; 744 if (w1->cu < w2->cu) 745 return -1; 746 if (w1->cu > w2->cu) 747 return 1; 748 if (w1->simd < w2->simd) 749 return -1; 750 if (w1->simd > w2->simd) 751 return 1; 752 if (w1->wave < w2->wave) 753 return -1; 754 if (w1->wave > w2->wave) 755 return 1; 756 757 return 0; 758} 759 760/* Return wave information. "waves" should be a large enough array. */ 761unsigned ac_get_wave_info(struct ac_wave_info waves[AC_MAX_WAVES_PER_CHIP]) 762{ 763 char line[2000]; 764 unsigned num_waves = 0; 765 766 FILE *p = popen("umr -O halt_waves -wa", "r"); 767 if (!p) 768 return 0; 769 770 if (!fgets(line, sizeof(line), p) || 771 strncmp(line, "SE", 2) != 0) { 772 pclose(p); 773 return 0; 774 } 775 776 while (fgets(line, sizeof(line), p)) { 777 struct ac_wave_info *w; 778 uint32_t pc_hi, pc_lo, exec_hi, exec_lo; 779 780 assert(num_waves < AC_MAX_WAVES_PER_CHIP); 781 w = &waves[num_waves]; 782 783 if (sscanf(line, "%u %u %u %u %u %x %x %x %x %x %x %x", 784 &w->se, &w->sh, &w->cu, &w->simd, &w->wave, 785 &w->status, &pc_hi, &pc_lo, &w->inst_dw0, 786 &w->inst_dw1, &exec_hi, &exec_lo) == 12) { 787 w->pc = ((uint64_t)pc_hi << 32) | pc_lo; 788 w->exec = ((uint64_t)exec_hi << 32) | exec_lo; 789 w->matched = false; 790 num_waves++; 791 } 792 } 793 794 qsort(waves, num_waves, sizeof(struct ac_wave_info), compare_wave); 795 796 pclose(p); 797 return num_waves; 798} 799