summaryrefslogtreecommitdiffstats
path: root/kernel/gsp_sema_service.c
diff options
context:
space:
mode:
authorArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-20 05:34:52 -0400
committerArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-20 05:34:52 -0400
commit720d3f5fa8b8bdbb947826927ae907cfc7d0ed56 (patch)
tree99d3fa39c156291089e496a5a58d1ad0aa20298e /kernel/gsp_sema_service.c
parentae534205925529fc06e0539218f0ddf9fe5f835a (diff)
downloadopen-iov-720d3f5fa8b8bdbb947826927ae907cfc7d0ed56.tar.gz
open-iov-720d3f5fa8b8bdbb947826927ae907cfc7d0ed56.zip
vgsp: pin-backed translation wins the write-side ledger divergence (r336)
The m180 unification redirected a divergent write to the ledger's page (where an earlier write landed) even when the current translation was pin-backed (guest pagemap truth, op_tr_src == 1). When the guest remaps/reuses a VA (free + reallocate, or migration), the ledger page is freed and can be reallocated by the guest kernel: the redirected write then smears client copy data over kernel memory. Observed on the r335 vector_add run: an RM map/AVL node's pointer field held client c-data (floats 551.25/552.0), the free-path traversal faulted (mapFindLEQ_IMPL/_mapInsertBase), and the guest panicked (Attempted to kill init). 4448 write-side divergences in that run. Now a pin-backed translation wins: the write goes to the fresh page and the ledger store after the write re-homes the entry, so readers converge on the same page. Non-pin translations (2..5) keep the m180 redirect - they can carry stale PTEs (m169) and the write history stays the authority there. New counter sema-svc ledger pinwins.
Diffstat (limited to 'kernel/gsp_sema_service.c')
-rw-r--r--kernel/gsp_sema_service.c67
1 files changed, 51 insertions, 16 deletions
diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c
index fb096f1..871e1af 100644
--- a/kernel/gsp_sema_service.c
+++ b/kernel/gsp_sema_service.c
@@ -3962,6 +3962,7 @@ static void svc_session_flush(void); /* defined next to the pending queue */
#define SVC_LEDGER_EVICT_RESET 256u
static u32 svc_ledger_n;
static u64 svc_ledger_diverges;
+static u64 svc_ledger_pinwins; /* r336: pin-backed divergence wins */
static u32 svc_d2hmap_log; /* D2H-MAP per-page destination budget */
static u64 svc_ledger_stores;
static u64 svc_ledger_evictions;
@@ -4111,10 +4112,10 @@ static void svc_rebuild(struct nv_vgpu_device *vgpu)
* content" window. n approaching SVC_LEDGER_MAX or evict > 0 in a
* client's window is the tell.
*/
- pr_info("sema-svc: ledger n=%u/%u stores=%llu evict=%llu resets=%llu diverges=%llu reloc_div=%llu rewrites=%llu\n",
+ pr_info("sema-svc: ledger n=%u/%u stores=%llu evict=%llu resets=%llu diverges=%llu pinwins=%llu reloc_div=%llu rewrites=%llu\n",
svc_ledger_n, SVC_LEDGER_MAX, svc_ledger_stores,
svc_ledger_evictions, svc_ledger_evict_resets,
- svc_ledger_diverges,
+ svc_ledger_diverges, svc_ledger_pinwins,
svc_ledger_reloc_diverges, svc_ledger_rewrites);
/*
* P6b wave 1: guest-forwarding summary. Printed whenever any counter
@@ -5901,21 +5902,55 @@ static int svc_copy(struct nv_vgpu_device *vgpu, u64 dst, u64 src, size_t total,
(pa & ~(u64)(SEMA_PAGE_SIZE - 1)) ||
(lap == SVC_APERTURE_FB) !=
(aper == CE_APERTURE_VID))) {
- /*
- * m180 unification: keep ONE authoritative
- * page per VA. A new write goes to the page
- * the previous content landed on, and the
- * fill/D2H readers (which prefer the table)
- * stay consistent with it.
- */
svc_ledger_diverges++;
- if (svc_ledger_diverges <= 512)
- pr_info("sema-ledger: DIVERGE write va=0x%llx prev=0x%llx cur=0x%llx\n",
- dst_orig + o, lpa, pa);
- pa = lpa;
- aper = (lap == SVC_APERTURE_FB) ?
- CE_APERTURE_VID : CE_APERTURE_SYS;
- wprov = 0xF0;
+ if (svc.op_tr_src == 1) {
+ /*
+ * r336 PIN-WINS (the r335 vector_add
+ * guest-panic class): a pin-backed
+ * translation (guest pagemap truth,
+ * op_tr_src == 1) that disagrees
+ * with the ledger means the guest
+ * remapped or reused this VA. The
+ * ledger page is where an earlier
+ * write landed; the guest has since
+ * freed or moved it, so writing it
+ * can land on memory the guest
+ * kernel now owns (observed: RM
+ * object fields overwritten with
+ * client c-data, slab freelist
+ * corruption, guest panic). Trust
+ * the pin for the write and re-home
+ * the ledger (the store after the
+ * write records the fresh page);
+ * readers then converge on the same
+ * page too.
+ */
+ svc_ledger_pinwins++;
+ if (svc_ledger_diverges <= 512)
+ pr_info("sema-ledger: DIVERGE write va=0x%llx prev=0x%llx cur=0x%llx (pin wins)\n",
+ dst_orig + o, lpa, pa);
+ wprov = svc.op_tr_src;
+ } else {
+ /*
+ * m180 unification: keep ONE
+ * authoritative page per VA. A new
+ * write goes to the page the
+ * previous content landed on, and
+ * the fill/D2H readers (which
+ * prefer the table) stay consistent
+ * with it. Non-pin translations
+ * (2..5) can carry stale PTEs
+ * (m169), so the write history
+ * stays the authority there.
+ */
+ if (svc_ledger_diverges <= 512)
+ pr_info("sema-ledger: DIVERGE write va=0x%llx prev=0x%llx cur=0x%llx\n",
+ dst_orig + o, lpa, pa);
+ pa = lpa;
+ aper = (lap == SVC_APERTURE_FB) ?
+ CE_APERTURE_VID : CE_APERTURE_SYS;
+ wprov = 0xF0;
+ }
} else {
wprov = svc.op_tr_src;
}