Mesa (main): freedreno/afuc: Add emulator support to run bootstrap

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Tue Jun 1 00:30:14 UTC 2021


Module: Mesa
Branch: main
Commit: df14af6480c3d70134a9308f8028d5627867f572
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=df14af6480c3d70134a9308f8028d5627867f572

Author: Rob Clark <robdclark at chromium.org>
Date:   Thu May 27 12:18:53 2021 -0700

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 at chromium.org>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/10944>

---

 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 0b24ea5f3aa..0af04808947 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 f7296352848..959761d3d78 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 d8bc4f0b98e..1ff84c72198 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



More information about the mesa-commit mailing list