summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArthur Hanson Rasmusson <arthur@vgpu.io>2026-11-15 15:36:24 -0500
committerArthur Hanson Rasmusson <arthur@vgpu.io>2026-11-15 15:36:24 -0500
commitfc000768b972a52e972830c2f5287c67c42275fd (patch)
tree2c5d3e9b1de8b571cbae4094684877beb7b41f14
parent82943ce19bdff4e0d9664562f448f91f81f68490 (diff)
downloadopen-iov-fc000768b972a52e972830c2f5287c67c42275fd.tar.gz
open-iov-fc000768b972a52e972830c2f5287c67c42275fd.zip
vgsp: eng61 - prefer a DRAW_IAB-bearing window in the release save (diagnostic + robustness)
The saved-window release carrier replays the client's held window with the CALL runs kept. Save the raw window after scanning it for the CALL_MME_MACRO(34) DRAW_IAB run (method 0x3910, the 0xA00A0E44 ten-data run); if the saved record already carries it and a later held window does not, keep the saved one (bounded MME-CARRY-SAVE-PREFER receipts). Caveat established from c772: its 728 B window also carries the 0xA00A0E44 slot-34 run at raw[113], so the DRAW_IAB window bytes are not the discriminator; the c772 replay ran 0x33/0x0/0x39 because SA[34]/the golden IR entry was stubbed, not because the window lacked the call. The next lever is the SA[34]/golden-body residency census, not the window choice. Build rc 0; validation pending.
-rw-r--r--kernel/gsp_phys_booter.c164
1 files changed, 121 insertions, 43 deletions
diff --git a/kernel/gsp_phys_booter.c b/kernel/gsp_phys_booter.c
index 0180da1..40a8791 100644
--- a/kernel/gsp_phys_booter.c
+++ b/kernel/gsp_phys_booter.c
@@ -18861,6 +18861,8 @@ struct gsp_phys_gr_mme_release_state {
u32 gen;
u32 held;
u32 win_n;
+ /* The saved raw window carries the CALL_MME_MACRO(34) DRAW_IAB run. */
+ bool draw_ia;
u64 push_va;
unsigned long due_j;
u32 boot_n;
@@ -18905,6 +18907,46 @@ module_param_named(sema_gl_mme_pack_release_ms,
MODULE_PARM_DESC(sema_gl_mme_pack_release_ms,
"Settle delay before the saved-window release carrier fires (clamped 20..5000 ms; default 100)");
+/*
+ * DRAW_IAB preference (release carrier follow-up): the held-call window that
+ * matters is the DRAW window, whose method stream carries the
+ * CALL_MME_MACRO(34) run that expands to DRAW_IAB (mac=0x22).
+ * CALL_MME_MACRO(j) is method 0x3800 + 8*j, so slot 34 is 0x3910; the
+ * client encodes it as the ONE_INCR run `a00a0e44` (op 5, count 10, method
+ * 0x3910, ten data words - c756 push 0x4011978 raw[12]; the same word in
+ * both c716 held windows and at raw[113] of the c772 728 B stream, whose
+ * replay executed only 0x33/0x39 for an SA-entry reason outside this
+ * preference). The scan uses the CALL hold/drop walk's run grammar (op 1/3/5
+ * carry 1+cnt words; only op 1/3 walk past the header method), so a
+ * CALL_MME_DATA(34) port write (0x3914) or another slot's call never
+ * selects the record.
+ */
+static bool gsp_phys_gr_mme_window_has_draw_ia(const u32 *win, u32 n)
+{
+ u32 r = 0;
+
+ while (r < n) {
+ u32 h = win[r];
+ u32 op = (h >> 29) & 7u;
+ u32 cnt = (h >> 16) & 0x1fffu;
+ u32 span = 1u, k;
+
+ if ((op == 1u || op == 3u || op == 5u) && cnt &&
+ r + 1u + cnt <= n)
+ span = 1u + cnt;
+ for (k = 0; k < span; k++) {
+ u32 m = ((h & 0xfffu) << 2) + 4u * k;
+
+ if (k && op != 1u && op != 3u)
+ break;
+ if (m == 0x3800u + 34u * 8u)
+ return true;
+ }
+ r += span;
+ }
+ return false;
+}
+
static u32 gsp_phys_gr_mme_release_due_ms(void)
{
u32 ms = READ_ONCE(gsp_phys_rmcall_gr_mme_pack_release_ms);
@@ -18929,6 +18971,9 @@ static void gsp_phys_gr_mme_release_save(const struct gsp_phys_gr_submit *req,
{
struct gsp_phys_gr_mme_release_state *s = &gsp_phys_gr_mme_release;
unsigned long flags;
+ bool draw_ia, keep = false;
+ u32 old_h = 0, old_win = 0;
+ static u32 prefer_log;
if (!READ_ONCE(gsp_phys_rmcall_gr_mme_pack_release) || !req)
return;
@@ -18947,51 +18992,84 @@ static void gsp_phys_gr_mme_release_save(const struct gsp_phys_gr_submit *req,
req->n_pages, req->n_inl, req->n_data);
return;
}
+ draw_ia = gsp_phys_gr_mme_window_has_draw_ia(req->stream,
+ req->stream_n);
spin_lock_irqsave(&gsp_phys_gr_mme_release_lock, flags);
- s->valid = false;
- s->armed = false;
- s->fired = false;
- s->consumed = false;
- s->arm_h = 0;
- s->arm_push = 0;
- s->h_object = req->h_object;
- s->gen = gen;
- s->held = held;
- s->win_n = win_n;
- s->push_va = req->push_va;
- memcpy(s->qmd, req->qmd, sizeof(s->qmd));
- s->n_pages = req->n_pages;
- if (req->n_pages)
- memcpy(s->pages, req->pages,
- (size_t)req->n_pages * sizeof(s->pages[0]));
- s->n_inl = req->n_inl;
- if (req->n_inl)
- memcpy(s->inl, req->inl,
- (size_t)req->n_inl * sizeof(s->inl[0]));
- s->n_data = req->n_data;
- if (req->n_data)
- memcpy(s->data, req->data,
- (size_t)req->n_data * sizeof(s->data[0]));
- s->n_data_wins = req->n_data_wins;
- if (req->n_data_wins)
- memcpy(s->data_wins, req->data_wins,
- (size_t)req->n_data_wins * sizeof(s->data_wins[0]));
- s->qmd_va = req->qmd_va;
- s->qmd_hpa = req->qmd_hpa;
- s->push_len = req->push_len;
- s->stream_rel = req->stream_rel;
- s->stream_n = req->stream_n;
- memcpy(s->win, req->stream, (size_t)req->stream_n * 4u);
- s->prog_va = req->prog_va;
- s->n_prog_binds = req->n_prog_binds;
- memcpy(s->prog_bind_va, req->prog_bind_va,
- sizeof(s->prog_bind_va));
- memcpy(s->prog_bind_slot, req->prog_bind_slot,
- sizeof(s->prog_bind_slot));
- s->valid = true;
+ /*
+ * The DRAW window's raw stream is the release payload that can run the
+ * DRAW_IAB CALL(34); a later held window whose stream lacks the call
+ * (e.g. a state-only window) must not supersede it. A cancelled,
+ * released or consumed record is never protected, so the no-DRAW_IAB
+ * case keeps the historical last-held-window-wins behaviour.
+ */
+ if (s->valid && !s->consumed && s->draw_ia && !draw_ia) {
+ old_h = s->h_object;
+ old_win = s->win_n;
+ keep = true;
+ }
+ if (!keep) {
+ s->valid = false;
+ s->armed = false;
+ s->fired = false;
+ s->consumed = false;
+ s->arm_h = 0;
+ s->arm_push = 0;
+ s->h_object = req->h_object;
+ s->gen = gen;
+ s->held = held;
+ s->win_n = win_n;
+ s->draw_ia = draw_ia;
+ s->push_va = req->push_va;
+ memcpy(s->qmd, req->qmd, sizeof(s->qmd));
+ s->n_pages = req->n_pages;
+ if (req->n_pages)
+ memcpy(s->pages, req->pages,
+ (size_t)req->n_pages * sizeof(s->pages[0]));
+ s->n_inl = req->n_inl;
+ if (req->n_inl)
+ memcpy(s->inl, req->inl,
+ (size_t)req->n_inl * sizeof(s->inl[0]));
+ s->n_data = req->n_data;
+ if (req->n_data)
+ memcpy(s->data, req->data,
+ (size_t)req->n_data * sizeof(s->data[0]));
+ s->n_data_wins = req->n_data_wins;
+ if (req->n_data_wins)
+ memcpy(s->data_wins, req->data_wins,
+ (size_t)req->n_data_wins *
+ sizeof(s->data_wins[0]));
+ s->qmd_va = req->qmd_va;
+ s->qmd_hpa = req->qmd_hpa;
+ s->push_len = req->push_len;
+ s->stream_rel = req->stream_rel;
+ s->stream_n = req->stream_n;
+ memcpy(s->win, req->stream, (size_t)req->stream_n * 4u);
+ s->prog_va = req->prog_va;
+ s->n_prog_binds = req->n_prog_binds;
+ memcpy(s->prog_bind_va, req->prog_bind_va,
+ sizeof(s->prog_bind_va));
+ memcpy(s->prog_bind_slot, req->prog_bind_slot,
+ sizeof(s->prog_bind_slot));
+ s->valid = true;
+ }
spin_unlock_irqrestore(&gsp_phys_gr_mme_release_lock, flags);
- pr_info("vgsp-gr: MME-CARRY-SAVE h=0x%x win=%u held=%u push=0x%llx\n",
- req->h_object, win_n, held,
+ if (keep) {
+ if (prefer_log < 16u) {
+ prefer_log++;
+ pr_info("vgsp-gr: MME-CARRY-SAVE-PREFER keep=draw-ia "
+ "h=0x%x old_win=%u new_win=%u\n",
+ old_h, old_win, win_n);
+ }
+ return;
+ }
+ if (draw_ia && prefer_log < 16u) {
+ prefer_log++;
+ pr_info("vgsp-gr: MME-CARRY-SAVE-PREFER take=draw-ia h=0x%x win=%u\n",
+ req->h_object, win_n);
+ }
+ pr_info("vgsp-gr: MME-CARRY-SAVE h=0x%x win=%u held=%u draw_ia=%u "
+ "raw=%u push=0x%llx\n",
+ req->h_object, win_n, held, draw_ia, req->stream_n,
(unsigned long long)req->push_va);
}