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

Ivan Gorinov ivan.gorinov at intel.com
Thu Jun 14 00:36:26 UTC 2018


On Tue, Jun 12, 2018 at 05:57:34PM +0200, Heinrich Schuchardt wrote:
> On 06/06/2018 08:28 PM, Ivan Gorinov wrote:
> > Add setjmp/longjmp functions for x86_64.
> > The FPU control word and MXCSR control bits are preserved across calls.
> 
> With this patch
> 
> make mrproper && make qemu-x86_64_defconfig && make -j6
> 
> produces
> 
> arch/x86/cpu/built-in.o: In function `car_init':
> arch/x86/cpu/qemu/car.S:25: undefined reference to `car_init_ret'
> 
> The error does not occur without this patch.
> 
> The missing symbol is defined in
> arch/x86/cpu/start.S:98:car_init_ret:
> but it is not defined in
> arch/x86/cpu/start64.S
> 
> The following patch helps:
> 
> [PATCH 1/1] x86: qemu: do not build car.o with start64.o
> https://lists.denx.de/pipermail/u-boot/2018-June/331440.html

Thank you! Now it builds.

> But bootefi selftest with your patch leads to an immediate reset of the
> qemu-x86_64 board.

Reproduced the qemu-x86_64 reset.
The "info registers" command shows CR0.MP = 0.
Setting it in 64-bit startup code did not help.
I will try to fix that.

On a 64-bit Minnowboard configuration, bootefi works without reset.

> 
> Best regards
> 
> Heinrich
> 
> > 
> > Signed-off-by: Ivan Gorinov <ivan.gorinov at intel.com>
> > ---
> >  arch/x86/cpu/x86_64/setjmp.S  | 66 +++++++++++++++++++++++++++++++++++++++++++
> >  arch/x86/cpu/x86_64/setjmp.c  | 19 -------------
> >  arch/x86/include/asm/setjmp.h | 19 +++++++++++++
> >  3 files changed, 85 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..ef61a4a
> > --- /dev/null
> > +++ b/arch/x86/cpu/x86_64/setjmp.S
> > @@ -0,0 +1,66 @@
> > +/*
> > + * Copyright (C) 2018 Intel Corporation
> > + *
> > + * SPDX-License-Identifier: GPL-2.0+
> > + *
> > + * See arch/x86/include/asm/setjmp.h for jmp_buf format
> > + */
> > +
> > +#include <linux/linkage.h>
> > +
> > +.text
> > +.align 8
> > +
> > +ENTRY(setjmp)
> > +
> > +	pop	%rcx
> > +	movq	%rcx, (%rdi)	/* Return address */
> > +	movq	%rsp, 8 (%rdi)
> > +	movq	%rbp, 16 (%rdi)
> > +	movq	%rbx, 24 (%rdi)
> > +	movq	%r12, 32 (%rdi)
> > +	movq	%r13, 40 (%rdi)
> > +	movq	%r14, 48 (%rdi)
> > +	movq	%r15, 56 (%rdi)
> > +	fnstcw	64 (%rdi)
> > +	stmxcsr	68 (%rdi)
> > +	xorq	%rax, %rax	/* Direct invocation returns 0 */
> > +	jmpq	*%rcx
> > +
> > +ENDPROC(setjmp)
> > +
> > +.align 8
> > +
> > +ENTRY(longjmp)
> > +
> > +	subq	$8, %rsp
> > +
> > +/* Restore the control bits of MXCSR */
> > +
> > +	stmxcsr	(%rsp)
> > +	movl	$0x3f, %eax
> > +	andl	%eax, (%rsp)
> > +	notl	%eax
> > +	andl	68 (%rdi), %eax
> > +	orl	%eax, (%rsp)
> > +	ldmxcsr	(%rsp)
> > +
> > +	fldcw	64 (%rdi)
> > +
> > +	movq	(%rdi), %rcx	/* Return address */
> > +	movq	8 (%rdi), %rsp
> > +	movq	16 (%rdi), %rbp
> > +	movq	24 (%rdi), %rbx
> > +	movq	32 (%rdi), %r12
> > +	movq	40 (%rdi), %r13
> > +	movq	48 (%rdi), %r14
> > +	movq	56 (%rdi), %r15
> > +
> > +	movq	%rsi, %rax	/* Value to be returned by setjmp() */
> > +	testq	%rax, %rax	/* cannot be 0 in this case */
> > +	jnz	1f
> > +	incq	%rax		/* Return 1 instead */
> > +1:
> > +	jmpq	*%rcx
> > +
> > +ENDPROC(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..eae33fb 100644
> > --- a/arch/x86/include/asm/setjmp.h
> > +++ b/arch/x86/include/asm/setjmp.h
> > @@ -8,6 +8,23 @@
> >  #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;
> > +	unsigned int __fcw;
> > +	unsigned int __mxcsr;
> > +};
> > +
> > +#else
> > +
> >  struct jmp_buf_data {
> >  	unsigned int __ebx;
> >  	unsigned int __esp;
> > @@ -17,6 +34,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