diff options
author | Dun Tan <dun.tan@intel.com> | 2024-05-10 11:36:41 +0800 |
---|---|---|
committer | mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> | 2024-06-04 07:40:27 +0000 |
commit | 68310cd56a9cf0824cf4c70e84eb9736b925dc64 (patch) | |
tree | 4117cfa146bbeb399a86cdb982a907fd39c49514 /UefiCpuPkg/Library | |
parent | ffb8481ba81b142f85204725344d9517e53fd978 (diff) | |
download | edk2-68310cd56a9cf0824cf4c70e84eb9736b925dc64.tar.gz edk2-68310cd56a9cf0824cf4c70e84eb9736b925dc64.tar.bz2 edk2-68310cd56a9cf0824cf4c70e84eb9736b925dc64.zip |
UefiCpuPkg:Abstract some DxeMpLib code to function
Abstract some DxeMpLib code to function in this commit.
Some of these internal functions will be moved to common
MpLib.c in following commits. Then PeiMpLib can reuse
the code.
Signed-off-by: Dun Tan <dun.tan@intel.com>
Reviewed-by: Ray Ni <ray.ni@intel.com>
Cc: Rahul Kumar <rahul1.kumar@intel.com>
Cc: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Jiaxin Wu <jiaxin.wu@intel.com>
Diffstat (limited to 'UefiCpuPkg/Library')
-rw-r--r-- | UefiCpuPkg/Library/MpInitLib/DxeMpLib.c | 222 |
1 files changed, 140 insertions, 82 deletions
diff --git a/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c b/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c index 57ddb86600..5f0a87c024 100644 --- a/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c +++ b/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c @@ -1,7 +1,7 @@ /** @file
MP initialize support functions for DXE phase.
- Copyright (c) 2016 - 2023, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2016 - 2024, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -423,6 +423,144 @@ RelocateApLoop ( }
/**
+ Allocate buffer for ApLoopCode.
+
+ @param[in] Pages Number of pages to allocate.
+ @param[in, out] Address Pointer to the allocated buffer.
+**/
+VOID
+AllocateApLoopCodeBuffer (
+ IN UINTN Pages,
+ IN OUT EFI_PHYSICAL_ADDRESS *Address
+ )
+{
+ EFI_STATUS Status;
+
+ Status = gBS->AllocatePages (
+ AllocateMaxAddress,
+ EfiReservedMemoryType,
+ Pages,
+ Address
+ );
+ ASSERT_EFI_ERROR (Status);
+}
+
+/**
+ Remove Nx protection for the range specific by BaseAddress and Length.
+
+ The PEI implementation uses CpuPageTableLib to change the attribute.
+ The DXE implementation uses gDS to change the attribute.
+
+ @param[in] BaseAddress BaseAddress of the range.
+ @param[in] Length Length of the range.
+**/
+VOID
+RemoveNxprotection (
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINTN Length
+ )
+{
+ EFI_STATUS Status;
+ EFI_GCD_MEMORY_SPACE_DESCRIPTOR MemDesc;
+
+ //
+ // TODO: Check EFI_MEMORY_XP bit set or not once it's available in DXE GCD
+ // service.
+ //
+ Status = gDS->GetMemorySpaceDescriptor (BaseAddress, &MemDesc);
+ if (!EFI_ERROR (Status)) {
+ gDS->SetMemorySpaceAttributes (
+ BaseAddress,
+ Length,
+ MemDesc.Attributes & (~EFI_MEMORY_XP)
+ );
+ }
+}
+
+/**
+ Prepare ApLoopCode.
+
+ @param[in] CpuMpData Pointer to CpuMpData.
+**/
+VOID
+PrepareApLoopCode (
+ IN CPU_MP_DATA *CpuMpData
+ )
+{
+ EFI_PHYSICAL_ADDRESS Address;
+ MP_ASSEMBLY_ADDRESS_MAP *AddressMap;
+ UINT8 *ApLoopFunc;
+ UINTN ApLoopFuncSize;
+ UINTN StackPages;
+ UINTN FuncPages;
+ IA32_CR0 Cr0;
+
+ AddressMap = &CpuMpData->AddressMap;
+ if (CpuMpData->UseSevEsAPMethod) {
+ //
+ // 64-bit AMD processors with SEV-ES
+ //
+ Address = BASE_4GB - 1;
+ ApLoopFunc = AddressMap->RelocateApLoopFuncAddressAmdSev;
+ ApLoopFuncSize = AddressMap->RelocateApLoopFuncSizeAmdSev;
+ } else {
+ //
+ // Intel processors (32-bit or 64-bit), 32-bit AMD processors, or 64-bit AMD processors without SEV-ES
+ //
+ Address = MAX_ADDRESS;
+ ApLoopFunc = AddressMap->RelocateApLoopFuncAddressGeneric;
+ ApLoopFuncSize = AddressMap->RelocateApLoopFuncSizeGeneric;
+ }
+
+ //
+ // Avoid APs access invalid buffer data which allocated by BootServices,
+ // so we will allocate reserved data for AP loop code. We also need to
+ // allocate this buffer below 4GB due to APs may be transferred to 32bit
+ // protected mode on long mode DXE.
+ // Allocating it in advance since memory services are not available in
+ // Exit Boot Services callback function.
+ //
+ // +------------+ (TopOfApStack)
+ // | Stack * N |
+ // +------------+ (stack base, 4k aligned)
+ // | Padding |
+ // +------------+
+ // | Ap Loop |
+ // +------------+ ((low address, 4k-aligned)
+ //
+
+ StackPages = EFI_SIZE_TO_PAGES (CpuMpData->CpuCount * AP_SAFE_STACK_SIZE);
+ FuncPages = EFI_SIZE_TO_PAGES (ApLoopFuncSize);
+
+ AllocateApLoopCodeBuffer (StackPages + FuncPages, &Address);
+ ASSERT (Address != 0);
+
+ Cr0.UintN = AsmReadCr0 ();
+ if (Cr0.Bits.PG != 0) {
+ //
+ // Make sure that the buffer memory is executable if NX protection is enabled
+ // for EfiReservedMemoryType.
+ //
+ RemoveNxprotection (Address, EFI_PAGES_TO_SIZE (FuncPages));
+ }
+
+ mReservedTopOfApStack = (UINTN)Address + EFI_PAGES_TO_SIZE (StackPages+FuncPages);
+ ASSERT ((mReservedTopOfApStack & (UINTN)(CPU_STACK_ALIGNMENT - 1)) == 0);
+ mReservedApLoop.Data = (VOID *)(UINTN)Address;
+ ASSERT (mReservedApLoop.Data != NULL);
+ CopyMem (mReservedApLoop.Data, ApLoopFunc, ApLoopFuncSize);
+ if (!CpuMpData->UseSevEsAPMethod) {
+ //
+ // processors without SEV-ES and paging is enabled
+ //
+ mApPageTable = CreatePageTable (
+ (UINTN)Address,
+ EFI_PAGES_TO_SIZE (StackPages+FuncPages)
+ );
+ }
+}
+
+/**
Callback function for ExitBootServices.
@param[in] Event Event whose notification function is being invoked.
@@ -477,16 +615,10 @@ InitMpGlobalData ( )
{
EFI_STATUS Status;
- EFI_PHYSICAL_ADDRESS Address;
UINTN Index;
EFI_GCD_MEMORY_SPACE_DESCRIPTOR MemDesc;
UINTN StackBase;
CPU_INFO_IN_HOB *CpuInfoInHob;
- MP_ASSEMBLY_ADDRESS_MAP *AddressMap;
- UINT8 *ApLoopFunc;
- UINTN ApLoopFuncSize;
- UINTN StackPages;
- UINTN FuncPages;
SaveCpuMpData (CpuMpData);
@@ -541,81 +673,7 @@ InitMpGlobalData ( }
}
- AddressMap = &CpuMpData->AddressMap;
- if (CpuMpData->UseSevEsAPMethod) {
- //
- // 64-bit AMD processors with SEV-ES
- //
- Address = BASE_4GB - 1;
- ApLoopFunc = AddressMap->RelocateApLoopFuncAddressAmdSev;
- ApLoopFuncSize = AddressMap->RelocateApLoopFuncSizeAmdSev;
- } else {
- //
- // Intel processors (32-bit or 64-bit), 32-bit AMD processors, or 64-bit AMD processors without SEV-ES
- //
- Address = MAX_ADDRESS;
- ApLoopFunc = AddressMap->RelocateApLoopFuncAddressGeneric;
- ApLoopFuncSize = AddressMap->RelocateApLoopFuncSizeGeneric;
- }
-
- //
- // Avoid APs access invalid buffer data which allocated by BootServices,
- // so we will allocate reserved data for AP loop code. We also need to
- // allocate this buffer below 4GB due to APs may be transferred to 32bit
- // protected mode on long mode DXE.
- // Allocating it in advance since memory services are not available in
- // Exit Boot Services callback function.
- //
- // +------------+ (TopOfApStack)
- // | Stack * N |
- // +------------+ (stack base, 4k aligned)
- // | Padding |
- // +------------+
- // | Ap Loop |
- // +------------+ ((low address, 4k-aligned)
- //
-
- StackPages = EFI_SIZE_TO_PAGES (CpuMpData->CpuCount * AP_SAFE_STACK_SIZE);
- FuncPages = EFI_SIZE_TO_PAGES (ApLoopFuncSize);
-
- Status = gBS->AllocatePages (
- AllocateMaxAddress,
- EfiReservedMemoryType,
- StackPages + FuncPages,
- &Address
- );
- ASSERT_EFI_ERROR (Status);
-
- //
- // 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,
- EFI_PAGES_TO_SIZE (FuncPages),
- MemDesc.Attributes & (~EFI_MEMORY_XP)
- );
- }
-
- mReservedTopOfApStack = (UINTN)Address + EFI_PAGES_TO_SIZE (StackPages+FuncPages);
- ASSERT ((mReservedTopOfApStack & (UINTN)(CPU_STACK_ALIGNMENT - 1)) == 0);
- mReservedApLoop.Data = (VOID *)(UINTN)Address;
- ASSERT (mReservedApLoop.Data != NULL);
- CopyMem (mReservedApLoop.Data, ApLoopFunc, ApLoopFuncSize);
- if (!CpuMpData->UseSevEsAPMethod) {
- //
- // processors without SEV-ES
- //
- mApPageTable = CreatePageTable (
- (UINTN)Address,
- EFI_PAGES_TO_SIZE (StackPages+FuncPages)
- );
- }
+ PrepareApLoopCode (CpuMpData);
Status = gBS->CreateEvent (
EVT_TIMER | EVT_NOTIFY_SIGNAL,
|