summaryrefslogtreecommitdiffstats
path: root/kernel/gsp_phys_booter.c
diff options
context:
space:
mode:
authorArthur Hanson Rasmusson <arthur@vgpu.io>2026-11-05 09:57:00 -0500
committerArthur Hanson Rasmusson <arthur@vgpu.io>2026-11-05 09:57:00 -0500
commitf9cecd5faafd9cd59cd1da764fbc6df32b154d97 (patch)
tree0bb9130c574d4db341e4067ed6467ddd172c9838 /kernel/gsp_phys_booter.c
parent4e65e2e28ee595e9210992752201a0c9c0143ba3 (diff)
downloadopen-iov-f9cecd5faafd9cd59cd1da764fbc6df32b154d97.tar.gz
open-iov-f9cecd5faafd9cd59cd1da764fbc6df32b154d97.zip
vgsp-gr: bind the beef GL draw to the captured 900-page screen surface, not a cross-VAS 10-page operand buffer
The PS SPH has MRT_ENABLE=0 (writes RT0); the beef window binds no colour target of its own, so the last trusted 0x800..0xbff run (the X screen surface 0x120400000, 1280x720, 900 pages) is the render target. Its pages were resolved through the global VA-keyed pin/ledger, which conflated clients: the beef client's own injected pin for VA 0x120400000 (a SYS staging/operand buffer holding SASS/method words) shadowed the X server's surface VAS and cut the set at 10 pages. Capture the surface's source VAS and resolve its pages through that VAS in the fill, bypassing the pin override for this page set. Re-patch the SURF prelude when the launch's rec base differs from the cached one, and copy the emitted SURF run's target/geometry into the RT0 run so RT0 == RT1 every launch (was hardcoded to the 0xa relocation half). r1483: the beef retirement is now 0/900 pages of the visible surface (was 0/10), RT0-BIND target=0xa000000, data[0] va=0x120400000 pa=0x100000, n_data =900, 6 launches, poison=0. The engine still stores nothing: GR-STATE sph is zero at retire and the launch traps at method 0x1528, so the next wall is making the pipeline program bind visible to the DS, not the RT VA.
Diffstat (limited to 'kernel/gsp_phys_booter.c')
-rw-r--r--kernel/gsp_phys_booter.c111
1 files changed, 99 insertions, 12 deletions
diff --git a/kernel/gsp_phys_booter.c b/kernel/gsp_phys_booter.c
index 33e1b35..1cfa11f 100644
--- a/kernel/gsp_phys_booter.c
+++ b/kernel/gsp_phys_booter.c
@@ -27041,6 +27041,16 @@ int gsp_phys_backend_guest_gr_submit(const struct gsp_phys_gr_submit *req,
gsp_phys_gr_wit_reset();
const u32 *win3d = NULL;
u32 win3d_n = 0;
+ /*
+ * r1483: the SURF prelude emitted for THIS launch. The RT0 bind
+ * (sema_gl_rt0_bind) used to carry a constant 0xa000000 target;
+ * that is only correct when this launch's data-rec base is the 0xa
+ * half. The PS writes RT0 while the client binds RT1, so RT0 must
+ * name the same surface as the SURF prelude or half the launches
+ * store into the other half's (untracked) bounce window. When set,
+ * the RT0 run copies the emitted SURF run's target words.
+ */
+ bool surf_pre_emitted = false;
bool qmd_rel_redirected = false; /* r420b: release0 -> module sem */
u64 qmd_rel_hpa = 0, ch_rel_hpa = 0;
u64 ch_sem_va = GSP_PHYS_RMCALL_VA_SEM + 4;
@@ -28752,7 +28762,50 @@ gr_page_unmapped:
sp = gsp_sema_surf_prelude_get(&spn, &spg);
if (sp && spn && spg) {
- if (spg != READ_ONCE(gsp_phys_gr_surf_pre_gen)) {
+ bool repatch =
+ spg != READ_ONCE(gsp_phys_gr_surf_pre_gen);
+ u64 want = 0;
+
+ /*
+ * r1483: the rec-over-alias preference below
+ * rewrites the pair to THIS launch's data-rec
+ * bounce VA, and the fill alternates its
+ * relocation half per capture push. A buffer
+ * patched once per capture generation would
+ * keep the first launch's half forever, so
+ * re-patch when the launch's complete surface
+ * rec names a different target.
+ */
+ if (!repatch && gsp_phys_gr_surf_pre_n >= 3) {
+ u64 sva = 0;
+ u32 sn = 0, di;
+
+ if (!gsp_sema_gr_surf_recs(&sva, &sn) &&
+ sva) {
+ for (di = 0; di < req->n_data;
+ di++) {
+ if (req->data[di].va ==
+ sva &&
+ req->data[di]
+ .reloc_va) {
+ want = req->data[di]
+ .reloc_va;
+ break;
+ }
+ }
+ }
+ if (want) {
+ u64 have =
+ ((u64)(gsp_phys_gr_surf_pre[1] &
+ 0xffu) << 32) |
+ (u64)(gsp_phys_gr_surf_pre[2] &
+ 0xfffffffcu);
+
+ if (have != want)
+ repatch = true;
+ }
+ }
+ if (repatch) {
u32 sdrop = 0, sn = spn;
u32 srel;
@@ -28771,12 +28824,21 @@ gr_page_unmapped:
bar0, epoch);
WRITE_ONCE(gsp_phys_gr_surf_pre_gen,
spg);
- pr_info("vgsp-gr: SURF-PRELUDE patched gen=%u raw=%u kept=%u dropped=%u reloc=%u h=0x%x push=0x%llx\n",
- spg, sn,
- gsp_phys_gr_surf_pre_n,
- sdrop, srel,
- req->h_object,
- req->push_va);
+ {
+ static u32 surf_patch_log;
+
+ if (surf_patch_log < 16u) {
+ surf_patch_log++;
+ pr_info("vgsp-gr: SURF-PRELUDE patched gen=%u raw=%u kept=%u dropped=%u reloc=%u target=0x%llx h=0x%x push=0x%llx\n",
+ spg, sn,
+ gsp_phys_gr_surf_pre_n,
+ sdrop, srel,
+ ((u64)(gsp_phys_gr_surf_pre[1] & 0xffu) << 32) |
+ (u64)(gsp_phys_gr_surf_pre[2] & 0xfffffffcu),
+ req->h_object,
+ req->push_va);
+ }
+ }
}
if (gsp_phys_gr_surf_pre_n &&
win3d_n + gsp_phys_gr_surf_pre_n + 2u +
@@ -28792,6 +28854,7 @@ gr_page_unmapped:
(size_t)gsp_phys_gr_surf_pre_n *
4u);
win3d_n += gsp_phys_gr_surf_pre_n;
+ surf_pre_emitted = true;
if (surf_emit_log < 16) {
surf_emit_log++;
pr_info("vgsp-gr: SURF-PRELUDE emitted words=%u window=%u h=0x%x push=0x%llx\n",
@@ -28919,19 +28982,43 @@ gr_page_unmapped:
2u + 8u <=
GSP_PHYS_RMCALL_GR_METHOD_WORDS) {
u32 rt0_old = win3d_n;
+ u32 rt0_words[GSP_PHYS_GR_RT0_BIND_WORDS];
+ memcpy(rt0_words, gsp_phys_gr_rt0_bind,
+ sizeof(rt0_words));
+ /*
+ * r1483: RT0 and RT1 must name the SAME
+ * surface. The SURF prelude just emitted
+ * ahead of this run already carries the
+ * launch's real target after relocation
+ * (the data-rec bounce base when the
+ * surface rec set is complete, the
+ * contiguous alias otherwise); copy its
+ * geometry words so the PS's RT0 stores
+ * land in the tracked target on BOTH
+ * relocation halves. Without the SURF
+ * prelude (the window binds its own
+ * target) keep the historical constant.
+ */
+ if (surf_pre_emitted &&
+ gsp_phys_gr_surf_pre_n >= 7u)
+ memcpy(&rt0_words[1],
+ &gsp_phys_gr_surf_pre[1],
+ 6u * sizeof(u32));
memmove(&stream_patch[rt0_at +
GSP_PHYS_GR_RT0_BIND_WORDS],
&stream_patch[rt0_at],
(size_t)(win3d_n - rt0_at) * 4u);
- memcpy(&stream_patch[rt0_at],
- gsp_phys_gr_rt0_bind,
- sizeof(gsp_phys_gr_rt0_bind));
+ memcpy(&stream_patch[rt0_at], rt0_words,
+ sizeof(rt0_words));
win3d_n += GSP_PHYS_GR_RT0_BIND_WORDS;
if (rt0_emit_log < 16u) {
rt0_emit_log++;
- pr_info("vgsp-gr: RT0-BIND emitted window=%u->%u at=%u\n",
- rt0_old, win3d_n, rt0_at);
+ pr_info("vgsp-gr: RT0-BIND emitted window=%u->%u at=%u target=0x%llx surf=%u\n",
+ rt0_old, win3d_n, rt0_at,
+ ((u64)(rt0_words[1] & 0xffu) << 32) |
+ (u64)(rt0_words[2] & 0xfffffffcu),
+ surf_pre_emitted ? 1u : 0u);
}
} else {
if (rt0_skip_log < 8u) {