From a7263b28de7e4c35cccda910a806e4c4db15786b Mon Sep 17 00:00:00 2001 From: Arthur Hanson Rasmusson Date: Mon, 12 Oct 2026 01:38:02 -0400 Subject: vgsp-sema: discover GR data candidates from the fresh inline param block (second-client fix) Second-client launches scanned a stale/reused guest param page that still held the FIRST client's device VAs: zero new candidates resolved, nothing was relocated, and the engine executed with unrelocated guest pointers (r97 evidence: client#1 '15 candidate ptrs, 100 pages resolved' and win0 param 160=110400; client#2 '12 candidates, 1 page' with 160=75552ec00000 unrelocated). The driver-authored inline param block is captured from the pushbuffer at request time, so scanning it makes pointer discovery independent of guest-page reuse timing. Adds svc_gr_scan_cand()/ svc_gr_scan_inline() and the DIAG win0/guest-param proof line. Client #1 stays green (4 cycles); the remaining second-client stall is the pool semaphore residue (see next commit). --- kernel/gsp_sema_service.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) (limited to 'kernel/gsp_sema_service.c') diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c index ec269c5..7d690ab 100644 --- a/kernel/gsp_sema_service.c +++ b/kernel/gsp_sema_service.c @@ -12129,6 +12129,56 @@ static bool svc_gr_page_inline_covers(u64 page) static u32 svc_gr_data_log; /* m142: bounded per-page attribution log */ +/* + * m144 (second-client launch-state divergence): collect device-VA-shaped + * candidate pointers from the bytes the ENGINE will actually execute. + * + * The guest page read through the operand HPA can be STALE across a session + * boundary: the guest reuses the previous client's physical page for the new + * client's parameter/bank page, and at scan time that page can still hold the + * previous client's device VAs (observed r97: the second client's data fill + * read the first client's VAs, resolved zero pages, relocated nothing, and + * the engine then executed the kernel against the ORIGINAL unrelocated + * pointers - the win0 param page kept 0x75552ec00000 instead of 0x110000). + * The driver ALSO writes the kernel parameter block inline; those bytes are + * captured fresh from the launch pushbuffer at request time and are overlaid + * onto the shadow page by the backend. Scan them too (the scan is by value, + * so the in-page offset of an inline record does not matter) so pointer + * discovery is independent of guest-page reuse timing. + */ +static void svc_gr_scan_cand(u64 *wins, u32 *n_cand, const u8 *data, u32 bytes) +{ + u32 k; + + for (k = 0; k + 8 <= bytes; k += 8) { + u64 v = get_unaligned_le64(data + k); + u64 wv; + u32 w; + + if (v < 0x10000000ULL || v >= (1ULL << 47) || (v & 3)) + continue; + wv = v & ~(u64)(SEMA_PAGE_SIZE - 1); + for (w = 0; w < *n_cand; w++) + if (wins[w] == wv) + break; + if (w == *n_cand && *n_cand < 16u) + wins[(*n_cand)++] = wv; + } +} + +static void svc_gr_scan_inline(u64 *wins, u32 *n_cand, u64 page_va) +{ + u32 j; + + for (j = 0; j < svc_gr_cand.n_inline && j < SVC_GR_INLINE_MAX; j++) { + const struct svc_gr_inline *inl = &svc_gr_cand.inline_recs[j]; + + if ((inl->dst_va & ~(u64)(SEMA_PAGE_SIZE - 1)) != page_va) + continue; + svc_gr_scan_cand(wins, n_cand, inl->data, inl->len); + } +} + static void svc_gr_data_fill(struct nv_vgpu_device *vgpu) { u64 wins[16]; @@ -12185,6 +12235,10 @@ static void svc_gr_data_fill(struct nv_vgpu_device *vgpu) if (w == n_cand && n_cand < ARRAY_SIZE(wins)) wins[n_cand++] = wv; } + /* m144: also scan the fresh inline-captured parameter block, + * so a reused/stale guest page cannot hide the kernel's device + * pointers. */ + svc_gr_scan_inline(wins, &n_cand, pp->va); } for (i = 0; i < svc_fwd_req.gr_n_pages; i++) { const struct svc_gr_page *pp = &svc_fwd_req.gr_pages[i]; @@ -12217,6 +12271,9 @@ static void svc_gr_data_fill(struct nv_vgpu_device *vgpu) if (w == n_cand && n_cand < ARRAY_SIZE(wins)) wins[n_cand++] = wv; } + /* m144: bank pages carry their own pointers too; scan the fresh + * inline-captured bytes as well (see svc_gr_scan_inline). */ + svc_gr_scan_inline(wins, &n_cand, pp->va); } /* m110: one contiguous run of pages per candidate pointer, relocated * into the engine-walkable main-PT window (0x110000 onward, fresh -- cgit v1.2.3