## @file\r
# MP Initialize Library instance for DXE driver.\r
#\r
-# Copyright (c) 2016 - 2022, Intel Corporation. All rights reserved.<BR>\r
+# Copyright (c) 2016 - 2021, Intel Corporation. All rights reserved.<BR>\r
# SPDX-License-Identifier: BSD-2-Clause-Patent\r
#\r
##\r
[Sources.IA32]\r
Ia32/AmdSev.c\r
Ia32/MpFuncs.nasm\r
- Ia32/CreatePageTable.c\r
\r
[Sources.X64]\r
X64/AmdSev.c\r
- X64/CreatePageTable.c\r
X64/MpFuncs.nasm\r
\r
[Sources.common]\r
CcExitLib\r
MicrocodeLib\r
\r
-[LibraryClasses.X64]\r
- CpuPageTableLib\r
-\r
[Protocols]\r
gEfiTimerArchProtocolGuid ## SOMETIMES_CONSUMES\r
\r
VOID *mReservedApLoopFunc = NULL;\r
UINTN mReservedTopOfApStack;\r
volatile UINT32 mNumberToFinish = 0;\r
-UINTN mApPageTable;\r
\r
//\r
// Begin wakeup buffer allocation below 0x88000\r
AsmRelocateApLoopFunc (\r
MwaitSupport,\r
CpuMpData->ApTargetCState,\r
+ CpuMpData->PmCodeSegment,\r
StackStart - ProcessorNumber * AP_SAFE_STACK_SIZE,\r
(UINTN)&mNumberToFinish,\r
- mApPageTable\r
+ CpuMpData->Pm16CodeSegment,\r
+ CpuMpData->SevEsAPBuffer,\r
+ CpuMpData->WakeupBuffer\r
);\r
}\r
\r
)\r
{\r
EFI_STATUS Status;\r
+ EFI_PHYSICAL_ADDRESS Address;\r
UINTN ApSafeBufferSize;\r
UINTN Index;\r
EFI_GCD_MEMORY_SPACE_DESCRIPTOR MemDesc;\r
// Allocating it in advance since memory services are not available in\r
// Exit Boot Services callback function.\r
//\r
- // +------------+\r
- // | Ap Loop |\r
- // +------------+\r
- // | Stack * N |\r
- // +------------+ (low address)\r
- //\r
ApSafeBufferSize = EFI_PAGES_TO_SIZE (\r
EFI_SIZE_TO_PAGES (\r
- CpuMpData->CpuCount * AP_SAFE_STACK_SIZE\r
- + CpuMpData->AddressMap.RelocateApLoopFuncSize\r
+ CpuMpData->AddressMap.RelocateApLoopFuncSize\r
)\r
);\r
+ Address = BASE_4GB - 1;\r
+ Status = gBS->AllocatePages (\r
+ AllocateMaxAddress,\r
+ EfiReservedMemoryType,\r
+ EFI_SIZE_TO_PAGES (ApSafeBufferSize),\r
+ &Address\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
\r
- mReservedTopOfApStack = (UINTN)AllocateReservedPages (EFI_SIZE_TO_PAGES (ApSafeBufferSize));\r
- ASSERT (mReservedTopOfApStack != 0);\r
- ASSERT ((mReservedTopOfApStack & (UINTN)(CPU_STACK_ALIGNMENT - 1)) == 0);\r
- ASSERT ((AP_SAFE_STACK_SIZE & (CPU_STACK_ALIGNMENT - 1)) == 0);\r
-\r
- mReservedApLoopFunc = (VOID *)(mReservedTopOfApStack + CpuMpData->CpuCount * AP_SAFE_STACK_SIZE);\r
- if (StandardSignatureIsAuthenticAMD ()) {\r
- CopyMem (\r
- mReservedApLoopFunc,\r
- CpuMpData->AddressMap.RelocateApLoopFuncAddressAmd,\r
- CpuMpData->AddressMap.RelocateApLoopFuncSizeAmd\r
- );\r
- } else {\r
- CopyMem (\r
- mReservedApLoopFunc,\r
- CpuMpData->AddressMap.RelocateApLoopFuncAddress,\r
- CpuMpData->AddressMap.RelocateApLoopFuncSize\r
- );\r
+ mReservedApLoopFunc = (VOID *)(UINTN)Address;\r
+ ASSERT (mReservedApLoopFunc != NULL);\r
\r
- mApPageTable = CreatePageTable (\r
- mReservedTopOfApStack,\r
- ApSafeBufferSize\r
- );\r
+ //\r
+ // Make sure that the buffer memory is executable if NX protection is enabled\r
+ // for EfiReservedMemoryType.\r
+ //\r
+ // TODO: Check EFI_MEMORY_XP bit set or not once it's available in DXE GCD\r
+ // service.\r
+ //\r
+ Status = gDS->GetMemorySpaceDescriptor (Address, &MemDesc);\r
+ if (!EFI_ERROR (Status)) {\r
+ gDS->SetMemorySpaceAttributes (\r
+ Address,\r
+ ApSafeBufferSize,\r
+ MemDesc.Attributes & (~EFI_MEMORY_XP)\r
+ );\r
}\r
\r
- mReservedTopOfApStack += CpuMpData->CpuCount * AP_SAFE_STACK_SIZE;\r
+ ApSafeBufferSize = EFI_PAGES_TO_SIZE (\r
+ EFI_SIZE_TO_PAGES (\r
+ CpuMpData->CpuCount * AP_SAFE_STACK_SIZE\r
+ )\r
+ );\r
+ Address = BASE_4GB - 1;\r
+ Status = gBS->AllocatePages (\r
+ AllocateMaxAddress,\r
+ EfiReservedMemoryType,\r
+ EFI_SIZE_TO_PAGES (ApSafeBufferSize),\r
+ &Address\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ mReservedTopOfApStack = (UINTN)Address + ApSafeBufferSize;\r
+ ASSERT ((mReservedTopOfApStack & (UINTN)(CPU_STACK_ALIGNMENT - 1)) == 0);\r
+ CopyMem (\r
+ mReservedApLoopFunc,\r
+ CpuMpData->AddressMap.RelocateApLoopFuncAddress,\r
+ CpuMpData->AddressMap.RelocateApLoopFuncSize\r
+ );\r
\r
Status = gBS->CreateEvent (\r
EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
+++ /dev/null
-/** @file\r
- Function to create page talbe.\r
- Only create page table for x64, and leave the CreatePageTable empty for Ia32.\r
-\r
- Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>\r
- SPDX-License-Identifier: BSD-2-Clause-Patent\r
-\r
-**/\r
-\r
-#include <Base.h>\r
-\r
-/**\r
- Only create page table for x64, and leave the CreatePageTable empty for Ia32.\r
-\r
- @param[in] LinearAddress The start of the linear address range.\r
- @param[in] Length The length of the linear address range.\r
-\r
- @return The page table to be created.\r
-**/\r
-UINTN\r
-CreatePageTable (\r
- IN UINTN Address,\r
- IN UINTN Length\r
- )\r
-{\r
- return 0;\r
-}\r
(EFIAPI *ASM_RELOCATE_AP_LOOP)(\r
IN BOOLEAN MwaitSupport,\r
IN UINTN ApTargetCState,\r
+ IN UINTN PmCodeSegment,\r
IN UINTN TopOfApStack,\r
IN UINTN NumberToFinish,\r
- IN UINTN Cr3\r
+ IN UINTN Pm16CodeSegment,\r
+ IN UINTN SevEsAPJumpTable,\r
+ IN UINTN WakeupBuffer\r
);\r
\r
/**\r
IN BOOLEAN WakeUpDisabledAps\r
);\r
\r
-/**\r
- Create 1:1 mapping page table in reserved memory to map the specified address range.\r
-\r
- @param[in] LinearAddress The start of the linear address range.\r
- @param[in] Length The length of the linear address range.\r
-\r
- @return The page table to be created.\r
-**/\r
-UINTN\r
-CreatePageTable (\r
- IN UINTN Address,\r
- IN UINTN Length\r
- );\r
-\r
/**\r
Initialize global data for MP support.\r
\r
+++ /dev/null
-/** @file\r
- Function to create page talbe.\r
- Only create page table for x64, and leave the CreatePageTable empty for Ia32.\r
-\r
- Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>\r
- SPDX-License-Identifier: BSD-2-Clause-Patent\r
-\r
-**/\r
-#include <Library/CpuPageTableLib.h>\r
-#include <Library/MemoryAllocationLib.h>\r
-#include <Base.h>\r
-#include <Library/BaseMemoryLib.h>\r
-#include <Library/DebugLib.h>\r
-\r
-/**\r
- Create 1:1 mapping page table in reserved memory to map the specified address range.\r
-\r
- @param[in] LinearAddress The start of the linear address range.\r
- @param[in] Length The length of the linear address range.\r
-\r
- @return The page table to be created.\r
-**/\r
-UINTN\r
-CreatePageTable (\r
- IN UINTN Address,\r
- IN UINTN Length\r
- )\r
-{\r
- EFI_STATUS Status;\r
- VOID *PageTableBuffer;\r
- UINTN PageTableBufferSize;\r
- UINTN PageTable;\r
-\r
- IA32_MAP_ATTRIBUTE MapAttribute;\r
- IA32_MAP_ATTRIBUTE MapMask;\r
-\r
- MapAttribute.Uint64 = Address;\r
- MapAttribute.Bits.Present = 1;\r
- MapAttribute.Bits.ReadWrite = 1;\r
-\r
- MapMask.Bits.PageTableBaseAddress = 1;\r
- MapMask.Bits.Present = 1;\r
- MapMask.Bits.ReadWrite = 1;\r
-\r
- PageTable = 0;\r
- PageTableBufferSize = 0;\r
-\r
- Status = PageTableMap (\r
- &PageTable,\r
- Paging4Level,\r
- NULL,\r
- &PageTableBufferSize,\r
- Address,\r
- Length,\r
- &MapAttribute,\r
- &MapMask\r
- );\r
- ASSERT (Status == EFI_BUFFER_TOO_SMALL);\r
- DEBUG ((DEBUG_INFO, "AP Page Table Buffer Size = %x\n", PageTableBufferSize));\r
-\r
- PageTableBuffer = AllocateReservedPages (EFI_SIZE_TO_PAGES (PageTableBufferSize));\r
- ASSERT (PageTableBuffer != NULL);\r
- Status = PageTableMap (\r
- &PageTable,\r
- Paging4Level,\r
- PageTableBuffer,\r
- &PageTableBufferSize,\r
- Address,\r
- Length,\r
- &MapAttribute,\r
- &MapMask\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
- return PageTable;\r
-}\r
RendezvousFunnelProcEnd:\r
\r
;-------------------------------------------------------------------------------------\r
-; AsmRelocateApLoop (MwaitSupport, ApTargetCState, TopOfApStack, CountTofinish, Cr3);\r
-; This function is called during the finalizaiton of Mp initialization before booting\r
-; to OS, and aim to put Aps either in Mwait or HLT.\r
+; AsmRelocateApLoop (MwaitSupport, ApTargetCState, PmCodeSegment, TopOfApStack, CountTofinish, Pm16CodeSegment, SevEsAPJumpTable, WakeupBuffer);\r
;-------------------------------------------------------------------------------------\r
-; +----------------+\r
-; | Cr3 | rsp+40\r
-; +----------------+\r
-; | CountTofinish | r9\r
-; +----------------+\r
-; | TopOfApStack | r8\r
-; +----------------+\r
-; | ApTargetCState | rdx\r
-; +----------------+\r
-; | MwaitSupport | rcx\r
-; +----------------+\r
-; | the return |\r
-; +----------------+ low address\r
-\r
AsmRelocateApLoopStart:\r
- mov rax, r9 ; CountTofinish\r
+BITS 64\r
+ cmp qword [rsp + 56], 0 ; SevEsAPJumpTable\r
+ je NoSevEs\r
+\r
+ ;\r
+ ; Perform some SEV-ES related setup before leaving 64-bit mode\r
+ ;\r
+ push rcx\r
+ push rdx\r
+\r
+ ;\r
+ ; Get the RDX reset value using CPUID\r
+ ;\r
+ mov rax, 1\r
+ cpuid\r
+ mov rsi, rax ; Save off the reset value for RDX\r
+\r
+ ;\r
+ ; Prepare the GHCB for the AP_HLT_LOOP VMGEXIT call\r
+ ; - Must be done while in 64-bit long mode so that writes to\r
+ ; the GHCB memory will be unencrypted.\r
+ ; - No NAE events can be generated once this is set otherwise\r
+ ; the AP_RESET_HOLD SW_EXITCODE will be overwritten.\r
+ ;\r
+ mov rcx, 0xc0010130\r
+ rdmsr ; Retrieve current GHCB address\r
+ shl rdx, 32\r
+ or rdx, rax\r
+\r
+ mov rdi, rdx\r
+ xor rax, rax\r
+ mov rcx, 0x800\r
+ shr rcx, 3\r
+ rep stosq ; Clear the GHCB\r
+\r
+ mov rax, 0x80000004 ; VMGEXIT AP_RESET_HOLD\r
+ mov [rdx + 0x390], rax\r
+ mov rax, 114 ; Set SwExitCode valid bit\r
+ bts [rdx + 0x3f0], rax\r
+ inc rax ; Set SwExitInfo1 valid bit\r
+ bts [rdx + 0x3f0], rax\r
+ inc rax ; Set SwExitInfo2 valid bit\r
+ bts [rdx + 0x3f0], rax\r
+\r
+ pop rdx\r
+ pop rcx\r
+\r
+NoSevEs:\r
+ cli ; Disable interrupt before switching to 32-bit mode\r
+ mov rax, [rsp + 40] ; CountTofinish\r
lock dec dword [rax] ; (*CountTofinish)--\r
\r
- mov rax, [rsp + 40] ; Cr3\r
- ; Do not push on old stack, since old stack is not mapped\r
- ; in the page table pointed by cr3\r
- mov cr3, rax\r
- mov rsp, r8 ; TopOfApStack\r
+ mov r10, [rsp + 48] ; Pm16CodeSegment\r
+ mov rax, [rsp + 56] ; SevEsAPJumpTable\r
+ mov rbx, [rsp + 64] ; WakeupBuffer\r
+ mov rsp, r9 ; TopOfApStack\r
+\r
+ push rax ; Save SevEsAPJumpTable\r
+ push rbx ; Save WakeupBuffer\r
+ push r10 ; Save Pm16CodeSegment\r
+ push rcx ; Save MwaitSupport\r
+ push rdx ; Save ApTargetCState\r
+\r
+ lea rax, [PmEntry] ; rax <- The start address of transition code\r
+\r
+ push r8\r
+ push rax\r
+\r
+ ;\r
+ ; Clear R8 - R15, for reset, before going into 32-bit mode\r
+ ;\r
+ xor r8, r8\r
+ xor r9, r9\r
+ xor r10, r10\r
+ xor r11, r11\r
+ xor r12, r12\r
+ xor r13, r13\r
+ xor r14, r14\r
+ xor r15, r15\r
+\r
+ ;\r
+ ; Far return into 32-bit mode\r
+ ;\r
+ retfq\r
+\r
+BITS 32\r
+PmEntry:\r
+ mov eax, cr0\r
+ btr eax, 31 ; Clear CR0.PG\r
+ mov cr0, eax ; Disable paging and caches\r
+\r
+ mov ecx, 0xc0000080\r
+ rdmsr\r
+ and ah, ~ 1 ; Clear LME\r
+ wrmsr\r
+ mov eax, cr4\r
+ and al, ~ (1 << 5) ; Clear PAE\r
+ mov cr4, eax\r
+\r
+ pop edx\r
+ add esp, 4\r
+ pop ecx,\r
+ add esp, 4\r
\r
MwaitCheck:\r
cmp cl, 1 ; Check mwait-monitor support\r
jnz HltLoop\r
- mov rbx, rdx ; Save C-State to ebx\r
-\r
+ mov ebx, edx ; Save C-State to ebx\r
MwaitLoop:\r
cli\r
- mov rax, rsp ; Set Monitor Address\r
+ mov eax, esp ; Set Monitor Address\r
xor ecx, ecx ; ecx = 0\r
xor edx, edx ; edx = 0\r
monitor\r
jmp MwaitLoop\r
\r
HltLoop:\r
+ pop edx ; PM16CodeSegment\r
+ add esp, 4\r
+ pop ebx ; WakeupBuffer\r
+ add esp, 4\r
+ pop eax ; SevEsAPJumpTable\r
+ add esp, 4\r
+ cmp eax, 0 ; Check for SEV-ES\r
+ je DoHlt\r
+\r
+ cli\r
+ ;\r
+ ; SEV-ES is enabled, use VMGEXIT (GHCB information already\r
+ ; set by caller)\r
+ ;\r
+BITS 64\r
+ rep vmmcall\r
+BITS 32\r
+\r
+ ;\r
+ ; Back from VMGEXIT AP_HLT_LOOP\r
+ ; Push the FLAGS/CS/IP values to use\r
+ ;\r
+ push word 0x0002 ; EFLAGS\r
+ xor ecx, ecx\r
+ mov cx, [eax + 2] ; CS\r
+ push cx\r
+ mov cx, [eax] ; IP\r
+ push cx\r
+ push word 0x0000 ; For alignment, will be discarded\r
+\r
+ push edx\r
+ push ebx\r
+\r
+ mov edx, esi ; Restore RDX reset value\r
+\r
+ retf\r
+\r
+DoHlt:\r
cli\r
hlt\r
- jmp HltLoop\r
+ jmp DoHlt\r
\r
+BITS 64\r
AsmRelocateApLoopEnd:\r
\r
;-------------------------------------------------------------------------------------\r
MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf\r
HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf\r
CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf\r
- CpuPageTableLib|UefiCpuPkg/Library/CpuPageTableLib/CpuPageTableLib.inf\r
MpInitLib|UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf\r
RegisterCpuFeaturesLib|UefiCpuPkg/Library/RegisterCpuFeaturesLib/DxeRegisterCpuFeaturesLib.inf\r
CpuCacheInfoLib|UefiCpuPkg/Library/CpuCacheInfoLib/DxeCpuCacheInfoLib.inf\r