summaryrefslogtreecommitdiff
path: root/arch/arm/kernel
diff options
context:
space:
mode:
authorVladimir Murzin <vladimir.murzin@arm.com>2017-10-16 13:00:45 +0100
committerRussell King <rmk+kernel@armlinux.org.uk>2017-10-23 16:59:31 +0100
commit216218308cfb0939aeecb246b34faf6e179c8d57 (patch)
treeac012bba6a2ab6728d7747b57cbf7fdc4a892912 /arch/arm/kernel
parent5c9d9a1b3a540779ba3f2d5e81150b2d92dcb74a (diff)
ARM: 8713/1: NOMMU: Support MPU in XIP configuration
Currently, there is assumption in early MPU setup code that kernel image is located in RAM, which is obviously not true for XIP. To run code from ROM we need to make sure that it is covered by MPU. However, due to we allocate regions (semi-)dynamically we can run into issue of trimming region we are running from in case ROM spawns several MPU regions. To help deal with that we enforce minimum alignments for start end end of XIP address space as 1MB and 128Kb correspondingly. Tested-by: Alexandre TORGUE <alexandre.torgue@st.com> Tested-by: Benjamin Gaignard <benjamin.gaignard@linaro.org> Signed-off-by: Vladimir Murzin <vladimir.murzin@arm.com> Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
Diffstat (limited to 'arch/arm/kernel')
-rw-r--r--arch/arm/kernel/head-nommu.S20
-rw-r--r--arch/arm/kernel/vmlinux-xip.lds.S23
2 files changed, 43 insertions, 0 deletions
diff --git a/arch/arm/kernel/head-nommu.S b/arch/arm/kernel/head-nommu.S
index 0d64b8ba7e9c..2e38f85b757a 100644
--- a/arch/arm/kernel/head-nommu.S
+++ b/arch/arm/kernel/head-nommu.S
@@ -258,6 +258,26 @@ M_CLASS(ldr r0, [r12, #MPU_TYPE])
setup_region r0, r5, r6, MPU_INSTR_SIDE r12 @ 0x0, BG region, enabled
2: isb
+#ifdef CONFIG_XIP_KERNEL
+ set_region_nr r0, #MPU_ROM_REGION, r12
+ isb
+
+ ldr r5,=(MPU_AP_PL1RO_PL0NA | MPU_RGN_NORMAL)
+
+ ldr r0, =CONFIG_XIP_PHYS_ADDR @ ROM start
+ ldr r6, =(_exiprom) @ ROM end
+ sub r6, r6, r0 @ Minimum size of region to map
+ clz r6, r6 @ Region size must be 2^N...
+ rsb r6, r6, #31 @ ...so round up region size
+ lsl r6, r6, #MPU_RSR_SZ @ Put size in right field
+ orr r6, r6, #(1 << MPU_RSR_EN) @ Set region enabled bit
+
+ setup_region r0, r5, r6, MPU_DATA_SIDE, r12 @ XIP_PHYS_ADDR, shared, enabled
+ beq 3f @ Memory-map not unified
+ setup_region r0, r5, r6, MPU_INSTR_SIDE, r12 @ XIP_PHYS_ADDR, shared, enabled
+3: isb
+#endif
+
/* Enable the MPU */
AR_CLASS(mrc p15, 0, r0, c1, c0, 0) @ Read SCTLR
AR_CLASS(bic r0, r0, #CR_BR) @ Disable the 'default mem-map'
diff --git a/arch/arm/kernel/vmlinux-xip.lds.S b/arch/arm/kernel/vmlinux-xip.lds.S
index 7a844310085e..74c93879532a 100644
--- a/arch/arm/kernel/vmlinux-xip.lds.S
+++ b/arch/arm/kernel/vmlinux-xip.lds.S
@@ -6,6 +6,8 @@
/* No __ro_after_init data in the .rodata section - which will always be ro */
#define RO_AFTER_INIT_DATA
+#include <linux/sizes.h>
+
#include <asm-generic/vmlinux.lds.h>
#include <asm/cache.h>
#include <asm/thread_info.h>
@@ -187,6 +189,9 @@ SECTIONS
INIT_RAM_FS
}
+#ifdef CONFIG_ARM_MPU
+ . = ALIGN(SZ_128K);
+#endif
_exiprom = .; /* End of XIP ROM area */
/*
@@ -314,3 +319,21 @@ ASSERT(__hyp_idmap_text_end - (__hyp_idmap_text_start & PAGE_MASK) <= PAGE_SIZE,
*/
ASSERT((_end - __bss_start) >= 12288, ".bss too small for CONFIG_XIP_DEFLATED_DATA")
#endif
+
+#ifdef CONFIG_ARM_MPU
+/*
+ * Due to PMSAv7 restriction on base address and size we have to
+ * enforce minimal alignment restrictions. It was seen that weaker
+ * alignment restriction on _xiprom will likely force XIP address
+ * space spawns multiple MPU regions thus it is likely we run in
+ * situation when we are reprogramming MPU region we run on with
+ * something which doesn't cover reprogramming code itself, so as soon
+ * as we update MPU settings we'd immediately try to execute straight
+ * from background region which is XN.
+ * It seem that alignment in 1M should suit most users.
+ * _exiprom is aligned as 1/8 of 1M so can be covered by subregion
+ * disable
+ */
+ASSERT(!(_xiprom & (SZ_1M - 1)), "XIP start address may cause MPU programming issues")
+ASSERT(!(_exiprom & (SZ_128K - 1)), "XIP end address may cause MPU programming issues")
+#endif