summaryrefslogtreecommitdiffstats
path: root/kernel/gsp_sema_service.c
diff options
context:
space:
mode:
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;
}