[PATCH 3/3] efi/x86: simplify mixed mode call wrapper

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Calling 32-bit EFI runtime services from a 64-bit OS involves
switching back to the flat mapping with a stack carved out of
memory that is 32-bit addressable.

There is no need to actually execute the 64-bit part of this
routine from the flat mapping as well, as long as the entry
and return address fit in 32 bits. There is also no need to
preserve part of the calling context in global variables: we
can simply preserve the old stack pointer in %r11 across the
call into 32-bit firmware, and use either stack to preserve
other values.

Signed-off-by: Ard Biesheuvel <ardb@xxxxxxxxxx>
---
 arch/x86/platform/efi/efi_thunk_64.S | 106 ++++++--------------
 1 file changed, 29 insertions(+), 77 deletions(-)

diff --git a/arch/x86/platform/efi/efi_thunk_64.S b/arch/x86/platform/efi/efi_thunk_64.S
index 3189f1394701..7357808d3ae8 100644
--- a/arch/x86/platform/efi/efi_thunk_64.S
+++ b/arch/x86/platform/efi/efi_thunk_64.S
@@ -28,11 +28,17 @@
 SYM_FUNC_START(efi64_thunk)
 	push	%rbp
 	push	%rbx
+	movl	%ds, %ebx
+	push	%rbx
+	movl	%es, %ebx
+	push	%rbx
+	movl	%ss, %ebx
+	push	%rbx
 
 	/*
 	 * Switch to 1:1 mapped 32-bit stack pointer.
 	 */
-	movq	%rsp, efi_saved_sp(%rip)
+	movq	%rsp, %r11
 	movq	efi_scratch(%rip), %rsp
 
 	/*
@@ -41,87 +47,41 @@ SYM_FUNC_START(efi64_thunk)
 	movq	$__START_KERNEL_map, %rax
 	subq	phys_base(%rip), %rax
 
-	/*
-	 * Push some physical addresses onto the stack. This is easier
-	 * to do now in a code64 section while the assembler can address
-	 * 64-bit values. Note that all the addresses on the stack are
-	 * 32-bit.
-	 */
-	subq	$16, %rsp
-	leaq	efi_exit32(%rip), %rbx
-	subq	%rax, %rbx
-	movl	%ebx, 8(%rsp)
-
-	leaq	__efi64_thunk(%rip), %rbx
-	subq	%rax, %rbx
-	call	*%rbx
-
-	movq	efi_saved_sp(%rip), %rsp
-	pop	%rbx
-	pop	%rbp
-	retq
-SYM_FUNC_END(efi64_thunk)
-
-/*
- * We run this function from the 1:1 mapping.
- *
- * This function must be invoked with a 1:1 mapped stack.
- */
-SYM_FUNC_START_LOCAL(__efi64_thunk)
-	movl	%ds, %eax
-	push	%rax
-	movl	%es, %eax
-	push	%rax
-	movl	%ss, %eax
-	push	%rax
-
-	subq	$32, %rsp
+	subq	$24, %rsp
 	movl	%esi, 0x0(%rsp)
 	movl	%edx, 0x4(%rsp)
 	movl	%ecx, 0x8(%rsp)
-	movq	%r8, %rsi
-	movl	%esi, 0xc(%rsp)
-	movq	%r9, %rsi
-	movl	%esi,  0x10(%rsp)
-
+	movl	%r8d, 0xc(%rsp)
+	movl	%r9d, 0x10(%rsp)
 	leaq	1f(%rip), %rbx
-	movq	%rbx, func_rt_ptr(%rip)
+	subq	%rax, %rbx
+	movl	%ebx, 0x14(%rsp)
 
 	/* Switch to 32-bit descriptor */
 	pushq	$__KERNEL32_CS
-	leaq	efi_enter32(%rip), %rax
-	pushq	%rax
+	leaq	efi_enter32(%rip), %rbx
+	subq	%rax, %rbx
+	pushq	%rbx
 	lretq
 
-1:	addq	$32, %rsp
-
+	/*
+	 * Convert 32-bit status code into 64-bit.
+	 */
+1:	btrl	$31, %eax
+	jb	3f
+2:	mov	%r11, %rsp
 	pop	%rbx
 	movl	%ebx, %ss
 	pop	%rbx
 	movl	%ebx, %es
 	pop	%rbx
 	movl	%ebx, %ds
-
-	/*
-	 * Convert 32-bit status code into 64-bit.
-	 */
-	test	%rax, %rax
-	jz	1f
-	movl	%eax, %ecx
-	andl	$0x0fffffff, %ecx
-	andl	$0xf0000000, %eax
-	shl	$32, %rax
-	or	%rcx, %rax
-1:
-	ret
-SYM_FUNC_END(__efi64_thunk)
-
-SYM_FUNC_START_LOCAL(efi_exit32)
-	movq	func_rt_ptr(%rip), %rax
-	push	%rax
-	mov	%rdi, %rax
-	ret
-SYM_FUNC_END(efi_exit32)
+	pop	%rbx
+	pop	%rbp
+	retq
+3:	btsq	$63, %rax
+	jmp	2b
+SYM_FUNC_END(efi64_thunk)
 
 	.code32
 /*
@@ -137,17 +97,9 @@ SYM_FUNC_START_LOCAL(efi_enter32)
 
 	call	*%edi
 
-	/* We must preserve return value */
-	movl	%eax, %edi
-
-	movl	72(%esp), %eax
+	movl	20(%esp), %edi
 	pushl	$__KERNEL_CS
-	pushl	%eax
+	pushl	%edi
 
 	lret
 SYM_FUNC_END(efi_enter32)
-
-	.data
-	.balign	8
-func_rt_ptr:		.quad 0
-efi_saved_sp:		.quad 0
-- 
2.17.1




[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux OMAP]     [Linux MIPS]     [ECOS]     [Asterisk Internet PBX]     [Linux API]

  Powered by Linux