[PATCH v2 08/10] ARM: mmu: use reserve mem entries to modify maps

Ahmad Fatoum a.fatoum at pengutronix.de
Wed Aug 17 04:42:42 PDT 2022


From: Rouven Czerwinski <r.czerwinski at pengutronix.de>

Like done for ARM64, use the reserved memory regions marked in the SDRAM
bank to map these regions uncached and eXecute Never to avoid speculative
access into these regions from causing hard-to-debug data aborts.

Unlike with mmu_64, for CONFIG_MMU_EARLY systems, the MMU isn't turned
off before changing the page table. So what we do instead is allocating
a 16K shadow buffer and modifying that and afterwards overwriting the
active TTB with it.

We could instead use set_ttbr() to move the page table, but in interest
of minimizing chance of breaking older ARM platforms, we keep the online
changing of the entries for now.

Signed-off-by: Rouven Czerwinski <r.czerwinski at pengutronix.de>
[afa: use SDRAM regions instead of FDT reserve entries]
Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 arch/arm/cpu/mmu.c | 40 +++++++++++++++++++++++++++++-----------
 1 file changed, 29 insertions(+), 11 deletions(-)

diff --git a/arch/arm/cpu/mmu.c b/arch/arm/cpu/mmu.c
index 6388e1bf14f6..f9c629c0f19d 100644
--- a/arch/arm/cpu/mmu.c
+++ b/arch/arm/cpu/mmu.c
@@ -413,6 +413,7 @@ static void vectors_init(void)
 void __mmu_init(bool mmu_on)
 {
 	struct memory_bank *bank;
+	void *oldttb = NULL;
 
 	arm_set_cache_functions();
 
@@ -430,15 +431,17 @@ void __mmu_init(bool mmu_on)
 		pte_flags_uncached = PTE_FLAGS_UNCACHED_V4;
 	}
 
+	ttb = xmemalign(ARM_TTB_SIZE, ARM_TTB_SIZE);
+
+	/*
+	 * Early MMU code may have already enabled the MMU. We assume a
+	 * flat 1:1 section mapping in this case.
+	 */
 	if (mmu_on) {
-		/*
-		 * Early MMU code has already enabled the MMU. We assume a
-		 * flat 1:1 section mapping in this case.
-		 */
-		/* Clear unpredictable bits [13:0] */
-		ttb = (uint32_t *)(get_ttbr() & ~0x3fff);
+		oldttb = (uint32_t *)(get_ttbr() & ~0x3fff);
+		memcpy(ttb, oldttb, ARM_TTB_SIZE);
 
-		if (!request_sdram_region("ttb", (unsigned long)ttb, SZ_16K))
+		if (!request_sdram_region("ttb", (unsigned long)oldttb, SZ_16K))
 			/*
 			 * This can mean that:
 			 * - the early MMU code has put the ttb into a place
@@ -447,10 +450,8 @@ void __mmu_init(bool mmu_on)
 			 *   the ttb will get corrupted.
 			 */
 			pr_crit("Critical Error: Can't request SDRAM region for ttb at %p\n",
-					ttb);
+				oldttb);
 	} else {
-		ttb = xmemalign(ARM_TTB_SIZE, ARM_TTB_SIZE);
-
 		set_ttbr(ttb);
 
 		/* For the XN bit to take effect, we can't be using DOMAIN_MANAGER. */
@@ -468,11 +469,28 @@ void __mmu_init(bool mmu_on)
 	vectors_init();
 
 	for_each_memory_bank(bank) {
+		struct resource *rsv;
+
 		create_sections(ttb, bank->start, bank->start + bank->size - 1,
 				PMD_SECT_DEF_CACHED);
-		__mmu_cache_flush();
+
+		for_each_reserved_region(bank, rsv) {
+			create_sections(ttb, resource_first_page(rsv),
+					resource_count_pages(rsv),
+					attrs_uncached_mem());
+		}
 	}
 
+	/*
+	 * We could set_ttbr(ttb) here instead and save on the copy, but
+	 * for now we play it safe, so we don't mess with the older ARMs.
+	 */
+	if (oldttb) {
+		memcpy(oldttb, ttb, ARM_TTB_SIZE);
+		free(ttb);
+	}
+
+	__mmu_cache_flush();
 	__mmu_cache_on();
 }
 
-- 
2.30.2




More information about the barebox mailing list