diff options
| author | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-10-24 14:12:55 -0400 |
|---|---|---|
| committer | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-10-24 14:12:55 -0400 |
| commit | 005b8e24b382f387ca1217018f9209aca741d726 (patch) | |
| tree | 93cb5f2ecebf3882f18ee6e3d51e60bcb08c79d6 | |
| parent | 3497ceb950e57130fdec244318e5b6b9ea58a63e (diff) | |
| download | open-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.
| -rw-r--r-- | kernel/gsp_sema_service.c | 24 |
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, |
