diff options
| author | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-10-22 18:09:30 -0400 |
|---|---|---|
| committer | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-10-22 18:09:30 -0400 |
| commit | f9ddd5a3004ab08feda43c3d17e674ab132969cb (patch) | |
| tree | 991b6f819e640fd5092a50e9a1520776d804d1f9 | |
| parent | 4d4bb3ca0f8c23b8a8bd9893a0f0b4ebbfddd7a8 (diff) | |
| download | open-iov-f9ddd5a3004ab08feda43c3d17e674ab132969cb.tar.gz open-iov-f9ddd5a3004ab08feda43c3d17e674ab132969cb.zip | |
r496f discover the kernel-RM client VAS page directory by verification
The X/GL channel's pushbuffer pages and progress semaphore live in a
kernel-RM internal VAS whose page directory is never published (fn 54 is
UVM/external-VAS only), so no translation source can resolve them: the
tracker push reads zeros/garbage and the driver's DMA sanity poll (which
waits on the progress-tracker semaphore the GPU writes when it consumes the
tracker push) never completes.
With the ring content-validated, try each 4 KB page of the vidmem shadow as
a walk root and register the first whose walk reproduces the ring
VA -> ring PA translation. The walker then resolves every other VA of the
same client - pushbuffer pages, the tracker push, the progress semaphore.
| -rw-r--r-- | kernel/gsp_sema_service.c | 57 |
1 files changed, 57 insertions, 0 deletions
diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c index d20ad92..52e921c 100644 --- a/kernel/gsp_sema_service.c +++ b/kernel/gsp_sema_service.c @@ -14237,6 +14237,54 @@ static bool svc_gr_ram_ring_scan(struct nv_vgpu_device *vgpu, return false; } +/* + * r496f: discover a kernel-RM client VAS's page directory in the emulated + * VRAM by verification. The CPU RM builds internal-VAS page tables in + * vidmem and never publishes them (SET_PAGE_DIRECTORY is an externally + * owned / UVM-only RPC), so the pushbuffer pages and the progress + * semaphore of an X/GL channel cannot be translated from any existing + * source. Try each 4 KB page as the walk root and accept the first whose + * walk reproduces the ring VA -> ring PA pair we already validated by + * content; registering it with the VAS table makes every other VA of the + * same client resolvable through the existing walker. Bounded to the + * vidmem shadow; verified, so a wrong candidate cannot be registered. + */ +static void svc_xvas_pdb_discover(struct nv_vgpu_device *vgpu, u64 ring_va, + u64 ring_pa) +{ + static const u32 ent_tab[] = { 4, 8, 16, 32, 64, 2, 128, 256, 512 }; + u64 lim = min_t(u64, svc_fb_shadow_size(vgpu), 0x20000000ULL); + u64 off; + unsigned int ei; + + if (!vgpu->bars[1].vaddr || !lim) + return; + for (off = 0; off + 0x1000 <= lim; off += 0x1000) { + for (ei = 0; ei < ARRAY_SIZE(ent_tab); ei++) { + u64 pa = 0; + int ap = 0; + + if (!svc_gmmu_walk(vgpu, off, ent_tab[ei], + ring_va & ~0xfffULL, + SVC_APERTURE_FB, &pa, &ap, false) && + (pa & ~0xfffULL) == (ring_pa & ~0xfffULL)) { + struct sema_vaspace_desc d; + + memset(&d, 0, sizeof(d)); + d.h_vaspace = 0x5a5a0000u | + (u32)(ring_va >> 20); + d.pdb = off; + d.num_entries = ent_tab[ei]; + d.b_vidmem = true; + gsp_sema_service_vaspace_add(&d); + pr_info("sema-chan: client VAS page directory discovered pdb=0x%llx entries=%u (ring VA 0x%llx -> pa 0x%llx verified; the client's other VAs are now walkable)\n", + off, ent_tab[ei], ring_va, ring_pa); + return; + } + } + } +} + static void svc_gr_ring_autopin(struct nv_vgpu_device *vgpu, struct svc_channel *ch) { @@ -14589,6 +14637,15 @@ static void svc_gr_ring_autopin(struct nv_vgpu_device *vgpu, set_bit(ch->gr_index, &svc_gr_ring_done); svc_ring_n++; /* + * r496f: with the ring content-validated, discover the + * client VAS's page directory in vidmem so the + * channel's other VAs (pushbuffer pages, the progress + * semaphore the driver polls) resolve through the + * walker. Runs before the pins below matter and only + * once per channel (the bitmap is set). + */ + svc_xvas_pdb_discover(vgpu, ch->gpfifo_va, hit_pa); + /* * Persist the latch immediately: a later stalled * path in this pass may `continue` past the * end-of-pass write-back, and the next pass's |
