From 55a77193c7b3bf3bcebf7e75e79b0c615a3a2fb3 Mon Sep 17 00:00:00 2001 From: Arthur Hanson Rasmusson Date: Wed, 21 Oct 2026 20:51:27 -0400 Subject: r436 full sysmem PTE aperture/VOL matrix: gsp_phys_rmcall_pte_coh becomes a 4-mode selector (0=0xf aperture3+VOL historical, 1=0xd aperture2+VOL r431, 2=0x5 aperture2 non-volatile, 3=0x7 aperture3 non-volatile) applied consistently to the leaf PTE and the single PDE (bit0 = IS_PDE there), so the r431 finding (aperture 2 with VOL still 1 is a pair the reference RM never emits) can be A/B'd against the consistent encodings --- kernel/gsp_phys_booter.c | 73 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 49 insertions(+), 24 deletions(-) (limited to 'kernel/gsp_phys_booter.c') diff --git a/kernel/gsp_phys_booter.c b/kernel/gsp_phys_booter.c index 1b8deae..b19fa0d 100644 --- a/kernel/gsp_phys_booter.c +++ b/kernel/gsp_phys_booter.c @@ -9626,41 +9626,66 @@ static int gsp_phys_rmcall_golden_replay(void __iomem *bar0) * (swref/published/pascal/gp100/dev_mmu.h:97-119,157; * uvm_pascal_mmu.c:64-141,235-303). */ -static u64 gsp_phys_rmcall_pde(u64 pa) -{ - return 0xeull | ((pa >> 12) << 8); -} - /* - * r431 COHERENCY ROOT-CAUSE CANDIDATE: the leaf-PTE aperture for every host - * page this backend maps (the ladder windows, the win0 shadow pool, the + * r431/r436 COHERENCY ROOT-CAUSE CANDIDATE: the leaf-PTE aperture for every + * host page this backend maps (the ladder windows, the win0 shadow pool, the * bounce/data regions, the release/scratch shadows) was hardcoded to - * aperture 3 = SYSTEM_NON_COHERENT_MEMORY. The reference RM picks the - * aperture from the allocation's CPU cache attribute - * (fabric_vaspace.c:1123-1134): NV_MEMORY_CACHED -> SYSTEM_COHERENT (2), - * otherwise NON_COHERENT (3). Every page here is dma_alloc_coherent (CPU - * cached/coherent by construction), so 3 is wrong: the GPU's L2 does not - * snoop the CPU, which makes the engine's stores linger in L2 (the host's - * retire scan reads stale memory = the "no-execute wedge") and the host's - * re-staged copy-in content invisible to the engine (the retries re-read - * stale lines). gsp_phys_rmcall_pte_coh selects aperture 2 (default 1) for - * a one-flag A/B against the historical 3 (0); the PTEs are planted before - * the engine's first fetch, so the flag is boot-time only. - */ -static bool gsp_phys_rmcall_pte_coh_param; + * aperture 3 = SYSTEM_NON_COHERENT_MEMORY. The reference RM derives the + * pair from the allocation's CPU cache attribute (fabric_vaspace.c:1123-1134 + * for the aperture, mem_desc.c memdescGetVolatility for VOL: NV_MEMORY_CACHED + * -> SYSTEM_COHERENT (2) + volatile FALSE, NV_MEMORY_UNCACHED -> NON_COHERENT + * (3) + volatile TRUE). The r431 experiment used aperture 2 with VOL still 1 + * (0xd) - a pair the reference RM never produces - and it made the engine's + * truncated writes visible sooner but worsened the wedge on a fresh boot. + * r436 turns the knob into the full 2x2 matrix so each consistent encoding + * can be A/B'd: + * 0 = aperture 3 + VOL 1 (0xf) - historical, NV_MEMORY_UNCACHED + * 1 = aperture 2 + VOL 1 (0xd) - r431 experiment (inconsistent pair) + * 2 = aperture 2 + VOL 0 (0x5) - NV_MEMORY_CACHED (coherent, non-volatile) + * 3 = aperture 3 + VOL 0 (0x7) - non-coherent, non-volatile + * The PTEs are planted before the engine's first fetch, so the flag is + * boot-time only. + */ +static int gsp_phys_rmcall_pte_coh_param; module_param_named(gsp_phys_rmcall_pte_coh, gsp_phys_rmcall_pte_coh_param, - bool, 0444); + int, 0444); MODULE_PARM_DESC(gsp_phys_rmcall_pte_coh, - "r431: sysmem leaf-PTE aperture: 1 = SYSTEM_COHERENT (correct for dma_alloc_coherent host pages), 0 = SYSTEM_NON_COHERENT (historical)"); + "r436: sysmem leaf-PTE aperture/VOL mode: 0=0xf (aperture3+VOL, historical), 1=0xd (aperture2+VOL, r431), 2=0x5 (aperture2, non-volatile), 3=0x7 (aperture3, non-volatile)"); + +static u64 gsp_phys_rmcall_sysmem_base_low(void) +{ + switch (gsp_phys_rmcall_pte_coh_param) { + case 1: + return 0xdull; /* aperture 2, VOL 1 */ + case 2: + return 0x5ull; /* aperture 2, VOL 0 */ + case 3: + return 0x7ull; /* aperture 3, VOL 0 */ + default: + return 0xfull; /* aperture 3, VOL 1 (historical) */ + } +} static u64 gsp_phys_rmcall_pte(u64 pa) { /* * Low nibble: VALID (1) | APERTURE<<1 | VOL (8). Aperture 2 = * SYSTEM_COHERENT_MEMORY -> 1|4|8 = 0xd; aperture 3 = NON_COHERENT - * -> 1|6|8 = 0xf. + * -> 1|6|8 = 0xf. r436: see gsp_phys_rmcall_pte_coh_param. */ - u64 base = gsp_phys_rmcall_pte_coh_param ? 0xdull : 0xfull; + u64 base = gsp_phys_rmcall_sysmem_base_low(); + + return base | ((pa >> 12) << 8); +} + +/* + * r436: the single PDE uses the same aperture/VOL pair as the leaf PTEs but + * with IS_PDE=0 in bit 0 (the low bit of the PTE base is VALID there), so the + * PDE base is the PTE base with bit 0 cleared: 0xe/0xc/0x4/0x6. + */ +static u64 gsp_phys_rmcall_pde(u64 pa) +{ + u64 base = gsp_phys_rmcall_sysmem_base_low() & ~1ull; return base | ((pa >> 12) << 8); } -- cgit v1.2.3