summaryrefslogtreecommitdiffstats
path: root/kernel/gsp_phys_booter.c
diff options
context:
space:
mode:
authorArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-21 20:51:27 -0400
committerArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-21 20:51:27 -0400
commit55a77193c7b3bf3bcebf7e75e79b0c615a3a2fb3 (patch)
treea6a6ff6f2a06418106763a3214ef747ff12bd476 /kernel/gsp_phys_booter.c
parent4925432a14bfab4e678b58fd6aa0236a3e229af5 (diff)
downloadopen-iov-55a77193c7b3bf3bcebf7e75e79b0c615a3a2fb3.tar.gz
open-iov-55a77193c7b3bf3bcebf7e75e79b0c615a3a2fb3.zip
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
Diffstat (limited to 'kernel/gsp_phys_booter.c')
-rw-r--r--kernel/gsp_phys_booter.c73
1 files changed, 49 insertions, 24 deletions
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);
}