diff options
Diffstat (limited to 'kernel/gsp_sema_service.c')
| -rw-r--r-- | kernel/gsp_sema_service.c | 65 |
1 files changed, 61 insertions, 4 deletions
diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c index a5f58db..2c6836f 100644 --- a/kernel/gsp_sema_service.c +++ b/kernel/gsp_sema_service.c @@ -2316,6 +2316,8 @@ static int svc_sem_read(struct nv_vgpu_device *vgpu, u64 va, u32 *val) return svc_read_ap(vgpu, addr, svc_ap_of(ap), val, sizeof(*val)); } +static void svc_pending_add(u64 va, u32 payload, u32 op); + static int svc_sem_write(struct nv_vgpu_device *vgpu, u32 h, u64 va, u32 val) { u64 addr = 0, old_addr; @@ -2335,10 +2337,25 @@ static int svc_sem_write(struct nv_vgpu_device *vgpu, u32 h, u64 va, u32 val) * historical order below. */ if (is_pool) { - if (!svc_pool_pa_resolve(vgpu, h, va, &addr, &ap, &src)) + if (!svc_pool_pa_resolve(vgpu, h, va, &addr, &ap, &src)) { verified = true; - else + } else { + /* + * A pool semaphore must never be written through the + * learned/content-scanned map: a stale PA there is + * silently lost (observed PA==VA fallback writes) + * while the client polls the real slot forever. The + * exact slot is known from the decoded release, so + * queue the absolute target for the retry pass until + * the verified resolver (pin -> read-back cache -> + * walk -> targeted rm_mem with read-back) can + * translate it. svc_apply_pending() retries every + * service pass and drops the entry once it lands. + */ svc_pool_pa_miss_note(va); + svc_pending_add(va, val, 0); + return -ENOENT; + } } if (!verified && svc_resolve_va(vgpu, va, &addr, &ap)) { /* @@ -5579,7 +5596,27 @@ static void svc_decode_stream(struct nv_vgpu_device *vgpu, const u8 *buf, if (st.have_sem && st.sem_payload && sem_va >= SEMA_VA_LO && sem_va < SEMA_VA_HI) { - if (svc_sem_read(vgpu, sem_va, &cur)) { + int rrc2; + + if (svc_pool_sem_va(sem_va)) { + u64 ppa = 0; + int pap = SVC_APERTURE_SYS; + + if (svc_pool_pa_resolve(vgpu, + ch->h_object, + sem_va, &ppa, + &pap, NULL)) + rrc2 = -ENOENT; + else + rrc2 = svc_read_ap(vgpu, ppa, + svc_ap_of(pap), + &cur, + sizeof(cur)); + } else { + rrc2 = svc_sem_read(vgpu, sem_va, + &cur); + } + if (rrc2) { svc.pushes_nomap++; /* * The semaphore page has no @@ -5826,7 +5863,27 @@ static void svc_apply_pending(struct nv_vgpu_device *vgpu) struct svc_pending_release *p = &svc_pending[i]; u32 cur = 0; - if (svc_sem_read(vgpu, p->va, &cur)) { + if (svc_pool_sem_va(p->va)) { + u64 ppa = 0; + int pap = SVC_APERTURE_SYS; + + /* + * Judge a pool semaphore only through the verified + * resolver: the learned map can answer with a stale + * page whose value makes this release look already + * delivered and drops it (see svc_sem_write). + */ + if (svc_pool_pa_resolve(vgpu, 0, p->va, &ppa, &pap, + NULL)) { + i++; /* not translatable yet: keep */ + continue; + } + if (svc_read_ap(vgpu, ppa, svc_ap_of(pap), &cur, + sizeof(cur))) { + i++; + continue; + } + } else if (svc_sem_read(vgpu, p->va, &cur)) { i++; /* translation still missing: keep waiting */ continue; } |
