All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH v2] x86: Add 64-bit setjmp/longjmp implementation
@ 2018-06-06 18:27 Ivan Gorinov
  0 siblings, 0 replies; 7+ messages in thread
From: Ivan Gorinov @ 2018-06-06 18:27 UTC (permalink / raw)
  To: u-boot

Add setjmp/longjmp functions for x86_64.
The FPU control word and MXCSR control bits are preserved across calls.

v2:
  Added the FPU control word and MXCSR to jmp_buf;
  Using ENTRY/ENDPROC macros.

Ivan Gorinov (1):
  x86: Add 64-bit setjmp/longjmp implementation

 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

-- 
2.7.4

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [U-Boot] [PATCH v2] x86: Add 64-bit setjmp/longjmp implementation
  2018-06-06 18:28 Ivan Gorinov
  2018-06-12 15:57 ` Heinrich Schuchardt
@ 2018-06-19  8:02 ` Bin Meng
  1 sibling, 0 replies; 7+ messages in thread
From: Bin Meng @ 2018-06-19  8:02 UTC (permalink / raw)
  To: u-boot

Hi Ivan,

On Thu, Jun 7, 2018 at 2:28 AM, Ivan Gorinov <ivan.gorinov@intel.com> wrote:
> Add setjmp/longjmp functions for x86_64.
> The FPU control word and MXCSR control bits are preserved across calls.
>
> Signed-off-by: Ivan Gorinov <ivan.gorinov@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+

This line should be put at the first line of this file, otherwise it
causes checkpatch to report warnings.

> + *
> + * 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)

nits: can we eliminate the space between 8 and (%edi)? and others in
this file too?

> +       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)

I don't think we need worry about these FP registers as U-Boot does
not enable them at all. It looks your v1 patch does not include this
but was added in v2. See the 32-bit setjmp/longjmp() implementation in
U-Boot and there is no FP save/restore too.

> +       xorq    %rax, %rax      /* Direct invocation returns 0 */
> +       jmpq    *%rcx
> +
> +ENDPROC(setjmp)
> +
> +.align 8
> +
> +ENTRY(longjmp)
> +
> +       subq    $8, %rsp
> +
> +/* Restore the control bits of MXCSR */

nits: comment indention should align to the assembly code

> +
> +       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);
>
> --

Regards,
Bin

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [U-Boot] [PATCH v2] x86: Add 64-bit setjmp/longjmp implementation
  2018-06-14 17:15     ` Ivan Gorinov
@ 2018-06-14 17:49       ` Alexander Graf
  0 siblings, 0 replies; 7+ messages in thread
From: Alexander Graf @ 2018-06-14 17:49 UTC (permalink / raw)
  To: u-boot



> Am 14.06.2018 um 19:15 schrieb Ivan Gorinov <ivan.gorinov@intel.com>:
> 
> On Wed, Jun 13, 2018 at 05:36:26PM -0700, Ivan Gorinov wrote:
> 
>>> 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.
> 
> The "bootefi selftest" command works on qemu-x86_64 when $loadaddr is changed:
>  => env set loadaddr 0x10000000
> 
> Another patch "x86: use EFI calling convention for efi_main on x86_64"
> also needs to be applied.
> 
> The self test starts but crashes on 'manage protocols':
> 
>  Tearing down 'graphical output'
>  Tearing down 'graphical output' succeeded
> 
>  Setting up 'manage protocols'
> 
> 
> Same effect with a 64-bit build for Minnowboard.

I see the same with the sandbox patch set I just sent. IIUC sonething goes wrong in varargs handling.

Alex

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [U-Boot] [PATCH v2] x86: Add 64-bit setjmp/longjmp implementation
  2018-06-14  0:36   ` Ivan Gorinov
@ 2018-06-14 17:15     ` Ivan Gorinov
  2018-06-14 17:49       ` Alexander Graf
  0 siblings, 1 reply; 7+ messages in thread
From: Ivan Gorinov @ 2018-06-14 17:15 UTC (permalink / raw)
  To: u-boot

On Wed, Jun 13, 2018 at 05:36:26PM -0700, Ivan Gorinov wrote:

> > 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.

The "bootefi selftest" command works on qemu-x86_64 when $loadaddr is changed:
  => env set loadaddr 0x10000000

Another patch "x86: use EFI calling convention for efi_main on x86_64"
also needs to be applied.

The self test starts but crashes on 'manage protocols':

  Tearing down 'graphical output'
  Tearing down 'graphical output' succeeded

  Setting up 'manage protocols'


Same effect with a 64-bit build for Minnowboard.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [U-Boot] [PATCH v2] x86: Add 64-bit setjmp/longjmp implementation
  2018-06-12 15:57 ` Heinrich Schuchardt
@ 2018-06-14  0:36   ` Ivan Gorinov
  2018-06-14 17:15     ` Ivan Gorinov
  0 siblings, 1 reply; 7+ messages in thread
From: Ivan Gorinov @ 2018-06-14  0:36 UTC (permalink / raw)
  To: u-boot

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@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);
> >  
> > 

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [U-Boot] [PATCH v2] x86: Add 64-bit setjmp/longjmp implementation
  2018-06-06 18:28 Ivan Gorinov
@ 2018-06-12 15:57 ` Heinrich Schuchardt
  2018-06-14  0:36   ` Ivan Gorinov
  2018-06-19  8:02 ` Bin Meng
  1 sibling, 1 reply; 7+ messages in thread
From: Heinrich Schuchardt @ 2018-06-12 15:57 UTC (permalink / raw)
  To: u-boot

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

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

Best regards

Heinrich

> 
> Signed-off-by: Ivan Gorinov <ivan.gorinov@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);
>  
> 

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [U-Boot] [PATCH v2] x86: Add 64-bit setjmp/longjmp implementation
@ 2018-06-06 18:28 Ivan Gorinov
  2018-06-12 15:57 ` Heinrich Schuchardt
  2018-06-19  8:02 ` Bin Meng
  0 siblings, 2 replies; 7+ messages in thread
From: Ivan Gorinov @ 2018-06-06 18:28 UTC (permalink / raw)
  To: u-boot

Add setjmp/longjmp functions for x86_64.
The FPU control word and MXCSR control bits are preserved across calls.

Signed-off-by: Ivan Gorinov <ivan.gorinov@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);
 
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2018-06-19  8:02 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-06-06 18:27 [U-Boot] [PATCH v2] x86: Add 64-bit setjmp/longjmp implementation Ivan Gorinov
2018-06-06 18:28 Ivan Gorinov
2018-06-12 15:57 ` Heinrich Schuchardt
2018-06-14  0:36   ` Ivan Gorinov
2018-06-14 17:15     ` Ivan Gorinov
2018-06-14 17:49       ` Alexander Graf
2018-06-19  8:02 ` Bin Meng

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.