diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/gsp_phys_booter.c | 135 | ||||
| -rw-r--r-- | kernel/gsp_sema_service.c | 24 | ||||
| -rw-r--r-- | kernel/gsp_sema_service.h | 11 |
3 files changed, 170 insertions, 0 deletions
diff --git a/kernel/gsp_phys_booter.c b/kernel/gsp_phys_booter.c index 40a8791..65ab874 100644 --- a/kernel/gsp_phys_booter.c +++ b/kernel/gsp_phys_booter.c @@ -18461,6 +18461,91 @@ static int gsp_phys_gr_golden_slot(u32 j, u32 *entry, const u32 **words, } /* + * r1625 SEMANTIC-GAP (sema_gl_mme_sa_golden_fill): the golden overlay + * writes the golden bodies into the packed IR and fills its LOCAL SA pair + * table, but the per-launch SA re-arm (and the stub/call-drop walk) + * reads the service's live START-ADDRESS RAM table - the client's own + * 0x11c/0x120 capture. When that capture never supplied a slot (c772: + * slots 0..11 only, slot 34 absent), the re-arm emits no pair for it and + * the release window's CALL_MME_MACRO(34) keeps the engine's stale + * SA[34] (0 or another macro's entry): the DRAW_IAB CALL resolves to IR + * offset 0 / slot 0's body and the c772 replay ran mac=0x33/0x0/0x39, + * never mac=0x22. Fill every golden-served slot the client table cannot + * serve with the same instruction entry the overlay uses, so the re-arm + * points the CALL at the golden DRAW_IAB body (slot 34 -> 0x265). + * Default 0 = byte-identical legacy behaviour (A/B). + */ +static bool gsp_phys_rmcall_gr_mme_sa_golden_fill; +module_param_named(sema_gl_mme_sa_golden_fill, + gsp_phys_rmcall_gr_mme_sa_golden_fill, bool, 0644); +MODULE_PARM_DESC(sema_gl_mme_sa_golden_fill, + "Golden SA completion: publish a golden IR entry into the host START-ADDRESS RAM table for every golden-served slot the client capture left missing/zero, so the SA re-arm resolves CALL_MME_MACRO(j) to the golden body (default 0; A/B)"); +static u32 gsp_phys_gr_golden_fill_log; +static u64 gsp_phys_gr_golden_fill_seen; +static u32 gsp_phys_gr_golden_census_log; + +/* + * Fill the host SA table for all golden-served slots the client's capture + * cannot serve. Returns the number of entries filled this call; each slot + * is logged once per boot so a replayed window cannot spam the receipt. + */ +static u32 gsp_phys_gr_mme_sa_golden_fill(void) +{ + u32 j, filled = 0; + + if (!READ_ONCE(gsp_phys_rmcall_gr_mme_sa_golden_fill)) + return 0; + for (j = 0; j < 64u; j++) { + u32 gent, gn; + const u32 *gw; + + if (!gsp_phys_gr_golden_slot(j, &gent, &gw, &gn)) + continue; + if (!gsp_sema_mme_sa_fill(j, gent)) + continue; + filled++; + if (!(gsp_phys_gr_golden_fill_seen & (1ull << j)) && + gsp_phys_gr_golden_fill_log < 64u) { + gsp_phys_gr_golden_fill_seen |= 1ull << j; + gsp_phys_gr_golden_fill_log++; + pr_info("vgsp-gr: MME-GOLDEN sa-fill slot=%u entry=0x%x (client=missing)\n", + j, gent); + } + } + return filled; +} + +/* + * r1625 receipt: for every slot the replayed window calls, print the + * client's captured entry, the golden entry and the entry the fill + * publishes (and the re-arm then emits). Called BEFORE the fill, so + * cli_mask / cli_ent are the client's own table; bounded per boot. A slot + * called through both the MACRO and DATA ports logs twice by design (the + * receipt is the raw walk, not a deduped view). + */ +static void gsp_phys_gr_mme_sa_census(u32 j, u64 cli_mask, + const u32 *cli_ent) +{ + u32 gent = 0, gn, used; + const u32 *gw; + bool have_cli; + + if (!READ_ONCE(gsp_phys_rmcall_gr_mme_sa_golden_fill) || + gsp_phys_gr_golden_census_log >= 64u || j >= 64u) + return; + have_cli = (cli_mask & (1ull << j)) && cli_ent[j]; + if (gsp_phys_gr_golden_slot(j, &gent, &gw, &gn)) + used = have_cli ? cli_ent[j] : gent; + else { + gent = 0; + used = have_cli ? cli_ent[j] : 0u; + } + gsp_phys_gr_golden_census_log++; + pr_info("vgsp-gr: MME-GOLDEN sa-census slot=%u client=0x%x golden=0x%x used=0x%x\n", + j, have_cli ? cli_ent[j] : 0u, gent, used); +} + +/* * r1448 STRATEGY 3.3 golden-only completion: with golden_force on and * the golden_only knob on, a slot the golden library cannot serve must * never execute. Returns true when the slot is outside the golden corpus @@ -23432,6 +23517,15 @@ if (gsp_phys_gr_slot_kept(j, sa_mask, u32 gj, goldn = 0, ginsp = 0; u32 gblank = 0; + /* + * r1625: complete the host SA table + * from the same library before the + * pack emission, so the per-launch + * re-arm and the release window's + * CALL runs resolve to these bodies + * (sema_gl_mme_sa_golden_fill). + */ + gsp_phys_gr_mme_sa_golden_fill(); for (gj = 0; gj < 64u; gj++) { u32 gent, gn, q; const u32 *gw; @@ -24458,6 +24552,39 @@ if (gsp_phys_gr_slot_kept(j, sa_mask, u64 sa_mask = gsp_sema_mme_sa_get(sa_ent, 64); u32 r = 0, rearm = 0; + /* + * r1625 census: sa_ent/sa_mask are the client's own + * table here (pre-fill); the census prints the entry + * the fill publishes and the re-arm then emits. + */ + while (r < win3d_n) { + u32 h = win3d[r]; + u32 op = (h >> 29) & 7u; + u32 cnt = (h >> 16) & 0xfffu; + u32 span = ((op == 1u || op == 3u || + op == 5u) && cnt && + r + 1u + cnt <= win3d_n) ? + 1u + cnt : 1u; + u32 mb = (h & 0xfffu) << 2; + + if (mb >= 0x3800u && mb <= 0x39fcu) + gsp_phys_gr_mme_sa_census( + (mb - 0x3800u) / 8u, sa_mask, + sa_ent); + r += span; + } + /* + * r1625: the saved-window release launch never emits + * the golden overlay (emit_prelude is off), and a + * client capture may have re-zeroed a slot after the + * overlay ran. Complete the host SA table here - the + * launch that actually runs the CALL runs - so the + * re-arm below points them at the golden bodies the + * pack holds (slot 34 -> DRAW_IAB at IR 0x265). + */ + gsp_phys_gr_mme_sa_golden_fill(); + sa_mask = gsp_sema_mme_sa_get(sa_ent, 64); + r = 0; while (r < win3d_n && rearm < 32u) { u32 h = win3d[r]; u32 op = (h >> 29) & 7u; @@ -31715,6 +31842,14 @@ gr_page_unmapped: win3d = stream_patch; win3d_n = win_n; /* + * r1625: publish the golden SA entries before the stub/drop + * walk reads the START-ADDRESS RAM table, so a golden-served + * slot the client capture never supplied (c772: slot 34) is + * present for both the drop decision here and the builder's + * per-launch re-arm. No-op with sema_gl_mme_sa_golden_fill=0. + */ + gsp_phys_gr_mme_sa_golden_fill(); + /* * SESSION 153-CONTINUED-69: drop the CALL_MME_MACRO/DATA runs * of stubbed slots (see gsp_phys_gr_mme_drop_calls). With the * stub as a pure NOP terminator the parameter port no longer diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c index 26d3b1a..603e9f0 100644 --- a/kernel/gsp_sema_service.c +++ b/kernel/gsp_sema_service.c @@ -20364,6 +20364,30 @@ static void svc_mme_sa_record(u32 slot, u32 entry) svc_mme_sa_present |= 1ull << slot; } +/* + * Golden SA completion (sema_gl_mme_sa_golden_fill): publish a slot's + * golden IR entry into the host-side START-ADDRESS RAM table when the + * client's own 0x11c/0x120 runs never supplied it (present bit clear, or + * present with entry 0 - the r1231 "SA[34]=0 lands last" shape). A + * nonzero client entry is never overwritten: the client's own upload is + * always the authority. The GR builder calls this before its per-launch + * SA re-arm and its stub/call-drop decisions, so a golden-served slot + * (e.g. DRAW_IAB slot 34 -> IR 0x265) resolves to the same IR offset the + * pack overlay wrote instead of jumping to macro 0. + */ +bool gsp_sema_mme_sa_fill(u32 slot, u32 entry) +{ + if (slot >= 64u) + return false; + if ((READ_ONCE(svc_mme_sa_present) & (1ull << slot)) && + svc_mme_sa_entry[slot]) + return false; + WRITE_ONCE(svc_mme_sa_entry[slot], entry); + WRITE_ONCE(svc_mme_sa_present, + READ_ONCE(svc_mme_sa_present) | (1ull << slot)); + return true; +} + static bool svc_mme_setup_run_addr(u32 addr) { return (addr >= 0x114u && addr <= 0x124u) || addr == 0x234u || diff --git a/kernel/gsp_sema_service.h b/kernel/gsp_sema_service.h index ba1da96..5a1c491 100644 --- a/kernel/gsp_sema_service.h +++ b/kernel/gsp_sema_service.h @@ -630,6 +630,17 @@ bool gsp_sema_gr_surf_recs(u64 *va, u32 *n); u64 gsp_sema_mme_sa_get(u32 *entries, u32 n); /* + * Golden SA completion (sema_gl_mme_sa_golden_fill): set the host-side + * START-ADDRESS RAM entry for `slot` to `entry` and mark it present, but + * only when the client's own table has no usable entry for the slot + * (absent, or present with entry 0). Returns true when the entry was + * filled, false when a nonzero client entry was kept (or slot out of + * range). The GR builder uses it to point the held window's CALL runs at + * the golden bodies the pack overlay wrote. + */ +bool gsp_sema_mme_sa_fill(u32 slot, u32 entry); + +/* * SESSION 153-CONTINUED-101: the client's own SET_MME_SHADOW_SCRATCH(0x18) * write (method 0x3460) - mmeCodeOGL_C597_SETUP_FIXED_CONST (slot 0) reads * shadow scratch 0x18/0xd18 via STATE and emits it as the fixed-function |
