summaryrefslogtreecommitdiffstats
path: root/kernel/gsp_sema_service.c
diff options
context:
space:
mode:
authorArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-12 01:38:02 -0400
committerArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-12 01:46:11 -0400
commita7263b28de7e4c35cccda910a806e4c4db15786b (patch)
tree90920d290618890b9179039b56fad77caf369b02 /kernel/gsp_sema_service.c
parent864b0ab4b74811282546bf9143a6379aac628839 (diff)
downloadopen-iov-a7263b28de7e4c35cccda910a806e4c4db15786b.tar.gz
open-iov-a7263b28de7e4c35cccda910a806e4c4db15786b.zip
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).
Diffstat (limited to 'kernel/gsp_sema_service.c')
-rw-r--r--kernel/gsp_sema_service.c57
1 files changed, 57 insertions, 0 deletions
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