x86: Add 64-bit setjmp/longjmp implementation
PATCH v2 1/1 x86: Add 64-bit setjmp/longjmp implementation
Add setjmp/longjmp functions for x86_64.
The FPU control word and MXCSR control bits are preserved across calls.
--- 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
arch/x86/cpu/x86_64/setjmp.S new file +66 -0
@@ -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)
arch/x86/cpu/x86_64/setjmp.c deleted +0 -19
@@ -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" ); -}
arch/x86/include/asm/setjmp.h +19 -0
@@ -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);
Signature · 1 line
2.7.4
PATCH v2 1/1 x86: Add 64-bit setjmp/longjmp implementation
Quoted 2 lines · Ivan Gorinov
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 inarch/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
Quoted 145 lines
Signed-off-by Ivan Gorinov <[email protected]>--- 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.carch/x86/cpu/x86_64/setjmp.S new file +66
-0@@ -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)arch/x86/cpu/x86_64/setjmp.c deleted +0
-19@@ -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" ); -}arch/x86/include/asm/setjmp.h +19
-0@@ -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);
PATCH v2 1/1 x86: Add 64-bit setjmp/longjmp implementation
Quoted 20 lines · Heinrich Schuchardt
Quoted 2 lines · Ivan Gorinov
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 inarch/x86/cpu/start64.S
Quoted 4 lines
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.
Quoted 2 lines
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.
Quoted 150 lines
Best regards
Heinrich
Quoted 145 lines
Signed-off-by Ivan Gorinov <[email protected]>--- 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.carch/x86/cpu/x86_64/setjmp.S new file +66
-0@@ -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)arch/x86/cpu/x86_64/setjmp.c deleted +0
-19@@ -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" ); -}arch/x86/include/asm/setjmp.h +19
-0@@ -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);
PATCH v2 1/1 x86: Add 64-bit setjmp/longjmp implementation
Quoted 9 lines · Ivan Gorinov
Quoted 2 lines
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.
PATCH v2 1/1 x86: Add 64-bit setjmp/longjmp implementation
Quoted 24 lines
Am 14.06.2018 um 19:15 schrieb Ivan Gorinov <[email protected]>:
Quoted 9 lines · Ivan Gorinov
Quoted 2 lines
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 loadaddr0x10000000Another patch "x86: use EFI calling convention for
efi_mainonx86_64" also needs to be applied.The self test starts but crashes on 'manage protocols':
Quoted 7 lines
Tearing down 'graphical output'
Tearing down 'graphical output' succeededSetting 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
PATCH v2 1/1 x86: Add 64-bit setjmp/longjmp implementation
In reply to Ivan GorinovHi Ivan,
Quoted 18 lines · Ivan Gorinov
Add setjmp/longjmp functions for
x86_64.
The FPU control word and MXCSR control bits are preserved across calls.Signed-off-by Ivan Gorinov <[email protected]>--- 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.carch/x86/cpu/x86_64/setjmp.S new file +0
-0
arch/x86/cpu/x86_64/setjmp.S line 4
Quoted 4 lines
arch/x86/cpu/x86_64/setjmp.S new file +4
-0@@ -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.
Quoted 4 lines
arch/x86/cpu/x86_64/setjmp.S new file +4
-0+ * + * See arch/x86/include/asm/setjmp.h for jmp_buf format + */ +
arch/x86/cpu/x86_64/setjmp.S line 18
Quoted 10 lines
arch/x86/cpu/x86_64/setjmp.S new file +10
-0+#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?
arch/x86/cpu/x86_64/setjmp.S line 26
Quoted 8 lines
arch/x86/cpu/x86_64/setjmp.S new file +8
-0+ 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.
arch/x86/cpu/x86_64/setjmp.S line 38
Quoted 12 lines
arch/x86/cpu/x86_64/setjmp.S new file +12
-0+ 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
Quoted 82 lines
arch/x86/cpu/x86_64/setjmp.S new file +28
-0+ + 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)arch/x86/cpu/x86_64/setjmp.c deleted +0
-19@@ -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" ); -}arch/x86/include/asm/setjmp.h +17
-0@@ -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;
arch/x86/include/asm/setjmp.h struct jmp_buf_data {
Quoted 9 lines
arch/x86/include/asm/setjmp.h +2
-1@@ -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