X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Famd%2Fcommon%2Fac_debug.c;h=77c0e0aa790cd13046d8d7e23ae0ebed06941cce;hb=3817fa7a4d1f51c385b28a2e45a1edf227526028;hp=570ba850851704b8b08d7977c1a17e573718146b;hpb=274f1dace74acbd41446fdffadd734397c528ada;p=mesa.git diff --git a/src/amd/common/ac_debug.c b/src/amd/common/ac_debug.c index 570ba850851..77c0e0aa790 100644 --- a/src/amd/common/ac_debug.c +++ b/src/amd/common/ac_debug.c @@ -19,9 +19,6 @@ * 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: - * Marek Olšák */ #include "ac_debug.h" @@ -31,18 +28,19 @@ #include #define VG(x) x #else -#define VG(x) +#define VG(x) ((void)0) #endif #include #include "sid.h" -#include "gfx9d.h" #include "sid_tables.h" #include "util/u_math.h" #include "util/u_memory.h" #include "util/u_string.h" +#include + /* Parsed IBs are difficult to read without colors. Use "less -R file" to * read them, or use "aha -b -f file" to convert them to html. */ @@ -101,54 +99,75 @@ static void print_named_value(FILE *file, const char *name, uint32_t value, print_value(file, value, bits); } +static const struct si_reg *find_register(const struct si_reg *table, + unsigned table_size, + unsigned offset) +{ + for (unsigned i = 0; i < table_size; i++) { + const struct si_reg *reg = &table[i]; + + if (reg->offset == offset) + return reg; + } + + return NULL; +} + void ac_dump_reg(FILE *file, enum chip_class chip_class, unsigned offset, uint32_t value, uint32_t field_mask) { - int r, f; - - for (r = 0; r < ARRAY_SIZE(sid_reg_table); r++) { - const struct si_reg *reg = &sid_reg_table[r]; + const struct si_reg *reg = NULL; + + if (chip_class >= GFX10) + reg = find_register(gfx10_reg_table, ARRAY_SIZE(gfx10_reg_table), offset); + else if (chip_class >= GFX9) + reg = find_register(gfx9_reg_table, ARRAY_SIZE(gfx9_reg_table), offset); + else if (chip_class >= GFX8) + reg = find_register(gfx8_reg_table, ARRAY_SIZE(gfx8_reg_table), offset); + else if (chip_class >= GFX7) + reg = find_register(gfx7_reg_table, ARRAY_SIZE(gfx7_reg_table), offset); + else + reg = find_register(gfx6_reg_table, ARRAY_SIZE(gfx6_reg_table), offset); + + if (reg) { const char *reg_name = sid_strings + reg->name_offset; + bool first_field = true; - if (reg->offset == offset) { - bool first_field = true; + print_spaces(file, INDENT_PKT); + fprintf(file, COLOR_YELLOW "%s" COLOR_RESET " <- ", + reg_name); - print_spaces(file, INDENT_PKT); - fprintf(file, COLOR_YELLOW "%s" COLOR_RESET " <- ", - reg_name); - - if (!reg->num_fields) { - print_value(file, value, 32); - return; - } + if (!reg->num_fields) { + print_value(file, value, 32); + return; + } - for (f = 0; f < reg->num_fields; f++) { - const struct si_field *field = sid_fields_table + reg->fields_offset + f; - const int *values_offsets = sid_strings_offsets + field->values_offset; - uint32_t val = (value & field->mask) >> - (ffs(field->mask) - 1); + for (unsigned f = 0; f < reg->num_fields; f++) { + const struct si_field *field = sid_fields_table + reg->fields_offset + f; + const int *values_offsets = sid_strings_offsets + field->values_offset; + uint32_t val = (value & field->mask) >> + (ffs(field->mask) - 1); - if (!(field->mask & field_mask)) - continue; + if (!(field->mask & field_mask)) + continue; - /* Indent the field. */ - if (!first_field) - print_spaces(file, - INDENT_PKT + strlen(reg_name) + 4); + /* Indent the field. */ + if (!first_field) + print_spaces(file, + INDENT_PKT + strlen(reg_name) + 4); - /* Print the field. */ - fprintf(file, "%s = ", sid_strings + field->name_offset); + /* Print the field. */ + fprintf(file, "%s = ", sid_strings + field->name_offset); - if (val < field->num_values && values_offsets[val] >= 0) - fprintf(file, "%s\n", sid_strings + values_offsets[val]); - else - print_value(file, val, - util_bitcount(field->mask)); + if (val < field->num_values && values_offsets[val] >= 0) + fprintf(file, "%s\n", sid_strings + values_offsets[val]); + else + print_value(file, val, + util_bitcount(field->mask)); - first_field = false; - } - return; + first_field = false; } + return; } print_spaces(file, INDENT_PKT); @@ -219,6 +238,7 @@ static void ac_parse_packet3(FILE *f, uint32_t header, struct ac_ib_parser *ib, if (op == PKT3_SET_CONTEXT_REG || op == PKT3_SET_CONFIG_REG || op == PKT3_SET_UCONFIG_REG || + op == PKT3_SET_UCONFIG_REG_INDEX || op == PKT3_SET_SH_REG) fprintf(f, COLOR_CYAN "%s%s" COLOR_CYAN ":\n", name, predicate); @@ -238,6 +258,7 @@ static void ac_parse_packet3(FILE *f, uint32_t header, struct ac_ib_parser *ib, ac_parse_set_reg_packet(f, count, SI_CONFIG_REG_OFFSET, ib); break; case PKT3_SET_UCONFIG_REG: + case PKT3_SET_UCONFIG_REG_INDEX: ac_parse_set_reg_packet(f, count, CIK_UCONFIG_REG_OFFSET, ib); break; case PKT3_SET_SH_REG: @@ -250,9 +271,11 @@ static void ac_parse_packet3(FILE *f, uint32_t header, struct ac_ib_parser *ib, ac_dump_reg(f, ib->chip_class, R_0301F8_CP_COHER_BASE, ac_ib_get(ib), ~0); ac_dump_reg(f, ib->chip_class, R_0301E4_CP_COHER_BASE_HI, ac_ib_get(ib), ~0); print_named_value(f, "POLL_INTERVAL", ac_ib_get(ib), 16); + if (ib->chip_class >= GFX10) + ac_dump_reg(f, ib->chip_class, R_586_GCR_CNTL, ac_ib_get(ib), ~0); break; case PKT3_SURFACE_SYNC: - if (ib->chip_class >= CIK) { + if (ib->chip_class >= GFX7) { ac_dump_reg(f, ib->chip_class, R_0301F0_CP_COHER_CNTL, ac_ib_get(ib), ~0); ac_dump_reg(f, ib->chip_class, R_0301F4_CP_COHER_SIZE, ac_ib_get(ib), ~0); ac_dump_reg(f, ib->chip_class, R_0301F8_CP_COHER_BASE, ac_ib_get(ib), ~0); @@ -297,17 +320,21 @@ static void ac_parse_packet3(FILE *f, uint32_t header, struct ac_ib_parser *ib, } case PKT3_RELEASE_MEM: { uint32_t event_dw = ac_ib_get(ib); - ac_dump_reg(f, ib->chip_class, R_028A90_VGT_EVENT_INITIATOR, event_dw, - S_028A90_EVENT_TYPE(~0)); - print_named_value(f, "EVENT_INDEX", (event_dw >> 8) & 0xf, 4); - print_named_value(f, "TCL1_VOL_ACTION_ENA", (event_dw >> 12) & 0x1, 1); - print_named_value(f, "TC_VOL_ACTION_ENA", (event_dw >> 13) & 0x1, 1); - print_named_value(f, "TC_WB_ACTION_ENA", (event_dw >> 15) & 0x1, 1); - print_named_value(f, "TCL1_ACTION_ENA", (event_dw >> 16) & 0x1, 1); - print_named_value(f, "TC_ACTION_ENA", (event_dw >> 17) & 0x1, 1); - print_named_value(f, "TC_NC_ACTION_ENA", (event_dw >> 19) & 0x1, 1); - print_named_value(f, "TC_WC_ACTION_ENA", (event_dw >> 20) & 0x1, 1); - print_named_value(f, "TC_MD_ACTION_ENA", (event_dw >> 21) & 0x1, 1); + if (ib->chip_class >= GFX10) { + ac_dump_reg(f, ib->chip_class, R_490_RELEASE_MEM_OP, event_dw, ~0u); + } else { + ac_dump_reg(f, ib->chip_class, R_028A90_VGT_EVENT_INITIATOR, event_dw, + S_028A90_EVENT_TYPE(~0)); + print_named_value(f, "EVENT_INDEX", (event_dw >> 8) & 0xf, 4); + print_named_value(f, "TCL1_VOL_ACTION_ENA", (event_dw >> 12) & 0x1, 1); + print_named_value(f, "TC_VOL_ACTION_ENA", (event_dw >> 13) & 0x1, 1); + print_named_value(f, "TC_WB_ACTION_ENA", (event_dw >> 15) & 0x1, 1); + print_named_value(f, "TCL1_ACTION_ENA", (event_dw >> 16) & 0x1, 1); + print_named_value(f, "TC_ACTION_ENA", (event_dw >> 17) & 0x1, 1); + print_named_value(f, "TC_NC_ACTION_ENA", (event_dw >> 19) & 0x1, 1); + print_named_value(f, "TC_WC_ACTION_ENA", (event_dw >> 20) & 0x1, 1); + print_named_value(f, "TC_MD_ACTION_ENA", (event_dw >> 21) & 0x1, 1); + } uint32_t sel_dw = ac_ib_get(ib); print_named_value(f, "DST_SEL", (sel_dw >> 16) & 0x3, 2); print_named_value(f, "INT_SEL", (sel_dw >> 24) & 0x7, 3); @@ -373,7 +400,7 @@ static void ac_parse_packet3(FILE *f, uint32_t header, struct ac_ib_parser *ib, uint32_t base_hi_dw = ac_ib_get(ib); ac_dump_reg(f, ib->chip_class, R_3F1_IB_BASE_HI, base_hi_dw, ~0); uint32_t control_dw = ac_ib_get(ib); - ac_dump_reg(f, ib->chip_class, R_3F2_CONTROL, control_dw, ~0); + ac_dump_reg(f, ib->chip_class, R_3F2_IB_CONTROL, control_dw, ~0); if (!ib->addr_callback) break; @@ -515,7 +542,7 @@ static void format_ib_output(FILE *f, char *out) if (indent) print_spaces(f, indent); - char *end = util_strchrnul(out, '\n'); + char *end = strchrnul(out, '\n'); fwrite(out, end - out, 1, f); fputc('\n', f); /* always end with a new line */ if (!*end) @@ -706,3 +733,80 @@ bool ac_vm_fault_occured(enum chip_class chip_class, return fault; } + +static int compare_wave(const void *p1, const void *p2) +{ + struct ac_wave_info *w1 = (struct ac_wave_info *)p1; + struct ac_wave_info *w2 = (struct ac_wave_info *)p2; + + /* Sort waves according to PC and then SE, SH, CU, etc. */ + if (w1->pc < w2->pc) + return -1; + if (w1->pc > w2->pc) + return 1; + if (w1->se < w2->se) + return -1; + if (w1->se > w2->se) + return 1; + if (w1->sh < w2->sh) + return -1; + if (w1->sh > w2->sh) + return 1; + if (w1->cu < w2->cu) + return -1; + if (w1->cu > w2->cu) + return 1; + if (w1->simd < w2->simd) + return -1; + if (w1->simd > w2->simd) + return 1; + if (w1->wave < w2->wave) + return -1; + if (w1->wave > w2->wave) + return 1; + + return 0; +} + +/* Return wave information. "waves" should be a large enough array. */ +unsigned ac_get_wave_info(enum chip_class chip_class, + struct ac_wave_info waves[AC_MAX_WAVES_PER_CHIP]) +{ + char line[2000], cmd[128]; + unsigned num_waves = 0; + + sprintf(cmd, "umr -O halt_waves -wa %s", chip_class >= GFX10 ? "gfx_0.0.0" : "gfx"); + + FILE *p = popen(cmd, "r"); + if (!p) + return 0; + + if (!fgets(line, sizeof(line), p) || + strncmp(line, "SE", 2) != 0) { + pclose(p); + return 0; + } + + while (fgets(line, sizeof(line), p)) { + struct ac_wave_info *w; + uint32_t pc_hi, pc_lo, exec_hi, exec_lo; + + assert(num_waves < AC_MAX_WAVES_PER_CHIP); + w = &waves[num_waves]; + + if (sscanf(line, "%u %u %u %u %u %x %x %x %x %x %x %x", + &w->se, &w->sh, &w->cu, &w->simd, &w->wave, + &w->status, &pc_hi, &pc_lo, &w->inst_dw0, + &w->inst_dw1, &exec_hi, &exec_lo) == 12) { + w->pc = ((uint64_t)pc_hi << 32) | pc_lo; + w->exec = ((uint64_t)exec_hi << 32) | exec_lo; + w->matched = false; + num_waves++; + } + } + + qsort(waves, num_waves, sizeof(struct ac_wave_info), compare_wave); + + pclose(p); + return num_waves; +}