File 0013-OvmfPkg-PlatformPei-Retrieve-APIC-IDs-from-the-hyper.patch of Package ovmf

From 143a55bbc0639341eaa863c372718715936a0822 Mon Sep 17 00:00:00 2001
From: Tom Lendacky <thomas.lendacky@amd.com>
Date: Tue, 9 Jan 2024 12:44:28 -0600
Subject: [PATCH 13/17] OvmfPkg/PlatformPei: Retrieve APIC IDs from the
 hypervisor

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.lendacky@amd.com>
---
 OvmfPkg/PlatformPei/AmdSev.c        | 87 +++++++++++++++++++++++++++++
 OvmfPkg/PlatformPei/PlatformPei.inf |  1 +
 2 files changed, 88 insertions(+)

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 ();
+  }
 }
 
 /**
diff --git a/OvmfPkg/PlatformPei/PlatformPei.inf b/OvmfPkg/PlatformPei/PlatformPei.inf
index d97057fc0a1a..4e6febb71b03 100644
--- a/OvmfPkg/PlatformPei/PlatformPei.inf
+++ b/OvmfPkg/PlatformPei/PlatformPei.inf
@@ -116,6 +116,7 @@
   gEfiMdePkgTokenSpaceGuid.PcdConfidentialComputingGuestAttr
   gUefiCpuPkgTokenSpaceGuid.PcdGhcbHypervisorFeatures
   gEfiMdeModulePkgTokenSpaceGuid.PcdTdxSharedBitMask
+  gUefiCpuPkgTokenSpaceGuid.PcdSevSnpApicIds
 
 [FixedPcd]
   gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCpuidBase
-- 
2.44.0

openSUSE Build Service is sponsored by