diff options
| author | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-10-30 12:41:59 -0400 |
|---|---|---|
| committer | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-10-30 12:41:59 -0400 |
| commit | 0b0b86d88cd1ef499db6817e605fff888bc7a16c (patch) | |
| tree | bd185f4e6e165c20ad200b4ed1d8f89a224de52c | |
| parent | b49301684fd59bea1143e6173522e4da7cc8a09b (diff) | |
| download | open-iov-0b0b86d88cd1ef499db6817e605fff888bc7a16c.tar.gz open-iov-0b0b86d88cd1ef499db6817e605fff888bc7a16c.zip | |
vgsp: FB USERD scan time-paced (1/25ms, cap 512) + pristine fallback for ring_pa==0 - fixes fresh-boot Xorg 10s DMA-init wall (2/2 boots green, DDX channel sub=3402, TWOD fills execute) - SESSION 153 r1014-r1015
| -rw-r--r-- | kernel/gsp_sema_service.c | 114 |
1 files changed, 113 insertions, 1 deletions
diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c index 4ec75d6..bc04e25 100644 --- a/kernel/gsp_sema_service.c +++ b/kernel/gsp_sema_service.c @@ -735,6 +735,19 @@ struct svc_channel { */ u8 userd_scans; /* + * SESSION 153-CONTINUED-37: time-paced re-run state for the FB USERD + * shape scan (r496b) and its pristine-block fallback. The old + * count-only cap spent every retry within ~64 ms of registration + * (pump pass cadence), while the X driver's pushbuffer test kicks its + * first GP_PUT hundreds of ms later and its VAS registers at ~1 s - + * so on unlucky timings the budget was gone before any candidate + * existed and the 10 s DMA test read GET=0 forever ("Failed to + * initialize DMA", r1013). One scan per 25 ms up to 512 keeps the + * discovery alive across the whole client window. + */ + unsigned long fb_userd_scan_at; /* jiffies of the last scan */ + u16 fb_userd_scan_n; /* scans spent since registration */ + /* * r828: the RC watchdog's notifier VA, captured from the class2d * SET_NOTIFY_A/B methods on subchannel 3 and zeroed at the NOTIFY * (see svc_notify2d_write). Survives the pass snapshot via the @@ -18451,6 +18464,61 @@ static bool svc_gr_ram_userd_scan(struct nv_vgpu_device *vgpu, u32 *put_out, u32 *get_out); /* + * SESSION 153-CONTINUED-37: pristine-block USERD fallback for a GR channel + * whose ring does not translate yet. + * + * Measured (r1013 fresh boot): the X driver's pushbuffer-test channel + * (class 0xc46f, 8192 entries, VA 0x120090000) reports its USERD as the FB + * memdesc base 0x30000, but the guest's GPPut write lands in emulated vidmem + * at 0xa0000 - the params' base is relative to a client pool the emulation + * cannot see (same class of problem the r496b sweep solves once the ring + * resolves). The block is pristine in the test window: the only non-zero + * bytes in [0x0, 0x100) are the GP_PUT dword at +0x8c (GP_GET at +0x88 is + * still 0, because the driver zeroes it before the NOP test). When the + * channel's VAS page directory has not registered yet, the r496b sweep + * cannot run (it validates a hit by reading the ring entries the put + * claims), so this bounded shape scan keeps the discovery alive: pending + * only (get < put), pristine page, unclaimed by any other channel, then + * adopt it exactly like the ring-validated sweep does. The r496b sweep + * still runs later and may re-adopt a ring-validated block; both paths + * claim their latch, so a foreign channel cannot take it in between. + */ +static bool svc_fb_userd_pristine_scan(struct nv_vgpu_device *vgpu, + struct svc_channel *ch, u64 *off_out, + u32 *put_out, u32 *get_out) +{ + u8 *base = vgpu->bars[1].vaddr; + u64 lim, off; + + if (!base || !ch->gpfifo_entries) + return false; + lim = min_t(u64, svc_fb_shadow_size(vgpu), 0x2000000ULL); + for (off = 0; off + 0x100 <= lim; off += 0x1000) { + u32 hp, hg; + + memcpy(&hp, base + off + SVC_USERD_GP_PUT, 4); + if (!hp || hp > ch->gpfifo_entries) + continue; + memcpy(&hg, base + off + SVC_USERD_GP_GET, 4); + /* Only a posed kick (get < put) - an idle/stale block stays + * with its owner. */ + if (hg >= hp) + continue; + if (memchr_inv(base + off, 0, SVC_USERD_GP_GET) || + memchr_inv(base + off + SVC_USERD_GP_GET + 8, 0, + 0x100 - SVC_USERD_GP_GET - 8)) + continue; + if (svc_fb_claim_foreign(vgpu, ch->h_object, 0, off)) + continue; + *off_out = off; + *put_out = hp; + *get_out = hg; + return true; + } + return false; +} + +/* * Locate a channel's USERD. The allocation parameters carry an offset that is * relative to a client pool the emulation cannot see, so it is only one * candidate: for the combined GPFIFO+USERD allocations the control block sits @@ -18774,7 +18842,11 @@ static int svc_chan_userd(struct nv_vgpu_device *vgpu, struct svc_channel *ch, * bounds the channel's life. */ if (!ch->engine_type && ring_pa && - ch->userd_scans < (ring_pa ? 64u : 8u)) { + ch->fb_userd_scan_n < 512 && + (!ch->fb_userd_scan_at || + time_after_eq(jiffies, + (unsigned long)ch->fb_userd_scan_at + + msecs_to_jiffies(25)))) { u64 off, lim; u8 *base = vgpu->bars[1].vaddr; u64 best = 0, best_dist = ~0ULL; @@ -18782,6 +18854,8 @@ static int svc_chan_userd(struct nv_vgpu_device *vgpu, struct svc_channel *ch, bool best_pending = false; u32 gate_n = 0, vfail_n = 0; + ch->fb_userd_scan_at = jiffies; + ch->fb_userd_scan_n++; ch->userd_scans++; lim = min_t(u64, svc_fb_shadow_size(vgpu), 0x20000000ULL); if (base && lim) { @@ -18914,6 +18988,40 @@ static int svc_chan_userd(struct nv_vgpu_device *vgpu, struct svc_channel *ch, } } /* + * SESSION 153-CONTINUED-37: the channel's ring VA does not translate + * yet (the client's VAS page directory registers ~1 s after channel + * creation; until then svc_lookup cannot resolve it and the + * ring-validated r496b sweep above never runs). The driver's DMA + * test only needs the block it is polling: a freshly kicked pristine + * FB block (see svc_fb_userd_pristine_scan). Adopt it so the pump + * starts iterating entries as soon as the ring walk lands, inside + * the driver's 10 s window. + */ + if (!ch->engine_type && !ring_pa && + ch->fb_userd_scan_n < 512 && + (!ch->fb_userd_scan_at || + time_after_eq(jiffies, + (unsigned long)ch->fb_userd_scan_at + + msecs_to_jiffies(25)))) { + u64 off = 0; + u32 p = 0, g = 0; + + ch->fb_userd_scan_at = jiffies; + ch->fb_userd_scan_n++; + if (svc_fb_userd_pristine_scan(vgpu, ch, &off, &p, &g)) { + ch->userd_pa = off; + ch->userd_as = SVC_APERTURE_FB; + ch->userd_ok = true; + svc_fb_claim_add(ch->h_object, 0, off); + *put = p; + *get = g; + pr_info("sema-chan: GR USERD h=0x%x rank=%u found by pristine-FB scan at fb 0x%llx (put=%u get=%u; ring 0x%llx not translated yet)\n", + ch->h_object, ch->gr_index, off, p, g, + ch->gpfifo_va); + return 0; + } + } + /* * SESSION 153-CONT-34: last resort for the GL client family - retry the * registered offset as a BAR0-shadow USERD. Every other source (layout, * ring-derived, RAM scan, FB sweep) has already missed the block whose @@ -35213,6 +35321,10 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu) svc.chan[k].gr_kick_ring_reval_at = ch->gr_kick_ring_reval_at; svc.chan[k].userd_scans = ch->userd_scans; + svc.chan[k].fb_userd_scan_at = + ch->fb_userd_scan_at; + svc.chan[k].fb_userd_scan_n = + ch->fb_userd_scan_n; svc.chan[k].notify2d_va = ch->notify2d_va; svc.chan[k].zero_held = ch->zero_held; svc.chan[k].userd_reg = ch->userd_reg; |
