[PATCH v3 4/6] arm: snapdragon: Disable MMU early before U-Boot reset vector

Balaji Selvanathan balaji.selvanathan at oss.qualcomm.com
Tue Jun 16 11:22:54 CEST 2026


When U-Boot is loaded by XBL in snagboot mode, XBL leaves the MMU
enabled with its own page tables. This causes stale TLB entries and
incorrect memory mappings when U-Boot initializes its own MMU.

Disable the MMU and invalidate TLBs at the earliest entry point,
before branching to the reset vector, handling EL1, EL2, and EL3.
This ensures a clean MMU state for U-Boot initialization.

The changes in this patch are based on:
https://lore.kernel.org/all/20260508-qcom_spl-v7-4-7d0e22aaaa8f@seznam.cz/
https://lore.kernel.org/u-boot/20260515130934.388894-1-aswin.murugan@oss.qualcomm.com/

Signed-off-by: Balaji Selvanathan <balaji.selvanathan at oss.qualcomm.com>
---
Changes in v3:
- Brought the MMU disable logic under CONFIG_QCOM_SNAGBOOT_SUPPORT
  ifdef condition
- Moved the MMU disable codes to a new seperate file

Changes in v2:
- Newly introduced in v2
---
 arch/arm/mach-snapdragon/include/mach/boot0.h      |  2 +
 .../mach-snapdragon/include/mach/snagboot_boot0.h  | 53 ++++++++++++++++++++++
 2 files changed, 55 insertions(+)

diff --git a/arch/arm/mach-snapdragon/include/mach/boot0.h b/arch/arm/mach-snapdragon/include/mach/boot0.h
index 032a9fbdb12..60ad15dba57 100644
--- a/arch/arm/mach-snapdragon/include/mach/boot0.h
+++ b/arch/arm/mach-snapdragon/include/mach/boot0.h
@@ -7,6 +7,8 @@
 #include "msm8916_boot0.h"
 #elif defined(CONFIG_QCOM_EL2_GUNYAH_EXIT_SUPPORT)
 #include "gunyah_exit_boot0.h"
+#elif defined(CONFIG_QCOM_SNAGBOOT_SUPPORT)
+#include "snagboot_boot0.h"
 #else
 	b	reset
 #endif
diff --git a/arch/arm/mach-snapdragon/include/mach/snagboot_boot0.h b/arch/arm/mach-snapdragon/include/mach/snagboot_boot0.h
new file mode 100644
index 00000000000..fb146384cba
--- /dev/null
+++ b/arch/arm/mach-snapdragon/include/mach/snagboot_boot0.h
@@ -0,0 +1,53 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Early MMU Disable for Snagboot Mode
+ *
+ * Disable MMU at the earliest possible point. This must be done before
+ * any other U-Boot code executes. Handle all exception levels (EL1, EL2, EL3).
+ *
+ * After disabling MMU, invalidate TLB to clear any stale entries that might
+ * cause issues when MMU is re-enabled later.
+ */
+
+	mrs	x0, CurrentEL
+	cmp	x0, #(3 << 2)	/* EL3? */
+	b.eq	disable_mmu_el3
+	cmp	x0, #(2 << 2)	/* EL2? */
+	b.eq	disable_mmu_el2
+
+	/* EL1 */
+	cmp	x0, #(1 << 2)	/* Confirm EL1 */
+	b.ne	reset		/* Skip MMU disable if not EL1 (e.g., EL0) */
+	mrs	x0, sctlr_el1
+	bic	x0, x0, #1	/* Clear M bit (MMU enable) */
+	msr	sctlr_el1, x0
+	isb
+	/* Invalidate TLB for EL1 */
+	tlbi	vmalle1
+	dsb	sy
+	isb
+	b	reset
+
+disable_mmu_el3:
+	mrs	x0, sctlr_el3
+	bic	x0, x0, #1	/* Clear M bit (MMU enable) */
+	bic	x0, x0, #(1 << 19)  /* Clear WXN bit (Write XOR Execute) */
+	msr	sctlr_el3, x0
+	isb
+	/* Invalidate entire TLB for all ELs */
+	tlbi	alle3
+	dsb	sy
+	isb
+	b	reset
+
+disable_mmu_el2:
+	mrs	x0, sctlr_el2
+	bic	x0, x0, #1	/* Clear M bit (MMU enable) */
+	msr	sctlr_el2, x0
+	isb
+	/* Invalidate TLB for EL2 */
+	tlbi	alle2
+	dsb	sy
+	isb
+	b	reset
+

-- 
2.34.1



More information about the U-Boot mailing list