diff options
| author | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-11-01 09:22:08 -0500 |
|---|---|---|
| committer | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-11-01 09:22:08 -0500 |
| commit | 1fdc48e5f19ce8832e0e0355ccd68a82a4bd8511 (patch) | |
| tree | 41acde5eaa855e04d1fc11bda2e207a1f30a3bc2 /kernel | |
| parent | 54a1711284abe23582eb0cd16dc9e53069c408e6 (diff) | |
| download | open-iov-1fdc48e5f19ce8832e0e0355ccd68a82a4bd8511.tar.gz open-iov-1fdc48e5f19ce8832e0e0355ccd68a82a4bd8511.zip | |
vgsp: CONT-89 - INLINE-APPLY-ALIAS real bug fix (inline records landing on qmd_word=NONE page never applied - 1408B real program @0x4350f00 was head-only 256B at engine; live fix INLINE-APPLY-ALIAS dst=0x4351000 len=1152 pa=0x85e0f4000 first=0d0d7623); full init-push pipeline block into SPH-BIND prelude in client order (0x2040<-0x11 SET_PIPELINE_SHADER(1), 0x204c<-0x1a,0 REGISTER_COUNT/BINDING(1), 0x21c<-0x1001 INVALIDATE_SHADER_CACHES, 0x155c/0x1574 TEX pools, 0x310<-0x705, 0x22c<-0x800, 0x1128<-ffffffff x2; emission-count bug fixed - uncounted emission caused SPH-BIND skipped reloc=6/4) - 9/11 (and 5/10) PERSISTS on executing launch reading real image (r1293 SPH-BIND fam=0x4390000 j1-type=0x11 rc=0x1a initblk=17 win=306 + INLINE-RB rb=020a0481 -> S/5/9/10/11; r1292 full block visible in-window) -> wall is emulated GMMU/PTE view; next A/B gsp_phys_rmcall_gr_shadow_win0=0 vs 1, canary at SPH offset via second alias - SESSION 153 r1287-r1293
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/gsp_phys_booter.c | 176 |
1 files changed, 170 insertions, 6 deletions
diff --git a/kernel/gsp_phys_booter.c b/kernel/gsp_phys_booter.c index a28aec0..3a24967 100644 --- a/kernel/gsp_phys_booter.c +++ b/kernel/gsp_phys_booter.c @@ -23706,6 +23706,59 @@ int gsp_phys_backend_guest_gr_submit(const struct gsp_phys_gr_submit *req, pg->guest_va, sh_va, slot); } } + /* + * SESSION 153-CONTINUED-89: inline records that land on a + * qmd_word-NONE page. The record-apply loop below belongs to + * the QMD-word shadow-*copy* path and never runs for these + * pages; they are resolved to the guest HPA directly (Tier-1 + * identity, contiguous shadow-line extension, or the alias + * above), so authoring the record into pg->hpa is exactly + * what the engine will read. The concrete case: the real + * captured upload at 0x4350f00 (1408 B) crosses its 4 KB + * page - the head (256 B) lands on the program page 0x4350000 + * and applies, but the tail page 0x4351000 is qmd_word=NONE + * and was silently dropped, leaving the draw's winning j=1 + * program (the later bind) truncated at 256 B at the engine + * (the DS rejects the SASS it cannot fetch: SPH 9/11). + */ + if (mapped && pg->hpa && + pg->qmd_word == GSP_PHYS_GR_QMD_WORD_NONE) { + u32 jx; + + for (jx = 0; jx < req->n_inl; jx++) { + const struct gsp_phys_gr_inline *inl = + &req->inl[jx]; + u32 len; + + if ((inl->dst_va & + ~(u64)(GSP_PHYS_PAGE_SIZE - 1)) != pg_va) + continue; + len = inl->len; + if (len > GSP_PHYS_GR_INLINE_BYTES) + len = GSP_PHYS_GR_INLINE_BYTES; + if ((u64)(inl->dst_va & + (GSP_PHYS_PAGE_SIZE - 1)) + len > + GSP_PHYS_PAGE_SIZE) + continue; + memcpy((u8 *)__va(pg->hpa) + + (inl->dst_va & + (GSP_PHYS_PAGE_SIZE - 1)), + inl->data, len); + { + static u32 inl_alias_log; + + if (inl_alias_log < 12u) { + inl_alias_log++; + pr_info("vgsp-gr: INLINE-APPLY-ALIAS dst=0x%llx len=%u pa=0x%llx first=%08x (qmd_word=NONE page authored)\n", + inl->dst_va, len, + pg->hpa, + len >= 4 ? + get_unaligned_le32(inl->data) : + 0u); + } + } + } + } if (!mapped && pg->qmd_word != GSP_PHYS_GR_QMD_WORD_NONE && pg->qmd_word + 1 < GSP_PHYS_GR_QMD_WORDS) { struct gsp_phys_boot_chunk *sh = @@ -24446,15 +24499,112 @@ gr_page_unmapped: if (READ_ONCE(gsp_phys_rmcall_gr_sph_bind) && (req->h_object & 0xfffff000u) == 0xbeef0000u && req->prog_va && - win3d_n + 40u + 13u <= GSP_PHYS_RMCALL_GR_METHOD_WORDS) { + win3d_n + 64u <= GSP_PHYS_RMCALL_GR_METHOD_WORDS) { static u32 sph_bind_log; u64 fam = req->prog_va & ~(u64)(GSP_PHYS_PAGE_SIZE - 1); - u32 in[40], out[40]; + u32 in[64], out[64]; u32 nfin = 0, nrun = 0, on = 0, odrop = 0, orel; u32 bi; /* + * SESSION 153-CONTINUED-89 (2nd half): the client's + * full channel-init pipeline block, harvested from the + * guest-RAM init-push image (guest PA 0x81efc5b4, this + * boot) and identical in the X channel's own captured + * window (methods 0x21c, 0x155c, 0x1574 in that exact + * order). The per-frame window carries none of it - + * on real hardware the client wrote it ONCE at + * channel init, and the replay channel's fresh context + * never receives it, so the DS validates the fetched + * SPHs against unset context state (9/11). Emitted + * verbatim in the client's own order, ahead of the + * stage binds: + * 0x21c <- 0x1001 INVALIDATE_SHADER_CACHES + * (INSTRUCTION|CONSTANT) + * 0x155c <- 1, 0x214fa200, 0 + * TEX_SAMPLER_POOL A/B/C + * 0x1574 <- 1, 0x214fa220, 0x10 + * TEX_HEADER_POOL A/B/C + * 0x310 <- 0x705 SET_SPA_VERSION + * 0x22c <- 0x800 SET_GO_IDLE_TIMEOUT + * 0x1128 <- ffffffff, ffffffff + * DA_OUTPUT_ATTRIBUTE_SKIP_MASK + * ZCULL_BOUNDS(0x196c) is already carried by the + * window itself. All constant runs (no relocation). + */ + in[nfin++] = 0x20000000u | (1u << 16) | + (0x21cu >> 2); + in[nfin++] = 0x1001u; + { + /* + * The pool runs are address-bearing (the patch + * pass's own rules: addr 0x155c/0x1574, cnt >= + * 3) and count toward the relocated-pair + * guard, so emit them only when their page is + * in this launch's page set (r1290: emitted + * unconditionally -> unaccounted pairs -> + * `SPH-BIND skipped (reloc=6/4)` and the whole + * prelude was lost). Both VAs share one page. + */ + bool pool_pg = false; + u32 pk; + + for (pk = 0; pk < req->n_pages; pk++) + if ((req->pages[pk].guest_va & + ~(u64)(GSP_PHYS_PAGE_SIZE - 1)) == + (0x214fa200u & + ~(u64)(GSP_PHYS_PAGE_SIZE - 1))) + pool_pg = true; + if (pool_pg) { + in[nfin++] = 0x20000000u | (3u << 16) | + (0x155cu >> 2); + in[nfin++] = 0x1u; + in[nfin++] = 0x214fa200u; + in[nfin++] = 0x0u; + in[nfin++] = 0x20000000u | (3u << 16) | + (0x1574u >> 2); + in[nfin++] = 0x1u; + in[nfin++] = 0x214fa220u; + in[nfin++] = 0x10u; + nrun += 2; + } + } + in[nfin++] = 0x20000000u | (1u << 16) | + (0x310u >> 2); + in[nfin++] = 0x705u; + in[nfin++] = 0x20000000u | (1u << 16) | + (0x22cu >> 2); + in[nfin++] = 0x800u; + in[nfin++] = 0x20000000u | (2u << 16) | + (0x1128u >> 2); + in[nfin++] = 0xffffffffu; + in[nfin++] = 0xffffffffu; + + /* + * SESSION 153-CONTINUED-89: the client's init-push + * pipeline state for the window's own stage 1. The + * guest-RAM init-push image (live at guest PA + * 0x81efc5b4, this boot) carries, beside the SPH + * version pair: + * 0x2040 <- 0x11 SET_PIPELINE_SHADER(1) + * ENABLE|TYPE=VERTEX + * 0x2054 <- 1, 0x21201b00 program address pair + * 0x204c <- 0x1a, 0x0 REGISTER_COUNT(1)=26, + * BINDING(1)=0 + * The per-frame window carries only the address pair, + * so the replay channel's TYPE/COUNT/BINDING stage + * registers stay unset - the state the DS validates + * the fetched SPH against (9/11). Emit the TYPE run + * before the binds and the COUNT/BINDING pair after + * them, in the client's own order. Both are constant + * runs (no relocation). + */ + in[nfin++] = 0x20000000u | (1u << 16) | + (0x2040u >> 2); + in[nfin++] = 0x11u; + + /* * SESSION 153-CONTINUED-87 (second half): the window's * OWN binds first. The captured per-frame window * carries draws (BEGIN at word 93) BEFORE its program @@ -24469,7 +24619,7 @@ gr_page_unmapped: u64 va = req->prog_bind_va[bi]; u32 sl = req->prog_bind_slot[bi] & 0x1fu; - if (!va || nfin + 3u > 40u) + if (!va || nfin + 3u > 64u) continue; in[nfin++] = 0x20000000u | (2u << 16) | ((0x2014u + sl * 0x40u) >> 2); @@ -24485,7 +24635,7 @@ gr_page_unmapped: * from guest RAM (`20020825 [0,04400200]`, * `20020855 [0,04400000]`). */ - if (nfin + 10u <= 40u) { + if (nfin + 13u <= 64u) { in[nfin++] = 0x20000000u | (2u << 16) | (0x2094u >> 2); in[nfin++] = (u32)((fam + 0x200u) >> 32) & 0xffu; @@ -24515,6 +24665,19 @@ gr_page_unmapped: (0x2140u >> 2); in[nfin++] = 1u | (5u << 4); /* + * SESSION 153-CONTINUED-89: the client's + * init-push stage-1 REGISTER_COUNT/BINDING + * pair (`20020813 0000001a 00000000` in the + * guest-RAM init image): REGISTER_COUNT(1) = + * 26 (the window SPH's reg count), BINDING(1) + * = group 0. Emitted after the address pair, + * exactly as the client's own push orders it. + */ + in[nfin++] = 0x20000000u | (2u << 16) | + (0x204cu >> 2); + in[nfin++] = 0x1au; + in[nfin++] = 0x0u; + /* * nrun counts only the two ADDRESS-bearing * binds above: the guard below matches it * against the relocation pass's @@ -24532,10 +24695,11 @@ gr_page_unmapped: win3d_n += nfin; if (sph_bind_log < 16u) { sph_bind_log++; - pr_info("vgsp-gr: SPH-BIND emitted fam=0x%llx win-binds=%u j2=0x%llx j5=0x%llx win=%u h=0x%x push=0x%llx\n", + pr_info("vgsp-gr: SPH-BIND emitted fam=0x%llx win-binds=%u j2=0x%llx j5=0x%llx j1-type=0x11 rc=0x1a initblk=17 win=%u (pre=%u) h=0x%x push=0x%llx\n", fam, req->n_prog_binds, fam + 0x200u, fam, - win3d_n, req->h_object, + win3d_n, nfin, + req->h_object, req->push_va); } } else if (sph_bind_log < 16u) { |
