diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/gsp_sema_service.c | 53 | ||||
| -rw-r--r-- | kernel/gsp_sema_service.h | 8 | ||||
| -rw-r--r-- | kernel/main.c | 7 |
3 files changed, 60 insertions, 8 deletions
diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c index 1296f81..ce2e0c9 100644 --- a/kernel/gsp_sema_service.c +++ b/kernel/gsp_sema_service.c @@ -143,6 +143,10 @@ struct svc_channel { u32 logged_expected; /* last pool value logged (rate limit) */ unsigned long rescue_last; /* rate limit for the full-RAM rescue scan */ u32 rescue_fail; /* consecutive failed rescues for the entry */ + unsigned long defer_since; /* first failure of the pending GR entry + * (0 = none): the entry is left pending + * for the GR grace window so a late + * window pin can still make it readable */ u64 counter_pa; /* guest PA of the u32 GPU completion counter * (registered via the sema_counter debug param); * 0 = not registered */ @@ -3255,6 +3259,14 @@ static int svc_chan_entry0(struct nv_vgpu_device *vgpu, struct svc_channel *ch, #define SVC_GR_USERD_OFF 0x2000ULL bool gsp_sema_gr_rings = true; +/* + * GR (compute) entries whose push page is not translatable are left pending + * for this long before the pump consumes them as stale. The push pages are + * mapped and pinned by a host watcher from guest truth a moment after the + * channels appear; without the grace the first entries are consumed before + * the pin lands and the releases they carry are lost. + */ +unsigned gsp_sema_gr_grace_ms = 8000; /* * CE release fallback: when a push carrying a tracking-semaphore release @@ -4029,7 +4041,12 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu) kfree(pb); break; } else if (++ch->rescue_fail >= - (ch->engine_type ? 2 : 1)) { + (ch->engine_type ? 2 : 1) && + (ch->engine_type || + (ch->defer_since && + time_after(jiffies, + ch->defer_since + + msecs_to_jiffies(gsp_sema_gr_grace_ms))))) { /* * The slot no longer holds this * push (overwritten buffer): the @@ -4045,18 +4062,20 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu) * cannot validate - and their * completion signal is the * per-channel counter we publish - * from `put`. Consume on the - * first failed attempt: a slow - * skip delays GPGet and the - * counter long enough for the - * client's submission wait to - * expire (observed at ~12 s with - * the 3-attempt path). + * from `put`. The entry is left + * pending for a grace window + * first: the push pages are + * pinned from guest truth a + * moment after the channels + * appear, and only a readable + * push carries the releases the + * client waits on. */ pr_info("sema-chan: skipping stale entry h=0x%x va=0x%llx len=%u after %u failed rescues\n", ch->h_object, va, len, ch->rescue_fail); ch->rescue_fail = 0; + ch->defer_since = 0; if (gsp_sema_fake_rel) svc_fake_release(vgpu, ch); @@ -4071,6 +4090,21 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu) kfree(pb); continue; } else { + /* + * First failure (CE) or + * inside the GR grace window: + * leave the entry pending so + * a translation that lands + * shortly still gets the push + * executed. The completion + * counter is published from + * `put` at the end of the pass + * either way. + */ + if (!ch->engine_type && + !ch->defer_since) + ch->defer_since = + jiffies; svc.gpfifo_nomap++; kfree(pb); break; @@ -4081,6 +4115,8 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu) } ch->last_get = (idx + 1) % ch->gpfifo_entries; + ch->rescue_fail = 0; + ch->defer_since = 0; /* Publish progress the way the GPU would. */ g = ch->last_get; @@ -4118,6 +4154,7 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu) svc.chan[k].last_rel_va = ch->last_rel_va; svc.chan[k].rescue_last = ch->rescue_last; svc.chan[k].rescue_fail = ch->rescue_fail; + svc.chan[k].defer_since = ch->defer_since; break; } } diff --git a/kernel/gsp_sema_service.h b/kernel/gsp_sema_service.h index 3b85591..8cd9e61 100644 --- a/kernel/gsp_sema_service.h +++ b/kernel/gsp_sema_service.h @@ -77,4 +77,12 @@ extern bool gsp_sema_gr_rings; */ extern bool gsp_sema_fake_rel; +/* + * Grace window (ms) an untranslatable GR GPFIFO entry is left pending before + * the pump consumes it as stale. The GR push pages are pinned from guest + * truth a moment after the channels appear; the window lets those pins land + * so the releases inside the pushes are applied. + */ +extern unsigned gsp_sema_gr_grace_ms; + #endif /* _GSP_SEMA_SERVICE_H_ */ diff --git a/kernel/main.c b/kernel/main.c index 726b4bf..952daf1 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -2441,6 +2441,13 @@ module_param_named(sema_fake_rel, gsp_sema_fake_rel, bool, 0644); MODULE_PARM_DESC(sema_fake_rel, "Acknowledge unreadable CE releases directly (default 0)"); /* + * Grace window (ms) an untranslatable GR entry stays pending before the pump + * consumes it as stale, so a late push-buffer pin can still make it readable. + */ +module_param_named(sema_gr_grace_ms, gsp_sema_gr_grace_ms, uint, 0644); +MODULE_PARM_DESC(sema_gr_grace_ms, "GR pending-entry grace window in ms (default 8000)"); + +/* * Debug: inject a verified {GPU VA -> guest PA} translation into the * semaphore service (used when the client's mapping cannot be discovered * from guest structures): |
