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 <robdclark@chromium.org>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/10944>
This commit is contained in:
Rob Clark 2021-05-27 12:18:53 -07:00 committed by Marge Bot
parent ea2e244198
commit df14af6480
3 changed files with 59 additions and 7 deletions

View File

@ -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);

View File

@ -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;
}

View File

@ -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