1b2441318SGreg Kroah-Hartman/* SPDX-License-Identifier: GPL-2.0 */ 24f9dbcfcSMatt Fleming/* 34f9dbcfcSMatt Fleming * Copyright (C) 2014 Intel Corporation; author Matt Fleming 496738c69SMatt Fleming * 596738c69SMatt Fleming * Support for invoking 32-bit EFI runtime services from a 64-bit 696738c69SMatt Fleming * kernel. 796738c69SMatt Fleming * 896738c69SMatt Fleming * The below thunking functions are only used after ExitBootServices() 996738c69SMatt Fleming * has been called. This simplifies things considerably as compared with 1096738c69SMatt Fleming * the early EFI thunking because we can leave all the kernel state 11f7081834SBo Liu * intact (GDT, IDT, etc) and simply invoke the 32-bit EFI runtime 1296738c69SMatt Fleming * services from __KERNEL32_CS. This means we can continue to service 1396738c69SMatt Fleming * interrupts across an EFI mixed mode call. 1496738c69SMatt Fleming * 1596738c69SMatt Fleming * We do however, need to handle the fact that we're running in a full 1696738c69SMatt Fleming * 64-bit virtual address space. Things like the stack and instruction 1796738c69SMatt Fleming * addresses need to be accessible by the 32-bit firmware, so we rely on 1896738c69SMatt Fleming * using the identity mappings in the EFI page table to access the stack 1996738c69SMatt Fleming * and kernel text (see efi_setup_page_tables()). 204f9dbcfcSMatt Fleming */ 214f9dbcfcSMatt Fleming 224f9dbcfcSMatt Fleming#include <linux/linkage.h> 23537da1edSPeter Zijlstra#include <linux/objtool.h> 244f9dbcfcSMatt Fleming#include <asm/page_types.h> 2596738c69SMatt Fleming#include <asm/segment.h> 264f9dbcfcSMatt Fleming 274f9dbcfcSMatt Fleming .text 284f9dbcfcSMatt Fleming .code64 29537da1edSPeter ZijlstraSYM_FUNC_START(__efi64_thunk) 30537da1edSPeter ZijlstraSTACK_FRAME_NON_STANDARD __efi64_thunk 314f9dbcfcSMatt Fleming push %rbp 324f9dbcfcSMatt Fleming push %rbx 334f9dbcfcSMatt Fleming 344f9dbcfcSMatt Fleming /* 354f9dbcfcSMatt Fleming * Switch to 1:1 mapped 32-bit stack pointer. 364f9dbcfcSMatt Fleming */ 37ea5e1919SArd Biesheuvel movq %rsp, %rax 383e1e00c0SArd Biesheuvel movq efi_mixed_mode_stack_pa(%rip), %rsp 39ea5e1919SArd Biesheuvel push %rax 404f9dbcfcSMatt Fleming 414f9dbcfcSMatt Fleming /* 4244f155b4SArd Biesheuvel * Copy args passed via the stack 4344f155b4SArd Biesheuvel */ 4444f155b4SArd Biesheuvel subq $0x24, %rsp 4544f155b4SArd Biesheuvel movq 0x18(%rax), %rbp 4644f155b4SArd Biesheuvel movq 0x20(%rax), %rbx 4744f155b4SArd Biesheuvel movq 0x28(%rax), %rax 4844f155b4SArd Biesheuvel movl %ebp, 0x18(%rsp) 4944f155b4SArd Biesheuvel movl %ebx, 0x1c(%rsp) 5044f155b4SArd Biesheuvel movl %eax, 0x20(%rsp) 5144f155b4SArd Biesheuvel 5244f155b4SArd Biesheuvel /* 534f9dbcfcSMatt Fleming * Calculate the physical address of the kernel text. 544f9dbcfcSMatt Fleming */ 554f9dbcfcSMatt Fleming movq $__START_KERNEL_map, %rax 564f9dbcfcSMatt Fleming subq phys_base(%rip), %rax 574f9dbcfcSMatt Fleming 58ea5e1919SArd Biesheuvel leaq 1f(%rip), %rbp 59ea5e1919SArd Biesheuvel leaq 2f(%rip), %rbx 60ea5e1919SArd Biesheuvel subq %rax, %rbp 614f9dbcfcSMatt Fleming subq %rax, %rbx 624f9dbcfcSMatt Fleming 63ea5e1919SArd Biesheuvel movl %ebx, 0x0(%rsp) /* return address */ 64ea5e1919SArd Biesheuvel movl %esi, 0x4(%rsp) 65ea5e1919SArd Biesheuvel movl %edx, 0x8(%rsp) 66ea5e1919SArd Biesheuvel movl %ecx, 0xc(%rsp) 67ea5e1919SArd Biesheuvel movl %r8d, 0x10(%rsp) 68ea5e1919SArd Biesheuvel movl %r9d, 0x14(%rsp) 6996738c69SMatt Fleming 7096738c69SMatt Fleming /* Switch to 32-bit descriptor */ 7196738c69SMatt Fleming pushq $__KERNEL32_CS 72ea5e1919SArd Biesheuvel pushq %rdi /* EFI runtime service address */ 7396738c69SMatt Fleming lretq 7496738c69SMatt Fleming 75*6c3a9c9aSArd Biesheuvel // This return instruction is not needed for correctness, as it will 76*6c3a9c9aSArd Biesheuvel // never be reached. It only exists to make objtool happy, which will 77*6c3a9c9aSArd Biesheuvel // otherwise complain about unreachable instructions in the callers. 78*6c3a9c9aSArd Biesheuvel RET 79*6c3a9c9aSArd BiesheuvelSYM_FUNC_END(__efi64_thunk) 80*6c3a9c9aSArd Biesheuvel 81*6c3a9c9aSArd Biesheuvel .section ".rodata", "a", @progbits 82*6c3a9c9aSArd Biesheuvel .balign 16 83*6c3a9c9aSArd BiesheuvelSYM_DATA_START(__efi64_thunk_ret_tramp) 8444f155b4SArd Biesheuvel1: movq 0x20(%rsp), %rsp 8596738c69SMatt Fleming pop %rbx 86ea5e1919SArd Biesheuvel pop %rbp 8751a6fa07SThadeu Lima de Souza Cascardo ret 8851a6fa07SThadeu Lima de Souza Cascardo int3 8996738c69SMatt Fleming 9096738c69SMatt Fleming .code32 91ea5e1919SArd Biesheuvel2: pushl $__KERNEL_CS 92ea5e1919SArd Biesheuvel pushl %ebp 9396738c69SMatt Fleming lret 94*6c3a9c9aSArd BiesheuvelSYM_DATA_END(__efi64_thunk_ret_tramp) 953e1e00c0SArd Biesheuvel 963e1e00c0SArd Biesheuvel .bss 973e1e00c0SArd Biesheuvel .balign 8 983e1e00c0SArd BiesheuvelSYM_DATA(efi_mixed_mode_stack_pa, .quad 0) 99