diff options
| author | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-10-11 22:34:10 -0400 |
|---|---|---|
| committer | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-10-11 22:34:10 -0400 |
| commit | 2d1afd5d04bd61bbea3d63ede5c020684963ca4c (patch) | |
| tree | 72a4109e21d1e610dada6f91bdeea8fff28fcfd4 | |
| parent | 3530fb6ee20d514eddb0e21645abddf512059367 (diff) | |
| download | open-iov-2d1afd5d04bd61bbea3d63ede5c020684963ca4c.tar.gz open-iov-2d1afd5d04bd61bbea3d63ede5c020684963ca4c.zip | |
vgsp-gr: one bounded re-arm of a stalled forwarded launch (context save/unload lottery)
r90 evidence: the 3rd session's forwarded launch entered SKED (CWD VALID)
and was then saved/unloaded by the FECS before dispatch; qmd_rel stayed at
5/6, GP_GET froze, and every later launch on the boot was never fetched
either. The service owns no repair path, so the channel stayed dead until
reboot.
On the first poll timeout, re-issue the two GPFIFO_SCHEDULE controls the
stage-4 sequence used (channel-level 0xa06f0103 + TSG-level 0xa06c0101,
both proven accepted) and re-ring the work-submit doorbell, then poll one
more full window before the postmortem. No BIND, no PROMOTE (m76-m81
proved the explicit PREEMPT/tail variants stop the QMD enqueuing).
| -rw-r--r-- | kernel/gsp_phys_booter.c | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/kernel/gsp_phys_booter.c b/kernel/gsp_phys_booter.c index 72b500a..e2c2989 100644 --- a/kernel/gsp_phys_booter.c +++ b/kernel/gsp_phys_booter.c @@ -16452,6 +16452,49 @@ static int gsp_phys_rmcall_gr_data_map(void __iomem *bar0, u64 va, u64 hpa, * queue (epoch-gated) into out->fault. Every refusal moves the GR counters * and returns an errno the sema service falls back on. */ +/* + * m142: re-arm a stalled forwarded launch. The engine dispatch path is + * nondeterministic: the QMD can enter SKED and then be saved/unloaded by the + * FECS before it dispatches, after which the channel is never fetched again + * (r90: qmd_rel stuck at 5/6, GP_GET frozen, every later launch on the boot + * also unfetched). The schedule state set once at stage 4 is the only re-arm + * lever the service owns: re-issue the same channel-level and TSG-level + * GPFIFO_SCHEDULE controls the stage-4 sequence used (both proven accepted) + * and re-ring the work-submit doorbell so a PBDMA that stopped polling is + * prompted again. No BIND, no PROMOTE: m76-m81 proved the explicit + * PREEMPT/tail variants stop the QMD from enqueuing at all. + */ +static int gsp_phys_rmcall_gr_resched_locked(void __iomem *bar0) +{ + u8 sched_params[2] = { 1, 0 }; + u32 rpc_result = 0, status = 0; + u32 runlist_id, ch_id, doorbell; + int ret; + + ret = gsp_phys_rmcall_control(bar0, boot_stage.rmcall_channel, + GSP_PHYS_RMCALL_CTRL_GPFIFO_SCHEDULE, + sched_params, sizeof(sched_params), 16, + NULL, 0, &rpc_result, &status, + "GR rearm GPFIFO_SCHEDULE"); + if (ret) + return ret; + rpc_result = 0; + status = 0; + ret = gsp_phys_rmcall_control(bar0, boot_stage.rmcall_tsg, + GSP_PHYS_RMCALL_CTRL_TSG_GPFIFO_SCHEDULE, + sched_params, sizeof(sched_params), 16, + NULL, 0, &rpc_result, &status, + "GR rearm TSG_GPFIFO_SCHEDULE"); + if (ret) + return ret; + runlist_id = (boot_stage.rmcall_token >> 16) & 0x7fu; + ch_id = boot_stage.rmcall_token & 0xfffu; + doorbell = ((runlist_id << 16) & 0x7f00000u) | (ch_id & 0xfffu); + wmb(); + writel(doorbell, bar0 + GSP_PHYS_RMCALL_DOORBELL_OFF); + return 0; +} + int gsp_phys_backend_guest_gr_submit(const struct gsp_phys_gr_submit *req, struct gsp_phys_backend_copy_result *out) { @@ -16502,6 +16545,7 @@ int gsp_phys_backend_guest_gr_submit(const struct gsp_phys_gr_submit *req, bool qmd_win_diag = false; bool qmdwin_on = false; char qmdwin_note[32] = ""; + bool rearmed = false; int ret = 0; if (out) @@ -17460,6 +17504,32 @@ gr_page_unmapped: pr_err("vgsp-gr: GR LAUNCH FAILED: timeout after %u ms (qmd_rel=0x%08x want=0x%08x ch_rel=0x%08x want=0x%08x) h=0x%x push=0x%llx\n", GSP_PHYS_RMCALL_GR_POLL_MS, w0, want_qmd, w1, want_ch, req->h_object, req->push_va); + /* + * m142: one bounded re-arm before declaring the launch + * dead. Re-issue the stage-4 schedule controls and re-ring + * the doorbell, then poll again; if the channel was merely + * de-scheduled (context save/unload lottery) this revives + * it. A second timeout falls through to the postmortem. + */ + if (!rearmed) { + int rr; + + rearmed = true; + mutex_lock(&gsp_phys_rm_lock); + rr = gsp_phys_rmcall_gr_resched_locked(bar0); + mutex_unlock(&gsp_phys_rm_lock); + if (!rr) { + pr_info("vgsp-gr: rearm after timeout: schedule re-issued + doorbell re-rung; re-polling %u ms\n", + GSP_PHYS_RMCALL_GR_POLL_MS); + deadline = jiffies + + msecs_to_jiffies( + GSP_PHYS_RMCALL_GR_POLL_MS); + grpoll_n = 0; + continue; + } + pr_info("vgsp-gr: rearm after timeout failed rc=%d\n", + rr); + } if (gsp_phys_gr_fault_active()) { struct gsp_phys_fault_info fi; u32 fep = 0; |
