diff options
| author | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-11-11 00:23:21 -0500 |
|---|---|---|
| committer | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-11-11 00:23:21 -0500 |
| commit | 131d44e083925f35f842114b6f7b6db546f28368 (patch) | |
| tree | b3cf3da4a55a920c8d04d289adf682d853598420 /kernel | |
| parent | 25e3e800df8e5caf18d7e846a0cd36df4f5834f9 (diff) | |
| download | open-iov-131d44e083925f35f842114b6f7b6db546f28368.tar.gz open-iov-131d44e083925f35f842114b6f7b6db546f28368.zip | |
vgsp: all-ones scrub release for registered waits; walk-page registration; GL frame publisher (CONT.416-417)
- gsp_sema_service: merge a scanner registration arriving after the
stash record instead of dropping it (a dropped registration let the
next authoring pass write the blocking pair into the page the guest
was polling, so the wait never ended); author the finish word
all-ones for every registered record while the sema word stays
put-based once real submissions were observed (CONT.416/417).
- scrub_pin_qmp (host scanner): accept an unstable-but-live wait page
instead of skipping it, and register the walk-resolved scrubber
channel page - first the walk summary, then the per-VAS kernel row
(h=0xc) when the summary path fails - so the release is armed before
the guest polls (r1762/r1764 evidence).
- guest-diag: add gl_frames, the direct-GL (GLX pbuffer) frame
publisher; with it the stack produced the first non-black
GPU-rendered frames (40/40, 640x480, animated) through
pbuffer -> sysmem -> ivshmem -> host frame_reader.
- gsp_rm_emulation: log the display-shim request words for triage.
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)); |
