summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/gsp_sema_service.c57
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