From f822403f0164be74a5161b65698d0f01f4556234 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 17 Oct 2016 20:29:07 -0600 Subject: [PATCH] x86: Add implementations of setjmp() and longjmp() Bring in these functions from Linux v4.4. They will be needed for EFI loader support. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- arch/x86/cpu/Makefile | 2 +- arch/x86/cpu/setjmp.S | 61 +++++++++++++++++++++++++++++++++++ arch/x86/include/asm/setjmp.h | 24 ++++++++++++++ 3 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 arch/x86/cpu/setjmp.S create mode 100644 arch/x86/include/asm/setjmp.h diff --git a/arch/x86/cpu/Makefile b/arch/x86/cpu/Makefile index 2667e0b478..f5b8c9e363 100644 --- a/arch/x86/cpu/Makefile +++ b/arch/x86/cpu/Makefile @@ -10,7 +10,7 @@ extra-y = start.o obj-$(CONFIG_X86_RESET_VECTOR) += resetvec.o start16.o -obj-y += interrupts.o cpu.o cpu_x86.o call64.o +obj-y += interrupts.o cpu.o cpu_x86.o call64.o setjmp.o AFLAGS_REMOVE_call32.o := -mregparm=3 \ $(if $(CONFIG_EFI_STUB_64BIT),-march=i386 -m32) diff --git a/arch/x86/cpu/setjmp.S b/arch/x86/cpu/setjmp.S new file mode 100644 index 0000000000..2ea1c6c766 --- /dev/null +++ b/arch/x86/cpu/setjmp.S @@ -0,0 +1,61 @@ +/* + * Written by H. Peter Anvin + * Brought in from Linux v4.4 and modified for U-Boot + * From Linux arch/um/sys-i386/setjmp.S + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#define _REGPARM + +/* + * The jmp_buf is assumed to contain the following, in order: + * %ebx + * %esp + * %ebp + * %esi + * %edi + * + */ + + .text + .align 4 + .globl setjmp + .type setjmp, @function +setjmp: +#ifdef _REGPARM + movl %eax, %edx +#else + movl 4(%esp), %edx +#endif + popl %ecx /* Return address, and adjust the stack */ + xorl %eax, %eax /* Return value */ + movl %ebx, (%edx) + movl %esp, 4(%edx) /* Post-return %esp! */ + pushl %ecx /* Make the call/return stack happy */ + movl %ebp, 8(%edx) + movl %esi, 12(%edx) + movl %edi, 16(%edx) + movl %ecx, 20(%edx) /* Return address */ + ret + + /* Provide function size if needed */ + .size setjmp, .-setjmp + + .align 4 + .globl longjmp + .type longjmp, @function +longjmp: +#ifdef _REGPARM + xchgl %eax, %edx +#else + movl 4(%esp), %edx /* jmp_ptr address */ +#endif + movl (%edx), %ebx + movl 4(%edx), %esp + movl 8(%edx), %ebp + movl 12(%edx), %esi + movl 16(%edx), %edi + jmp *20(%edx) + + .size longjmp, .-longjmp diff --git a/arch/x86/include/asm/setjmp.h b/arch/x86/include/asm/setjmp.h new file mode 100644 index 0000000000..1feaa892ad --- /dev/null +++ b/arch/x86/include/asm/setjmp.h @@ -0,0 +1,24 @@ +/* + * Written by H. Peter Anvin + * Brought in from Linux v4.4 and modified for U-Boot + * From Linux arch/um/sys-i386/setjmp.S + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#ifndef __setjmp_h +#define __setjmp_h + +struct jmp_buf_data { + unsigned int __ebx; + unsigned int __esp; + unsigned int __ebp; + unsigned int __esi; + unsigned int __edi; + unsigned int __eip; +}; + +int setjmp(struct jmp_buf_data *jmp_buf); +void longjmp(struct jmp_buf_data *jmp_buf, int val); + +#endif -- 2.39.5