summaryrefslogtreecommitdiffstats
path: root/kernel/gsp_phys_booter.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/gsp_phys_booter.c')
-rw-r--r--kernel/gsp_phys_booter.c97
1 files changed, 88 insertions, 9 deletions
diff --git a/kernel/gsp_phys_booter.c b/kernel/gsp_phys_booter.c
index 2f74fa1..bc0ca74 100644
--- a/kernel/gsp_phys_booter.c
+++ b/kernel/gsp_phys_booter.c
@@ -140,6 +140,33 @@ static inline bool gsp_phys_gr_copywit_enabled(void)
return READ_ONCE(gsp_phys_gr_copyout_dump_param);
}
+/*
+ * COPYWIT fail4 r224 follow-up: the r224 OUT-PAGE-WIT dumps proved the
+ * engine's outputs are structurally corrupted (row bands >= 16 replicate a
+ * single tile per buffer) while the copy-out write/read pairs agree
+ * byte-for-byte. Two witnesses make the next cycle name the source:
+ *
+ * - OUT-ALIAS-WIT: during copy-out, every changed page's first 8 bytes are
+ * matched against the earlier changed pages of the SAME launch; a hit
+ * logs the (va, bi) pair, i.e. the replicated-page structure and the rec
+ * partners - the direct evidence for "one tile replicated across the
+ * band" and against "pass-through of pre-launch content" (the pre/post
+ * csums in OUT-PAGE-WIT prove the engine changed the page).
+ * - IN-ALIAS-WIT: during the copy-in fill, consecutive recs with identical
+ * content (equal per-page csum) are logged - a replicated INPUT buffer
+ * (e.g. an X or weight region whose H2D/copy-in served one page many
+ * times) is caught here before any launch runs.
+ * Bounded boot-wide and per launch; same single-inflight static discipline
+ * as the other submit scratch.
+ */
+#define GSP_PHYS_GR_OUTWIT_SLOTS 16u
+static u64 gsp_phys_gr_outwit_first8[GSP_PHYS_GR_OUTWIT_SLOTS];
+static u64 gsp_phys_gr_outwit_va[GSP_PHYS_GR_OUTWIT_SLOTS];
+static u32 gsp_phys_gr_outwit_bi[GSP_PHYS_GR_OUTWIT_SLOTS];
+static u32 gsp_phys_gr_outwit_n;
+static u32 gsp_phys_gr_alias_log; /* boot-wide alias-line budget */
+static u32 gsp_phys_gr_in_alias_log;
+
bool gsp_phys_boot_enabled(void)
{
return gsp_phys_boot_param;
@@ -17721,6 +17748,8 @@ static u32 gsp_phys_gr_fill_bounce(const struct gsp_phys_gr_submit *req,
{
struct gsp_phys_boot_chunk *dchunk = gsp_phys_gr_data_chunk();
u32 di, copied = 0;
+ u64 prev_va = 0;
+ u32 prev_csum = 0;
for (di = 0; di < req->n_data; di++) {
u32 bi = gsp_phys_gr_data_bi(req->data[di].reloc_va);
@@ -17740,6 +17769,20 @@ static u32 gsp_phys_gr_fill_bounce(const struct gsp_phys_gr_submit *req,
for (ci = 0; ci < GSP_PHYS_PAGE_SIZE; ci += 4)
csum += get_unaligned_le32(dst + ci);
csum_in[bi] = csum;
+ /*
+ * IN-ALIAS-WIT (COPYWIT r224 follow-up): two consecutive tracked
+ * recs whose guest content is identical prove a replicated INPUT
+ * region (one page served for many VAs). Logged with both VAs so
+ * the source can be named; bounded boot-wide.
+ */
+ if (prev_va && csum == prev_csum && gsp_phys_gr_copywit_enabled() &&
+ gsp_phys_gr_in_alias_log < 12) {
+ gsp_phys_gr_in_alias_log++;
+ pr_info_ratelimited("vgsp-gr: IN-ALIAS-WIT va=0x%llx prev_va=0x%llx csum=0x%08x (identical guest page content)\n",
+ req->data[di].va, prev_va, csum);
+ }
+ prev_va = req->data[di].va;
+ prev_csum = csum;
copied++;
}
dma_wmb();
@@ -18418,6 +18461,7 @@ int gsp_phys_backend_guest_gr_submit(const struct gsp_phys_gr_submit *req,
gsp_phys_gr_gap_word_n = 0;
gsp_phys_gr_reloc_fixed = 0;
gsp_phys_gr_reloc_fixed_first = 0;
+ gsp_phys_gr_outwit_n = 0; /* COPYWIT: per-launch alias table */
gsp_phys_gr_gap_logged_n = 0;
/*
* The fault record is static scratch (frame bound): reset it per
@@ -20596,6 +20640,8 @@ gr_page_unmapped:
for (ci = 0; ci < GSP_PHYS_PAGE_SIZE; ci += 4)
csum += get_unaligned_le32(src + ci);
if (csum != bounce_csum_in[bi]) {
+ u64 f8 = (u64)get_unaligned_le64(src);
+
/*
* m142: which pages the engine touched. bi is
* the page index inside the active data region
@@ -20618,22 +20664,55 @@ gr_page_unmapped:
* 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.
+ * plus the first/last 8 bytes shipped and the
+ * pre/post csum pair (proof the engine changed
+ * the page vs the copy-in baseline). The D2H
+ * side of the same VA is named by the
+ * sema-bigcopy resolution lines.
*/
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",
+ pr_info("vgsp-gr: OUT-PAGE-WIT va=0x%llx hpa=0x%llx bi=%u first8=%016llx last8=%016llx pre=%08x post=%08x\n",
req->data[wbi].va,
- req->data[wbi].hpa, bi,
- (u64)get_unaligned_le64(src),
+ req->data[wbi].hpa, bi, f8,
(u64)get_unaligned_le64(
src + GSP_PHYS_PAGE_SIZE -
- 8));
+ 8),
+ bounce_csum_in[bi], csum);
+ }
+ /*
+ * OUT-ALIAS-WIT: identical first 8 bytes as
+ * an earlier changed page of this launch =
+ * the replicated-tile structure, with both
+ * recs named.
+ */
+ if (gsp_phys_gr_copywit_enabled()) {
+ u32 wi;
+
+ for (wi = 0; wi < gsp_phys_gr_outwit_n;
+ wi++) {
+ if (gsp_phys_gr_outwit_first8[wi] !=
+ f8)
+ continue;
+ if (gsp_phys_gr_alias_log < 12) {
+ gsp_phys_gr_alias_log++;
+ pr_info("vgsp-gr: OUT-ALIAS-WIT va=0x%llx bi=%u partner_va=0x%llx partner_bi=%u first8=%016llx\n",
+ req->data[wbi].va,
+ bi,
+ gsp_phys_gr_outwit_va[wi],
+ gsp_phys_gr_outwit_bi[wi],
+ f8);
+ }
+ break;
+ }
+ if (gsp_phys_gr_outwit_n <
+ GSP_PHYS_GR_OUTWIT_SLOTS) {
+ gsp_phys_gr_outwit_first8[gsp_phys_gr_outwit_n] = f8;
+ gsp_phys_gr_outwit_va[gsp_phys_gr_outwit_n] = req->data[wbi].va;
+ gsp_phys_gr_outwit_bi[gsp_phys_gr_outwit_n] = bi;
+ gsp_phys_gr_outwit_n++;
+ }
}
if (changed < 8)
chg[changed] = bi;