summaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-09 21:55:10 -0400
committerArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-09 21:55:10 -0400
commit3b063e2fc846b367b2d782d04ec9588078a3ae26 (patch)
tree1e5f0a157b5527a90e758c987603e46310f75d2e /kernel
parentd0ae432ade6941a705875b9db2a9d26b23c23b59 (diff)
downloadopen-iov-3b063e2fc846b367b2d782d04ec9588078a3ae26.tar.gz
open-iov-3b063e2fc846b367b2d782d04ec9588078a3ae26.zip
vgsp-sema: hold an entry on ANY failed op, not only an unresolvable operand (ISSUE-0002)
r71 c3 reached the pma scrub and froze in scrubCheckAndWaitForSize: three vidmem memsets (1 MiB / 297 KiB / 608 KiB) failed with -EINVAL because svc_op_translate resolved their client-VA destinations through a walk to an out-of-bounds vidmem translation before the scanner pinned the real sysmem pages. Only svc_op_translate's own failure sets op_tr_pending, so the pump consumed the entry and applied the release while the memset work was lost. svc_run_ops now marks the pass op-pending for any op that did not run (rc != 0, rc != SVC_COPY_FORWARDED): the pump holds the entry and withholds its releases (bounded by SVC_OPDEF_HOLD_MS) so the retried decode picks up the injected pin and runs the memset; on expiry the release is flushed and the op stays skipped, exactly like the -ENOENT path. Sessions with no failed ops (c1/c2 were 0 fails in r71) are unaffected.
Diffstat (limited to 'kernel')
-rw-r--r--kernel/gsp_sema_service.c17
1 files changed, 17 insertions, 0 deletions
diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c
index 075a429..77ae4b4 100644
--- a/kernel/gsp_sema_service.c
+++ b/kernel/gsp_sema_service.c
@@ -4613,6 +4613,23 @@ static void svc_run_ops(struct nv_vgpu_device *vgpu, struct svc_memset_op *ops,
svc.memsets_nomap++;
else
svc.memsets_fail++;
+ /*
+ * ISSUE-0002 (r71): ANY failed op leaves work owed on this
+ * entry, not only an unresolvable operand. The pma scrub
+ * memsets resolve a bogus out-of-bounds vidmem destination
+ * through a walk before the scanner pins the real sysmem
+ * page; svc_copy fails them with -EINVAL, and the old code
+ * consumed the entry and applied the release anyway, leaving
+ * the client frozen in scrubCheckAndWaitForSize. Mark the
+ * pass as op-pending so the pump holds the entry and
+ * withholds its releases (bounded by SVC_OPDEF_HOLD_MS,
+ * exactly like the -ENOENT path): the retried decode checks
+ * the injected pins first and runs the memset once the real
+ * translation lands. On expiry the release is flushed and the
+ * op stays skipped (the pre-r62 fallback).
+ */
+ if (rc != 0 && rc != SVC_COPY_FORWARDED)
+ svc.op_tr_pending = 1;
if (gsp_sema_dbg && m->bytes == 256 && svc.sem256_log < 64) {
svc.sem256_log++;
pr_info("sema-256: type=%u dst=0x%llx src=0x%llx bytes=%llu rc=%d h=0x%x done=%llu nomap=%llu fail=%llu\n",