diff options
author | Ahmad Fatoum <ahmad@a3f.at> | 2019-10-09 18:40:09 +0200 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2019-10-14 15:26:46 +0200 |
commit | 3e4a0405455f66fbae0a98dc1faee5c7c39f17a2 (patch) | |
tree | 1b639eb46a5facb106461c50d79ddc34b221bb47 /arch/arm/cpu | |
parent | 2183ca1c6087882a40834a7f271a2c185dba9de0 (diff) | |
download | barebox-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.c | 7 | ||||
-rw-r--r-- | arch/arm/cpu/mmu.c | 7 | ||||
-rw-r--r-- | arch/arm/cpu/mmu.h | 1 |
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) |