From 8898bd00b7c2e6385ceb7238f29d3672308b949a Mon Sep 17 00:00:00 2001 From: Arthur Hanson Rasmusson Date: Tue, 27 Oct 2026 06:36:00 -0400 Subject: vgsp: service the guest RC watchdog channel (Volta GPFIFO class + class2d notifier ack) The guest kernel's krcWatchdog posts a notifier cycle on its own channel (object 0x31415900) every second and declares 'GPU is probably locked' when the zeroed notification never comes back within 7 s. Observed as the sustained-GL-load wedge: once a GL client (GZDOOM) enabled robust channels the errors started and Xorg eventually stalled on screen readback. - rm: register the Volta GPFIFO class 0xc36f (plus the later generations) as a channel class. The watchdog's channel allocates 0xc36f on this device - the driver picks the first class the gpu reports supported - and without it the channel never reached the progress service. It now registers and latches (put visible, entries walked). - sema: decode the class2d notifier cycle on subchannel 3 (SET_NOTIFY_A/B name the notifier VA, NOTIFY WRITE_ONLY writes the zeroed NvNotification) and author the write, like svc_notify_complete does for the work-submit token. Proven live: 'sema-notify2d: va=... zeroed (RC watchdog acked)'. - sema: also ack on every pass that sees the channel's put != get, so the ack does not depend on the ring reads (its VA is known from the first decode); idempotent. - sema: never consume a zero-length/zero-VA GPFIFO entry as empty work. Two bogus zero entries consumed through a mis-resolved ring page pushed the watchdog userd's GPGet past the driver's own GPPut and every later userd probe then read get>put, permanently rejecting the channel's real userd. Hold such entries (bounded, per-channel counter persists through the pass snapshot). - sema: a registered userd value that is a real guest PA (the watchdog's own block) outranks the ring+0x2000 convention guess the ring auto-pin applies for the CUDA GR layout. - rm: log channel-class allocs whose params are too short for registration instead of skipping silently. Remaining (next): under heavy GL traffic the watchdog ring's translation can go stale for stretches (content-scanned map answering where a pin used to), which starves the ack; pin the push/notifier pages when the first real decode delivers them. The frame capture (xshm_pub -> XShmGetImage) still stalls while that starvation is active. --- kernel/gsp_rm_emulation.c | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) (limited to 'kernel/gsp_rm_emulation.c') diff --git a/kernel/gsp_rm_emulation.c b/kernel/gsp_rm_emulation.c index d6412c3..fc08b9d 100644 --- a/kernel/gsp_rm_emulation.c +++ b/kernel/gsp_rm_emulation.c @@ -3052,8 +3052,21 @@ static bool gsp_rm_is_channel_class(u32 class_id) case 0x906f: /* MAXWELL_CHANNEL_GPFIFO_A */ case 0xa06f: /* KEPLER_CHANNEL_GPFIFO_A */ case 0xb06f: /* PASCAL_CHANNEL_GPFIFO_A */ - case 0xc06f: /* VOLTA_CHANNEL_GPFIFO_A */ + case 0xc06f: /* VOLTA_CHANNEL_GPFIFO_A (PRE-TURING NAME) */ + case 0xc36f: /* VOLTA_CHANNEL_GPFIFO_A */ + /* + * r828: the RC watchdog's channel allocates 0xc36f on this + * device (the driver's gpfifoMapping loop picks the first + * class the gpu reports supported) - without it in this set + * the channel never reaches the progress service, its class2d + * notifier cycle (SET_NOTIFY_A/B + NOTIFY) never executes and + * the guest's krcWatchdog declares the GPU locked after its + * 7 s timeout as soon as robust channels are in play. + */ case 0xc46f: /* TURING_CHANNEL_GPFIFO_A */ + case 0xc56f: /* AMPERE_CHANNEL_GPFIFO_A */ + case 0xc86f: /* HOPPER_CHANNEL_GPFIFO_A */ + case 0xc96f: /* BLACKWELL_CHANNEL_GPFIFO_A */ return true; default: return false; @@ -3075,8 +3088,18 @@ static void gsp_rm_register_channel(struct gsp_emu_context *ctx, u32 h_object, { struct sema_channel_desc desc; - if (params_size < GSPRM_CHAN_NOTIFIER_MEM + 8) + if (params_size < GSPRM_CHAN_NOTIFIER_MEM + 8) { + /* + * r828 diag: a channel-class alloc whose params are shorter + * than the notifier field is not registered, silently. The + * RC watchdog channel (hObject 0x31415900) never appeared in + * the sema table; name every such skip with its size so the + * shape question is answered by a log, not inference. + */ + pr_info("vgsp-rm: channel alloc hObject=0x%x params_size=%u too short (< %u); NOT registered\n", + h_object, params_size, GSPRM_CHAN_NOTIFIER_MEM + 8); return; + } memset(&desc, 0, sizeof(desc)); desc.vgpu = ctx->vgpu; -- cgit v1.2.3