summaryrefslogtreecommitdiffstats
path: root/kernel/gsp_emulation.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/gsp_emulation.c')
-rw-r--r--kernel/gsp_emulation.c41
1 files changed, 38 insertions, 3 deletions
diff --git a/kernel/gsp_emulation.c b/kernel/gsp_emulation.c
index c8f8041..94af0d2 100644
--- a/kernel/gsp_emulation.c
+++ b/kernel/gsp_emulation.c
@@ -179,6 +179,39 @@ static void gsp_emu_poll_boot(struct gsp_emu_context *ctx)
u32 sec2_cpuctl = gsp_emu_shadow_read32(ctx, GSP_EMU_REG_SEC2_CPUCTL);
u32 engine = gsp_emu_shadow_read32(ctx, GSP_EMU_REG_GSP_ENGINE);
u32 mmu_inv = gsp_emu_shadow_read32(ctx, GSP_EMU_REG_MMU_INVALIDATE);
+ u32 sw_vector;
+
+ /* Software-interrupt trigger: the driver writes a vector to
+ * CPU_INTR_LEAF_TRIGGER to fire it (the osVerifyInterrupts sanity
+ * test uses the doorbell vector). Set the pending bits in the LEAF
+ * and TOP interrupt-tree registers and inject MSI-X so the guest's
+ * ISR runs - without this the sanity test times out and
+ * osVerifySystemEnvironment fails, bailing RmInitAdapter. */
+ sw_vector = gsp_emu_shadow_read32(ctx, GSP_EMU_REG_CPU_INTR_LEAF_TRIGGER);
+ if (sw_vector) {
+ u32 leaf_idx = sw_vector / 32;
+ u32 leaf_bit = sw_vector % 32;
+ u32 subtree = sw_vector / 64;
+ u32 top_idx = subtree / 32;
+ u32 top_bit = subtree % 32;
+ u32 leaf_val = gsp_emu_shadow_read32(ctx,
+ GSP_EMU_REG_CPU_INTR_LEAF_BASE + leaf_idx * 4);
+ u32 top_val = gsp_emu_shadow_read32(ctx,
+ GSP_EMU_REG_CPU_INTR_TOP_BASE + top_idx * 4);
+
+ gsp_emu_shadow_write32(ctx,
+ GSP_EMU_REG_CPU_INTR_LEAF_BASE + leaf_idx * 4,
+ leaf_val | (1U << leaf_bit));
+ gsp_emu_shadow_write32(ctx,
+ GSP_EMU_REG_CPU_INTR_TOP_BASE + top_idx * 4,
+ top_val | (1U << top_bit));
+ gsp_emu_shadow_write32(ctx, GSP_EMU_REG_CPU_INTR_LEAF_TRIGGER, 0);
+
+ nv_vgpu_info(ctx->vgpu, "GSP-BOOT: SW interrupt vector %u -> LEAF[%u]|=0x%x TOP[%u]|=0x%x, MSI-X",
+ sw_vector, leaf_idx, 1U << leaf_bit, top_idx,
+ 1U << top_bit);
+ gsp_emu_inject_completion_interrupt(ctx, 0);
+ }
/* TLB invalidate auto-complete: the driver sets TRIGGER then spins
* polling for it to clear (kgmmuCheckPendingInvalidates). Report
@@ -267,16 +300,18 @@ static void gsp_emu_poll_boot(struct gsp_emu_context *ctx)
* driver reads a stale/garbage error code (0xff) and the unload
* fails, killing the subsequent re-init. A SEC2 kick after a
* completed boot is a GSP shutdown/reload: drop the boot state
- * (GSP no longer active, queue dead). */
+ * (GSP no longer active, queue dead). Clear boot state FIRST so
+ * WPR2 is already down when the driver sees CPUCTL=HALTED and
+ * checks kgspIsWpr2Up (avoids "Booter Unload: WPR2 is still up"). */
if (gsp_cpuctl & GSP_EMU_CPUCTL_STARTCPU)
gsp_emu_shadow_write32(ctx, GSP_EMU_REG_GSP_CPUCTL,
GSP_EMU_CPUCTL_HALTED);
if (sec2_cpuctl & GSP_EMU_CPUCTL_STARTCPU) {
+ if (ctx->boot_stage == GSP_BOOT_STAGE_BOOTER_DONE)
+ gsp_emu_clear_boot_state(ctx, "Booter unload/reload kick");
gsp_emu_shadow_write32(ctx, GSP_EMU_REG_SEC2_MAILBOX0, 0);
gsp_emu_shadow_write32(ctx, GSP_EMU_REG_SEC2_CPUCTL,
GSP_EMU_CPUCTL_HALTED);
- if (ctx->boot_stage == GSP_BOOT_STAGE_BOOTER_DONE)
- gsp_emu_clear_boot_state(ctx, "Booter unload/reload kick");
}
}