barebox_riscv_entry() is a naked function that switches the stack with inline assembly and then continues in C. GCC only supports basic asm in naked functions and clang rejects anything else outright.
Let's move the stack switch into an assembly __barebox_riscv_entry() like on ARM. barebox_riscv_entry() becomes an always inlined function, so the naked ENTRY_FUNCTION()s, which may run without a stack, can still call it. Assisted-by: Claude:opus-5.5 Signed-off-by: Ahmad Fatoum <[email protected]> --- arch/riscv/boot/Makefile | 2 +- arch/riscv/boot/entry.c | 31 -------------------------- arch/riscv/boot/entry_ll.S | 15 +++++++++++++ arch/riscv/include/asm/barebox-riscv.h | 30 ++++++++++++++++++++++--- 4 files changed, 43 insertions(+), 35 deletions(-) delete mode 100644 arch/riscv/boot/entry.c create mode 100644 arch/riscv/boot/entry_ll.S diff --git a/arch/riscv/boot/Makefile b/arch/riscv/boot/Makefile index 936f6e2e0391..2cd6f098d5ef 100644 --- a/arch/riscv/boot/Makefile +++ b/arch/riscv/boot/Makefile @@ -1,4 +1,4 @@ # SPDX-License-Identifier: GPL-2.0 -pbl-y += entry.o uncompress.o +pbl-y += entry_ll.o uncompress.o pbl-y += nmon_entry.o pbl-$(CONFIG_BOARD_GENERIC_DT) += board-dt-2nd.o diff --git a/arch/riscv/boot/entry.c b/arch/riscv/boot/entry.c deleted file mode 100644 index f5a536fc78a9..000000000000 --- a/arch/riscv/boot/entry.c +++ /dev/null @@ -1,31 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#include <types.h> - -#include <asm/barebox-riscv.h> - -#include "entry.h" -#include <debug_ll.h> - -/* - * Main RISC-V entry point. Call this with the memory region you can - * spare for barebox. This doesn't necessarily have to be the full - * SDRAM. The currently running binary can be inside or outside of - * this region. The PBL can be running inside or outside of this - * region. - * - * -> membase + memsize - * STACK_SIZE - stack - * 128KiB - early memory space - * -> maximum end of barebox binary - */ - -void __noreturn __naked barebox_riscv_entry(unsigned long membase, - unsigned long memsize, void *boarddata, - unsigned flags) -{ - unsigned long stack_top = riscv_mem_stack_top(membase, membase + memsize); - asm volatile ("move sp, %0" : : "r"(stack_top)); - riscv_set_flags(flags); - barebox_pbl_start(membase, memsize, boarddata); -} - diff --git a/arch/riscv/boot/entry_ll.S b/arch/riscv/boot/entry_ll.S new file mode 100644 index 000000000000..3611d72a3a78 --- /dev/null +++ b/arch/riscv/boot/entry_ll.S @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <linux/linkage.h> + +/* + * a0: memory base + * a1: memory size + * a2: board data + * a3: new value for SP + */ +.section .text.__barebox_riscv_entry +ENTRY(__barebox_riscv_entry) + mv sp, a3 + tail barebox_pbl_start +ENDPROC(__barebox_riscv_entry) diff --git a/arch/riscv/include/asm/barebox-riscv.h b/arch/riscv/include/asm/barebox-riscv.h index 9fdffb213e8c..4a7726ddc508 100644 --- a/arch/riscv/include/asm/barebox-riscv.h +++ b/arch/riscv/include/asm/barebox-riscv.h @@ -25,9 +25,6 @@ #include <asm/reloc.h> #include <pbl/handoff-data.h> -void __noreturn __naked barebox_riscv_entry(unsigned long membase, unsigned long memsize, - void *boarddata, unsigned int flags); - #define barebox_riscv_machine_entry(membase, memsize, boarddata) \ barebox_riscv_entry(membase, memsize, boarddata, RISCV_M_MODE) @@ -82,6 +79,33 @@ static inline unsigned long riscv_mem_barebox_image(unsigned long membase, return ALIGN_DOWN(endmem - size, SZ_1M); } +void __noreturn __barebox_riscv_entry(unsigned long membase, + unsigned long memsize, void *boarddata, + unsigned long sp); + +/* + * Main RISC-V entry point. Call this with the memory region you can + * spare for barebox. This doesn't necessarily have to be the full + * SDRAM. The currently running binary can be inside or outside of + * this region. The PBL can be running inside or outside of this + * region. + * + * -> membase + memsize + * STACK_SIZE - stack + * 128KiB - early memory space + * -> maximum end of barebox binary + * + * Inline, so naked ENTRY_FUNCTION()s can call it without a stack. + */ +static __always_inline void __noreturn +barebox_riscv_entry(unsigned long membase, unsigned long memsize, + void *boarddata, unsigned int flags) +{ + riscv_set_flags(flags); + __barebox_riscv_entry(membase, memsize, boarddata, + riscv_mem_stack_top(membase, membase + memsize)); +} + #define ENTRY_FUNCTION(name, arg0, arg1, arg2) \ void name (ulong r0, ulong r1, ulong r2); \ static void __##name(ulong, ulong, ulong); \ -- 2.47.3
