Message ID | 20240522-loongarch-v1-7-1407e0b69678@flygoat.com |
---|---|
State | Changes Requested |
Delegated to: | Tom Rini |
Headers | show |
Series | LoongArch initial support | expand |
On 5/22/24 17:34, Jiaxun Yang wrote: > Add some common library routines for the architecture. > > Signed-off-by: Jiaxun Yang <jiaxun.yang@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@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@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@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@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@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@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 >
在2024年6月16日六月 下午12:01,Heinrich Schuchardt写道: > On 5/22/24 17:34, Jiaxun Yang wrote: >> Add some common library routines for the architecture. >> >> Signed-off-by: Jiaxun Yang <jiaxun.yang@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@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@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@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@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. Yes, I haven't thought about that yet :-( As this series is only concerning QEMU machine, I left all cache stuff blank. I'll add it to future TODOs. Thanks - Jiaxun > >> +} >> + >> +__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 >
On 6/16/24 15:06, Jiaxun Yang wrote: > > > 在2024年6月16日六月 下午12:01,Heinrich Schuchardt写道: >> On 5/22/24 17:34, Jiaxun Yang wrote: >>> Add some common library routines for the architecture. >>> >>> Signed-off-by: Jiaxun Yang <jiaxun.yang@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@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@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@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@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. > > Yes, I haven't thought about that yet :-( > As this series is only concerning QEMU machine, I left all cache stuff blank. > > I'll add it to future TODOs. > > Thanks > - Jiaxun The "LoongArch Reference Manual" is available at: https://loongson.github.io/LoongArch-Documentation/LoongArch-Vol1-EN.html#_cacop What irritates me in 2.1.7.1. Cache Coherency Maintenance of Instruction Cache is the word *can*: The Cache coherency maintenance between the instruction Cache and the data Cache within the processor core *can* be implemented as hardware maintenance. Maybe you have to consult the Chinese version. 处理器核内部指令 Cache 与数据 Cache 之间的缓存一致性维护可以实现为硬件维护 The cache consistency maintenance between the instruction cache and data cache inside the processor core *can* be implemented as hardware maintenance. Best regards Heinrich > >> >>> +} >>> + >>> +__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 >> >
在2024年6月16日六月 下午5:00,Heinrich Schuchardt写道: [...] > The "LoongArch Reference Manual" is available at: > > https://loongson.github.io/LoongArch-Documentation/LoongArch-Vol1-EN.html#_cacop > > What irritates me in > 2.1.7.1. Cache Coherency Maintenance of Instruction Cache > is the word *can*: > > The Cache coherency maintenance between the instruction Cache and the > data Cache within the processor core *can* be implemented as hardware > maintenance. > > Maybe you have to consult the Chinese version. > > 处理器核内部指令 Cache 与数据 Cache 之间的缓存一致性维护可以实现为硬件维护 > > The cache consistency maintenance between the instruction cache and data > cache inside the processor core *can* be implemented as hardware > maintenance. Hi Heinrich, Thanks for the investigation! Impressive effort on decrypting Chinese semantics :-) I had consulted Loongson folks, and they told me that all current hardware implementation do have I/D cache coherency maintained by hardware, see implementation[1] in kernel. For dcache I'll implement it with cac_op. Thanks [1]: https://elixir.bootlin.com/linux/v6.9.5/source/arch/loongarch/mm/cache.c > > Best regards > > Heinrich
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@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@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@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@flygoat.com> + */ + +#include <cpu_func.h> +#include <asm/cache.h> +#include <asm/loongarch.h> + +void invalidate_icache_all(void) +{ + asm volatile ("\tibar 0\n"::); +} + +__weak void flush_dcache_all(void) +{ + asm volatile ("\tdbar 0\n"::); +} + +__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@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@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
Add some common library routines for the architecture. Signed-off-by: Jiaxun Yang <jiaxun.yang@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(+)