diff options
| -rw-r--r-- | kernel/gsp_phys_booter.c | 97 |
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; |
