From df14af6480c3d70134a9308f8028d5627867f572 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Thu, 27 May 2021 12:18:53 -0700 Subject: [PATCH] freedreno/afuc: Add emulator support to run bootstrap Run until the packet-table is populated, so the disassembler can use this to know the offsets of various pm4 packet handlers without having to rely on heuristics. Signed-off-by: Rob Clark Part-of: --- src/freedreno/afuc/emu-ui.c | 3 +++ src/freedreno/afuc/emu.c | 52 +++++++++++++++++++++++++++++++++++++++------ src/freedreno/afuc/emu.h | 11 ++++++++++ 3 files changed, 59 insertions(+), 7 deletions(-) diff --git a/src/freedreno/afuc/emu-ui.c b/src/freedreno/afuc/emu-ui.c index 0b24ea5..0af0480 100644 --- a/src/freedreno/afuc/emu-ui.c +++ b/src/freedreno/afuc/emu-ui.c @@ -508,6 +508,9 @@ emu_dump_state_change(struct emu *emu) { unsigned i; + if (emu->quiet) + return; + /* Print the GPRs that changed: */ BITSET_FOREACH_SET (i, emu->gpr_regs.written, EMU_NUM_GPR_REGS) { dump_gpr_register(emu, i); diff --git a/src/freedreno/afuc/emu.c b/src/freedreno/afuc/emu.c index f729635..959761d 100644 --- a/src/freedreno/afuc/emu.c +++ b/src/freedreno/afuc/emu.c @@ -191,7 +191,7 @@ emu_instr(struct emu *emu, afuc_instr *instr) if (instr->control.flags == 0x4) { emu_set_gpr_reg(emu, instr->control.src2, src2 + instr->control.uimm); - } else if (instr->control.flags) { + } else if (instr->control.flags && !emu->quiet) { printf("unhandled flags: %x\n", instr->control.flags); } @@ -203,7 +203,7 @@ emu_instr(struct emu *emu, afuc_instr *instr) if (instr->control.flags == 0x4) { emu_set_gpr_reg(emu, instr->control.src2, src2 + instr->control.uimm); - } else if (instr->control.flags) { + } else if (instr->control.flags && !emu->quiet) { printf("unhandled flags: %x\n", instr->control.flags); } @@ -218,7 +218,7 @@ emu_instr(struct emu *emu, afuc_instr *instr) if (instr->control.flags == 0x4) { uint32_t src2 = emu_get_gpr_reg(emu, instr->control.src2); emu_set_gpr_reg(emu, instr->control.src2, src2 + instr->control.uimm); - } else if (instr->control.flags) { + } else if (instr->control.flags && !emu->quiet) { printf("unhandled flags: %x\n", instr->control.flags); } @@ -235,7 +235,7 @@ emu_instr(struct emu *emu, afuc_instr *instr) if (instr->control.flags == 0x4) { uint32_t src2 = emu_get_gpr_reg(emu, instr->control.src2); emu_set_gpr_reg(emu, instr->control.src2, src2 + instr->control.uimm); - } else if (instr->control.flags) { + } else if (instr->control.flags && !emu->quiet) { printf("unhandled flags: %x\n", instr->control.flags); } @@ -382,6 +382,20 @@ emu_step(struct emu *emu) emu_dump_state_change(emu); } +void +emu_run_bootstrap(struct emu *emu) +{ + EMU_CONTROL_REG(PACKET_TABLE_WRITE_ADDR); + + emu->quiet = true; + emu->run_mode = true; + + while (emu_get_reg32(emu, &PACKET_TABLE_WRITE_ADDR) < 0x80) { + emu_step(emu); + } +} + + static void check_access(struct emu *emu, uintptr_t gpuaddr, unsigned sz) { @@ -435,10 +449,34 @@ emu_init(struct emu *emu) mem_write_dword(emu, EMU_INSTR_BASE + (4 * i), emu->instrs[i]); } - printf("instruction base: %p\n", (void *)(uintptr_t)EMU_INSTR_BASE); + EMU_GPU_REG(CP_SQE_INSTR_BASE); + EMU_GPU_REG(CP_LPAC_SQE_INSTR_BASE); /* Setup the address of the SQE fw, just use the normal CPU ptr address: */ - EMU_GPU_REG(CP_SQE_INSTR_BASE); - emu_set_reg64(emu, &CP_SQE_INSTR_BASE, EMU_INSTR_BASE); + if (emu->lpac) { + emu_set_reg64(emu, &CP_LPAC_SQE_INSTR_BASE, EMU_INSTR_BASE); + } else { + emu_set_reg64(emu, &CP_SQE_INSTR_BASE, EMU_INSTR_BASE); + } + + if (emu->gpu_id == 660) { + emu_set_control_reg(emu, 0, 3 << 28); + } else if (emu->gpu_id == 650) { + emu_set_control_reg(emu, 0, 1 << 28); + } } +void +emu_fini(struct emu *emu) +{ + uint32_t *instrs = emu->instrs; + unsigned sizedwords = emu->sizedwords; + unsigned gpu_id = emu->gpu_id; + + munmap(emu->gpumem, EMU_MEMORY_SIZE); + memset(emu, 0, sizeof(*emu)); + + emu->instrs = instrs; + emu->sizedwords = sizedwords; + emu->gpu_id = gpu_id; +} diff --git a/src/freedreno/afuc/emu.h b/src/freedreno/afuc/emu.h index d8bc4f0..1ff84c7 100644 --- a/src/freedreno/afuc/emu.h +++ b/src/freedreno/afuc/emu.h @@ -149,8 +149,17 @@ struct emu_draw_state { * Emulated hw state. */ struct emu { + /** + * In bootstrap mode, execute bootstrap without outputting anything. + * Useful to (for example) extract packet-table. + */ + bool quiet; + + bool lpac; + uint32_t *instrs; unsigned sizedwords; + unsigned gpu_id; struct emu_control_regs control_regs; struct emu_pipe_regs pipe_regs; @@ -214,7 +223,9 @@ struct emu { * API for disasm to use: */ void emu_step(struct emu *emu); +void emu_run_bootstrap(struct emu *emu); void emu_init(struct emu *emu); +void emu_fini(struct emu *emu); /* * Internal APIs -- 2.7.4