diff options
| author | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-11-05 09:57:00 -0500 |
|---|---|---|
| committer | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-11-05 09:57:00 -0500 |
| commit | f9cecd5faafd9cd59cd1da764fbc6df32b154d97 (patch) | |
| tree | 0bb9130c574d4db341e4067ed6467ddd172c9838 /kernel/gsp_sema_service.c | |
| parent | 4e65e2e28ee595e9210992752201a0c9c0143ba3 (diff) | |
| download | open-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_sema_service.c')
| -rw-r--r-- | kernel/gsp_sema_service.c | 82 |
1 files changed, 72 insertions, 10 deletions
diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c index bfed3b7..18d5e78 100644 --- a/kernel/gsp_sema_service.c +++ b/kernel/gsp_sema_service.c @@ -4449,19 +4449,25 @@ static bool svc_resolve_in_progress(u64 va) */ static u32 svc_cur_vas; -static int svc_chanvas_lookup(struct nv_vgpu_device *vgpu, u64 va, u64 *addr, - int *ap) +/* + * r1483: walk the page tables of one specific published VAS handle. The + * render-target seed uses this with the VAS recorded by + * svc_surf_prelude_capture - a VA-keyed pin from another client's VAS must + * never answer for a surface the captured bind does not belong to. + */ +static int svc_vas_lookup_h(struct nv_vgpu_device *vgpu, u32 h_vaspace, + u64 va, u64 *addr, int *ap) { int i; - if (!svc_cur_vas) + if (!h_vaspace) return -ENOENT; for (i = 0; i < SVC_MAX_VASPACES; i++) { u64 pa = 0; int a = SVC_APERTURE_SYS; if (!svc.vas[i].valid || - svc.vas[i].h_vaspace != svc_cur_vas) + svc.vas[i].h_vaspace != h_vaspace) continue; if (svc_gmmu_walk(vgpu, svc.vas[i].pdb, svc.vas[i].entries, va & ~(u64)(SEMA_PAGE_SIZE - 1), @@ -4474,6 +4480,12 @@ static int svc_chanvas_lookup(struct nv_vgpu_device *vgpu, u64 va, u64 *addr, return -ENOENT; } +static int svc_chanvas_lookup(struct nv_vgpu_device *vgpu, u64 va, u64 *addr, + int *ap) +{ + return svc_vas_lookup_h(vgpu, READ_ONCE(svc_cur_vas), va, addr, ap); +} + /* * SESSION 153-CONTINUED-67: which sub-source of svc_lookup_trusted answered * the last call (1=channel VAS 2=pin 3=learned 4=discovered map 5=VAS walk @@ -15894,9 +15906,28 @@ static u32 svc_surf_pre_flag = 1; */ static u64 svc_surf_pre_va; static u32 svc_surf_pre_npages; +/* + * SESSION 154 r1483: the VAS the captured colour-target bind came from. + * The pin/learned/map tables are keyed by VA ALONE, and every client's RM + * window sits at the same VAs (0x1200xxxxx): at r1482 the beef client held + * an injected pin for VA 0x120400000 (its own SYS allocation, guest PA + * 0x120400000) while the X server's screen surface of the SAME VA is a + * 900-page FB allocation. The fill seeded the captured surface VA and the + * global pin answered first, so the render-target recs became 10 pages of + * the beef client's buffer (the SASS-like content in the A-TRACE dump) + * instead of the screen the bind actually names. Resolve the captured + * surface through the page tables of the VAS that emitted the bind (the + * same channel-scoped rule as svc_chanvas_lookup, r835). Default 1; + * sema_gl_surf_vas=0 restores the legacy pin-first order for A/B. + */ +static u32 svc_surf_pre_hvas; +static u32 svc_surf_vas_first = 1; module_param_named(sema_surf_prelude_cap, svc_surf_pre_flag, uint, 0644); MODULE_PARM_DESC(sema_surf_prelude_cap, "Capture the last C597 colour-target bind (INC 0x800+j*0x40, fmt 0xe6) from trusted pushes so the GR launch builder can replay it ahead of 3D windows that carry no render target (default 1)"); +module_param_named(sema_gl_surf_vas, svc_surf_vas_first, uint, 0644); +MODULE_PARM_DESC(sema_gl_surf_vas, + "Resolve the captured colour-target (render-target) pages through the page tables of the VAS that emitted the bind, before the global VA-keyed pin chain (default 1; 0 = legacy pin-first A/B)"); const u32 *gsp_sema_surf_prelude_get(u32 *n, u32 *gen) { @@ -15920,7 +15951,7 @@ bool gsp_sema_surf_va_get(u64 *va, u32 *npages) return true; } -static void svc_surf_prelude_capture(const u8 *buf, u32 len) +static void svc_surf_prelude_capture(const u8 *buf, u32 len, u32 h_vaspace) { u32 off = 0; @@ -15971,12 +16002,16 @@ static void svc_surf_prelude_capture(const u8 *buf, u32 len) svc_surf_pre_sig = sig; svc_surf_pre_va = va; WRITE_ONCE(svc_surf_pre_npages, (u32)npages); + /* r1483: remember which client VAS this bind belongs to (see + * svc_surf_pre_hvas): its page tables are the only authority + * for the surface's pages. */ + WRITE_ONCE(svc_surf_pre_hvas, h_vaspace); WRITE_ONCE(svc_surf_pre_gen, svc_surf_pre_gen + 1); if (svc_surf_pre_log < 8) { svc_surf_pre_log++; - pr_info("sema-surf-pre: captured gen=%u words=%u va=0x%llx %ux%u fmt=0x%x hdr=%08x\n", + pr_info("sema-surf-pre: captured gen=%u words=%u va=0x%llx %ux%u fmt=0x%x hdr=%08x vas=0x%x\n", svc_surf_pre_gen, n, va, v[2], v[3], v[4], - hdr); + hdr, h_vaspace); } off += span * 4u; } @@ -16744,7 +16779,7 @@ static void svc_decode_stream(struct nv_vgpu_device *vgpu, const u8 *buf, * channel. See svc_surf_prelude_capture. */ if (ch && trusted) - svc_surf_prelude_capture(buf, len); + svc_surf_prelude_capture(buf, len, ch->h_vaspace); memset(&st, 0, sizeof(st)); st.push_va = push_va; @@ -32841,6 +32876,16 @@ static void svc_gr_data_fill(struct nv_vgpu_device *vgpu, span = surf_cand_span; surf_cand_used = true; } + /* + * r1483: the captured surface's OWN VAS answers its pages + * first (see svc_surf_pre_hvas). The global pin/ledger layers + * are VA-keyed and another client's allocation sits at the + * same 0x1200xxxxx VA, which is how the render-target recs + * became 10 pages of the client's code/operand buffer. + */ + u32 surf_vas_h = (surf_cand_va && base == surf_cand_va && + READ_ONCE(svc_surf_vas_first)) ? + READ_ONCE(svc_surf_pre_hvas) : 0; if (is_arg[w] && base >= 0x40000000000ULL) n_arg_hi++; @@ -32862,6 +32907,7 @@ static void svc_gr_data_fill(struct nv_vgpu_device *vgpu, u32 ap = 0, x; struct svc_gr_data *rec; bool shadow_serve = false; + bool surf_vas_answered = false; /* r1483 */ int serve = SVC_GR_SHADOW_NONE; bool real_content = false; /* r635 */ @@ -32884,8 +32930,24 @@ static void svc_gr_data_fill(struct nv_vgpu_device *vgpu, { u64 ipa = 0; int iap = SVC_APERTURE_SYS; + u64 vpa = 0; + int vap = SVC_APERTURE_SYS; - if (!svc_ipin_lookup(va, &ipa, &iap)) { + if (surf_vas_h && + !svc_vas_lookup_h(vgpu, surf_vas_h, va, + &vpa, &vap)) { + static u32 surf_vas_log; + + pa = vpa; + ap = (u32)vap; + cand_anchored = true; + surf_vas_answered = true; + if (surf_vas_log < 8u) { + surf_vas_log++; + pr_info("sema-gr: surf-vas h=0x%x va=0x%llx -> pa=0x%llx ap=%u (captured-surface VAS wins over the VA-keyed pin chain)\n", + surf_vas_h, va, pa, ap); + } + } else if (!svc_ipin_lookup(va, &ipa, &iap)) { pa = ipa; ap = (u32)iap; cand_anchored = true; @@ -33062,7 +33124,7 @@ static void svc_gr_data_fill(struct nv_vgpu_device *vgpu, * aperture-aware (a SYS page and an FB page with the * same numeric address are not the same page). */ - if (va >= SVC_VAS_FLOOR) { + if (va >= SVC_VAS_FLOOR && !surf_vas_answered) { u64 lpa = 0; u32 lap = 0; u64 ipa = 0; |
