1 /* SPDX-License-Identifier: GPL-2.0 */
3 * Copyright (C) 2014, 2015 Intel Corporation; author Matt Fleming
5 * Early support for invoking 32-bit EFI services from a 64-bit kernel.
7 * Because this thunking occurs before ExitBootServices() we have to
8 * restore the firmware's 32-bit GDT and IDT before we make EFI service
11 * On the plus side, we don't have to worry about mangling 64-bit
12 * addresses into 32-bits because we're executing with an identity
13 * mapped pagetable and haven't transitioned to 64-bit virtual addresses
17 #include <linux/linkage.h>
19 #include <asm/page_types.h>
20 #include <asm/processor-flags.h>
21 #include <asm/segment.h>
25 SYM_FUNC_START(__efi64_thunk)
36 /* Copy args passed on stack */
42 * Convert x86-64 ABI params to i386 ABI
63 * Switch to IDT and GDT with 32-bit segments. This is the firmware GDT
64 * and IDT that was installed when the kernel started executing. The
65 * pointers were saved at the EFI stub entry point in head_64.S.
67 * Pass the saved DS selector to the 32-bit code, and use far return to
68 * restore the saved CS selector.
70 leaq efi32_boot_idt(%rip), %rax
72 leaq efi32_boot_gdt(%rip), %rax
75 movzwl efi32_boot_ds(%rip), %edx
76 movzwq efi32_boot_cs(%rip), %rax
78 leaq efi_enter32(%rip), %rax
91 /* Clear out 32-bit selector from FS and GS */
97 * Convert 32-bit status code into 64-bit.
105 SYM_FUNC_END(__efi64_thunk)
109 * EFI service pointer must be in %edi.
111 * The stack should represent the 32-bit calling convention.
113 SYM_FUNC_START_LOCAL(efi_enter32)
114 /* Load firmware selector into data and stack segment registers */
121 /* Reload pgtables */
127 btrl $X86_CR0_PG_BIT, %eax
130 /* Disable long mode via EFER */
133 btrl $_EFER_LME, %eax
138 /* We must preserve return value */
142 * Some firmware will return with interrupts enabled. Be sure to
143 * disable them before we switch GDTs and IDTs.
153 btsl $(X86_CR4_PAE_BIT), %eax
161 btsl $_EFER_LME, %eax
172 btsl $X86_CR0_PG_BIT, %eax
175 SYM_FUNC_END(efi_enter32)
179 SYM_DATA_START(efi32_boot_gdt)
182 SYM_DATA_END(efi32_boot_gdt)
184 SYM_DATA_START(efi32_boot_idt)
187 SYM_DATA_END(efi32_boot_idt)
189 SYM_DATA_START(efi32_boot_cs)
191 SYM_DATA_END(efi32_boot_cs)
193 SYM_DATA_START(efi32_boot_ds)
195 SYM_DATA_END(efi32_boot_ds)