summaryrefslogtreecommitdiffstats
path: root/kernel/gsp_sema_service.c
diff options
context:
space:
mode:
authorArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-17 01:15:00 -0400
committerArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-17 01:15:00 -0400
commit0bb52e0e3cdc86b31dce2daa23eafd099461604a (patch)
tree5d194cf768445884396369e4dc4675ec5bf749e8 /kernel/gsp_sema_service.c
parent01994e83c3754c98c065489daabd980fa001d5ba (diff)
downloadopen-iov-0bb52e0e3cdc86b31dce2daa23eafd099461604a.tar.gz
open-iov-0bb52e0e3cdc86b31dce2daa23eafd099461604a.zip
vgsp: m171 event completion fixes (minimal cudaEventSynchronize repro now passes) + AGENT-F R2 write/read consistency ledger
- gsp_rm_emulation: the event burst budget becomes a time-windowed rate (1 s) with completion posts allowed headroom over hint re-posts; the periodic hint dedups events posted within 250 ms (strictly below its own 500 ms cadence - an equal window races the boundary and skips forever); force_post skips retired slots (rc=22 spam was an artifact). Verified: the minimal cudaEventCreate/Record/Synchronize repro and a second repro with cross-stream waits and elapsed-time now complete on a live boot; previously cudaEventSynchronize hung forever. - gsp_sema_service: write/read consistency ledger (AGENT-F R2). Large device-destination writes record {va_page -> pa, aperture}; the launch data fill and device-source reads prefer the recorded page whenever their own resolution disagrees (sema-ledger DIVERGE log). Session scoped, zero cost while empty.
Diffstat (limited to 'kernel/gsp_sema_service.c')
-rw-r--r--kernel/gsp_sema_service.c121
1 files changed, 121 insertions, 0 deletions
diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c
index 0217594..95134bd 100644
--- a/kernel/gsp_sema_service.c
+++ b/kernel/gsp_sema_service.c
@@ -4519,6 +4519,74 @@ static bool svc_fwd_defer_armed;
#define SVC_COPY_FORWARDED 1
/* Byte copy between two CE addresses (src/dst decoding mirrors svc_fill). */
+/*
+ * m171 (AGENT-F R2): write/read consistency ledger. A large H2D write to a
+ * device VA records {va_page -> pa, aperture} for every page it wrote; the
+ * later read of the same VA (the launch data fill, or a D2H copy) prefers
+ * the recorded page whenever its own resolution disagrees. The pipeline
+ * then reads exactly what was written regardless of which of the two
+ * resolutions is stale - the r174/r175 first-page divergence (the write
+ * landed on pa X, the fill read a stale page Y, and the engine computed on
+ * old bytes) can no longer split a write/read pair. Session-scoped: cleared
+ * with the flush; zero cost while empty. Apertures are stored in the SVC_
+ * encoding, the canonical space for the svc accessors.
+ */
+struct svc_ledger_ent {
+ u64 va_page;
+ u64 pa_page;
+ u32 ap;
+};
+#define SVC_LEDGER_MAX 256
+static struct svc_ledger_ent svc_ledger[SVC_LEDGER_MAX];
+static u32 svc_ledger_n;
+static u32 svc_ledger_next;
+static u64 svc_ledger_diverges;
+
+static void svc_ledger_store(u64 va, u64 pa, u32 ap)
+{
+ u64 page = va & ~(u64)(SEMA_PAGE_SIZE - 1);
+ u64 pa_page = pa & ~(u64)(SEMA_PAGE_SIZE - 1);
+ u32 i;
+
+ for (i = 0; i < svc_ledger_n; i++) {
+ if (svc_ledger[i].va_page == page) {
+ svc_ledger[i].pa_page = pa_page;
+ svc_ledger[i].ap = ap;
+ return;
+ }
+ }
+ if (svc_ledger_n < SVC_LEDGER_MAX)
+ i = svc_ledger_n++;
+ else
+ i = svc_ledger_next++ % SVC_LEDGER_MAX;
+ svc_ledger[i].va_page = page;
+ svc_ledger[i].pa_page = pa_page;
+ svc_ledger[i].ap = ap;
+}
+
+static int svc_ledger_lookup(u64 va, u64 *pa, u32 *ap)
+{
+ u64 page = va & ~(u64)(SEMA_PAGE_SIZE - 1);
+ u32 i;
+
+ for (i = 0; i < svc_ledger_n; i++) {
+ if (svc_ledger[i].va_page == page) {
+ *pa = svc_ledger[i].pa_page |
+ (va & (SEMA_PAGE_SIZE - 1));
+ *ap = svc_ledger[i].ap;
+ return 0;
+ }
+ }
+ return -ENOENT;
+}
+
+static void svc_ledger_clear(void)
+{
+ memset(svc_ledger, 0, sizeof(svc_ledger));
+ svc_ledger_n = 0;
+ svc_ledger_next = 0;
+}
+
static int svc_copy(struct nv_vgpu_device *vgpu, u64 dst, u64 src, size_t total,
u32 dst_phys, u32 dst_aperture, u32 src_phys, u32 src_aperture)
{
@@ -4830,9 +4898,28 @@ static int svc_copy(struct nv_vgpu_device *vgpu, u64 dst, u64 src, size_t total,
} else if (src_virt) {
u64 pa = 0;
u32 aper = 0;
+ u64 lpa = 0;
+ u32 lap = 0;
if (svc_op_translate(vgpu, src_orig + o, &pa, &aper))
return -ENOENT;
+ /*
+ * m171 (AGENT-F R2): read-after-write - when a large
+ * H2D wrote this device VA page through a different
+ * translation, read the page the write landed on.
+ */
+ if (src_orig >= SVC_VAS_FLOOR &&
+ !svc_ledger_lookup(src_orig + o, &lpa, &lap) &&
+ (lpa & ~(u64)(SEMA_PAGE_SIZE - 1)) !=
+ (pa & ~(u64)(SEMA_PAGE_SIZE - 1))) {
+ svc_ledger_diverges++;
+ if (svc_ledger_diverges <= 32)
+ pr_info("sema-ledger: DIVERGE read va=0x%llx wrote=0x%llx read=0x%llx\n",
+ src_orig + o, lpa, pa);
+ pa = lpa;
+ aper = (lap == SVC_APERTURE_FB) ?
+ CE_APERTURE_VID : CE_APERTURE_SYS;
+ }
if (aper == CE_APERTURE_VID) {
u8 *base = vgpu->bars[1].vaddr;
@@ -4869,6 +4956,16 @@ static int svc_copy(struct nv_vgpu_device *vgpu, u64 dst, u64 src, size_t total,
if (!base || pa + chunk > svc_fb_shadow_size(vgpu))
return -EINVAL;
memcpy(base + pa, bounce, chunk);
+ /*
+ * m171 (AGENT-F R2): a large device-dest write
+ * records its landing page so the later kernel
+ * fill / D2H read of the same VA uses it even
+ * if its own resolution is stale.
+ */
+ if (dst_orig >= SVC_VAS_FLOOR &&
+ total >= (64u << 10))
+ svc_ledger_store(dst_orig + o, pa,
+ SVC_APERTURE_FB);
} else if (svc_write(vgpu, pa, bounce, chunk)) {
return -EIO;
}
@@ -7647,6 +7744,8 @@ static void svc_session_flush(void)
}
svc_vas_n = 0;
memset(svc.lat, 0, sizeof(svc.lat));
+ /* m171 (AGENT-F R2): the write/read ledger is per-session. */
+ svc_ledger_clear();
spin_lock_irqsave(&svc.vas_lock, flags);
for (i = 0; i < SVC_MAX_VASPACES; i++)
svc.vas[i].valid = false;
@@ -13308,6 +13407,28 @@ static void svc_gr_data_fill(struct nv_vgpu_device *vgpu)
break;
}
}
+ /*
+ * m171 (AGENT-F R2): prefer the write/read ledger's
+ * landing page for this operand VA when it disagrees
+ * with the resolution - the kernel then reads exactly
+ * the page a large H2D wrote (r174: write landed on
+ * pa X while the fill read a stale page Y).
+ */
+ if (va >= SVC_VAS_FLOOR) {
+ u64 lpa = 0;
+ u32 lap = 0;
+
+ if (!svc_ledger_lookup(va, &lpa, &lap) &&
+ (lpa & ~(u64)(SEMA_PAGE_SIZE - 1)) !=
+ (pa & ~(u64)(SEMA_PAGE_SIZE - 1))) {
+ svc_ledger_diverges++;
+ if (svc_ledger_diverges <= 32)
+ pr_info("sema-ledger: DIVERGE fill va=0x%llx wrote=0x%llx read=0x%llx\n",
+ va, lpa, pa);
+ pa = lpa;
+ ap = lap;
+ }
+ }
if (svc_fwd_req.gr_n_data >= bounce_max) {
/*
* B-2 fail-closed cap: the active region is