diff options
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; |
