summaryrefslogtreecommitdiffstats
path: root/kernel/gsp_sema_service.c
diff options
context:
space:
mode:
authorArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-24 14:12:55 -0400
committerArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-24 14:12:55 -0400
commit005b8e24b382f387ca1217018f9209aca741d726 (patch)
tree93cb5f2ecebf3882f18ee6e3d51e60bcb08c79d6 /kernel/gsp_sema_service.c
parent3497ceb950e57130fdec244318e5b6b9ea58a63e (diff)
downloadopen-iov-005b8e24b382f387ca1217018f9209aca741d726.tar.gz
open-iov-005b8e24b382f387ca1217018f9209aca741d726.zip
vgsp-sema r627: the copy-landing parity pass no longer clobbers per-page landings - the r623c wrong-write site
The post-loop parity store (r254-era) recorded a large virtual-destination copy's whole range contiguously (dst + po) AFTER the per-page loop had already stored each page's true resolved PA (m180/r391). For a scattered UVM host buffer the contiguity guess overwrote the true entries; the next copy of the same VA then followed the poisoned ledger (the non-pin DIVERGE branch keeps the ledger) and wrote client c-data into guest pages the kernel had since re-used. r623c evidence chain (saxpy D2H readback of 0x70e64e700000): sema-ledger: rewrite va=0x70e64e77f000 old=0x12e700000 new=0x115800000 504x sema-ledger: DIVERGE write ... prev=0x1158xxxxx cur=0x12e7xxxxx guest panic: kchannelGetGfid_IMPL+0x12, garbage 0x44560800445590f0 (IEEE754 floats 854.25/856.125 = client c-data in nvidia channel structs) Fix: the parity pass skips pages the per-page loop already stored (lookup guard); it only seeds pages the loop did not reach. True per-page landings are never overwritten.
Diffstat (limited to 'kernel/gsp_sema_service.c')
-rw-r--r--kernel/gsp_sema_service.c24
1 files changed, 23 insertions, 1 deletions
diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c
index 0e8474f..70c9d72 100644
--- a/kernel/gsp_sema_service.c
+++ b/kernel/gsp_sema_service.c
@@ -7802,6 +7802,22 @@ static int svc_copy_1d(struct nv_vgpu_device *vgpu, u64 dst, u64 src, size_t tot
* kept the stale pre-pin pages while the copy landed on the pinned
* page (streams2 r254: the b1 rec range carried the a2 pages and
* the vadd read a2's pattern as its second input).
+ *
+ * r627: NEVER overwrite a per-page landing the loop above already
+ * stored. That loop stores each page's true resolved PA; this
+ * pass's `dst + po` is a contiguity guess valid only while the VA
+ * range maps contiguously. For a scattered UVM host buffer (r623c
+ * saxpy: page 0 at pa 0x115781000, page 0x7f000 at pa 0x12e700000)
+ * the guess clobbered the true entries -
+ * `sema-ledger: rewrite va=0x70e64e77f000 old=0x12e700000
+ * new=0x115800000` - and the NEXT copy of the same VA then
+ * followed the poisoned ledger: 504x `sema-ledger: DIVERGE write
+ * va=0x70e64e7xxxxx prev=0x1158xxxxx cur=0x12e7xxxxx`; the
+ * non-pin branch keeps the ledger, so ~2 MiB of client c-data
+ * landed in guest pages the kernel had since re-used and the
+ * guest died in kchannelGetGfid_IMPL (r623c panic). The loop's
+ * per-page entries are the authority; this pass only seeds pages
+ * the loop did not reach.
*/
if (!dst_phys && dst_virt && dst_orig >= SVC_VAS_FLOOR &&
total >= (64u << 10)) {
@@ -7809,8 +7825,14 @@ static int svc_copy_1d(struct nv_vgpu_device *vgpu, u64 dst, u64 src, size_t tot
SVC_APERTURE_FB : SVC_APERTURE_SYS;
size_t po;
- for (po = 0; po < total; po += SEMA_PAGE_SIZE)
+ for (po = 0; po < total; po += SEMA_PAGE_SIZE) {
+ u64 lpa = 0;
+ u32 lap = 0;
+
+ if (!svc_ledger_lookup(dst_orig + po, &lpa, &lap))
+ continue;
svc_ledger_store(dst_orig + po, dst + po, cap);
+ }
}
if (snap)
svc_copy_snap_free(dst_orig, src_orig, total, owner_ch,