Skip to contentSkip to conversation

ARMv8: bug fix of mmu setup and code optimization

PATCH New fenghua at phytium.com.cn 2 participants 2 messages Jan 31, 2015 – Mar 27, 2015 Arm (32-bit)

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 ARMv8: bug fix of mmu setup and code optimization

From: David Feng <[email protected]>

1. Fix a bug of mmu_setup that variable i and j should be type long instead of int.
2. Give mmu_setup weak attribute so that other implementation can redfine it.
3. A more common set_pgtable_section().
4. Give device memory PXN and UXN attribute. CPU may speculatively prefetch instructions from device memory, but the IO subsystem of some implementation may not support this operation. The two attributes prevent this behavior.

---
 arch/arm/cpu/armv8/cache_v8.c      |   73 +++++++++++++++++++++++-------------
 arch/arm/cpu/armv8/fsl-lsch3/cpu.c |   22 +++++------
 arch/arm/include/asm/armv8/mmu.h   |   71 +++++++++++++++++++----------------
 3 files changed, 95 insertions(+), 71 deletions(-)
arch/arm/cpu/armv8/cache_v8.c +46 -27
index e4415e8..023dd23 100644
@@ -22,55 +22,74 @@ __weak void outer_cache_flush_range(unsigned long start, unsigned long end) {}
 __weak void outer_cache_inval_range(unsigned long start, unsigned long end) {}
 
 #ifndef CONFIG_SYS_DCACHE_OFF
-void set_pgtable_section(u64 *page_table, u64 index, u64 section,
-			 u64 memory_type)
-{
-	u64 value;
 
-	value = section | PMD_TYPE_SECT | PMD_SECT_AF;
-	value |= PMD_ATTRINDX(memory_type);
-	page_table[index] = value;
+/* 42 bits virtual address */
+#define VA_BITS			(42)
+
+/* 42 bits physical address */
+#define TCR_EL1_IPS_BITS	TCR_EL1_IPS_BITS_42
+#define TCR_EL2_IPS_BITS	TCR_EL2_IPS_BITS_42
+#define TCR_EL3_IPS_BITS	TCR_EL3_IPS_BITS_42
+
+/* PTWs cacheable, inner/outer WBWA and inner-shareable */
+#define TCR_FLAGS		(TCR_TG0_64K |		\
+				TCR_SHARED_INNER |	\
+				TCR_ORGN_WBWA |		\
+				TCR_IRGN_WBWA |		\
+				TCR_T0SZ(VA_BITS))
+
+void set_pgtable_section(u64 *page_table, u64 index, u64 output_address,
+			 u64 memory_type, u64 extra_flags)
+{
+	page_table[index] = output_address | PMD_TYPE_SECT | PMD_SECT_AF |
+			    PMD_SECT_SHARED_INNER | PMD_ATTRINDX(memory_type) |
+			    extra_flags;
 }
 
 /* to activate the MMU we need to set up virtual memory */
-static void mmu_setup(void)
+void __weak mmu_setup(void)
 {
-	int i, j, el;
+	int el;
+	u64 i, j, tcr;
 	bd_t *bd = gd->bd;
 	u64 *page_table = (u64 *)gd->arch.tlb_addr;
 
 	/* Setup an identity-mapping for all spaces */
 	for (i = 0; i < (PGTABLE_SIZE >> 3); i++) {
 		set_pgtable_section(page_table, i, i << SECTION_SHIFT,
-				    MT_DEVICE_NGNRNE);
+				    MT_DEVICE_NGNRNE,
+				    PMD_SECT_PXN | PMD_SECT_UXN);
+
 	}
 
-	/* Setup an identity-mapping for all RAM space */
+	/*
+	 * Setup an identity-mapping for all RAM space.
+	 * The secure or non-secure memory access make sense
+	 * when u-boot running@el3 and is mostly implementation
+	 * specific.
+	 */
 	for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
-		ulong start = bd->bi_dram[i].start;
-		ulong end = bd->bi_dram[i].start + bd->bi_dram[i].size;
+		u64 start = bd->bi_dram[i].start;
+		u64 end = bd->bi_dram[i].start + bd->bi_dram[i].size;
 		for (j = start >> SECTION_SHIFT;
 		     j < end >> SECTION_SHIFT; j++) {
 			set_pgtable_section(page_table, j, j << SECTION_SHIFT,
-					    MT_NORMAL);
+					    MT_NORMAL, PMD_SECT_NS);
 		}
 	}
 
 	/* load TTBR0 */
+	tcr = TCR_FLAGS;
 	el = current_el();
-	if (el == 1) {
-		set_ttbr_tcr_mair(el, gd->arch.tlb_addr,
-				  TCR_FLAGS | TCR_EL1_IPS_BITS,
-				  MEMORY_ATTRIBUTES);
-	} else if (el == 2) {
-		set_ttbr_tcr_mair(el, gd->arch.tlb_addr,
-				  TCR_FLAGS | TCR_EL2_IPS_BITS,
-				  MEMORY_ATTRIBUTES);
-	} else {
-		set_ttbr_tcr_mair(el, gd->arch.tlb_addr,
-				  TCR_FLAGS | TCR_EL3_IPS_BITS,
-				  MEMORY_ATTRIBUTES);
-	}
+	if (el == 1)
+		tcr |= TCR_EL1_IPS_BITS;
+	else if (el == 2)
+		tcr |= TCR_EL2_IPS_BITS;
+	else
+		tcr |= TCR_EL3_IPS_BITS;
+
+	set_ttbr_tcr_mair(el, gd->arch.tlb_addr, tcr, MEMORY_ATTRIBUTES);
+
 	/* enable the mmu */
 	set_sctlr(get_sctlr() | CR_M);
 }
arch/arm/cpu/armv8/fsl-lsch3/cpu.c +11 -11
index 1f36f7e..bcd2cf2 100644
@@ -82,11 +82,11 @@ static inline void early_mmu_setup(void)
 	section_l2 = 0;
 	for (i = 0; i < 512; i++) {
 		set_pgtable_section(level1_table_0, i, section_l1t0,
-				    MT_DEVICE_NGNRNE);
+				    MT_DEVICE_NGNRNE, 0);
 		set_pgtable_section(level1_table_1, i, section_l1t1,
-				    MT_NORMAL);
+				    MT_NORMAL, 0);
 		set_pgtable_section(level2_table, i, section_l2,
-				    MT_DEVICE_NGNRNE);
+				    MT_DEVICE_NGNRNE, 0);
 		section_l1t0 += BLOCK_SIZE_L1;
 		section_l1t1 += BLOCK_SIZE_L1;
 		section_l2 += BLOCK_SIZE_L2;
@@ -108,13 +108,13 @@ static inline void early_mmu_setup(void)
 	set_pgtable_section(level2_table,
 			    CONFIG_SYS_FSL_OCRAM_BASE >> SECTION_SHIFT_L2,
 			    CONFIG_SYS_FSL_OCRAM_BASE,
-			    MT_NORMAL);
+			    MT_NORMAL, 0);
 	for (i = CONFIG_SYS_IFC_BASE >> SECTION_SHIFT_L2;
 	     i < (CONFIG_SYS_IFC_BASE + CONFIG_SYS_IFC_SIZE)
 	     >> SECTION_SHIFT_L2; i++) {
 		section_l2 = i << SECTION_SHIFT_L2;
 		set_pgtable_section(level2_table, i,
-				    section_l2, MT_NORMAL);
+				    section_l2, MT_NORMAL, 0);
 	}
 
 	el = current_el();
@@ -154,11 +154,11 @@ static inline void final_mmu_setup(void)
 	section_l2 = 0;
 	for (i = 0; i < 512; i++) {
 		set_pgtable_section(level1_table_0, i, section_l1t0,
-				    MT_DEVICE_NGNRNE);
+				    MT_DEVICE_NGNRNE, 0);
 		set_pgtable_section(level1_table_1, i, section_l1t1,
-				    MT_NORMAL);
+				    MT_NORMAL, 0);
 		set_pgtable_section(level2_table_0, i, section_l2,
-				    MT_DEVICE_NGNRNE);
+				    MT_DEVICE_NGNRNE, 0);
 		section_l1t0 += BLOCK_SIZE_L1;
 		section_l1t1 += BLOCK_SIZE_L1;
 		section_l2 += BLOCK_SIZE_L2;
@@ -177,7 +177,7 @@ static inline void final_mmu_setup(void)
 	set_pgtable_section(level2_table_0,
 			    CONFIG_SYS_FSL_OCRAM_BASE >> SECTION_SHIFT_L2,
 			    CONFIG_SYS_FSL_OCRAM_BASE,
-			    MT_NORMAL);
+			    MT_NORMAL, 0);
 
 	/*
 	 * Fill in other part of tables if cache is needed
@@ -190,7 +190,7 @@ static inline void final_mmu_setup(void)
 	section_l2 = section_base;
 	for (i = 0; i < 512; i++) {
 		set_pgtable_section(level2_table_1, i, section_l2,
-				    MT_DEVICE_NGNRNE);
+				    MT_DEVICE_NGNRNE, 0);
 		section_l2 += BLOCK_SIZE_L2;
 	}
 	tbl_base = FINAL_QBMAN_CACHED_MEM & (BLOCK_SIZE_L1 - 1);
@@ -200,7 +200,7 @@ static inline void final_mmu_setup(void)
 	     i < tbl_limit >> SECTION_SHIFT_L2; i++) {
 		section_l2 = section_base + (i << SECTION_SHIFT_L2);
 		set_pgtable_section(level2_table_1, i,
-				    section_l2, MT_NORMAL);
+				    section_l2, MT_NORMAL, 0);
 	}
 
 	/* flush new MMU table */
arch/arm/include/asm/armv8/mmu.h +38 -33

96 lines not on this page · raw message

Signature · 1 line
1.7.9.5
#1 lore raw

PATCH 1/1 ARMv8: bug fix of mmu setup and code optimization

Hello fenghua at phytium.com.cn,

Quoted 12 lines · fenghua at phytium.com.cn

From: David Feng <[email protected]>

1. Fix a bug of mmu_setup that variable i and j should be type long instead of int.
2. Give mmu_setup weak attribute so that other implementation can redfine it.
3. A more common set_pgtable_section().
4. Give device memory PXN and UXN attribute. CPU may speculatively prefetch instructions from device memory, but the IO subsystem of some implementation may not support this operation. The two attributes prevent this behavior.

Quoted 6 lines
---
 arch/arm/cpu/armv8/cache_v8.c      |   73 +++++++++++++++++++++++-------------
 arch/arm/cpu/armv8/fsl-lsch3/cpu.c |   22 +++++------
 arch/arm/include/asm/armv8/mmu.h   |   71 +++++++++++++++++++----------------
 3 files changed, 95 insertions(+), 71 deletions(-)

This patch does not apply on current ARM tree; at least part of it must be rewritten.

Amicalement,

Signature · 1 line
Albert.