diff options
Diffstat (limited to 'UefiCpuPkg/Library/MpInitLib')
-rw-r--r-- | UefiCpuPkg/Library/MpInitLib/DxeMpLib.c | 186 | ||||
-rw-r--r-- | UefiCpuPkg/Library/MpInitLib/Ia32/MpFuncs.nasm | 6 | ||||
-rw-r--r-- | UefiCpuPkg/Library/MpInitLib/LoongArch64/MpLib.c | 4 | ||||
-rw-r--r-- | UefiCpuPkg/Library/MpInitLib/MpLib.c | 377 | ||||
-rw-r--r-- | UefiCpuPkg/Library/MpInitLib/MpLib.h | 65 | ||||
-rw-r--r-- | UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf | 6 | ||||
-rw-r--r-- | UefiCpuPkg/Library/MpInitLib/PeiMpLib.c | 154 | ||||
-rw-r--r-- | UefiCpuPkg/Library/MpInitLib/X64/AmdSev.c | 2 |
8 files changed, 523 insertions, 277 deletions
diff --git a/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c b/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c index 57ddb86600..a8d884f607 100644 --- a/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c +++ b/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c @@ -1,7 +1,8 @@ /** @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>
+ Copyright (c) 2024, AMD Inc. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -13,22 +14,18 @@ #include <Library/DebugAgentLib.h>
#include <Library/DxeServicesTableLib.h>
#include <Library/CcExitLib.h>
-#include <Register/Amd/Fam17Msr.h>
+#include <Register/Amd/SevSnpMsr.h>
#include <Register/Amd/Ghcb.h>
#include <Protocol/Timer.h>
#define AP_SAFE_STACK_SIZE 128
-CPU_MP_DATA *mCpuMpData = NULL;
-EFI_EVENT mCheckAllApsEvent = NULL;
-EFI_EVENT mMpInitExitBootServicesEvent = NULL;
-EFI_EVENT mLegacyBootEvent = NULL;
-volatile BOOLEAN mStopCheckAllApsStatus = TRUE;
-RELOCATE_AP_LOOP_ENTRY mReservedApLoop;
-UINTN mReservedTopOfApStack;
-volatile UINT32 mNumberToFinish = 0;
-UINTN mApPageTable;
+CPU_MP_DATA *mCpuMpData = NULL;
+EFI_EVENT mCheckAllApsEvent = NULL;
+EFI_EVENT mMpInitExitBootServicesEvent = NULL;
+EFI_EVENT mLegacyBootEvent = NULL;
+volatile BOOLEAN mStopCheckAllApsStatus = TRUE;
//
// Begin wakeup buffer allocation below 0x88000
@@ -369,57 +366,58 @@ GetProtectedModeCS ( }
/**
- Do sync on APs.
+ Allocate buffer for ApLoopCode.
- @param[in, out] Buffer Pointer to private data buffer.
+ @param[in] Pages Number of pages to allocate.
+ @param[in, out] Address Pointer to the allocated buffer.
**/
VOID
-EFIAPI
-RelocateApLoop (
- IN OUT VOID *Buffer
+AllocateApLoopCodeBuffer (
+ IN UINTN Pages,
+ IN OUT EFI_PHYSICAL_ADDRESS *Address
)
{
- CPU_MP_DATA *CpuMpData;
- BOOLEAN MwaitSupport;
- UINTN ProcessorNumber;
- UINTN StackStart;
+ EFI_STATUS Status;
- MpInitLibWhoAmI (&ProcessorNumber);
- CpuMpData = GetCpuMpData ();
- MwaitSupport = IsMwaitSupport ();
- if (CpuMpData->UseSevEsAPMethod) {
- //
- // 64-bit AMD processors with SEV-ES
- //
- StackStart = CpuMpData->SevEsAPResetStackStart;
- mReservedApLoop.AmdSevEntry (
- MwaitSupport,
- CpuMpData->ApTargetCState,
- CpuMpData->PmCodeSegment,
- StackStart - ProcessorNumber * AP_SAFE_STACK_SIZE,
- (UINTN)&mNumberToFinish,
- CpuMpData->Pm16CodeSegment,
- CpuMpData->SevEsAPBuffer,
- CpuMpData->WakeupBuffer
- );
- } else {
- //
- // Intel processors (32-bit or 64-bit), 32-bit AMD processors, or 64-bit AMD processors without SEV-ES
- //
- StackStart = mReservedTopOfApStack;
- mReservedApLoop.GenericEntry (
- MwaitSupport,
- CpuMpData->ApTargetCState,
- StackStart - ProcessorNumber * AP_SAFE_STACK_SIZE,
- (UINTN)&mNumberToFinish,
- mApPageTable
- );
- }
+ 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;
//
- // It should never reach here
+ // TODO: Check EFI_MEMORY_XP bit set or not once it's available in DXE GCD
+ // service.
//
- ASSERT (FALSE);
+ Status = gDS->GetMemorySpaceDescriptor (BaseAddress, &MemDesc);
+ if (!EFI_ERROR (Status)) {
+ gDS->SetMemorySpaceAttributes (
+ BaseAddress,
+ Length,
+ MemDesc.Attributes & (~EFI_MEMORY_XP)
+ );
+ }
}
/**
@@ -477,16 +475,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 +533,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,
diff --git a/UefiCpuPkg/Library/MpInitLib/Ia32/MpFuncs.nasm b/UefiCpuPkg/Library/MpInitLib/Ia32/MpFuncs.nasm index d117f09ef5..c0fe631635 100644 --- a/UefiCpuPkg/Library/MpInitLib/Ia32/MpFuncs.nasm +++ b/UefiCpuPkg/Library/MpInitLib/Ia32/MpFuncs.nasm @@ -1,5 +1,5 @@ ;------------------------------------------------------------------------------ ;
-; Copyright (c) 2015 - 2023, Intel Corporation. All rights reserved.<BR>
+; Copyright (c) 2015 - 2024, Intel Corporation. All rights reserved.<BR>
; SPDX-License-Identifier: BSD-2-Clause-Patent
;
; Module Name:
@@ -225,6 +225,10 @@ RendezvousFunnelProcEnd: ; specific to SEV-ES support and are not applicable on IA32.
;-------------------------------------------------------------------------------------
AsmRelocateApLoopGenericStart:
+ mov eax, cr0
+ btr eax, 31 ; Clear CR0.PG
+ mov cr0, eax ; Disable paging since the page table might be unavailiable
+
mov eax, esp
mov esp, [eax + 12] ; TopOfApStack
push dword [eax] ; push return address for stack trace
diff --git a/UefiCpuPkg/Library/MpInitLib/LoongArch64/MpLib.c b/UefiCpuPkg/Library/MpInitLib/LoongArch64/MpLib.c index c18671e95f..54c23ecf10 100644 --- a/UefiCpuPkg/Library/MpInitLib/LoongArch64/MpLib.c +++ b/UefiCpuPkg/Library/MpInitLib/LoongArch64/MpLib.c @@ -130,8 +130,8 @@ SortApicId ( } else {
for ( ; Index2 <= ApCount; Index2++) {
if (CpuInfoInHob[Index2].ApicId == INVALID_APIC_ID) {
- CopyMem (&CpuInfoInHob[Index2], &CpuInfoInHob[Index1], sizeof (CPU_INFO_IN_HOB));
- CpuMpData->CpuData[Index2] = CpuMpData->CpuData[Index1];
+ CopyMem (CpuInfoInHob + Index2, CpuInfoInHob + Index1, sizeof (CPU_INFO_IN_HOB));
+ CopyMem (CpuMpData->CpuData + Index2, CpuMpData->CpuData + Index1, sizeof (CPU_AP_DATA));
CpuInfoInHob[Index1].ApicId = INVALID_APIC_ID;
break;
}
diff --git a/UefiCpuPkg/Library/MpInitLib/MpLib.c b/UefiCpuPkg/Library/MpInitLib/MpLib.c index 4bf3dc5fca..4088e76f45 100644 --- a/UefiCpuPkg/Library/MpInitLib/MpLib.c +++ b/UefiCpuPkg/Library/MpInitLib/MpLib.c @@ -10,13 +10,18 @@ #include "MpLib.h"
#include <Library/CcExitLib.h>
-#include <Register/Amd/Fam17Msr.h>
+#include <Register/Amd/SevSnpMsr.h>
#include <Register/Amd/Ghcb.h>
EFI_GUID mCpuInitMpLibHobGuid = CPU_INIT_MP_LIB_HOB_GUID;
EFI_GUID mMpHandOffGuid = MP_HANDOFF_GUID;
EFI_GUID mMpHandOffConfigGuid = MP_HANDOFF_CONFIG_GUID;
+RELOCATE_AP_LOOP_ENTRY mReservedApLoop;
+UINTN mReservedTopOfApStack;
+volatile UINT32 mNumberToFinish = 0;
+UINTN mApPageTable;
+
/**
Save the volatile registers required to be restored following INIT IPI.
@@ -36,8 +41,7 @@ SaveVolatileRegisters ( **/
VOID
RestoreVolatileRegisters (
- IN CPU_VOLATILE_REGISTERS *VolatileRegisters,
- IN BOOLEAN IsRestoreDr
+ IN CPU_VOLATILE_REGISTERS *VolatileRegisters
);
/**
@@ -113,11 +117,7 @@ FutureBSPProc ( //
SaveVolatileRegisters (&DataInHob->APInfo.VolatileRegisters);
AsmExchangeRole (&DataInHob->APInfo, &DataInHob->BSPInfo);
- RestoreVolatileRegisters (&DataInHob->APInfo.VolatileRegisters, FALSE);
- //
- // Update VolatileRegisters saved in CpuMpData->CpuData
- //
- CopyMem (&DataInHob->CpuData[DataInHob->BspNumber].VolatileRegisters, &DataInHob->APInfo.VolatileRegisters, sizeof (CPU_VOLATILE_REGISTERS));
+ RestoreVolatileRegisters (&DataInHob->APInfo.VolatileRegisters);
}
/**
@@ -162,16 +162,19 @@ SaveLocalApicTimerSetting ( IN CPU_MP_DATA *CpuMpData
)
{
- //
- // Record the current local APIC timer setting of BSP
- //
- GetApicTimerState (
- &CpuMpData->DivideValue,
- &CpuMpData->PeriodicMode,
- &CpuMpData->Vector
- );
- CpuMpData->CurrentTimerCount = GetApicTimerCurrentCount ();
- CpuMpData->TimerInterruptState = GetApicTimerInterruptState ();
+ CpuMpData->InitTimerCount = GetApicTimerInitCount ();
+ if (CpuMpData->InitTimerCount != 0) {
+ //
+ // Record the current local APIC timer setting of BSP
+ //
+ GetApicTimerState (
+ &CpuMpData->DivideValue,
+ &CpuMpData->PeriodicMode,
+ &CpuMpData->Vector
+ );
+
+ CpuMpData->TimerInterruptState = GetApicTimerInterruptState ();
+ }
}
/**
@@ -184,19 +187,21 @@ SyncLocalApicTimerSetting ( IN CPU_MP_DATA *CpuMpData
)
{
- //
- // Sync local APIC timer setting from BSP to AP
- //
- InitializeApicTimer (
- CpuMpData->DivideValue,
- CpuMpData->CurrentTimerCount,
- CpuMpData->PeriodicMode,
- CpuMpData->Vector
- );
- //
- // Disable AP's local APIC timer interrupt
- //
- DisableApicTimerInterrupt ();
+ if (CpuMpData->InitTimerCount != 0) {
+ //
+ // Sync local APIC timer setting from BSP to AP
+ //
+ InitializeApicTimer (
+ CpuMpData->DivideValue,
+ CpuMpData->InitTimerCount,
+ CpuMpData->PeriodicMode,
+ CpuMpData->Vector
+ );
+ //
+ // Disable AP's local APIC timer interrupt
+ //
+ DisableApicTimerInterrupt ();
+ }
}
/**
@@ -238,13 +243,11 @@ SaveVolatileRegisters ( Restore the volatile registers following INIT IPI.
@param[in] VolatileRegisters Pointer to volatile resisters
- @param[in] IsRestoreDr TRUE: Restore DRx if supported
- FALSE: Do not restore DRx
+
**/
VOID
RestoreVolatileRegisters (
- IN CPU_VOLATILE_REGISTERS *VolatileRegisters,
- IN BOOLEAN IsRestoreDr
+ IN CPU_VOLATILE_REGISTERS *VolatileRegisters
)
{
CPUID_VERSION_INFO_EDX VersionInfoEdx;
@@ -254,20 +257,18 @@ RestoreVolatileRegisters ( AsmWriteCr4 (VolatileRegisters->Cr4);
AsmWriteCr0 (VolatileRegisters->Cr0);
- if (IsRestoreDr) {
- AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, NULL, &VersionInfoEdx.Uint32);
- if (VersionInfoEdx.Bits.DE != 0) {
- //
- // If processor supports Debugging Extensions feature
- // by CPUID.[EAX=01H]:EDX.BIT2
- //
- AsmWriteDr0 (VolatileRegisters->Dr0);
- AsmWriteDr1 (VolatileRegisters->Dr1);
- AsmWriteDr2 (VolatileRegisters->Dr2);
- AsmWriteDr3 (VolatileRegisters->Dr3);
- AsmWriteDr6 (VolatileRegisters->Dr6);
- AsmWriteDr7 (VolatileRegisters->Dr7);
- }
+ AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, NULL, &VersionInfoEdx.Uint32);
+ if (VersionInfoEdx.Bits.DE != 0) {
+ //
+ // If processor supports Debugging Extensions feature
+ // by CPUID.[EAX=01H]:EDX.BIT2
+ //
+ AsmWriteDr0 (VolatileRegisters->Dr0);
+ AsmWriteDr1 (VolatileRegisters->Dr1);
+ AsmWriteDr2 (VolatileRegisters->Dr2);
+ AsmWriteDr3 (VolatileRegisters->Dr3);
+ AsmWriteDr6 (VolatileRegisters->Dr6);
+ AsmWriteDr7 (VolatileRegisters->Dr7);
}
AsmWriteGdtr (&VolatileRegisters->Gdtr);
@@ -372,10 +373,9 @@ SortApicId ( UINTN Index3;
UINT32 ApicId;
CPU_INFO_IN_HOB CpuInfo;
+ CPU_AP_DATA CpuApData;
UINT32 ApCount;
CPU_INFO_IN_HOB *CpuInfoInHob;
- volatile UINT32 *StartupApSignal;
- VOID *SevEsSaveArea;
ApCount = CpuMpData->CpuCount - 1;
CpuInfoInHob = (CPU_INFO_IN_HOB *)(UINTN)CpuMpData->CpuInfoInHob;
@@ -402,18 +402,13 @@ SortApicId ( );
CopyMem (&CpuInfoInHob[Index1], &CpuInfo, sizeof (CPU_INFO_IN_HOB));
- //
- // Also exchange the StartupApSignal and SevEsSaveArea.
- //
- StartupApSignal = CpuMpData->CpuData[Index3].StartupApSignal;
- CpuMpData->CpuData[Index3].StartupApSignal =
- CpuMpData->CpuData[Index1].StartupApSignal;
- CpuMpData->CpuData[Index1].StartupApSignal = StartupApSignal;
-
- SevEsSaveArea = CpuMpData->CpuData[Index3].SevEsSaveArea;
- CpuMpData->CpuData[Index3].SevEsSaveArea =
- CpuMpData->CpuData[Index1].SevEsSaveArea;
- CpuMpData->CpuData[Index1].SevEsSaveArea = SevEsSaveArea;
+ CopyMem (&CpuApData, &CpuMpData->CpuData[Index3], sizeof (CPU_AP_DATA));
+ CopyMem (
+ &CpuMpData->CpuData[Index3],
+ &CpuMpData->CpuData[Index1],
+ sizeof (CPU_AP_DATA)
+ );
+ CopyMem (&CpuMpData->CpuData[Index1], &CpuApData, sizeof (CPU_AP_DATA));
}
}
@@ -765,11 +760,11 @@ ApWakeupFunction ( BistData = (UINT32)ApStackData->Bist;
//
- // CpuMpData->CpuData[BspNumber].VolatileRegisters is initialized based on BSP environment,
+ // CpuMpData->CpuData[ProcessorNumber].VolatileRegisters is initialized based on BSP environment,
// to initialize AP in InitConfig path.
- // NOTE: IDTR.BASE stored in CpuMpData->CpuData[BspNumber].VolatileRegisters points to a different IDT shared by all APs.
+ // NOTE: IDTR.BASE stored in CpuMpData->CpuData[ProcessorNumber].VolatileRegisters points to a different IDT shared by all APs.
//
- RestoreVolatileRegisters (&CpuMpData->CpuData[CpuMpData->BspNumber].VolatileRegisters, FALSE);
+ RestoreVolatileRegisters (&CpuMpData->CpuData[ProcessorNumber].VolatileRegisters);
InitializeApData (CpuMpData, ProcessorNumber, BistData, ApTopOfStack);
ApStartupSignalBuffer = CpuMpData->CpuData[ProcessorNumber].StartupApSignal;
} else {
@@ -796,31 +791,7 @@ ApWakeupFunction ( 0
);
- if (CpuMpData->InitFlag == ApInitReconfig) {
- //
- // ApInitReconfig happens when:
- // 1. AP is re-enabled after it's disabled, in either PEI or DXE phase.
- // 2. AP is initialized in DXE phase.
- // In either case, use the volatile registers value derived from BSP.
- // NOTE: IDTR.BASE stored in CpuMpData->CpuData[BspNumber].VolatileRegisters points to a
- // different IDT shared by all APs.
- //
- RestoreVolatileRegisters (&CpuMpData->CpuData[CpuMpData->BspNumber].VolatileRegisters, FALSE);
- } else {
- if (CpuMpData->ApLoopMode == ApInHltLoop) {
- //
- // Restore AP's volatile registers saved before AP is halted
- //
- RestoreVolatileRegisters (&CpuMpData->CpuData[ProcessorNumber].VolatileRegisters, TRUE);
- } else {
- //
- // The CPU driver might not flush TLB for APs on spot after updating
- // page attributes. AP in mwait loop mode needs to take care of it when
- // woken up.
- //
- CpuFlushTlb ();
- }
- }
+ RestoreVolatileRegisters (&CpuMpData->CpuData[ProcessorNumber].VolatileRegisters);
if (GetApState (&CpuMpData->CpuData[ProcessorNumber]) == CpuStateReady) {
Procedure = (EFI_AP_PROCEDURE)CpuMpData->CpuData[ProcessorNumber].ApFunction;
@@ -871,12 +842,7 @@ ApWakeupFunction ( }
}
- if (CpuMpData->ApLoopMode == ApInHltLoop) {
- //
- // Save AP volatile registers
- //
- SaveVolatileRegisters (&CpuMpData->CpuData[ProcessorNumber].VolatileRegisters);
- }
+ SaveVolatileRegisters (&CpuMpData->CpuData[ProcessorNumber].VolatileRegisters);
//
// AP finished executing C code
@@ -931,7 +897,7 @@ DxeApEntryPoint ( AsmWriteMsr64 (MSR_IA32_EFER, EferMsr.Uint64);
}
- RestoreVolatileRegisters (&CpuMpData->CpuData[CpuMpData->BspNumber].VolatileRegisters, FALSE);
+ RestoreVolatileRegisters (&CpuMpData->CpuData[ProcessorNumber].VolatileRegisters);
InterlockedIncrement ((UINT32 *)&CpuMpData->FinishedCount);
PlaceAPInMwaitLoopOrRunLoop (
CpuMpData->ApLoopMode,
@@ -1253,13 +1219,12 @@ WakeUpAP ( ResetVectorRequired = FALSE;
if (CpuMpData->WakeUpByInitSipiSipi ||
- (CpuMpData->InitFlag != ApInitDone))
+ (CpuMpData->InitFlag == ApInitConfig))
{
ResetVectorRequired = TRUE;
AllocateResetVectorBelow1Mb (CpuMpData);
AllocateSevEsAPMemory (CpuMpData);
FillExchangeInfoData (CpuMpData);
- SaveLocalApicTimerSetting (CpuMpData);
}
if (CpuMpData->ApLoopMode == ApInMwaitLoop) {
@@ -1288,7 +1253,7 @@ WakeUpAP ( CpuData->ApFunction = (UINTN)Procedure;
CpuData->ApFunctionArgument = (UINTN)ProcedureArgument;
SetApState (CpuData, CpuStateReady);
- if (CpuMpData->InitFlag != ApInitConfig) {
+ if (CpuMpData->InitFlag == ApInitDone) {
*(UINT32 *)CpuData->StartupApSignal = WAKEUP_AP_SIGNAL;
}
}
@@ -1406,7 +1371,7 @@ WakeUpAP ( //
// Wakeup specified AP
//
- ASSERT (CpuMpData->InitFlag != ApInitConfig);
+ ASSERT (CpuMpData->InitFlag == ApInitDone);
*(UINT32 *)CpuData->StartupApSignal = WAKEUP_AP_SIGNAL;
if (ResetVectorRequired) {
CpuInfoInHob = (CPU_INFO_IN_HOB *)(UINTN)CpuMpData->CpuInfoInHob;
@@ -1678,14 +1643,12 @@ ResetProcessorToIdleState ( CpuMpData = GetCpuMpData ();
- CpuMpData->InitFlag = ApInitReconfig;
+ CpuMpData->WakeUpByInitSipiSipi = TRUE;
WakeUpAP (CpuMpData, FALSE, ProcessorNumber, NULL, NULL, TRUE);
while (CpuMpData->FinishedCount < 1) {
CpuPause ();
}
- CpuMpData->InitFlag = ApInitDone;
-
SetApState (&CpuMpData->CpuData[ProcessorNumber], CpuStateIdle);
}
@@ -2195,7 +2158,25 @@ MpInitLibInitialize ( // Don't pass BSP's TR to APs to avoid AP init failure.
//
VolatileRegisters.Tr = 0;
- CopyMem (&CpuMpData->CpuData[CpuMpData->BspNumber].VolatileRegisters, &VolatileRegisters, sizeof (VolatileRegisters));
+ //
+ // Set DR as 0 since DR is set only for BSP.
+ //
+ VolatileRegisters.Dr0 = 0;
+ VolatileRegisters.Dr1 = 0;
+ VolatileRegisters.Dr2 = 0;
+ VolatileRegisters.Dr3 = 0;
+ VolatileRegisters.Dr6 = 0;
+ VolatileRegisters.Dr7 = 0;
+
+ //
+ // Copy volatile registers since either APs are the first time to bring up,
+ // or BSP is in DXE phase but APs are still running in PEI context.
+ // In both cases, APs need use volatile registers from BSP
+ //
+ for (Index = 0; Index < MaxLogicalProcessorNumber; Index++) {
+ CopyMem (&CpuMpData->CpuData[Index].VolatileRegisters, &VolatileRegisters, sizeof (VolatileRegisters));
+ }
+
//
// Set BSP basic information
//
@@ -2237,6 +2218,7 @@ MpInitLibInitialize ( // Enable the local APIC for Virtual Wire Mode.
//
ProgramVirtualWireMode ();
+ SaveLocalApicTimerSetting (CpuMpData);
if (FirstMpHandOff == NULL) {
if (MaxLogicalProcessorNumber > 1) {
@@ -2250,6 +2232,7 @@ MpInitLibInitialize ( // APs have been wakeup before, just get the CPU Information
// from HOB
//
+ CpuMpData->InitFlag = ApInitDone;
if (CpuMpData->UseSevEsAPMethod) {
AmdSevUpdateCpuMpData (CpuMpData);
}
@@ -2293,7 +2276,6 @@ MpInitLibInitialize ( ASSERT (CpuMpData->ApLoopMode != ApInHltLoop);
CpuMpData->FinishedCount = 0;
- CpuMpData->InitFlag = ApInitDone;
CpuMpData->EnableExecuteDisableForSwitchContext = IsBspExecuteDisableEnabled ();
SaveCpuMpData (CpuMpData);
//
@@ -2326,6 +2308,12 @@ MpInitLibInitialize ( //
InitMpGlobalData (CpuMpData);
return EFI_SUCCESS;
+ } else {
+ //
+ // PEI and DXE are in different Execution Mode
+ // Use Init Sipi Sipi for the first AP wake up in DXE phase.
+ //
+ CpuMpData->WakeUpByInitSipiSipi = TRUE;
}
}
@@ -2354,15 +2342,6 @@ MpInitLibInitialize ( // Wakeup APs to do some AP initialize sync (Microcode & MTRR)
//
if (CpuMpData->CpuCount > 1) {
- if (FirstMpHandOff != NULL) {
- //
- // Only needs to use this flag for DXE phase to update the wake up
- // buffer. Wakeup buffer allocated in PEI phase is no longer valid
- // in DXE.
- //
- CpuMpData->InitFlag = ApInitReconfig;
- }
-
WakeUpAP (CpuMpData, TRUE, 0, ApInitializeSync, CpuMpData, TRUE);
//
// Wait for all APs finished initialization
@@ -2371,10 +2350,6 @@ MpInitLibInitialize ( CpuPause ();
}
- if (FirstMpHandOff != NULL) {
- CpuMpData->InitFlag = ApInitDone;
- }
-
for (Index = 0; Index < CpuMpData->CpuCount; Index++) {
SetApState (&CpuMpData->CpuData[Index], CpuStateIdle);
}
@@ -2613,6 +2588,11 @@ SwitchBSPWorker ( AsmWriteMsr64 (MSR_IA32_APIC_BASE, ApicBaseMsr.Uint64);
//
+ // Save BSP's local APIC timer setting.
+ //
+ SaveLocalApicTimerSetting (CpuMpData);
+
+ //
// Need to wakeUp AP (future BSP).
//
WakeUpAP (CpuMpData, FALSE, ProcessorNumber, FutureBSPProc, CpuMpData, TRUE);
@@ -2622,13 +2602,7 @@ SwitchBSPWorker ( //
SaveVolatileRegisters (&CpuMpData->BSPInfo.VolatileRegisters);
AsmExchangeRole (&CpuMpData->BSPInfo, &CpuMpData->APInfo);
- RestoreVolatileRegisters (&CpuMpData->BSPInfo.VolatileRegisters, FALSE);
- //
- // Update VolatileRegisters saved in CpuMpData->CpuData
- // Don't pass BSP's TR to APs to avoid AP init failure.
- //
- CopyMem (&CpuMpData->CpuData[CpuMpData->NewBspNumber].VolatileRegisters, &CpuMpData->BSPInfo.VolatileRegisters, sizeof (CPU_VOLATILE_REGISTERS));
- CpuMpData->CpuData[CpuMpData->NewBspNumber].VolatileRegisters.Tr = 0;
+ RestoreVolatileRegisters (&CpuMpData->BSPInfo.VolatileRegisters);
//
// Set the BSP bit of MSR_IA32_APIC_BASE on new BSP
//
@@ -3191,19 +3165,25 @@ AmdMemEncryptionAttrCheck ( IN CONFIDENTIAL_COMPUTING_GUEST_ATTR Attr
)
{
+ UINT64 CurrentLevel;
+
+ CurrentLevel = CurrentAttr & CCAttrTypeMask;
+
switch (Attr) {
case CCAttrAmdSev:
//
// SEV is automatically enabled if SEV-ES or SEV-SNP is active.
//
- return CurrentAttr >= CCAttrAmdSev;
+ return CurrentLevel >= CCAttrAmdSev;
case CCAttrAmdSevEs:
//
// SEV-ES is automatically enabled if SEV-SNP is active.
//
- return CurrentAttr >= CCAttrAmdSevEs;
+ return CurrentLevel >= CCAttrAmdSevEs;
case CCAttrAmdSevSnp:
- return CurrentAttr == CCAttrAmdSevSnp;
+ return CurrentLevel == CCAttrAmdSevSnp;
+ case CCAttrFeatureAmdSevEsDebugVirtualization:
+ return !!(CurrentAttr & CCAttrFeatureAmdSevEsDebugVirtualization);
default:
return FALSE;
}
@@ -3240,3 +3220,140 @@ ConfidentialComputingGuestHas ( return (CurrentAttr == Attr);
}
+
+/**
+ Do sync on APs.
+
+ @param[in, out] Buffer Pointer to private data buffer.
+**/
+VOID
+EFIAPI
+RelocateApLoop (
+ IN OUT VOID *Buffer
+ )
+{
+ CPU_MP_DATA *CpuMpData;
+ BOOLEAN MwaitSupport;
+ UINTN ProcessorNumber;
+ UINTN StackStart;
+
+ MpInitLibWhoAmI (&ProcessorNumber);
+ CpuMpData = GetCpuMpData ();
+ MwaitSupport = IsMwaitSupport ();
+ if (CpuMpData->UseSevEsAPMethod) {
+ //
+ // 64-bit AMD processors with SEV-ES
+ //
+ StackStart = CpuMpData->SevEsAPResetStackStart;
+ mReservedApLoop.AmdSevEntry (
+ MwaitSupport,
+ CpuMpData->ApTargetCState,
+ CpuMpData->PmCodeSegment,
+ StackStart - ProcessorNumber * AP_SAFE_STACK_SIZE,
+ (UINTN)&mNumberToFinish,
+ CpuMpData->Pm16CodeSegment,
+ CpuMpData->SevEsAPBuffer,
+ CpuMpData->WakeupBuffer
+ );
+ } else {
+ //
+ // Intel processors (32-bit or 64-bit), 32-bit AMD processors, or 64-bit AMD processors without SEV-ES
+ //
+ StackStart = mReservedTopOfApStack;
+ mReservedApLoop.GenericEntry (
+ MwaitSupport,
+ CpuMpData->ApTargetCState,
+ StackStart - ProcessorNumber * AP_SAFE_STACK_SIZE,
+ (UINTN)&mNumberToFinish,
+ mApPageTable
+ );
+ }
+
+ //
+ // It should never reach here
+ //
+ ASSERT (FALSE);
+}
+
+/**
+ 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)
+ );
+ }
+}
diff --git a/UefiCpuPkg/Library/MpInitLib/MpLib.h b/UefiCpuPkg/Library/MpInitLib/MpLib.h index 179f8e585b..e92991d5dc 100644 --- a/UefiCpuPkg/Library/MpInitLib/MpLib.h +++ b/UefiCpuPkg/Library/MpInitLib/MpLib.h @@ -1,7 +1,7 @@ /** @file
Common header file for MP Initialize Library.
- Copyright (c) 2016 - 2023, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2016 - 2024, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2020 - 2024, AMD Inc. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -33,9 +33,10 @@ #include <Library/HobLib.h>
#include <Library/PcdLib.h>
#include <Library/MicrocodeLib.h>
+#include <Library/CpuPageTableLib.h>
#include <ConfidentialComputingGuestAttr.h>
-#include <Register/Amd/Fam17Msr.h>
+#include <Register/Amd/SevSnpMsr.h>
#include <Register/Amd/Ghcb.h>
#include <Guid/MicrocodePatchHob.h>
@@ -68,6 +69,8 @@ //
#define DEFAULT_MAX_MICROCODE_PATCH_NUM 8
+#define PAGING_4K_ADDRESS_MASK_64 0x000FFFFFFFFFF000ull
+
//
// Data structure for microcode patch information
//
@@ -117,9 +120,8 @@ typedef enum { // AP initialization state during APs wakeup
//
typedef enum {
- ApInitConfig = 1,
- ApInitReconfig = 2,
- ApInitDone = 3
+ ApInitConfig = 1,
+ ApInitDone = 2
} AP_INIT_STATE;
//
@@ -286,7 +288,7 @@ struct _CPU_MP_DATA { CPU_AP_DATA *CpuData;
volatile MP_CPU_EXCHANGE_INFO *MpCpuExchangeInfo;
- UINT32 CurrentTimerCount;
+ UINT32 InitTimerCount;
UINTN DivideValue;
UINT8 Vector;
BOOLEAN PeriodicMode;
@@ -357,7 +359,8 @@ typedef IN UINTN StackStart
);
-extern EFI_GUID mCpuInitMpLibHobGuid;
+extern EFI_GUID mCpuInitMpLibHobGuid;
+extern volatile UINT32 mNumberToFinish;
/**
Assembly code to place AP into safe loop mode.
@@ -933,4 +936,52 @@ AmdSevUpdateCpuMpData ( IN CPU_MP_DATA *CpuMpData
);
+/**
+ Prepare ApLoopCode.
+
+ @param[in] CpuMpData Pointer to CpuMpData.
+**/
+VOID
+PrepareApLoopCode (
+ IN CPU_MP_DATA *CpuMpData
+ );
+
+/**
+ Do sync on APs.
+
+ @param[in, out] Buffer Pointer to private data buffer.
+**/
+VOID
+EFIAPI
+RelocateApLoop (
+ IN OUT VOID *Buffer
+ );
+
+/**
+ 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
+ );
+
+/**
+ 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
+ );
+
#endif
diff --git a/UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf b/UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf index e31e34b6f9..e4a7485fef 100644 --- a/UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf +++ b/UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf @@ -1,7 +1,7 @@ ## @file
# MP Initialize Library instance for PEI driver.
#
-# Copyright (c) 2016 - 2021, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2016 - 2024, Intel Corporation. All rights reserved.<BR>
# Copyright (c) 2024, Loongson Technology Corporation Limited. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@@ -25,10 +25,12 @@ [Sources.IA32]
Ia32/AmdSev.c
Ia32/MpFuncs.nasm
+ Ia32/CreatePageTable.c
[Sources.X64]
X64/AmdSev.c
X64/MpFuncs.nasm
+ X64/CreatePageTable.c
[Sources.IA32, Sources.X64]
AmdSev.c
@@ -64,6 +66,7 @@ LocalApicLib
MicrocodeLib
MtrrLib
+ CpuPageTableLib
[Pcd]
gEfiMdeModulePkgTokenSpaceGuid.PcdGhcbBase ## CONSUMES
@@ -87,6 +90,7 @@ gEdkiiS3SmmInitDoneGuid
gEdkiiMicrocodePatchHobGuid
gGhcbApicIdsGuid ## SOMETIMES_CONSUMES
+ gEdkiiEndOfS3ResumeGuid
[Guids.LoongArch64]
gProcessorResourceHobGuid ## SOMETIMES_CONSUMES ## HOB
diff --git a/UefiCpuPkg/Library/MpInitLib/PeiMpLib.c b/UefiCpuPkg/Library/MpInitLib/PeiMpLib.c index 4d3acb491f..16a858d542 100644 --- a/UefiCpuPkg/Library/MpInitLib/PeiMpLib.c +++ b/UefiCpuPkg/Library/MpInitLib/PeiMpLib.c @@ -1,7 +1,7 @@ /** @file
MP initialize support functions for PEI phase.
- Copyright (c) 2016 - 2020, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2016 - 2024, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -9,6 +9,7 @@ #include "MpLib.h"
#include <Library/PeiServicesLib.h>
#include <Guid/S3SmmInitDone.h>
+#include <Guid/EndOfS3Resume.h>
#include <Ppi/ShadowMicrocode.h>
STATIC UINT64 mSevEsPeiWakeupBuffer = BASE_1MB;
@@ -450,6 +451,47 @@ BuildMicrocodeCacheHob ( }
/**
+ S3 SMM Init Done notification function.
+
+ @param PeiServices Indirect reference to the PEI Services Table.
+ @param NotifyDesc Address of the notification descriptor data structure.
+ @param InvokePpi Address of the PPI that was invoked.
+
+ @retval EFI_SUCCESS The function completes successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+NotifyOnEndOfS3Resume (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDesc,
+ IN VOID *InvokePpi
+ )
+{
+ CPU_MP_DATA *CpuMpData;
+
+ CpuMpData = GetCpuMpData ();
+ mNumberToFinish = CpuMpData->CpuCount - 1;
+ WakeUpAP (CpuMpData, TRUE, 0, RelocateApLoop, NULL, TRUE);
+ while (mNumberToFinish > 0) {
+ CpuPause ();
+ }
+
+ DEBUG ((DEBUG_INFO, "%a() done!\n", __func__));
+
+ return EFI_SUCCESS;
+}
+
+//
+// Global function
+//
+EFI_PEI_NOTIFY_DESCRIPTOR mEndOfS3ResumeNotifyDesc = {
+ EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
+ &gEdkiiEndOfS3ResumeGuid,
+ NotifyOnEndOfS3Resume
+};
+
+/**
Initialize global data for MP support.
@param[in] CpuMpData The pointer to CPU MP Data structure.
@@ -463,12 +505,16 @@ InitMpGlobalData ( BuildMicrocodeCacheHob (CpuMpData);
SaveCpuMpData (CpuMpData);
+ PrepareApLoopCode (CpuMpData);
///
/// Install Notify
///
Status = PeiServicesNotifyPpi (&mS3SmmInitDoneNotifyDesc);
ASSERT_EFI_ERROR (Status);
+
+ Status = PeiServicesNotifyPpi (&mEndOfS3ResumeNotifyDesc);
+ ASSERT_EFI_ERROR (Status);
}
/**
@@ -815,3 +861,109 @@ PlatformShadowMicrocode ( return EFI_SUCCESS;
}
+
+/**
+ 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 = PeiServicesAllocatePages (EfiACPIMemoryNVS, Pages, Address);
+ if (EFI_ERROR (Status)) {
+ *Address = 0;
+ }
+}
+
+/**
+ 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;
+ UINTN PageTable;
+ EFI_PHYSICAL_ADDRESS Buffer;
+ UINTN BufferSize;
+ IA32_MAP_ATTRIBUTE MapAttribute;
+ IA32_MAP_ATTRIBUTE MapMask;
+ PAGING_MODE PagingMode;
+ IA32_CR4 Cr4;
+ BOOLEAN Page5LevelSupport;
+ UINT32 RegEax;
+ BOOLEAN Page1GSupport;
+ CPUID_EXTENDED_CPU_SIG_EDX RegEdx;
+
+ if (sizeof (UINTN) == sizeof (UINT64)) {
+ //
+ // Check Page5Level Support or not.
+ //
+ Cr4.UintN = AsmReadCr4 ();
+ Page5LevelSupport = (Cr4.Bits.LA57 ? TRUE : FALSE);
+
+ //
+ // Check Page1G Support or not.
+ //
+ Page1GSupport = FALSE;
+ AsmCpuid (CPUID_EXTENDED_FUNCTION, &RegEax, NULL, NULL, NULL);
+ if (RegEax >= CPUID_EXTENDED_CPU_SIG) {
+ AsmCpuid (CPUID_EXTENDED_CPU_SIG, NULL, NULL, NULL, &RegEdx.Uint32);
+ if (RegEdx.Bits.Page1GB != 0) {
+ Page1GSupport = TRUE;
+ }
+ }
+
+ //
+ // Decide Paging Mode according Page5LevelSupport & Page1GSupport.
+ //
+ if (Page5LevelSupport) {
+ PagingMode = Page1GSupport ? Paging5Level1GB : Paging5Level;
+ } else {
+ PagingMode = Page1GSupport ? Paging4Level1GB : Paging4Level;
+ }
+ } else {
+ PagingMode = PagingPae;
+ }
+
+ MapAttribute.Uint64 = 0;
+ MapMask.Uint64 = 0;
+ MapMask.Bits.Nx = 1;
+ PageTable = AsmReadCr3 () & PAGING_4K_ADDRESS_MASK_64;
+ BufferSize = 0;
+
+ //
+ // Get required buffer size for changing the pagetable.
+ //
+ Status = PageTableMap (&PageTable, PagingMode, 0, &BufferSize, BaseAddress, Length, &MapAttribute, &MapMask, NULL);
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ //
+ // Allocate required Buffer.
+ //
+ Status = PeiServicesAllocatePages (
+ EfiBootServicesData,
+ EFI_SIZE_TO_PAGES (BufferSize),
+ &Buffer
+ );
+ ASSERT_EFI_ERROR (Status);
+ Status = PageTableMap (&PageTable, PagingMode, (VOID *)(UINTN)Buffer, &BufferSize, BaseAddress, Length, &MapAttribute, &MapMask, NULL);
+ }
+
+ ASSERT_EFI_ERROR (Status);
+ AsmWriteCr3 (PageTable);
+}
diff --git a/UefiCpuPkg/Library/MpInitLib/X64/AmdSev.c b/UefiCpuPkg/Library/MpInitLib/X64/AmdSev.c index bbdc47b5a3..a75e1e2018 100644 --- a/UefiCpuPkg/Library/MpInitLib/X64/AmdSev.c +++ b/UefiCpuPkg/Library/MpInitLib/X64/AmdSev.c @@ -11,7 +11,7 @@ #include "MpLib.h"
#include <Library/CcExitLib.h>
#include <Library/AmdSvsmLib.h>
-#include <Register/Amd/Fam17Msr.h>
+#include <Register/Amd/SevSnpMsr.h>
#include <Register/Amd/Ghcb.h>
#define _IS_ALIGNED(x, y) (ALIGN_POINTER((x), (y)) == (x))
|