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 * Authors: 24 * Marek Olk <maraeo (at) gmail.com> 25 */ 26 27 #include "ac_debug.h" 28 29 #include "sid.h" 30 #include "sid_tables.h" 31 #include "util/u_math.h" 32 #include "util/u_memory.h" 33 34 /* Parsed IBs are difficult to read without colors. Use "less -R file" to 35 * read them, or use "aha -b -f file" to convert them to html. 36 */ 37 #define COLOR_RESET "\033[0m" 38 #define COLOR_RED "\033[31m" 39 #define COLOR_GREEN "\033[1;32m" 40 #define COLOR_YELLOW "\033[1;33m" 41 #define COLOR_CYAN "\033[1;36m" 42 43 #define INDENT_PKT 8 44 45 static void print_spaces(FILE *f, unsigned num) 46 { 47 fprintf(f, "%*s", num, ""); 48 } 49 50 static void print_value(FILE *file, uint32_t value, int bits) 51 { 52 /* Guess if it's int or float */ 53 if (value <= (1 << 15)) { 54 if (value <= 9) 55 fprintf(file, "%u\n", value); 56 else 57 fprintf(file, "%u (0x%0*x)\n", value, bits / 4, value); 58 } else { 59 float f = uif(value); 60 61 if (fabs(f) < 100000 && f*10 == floor(f*10)) 62 fprintf(file, "%.1ff (0x%0*x)\n", f, bits / 4, value); 63 else 64 /* Don't print more leading zeros than there are bits. */ 65 fprintf(file, "0x%0*x\n", bits / 4, value); 66 } 67 } 68 69 static void print_named_value(FILE *file, const char *name, uint32_t value, 70 int bits) 71 { 72 print_spaces(file, INDENT_PKT); 73 fprintf(file, COLOR_YELLOW "%s" COLOR_RESET " <- ", name); 74 print_value(file, value, bits); 75 } 76 77 void ac_dump_reg(FILE *file, unsigned offset, uint32_t value, 78 uint32_t field_mask) 79 { 80 int r, f; 81 82 for (r = 0; r < ARRAY_SIZE(sid_reg_table); r++) { 83 const struct si_reg *reg = &sid_reg_table[r]; 84 const char *reg_name = sid_strings + reg->name_offset; 85 86 if (reg->offset == offset) { 87 bool first_field = true; 88 89 print_spaces(file, INDENT_PKT); 90 fprintf(file, COLOR_YELLOW "%s" COLOR_RESET " <- ", 91 reg_name); 92 93 if (!reg->num_fields) { 94 print_value(file, value, 32); 95 return; 96 } 97 98 for (f = 0; f < reg->num_fields; f++) { 99 const struct si_field *field = sid_fields_table + reg->fields_offset + f; 100 const int *values_offsets = sid_strings_offsets + field->values_offset; 101 uint32_t val = (value & field->mask) >> 102 (ffs(field->mask) - 1); 103 104 if (!(field->mask & field_mask)) 105 continue; 106 107 /* Indent the field. */ 108 if (!first_field) 109 print_spaces(file, 110 INDENT_PKT + strlen(reg_name) + 4); 111 112 /* Print the field. */ 113 fprintf(file, "%s = ", sid_strings + field->name_offset); 114 115 if (val < field->num_values && values_offsets[val] >= 0) 116 fprintf(file, "%s\n", sid_strings + values_offsets[val]); 117 else 118 print_value(file, val, 119 util_bitcount(field->mask)); 120 121 first_field = false; 122 } 123 return; 124 } 125 } 126 127 print_spaces(file, INDENT_PKT); 128 fprintf(file, COLOR_YELLOW "0x%05x" COLOR_RESET " <- 0x%08x\n", offset, value); 129 } 130 131 static void ac_parse_set_reg_packet(FILE *f, uint32_t *ib, unsigned count, 132 unsigned reg_offset) 133 { 134 unsigned reg = (ib[1] << 2) + reg_offset; 135 int i; 136 137 for (i = 0; i < count; i++) 138 ac_dump_reg(f, reg + i*4, ib[2+i], ~0); 139 } 140 141 static uint32_t *ac_parse_packet3(FILE *f, uint32_t *ib, int *num_dw, 142 int trace_id, enum chip_class chip_class, 143 ac_debug_addr_callback addr_callback, 144 void *addr_callback_data) 145 { 146 unsigned count = PKT_COUNT_G(ib[0]); 147 unsigned op = PKT3_IT_OPCODE_G(ib[0]); 148 const char *predicate = PKT3_PREDICATE(ib[0]) ? "(predicate)" : ""; 149 int i; 150 151 /* Print the name first. */ 152 for (i = 0; i < ARRAY_SIZE(packet3_table); i++) 153 if (packet3_table[i].op == op) 154 break; 155 156 if (i < ARRAY_SIZE(packet3_table)) { 157 const char *name = sid_strings + packet3_table[i].name_offset; 158 159 if (op == PKT3_SET_CONTEXT_REG || 160 op == PKT3_SET_CONFIG_REG || 161 op == PKT3_SET_UCONFIG_REG || 162 op == PKT3_SET_SH_REG) 163 fprintf(f, COLOR_CYAN "%s%s" COLOR_CYAN ":\n", 164 name, predicate); 165 else 166 fprintf(f, COLOR_GREEN "%s%s" COLOR_RESET ":\n", 167 name, predicate); 168 } else 169 fprintf(f, COLOR_RED "PKT3_UNKNOWN 0x%x%s" COLOR_RESET ":\n", 170 op, predicate); 171 172 /* Print the contents. */ 173 switch (op) { 174 case PKT3_SET_CONTEXT_REG: 175 ac_parse_set_reg_packet(f, ib, count, SI_CONTEXT_REG_OFFSET); 176 break; 177 case PKT3_SET_CONFIG_REG: 178 ac_parse_set_reg_packet(f, ib, count, SI_CONFIG_REG_OFFSET); 179 break; 180 case PKT3_SET_UCONFIG_REG: 181 ac_parse_set_reg_packet(f, ib, count, CIK_UCONFIG_REG_OFFSET); 182 break; 183 case PKT3_SET_SH_REG: 184 ac_parse_set_reg_packet(f, ib, count, SI_SH_REG_OFFSET); 185 break; 186 case PKT3_ACQUIRE_MEM: 187 ac_dump_reg(f, R_0301F0_CP_COHER_CNTL, ib[1], ~0); 188 ac_dump_reg(f, R_0301F4_CP_COHER_SIZE, ib[2], ~0); 189 ac_dump_reg(f, R_030230_CP_COHER_SIZE_HI, ib[3], ~0); 190 ac_dump_reg(f, R_0301F8_CP_COHER_BASE, ib[4], ~0); 191 ac_dump_reg(f, R_0301E4_CP_COHER_BASE_HI, ib[5], ~0); 192 print_named_value(f, "POLL_INTERVAL", ib[6], 16); 193 break; 194 case PKT3_SURFACE_SYNC: 195 if (chip_class >= CIK) { 196 ac_dump_reg(f, R_0301F0_CP_COHER_CNTL, ib[1], ~0); 197 ac_dump_reg(f, R_0301F4_CP_COHER_SIZE, ib[2], ~0); 198 ac_dump_reg(f, R_0301F8_CP_COHER_BASE, ib[3], ~0); 199 } else { 200 ac_dump_reg(f, R_0085F0_CP_COHER_CNTL, ib[1], ~0); 201 ac_dump_reg(f, R_0085F4_CP_COHER_SIZE, ib[2], ~0); 202 ac_dump_reg(f, R_0085F8_CP_COHER_BASE, ib[3], ~0); 203 } 204 print_named_value(f, "POLL_INTERVAL", ib[4], 16); 205 break; 206 case PKT3_EVENT_WRITE: 207 ac_dump_reg(f, R_028A90_VGT_EVENT_INITIATOR, ib[1], 208 S_028A90_EVENT_TYPE(~0)); 209 print_named_value(f, "EVENT_INDEX", (ib[1] >> 8) & 0xf, 4); 210 print_named_value(f, "INV_L2", (ib[1] >> 20) & 0x1, 1); 211 if (count > 0) { 212 print_named_value(f, "ADDRESS_LO", ib[2], 32); 213 print_named_value(f, "ADDRESS_HI", ib[3], 16); 214 } 215 break; 216 case PKT3_DRAW_INDEX_AUTO: 217 ac_dump_reg(f, R_030930_VGT_NUM_INDICES, ib[1], ~0); 218 ac_dump_reg(f, R_0287F0_VGT_DRAW_INITIATOR, ib[2], ~0); 219 break; 220 case PKT3_DRAW_INDEX_2: 221 ac_dump_reg(f, R_028A78_VGT_DMA_MAX_SIZE, ib[1], ~0); 222 ac_dump_reg(f, R_0287E8_VGT_DMA_BASE, ib[2], ~0); 223 ac_dump_reg(f, R_0287E4_VGT_DMA_BASE_HI, ib[3], ~0); 224 ac_dump_reg(f, R_030930_VGT_NUM_INDICES, ib[4], ~0); 225 ac_dump_reg(f, R_0287F0_VGT_DRAW_INITIATOR, ib[5], ~0); 226 break; 227 case PKT3_INDEX_TYPE: 228 ac_dump_reg(f, R_028A7C_VGT_DMA_INDEX_TYPE, ib[1], ~0); 229 break; 230 case PKT3_NUM_INSTANCES: 231 ac_dump_reg(f, R_030934_VGT_NUM_INSTANCES, ib[1], ~0); 232 break; 233 case PKT3_WRITE_DATA: 234 ac_dump_reg(f, R_370_CONTROL, ib[1], ~0); 235 ac_dump_reg(f, R_371_DST_ADDR_LO, ib[2], ~0); 236 ac_dump_reg(f, R_372_DST_ADDR_HI, ib[3], ~0); 237 for (i = 2; i < count; i++) { 238 print_spaces(f, INDENT_PKT); 239 fprintf(f, "0x%08x\n", ib[2+i]); 240 } 241 break; 242 case PKT3_CP_DMA: 243 ac_dump_reg(f, R_410_CP_DMA_WORD0, ib[1], ~0); 244 ac_dump_reg(f, R_411_CP_DMA_WORD1, ib[2], ~0); 245 ac_dump_reg(f, R_412_CP_DMA_WORD2, ib[3], ~0); 246 ac_dump_reg(f, R_413_CP_DMA_WORD3, ib[4], ~0); 247 ac_dump_reg(f, R_414_COMMAND, ib[5], ~0); 248 break; 249 case PKT3_DMA_DATA: 250 ac_dump_reg(f, R_500_DMA_DATA_WORD0, ib[1], ~0); 251 ac_dump_reg(f, R_501_SRC_ADDR_LO, ib[2], ~0); 252 ac_dump_reg(f, R_502_SRC_ADDR_HI, ib[3], ~0); 253 ac_dump_reg(f, R_503_DST_ADDR_LO, ib[4], ~0); 254 ac_dump_reg(f, R_504_DST_ADDR_HI, ib[5], ~0); 255 ac_dump_reg(f, R_414_COMMAND, ib[6], ~0); 256 break; 257 case PKT3_INDIRECT_BUFFER_SI: 258 case PKT3_INDIRECT_BUFFER_CONST: 259 case PKT3_INDIRECT_BUFFER_CIK: 260 ac_dump_reg(f, R_3F0_IB_BASE_LO, ib[1], ~0); 261 ac_dump_reg(f, R_3F1_IB_BASE_HI, ib[2], ~0); 262 ac_dump_reg(f, R_3F2_CONTROL, ib[3], ~0); 263 264 if (addr_callback) { 265 uint64_t addr = ((uint64_t)ib[2] << 32) | ib[1]; 266 void *data = addr_callback(addr_callback_data, addr); 267 const char *name = G_3F2_CHAIN(ib[3]) ? "chained" : "nested"; 268 269 if (data) 270 ac_parse_ib(f, data, G_3F2_IB_SIZE(ib[3]), 271 trace_id, name, chip_class, 272 addr_callback, addr_callback_data); 273 } 274 break; 275 case PKT3_CLEAR_STATE: 276 case PKT3_INCREMENT_DE_COUNTER: 277 case PKT3_PFP_SYNC_ME: 278 break; 279 case PKT3_NOP: 280 if (ib[0] == 0xffff1000) { 281 count = -1; /* One dword NOP. */ 282 break; 283 } else if (count == 0 && AC_IS_TRACE_POINT(ib[1])) { 284 unsigned packet_id = AC_GET_TRACE_POINT_ID(ib[1]); 285 286 print_spaces(f, INDENT_PKT); 287 fprintf(f, COLOR_RED "Trace point ID: %u\n", packet_id); 288 289 if (trace_id == -1) 290 break; /* tracing was disabled */ 291 292 print_spaces(f, INDENT_PKT); 293 if (packet_id < trace_id) 294 fprintf(f, COLOR_RED 295 "This trace point was reached by the CP." 296 COLOR_RESET "\n"); 297 else if (packet_id == trace_id) 298 fprintf(f, COLOR_RED 299 "!!!!! This is the last trace point that " 300 "was reached by the CP !!!!!" 301 COLOR_RESET "\n"); 302 else if (packet_id+1 == trace_id) 303 fprintf(f, COLOR_RED 304 "!!!!! This is the first trace point that " 305 "was NOT been reached by the CP !!!!!" 306 COLOR_RESET "\n"); 307 else 308 fprintf(f, COLOR_RED 309 "!!!!! This trace point was NOT reached " 310 "by the CP !!!!!" 311 COLOR_RESET "\n"); 312 break; 313 } 314 /* fall through, print all dwords */ 315 default: 316 for (i = 0; i < count+1; i++) { 317 print_spaces(f, INDENT_PKT); 318 fprintf(f, "0x%08x\n", ib[1+i]); 319 } 320 } 321 322 ib += count + 2; 323 *num_dw -= count + 2; 324 return ib; 325 } 326 327 /** 328 * Parse and print an IB into a file. 329 * 330 * \param f file 331 * \param ib IB 332 * \param num_dw size of the IB 333 * \param chip_class chip class 334 * \param trace_id the last trace ID that is known to have been reached 335 * and executed by the CP, typically read from a buffer 336 * \param addr_callback Get a mapped pointer of the IB at a given address. Can 337 * be NULL. 338 * \param addr_callback_data user data for addr_callback 339 */ 340 void ac_parse_ib(FILE *f, uint32_t *ib, int num_dw, int trace_id, 341 const char *name, enum chip_class chip_class, 342 ac_debug_addr_callback addr_callback, void *addr_callback_data) 343 { 344 fprintf(f, "------------------ %s begin ------------------\n", name); 345 346 while (num_dw > 0) { 347 unsigned type = PKT_TYPE_G(ib[0]); 348 349 switch (type) { 350 case 3: 351 ib = ac_parse_packet3(f, ib, &num_dw, trace_id, 352 chip_class, addr_callback, 353 addr_callback_data); 354 break; 355 case 2: 356 /* type-2 nop */ 357 if (ib[0] == 0x80000000) { 358 fprintf(f, COLOR_GREEN "NOP (type 2)" COLOR_RESET "\n"); 359 ib++; 360 num_dw--; 361 break; 362 } 363 /* fall through */ 364 default: 365 fprintf(f, "Unknown packet type %i\n", type); 366 return; 367 } 368 } 369 370 fprintf(f, "------------------- %s end -------------------\n", name); 371 if (num_dw < 0) { 372 printf("Packet ends after the end of IB.\n"); 373 exit(0); 374 } 375 fprintf(f, "\n"); 376 } 377