summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/gsp_phys_booter.c103
1 files changed, 73 insertions, 30 deletions
diff --git a/kernel/gsp_phys_booter.c b/kernel/gsp_phys_booter.c
index e336247..d32d588 100644
--- a/kernel/gsp_phys_booter.c
+++ b/kernel/gsp_phys_booter.c
@@ -165,7 +165,6 @@ 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)
{
@@ -17660,6 +17659,23 @@ gsp_phys_gr_output_retire_wait(const struct gsp_phys_gr_submit *req,
if (!req->n_data)
return 0;
n_all = gsp_phys_gr_scan_pages(req, csum_in, n_tracked, NULL);
+ /*
+ * RETIRE-WIT (r227): the r227 capture shows n_tracked far below the
+ * copy-in/copy-out rec counts for the same launch (4 tracked vs 1482
+ * written back) - either the rec array genuinely aliases reloc VAs
+ * mid-launch or the observed kernel differs from this source. One
+ * line per launch proves which: n_data, the unique-bi count, and the
+ * first/last recs' va/reloc_va/bi must be sequential and in-region
+ * for a healthy launch.
+ */
+ if (gsp_phys_gr_copywit_enabled())
+ pr_info_ratelimited("vgsp-gr: RETIRE-WIT n_data=%u n_tracked=%u first_va=0x%llx first_rel=0x%llx first_bi=%u last_va=0x%llx last_rel=0x%llx last_bi=%u\n",
+ req->n_data, n_tracked ? *n_tracked : 0,
+ req->data[0].va, req->data[0].reloc_va,
+ gsp_phys_gr_data_bi(req->data[0].reloc_va),
+ req->data[req->n_data - 1].va,
+ req->data[req->n_data - 1].reloc_va,
+ gsp_phys_gr_data_bi(req->data[req->n_data - 1].reloc_va));
if (!n_all)
return 0;
for (iter = 0; iter < 300u; iter++) {
@@ -17757,6 +17773,24 @@ static inline bool gsp_phys_gr_page_all_zero(u32 csum, const u8 *p)
}
/*
+ * COPYWIT r22x INPUT-ALIAS-WIT: per-launch census of the copy-in recs (the
+ * exact VA -> HPA -> content triples the engine will read for this launch,
+ * inputs included). Each new non-zero rec is compared against the last
+ * GSP_PHYS_GR_IN_CENSUS recs:
+ * - distinct VA resolving to the SAME host page (hpa collision) is the
+ * resolver-aliasing smoking gun: several guest pages served by one host
+ * page would replicate those rows through every consumer (the observed
+ * band-replication signature);
+ * - distinct HPA with identical content is the upstream-write-clone class
+ * (an H2D that landed on one page, or guest pages that genuinely hold
+ * the same bytes).
+ * Zero pages are excluded on both sides (fresh-client zero runs are not
+ * aliasing evidence). Bounded boot-wide; same single-inflight discipline.
+ */
+#define GSP_PHYS_GR_IN_CENSUS 64u
+static u32 gsp_phys_gr_in_census_log;
+
+/*
* m153: fill the bounce window from the request's guest pages and capture a
* per-page checksum baseline. Used before the first publish and again before
* every outcome retry (a mis-executing first attempt can leave stale or
@@ -17767,9 +17801,13 @@ static u32 gsp_phys_gr_fill_bounce(const struct gsp_phys_gr_submit *req,
u32 *csum_in)
{
struct gsp_phys_boot_chunk *dchunk = gsp_phys_gr_data_chunk();
+ struct {
+ u64 va;
+ u64 hpa;
+ u32 csum;
+ } census[GSP_PHYS_GR_IN_CENSUS];
+ u32 n_census = 0;
u32 di, copied = 0;
- u64 prev_va = 0, prev_hpa = 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);
@@ -17791,33 +17829,38 @@ static u32 gsp_phys_gr_fill_bounce(const struct gsp_phys_gr_submit *req,
csum += get_unaligned_le32(dst + ci);
csum_in[bi] = csum;
zero = gsp_phys_gr_page_all_zero(csum, dst);
- /*
- * 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). The HPAs tell the two
- * classes apart: equal hpa = the resolver served ONE page for
- * several VAs (resolution aliasing); different hpa = the guest
- * pages genuinely hold the same bytes (upstream write aliasing,
- * e.g. an H2D that landed on one page). Bounded boot-wide; all-
- * zero pages are excluded on both sides (r226: a fresh client's
- * zero runs are not aliasing evidence).
- */
- if (prev_va && !zero && 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 hpa=0x%llx prev_va=0x%llx prev_hpa=0x%llx csum=0x%08x (%s)\n",
- req->data[di].va,
- req->data[di].hpa, prev_va,
- prev_hpa, csum,
- prev_hpa == req->data[di].hpa ?
- "resolver served one page for many VAs" :
- "distinct pages, identical contents");
- }
- if (!zero) {
- prev_va = req->data[di].va;
- prev_hpa = req->data[di].hpa;
- prev_csum = csum;
+ if (!zero && gsp_phys_gr_copywit_enabled()) {
+ u32 j;
+
+ for (j = 0; j < n_census; j++) {
+ if (census[j].hpa == req->data[di].hpa &&
+ census[j].va != req->data[di].va) {
+ if (gsp_phys_gr_in_census_log < 24) {
+ gsp_phys_gr_in_census_log++;
+ pr_info("vgsp-gr: INPUT-ALIAS-WIT kind=hpa-collision va=0x%llx hpa=0x%llx prev_va=0x%llx (two guest pages served by one host page)\n",
+ req->data[di].va,
+ req->data[di].hpa,
+ census[j].va);
+ }
+ } else if (census[j].csum == csum &&
+ census[j].hpa != req->data[di].hpa) {
+ if (gsp_phys_gr_in_census_log < 24) {
+ gsp_phys_gr_in_census_log++;
+ pr_info("vgsp-gr: INPUT-ALIAS-WIT kind=content-clone va=0x%llx hpa=0x%llx prev_va=0x%llx prev_hpa=0x%llx csum=0x%08x\n",
+ req->data[di].va,
+ req->data[di].hpa,
+ census[j].va,
+ census[j].hpa,
+ csum);
+ }
+ }
+ }
+ if (n_census < GSP_PHYS_GR_IN_CENSUS) {
+ census[n_census].va = req->data[di].va;
+ census[n_census].hpa = req->data[di].hpa;
+ census[n_census].csum = csum;
+ n_census++;
+ }
}
copied++;
}