Skip to content

Commit b891e42

Browse files
committed
x86/efi/mixed: Simplify and document thunking logic
Now that the GDT/IDT and data segment selector preserve/restore logic has been removed from the boot-time EFI mixed mode thunking routines, the remaining logic to handle the function arguments can be simplified: the setup of the arguments on the stack can be moved into the 32-bit callee, which is able to use a more idiomatic sequence of PUSH instructions. This, in turn, allows the far call and far return to be issued using plain LCALL and LRET instructions, removing the need to set up the return explicitly. Acked-by: Ingo Molnar <[email protected]> Signed-off-by: Ard Biesheuvel <[email protected]>
1 parent 6e2da8d commit b891e42

File tree

1 file changed

+37
-40
lines changed

1 file changed

+37
-40
lines changed

arch/x86/boot/compressed/efi_mixed.S

Lines changed: 37 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -22,43 +22,7 @@
2222
#include <asm/processor-flags.h>
2323
#include <asm/segment.h>
2424

25-
.code64
2625
.text
27-
SYM_FUNC_START(__efi64_thunk)
28-
push %rbp
29-
push %rbx
30-
31-
/* Copy args passed on stack */
32-
movq 0x18(%rsp), %rbp
33-
movq 0x20(%rsp), %rbx
34-
movq 0x28(%rsp), %rax
35-
36-
/*
37-
* Convert x86-64 ABI params to i386 ABI
38-
*/
39-
subq $64, %rsp
40-
movl %esi, 0x0(%rsp)
41-
movl %edx, 0x4(%rsp)
42-
movl %ecx, 0x8(%rsp)
43-
movl %r8d, 0xc(%rsp)
44-
movl %r9d, 0x10(%rsp)
45-
movl %ebp, 0x14(%rsp)
46-
movl %ebx, 0x18(%rsp)
47-
movl %eax, 0x1c(%rsp)
48-
49-
leaq 1f(%rip), %rbp
50-
movl %cs, %ebx
51-
52-
ljmpl *efi32_call(%rip)
53-
54-
1: addq $64, %rsp
55-
movq %rdi, %rax
56-
57-
pop %rbx
58-
pop %rbp
59-
RET
60-
SYM_FUNC_END(__efi64_thunk)
61-
6226
.code32
6327
#ifdef CONFIG_EFI_HANDOVER_PROTOCOL
6428
SYM_FUNC_START(efi32_stub_entry)
@@ -81,11 +45,26 @@ SYM_FUNC_END(efi32_stub_entry)
8145
#endif
8246

8347
/*
84-
* EFI service pointer must be in %edi.
48+
* Called using a far call from __efi64_thunk() below, using the x86_64 SysV
49+
* ABI (except for R8/R9 which are inaccessible to 32-bit code - EAX/EBX are
50+
* used instead). EBP+16 points to the arguments passed via the stack.
8551
*
86-
* The stack should represent the 32-bit calling convention.
52+
* The first argument (EDI) is a pointer to the boot service or protocol, to
53+
* which the remaining arguments are passed, each truncated to 32 bits.
8754
*/
8855
SYM_FUNC_START_LOCAL(efi_enter32)
56+
/*
57+
* Convert x86-64 SysV ABI params to i386 ABI
58+
*/
59+
pushl 32(%ebp) /* Up to 3 args passed via the stack */
60+
pushl 24(%ebp)
61+
pushl 16(%ebp)
62+
pushl %ebx /* R9 */
63+
pushl %eax /* R8 */
64+
pushl %ecx
65+
pushl %edx
66+
pushl %esi
67+
8968
/* Disable paging */
9069
movl %cr0, %eax
9170
btrl $X86_CR0_PG_BIT, %eax
@@ -104,11 +83,29 @@ SYM_FUNC_START_LOCAL(efi_enter32)
10483

10584
call efi32_enable_long_mode
10685

107-
pushl %ebx
108-
pushl %ebp
86+
addl $32, %esp
87+
movl %edi, %eax
10988
lret
11089
SYM_FUNC_END(efi_enter32)
11190

91+
.code64
92+
SYM_FUNC_START(__efi64_thunk)
93+
push %rbp
94+
movl %esp, %ebp
95+
push %rbx
96+
97+
/* Move args #5 and #6 into 32-bit accessible registers */
98+
movl %r8d, %eax
99+
movl %r9d, %ebx
100+
101+
lcalll *efi32_call(%rip)
102+
103+
pop %rbx
104+
pop %rbp
105+
RET
106+
SYM_FUNC_END(__efi64_thunk)
107+
108+
.code32
112109
SYM_FUNC_START_LOCAL(efi32_enable_long_mode)
113110
movl %cr4, %eax
114111
btsl $(X86_CR4_PAE_BIT), %eax

0 commit comments

Comments
 (0)