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

Heinrich Schuchardt xypron.glpk at gmx.de
Sun Jun 16 13:01:46 CEST 2024


On 5/22/24 17:34, Jiaxun Yang wrote:
> Add some common library routines for the architecture.
>
> Signed-off-by: Jiaxun Yang <jiaxun.yang at flygoat.com>
> ---
>   arch/loongarch/lib/Makefile      |  7 ++++
>   arch/loongarch/lib/asm-offsets.c | 66 ++++++++++++++++++++++++++++++++++++
>   arch/loongarch/lib/boot.c        | 14 ++++++++
>   arch/loongarch/lib/cache.c       | 73 ++++++++++++++++++++++++++++++++++++++++
>   arch/loongarch/lib/reset.c       | 14 ++++++++
>   arch/loongarch/lib/setjmp.S      | 52 ++++++++++++++++++++++++++++
>   6 files changed, 226 insertions(+)
>
> diff --git a/arch/loongarch/lib/Makefile b/arch/loongarch/lib/Makefile
> index 3dbed94cc624..3c17b9cd85af 100644
> --- a/arch/loongarch/lib/Makefile
> +++ b/arch/loongarch/lib/Makefile
> @@ -3,3 +3,10 @@
>   # Copyright (C) 2024 Jiaxun yang <jiaxun.yang at flygoat.com>
>   #
>
> +obj-$(CONFIG_CMD_GO) += boot.o
> +obj-y	+= cache.o
> +obj-y	+= interrupts.o
> +ifeq ($(CONFIG_$(SPL_)SYSRESET),)
> +obj-y	+= reset.o
> +endif
> +obj-y	+= setjmp.o
> diff --git a/arch/loongarch/lib/asm-offsets.c b/arch/loongarch/lib/asm-offsets.c
> new file mode 100644
> index 000000000000..e3f4c629b63d
> --- /dev/null
> +++ b/arch/loongarch/lib/asm-offsets.c
> @@ -0,0 +1,66 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright (C) 2024 Jiaxun Yang <jiaxun.yang at flygoat.com>
> + *
> + * From arch/x86/lib/asm-offsets.c
> + *
> + * This program is used to generate definitions needed by
> + * assembly language modules.
> + */
> +
> +#include <asm/global_data.h>
> +#include <asm/ptrace.h>
> +#include <linux/kbuild.h>
> +
> +static void __used output_ptreg_defines(void)
> +{
> +	COMMENT("LoongArch pt_regs offsets.");
> +	OFFSET(PT_R0, pt_regs, regs[0]);
> +	OFFSET(PT_R1, pt_regs, regs[1]);
> +	OFFSET(PT_R2, pt_regs, regs[2]);
> +	OFFSET(PT_R3, pt_regs, regs[3]);
> +	OFFSET(PT_R4, pt_regs, regs[4]);
> +	OFFSET(PT_R5, pt_regs, regs[5]);
> +	OFFSET(PT_R6, pt_regs, regs[6]);
> +	OFFSET(PT_R7, pt_regs, regs[7]);
> +	OFFSET(PT_R8, pt_regs, regs[8]);
> +	OFFSET(PT_R9, pt_regs, regs[9]);
> +	OFFSET(PT_R10, pt_regs, regs[10]);
> +	OFFSET(PT_R11, pt_regs, regs[11]);
> +	OFFSET(PT_R12, pt_regs, regs[12]);
> +	OFFSET(PT_R13, pt_regs, regs[13]);
> +	OFFSET(PT_R14, pt_regs, regs[14]);
> +	OFFSET(PT_R15, pt_regs, regs[15]);
> +	OFFSET(PT_R16, pt_regs, regs[16]);
> +	OFFSET(PT_R17, pt_regs, regs[17]);
> +	OFFSET(PT_R18, pt_regs, regs[18]);
> +	OFFSET(PT_R19, pt_regs, regs[19]);
> +	OFFSET(PT_R20, pt_regs, regs[20]);
> +	OFFSET(PT_R21, pt_regs, regs[21]);
> +	OFFSET(PT_R22, pt_regs, regs[22]);
> +	OFFSET(PT_R23, pt_regs, regs[23]);
> +	OFFSET(PT_R24, pt_regs, regs[24]);
> +	OFFSET(PT_R25, pt_regs, regs[25]);
> +	OFFSET(PT_R26, pt_regs, regs[26]);
> +	OFFSET(PT_R27, pt_regs, regs[27]);
> +	OFFSET(PT_R28, pt_regs, regs[28]);
> +	OFFSET(PT_R29, pt_regs, regs[29]);
> +	OFFSET(PT_R30, pt_regs, regs[30]);
> +	OFFSET(PT_R31, pt_regs, regs[31]);
> +	OFFSET(PT_CRMD, pt_regs, csr_crmd);
> +	OFFSET(PT_PRMD, pt_regs, csr_prmd);
> +	OFFSET(PT_EUEN, pt_regs, csr_euen);
> +	OFFSET(PT_ECFG, pt_regs, csr_ecfg);
> +	OFFSET(PT_ESTAT, pt_regs, csr_estat);
> +	OFFSET(PT_ERA, pt_regs, csr_era);
> +	OFFSET(PT_BVADDR, pt_regs, csr_badvaddr);
> +	OFFSET(PT_ORIG_A0, pt_regs, orig_a0);
> +	DEFINE(PT_SIZE, sizeof(struct pt_regs));
> +	BLANK();
> +}
> +
> +int main(void)
> +{
> +	output_ptreg_defines();
> +	return 0;
> +}
> diff --git a/arch/loongarch/lib/boot.c b/arch/loongarch/lib/boot.c
> new file mode 100644
> index 000000000000..327be16bb59f
> --- /dev/null
> +++ b/arch/loongarch/lib/boot.c
> @@ -0,0 +1,14 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright (C) 2024 Jiaxun Yang <jiaxun.yang at flygoat.com>
> + */
> +
> +#include <asm/u-boot.h>
> +
> +unsigned long do_go_exec(ulong (*entry)(int, char * const []),
> +			 int argc, char *const argv[])
> +{
> +	cleanup_before_linux();
> +
> +	return entry(argc, argv);
> +}
> diff --git a/arch/loongarch/lib/cache.c b/arch/loongarch/lib/cache.c
> new file mode 100644
> index 000000000000..54566edef8a3
> --- /dev/null
> +++ b/arch/loongarch/lib/cache.c
> @@ -0,0 +1,73 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright (C) 2024 Jiaxun Yang <jiaxun.yang at flygoat.com>
> + */
> +
> +#include <cpu_func.h>
> +#include <asm/cache.h>
> +#include <asm/loongarch.h>
> +
> +void invalidate_icache_all(void)
> +{
> +	asm volatile ("\tibar 0\n"::);

According to
https://loongson.github.io/LoongArch-Documentation/LoongArch-Vol1-EN.html#_dbar
this is not invalidating the instruction cache.

After loading an image into memory and before executing it we must
invalidate the instruction cache to ensure that the newly loaded code is
executed.

I guess you want to use CACOP here.

> +}
> +
> +__weak void flush_dcache_all(void)

In cmd/cache.c we have another __weak implementation. How is the linke:w
meant to know which one to use?

I guess we need to fix cmd/cache.c. But that is beyond the scope of this
series.

> +{
> +	asm volatile ("\tdbar 0\n"::);

CACOP?

Best regards

Heinrich

> +}
> +
> +__weak void flush_dcache_range(unsigned long start, unsigned long end)
> +{
> +	/* Placeholder */
> +	flush_dcache_all();
> +}
> +
> +__weak void invalidate_icache_range(unsigned long start, unsigned long end)
> +{
> +	/* LoongArch mandatory hardware I-Cache coherence */
> +	invalidate_icache_all();
> +}
> +
> +__weak void invalidate_dcache_range(unsigned long start, unsigned long end)
> +{
> +	/* Placeholder */
> +	flush_dcache_all();
> +}
> +
> +__weak void cache_flush(void)
> +{
> +	/* Placeholder */
> +	flush_dcache_all();
> +}
> +
> +__weak void cache_invalidate(void)
> +{
> +	/* Placeholder */
> +	flush_dcache_all();
> +}
> +
> +__weak void flush_cache(unsigned long addr, unsigned long size)
> +{
> +	cache_flush();
> +}
> +
> +__weak void dcache_enable(void)
> +{
> +}
> +
> +__weak void dcache_disable(void)
> +{
> +}
> +
> +__weak int dcache_status(void)
> +{
> +	return 0;
> +}
> +
> +__weak void enable_caches(void)
> +{
> +	cache_invalidate();
> +	/* Enable cache for direct address translation mode */
> +	csr_xchg64(1 << CSR_CRMD_DACM_SHIFT, CSR_CRMD_DACM, LOONGARCH_CSR_CRMD);
> +}
> diff --git a/arch/loongarch/lib/reset.c b/arch/loongarch/lib/reset.c
> new file mode 100644
> index 000000000000..ddf29ee41d95
> --- /dev/null
> +++ b/arch/loongarch/lib/reset.c
> @@ -0,0 +1,14 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright (C) 2024 Jiaxun Yang <jiaxun.yang at flygoat.com>
> + */
> +
> +#include <command.h>
> +#include <cpu_func.h>
> +
> +int do_reset(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
> +{
> +	reset_cpu();
> +
> +	return 0;
> +}
> diff --git a/arch/loongarch/lib/setjmp.S b/arch/loongarch/lib/setjmp.S
> new file mode 100644
> index 000000000000..12981d0013fa
> --- /dev/null
> +++ b/arch/loongarch/lib/setjmp.S
> @@ -0,0 +1,52 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * Copyright (C) 2024 Jiaxun Yang <jiaxun.yang at flygoat.com>
> + */
> +
> +#include <config.h>
> +#include <asm/asm.h>
> +#include <linux/linkage.h>
> +
> +.pushsection .text.setjmp, "ax"
> +ENTRY(setjmp)
> +	LONG_S		s0, a0, 0
> +	LONG_S 		s1, a0, (1 * LONGSIZE)
> +	LONG_S		s2, a0, (2 * LONGSIZE)
> +	LONG_S		s3, a0, (3 * LONGSIZE)
> +	LONG_S		s4, a0, (4 * LONGSIZE)
> +	LONG_S		s5, a0, (5 * LONGSIZE)
> +	LONG_S		s6, a0, (6 * LONGSIZE)
> +	LONG_S		s7, a0, (7 * LONGSIZE)
> +	LONG_S		s8, a0, (8 * LONGSIZE)
> +	LONG_S		fp, a0, (9 * LONGSIZE)
> +	LONG_S		sp, a0, (10 * LONGSIZE)
> +	LONG_S		ra, a0, (11 * LONGSIZE)
> +
> +	move		a0, zero
> +	ret
> +ENDPROC(setjmp)
> +.popsection
> +
> +.pushsection .text.longjmp, "ax"
> +ENTRY(longjmp)
> +	LONG_L		s0, a0, 0
> +	LONG_L 		s1, a0, (1 * LONGSIZE)
> +	LONG_L		s2, a0, (2 * LONGSIZE)
> +	LONG_L		s3, a0, (3 * LONGSIZE)
> +	LONG_L		s4, a0, (4 * LONGSIZE)
> +	LONG_L		s5, a0, (5 * LONGSIZE)
> +	LONG_L		s6, a0, (6 * LONGSIZE)
> +	LONG_L		s7, a0, (7 * LONGSIZE)
> +	LONG_L		s8, a0, (8 * LONGSIZE)
> +	LONG_L		fp, a0, (9 * LONGSIZE)
> +	LONG_L		sp, a0, (10 * LONGSIZE)
> +	LONG_L		ra, a0, (11 * LONGSIZE)
> +
> +	/* Move the return value in place, but return 1 if passed 0. */
> +	li.w		a0, 1
> +	beqz		a1, 1f
> +	move		a0, a1
> +1:
> +	jr		ra
> +ENDPROC(longjmp)
> +.popsection
>



More information about the U-Boot mailing list