diff options
| author | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-10-05 19:53:09 -0400 |
|---|---|---|
| committer | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-10-05 19:53:09 -0400 |
| commit | db7774c297ffd30db7a88ebddcf5d0a2d12c5f33 (patch) | |
| tree | aa1d16e1f516d8a819ae13fd5451f62418d71cb5 /kernel | |
| parent | 777b962455c9e6e51529a5f056e530a42fc1bd05 (diff) | |
| download | open-iov-db7774c297ffd30db7a88ebddcf5d0a2d12c5f33.tar.gz open-iov-db7774c297ffd30db7a88ebddcf5d0a2d12c5f33.zip | |
vgsp: golden9g - fabricated golden-VAS page-table levels + walker ctx window
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/gsp_phys_booter.c | 185 |
1 files changed, 124 insertions, 61 deletions
diff --git a/kernel/gsp_phys_booter.c b/kernel/gsp_phys_booter.c index f7cb150..c7abdaf 100644 --- a/kernel/gsp_phys_booter.c +++ b/kernel/gsp_phys_booter.c @@ -924,6 +924,15 @@ enum gsp_phys_rmcall_buf { GSP_PHYS_RMCALL_BUF_GUEST_PT13, GSP_PHYS_RMCALL_BUF_GUEST_PT14, GSP_PHYS_RMCALL_BUF_GUEST_PT15, + /* + * Golden9g: the three client page-table levels the real golden VAS + * hands to the server with VASPACE_COPY_SERVER_RESERVED_PDES + * (0x90f10106): PD2 (0x2f, size 0x20), PD1 (0x26) and PD0 (0x1d), + * chained 0 -> 1 -> 2 with the proven GP10X sysmem PDEs. + */ + GSP_PHYS_RMCALL_BUF_GOLDEN_PT0, + GSP_PHYS_RMCALL_BUF_GOLDEN_PT1, + GSP_PHYS_RMCALL_BUF_GOLDEN_PT2, GSP_PHYS_RMCALL_BUF_COUNT }; @@ -6646,6 +6655,7 @@ static int gsp_phys_rmcall_control(void __iomem *bar0, u32 h_object, u32 cmd, u32 *out_rpc_result, u32 *out_status, const char *what); static void gsp_phys_rmcall_pdb_build(void); +static u64 gsp_phys_rmcall_pde(u64 pa); /* * Shared-management VAS: install the ladder's page-table window through the @@ -7795,44 +7805,138 @@ static void gsp_phys_rmcall_golden_fail(const char *step, u32 handle, /* * Mode-25 VAS construct control (0x90f10106), gated by fwclient mask bit 8. - * The captured real-client control copied three server-RM-internal page-table - * levels; the ladder has no safe source for those PAs, so the only form this - * path can send is the zero-level no-op range (numLevelsToCopy=0) and it does - * so only when the gate is set. With the default mask the control is skipped - * and the deviation is logged; this sub-step still needs a live bisection - * (report open item 3). + * golden9g: the real client's VAS construction (gvaspaceReserveSplitVaSpace -> + * _gvaspaceReserveVaForClientRm) allocates the three client page-table levels + * for the server range [4GB, 4.5GB] and hands their PAs to the server with + * this control; the server mirrors them with mmuWalkModifyLevelInstance. The + * ladder now fabricates the identical chain in host sysmem (pageShifts + * 0x2f/0x26/0x1d, sizes 0x20/0x1000/0x1000, aperture SYS_COH) with the proven + * GP10X sysmem PDEs, so the golden VAS has the same server-side walker state + * as the real client's. Set gsp_phys_rmcall_fwclient_mask bit 8 (0x100) to + * send it; without the bit the control is skipped and the deviation logged. */ static int gsp_phys_rmcall_golden9_vas_control(void __iomem *bar0) { struct gsp_phys_rmcall_vas_copy_pdes_params *p; + u64 pa0, pa1, pa2; u32 rpc_result = 0, status = 0; int ret; if (!(gsp_phys_rmcall_fwclient_mask_value() & GSP_PHYS_RMCALL_GOLDEN9_MASK_VAS_COPY_PDES)) { - pr_info("vgsp-boot: rm-call: GOLDEN9 VAS COPY_SERVER_RESERVED_PDES (0x90f10106) skipped: the captured three level PAs are server-RM-internal and the ladder has no safe source (uncertain, report open item 3); set gsp_phys_rmcall_fwclient_mask bit 8 (0x%x) to send the zero-level no-op-range form for bisection\n", + pr_info("vgsp-boot: rm-call: GOLDEN9 VAS COPY_SERVER_RESERVED_PDES (0x90f10106) skipped (set gsp_phys_rmcall_fwclient_mask bit 8 (0x%x) to send the fabricated three-level chain)\n", GSP_PHYS_RMCALL_GOLDEN9_MASK_VAS_COPY_PDES); return 0; } + /* Build the client page-table chain: PT0(PD2[0]) -> PT1(PD1[0]) -> PT2(PD0). */ + gsp_phys_chunk_zero( + &boot_stage.rmcall_chunks[GSP_PHYS_RMCALL_BUF_GOLDEN_PT0]); + gsp_phys_chunk_zero( + &boot_stage.rmcall_chunks[GSP_PHYS_RMCALL_BUF_GOLDEN_PT1]); + gsp_phys_chunk_zero( + &boot_stage.rmcall_chunks[GSP_PHYS_RMCALL_BUF_GOLDEN_PT2]); + pa0 = (u64)gsp_phys_chunk_page_dma( + &boot_stage.rmcall_chunks[GSP_PHYS_RMCALL_BUF_GOLDEN_PT0], 0); + pa1 = (u64)gsp_phys_chunk_page_dma( + &boot_stage.rmcall_chunks[GSP_PHYS_RMCALL_BUF_GOLDEN_PT1], 0); + pa2 = (u64)gsp_phys_chunk_page_dma( + &boot_stage.rmcall_chunks[GSP_PHYS_RMCALL_BUF_GOLDEN_PT2], 0); + put_unaligned_le64(gsp_phys_rmcall_pde(pa1), + (u8 *)gsp_phys_chunk_page_va( + &boot_stage.rmcall_chunks[GSP_PHYS_RMCALL_BUF_GOLDEN_PT0], 0)); + put_unaligned_le64(gsp_phys_rmcall_pde(pa2), + (u8 *)gsp_phys_chunk_page_va( + &boot_stage.rmcall_chunks[GSP_PHYS_RMCALL_BUF_GOLDEN_PT1], 0)); + p = kvzalloc(sizeof(*p), GFP_KERNEL); if (!p) return -ENOMEM; p->page_size = cpu_to_le64(1ULL << 29); /* GMMU_PD1_VADDR_BIT_LO */ + p->virt_addr_lo = cpu_to_le64(0x100000000ULL); /* SPLIT_VAS_SERVER_RM_MANAGED_VA_START */ p->virt_addr_hi = cpu_to_le64(0x11fffffffULL); - p->num_levels_to_copy = cpu_to_le32(0); + p->num_levels_to_copy = cpu_to_le32(3); + p->levels[0].phys_addr = cpu_to_le64(pa0); + p->levels[0].size = cpu_to_le64(0x20); + p->levels[0].aperture = cpu_to_le32(4); /* GMMU_APERTURE_SYS_COH */ + p->levels[0].page_shift = cpu_to_le32(0x2f); + p->levels[1].phys_addr = cpu_to_le64(pa1); + p->levels[1].size = cpu_to_le64(0x1000); + p->levels[1].aperture = cpu_to_le32(4); + p->levels[1].page_shift = cpu_to_le32(0x26); + p->levels[2].phys_addr = cpu_to_le64(pa2); + p->levels[2].size = cpu_to_le64(0x1000); + p->levels[2].aperture = cpu_to_le32(4); + p->levels[2].page_shift = cpu_to_le32(0x1d); /* The captured RPC targets the VAS itself (hObject=0xbaba0042). */ ret = gsp_phys_rmcall_control(bar0, GSP_PHYS_RMCALL_HANDLE_GOLDEN_VAS, GSP_PHYS_RMCALL_CTRL_VASPACE_COPY_SERVER_RESERVED_PDES, p, sizeof(*p), 24, NULL, 0, &rpc_result, &status, - "VASPACE_COPY_SERVER_RESERVED_PDES (no-op range, gated)"); - pr_info("vgsp-boot: rm-call: GOLDEN9 VAS COPY_SERVER_RESERVED_PDES: no-op range numLevels=0 pageSize=0x20000000 virtAddrHi=0x11fffffff status=0x%x rpc_result=0x%x ret=%d\n", - status, rpc_result, ret); + "VASPACE_COPY_SERVER_RESERVED_PDES (3 fabricated levels)"); + pr_info("vgsp-boot: rm-call: GOLDEN9G VAS COPY_SERVER_RESERVED_PDES: numLevels=3 pageSize=0x20000000 range=[0x%llx,0x%llx] levels={0x%llx/0x20/0x2f, 0x%llx/0x1000/0x26, 0x%llx/0x1000/0x1d} status=0x%x rpc_result=0x%x ret=%d\n", + le64_to_cpu(p->virt_addr_lo), le64_to_cpu(p->virt_addr_hi), + pa0, pa1, pa2, status, rpc_result, ret); kvfree(p); return ret; } +/* + * golden9g: install the golden VAS context window (VA_GR_CTX >> 21) in the + * server's own MMU walker via NV0080_CTRL_CMD_DMA_UPDATE_PDE_2, the supported + * client map path for a non-external VAS. The PT pages hold the golden9e + * VIDMEM leaf PTEs (built by gsp_phys_rmcall_pdb_build) for the FBMEM + * MAIN/PATCH/FECS/PRIV/UNR buffers, so the GR engine can fetch the promoted + * context VAs through the golden VAS exactly as it did through the ladder + * VAS's raw PDB. Gated by fwclient mask bit 8 together with the copy control. + */ +static int gsp_phys_rmcall_golden9_vas_windows(void __iomem *bar0) +{ + struct gsp_phys_rmcall_update_pde2_params p; + u32 i; + int ret; + + if (!(gsp_phys_rmcall_fwclient_mask_value() & + GSP_PHYS_RMCALL_GOLDEN9_MASK_VAS_COPY_PDES)) + return 0; + if (!boot_stage.rmcall_ctx_pt_pages) { + pr_err("vgsp-boot: rm-call: GOLDEN9G ctx window install: no ctx PT pages built; aborting the golden replay with no retry\n"); + return -EINVAL; + } + for (i = 0; i < boot_stage.rmcall_ctx_pt_pages; i++) { + u32 ctx_index = (u32)((GSP_PHYS_RMCALL_VA_GR_CTX >> 21) + i); + u64 ctx_pt_pa = (u64)gsp_phys_chunk_page_dma( + &boot_stage.rmcall_ctx_pt[i], 0); + u32 rpc_result = 0, status = 0; + + memset(&p, 0, sizeof(p)); + p.pde_index = cpu_to_le32(ctx_index); + p.flags = cpu_to_le32(GSP_PHYS_RMCALL_PDE2_FLAG_FLUSH); + p.pt[0].phys_addr = cpu_to_le64(ctx_pt_pa); + p.pt[0].aperture = + cpu_to_le32(GSP_PHYS_RMCALL_PDE2_APERTURE_SYS_COH); + p.pt[1].aperture = + cpu_to_le32(GSP_PHYS_RMCALL_PDE2_APERTURE_INVALID); + p.h_va_space = cpu_to_le32(GSP_PHYS_RMCALL_HANDLE_GOLDEN_VAS); + p.sub_device_id = 0; + ret = gsp_phys_rmcall_control(bar0, + boot_stage.rmcall_device, + GSP_PHYS_RMCALL_CTRL_DMA_UPDATE_PDE_2, + &p, sizeof(p), sizeof(p), &p, sizeof(p), + &rpc_result, &status, + "DMA_UPDATE_PDE_2 (golden9g golden VAS ctx window)"); + if (ret) { + pr_err("vgsp-boot: rm-call: GOLDEN9G golden VAS ctx window %u rejected: status=0x%x rpc_result=0x%x ret=%d; aborting the golden replay with no retry\n", + ctx_index, status, rpc_result, ret); + return ret; + } + pr_info("vgsp-boot: rm-call: GOLDEN9G golden VAS ctx window accepted: pdeIndex=%u ptPa=0x%llx hVas=0x%x status=0x%x\n", + ctx_index, ctx_pt_pa, + GSP_PHYS_RMCALL_HANDLE_GOLDEN_VAS, status); + } + return 0; +} + static int gsp_phys_rmcall_golden9_promote(void __iomem *bar0); static int gsp_phys_rmcall_golden_mem(void __iomem *bar0, @@ -7854,45 +7958,6 @@ static int gsp_phys_rmcall_golden_mem(void __iomem *bar0, return ret; } -/* - * Golden9f: install the client PDB hierarchy on the golden VAS. The golden - * VAS is PTETABLE_HEAP_MANAGED (client-owned page tables on this config, no - * split range), so the supported client mechanism is - * DMA_SET_PAGE_DIRECTORY with the ladder's root PDB (the same tree the - * ladder VAS uses; its window maps the promoted ctx VAs). Without this the - * channel alloc's pVAS validation rejects the empty golden VAS (the - * golden9a/b NOCAT chain 0x51a8f10/0x52008f4/0x51a89a4). - */ -static int gsp_phys_rmcall_golden9_vas_pdb(void __iomem *bar0) -{ - struct gsp_phys_rmcall_pdb_params pdb; - u32 pdb_rpc = 0; - int ret; - - memset(&pdb, 0, sizeof(pdb)); - pdb.phys_address = cpu_to_le64((u64)gsp_phys_chunk_page_dma( - &boot_stage.rmcall_chunks[GSP_PHYS_RMCALL_BUF_VASPDB], 0)); - pdb.num_entries = cpu_to_le32(GSP_PHYS_RMCALL_PDB_NUM_ENTRIES); - pdb.flags = cpu_to_le32(GSP_PHYS_RMCALL_PDB_FLAG_APERTURE_SYSMEM_NONCOH | - GSP_PHYS_RMCALL_PDB_FLAG_ALL_CHANNELS); - pdb.h_va_space = cpu_to_le32(GSP_PHYS_RMCALL_HANDLE_GOLDEN_VAS); - pdb.ch_id = 0; - pdb.sub_device_id = cpu_to_le32(GSP_PHYS_RMCALL_PDB_SUBDEVICE_ID); - pdb.pasid = 0; - ret = gsp_phys_rmcall_control(bar0, boot_stage.rmcall_device, - GSP_PHYS_RMCALL_CTRL_DMA_SET_PAGE_DIRECTORY, - &pdb, sizeof(pdb), 16, NULL, 0, - &pdb_rpc, NULL, - "DMA_SET_PAGE_DIRECTORY (golden9f golden VAS)"); - pr_info("vgsp-boot: rm-call: GOLDEN9F golden VAS PDB install: hVas=0x%x root=0x%llx numEntries=%u ret=%d rpc_result=0x%x\n", - GSP_PHYS_RMCALL_HANDLE_GOLDEN_VAS, - (u64)gsp_phys_chunk_page_dma( - &boot_stage.rmcall_chunks[GSP_PHYS_RMCALL_BUF_VASPDB], - 0), - le32_to_cpu(pdb.num_entries), ret, pdb_rpc); - return ret; -} - static int gsp_phys_rmcall_golden_replay(void __iomem *bar0) { struct gsp_phys_rmcall_vas_params va; @@ -7926,9 +7991,11 @@ static int gsp_phys_rmcall_golden_replay(void __iomem *bar0) } /* - * Mode 25: the captured VAS construct control follows the VAS alloc. - * It is gated off by default and aborts the replay only when the - * operator enabled the gate and the server rejected it. + * Mode 25: the captured VAS construct control follows the VAS alloc, + * then golden9g installs the context window in the golden VAS's + * server walker. Both are gated off by default (fwclient mask bit 8) + * and abort the replay only when the gate is enabled and the server + * rejects a step. */ if (boot_stage.rmcall_gr_promote == GSP_PHYS_RMCALL_GR_PROMOTE_GOLDEN9 && @@ -7939,13 +8006,9 @@ static int gsp_phys_rmcall_golden_replay(void __iomem *bar0) ret); return ret; } - /* - * Golden9f: give the golden VAS real page tables (the ladder's - * root PDB) before the channel alloc validates its pVAS. - */ - ret = gsp_phys_rmcall_golden9_vas_pdb(bar0); + ret = gsp_phys_rmcall_golden9_vas_windows(bar0); if (ret) { - pr_err("vgsp-boot: rm-call: GOLDEN9F golden VAS PDB install failed (%d); the golden replay aborts with no retry\n", + pr_err("vgsp-boot: rm-call: GOLDEN9G golden VAS ctx window install failed (%d); the golden replay aborts with no retry\n", ret); return ret; } @@ -15152,8 +15215,8 @@ static_assert(offsetof(struct gsp_phys_rmcall_channel_params, process_id) == 296 "NV_CHANNEL_ALLOC_PARAMS.ProcessID must be at offset 296"); static_assert(offsetof(struct gsp_phys_rmcall_channel_params, tpc_config_id) == 360, "NV_CHANNEL_ALLOC_PARAMS.tpcConfigID must be at offset 360"); -static_assert(GSP_PHYS_RMCALL_BUF_COUNT == 30, - "the rm-call ladder registers exactly thirty DMA buffers (14 ladder + 16 single-page guest scratch PTs)"); +static_assert(GSP_PHYS_RMCALL_BUF_COUNT == 33, + "the rm-call ladder registers exactly thirty-three DMA buffers (14 ladder + 16 single-page guest scratch PTs + 3 golden9g VAS levels)"); static_assert((GSP_PHYS_RMCALL_HANDLE_MEM_BASE + (GSP_PHYS_RMCALL_BUF_COUNT - 1) * GSP_PHYS_RMCALL_HANDLE_MEM_STRIDE) < 0xcaf80000u, |
