BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=4654
If the hypervisor supports retrieval of the vCPU APIC IDs, retrieve them before any APs are actually started. The APIC IDs can be used to start the APs for any SEV-SNP guest, but is a requirement for an SEV-SNP guest that is running under an SVSM. After retrieving the APIC IDs, save the address of the APIC ID data structure in the PcdSevSnpApicIds PCD. Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com> --- OvmfPkg/PlatformPei/PlatformPei.inf | 1 + OvmfPkg/PlatformPei/AmdSev.c | 87 ++++++++++++++++++++ 2 files changed, 88 insertions(+) diff --git a/OvmfPkg/PlatformPei/PlatformPei.inf b/OvmfPkg/PlatformPei/PlatformPei.inf index 6907cc72669e..6379f66b627d 100644 --- a/OvmfPkg/PlatformPei/PlatformPei.inf +++ b/OvmfPkg/PlatformPei/PlatformPei.inf @@ -116,6 +116,7 @@ [Pcd] gEfiMdePkgTokenSpaceGuid.PcdConfidentialComputingGuestAttr gUefiCpuPkgTokenSpaceGuid.PcdGhcbHypervisorFeatures gEfiMdeModulePkgTokenSpaceGuid.PcdTdxSharedBitMask + gUefiCpuPkgTokenSpaceGuid.PcdSevSnpApicIds [FixedPcd] gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCpuidBase diff --git a/OvmfPkg/PlatformPei/AmdSev.c b/OvmfPkg/PlatformPei/AmdSev.c index af832d3e535e..d8a30b6e1613 100644 --- a/OvmfPkg/PlatformPei/AmdSev.c +++ b/OvmfPkg/PlatformPei/AmdSev.c @@ -31,6 +31,85 @@ 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; + + 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; + } + + Status = PcdSet64S (PcdSevSnpApicIds, (UINTN)ApicIds); +} + /** Initialize SEV-SNP support if running as an SEV-SNP guest. @@ -78,6 +157,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 (); + } } /** -- 2.42.0 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#114638): https://edk2.groups.io/g/devel/message/114638 Mute This Topic: https://groups.io/mt/103986465/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-