diff options
| -rw-r--r-- | kernel/gsp_phys_booter.c | 68 |
1 files changed, 62 insertions, 6 deletions
diff --git a/kernel/gsp_phys_booter.c b/kernel/gsp_phys_booter.c index 5aeee31..62ab6eb 100644 --- a/kernel/gsp_phys_booter.c +++ b/kernel/gsp_phys_booter.c @@ -18453,12 +18453,27 @@ module_param_named(sema_gl_pair_chain, gsp_phys_rmcall_gr_pair_chain, bool, 0644); MODULE_PARM_DESC(sema_gl_pair_chain, "One logical BEGIN..END chain per launch: carry the full 32-bit BEGIN data (SPLIT_MODE 30:29), insert WAIT_FOR_IDLE(0x110) drains between back-to-back normal/normal pairs, and extend pair elision to held-call windows (default 1; 0 = legacy bytes)"); +/* + * r1465 PAIR-ORPHAN-DROP (sema_gl_pair_orphan_drop): the pair_open/split + * tracker is a projection of the FE's pair state, so it must only advance + * through windows the FE actually consumed. A dropped/held/LOAD-ONLY + * window is a pair-state no-op (restore the launch-entry snapshot), and an + * END observed while the model is closed is provably orphaned (its opener + * window was dropped) - the FE has no pair to close and faults EC 0x0d, so + * the END run is elided. Default 1; 0 = legacy bytes (leak/0x1614). + */ +static bool gsp_phys_rmcall_gr_pair_orphan_drop = true; +module_param_named(sema_gl_pair_orphan_drop, + gsp_phys_rmcall_gr_pair_orphan_drop, bool, 0644); +MODULE_PARM_DESC(sema_gl_pair_orphan_drop, + "Pair-state sync: roll pair_open/open_split back on dropped/held/LOAD-ONLY windows and elide orphan END runs when no pair is open (default 1; 0 = legacy bytes)"); 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_open_entry_split; /* split of the entry-open BEGIN */ static u32 gsp_phys_gr_mme_pair_entry_elide_n; /* entry-open pair-run elisions */ /* @@ -18497,12 +18512,13 @@ static bool gsp_phys_gr_pair_present(const u32 *w, u32 n) 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; + u32 chains = 0, orphans = 0, orphan_dropped = 0, nested = 0, badv = 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); + WRITE_ONCE(gsp_phys_gr_mme_pair_open_entry_split, open_split); while (r < n) { u32 h = w[r]; @@ -18583,6 +18599,25 @@ static u32 gsp_phys_gr_pair_chain_fix(u32 *w, u32 *np, u32 cap) begins++; } else if (is_end) { if (!open) { + /* + * r1465 PAIR-ORPHAN-DROP: the opener's + * window was dropped, so the FE has no + * pair to close and would raise EC 0x0d + * on this END. Remove the whole END run + * (header 0x80000585/0x80000584 immd13 + * form or a 1+cnt run32) in place; never + * rewrite it. + */ + if (READ_ONCE(gsp_phys_rmcall_gr_pair_orphan_drop) && + span <= n - r) { + memmove(&w[r], &w[r + span], + (size_t)(n - r - span) * 4u); + n -= span; + orphan_dropped++; + pr_info_ratelimited("vgsp-gr: PAIR-ORPHAN-DROP off=%u span=%u window=%u\n", + r, span, n); + continue; + } orphans++; } else { u32 expect = ((open_split == 1u || @@ -18596,11 +18631,11 @@ static u32 gsp_phys_gr_pair_chain_fix(u32 *w, u32 *np, u32 cap) } r += span; } - 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 entry=%u window=%u\n", - begins, ends, drains, chains, orphans, nested, - badv, open ? 1u : 0u, + if (begins > 1u || drains || chains || orphans || orphan_dropped || + nested || badv || open) + pr_info_ratelimited("vgsp-gr: PAIR-CHAIN begin=%u end=%u drains=%u chain=%u orphan_end=%u orphan_drop=%u nested=%u endv_mismatch=%u open_at_end=%u entry=%u window=%u\n", + begins, ends, drains, chains, orphans, orphan_dropped, + nested, badv, open ? 1u : 0u, READ_ONCE(gsp_phys_gr_mme_pair_open_entry) ? 1u : 0u, n); *np = n; @@ -22009,6 +22044,20 @@ if (gsp_phys_gr_slot_kept(j, sa_mask, */ win_emit_off = (u32)(p - pb); if (mme_load_only || mme_hold_window) { + /* + * r1465 PAIR-ORPHAN-DROP: the FE consumed none of + * this window, so the pair projection is a no-op: + * restore the launch-entry snapshot the fixer took + * before the walk (MME-WINDOW-HOLD and MME-LOAD-ONLY + * both land here; the held-call branch still emits + * the window, so its pairs are FE-visible). + */ + if (READ_ONCE(gsp_phys_rmcall_gr_pair_orphan_drop)) { + WRITE_ONCE(gsp_phys_gr_mme_pair_open, + READ_ONCE(gsp_phys_gr_mme_pair_open_entry)); + WRITE_ONCE(gsp_phys_gr_mme_pair_open_split, + READ_ONCE(gsp_phys_gr_mme_pair_open_entry_split)); + } if (mme_hold_window && !mme_load_only) { pr_info_ratelimited("vgsp-gr: MME-WINDOW-HOLD gen=%u h=%#x window=%u dropped (r1447 arming hold) push=0x%llx\n", pl_gen, req->h_object, win3d_n, @@ -27096,6 +27145,7 @@ int gsp_phys_backend_guest_gr_submit(const struct gsp_phys_gr_submit *req, * reaches gsp_phys_gr_pair_chain_fix cannot elide. */ gsp_phys_gr_mme_pair_open_entry = false; + gsp_phys_gr_mme_pair_open_entry_split = 0; gsp_phys_gr_codehash_done = false; /* CODEHASH: once per launch */ /* * M91 FAULT-CAP: snapshot the fault epoch per launch, so the capture @@ -29734,6 +29784,9 @@ gr_page_unmapped: 0); WRITE_ONCE(gsp_phys_gr_mme_pair_open_entry, false); + WRITE_ONCE( + gsp_phys_gr_mme_pair_open_entry_split, + 0); /* * r1447: the wiped context voids the arming * window-hold and the strict grace budget too. @@ -30112,6 +30165,9 @@ gr_page_unmapped: WRITE_ONCE( gsp_phys_gr_mme_pair_open_entry, false); + WRITE_ONCE( + gsp_phys_gr_mme_pair_open_entry_split, + 0); /* * r1447: same context wipe - * void the arming window-hold |
