diff options
| author | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-09-29 16:37:02 -0400 |
|---|---|---|
| committer | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-09-29 16:37:02 -0400 |
| commit | 4a4742f62475a2be9c0dc0f2c2a5d864c686f5f0 (patch) | |
| tree | 0c7a0217e30267d33007f47b004a8cc4c038a2b6 /kernel/gsp_sema_service.c | |
| parent | 26e6bc390cc9f466448a7470420d9de750e7611e (diff) | |
| download | open-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/gsp_sema_service.c')
| -rw-r--r-- | kernel/gsp_sema_service.c | 47 |
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); - } - } } } |
