[PATCH v2 07/16] LoongArch: lib: General routines

Simon Glass sjg at chromium.org
Thu Jul 2 12:28:08 CEST 2026


Hi Yao,

On 2026-07-01T11:17:53, Yao Zi <me at ziyao.cc> wrote:
> LoongArch: lib: General routines
>
> Add some common library routines for the architecture.
>
> Signed-off-by: Jiaxun Yang <jiaxun.yang at flygoat.com>
> Signed-off-by: Yao Zi <me at ziyao.cc>
>
> arch/loongarch/include/asm/cache.h       |  10 ++
>  arch/loongarch/include/asm/global_data.h |   7 +
>  arch/loongarch/lib/Makefile              |   7 +
>  arch/loongarch/lib/asm-offsets.c         |  66 ++++++++++
>  arch/loongarch/lib/boot.c                |  14 ++
>  arch/loongarch/lib/cache.c               | 213 +++++++++++++++++++++++++++++++
>  arch/loongarch/lib/reset.c               |  14 ++
>  arch/loongarch/lib/setjmp.S              |  52 ++++++++
>  8 files changed, 383 insertions(+)

> Add some common library routines for the architecture.

Please expand the commit message: list what the routines are
(cache maintenance, setjmp/longjmp, asm-offsets, do_go_exec,
do_reset) and note that cache handling probes the hierarchy via
CPUCFG.

> diff --git a/arch/loongarch/lib/cache.c b/arch/loongarch/lib/cache.c
> @@ -0,0 +1,213 @@
> +static inline void flush_cache_line_index(unsigned int index,
> +                                       unsigned long addr)
> +{
> +#define do_flush(index)                                                      \
> +     case index:                                                     \
> +             cache_op(FIELD_PREP(CACHE_OP, CACHE_INDEX_INVWB) |      \
> +                      FIELD_PREP(CACHE_INDEX, index),                \
> +                      index);                                        \
> +             break;
> +
> +     switch (index) {
> +             do_flush(0);
> +             do_flush(1);
> +             do_flush(2);
> +             do_flush(3);
> +             do_flush(4);
> +             do_flush(5);
> +     }
> +
> +#undef do_flush
> +}

addr is silently dropped. Inside do_flush() the token index
resolves to the macro parameter (0..5, the cache identifier), so
cache_op() always gets the small constant as its address operand.
The way/set offset that flush_dcache_level_all() computes never
reaches the CACOP instruction, so this hammers way 0 / set 0 of
the selected cache repeatedly instead of walking it. Please pass
addr through (rename the macro parameter to avoid the shadow), and
confirm with a real by-index flush test.

> diff --git a/arch/loongarch/lib/cache.c b/arch/loongarch/lib/cache.c
> @@ -0,0 +1,213 @@
> +void probe_caches(void)
> +{
> +     unsigned int level = 0, index = 0;
> +     u32 cfg = read_cpucfg(LOONGARCH_CPUCFG16);
> +
> +     if (cfg & CPUCFG16_L1_IUPRE) {
> +             if (cfg & CPUCFG16_L1_IUUNIFY) {
> +                     gd->arch.dcache_index[level] = index;
> +                     populate_dcache_properties(cfg, level++,
> +                                                LOONGARCH_CPUCFG17);
> +             }
> +
> +             index++;
> +     }
> +
> +     if (cfg & CPUCFG16_L1_DPRE) {
> +             gd->arch.dcache_index[level] = index++;
> +             populate_dcache_properties(cfg, level++, LOONGARCH_CPUCFG18);
> +     }
> +
> +     cfg >>= 3;
> +
> +     for (; level < 3; level++) {

Please use CACHE_MAX_LEVEL rather than the bare 3.
populate_dcache_properties() also sets dcache_inclusive from cfg
whenever level != 0, but on the L1D path cfg is still CPUCFG16 -
the L1 inclusive bit describes L1I vs L1D, not L1D vs L2, so this
looks incorrect. Please double-check.

> diff --git a/arch/loongarch/include/asm/cache.h b/arch/loongarch/include/asm/cache.h
> @@ -15,6 +18,13 @@ void cache_flush(void);
> +#define CACHE_MAX_LEVEL              3
> +#define CACHE_MAX_INDEX              6

A short comment on what these two bounds represent (max dcache
levels tracked vs. max hardware cache-id encoded in CACOP) would
help - they are easy to confuse.

> diff --git a/arch/loongarch/lib/setjmp.S b/arch/loongarch/lib/setjmp.S
> @@ -0,0 +1,52 @@
> +ENTRY(setjmp)
> +     LONG_S          s0, a0, 0
> +     LONG_S          s1, a0, (1 * LONGSIZE)

Stray space after LONG_S here (and in longjmp). Please clean up.

Regards,
Simon


More information about the U-Boot mailing list