summaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-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);
}