From 5fa773c2cd4e166d2c31a40aff9fb63e7534fec3 Mon Sep 17 00:00:00 2001 From: Arthur Hanson Rasmusson Date: Sun, 11 Oct 2026 16:43:33 -0400 Subject: vgsp-sema: scope channel deletion to the owning RM client (ISSUE-0002) Handles are per-client, but the FREE path unregistered any channel whose numeric handle matched the freed object, with no client check. r77 root cause of the third-client pma scrub hang: the boot session's CeUtils scrubber channel (h=0x2, gpfifo=0x120064000, entries=4096) was unregistered when an unrelated class-0x2080 object with handle 0x2 in client 0xc1d00011 was freed. The guest kept using the live channel for the scrub; the service no longer pumped it, its pushes were never decoded and the channel-buffer finish payload (pbGpuVA+0x6c004) was never written, so scrubCheckAndWaitForSize polled forever (sysrq stack: ceutilsUpdateProgress -> channelReadChannelMemdesc). Channel registration now records h_client (the RM alloc header's client) and deletion matches (h_object, h_client); a missing client on either side keeps the handle-only behaviour. Re-registration keeps the counter/release slots only for the same (handle, client) pair. Live proof from the hung VM: sema_probe translates the finish-payload VA 0x12006c004 to pa=0x10f962004 aperture=ram - the word the guest polls is reachable; the channel was simply invisible to the pump. --- kernel/gsp_rm_emulation.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'kernel/gsp_rm_emulation.c') diff --git a/kernel/gsp_rm_emulation.c b/kernel/gsp_rm_emulation.c index 8318f56..b4bee46 100644 --- a/kernel/gsp_rm_emulation.c +++ b/kernel/gsp_rm_emulation.c @@ -2348,8 +2348,9 @@ static bool gsp_rm_is_channel_class(u32 class_id) #define GSPRM_CHAN_MEM_APERTURE 16 /* offset of addressSpace in the desc */ #define GSPRM_CHAN_NOTIFIER_MEM 248 -static void gsp_rm_register_channel(struct gsp_emu_context *ctx, u32 h_object, - const u8 *params, u32 params_size) +static void gsp_rm_register_channel(struct gsp_emu_context *ctx, u32 h_client, + u32 h_object, const u8 *params, + u32 params_size) { struct sema_channel_desc desc; @@ -2358,6 +2359,7 @@ static void gsp_rm_register_channel(struct gsp_emu_context *ctx, u32 h_object, memset(&desc, 0, sizeof(desc)); desc.h_object = h_object; + desc.h_client = h_client; memcpy(&desc.gpfifo_va, params + GSPRM_CHAN_GPFIFO_OFFSET, 8); memcpy(&desc.gpfifo_entries, params + GSPRM_CHAN_GPFIFO_ENTRIES, 4); memcpy(&desc.engine_type, params + GSPRM_CHAN_ENGINE_TYPE, 4); @@ -2435,7 +2437,7 @@ static void gsp_rm_handle_rm_alloc(struct gsp_emu_context *ctx, /* Channels: hand the progress service everything it needs to run the * work submitted on this channel (GPFIFO ring + USERD). */ if (gsp_rm_is_channel_class(class_id)) - gsp_rm_register_channel(ctx, ho, params, params_size); + gsp_rm_register_channel(ctx, hc, ho, params, params_size); /* * NV01_EVENT (allocated with class 0x79 in the guest ABI; params are @@ -3244,7 +3246,7 @@ static void gsp_rm_handle_free(struct gsp_emu_context *ctx, const u8 *elem, memcpy(&hObjOld, params + 8, 4); memset(params + 12, 0, 4); /* status = NV_OK */ - gsp_sema_service_channel_del(hObjOld); + gsp_sema_service_channel_del(hObjOld, hRoot); /* * Retire event records that refer to the object being freed. Posting an -- cgit v1.2.3