[PATCH v2 2/2] common/memsize.c: Fix get_ram_size() when cache is enabled
Michael Nazzareno Trimarchi
michael at amarulasolutions.com
Tue May 30 15:42:18 CEST 2023
Hi
Few questions
On Tue, May 30, 2023 at 3:34 PM Francesco Dolcini <francesco at dolcini.it> wrote:
>
> From: Emanuele Ghidoli <emanuele.ghidoli at toradex.com>
>
> Ensure that every write is flushed to memory and afterward reads are
> from memory.
> Since the algorithm rely on the fact that accessing to not existent
> memory lead to write at addr / 2 without this modification accesses
> to aliased (not physically present) addresses are cached and
> wrong size is returned.
>
> This was discovered while working on a TI AM625 based board
> where cache is normally enabled, see commit c02712a74849 ("arm: mach-k3: Enable dcache in SPL").
>
> Signed-off-by: Emanuele Ghidoli <emanuele.ghidoli at toradex.com>
> Signed-off-by: Francesco Dolcini <francesco.dolcini at toradex.com>
> ---
> v2:
> * check if CONFIG_SYS_CACHELINE_SIZE is defined
> * do flush only when cache is enabled
> ---
> common/memsize.c | 24 ++++++++++++++++++++++++
> 1 file changed, 24 insertions(+)
>
> diff --git a/common/memsize.c b/common/memsize.c
> index 66d5be6a1ff3..d646df8b04cb 100644
> --- a/common/memsize.c
> +++ b/common/memsize.c
> @@ -7,9 +7,18 @@
> #include <common.h>
> #include <init.h>
> #include <asm/global_data.h>
> +#include <cpu_func.h>
> +#include <stdint.h>
>
> DECLARE_GLOBAL_DATA_PTR;
>
> +#ifdef CONFIG_SYS_CACHELINE_SIZE
> +# define MEMSIZE_CACHELINE_SIZE CONFIG_SYS_CACHELINE_SIZE
> +#else
> +/* Just use the greatest cache flush alignment requirement I'm aware of */
> +# define MEMSIZE_CACHELINE_SIZE 128
> +#endif
> +
> #ifdef __PPC__
> /*
> * At least on G2 PowerPC cores, sequential accesses to non-existent
> @@ -20,6 +29,15 @@ DECLARE_GLOBAL_DATA_PTR;
> # define sync() /* nothing */
> #endif
>
> +static void dcache_flush_invalidate(volatile long *p)
> +{
> + uintptr_t start, stop;
> + start = ALIGN_DOWN((uintptr_t)p, MEMSIZE_CACHELINE_SIZE);
> + stop = start + MEMSIZE_CACHELINE_SIZE;
> + flush_dcache_range(start, stop);
> + invalidate_dcache_range(start, stop);
> +}
> +
> /*
> * Check memory range for valid RAM. A simple memory test determines
> * the actually available RAM size between addresses `base' and
> @@ -34,6 +52,7 @@ long get_ram_size(long *base, long maxsize)
> long val;
> long size;
> int i = 0;
> + int dcache_en = dcache_status();
>
> for (cnt = (maxsize / sizeof(long)) >> 1; cnt > 0; cnt >>= 1) {
> addr = base + cnt; /* pointer arith! */
> @@ -41,6 +60,8 @@ long get_ram_size(long *base, long maxsize)
> save[i++] = *addr;
> sync();
> *addr = ~cnt;
> + if (dcache_en)
> + dcache_flush_invalidate(addr);
Why this should be done on every increment if the invalidate keep a
range of address?
> }
>
> addr = base;
> @@ -50,6 +71,9 @@ long get_ram_size(long *base, long maxsize)
> *addr = 0;
>
> sync();
> + if (dcache_en)
> + dcache_flush_invalidate(addr);
> +
> if ((val = *addr) != 0) {
> /* Restore the original data before leaving the function. */
> sync();
Can be possible just to enable/disable cache around memory test?
Michael
> --
> 2.25.1
>
--
Michael Nazzareno Trimarchi
Co-Founder & Chief Executive Officer
M. +39 347 913 2170
michael at amarulasolutions.com
__________________________________
Amarula Solutions BV
Joop Geesinkweg 125, 1114 AB, Amsterdam, NL
T. +31 (0)85 111 9172
info at amarulasolutions.com
www.amarulasolutions.com
More information about the U-Boot
mailing list