diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/gsp_rm_emulation.c | 13 | ||||
| -rw-r--r-- | kernel/gsp_sema_service.c | 51 |
2 files changed, 57 insertions, 7 deletions
diff --git a/kernel/gsp_rm_emulation.c b/kernel/gsp_rm_emulation.c index ca14744..4ea6839 100644 --- a/kernel/gsp_rm_emulation.c +++ b/kernel/gsp_rm_emulation.c @@ -2260,8 +2260,17 @@ static void gsp_rm_handle_display_heads(struct gsp_emu_context *ctx, u32 cmd, u32 one = 1; u32 sz = req_size ? req_size : 72; u32 v; + u32 req_w0 = 0, req_w1 = 0, req_w2 = 0; memset(out_params, 0, sz); + if (req_params) { + if (req_size >= 4) + memcpy(&req_w0, req_params, 4); + if (req_size >= 8) + memcpy(&req_w1, req_params + 4, 4); + if (req_size >= 12) + memcpy(&req_w2, req_params + 8, 4); + } switch (cmd) { case 0x730102: /* SYSTEM_GET_NUM_HEADS: {subDev, flags, numHeads} */ if (sz >= 12) @@ -2371,8 +2380,8 @@ static void gsp_rm_handle_display_heads(struct gsp_emu_context *ctx, u32 cmd, *out_params_size = sz; *out_status = 0; nv_vgpu_info(ctx->vgpu, - "vgsp-rm: DISPLAY shim cmd=0x%x -> 1 head / 1 HDMI connector (size %u)", - cmd, sz); + "vgsp-rm: DISPLAY shim cmd=0x%x -> 1 head / 1 HDMI connector (size %u req=%#x/%#x/%#x)", + cmd, sz, req_w0, req_w1, req_w2); } /* diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c index 7bd1b26..be91f6d 100644 --- a/kernel/gsp_sema_service.c +++ b/kernel/gsp_sema_service.c @@ -47066,7 +47066,29 @@ static void svc_scrub_one(struct nv_vgpu_device *vgpu, struct svc_scrub *s) if (svc_scrubs[j].registered && !svc_scrubs[j].userd_ok && svc_scrubs[j].hsem_pa == s->hsem_pa) { - pr_info("sema-svc: scrub dedup slot %d (stash owns hsem_pa=0x%llx)\n", + /* + * CONT.416: merge the scanner + * registration onto the stash + * record instead of dropping it. + * Dropping it left this record + * registered=false, so the next + * authoring pass wrote the + * blocking pair (sema=entries-1, + * fin=0) to the very page the + * guest waited on (r1749/r1752: + * Xorg's PMA scrub wait never + * ended). The wait needs the + * all-ones release, which only + * registered records author. + */ + if (!s->registered || + s->fin_pa != svc_scrubs[j].fin_pa) { + s->registered = true; + s->fin_pa = svc_scrubs[j].fin_pa; + s->pa_gen++; + s->seeded = false; + } + pr_info("sema-svc: scrub dedup slot %d (stash owns hsem_pa=0x%llx; registration merged)\n", j, s->hsem_pa); memset(&svc_scrubs[j], 0, sizeof(svc_scrubs[j])); @@ -47162,7 +47184,7 @@ static void svc_scrub_one(struct nv_vgpu_device *vgpu, struct svc_scrub *s) s->consumed = put ? put - 1 : s->entries - 1; } else if (s->submitted == s->authored && s->authored_gen == s->pa_gen && - !(s->registered && !s->submitted)) { + !s->registered) { /* * CONT.414: re-author the release pair every pass while a * scanner-registered buffer has no observed submissions, so a @@ -47202,10 +47224,29 @@ static void svc_scrub_one(struct nv_vgpu_device *vgpu, struct svc_scrub *s) * and the folded finish counter is at its maximum. */ { - bool release = s->registered && !s->submitted; + /* + * CONT.416: a scanner-registered record always takes the + * all-ones release. The PMA scrub wait (mem_scrub + * _scrubWaitAndSave; finish word at vmap+0x6c004) has no + * timeout, and the registered page is by definition the one + * the guest polled. The put-based values remain for + * stash-only records (no scanner registration). + * + * CONT.417 (reboot #2 cold-boot decision, previously "candidate" + * in the CONT.416 note): the finish word is all-ones for EVERY + * registered record (not just submitted==0), because the finish + * wait accepts only fin >= lastSeen+itemsToSave and the + * emulation never executes the memsets; the sema word stays + * put-based once real submissions were observed so an active + * scrubber still sees forward progress. 0xffffffff can never + * equal a putIndex below the ring size, so the free-entry wait + * cannot block either way. + */ + bool rel_sema = s->registered && !s->submitted; + bool rel_fin = s->registered; u32 idle = 0xffffffffu; - u32 sema = release ? idle : s->consumed; - u32 fin = release ? idle : (u32)s->submitted; + u32 sema = rel_sema ? idle : s->consumed; + u32 fin = rel_fin ? idle : (u32)s->submitted; svc_write_ap(vgpu, s->hsem_pa, SVC_APERTURE_SYS, &sema, sizeof(sema)); |
