diff options
| author | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-10-19 07:57:32 -0400 |
|---|---|---|
| committer | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-10-19 07:57:32 -0400 |
| commit | c1350b040f740f3aeb426bf8407ab930f5e87c28 (patch) | |
| tree | cf5ad3e8eb2a470395bac72270b5128973c94076 /kernel/gsp_sema_service.c | |
| parent | 459384e02bba4eca04fa3eca2365a731a4a7a33a (diff) | |
| download | open-iov-c1350b040f740f3aeb426bf8407ab930f5e87c28.tar.gz open-iov-c1350b040f740f3aeb426bf8407ab930f5e87c28.zip | |
vgsp: newbind holds are residual-only and short (r237 T2 3 s GP_GET delay)stallfree
r237-2: T2's GR channel carried T1's residual put=115; my 3 s empty-decode
hold delayed the host's GP_GET during the residual walk, and the guest
unwound at binding+3.46 s (zeroed PROMOTE_CTX, then full FREE) - exactly
when the host finally consumed the residual. The guest's ctx-init
patience is ~3 s, so the hold must never delay the walk that long.
- New SVC_GR_NEWBIND_HOLD_MS 1200u and per-channel
wd_newbind_hold_until: the hold windows (empty-decode and unmapped
entry) now apply only while it is fresh (<1.2 s; the rebuild lands in
~0.8 s) and only when put == get (residual context, no producer work
pending). Any pending producer work is walked without delay, so
GP_GET always advances promptly.
- wd_newbind_until (3 s) still governs retry eligibility; the opdef
drop, chanswitch log, pending-map/rebuild path are unchanged.
make kernel green.
Diffstat (limited to 'kernel/gsp_sema_service.c')
| -rw-r--r-- | kernel/gsp_sema_service.c | 26 |
1 files changed, 22 insertions, 4 deletions
diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c index 6e37b2f..0520c4f 100644 --- a/kernel/gsp_sema_service.c +++ b/kernel/gsp_sema_service.c @@ -425,6 +425,9 @@ struct svc_channel { * must reconcile the binding before the walk * (drop dead opdef slots whose since predates * the binding; log the transition) */ + unsigned long wd_newbind_hold_until; /* short hold window inside + * wd_newbind_until (residual-only, + * put==get; never delays fresh work) */ unsigned long wd_newbind_until; /* STALLFREE: freshness window of a * new binding; inside it an * unmapped/undecoded GR entry is held @@ -16604,6 +16607,15 @@ static void svc_userd_sweep(struct nv_vgpu_device *vgpu, struct svc_channel *ch, * window of extra latency on first contact. */ #define SVC_GR_NEWBIND_MS 3000u +/* + * STALLFREE r237: the HOLD part of the window must be shorter than the + * window itself. r237-2: the 3 s hold on T2's residual ring delayed its + * GP_GET past the guest's ~3 s ctx-init patience (T2 unwound with a + * zeroed PROMOTE_CTX at binding+3.46 s, exactly when the host finally + * consumed the residual). The guest needs GP_GET to advance promptly; + * the rebuild lands in ~0.8 s, so 1.2 s is enough for one attempt. + */ +#define SVC_GR_NEWBIND_HOLD_MS 1200u static void svc_gr_stale_wedge_check(struct nv_vgpu_device *vgpu, struct svc_channel *ch, u32 put, u32 get) @@ -17195,6 +17207,8 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu) svc_opdef_drop_channel(vgpu, ch->h_object, jiffies); ch->wd_newbind_until = jiffies + msecs_to_jiffies(SVC_GR_NEWBIND_MS); + ch->wd_newbind_hold_until = jiffies + + msecs_to_jiffies(SVC_GR_NEWBIND_HOLD_MS); /* * Bounded proof (r234 asks): the window was armed for * THIS binding; if a later stall shows no such line, @@ -17719,9 +17733,10 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu) !entry_replay && svc_rel_count == rel_n_iter && svc_gr_qmd_seen == 0 && - ch->wd_newbind_until && + put == get && + ch->wd_newbind_hold_until && time_before(jiffies, - ch->wd_newbind_until)) { + ch->wd_newbind_hold_until)) { if (!ch->defer_since) ch->defer_since = jiffies; @@ -18805,9 +18820,10 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu) * the rebuild caught up). */ if (!ch->engine_type && - ch->wd_newbind_until && + put == get && + ch->wd_newbind_hold_until && time_before(jiffies, - ch->wd_newbind_until)) { + ch->wd_newbind_hold_until)) { svc.rebuild_now = true; if (svc.gr_pending_map < 16) { svc.gr_pending_map++; @@ -19045,6 +19061,8 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu) svc.chan[k].wd_nocap_put = ch->wd_nocap_put; svc.chan[k].wd_chanswitch = ch->wd_chanswitch; svc.chan[k].wd_newbind_until = ch->wd_newbind_until; + svc.chan[k].wd_newbind_hold_until = + ch->wd_newbind_hold_until; svc.chan[k].pushpg_va = ch->pushpg_va; svc.chan[k].pushpg_n = ch->pushpg_n; svc.chan[k].content_max = ch->content_max; |
