From a478f0b418bd3dd5fbcc6260979865160ca25cf0 Mon Sep 17 00:00:00 2001 From: Arthur Hanson Rasmusson Date: Mon, 9 Nov 2026 19:27:48 -0500 Subject: vgsp: raise the GSP engine event interrupt so guest ISR drains events and wakes poll() waiters The emulated GSP only signalled the MSI-X eventfd when it queued a status record. The guest's primary ISR (nvidia_isr) decides pending from the CPU_INTR leaf registers, which we never set for the GSP stall vector, so it returned IRQ_NONE: IRQ 33 counted thousands of interrupts while the nvidia event thread sat idle and a client blocked in poll() on /dev/nvidia0 (a GLX swap) waited forever even though the event was already in the status queue. Mirror what a real GSP-RM does when it queues an event: - program RISC-V IRQMASK/IRQDEST for SWGEN0 (read-only to the guest; the GSP firmware owns them), - set SWGEN0 in the falcon IRQSTAT, - latch GSP stall vector 155 in the CPU interrupt tree (LEAF[4] bit 27, UVM_SHARED subtree 2 -> TOP[0] bit 2), - signal MSI-X. Raise it only for POST_EVENT records (replies are polled by the client). Verified on r1680: the guest now writes IRQSCLR SWGEN0, kgspService_TU102 drains events, and glxgears renders (was a hard hang). --- kernel/gsp_emulation.h | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'kernel/gsp_emulation.h') diff --git a/kernel/gsp_emulation.h b/kernel/gsp_emulation.h index 9a8f241..d9a7f01 100644 --- a/kernel/gsp_emulation.h +++ b/kernel/gsp_emulation.h @@ -116,6 +116,29 @@ #define GSP_EMU_REG_CPU_INTR_LEAF_BASE (GSP_EMU_REG_FULL_PHYS_OFFSET + 0x1000) #define GSP_EMU_REG_CPU_INTR_TOP_BASE (GSP_EMU_REG_FULL_PHYS_OFFSET + 0x1600) +/* GSP event interrupt (Turing, physical-GPU path). + * + * A real GSP-RM posts an event into the status queue and raises the GSP + * engine interrupt: it sets SWGEN0 in the falcon IRQSTAT and the host CPU's + * interrupt tree latches the GSP stall vector (155 = LEAF[4] bit 27, UVM_SHARED + * subtree 2 -> TOP[0] bit 2). The guest's primary ISR (nvidia_isr) then + * returns IRQ_WAKE_THREAD, kgspService_TU102 reads + * IRQSTAT & RISCV_IRQMASK & RISCV_IRQDEST, sees SWGEN0, calls + * kgspRpcRecvEvents -> nv_post_event -> wake_up_interruptible, which is what + * releases a client blocked in poll() on /dev/nvidia0 (e.g. a GLX swap). + * + * We were only signalling the MSI-X eventfd, so the primary ISR returned + * IRQ_NONE (no pending leaf bit) and the event thread never ran: IRQ 33 + * counted thousands of interrupts while the guest's nvidia worker threads sat + * idle and the client polled forever. IRQMASK/IRQDEST are read-only to the + * guest (the GSP firmware owns them), so the emulated GSP must program them. */ +#define GSP_EMU_REG_FALCON_IRQSCLR 0x110004 /* -W- : write 1 to clear */ +#define GSP_EMU_REG_FALCON_IRQSTAT 0x110008 /* R-- : pending sources */ +#define GSP_EMU_REG_RISCV_IRQMASK 0x1112b4 /* R-I : enabled sources */ +#define GSP_EMU_REG_RISCV_IRQDEST 0x1112b8 /* RW : routed to CPU */ +#define GSP_EMU_FALCON_IRQSTAT_SWGEN0 (1U << 6) +#define GSP_EMU_GSP_EVENT_VECTOR 155 /* MC_ENGINE_IDX_GSP stall */ + /* Windowed aliases of the VF L2 invalidate registers (GPU_VREG_* path). */ #define GSP_EMU_REG_VF_L2_SYSMEM_INV_WIN (GSP_EMU_REG_FULL_PHYS_OFFSET + 0x000f00) #define GSP_EMU_REG_VF_L2_PEERMEM_INV_WIN (GSP_EMU_REG_FULL_PHYS_OFFSET + 0x000f04) @@ -195,6 +218,9 @@ void gsp_emu_cleanup(struct nv_vgpu_device *vgpu); void gsp_emu_clear_boot_state(struct gsp_emu_context *ctx, const char *reason); int gsp_emu_process_rpc(struct gsp_emu_context *ctx); void gsp_emu_inject_completion_interrupt(struct gsp_emu_context *ctx, u32 seq_id); +/* Raise the GSP event interrupt (falcon SWGEN0 + CPU_INTR leaf/top + MSI-X) + * so the guest's ISR drains the status queue and wakes poll() waiters. */ +void gsp_emu_raise_gsp_event_irq(struct gsp_emu_context *ctx); /* ============================================================ * Debug/Statistics -- cgit v1.2.3