]> git.proxmox.com Git - mirror_edk2.git/commitdiff
OvmfPkg/VmgExitLib: Support nested #VCs
authorTom Lendacky <thomas.lendacky@amd.com>
Thu, 7 Jan 2021 18:48:23 +0000 (12:48 -0600)
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Thu, 7 Jan 2021 19:34:39 +0000 (19:34 +0000)
BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3108

In order to be able to issue messages or make interface calls that cause
another #VC (e.g. GetLocalApicBaseAddress () issues RDMSR), add support
for nested #VCs.

In order to support nested #VCs, GHCB backup pages are required. If a #VC
is received while currently processing a #VC, a backup of the current GHCB
content is made. This allows the #VC handler to continue processing the
new #VC. Upon completion of the new #VC, the GHCB is restored from the
backup page. The #VC recursion level is tracked in the per-vCPU variable
area.

Support is added to handle up to one nested #VC (or two #VCs total). If
a second nested #VC is encountered, an ASSERT will be issued and the vCPU
will enter CpuDeadLoop ().

For SEC, the GHCB backup pages are reserved in the OvmfPkgX64.fdf memory
layout, with two new fixed PCDs to provide the address and size of the
backup area.

For PEI/DXE, the GHCB backup pages are allocated as boot services pages
using the memory allocation library.

Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>
Cc: Brijesh Singh <brijesh.singh@amd.com>
Acked-by: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
Message-Id: <ac2e8203fc41a351b43f60d68bdad6b57c4fb106.1610045305.git.thomas.lendacky@amd.com>

13 files changed:
OvmfPkg/AmdSev/AmdSevX64.dsc
OvmfPkg/AmdSev/AmdSevX64.fdf
OvmfPkg/Include/Library/MemEncryptSevLib.h
OvmfPkg/Library/VmgExitLib/PeiDxeVmgExitVcHandler.c [new file with mode: 0644]
OvmfPkg/Library/VmgExitLib/SecVmgExitLib.inf [new file with mode: 0644]
OvmfPkg/Library/VmgExitLib/SecVmgExitVcHandler.c [new file with mode: 0644]
OvmfPkg/Library/VmgExitLib/VmgExitLib.inf
OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c
OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.h [new file with mode: 0644]
OvmfPkg/OvmfPkg.dec
OvmfPkg/OvmfPkgX64.dsc
OvmfPkg/OvmfPkgX64.fdf
OvmfPkg/PlatformPei/AmdSev.c

index d39436e7afc92ab917d182284c43fa5f91c7cc64..c4d93f39b9f193359cb8c61eb27c2c13e18a9389 100644 (file)
 !else\r
   CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf\r
 !endif\r
+  VmgExitLib|OvmfPkg/Library/VmgExitLib/SecVmgExitLib.inf\r
 \r
 [LibraryClasses.common.PEI_CORE]\r
   HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf\r
index e8fd4b8c7b89e9e73f313e38acfb2123e2ddcea8..c0098502aa9085d27ec99b3218f148b088faf7b2 100644 (file)
@@ -62,6 +62,9 @@ gUefiCpuPkgTokenSpaceGuid.PcdSevEsWorkAreaBase|gUefiCpuPkgTokenSpaceGuid.PcdSevE
 0x00C000|0x001000\r
 gUefiOvmfPkgTokenSpaceGuid.PcdSevLaunchSecretBase|gUefiOvmfPkgTokenSpaceGuid.PcdSevLaunchSecretSize\r
 \r
+0x00D000|0x001000\r
+gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupSize\r
+\r
 0x010000|0x010000\r
 gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize\r
 \r
index ec470b8d036395b3e83ce33283228e62dde677f0..99f15a7d12719a35d0effaf6764e5e4a2f038f47 100644 (file)
 \r
 #include <Base.h>\r
 \r
+//\r
+// Define the maximum number of #VCs allowed (e.g. the level of nesting\r
+// that is allowed => 2 allows for 1 nested #VCs). I this value is changed,\r
+// be sure to increase the size of\r
+//   gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupSize\r
+// in any FDF file using this PCD.\r
+//\r
+#define VMGEXIT_MAXIMUM_VC_COUNT   2\r
+\r
+//\r
+// Per-CPU data mapping structure\r
+//   Use UINT32 for cached indicators and compare to a specific value\r
+//   so that the hypervisor can't indicate a value is cached by just\r
+//   writing random data to that area.\r
+//\r
+typedef struct {\r
+  UINT32  Dr7Cached;\r
+  UINT64  Dr7;\r
+\r
+  UINTN   VcCount;\r
+  VOID    *GhcbBackupPages;\r
+} SEV_ES_PER_CPU_DATA;\r
+\r
 //\r
 // Internal structure for holding SEV-ES information needed during SEC phase\r
 // and valid only during SEC phase and early PEI during platform\r
diff --git a/OvmfPkg/Library/VmgExitLib/PeiDxeVmgExitVcHandler.c b/OvmfPkg/Library/VmgExitLib/PeiDxeVmgExitVcHandler.c
new file mode 100644 (file)
index 0000000..fb4942d
--- /dev/null
@@ -0,0 +1,103 @@
+/** @file\r
+  X64 #VC Exception Handler functon.\r
+\r
+  Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved.<BR>\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#include <Base.h>\r
+#include <Uefi.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/MemEncryptSevLib.h>\r
+#include <Library/VmgExitLib.h>\r
+#include <Register/Amd/Msr.h>\r
+\r
+#include "VmgExitVcHandler.h"\r
+\r
+/**\r
+  Handle a #VC exception.\r
+\r
+  Performs the necessary processing to handle a #VC exception.\r
+\r
+  @param[in, out]  ExceptionType  Pointer to an EFI_EXCEPTION_TYPE to be set\r
+                                  as value to use on error.\r
+  @param[in, out]  SystemContext  Pointer to EFI_SYSTEM_CONTEXT\r
+\r
+  @retval  EFI_SUCCESS            Exception handled\r
+  @retval  EFI_UNSUPPORTED        #VC not supported, (new) exception value to\r
+                                  propagate provided\r
+  @retval  EFI_PROTOCOL_ERROR     #VC handling failed, (new) exception value to\r
+                                  propagate provided\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+VmgExitHandleVc (\r
+  IN OUT EFI_EXCEPTION_TYPE  *ExceptionType,\r
+  IN OUT EFI_SYSTEM_CONTEXT  SystemContext\r
+  )\r
+{\r
+  MSR_SEV_ES_GHCB_REGISTER  Msr;\r
+  GHCB                      *Ghcb;\r
+  GHCB                      *GhcbBackup;\r
+  EFI_STATUS                VcRet;\r
+  BOOLEAN                   InterruptState;\r
+  SEV_ES_PER_CPU_DATA       *SevEsData;\r
+\r
+  InterruptState = GetInterruptState ();\r
+  if (InterruptState) {\r
+    DisableInterrupts ();\r
+  }\r
+\r
+  Msr.GhcbPhysicalAddress = AsmReadMsr64 (MSR_SEV_ES_GHCB);\r
+  ASSERT (Msr.GhcbInfo.Function == 0);\r
+  ASSERT (Msr.Ghcb != 0);\r
+\r
+  Ghcb = Msr.Ghcb;\r
+  GhcbBackup = NULL;\r
+\r
+  SevEsData = (SEV_ES_PER_CPU_DATA *) (Ghcb + 1);\r
+  SevEsData->VcCount++;\r
+\r
+  //\r
+  // Check for maximum PEI/DXE #VC nesting.\r
+  //\r
+  if (SevEsData->VcCount > VMGEXIT_MAXIMUM_VC_COUNT) {\r
+    VmgExitIssueAssert (SevEsData);\r
+  } else if (SevEsData->VcCount > 1) {\r
+    //\r
+    // Nested #VC\r
+    //\r
+    if (SevEsData->GhcbBackupPages == NULL) {\r
+      VmgExitIssueAssert (SevEsData);\r
+    }\r
+\r
+    //\r
+    // Save the active GHCB to a backup page.\r
+    //   To access the correct backup page, increment the backup page pointer\r
+    //   based on the current VcCount.\r
+    //\r
+    GhcbBackup = (GHCB *) SevEsData->GhcbBackupPages;\r
+    GhcbBackup += (SevEsData->VcCount - 2);\r
+\r
+    CopyMem (GhcbBackup, Ghcb, sizeof (*Ghcb));\r
+  }\r
+\r
+  VcRet = InternalVmgExitHandleVc (Ghcb, ExceptionType, SystemContext);\r
+\r
+  if (GhcbBackup != NULL) {\r
+    //\r
+    // Restore the active GHCB from the backup page.\r
+    //\r
+    CopyMem (Ghcb, GhcbBackup, sizeof (*Ghcb));\r
+  }\r
+\r
+  SevEsData->VcCount--;\r
+\r
+  if (InterruptState) {\r
+    EnableInterrupts ();\r
+  }\r
+\r
+  return VcRet;\r
+}\r
diff --git a/OvmfPkg/Library/VmgExitLib/SecVmgExitLib.inf b/OvmfPkg/Library/VmgExitLib/SecVmgExitLib.inf
new file mode 100644 (file)
index 0000000..df14de3
--- /dev/null
@@ -0,0 +1,43 @@
+## @file\r
+#  VMGEXIT Support Library.\r
+#\r
+#  Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved.<BR>\r
+#  SPDX-License-Identifier: BSD-2-Clause-Patent\r
+#\r
+##\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = SecVmgExitLib\r
+  FILE_GUID                      = dafff819-f86c-4cff-a70e-83161e5bcf9a\r
+  MODULE_TYPE                    = BASE\r
+  VERSION_STRING                 = 1.0\r
+  LIBRARY_CLASS                  = VmgExitLib|SEC\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = X64\r
+#\r
+\r
+[Sources.common]\r
+  VmgExitLib.c\r
+  VmgExitVcHandler.c\r
+  VmgExitVcHandler.h\r
+  SecVmgExitVcHandler.c\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  OvmfPkg/OvmfPkg.dec\r
+  UefiCpuPkg/UefiCpuPkg.dec\r
+\r
+[LibraryClasses]\r
+  BaseLib\r
+  BaseMemoryLib\r
+  DebugLib\r
+  PcdLib\r
+\r
+[FixedPcd]\r
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupBase\r
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupSize\r
+\r
diff --git a/OvmfPkg/Library/VmgExitLib/SecVmgExitVcHandler.c b/OvmfPkg/Library/VmgExitLib/SecVmgExitVcHandler.c
new file mode 100644 (file)
index 0000000..85853d3
--- /dev/null
@@ -0,0 +1,109 @@
+/** @file\r
+  X64 #VC Exception Handler functon.\r
+\r
+  Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved.<BR>\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#include <Base.h>\r
+#include <Uefi.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/MemEncryptSevLib.h>\r
+#include <Library/VmgExitLib.h>\r
+#include <Register/Amd/Msr.h>\r
+\r
+#include "VmgExitVcHandler.h"\r
+\r
+/**\r
+  Handle a #VC exception.\r
+\r
+  Performs the necessary processing to handle a #VC exception.\r
+\r
+  @param[in, out]  ExceptionType  Pointer to an EFI_EXCEPTION_TYPE to be set\r
+                                  as value to use on error.\r
+  @param[in, out]  SystemContext  Pointer to EFI_SYSTEM_CONTEXT\r
+\r
+  @retval  EFI_SUCCESS            Exception handled\r
+  @retval  EFI_UNSUPPORTED        #VC not supported, (new) exception value to\r
+                                  propagate provided\r
+  @retval  EFI_PROTOCOL_ERROR     #VC handling failed, (new) exception value to\r
+                                  propagate provided\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+VmgExitHandleVc (\r
+  IN OUT EFI_EXCEPTION_TYPE  *ExceptionType,\r
+  IN OUT EFI_SYSTEM_CONTEXT  SystemContext\r
+  )\r
+{\r
+  MSR_SEV_ES_GHCB_REGISTER  Msr;\r
+  GHCB                      *Ghcb;\r
+  GHCB                      *GhcbBackup;\r
+  EFI_STATUS                VcRet;\r
+  BOOLEAN                   InterruptState;\r
+  SEV_ES_PER_CPU_DATA       *SevEsData;\r
+\r
+  InterruptState = GetInterruptState ();\r
+  if (InterruptState) {\r
+    DisableInterrupts ();\r
+  }\r
+\r
+  Msr.GhcbPhysicalAddress = AsmReadMsr64 (MSR_SEV_ES_GHCB);\r
+  ASSERT (Msr.GhcbInfo.Function == 0);\r
+  ASSERT (Msr.Ghcb != 0);\r
+\r
+  Ghcb = Msr.Ghcb;\r
+  GhcbBackup = NULL;\r
+\r
+  SevEsData = (SEV_ES_PER_CPU_DATA *) (Ghcb + 1);\r
+  SevEsData->VcCount++;\r
+\r
+  //\r
+  // Check for maximum SEC #VC nesting.\r
+  //\r
+  if (SevEsData->VcCount > VMGEXIT_MAXIMUM_VC_COUNT) {\r
+    VmgExitIssueAssert (SevEsData);\r
+  } else if (SevEsData->VcCount > 1) {\r
+    UINTN  GhcbBackupSize;\r
+\r
+    //\r
+    // Be sure that the proper amount of pages are allocated\r
+    //\r
+    GhcbBackupSize = (VMGEXIT_MAXIMUM_VC_COUNT - 1) * sizeof (*Ghcb);\r
+    if (GhcbBackupSize > FixedPcdGet32 (PcdOvmfSecGhcbBackupSize)) {\r
+      //\r
+      // Not enough SEC backup pages allocated.\r
+      //\r
+      VmgExitIssueAssert (SevEsData);\r
+    }\r
+\r
+    //\r
+    // Save the active GHCB to a backup page.\r
+    //   To access the correct backup page, increment the backup page pointer\r
+    //   based on the current VcCount.\r
+    //\r
+    GhcbBackup = (GHCB *) FixedPcdGet32 (PcdOvmfSecGhcbBackupBase);\r
+    GhcbBackup += (SevEsData->VcCount - 2);\r
+\r
+    CopyMem (GhcbBackup, Ghcb, sizeof (*Ghcb));\r
+  }\r
+\r
+  VcRet = InternalVmgExitHandleVc (Ghcb, ExceptionType, SystemContext);\r
+\r
+  if (GhcbBackup != NULL) {\r
+    //\r
+    // Restore the active GHCB from the backup page.\r
+    //\r
+    CopyMem (Ghcb, GhcbBackup, sizeof (*Ghcb));\r
+  }\r
+\r
+  SevEsData->VcCount--;\r
+\r
+  if (InterruptState) {\r
+    EnableInterrupts ();\r
+  }\r
+\r
+  return VcRet;\r
+}\r
index d003ac63173eb769d2b920f972fdec5f4e6faaea..b3c3e56ecff8a405043eb371fcde87eb92ea3571 100644 (file)
@@ -12,7 +12,7 @@
   FILE_GUID                      = 0e923c25-13cd-430b-8714-ffe85652a97b\r
   MODULE_TYPE                    = BASE\r
   VERSION_STRING                 = 1.0\r
-  LIBRARY_CLASS                  = VmgExitLib\r
+  LIBRARY_CLASS                  = VmgExitLib|PEIM DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER UEFI_DRIVER\r
 \r
 #\r
 # The following information is for reference only and not required by the build tools.\r
@@ -23,6 +23,8 @@
 [Sources.common]\r
   VmgExitLib.c\r
   VmgExitVcHandler.c\r
+  VmgExitVcHandler.h\r
+  PeiDxeVmgExitVcHandler.c\r
 \r
 [Packages]\r
   MdePkg/MdePkg.dec\r
index 5149ab2bc98927956ea36a3b4b337ceb9fddc55b..ce577e4677ebb93c9be62b58af7487d5626b757f 100644 (file)
@@ -9,11 +9,14 @@
 #include <Base.h>\r
 #include <Uefi.h>\r
 #include <Library/BaseMemoryLib.h>\r
+#include <Library/MemEncryptSevLib.h>\r
 #include <Library/VmgExitLib.h>\r
 #include <Register/Amd/Msr.h>\r
 #include <Register/Intel/Cpuid.h>\r
 #include <IndustryStandard/InstructionParsing.h>\r
 \r
+#include "VmgExitVcHandler.h"\r
+\r
 //\r
 // Instruction execution mode definition\r
 //\r
@@ -126,18 +129,6 @@ UINT64
   SEV_ES_INSTRUCTION_DATA  *InstructionData\r
   );\r
 \r
-//\r
-// Per-CPU data mapping structure\r
-//   Use UINT32 for cached indicators and compare to a specific value\r
-//   so that the hypervisor can't indicate a value is cached by just\r
-//   writing random data to that area.\r
-//\r
-typedef struct {\r
-  UINT32  Dr7Cached;\r
-  UINT64  Dr7;\r
-} SEV_ES_PER_CPU_DATA;\r
-\r
-\r
 /**\r
   Return a pointer to the contents of the specified register.\r
 \r
@@ -1546,6 +1537,7 @@ Dr7ReadExit (
 \r
   Performs the necessary processing to handle a #VC exception.\r
 \r
+  @param[in, out]  Ghcb           Pointer to the GHCB\r
   @param[in, out]  ExceptionType  Pointer to an EFI_EXCEPTION_TYPE to be set\r
                                   as value to use on error.\r
   @param[in, out]  SystemContext  Pointer to EFI_SYSTEM_CONTEXT\r
@@ -1559,14 +1551,13 @@ Dr7ReadExit (
 **/\r
 EFI_STATUS\r
 EFIAPI\r
-VmgExitHandleVc (\r
+InternalVmgExitHandleVc (\r
+  IN OUT GHCB                *Ghcb,\r
   IN OUT EFI_EXCEPTION_TYPE  *ExceptionType,\r
   IN OUT EFI_SYSTEM_CONTEXT  SystemContext\r
   )\r
 {\r
-  MSR_SEV_ES_GHCB_REGISTER  Msr;\r
   EFI_SYSTEM_CONTEXT_X64    *Regs;\r
-  GHCB                      *Ghcb;\r
   NAE_EXIT                  NaeExit;\r
   SEV_ES_INSTRUCTION_DATA   InstructionData;\r
   UINT64                    ExitCode, Status;\r
@@ -1575,12 +1566,7 @@ VmgExitHandleVc (
 \r
   VcRet = EFI_SUCCESS;\r
 \r
-  Msr.GhcbPhysicalAddress = AsmReadMsr64 (MSR_SEV_ES_GHCB);\r
-  ASSERT (Msr.GhcbInfo.Function == 0);\r
-  ASSERT (Msr.Ghcb != 0);\r
-\r
   Regs = SystemContext.SystemContextX64;\r
-  Ghcb = Msr.Ghcb;\r
 \r
   VmgInit (Ghcb, &InterruptState);\r
 \r
@@ -1670,3 +1656,25 @@ VmgExitHandleVc (
 \r
   return VcRet;\r
 }\r
+\r
+/**\r
+  Routine to allow ASSERT from within #VC.\r
+\r
+  @param[in, out]  SevEsData  Pointer to the per-CPU data\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+VmgExitIssueAssert (\r
+  IN OUT SEV_ES_PER_CPU_DATA  *SevEsData\r
+  )\r
+{\r
+  //\r
+  // Progress will be halted, so set VcCount to allow for ASSERT output\r
+  // to be seen.\r
+  //\r
+  SevEsData->VcCount = 0;\r
+\r
+  ASSERT (FALSE);\r
+  CpuDeadLoop ();\r
+}\r
diff --git a/OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.h b/OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.h
new file mode 100644 (file)
index 0000000..3a37cb0
--- /dev/null
@@ -0,0 +1,53 @@
+/** @file\r
+  X64 #VC Exception Handler functon header file.\r
+\r
+  Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved.<BR>\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#ifndef __VMG_EXIT_VC_HANDLER_H__\r
+#define __VMG_EXIT_VC_HANDLER_H__\r
+\r
+#include <Base.h>\r
+#include <Uefi.h>\r
+#include <Library/VmgExitLib.h>\r
+\r
+/**\r
+  Handle a #VC exception.\r
+\r
+  Performs the necessary processing to handle a #VC exception.\r
+\r
+  @param[in, out]  Ghcb           Pointer to the GHCB\r
+  @param[in, out]  ExceptionType  Pointer to an EFI_EXCEPTION_TYPE to be set\r
+                                  as value to use on error.\r
+  @param[in, out]  SystemContext  Pointer to EFI_SYSTEM_CONTEXT\r
+\r
+  @retval  EFI_SUCCESS            Exception handled\r
+  @retval  EFI_UNSUPPORTED        #VC not supported, (new) exception value to\r
+                                  propagate provided\r
+  @retval  EFI_PROTOCOL_ERROR     #VC handling failed, (new) exception value to\r
+                                  propagate provided\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+InternalVmgExitHandleVc (\r
+  IN OUT GHCB                *Ghcb,\r
+  IN OUT EFI_EXCEPTION_TYPE  *ExceptionType,\r
+  IN OUT EFI_SYSTEM_CONTEXT  SystemContext\r
+  );\r
+\r
+/**\r
+  Routine to allow ASSERT from within #VC.\r
+\r
+  @param[in, out]  SevEsData  Pointer to the per-CPU data\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+VmgExitIssueAssert (\r
+  IN OUT SEV_ES_PER_CPU_DATA  *SevEsData\r
+  );\r
+\r
+#endif\r
index 50d7b27d941c1662c5db2f9e285f249cd7ecb2b3..54804962ec02a04603423a5e4bd20ab957bfb2d6 100644 (file)
   ## The base address of the SEC GHCB page used by SEV-ES.\r
   gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBase|0|UINT32|0x40\r
   gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbSize|0|UINT32|0x41\r
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupBase|0|UINT32|0x44\r
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupSize|0|UINT32|0x45\r
 \r
   ## The base address and size of the SEV Launch Secret Area provisioned\r
   #  after remote attestation.  If this is set in the .fdf, the platform\r
index 799468e08e92b3a4e5cf8f2119114eeb64dc8814..bfa9dd7cac1fd38230bc20ef434adfdc1bb2162a 100644 (file)
 !else\r
   CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf\r
 !endif\r
+  VmgExitLib|OvmfPkg/Library/VmgExitLib/SecVmgExitLib.inf\r
 \r
 [LibraryClasses.common.PEI_CORE]\r
   HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf\r
index 1a2ef5bf2ae3d72549618823c9e9ba00e0435d1c..d519f85328227e67ceebf038f13687b378b44689 100644 (file)
@@ -85,6 +85,9 @@ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmf
 0x00B000|0x001000\r
 gUefiCpuPkgTokenSpaceGuid.PcdSevEsWorkAreaBase|gUefiCpuPkgTokenSpaceGuid.PcdSevEsWorkAreaSize\r
 \r
+0x00C000|0x001000\r
+gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupSize\r
+\r
 0x010000|0x010000\r
 gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize\r
 \r
index 954d53eba4e82eb63cda5537500743dacf16c49c..dddffdebda4b82b1aad79806bc3f0323449ed769 100644 (file)
@@ -33,12 +33,17 @@ AmdSevEsInitialize (
   VOID\r
   )\r
 {\r
-  VOID              *GhcbBase;\r
-  PHYSICAL_ADDRESS  GhcbBasePa;\r
-  UINTN             GhcbPageCount, PageCount;\r
-  RETURN_STATUS     PcdStatus, DecryptStatus;\r
-  IA32_DESCRIPTOR   Gdtr;\r
-  VOID              *Gdt;\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
@@ -84,6 +89,27 @@ AmdSevEsInitialize (
     "SEV-ES is enabled, %lu GHCB pages allocated starting at 0x%p\n",\r
     (UINT64)GhcbPageCount, GhcbBase));\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 ((DEBUG_INFO,\r
+    "SEV-ES is enabled, %lu GHCB backup pages allocated starting at 0x%p\n",\r
+    (UINT64)GhcbBackupPageCount, GhcbBackupBase));\r
+\r
   AsmWriteMsr64 (MSR_SEV_ES_GHCB, GhcbBasePa);\r
 \r
   //\r