X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=UefiCpuPkg%2FPiSmmCpuDxeSmm%2FX64%2FSmiEntry.nasm;h=8bfba55b5d082dcb9b51f257c832f2aff425f345;hb=ef62da4ff742a0b9f4b718ccc2a03f5497115c9f;hp=b717cda2c93ecf23286aa58c369faf80b71ff599;hpb=9a36d4dc3f5ec6a4e134198329883df8bf43634f;p=mirror_edk2.git diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmiEntry.nasm b/UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmiEntry.nasm index b717cda2c9..8bfba55b5d 100644 --- a/UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmiEntry.nasm +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmiEntry.nasm @@ -1,12 +1,6 @@ ;------------------------------------------------------------------------------ ; -; Copyright (c) 2016, Intel Corporation. All rights reserved.
-; This program and the accompanying materials -; are licensed and made available under the terms and conditions of the BSD License -; which accompanies this distribution. The full text of the license may be found at -; http://opensource.org/licenses/bsd-license.php. -; -; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent ; ; Module Name: ; @@ -18,10 +12,31 @@ ; ;------------------------------------------------------------------------------- +%include "StuffRsbNasm.inc" +%include "Nasm.inc" + ; -; Variables referrenced by C code +; Variables referenced by C code ; +%define MSR_IA32_S_CET 0x6A2 +%define MSR_IA32_CET_SH_STK_EN 0x1 +%define MSR_IA32_CET_WR_SHSTK_EN 0x2 +%define MSR_IA32_CET_ENDBR_EN 0x4 +%define MSR_IA32_CET_LEG_IW_EN 0x8 +%define MSR_IA32_CET_NO_TRACK_EN 0x10 +%define MSR_IA32_CET_SUPPRESS_DIS 0x20 +%define MSR_IA32_CET_SUPPRESS 0x400 +%define MSR_IA32_CET_TRACKER 0x800 +%define MSR_IA32_PL0_SSP 0x6A4 +%define MSR_IA32_INTERRUPT_SSP_TABLE_ADDR 0x6A8 + +%define CR4_CET 0x800000 + +%define MSR_IA32_MISC_ENABLE 0x1A0 +%define MSR_EFER 0xc0000080 +%define MSR_EFER_XD 0x800 + ; ; Constants relating to PROCESSOR_SMM_DESCRIPTOR ; @@ -49,12 +64,21 @@ extern ASM_PFX(gSmiHandlerIdtr) extern ASM_PFX(CpuSmmDebugEntry) extern ASM_PFX(CpuSmmDebugExit) -global ASM_PFX(gSmbase) -global ASM_PFX(gSmiStack) -global ASM_PFX(gSmiCr3) +global ASM_PFX(gPatchSmbase) +extern ASM_PFX(mXdSupported) +global ASM_PFX(gPatchXdSupported) +global ASM_PFX(gPatchSmiStack) +global ASM_PFX(gPatchSmiCr3) +global ASM_PFX(gPatch5LevelPagingNeeded) global ASM_PFX(gcSmiHandlerTemplate) global ASM_PFX(gcSmiHandlerSize) +extern ASM_PFX(mCetSupported) +global ASM_PFX(mPatchCetSupported) +global ASM_PFX(mPatchCetPl0Ssp) +global ASM_PFX(mPatchCetInterruptSsp) +global ASM_PFX(mPatchCetInterruptSspTable) + DEFAULT REL SECTION .text @@ -69,9 +93,9 @@ _SmiEntryPoint: mov [cs:bx + 2], eax o32 lgdt [cs:bx] ; lgdt fword ptr cs:[bx] mov ax, PROTECT_MODE_CS - mov [cs:bx-0x2],ax - DB 0x66, 0xbf ; mov edi, SMBASE -ASM_PFX(gSmbase): DD 0 + mov [cs:bx-0x2],ax + mov edi, strict dword 0 ; source operand will be patched +ASM_PFX(gPatchSmbase): lea eax, [edi + (@ProtectedMode - _SmiEntryPoint) + 0x8000] mov [cs:bx-0x6],eax mov ebx, cr0 @@ -79,7 +103,7 @@ ASM_PFX(gSmbase): DD 0 or ebx, 0x23 mov cr0, ebx jmp dword 0x0:0x0 -_GdtDesc: +_GdtDesc: DW 0 DD 0 @@ -91,16 +115,27 @@ o16 mov es, ax o16 mov fs, ax o16 mov gs, ax o16 mov ss, ax - DB 0xbc ; mov esp, imm32 -ASM_PFX(gSmiStack): DD 0 + mov esp, strict dword 0 ; source operand will be patched +ASM_PFX(gPatchSmiStack): jmp ProtFlatMode BITS 64 ProtFlatMode: - DB 0xb8 ; mov eax, offset gSmiCr3 -ASM_PFX(gSmiCr3): DD 0 + mov eax, strict dword 0 ; source operand will be patched +ASM_PFX(gPatchSmiCr3): mov cr3, rax mov eax, 0x668 ; as cr4.PGE is not set here, refresh cr3 + + mov cl, strict byte 0 ; source operand will be patched +ASM_PFX(gPatch5LevelPagingNeeded): + cmp cl, 0 + je SkipEnable5LevelPaging + ; + ; Enable 5-Level Paging bit + ; + bts eax, 12 ; Set LA57 bit (bit #12) +SkipEnable5LevelPaging: + mov cr4, rax ; in PreModifyMtrrs() to flush TLB. ; Load TSS sub esp, 8 ; reserve room in stack @@ -112,21 +147,49 @@ ASM_PFX(gSmiCr3): DD 0 mov eax, TSS_SEGMENT ltr ax +; enable NXE if supported + mov al, strict byte 1 ; source operand may be patched +ASM_PFX(gPatchXdSupported): + cmp al, 0 + jz @SkipXd +; +; Check XD disable bit +; + mov ecx, MSR_IA32_MISC_ENABLE + rdmsr + sub esp, 4 + push rdx ; save MSR_IA32_MISC_ENABLE[63-32] + test edx, BIT2 ; MSR_IA32_MISC_ENABLE[34] + jz .0 + and dx, 0xFFFB ; clear XD Disable bit if it is set + wrmsr +.0: + mov ecx, MSR_EFER + rdmsr + or ax, MSR_EFER_XD ; enable NXE + wrmsr + jmp @XdDone +@SkipXd: + sub esp, 8 +@XdDone: + ; Switch into @LongMode push LONG_MODE_CS ; push cs hardcore here - call Base ; push reture address for retf later + call Base ; push return address for retf later Base: add dword [rsp], @LongMode - Base; offset for far retf, seg is the 1st arg - mov ecx, 0xc0000080 + + mov ecx, MSR_EFER rdmsr - or ah, 1 + or ah, 1 ; enable LME wrmsr mov rbx, cr0 - or ebx, 080010000h ; enable paging + WP + or ebx, 0x80010023 ; enable paging + WP + NE + MP + PE mov cr0, rbx retf @LongMode: ; long mode (64-bit code) starts here - mov rax, ASM_PFX(gSmiHandlerIdtr) + mov rax, strict qword 0 ; mov rax, ASM_PFX(gSmiHandlerIdtr) +SmiHandlerIdtrAbsAddr: lidt [rax] lea ebx, [rdi + DSC_OFFSET] mov ax, [rbx + DSC_DS] @@ -137,41 +200,181 @@ Base: mov gs, eax mov ax, [rbx + DSC_SS] mov ss, eax -; jmp _SmiHandler ; instruction is not needed -_SmiHandler: - mov rbx, [rsp] ; rbx <- CpuIndex + mov rbx, [rsp + 0x8] ; rbx <- CpuIndex + +; enable CET if supported + mov al, strict byte 1 ; source operand may be patched +ASM_PFX(mPatchCetSupported): + cmp al, 0 + jz CetDone + + mov ecx, MSR_IA32_S_CET + rdmsr + push rdx + push rax + + mov ecx, MSR_IA32_PL0_SSP + rdmsr + push rdx + push rax + + mov ecx, MSR_IA32_INTERRUPT_SSP_TABLE_ADDR + rdmsr + push rdx + push rax + + mov ecx, MSR_IA32_S_CET + mov eax, MSR_IA32_CET_SH_STK_EN + xor edx, edx + wrmsr + + mov ecx, MSR_IA32_PL0_SSP + mov eax, strict dword 0 ; source operand will be patched +ASM_PFX(mPatchCetPl0Ssp): + xor edx, edx + wrmsr + mov rcx, cr0 + btr ecx, 16 ; clear WP + mov cr0, rcx + mov [eax], eax ; reload SSP, and clear busyflag. + xor ecx, ecx + mov [eax + 4], ecx + + mov ecx, MSR_IA32_INTERRUPT_SSP_TABLE_ADDR + mov eax, strict dword 0 ; source operand will be patched +ASM_PFX(mPatchCetInterruptSspTable): + xor edx, edx + wrmsr + + mov eax, strict dword 0 ; source operand will be patched +ASM_PFX(mPatchCetInterruptSsp): + cmp eax, 0 + jz CetInterruptDone + mov [eax], eax ; reload SSP, and clear busyflag. + xor ecx, ecx + mov [eax + 4], ecx +CetInterruptDone: + + mov rcx, cr0 + bts ecx, 16 ; set WP + mov cr0, rcx + + mov eax, 0x668 | CR4_CET + mov cr4, rax + + SETSSBSY + +CetDone: ; ; Save FP registers ; - sub rsp, 0x208 - DB 0x48 ; FXSAVE64 - fxsave [rsp] + sub rsp, 0x200 + fxsave64 [rsp] add rsp, -0x20 mov rcx, rbx - mov rax, CpuSmmDebugEntry + mov rax, strict qword 0 ; call ASM_PFX(CpuSmmDebugEntry) +CpuSmmDebugEntryAbsAddr: call rax - + mov rcx, rbx - mov rax, SmiRendezvous ; rax <- absolute addr of SmiRedezvous + mov rax, strict qword 0 ; call ASM_PFX(SmiRendezvous) +SmiRendezvousAbsAddr: call rax - + mov rcx, rbx - mov rax, CpuSmmDebugExit + mov rax, strict qword 0 ; call ASM_PFX(CpuSmmDebugExit) +CpuSmmDebugExitAbsAddr: call rax - + add rsp, 0x20 ; ; Restore FP registers ; - DB 0x48 ; FXRSTOR64 - fxrstor [rsp] + fxrstor64 [rsp] + + add rsp, 0x200 + + mov rax, strict qword 0 ; mov rax, ASM_PFX(mCetSupported) +mCetSupportedAbsAddr: + mov al, [rax] + cmp al, 0 + jz CetDone2 + + mov eax, 0x668 + mov cr4, rax ; disable CET + + mov ecx, MSR_IA32_INTERRUPT_SSP_TABLE_ADDR + pop rax + pop rdx + wrmsr + + mov ecx, MSR_IA32_PL0_SSP + pop rax + pop rdx + wrmsr + + mov ecx, MSR_IA32_S_CET + pop rax + pop rdx + wrmsr +CetDone2: + + mov rax, strict qword 0 ; lea rax, [ASM_PFX(mXdSupported)] +mXdSupportedAbsAddr: + mov al, [rax] + cmp al, 0 + jz .1 + pop rdx ; get saved MSR_IA32_MISC_ENABLE[63-32] + test edx, BIT2 + jz .1 + mov ecx, MSR_IA32_MISC_ENABLE + rdmsr + or dx, BIT2 ; set XD Disable bit if it was set before entering into SMM + wrmsr +.1: + + StuffRsb64 rsm -gcSmiHandlerSize DW $ - _SmiEntryPoint +ASM_PFX(gcSmiHandlerSize) DW $ - _SmiEntryPoint + +; +; Retrieve the address and fill it into mov opcode. +; +; It is called in the driver entry point first. +; It is used to fix up the real address in mov opcode. +; Then, after the code logic is copied to the different location, +; the code can also run. +; +global ASM_PFX(PiSmmCpuSmiEntryFixupAddress) +ASM_PFX(PiSmmCpuSmiEntryFixupAddress): + lea rax, [ASM_PFX(gSmiHandlerIdtr)] + lea rcx, [SmiHandlerIdtrAbsAddr] + mov qword [rcx - 8], rax + + lea rax, [ASM_PFX(CpuSmmDebugEntry)] + lea rcx, [CpuSmmDebugEntryAbsAddr] + mov qword [rcx - 8], rax + + lea rax, [ASM_PFX(SmiRendezvous)] + lea rcx, [SmiRendezvousAbsAddr] + mov qword [rcx - 8], rax + + lea rax, [ASM_PFX(CpuSmmDebugExit)] + lea rcx, [CpuSmmDebugExitAbsAddr] + mov qword [rcx - 8], rax + + lea rax, [ASM_PFX(mXdSupported)] + lea rcx, [mXdSupportedAbsAddr] + mov qword [rcx - 8], rax + lea rax, [ASM_PFX(mCetSupported)] + lea rcx, [mCetSupportedAbsAddr] + mov qword [rcx - 8], rax + ret