summaryrefslogtreecommitdiffstats
path: root/kernel/gsp_phys_booter.c
diff options
context:
space:
mode:
authorArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-18 12:00:52 -0400
committerArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-18 12:10:03 -0400
commit04aad03adc45683d03fe1451b8f234061e6b88ff (patch)
treebd354b50006a57bf54a302ba6a086fdca137f902 /kernel/gsp_phys_booter.c
parent2658fedd556f872f11dd3aeefa88ff6eb76c5342 (diff)
downloadopen-iov-04aad03adc45683d03fe1451b8f234061e6b88ff.tar.gz
open-iov-04aad03adc45683d03fe1451b8f234061e6b88ff.zip
vgsp: fail4 discrimination tooling - copy-out page witnesses + full-boot bigcopy resolution budget
Four guest CUDA clients fail all-bad while four pass; the aggregate counters cannot separate 'engine result never produced' from 'produced but written to a different guest page than the client's read resolves'. Add the two per-page witnesses that correlate the write side with the read side: - gsp_phys_gr_copyout_dump (booter, default 1): per-changed-page OUT-PAGE-WIT va=<device VA> hpa=<guest PA written> first8/last8=<bytes shipped>, bounded 12 pages per launch, plus one RELOC-CENSUS line per launch (gaps vs late-resolved words vs late pages). - sema_bigcopy_log (sema service, default 24, was a hardcoded per-boot budget): the svc_copy large-copy proof already logs both operands' resolved VA -> pa/aperture/provenance and the first 16 bytes each side; raising the budget past the boot's head makes the failing clients' H2D/D2H resolutions visible. Discrimination test for the next cycle: same device VA on OUT-PAGE-WIT (copy-out HPA) and sema-bigcopy (D2H source pa) with different PAs proves the produced-but-misplaced class; equal PAs redirects to the readback content/engine-input path. (cherry picked from commit 78ea8b7807231ac418a17b85c29ed1845e1b0062)
Diffstat (limited to 'kernel/gsp_phys_booter.c')
-rw-r--r--kernel/gsp_phys_booter.c59
1 files changed, 59 insertions, 0 deletions
diff --git a/kernel/gsp_phys_booter.c b/kernel/gsp_phys_booter.c
index 6a66a16..2f74fa1 100644
--- a/kernel/gsp_phys_booter.c
+++ b/kernel/gsp_phys_booter.c
@@ -116,6 +116,30 @@ module_param_named(gsp_phys_gr_reloc_resolve, gsp_phys_gr_reloc_resolve_param,
MODULE_PARM_DESC(gsp_phys_gr_reloc_resolve,
"Resolve QMD words that match no tracked data page and author them as late data pages (default 1: RELOC-FIXED; 0: RELOC-GAP only)");
+/*
+ * COPYWIT (2026-10-18 fail4 discrimination tooling, default 1): witness the
+ * copy-out of every tracked page the engine changed - device VA, guest HPA
+ * the results were written back to, and the first/last 8 bytes actually
+ * shipped. Correlating these lines with the sema-bigcopy D2H resolution lines
+ * (same VA -> pa) and the client's own check discriminates "engine result
+ * never produced" from "produced but landed on a different guest page than
+ * the client's read resolves" - the two classes the all-bad client results
+ * cannot separate from the aggregate counters alone. Bounded per launch
+ * (GSP_PHYS_GR_COPYWIT_MAX) and rate-limited; 0 disables both this and the
+ * per-launch RELOC-CENSUS line.
+ */
+#define GSP_PHYS_GR_COPYWIT_MAX 12u
+static bool gsp_phys_gr_copyout_dump_param = true;
+module_param_named(gsp_phys_gr_copyout_dump, gsp_phys_gr_copyout_dump_param,
+ bool, 0644);
+MODULE_PARM_DESC(gsp_phys_gr_copyout_dump,
+ "Log per-changed-page copy-out witnesses (VA, HPA, first/last 8 bytes) and the per-launch relocation census (default 1)");
+
+static inline bool gsp_phys_gr_copywit_enabled(void)
+{
+ return READ_ONCE(gsp_phys_gr_copyout_dump_param);
+}
+
bool gsp_phys_boot_enabled(void)
{
return gsp_phys_boot_param;
@@ -19124,6 +19148,19 @@ gr_page_unmapped:
ret = -EAGAIN;
goto out;
}
+ /*
+ * COPYWIT fail4: one per-launch census of the rewrite outcome so the
+ * resolved/unresolved split of every bank pass is provable from a
+ * single line (gaps left as guest VAs vs late-resolved words authored
+ * via RELOC-FIXED). Rate-limited like the per-word lines.
+ */
+ if (gsp_phys_gr_copywit_enabled() &&
+ (reloc_gap || gsp_phys_gr_reloc_fixed))
+ pr_info_ratelimited("vgsp-gr: RELOC-CENSUS gaps=%u first_gap=0x%llx fixed=%llu first_fixed=0x%llx late_pages=%u\n",
+ reloc_gap, reloc_gap_first,
+ gsp_phys_gr_reloc_fixed,
+ gsp_phys_gr_reloc_fixed_first,
+ gsp_phys_gr_gap_n);
/*
* Rank-2 qmdwin (gsp_phys_rmcall_gr_qmdwin=1): relocate the inline-QMD
@@ -20545,6 +20582,7 @@ gr_page_unmapped:
struct gsp_phys_boot_chunk *dchunk = gsp_phys_gr_data_chunk();
u32 wbi, wrote = 0, changed = 0;
u32 chg[8] = { };
+ u32 outwit = 0; /* COPYWIT: bounded per-launch witness lines */
for (wbi = 0; wbi < req->n_data; wbi++) {
u32 bi = gsp_phys_gr_data_bi(req->data[wbi].reloc_va);
@@ -20576,6 +20614,27 @@ gr_page_unmapped:
get_unaligned_le32(src + 4),
get_unaligned_le32(src + 8),
get_unaligned_le32(src + 12));
+ /*
+ * COPYWIT fail4: per-changed-page copy-out
+ * witness - the exact (device VA -> guest
+ * HPA) pair the results were written back to
+ * plus the first/last 8 bytes shipped. The
+ * D2H side of the same VA is named by the
+ * sema-bigcopy resolution lines; equal VAs
+ * with different PAs on the two sides is the
+ * produced-but-misplaced class.
+ */
+ if (gsp_phys_gr_copywit_enabled() &&
+ outwit < GSP_PHYS_GR_COPYWIT_MAX) {
+ outwit++;
+ pr_info("vgsp-gr: OUT-PAGE-WIT va=0x%llx hpa=0x%llx bi=%u first8=%016llx last8=%016llx\n",
+ req->data[wbi].va,
+ req->data[wbi].hpa, bi,
+ (u64)get_unaligned_le64(src),
+ (u64)get_unaligned_le64(
+ src + GSP_PHYS_PAGE_SIZE -
+ 8));
+ }
if (changed < 8)
chg[changed] = bi;
changed++;