[U-Boot] [PATCH] x86: Add 64-bit setjmp/longjmp implementation

Alexander Graf agraf at suse.de
Wed Jun 6 08:17:52 UTC 2018



On 05.06.18 19:56, Ivan Gorinov wrote:
> On Sun, Jun 03, 2018 at 02:06:47PM +0200, Alexander Graf wrote:
>> 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.
> 
> I can confirm that gcc does save %rsi and %rdi in EFIAPI functions before
> using those two registers for setjmp() parameters. The other callee-saved
> registers in ms_abi are also callee-saved in sysv and correctly handled by
> the proposed implementation.
> 
> static efi_status_t EFIAPI efi_start_image(efi_handle_t image_handle,
> 					   unsigned long *exit_data_size,
> 					   s16 **exit_data)
> {
>     5f03ce56:	57                   	push   %rdi
>     5f03ce57:	56                   	push   %rsi
> 
>     ...
> 
> 	/* call the image! */
> 	if (setjmp(&info->exit_jmp)) {
>     5f03cecd:	48 8b 84 24 f0 00 00 	mov    0xf0(%rsp),%rax
>     5f03ced4:	00 
>     5f03ced5:	48 8d 78 78          	lea    0x78(%rax),%rdi
>     5f03ced9:	e8 82 32 fc ff       	callq  5f000160 <setjmp>
>     5f03cede:	85 c0                	test   %eax,%eax
>     5f03cee0:	74 1b                	je     5f03cefd <efi_start_image+0xa7>
> 
>     ...
> 
>> 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.
> 
>>> 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.
> 
> Thank you for the link! I will add MXCSR to the callee-saved register set.
> 
>>> 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
>>>
>>>>
>>>> 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.
> 
> OK. Shall I also add .pushsection/.popsection?
> Can't find any example in arch/x86/

The ENTRY/ENDPROC macros are architecture agnostic, so you should just
be able to use them exactly like in the arm example above.


Alex


More information about the U-Boot mailing list