]> git.proxmox.com Git - mirror_edk2.git/commitdiff
OvmfPkg/BaseMemEncryptSevLib: skip the pre-validated system RAM
authorBrijesh Singh <brijesh.singh@amd.com>
Thu, 9 Dec 2021 03:27:44 +0000 (11:27 +0800)
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Thu, 9 Dec 2021 06:28:10 +0000 (06:28 +0000)
BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3275

The MemEncryptSevSnpPreValidateSystemRam() is used for pre-validating the
system RAM. As the boot progress, each phase validates a fixed region of
the RAM. In the PEI phase, the PlatformPei detects all the available RAM
and calls to pre-validate the detected system RAM.

While validating the system RAM in PEI phase, we must skip previously
validated system RAM to avoid the double validation.

Cc: Michael Roth <michael.roth@amd.com>
Cc: James Bottomley <jejb@linux.ibm.com>
Cc: Min Xu <min.m.xu@intel.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Erdem Aktas <erdemaktas@google.com>
Cc: Gerd Hoffmann <kraxel@redhat.com>
Acked-by: Jiewen Yao <Jiewen.yao@intel.com>
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLib.inf
OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiSnpSystemRamValidate.c

index 0402e49a1028c9fd39ba142d73e1c016ceb4c1fe..49d5bd1beff15e27ea982b85bb870b02a23621ff 100644 (file)
@@ -58,3 +58,5 @@
 \r
 [FixedPcd]\r
   gUefiCpuPkgTokenSpaceGuid.PcdSevEsWorkAreaBase\r
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvBase\r
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPageTablesBase\r
index bc891c2636d6f3da7b016f0704432bd18b0bcd6c..2d2136f8054c6756a50cf281554958b20131e864 100644 (file)
 \r
 #include "SnpPageStateChange.h"\r
 \r
+typedef struct {\r
+  UINT64    StartAddress;\r
+  UINT64    EndAddress;\r
+} SNP_PRE_VALIDATED_RANGE;\r
+\r
+STATIC SNP_PRE_VALIDATED_RANGE  mPreValidatedRange[] = {\r
+  // The below address range was part of the SEV OVMF metadata, and range\r
+  // should be pre-validated by the Hypervisor.\r
+  {\r
+    FixedPcdGet32 (PcdOvmfSecPageTablesBase),\r
+    FixedPcdGet32 (PcdOvmfPeiMemFvBase),\r
+  },\r
+};\r
+\r
+STATIC\r
+BOOLEAN\r
+DetectPreValidatedOverLap (\r
+  IN    PHYSICAL_ADDRESS         StartAddress,\r
+  IN    PHYSICAL_ADDRESS         EndAddress,\r
+  OUT   SNP_PRE_VALIDATED_RANGE  *OverlapRange\r
+  )\r
+{\r
+  UINTN  i;\r
+\r
+  //\r
+  // Check if the specified address range exist in pre-validated array.\r
+  //\r
+  for (i = 0; i < ARRAY_SIZE (mPreValidatedRange); i++) {\r
+    if ((mPreValidatedRange[i].StartAddress < EndAddress) &&\r
+        (StartAddress < mPreValidatedRange[i].EndAddress))\r
+    {\r
+      OverlapRange->StartAddress = mPreValidatedRange[i].StartAddress;\r
+      OverlapRange->EndAddress   = mPreValidatedRange[i].EndAddress;\r
+      return TRUE;\r
+    }\r
+  }\r
+\r
+  return FALSE;\r
+}\r
+\r
 /**\r
   Pre-validate the system RAM when SEV-SNP is enabled in the guest VM.\r
 \r
@@ -28,9 +68,34 @@ MemEncryptSevSnpPreValidateSystemRam (
   IN UINTN             NumPages\r
   )\r
 {\r
+  PHYSICAL_ADDRESS         EndAddress;\r
+  SNP_PRE_VALIDATED_RANGE  OverlapRange;\r
+\r
   if (!MemEncryptSevSnpIsEnabled ()) {\r
     return;\r
   }\r
 \r
-  InternalSetPageState (BaseAddress, NumPages, SevSnpPagePrivate, TRUE);\r
+  EndAddress = BaseAddress + EFI_PAGES_TO_SIZE (NumPages);\r
+\r
+  while (BaseAddress < EndAddress) {\r
+    //\r
+    // Check if the range overlaps with the pre-validated ranges.\r
+    //\r
+    if (DetectPreValidatedOverLap (BaseAddress, EndAddress, &OverlapRange)) {\r
+      // Validate the non-overlap regions.\r
+      if (BaseAddress < OverlapRange.StartAddress) {\r
+        NumPages = EFI_SIZE_TO_PAGES (OverlapRange.StartAddress - BaseAddress);\r
+\r
+        InternalSetPageState (BaseAddress, NumPages, SevSnpPagePrivate, TRUE);\r
+      }\r
+\r
+      BaseAddress = OverlapRange.EndAddress;\r
+      continue;\r
+    }\r
+\r
+    // Validate the remaining pages.\r
+    NumPages = EFI_SIZE_TO_PAGES (EndAddress - BaseAddress);\r
+    InternalSetPageState (BaseAddress, NumPages, SevSnpPagePrivate, TRUE);\r
+    BaseAddress = EndAddress;\r
+  }\r
 }\r