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.c104
1 files changed, 100 insertions, 4 deletions
diff --git a/kernel/gsp_phys_booter.c b/kernel/gsp_phys_booter.c
index b9e247c..94d5f5f 100644
--- a/kernel/gsp_phys_booter.c
+++ b/kernel/gsp_phys_booter.c
@@ -18442,6 +18442,10 @@ MODULE_PARM_DESC(sema_gl_pair_chain,
static bool gsp_phys_gr_mme_pairs_emitted; /* launch emitted a pair run */
static u32 gsp_phys_gr_mme_pairs_gen; /* gen whose pairs retired OK */
static u32 gsp_phys_gr_mme_launch_gen; /* last built launch's gen */
+static bool gsp_phys_gr_mme_pair_open; /* BEGIN..END open across windows */
+static u32 gsp_phys_gr_mme_pair_open_split; /* split mode of that BEGIN */
+static bool gsp_phys_gr_mme_pair_open_entry; /* open seen when THIS window was fixed */
+static u32 gsp_phys_gr_mme_pair_entry_elide_n; /* entry-open pair-run elisions */
/*
* True when a method run in [w, w+n) writes NVC597_BEGIN (0x1618) or
@@ -18480,8 +18484,11 @@ static u32 gsp_phys_gr_pair_chain_fix(u32 *w, u32 *np, u32 cap)
{
u32 n = *np, r = 0, begins = 0, ends = 0, drains = 0;
u32 chains = 0, orphans = 0, nested = 0, badv = 0;
- bool open = false, seen = false, begin_logged = false;
- u32 open_split = 0;
+ bool open = READ_ONCE(gsp_phys_gr_mme_pair_open);
+ bool seen = false, begin_logged = false;
+ u32 open_split = READ_ONCE(gsp_phys_gr_mme_pair_open_split);
+
+ WRITE_ONCE(gsp_phys_gr_mme_pair_open_entry, open);
while (r < n) {
u32 h = w[r];
@@ -18577,10 +18584,14 @@ static u32 gsp_phys_gr_pair_chain_fix(u32 *w, u32 *np, u32 cap)
}
if (begins > 1u || drains || chains || orphans || nested || badv ||
open)
- pr_info_ratelimited("vgsp-gr: PAIR-CHAIN begin=%u end=%u drains=%u chain=%u orphan_end=%u nested=%u endv_mismatch=%u open_at_end=%u window=%u\n",
+ pr_info_ratelimited("vgsp-gr: PAIR-CHAIN begin=%u end=%u drains=%u chain=%u orphan_end=%u nested=%u endv_mismatch=%u open_at_end=%u entry=%u window=%u\n",
begins, ends, drains, chains, orphans, nested,
- badv, open ? 1u : 0u, n);
+ badv, open ? 1u : 0u,
+ READ_ONCE(gsp_phys_gr_mme_pair_open_entry) ? 1u : 0u,
+ n);
*np = n;
+ WRITE_ONCE(gsp_phys_gr_mme_pair_open, open);
+ WRITE_ONCE(gsp_phys_gr_mme_pair_open_split, open_split);
return drains;
}
@@ -21927,6 +21938,63 @@ if (gsp_phys_gr_slot_kept(j, sa_mask,
p += win3d_n;
}
/*
+ * r1454 PAIR-CHAIN-ENTRY-ELIDE: a window that ENTERS with a
+ * BEGIN..END pair already open (carried from the previous
+ * emitted window) must not re-write the program-address pair
+ * runs - the FE refuses the first state method with EC0x0d
+ * BEGIN_END_ACTIVE (r1453b #11: 0x2058 <- shadow VA at words
+ * 18-20, before the orphan END that closes the carried pair).
+ * Re-walk the FINAL emitted window with the same run math as
+ * the nop_pair branch and compact away every run overlapping
+ * [0x2054, 0x2158]. Fail closed: requires the pair_chain
+ * knob, the entry-open snapshot, and the non-zero pairs_gen
+ * retire proof (set only when a pair-bearing window retires),
+ * so launch #1 still writes its pairs (prev_open=0) and D1
+ * stays structurally dead.
+ */
+ if (READ_ONCE(gsp_phys_rmcall_gr_pair_chain) &&
+ READ_ONCE(gsp_phys_gr_mme_pair_open_entry) &&
+ READ_ONCE(gsp_phys_gr_mme_pairs_gen) != 0u &&
+ (u32)(p - pb) > win_emit_off) {
+ u32 *ww = &pb[win_emit_off];
+ u32 wn = (u32)(p - ww);
+ u32 r = 0, w = 0, elided = 0;
+
+ while (r < wn) {
+ u32 h = ww[r];
+ u32 op = (h >> 29) & 7u;
+ u32 cnt = (h >> 16) & 0xfffu;
+ u32 span = 1u, m0, mend;
+
+ if ((op == 1u || op == 3u || op == 5u) &&
+ cnt && r + 1u + cnt <= wn)
+ span = 1u + cnt;
+ m0 = (h & 0xfffu) << 2;
+ mend = m0 + 4u * (span - 1u);
+ if ((op == 0u || op == 1u || op == 3u ||
+ op == 4u || op == 5u) &&
+ m0 <= 0x2158u && mend >= 0x2054u) {
+ elided += span;
+ r += span;
+ continue;
+ }
+ if (w != r)
+ memmove(&ww[w], &ww[r],
+ (size_t)span * 4u);
+ w += span;
+ r += span;
+ }
+ if (elided) {
+ gsp_phys_gr_mme_pair_entry_elide_n++;
+ p -= elided;
+ pr_info_ratelimited("vgsp-gr: PAIR-CHAIN-ENTRY-ELIDE gen=%u n=%u total=%u (pair open at launch start; window=%u->%u)\n",
+ READ_ONCE(gsp_phys_gr_mme_pairs_gen),
+ elided,
+ gsp_phys_gr_mme_pair_entry_elide_n,
+ wn, w);
+ }
+ }
+ /*
* r1453 PAIR-CHAIN: the install proof for the held-call
* elision extension. Recomputed from the FINAL emitted window
* (after the CALL/pair elision branches above), so a launch
@@ -26790,6 +26858,14 @@ int gsp_phys_backend_guest_gr_submit(const struct gsp_phys_gr_submit *req,
deposit_rb_done = false;
gsp_phys_gr_mme_pairs_emitted = false; /* r1453 PAIR-CHAIN */
gsp_phys_gr_mme_launch_gen = 0;
+ /*
+ * r1454 PAIR-CHAIN-ENTRY-ELIDE: per-launch scratch only - the
+ * cross-launch tracker (pair_open/split) must survive this site
+ * (it is reset at the two context wipes instead). Clearing the
+ * entry snapshot here is fail-closed: a launch whose window never
+ * reaches gsp_phys_gr_pair_chain_fix cannot elide.
+ */
+ gsp_phys_gr_mme_pair_open_entry = false;
gsp_phys_gr_codehash_done = false; /* CODEHASH: once per launch */
/*
* M91 FAULT-CAP: snapshot the fault epoch per launch, so the capture
@@ -29273,6 +29349,14 @@ gr_page_unmapped:
/* r1453 PAIR-CHAIN: context wipe voids the
* pair-install proof; re-earn it. */
WRITE_ONCE(gsp_phys_gr_mme_pairs_gen, 0);
+ /* r1454 PAIR-CHAIN-ENTRY-ELIDE: the wiped
+ * context has no open FE pair; clear the
+ * cross-launch tracker too. */
+ WRITE_ONCE(gsp_phys_gr_mme_pair_open, false);
+ WRITE_ONCE(gsp_phys_gr_mme_pair_open_split,
+ 0);
+ WRITE_ONCE(gsp_phys_gr_mme_pair_open_entry,
+ false);
/*
* r1447: the wiped context voids the arming
* window-hold and the strict grace budget too.
@@ -29639,6 +29723,18 @@ gr_page_unmapped:
WRITE_ONCE(
gsp_phys_gr_mme_pairs_gen,
0);
+ /* r1454 PAIR-CHAIN-ENTRY-
+ * ELIDE: same wipe - no
+ * open FE pair remains. */
+ WRITE_ONCE(
+ gsp_phys_gr_mme_pair_open,
+ false);
+ WRITE_ONCE(
+ gsp_phys_gr_mme_pair_open_split,
+ 0);
+ WRITE_ONCE(
+ gsp_phys_gr_mme_pair_open_entry,
+ false);
/*
* r1447: same context wipe -
* void the arming window-hold