From 579e29b6e5924873489e88afa7796a2bda3e95a2 Mon Sep 17 00:00:00 2001 From: Arthur Hanson Rasmusson Date: Fri, 13 Nov 2026 02:52:11 -0500 Subject: vgsp: serve word-34..47 section pages from their resolved PAs; seed the pointer pairs (n_data 0->1024) The final-pixel-wall data window: svc_gr_data_fill discarded a candidate page that HAD resolved in gr_pages (launch_internal blanket skip: c203 evidence 'page[2] va=0x120400000 pa=0xa00000 ap=2 word=34' + '10 candidate ptrs, 0 pages resolved; 7 dropped' -> GR-DEC n_data=0), and the stream3d lane (qmd=0x0) never seeded the capture's decoded operand pairs (inline-QMD words 34..47) as candidates. Serve word-34..47 pages from their resolved gr_pages PA (li_pa, span=1; word 32/48/49 stay excluded as before) and seed the pointer pairs from a request-carried copy (race-free vs the capture ring). Live proof c215: 'li cand va=0x120400000 word=34 pa=0xa00000 ap=2' -> 'GR-DEC n_data=1024' (was 0). Residual: the 1524 B first-frame's pointer pages are not yet resolvable at that instant (n_ptr_req=5 seed_add=0; frames 2+ resolve 1024) - resolver timing, documented. Also documented (no change): the copy-out refusal for dst=0x120700000 (the GL client's fixed-CB page) falls through to the forced-seed path and is benign for pixels; the TRUE px0 blocker is engine-zero-write: every stream3d launch ends 'NOWRITE-CONFIRMED ... n_data=1024 tracked=1024 wrote=0' + 'NOWRITE-REGS fe_esr=0x80000000 trap=0x8000022c/00000800/00000000' even with the full RT window (SURF-PRELUDE target=0xa000000) - the engine executes but stores nothing. --- kernel/gsp_sema_service.c | 112 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 107 insertions(+), 5 deletions(-) (limited to 'kernel/gsp_sema_service.c') diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c index 34e2b49..6ce84f1 100644 --- a/kernel/gsp_sema_service.c +++ b/kernel/gsp_sema_service.c @@ -34942,6 +34942,14 @@ struct svc_fwd_req { u32 gr_n_prog_binds; u64 gr_prog_bind_va[SVC_GR_CAND_PROG_BINDS]; u32 gr_prog_bind_slot[SVC_GR_CAND_PROG_BINDS]; + /* + * ENG10: the capture's decoded operand pointer pairs (inline-QMD words + * 34..47). Carried on the request like gr_prog_bind_va so the fill's + * candidate seed reads the REQUEST's capture, not whatever the + * rotating svc_gr_cand ring holds when the work item runs. + */ + u32 gr_n_pointer; + u64 gr_pointer_va[SVC_GR_POINTER_MAX]; u64 gr_param_va; u32 gr_param_size; u32 gr_qmd[SVC_GR_QMD_WORDS]; @@ -39512,6 +39520,8 @@ static void svc_gr_data_fill(struct nv_vgpu_device *vgpu, static u64 svc_gr_reloc_half_key; static u8 svc_gr_reloc_half; u64 reloc_off = 0; + u32 eng10_seed_added = 0; + static u32 eng10_li_log; if (region_on) { if (svc_gr_cand.push_va != svc_gr_reloc_half_key) { @@ -39883,11 +39893,45 @@ static void svc_gr_data_fill(struct nv_vgpu_device *vgpu, } } } + /* + * ENG10 (r1780 GL): the stream3d sections carry no QMD page (qmd=0), + * so the qmd-ptr seed above has no words to work from and the only + * candidates left were the param-page content scans - junk VAs whose + * pages resolve to nothing (c203/c211: 24 cands, 0 resolved, + * GR-DEC n_data=0 on every first-frame 1524 B launch while the + * launch's own word-34..47 pages sat RESOLVED in gr_pages: + * ptr[0] 0x120400000 -> pa=0xa00000/vidmem). The capture DID decode + * those operand pointer pairs (svc_gr_cand.pointer_va[] = the + * inline-QMD words 34..47); seed them as candidates here - exactly + * what the qmd-ptr seed does when a QMD exists. The span resolution + * then serves each from its gr_pages pa (the li_pa clause below). + * is_arg stays false so the m170 fail-closed hold semantics are + * unchanged (these are operands, not the argument set). + */ + for (i = 0; i < svc_fwd_req.gr_n_pointer; i++) { + u64 pv = svc_fwd_req.gr_pointer_va[i]; + u64 pw; + + if (pv < 0x10000000ULL || pv >= (1ULL << 47) || (pv & 3)) + continue; + pw = pv & ~(u64)(SEMA_PAGE_SIZE - 1); + for (w = 0; w < n_cand; w++) + if (wins[w] == pw) + break; + if (w == n_cand && n_cand < ARRAY_SIZE(wins)) { + wins[n_cand++] = pw; + eng10_seed_added++; + } + } if (gsp_sema_dbg && svc_gr_pages_log < 48) { svc_gr_pages_log++; - pr_info("sema-gr: fill cand n=%u pages=%u push=0x%llx\n", + pr_info("sema-gr: fill cand n=%u pages=%u push=0x%llx n_ptr_req=%u ptr0=0x%llx seed_add=%u\n", n_cand, svc_fwd_req.gr_n_pages, - svc_fwd_req.gr_push_va); + svc_fwd_req.gr_push_va, + svc_fwd_req.gr_n_pointer, + svc_fwd_req.gr_n_pointer ? + svc_fwd_req.gr_pointer_va[0] : 0ull, + eng10_seed_added); for (w = 0; w < n_cand && w < 12; w++) pr_info("sema-gr: win[%u] va=0x%llx arg=%u\n", w, wins[w], is_arg[w]); @@ -39976,6 +40020,9 @@ static void svc_gr_data_fill(struct nv_vgpu_device *vgpu, (base & ~(u64)(SEMA_PAGE_SIZE - 1)) == (svc_fwd_req.gr_param_va & ~(u64)(SEMA_PAGE_SIZE - 1))) continue; + u64 li_pa = 0; + u32 li_ap = 0; + { bool launch_internal = false; @@ -39988,10 +40035,47 @@ static void svc_gr_data_fill(struct nv_vgpu_device *vgpu, (base & ~(u64)(SEMA_PAGE_SIZE - 1)) == (pp->va & ~(u64)(SEMA_PAGE_SIZE - 1))) { launch_internal = true; + /* + * ENG10 (r1780 GL, c203 evidence): the + * capture can ALREADY have resolved a + * pointer-pair page: the 288 B section's + * word-34 operand 0x120400000 sat in + * gr_pages as pa=0xa00000/vidmem while + * this blanket skip kept it out of the + * data window - the whole candidate set + * then resolved 0 pages and GR-DEC + * stayed n_data=0 ("fill: 0 pages + * resolved; 7 dropped"). Serve the + * resolved pointer-pair page (words + * 34..47 are the launch's device + * operands) from gr_pages below. + * Word 32 (param) and 48/49 (program) + * remain excluded: their shadow/Tier-2 + * paths own them and must not be + * re-relocated as data. + */ + if (pp->qmd_word >= 34u && + pp->qmd_word <= 47u && pp->pa) { + li_pa = pp->pa; + li_ap = pp->ap; + if (eng10_li_log < 32) { + eng10_li_log++; + pr_info("sema-gr: li cand va=0x%llx word=%u pa=0x%llx ap=%u\n", + base, + pp->qmd_word, + pp->pa, + pp->ap); + } + } else if (eng10_li_log < 32) { + eng10_li_log++; + pr_info("sema-gr: li cand va=0x%llx word=%u pa=0x%llx (NOT served: word/pa)\n", + base, pp->qmd_word, + pp->pa); + } break; } } - if (launch_internal) + if (launch_internal && !li_pa) continue; } span = (base >= 0x40000000000ULL) ? per_ptr : 1u; @@ -40064,7 +40148,18 @@ static void svc_gr_data_fill(struct nv_vgpu_device *vgpu, u64 vpa = 0; int vap = SVC_APERTURE_SYS; - if (surf_vas_h && + /* + * ENG10: a pointer-pair page the capture already + * resolved (gr_pages pa/ap) is the strongest + * source - the same pages the launch's Tier-2 + * shadow path uses. Served span=1 (low VA rule). + */ + if (li_pa && + va == (base & ~(u64)(SEMA_PAGE_SIZE - 1))) { + pa = li_pa; + ap = li_ap; + cand_anchored = true; + } else if (surf_vas_h && !svc_vas_lookup_h(vgpu, surf_vas_h, va, &vpa, &vap)) { static u32 surf_vas_log; @@ -40661,7 +40756,7 @@ static void svc_gr_inline_retarget(u64 prog_va, const u64 *binds, u32 n_binds) static int svc_gr_req_fill(struct nv_vgpu_device *vgpu, const struct svc_channel *ch) { - u32 i; + u32 i, pb2; svc_fwd_req.done = false; svc_fwd_req.hw_rc = 0; @@ -40701,6 +40796,13 @@ static int svc_gr_req_fill(struct nv_vgpu_device *vgpu, svc_gr_cand.prog_bind_slot[pb]; } } + /* ENG10: snapshot the decoded operand pointer pairs (words 34..47) so + * the fill's seed loop cannot race the rotating capture ring. */ + svc_fwd_req.gr_n_pointer = svc_gr_cand.n_pointer; + if (svc_fwd_req.gr_n_pointer > SVC_GR_POINTER_MAX) + svc_fwd_req.gr_n_pointer = SVC_GR_POINTER_MAX; + for (pb2 = 0; pb2 < svc_fwd_req.gr_n_pointer; pb2++) + svc_fwd_req.gr_pointer_va[pb2] = svc_gr_cand.pointer_va[pb2]; memcpy(svc_fwd_req.gr_raw, svc_gr_cand.raw, sizeof(svc_fwd_req.gr_raw)); svc_fwd_req.gr_qmd_dev_va = svc_gr_cand.qmd_dev_va; -- cgit v1.2.3