diff options
| author | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-11-14 07:31:03 -0500 |
|---|---|---|
| committer | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-11-14 07:31:03 -0500 |
| commit | 17c7ed7cb1cbf2dad6f544b554808f188468980f (patch) | |
| tree | 285d0c9f67b030d8cf21dc05a111103a15a37ff2 /kernel/gsp_sema_service.c | |
| parent | cde85ce3f48350d160bc35bdd2fc178c392c36a6 (diff) | |
| download | open-iov-17c7ed7cb1cbf2dad6f544b554808f188468980f.tar.gz open-iov-17c7ed7cb1cbf2dad6f544b554808f188468980f.zip | |
vgsp: relocate a CODESRC-SUSPECT GR program page to the engine-mapped window-0 shadow instead of leaving the QMD pointer at an unmapped guest VA (eng33)
The client's MME-expanded draw builds a QMD whose program page (qmd[48])
classifies CODESRC-SUSPECT (empty-page): the engine's GPCCLIENT_GCC I-fetch
then read the guest VA above every engine-PDB window, raised FAULT_PDE and
the FIFO parked for the rest of the boot (the TSG re-arm cannot revive a
parked PBDMA). c361-c368 receipts.
With gsp_phys_gr_codesrc_reloc=1 (default) the builder copies the page into
the window-0 shadow (empty sources only; PTE/module pages are never
republished), overlays the client's own known-good SPH+SASS stage image at
the original QMD program offset (gsp_sema_gl_prog_img, stage-typed from the
section bind; truncated at a 128-bit boundary with a terminal EXIT when the
image is larger than the remaining page), and the existing QMD w48/49 +
prefetch rewrite publishes the shadow VA. If the shadow mapping cannot be
installed the page stays unmapped and the existing refusal drops the launch,
so an unmapped QMD program pointer is never published. 0 restores the old
guest-VA behaviour for a one-flip A/B.
Validation (c373, params-r1624): 31 CODESRC-RELOC events (img_len=384,
off=0xb00, 0 truncations), 51 GR LAUNCH submitted, 11 MME-FAST end
events=3, 79 FETCH-WIT with GP_GET advancing engine-fetched, 0 FAULT_PDE,
0 vgsp-fault, 0 WEDGE-REARM/PARK-RECOVER; work_gr backend_ok=35 fault=0.
The draws still write nothing (NOWRITE, no clear run in the emitted
window), so px0 stays 0 - the store wall is unchanged and is the next
target.
Diffstat (limited to 'kernel/gsp_sema_service.c')
| -rw-r--r-- | kernel/gsp_sema_service.c | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c index 5071314..e7a0172 100644 --- a/kernel/gsp_sema_service.c +++ b/kernel/gsp_sema_service.c @@ -10447,6 +10447,51 @@ int gsp_sema_gl_sph_blob_version(void) } /* + * r1625: the engine-visible known-good program image for a refused + * program page (CODESRC-SUSPECT relocation in the GR launch builder). + * A program page the engine is about to I-fetch must contain an SPH+SASS + * image, not raw filler: the client's per-window program upload never + * ran on this lane, so the page reads empty while the client's own + * SPH+SASS image is already published (`svc_gl_vs`/`svc_gl_ps`, the + * captured upload or the built-in known-good image). Return the image + * for the pipeline stage the section bound at this VA (the sticky + * SET_PIPELINE_SHADER TYPE: 5 = PIXEL, otherwise VTG), falling back to + * the PIXEL image - the observed empty-program class is the pixel stage + * (its 0x2154 upload was never captured). NULL when no image is loaded. + */ +const u8 *gsp_sema_gl_prog_img(u64 va, u32 *len_out) +{ + u64 page = va & ~(u64)(SEMA_PAGE_SIZE - 1); + u32 i, slot = 0, t = 0xff; + + if (len_out) + *len_out = 0; + for (i = 0; i < svc_gl.n_progs && i < SVC_GL_PROG_MAX; i++) { + if ((svc_gl.progs[i] & ~(u64)(SEMA_PAGE_SIZE - 1)) != page) + continue; + slot = svc_gl.prog_slot[i] < 32 ? svc_gl.prog_slot[i] : 0; + t = svc_gl_shader_type[slot]; + break; + } + if (t != 5 && t != 0xff && svc_gl_vs_len) { + if (len_out) + *len_out = svc_gl_vs_len; + return svc_gl_vs; + } + if (svc_gl_ps_len) { + if (len_out) + *len_out = svc_gl_ps_len; + return svc_gl_ps; + } + if (svc_gl_vs_len) { + if (len_out) + *len_out = svc_gl_vs_len; + return svc_gl_vs; + } + return NULL; +} + +/* * SESSION 153 (GL client draw sections): the GL client's own per-frame * pushes bind TURING_A (0xC597) exactly like the X server's one-shot * section, but carry no program/param/release operands at all (measured: |
