From cbcf0cd65ed44e88f3f36edc18a14c59d5372b3b Mon Sep 17 00:00:00 2001 From: Yuanhao Xie Date: Mon, 9 Jan 2023 11:37:21 +0800 Subject: [PATCH] Revert "UefiCpuPkg: Has APs in 64 bit long-mode before booting to OS." This reverts commit 73ccde8f6d04a246377cabaed2875e69d4b6b719 since it results in a hang of the IA32 processor and needs further clean-up. Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=4234 Cc: Eric Dong Cc: Ray Ni Cc: Rahul Kumar Cc: Gerd Hoffmann Reviewed-by: Laszlo Ersek Signed-off-by: Yuanhao Xie --- UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf | 7 +- UefiCpuPkg/Library/MpInitLib/DxeMpLib.c | 84 +++++---- .../Library/MpInitLib/Ia32/CreatePageTable.c | 27 --- UefiCpuPkg/Library/MpInitLib/MpLib.h | 19 +- .../Library/MpInitLib/X64/CreatePageTable.c | 75 -------- UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm | 171 +++++++++++++++--- UefiCpuPkg/UefiCpuPkg.dsc | 1 - 7 files changed, 200 insertions(+), 184 deletions(-) delete mode 100644 UefiCpuPkg/Library/MpInitLib/Ia32/CreatePageTable.c delete mode 100644 UefiCpuPkg/Library/MpInitLib/X64/CreatePageTable.c diff --git a/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf b/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf index 8c8b81d933..cd07de3a3c 100644 --- a/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf +++ b/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf @@ -1,7 +1,7 @@ ## @file # MP Initialize Library instance for DXE driver. # -# Copyright (c) 2016 - 2022, Intel Corporation. All rights reserved.
+# Copyright (c) 2016 - 2021, Intel Corporation. All rights reserved.
# SPDX-License-Identifier: BSD-2-Clause-Patent # ## @@ -24,11 +24,9 @@ [Sources.IA32] Ia32/AmdSev.c Ia32/MpFuncs.nasm - Ia32/CreatePageTable.c [Sources.X64] X64/AmdSev.c - X64/CreatePageTable.c X64/MpFuncs.nasm [Sources.common] @@ -59,9 +57,6 @@ CcExitLib MicrocodeLib -[LibraryClasses.X64] - CpuPageTableLib - [Protocols] gEfiTimerArchProtocolGuid ## SOMETIMES_CONSUMES diff --git a/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c b/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c index beab06a5b1..445e0853d2 100644 --- a/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c +++ b/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c @@ -28,7 +28,6 @@ volatile BOOLEAN mStopCheckAllApsStatus = TRUE; VOID *mReservedApLoopFunc = NULL; UINTN mReservedTopOfApStack; volatile UINT32 mNumberToFinish = 0; -UINTN mApPageTable; // // Begin wakeup buffer allocation below 0x88000 @@ -408,9 +407,12 @@ RelocateApLoop ( AsmRelocateApLoopFunc ( MwaitSupport, CpuMpData->ApTargetCState, + CpuMpData->PmCodeSegment, StackStart - ProcessorNumber * AP_SAFE_STACK_SIZE, (UINTN)&mNumberToFinish, - mApPageTable + CpuMpData->Pm16CodeSegment, + CpuMpData->SevEsAPBuffer, + CpuMpData->WakeupBuffer ); } @@ -475,6 +477,7 @@ InitMpGlobalData ( ) { EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS Address; UINTN ApSafeBufferSize; UINTN Index; EFI_GCD_MEMORY_SPACE_DESCRIPTOR MemDesc; @@ -542,45 +545,60 @@ InitMpGlobalData ( // Allocating it in advance since memory services are not available in // Exit Boot Services callback function. // - // +------------+ - // | Ap Loop | - // +------------+ - // | Stack * N | - // +------------+ (low address) - // ApSafeBufferSize = EFI_PAGES_TO_SIZE ( EFI_SIZE_TO_PAGES ( - CpuMpData->CpuCount * AP_SAFE_STACK_SIZE - + CpuMpData->AddressMap.RelocateApLoopFuncSize + CpuMpData->AddressMap.RelocateApLoopFuncSize ) ); + Address = BASE_4GB - 1; + Status = gBS->AllocatePages ( + AllocateMaxAddress, + EfiReservedMemoryType, + EFI_SIZE_TO_PAGES (ApSafeBufferSize), + &Address + ); + ASSERT_EFI_ERROR (Status); - mReservedTopOfApStack = (UINTN)AllocateReservedPages (EFI_SIZE_TO_PAGES (ApSafeBufferSize)); - ASSERT (mReservedTopOfApStack != 0); - ASSERT ((mReservedTopOfApStack & (UINTN)(CPU_STACK_ALIGNMENT - 1)) == 0); - ASSERT ((AP_SAFE_STACK_SIZE & (CPU_STACK_ALIGNMENT - 1)) == 0); - - mReservedApLoopFunc = (VOID *)(mReservedTopOfApStack + CpuMpData->CpuCount * AP_SAFE_STACK_SIZE); - if (StandardSignatureIsAuthenticAMD ()) { - CopyMem ( - mReservedApLoopFunc, - CpuMpData->AddressMap.RelocateApLoopFuncAddressAmd, - CpuMpData->AddressMap.RelocateApLoopFuncSizeAmd - ); - } else { - CopyMem ( - mReservedApLoopFunc, - CpuMpData->AddressMap.RelocateApLoopFuncAddress, - CpuMpData->AddressMap.RelocateApLoopFuncSize - ); + mReservedApLoopFunc = (VOID *)(UINTN)Address; + ASSERT (mReservedApLoopFunc != NULL); - mApPageTable = CreatePageTable ( - mReservedTopOfApStack, - ApSafeBufferSize - ); + // + // Make sure that the buffer memory is executable if NX protection is enabled + // for EfiReservedMemoryType. + // + // TODO: Check EFI_MEMORY_XP bit set or not once it's available in DXE GCD + // service. + // + Status = gDS->GetMemorySpaceDescriptor (Address, &MemDesc); + if (!EFI_ERROR (Status)) { + gDS->SetMemorySpaceAttributes ( + Address, + ApSafeBufferSize, + MemDesc.Attributes & (~EFI_MEMORY_XP) + ); } - mReservedTopOfApStack += CpuMpData->CpuCount * AP_SAFE_STACK_SIZE; + ApSafeBufferSize = EFI_PAGES_TO_SIZE ( + EFI_SIZE_TO_PAGES ( + CpuMpData->CpuCount * AP_SAFE_STACK_SIZE + ) + ); + Address = BASE_4GB - 1; + Status = gBS->AllocatePages ( + AllocateMaxAddress, + EfiReservedMemoryType, + EFI_SIZE_TO_PAGES (ApSafeBufferSize), + &Address + ); + ASSERT_EFI_ERROR (Status); + + mReservedTopOfApStack = (UINTN)Address + ApSafeBufferSize; + ASSERT ((mReservedTopOfApStack & (UINTN)(CPU_STACK_ALIGNMENT - 1)) == 0); + CopyMem ( + mReservedApLoopFunc, + CpuMpData->AddressMap.RelocateApLoopFuncAddress, + CpuMpData->AddressMap.RelocateApLoopFuncSize + ); Status = gBS->CreateEvent ( EVT_TIMER | EVT_NOTIFY_SIGNAL, diff --git a/UefiCpuPkg/Library/MpInitLib/Ia32/CreatePageTable.c b/UefiCpuPkg/Library/MpInitLib/Ia32/CreatePageTable.c deleted file mode 100644 index 525885b77d..0000000000 --- a/UefiCpuPkg/Library/MpInitLib/Ia32/CreatePageTable.c +++ /dev/null @@ -1,27 +0,0 @@ -/** @file - Function to create page talbe. - Only create page table for x64, and leave the CreatePageTable empty for Ia32. - - Copyright (c) 2022, Intel Corporation. All rights reserved.
- SPDX-License-Identifier: BSD-2-Clause-Patent - -**/ - -#include - -/** - Only create page table for x64, and leave the CreatePageTable empty for Ia32. - - @param[in] LinearAddress The start of the linear address range. - @param[in] Length The length of the linear address range. - - @return The page table to be created. -**/ -UINTN -CreatePageTable ( - IN UINTN Address, - IN UINTN Length - ) -{ - return 0; -} diff --git a/UefiCpuPkg/Library/MpInitLib/MpLib.h b/UefiCpuPkg/Library/MpInitLib/MpLib.h index 13d515c2df..1102003a93 100644 --- a/UefiCpuPkg/Library/MpInitLib/MpLib.h +++ b/UefiCpuPkg/Library/MpInitLib/MpLib.h @@ -392,9 +392,12 @@ typedef (EFIAPI *ASM_RELOCATE_AP_LOOP)( IN BOOLEAN MwaitSupport, IN UINTN ApTargetCState, + IN UINTN PmCodeSegment, IN UINTN TopOfApStack, IN UINTN NumberToFinish, - IN UINTN Cr3 + IN UINTN Pm16CodeSegment, + IN UINTN SevEsAPJumpTable, + IN UINTN WakeupBuffer ); /** @@ -509,20 +512,6 @@ WakeUpAP ( IN BOOLEAN WakeUpDisabledAps ); -/** - Create 1:1 mapping page table in reserved memory to map the specified address range. - - @param[in] LinearAddress The start of the linear address range. - @param[in] Length The length of the linear address range. - - @return The page table to be created. -**/ -UINTN -CreatePageTable ( - IN UINTN Address, - IN UINTN Length - ); - /** Initialize global data for MP support. diff --git a/UefiCpuPkg/Library/MpInitLib/X64/CreatePageTable.c b/UefiCpuPkg/Library/MpInitLib/X64/CreatePageTable.c deleted file mode 100644 index 548ef3f2c8..0000000000 --- a/UefiCpuPkg/Library/MpInitLib/X64/CreatePageTable.c +++ /dev/null @@ -1,75 +0,0 @@ -/** @file - Function to create page talbe. - Only create page table for x64, and leave the CreatePageTable empty for Ia32. - - Copyright (c) 2022, Intel Corporation. All rights reserved.
- SPDX-License-Identifier: BSD-2-Clause-Patent - -**/ -#include -#include -#include -#include -#include - -/** - Create 1:1 mapping page table in reserved memory to map the specified address range. - - @param[in] LinearAddress The start of the linear address range. - @param[in] Length The length of the linear address range. - - @return The page table to be created. -**/ -UINTN -CreatePageTable ( - IN UINTN Address, - IN UINTN Length - ) -{ - EFI_STATUS Status; - VOID *PageTableBuffer; - UINTN PageTableBufferSize; - UINTN PageTable; - - IA32_MAP_ATTRIBUTE MapAttribute; - IA32_MAP_ATTRIBUTE MapMask; - - MapAttribute.Uint64 = Address; - MapAttribute.Bits.Present = 1; - MapAttribute.Bits.ReadWrite = 1; - - MapMask.Bits.PageTableBaseAddress = 1; - MapMask.Bits.Present = 1; - MapMask.Bits.ReadWrite = 1; - - PageTable = 0; - PageTableBufferSize = 0; - - Status = PageTableMap ( - &PageTable, - Paging4Level, - NULL, - &PageTableBufferSize, - Address, - Length, - &MapAttribute, - &MapMask - ); - ASSERT (Status == EFI_BUFFER_TOO_SMALL); - DEBUG ((DEBUG_INFO, "AP Page Table Buffer Size = %x\n", PageTableBufferSize)); - - PageTableBuffer = AllocateReservedPages (EFI_SIZE_TO_PAGES (PageTableBufferSize)); - ASSERT (PageTableBuffer != NULL); - Status = PageTableMap ( - &PageTable, - Paging4Level, - PageTableBuffer, - &PageTableBufferSize, - Address, - Length, - &MapAttribute, - &MapMask - ); - ASSERT_EFI_ERROR (Status); - return PageTable; -} diff --git a/UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm b/UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm index 8ae287dd8d..39c3e8606a 100644 --- a/UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm +++ b/UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm @@ -279,42 +279,120 @@ CProcedureInvoke: RendezvousFunnelProcEnd: ;------------------------------------------------------------------------------------- -; AsmRelocateApLoop (MwaitSupport, ApTargetCState, TopOfApStack, CountTofinish, Cr3); -; This function is called during the finalizaiton of Mp initialization before booting -; to OS, and aim to put Aps either in Mwait or HLT. +; AsmRelocateApLoop (MwaitSupport, ApTargetCState, PmCodeSegment, TopOfApStack, CountTofinish, Pm16CodeSegment, SevEsAPJumpTable, WakeupBuffer); ;------------------------------------------------------------------------------------- -; +----------------+ -; | Cr3 | rsp+40 -; +----------------+ -; | CountTofinish | r9 -; +----------------+ -; | TopOfApStack | r8 -; +----------------+ -; | ApTargetCState | rdx -; +----------------+ -; | MwaitSupport | rcx -; +----------------+ -; | the return | -; +----------------+ low address - AsmRelocateApLoopStart: - mov rax, r9 ; CountTofinish +BITS 64 + cmp qword [rsp + 56], 0 ; SevEsAPJumpTable + je NoSevEs + + ; + ; Perform some SEV-ES related setup before leaving 64-bit mode + ; + push rcx + push rdx + + ; + ; Get the RDX reset value using CPUID + ; + mov rax, 1 + cpuid + mov rsi, rax ; Save off the reset value for RDX + + ; + ; Prepare the GHCB for the AP_HLT_LOOP VMGEXIT call + ; - Must be done while in 64-bit long mode so that writes to + ; the GHCB memory will be unencrypted. + ; - No NAE events can be generated once this is set otherwise + ; the AP_RESET_HOLD SW_EXITCODE will be overwritten. + ; + mov rcx, 0xc0010130 + rdmsr ; Retrieve current GHCB address + shl rdx, 32 + or rdx, rax + + mov rdi, rdx + xor rax, rax + mov rcx, 0x800 + shr rcx, 3 + rep stosq ; Clear the GHCB + + mov rax, 0x80000004 ; VMGEXIT AP_RESET_HOLD + mov [rdx + 0x390], rax + mov rax, 114 ; Set SwExitCode valid bit + bts [rdx + 0x3f0], rax + inc rax ; Set SwExitInfo1 valid bit + bts [rdx + 0x3f0], rax + inc rax ; Set SwExitInfo2 valid bit + bts [rdx + 0x3f0], rax + + pop rdx + pop rcx + +NoSevEs: + cli ; Disable interrupt before switching to 32-bit mode + mov rax, [rsp + 40] ; CountTofinish lock dec dword [rax] ; (*CountTofinish)-- - mov rax, [rsp + 40] ; Cr3 - ; Do not push on old stack, since old stack is not mapped - ; in the page table pointed by cr3 - mov cr3, rax - mov rsp, r8 ; TopOfApStack + mov r10, [rsp + 48] ; Pm16CodeSegment + mov rax, [rsp + 56] ; SevEsAPJumpTable + mov rbx, [rsp + 64] ; WakeupBuffer + mov rsp, r9 ; TopOfApStack + + push rax ; Save SevEsAPJumpTable + push rbx ; Save WakeupBuffer + push r10 ; Save Pm16CodeSegment + push rcx ; Save MwaitSupport + push rdx ; Save ApTargetCState + + lea rax, [PmEntry] ; rax <- The start address of transition code + + push r8 + push rax + + ; + ; Clear R8 - R15, for reset, before going into 32-bit mode + ; + xor r8, r8 + xor r9, r9 + xor r10, r10 + xor r11, r11 + xor r12, r12 + xor r13, r13 + xor r14, r14 + xor r15, r15 + + ; + ; Far return into 32-bit mode + ; + retfq + +BITS 32 +PmEntry: + mov eax, cr0 + btr eax, 31 ; Clear CR0.PG + mov cr0, eax ; Disable paging and caches + + mov ecx, 0xc0000080 + rdmsr + and ah, ~ 1 ; Clear LME + wrmsr + mov eax, cr4 + and al, ~ (1 << 5) ; Clear PAE + mov cr4, eax + + pop edx + add esp, 4 + pop ecx, + add esp, 4 MwaitCheck: cmp cl, 1 ; Check mwait-monitor support jnz HltLoop - mov rbx, rdx ; Save C-State to ebx - + mov ebx, edx ; Save C-State to ebx MwaitLoop: cli - mov rax, rsp ; Set Monitor Address + mov eax, esp ; Set Monitor Address xor ecx, ecx ; ecx = 0 xor edx, edx ; edx = 0 monitor @@ -324,10 +402,49 @@ MwaitLoop: jmp MwaitLoop HltLoop: + pop edx ; PM16CodeSegment + add esp, 4 + pop ebx ; WakeupBuffer + add esp, 4 + pop eax ; SevEsAPJumpTable + add esp, 4 + cmp eax, 0 ; Check for SEV-ES + je DoHlt + + cli + ; + ; SEV-ES is enabled, use VMGEXIT (GHCB information already + ; set by caller) + ; +BITS 64 + rep vmmcall +BITS 32 + + ; + ; Back from VMGEXIT AP_HLT_LOOP + ; Push the FLAGS/CS/IP values to use + ; + push word 0x0002 ; EFLAGS + xor ecx, ecx + mov cx, [eax + 2] ; CS + push cx + mov cx, [eax] ; IP + push cx + push word 0x0000 ; For alignment, will be discarded + + push edx + push ebx + + mov edx, esi ; Restore RDX reset value + + retf + +DoHlt: cli hlt - jmp HltLoop + jmp DoHlt +BITS 64 AsmRelocateApLoopEnd: ;------------------------------------------------------------------------------------- diff --git a/UefiCpuPkg/UefiCpuPkg.dsc b/UefiCpuPkg/UefiCpuPkg.dsc index 781acedfc5..f9a46089d2 100644 --- a/UefiCpuPkg/UefiCpuPkg.dsc +++ b/UefiCpuPkg/UefiCpuPkg.dsc @@ -94,7 +94,6 @@ MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf - CpuPageTableLib|UefiCpuPkg/Library/CpuPageTableLib/CpuPageTableLib.inf MpInitLib|UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf RegisterCpuFeaturesLib|UefiCpuPkg/Library/RegisterCpuFeaturesLib/DxeRegisterCpuFeaturesLib.inf CpuCacheInfoLib|UefiCpuPkg/Library/CpuCacheInfoLib/DxeCpuCacheInfoLib.inf -- 2.39.2