[U-Boot] [RFC PATCH] armv8: Extend modification of MMU tables

York Sun york.sun at nxp.com
Fri Feb 3 22:24:25 UTC 2017


Device memory needs to be set along with PXN and UNX bits. Normal memory
must clear these bits. To support modification of PXN, UXN bits, extend
existing function mmu_set_region_dcache_behaviour() to accept attributes
directly. Also fix parsing d-cache option by removing extra shifting.

Signed-off-by: York Sun <york.sun at nxp.com>
CC: Alexander Graf <agraf at suse.de>
---
Looks like original function mmu_set_region_dcache_behaviour() was written
to support changing d-cache option. However the PMD_ATTRINDX(option) shifts
it further higher. Maybe this function wasn't really used for ARMv8.
I have a need to update existing MMU table with a little bit more than
d-cache options. With a recent debug on memory barrier, it came to my
attention that code should run on "normal" memory, while "device" memory
should have PXN and UXN bits set. A new function mmu_set_region_attr() is
hence introduced and mmu_set_region_dcache_behaviour() becomes a wrapper.

BTW, if we don't plan to use "read_start" and "real_size" variables, they
should be removed.

 arch/arm/cpu/armv8/cache_v8.c    | 28 +++++++++++++++++++---------
 arch/arm/include/asm/armv8/mmu.h |  1 +
 arch/arm/include/asm/system.h    |  1 +
 3 files changed, 21 insertions(+), 9 deletions(-)

diff --git a/arch/arm/cpu/armv8/cache_v8.c b/arch/arm/cpu/armv8/cache_v8.c
index afa76c1..3b2f3f8 100644
--- a/arch/arm/cpu/armv8/cache_v8.c
+++ b/arch/arm/cpu/armv8/cache_v8.c
@@ -509,8 +509,8 @@ static u64 set_one_region(u64 start, u64 size, u64 attrs, int level)
 
 	/* Can we can just modify the current level block PTE? */
 	if (is_aligned(start, size, levelsize)) {
-		*pte &= ~PMD_ATTRINDX_MASK;
-		*pte |= attrs;
+		*pte &= ~PMD_ATTRMASK;
+		*pte |= attrs & PMD_ATTRMASK;
 		debug("Set attrs=%llx pte=%p level=%d\n", attrs, pte, level);
 
 		return levelsize;
@@ -532,13 +532,8 @@ static u64 set_one_region(u64 start, u64 size, u64 attrs, int level)
 	return 0;
 }
 
-void mmu_set_region_dcache_behaviour(phys_addr_t start, size_t size,
-				     enum dcache_option option)
+void mmu_set_region_attr(phys_addr_t start, size_t size, u64 attrs)
 {
-	u64 attrs = PMD_ATTRINDX(option);
-	u64 real_start = start;
-	u64 real_size = size;
-
 	debug("start=%lx size=%lx\n", (ulong)start, (ulong)size);
 
 	if (!gd->arch.tlb_emerg)
@@ -572,7 +567,19 @@ void mmu_set_region_dcache_behaviour(phys_addr_t start, size_t size,
 	}
 
 	/* We're done modifying page tables, switch back to our primary ones */
+	flush_dcache_range(gd->arch.tlb_addr,
+			   gd->arch.tlb_addr + gd->arch.tlb_size);
 	__asm_switch_ttbr(gd->arch.tlb_addr);
+}
+
+void mmu_set_region_dcache_behaviour(phys_addr_t start, size_t size,
+				     enum dcache_option option)
+{
+	u64 attrs = option;
+	u64 real_start = start;
+	u64 real_size = size;
+
+	mmu_set_region_attr(start, size, attrs);
 
 	/*
 	 * Make sure there's nothing stale in dcache for a region that might
@@ -580,7 +587,6 @@ void mmu_set_region_dcache_behaviour(phys_addr_t start, size_t size,
 	 */
 	flush_dcache_range(real_start, real_start + real_size);
 }
-
 #else	/* CONFIG_SYS_DCACHE_OFF */
 
 /*
@@ -613,6 +619,10 @@ int dcache_status(void)
 	return 0;
 }
 
+void mmu_set_region_attr(phys_addr_t start, size_t size, u64 attrs)
+{
+}
+
 void mmu_set_region_dcache_behaviour(phys_addr_t start, size_t size,
 				     enum dcache_option option)
 {
diff --git a/arch/arm/include/asm/armv8/mmu.h b/arch/arm/include/asm/armv8/mmu.h
index 58aecb9..c1cff23 100644
--- a/arch/arm/include/asm/armv8/mmu.h
+++ b/arch/arm/include/asm/armv8/mmu.h
@@ -86,6 +86,7 @@
  */
 #define PMD_ATTRINDX(t)		((t) << 2)
 #define PMD_ATTRINDX_MASK	(7 << 2)
+#define PMD_ATTRMASK		(PTE_BLOCK_PXN | PTE_BLOCK_UXN | PMD_ATTRINDX_MASK)
 
 /*
  * TCR flags.
diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h
index dc4c991..81709ec 100644
--- a/arch/arm/include/asm/system.h
+++ b/arch/arm/include/asm/system.h
@@ -224,6 +224,7 @@ void protect_secure_region(void);
 void smp_kick_all_cpus(void);
 
 void flush_l3_cache(void);
+void mmu_set_region_attr(phys_addr_t start, size_t size, u64 attrs);
 
 /*
  *Issue a secure monitor call in accordance with ARM "SMC Calling convention",
-- 
2.7.4



More information about the U-Boot mailing list