diff --git a/OvmfPkg/PlatformPei/AmdSev.c b/OvmfPkg/PlatformPei/AmdSev.c index e6b602d79a..a9de33074a 100644 --- a/OvmfPkg/PlatformPei/AmdSev.c +++ b/OvmfPkg/PlatformPei/AmdSev.c @@ -1,7 +1,7 @@ /**@file Initialize Secure Encrypted Virtualization (SEV) support - Copyright (c) 2017 - 2020, Advanced Micro Devices. All rights reserved.
+ Copyright (c) 2017 - 2024, Advanced Micro Devices. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent @@ -9,6 +9,7 @@ // // The package level header files this module uses // +#include #include #include #include @@ -31,6 +32,87 @@ GetHypervisorFeature ( VOID ); +/** + Retrieve APIC IDs from the hypervisor. + +**/ +STATIC +VOID +AmdSevSnpGetApicIds ( + VOID + ) +{ + MSR_SEV_ES_GHCB_REGISTER Msr; + GHCB *Ghcb; + BOOLEAN InterruptState; + UINT64 VmgExitStatus; + UINT64 PageCount; + BOOLEAN PageCountValid; + VOID *ApicIds; + RETURN_STATUS Status; + UINT64 GuidData; + + Msr.GhcbPhysicalAddress = AsmReadMsr64 (MSR_SEV_ES_GHCB); + Ghcb = Msr.Ghcb; + + PageCount = 0; + PageCountValid = FALSE; + + CcExitVmgInit (Ghcb, &InterruptState); + Ghcb->SaveArea.Rax = PageCount; + CcExitVmgSetOffsetValid (Ghcb, GhcbRax); + VmgExitStatus = CcExitVmgExit (Ghcb, SVM_EXIT_GET_APIC_IDS, 0, 0); + if (CcExitVmgIsOffsetValid (Ghcb, GhcbRax)) { + PageCount = Ghcb->SaveArea.Rax; + PageCountValid = TRUE; + } + + CcExitVmgDone (Ghcb, InterruptState); + + ASSERT (VmgExitStatus == 0); + ASSERT (PageCountValid); + if ((VmgExitStatus != 0) || !PageCountValid) { + return; + } + + // + // Allocate the memory for the APIC IDs + // + ApicIds = AllocateReservedPages ((UINTN)PageCount); + ASSERT (ApicIds != NULL); + + Status = MemEncryptSevClearPageEncMask ( + 0, + (UINTN)ApicIds, + (UINTN)PageCount + ); + ASSERT_RETURN_ERROR (Status); + + ZeroMem (ApicIds, EFI_PAGES_TO_SIZE ((UINTN)PageCount)); + + PageCountValid = FALSE; + + CcExitVmgInit (Ghcb, &InterruptState); + Ghcb->SaveArea.Rax = PageCount; + CcExitVmgSetOffsetValid (Ghcb, GhcbRax); + VmgExitStatus = CcExitVmgExit (Ghcb, SVM_EXIT_GET_APIC_IDS, (UINTN)ApicIds, 0); + if (CcExitVmgIsOffsetValid (Ghcb, GhcbRax) && (Ghcb->SaveArea.Rax == PageCount)) { + PageCountValid = TRUE; + } + + CcExitVmgDone (Ghcb, InterruptState); + + ASSERT (VmgExitStatus == 0); + ASSERT (PageCountValid); + if ((VmgExitStatus != 0) || !PageCountValid) { + FreePages (ApicIds, (UINTN)PageCount); + return; + } + + GuidData = (UINT64)(UINTN)ApicIds; + BuildGuidDataHob (&gGhcbApicIdsGuid, &GuidData, sizeof (GuidData)); +} + /** Initialize SEV-SNP support if running as an SEV-SNP guest. @@ -78,6 +160,14 @@ AmdSevSnpInitialize ( } } } + + // + // Retrieve the APIC IDs if the hypervisor supports it. These will be used + // to always start APs using SNP AP Create. + // + if ((HvFeatures & GHCB_HV_FEATURES_APIC_ID_LIST) == GHCB_HV_FEATURES_APIC_ID_LIST) { + AmdSevSnpGetApicIds (); + } } /** diff --git a/OvmfPkg/PlatformPei/PlatformPei.inf b/OvmfPkg/PlatformPei/PlatformPei.inf index ad52be3065..2206316fec 100644 --- a/OvmfPkg/PlatformPei/PlatformPei.inf +++ b/OvmfPkg/PlatformPei/PlatformPei.inf @@ -45,6 +45,7 @@ gEfiMemoryTypeInformationGuid gFdtHobGuid gUefiOvmfPkgPlatformInfoGuid + gGhcbApicIdsGuid [LibraryClasses] BaseLib