From 919a421e86b827f63d58a2ab702b26d37aa43ed7 Mon Sep 17 00:00:00 2001 From: Arthur Hanson Rasmusson Date: Sun, 15 Nov 2026 12:59:26 -0500 Subject: vgsp: eng55 - VTG SPH authoring at family+0x900, DDX ring-head tracker decode, MME pack carrier, and the pump atomic-sleep hoist - gsp_phys_booter.c: sema_gl_sph_vtg_auth (default 1) authors the client's live VTG SPH image at family+0x900 and binds VSA/VSB there; new SPH-AUTHOR / SPH-ALIAS-auth receipts and a DS-IMAGE stage census at the DS latch (stage-start w0 + code word through the pair cache). - gsp_phys_booter.c: sema_gl_mme_pack_carry (default 0) + _ms (default 100) host-initiated windowless continuation carrier for a split MME pack; MME-CARRY-ARM/FIRE/COMPLETE/CANCEL/ABORT receipts, beef-only, bounded. - gsp_sema_service.c: sema_ddx_tracker_auth (default 0) ring-head decode for the DDX channel when the USERD is missing/reset (guest-authored C36F release applied verbatim); sema_gr_scan_top default raised to 0x300000000 for the 12 GiB campaign guest. - gsp_sema_service.c: hoist the r707e VAS candidate verify out of svc.chan_lock (its vfio_dma_rw path can sleep) and add in_atomic guards to svc_read/svc_write; fixes the gsp-sema-svc "scheduling while atomic" pump stall that lost the marked draw-window launch. - tools: enable sema_ddx_tracker_auth=1 in params-r1624; use timeout -k in the guest GL/GZDoom wrappers so a wedged GPU wait cannot hang a cycle. Validation: c741/c743 boots (VTG author byte readback, cross-lane and beef pack completion + REARM, DS-IMAGE census) and the c743 DS-FAST chain; A/B for the carrier and the tracker decode is still open. --- kernel/gsp_sema_service.c | 537 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 515 insertions(+), 22 deletions(-) (limited to 'kernel/gsp_sema_service.c') diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c index 96fabcf..4655e77 100644 --- a/kernel/gsp_sema_service.c +++ b/kernel/gsp_sema_service.c @@ -47,6 +47,7 @@ #include #include #include +#include #include #include "nvidia-vgpu-vfio.h" @@ -251,14 +252,24 @@ struct sema_map_entry { * The module parameter is the per-cycle guard: shrink it to the boot's real * RAM top. * - * r933: this parameter is now the single live PA acceptance bound for the - * whole service (svc_pa_max), not just the ring scan - the walk leaves in - * the 6-8 GiB band were exactly what the old separate 6 GB SEMA_PA_MAX - * rejected (the GL client's kick pages). SEMA_PA_MAX remains the - * compile-time maximum that sizes fixed tables; the param clamps it. - */ -unsigned long long gsp_sema_gr_scan_top = 0x280000000ULL; + * X-DMA-FIX (2026-11-15): the campaign guest is 12 GiB (e820 top + * 0x300000000), so the old 0x280000000 default stopped every content scan + * 2 GiB below the guest's own allocations ("RAM scan found no candidate + * ... top 0x280000000"). The default now covers the whole 12 GiB band; + * a smaller guest still fails reads past its mapped RAM fast. + * + * r933: this parameter is the live PA acceptance bound for the whole + * service (svc_pa_max), not just the ring scan - the walk leaves in the + * 6-8 GiB band were exactly what the old separate 6 GB SEMA_PA_MAX + * rejected (the GL client's kick pages). svc_pa_max() clamps a larger + * param to the compile-time SEMA_PA_MAX before extending it to the + * registered guest-RAM top (CONT.478), so the param sizes the scans + * while registration provides the acceptance truth. + */ +unsigned long long gsp_sema_gr_scan_top = 0x300000000ULL; module_param_named(sema_gr_scan_top, gsp_sema_gr_scan_top, ullong, 0644); +MODULE_PARM_DESC(sema_gr_scan_top, + "Guest-RAM ring/USERD content-scan top, guest-physical bytes (default 0x300000000 = 12 GiB); shrink to the boot's RAM top"); /* * r1780 (CONT.430b): keep the direct-GL (beef GR) ring content scan alive @@ -888,6 +899,23 @@ struct svc_channel { * write-back list. */ u64 notify2d_va; + /* + * X-DMA tracker fix (sema_ddx_tracker_auth): a re-created DDX + * channel loses its USERD latch, so the pump refuses to walk the + * ring and the client's own release push (C36F/SEM_EXECUTE) is + * never decoded. svc_ddx_head_decode reads the head entries + * directly instead. ddx_head_at paces that scan to one attempt per + * 100 ms per channel (persisted immediately - the stalled branch + * skips the end-of-pass write-back); ddx_cache_* hold the last + * decoded release for the mode-2 forward-only diagnostic re-apply. + * All four are zeroed by the registration memset, so a + * re-registration or a generation change never inherits a dead + * session's release. + */ + unsigned long ddx_head_at; + u64 ddx_cache_va; + u32 ddx_cache_payload; + bool ddx_cache_valid; /* r829: bounded count of zero-entry (bad-translation) holds; see the * zero-entry hold in svc_pump_channels. Persists via the write-back. */ u32 zero_held; @@ -2129,11 +2157,16 @@ static void svc_retry_enqueue(u64 va, u32 len, u32 want) static int svc_read(struct nv_vgpu_device *vgpu, u64 gpa, void *buf, size_t len) { + /* vfio_dma_rw() may sleep on the type1 iommu mutex. */ + if (WARN_ON_ONCE(in_atomic())) + return -EINVAL; return vfio_dma_rw(&vgpu->vfio_dev, gpa, buf, len, false); } static int svc_write(struct nv_vgpu_device *vgpu, u64 gpa, void *buf, size_t len) { + if (WARN_ON_ONCE(in_atomic())) + return -EINVAL; return vfio_dma_rw(&vgpu->vfio_dev, gpa, buf, len, true); } @@ -3686,6 +3719,17 @@ static void svc_vas_candidates_verify(struct nv_vgpu_device *vgpu, u64 va, { int i; + /* + * The walk reads guest page tables through vfio_dma_rw(), which + * takes the type1 iommu mutex and may sleep. The r707e every-pass + * verify originally ran under svc.chan_lock and produced the + * "scheduling while atomic" class (PART 43 / PART 57) again in + * c741; this guard keeps a future locked call site from silently + * reintroducing it. + */ + if (WARN_ON_ONCE(in_atomic())) + return; + for (i = 0; i < SVC_VAS_CAND_MAX; i++) { u64 wpa = 0; int wap = 0; @@ -10491,6 +10535,20 @@ const u8 *gsp_sema_gl_prog_img(u64 va, u32 *len_out) return NULL; } +/* + * eng52 (DS stage-image gate): the published VTG image without the + * stage-typed selection above. The booter's family+0x900 authoring must + * always copy the VERTEX image; gsp_sema_gl_prog_img can legitimately + * answer the PIXEL image for an unregistered page, which would poison the + * VSA/VSB stages it is bound to. + */ +const u8 *gsp_sema_gl_vs_img(u32 *len_out) +{ + if (len_out) + *len_out = svc_gl_vs_len; + return svc_gl_vs_len ? svc_gl_vs : NULL; +} + /* * SESSION 153 (GL client draw sections): the GL client's own per-frame * pushes bind TURING_A (0xC597) exactly like the X server's one-shot @@ -23244,6 +23302,15 @@ static void svc_decode_stream(struct nv_vgpu_device *vgpu, const u8 *buf, svc.pushes_seen++; st.rel_va = va; st.rel_payload = payload; + /* + * X-DMA tracker fix: keep this guest-authored + * release for svc_ddx_head_decode's mode-2 + * diagnostic re-apply (forward-only). The + * snapshot write-back persists it. + */ + ch->ddx_cache_va = va; + ch->ddx_cache_payload = payload; + ch->ddx_cache_valid = true; /* SESSION 149 R14: keep the last VALID release * decoded on this channel for the GL section * synthesizer (the 24 B release pushes bracket @@ -23458,6 +23525,12 @@ static void svc_decode_stream(struct nv_vgpu_device *vgpu, const u8 *buf, svc.pushes_seen++; st.rel_va = va; st.rel_payload = st.rs_payload; + /* X-DMA tracker fix: cache the + * validated REPORT_SEM release for the + * head-decode mode-2 diagnostic. */ + ch->ddx_cache_va = va; + ch->ddx_cache_payload = st.rs_payload; + ch->ddx_cache_valid = true; svc_wait_rel_va = va; svc_wait_rel_payload = st.rs_payload; svc_wait_rel_off = off; @@ -24770,6 +24843,13 @@ static void svc_decode_stream(struct nv_vgpu_device *vgpu, const u8 *buf, sem_va >= SEMA_VA_LO && sem_va < SEMA_VA_HI) { int rrc2; + /* X-DMA tracker fix: cache only the + * validated release (a missing + * semaphore word would cache a + * fabricated target). */ + ch->ddx_cache_va = sem_va; + ch->ddx_cache_payload = st.sem_payload; + ch->ddx_cache_valid = true; if (svc_pool_sem_va(sem_va)) { u64 ppa = 0; int pap = SVC_APERTURE_SYS; @@ -27805,6 +27885,199 @@ static void svc_kick_capture_arm(struct nv_vgpu_device *vgpu, ch->h_object, ch->notify2d_va); } +/* + * X-DMA tracker fix (DDX ring-head tracker decode). + * + * The guest X DDX's channel (0x01000013 and the 0xbfef00xx kick family) is + * re-created between push generations. Its USERD is client-allocated in + * guest RAM and the latch can go missing/reset, so the pump refuses to walk + * the ring (!userd_ok) and the client's own release push - measured as + * va=0x1200a0000 len=24 targeting rel=0x120001000, the nvPush progress + * tracker - is never decoded. The tracker word then never advances and the + * DDX reports "Failed to idle DMA". + * + * This decode walks the ring head directly - no USERD, no GP_GET advance, no + * userd_ok latch - and runs the normal release/decode path with method ops + * disabled: the guest-authored payload is applied verbatim through + * svc_rel_apply_906f/svc_sem_write, never synthesized. The + * 0x120000000-0x121000000 window is the driver's push window (the X ring, + * its pushes and the tracker word all live there). + * + * sema_ddx_tracker_auth: 0 = off (default), 1 = head decode, 2 = also + * re-apply the last decoded release forward-only when the head itself is + * unreadable (diagnostic only; never fabricates a payload). + */ +static uint gsp_sema_ddx_tracker_auth; +module_param_named(sema_ddx_tracker_auth, gsp_sema_ddx_tracker_auth, uint, + 0644); +MODULE_PARM_DESC(sema_ddx_tracker_auth, + "DDX ring-head tracker decode when the USERD latch is missing: 0=off, 1=decode head entries, 2=also re-apply the last decoded release forward-only"); + +/* + * Persist the head-decode pacing/cache immediately: the !userd_ok path + * `continue`s past the end-of-pass snapshot write-back, so the 100 ms rate + * limit and the cached release must survive on their own. + */ +static void svc_ddx_state_store(struct nv_vgpu_device *vgpu, + const struct svc_channel *ch) +{ + unsigned long flags; + int i; + + spin_lock_irqsave(&svc.chan_lock, flags); + for (i = 0; i < SVC_MAX_CHANNELS; i++) { + if (svc.chan[i].valid && svc.chan[i].vgpu == vgpu && + svc.chan[i].h_object == ch->h_object) { + svc.chan[i].ddx_head_at = ch->ddx_head_at; + svc.chan[i].ddx_cache_va = ch->ddx_cache_va; + svc.chan[i].ddx_cache_payload = + ch->ddx_cache_payload; + svc.chan[i].ddx_cache_valid = ch->ddx_cache_valid; + break; + } + } + spin_unlock_irqrestore(&svc.chan_lock, flags); +} + +static void svc_ddx_head_decode(struct nv_vgpu_device *vgpu, + struct svc_channel *ch, u64 ring_pa, + int ring_ap) +{ + static u8 *buf; + const char *reason = NULL; + u32 entries = ch->gpfifo_entries; + u32 start = (u32)ch->last_get; + u32 maxn, idx = 0, slot = 0; + u64 va = 0; + u32 len = 0; + u64 rel_va = 0; + u32 rel_pay = 0; + bool released = false; + bool head_unreadable = false; + + if (!gsp_sema_ddx_tracker_auth) + return; + if (!svc_userd_ddx_family(ch)) + return; + if (ch->ddx_head_at && time_before(jiffies, ch->ddx_head_at)) { + reason = "rate"; + goto miss; + } + ch->ddx_head_at = jiffies + msecs_to_jiffies(100); + svc_ddx_state_store(vgpu, ch); + if (!ring_pa || ring_ap < 0) { + reason = "no-ring"; + head_unreadable = true; + goto miss; + } + if (!entries || start >= entries) { + reason = "no-entry"; + head_unreadable = true; + goto miss; + } + + maxn = min_t(u32, 8u, entries - start); + for (idx = 0; idx < maxn; idx++) { + u8 ent[SVC_GPFIFO_ENTRY_SIZE]; + u32 e0, e1, mark; + + slot = (start + idx) % entries; + if (svc_read_ap(vgpu, + ring_pa + (u64)slot * SVC_GPFIFO_ENTRY_SIZE, + ring_ap, ent, sizeof(ent))) { + reason = "unreadable"; + head_unreadable = true; + break; + } + memcpy(&e0, ent, 4); + memcpy(&e1, ent + 4, 4); + if (!e0 && !e1) { + reason = "no-entry"; + head_unreadable = true; + break; + } + va = ((u64)(e1 & 0xff) << 32) | (u64)(e0 & 0xfffffffc); + len = ((e1 >> 10) & 0x1fffff) << 2; + if (va < 0x120000000ULL || va >= 0x121000000ULL) { + reason = "bad-va"; + break; + } + if (len < 4 || len > 0x10000) { + reason = "bad-len"; + break; + } + if (!buf) { + buf = kmalloc(0x10000, GFP_KERNEL); + if (!buf) { + reason = "unreadable"; + head_unreadable = true; + break; + } + } + if (svc_read_va_push(vgpu, ch, va, buf, len)) { + reason = "unreadable"; + head_unreadable = true; + break; + } + if (!memchr_inv(buf, 0, len)) { + /* + * The push read succeeded but answered an all-zero + * page (a stale/zero translation): there is no + * release to decode and no value to apply. + */ + reason = "zero-payload"; + head_unreadable = true; + break; + } + mark = svc_rel_count; + /* + * No ops (allow_ops=false): the release apply and the + * trusted-decode side effects stay, method execution does + * not. page_pa only feeds svc_mark_hot; use the page the + * push read actually answered from. + */ + svc_decode_stream(vgpu, buf, len, + svc_read_last_pa & + ~(u64)(SEMA_PAGE_SIZE - 1), + false, ch, slot, va, true, false, NULL); + if (svc_rel_count != mark && ch->ddx_cache_valid) { + released = true; + rel_va = ch->ddx_cache_va; + rel_pay = ch->ddx_cache_payload; + break; + } + } + svc_ddx_state_store(vgpu, ch); + if (released) { + pr_info_ratelimited("sema-ddx: head-decode h=0x%x idx=%u va=0x%llx len=%u rel=0x%llx pay=0x%x\n", + ch->h_object, slot, va, len, rel_va, rel_pay); + return; + } + if (!reason) + reason = "no-release"; +miss: + pr_info_ratelimited("sema-ddx: head-decode MISS h=0x%x idx=%u reason=%s\n", + ch->h_object, slot, reason); + /* + * Mode 2 diagnostic: the ring head itself is unreadable and the + * channel already decoded a real release. Re-apply that exact + * (va, payload) forward-only - never a synthesized value, never in + * mode 1. + */ + if (gsp_sema_ddx_tracker_auth == 2 && head_unreadable && + ch->ddx_cache_valid) { + u32 cur = 0; + + (void)svc_sem_read(vgpu, ch->ddx_cache_va, &cur); + if (svc_rel_apply_906f(vgpu, ch, ch->ddx_cache_va, + ch->ddx_cache_payload, + HOST_SEM_OP_RELEASE)) + pr_info_ratelimited("sema-ddx: cached-apply h=0x%x rel=0x%llx pay=0x%x cur=0x%x\n", + ch->h_object, ch->ddx_cache_va, + ch->ddx_cache_payload, cur); + } +} + /* * r1659: direct-GL CE USERD adoption. The beef0101/0102 channels declare a * real FB control page (userdMem.base + userdOffset: 0x244f800 / 0x244f400) @@ -35747,6 +36020,17 @@ struct svc_fwd_req { * exactly-once latch for the work-item CUDA bridge fallback. */ bool gr; + /* + * Host-initiated MME pack-continuation carrier (sema_gl_mme_pack_carry): + * gr_synthetic marks the service-authored request that carries the next + * packed-prelude part for an already-armed beef channel. It has no guest + * push, pages, inline records, data records, releases or QMD completion: + * the backend emits a windowless LOAD-ONLY launch from its own pack + * cursor. Its outcome never authorises a guest release and never raises + * a synthetic fault - on launch failure the booter's carrier failure + * path rewinds the pack so the next client window re-emits from word 0. + */ + bool gr_synthetic; bool gr_bridge_done; bool gr_page_overflow; /* @@ -37578,6 +37862,13 @@ static void svc_fwd_outcome_check(struct nv_vgpu_device *vgpu) bool done = smp_load_acquire(&svc_fwd_req.done); unsigned long waited; + /* + * Host-initiated carrier: its failure path is the backend call's own + * (gsp_phys_gr_mme_carry_failed); it carries no guest release and no + * QMD word, so the stall-completion path must never touch it. + */ + if (svc_fwd_req.gr_synthetic) + return; if (!svc_fwd_req.gr || svc_fwd_req.vgpu != vgpu || svc_fwd_req.gr_swrel_done || svc_fwd_hold.active || !done) return; @@ -38709,6 +39000,8 @@ static void svc_fwd_gr_work(void) } } gs.h_object = svc_fwd_req.gr_h_object; + /* Host-initiated carrier: no guest window/pages/releases. */ + gs.mme_carrier = svc_fwd_req.gr_synthetic; /* * GRVAUDIT: one line per launch (n_data matches the backend @@ -38742,12 +39035,23 @@ static void svc_fwd_gr_work(void) if (cp.fault.valid) svc.fwd_gr_fault++; } - if ((svc.fwd_gr_fallback & SVC_FWD_LOG_MASK) == 1) - pr_info("vgsp-work: GR forward failed rc=%d h=0x%x push=0x%llx; falling back to the CUDA bridge (req=%llu ok=%llu fallback=%llu)\n", - hw_rc, svc_fwd_req.gr_h_object, - svc_fwd_req.gr_push_va, svc.fwd_gr_req, - svc.fwd_gr_ok, svc.fwd_gr_fallback); - svc_gr_req_bridge_fallback(svc_fwd_req.vgpu); + if (svc_fwd_req.gr_synthetic) { + /* + * The carrier never reached the engine (or the engine + * rejected the load-only block). Never fabricate a + * completion: void the carrier and rewind the pack so + * the next client window re-emits from word 0. The + * failure path logs MME-CARRY-ABORT. + */ + gsp_phys_gr_mme_carry_failed(hw_rc); + } else { + if ((svc.fwd_gr_fallback & SVC_FWD_LOG_MASK) == 1) + pr_info("vgsp-work: GR forward failed rc=%d h=0x%x push=0x%llx; falling back to the CUDA bridge (req=%llu ok=%llu fallback=%llu)\n", + hw_rc, svc_fwd_req.gr_h_object, + svc_fwd_req.gr_push_va, svc.fwd_gr_req, + svc.fwd_gr_ok, svc.fwd_gr_fallback); + svc_gr_req_bridge_fallback(svc_fwd_req.vgpu); + } } svc_fwd_req.fault = cp.fault; @@ -41643,6 +41947,7 @@ static int svc_gr_req_fill(struct nv_vgpu_device *vgpu, memset(&svc_fwd_req.fault, 0, sizeof(svc_fwd_req.fault)); svc_fwd_req.guest = false; svc_fwd_req.gr = true; + svc_fwd_req.gr_synthetic = false; svc_fwd_req.gr_bridge_done = false; /* STALLFREE: fresh request - re-arm the software-completion latch and * stamp the fill time for the GR-STALL waited_ms accounting. */ @@ -43165,6 +43470,112 @@ static bool svc_gr_request(struct nv_vgpu_device *vgpu, return true; } +/* + * Host-initiated MME pack-continuation carrier (sema_gl_mme_pack_carry). + * + * c727: a split packed emission stalled at part 1 of 3 (1512/2799 words) and + * no later client launch carried the remaining parts, so the CALL runs stayed + * held. c716 proved the completing launch shape: a final-part, window-dropped + * LOAD-ONLY launch. The service therefore asks the booter for a due carrier + * (armed at a partial receipt for a beef channel on which the forced-golden + * pack is contiguously loaded from word 0) and queues it as a synthetic GR + * request. The request carries no guest push/pages/inline/data/releases, so + * the backend can only emit the next golden pack part on a windowless + * LOAD-ONLY block: no draw runs, no unheld CALL runs, no guest memory is read + * or written. The booter re-validates the live cursor in carry_take(); on any + * mismatch it cancels and this function is a no-op. + */ +#define SVC_GR_CARRIER_PUSH_VA 0x6d6d6500ULL /* unique synthetic id */ +#define SVC_GR_CARRIER_STUB_WAIT 0x20010044u /* INC 0x110 WAIT_FOR_IDLE */ + +static bool svc_gr_cand_unoffered_for(u32 h_object) +{ + u32 ri; + + for (ri = 0; ri < SVC_GR_CAND_RING; ri++) { + struct svc_gr_cand_rec *c = &svc_gr_cand_ring[ri]; + + if (c->valid && !c->offered && c->h_object == h_object) + return true; + } + return false; +} + +static bool svc_gr_carrier_request(struct nv_vgpu_device *vgpu, + const struct svc_channel *ch) +{ + u32 h_object = ch->h_object; + u32 gen = 0, off = 0, maxa = 0; + + if (!gsp_phys_gr_forward_enabled() || + !gsp_phys_backend_gr_ready() || !gsp_phys_guest_mem_enabled()) + return false; + /* One launch owner per channel: never compete with a real candidate. */ + if (svc_gr_cand_unoffered_for(h_object) || svc_fwd_hold.active) + return false; + if (!gsp_phys_gr_mme_carry_take(h_object, &gen, &off, &maxa)) + return false; + pr_info("vgsp-gr: MME-CARRY-FIRE h=0x%x gen=%u off=%u/%u push=0x%llx\n", + h_object, gen, off, maxa, + (unsigned long long)SVC_GR_CARRIER_PUSH_VA); + mutex_lock(&svc_fwd_lock); + if (svc_fwd_paused || + test_and_set_bit_lock(SVC_FWD_INFLIGHT, &svc_fwd_state)) { + mutex_unlock(&svc_fwd_lock); + /* + * Nothing was queued and nothing was emitted: drop the carrier + * without rewinding the pack (the next client window continues + * from the current cursor). + */ + gsp_phys_gr_mme_carry_cancel("request-busy"); + return false; + } + memset(&svc_fwd_req, 0, sizeof(svc_fwd_req)); + svc_fwd_req.done = false; + svc_fwd_req.hw_rc = 0; + svc_fwd_req.vgpu = vgpu; + svc_fwd_req.gr = true; + svc_fwd_req.gr_synthetic = true; + svc_fwd_req.gr_h_object = h_object; + svc_fwd_req.gr_push_va = SVC_GR_CARRIER_PUSH_VA; + svc_fwd_req.gr_fill_jiffies = jiffies; + /* + * The backend's 3D branch is entered by a non-empty stream; the + * two-word stub here is only the request shape (the booter replaces it + * with its own WAIT_FOR_IDLE stub and forces LOAD-ONLY), so this body + * is never executed. No pages, inline records, data records, windows, + * program binds, sem fields or release fields are filled - the memset + * above zeroed them and qmd[] is the all-zero 64-word source the + * submit requires. + */ + svc_fwd_req.gr_stream_3d = true; + svc_fwd_req.gr_stream_off = 0; + svc_fwd_req.gr_stream_n = 2; + svc_fwd_req.gr_stream_rel = 0; + svc_fwd_req.gr_raw[0] = SVC_GR_CARRIER_STUB_WAIT; + svc_fwd_req.gr_raw[1] = 0; + svc_fwd_requests++; + if (!svc_fwd_wq) { + svc_fwd_wq = alloc_ordered_workqueue("gsp-phys-work", 0); + if (!svc_fwd_wq) { + clear_bit_unlock(SVC_FWD_INFLIGHT, &svc_fwd_state); + svc_fwd_dropped++; + mutex_unlock(&svc_fwd_lock); + gsp_phys_gr_mme_carry_cancel("queue-alloc"); + return false; + } + } + if (!queue_work(svc_fwd_wq, &svc_fwd_work)) { + clear_bit_unlock(SVC_FWD_INFLIGHT, &svc_fwd_state); + svc_fwd_dropped++; + mutex_unlock(&svc_fwd_lock); + gsp_phys_gr_mme_carry_cancel("queue-work"); + return false; + } + mutex_unlock(&svc_fwd_lock); + return true; +} + /* * Called only from the service thread (the pump). Returns true when a guest * (hardware-copy) request was queued; the caller then decides whether to hold @@ -43234,6 +43645,7 @@ static bool svc_fwd_request(struct nv_vgpu_device *vgpu, * return value below would report a queue that never happened). */ svc_fwd_req.gr = false; + svc_fwd_req.gr_synthetic = false; svc_fwd_req.gr_bridge_done = false; svc_fwd_req.guest = svc_fwd_cand.valid && gsp_phys_guest_mem_enabled(); @@ -45249,6 +45661,24 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu) int i, k, n = 0, n_gr = 0; bool stalled = false; + /* + * r707e: every-pass candidate verify with the last-good ring pair. + * Cheap (<=16 parked candidates, one walk each) and idempotent; the + * first pass after the user-VAS candidate parks registers it, so the + * client's very first push reads resolve. + * + * c741: this walk calls svc_read_ap() -> vfio_dma_rw(), which takes + * the type1 iommu mutex and may sleep. It must run unlocked: the + * original placement under svc.chan_lock produced the re-entered + * "scheduling while atomic" class (PART 43 / PART 57) and stalled + * the pump (the pending draw-window launch was never issued). + * Hoisting it here keeps the same-pass ordering (it still runs + * before the per-channel loop) without the atomic section. + */ + if (svc_lastgood_ring_pa) + svc_vas_candidates_verify(vgpu, svc_lastgood_ring_va, + svc_lastgood_ring_pa); + spin_lock_irqsave(&svc.chan_lock, flags); if (svc_rewind_pending) { svc_rewind_pending = false; @@ -45272,15 +45702,6 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu) svc_gr_setup_hold_clear(c); } } - /* - * r707e: every-pass candidate verify with the last-good ring pair. - * Cheap (<=16 parked candidates, one walk each) and idempotent; the - * first pass after the user-VAS candidate parks registers it, so the - * client's very first push reads resolve. - */ - if (svc_lastgood_ring_pa) - svc_vas_candidates_verify(vgpu, svc_lastgood_ring_va, - svc_lastgood_ring_pa); /* * r507o stream-order: walk the CE channels BEFORE the GR channels. * The client's stream order places its H2D copies before the kernel @@ -45839,6 +46260,19 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu) (void)svc_notify2d_write(vgpu, ch, true); } + /* + * X-DMA tracker fix: the USERD latch is gone, + * so the put-bounded walk below never runs and + * the client's own release push (the nvPush + * progress tracker, measured va=0x1200a0000 + * len=24 rel=0x120001000) is never decoded. + * Decode the ring head directly and apply that + * guest-authored payload; no USERD is + * fabricated and last_get/GP_GET stay put. + * Gated/rate-limited inside. + */ + svc_ddx_head_decode(vgpu, ch, rrc ? 0 : ring_pa, + rrc ? -1 : ring_ap); stalled = true; continue; } @@ -45849,6 +46283,19 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu) (void)svc_read_ap(vgpu, ch->userd_pa + SVC_USERD_GP_GET, ch->userd_as, &get, sizeof(get)); + /* + * X-DMA tracker fix: a GP_PUT reset to 0 on a + * channel that had consumed entries means the DDX + * re-created its ring. The stale USERD block can + * still read coherent, so the normal walk does not + * run for the fresh ring; decode its head directly + * (same gated/rate-limited path as the missing- + * USERD case above). + */ + if (!put && ch->last_get) + svc_ddx_head_decode(vgpu, ch, + rrc ? 0 : ring_pa, + rrc ? -1 : ring_ap); } /* @@ -49249,6 +49696,17 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu) svc.chan[k].fb_userd_scan_n = ch->fb_userd_scan_n; svc.chan[k].notify2d_va = ch->notify2d_va; + /* X-DMA tracker fix: head-decode pacing and + * the last decoded release are snapshot state + * too (the helper also stores them immediately + * on the stalled path, which skips this + * write-back). */ + svc.chan[k].ddx_head_at = ch->ddx_head_at; + svc.chan[k].ddx_cache_va = ch->ddx_cache_va; + svc.chan[k].ddx_cache_payload = + ch->ddx_cache_payload; + svc.chan[k].ddx_cache_valid = + ch->ddx_cache_valid; svc.chan[k].zero_held = ch->zero_held; svc.chan[k].userd_reg = ch->userd_reg; svc.chan[k].logged = ch->logged; @@ -49459,6 +49917,41 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu) stalled = true; } + /* + * c727 host-initiated MME pack continuation. After the channel loop (so + * a client window decoded in this pass can complete the pack first), + * emit the next golden pack part for the armed beef channel. The gates + * mirror the request path: the channel must still be in this pass's + * snapshot, no unoffered client candidate may exist for it, no hold or + * in-flight request may own the slot, and the FE-busy defer must not + * veto a load-only carrier. gsp_phys_gr_mme_carry_take() re-validates + * the live pack cursor honestly; a mismatch cancels (never fires a + * stale carrier). + */ + { + u32 carry_h = 0; + + if (gsp_phys_gr_mme_carry_peek(&carry_h)) { + int ci; + + for (ci = 0; ci < n; ci++) { + struct svc_channel *c = &local[ci]; + + if (c->h_object != carry_h || c->engine_type) + continue; + if (svc_gr_cand_unoffered_for(carry_h)) + break; + if (svc_fwd_hold.active || + test_bit(SVC_FWD_INFLIGHT, &svc_fwd_state)) + break; + if (gsp_phys_gr_mme_fe_defer_wanted(carry_h, 2)) + break; + (void)svc_gr_carrier_request(vgpu, c); + break; + } + } + } + /* * A channel still has pending entries after the pass: its pushes either * fail translation or decode to nothing (stale/wrong VA->PA pair). A -- cgit v1.2.3