Hi Ray and Rahul, Any comment on this patch ? If you are okay with the approach then can I get Ack or R-b ?
-Brijesh On 10/22/21 11:13 PM, Brijesh Singh via groups.io wrote: > From: Tom Lendacky <thomas.lenda...@amd.com> > > BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3275 > > Use the SEV-SNP AP Creation NAE event to create and launch APs under > SEV-SNP. This capability will be advertised in the SEV Hypervisor > Feature Support PCD (PcdSevEsHypervisorFeatures). > > Cc: Michael Roth <michael.r...@amd.com> > Cc: Eric Dong <eric.d...@intel.com> > Cc: Ray Ni <ray...@intel.com> > Cc: Rahul Kumar <rahul1.ku...@intel.com> > Cc: James Bottomley <j...@linux.ibm.com> > Cc: Min Xu <min.m...@intel.com> > Cc: Jiewen Yao <jiewen....@intel.com> > Cc: Tom Lendacky <thomas.lenda...@amd.com> > Cc: Jordan Justen <jordan.l.jus...@intel.com> > Cc: Ard Biesheuvel <ardb+tianoc...@kernel.org> > Cc: Erdem Aktas <erdemak...@google.com> > Cc: Gerd Hoffmann <kra...@redhat.com> > Acked-by: Gerd Hoffmann <kra...@redhat.com> > Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com> > Signed-off-by: Brijesh Singh <brijesh.si...@amd.com> > --- > UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf | 3 + > UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf | 3 + > UefiCpuPkg/Library/MpInitLib/MpLib.h | 44 +++ > UefiCpuPkg/Library/MpInitLib/DxeMpLib.c | 12 +- > UefiCpuPkg/Library/MpInitLib/Ia32/AmdSev.c | 70 +++++ > UefiCpuPkg/Library/MpInitLib/MpLib.c | 51 ++-- > UefiCpuPkg/Library/MpInitLib/X64/AmdSev.c | 261 ++++++++++++++++++ > 7 files changed, 425 insertions(+), 19 deletions(-) > create mode 100644 UefiCpuPkg/Library/MpInitLib/Ia32/AmdSev.c > create mode 100644 UefiCpuPkg/Library/MpInitLib/X64/AmdSev.c > > diff --git a/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf > b/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf > index de705bc54bb4..e1cd0b350008 100644 > --- a/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf > +++ b/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf > @@ -22,9 +22,11 @@ [Defines] > # > > [Sources.IA32] > + Ia32/AmdSev.c > Ia32/MpFuncs.nasm > > [Sources.X64] > + X64/AmdSev.c > X64/MpFuncs.nasm > > [Sources.common] > @@ -73,6 +75,7 @@ [Pcd] > gUefiCpuPkgTokenSpaceGuid.PcdCpuApLoopMode ## > CONSUMES > gUefiCpuPkgTokenSpaceGuid.PcdCpuApTargetCstate ## > SOMETIMES_CONSUMES > gUefiCpuPkgTokenSpaceGuid.PcdCpuApStatusCheckIntervalInMicroSeconds ## > CONSUMES > + gUefiCpuPkgTokenSpaceGuid.PcdGhcbHypervisorFeatures ## > CONSUMES > gUefiCpuPkgTokenSpaceGuid.PcdSevEsWorkAreaBase ## > SOMETIMES_CONSUMES > gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard ## > CONSUMES > gEfiMdeModulePkgTokenSpaceGuid.PcdGhcbBase ## > CONSUMES > diff --git a/UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf > b/UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf > index b7e15ee023f0..5facf4db9499 100644 > --- a/UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf > +++ b/UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf > @@ -22,9 +22,11 @@ [Defines] > # > > [Sources.IA32] > + Ia32/AmdSev.c > Ia32/MpFuncs.nasm > > [Sources.X64] > + X64/AmdSev.c > X64/MpFuncs.nasm > > [Sources.common] > @@ -64,6 +66,7 @@ [Pcd] > gUefiCpuPkgTokenSpaceGuid.PcdCpuApLoopMode ## > CONSUMES > gUefiCpuPkgTokenSpaceGuid.PcdCpuApTargetCstate ## > SOMETIMES_CONSUMES > gUefiCpuPkgTokenSpaceGuid.PcdSevEsWorkAreaBase ## > SOMETIMES_CONSUMES > + gUefiCpuPkgTokenSpaceGuid.PcdGhcbHypervisorFeatures ## > CONSUMES > gEfiMdeModulePkgTokenSpaceGuid.PcdGhcbBase ## > CONSUMES > gEfiMdePkgTokenSpaceGuid.PcdConfidentialComputingGuestAttr ## > CONSUMES > > diff --git a/UefiCpuPkg/Library/MpInitLib/MpLib.h > b/UefiCpuPkg/Library/MpInitLib/MpLib.h > index c52b6157429b..48f6e933bb36 100644 > --- a/UefiCpuPkg/Library/MpInitLib/MpLib.h > +++ b/UefiCpuPkg/Library/MpInitLib/MpLib.h > @@ -15,6 +15,7 @@ > > #include <Register/Intel/Cpuid.h> > #include <Register/Amd/Cpuid.h> > +#include <Register/Amd/Ghcb.h> > #include <Register/Intel/Msr.h> > #include <Register/Intel/LocalApic.h> > #include <Register/Intel/Microcode.h> > @@ -150,6 +151,7 @@ typedef struct { > UINT8 PlatformId; > UINT64 MicrocodeEntryAddr; > UINT32 MicrocodeRevision; > + SEV_ES_SAVE_AREA *SevEsSaveArea; > } CPU_AP_DATA; > > // > @@ -294,6 +296,7 @@ struct _CPU_MP_DATA { > > BOOLEAN SevEsIsEnabled; > BOOLEAN SevSnpIsEnabled; > + BOOLEAN UseSevEsAPMethod; > UINTN SevEsAPBuffer; > UINTN SevEsAPResetStackStart; > CPU_MP_DATA *NewCpuMpData; > @@ -790,5 +793,46 @@ ConfidentialComputingGuestHas ( > CONFIDENTIAL_COMPUTING_GUEST_ATTR Attr > ); > > +/** > + Issue RMPADJUST to adjust the VMSA attribute of an SEV-SNP page. > + > + @param[in] PageAddress > + @param[in] VmsaPage > + > + @return RMPADJUST return value > +**/ > +UINT32 > +SevSnpRmpAdjust ( > + IN EFI_PHYSICAL_ADDRESS PageAddress, > + IN BOOLEAN VmsaPage > + ); > + > +/** > + Create an SEV-SNP AP save area (VMSA) for use in running the vCPU. > + > + @param[in] CpuMpData Pointer to CPU MP Data > + @param[in] CpuData Pointer to CPU AP Data > + @param[in] ApicId APIC ID of the vCPU > +**/ > +VOID > +SevSnpCreateSaveArea ( > + IN CPU_MP_DATA *CpuMpData, > + IN CPU_AP_DATA *CpuData, > + UINT32 ApicId > + ); > + > +/** > + Create SEV-SNP APs. > + > + @param[in] CpuMpData Pointer to CPU MP Data > + @param[in] ProcessorNumber The handle number of specified processor > + (-1 for all APs) > +**/ > +VOID > +SevSnpCreateAP ( > + IN CPU_MP_DATA *CpuMpData, > + IN INTN ProcessorNumber > + ); > + > #endif > > diff --git a/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c > b/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c > index 657a73dca05e..7a3ef0015a31 100644 > --- a/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c > +++ b/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c > @@ -93,7 +93,13 @@ GetWakeupBuffer ( > EFI_PHYSICAL_ADDRESS StartAddress; > EFI_MEMORY_TYPE MemoryType; > > - if (ConfidentialComputingGuestHas (CCAttrAmdSevEs)) { > + if (ConfidentialComputingGuestHas (CCAttrAmdSevEs) && > + !ConfidentialComputingGuestHas (CCAttrAmdSevSnp)) { > + // > + // An SEV-ES-only guest requires the memory to be reserved. SEV-SNP, which > + // is also considered SEV-ES, uses a different AP startup method, though, > + // which does not have the same requirement. > + // > MemoryType = EfiReservedMemoryType; > } else { > MemoryType = EfiBootServicesData; > @@ -373,7 +379,7 @@ RelocateApLoop ( > MpInitLibWhoAmI (&ProcessorNumber); > CpuMpData = GetCpuMpData (); > MwaitSupport = IsMwaitSupport (); > - if (CpuMpData->SevEsIsEnabled) { > + if (CpuMpData->UseSevEsAPMethod) { > StackStart = CpuMpData->SevEsAPResetStackStart; > } else { > StackStart = mReservedTopOfApStack; > @@ -422,7 +428,7 @@ MpInitChangeApLoopCallback ( > CpuPause (); > } > > - if (CpuMpData->SevEsIsEnabled && (CpuMpData->WakeupBuffer != (UINTN) -1)) { > + if (CpuMpData->UseSevEsAPMethod && (CpuMpData->WakeupBuffer != (UINTN) > -1)) { > // > // There are APs present. Re-use reserved memory area below 1MB from > // WakeupBuffer as the area to be used for transitioning to 16-bit mode > diff --git a/UefiCpuPkg/Library/MpInitLib/Ia32/AmdSev.c > b/UefiCpuPkg/Library/MpInitLib/Ia32/AmdSev.c > new file mode 100644 > index 000000000000..a4702e298d98 > --- /dev/null > +++ b/UefiCpuPkg/Library/MpInitLib/Ia32/AmdSev.c > @@ -0,0 +1,70 @@ > +/** @file > + > + AMD SEV helper function. > + > + Copyright (c) 2021, AMD Incorporated. All rights reserved.<BR> > + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#include "MpLib.h" > + > +/** > + Create an SEV-SNP AP save area (VMSA) for use in running the vCPU. > + > + @param[in] CpuMpData Pointer to CPU MP Data > + @param[in] CpuData Pointer to CPU AP Data > + @param[in] ApicId APIC ID of the vCPU > +**/ > +VOID > +SevSnpCreateSaveArea ( > + IN CPU_MP_DATA *CpuMpData, > + IN CPU_AP_DATA *CpuData, > + UINT32 ApicId > + ) > +{ > + // > + // SEV-SNP is not support on 32-bit build. > + // > + ASSERT (FALSE); > +} > + > +/** > + Create SEV-SNP APs. > + > + @param[in] CpuMpData Pointer to CPU MP Data > + @param[in] ProcessorNumber The handle number of specified processor > + (-1 for all APs) > +**/ > +VOID > +SevSnpCreateAP ( > + IN CPU_MP_DATA *CpuMpData, > + IN INTN ProcessorNumber > + ) > +{ > + // > + // SEV-SNP is not support on 32-bit build. > + // > + ASSERT (FALSE); > +} > + > +/** > + Issue RMPADJUST to adjust the VMSA attribute of an SEV-SNP page. > + > + @param[in] PageAddress > + @param[in] VmsaPage > + > + @return RMPADJUST return value > +**/ > +UINT32 > +SevSnpRmpAdjust ( > + IN EFI_PHYSICAL_ADDRESS PageAddress, > + IN BOOLEAN VmsaPage > + ) > +{ > + // > + // RMPADJUST is not supported in 32-bit mode > + // > + return RETURN_UNSUPPORTED; > +} > diff --git a/UefiCpuPkg/Library/MpInitLib/MpLib.c > b/UefiCpuPkg/Library/MpInitLib/MpLib.c > index d8372ffa9d5a..d134dc1326e8 100644 > --- a/UefiCpuPkg/Library/MpInitLib/MpLib.c > +++ b/UefiCpuPkg/Library/MpInitLib/MpLib.c > @@ -295,10 +295,11 @@ GetApLoopMode ( > ApLoopMode = ApInHltLoop; > } > > - if (ConfidentialComputingGuestHas (CCAttrAmdSevEs)) { > + if (ConfidentialComputingGuestHas (CCAttrAmdSevEs) && > + !ConfidentialComputingGuestHas (CCAttrAmdSevSnp)) { > // > - // For SEV-ES, force AP in Hlt-loop mode in order to use the GHCB > - // protocol for starting APs > + // For SEV-ES (SEV-SNP is also considered SEV-ES), force AP in Hlt-loop > + // mode in order to use the GHCB protocol for starting APs > // > ApLoopMode = ApInHltLoop; > } > @@ -758,7 +759,7 @@ ApWakeupFunction ( > // to allow the APs to issue an AP_RESET_HOLD before the BSP possibly > // performs another INIT-SIPI-SIPI sequence. > // > - if (!CpuMpData->SevEsIsEnabled) { > + if (!CpuMpData->UseSevEsAPMethod) { > InterlockedDecrement ((UINT32 *) > &CpuMpData->MpCpuExchangeInfo->NumApsExecuting); > } > } > @@ -772,7 +773,7 @@ ApWakeupFunction ( > // > while (TRUE) { > DisableInterrupts (); > - if (CpuMpData->SevEsIsEnabled) { > + if (CpuMpData->UseSevEsAPMethod) { > SevEsPlaceApHlt (CpuMpData); > } else { > CpuSleep (); > @@ -1056,9 +1057,12 @@ AllocateResetVector ( > ); > // > // The AP reset stack is only used by SEV-ES guests. Do not allocate it > - // if SEV-ES is not enabled. > + // if SEV-ES is not enabled. An SEV-SNP guest is also considered > + // an SEV-ES guest, but uses a different method of AP startup, > eliminating > + // the need for the allocation. > // > - if (ConfidentialComputingGuestHas (CCAttrAmdSevEs)) { > + if (ConfidentialComputingGuestHas (CCAttrAmdSevEs) && > + !ConfidentialComputingGuestHas (CCAttrAmdSevSnp)) { > // > // Stack location is based on ProcessorNumber, so use the total number > // of processors for calculating the total stack area. > @@ -1108,7 +1112,7 @@ FreeResetVector ( > // perform the restore as this will overwrite memory which has data > // needed by SEV-ES. > // > - if (!CpuMpData->SevEsIsEnabled) { > + if (!CpuMpData->UseSevEsAPMethod) { > RestoreWakeupBuffer (CpuMpData); > } > } > @@ -1144,7 +1148,7 @@ WakeUpAP ( > ResetVectorRequired = FALSE; > > if (CpuMpData->WakeUpByInitSipiSipi || > - CpuMpData->InitFlag != ApInitDone) { > + CpuMpData->InitFlag != ApInitDone) { > ResetVectorRequired = TRUE; > AllocateResetVector (CpuMpData); > AllocateSevEsAPMemory (CpuMpData); > @@ -1185,7 +1189,7 @@ WakeUpAP ( > } > if (ResetVectorRequired) { > // > - // For SEV-ES, the initial AP boot address will be defined by > + // For SEV-ES and SEV-SNP, the initial AP boot address will be defined > by > // PcdSevEsWorkAreaBase. The Segment/Rip must be the jump address > // from the original INIT-SIPI-SIPI. > // > @@ -1195,8 +1199,14 @@ WakeUpAP ( > > // > // Wakeup all APs > + // Must use the INIT-SIPI-SIPI method for initial configuration in > + // order to obtain the APIC ID. > // > - SendInitSipiSipiAllExcludingSelf ((UINT32) ExchangeInfo->BufferStart); > + if (CpuMpData->SevSnpIsEnabled && CpuMpData->InitFlag != ApInitConfig) > { > + SevSnpCreateAP (CpuMpData, -1); > + } else { > + SendInitSipiSipiAllExcludingSelf ((UINT32) > ExchangeInfo->BufferStart); > + } > } > if (CpuMpData->InitFlag == ApInitConfig) { > if (PcdGet32 (PcdCpuBootLogicalProcessorNumber) > 0) { > @@ -1286,7 +1296,7 @@ WakeUpAP ( > CpuInfoInHob = (CPU_INFO_IN_HOB *) (UINTN) CpuMpData->CpuInfoInHob; > > // > - // For SEV-ES, the initial AP boot address will be defined by > + // For SEV-ES and SEV-SNP, the initial AP boot address will be defined > by > // PcdSevEsWorkAreaBase. The Segment/Rip must be the jump address > // from the original INIT-SIPI-SIPI. > // > @@ -1294,10 +1304,14 @@ WakeUpAP ( > SetSevEsJumpTable (ExchangeInfo->BufferStart); > } > > - SendInitSipiSipi ( > - CpuInfoInHob[ProcessorNumber].ApicId, > - (UINT32) ExchangeInfo->BufferStart > - ); > + if (CpuMpData->SevSnpIsEnabled && CpuMpData->InitFlag != ApInitConfig) > { > + SevSnpCreateAP (CpuMpData, (INTN) ProcessorNumber); > + } else { > + SendInitSipiSipi ( > + CpuInfoInHob[ProcessorNumber].ApicId, > + (UINT32) ExchangeInfo->BufferStart > + ); > + } > } > // > // Wait specified AP waken up > @@ -1832,6 +1846,11 @@ MpInitLibInitialize ( > CpuMpData->SevSnpIsEnabled = ConfidentialComputingGuestHas > (CCAttrAmdSevSnp); > CpuMpData->SevEsAPBuffer = (UINTN) -1; > CpuMpData->GhcbBase = PcdGet64 (PcdGhcbBase); > + CpuMpData->UseSevEsAPMethod = CpuMpData->SevEsIsEnabled && > !CpuMpData->SevSnpIsEnabled; > + > + if (CpuMpData->SevSnpIsEnabled) { > + ASSERT ((PcdGet64 (PcdGhcbHypervisorFeatures) & > GHCB_HV_FEATURES_SNP_AP_CREATE) == GHCB_HV_FEATURES_SNP_AP_CREATE); > + } > > // > // Make sure no memory usage outside of the allocated buffer. > diff --git a/UefiCpuPkg/Library/MpInitLib/X64/AmdSev.c > b/UefiCpuPkg/Library/MpInitLib/X64/AmdSev.c > new file mode 100644 > index 000000000000..303271abdaad > --- /dev/null > +++ b/UefiCpuPkg/Library/MpInitLib/X64/AmdSev.c > @@ -0,0 +1,261 @@ > +/** @file > + > + AMD SEV helper function. > + > + Copyright (c) 2021, AMD Incorporated. All rights reserved.<BR> > + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#include "MpLib.h" > +#include <Library/VmgExitLib.h> > +#include <Register/Amd/Fam17Msr.h> > +#include <Register/Amd/Ghcb.h> > + > +/** > + Create an SEV-SNP AP save area (VMSA) for use in running the vCPU. > + > + @param[in] CpuMpData Pointer to CPU MP Data > + @param[in] CpuData Pointer to CPU AP Data > + @param[in] ApicId APIC ID of the vCPU > +**/ > +VOID > +SevSnpCreateSaveArea ( > + IN CPU_MP_DATA *CpuMpData, > + IN CPU_AP_DATA *CpuData, > + UINT32 ApicId > + ) > +{ > + SEV_ES_SAVE_AREA *SaveArea; > + IA32_CR0 ApCr0; > + IA32_CR0 ResetCr0; > + IA32_CR4 ApCr4; > + IA32_CR4 ResetCr4; > + UINTN StartIp; > + UINT8 SipiVector; > + UINT32 RmpAdjustStatus; > + UINT64 VmgExitStatus; > + MSR_SEV_ES_GHCB_REGISTER Msr; > + GHCB *Ghcb; > + BOOLEAN InterruptState; > + UINT64 ExitInfo1; > + UINT64 ExitInfo2; > + > + // > + // Allocate a single page for the SEV-ES Save Area and initialize it. > + // > + SaveArea = AllocateReservedPages (1); > + if (!SaveArea) { > + return; > + } > + ZeroMem (SaveArea, EFI_PAGE_SIZE); > + > + // > + // Propogate the CR0.NW and CR0.CD setting to the AP > + // > + ResetCr0.UintN = 0x00000010; > + ApCr0.UintN = CpuData->VolatileRegisters.Cr0; > + if (ApCr0.Bits.NW) { > + ResetCr0.Bits.NW = 1; > + } > + if (ApCr0.Bits.CD) { > + ResetCr0.Bits.CD = 1; > + } > + > + // > + // Propagate the CR4.MCE setting to the AP > + // > + ResetCr4.UintN = 0; > + ApCr4.UintN = CpuData->VolatileRegisters.Cr4; > + if (ApCr4.Bits.MCE) { > + ResetCr4.Bits.MCE = 1; > + } > + > + // > + // Convert the start IP into a SIPI Vector > + // > + StartIp = CpuMpData->MpCpuExchangeInfo->BufferStart; > + SipiVector = (UINT8) (StartIp >> 12); > + > + // > + // Set the CS:RIP value based on the start IP > + // > + SaveArea->Cs.Base = SipiVector << 12; > + SaveArea->Cs.Selector = SipiVector << 8; > + SaveArea->Cs.Limit = 0xFFFF; > + SaveArea->Cs.Attributes.Bits.Present = 1; > + SaveArea->Cs.Attributes.Bits.Sbit = 1; > + SaveArea->Cs.Attributes.Bits.Type = SEV_ES_RESET_CODE_SEGMENT_TYPE; > + SaveArea->Rip = StartIp & 0xFFF; > + > + // > + // Set the remaining values as defined in APM for INIT > + // > + SaveArea->Ds.Limit = 0xFFFF; > + SaveArea->Ds.Attributes.Bits.Present = 1; > + SaveArea->Ds.Attributes.Bits.Sbit = 1; > + SaveArea->Ds.Attributes.Bits.Type = SEV_ES_RESET_DATA_SEGMENT_TYPE; > + SaveArea->Es = SaveArea->Ds; > + SaveArea->Fs = SaveArea->Ds; > + SaveArea->Gs = SaveArea->Ds; > + SaveArea->Ss = SaveArea->Ds; > + > + SaveArea->Gdtr.Limit = 0xFFFF; > + SaveArea->Ldtr.Limit = 0xFFFF; > + SaveArea->Ldtr.Attributes.Bits.Present = 1; > + SaveArea->Ldtr.Attributes.Bits.Type = SEV_ES_RESET_LDT_TYPE; > + SaveArea->Idtr.Limit = 0xFFFF; > + SaveArea->Tr.Limit = 0xFFFF; > + SaveArea->Ldtr.Attributes.Bits.Present = 1; > + SaveArea->Ldtr.Attributes.Bits.Type = SEV_ES_RESET_TSS_TYPE; > + > + SaveArea->Efer = 0x1000; > + SaveArea->Cr4 = ResetCr4.UintN; > + SaveArea->Cr0 = ResetCr0.UintN; > + SaveArea->Dr7 = 0x0400; > + SaveArea->Dr6 = 0xFFFF0FF0; > + SaveArea->Rflags = 0x0002; > + SaveArea->GPat = 0x0007040600070406ULL; > + SaveArea->XCr0 = 0x0001; > + SaveArea->Mxcsr = 0x1F80; > + SaveArea->X87Ftw = 0x5555; > + SaveArea->X87Fcw = 0x0040; > + > + // > + // Set the SEV-SNP specific fields for the save area: > + // VMPL - always VMPL0 > + // SEV_FEATURES - equivalent to the SEV_STATUS MSR right shifted 2 bits > + // > + SaveArea->Vmpl = 0; > + SaveArea->SevFeatures = AsmReadMsr64 (MSR_SEV_STATUS) >> 2; > + > + // > + // To turn the page into a recognized VMSA page, issue RMPADJUST: > + // Target VMPL but numerically higher than current VMPL > + // Target PermissionMask is not used > + // > + RmpAdjustStatus = SevSnpRmpAdjust ( > + (EFI_PHYSICAL_ADDRESS) (UINTN) SaveArea, > + TRUE > + ); > + ASSERT (RmpAdjustStatus == 0); > + > + ExitInfo1 = (UINT64) ApicId << 32; > + ExitInfo1 |= SVM_VMGEXIT_SNP_AP_CREATE; > + ExitInfo2 = (UINT64) (UINTN) SaveArea; > + > + Msr.GhcbPhysicalAddress = AsmReadMsr64 (MSR_SEV_ES_GHCB); > + Ghcb = Msr.Ghcb; > + > + VmgInit (Ghcb, &InterruptState); > + Ghcb->SaveArea.Rax = SaveArea->SevFeatures; > + VmgSetOffsetValid (Ghcb, GhcbRax); > + VmgExitStatus = VmgExit ( > + Ghcb, > + SVM_EXIT_SNP_AP_CREATION, > + ExitInfo1, > + ExitInfo2 > + ); > + VmgDone (Ghcb, InterruptState); > + > + ASSERT (VmgExitStatus == 0); > + if (VmgExitStatus != 0) { > + RmpAdjustStatus = SevSnpRmpAdjust ( > + (EFI_PHYSICAL_ADDRESS) (UINTN) SaveArea, > + FALSE > + ); > + if (RmpAdjustStatus == 0) { > + FreePages (SaveArea, 1); > + } else { > + DEBUG ((DEBUG_INFO, "SEV-SNP: RMPADJUST failed, leaking VMSA page\n")); > + } > + > + SaveArea = NULL; > + } > + > + if (CpuData->SevEsSaveArea) { > + RmpAdjustStatus = SevSnpRmpAdjust ( > + (EFI_PHYSICAL_ADDRESS) (UINTN) > CpuData->SevEsSaveArea, > + FALSE > + ); > + if (RmpAdjustStatus == 0) { > + FreePages (CpuData->SevEsSaveArea, 1); > + } else { > + DEBUG ((DEBUG_INFO, "SEV-SNP: RMPADJUST failed, leaking VMSA page\n")); > + } > + } > + > + CpuData->SevEsSaveArea = SaveArea; > +} > + > +/** > + Create SEV-SNP APs. > + > + @param[in] CpuMpData Pointer to CPU MP Data > + @param[in] ProcessorNumber The handle number of specified processor > + (-1 for all APs) > +**/ > +VOID > +SevSnpCreateAP ( > + IN CPU_MP_DATA *CpuMpData, > + IN INTN ProcessorNumber > + ) > +{ > + CPU_INFO_IN_HOB *CpuInfoInHob; > + CPU_AP_DATA *CpuData; > + UINTN Index; > + UINT32 ApicId; > + > + ASSERT (CpuMpData->MpCpuExchangeInfo->BufferStart < 0x100000); > + > + CpuInfoInHob = (CPU_INFO_IN_HOB *) (UINTN) CpuMpData->CpuInfoInHob; > + > + if (ProcessorNumber < 0) { > + for (Index = 0; Index < CpuMpData->CpuCount; Index++) { > + if (Index != CpuMpData->BspNumber) { > + CpuData = &CpuMpData->CpuData[Index]; > + ApicId = CpuInfoInHob[Index].ApicId, > + SevSnpCreateSaveArea (CpuMpData, CpuData, ApicId); > + } > + } > + } else { > + Index = (UINTN) ProcessorNumber; > + CpuData = &CpuMpData->CpuData[Index]; > + ApicId = CpuInfoInHob[ProcessorNumber].ApicId, > + SevSnpCreateSaveArea (CpuMpData, CpuData, ApicId); > + } > +} > + > +/** > + Issue RMPADJUST to adjust the VMSA attribute of an SEV-SNP page. > + > + @param[in] PageAddress > + @param[in] VmsaPage > + > + @return RMPADJUST return value > +**/ > +UINT32 > +SevSnpRmpAdjust ( > + IN EFI_PHYSICAL_ADDRESS PageAddress, > + IN BOOLEAN VmsaPage > + ) > +{ > + UINT64 Rdx; > + > + // > + // The RMPADJUST instruction is used to set or clear the VMSA bit for a > + // page. The VMSA change is only made when running at VMPL0 and is ignored > + // otherwise. If too low a target VMPL is specified, the instruction can > + // succeed without changing the VMSA bit when not running at VMPL0. Using a > + // target VMPL level of 1, RMPADJUST will return a FAIL_PERMISSION error if > + // not running at VMPL0, thus ensuring that the VMSA bit is set > appropriately > + // when no error is returned. > + // > + Rdx = 1; > + if (VmsaPage) { > + Rdx |= RMPADJUST_VMSA_PAGE_BIT; > + } > + > + return AsmRmpAdjust ((UINT64) PageAddress, 0, Rdx); > +} -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#82609): https://edk2.groups.io/g/devel/message/82609 Mute This Topic: https://groups.io/mt/86566126/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-