summaryrefslogtreecommitdiffstats
path: root/arch/arm/cpu
diff options
context:
space:
mode:
authorAhmad Fatoum <ahmad@a3f.at>2019-10-09 18:40:09 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2019-10-14 15:26:46 +0200
commit3e4a0405455f66fbae0a98dc1faee5c7c39f17a2 (patch)
tree1b639eb46a5facb106461c50d79ddc34b221bb47 /arch/arm/cpu
parent2183ca1c6087882a40834a7f271a2c185dba9de0 (diff)
downloadbarebox-3e4a0405455f66fbae0a98dc1faee5c7c39f17a2.tar.gz
barebox-3e4a0405455f66fbae0a98dc1faee5c7c39f17a2.tar.xz
ARM: mmu: use client domain permissions to support ARMv7 eXecute Never
The ARM Architecture Reference Manual notes[1]: > When using the Short-descriptor translation table format, the XN > attribute is not checked for domains marked as Manager. > Therefore, the system must not include read-sensitive memory in > domains marked as Manager, because the XN bit does not prevent > speculative fetches from a Manager domain. To avoid speculative access to read-sensitive memory-mapped peripherals on ARMv7, let's use client domain permissions for all memory, so the XN bit (and also R/W bits) can function. This aligns us with what Linux is doing on ARMv7. This fixes cache corruption instances that had been observed on the i.MX6UL(L) when the instruction prefetcher speculates into memory following the end of a 512M SDRAM[2]. While this is not necessary to avoid speculative accesses on < ARMv7, we could probably have everything there in client domain as well, but due to lack of test coverage, we'll restrict the change to ARMv7. [1]: B3.7.2 - Execute-never restrictions on instruction fetching [2]: "Cache Corruption on MX6UL(L)": https://community.nxp.com/thread/511925 Fixes: 0198567c4 ("ARM: mmu: mark uncached regions as eXecute never on v7") Signed-off-by: Ahmad Fatoum <ahmad@a3f.at> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'arch/arm/cpu')
-rw-r--r--arch/arm/cpu/mmu-early.c7
-rw-r--r--arch/arm/cpu/mmu.c7
-rw-r--r--arch/arm/cpu/mmu.h1
3 files changed, 13 insertions, 2 deletions
diff --git a/arch/arm/cpu/mmu-early.c b/arch/arm/cpu/mmu-early.c
index 2f5876fc46..7c30526b94 100644
--- a/arch/arm/cpu/mmu-early.c
+++ b/arch/arm/cpu/mmu-early.c
@@ -29,7 +29,12 @@ void mmu_early_enable(unsigned long membase, unsigned long memsize,
arm_set_cache_functions();
set_ttbr(ttb);
- set_domain(DOMAIN_MANAGER);
+
+ /* For the XN bit to take effect, we can't be using DOMAIN_MANAGER. */
+ if (cpu_architecture() >= CPU_ARCH_ARMv7)
+ set_domain(DOMAIN_CLIENT);
+ else
+ set_domain(DOMAIN_MANAGER);
/*
* This marks the whole address space as uncachable as well as
diff --git a/arch/arm/cpu/mmu.c b/arch/arm/cpu/mmu.c
index efe4620d84..158b130b57 100644
--- a/arch/arm/cpu/mmu.c
+++ b/arch/arm/cpu/mmu.c
@@ -446,7 +446,12 @@ void __mmu_init(bool mmu_on)
ttb = xmemalign(ARM_TTB_SIZE, ARM_TTB_SIZE);
set_ttbr(ttb);
- set_domain(DOMAIN_MANAGER);
+
+ /* For the XN bit to take effect, we can't be using DOMAIN_MANAGER. */
+ if (cpu_architecture() >= CPU_ARCH_ARMv7)
+ set_domain(DOMAIN_CLIENT);
+ else
+ set_domain(DOMAIN_MANAGER);
create_flat_mapping(ttb);
__mmu_cache_flush();
diff --git a/arch/arm/cpu/mmu.h b/arch/arm/cpu/mmu.h
index c911ee209f..6e7a4c0350 100644
--- a/arch/arm/cpu/mmu.h
+++ b/arch/arm/cpu/mmu.h
@@ -36,6 +36,7 @@ static inline void set_ttbr(void *ttb)
asm volatile ("mcr p15,0,%0,c2,c0,0" : : "r"(ttb) /*:*/);
}
+#define DOMAIN_CLIENT 1
#define DOMAIN_MANAGER 3
static inline void set_domain(unsigned val)