From 6b445171b4c50ed74f19272f5bff7c0f42887e6d Mon Sep 17 00:00:00 2001 From: Arthur Hanson Rasmusson Date: Tue, 29 Sep 2026 16:14:12 -0400 Subject: sema-svc: persist GR counter slot per channel; stable slot layout; bulk pin queue 4k - counter_pa autoreg result is written back to the channel table so later passes cannot re-target a different slot when the live GR count changes during teardown; re-registration of the same channel preserves the slot. - counter slot layout uses the max GR count ever seen in the generation instead of the shrinking live count. - sema_map_add queue 64 -> 4096 entries so a full-window pin burst drains without ENOSPC retries. - pin_gr_stream: one batched sudo pass per flush (was one process per run, ~4 s for 400 runs), retrying only queue-rejected runs. - semfix_uvmt: SEMFIX_SKIP_PB=1 skips the blocking push-buffer chain walk when the vsock window stream already supplies those pages. --- kernel/gsp_sema_service.c | 43 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) (limited to 'kernel') diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c index c46cbbb..5bff6ca 100644 --- a/kernel/gsp_sema_service.c +++ b/kernel/gsp_sema_service.c @@ -481,6 +481,21 @@ void gsp_sema_service_channel_add(const struct sema_channel_desc *desc) } if (ch) { int k; + u64 keep_counter_pa = 0; + u8 keep_gr_index = 0, keep_ce_index = 0; + bool same = ch->valid && ch->h_object == desc->h_object; + + /* + * A re-registration of the same channel must not lose the + * counter slot learned for it (the RM re-issues registration + * for an existing channel on some control paths, and the + * counter layout does not change). + */ + if (same) { + keep_counter_pa = ch->counter_pa; + keep_gr_index = ch->gr_index; + keep_ce_index = ch->ce_index; + } memset(ch, 0, sizeof(*ch)); /* @@ -520,6 +535,11 @@ void gsp_sema_service_channel_add(const struct sema_channel_desc *desc) ch->notifier_pa = desc->notifier_pa; ch->notifier_as = desc->notifier_as ? desc->notifier_as : SVC_APERTURE_SYS; + if (same) { + ch->counter_pa = keep_counter_pa; + ch->gr_index = keep_gr_index; + ch->ce_index = keep_ce_index; + } } spin_unlock_irqrestore(&svc.chan_lock, flags); @@ -3987,6 +4007,13 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu) { /* Only ever called from the service thread. */ static struct svc_channel local[SVC_MAX_CHANNELS]; + /* + * Total GR channels the client ever had in the current generation. + * The counter-slot layout is fixed when the client allocates all its + * channels, so the slot must not be recomputed with a shrinking live + * count (a teardown pass would re-target the wrong slot). + */ + static int svc_gr_max; unsigned long flags; int i, k, n = 0, n_gr = 0; bool stalled = false; @@ -4001,6 +4028,12 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu) } spin_unlock_irqrestore(&svc.chan_lock, flags); + if (n_gr > svc_gr_max) + svc_gr_max = n_gr; + else if (!n_gr) + svc_gr_max = 0; + n_gr = svc_gr_max; + for (i = 0; i < n; i++) { struct svc_channel *ch = &local[i]; u64 ring_pa = 0; @@ -4354,6 +4387,14 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu) svc.chan[k].rescue_last = ch->rescue_last; svc.chan[k].rescue_fail = ch->rescue_fail; svc.chan[k].defer_since = ch->defer_since; + /* + * Persist the counter slot autoreg resolved on the + * snapshot: without this the next pass re-derives + * it (with a different live GR count during + * teardown) and the publishes target the wrong + * slot. + */ + svc.chan[k].counter_pa = ch->counter_pa; break; } } @@ -4620,7 +4661,7 @@ int gsp_sema_service_dump_channels(void) * could not take a batch at all. */ #define SVC_PIN_REWIND 8 -#define SVC_MAP_ADD_MAX 64 +#define SVC_MAP_ADD_MAX 4096 struct svc_map_add_req { u64 va; -- cgit v1.2.3