summaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorArthur Hanson Rasmusson <arthur@vgpu.io>2026-09-29 16:37:02 -0400
committerArthur Hanson Rasmusson <arthur@vgpu.io>2026-09-29 16:37:02 -0400
commit4a4742f62475a2be9c0dc0f2c2a5d864c686f5f0 (patch)
tree0c7a0217e30267d33007f47b004a8cc4c038a2b6 /kernel
parent26e6bc390cc9f466448a7470420d9de750e7611e (diff)
downloadopen-iov-4a4742f62475a2be9c0dc0f2c2a5d864c686f5f0.tar.gz
open-iov-4a4742f62475a2be9c0dc0f2c2a5d864c686f5f0.zip
sema-svc: GR counter slots only from injected pins; route GR releases through the exact slot
Live evidence: with the counter page pinned, counter_pa still resolved to a stale self-discovered page, so every release write went to memory the client never polls (host read back its own 1s; client's page stayed 0) and the client's context-init wait expired. The generic release path could also write through that stale translation. - svc_counter_autoreg / svc_counter_learn trust only the injected-pin table (svc_ipin_lookup); learn re-registers when the injected PA differs. - Releases whose target is in the GR counter VA range skip the generic translation write entirely and go through the injected-pin-backed slot.
Diffstat (limited to 'kernel')
-rw-r--r--kernel/gsp_sema_service.c47
1 files changed, 33 insertions, 14 deletions
diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c
index e336277..d476188 100644
--- a/kernel/gsp_sema_service.c
+++ b/kernel/gsp_sema_service.c
@@ -2152,6 +2152,7 @@ static void svc_counter_release_apply(struct nv_vgpu_device *vgpu, u32 h,
return;
svc.releases_applied++;
svc.counter_rel_applied++;
+ svc.gr_rel_applied++;
svc.post_hint_until = jiffies + 10 * HZ;
if (svc.counter_rel_dbg < 32) {
svc.counter_rel_dbg++;
@@ -2182,7 +2183,14 @@ static void svc_counter_autoreg(struct svc_channel *ch, int n_gr)
if (ch->gr_index >= n_gr)
return;
va = 0x20400fec0ULL + (u64)(n_gr - 1 - ch->gr_index) * 0x10ULL;
- if (svc_pin_lookup_any(va, &pa, &ap) || ap != SVC_APERTURE_SYS)
+ /*
+ * Only the authoritative injected-pin table may register a counter
+ * slot: the self-discovered map can hold a stale translation for this
+ * VA (content-scanned page), and a write to that page never reaches
+ * the client. If no injected pin exists yet, leave counter_pa zero so
+ * a later pass (once the pin lands) registers it.
+ */
+ if (svc_ipin_lookup(va, &pa, &ap) || ap != SVC_APERTURE_SYS)
return;
ch->counter_pa = pa & ~0x3ULL;
pr_info("sema-chan: counter auto h=0x%x rank=%u pa=0x%llx (slot va=0x%llx)\n",
@@ -2205,13 +2213,19 @@ static void svc_counter_learn(u32 h, u64 sem_va)
if (!h || sem_va < 0x204000000ULL || sem_va >= 0x204100000ULL)
return;
- if (svc_pin_lookup_any(sem_va, &pa, &ap) || ap != SVC_APERTURE_SYS)
+ /*
+ * Authoritative injected pins only (see svc_counter_autoreg): a stale
+ * self-discovered entry would make every release land on a page the
+ * client never polls. Re-learn when the injected PA differs, so a pin
+ * that lands after an earlier stale registration still wins.
+ */
+ if (svc_ipin_lookup(sem_va, &pa, &ap) || ap != SVC_APERTURE_SYS)
return;
spin_lock_irqsave(&svc.chan_lock, flags);
for (i = 0; i < SVC_MAX_CHANNELS; i++) {
if (svc.chan[i].valid && svc.chan[i].h_object == h) {
- if (!svc.chan[i].counter_pa) {
+ if (svc.chan[i].counter_pa != (pa & ~0x3ULL)) {
svc.chan[i].counter_pa = pa & ~0x3ULL;
pr_info("sema-chan: counter learned h=0x%x pa=0x%llx (from release va=0x%llx)\n",
h, pa & ~0x3ULL, sem_va);
@@ -2636,19 +2650,24 @@ static void svc_decode_stream(struct nv_vgpu_device *vgpu, const u8 *buf,
cur += st.sem_payload;
else
cur = st.sem_payload;
- if (!svc_sem_write(vgpu, sem_va, cur)) {
+ /*
+ * GR completion counters live in a
+ * client semaphore page whose generic
+ * translation can be a stale
+ * content-scanned page; writing there
+ * corrupts an unrelated page and never
+ * reaches the client. Those releases go
+ * through the injected-pin-backed slot
+ * (svc_counter_learn /
+ * svc_counter_release_apply) below.
+ */
+ if (ch_eng == 0 &&
+ sem_va >= 0x204000000ULL &&
+ sem_va < 0x204100000ULL) {
+ /* handled by the exact-slot path */
+ } else if (!svc_sem_write(vgpu, sem_va, cur)) {
svc.releases_applied++;
svc.post_hint_until = jiffies + 10 * HZ;
- if (ch_eng == 0 &&
- sem_va >= 0x204000000ULL &&
- sem_va < 0x204100000ULL) {
- svc.gr_rel_applied++;
- if (svc.gr_rel_log < 48) {
- svc.gr_rel_log++;
- pr_info("sema-chan: gr release h=0x%x va=0x%llx pay=%u\n",
- ch_h, sem_va, cur);
- }
- }
}
}