diff --git a/src/freedreno/decode/cffdec.c b/src/freedreno/decode/cffdec.c index c2c743eb275..da12cc627e8 100644 --- a/src/freedreno/decode/cffdec.c +++ b/src/freedreno/decode/cffdec.c @@ -62,7 +62,7 @@ static inline unsigned regcnt(void) { if (options->info->chip >= 5) - return 0xffff; + return 0x3ffff; else return 0x7fff; } @@ -293,7 +293,7 @@ parse_dword_addr(uint32_t dword, uint32_t *gpuaddr, uint32_t *flags, *flags = dword & mask; } -static uint32_t type0_reg_vals[0xffff + 1]; +static uint32_t type0_reg_vals[0x3ffff + 1]; static uint8_t type0_reg_rewritten[sizeof(type0_reg_vals) / 8]; /* written since last draw */ static uint8_t type0_reg_written[sizeof(type0_reg_vals) / 8]; diff --git a/src/freedreno/decode/crashdec-mempool.c b/src/freedreno/decode/crashdec-mempool.c index cee95c76edb..c8fcd17a22c 100644 --- a/src/freedreno/decode/crashdec-mempool.c +++ b/src/freedreno/decode/crashdec-mempool.c @@ -47,7 +47,13 @@ dump_mem_pool_reg_write(unsigned reg, uint32_t data, unsigned context, } rnn_reginfo_free(info); } else { - printf("\t\twrite %s (%05x) context %d\n", regname(reg, 1), reg, context); + printf("\t\twrite %s (%05x)", regname(reg, 1), reg); + + if (is_a6xx()) { + printf(" context %d", context); + } + + printf("\n"); dump_register_val(&r, 2); } } @@ -133,7 +139,7 @@ dump_cp_mem_pool(uint32_t *mempool) const int num_blocks = small_mem_pool ? 0x30 : 0x80; /* Number of queues */ - const unsigned num_queues = 6; + const unsigned num_queues = is_a6xx() ? 6 : 7; /* Unfortunately the per-queue state is a little more complicated than * a simple pair of begin/end pointers. Instead of a single beginning @@ -198,31 +204,31 @@ dump_cp_mem_pool(uint32_t *mempool) uint32_t chunk : 3; uint32_t first_block : 32 - 3; } writer[6]; - uint32_t padding1[2]; /* Mirrors of writer[4], writer[5] */ + uint32_t padding1[2]; /* Mirror of writer[5] */ uint32_t unk1; uint32_t padding2[7]; /* Mirrors of unk1 */ - uint32_t writer_second_block[6]; - uint32_t padding3[2]; + uint32_t writer_second_block[7]; + uint32_t padding3[1]; - uint32_t unk2[6]; - uint32_t padding4[2]; + uint32_t unk2[7]; + uint32_t padding4[1]; struct { uint32_t chunk : 3; uint32_t first_block : 32 - 3; - } reader[6]; - uint32_t padding5[2]; /* Mirrors of reader[4], reader[5] */ + } reader[7]; + uint32_t padding5[1]; /* Mirror of reader[5] */ uint32_t unk3; uint32_t padding6[7]; /* Mirrors of unk3 */ - uint32_t reader_second_block[6]; - uint32_t padding7[2]; + uint32_t reader_second_block[7]; + uint32_t padding7[1]; - uint32_t block_count[6]; - uint32_t padding[2]; + uint32_t block_count[7]; + uint32_t padding[1]; uint32_t unk4; uint32_t padding9[7]; /* Mirrors of unk4 */ @@ -254,9 +260,12 @@ dump_cp_mem_pool(uint32_t *mempool) } for (int queue = 0; queue < num_queues; queue++) { - const char *cluster_names[6] = {"FE", "SP_VS", "PC_VS", - "GRAS", "SP_PS", "PS"}; - printf("\tCLUSTER_%s:\n\n", cluster_names[queue]); + const char *cluster_names_a6xx[6] = {"FE", "SP_VS", "PC_VS", + "GRAS", "SP_PS", "PS"}; + const char *cluster_names_a7xx[7] = {"FE", "SP_VS", "PC_VS", + "GRAS", "SP_PS", "VPC_PS", "PS"}; + printf("\tCLUSTER_%s:\n\n", + is_a6xx() ? cluster_names_a6xx[queue] : cluster_names_a7xx[queue]); if (verbose) { printf("\t\twriter_first_block: 0x%x\n", diff --git a/src/freedreno/decode/crashdec.c b/src/freedreno/decode/crashdec.c index 35316acf320..383a346e003 100644 --- a/src/freedreno/decode/crashdec.c +++ b/src/freedreno/decode/crashdec.c @@ -174,8 +174,16 @@ startswith(const char *line, const char *start) return strstr(line, start) == line; } +static bool +startswith_nowhitespace(const char *line, const char *start) +{ + while (*line == ' ' || *line == '\t') + line++; + return startswith(line, start); +} + static void -parseline(const char *line, const char *fmt, ...) +vparseline(const char *line, const char *fmt, va_list ap) { int fmtlen = strlen(fmt); int n = 0; @@ -194,12 +202,30 @@ parseline(const char *line, const char *fmt, ...) } } - va_list ap; - va_start(ap, fmt); if (vsscanf(line, fmt, ap) != n) { fprintf(stderr, "parse error scanning: '%s'\n", fmt); exit(1); } +} + +static void +parseline(const char *line, const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + vparseline(line, fmt, ap); + va_end(ap); +} + +static void +parseline_nowhitespace(const char *line, const char *fmt, ...) +{ + while (*line == ' ' || *line == '\t') + line++; + + va_list ap; + va_start(ap, fmt); + vparseline(line, fmt, ap); va_end(ap); } @@ -348,10 +374,10 @@ dump_cmdstream(void) printf("got rb_base=%" PRIx64 "\n", rb_base); options.ibs[1].base = regval64("CP_IB1_BASE"); - if (is_a6xx()) + if (have_rem_info()) options.ibs[1].rem = regval("CP_IB1_REM_SIZE"); options.ibs[2].base = regval64("CP_IB2_BASE"); - if (is_a6xx()) + if (have_rem_info()) options.ibs[2].rem = regval("CP_IB2_REM_SIZE"); /* Adjust remaining size to account for cmdstream slurped into ROQ @@ -363,7 +389,7 @@ dump_cmdstream(void) * TODO it would be nice to be able to extract out register bitfields * by name rather than hard-coding this. */ - if (is_a6xx()) { + if (have_rem_info()) { uint32_t ib1_rem = regval("CP_ROQ_AVAIL_IB1") >> 16; uint32_t ib2_rem = regval("CP_ROQ_AVAIL_IB2") >> 16; options.ibs[1].rem += ib1_rem ? ib1_rem - 1 : 0; @@ -563,14 +589,15 @@ decode_clusters(void) struct regacc r = regacc(NULL); foreach_line_in_section (line) { - if (startswith(line, " - cluster-name:") || - startswith(line, " - context:")) { + if (startswith_nowhitespace(line, "- cluster-name:") || + startswith_nowhitespace(line, "- context:") || + startswith_nowhitespace(line, "- pipe:")) { printf("%s", line); continue; } uint32_t offset, value; - parseline(line, " - { offset: %x, value: %x }", &offset, &value); + parseline_nowhitespace(line, "- { offset: %x, value: %x }", &offset, &value); if (regacc_push(&r, offset / 4, value)) { printf("\t%08"PRIx64, r.value); @@ -590,7 +617,7 @@ dump_cp_sqe_stat(uint32_t *stat) printf("\t PC: %04x\n", stat[0]); stat++; - if (is_a6xx() && valid_header(stat[0])) { + if (!is_a5xx() && valid_header(stat[0])) { if (pkt_is_type7(stat[0])) { unsigned opc = cp_type7_opcode(stat[0]); const char *name = pktname(opc); @@ -690,10 +717,11 @@ decode_indexed_registers(void) * so far) not useful, so skip them if not in verbose mode: */ bool dump = verbose || !strcmp(name, "CP_SQE_STAT") || + !strcmp(name, "CP_BV_SQE_STAT") || !strcmp(name, "CP_DRAW_STATE") || !strcmp(name, "CP_ROQ") || 0; - if (!strcmp(name, "CP_SQE_STAT")) + if (!strcmp(name, "CP_SQE_STAT") || !strcmp(name, "CP_BV_SQE_STAT")) dump_cp_sqe_stat(buf); if (!strcmp(name, "CP_UCODE_DBG_DATA")) @@ -728,19 +756,23 @@ decode_shader_blocks(void) if (startswith(line, " - type:")) { free(type); parseline(line, " - type: %ms", &type); - } else if (startswith(line, " size:")) { - parseline(line, " size: %u", &sizedwords); - } else if (startswith(line, " data: !!ascii85 |")) { + } else if (startswith_nowhitespace(line, "size:")) { + parseline_nowhitespace(line, "size: %u", &sizedwords); + } else if (startswith_nowhitespace(line, "data: !!ascii85 |")) { uint32_t *buf = popline_ascii85(sizedwords); /* some of the sections are pretty large, and are (at least * so far) not useful, so skip them if not in verbose mode: */ bool dump = verbose || !strcmp(type, "A6XX_SP_INST_DATA") || - !strcmp(type, "A6XX_HLSQ_INST_RAM") || 0; + !strcmp(type, "A6XX_HLSQ_INST_RAM") || + !strcmp(type, "A7XX_SP_INST_DATA") || + !strcmp(type, "A7XX_HLSQ_INST_RAM") || 0; if (!strcmp(type, "A6XX_SP_INST_DATA") || - !strcmp(type, "A6XX_HLSQ_INST_RAM")) { + !strcmp(type, "A6XX_HLSQ_INST_RAM") || + !strcmp(type, "A7XX_SP_INST_DATA") || + !strcmp(type, "A7XX_HLSQ_INST_RAM")) { /* TODO this section actually contains multiple shaders * (or parts of shaders?), so perhaps we should search * for ends of shaders and decode each? @@ -826,7 +858,16 @@ decode(void) cffdec_init(&options); - if (is_a6xx()) { + if (is_a7xx()) { + rnn_gmu = rnn_new(!options.color); + rnn_load_file(rnn_gmu, "adreno/a6xx_gmu.xml", "A6XX"); + rnn_control = rnn_new(!options.color); + rnn_load_file(rnn_control, "adreno/adreno_control_regs.xml", + "A7XX_CONTROL_REG"); + rnn_pipe = rnn_new(!options.color); + rnn_load_file(rnn_pipe, "adreno/adreno_pipe_regs.xml", + "A7XX_PIPE_REG"); + } else if (is_a6xx()) { rnn_gmu = rnn_new(!options.color); rnn_load_file(rnn_gmu, "adreno/a6xx_gmu.xml", "A6XX"); rnn_control = rnn_new(!options.color); diff --git a/src/freedreno/decode/crashdec.h b/src/freedreno/decode/crashdec.h index 2307754a274..862e33fae80 100644 --- a/src/freedreno/decode/crashdec.h +++ b/src/freedreno/decode/crashdec.h @@ -53,6 +53,18 @@ extern bool verbose; extern struct cffdec_options options; +static inline bool +have_rem_info(void) +{ + return options.info->chip == 6 || options.info->chip == 7; +} + +static inline bool +is_a7xx(void) +{ + return options.info->chip == 7; +} + static inline bool is_a6xx(void) {