summaryrefslogtreecommitdiffstats
path: root/kernel/gsp_rm_emulation.c
diff options
context:
space:
mode:
authorArthur Hanson Rasmusson <arthur@vgpu.io>2026-11-09 19:27:48 -0500
committerArthur Hanson Rasmusson <arthur@vgpu.io>2026-11-09 19:27:48 -0500
commita478f0b418bd3dd5fbcc6260979865160ca25cf0 (patch)
treee29fb7ec56741b9be1d8e747c108cb661b89d6c2 /kernel/gsp_rm_emulation.c
parent4a2cf8292ad37767de22a26e7e35d0a8a06edad3 (diff)
downloadopen-iov-a478f0b418bd3dd5fbcc6260979865160ca25cf0.tar.gz
open-iov-a478f0b418bd3dd5fbcc6260979865160ca25cf0.zip
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).
Diffstat (limited to 'kernel/gsp_rm_emulation.c')
-rw-r--r--kernel/gsp_rm_emulation.c14
1 files changed, 9 insertions, 5 deletions
diff --git a/kernel/gsp_rm_emulation.c b/kernel/gsp_rm_emulation.c
index c14a767..f395ce6 100644
--- a/kernel/gsp_rm_emulation.c
+++ b/kernel/gsp_rm_emulation.c
@@ -737,11 +737,15 @@ static int gsp_rm_send_flags(struct gsp_emu_context *ctx, u32 function,
return ret;
}
- /* Notify the guest (MSI-X vector 0). The driver's bottom-half drains
- * events under the GPU lock; the rpcRecvPoll poller holds the same
- * lock from send to poll, so a reply can't be consumed by the event
- * drain while a poller waits for it (same as real GSP-RM). */
- gsp_emu_inject_completion_interrupt(ctx, rm->stat_seq);
+ /* Notify the guest. An event must also raise the GSP engine interrupt
+ * (falcon SWGEN0 + CPU_INTR leaf/top) so the guest's ISR drains the
+ * status queue and nv_post_event() wakes a client blocked in poll() on
+ * /dev/nvidia0 (e.g. a GLX swap). Replies only need the MSI-X ping
+ * because the client polls the queue for them. */
+ if (function == GSPRM_RPC_EVENT_POST_EVENT)
+ gsp_emu_raise_gsp_event_irq(ctx);
+ else
+ gsp_emu_inject_completion_interrupt(ctx, rm->stat_seq);
mutex_unlock(&rm->stat_lock);
return 0;