]> git.proxmox.com Git - mirror_edk2.git/blobdiff - OvmfPkg/PlatformPei/AmdSev.c
OvmfPkg: Apply uncrustify changes
[mirror_edk2.git] / OvmfPkg / PlatformPei / AmdSev.c
index 4dc5340caa7a2814e8914ecfa7a3a6deb12acbd8..3991edfd1e82b1edfe4f6e1a59f6eeeaec778227 100644 (file)
@@ -1,7 +1,7 @@
 /**@file\r
   Initialize Secure Encrypted Virtualization (SEV) support\r
 \r
-  Copyright (c) 2017, Advanced Micro Devices. All rights reserved.<BR>\r
+  Copyright (c) 2017 - 2020, Advanced Micro Devices. All rights reserved.<BR>\r
 \r
   SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 // 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/Cpuid.h>\r
+#include <Register/Amd/Msr.h>\r
 #include <Register/Intel/SmramSaveStateMap.h>\r
 \r
 #include "Platform.h"\r
@@ -32,7 +33,17 @@ AmdSevEsInitialize (
   VOID\r
   )\r
 {\r
-  RETURN_STATUS     PcdStatus;\r
+  UINT8                *GhcbBase;\r
+  PHYSICAL_ADDRESS     GhcbBasePa;\r
+  UINTN                GhcbPageCount;\r
+  UINT8                *GhcbBackupBase;\r
+  UINT8                *GhcbBackupPages;\r
+  UINTN                GhcbBackupPageCount;\r
+  SEV_ES_PER_CPU_DATA  *SevEsData;\r
+  UINTN                PageCount;\r
+  RETURN_STATUS        PcdStatus, DecryptStatus;\r
+  IA32_DESCRIPTOR      Gdtr;\r
+  VOID                 *Gdt;\r
 \r
   if (!MemEncryptSevEsIsEnabled ()) {\r
     return;\r
@@ -40,6 +51,87 @@ AmdSevEsInitialize (
 \r
   PcdStatus = PcdSetBoolS (PcdSevEsIsEnabled, TRUE);\r
   ASSERT_RETURN_ERROR (PcdStatus);\r
+\r
+  //\r
+  // Allocate GHCB and per-CPU variable pages.\r
+  //   Since the pages must survive across the UEFI to OS transition\r
+  //   make them reserved.\r
+  //\r
+  GhcbPageCount = mMaxCpuCount * 2;\r
+  GhcbBase      = AllocateReservedPages (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
+                      );\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 ((\r
+    DEBUG_INFO,\r
+    "SEV-ES is enabled, %lu GHCB pages allocated starting at 0x%p\n",\r
+    (UINT64)GhcbPageCount,\r
+    GhcbBase\r
+    ));\r
+\r
+  //\r
+  // Allocate #VC recursion backup pages. The number of backup pages needed is\r
+  // one less than the maximum VC count.\r
+  //\r
+  GhcbBackupPageCount = mMaxCpuCount * (VMGEXIT_MAXIMUM_VC_COUNT - 1);\r
+  GhcbBackupBase      = AllocatePages (GhcbBackupPageCount);\r
+  ASSERT (GhcbBackupBase != NULL);\r
+\r
+  GhcbBackupPages = GhcbBackupBase;\r
+  for (PageCount = 1; PageCount < GhcbPageCount; PageCount += 2) {\r
+    SevEsData =\r
+      (SEV_ES_PER_CPU_DATA *)(GhcbBase + EFI_PAGES_TO_SIZE (PageCount));\r
+    SevEsData->GhcbBackupPages = GhcbBackupPages;\r
+\r
+    GhcbBackupPages += EFI_PAGE_SIZE * (VMGEXIT_MAXIMUM_VC_COUNT - 1);\r
+  }\r
+\r
+  DEBUG ((\r
+    DEBUG_INFO,\r
+    "SEV-ES is enabled, %lu GHCB backup pages allocated starting at 0x%p\n",\r
+    (UINT64)GhcbBackupPageCount,\r
+    GhcbBackupBase\r
+    ));\r
+\r
+  AsmWriteMsr64 (MSR_SEV_ES_GHCB, GhcbBasePa);\r
+\r
+  //\r
+  // The SEV support will clear the C-bit from non-RAM areas.  The early GDT\r
+  // lives in a non-RAM area, so when an exception occurs (like a #VC) the GDT\r
+  // will be read as un-encrypted even though it was created before the C-bit\r
+  // was cleared (encrypted). This will result in a failure to be able to\r
+  // handle the exception.\r
+  //\r
+  AsmReadGdtr (&Gdtr);\r
+\r
+  Gdt = AllocatePages (EFI_SIZE_TO_PAGES ((UINTN)Gdtr.Limit + 1));\r
+  ASSERT (Gdt != NULL);\r
+\r
+  CopyMem (Gdt, (VOID *)Gdtr.Base, Gdtr.Limit + 1);\r
+  Gdtr.Base = (UINTN)Gdt;\r
+  AsmWriteGdtr (&Gdtr);\r
 }\r
 \r
 /**\r
@@ -53,9 +145,8 @@ AmdSevInitialize (
   VOID\r
   )\r
 {\r
-  CPUID_MEMORY_ENCRYPTION_INFO_EBX  Ebx;\r
-  UINT64                            EncryptionMask;\r
-  RETURN_STATUS                     PcdStatus;\r
+  UINT64         EncryptionMask;\r
+  RETURN_STATUS  PcdStatus;\r
 \r
   //\r
   // Check if SEV is enabled\r
@@ -64,16 +155,11 @@ AmdSevInitialize (
     return;\r
   }\r
 \r
-  //\r
-  // CPUID Fn8000_001F[EBX] Bit 0:5 (memory encryption bit position)\r
-  //\r
-  AsmCpuid (CPUID_MEMORY_ENCRYPTION_INFO, NULL, &Ebx.Uint32, NULL, NULL);\r
-  EncryptionMask = LShiftU64 (1, Ebx.Bits.PtePosBits);\r
-\r
   //\r
   // Set Memory Encryption Mask PCD\r
   //\r
-  PcdStatus = PcdSet64S (PcdPteMemoryEncryptionAddressOrMask, EncryptionMask);\r
+  EncryptionMask = MemEncryptSevGetEncryptionMask ();\r
+  PcdStatus      = PcdSet64S (PcdPteMemoryEncryptionAddressOrMask, EncryptionMask);\r
   ASSERT_RETURN_ERROR (PcdStatus);\r
 \r
   DEBUG ((DEBUG_INFO, "SEV is enabled (mask 0x%lx)\n", EncryptionMask));\r
@@ -96,9 +182,9 @@ AmdSevInitialize (
   // hypervisor.\r
   //\r
   if (FeaturePcdGet (PcdSmmSmramRequire) && (mBootMode != BOOT_ON_S3_RESUME)) {\r
-    RETURN_STATUS LocateMapStatus;\r
-    UINTN         MapPagesBase;\r
-    UINTN         MapPagesCount;\r
+    RETURN_STATUS  LocateMapStatus;\r
+    UINTN          MapPagesBase;\r
+    UINTN          MapPagesCount;\r
 \r
     LocateMapStatus = MemEncryptSevLocateInitialSmramSaveStateMapPages (\r
                         &MapPagesBase,\r