mail archive of the barebox mailing list
 help / color / mirror / Atom feed
* [PATCH 0/3] ARMv7: mmu: fix setting eXecute Never for device memory
@ 2019-10-09 16:40 Ahmad Fatoum
  2019-10-09 16:40 ` [PATCH 1/3] ARM: cache-armv7: remove duplicate domain initialization Ahmad Fatoum
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Ahmad Fatoum @ 2019-10-09 16:40 UTC (permalink / raw)
  To: barebox; +Cc: Ahmad Fatoum

Greetings,

in 0198567c4 ("ARM: mmu: mark uncached regions as eXecute never on v7"),
I had my first attempt at supporting eXecute Never in barebox.
This was meant to prevent speculative execution from accessing
read-sensitive device memory and the erratic behavior it could entail.

The XN bit not only prevents speculation, but also any execution at all,
as the name suggests, so the patchset can be tested by just executing
the code and asserting that the prefetch abort occurs, something that
I unfortunately missed during the first time round.

This patchset rectifies this and now Prefetch Aborts are thrown as
expected. They weren't before barebox uses a domain with manager permissions
for all mappings. This means that no permission checks at all are conducted
and our new XN settings were without effect.

There are theoritical regressions with this patch: any ARMv7 barebox platform
that directly jumps into ROM code with the MMU enabled will cease to
work. Assuming all memory outside of the barebox text section and SDRAM to be
non-executable however seems the right thing to do. Platforms that do
call back into ROM code should explicitly indicate that they intend to
do so in the PBL.

These patches fix a cache corruption issue[1] I've observed on the i.MX6UL(L)
that resulted from speculative fetches into the MMDC region following the 512M
SDRAM on the EVKs.

This time I tested it by by jumping into IO memory with go -m, which I had
introduced in this patch:
https://www.spinics.net/lists/u-boot-v2/msg38947.html

Tested SoCs:

- i.MX6UL (Cortex-A7, barebox directly loaded into SDRAM)
- i.MX6Q  (Cortex-A9, barebox directly loaded into SDRAM)
- SAMA5D3 (Cortex-A5, barebox loaded into SRAM then SDRAM)

[1]: https://community.nxp.com/thread/511925

Cheers
Ahmad Fatoum (3):
  ARM: cache-armv7: remove duplicate domain initialization
  ARM: mmu: set R/W bits in ARMv7 translation table
  ARM: mmu: use client domain permissions to support ARMv7 eXecute Never

 arch/arm/cpu/cache-armv7.S |  2 --
 arch/arm/cpu/mmu-early.c   |  7 ++++++-
 arch/arm/cpu/mmu.c         | 18 ++++++++++++------
 arch/arm/cpu/mmu.h         |  1 +
 4 files changed, 19 insertions(+), 9 deletions(-)

-- 
2.23.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH 1/3] ARM: cache-armv7: remove duplicate domain initialization
  2019-10-09 16:40 [PATCH 0/3] ARMv7: mmu: fix setting eXecute Never for device memory Ahmad Fatoum
@ 2019-10-09 16:40 ` Ahmad Fatoum
  2019-10-09 16:40 ` [PATCH 2/3] ARM: mmu: set R/W bits in ARMv7 translation table Ahmad Fatoum
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Ahmad Fatoum @ 2019-10-09 16:40 UTC (permalink / raw)
  To: barebox; +Cc: Ahmad Fatoum

From: Ahmad Fatoum <ahmad@a3f.at>

We already call set_domain each time we do __mmu_cache_on. Writing the
DACR in the armv7 __mmu_cache_on is thus superfluous. Drop it.

This changes existing behavior, whereas all 16 memory domains had the same
access permissions set (manager) before, now only the first domain has.
This is ok, as we only ever use domain 0 in barebox and on non-armv7,
we don't bother with the other ones at all.

Signed-off-by: Ahmad Fatoum <ahmad@a3f.at>
---
 arch/arm/cpu/cache-armv7.S | 2 --
 1 file changed, 2 deletions(-)

diff --git a/arch/arm/cpu/cache-armv7.S b/arch/arm/cpu/cache-armv7.S
index 6a8aff8bb12c..2aa34ab4d7d8 100644
--- a/arch/arm/cpu/cache-armv7.S
+++ b/arch/arm/cpu/cache-armv7.S
@@ -21,8 +21,6 @@ ENTRY(v7_mmu_cache_on)
 		orr	r0, r0, #1 << 25	@ big-endian page tables
 #endif
 		orrne	r0, r0, #1		@ MMU enabled
-		movne	r1, #-1
-		mcrne	p15, 0, r1, c3, c0, 0	@ load domain access control
 #endif
 		isb
 		mcr	p15, 0, r0, c1, c0, 0	@ load control register
-- 
2.23.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH 2/3] ARM: mmu: set R/W bits in ARMv7 translation table
  2019-10-09 16:40 [PATCH 0/3] ARMv7: mmu: fix setting eXecute Never for device memory Ahmad Fatoum
  2019-10-09 16:40 ` [PATCH 1/3] ARM: cache-armv7: remove duplicate domain initialization Ahmad Fatoum
@ 2019-10-09 16:40 ` Ahmad Fatoum
  2019-10-09 16:40 ` [PATCH 3/3] ARM: mmu: use client domain permissions to support ARMv7 eXecute Never Ahmad Fatoum
  2019-10-14 10:47 ` [PATCH 0/3] ARMv7: mmu: fix setting eXecute Never for device memory Sascha Hauer
  3 siblings, 0 replies; 5+ messages in thread
From: Ahmad Fatoum @ 2019-10-09 16:40 UTC (permalink / raw)
  To: barebox; +Cc: Ahmad Fatoum

From: Ahmad Fatoum <ahmad@a3f.at>

With barebox using the manager permissions for domain 0 that's used for
all page table entries and directories, we never had the need so far to
explicitly set R/W bits. We did so anyway for sections in the early MMU
code, but later on in the normal MMU setup, we didn't do so consistently.

In preparation for switching to DOMAIN_CLIENT for ARMv7, configure R/W
everywhere in normal MMU code as well.

Signed-off-by: Ahmad Fatoum <ahmad@a3f.at>
---
 arch/arm/cpu/mmu.c | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/arch/arm/cpu/mmu.c b/arch/arm/cpu/mmu.c
index 123e19e9e55c..f7158871fe6f 100644
--- a/arch/arm/cpu/mmu.c
+++ b/arch/arm/cpu/mmu.c
@@ -56,13 +56,14 @@ static inline void tlb_invalidate(void)
 	);
 }
 
-#define PTE_FLAGS_CACHED_V7 (PTE_EXT_TEX(1) | PTE_BUFFERABLE | PTE_CACHEABLE)
-#define PTE_FLAGS_WC_V7 (PTE_EXT_TEX(1) | PTE_EXT_XN)
-#define PTE_FLAGS_UNCACHED_V7 PTE_EXT_XN
+#define PTE_FLAGS_CACHED_V7 (PTE_EXT_TEX(1) | PTE_BUFFERABLE | PTE_CACHEABLE | \
+			     PTE_EXT_AP_URW_SRW)
+#define PTE_FLAGS_WC_V7 (PTE_EXT_TEX(1) | PTE_EXT_AP_URW_SRW | PTE_EXT_XN)
+#define PTE_FLAGS_UNCACHED_V7 (PTE_EXT_AP_URW_SRW | PTE_EXT_XN)
 #define PTE_FLAGS_CACHED_V4 (PTE_SMALL_AP_UNO_SRW | PTE_BUFFERABLE | PTE_CACHEABLE)
 #define PTE_FLAGS_UNCACHED_V4 PTE_SMALL_AP_UNO_SRW
-#define PGD_FLAGS_WC_V7 (PMD_SECT_TEX(1) | PMD_TYPE_SECT | PMD_SECT_BUFFERABLE | \
-			 PMD_SECT_XN)
+#define PGD_FLAGS_WC_V7 (PMD_SECT_TEX(1) | PMD_SECT_DEF_UNCACHED | \
+			 PMD_SECT_BUFFERABLE | PMD_SECT_XN)
 #define PGD_FLAGS_UNCACHED_V7 (PMD_SECT_DEF_UNCACHED | PMD_SECT_XN)
 
 /*
-- 
2.23.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH 3/3] ARM: mmu: use client domain permissions to support ARMv7 eXecute Never
  2019-10-09 16:40 [PATCH 0/3] ARMv7: mmu: fix setting eXecute Never for device memory Ahmad Fatoum
  2019-10-09 16:40 ` [PATCH 1/3] ARM: cache-armv7: remove duplicate domain initialization Ahmad Fatoum
  2019-10-09 16:40 ` [PATCH 2/3] ARM: mmu: set R/W bits in ARMv7 translation table Ahmad Fatoum
@ 2019-10-09 16:40 ` Ahmad Fatoum
  2019-10-14 10:47 ` [PATCH 0/3] ARMv7: mmu: fix setting eXecute Never for device memory Sascha Hauer
  3 siblings, 0 replies; 5+ messages in thread
From: Ahmad Fatoum @ 2019-10-09 16:40 UTC (permalink / raw)
  To: barebox; +Cc: Ahmad Fatoum

From: Ahmad Fatoum <ahmad@a3f.at>

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>
---
 arch/arm/cpu/mmu-early.c | 7 ++++++-
 arch/arm/cpu/mmu.c       | 7 ++++++-
 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 2f5876fc46d8..7c30526b9499 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 f7158871fe6f..2c5c4b574928 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 c911ee209f51..6e7a4c0350a1 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)
-- 
2.23.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH 0/3] ARMv7: mmu: fix setting eXecute Never for device memory
  2019-10-09 16:40 [PATCH 0/3] ARMv7: mmu: fix setting eXecute Never for device memory Ahmad Fatoum
                   ` (2 preceding siblings ...)
  2019-10-09 16:40 ` [PATCH 3/3] ARM: mmu: use client domain permissions to support ARMv7 eXecute Never Ahmad Fatoum
@ 2019-10-14 10:47 ` Sascha Hauer
  3 siblings, 0 replies; 5+ messages in thread
From: Sascha Hauer @ 2019-10-14 10:47 UTC (permalink / raw)
  To: Ahmad Fatoum; +Cc: barebox

On Wed, Oct 09, 2019 at 06:40:06PM +0200, Ahmad Fatoum wrote:
> Greetings,
> 
> in 0198567c4 ("ARM: mmu: mark uncached regions as eXecute never on v7"),
> I had my first attempt at supporting eXecute Never in barebox.
> This was meant to prevent speculative execution from accessing
> read-sensitive device memory and the erratic behavior it could entail.
> 
> The XN bit not only prevents speculation, but also any execution at all,
> as the name suggests, so the patchset can be tested by just executing
> the code and asserting that the prefetch abort occurs, something that
> I unfortunately missed during the first time round.
> 
> This patchset rectifies this and now Prefetch Aborts are thrown as
> expected. They weren't before barebox uses a domain with manager permissions
> for all mappings. This means that no permission checks at all are conducted
> and our new XN settings were without effect.
> 
> There are theoritical regressions with this patch: any ARMv7 barebox platform
> that directly jumps into ROM code with the MMU enabled will cease to
> work. Assuming all memory outside of the barebox text section and SDRAM to be
> non-executable however seems the right thing to do. Platforms that do
> call back into ROM code should explicitly indicate that they intend to
> do so in the PBL.
> 
> These patches fix a cache corruption issue[1] I've observed on the i.MX6UL(L)
> that resulted from speculative fetches into the MMDC region following the 512M
> SDRAM on the EVKs.
> 
> This time I tested it by by jumping into IO memory with go -m, which I had
> introduced in this patch:
> https://www.spinics.net/lists/u-boot-v2/msg38947.html
> 
> Tested SoCs:
> 
> - i.MX6UL (Cortex-A7, barebox directly loaded into SDRAM)
> - i.MX6Q  (Cortex-A9, barebox directly loaded into SDRAM)
> - SAMA5D3 (Cortex-A5, barebox loaded into SRAM then SDRAM)
> 
> [1]: https://community.nxp.com/thread/511925
> 
> Cheers
> Ahmad Fatoum (3):
>   ARM: cache-armv7: remove duplicate domain initialization
>   ARM: mmu: set R/W bits in ARMv7 translation table
>   ARM: mmu: use client domain permissions to support ARMv7 eXecute Never

Finally this is resolved \o/

Thanks Ahmad. Applied.

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2019-10-14 10:47 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-10-09 16:40 [PATCH 0/3] ARMv7: mmu: fix setting eXecute Never for device memory Ahmad Fatoum
2019-10-09 16:40 ` [PATCH 1/3] ARM: cache-armv7: remove duplicate domain initialization Ahmad Fatoum
2019-10-09 16:40 ` [PATCH 2/3] ARM: mmu: set R/W bits in ARMv7 translation table Ahmad Fatoum
2019-10-09 16:40 ` [PATCH 3/3] ARM: mmu: use client domain permissions to support ARMv7 eXecute Never Ahmad Fatoum
2019-10-14 10:47 ` [PATCH 0/3] ARMv7: mmu: fix setting eXecute Never for device memory Sascha Hauer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox