From d03e69b85d4d795222fdf5eae637d7ae763c3702 Mon Sep 17 00:00:00 2001 From: Arthur Hanson Rasmusson Date: Thu, 22 Oct 2026 18:20:31 -0400 Subject: r496g register the internal VAS page directory from COPY_SERVER_RESERVED_PDES NV90F1_CTRL_CMD_VASPACE_COPY_SERVER_RESERVED_PDES (0x90f10106) is the kernel RM publishing its internal VAS page-table chain - level[0..] with phys addresses, sizes and page shifts (the handler already parsed and logged it, then discarded it). Register level[0] as the VAS root with the progress service so the walker translates every VA of that client, which is exactly what the X/GL channel needs: its pushbuffer pages and progress semaphore have no other translation source (fn-54 is external-VAS/UVM only, the rm_mem content scan finds nothing for these VAs, and the sysmem/linear window guesses are wrong for the noncontiguous surface). --- kernel/gsp_rm_emulation.c | 41 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) (limited to 'kernel/gsp_rm_emulation.c') diff --git a/kernel/gsp_rm_emulation.c b/kernel/gsp_rm_emulation.c index 63a4338..4c848b8 100644 --- a/kernel/gsp_rm_emulation.c +++ b/kernel/gsp_rm_emulation.c @@ -2456,6 +2456,7 @@ static void gsp_rm_handle_bus_get_info_v2(struct gsp_emu_context *ctx, #define GSPRM_COPY_PDES_MAX_LEVELS 6 static void gsp_rm_handle_copy_server_pdes(struct gsp_emu_context *ctx, + u32 h_object, const u8 *params, u32 params_size) { struct gsp_rm_emu *rm = ctx->rm_emu; @@ -2506,6 +2507,43 @@ static void gsp_rm_handle_copy_server_pdes(struct gsp_emu_context *ctx, "vgsp-rm: pt level[%u] phys=0x%llx size=0x%llx aperture=%u pageShift=%u", i, phys, size, aperture, page_shift); } + + /* + * r496g: this control IS the kernel RM publishing the page-table + * chain of its internal VAS (the level[0..] instances with their + * phys addresses and page shifts). Register the root with the + * progress service so the walker can translate every VA of this + * client - the X/GL channel's pushbuffer pages and its progress + * semaphore, for which no other translation source exists (the + * fn-54 SET_PAGE_DIRECTORY path is external-VAS/UVM only). The + * level values are sanity-gated; a wrong chain only costs failed + * walks. + */ + if (num_levels >= 1 && rm->pt.levels[0].phys && + rm->pt.levels[0].size >= 16 && + rm->pt.levels[0].size <= 4096 * 8) { + struct sema_vaspace_desc d; + + memset(&d, 0, sizeof(d)); + d.h_vaspace = h_object; + d.pdb = rm->pt.levels[0].phys; + d.num_entries = (u32)(rm->pt.levels[0].size / 8); + /* + * The level phys values are guest PAs on this platform + * (observed 4+ GiB, above any FB shadow); aperture 3 in the + * message does not match the walker's FB/SYS encoding, so + * classify by address: values inside the emulated VRAM are + * FB, everything else sysmem. The walker also retries the + * other aperture, so a misclassification only costs a walk. + */ + d.b_vidmem = rm->pt.levels[0].phys < + (u64)ctx->vgpu->bars[1].size; + gsp_sema_service_vaspace_add(&d); + nv_vgpu_info(ctx->vgpu, + "vgsp-rm: VAS 0x%x page directory registered from COPY_SERVER_PDES pdb=0x%llx entries=%u (%s)", + h_object, d.pdb, d.num_entries, + d.b_vidmem ? "vidmem" : "sysmem"); + } } static bool gsp_rm_alloc_interesting(u32 class_id); @@ -3219,7 +3257,8 @@ static void gsp_rm_handle_rm_control(struct gsp_emu_context *ctx, break; case 0x90f10106: /* NV90F1_CTRL_CMD_VASPACE_COPY_SERVER_RESERVED_PDES */ - gsp_rm_handle_copy_server_pdes(ctx, req_data + GSP_RM_CTRL_HDR_SIZE, + gsp_rm_handle_copy_server_pdes(ctx, req.hObject, + req_data + GSP_RM_CTRL_HDR_SIZE, req.paramsSize); out_status = 0; out_params_size = 0; -- cgit v1.2.3