* [PATCH v2 1/3] ARM: cpu: suppress arm_early_mmu_cache_invalidate if dcache enabled
@ 2026-08-25 8:13 Ahmad Fatoum
2026-08-25 8:13 ` [PATCH v2 2/3] ARM: v7r: factor out armv7r_cache_enable Ahmad Fatoum
` (3 more replies)
0 siblings, 4 replies; 5+ messages in thread
From: Ahmad Fatoum @ 2026-08-25 8:13 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
barebox built as EFI payload on ARM invalidates the data caches inside
barebox_arm_entry(), which may lead to memory corruption.
Generally, calling arm_early_mmu_cache_invalidate() while the caches are
enabled is a bad idea, so add a function that protects against that and
use it in common code.
Fixes: 742e78976dd4 ("ARM64: add optional EFI stub")
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
v1 -> v2:
- rename dcache_invalidate_stale(to cache_invalidate_stale (Lucas)
---
arch/arm/cpu/common.c | 16 ++++++++++++++++
arch/arm/cpu/entry_ll_32.S | 2 +-
arch/arm/cpu/entry_ll_64.S | 2 +-
arch/arm/include/asm/cache.h | 3 +++
4 files changed, 21 insertions(+), 2 deletions(-)
diff --git a/arch/arm/cpu/common.c b/arch/arm/cpu/common.c
index adb5d6a02bc8..e079f55b8bb7 100644
--- a/arch/arm/cpu/common.c
+++ b/arch/arm/cpu/common.c
@@ -37,6 +37,22 @@ void sync_caches_for_execution(void)
arm_early_mmu_cache_flush();
}
+/**
+ * cache_invalidate_stale - invalidate caches prior to enabling them
+ *
+ * Some SoCs can come up with invalid entries, but with the valid bit set.
+ * This function discards them, as that would lead to memory corruption
+ * otherwise.
+ */
+void cache_invalidate_stale(void)
+{
+ /* if caches are already enabled, don't cause data loss */
+ if (get_cr() & CR_C)
+ return;
+
+ arm_early_mmu_cache_invalidate();
+}
+
void pbl_barebox_break(void)
{
__asm__ __volatile__ (
diff --git a/arch/arm/cpu/entry_ll_32.S b/arch/arm/cpu/entry_ll_32.S
index 0d4c47c1c870..0763581fded4 100644
--- a/arch/arm/cpu/entry_ll_32.S
+++ b/arch/arm/cpu/entry_ll_32.S
@@ -15,7 +15,7 @@ ENTRY(__barebox_arm_entry)
mov r4, r0
mov r5, r1
mov r6, r2
- bl arm_early_mmu_cache_invalidate
+ bl cache_invalidate_stale
mov r0, r4
mov r1, r5
mov r2, r6
diff --git a/arch/arm/cpu/entry_ll_64.S b/arch/arm/cpu/entry_ll_64.S
index 5eb6efed5baf..c80a23c6506d 100644
--- a/arch/arm/cpu/entry_ll_64.S
+++ b/arch/arm/cpu/entry_ll_64.S
@@ -15,7 +15,7 @@ ENTRY(__barebox_arm_entry)
mov x19, x0
mov x20, x1
mov x21, x2
- bl arm_early_mmu_cache_invalidate
+ bl cache_invalidate_stale
mov x0, x19
mov x1, x20
mov x2, x21
diff --git a/arch/arm/include/asm/cache.h b/arch/arm/include/asm/cache.h
index ea78ae123aec..9dbf433356b9 100644
--- a/arch/arm/include/asm/cache.h
+++ b/arch/arm/include/asm/cache.h
@@ -26,6 +26,9 @@ static inline void icache_invalidate(void)
#endif
}
+
+void cache_invalidate_stale(void);
+
void arm_early_mmu_cache_flush(void);
void arm_early_mmu_cache_invalidate(void);
--
2.47.3
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v2 2/3] ARM: v7r: factor out armv7r_cache_enable
2026-08-25 8:13 [PATCH v2 1/3] ARM: cpu: suppress arm_early_mmu_cache_invalidate if dcache enabled Ahmad Fatoum
@ 2026-08-25 8:13 ` Ahmad Fatoum
2026-08-25 8:13 ` [PATCH v2 3/3] ARM: always call cache_invalidate_stale before enabling D-Cache Ahmad Fatoum
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Ahmad Fatoum @ 2026-08-25 8:13 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
We enable caches early on ARMv7-R to speed up decompression.
On ARMv7-A, we need to enable the MMU as well, but for ARMv7-R enabling
the MPU is not necessary and so the code is a one-liner.
That one line will become two in a subsequent commit, so prepare for
that by moving it into an appropriately named helper function.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
v1 -> v2:
- no change
---
arch/arm/cpu/armv7r-mpu.c | 5 +++++
arch/arm/cpu/uncompress.c | 3 ++-
arch/arm/include/asm/armv7r-mpu.h | 2 ++
3 files changed, 9 insertions(+), 1 deletion(-)
diff --git a/arch/arm/cpu/armv7r-mpu.c b/arch/arm/cpu/armv7r-mpu.c
index d96411a61632..d494aec583ef 100644
--- a/arch/arm/cpu/armv7r-mpu.c
+++ b/arch/arm/cpu/armv7r-mpu.c
@@ -32,6 +32,11 @@
* [1] http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0460d/I1002400.html
*/
+void armv7r_cache_enable(void)
+{
+ set_cr(get_cr() | CR_C);
+}
+
void armv7r_mpu_disable(void)
{
u32 reg;
diff --git a/arch/arm/cpu/uncompress.c b/arch/arm/cpu/uncompress.c
index 55bbe0019cc4..8f0d0f55f862 100644
--- a/arch/arm/cpu/uncompress.c
+++ b/arch/arm/cpu/uncompress.c
@@ -18,6 +18,7 @@
#include <asm/secure.h>
#include <asm/cache.h>
#include <asm/mmu.h>
+#include <asm/armv7r-mpu.h>
#include <asm/unaligned.h>
#include <compressed-dtb.h>
#include <elf.h>
@@ -87,7 +88,7 @@ void __noreturn barebox_pbl_start(unsigned long membase, unsigned long memsize,
if (IS_ENABLED(CONFIG_MMU))
mmu_early_enable(membase, memsize);
else if (IS_ENABLED(CONFIG_ARMV7R_MPU))
- set_cr(get_cr() | CR_C);
+ armv7r_cache_enable();
pr_debug("uncompressing barebox ELF at 0x%p (size 0x%08x) to 0x%08lx (uncompressed size: 0x%08x)\n",
pg_start, pg_len, barebox_base, uncompressed_len);
diff --git a/arch/arm/include/asm/armv7r-mpu.h b/arch/arm/include/asm/armv7r-mpu.h
index 8d737d6d1407..1d890ab90a67 100644
--- a/arch/arm/include/asm/armv7r-mpu.h
+++ b/arch/arm/include/asm/armv7r-mpu.h
@@ -91,6 +91,8 @@ struct mpu_region_config {
enum size reg_size;
};
+void armv7r_cache_enable(void);
+
void armv7r_mpu_disable(void);
void armv7r_mpu_enable(void);
int armv7r_mpu_enabled(void);
--
2.47.3
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v2 3/3] ARM: always call cache_invalidate_stale before enabling D-Cache
2026-08-25 8:13 [PATCH v2 1/3] ARM: cpu: suppress arm_early_mmu_cache_invalidate if dcache enabled Ahmad Fatoum
2026-08-25 8:13 ` [PATCH v2 2/3] ARM: v7r: factor out armv7r_cache_enable Ahmad Fatoum
@ 2026-08-25 8:13 ` Ahmad Fatoum
2026-08-26 8:39 ` [PATCH v2 1/3] ARM: cpu: suppress arm_early_mmu_cache_invalidate if dcache enabled Lucas Stach
2026-08-28 14:24 ` Sascha Hauer
3 siblings, 0 replies; 5+ messages in thread
From: Ahmad Fatoum @ 2026-08-25 8:13 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
cache_invalidate_stale() needs to be executed prior to enabling the
MMU. This was so far guaranteed by __barebox_arm_entry() invoking it
prior to barebox_pbl_start(), which does mmu_early_enable().
As there's more boot time to be saved by calling mmu_early_enable()
earlier, some SoC support has already started calling mmu_early_enable()
prior to barebox_pbl_start(). Should this be extended to older CPUs like
Cortex-A9, we would introduce a regression as the data cache would not be
discarded prior to enabling it.
Avoid this failure mode altogether by having cache_invalidate_stale()
precede the code that depends on it having run.
This function invalidates both I-Cache and D-Cache, but only D-Cache is
interesting to us here as I-Cache has already been invalidated in
arm_cpu_lowlevel_init().
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
v1 -> v2:
- point out that arm_cpu_lowlevel_init() invalidates (Lucas)
---
arch/arm/cpu/armv7r-mpu.c | 1 +
arch/arm/cpu/entry_ll_32.S | 7 -------
arch/arm/cpu/entry_ll_64.S | 7 -------
arch/arm/cpu/mmu_32.c | 2 ++
arch/arm/cpu/uncompress.c | 12 ++++++++++--
5 files changed, 13 insertions(+), 16 deletions(-)
diff --git a/arch/arm/cpu/armv7r-mpu.c b/arch/arm/cpu/armv7r-mpu.c
index d494aec583ef..47e108133178 100644
--- a/arch/arm/cpu/armv7r-mpu.c
+++ b/arch/arm/cpu/armv7r-mpu.c
@@ -34,6 +34,7 @@
void armv7r_cache_enable(void)
{
+ cache_invalidate_stale();
set_cr(get_cr() | CR_C);
}
diff --git a/arch/arm/cpu/entry_ll_32.S b/arch/arm/cpu/entry_ll_32.S
index 0763581fded4..981722ab7b05 100644
--- a/arch/arm/cpu/entry_ll_32.S
+++ b/arch/arm/cpu/entry_ll_32.S
@@ -12,12 +12,5 @@
.section .text.__barebox_arm_entry
ENTRY(__barebox_arm_entry)
mov sp, r3
- mov r4, r0
- mov r5, r1
- mov r6, r2
- bl cache_invalidate_stale
- mov r0, r4
- mov r1, r5
- mov r2, r6
b barebox_pbl_start
ENDPROC(__barebox_arm_entry)
diff --git a/arch/arm/cpu/entry_ll_64.S b/arch/arm/cpu/entry_ll_64.S
index c80a23c6506d..71fb74b48f7e 100644
--- a/arch/arm/cpu/entry_ll_64.S
+++ b/arch/arm/cpu/entry_ll_64.S
@@ -12,12 +12,5 @@
.section .text.__barebox_arm_entry
ENTRY(__barebox_arm_entry)
mov sp, x3
- mov x19, x0
- mov x20, x1
- mov x21, x2
- bl cache_invalidate_stale
- mov x0, x19
- mov x1, x20
- mov x2, x21
b barebox_pbl_start
ENDPROC(__barebox_arm_entry)
diff --git a/arch/arm/cpu/mmu_32.c b/arch/arm/cpu/mmu_32.c
index efdb867532f9..7b49643fd79b 100644
--- a/arch/arm/cpu/mmu_32.c
+++ b/arch/arm/cpu/mmu_32.c
@@ -613,6 +613,8 @@ void mmu_early_enable(unsigned long membase, unsigned long memsize)
pr_debug("enabling MMU, ttb @ 0x%p\n", ttb);
+ cache_invalidate_stale();
+
if (get_cr() & CR_M)
return;
diff --git a/arch/arm/cpu/uncompress.c b/arch/arm/cpu/uncompress.c
index 8f0d0f55f862..4d954b3eaaae 100644
--- a/arch/arm/cpu/uncompress.c
+++ b/arch/arm/cpu/uncompress.c
@@ -85,10 +85,18 @@ void __noreturn barebox_pbl_start(unsigned long membase, unsigned long memsize,
#ifdef DEBUG
print_pbl_mem_layout(membase, endmem, barebox_base);
#endif
- if (IS_ENABLED(CONFIG_MMU))
+
+ /* Enable Caches to speed up the decompression below. */
+ if (IS_ENABLED(CONFIG_MMU)) {
mmu_early_enable(membase, memsize);
- else if (IS_ENABLED(CONFIG_ARMV7R_MPU))
+ } else if (IS_ENABLED(CONFIG_ARMV7R_MPU)) {
armv7r_cache_enable();
+ } else {
+ /* Even if we don't use the cache right now, it may be used later.
+ * Some CPUs may boot up with dirty cache lines, get rid of them.
+ */
+ cache_invalidate_stale();
+ }
pr_debug("uncompressing barebox ELF at 0x%p (size 0x%08x) to 0x%08lx (uncompressed size: 0x%08x)\n",
pg_start, pg_len, barebox_base, uncompressed_len);
--
2.47.3
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v2 1/3] ARM: cpu: suppress arm_early_mmu_cache_invalidate if dcache enabled
2026-08-25 8:13 [PATCH v2 1/3] ARM: cpu: suppress arm_early_mmu_cache_invalidate if dcache enabled Ahmad Fatoum
2026-08-25 8:13 ` [PATCH v2 2/3] ARM: v7r: factor out armv7r_cache_enable Ahmad Fatoum
2026-08-25 8:13 ` [PATCH v2 3/3] ARM: always call cache_invalidate_stale before enabling D-Cache Ahmad Fatoum
@ 2026-08-26 8:39 ` Lucas Stach
2026-08-28 14:24 ` Sascha Hauer
3 siblings, 0 replies; 5+ messages in thread
From: Lucas Stach @ 2026-08-26 8:39 UTC (permalink / raw)
To: Ahmad Fatoum, barebox
Am Dienstag, dem 25.08.2026 um 10:13 +0200 schrieb Ahmad Fatoum:
> barebox built as EFI payload on ARM invalidates the data caches inside
> barebox_arm_entry(), which may lead to memory corruption.
>
> Generally, calling arm_early_mmu_cache_invalidate() while the caches are
> enabled is a bad idea, so add a function that protects against that and
> use it in common code.
>
> Fixes: 742e78976dd4 ("ARM64: add optional EFI stub")
> Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
Entire series looks good to me.
Reviewed-by: Lucas Stach <l.stach@pengutronix.de>
> ---
> v1 -> v2:
> - rename dcache_invalidate_stale(to cache_invalidate_stale (Lucas)
> ---
> arch/arm/cpu/common.c | 16 ++++++++++++++++
> arch/arm/cpu/entry_ll_32.S | 2 +-
> arch/arm/cpu/entry_ll_64.S | 2 +-
> arch/arm/include/asm/cache.h | 3 +++
> 4 files changed, 21 insertions(+), 2 deletions(-)
>
> diff --git a/arch/arm/cpu/common.c b/arch/arm/cpu/common.c
> index adb5d6a02bc8..e079f55b8bb7 100644
> --- a/arch/arm/cpu/common.c
> +++ b/arch/arm/cpu/common.c
> @@ -37,6 +37,22 @@ void sync_caches_for_execution(void)
> arm_early_mmu_cache_flush();
> }
>
> +/**
> + * cache_invalidate_stale - invalidate caches prior to enabling them
> + *
> + * Some SoCs can come up with invalid entries, but with the valid bit set.
> + * This function discards them, as that would lead to memory corruption
> + * otherwise.
> + */
> +void cache_invalidate_stale(void)
> +{
> + /* if caches are already enabled, don't cause data loss */
> + if (get_cr() & CR_C)
> + return;
> +
> + arm_early_mmu_cache_invalidate();
> +}
> +
> void pbl_barebox_break(void)
> {
> __asm__ __volatile__ (
> diff --git a/arch/arm/cpu/entry_ll_32.S b/arch/arm/cpu/entry_ll_32.S
> index 0d4c47c1c870..0763581fded4 100644
> --- a/arch/arm/cpu/entry_ll_32.S
> +++ b/arch/arm/cpu/entry_ll_32.S
> @@ -15,7 +15,7 @@ ENTRY(__barebox_arm_entry)
> mov r4, r0
> mov r5, r1
> mov r6, r2
> - bl arm_early_mmu_cache_invalidate
> + bl cache_invalidate_stale
> mov r0, r4
> mov r1, r5
> mov r2, r6
> diff --git a/arch/arm/cpu/entry_ll_64.S b/arch/arm/cpu/entry_ll_64.S
> index 5eb6efed5baf..c80a23c6506d 100644
> --- a/arch/arm/cpu/entry_ll_64.S
> +++ b/arch/arm/cpu/entry_ll_64.S
> @@ -15,7 +15,7 @@ ENTRY(__barebox_arm_entry)
> mov x19, x0
> mov x20, x1
> mov x21, x2
> - bl arm_early_mmu_cache_invalidate
> + bl cache_invalidate_stale
> mov x0, x19
> mov x1, x20
> mov x2, x21
> diff --git a/arch/arm/include/asm/cache.h b/arch/arm/include/asm/cache.h
> index ea78ae123aec..9dbf433356b9 100644
> --- a/arch/arm/include/asm/cache.h
> +++ b/arch/arm/include/asm/cache.h
> @@ -26,6 +26,9 @@ static inline void icache_invalidate(void)
> #endif
> }
>
> +
> +void cache_invalidate_stale(void);
> +
> void arm_early_mmu_cache_flush(void);
> void arm_early_mmu_cache_invalidate(void);
>
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v2 1/3] ARM: cpu: suppress arm_early_mmu_cache_invalidate if dcache enabled
2026-08-25 8:13 [PATCH v2 1/3] ARM: cpu: suppress arm_early_mmu_cache_invalidate if dcache enabled Ahmad Fatoum
` (2 preceding siblings ...)
2026-08-26 8:39 ` [PATCH v2 1/3] ARM: cpu: suppress arm_early_mmu_cache_invalidate if dcache enabled Lucas Stach
@ 2026-08-28 14:24 ` Sascha Hauer
3 siblings, 0 replies; 5+ messages in thread
From: Sascha Hauer @ 2026-08-28 14:24 UTC (permalink / raw)
To: barebox, Ahmad Fatoum
On Tue, 25 Aug 2026 10:13:15 +0200, Ahmad Fatoum wrote:
> barebox built as EFI payload on ARM invalidates the data caches inside
> barebox_arm_entry(), which may lead to memory corruption.
>
> Generally, calling arm_early_mmu_cache_invalidate() while the caches are
> enabled is a bad idea, so add a function that protects against that and
> use it in common code.
>
> [...]
Applied, thanks!
[1/3] ARM: cpu: suppress arm_early_mmu_cache_invalidate if dcache enabled
https://git.pengutronix.de/cgit/barebox/commit/?id=72faea821232 (link may not be stable)
[2/3] ARM: v7r: factor out armv7r_cache_enable
https://git.pengutronix.de/cgit/barebox/commit/?id=14eafd21e89b (link may not be stable)
[3/3] ARM: always call cache_invalidate_stale before enabling D-Cache
https://git.pengutronix.de/cgit/barebox/commit/?id=fcec14feed91 (link may not be stable)
Best regards,
--
Sascha Hauer <s.hauer@pengutronix.de>
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-08-28 14:25 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-08-25 8:13 [PATCH v2 1/3] ARM: cpu: suppress arm_early_mmu_cache_invalidate if dcache enabled Ahmad Fatoum
2026-08-25 8:13 ` [PATCH v2 2/3] ARM: v7r: factor out armv7r_cache_enable Ahmad Fatoum
2026-08-25 8:13 ` [PATCH v2 3/3] ARM: always call cache_invalidate_stale before enabling D-Cache Ahmad Fatoum
2026-08-26 8:39 ` [PATCH v2 1/3] ARM: cpu: suppress arm_early_mmu_cache_invalidate if dcache enabled Lucas Stach
2026-08-28 14:24 ` Sascha Hauer
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox