summaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/gsp_sema_service.c38
1 files changed, 38 insertions, 0 deletions
diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c
index 9f967a5..5f76442 100644
--- a/kernel/gsp_sema_service.c
+++ b/kernel/gsp_sema_service.c
@@ -13110,6 +13110,44 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu)
if (!ch->gpfifo_va || !ch->gpfifo_entries)
continue;
+ /*
+ * ISSUE-0002 (r80): the CeUtils scrubber channel is a
+ * GPU-global kernel channel that stays registered across
+ * client sessions (client-scoped deletion). It must not be
+ * entry-pumped: its channel buffer memory is reused by later
+ * clients' push buffers, so decoding its stale ring invents
+ * work and perturbs the session (r79/r80 wedges). What the
+ * guest's pma scrub waits on is the channel buffer's finish
+ * payload at pbGpuVA + channelPbSize + gpfifo_size + 4,
+ * i.e. gpfifo_va + 8*entries + 4 (verified against the live
+ * channel object: gpfifo=0x120064000 entries=4096 ->
+ * 0x12006c004). Publish it forward-only from the channel's
+ * own GP_PUT: the guest waits for submittedWorkId <=
+ * payload, one payload per submitted push, and the put
+ * counts exactly those pushes. The scrub work itself is
+ * emulated vidmem maintenance; the guest reads its own
+ * shadow through BAR1, so completing the counter is the
+ * contract.
+ */
+ if (ch->gpfifo_entries >= 4096) {
+ u32 sfin = 0;
+
+ if (ch->userd_pa &&
+ !svc_read_ap(vgpu, ch->userd_pa + SVC_USERD_GP_PUT,
+ ch->userd_as, &sfin, sizeof(sfin)) &&
+ sfin) {
+ u64 fin_va = ch->gpfifo_va +
+ 8ULL * ch->gpfifo_entries + 4;
+ u32 fcur = 0;
+
+ if (!svc_sem_read(vgpu, fin_va, &fcur) &&
+ sfin > fcur)
+ svc_sem_write(vgpu, ch->h_object,
+ fin_va, sfin);
+ }
+ continue;
+ }
+
svc_ring_autopin(vgpu, ch);
rrc = svc_lookup(vgpu, ch->gpfifo_va, &ring_pa, &ring_ap);