From 6fa955affe6ebca807737fcf1e51673e3859aa47 Mon Sep 17 00:00:00 2001 From: Arthur Hanson Rasmusson Date: Wed, 7 Oct 2026 14:31:55 -0400 Subject: vgsp: m101 - route guest data pages through the server walker (Tier-1 map_va_locked) The scratch-window comment is decisive: on the shared-management VAS the client PD0 entries built by pdb_build are NOT preserved by the server's root migration, so every engine-visible mapping must be installed through DMA_UPDATE_PDE_2 - the m99/m100 direct plants were invisible (same NACK with 16381 pages 'mapped'). Route each data page through gsp_phys_rmcall_gr_map_va_locked (same call the request pages use) and log the per-window acceptance/refusal (server 0x1f) so the high-VA install behavior is measured. The window pool is currently 8 windows x 32 PTEs. --- kernel/gsp_phys_booter.c | 141 ++++++++--------------------------------------- 1 file changed, 22 insertions(+), 119 deletions(-) diff --git a/kernel/gsp_phys_booter.c b/kernel/gsp_phys_booter.c index 880299c..04788d2 100644 --- a/kernel/gsp_phys_booter.c +++ b/kernel/gsp_phys_booter.c @@ -16150,125 +16150,26 @@ static void gsp_phys_rmcall_gr_gpc_mmu_init(void __iomem *bar0) * carries GENERIC_MEMORY (0x06) in KIND[63:56] like the Turing UVM/RM * mappings (PITCH does not exist on Turing). */ -static struct gsp_phys_boot_chunk *gsp_phys_rmcall_gr_data_pd1_get(u32 i2) -{ - struct gsp_phys_boot_chunk *pd2 = - &boot_stage.rmcall_chunks[GSP_PHYS_RMCALL_BUF_PD2]; - u32 k; - - for (k = 0; k < boot_stage.rmcall_gr_data_pd1_n; k++) - if (boot_stage.rmcall_gr_data_pd1_idx[k] == i2) - return &boot_stage.rmcall_gr_data_pd1[k]; - if (boot_stage.rmcall_gr_data_pd1_n >= GSP_PHYS_RMCALL_GR_DATA_PD1_MAX) - return NULL; - k = boot_stage.rmcall_gr_data_pd1_n; - if (gsp_phys_chunk_alloc(boot_stage.pdev, - &boot_stage.rmcall_gr_data_pd1[k], 1)) - return NULL; - gsp_phys_chunk_zero(&boot_stage.rmcall_gr_data_pd1[k]); - boot_stage.rmcall_gr_data_pd1_idx[k] = i2; - boot_stage.rmcall_gr_data_pd1_n++; - put_unaligned_le64(gsp_phys_rmcall_pde((u64)gsp_phys_chunk_page_dma( - &boot_stage.rmcall_gr_data_pd1[k], 0)), - (u8 *)gsp_phys_chunk_page_va(pd2, 0) + - (size_t)i2 * 8); - dma_wmb(); - pr_info("vgsp-gr: data-map PD2[%u] -> pd1 dma=0x%llx\n", i2, - (u64)gsp_phys_chunk_page_dma(&boot_stage.rmcall_gr_data_pd1[k], 0)); - return &boot_stage.rmcall_gr_data_pd1[k]; -} - -static struct gsp_phys_boot_chunk *gsp_phys_rmcall_gr_data_pd0_get(u32 i2, - u32 i1) -{ - struct gsp_phys_boot_chunk *pd1 = gsp_phys_rmcall_gr_data_pd1_get(i2); - u32 key = (i2 << 9) | i1; - u32 k; - - if (!pd1) - return NULL; - for (k = 0; k < boot_stage.rmcall_gr_data_pd0_n; k++) - if (boot_stage.rmcall_gr_data_pd0_idx[k] == key) - return &boot_stage.rmcall_gr_data_pd0[k]; - if (boot_stage.rmcall_gr_data_pd0_n >= GSP_PHYS_RMCALL_GR_DATA_PD0_MAX) - return NULL; - k = boot_stage.rmcall_gr_data_pd0_n; - if (gsp_phys_chunk_alloc(boot_stage.pdev, - &boot_stage.rmcall_gr_data_pd0[k], 1)) - return NULL; - gsp_phys_chunk_zero(&boot_stage.rmcall_gr_data_pd0[k]); - boot_stage.rmcall_gr_data_pd0_idx[k] = key; - boot_stage.rmcall_gr_data_pd0_n++; - put_unaligned_le64(gsp_phys_rmcall_pde((u64)gsp_phys_chunk_page_dma( - &boot_stage.rmcall_gr_data_pd0[k], 0)), - (u8 *)gsp_phys_chunk_page_va(pd1, 0) + - (size_t)i1 * 8); - dma_wmb(); - pr_info("vgsp-gr: data-map PD1[%u] -> pd0 dma=0x%llx (i2=%u)\n", i1, - (u64)gsp_phys_chunk_page_dma(&boot_stage.rmcall_gr_data_pd0[k], 0), - i2); - return &boot_stage.rmcall_gr_data_pd0[k]; -} - -static struct gsp_phys_boot_chunk *gsp_phys_rmcall_gr_data_pt_get(u32 i2, - u32 i1, - u32 i0) +/* + * m101: map one guest data page through the server walker (Tier-1 + * DMA_UPDATE_PDE_2), exactly like the launch request pages. On the + * shared-management VAS the client PD0 entries are not preserved by the + * server's root migration (see gsp_phys_rmcall_gr_scratch_win_install_locked), + * so the m99/m100 direct plants were invisible to the engine; every + * engine-visible mapping must be installed through DMA_UPDATE_PDE_2. The + * window pool is small (GSP_PHYS_RMCALL_GR_PT_PAGES x GR_PT_ENTRIES), so the + * high-VA acceptance/refusal pattern (server 0x1f) is logged per window. + */ +static int gsp_phys_rmcall_gr_data_map(void __iomem *bar0, u64 va, u64 hpa, + u32 epoch) { - struct gsp_phys_boot_chunk *pd0 = - gsp_phys_rmcall_gr_data_pd0_get(i2, i1); - u32 key = (i2 << 18) | (i1 << 9) | i0; - u32 k; - - if (!pd0) - return NULL; - for (k = 0; k < boot_stage.rmcall_gr_data_pt_n; k++) - if (boot_stage.rmcall_gr_data_pt_idx[k] == key) - return &boot_stage.rmcall_gr_data_pt[k]; - if (boot_stage.rmcall_gr_data_pt_n >= GSP_PHYS_RMCALL_GR_DATA_PT_MAX) - return NULL; - k = boot_stage.rmcall_gr_data_pt_n; - if (gsp_phys_chunk_alloc(boot_stage.pdev, - &boot_stage.rmcall_gr_data_pt[k], 1)) - return NULL; - gsp_phys_chunk_zero(&boot_stage.rmcall_gr_data_pt[k]); - boot_stage.rmcall_gr_data_pt_idx[k] = key; - boot_stage.rmcall_gr_data_pt_n++; - /* 16 B dual PDE: big half unused, small half -> 4 KB PT. */ - put_unaligned_le64(0, - (u8 *)gsp_phys_chunk_page_va(pd0, 0) + - (size_t)i0 * 16); - put_unaligned_le64(gsp_phys_rmcall_pde((u64)gsp_phys_chunk_page_dma( - &boot_stage.rmcall_gr_data_pt[k], 0)), - (u8 *)gsp_phys_chunk_page_va(pd0, 0) + - (size_t)i0 * 16 + 8); - dma_wmb(); - pr_info("vgsp-gr: data-map PD0[%u] -> pt dma=0x%llx (i2=%u i1=%u)\n", i0, - (u64)gsp_phys_chunk_page_dma(&boot_stage.rmcall_gr_data_pt[k], 0), - i2, i1); - return &boot_stage.rmcall_gr_data_pt[k]; -} + int ret = gsp_phys_rmcall_gr_map_va_locked(bar0, va, hpa, epoch); -static int gsp_phys_rmcall_gr_data_map(u64 va, u64 hpa) -{ - struct gsp_phys_boot_chunk *pt; - u32 r = (u32)((va >> 47) & 0x1u); - u32 i2 = (u32)((va >> 38) & 0x1ffu); - u32 i1 = (u32)((va >> 29) & 0x1ffu); - u32 i0 = (u32)((va >> 21) & 0x1ffu); - u32 ip = (u32)((va >> 12) & 0x1ffu); - u64 pte; - - if (r != 0) - return -ERANGE; /* root[0] only; the demo VAs are < 2^47 */ - pt = gsp_phys_rmcall_gr_data_pt_get(i2, i1, i0); - if (!pt) - return -ENOSPC; - pte = gsp_phys_rmcall_pte(hpa); - if (gsp_phys_rmcall_gr_pte_kind_value()) - pte |= (u64)gsp_phys_rmcall_gr_pte_kind_value() << 56; - put_unaligned_le64(pte, (u8 *)gsp_phys_chunk_page_va(pt, 0) + - (size_t)ip * 8); - dma_wmb(); + if (ret) { + pr_err_ratelimited("vgsp-gr: data Tier-1 map refused va=0x%llx hpa=0x%llx ret=%d\n", + va, hpa, ret); + return ret; + } boot_stage.rmcall_gr_data_pages++; return 0; } @@ -16990,8 +16891,10 @@ gr_page_unmapped: u32 dmapped = 0, dfailed = 0, di; for (di = 0; di < req->n_data; di++) { - if (gsp_phys_rmcall_gr_data_map(req->data[di].va, - req->data[di].hpa)) + if (gsp_phys_rmcall_gr_data_map(bar0, + req->data[di].va, + req->data[di].hpa, + boot_stage.rmcall_gr_submit_epoch)) dfailed++; else dmapped++; -- cgit v1.2.3