summaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/gsp_rm_emulation.c13
-rw-r--r--kernel/gsp_sema_service.c51
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));