summaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-11 17:23:45 -0400
committerArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-11 17:23:45 -0400
commit12732c5894c893344422da4fd8d075c4c43c8e8a (patch)
tree6df0f33b1d519e9bd37737dd44bc758a97ad718e /kernel
parent35ca086b20f04f6be5bd935fd53d08e43f67e869 (diff)
downloadopen-iov-12732c5894c893344422da4fd8d075c4c43c8e8a.tar.gz
open-iov-12732c5894c893344422da4fd8d075c4c43c8e8a.zip
vgsp-sema: session boundary is a client change, not the last channel closing (ISSUE-0002)
r79 regression from keeping the CeUtils scrubber channel registered (client-scoped deletion): the session flush trigger required EVERY channel to close, and the scrubber never closes, so the per-session discovery reset never ran and the next client inherited the previous session's map/pins (the r9 class; the first client of r79 wedged the guest on an rwsem with no output). The session is now keyed by owning client: channel_add records svc_sess_client and requests the flush when a channel of a DIFFERENT client registers while the previous session is live (then waits for it, exactly like a pending flush); channel_del's flush trigger counts only channels of the current session client, so persistent kernel/GPU-global channels (the scrubber) no longer keep a dead session open.
Diffstat (limited to 'kernel')
-rw-r--r--kernel/gsp_sema_service.c50
1 files changed, 40 insertions, 10 deletions
diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c
index 638a866..9f967a5 100644
--- a/kernel/gsp_sema_service.c
+++ b/kernel/gsp_sema_service.c
@@ -451,6 +451,11 @@ static u32 svc_ring_n;
*/
static u8 svc_sess_flush;
static u8 svc_sess_active; /* a channel of a session has registered (until flush) */
+static u32 svc_sess_client; /* owning client of the current session's channels.
+ * The kernel/GPU-global channels (the CeUtils
+ * scrubber) persist across clients; the session
+ * boundary is a change of owning client, not the
+ * last channel closing (ISSUE-0002 r79). */
static struct completion svc_sess_flush_done; /* a pending flush has executed */
static unsigned long svc_ring_done; /* CE ranks whose ring is pinned (session state) */
static u8 svc_pb_passes;
@@ -950,6 +955,20 @@ void gsp_sema_service_channel_add(const struct sema_channel_desc *desc)
WRITE_ONCE(svc_gr_content_rearm, true);
/*
+ * ISSUE-0002 (r79): the kernel/GPU-global channels (the CeUtils
+ * scrubber, entries=4096) persist across client sessions, so the
+ * "last channel closed" trigger never fires once they are kept
+ * registered. The real session boundary is a change of owning
+ * client: when a channel of a new client registers while the
+ * previous session's state is still live, request the same flush a
+ * session end would (the wait below then lets svc_thread execute it
+ * before this session's state exists).
+ */
+ if (desc->h_client && svc_sess_client &&
+ desc->h_client != svc_sess_client && svc_sess_active)
+ WRITE_ONCE(svc_sess_flush, 1);
+
+ /*
* ISSUE-0002: a session-end flush may still be pending on svc_thread.
* It must not execute after this session's state exists (r9: the
* deferred flush ran between the first and second channel
@@ -1050,6 +1069,8 @@ void gsp_sema_service_channel_add(const struct sema_channel_desc *desc)
}
ch->valid = true;
svc_sess_active = 1;
+ if (desc->h_client)
+ svc_sess_client = desc->h_client;
ch->h_object = desc->h_object;
ch->h_client = desc->h_client;
ch->engine_type = desc->engine_type;
@@ -1136,19 +1157,28 @@ void gsp_sema_service_channel_del(u32 h_object, u32 h_client)
break;
}
/*
- * ISSUE-0002: when the last channel closes, the next client is a new
- * session in a new UVM VA space; its discovery state must not inherit
- * this session's map/pins/page-directory latch. Request the flush
- * here; it executes at the next rebuild (the only writer of that
- * state) just like a fresh boot would start empty. Only the transition
- * from "a session existed" to "empty" may request it: redundant
- * deletes for handles that never registered would otherwise re-flush
- * (and wipe) a session that started after the real one ended.
+ * ISSUE-0002: when the last channel of the current session's client
+ * closes, the next client is a new session in a new UVM VA space; its
+ * discovery state must not inherit this session's map/pins/page-
+ * directory latch. Request the flush here; it executes at the next
+ * rebuild (the only writer of that state) just like a fresh boot
+ * would start empty. Only the transition from "a session existed" to
+ * "empty" may request it: redundant deletes for handles that never
+ * registered would otherwise re-flush (and wipe) a session that
+ * started after the real one ended. Persistent kernel/GPU-global
+ * channels (a different owning client, e.g. the CeUtils scrubber) do
+ * not keep the session open (ISSUE-0002 r79: with the scrubber kept
+ * registered the old all-channels check never fired and the next
+ * client inherited stale state).
*/
if (svc_sess_active) {
for (i = 0; i < SVC_MAX_CHANNELS; i++) {
- if (svc.chan[i].valid)
- break;
+ if (!svc.chan[i].valid)
+ continue;
+ if (svc_sess_client && svc.chan[i].h_client &&
+ svc.chan[i].h_client != svc_sess_client)
+ continue;
+ break;
}
if (i == SVC_MAX_CHANNELS) {
svc_sess_active = 0;