diff options
| author | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-10-18 06:36:08 -0400 |
|---|---|---|
| committer | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-10-18 06:37:12 -0400 |
| commit | 7cd528ad8614a1e623bea598711c276a925b9f57 (patch) | |
| tree | 3a383e863c9fec440b2d6dc506a6becb6f51587b | |
| parent | e99040b9ca2acc10a9d4b57fe45626331e203a7c (diff) | |
| download | open-iov-7cd528ad8614a1e623bea598711c276a925b9f57.tar.gz open-iov-7cd528ad8614a1e623bea598711c276a925b9f57.zip | |
vgsp: GR fill hold - self-enforcing bound at decision point; benign-unresolvable class undecidable (bounded, not bypassed)
| -rw-r--r-- | kernel/gsp_sema_service.c | 77 |
1 files changed, 66 insertions, 11 deletions
diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c index 6286d38..3a955df 100644 --- a/kernel/gsp_sema_service.c +++ b/kernel/gsp_sema_service.c @@ -13422,10 +13422,14 @@ static bool svc_fwd_hold_poll(struct nv_vgpu_device *vgpu, ch->last_get = (idx + 1) % ch->gpfifo_entries; ch->rescue_fail = 0; ch->defer_since = 0; - /* GRFIX FIX1b: this entry is consumed; its per-launch absolute-bound - * record resets so a later launch (slot/VA reuse) arms a fresh one. */ - ch->gr_hold_dead_va = 0; - ch->gr_hold_exp_logged = false; + /* + * GRFIX FIX1c (r214): do NOT reset the per-launch bound record + * here. This consume can belong to a different entry than the held + * launch, and resetting on every consume re-armed the bound before + * it could pass (r214: 420 re-holds, GRFILL-EXPIRED=0 over 220 s). + * The record is keyed by the launch push VA; it resets only on + * channel (re)registration or the session diag reset. + */ ch->submissions++; svc.gpfifo_entries_done++; if (ch->engine_type && ch->expected_sem_payload) @@ -14372,7 +14376,8 @@ static bool svc_gr_hold_bound_expired(struct svc_channel *ch, u64 launch_va) return time_after_eq(jiffies, ch->gr_hold_deadline); } -static void svc_gr_data_fill(struct nv_vgpu_device *vgpu) +static void svc_gr_data_fill(struct nv_vgpu_device *vgpu, + struct svc_channel *ch) { u64 wins[16]; bool is_arg[16]; /* m150: candidate came from the argument scan */ @@ -14412,6 +14417,8 @@ static void svc_gr_data_fill(struct nv_vgpu_device *vgpu) * (gsp_phys_gr_hold_max_ms) - when it passes the launch proceeds. */ u32 dropped_pages = 0; + bool bound_hit = false; /* GRFIX FIX1c: the absolute bound fired this + * pass - the launch proceeds, no hold */ /* * GRFIX FIX1c (r213): detail for the first (up to 4) dropped pages, * so the cycle records WHICH VAs and which candidate class dropped. @@ -14826,7 +14833,44 @@ static void svc_gr_data_fill(struct nv_vgpu_device *vgpu) svc_gr_data_stalled = (dropped_pages > 0) || (n_arg_hi > 0 && n_arg_hi_res == 0); svc_fwd_req.gr_dropped = dropped_pages; - if (dropped_pages > 0) { + /* + * GRFIX FIX1c (r214): the DECISION POINT IS SELF-ENFORCING. The + * absolute per-launch bound is consulted here - at the only place + * the stalled verdict is produced, before the GRFILL-HOLD line can + * be emitted and before any caller can act on the verdict - so no + * re-drive pass can bypass it. r214: the same launch re-filled + * ~2/s for 220 s with GRFILL-EXPIRED=0 because the a5715df1 + * consume-tail resets wiped the per-launch record between passes + * while the entry index moved (107 -> 99) under pin-batch rewinds, + * so the bound svc_gr_request consulted was re-armed before it + * could pass. When the bound passes the launch PROCEEDS: the + * historical (pre-8b058884) forward path runs, exactly as if the + * fill had not stalled. + * + * GRFIX FIX1d (benign class): the observed drops (probe=none / + * walk rc=-2) are indistinguishable at fill time from a page + * whose pin simply has not landed yet - both have no source at + * this instant and the only discriminator is whether the pin + * arrives inside the window. A blanket "probe=none => never hold" + * would also disable the pin-late retry the hold exists for, so + * the absolute bound stays the only guard: benign drops cost at + * most gsp_phys_gr_hold_max_ms once per launch VA, then the + * launch proceeds. + */ + if (svc_gr_data_stalled && ch && + svc_gr_hold_bound_expired(ch, svc_fwd_req.gr_push_va)) { + svc.fwd_gr_hold_exp++; + bound_hit = true; + if (!ch->gr_hold_exp_logged) { + ch->gr_hold_exp_logged = true; + pr_info("vgsp-gr: GRFILL-EXPIRED launch=0x%llx dropped=%u waited_ms=%u\n", + svc_fwd_req.gr_push_va, dropped_pages, + jiffies_to_msecs(jiffies - + ch->gr_hold_dead_since)); + } + svc_gr_data_stalled = false; /* proceed: forward */ + } + if (dropped_pages > 0 && !bound_hit) { pr_info_ratelimited("vgsp-gr: GRFILL-HOLD launch=0x%llx dropped=%u kept=%u\n", svc_fwd_req.gr_push_va, dropped_pages, svc_fwd_req.gr_n_data); @@ -14851,6 +14895,9 @@ static void svc_gr_data_fill(struct nv_vgpu_device *vgpu) pr_info("vgsp-sema: svc-gr data fill: %u candidate ptrs, %u pages resolved; %u high argument ptr(s), %u resolved; %u dropped page(s) -> launch held for a bounded retry\n", n_cand, svc_fwd_req.gr_n_data, n_arg_hi, n_arg_hi_res, dropped_pages); + else if (bound_hit) + pr_info_ratelimited("vgsp-sema: svc-gr data fill: %u candidate ptrs, %u pages resolved; %u dropped page(s); hold bound expired -> launch proceeds\n", + n_cand, svc_fwd_req.gr_n_data, dropped_pages); else pr_info("vgsp-sema: svc-gr data fill: %u candidate ptrs, %u pages resolved (reloc 0x%llx+)\n", n_cand, svc_fwd_req.gr_n_data, reloc_base); @@ -14969,7 +15016,14 @@ static int svc_gr_req_fill(struct nv_vgpu_device *vgpu, if (!svc_gr_page_inline_covers(pg->va)) return -ENOENT; } - svc_gr_data_fill(vgpu); + /* + * GRFIX FIX1c: the fill hosts the self-enforcing decision point and + * therefore needs the channel's per-launch bound record. The const + * view exists for the read-only gates; the channel is the pump's + * mutable live bookkeeping object and this runs on the same + * service thread. + */ + svc_gr_data_fill(vgpu, (struct svc_channel *)ch); return 0; } @@ -17487,10 +17541,11 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu) ch->gr_nocap_va = 0; ch->unread_va = 0; ch->unread_until = 0; - /* GRFIX FIX1b: the entry is consumed; the per-launch - * absolute-bound record resets with it. */ - ch->gr_hold_dead_va = 0; - ch->gr_hold_exp_logged = false; + /* GRFIX FIX1c (r214): do NOT reset the per-launch + * bound record here - a consume of an unrelated entry + * would re-arm the held launch's bound every pass + * (see svc_fwd_hold_poll). Reset happens on channel + * (re)registration and the session diag reset. */ /* Publish progress the way the GPU would. */ g = ch->last_get; |
