From 15a15e3febdc6860d5abf3ee10d12b0f237af436 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sun, 16 Jun 2024 19:31:04 +0200 Subject: [PATCH 1/9] arm: implement invalidate_icache_all on ARM11 In EFI sub-system we rely on invalidate_icache_all() to invalidate the instruction cache after loading binaries. Add the missing implementation on ARM1136, ARM1176. Signed-off-by: Heinrich Schuchardt --- arch/arm/cpu/arm11/cpu.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/arch/arm/cpu/arm11/cpu.c b/arch/arm/cpu/arm11/cpu.c index 01d2e1a125d..4bf0446b543 100644 --- a/arch/arm/cpu/arm11/cpu.c +++ b/arch/arm/cpu/arm11/cpu.c @@ -116,3 +116,15 @@ void enable_caches(void) #endif } #endif + +#if !CONFIG_IS_ENABLED(SYS_ICACHE_OFF) +/* Invalidate entire I-cache */ +void invalidate_icache_all(void) +{ + unsigned long i = 0; + + asm ("mcr p15, 0, %0, c7, c5, 0" : : "r" (i)); +} +#else +void invalidate_icache_all(void) {} +#endif From 19d41f495a24f112ed62c041d18e53334e1b791d Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sun, 16 Jun 2024 19:31:05 +0200 Subject: [PATCH 2/9] efi_loader: avoid duplicate weak invalidate_icache_all() If multiple weak implementations of a weak function exist, it is unclear which one the linker should chose. cmd/cache.c already defines a weak invalidate_icache_all(). We don't need a call to invalidate_icache_all() on x86. ARM, RISC-V, and Sandbox provide an implementation. Signed-off-by: Heinrich Schuchardt Reviewed-by: Ilias Apalodimas --- lib/efi_loader/efi_image_loader.c | 13 +++++++------ lib/efi_loader/efi_runtime.c | 7 ++++++- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/lib/efi_loader/efi_image_loader.c b/lib/efi_loader/efi_image_loader.c index 60424360328..45dc5b6b244 100644 --- a/lib/efi_loader/efi_image_loader.c +++ b/lib/efi_loader/efi_image_loader.c @@ -173,11 +173,6 @@ static efi_status_t efi_loader_relocate(const IMAGE_BASE_RELOCATION *rel, return EFI_SUCCESS; } -void __weak invalidate_icache_all(void) -{ - /* If the system doesn't support icache_all flush, cross our fingers */ -} - /** * efi_set_code_and_data_type() - determine the memory types to be used for code * and data. @@ -986,7 +981,13 @@ efi_status_t efi_load_pe(struct efi_loaded_image_obj *handle, /* Flush cache */ flush_cache((ulong)efi_reloc, ALIGN(virt_size, EFI_CACHELINE_SIZE)); - invalidate_icache_all(); + + /* + * If on x86 a write affects a prefetched instruction, + * the prefetch queue is invalidated. + */ + if (!CONFIG_IS_ENABLED(X86)) + invalidate_icache_all(); /* Populate the loaded image interface bits */ loaded_image_info->image_base = efi_reloc; diff --git a/lib/efi_loader/efi_runtime.c b/lib/efi_loader/efi_runtime.c index 011bcd04836..05369c47b01 100644 --- a/lib/efi_loader/efi_runtime.c +++ b/lib/efi_loader/efi_runtime.c @@ -783,7 +783,12 @@ void efi_runtime_relocate(ulong offset, struct efi_mem_desc *map) lastoff = offset; #endif - invalidate_icache_all(); + /* + * If on x86 a write affects a prefetched instruction, + * the prefetch queue is invalidated. + */ + if (!CONFIG_IS_ENABLED(X86)) + invalidate_icache_all(); } /** From e32d513304043ddc31bfcf586b799757e47e54ad Mon Sep 17 00:00:00 2001 From: Tom Rini Date: Wed, 19 Jun 2024 15:27:53 -0600 Subject: [PATCH 3/9] m68k: Implement a default flush_dcache_all Implement a weak default version of flush_dcache_all which is based on the ARM default, which is to flush the entire range via flush_dcache_range(...). Acked-by: Angelo Dureghello Acked-by: Ilias Apalodimas Signed-off-by: Tom Rini --- arch/m68k/lib/cache.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/m68k/lib/cache.c b/arch/m68k/lib/cache.c index de04124404c..dab834c1cbd 100644 --- a/arch/m68k/lib/cache.c +++ b/arch/m68k/lib/cache.c @@ -134,6 +134,15 @@ void dcache_invalid(void) #endif } +/* + * Default implementation: + * do a range flush for the entire range + */ +__weak void flush_dcache_all(void) +{ + flush_dcache_range(0, ~0); +} + __weak void invalidate_dcache_range(unsigned long start, unsigned long stop) { /* An empty stub, real implementation should be in platform code */ From 8f25b150651d45f3fe75ea19195fc6cc8169d0d2 Mon Sep 17 00:00:00 2001 From: Tom Rini Date: Wed, 19 Jun 2024 15:27:54 -0600 Subject: [PATCH 4/9] m68k: Rename icache_invalid to invalidate_icache_all The implementation of icache_invalid appears to be doing what other architectures call invalidate_icache_all so rename to match. Reviewed-by: Ilias Apalodimas Signed-off-by: Tom Rini --- arch/m68k/include/asm/cache.h | 1 - arch/m68k/lib/cache.c | 6 +++--- drivers/net/mcffec.c | 5 +++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/m68k/include/asm/cache.h b/arch/m68k/include/asm/cache.h index 6ef7f7be1af..aa8d2edb40b 100644 --- a/arch/m68k/include/asm/cache.h +++ b/arch/m68k/include/asm/cache.h @@ -185,7 +185,6 @@ #ifndef __ASSEMBLY__ /* put C only stuff in this section */ -void icache_invalid(void); void dcache_invalid(void); #endif diff --git a/arch/m68k/lib/cache.c b/arch/m68k/lib/cache.c index dab834c1cbd..370ad40f142 100644 --- a/arch/m68k/lib/cache.c +++ b/arch/m68k/lib/cache.c @@ -29,7 +29,7 @@ int dcache_status(void) void icache_enable(void) { - icache_invalid(); + invalidate_icache_all(); *cf_icache_status = 1; @@ -53,7 +53,7 @@ void icache_disable(void) u32 temp = 0; *cf_icache_status = 0; - icache_invalid(); + invalidate_icache_all(); #if defined(CONFIG_CF_V4) || defined(CFG_CF_V4E) __asm__ __volatile__("movec %0, %%acr2"::"r"(temp)); @@ -68,7 +68,7 @@ void icache_disable(void) #endif } -void icache_invalid(void) +void invalidate_icache_all(void) { u32 temp; diff --git a/drivers/net/mcffec.c b/drivers/net/mcffec.c index 04b711e4f65..7e53492733e 100644 --- a/drivers/net/mcffec.c +++ b/drivers/net/mcffec.c @@ -11,6 +11,7 @@ */ #include +#include #include #include #include @@ -399,7 +400,7 @@ static int mcffec_send(struct udevice *dev, void *packet, int length) #endif #ifdef CONFIG_SYS_UNIFY_CACHE - icache_invalid(); + invalidate_icache_all(); #endif j = 0; @@ -433,7 +434,7 @@ static int mcffec_recv(struct udevice *dev, int flags, uchar **packetp) for (;;) { #ifdef CONFIG_SYS_UNIFY_CACHE - icache_invalid(); + invalidate_icache_all(); #endif /* If nothing received - leave for() loop */ if (info->rxbd[info->rx_idx].cbd_sc & BD_ENET_RX_EMPTY) From be9f4ff58567420e470f2f0eccda41347747c8f5 Mon Sep 17 00:00:00 2001 From: Tom Rini Date: Wed, 19 Jun 2024 15:27:55 -0600 Subject: [PATCH 5/9] sh: Implement a default flush_dcache_all Implement a weak default version of flush_dcache_all which is based on the ARM default, which is to flush the entire range via flush_dcache_range(...). Acked-by: Ilias Apalodimas Signed-off-by: Tom Rini --- arch/sh/cpu/sh4/cache.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/sh/cpu/sh4/cache.c b/arch/sh/cpu/sh4/cache.c index 8c1839935ca..f0cb39d6a92 100644 --- a/arch/sh/cpu/sh4/cache.c +++ b/arch/sh/cpu/sh4/cache.c @@ -65,6 +65,15 @@ void flush_dcache_range(unsigned long start, unsigned long end) } } +/* + * Default implementation: + * do a range flush for the entire range + */ +void flush_dcache_all(void) +{ + flush_dcache_range(0, ~0); +} + void invalidate_dcache_range(unsigned long start, unsigned long end) { u32 v; From 6912c9c2f9f1fc4d62ba33c41a07d137ab04d743 Mon Sep 17 00:00:00 2001 From: Tom Rini Date: Wed, 19 Jun 2024 15:27:56 -0600 Subject: [PATCH 6/9] sh: Add the old invalidate_icache_all function Add the old invalidate_icache_all function that prints a warning that was previously found in cmd/cache.c Signed-off-by: Tom Rini --- arch/sh/cpu/sh4/cache.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/sh/cpu/sh4/cache.c b/arch/sh/cpu/sh4/cache.c index f0cb39d6a92..d3c480e79ed 100644 --- a/arch/sh/cpu/sh4/cache.c +++ b/arch/sh/cpu/sh4/cache.c @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -100,6 +101,11 @@ void icache_disable(void) cache_control(CACHE_DISABLE); } +void invalidate_icache_all(void) +{ + puts("No arch specific invalidate_icache_all available!\n"); +} + int icache_status(void) { return 0; From 34a0c164a5368099351fe63e86543ed0f6d394b7 Mon Sep 17 00:00:00 2001 From: Tom Rini Date: Wed, 19 Jun 2024 15:27:57 -0600 Subject: [PATCH 7/9] powerpc: Implement a default flush_dcache_all Implement a weak default version of flush_dcache_all which is based on the ARM default, which is to flush the entire range via flush_dcache_range(...). Acked-by: Ilias Apalodimas Signed-off-by: Tom Rini --- arch/powerpc/lib/cache.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/powerpc/lib/cache.c b/arch/powerpc/lib/cache.c index e480b269649..130318d745a 100644 --- a/arch/powerpc/lib/cache.c +++ b/arch/powerpc/lib/cache.c @@ -43,3 +43,12 @@ void flush_cache(ulong start_addr, ulong size) /* flush prefetch queue */ asm volatile("isync" : : : "memory"); } + +/* + * Default implementation: + * do a range flush for the entire range + */ +void flush_dcache_all(void) +{ + flush_dcache_range(0, ~0); +} From 280e54656f3e1a356baca02dc264d9d9407bf0a9 Mon Sep 17 00:00:00 2001 From: Tom Rini Date: Wed, 19 Jun 2024 15:27:58 -0600 Subject: [PATCH 8/9] powerpc: Add the old invalidate_icache_all function Add the old invalidate_icache_all function that prints a warning that was previously found in cmd/cache.c Signed-off-by: Tom Rini --- arch/powerpc/lib/cache.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/powerpc/lib/cache.c b/arch/powerpc/lib/cache.c index 130318d745a..a9cd7b8d30a 100644 --- a/arch/powerpc/lib/cache.c +++ b/arch/powerpc/lib/cache.c @@ -5,6 +5,7 @@ */ #include +#include #include #include @@ -52,3 +53,8 @@ void flush_dcache_all(void) { flush_dcache_range(0, ~0); } + +void invalidate_icache_all(void) +{ + puts("No arch specific invalidate_icache_all available!\n"); +} From 7d6cee2cd0e2e2507aca1e3a6fe0e2cb241a116e Mon Sep 17 00:00:00 2001 From: Tom Rini Date: Wed, 19 Jun 2024 15:27:59 -0600 Subject: [PATCH 9/9] cmd: cache: Remove weak functions It should be up to an architecture to decide how to implement cache functions, and if they need to use weak functions or not. Allowing the cache command to be built without cache functionality implemented is unhelpful. Further, guard the call to noncached_set_region with CONFIG_SYS_NONCACHED_MEMORY as that's when it's implemented and again is an architecture specific detail. Reviewed-by: Ilias Apalodimas Signed-off-by: Tom Rini --- cmd/cache.c | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/cmd/cache.c b/cmd/cache.c index 0254ff17f9b..7a2068296ef 100644 --- a/cmd/cache.c +++ b/cmd/cache.c @@ -13,16 +13,6 @@ static int parse_argv(const char *); -void __weak invalidate_icache_all(void) -{ - /* please define arch specific invalidate_icache_all */ - puts("No arch specific invalidate_icache_all available!\n"); -} - -__weak void noncached_set_region(void) -{ -} - static int do_icache(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { @@ -52,12 +42,6 @@ static int do_icache(struct cmd_tbl *cmdtp, int flag, int argc, return 0; } -void __weak flush_dcache_all(void) -{ - puts("No arch specific flush_dcache_all available!\n"); - /* please define arch specific flush_dcache_all */ -} - static int do_dcache(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { @@ -69,7 +53,9 @@ static int do_dcache(struct cmd_tbl *cmdtp, int flag, int argc, break; case 1: dcache_enable(); +#ifdef CONFIG_SYS_NONCACHED_MEMORY noncached_set_region(); +#endif break; case 2: flush_dcache_all();