]> git.proxmox.com Git - mirror_edk2.git/commitdiff
OvmfPkg: Create GHCB pages for use during Pei and Dxe phase
authorTom Lendacky <thomas.lendacky@amd.com>
Wed, 12 Aug 2020 20:21:40 +0000 (15:21 -0500)
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Mon, 17 Aug 2020 02:46:39 +0000 (02:46 +0000)
BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=2198

Allocate memory for the GHCB pages and the per-CPU variable pages during
SEV initialization for use during Pei and Dxe phases. The GHCB page(s)
must be shared pages, so clear the encryption mask from the current page
table entries. Upon successful allocation, set the GHCB PCDs (PcdGhcbBase
and PcdGhcbSize).

The per-CPU variable page needs to be unique per AP. Using the page after
the GHCB ensures that it is unique per AP. Only the GHCB page is marked as
shared, keeping the per-CPU variable page encyrpted. The same logic is
used in DXE using CreateIdentityMappingPageTables() before switching to
the DXE pagetables.

The GHCB pages (one per vCPU) will be used by the PEI and DXE #VC
exception handlers. The #VC exception handler will fill in the necessary
fields of the GHCB and exit to the hypervisor using the VMGEXIT
instruction. The hypervisor then accesses the GHCB associated with the
vCPU in order to perform the requested function.

Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
Regression-tested-by: Laszlo Ersek <lersek@redhat.com>
OvmfPkg/OvmfPkgIa32.dsc
OvmfPkg/OvmfPkgIa32X64.dsc
OvmfPkg/OvmfPkgX64.dsc
OvmfPkg/PlatformPei/AmdSev.c
OvmfPkg/PlatformPei/PlatformPei.inf

index f84f23f250ef0716a6486e2d7c9f4c7e7127beb7..133a9a93c071456af72d8ef605b3c2da45c636e5 100644 (file)
   gEfiMdeModulePkgTokenSpaceGuid.PcdPteMemoryEncryptionAddressOrMask|0x0\r
 \r
   # Set SEV-ES defaults\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdGhcbBase|0\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdGhcbSize|0\r
   gUefiCpuPkgTokenSpaceGuid.PcdSevEsIsEnabled|0\r
 \r
 !if $(SMM_REQUIRE) == TRUE\r
index a66abccf82660dc0db1fa9c26bc998a999316d77..338c38db29b51bef33a1e83043c1a0462c0f9dcc 100644 (file)
   gEfiMdeModulePkgTokenSpaceGuid.PcdPteMemoryEncryptionAddressOrMask|0x0\r
 \r
   # Set SEV-ES defaults\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdGhcbBase|0\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdGhcbSize|0\r
   gUefiCpuPkgTokenSpaceGuid.PcdSevEsIsEnabled|0\r
 \r
 !if $(SMM_REQUIRE) == TRUE\r
index 2a8975fd3d296f72a0e055a0571ea26af8e4a997..b80710fbdca49736788349998fa6f8327e1c77db 100644 (file)
   gEfiMdeModulePkgTokenSpaceGuid.PcdPteMemoryEncryptionAddressOrMask|0x0\r
 \r
   # Set SEV-ES defaults\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdGhcbBase|0\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdGhcbSize|0\r
   gUefiCpuPkgTokenSpaceGuid.PcdSevEsIsEnabled|0\r
 \r
 !if $(SMM_REQUIRE) == TRUE\r
index 4dc5340caa7a2814e8914ecfa7a3a6deb12acbd8..4fd4534cabeab8730434d8ee563f6bd7a26ec745 100644 (file)
 // The package level header files this module uses\r
 //\r
 #include <IndustryStandard/Q35MchIch9.h>\r
+#include <Library/BaseMemoryLib.h>\r
 #include <Library/DebugLib.h>\r
 #include <Library/HobLib.h>\r
 #include <Library/MemEncryptSevLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
 #include <Library/PcdLib.h>\r
 #include <PiPei.h>\r
 #include <Register/Amd/Cpuid.h>\r
+#include <Register/Amd/Msr.h>\r
 #include <Register/Cpuid.h>\r
 #include <Register/Intel/SmramSaveStateMap.h>\r
 \r
@@ -32,7 +35,10 @@ AmdSevEsInitialize (
   VOID\r
   )\r
 {\r
-  RETURN_STATUS     PcdStatus;\r
+  VOID              *GhcbBase;\r
+  PHYSICAL_ADDRESS  GhcbBasePa;\r
+  UINTN             GhcbPageCount, PageCount;\r
+  RETURN_STATUS     PcdStatus, DecryptStatus;\r
 \r
   if (!MemEncryptSevEsIsEnabled ()) {\r
     return;\r
@@ -40,6 +46,43 @@ AmdSevEsInitialize (
 \r
   PcdStatus = PcdSetBoolS (PcdSevEsIsEnabled, TRUE);\r
   ASSERT_RETURN_ERROR (PcdStatus);\r
+\r
+  //\r
+  // Allocate GHCB and per-CPU variable pages.\r
+  //\r
+  GhcbPageCount = mMaxCpuCount * 2;\r
+  GhcbBase = AllocatePages (GhcbPageCount);\r
+  ASSERT (GhcbBase != NULL);\r
+\r
+  GhcbBasePa = (PHYSICAL_ADDRESS)(UINTN) GhcbBase;\r
+\r
+  //\r
+  // Each vCPU gets two consecutive pages, the first is the GHCB and the\r
+  // second is the per-CPU variable page. Loop through the allocation and\r
+  // only clear the encryption mask for the GHCB pages.\r
+  //\r
+  for (PageCount = 0; PageCount < GhcbPageCount; PageCount += 2) {\r
+    DecryptStatus = MemEncryptSevClearPageEncMask (\r
+      0,\r
+      GhcbBasePa + EFI_PAGES_TO_SIZE (PageCount),\r
+      1,\r
+      TRUE\r
+      );\r
+    ASSERT_RETURN_ERROR (DecryptStatus);\r
+  }\r
+\r
+  ZeroMem (GhcbBase, EFI_PAGES_TO_SIZE (GhcbPageCount));\r
+\r
+  PcdStatus = PcdSet64S (PcdGhcbBase, GhcbBasePa);\r
+  ASSERT_RETURN_ERROR (PcdStatus);\r
+  PcdStatus = PcdSet64S (PcdGhcbSize, EFI_PAGES_TO_SIZE (GhcbPageCount));\r
+  ASSERT_RETURN_ERROR (PcdStatus);\r
+\r
+  DEBUG ((DEBUG_INFO,\r
+    "SEV-ES is enabled, %lu GHCB pages allocated starting at 0x%p\n",\r
+    (UINT64)GhcbPageCount, GhcbBase));\r
+\r
+  AsmWriteMsr64 (MSR_SEV_ES_GHCB, GhcbBasePa);\r
 }\r
 \r
 /**\r
index a54d10ba90d5321a82c6db505d5d3268c3333df4..4742e1bdf42b7076351c1320a8d8e63aacb134ae 100644 (file)
   gEfiMdeModulePkgTokenSpaceGuid.PcdSetNxForStack\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiS3Enable\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdPteMemoryEncryptionAddressOrMask\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdGhcbBase\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdGhcbSize\r
   gEfiSecurityPkgTokenSpaceGuid.PcdOptionRomImageVerificationPolicy\r
   gUefiCpuPkgTokenSpaceGuid.PcdCpuLocalApicBaseAddress\r
   gUefiCpuPkgTokenSpaceGuid.PcdCpuMaxLogicalProcessorNumber\r