summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-16 13:42:14 -0400
committerArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-16 13:42:14 -0400
commita8d816cda07935fe7bd31215b0edd6caf722c412 (patch)
treeec7371baddbc8628af0401e17056865b4b4d2c78
parent06b9333cf64f613be5dfb3ea1ee40e087a182061 (diff)
downloadopen-iov-a8d816cda07935fe7bd31215b0edd6caf722c412.tar.gz
open-iov-a8d816cda07935fe7bd31215b0edd6caf722c412.zip
vgsp-gr: m156 integrate bigpath+dual; qmdwin double-buffer (E3); warm sem push on zero-write retry (E5)
- Merge bigpath (B-2 64 MiB grown data-bounce region for large operands) and dual (per-mdev separation G1-G8a) into master. - E3: the inline-QMD destination is now double-buffered (0x107000/0x108000, same proven PTE fetch line); launches alternate banks by submission epoch so a QMD-unit look-ahead read of the previous launch's page can never race this launch's rewrite. - E5: on the first zero-write outcome retry the module pushes the proven stage-4 GR semaphore block; OK = engine alive (retry can recover), timeout = engine wedged for the boot and further retries are skipped (saves ~20 s), counted in work_gr sem_wedged.
-rw-r--r--kernel/gsp_phys_booter.c90
1 files changed, 71 insertions, 19 deletions
diff --git a/kernel/gsp_phys_booter.c b/kernel/gsp_phys_booter.c
index ec39d39..0f7e91c 100644
--- a/kernel/gsp_phys_booter.c
+++ b/kernel/gsp_phys_booter.c
@@ -1061,6 +1061,16 @@ bool gsp_phys_boot_requested(void)
* engine's first fetch of the line - and never at launch time.
*/
#define GSP_PHYS_RMCALL_VA_GR_QMDWIN (GSP_PHYS_RMCALL_VA_BASE + 0x7000)
+/*
+ * m156 (E3): double-buffer the inline-QMD destination. The page is
+ * prewritten every launch; when a single VA is reused the engine's QMD-unit
+ * look-ahead reads of the previous launch may still be in flight against the
+ * rewrite (the rationale the m151 win0 banks give). Slot 0x108 sits in the
+ * same already-proven 128 B PTE fetch line as 0x107 and is otherwise unused;
+ * launches alternate 0x107000/0x108000 by submission epoch. Both PTEs are
+ * planted once at stage 3 (no invalidate path exists).
+ */
+#define GSP_PHYS_RMCALL_GR_QMDWIN_SLOTS 2u
/*
* P6a guest-memory windows (gsp_phys_guest_mem=1). Two more slots in the same
@@ -9629,29 +9639,33 @@ static void gsp_phys_rmcall_pdb_build(void)
&boot_stage.rmcall_gr_qmdwin;
u32 qw_idx = (u32)((GSP_PHYS_RMCALL_VA_GR_QMDWIN >> 12) &
0x1ffu);
+ u32 qw_s;
if (!qw->pages) {
if (!boot_stage.pdev) {
pr_warn("vgsp-boot: rm-call: qmdwin plant skipped: no claimed pci_dev; launches keep the guest QMD destination\n");
- } else if (!gsp_phys_chunk_alloc(boot_stage.pdev, qw, 1u)) {
+ } else if (!gsp_phys_chunk_alloc(boot_stage.pdev, qw,
+ GSP_PHYS_RMCALL_GR_QMDWIN_SLOTS)) {
gsp_phys_chunk_zero(qw);
} else {
pr_warn("vgsp-boot: rm-call: qmdwin page allocation failed; launches keep the guest QMD destination\n");
}
}
- if (qw->pages) {
- put_unaligned_le64(gsp_phys_rmcall_pte(
- (u64)gsp_phys_chunk_page_dma(qw, 0)),
- (u8 *)gsp_phys_chunk_page_va(pt, 0) +
- (size_t)qw_idx * 8);
+ if (qw->pages >= GSP_PHYS_RMCALL_GR_QMDWIN_SLOTS) {
+ for (qw_s = 0; qw_s < GSP_PHYS_RMCALL_GR_QMDWIN_SLOTS;
+ qw_s++)
+ put_unaligned_le64(gsp_phys_rmcall_pte(
+ (u64)gsp_phys_chunk_page_dma(qw,
+ qw_s)),
+ (u8 *)gsp_phys_chunk_page_va(pt, 0) +
+ (size_t)(qw_idx + qw_s) * 8);
if (!boot_stage.rmcall_gr_qmdwin_va)
- pr_info("vgsp-boot: rm-call: qmdwin module page planted VA=0x%llx ptSlot=0x%x pte=0x%016llx dma=0x%llx (before the engine's first fetch)\n",
- GSP_PHYS_RMCALL_VA_GR_QMDWIN, qw_idx,
- get_unaligned_le64(
- (u8 *)gsp_phys_chunk_page_va(
- pt, 0) +
- (size_t)qw_idx * 8),
- (u64)gsp_phys_chunk_page_dma(qw, 0));
+ pr_info("vgsp-boot: rm-call: qmdwin module pages planted VA=0x%llx..0x%llx ptSlots=0x%x/0x%x (double-buffer, before the engine's first fetch)\n",
+ GSP_PHYS_RMCALL_VA_GR_QMDWIN,
+ GSP_PHYS_RMCALL_VA_GR_QMDWIN +
+ (GSP_PHYS_RMCALL_GR_QMDWIN_SLOTS - 1u) *
+ GSP_PHYS_PAGE_SIZE,
+ qw_idx, qw_idx + 1u);
boot_stage.rmcall_gr_qmdwin_va =
GSP_PHYS_RMCALL_VA_GR_QMDWIN;
}
@@ -16135,6 +16149,9 @@ static u64 gsp_phys_gr_refused;
static u64 gsp_phys_gr_timed_out;
static u64 gsp_phys_gr_retries; /* fresh-entry launch retries published */
static u64 gsp_phys_gr_pool_exhausted;
+/* m156 (E5): zero-write retries where the warm sem push proved the engine
+ * wedged (the persistent-lottery class); further retries are skipped. */
+static u64 gsp_phys_gr_sem_wedged;
/* m86: program-page override blob (see gsp-phys-gr-override). */
static u8 gsp_phys_gr_override[GSP_PHYS_PAGE_SIZE];
static u32 gsp_phys_gr_override_len;
@@ -17801,11 +17818,16 @@ gr_page_unmapped:
NULL;
if (boot_stage.rmcall_gr_qmdwin_va && qw) {
+ u32 qw_bank = (epoch & 1u) %
+ GSP_PHYS_RMCALL_GR_QMDWIN_SLOTS;
+
qmdwin_on = true;
- qmd_dst = boot_stage.rmcall_gr_qmdwin_va;
- qmd_dst_mem = qw;
- pr_info("vgsp-gr: qmdwin: relocating inline-QMD dest 0x%llx -> 0x%llx (module ring chunk page)\n",
- req->qmd_va, qmd_dst);
+ qmd_dst = boot_stage.rmcall_gr_qmdwin_va +
+ (u64)qw_bank * GSP_PHYS_PAGE_SIZE;
+ qmd_dst_mem = gsp_phys_chunk_page_va(
+ &boot_stage.rmcall_gr_qmdwin, qw_bank);
+ pr_info("vgsp-gr: qmdwin: relocating inline-QMD dest 0x%llx -> 0x%llx (module ring chunk page, bank %u)\n",
+ req->qmd_va, qmd_dst, qw_bank);
} else {
pr_warn("vgsp-gr: qmdwin=1 but no planted module page (stage-3 plant skipped or failed); using the guest QMD destination\n");
}
@@ -18592,6 +18614,35 @@ gr_page_unmapped:
pr_info("vgsp-gr: outcome retry %u/%u (wrote=%u): refill + re-publish\n",
attempts, GSP_PHYS_RMCALL_GR_ATTEMPTS,
wrote);
+ /*
+ * m156 (E5): on the first zero-write retry, push the
+ * proven stage-4 GR semaphore block before re-publishing.
+ * It is the discriminator the lottery report asked for:
+ * if the channel can still dispatch the ladder's own
+ * 10-dword sem block, the engine is alive and the failed
+ * launch is a launch-form race (retry can recover); if
+ * the sem push times out, the engine/channel is wedged
+ * for the boot and every further retry is futile - break
+ * immediately instead of burning ~20 s of futile polls
+ * (r155: 3 outcome retries + rearm all dead after the
+ * wedge). Both outcomes are logged distinctly.
+ */
+ if (attempts == 1) {
+ int sp_ret;
+
+ mutex_lock(&gsp_phys_rm_lock);
+ sp_ret = gsp_phys_rmcall_gr_sem_push_locked(
+ bar0);
+ mutex_unlock(&gsp_phys_rm_lock);
+ pr_info("vgsp-gr: outcome retry %u: warm sem push rc=%d (engine %s)\n",
+ attempts, sp_ret,
+ sp_ret ? "WEDGED - skipping further retries" :
+ "ALIVE");
+ if (sp_ret) {
+ gsp_phys_gr_sem_wedged++;
+ break;
+ }
+ }
gsp_phys_gr_fill_bounce(req, bounce_csum_in);
mutex_lock(&gsp_phys_rm_lock);
ret = gsp_phys_rmcall_publish_locked(
@@ -19878,11 +19929,12 @@ static int gsp_phys_state_show(struct seq_file *m, void *v)
gsp_phys_backend_gr_counters(&b_sub, &b_ok, &b_refused,
&b_timeout, &b_pool);
seq_printf(m,
- "work_gr: req=%llu fallback=%llu ok=%llu refused=%llu timeout=%llu fault=%llu submitted=%llu backend_ok=%llu backend_refused=%llu backend_timeout=%llu pool_exhausted=%llu forward_param=%u exec_ok=%u\n",
+ "work_gr: req=%llu fallback=%llu ok=%llu refused=%llu timeout=%llu fault=%llu submitted=%llu backend_ok=%llu backend_refused=%llu backend_timeout=%llu pool_exhausted=%llu forward_param=%u exec_ok=%u sem_wedged=%llu\n",
gr_req, gr_fallback, gr_ok, gr_refused, gr_timeout,
gr_fault, b_sub, b_ok, b_refused, b_timeout, b_pool,
gsp_phys_gr_forward_enabled(),
- boot_stage.rmcall_gr_exec_ok);
+ boot_stage.rmcall_gr_exec_ok,
+ READ_ONCE(gsp_phys_gr_sem_wedged));
}
{
/*