On Fri, 20 Aug 2021 at 09:34, Joerg Roedel joro@8bytes.org wrote:
From: Joerg Roedel jroedel@suse.de
Commit 79419e13e808 ("x86/boot/compressed/64: Setup IDT in startup_32 boot path") introduced an IDT into the 32 bit boot path of the decompressor stub. But the IDT is set up before ExitBootServices() is called and some UEFI firmwares rely on their own IDT.
Save the firmware IDT on boot and restore it before calling into EFI functions to fix boot failures introduced by above commit.
Reported-by: Fabio Aiuto fabioaiuto83@gmail.com Fixes: 79419e13e808 ("x86/boot/compressed/64: Setup IDT in startup_32 boot path") Cc: stable@vger.kernel.org # 5.13+ Signed-off-by: Joerg Roedel jroedel@suse.de
Acked by: Ard Biesheuvel ardb@kernel.org
One nit below
arch/x86/boot/compressed/efi_thunk_64.S | 23 ++++++++++++++++++----- arch/x86/boot/compressed/head_64.S | 3 +++ 2 files changed, 21 insertions(+), 5 deletions(-)
diff --git a/arch/x86/boot/compressed/efi_thunk_64.S b/arch/x86/boot/compressed/efi_thunk_64.S index 95a223b3e56a..99cfd5dea23c 100644 --- a/arch/x86/boot/compressed/efi_thunk_64.S +++ b/arch/x86/boot/compressed/efi_thunk_64.S @@ -39,7 +39,7 @@ SYM_FUNC_START(__efi64_thunk) /* * Convert x86-64 ABI params to i386 ABI */
subq $32, %rsp
subq $64, %rsp
Any reason in particular for the increase by 32?
movl %esi, 0x0(%rsp) movl %edx, 0x4(%rsp) movl %ecx, 0x8(%rsp)
@@ -49,14 +49,19 @@ SYM_FUNC_START(__efi64_thunk) leaq 0x14(%rsp), %rbx sgdt (%rbx)
addq $16, %rbx
sidt (%rbx)
/*
* Switch to gdt with 32-bit segments. This is the firmware GDT
* that was installed when the kernel started executing. This
* pointer was saved at the EFI stub entry point in head_64.S.
* Switch to idt and gdt with 32-bit segments. This is the firmware GDT
* and IDT that was installed when the kernel started executing. The
* pointers were saved at the EFI stub entry point in head_64.S. * * Pass the saved DS selector to the 32-bit code, and use far return to * restore the saved CS selector. */
leaq efi32_boot_idt(%rip), %rax
lidt (%rax) leaq efi32_boot_gdt(%rip), %rax lgdt (%rax)
@@ -67,7 +72,7 @@ SYM_FUNC_START(__efi64_thunk) pushq %rax lretq
-1: addq $32, %rsp +1: addq $64, %rsp movq %rdi, %rax
pop %rbx
@@ -132,6 +137,9 @@ SYM_FUNC_START_LOCAL(efi_enter32) */ cli
lidtl (%ebx)
subl $16, %ebx
lgdtl (%ebx) movl %cr4, %eax
@@ -166,6 +174,11 @@ SYM_DATA_START(efi32_boot_gdt) .quad 0 SYM_DATA_END(efi32_boot_gdt)
+SYM_DATA_START(efi32_boot_idt)
.word 0
.quad 0
+SYM_DATA_END(efi32_boot_idt)
SYM_DATA_START(efi32_boot_cs) .word 0 SYM_DATA_END(efi32_boot_cs) diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S index a2347ded77ea..572c535cf45b 100644 --- a/arch/x86/boot/compressed/head_64.S +++ b/arch/x86/boot/compressed/head_64.S @@ -319,6 +319,9 @@ SYM_INNER_LABEL(efi32_pe_stub_entry, SYM_L_LOCAL) movw %cs, rva(efi32_boot_cs)(%ebp) movw %ds, rva(efi32_boot_ds)(%ebp)
/* Store firmware IDT descriptor */
sidtl rva(efi32_boot_idt)(%ebp)
/* Disable paging */ movl %cr0, %eax btrl $X86_CR0_PG_BIT, %eax
-- 2.32.0