summaryrefslogtreecommitdiffstats
path: root/kernel/gsp_emulation.c
diff options
context:
space:
mode:
authorArthur Hanson Rasmusson <arthur@vgpu.io>2026-11-12 14:55:25 -0500
committerArthur Hanson Rasmusson <arthur@vgpu.io>2026-11-12 14:55:25 -0500
commit10c043a669fed5340eb953a17e341a35a4bce1b5 (patch)
treeb4fc5a197bd4ce7518ffe5356d420a0e9809caab /kernel/gsp_emulation.c
parent6260daa1eb66094e86a1d02128b97708242074e8 (diff)
downloadopen-iov-10c043a669fed5340eb953a17e341a35a4bce1b5.tar.gz
open-iov-10c043a669fed5340eb953a17e341a35a4bce1b5.zip
vgsp: direct-GL ring/push rescue, VAS/pdb scanners and PTIMER tick; r1780 cycle tooling
Diffstat (limited to 'kernel/gsp_emulation.c')
-rw-r--r--kernel/gsp_emulation.c35
1 files changed, 35 insertions, 0 deletions
diff --git a/kernel/gsp_emulation.c b/kernel/gsp_emulation.c
index 38f6284..b82bab1 100644
--- a/kernel/gsp_emulation.c
+++ b/kernel/gsp_emulation.c
@@ -705,6 +705,38 @@ void gsp_emu_raise_gsp_event_irq(struct gsp_emu_context *ctx)
* Emulation Thread
* ============================================================ */
+/* Advance the emulated GPU PTIMER (NV_PTIMER_TIME_0/1 at BAR0 0x9400/0x9410).
+ *
+ * The guest's nvidia.ko RM uses this register as its time source for timed
+ * waits (e.g. _nv015102rm -> _nv018147rm -> _nv018351rm). BAR0 is a plain
+ * host shadow mapped to the guest, so nothing advances these registers by
+ * default: every RM deadline becomes unreachable and the DDX/GL client
+ * spins forever inside the driver (observed as an Xorg hang at GDI/window
+ * creation). Seed from the existing value to keep time continuous, then
+ * advance by the host monotonic clock.
+ */
+static void gsp_emu_tick_ptimer(struct gsp_emu_context *ctx)
+{
+ u64 now, val;
+
+ if (!ctx->bar0_vaddr)
+ return;
+
+ now = ktime_get_ns();
+ if (!ctx->ptimer_seeded) {
+ u32 lo = gsp_emu_shadow_read32(ctx, 0x9400);
+ u32 hi = gsp_emu_shadow_read32(ctx, 0x9410);
+
+ ctx->ptimer_base = ((u64)hi << 32) | lo;
+ ctx->ptimer_t0 = now;
+ ctx->ptimer_seeded = true;
+ }
+
+ val = ctx->ptimer_base + (now - ctx->ptimer_t0);
+ gsp_emu_shadow_write32(ctx, 0x9400, (u32)val);
+ gsp_emu_shadow_write32(ctx, 0x9410, (u32)(val >> 32));
+}
+
static int gsp_emu_thread_fn(void *data)
{
struct gsp_emu_context *ctx = data;
@@ -716,6 +748,9 @@ static int gsp_emu_thread_fn(void *data)
nv_vgpu_info(ctx->vgpu, "GSP emulation thread started");
while (!kthread_should_stop()) {
+ /* Keep the guest-visible GPU timer advancing (RM timed waits) */
+ gsp_emu_tick_ptimer(ctx);
+
/* Read doorbell */
doorbell_val = gsp_emu_read_doorbell(ctx);