cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

efi_thunk_64.S (3622B)


      1/* SPDX-License-Identifier: GPL-2.0 */
      2/*
      3 * Copyright (C) 2014, 2015 Intel Corporation; author Matt Fleming
      4 *
      5 * Early support for invoking 32-bit EFI services from a 64-bit kernel.
      6 *
      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
      9 * calls.
     10 *
     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
     14 * yet.
     15 */
     16
     17#include <linux/linkage.h>
     18#include <asm/msr.h>
     19#include <asm/page_types.h>
     20#include <asm/processor-flags.h>
     21#include <asm/segment.h>
     22
     23	.code64
     24	.text
     25SYM_FUNC_START(__efi64_thunk)
     26	push	%rbp
     27	push	%rbx
     28
     29	movl	%ds, %eax
     30	push	%rax
     31	movl	%es, %eax
     32	push	%rax
     33	movl	%ss, %eax
     34	push	%rax
     35
     36	/* Copy args passed on stack */
     37	movq	0x30(%rsp), %rbp
     38	movq	0x38(%rsp), %rbx
     39	movq	0x40(%rsp), %rax
     40
     41	/*
     42	 * Convert x86-64 ABI params to i386 ABI
     43	 */
     44	subq	$64, %rsp
     45	movl	%esi, 0x0(%rsp)
     46	movl	%edx, 0x4(%rsp)
     47	movl	%ecx, 0x8(%rsp)
     48	movl	%r8d, 0xc(%rsp)
     49	movl	%r9d, 0x10(%rsp)
     50	movl	%ebp, 0x14(%rsp)
     51	movl	%ebx, 0x18(%rsp)
     52	movl	%eax, 0x1c(%rsp)
     53
     54	leaq	0x20(%rsp), %rbx
     55	sgdt	(%rbx)
     56
     57	addq	$16, %rbx
     58	sidt	(%rbx)
     59
     60	leaq	1f(%rip), %rbp
     61
     62	/*
     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.
     66	 *
     67	 * Pass the saved DS selector to the 32-bit code, and use far return to
     68	 * restore the saved CS selector.
     69	 */
     70	leaq	efi32_boot_idt(%rip), %rax
     71	lidt	(%rax)
     72	leaq	efi32_boot_gdt(%rip), %rax
     73	lgdt	(%rax)
     74
     75	movzwl	efi32_boot_ds(%rip), %edx
     76	movzwq	efi32_boot_cs(%rip), %rax
     77	pushq	%rax
     78	leaq	efi_enter32(%rip), %rax
     79	pushq	%rax
     80	lretq
     81
     821:	addq	$64, %rsp
     83	movq	%rdi, %rax
     84
     85	pop	%rbx
     86	movl	%ebx, %ss
     87	pop	%rbx
     88	movl	%ebx, %es
     89	pop	%rbx
     90	movl	%ebx, %ds
     91	/* Clear out 32-bit selector from FS and GS */
     92	xorl	%ebx, %ebx
     93	movl	%ebx, %fs
     94	movl	%ebx, %gs
     95
     96	/*
     97	 * Convert 32-bit status code into 64-bit.
     98	 */
     99	roll	$1, %eax
    100	rorq	$1, %rax
    101
    102	pop	%rbx
    103	pop	%rbp
    104	RET
    105SYM_FUNC_END(__efi64_thunk)
    106
    107	.code32
    108/*
    109 * EFI service pointer must be in %edi.
    110 *
    111 * The stack should represent the 32-bit calling convention.
    112 */
    113SYM_FUNC_START_LOCAL(efi_enter32)
    114	/* Load firmware selector into data and stack segment registers */
    115	movl	%edx, %ds
    116	movl	%edx, %es
    117	movl	%edx, %fs
    118	movl	%edx, %gs
    119	movl	%edx, %ss
    120
    121	/* Reload pgtables */
    122	movl	%cr3, %eax
    123	movl	%eax, %cr3
    124
    125	/* Disable paging */
    126	movl	%cr0, %eax
    127	btrl	$X86_CR0_PG_BIT, %eax
    128	movl	%eax, %cr0
    129
    130	/* Disable long mode via EFER */
    131	movl	$MSR_EFER, %ecx
    132	rdmsr
    133	btrl	$_EFER_LME, %eax
    134	wrmsr
    135
    136	call	*%edi
    137
    138	/* We must preserve return value */
    139	movl	%eax, %edi
    140
    141	/*
    142	 * Some firmware will return with interrupts enabled. Be sure to
    143	 * disable them before we switch GDTs and IDTs.
    144	 */
    145	cli
    146
    147	lidtl	(%ebx)
    148	subl	$16, %ebx
    149
    150	lgdtl	(%ebx)
    151
    152	movl	%cr4, %eax
    153	btsl	$(X86_CR4_PAE_BIT), %eax
    154	movl	%eax, %cr4
    155
    156	movl	%cr3, %eax
    157	movl	%eax, %cr3
    158
    159	movl	$MSR_EFER, %ecx
    160	rdmsr
    161	btsl	$_EFER_LME, %eax
    162	wrmsr
    163
    164	xorl	%eax, %eax
    165	lldt	%ax
    166
    167	pushl	$__KERNEL_CS
    168	pushl	%ebp
    169
    170	/* Enable paging */
    171	movl	%cr0, %eax
    172	btsl	$X86_CR0_PG_BIT, %eax
    173	movl	%eax, %cr0
    174	lret
    175SYM_FUNC_END(efi_enter32)
    176
    177	.data
    178	.balign	8
    179SYM_DATA_START(efi32_boot_gdt)
    180	.word	0
    181	.quad	0
    182SYM_DATA_END(efi32_boot_gdt)
    183
    184SYM_DATA_START(efi32_boot_idt)
    185	.word	0
    186	.quad	0
    187SYM_DATA_END(efi32_boot_idt)
    188
    189SYM_DATA_START(efi32_boot_cs)
    190	.word	0
    191SYM_DATA_END(efi32_boot_cs)
    192
    193SYM_DATA_START(efi32_boot_ds)
    194	.word	0
    195SYM_DATA_END(efi32_boot_ds)