[U-Boot] [PATCH] x86: Add 64-bit setjmp/longjmp implementation
Alexander Graf
agraf at suse.de
Sun Jun 3 12:06:47 UTC 2018
On 02.06.18 20:44, Heinrich Schuchardt wrote:
> On 05/31/2018 12:50 AM, Ivan Gorinov wrote:
>> Add setjmp/longjmp functions for x86_64,
>> based on existing 32-bit implementation.
>
> Thank you for your patch. This addresses a gap that really should be closed.
>
> Please, add a line to the commit message indicating the calling
> conventions that are supported. This is important because we use
> different calling conventions in different places.
>
> One function where we need setjmp() is efi_start_image(). The function
> is defined as EFIAPI. So we need an implementation supporting the ms_abi
> calling convention.
I don't quite follow. The calling convention is declared in the C header
(omitted means sysv, EFIAPI means ms). The compiler will adapt the call
to the respective convention automatically. So if you call a sysv
function from an EFIAPI function, gcc will push all registers that are
potentially getting clobbered on the stack.
So IIUC we really only need the sysv variant - which this patch
implements, right? This also shouldn't need any mentioning, as it's the
default throughout the code base, unless the function is annotated with
the EFIAPI tag.
Alex
>
> Another function where we use setjmp() is do_bootefi_exec() but this
> function is defined as sysv_abi.
>
> I guess the patch relates to the sysv_abi calling convention:
>
> "System V Application Binary Interface: AMD64 Architecture Processor
> Supplement (With LP64 and ILP32 Programming Models)"
> https://software.intel.com/sites/default/files/article/402129/mpx-linux64-abi.pdf
>
> This document contains the following sentence:
>
> The control bits of the MXCSR register are callee-saved (preserved
> across calls), while the status bits are caller-saved (not preserved).
> I cannot see that this is reflected in the patch.
>
> See also https://msdn.microsoft.com/en-us/library/36d3b75w.aspx
>
> Your setjmp implemantion is not usable for the ms_abi that we need in
> for efi_start_image(). Here you would have to save registers RBX, RBP,
> RDI, RSI, RSP, R12, R13, R14, and R15.
>
> As reference have a look at this implementation:
> https://github.com/freebsd/freebsd/blob/master/lib/libc/amd64/gen/setjmp.S
>
> Best regards
>
> Heinrich
>
>>
>> Signed-off-by: Ivan Gorinov <ivan.gorinov at intel.com>
>
>
>
>> ---
>> arch/x86/cpu/x86_64/setjmp.S | 56 +++++++++++++++++++++++++++++++++++++++++++
>> arch/x86/cpu/x86_64/setjmp.c | 19 ---------------
>> arch/x86/include/asm/setjmp.h | 17 +++++++++++++
>> 3 files changed, 73 insertions(+), 19 deletions(-)
>> create mode 100644 arch/x86/cpu/x86_64/setjmp.S
>> delete mode 100644 arch/x86/cpu/x86_64/setjmp.c
>>
>> diff --git a/arch/x86/cpu/x86_64/setjmp.S b/arch/x86/cpu/x86_64/setjmp.S
>> new file mode 100644
>> index 0000000..e10ee49
>> --- /dev/null
>> +++ b/arch/x86/cpu/x86_64/setjmp.S
>> @@ -0,0 +1,56 @@
>> +/*
>> + * Based on arch/x86/cpu/i386/setjmp.S by H. Peter Anvin <hpa at zytor.com>
>> + *
>> + * SPDX-License-Identifier: GPL-2.0
>> + */
>> +
>> +/*
>> + * The jmp_buf is assumed to contain the following, in order:
>> + * <return address>
>> + * %rsp
>> + * %rbp
>> + * %rbx
>> + * %r12
>> + * %r13
>> + * %r14
>> + * %r15
>> + */
>> +
>> +.text
>> +.align 8
>> +.globl setjmp
>> +.type setjmp, @function
>> +
>> +setjmp:
We have macros for asm provided functions (see arch/arm/lib/setjmp.S) to
ensure that linker based section elimination works. Please make sure you
use those.
Thanks,
Alex
>> + pop %rcx
>> + movq %rcx, (%rdi) /* Return address */
>> + movq %rsp, 8 (%rdi) /* Post-return %rsp! */
>> + movq %rbp, 16 (%rdi)
>> + movq %rbx, 24 (%rdi)
>> + movq %r12, 32 (%rdi)
>> + movq %r13, 40 (%rdi)
>> + movq %r14, 48 (%rdi)
>> + movq %r15, 56 (%rdi)
>> + xorq %rax, %rax /* Return value */
>> + jmpq *%rcx
>> +
>> +/* Provide function size if needed */
>> +.size setjmp, .-setjmp
>> +
>> +.align 8
>> +.globl longjmp
>> +.type longjmp, @function
>> +
>> +longjmp:
>> + movq 32 (%rdi), %r12
>> + movq 40 (%rdi), %r13
>> + movq 48 (%rdi), %r14
>> + movq 56 (%rdi), %r15
>> + movq 16 (%rdi), %rbp
>> + movq 24 (%rdi), %rbx
>> + movq 8 (%rdi), %rsp
>> + movq (%rdi), %rcx
>> + movq %rsi, %rdi
>> + jmpq *%rcx
>> +
>> + .size longjmp, .-longjmp
>> diff --git a/arch/x86/cpu/x86_64/setjmp.c b/arch/x86/cpu/x86_64/setjmp.c
>> deleted file mode 100644
>> index 5d4a74a..0000000
>> --- a/arch/x86/cpu/x86_64/setjmp.c
>> +++ /dev/null
>> @@ -1,19 +0,0 @@
>> -// SPDX-License-Identifier: GPL-2.0+
>> -/*
>> - * Copyright (c) 2016 Google, Inc
>> - */
>> -
>> -#include <common.h>
>> -#include <asm/setjmp.h>
>> -
>> -int setjmp(struct jmp_buf_data *jmp_buf)
>> -{
>> - printf("WARNING: setjmp() is not supported\n");
>> -
>> - return 0;
>> -}
>> -
>> -void longjmp(struct jmp_buf_data *jmp_buf, int val)
>> -{
>> - printf("WARNING: longjmp() is not supported\n");
>> -}
>> diff --git a/arch/x86/include/asm/setjmp.h b/arch/x86/include/asm/setjmp.h
>> index f25975f..49c36c1 100644
>> --- a/arch/x86/include/asm/setjmp.h
>> +++ b/arch/x86/include/asm/setjmp.h
>> @@ -8,6 +8,21 @@
>> #ifndef __setjmp_h
>> #define __setjmp_h
>>
>> +#ifdef CONFIG_X86_64
>> +
>> +struct jmp_buf_data {
>> + unsigned long __rip;
>> + unsigned long __rsp;
>> + unsigned long __rbp;
>> + unsigned long __rbx;
>> + unsigned long __r12;
>> + unsigned long __r13;
>> + unsigned long __r14;
>> + unsigned long __r15;
>> +};
>> +
>> +#else
>> +
>> struct jmp_buf_data {
>> unsigned int __ebx;
>> unsigned int __esp;
>> @@ -17,6 +32,8 @@ struct jmp_buf_data {
>> unsigned int __eip;
>> };
>>
>> +#endif
>> +
>> int setjmp(struct jmp_buf_data *jmp_buf);
>> void longjmp(struct jmp_buf_data *jmp_buf, int val);
>>
>>
>
More information about the U-Boot
mailing list