summaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorArthur Hanson Rasmusson <arthur@vgpu.io>2026-11-01 09:22:08 -0500
committerArthur Hanson Rasmusson <arthur@vgpu.io>2026-11-01 09:22:08 -0500
commit1fdc48e5f19ce8832e0e0355ccd68a82a4bd8511 (patch)
tree41acde5eaa855e04d1fc11bda2e207a1f30a3bc2 /kernel
parent54a1711284abe23582eb0cd16dc9e53069c408e6 (diff)
downloadopen-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.c176
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) {