Implement setjmp with o32/n64 ABI's standard stack frame. Note that those two ABIs slightly disagreed on placement of registers so they are being implemented in two different files.
Signed-off-by: Jiaxun Yang <jiaxun.y...@flygoat.com> --- arch/mips/include/asm/setjmp.h | 36 +++++++++++++++++++++++++++ arch/mips/lib/Makefile | 2 ++ arch/mips/lib/setjmp32.S | 51 ++++++++++++++++++++++++++++++++++++++ arch/mips/lib/setjmp64.S | 56 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 145 insertions(+) diff --git a/arch/mips/include/asm/setjmp.h b/arch/mips/include/asm/setjmp.h new file mode 100644 index 000000000000..afa2ffb007e6 --- /dev/null +++ b/arch/mips/include/asm/setjmp.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) 2024 Jiaxun Yang <jiaxun.y...@flygoat.com> + */ + +#ifndef _SETJMP_H_ +#define _SETJMP_H_ 1 + +/* + * This really should be opaque, but the EFI implementation wrongly + * assumes that a 'struct jmp_buf_data' is defined. + */ +#if __mips == 64 +struct jmp_buf_data { + unsigned long ra; + unsigned long sp; + unsigned long fp; + unsigned long gp; + unsigned long s_regs[8]; /* s0 - s7 */ +}; +#else +struct jmp_buf_data { + unsigned long ra; + unsigned long sp; + unsigned long s_regs[8]; /* s0 - s7 */ + unsigned long fp; + unsigned long gp; +}; +#endif + +typedef struct jmp_buf_data jmp_buf[1]; + +int setjmp(jmp_buf jmp); +void longjmp(jmp_buf jmp, int ret); + +#endif /* _SETJMP_H_ */ diff --git a/arch/mips/lib/Makefile b/arch/mips/lib/Makefile index 1621cc9a1ff9..e36dfd0547b5 100644 --- a/arch/mips/lib/Makefile +++ b/arch/mips/lib/Makefile @@ -10,6 +10,8 @@ obj-y += reloc.o obj-y += stack.o obj-y += traps.o +obj-$(CONFIG_32BIT) += setjmp32.o +obj-$(CONFIG_64BIT) += setjmp64.o obj-$(CONFIG_CMD_BOOTM) += bootm.o obj-$(CONFIG_CMD_GO) += boot.o obj-$(CONFIG_SPL_BUILD) += spl.o diff --git a/arch/mips/lib/setjmp32.S b/arch/mips/lib/setjmp32.S new file mode 100644 index 000000000000..4a2661d29249 --- /dev/null +++ b/arch/mips/lib/setjmp32.S @@ -0,0 +1,51 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) 2024 Jiaxun Yang <jiaxun.y...@flygoat.com> + */ + +#include <linux/linkage.h> +#include <asm/regdef.h> + +.pushsection .text.setjmp, "ax" +ENTRY(setjmp) + sw ra, 0(a0) + sw sp, 4(a0) + sw s0, 8(a0) + sw s1, 12(a0) + sw s2, 16(a0) + sw s3, 20(a0) + sw s4, 24(a0) + sw s5, 28(a0) + sw s6, 32(a0) + sw s7, 36(a0) + sw fp, 40(a0) + sw gp, 44(a0) + + move v0, zero + jr ra +ENDPROC(setjmp) +.popsection + +.pushsection .text.longjmp, "ax" +ENTRY(longjmp) + lw ra, 0(a0) + lw sp, 4(a0) + lw s0, 8(a0) + lw s1, 12(a0) + lw s2, 16(a0) + lw s3, 20(a0) + lw s4, 24(a0) + lw s5, 28(a0) + lw s6, 32(a0) + lw s7, 36(a0) + lw fp, 40(a0) + lw gp, 44(a0) + + beqz a1, 1f + move v0, a1 + jr ra +1: + li v0, 1 + jr ra +ENDPROC(longjmp) +.popsection diff --git a/arch/mips/lib/setjmp64.S b/arch/mips/lib/setjmp64.S new file mode 100644 index 000000000000..6f615bb10014 --- /dev/null +++ b/arch/mips/lib/setjmp64.S @@ -0,0 +1,56 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved. + * Copyright (c) 2017 Lemote Co.Ltd + * Author: Heiher <r...@hev.cc> + * Copyright (c) 2024 Jiaxun Yang <jiaxun.y...@flygoat.com> + */ + +#include <linux/linkage.h> +#include <asm/regdef.h> + +.pushsection .text.setjmp, "ax" +ENTRY(setjmp) + sd ra, 0x00(a0) + sd sp, 0x08(a0) + sd fp, 0x10(a0) + sd gp, 0x18(a0) + + sd s0, 0x20(a0) + sd s1, 0x28(a0) + sd s2, 0x30(a0) + sd s3, 0x38(a0) + sd s4, 0x40(a0) + sd s5, 0x48(a0) + sd s6, 0x50(a0) + sd s7, 0x58(a0) + + move v0, zero + jr ra +ENDPROC(setjmp) +.popsection + +.pushsection .text.longjmp, "ax" +ENTRY(longjmp) + ld ra, 0x00(a0) + ld sp, 0x08(a0) + ld fp, 0x10(a0) + ld gp, 0x18(a0) + + ld s0, 0x20(a0) + ld s1, 0x28(a0) + ld s2, 0x30(a0) + ld s3, 0x38(a0) + ld s4, 0x40(a0) + ld s5, 0x48(a0) + ld s6, 0x50(a0) + ld s7, 0x58(a0) + + beqz a1, 1f + move v0, a1 + jr ra +1: + li v0, 1 + jr ra +ENDPROC(longjmp) +.popsection -- 2.34.1