]> git.proxmox.com Git - mirror_edk2.git/commitdiff
OvmfPkg/UefiCpuPkg/UefiPayloadPkg: Rename VmgExitLib to CcExitLib
authorMin M Xu <min.m.xu@intel.com>
Mon, 7 Nov 2022 06:30:26 +0000 (14:30 +0800)
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Mon, 14 Nov 2022 04:55:34 +0000 (04:55 +0000)
BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=4123

VmgExitLib once was designed to provide interfaces to support #VC handler
and issue VMGEXIT instruction. After TDVF (enable TDX feature in OVMF) is
introduced, this library is updated to support #VE as well. Now the name
of VmgExitLib cannot reflect what the lib does.

This patch renames VmgExitLib to CcExitLib (Cc means Confidential
Computing). This is a simple renaming and there is no logic changes.
After renaming all the VmgExitLib related codes are updated with
CcExitLib. These changes are in OvmfPkg/UefiCpuPkg/UefiPayloadPkg.

Cc: Guo Dong <guo.dong@intel.com>
Cc: Sean Rhodes <sean@starlabs.systems>
Cc: James Lu <james.lu@intel.com>
Cc: Gua Guo <gua.guo@intel.com>
Cc: Eric Dong <eric.dong@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Cc: Brijesh Singh <brijesh.singh@amd.com>
Cc: Erdem Aktas <erdemaktas@google.com>
Cc: Gerd Hoffmann <kraxel@redhat.com>
Cc: James Bottomley <jejb@linux.ibm.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Reviewed-by: James Lu <james.lu@intel.com>
Reviewed-by: Gua Guo <gua.guo@intel.com>
Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
Reviewed-by: Ray Ni <ray.ni@intel.com>
Signed-off-by: Min Xu <min.m.xu@intel.com>
62 files changed:
OvmfPkg/AmdSev/AmdSevX64.dsc
OvmfPkg/Bhyve/BhyveX64.dsc
OvmfPkg/CloudHv/CloudHvX64.dsc
OvmfPkg/IntelTdx/IntelTdxX64.dsc
OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf
OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLib.inf
OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLib.inf
OvmfPkg/Library/BaseMemEncryptSevLib/X64/SnpPageStateChangeInternal.c
OvmfPkg/Library/CcExitLib/CcExitLib.c [new file with mode: 0644]
OvmfPkg/Library/CcExitLib/CcExitLib.inf [new file with mode: 0644]
OvmfPkg/Library/CcExitLib/CcExitTd.h [new file with mode: 0644]
OvmfPkg/Library/CcExitLib/CcExitVcHandler.c [new file with mode: 0644]
OvmfPkg/Library/CcExitLib/CcExitVcHandler.h [new file with mode: 0644]
OvmfPkg/Library/CcExitLib/CcExitVeHandler.c [new file with mode: 0644]
OvmfPkg/Library/CcExitLib/PeiDxeCcExitVcHandler.c [new file with mode: 0644]
OvmfPkg/Library/CcExitLib/SecCcExitLib.inf [new file with mode: 0644]
OvmfPkg/Library/CcExitLib/SecCcExitVcHandler.c [new file with mode: 0644]
OvmfPkg/Library/CcExitLib/X64/TdVmcallCpuid.nasm [new file with mode: 0644]
OvmfPkg/Library/VmgExitLib/PeiDxeVmgExitVcHandler.c [deleted file]
OvmfPkg/Library/VmgExitLib/SecVmgExitLib.inf [deleted file]
OvmfPkg/Library/VmgExitLib/SecVmgExitVcHandler.c [deleted file]
OvmfPkg/Library/VmgExitLib/VmTdExitHandler.h [deleted file]
OvmfPkg/Library/VmgExitLib/VmTdExitVeHandler.c [deleted file]
OvmfPkg/Library/VmgExitLib/VmgExitLib.c [deleted file]
OvmfPkg/Library/VmgExitLib/VmgExitLib.inf [deleted file]
OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c [deleted file]
OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.h [deleted file]
OvmfPkg/Library/VmgExitLib/X64/TdVmcallCpuid.nasm [deleted file]
OvmfPkg/Microvm/MicrovmX64.dsc
OvmfPkg/OvmfPkgIa32.dsc
OvmfPkg/OvmfPkgIa32X64.dsc
OvmfPkg/OvmfPkgX64.dsc
OvmfPkg/OvmfXen.dsc
OvmfPkg/PlatformPei/AmdSev.c
OvmfPkg/PlatformPei/PlatformPei.inf
OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FvbServicesRuntimeDxe.inf
OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlashDxe.c
UefiCpuPkg/Include/Library/CcExitLib.h [new file with mode: 0644]
UefiCpuPkg/Include/Library/VmgExitLib.h [deleted file]
UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.c [new file with mode: 0644]
UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.inf [new file with mode: 0644]
UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.uni [new file with mode: 0644]
UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf
UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiCpuExceptionHandlerLib.inf
UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiDxeSmmCpuException.c
UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuException.c
UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf
UefiCpuPkg/Library/CpuExceptionHandlerLib/SmmCpuExceptionHandlerLib.inf
UefiCpuPkg/Library/CpuExceptionHandlerLib/Xcode5SecPeiCpuExceptionHandlerLib.inf
UefiCpuPkg/Library/MpInitLib/AmdSev.c
UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf
UefiCpuPkg/Library/MpInitLib/DxeMpLib.c
UefiCpuPkg/Library/MpInitLib/MpLib.c
UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf
UefiCpuPkg/Library/MpInitLib/X64/AmdSev.c
UefiCpuPkg/Library/VmgExitLibNull/VmTdExitNull.c [deleted file]
UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.c [deleted file]
UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.inf [deleted file]
UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.uni [deleted file]
UefiCpuPkg/UefiCpuPkg.dec
UefiCpuPkg/UefiCpuPkg.dsc
UefiPayloadPkg/UefiPayloadPkg.dsc

index 90e8a213ef771b5a1bc0a4b925d4cc257c308f5c..8f7cae787e9786a28516d96d2bd5bb3ae96d9105 100644 (file)
 \r
 [LibraryClasses.common]\r
   BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf\r
-  VmgExitLib|OvmfPkg/Library/VmgExitLib/VmgExitLib.inf\r
+  CcExitLib|OvmfPkg/Library/CcExitLib/CcExitLib.inf\r
   TdxLib|MdePkg/Library/TdxLib/TdxLib.inf\r
 \r
 [LibraryClasses.common.SEC]\r
 !else\r
   CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf\r
 !endif\r
-  VmgExitLib|OvmfPkg/Library/VmgExitLib/SecVmgExitLib.inf\r
+  CcExitLib|OvmfPkg/Library/CcExitLib/SecCcExitLib.inf\r
   MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLib.inf\r
 \r
 [LibraryClasses.common.PEI_CORE]\r
index 475b88b21a4c83c37e30336eb1b9c5f5d0982ea3..e3bb367b6bf6f5b3ef79c196eb7bf58103d9ca98 100644 (file)
 \r
 [LibraryClasses.common]\r
   BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf\r
-  VmgExitLib|UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.inf\r
+  CcExitLib|UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.inf\r
   TdxLib|MdePkg/Library/TdxLib/TdxLib.inf\r
 \r
 [LibraryClasses.common.SEC]\r
index 10b16104acd73deeacc8c3ecfbd2e0777903aa78..ce277cb2398b0c1f3e02a2abb66246977c471f64 100644 (file)
 \r
 [LibraryClasses.common]\r
   BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf\r
-  VmgExitLib|OvmfPkg/Library/VmgExitLib/VmgExitLib.inf\r
+  CcExitLib|OvmfPkg/Library/CcExitLib/CcExitLib.inf\r
   TdxLib|MdePkg/Library/TdxLib/TdxLib.inf\r
 \r
 [LibraryClasses.common.SEC]\r
 !else\r
   CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf\r
 !endif\r
-  VmgExitLib|OvmfPkg/Library/VmgExitLib/SecVmgExitLib.inf\r
+  CcExitLib|OvmfPkg/Library/CcExitLib/SecCcExitLib.inf\r
   MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLib.inf\r
 \r
 [LibraryClasses.common.PEI_CORE]\r
   #\r
   OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FvbServicesSmm.inf {\r
     <LibraryClasses>\r
-    VmgExitLib|UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.inf\r
+    CcExitLib|UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.inf\r
   }\r
   MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.inf\r
   MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf {\r
index c0c1a15b0926270b74fe3af79a038deef8c65949..3458926515206843722a55ef5b44bf87b0fa3143 100644 (file)
 \r
 [LibraryClasses.common]\r
   BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf\r
-  VmgExitLib|OvmfPkg/Library/VmgExitLib/VmgExitLib.inf\r
+  CcExitLib|OvmfPkg/Library/CcExitLib/CcExitLib.inf\r
   TdxLib|MdePkg/Library/TdxLib/TdxLib.inf\r
   TdxMailboxLib|OvmfPkg/Library/TdxMailboxLib/TdxMailboxLib.inf\r
   PlatformInitLib|OvmfPkg/Library/PlatformInitLib/PlatformInitLib.inf\r
 !else\r
   CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf\r
 !endif\r
-  VmgExitLib|OvmfPkg/Library/VmgExitLib/SecVmgExitLib.inf\r
+  CcExitLib|OvmfPkg/Library/CcExitLib/SecCcExitLib.inf\r
   MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLib.inf\r
   PrePiHobListPointerLib|OvmfPkg/IntelTdx/PrePiHobListPointerLibTdx/PrePiHobListPointerLibTdx.inf\r
   HobLib|EmbeddedPkg/Library/PrePiHobLib/PrePiHobLib.inf\r
index 35b7d519d9389243655d93343a8dc5a7462d5ff6..cc24961c9265e2939e3f64af8cdf418da701edd5 100644 (file)
@@ -51,7 +51,7 @@
   DebugLib\r
   MemoryAllocationLib\r
   PcdLib\r
-  VmgExitLib\r
+  CcExitLib\r
 \r
 [FeaturePcd]\r
   gUefiOvmfPkgTokenSpaceGuid.PcdSmmSmramRequire\r
index 714da33237655fee06816688625c4534b5d612bc..8f56783da55e8e9d3a866acbd6d1fd66dad14a0b 100644 (file)
@@ -51,7 +51,7 @@
   DebugLib\r
   MemoryAllocationLib\r
   PcdLib\r
-  VmgExitLib\r
+  CcExitLib\r
 \r
 [FeaturePcd]\r
   gUefiOvmfPkgTokenSpaceGuid.PcdSmmSmramRequire\r
index 284e5acc11779a1b85b88ac6c942e6f747484216..b6d76e7e630f4353d3e709cf04d7abe2d1bce28c 100644 (file)
@@ -48,7 +48,7 @@
   CpuLib\r
   DebugLib\r
   PcdLib\r
-  VmgExitLib\r
+  CcExitLib\r
 \r
 [FixedPcd]\r
   gUefiCpuPkgTokenSpaceGuid.PcdSevEsWorkAreaBase\r
index d11aafae84727ba8e1b0031e74b28db7dd7c14e2..73698a7b9d8c0228e8f35efb1adfa0274d10a39e 100644 (file)
@@ -13,7 +13,7 @@
 #include <Library/BaseMemoryLib.h>\r
 #include <Library/MemEncryptSevLib.h>\r
 #include <Library/DebugLib.h>\r
-#include <Library/VmgExitLib.h>\r
+#include <Library/CcExitLib.h>\r
 \r
 #include <Register/Amd/Ghcb.h>\r
 #include <Register/Amd/Msr.h>\r
diff --git a/OvmfPkg/Library/CcExitLib/CcExitLib.c b/OvmfPkg/Library/CcExitLib/CcExitLib.c
new file mode 100644 (file)
index 0000000..477064c
--- /dev/null
@@ -0,0 +1,239 @@
+/** @file\r
+  CcExitLib Support Library.\r
+\r
+  Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved.<BR>\r
+  Copyright (C) 2020 - 2022, Intel Corporation. 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/CcExitLib.h>\r
+#include <Register/Amd/Msr.h>\r
+\r
+/**\r
+  Check for VMGEXIT error\r
+\r
+  Check if the hypervisor has returned an error after completion of the VMGEXIT\r
+  by examining the SwExitInfo1 field of the GHCB.\r
+\r
+  @param[in]  Ghcb       A pointer to the GHCB\r
+\r
+  @retval  0             VMGEXIT succeeded.\r
+  @return                Exception number to be propagated, VMGEXIT processing\r
+                         did not succeed.\r
+\r
+**/\r
+STATIC\r
+UINT64\r
+VmgExitErrorCheck (\r
+  IN GHCB  *Ghcb\r
+  )\r
+{\r
+  GHCB_EVENT_INJECTION  Event;\r
+  GHCB_EXIT_INFO        ExitInfo;\r
+  UINT64                Status;\r
+\r
+  ExitInfo.Uint64 = Ghcb->SaveArea.SwExitInfo1;\r
+  ASSERT (\r
+    (ExitInfo.Elements.Lower32Bits == 0) ||\r
+    (ExitInfo.Elements.Lower32Bits == 1)\r
+    );\r
+\r
+  Status = 0;\r
+  if (ExitInfo.Elements.Lower32Bits == 0) {\r
+    return Status;\r
+  }\r
+\r
+  if (ExitInfo.Elements.Lower32Bits == 1) {\r
+    ASSERT (Ghcb->SaveArea.SwExitInfo2 != 0);\r
+\r
+    //\r
+    // Check that the return event is valid\r
+    //\r
+    Event.Uint64 = Ghcb->SaveArea.SwExitInfo2;\r
+    if (Event.Elements.Valid &&\r
+        (Event.Elements.Type == GHCB_EVENT_INJECTION_TYPE_EXCEPTION))\r
+    {\r
+      switch (Event.Elements.Vector) {\r
+        case GP_EXCEPTION:\r
+        case UD_EXCEPTION:\r
+          //\r
+          // Use returned event as return code\r
+          //\r
+          Status = Event.Uint64;\r
+      }\r
+    }\r
+  }\r
+\r
+  if (Status == 0) {\r
+    GHCB_EVENT_INJECTION  GpEvent;\r
+\r
+    GpEvent.Uint64          = 0;\r
+    GpEvent.Elements.Vector = GP_EXCEPTION;\r
+    GpEvent.Elements.Type   = GHCB_EVENT_INJECTION_TYPE_EXCEPTION;\r
+    GpEvent.Elements.Valid  = 1;\r
+\r
+    Status = GpEvent.Uint64;\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Perform VMGEXIT.\r
+\r
+  Sets the necessary fields of the GHCB, invokes the VMGEXIT instruction and\r
+  then handles the return actions.\r
+\r
+  @param[in, out]  Ghcb       A pointer to the GHCB\r
+  @param[in]       ExitCode   VMGEXIT code to be assigned to the SwExitCode\r
+                              field of the GHCB.\r
+  @param[in]       ExitInfo1  VMGEXIT information to be assigned to the\r
+                              SwExitInfo1 field of the GHCB.\r
+  @param[in]       ExitInfo2  VMGEXIT information to be assigned to the\r
+                              SwExitInfo2 field of the GHCB.\r
+\r
+  @retval  0                  VMGEXIT succeeded.\r
+  @return                     Exception number to be propagated, VMGEXIT\r
+                              processing did not succeed.\r
+\r
+**/\r
+UINT64\r
+EFIAPI\r
+VmgExit (\r
+  IN OUT GHCB    *Ghcb,\r
+  IN     UINT64  ExitCode,\r
+  IN     UINT64  ExitInfo1,\r
+  IN     UINT64  ExitInfo2\r
+  )\r
+{\r
+  Ghcb->SaveArea.SwExitCode  = ExitCode;\r
+  Ghcb->SaveArea.SwExitInfo1 = ExitInfo1;\r
+  Ghcb->SaveArea.SwExitInfo2 = ExitInfo2;\r
+\r
+  VmgSetOffsetValid (Ghcb, GhcbSwExitCode);\r
+  VmgSetOffsetValid (Ghcb, GhcbSwExitInfo1);\r
+  VmgSetOffsetValid (Ghcb, GhcbSwExitInfo2);\r
+\r
+  //\r
+  // Guest memory is used for the guest-hypervisor communication, so fence\r
+  // the invocation of the VMGEXIT instruction to ensure GHCB accesses are\r
+  // synchronized properly.\r
+  //\r
+  MemoryFence ();\r
+  AsmVmgExit ();\r
+  MemoryFence ();\r
+\r
+  return VmgExitErrorCheck (Ghcb);\r
+}\r
+\r
+/**\r
+  Perform pre-VMGEXIT initialization/preparation.\r
+\r
+  Performs the necessary steps in preparation for invoking VMGEXIT. Must be\r
+  called before setting any fields within the GHCB.\r
+\r
+  @param[in, out]  Ghcb            A pointer to the GHCB\r
+  @param[in, out]  InterruptState  A pointer to hold the current interrupt\r
+                                   state, used for restoring in VmgDone ()\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+VmgInit (\r
+  IN OUT GHCB     *Ghcb,\r
+  IN OUT BOOLEAN  *InterruptState\r
+  )\r
+{\r
+  //\r
+  // Be sure that an interrupt can't cause a #VC while the GHCB is\r
+  // being used.\r
+  //\r
+  *InterruptState = GetInterruptState ();\r
+  if (*InterruptState) {\r
+    DisableInterrupts ();\r
+  }\r
+\r
+  SetMem (&Ghcb->SaveArea, sizeof (Ghcb->SaveArea), 0);\r
+}\r
+\r
+/**\r
+  Perform post-VMGEXIT cleanup.\r
+\r
+  Performs the necessary steps to cleanup after invoking VMGEXIT. Must be\r
+  called after obtaining needed fields within the GHCB.\r
+\r
+  @param[in, out]  Ghcb            A pointer to the GHCB\r
+  @param[in]       InterruptState  An indicator to conditionally (re)enable\r
+                                   interrupts\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+VmgDone (\r
+  IN OUT GHCB     *Ghcb,\r
+  IN     BOOLEAN  InterruptState\r
+  )\r
+{\r
+  if (InterruptState) {\r
+    EnableInterrupts ();\r
+  }\r
+}\r
+\r
+/**\r
+  Marks a field at the specified offset as valid in the GHCB.\r
+\r
+  The ValidBitmap area represents the areas of the GHCB that have been marked\r
+  valid. Set the bit in ValidBitmap for the input offset.\r
+\r
+  @param[in, out] Ghcb    Pointer to the Guest-Hypervisor Communication Block\r
+  @param[in]      Offset  Qword offset in the GHCB to mark valid\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+VmgSetOffsetValid (\r
+  IN OUT GHCB           *Ghcb,\r
+  IN     GHCB_REGISTER  Offset\r
+  )\r
+{\r
+  UINT32  OffsetIndex;\r
+  UINT32  OffsetBit;\r
+\r
+  OffsetIndex = Offset / 8;\r
+  OffsetBit   = Offset % 8;\r
+\r
+  Ghcb->SaveArea.ValidBitmap[OffsetIndex] |= (1 << OffsetBit);\r
+}\r
+\r
+/**\r
+  Checks if a specified offset is valid in the GHCB.\r
+\r
+  The ValidBitmap area represents the areas of the GHCB that have been marked\r
+  valid. Return whether the bit in the ValidBitmap is set for the input offset.\r
+\r
+  @param[in]  Ghcb            A pointer to the GHCB\r
+  @param[in]  Offset          Qword offset in the GHCB to mark valid\r
+\r
+  @retval TRUE                Offset is marked valid in the GHCB\r
+  @retval FALSE               Offset is not marked valid in the GHCB\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+VmgIsOffsetValid (\r
+  IN GHCB           *Ghcb,\r
+  IN GHCB_REGISTER  Offset\r
+  )\r
+{\r
+  UINT32  OffsetIndex;\r
+  UINT32  OffsetBit;\r
+\r
+  OffsetIndex = Offset / 8;\r
+  OffsetBit   = Offset % 8;\r
+\r
+  return ((Ghcb->SaveArea.ValidBitmap[OffsetIndex] & (1 << OffsetBit)) != 0);\r
+}\r
diff --git a/OvmfPkg/Library/CcExitLib/CcExitLib.inf b/OvmfPkg/Library/CcExitLib/CcExitLib.inf
new file mode 100644 (file)
index 0000000..131fa62
--- /dev/null
@@ -0,0 +1,46 @@
+## @file\r
+#  CcExitLib Library.\r
+#\r
+#  Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved.<BR>\r
+#  Copyright (C) 2020 - 2022, Intel Corporation. All rights reserved.<BR>\r
+#  SPDX-License-Identifier: BSD-2-Clause-Patent\r
+#\r
+##\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = CcExitLib\r
+  FILE_GUID                      = 0e923c25-13cd-430b-8714-ffe85652a97b\r
+  MODULE_TYPE                    = BASE\r
+  VERSION_STRING                 = 1.0\r
+  LIBRARY_CLASS                  = CcExitLib|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
+#\r
+#  VALID_ARCHITECTURES           = X64\r
+#\r
+\r
+[Sources.common]\r
+  CcExitLib.c\r
+  CcExitVcHandler.c\r
+  CcExitVcHandler.h\r
+  PeiDxeCcExitVcHandler.c\r
+  CcExitVeHandler.c\r
+  X64/TdVmcallCpuid.nasm\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
+  LocalApicLib\r
+  MemEncryptSevLib\r
+\r
+[Pcd]\r
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCpuidBase\r
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCpuidSize\r
diff --git a/OvmfPkg/Library/CcExitLib/CcExitTd.h b/OvmfPkg/Library/CcExitLib/CcExitTd.h
new file mode 100644 (file)
index 0000000..013a55e
--- /dev/null
@@ -0,0 +1,32 @@
+/** @file\r
+\r
+  Copyright (c) 2020 - 2021, Intel Corporation. All rights reserved.<BR>\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#ifndef CC_EXIT_TD_H_\r
+#define CC_EXIT_TD_H_\r
+\r
+#include <Base.h>\r
+#include <Uefi.h>\r
+\r
+/**\r
+  This function enable the TD guest to request the VMM to emulate CPUID\r
+  operation, especially for non-architectural, CPUID leaves.\r
+\r
+  @param[in]  Eax        Main leaf of the CPUID\r
+  @param[in]  Ecx        Sub-leaf of the CPUID\r
+  @param[out] Results    Returned result of CPUID operation\r
+\r
+  @return EFI_SUCCESS\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+TdVmCallCpuid (\r
+  IN UINT64  Eax,\r
+  IN UINT64  Ecx,\r
+  OUT VOID   *Results\r
+  );\r
+\r
+#endif\r
diff --git a/OvmfPkg/Library/CcExitLib/CcExitVcHandler.c b/OvmfPkg/Library/CcExitLib/CcExitVcHandler.c
new file mode 100644 (file)
index 0000000..ad2a922
--- /dev/null
@@ -0,0 +1,2355 @@
+/** @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/LocalApicLib.h>\r
+#include <Library/MemEncryptSevLib.h>\r
+#include <Library/CcExitLib.h>\r
+#include <Register/Amd/Msr.h>\r
+#include <Register/Intel/Cpuid.h>\r
+#include <IndustryStandard/InstructionParsing.h>\r
+\r
+#include "CcExitVcHandler.h"\r
+\r
+//\r
+// Instruction execution mode definition\r
+//\r
+typedef enum {\r
+  LongMode64Bit = 0,\r
+  LongModeCompat32Bit,\r
+  LongModeCompat16Bit,\r
+} SEV_ES_INSTRUCTION_MODE;\r
+\r
+//\r
+// Instruction size definition (for operand and address)\r
+//\r
+typedef enum {\r
+  Size8Bits = 0,\r
+  Size16Bits,\r
+  Size32Bits,\r
+  Size64Bits,\r
+} SEV_ES_INSTRUCTION_SIZE;\r
+\r
+//\r
+// Intruction segment definition\r
+//\r
+typedef enum {\r
+  SegmentEs = 0,\r
+  SegmentCs,\r
+  SegmentSs,\r
+  SegmentDs,\r
+  SegmentFs,\r
+  SegmentGs,\r
+} SEV_ES_INSTRUCTION_SEGMENT;\r
+\r
+//\r
+// Instruction rep function definition\r
+//\r
+typedef enum {\r
+  RepNone = 0,\r
+  RepZ,\r
+  RepNZ,\r
+} SEV_ES_INSTRUCTION_REP;\r
+\r
+typedef struct {\r
+  UINT8    Rm;\r
+  UINT8    Reg;\r
+  UINT8    Mod;\r
+} SEV_ES_INSTRUCTION_MODRM_EXT;\r
+\r
+typedef struct {\r
+  UINT8    Base;\r
+  UINT8    Index;\r
+  UINT8    Scale;\r
+} SEV_ES_INSTRUCTION_SIB_EXT;\r
+\r
+//\r
+// Instruction opcode definition\r
+//\r
+typedef struct {\r
+  SEV_ES_INSTRUCTION_MODRM_EXT    ModRm;\r
+\r
+  SEV_ES_INSTRUCTION_SIB_EXT      Sib;\r
+\r
+  UINTN                           RegData;\r
+  UINTN                           RmData;\r
+} SEV_ES_INSTRUCTION_OPCODE_EXT;\r
+\r
+//\r
+// Instruction parsing context definition\r
+//\r
+typedef struct {\r
+  GHCB                             *Ghcb;\r
+\r
+  SEV_ES_INSTRUCTION_MODE          Mode;\r
+  SEV_ES_INSTRUCTION_SIZE          DataSize;\r
+  SEV_ES_INSTRUCTION_SIZE          AddrSize;\r
+  BOOLEAN                          SegmentSpecified;\r
+  SEV_ES_INSTRUCTION_SEGMENT       Segment;\r
+  SEV_ES_INSTRUCTION_REP           RepMode;\r
+\r
+  UINT8                            *Begin;\r
+  UINT8                            *End;\r
+\r
+  UINT8                            *Prefixes;\r
+  UINT8                            *OpCodes;\r
+  UINT8                            *Displacement;\r
+  UINT8                            *Immediate;\r
+\r
+  INSTRUCTION_REX_PREFIX           RexPrefix;\r
+\r
+  BOOLEAN                          ModRmPresent;\r
+  INSTRUCTION_MODRM                ModRm;\r
+\r
+  BOOLEAN                          SibPresent;\r
+  INSTRUCTION_SIB                  Sib;\r
+\r
+  UINTN                            PrefixSize;\r
+  UINTN                            OpCodeSize;\r
+  UINTN                            DisplacementSize;\r
+  UINTN                            ImmediateSize;\r
+\r
+  SEV_ES_INSTRUCTION_OPCODE_EXT    Ext;\r
+} SEV_ES_INSTRUCTION_DATA;\r
+\r
+//\r
+// Non-automatic Exit function prototype\r
+//\r
+typedef\r
+UINT64\r
+(*NAE_EXIT) (\r
+  GHCB                     *Ghcb,\r
+  EFI_SYSTEM_CONTEXT_X64   *Regs,\r
+  SEV_ES_INSTRUCTION_DATA  *InstructionData\r
+  );\r
+\r
+//\r
+// SEV-SNP Cpuid table entry/function\r
+//\r
+typedef PACKED struct {\r
+  UINT32    EaxIn;\r
+  UINT32    EcxIn;\r
+  UINT64    Unused;\r
+  UINT64    Unused2;\r
+  UINT32    Eax;\r
+  UINT32    Ebx;\r
+  UINT32    Ecx;\r
+  UINT32    Edx;\r
+  UINT64    Reserved;\r
+} SEV_SNP_CPUID_FUNCTION;\r
+\r
+//\r
+// SEV-SNP Cpuid page format\r
+//\r
+typedef PACKED struct {\r
+  UINT32                    Count;\r
+  UINT32                    Reserved1;\r
+  UINT64                    Reserved2;\r
+  SEV_SNP_CPUID_FUNCTION    function[0];\r
+} SEV_SNP_CPUID_INFO;\r
+\r
+/**\r
+  Return a pointer to the contents of the specified register.\r
+\r
+  Based upon the input register, return a pointer to the registers contents\r
+  in the x86 processor context.\r
+\r
+  @param[in] Regs      x64 processor context\r
+  @param[in] Register  Register to obtain pointer for\r
+\r
+  @return              Pointer to the contents of the requested register\r
+\r
+**/\r
+STATIC\r
+UINT64 *\r
+GetRegisterPointer (\r
+  IN EFI_SYSTEM_CONTEXT_X64  *Regs,\r
+  IN UINT8                   Register\r
+  )\r
+{\r
+  UINT64  *Reg;\r
+\r
+  switch (Register) {\r
+    case 0:\r
+      Reg = &Regs->Rax;\r
+      break;\r
+    case 1:\r
+      Reg = &Regs->Rcx;\r
+      break;\r
+    case 2:\r
+      Reg = &Regs->Rdx;\r
+      break;\r
+    case 3:\r
+      Reg = &Regs->Rbx;\r
+      break;\r
+    case 4:\r
+      Reg = &Regs->Rsp;\r
+      break;\r
+    case 5:\r
+      Reg = &Regs->Rbp;\r
+      break;\r
+    case 6:\r
+      Reg = &Regs->Rsi;\r
+      break;\r
+    case 7:\r
+      Reg = &Regs->Rdi;\r
+      break;\r
+    case 8:\r
+      Reg = &Regs->R8;\r
+      break;\r
+    case 9:\r
+      Reg = &Regs->R9;\r
+      break;\r
+    case 10:\r
+      Reg = &Regs->R10;\r
+      break;\r
+    case 11:\r
+      Reg = &Regs->R11;\r
+      break;\r
+    case 12:\r
+      Reg = &Regs->R12;\r
+      break;\r
+    case 13:\r
+      Reg = &Regs->R13;\r
+      break;\r
+    case 14:\r
+      Reg = &Regs->R14;\r
+      break;\r
+    case 15:\r
+      Reg = &Regs->R15;\r
+      break;\r
+    default:\r
+      Reg = NULL;\r
+  }\r
+\r
+  ASSERT (Reg != NULL);\r
+\r
+  return Reg;\r
+}\r
+\r
+/**\r
+  Update the instruction parsing context for displacement bytes.\r
+\r
+  @param[in, out] InstructionData  Instruction parsing context\r
+  @param[in]      Size             The instruction displacement size\r
+\r
+**/\r
+STATIC\r
+VOID\r
+UpdateForDisplacement (\r
+  IN OUT SEV_ES_INSTRUCTION_DATA  *InstructionData,\r
+  IN     UINTN                    Size\r
+  )\r
+{\r
+  InstructionData->DisplacementSize = Size;\r
+  InstructionData->Immediate       += Size;\r
+  InstructionData->End             += Size;\r
+}\r
+\r
+/**\r
+  Determine if an instruction address if RIP relative.\r
+\r
+  Examine the instruction parsing context to determine if the address offset\r
+  is relative to the instruction pointer.\r
+\r
+  @param[in] InstructionData  Instruction parsing context\r
+\r
+  @retval TRUE                Instruction addressing is RIP relative\r
+  @retval FALSE               Instruction addressing is not RIP relative\r
+\r
+**/\r
+STATIC\r
+BOOLEAN\r
+IsRipRelative (\r
+  IN SEV_ES_INSTRUCTION_DATA  *InstructionData\r
+  )\r
+{\r
+  SEV_ES_INSTRUCTION_OPCODE_EXT  *Ext;\r
+\r
+  Ext = &InstructionData->Ext;\r
+\r
+  return ((InstructionData->Mode == LongMode64Bit) &&\r
+          (Ext->ModRm.Mod == 0) &&\r
+          (Ext->ModRm.Rm == 5)  &&\r
+          (InstructionData->SibPresent == FALSE));\r
+}\r
+\r
+/**\r
+  Return the effective address of a memory operand.\r
+\r
+  Examine the instruction parsing context to obtain the effective memory\r
+  address of a memory operand.\r
+\r
+  @param[in] Regs             x64 processor context\r
+  @param[in] InstructionData  Instruction parsing context\r
+\r
+  @return                     The memory operand effective address\r
+\r
+**/\r
+STATIC\r
+UINT64\r
+GetEffectiveMemoryAddress (\r
+  IN EFI_SYSTEM_CONTEXT_X64   *Regs,\r
+  IN SEV_ES_INSTRUCTION_DATA  *InstructionData\r
+  )\r
+{\r
+  SEV_ES_INSTRUCTION_OPCODE_EXT  *Ext;\r
+  UINT64                         EffectiveAddress;\r
+\r
+  Ext              = &InstructionData->Ext;\r
+  EffectiveAddress = 0;\r
+\r
+  if (IsRipRelative (InstructionData)) {\r
+    //\r
+    // RIP-relative displacement is a 32-bit signed value\r
+    //\r
+    INT32  RipRelative;\r
+\r
+    RipRelative = *(INT32 *)InstructionData->Displacement;\r
+\r
+    UpdateForDisplacement (InstructionData, 4);\r
+\r
+    //\r
+    // Negative displacement is handled by standard UINT64 wrap-around.\r
+    //\r
+    return Regs->Rip + (UINT64)RipRelative;\r
+  }\r
+\r
+  switch (Ext->ModRm.Mod) {\r
+    case 1:\r
+      UpdateForDisplacement (InstructionData, 1);\r
+      EffectiveAddress += (UINT64)(*(INT8 *)(InstructionData->Displacement));\r
+      break;\r
+    case 2:\r
+      switch (InstructionData->AddrSize) {\r
+        case Size16Bits:\r
+          UpdateForDisplacement (InstructionData, 2);\r
+          EffectiveAddress += (UINT64)(*(INT16 *)(InstructionData->Displacement));\r
+          break;\r
+        default:\r
+          UpdateForDisplacement (InstructionData, 4);\r
+          EffectiveAddress += (UINT64)(*(INT32 *)(InstructionData->Displacement));\r
+          break;\r
+      }\r
+\r
+      break;\r
+  }\r
+\r
+  if (InstructionData->SibPresent) {\r
+    INT64  Displacement;\r
+\r
+    if (Ext->Sib.Index != 4) {\r
+      CopyMem (\r
+        &Displacement,\r
+        GetRegisterPointer (Regs, Ext->Sib.Index),\r
+        sizeof (Displacement)\r
+        );\r
+      Displacement *= (INT64)(1 << Ext->Sib.Scale);\r
+\r
+      //\r
+      // Negative displacement is handled by standard UINT64 wrap-around.\r
+      //\r
+      EffectiveAddress += (UINT64)Displacement;\r
+    }\r
+\r
+    if ((Ext->Sib.Base != 5) || Ext->ModRm.Mod) {\r
+      EffectiveAddress += *GetRegisterPointer (Regs, Ext->Sib.Base);\r
+    } else {\r
+      UpdateForDisplacement (InstructionData, 4);\r
+      EffectiveAddress += (UINT64)(*(INT32 *)(InstructionData->Displacement));\r
+    }\r
+  } else {\r
+    EffectiveAddress += *GetRegisterPointer (Regs, Ext->ModRm.Rm);\r
+  }\r
+\r
+  return EffectiveAddress;\r
+}\r
+\r
+/**\r
+  Decode a ModRM byte.\r
+\r
+  Examine the instruction parsing context to decode a ModRM byte and the SIB\r
+  byte, if present.\r
+\r
+  @param[in]      Regs             x64 processor context\r
+  @param[in, out] InstructionData  Instruction parsing context\r
+\r
+**/\r
+STATIC\r
+VOID\r
+DecodeModRm (\r
+  IN     EFI_SYSTEM_CONTEXT_X64   *Regs,\r
+  IN OUT SEV_ES_INSTRUCTION_DATA  *InstructionData\r
+  )\r
+{\r
+  SEV_ES_INSTRUCTION_OPCODE_EXT  *Ext;\r
+  INSTRUCTION_REX_PREFIX         *RexPrefix;\r
+  INSTRUCTION_MODRM              *ModRm;\r
+  INSTRUCTION_SIB                *Sib;\r
+\r
+  RexPrefix = &InstructionData->RexPrefix;\r
+  Ext       = &InstructionData->Ext;\r
+  ModRm     = &InstructionData->ModRm;\r
+  Sib       = &InstructionData->Sib;\r
+\r
+  InstructionData->ModRmPresent = TRUE;\r
+  ModRm->Uint8                  = *(InstructionData->End);\r
+\r
+  InstructionData->Displacement++;\r
+  InstructionData->Immediate++;\r
+  InstructionData->End++;\r
+\r
+  Ext->ModRm.Mod = ModRm->Bits.Mod;\r
+  Ext->ModRm.Reg = (RexPrefix->Bits.BitR << 3) | ModRm->Bits.Reg;\r
+  Ext->ModRm.Rm  = (RexPrefix->Bits.BitB << 3) | ModRm->Bits.Rm;\r
+\r
+  Ext->RegData = *GetRegisterPointer (Regs, Ext->ModRm.Reg);\r
+\r
+  if (Ext->ModRm.Mod == 3) {\r
+    Ext->RmData = *GetRegisterPointer (Regs, Ext->ModRm.Rm);\r
+  } else {\r
+    if (ModRm->Bits.Rm == 4) {\r
+      InstructionData->SibPresent = TRUE;\r
+      Sib->Uint8                  = *(InstructionData->End);\r
+\r
+      InstructionData->Displacement++;\r
+      InstructionData->Immediate++;\r
+      InstructionData->End++;\r
+\r
+      Ext->Sib.Scale = Sib->Bits.Scale;\r
+      Ext->Sib.Index = (RexPrefix->Bits.BitX << 3) | Sib->Bits.Index;\r
+      Ext->Sib.Base  = (RexPrefix->Bits.BitB << 3) | Sib->Bits.Base;\r
+    }\r
+\r
+    Ext->RmData = GetEffectiveMemoryAddress (Regs, InstructionData);\r
+  }\r
+}\r
+\r
+/**\r
+  Decode instruction prefixes.\r
+\r
+  Parse the instruction data to track the instruction prefixes that have\r
+  been used.\r
+\r
+  @param[in]      Regs             x64 processor context\r
+  @param[in, out] InstructionData  Instruction parsing context\r
+\r
+**/\r
+STATIC\r
+VOID\r
+DecodePrefixes (\r
+  IN     EFI_SYSTEM_CONTEXT_X64   *Regs,\r
+  IN OUT SEV_ES_INSTRUCTION_DATA  *InstructionData\r
+  )\r
+{\r
+  SEV_ES_INSTRUCTION_MODE  Mode;\r
+  SEV_ES_INSTRUCTION_SIZE  ModeDataSize;\r
+  SEV_ES_INSTRUCTION_SIZE  ModeAddrSize;\r
+  UINT8                    *Byte;\r
+\r
+  //\r
+  // Always in 64-bit mode\r
+  //\r
+  Mode         = LongMode64Bit;\r
+  ModeDataSize = Size32Bits;\r
+  ModeAddrSize = Size64Bits;\r
+\r
+  InstructionData->Mode     = Mode;\r
+  InstructionData->DataSize = ModeDataSize;\r
+  InstructionData->AddrSize = ModeAddrSize;\r
+\r
+  InstructionData->Prefixes = InstructionData->Begin;\r
+\r
+  Byte = InstructionData->Prefixes;\r
+  for ( ; ; Byte++, InstructionData->PrefixSize++) {\r
+    //\r
+    // Check the 0x40 to 0x4F range using an if statement here since some\r
+    // compilers don't like the "case 0x40 ... 0x4F:" syntax. This avoids\r
+    // 16 case statements below.\r
+    //\r
+    if ((*Byte >= REX_PREFIX_START) && (*Byte <= REX_PREFIX_STOP)) {\r
+      InstructionData->RexPrefix.Uint8 = *Byte;\r
+      if ((*Byte & REX_64BIT_OPERAND_SIZE_MASK) != 0) {\r
+        InstructionData->DataSize = Size64Bits;\r
+      }\r
+\r
+      continue;\r
+    }\r
+\r
+    switch (*Byte) {\r
+      case OVERRIDE_SEGMENT_CS:\r
+      case OVERRIDE_SEGMENT_DS:\r
+      case OVERRIDE_SEGMENT_ES:\r
+      case OVERRIDE_SEGMENT_SS:\r
+        if (Mode != LongMode64Bit) {\r
+          InstructionData->SegmentSpecified = TRUE;\r
+          InstructionData->Segment          = (*Byte >> 3) & 3;\r
+        }\r
+\r
+        break;\r
+\r
+      case OVERRIDE_SEGMENT_FS:\r
+      case OVERRIDE_SEGMENT_GS:\r
+        InstructionData->SegmentSpecified = TRUE;\r
+        InstructionData->Segment          = *Byte & 7;\r
+        break;\r
+\r
+      case OVERRIDE_OPERAND_SIZE:\r
+        if (InstructionData->RexPrefix.Uint8 == 0) {\r
+          InstructionData->DataSize =\r
+            (Mode == LongMode64Bit)       ? Size16Bits :\r
+            (Mode == LongModeCompat32Bit) ? Size16Bits :\r
+            (Mode == LongModeCompat16Bit) ? Size32Bits : 0;\r
+        }\r
+\r
+        break;\r
+\r
+      case OVERRIDE_ADDRESS_SIZE:\r
+        InstructionData->AddrSize =\r
+          (Mode == LongMode64Bit)       ? Size32Bits :\r
+          (Mode == LongModeCompat32Bit) ? Size16Bits :\r
+          (Mode == LongModeCompat16Bit) ? Size32Bits : 0;\r
+        break;\r
+\r
+      case LOCK_PREFIX:\r
+        break;\r
+\r
+      case REPZ_PREFIX:\r
+        InstructionData->RepMode = RepZ;\r
+        break;\r
+\r
+      case REPNZ_PREFIX:\r
+        InstructionData->RepMode = RepNZ;\r
+        break;\r
+\r
+      default:\r
+        InstructionData->OpCodes    = Byte;\r
+        InstructionData->OpCodeSize = (*Byte == TWO_BYTE_OPCODE_ESCAPE) ? 2 : 1;\r
+\r
+        InstructionData->End          = Byte + InstructionData->OpCodeSize;\r
+        InstructionData->Displacement = InstructionData->End;\r
+        InstructionData->Immediate    = InstructionData->End;\r
+        return;\r
+    }\r
+  }\r
+}\r
+\r
+/**\r
+  Determine instruction length\r
+\r
+  Return the total length of the parsed instruction.\r
+\r
+  @param[in] InstructionData  Instruction parsing context\r
+\r
+  @return                     Length of parsed instruction\r
+\r
+**/\r
+STATIC\r
+UINT64\r
+InstructionLength (\r
+  IN SEV_ES_INSTRUCTION_DATA  *InstructionData\r
+  )\r
+{\r
+  return (UINT64)(InstructionData->End - InstructionData->Begin);\r
+}\r
+\r
+/**\r
+  Initialize the instruction parsing context.\r
+\r
+  Initialize the instruction parsing context, which includes decoding the\r
+  instruction prefixes.\r
+\r
+  @param[in, out] InstructionData  Instruction parsing context\r
+  @param[in]      Ghcb             Pointer to the Guest-Hypervisor Communication\r
+                                   Block\r
+  @param[in]      Regs             x64 processor context\r
+\r
+**/\r
+STATIC\r
+VOID\r
+InitInstructionData (\r
+  IN OUT SEV_ES_INSTRUCTION_DATA  *InstructionData,\r
+  IN     GHCB                     *Ghcb,\r
+  IN     EFI_SYSTEM_CONTEXT_X64   *Regs\r
+  )\r
+{\r
+  SetMem (InstructionData, sizeof (*InstructionData), 0);\r
+  InstructionData->Ghcb  = Ghcb;\r
+  InstructionData->Begin = (UINT8 *)Regs->Rip;\r
+  InstructionData->End   = (UINT8 *)Regs->Rip;\r
+\r
+  DecodePrefixes (Regs, InstructionData);\r
+}\r
+\r
+/**\r
+  Report an unsupported event to the hypervisor\r
+\r
+  Use the VMGEXIT support to report an unsupported event to the hypervisor.\r
+\r
+  @param[in] Ghcb             Pointer to the Guest-Hypervisor Communication\r
+                              Block\r
+  @param[in] Regs             x64 processor context\r
+  @param[in] InstructionData  Instruction parsing context\r
+\r
+  @return                     New exception value to propagate\r
+\r
+**/\r
+STATIC\r
+UINT64\r
+UnsupportedExit (\r
+  IN GHCB                     *Ghcb,\r
+  IN EFI_SYSTEM_CONTEXT_X64   *Regs,\r
+  IN SEV_ES_INSTRUCTION_DATA  *InstructionData\r
+  )\r
+{\r
+  UINT64  Status;\r
+\r
+  Status = VmgExit (Ghcb, SVM_EXIT_UNSUPPORTED, Regs->ExceptionData, 0);\r
+  if (Status == 0) {\r
+    GHCB_EVENT_INJECTION  Event;\r
+\r
+    Event.Uint64          = 0;\r
+    Event.Elements.Vector = GP_EXCEPTION;\r
+    Event.Elements.Type   = GHCB_EVENT_INJECTION_TYPE_EXCEPTION;\r
+    Event.Elements.Valid  = 1;\r
+\r
+    Status = Event.Uint64;\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Validate that the MMIO memory access is not to encrypted memory.\r
+\r
+  Examine the pagetable entry for the memory specified. MMIO should not be\r
+  performed against encrypted memory. MMIO to the APIC page is always allowed.\r
+\r
+  @param[in] Ghcb           Pointer to the Guest-Hypervisor Communication Block\r
+  @param[in] MemoryAddress  Memory address to validate\r
+  @param[in] MemoryLength   Memory length to validate\r
+\r
+  @retval 0          Memory is not encrypted\r
+  @return            New exception value to propogate\r
+\r
+**/\r
+STATIC\r
+UINT64\r
+ValidateMmioMemory (\r
+  IN GHCB   *Ghcb,\r
+  IN UINTN  MemoryAddress,\r
+  IN UINTN  MemoryLength\r
+  )\r
+{\r
+  MEM_ENCRYPT_SEV_ADDRESS_RANGE_STATE  State;\r
+  GHCB_EVENT_INJECTION                 GpEvent;\r
+  UINTN                                Address;\r
+\r
+  //\r
+  // Allow APIC accesses (which will have the encryption bit set during\r
+  // SEC and PEI phases).\r
+  //\r
+  Address = MemoryAddress & ~(SIZE_4KB - 1);\r
+  if (Address == GetLocalApicBaseAddress ()) {\r
+    return 0;\r
+  }\r
+\r
+  State = MemEncryptSevGetAddressRangeState (\r
+            0,\r
+            MemoryAddress,\r
+            MemoryLength\r
+            );\r
+  if (State == MemEncryptSevAddressRangeUnencrypted) {\r
+    return 0;\r
+  }\r
+\r
+  //\r
+  // Any state other than unencrypted is an error, issue a #GP.\r
+  //\r
+  DEBUG ((\r
+    DEBUG_ERROR,\r
+    "MMIO using encrypted memory: %lx\n",\r
+    (UINT64)MemoryAddress\r
+    ));\r
+  GpEvent.Uint64          = 0;\r
+  GpEvent.Elements.Vector = GP_EXCEPTION;\r
+  GpEvent.Elements.Type   = GHCB_EVENT_INJECTION_TYPE_EXCEPTION;\r
+  GpEvent.Elements.Valid  = 1;\r
+\r
+  return GpEvent.Uint64;\r
+}\r
+\r
+/**\r
+  Handle an MMIO event.\r
+\r
+  Use the VMGEXIT instruction to handle either an MMIO read or an MMIO write.\r
+\r
+  @param[in, out] Ghcb             Pointer to the Guest-Hypervisor Communication\r
+                                   Block\r
+  @param[in, out] Regs             x64 processor context\r
+  @param[in, out] InstructionData  Instruction parsing context\r
+\r
+  @retval 0                        Event handled successfully\r
+  @return                          New exception value to propagate\r
+\r
+**/\r
+STATIC\r
+UINT64\r
+MmioExit (\r
+  IN OUT GHCB                     *Ghcb,\r
+  IN OUT EFI_SYSTEM_CONTEXT_X64   *Regs,\r
+  IN OUT SEV_ES_INSTRUCTION_DATA  *InstructionData\r
+  )\r
+{\r
+  UINT64  ExitInfo1, ExitInfo2, Status;\r
+  UINTN   Bytes;\r
+  UINT64  *Register;\r
+  UINT8   OpCode, SignByte;\r
+  UINTN   Address;\r
+\r
+  Bytes = 0;\r
+\r
+  OpCode = *(InstructionData->OpCodes);\r
+  if (OpCode == TWO_BYTE_OPCODE_ESCAPE) {\r
+    OpCode = *(InstructionData->OpCodes + 1);\r
+  }\r
+\r
+  switch (OpCode) {\r
+    //\r
+    // MMIO write (MOV reg/memX, regX)\r
+    //\r
+    case 0x88:\r
+      Bytes = 1;\r
+    //\r
+    // fall through\r
+    //\r
+    case 0x89:\r
+      DecodeModRm (Regs, InstructionData);\r
+      Bytes = ((Bytes != 0) ? Bytes :\r
+               (InstructionData->DataSize == Size16Bits) ? 2 :\r
+               (InstructionData->DataSize == Size32Bits) ? 4 :\r
+               (InstructionData->DataSize == Size64Bits) ? 8 :\r
+               0);\r
+\r
+      if (InstructionData->Ext.ModRm.Mod == 3) {\r
+        //\r
+        // NPF on two register operands???\r
+        //\r
+        return UnsupportedExit (Ghcb, Regs, InstructionData);\r
+      }\r
+\r
+      Status = ValidateMmioMemory (Ghcb, InstructionData->Ext.RmData, Bytes);\r
+      if (Status != 0) {\r
+        return Status;\r
+      }\r
+\r
+      ExitInfo1 = InstructionData->Ext.RmData;\r
+      ExitInfo2 = Bytes;\r
+      CopyMem (Ghcb->SharedBuffer, &InstructionData->Ext.RegData, Bytes);\r
+\r
+      Ghcb->SaveArea.SwScratch = (UINT64)Ghcb->SharedBuffer;\r
+      VmgSetOffsetValid (Ghcb, GhcbSwScratch);\r
+      Status = VmgExit (Ghcb, SVM_EXIT_MMIO_WRITE, ExitInfo1, ExitInfo2);\r
+      if (Status != 0) {\r
+        return Status;\r
+      }\r
+\r
+      break;\r
+\r
+    //\r
+    // MMIO write (MOV moffsetX, aX)\r
+    //\r
+    case 0xA2:\r
+      Bytes = 1;\r
+    //\r
+    // fall through\r
+    //\r
+    case 0xA3:\r
+      Bytes = ((Bytes != 0) ? Bytes :\r
+               (InstructionData->DataSize == Size16Bits) ? 2 :\r
+               (InstructionData->DataSize == Size32Bits) ? 4 :\r
+               (InstructionData->DataSize == Size64Bits) ? 8 :\r
+               0);\r
+\r
+      InstructionData->ImmediateSize = (UINTN)(1 << InstructionData->AddrSize);\r
+      InstructionData->End          += InstructionData->ImmediateSize;\r
+\r
+      //\r
+      // This code is X64 only, so a possible 8-byte copy to a UINTN is ok.\r
+      // Use a STATIC_ASSERT to be certain the code is being built as X64.\r
+      //\r
+      STATIC_ASSERT (\r
+        sizeof (UINTN) == sizeof (UINT64),\r
+        "sizeof (UINTN) != sizeof (UINT64), this file must be built as X64"\r
+        );\r
+\r
+      Address = 0;\r
+      CopyMem (\r
+        &Address,\r
+        InstructionData->Immediate,\r
+        InstructionData->ImmediateSize\r
+        );\r
+\r
+      Status = ValidateMmioMemory (Ghcb, Address, Bytes);\r
+      if (Status != 0) {\r
+        return Status;\r
+      }\r
+\r
+      ExitInfo1 = Address;\r
+      ExitInfo2 = Bytes;\r
+      CopyMem (Ghcb->SharedBuffer, &Regs->Rax, Bytes);\r
+\r
+      Ghcb->SaveArea.SwScratch = (UINT64)Ghcb->SharedBuffer;\r
+      VmgSetOffsetValid (Ghcb, GhcbSwScratch);\r
+      Status = VmgExit (Ghcb, SVM_EXIT_MMIO_WRITE, ExitInfo1, ExitInfo2);\r
+      if (Status != 0) {\r
+        return Status;\r
+      }\r
+\r
+      break;\r
+\r
+    //\r
+    // MMIO write (MOV reg/memX, immX)\r
+    //\r
+    case 0xC6:\r
+      Bytes = 1;\r
+    //\r
+    // fall through\r
+    //\r
+    case 0xC7:\r
+      DecodeModRm (Regs, InstructionData);\r
+      Bytes = ((Bytes != 0) ? Bytes :\r
+               (InstructionData->DataSize == Size16Bits) ? 2 :\r
+               (InstructionData->DataSize == Size32Bits) ? 4 :\r
+               0);\r
+\r
+      InstructionData->ImmediateSize = Bytes;\r
+      InstructionData->End          += Bytes;\r
+\r
+      Status = ValidateMmioMemory (Ghcb, InstructionData->Ext.RmData, Bytes);\r
+      if (Status != 0) {\r
+        return Status;\r
+      }\r
+\r
+      ExitInfo1 = InstructionData->Ext.RmData;\r
+      ExitInfo2 = Bytes;\r
+      CopyMem (Ghcb->SharedBuffer, InstructionData->Immediate, Bytes);\r
+\r
+      Ghcb->SaveArea.SwScratch = (UINT64)Ghcb->SharedBuffer;\r
+      VmgSetOffsetValid (Ghcb, GhcbSwScratch);\r
+      Status = VmgExit (Ghcb, SVM_EXIT_MMIO_WRITE, ExitInfo1, ExitInfo2);\r
+      if (Status != 0) {\r
+        return Status;\r
+      }\r
+\r
+      break;\r
+\r
+    //\r
+    // MMIO read (MOV regX, reg/memX)\r
+    //\r
+    case 0x8A:\r
+      Bytes = 1;\r
+    //\r
+    // fall through\r
+    //\r
+    case 0x8B:\r
+      DecodeModRm (Regs, InstructionData);\r
+      Bytes = ((Bytes != 0) ? Bytes :\r
+               (InstructionData->DataSize == Size16Bits) ? 2 :\r
+               (InstructionData->DataSize == Size32Bits) ? 4 :\r
+               (InstructionData->DataSize == Size64Bits) ? 8 :\r
+               0);\r
+      if (InstructionData->Ext.ModRm.Mod == 3) {\r
+        //\r
+        // NPF on two register operands???\r
+        //\r
+        return UnsupportedExit (Ghcb, Regs, InstructionData);\r
+      }\r
+\r
+      Status = ValidateMmioMemory (Ghcb, InstructionData->Ext.RmData, Bytes);\r
+      if (Status != 0) {\r
+        return Status;\r
+      }\r
+\r
+      ExitInfo1 = InstructionData->Ext.RmData;\r
+      ExitInfo2 = Bytes;\r
+\r
+      Ghcb->SaveArea.SwScratch = (UINT64)Ghcb->SharedBuffer;\r
+      VmgSetOffsetValid (Ghcb, GhcbSwScratch);\r
+      Status = VmgExit (Ghcb, SVM_EXIT_MMIO_READ, ExitInfo1, ExitInfo2);\r
+      if (Status != 0) {\r
+        return Status;\r
+      }\r
+\r
+      Register = GetRegisterPointer (Regs, InstructionData->Ext.ModRm.Reg);\r
+      if (Bytes == 4) {\r
+        //\r
+        // Zero-extend for 32-bit operation\r
+        //\r
+        *Register = 0;\r
+      }\r
+\r
+      CopyMem (Register, Ghcb->SharedBuffer, Bytes);\r
+      break;\r
+\r
+    //\r
+    // MMIO read (MOV aX, moffsetX)\r
+    //\r
+    case 0xA0:\r
+      Bytes = 1;\r
+    //\r
+    // fall through\r
+    //\r
+    case 0xA1:\r
+      Bytes = ((Bytes != 0) ? Bytes :\r
+               (InstructionData->DataSize == Size16Bits) ? 2 :\r
+               (InstructionData->DataSize == Size32Bits) ? 4 :\r
+               (InstructionData->DataSize == Size64Bits) ? 8 :\r
+               0);\r
+\r
+      InstructionData->ImmediateSize = (UINTN)(1 << InstructionData->AddrSize);\r
+      InstructionData->End          += InstructionData->ImmediateSize;\r
+\r
+      //\r
+      // This code is X64 only, so a possible 8-byte copy to a UINTN is ok.\r
+      // Use a STATIC_ASSERT to be certain the code is being built as X64.\r
+      //\r
+      STATIC_ASSERT (\r
+        sizeof (UINTN) == sizeof (UINT64),\r
+        "sizeof (UINTN) != sizeof (UINT64), this file must be built as X64"\r
+        );\r
+\r
+      Address = 0;\r
+      CopyMem (\r
+        &Address,\r
+        InstructionData->Immediate,\r
+        InstructionData->ImmediateSize\r
+        );\r
+\r
+      Status = ValidateMmioMemory (Ghcb, Address, Bytes);\r
+      if (Status != 0) {\r
+        return Status;\r
+      }\r
+\r
+      ExitInfo1 = Address;\r
+      ExitInfo2 = Bytes;\r
+\r
+      Ghcb->SaveArea.SwScratch = (UINT64)Ghcb->SharedBuffer;\r
+      VmgSetOffsetValid (Ghcb, GhcbSwScratch);\r
+      Status = VmgExit (Ghcb, SVM_EXIT_MMIO_READ, ExitInfo1, ExitInfo2);\r
+      if (Status != 0) {\r
+        return Status;\r
+      }\r
+\r
+      if (Bytes == 4) {\r
+        //\r
+        // Zero-extend for 32-bit operation\r
+        //\r
+        Regs->Rax = 0;\r
+      }\r
+\r
+      CopyMem (&Regs->Rax, Ghcb->SharedBuffer, Bytes);\r
+      break;\r
+\r
+    //\r
+    // MMIO read w/ zero-extension ((MOVZX regX, reg/memX)\r
+    //\r
+    case 0xB6:\r
+      Bytes = 1;\r
+    //\r
+    // fall through\r
+    //\r
+    case 0xB7:\r
+      DecodeModRm (Regs, InstructionData);\r
+      Bytes = (Bytes != 0) ? Bytes : 2;\r
+\r
+      Status = ValidateMmioMemory (Ghcb, InstructionData->Ext.RmData, Bytes);\r
+      if (Status != 0) {\r
+        return Status;\r
+      }\r
+\r
+      ExitInfo1 = InstructionData->Ext.RmData;\r
+      ExitInfo2 = Bytes;\r
+\r
+      Ghcb->SaveArea.SwScratch = (UINT64)Ghcb->SharedBuffer;\r
+      VmgSetOffsetValid (Ghcb, GhcbSwScratch);\r
+      Status = VmgExit (Ghcb, SVM_EXIT_MMIO_READ, ExitInfo1, ExitInfo2);\r
+      if (Status != 0) {\r
+        return Status;\r
+      }\r
+\r
+      Register = GetRegisterPointer (Regs, InstructionData->Ext.ModRm.Reg);\r
+      SetMem (Register, (UINTN)(1 << InstructionData->DataSize), 0);\r
+      CopyMem (Register, Ghcb->SharedBuffer, Bytes);\r
+      break;\r
+\r
+    //\r
+    // MMIO read w/ sign-extension (MOVSX regX, reg/memX)\r
+    //\r
+    case 0xBE:\r
+      Bytes = 1;\r
+    //\r
+    // fall through\r
+    //\r
+    case 0xBF:\r
+      DecodeModRm (Regs, InstructionData);\r
+      Bytes = (Bytes != 0) ? Bytes : 2;\r
+\r
+      Status = ValidateMmioMemory (Ghcb, InstructionData->Ext.RmData, Bytes);\r
+      if (Status != 0) {\r
+        return Status;\r
+      }\r
+\r
+      ExitInfo1 = InstructionData->Ext.RmData;\r
+      ExitInfo2 = Bytes;\r
+\r
+      Ghcb->SaveArea.SwScratch = (UINT64)Ghcb->SharedBuffer;\r
+      VmgSetOffsetValid (Ghcb, GhcbSwScratch);\r
+      Status = VmgExit (Ghcb, SVM_EXIT_MMIO_READ, ExitInfo1, ExitInfo2);\r
+      if (Status != 0) {\r
+        return Status;\r
+      }\r
+\r
+      if (Bytes == 1) {\r
+        UINT8  *Data;\r
+\r
+        Data     = (UINT8 *)Ghcb->SharedBuffer;\r
+        SignByte = ((*Data & BIT7) != 0) ? 0xFF : 0x00;\r
+      } else {\r
+        UINT16  *Data;\r
+\r
+        Data     = (UINT16 *)Ghcb->SharedBuffer;\r
+        SignByte = ((*Data & BIT15) != 0) ? 0xFF : 0x00;\r
+      }\r
+\r
+      Register = GetRegisterPointer (Regs, InstructionData->Ext.ModRm.Reg);\r
+      SetMem (Register, (UINTN)(1 << InstructionData->DataSize), SignByte);\r
+      CopyMem (Register, Ghcb->SharedBuffer, Bytes);\r
+      break;\r
+\r
+    default:\r
+      DEBUG ((DEBUG_ERROR, "Invalid MMIO opcode (%x)\n", OpCode));\r
+      Status = GP_EXCEPTION;\r
+      ASSERT (FALSE);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Handle a MWAIT event.\r
+\r
+  Use the VMGEXIT instruction to handle a MWAIT event.\r
+\r
+  @param[in, out] Ghcb             Pointer to the Guest-Hypervisor Communication\r
+                                   Block\r
+  @param[in, out] Regs             x64 processor context\r
+  @param[in]      InstructionData  Instruction parsing context\r
+\r
+  @retval 0                        Event handled successfully\r
+  @return                          New exception value to propagate\r
+\r
+**/\r
+STATIC\r
+UINT64\r
+MwaitExit (\r
+  IN OUT GHCB                     *Ghcb,\r
+  IN OUT EFI_SYSTEM_CONTEXT_X64   *Regs,\r
+  IN     SEV_ES_INSTRUCTION_DATA  *InstructionData\r
+  )\r
+{\r
+  DecodeModRm (Regs, InstructionData);\r
+\r
+  Ghcb->SaveArea.Rax = Regs->Rax;\r
+  VmgSetOffsetValid (Ghcb, GhcbRax);\r
+  Ghcb->SaveArea.Rcx = Regs->Rcx;\r
+  VmgSetOffsetValid (Ghcb, GhcbRcx);\r
+\r
+  return VmgExit (Ghcb, SVM_EXIT_MWAIT, 0, 0);\r
+}\r
+\r
+/**\r
+  Handle a MONITOR event.\r
+\r
+  Use the VMGEXIT instruction to handle a MONITOR event.\r
+\r
+  @param[in, out] Ghcb             Pointer to the Guest-Hypervisor Communication\r
+                                   Block\r
+  @param[in, out] Regs             x64 processor context\r
+  @param[in]      InstructionData  Instruction parsing context\r
+\r
+  @retval 0                        Event handled successfully\r
+  @return                          New exception value to propagate\r
+\r
+**/\r
+STATIC\r
+UINT64\r
+MonitorExit (\r
+  IN OUT GHCB                     *Ghcb,\r
+  IN OUT EFI_SYSTEM_CONTEXT_X64   *Regs,\r
+  IN     SEV_ES_INSTRUCTION_DATA  *InstructionData\r
+  )\r
+{\r
+  DecodeModRm (Regs, InstructionData);\r
+\r
+  Ghcb->SaveArea.Rax = Regs->Rax;  // Identity mapped, so VA = PA\r
+  VmgSetOffsetValid (Ghcb, GhcbRax);\r
+  Ghcb->SaveArea.Rcx = Regs->Rcx;\r
+  VmgSetOffsetValid (Ghcb, GhcbRcx);\r
+  Ghcb->SaveArea.Rdx = Regs->Rdx;\r
+  VmgSetOffsetValid (Ghcb, GhcbRdx);\r
+\r
+  return VmgExit (Ghcb, SVM_EXIT_MONITOR, 0, 0);\r
+}\r
+\r
+/**\r
+  Handle a WBINVD event.\r
+\r
+  Use the VMGEXIT instruction to handle a WBINVD event.\r
+\r
+  @param[in, out] Ghcb             Pointer to the Guest-Hypervisor Communication\r
+                                   Block\r
+  @param[in, out] Regs             x64 processor context\r
+  @param[in]      InstructionData  Instruction parsing context\r
+\r
+  @retval 0                        Event handled successfully\r
+  @return                          New exception value to propagate\r
+\r
+**/\r
+STATIC\r
+UINT64\r
+WbinvdExit (\r
+  IN OUT GHCB                     *Ghcb,\r
+  IN OUT EFI_SYSTEM_CONTEXT_X64   *Regs,\r
+  IN     SEV_ES_INSTRUCTION_DATA  *InstructionData\r
+  )\r
+{\r
+  return VmgExit (Ghcb, SVM_EXIT_WBINVD, 0, 0);\r
+}\r
+\r
+/**\r
+  Handle a RDTSCP event.\r
+\r
+  Use the VMGEXIT instruction to handle a RDTSCP event.\r
+\r
+  @param[in, out] Ghcb             Pointer to the Guest-Hypervisor Communication\r
+                                   Block\r
+  @param[in, out] Regs             x64 processor context\r
+  @param[in]      InstructionData  Instruction parsing context\r
+\r
+  @retval 0                        Event handled successfully\r
+  @return                          New exception value to propagate\r
+\r
+**/\r
+STATIC\r
+UINT64\r
+RdtscpExit (\r
+  IN OUT GHCB                     *Ghcb,\r
+  IN OUT EFI_SYSTEM_CONTEXT_X64   *Regs,\r
+  IN     SEV_ES_INSTRUCTION_DATA  *InstructionData\r
+  )\r
+{\r
+  UINT64  Status;\r
+\r
+  DecodeModRm (Regs, InstructionData);\r
+\r
+  Status = VmgExit (Ghcb, SVM_EXIT_RDTSCP, 0, 0);\r
+  if (Status != 0) {\r
+    return Status;\r
+  }\r
+\r
+  if (!VmgIsOffsetValid (Ghcb, GhcbRax) ||\r
+      !VmgIsOffsetValid (Ghcb, GhcbRcx) ||\r
+      !VmgIsOffsetValid (Ghcb, GhcbRdx))\r
+  {\r
+    return UnsupportedExit (Ghcb, Regs, InstructionData);\r
+  }\r
+\r
+  Regs->Rax = Ghcb->SaveArea.Rax;\r
+  Regs->Rcx = Ghcb->SaveArea.Rcx;\r
+  Regs->Rdx = Ghcb->SaveArea.Rdx;\r
+\r
+  return 0;\r
+}\r
+\r
+/**\r
+  Handle a VMMCALL event.\r
+\r
+  Use the VMGEXIT instruction to handle a VMMCALL event.\r
+\r
+  @param[in, out] Ghcb             Pointer to the Guest-Hypervisor Communication\r
+                                   Block\r
+  @param[in, out] Regs             x64 processor context\r
+  @param[in]      InstructionData  Instruction parsing context\r
+\r
+  @retval 0                        Event handled successfully\r
+  @return                          New exception value to propagate\r
+\r
+**/\r
+STATIC\r
+UINT64\r
+VmmCallExit (\r
+  IN OUT GHCB                     *Ghcb,\r
+  IN OUT EFI_SYSTEM_CONTEXT_X64   *Regs,\r
+  IN     SEV_ES_INSTRUCTION_DATA  *InstructionData\r
+  )\r
+{\r
+  UINT64  Status;\r
+\r
+  DecodeModRm (Regs, InstructionData);\r
+\r
+  Ghcb->SaveArea.Rax = Regs->Rax;\r
+  VmgSetOffsetValid (Ghcb, GhcbRax);\r
+  Ghcb->SaveArea.Cpl = (UINT8)(Regs->Cs & 0x3);\r
+  VmgSetOffsetValid (Ghcb, GhcbCpl);\r
+\r
+  Status = VmgExit (Ghcb, SVM_EXIT_VMMCALL, 0, 0);\r
+  if (Status != 0) {\r
+    return Status;\r
+  }\r
+\r
+  if (!VmgIsOffsetValid (Ghcb, GhcbRax)) {\r
+    return UnsupportedExit (Ghcb, Regs, InstructionData);\r
+  }\r
+\r
+  Regs->Rax = Ghcb->SaveArea.Rax;\r
+\r
+  return 0;\r
+}\r
+\r
+/**\r
+  Handle an MSR event.\r
+\r
+  Use the VMGEXIT instruction to handle either a RDMSR or WRMSR event.\r
+\r
+  @param[in, out] Ghcb             Pointer to the Guest-Hypervisor Communication\r
+                                   Block\r
+  @param[in, out] Regs             x64 processor context\r
+  @param[in]      InstructionData  Instruction parsing context\r
+\r
+  @retval 0                        Event handled successfully\r
+  @return                          New exception value to propagate\r
+\r
+**/\r
+STATIC\r
+UINT64\r
+MsrExit (\r
+  IN OUT GHCB                     *Ghcb,\r
+  IN OUT EFI_SYSTEM_CONTEXT_X64   *Regs,\r
+  IN     SEV_ES_INSTRUCTION_DATA  *InstructionData\r
+  )\r
+{\r
+  UINT64  ExitInfo1, Status;\r
+\r
+  ExitInfo1 = 0;\r
+\r
+  switch (*(InstructionData->OpCodes + 1)) {\r
+    case 0x30: // WRMSR\r
+      ExitInfo1          = 1;\r
+      Ghcb->SaveArea.Rax = Regs->Rax;\r
+      VmgSetOffsetValid (Ghcb, GhcbRax);\r
+      Ghcb->SaveArea.Rdx = Regs->Rdx;\r
+      VmgSetOffsetValid (Ghcb, GhcbRdx);\r
+    //\r
+    // fall through\r
+    //\r
+    case 0x32: // RDMSR\r
+      Ghcb->SaveArea.Rcx = Regs->Rcx;\r
+      VmgSetOffsetValid (Ghcb, GhcbRcx);\r
+      break;\r
+    default:\r
+      return UnsupportedExit (Ghcb, Regs, InstructionData);\r
+  }\r
+\r
+  Status = VmgExit (Ghcb, SVM_EXIT_MSR, ExitInfo1, 0);\r
+  if (Status != 0) {\r
+    return Status;\r
+  }\r
+\r
+  if (ExitInfo1 == 0) {\r
+    if (!VmgIsOffsetValid (Ghcb, GhcbRax) ||\r
+        !VmgIsOffsetValid (Ghcb, GhcbRdx))\r
+    {\r
+      return UnsupportedExit (Ghcb, Regs, InstructionData);\r
+    }\r
+\r
+    Regs->Rax = Ghcb->SaveArea.Rax;\r
+    Regs->Rdx = Ghcb->SaveArea.Rdx;\r
+  }\r
+\r
+  return 0;\r
+}\r
+\r
+/**\r
+  Build the IOIO event information.\r
+\r
+  The IOIO event information identifies the type of IO operation to be performed\r
+  by the hypervisor. Build this information based on the instruction data.\r
+\r
+  @param[in]       Regs             x64 processor context\r
+  @param[in, out]  InstructionData  Instruction parsing context\r
+\r
+  @return                           IOIO event information value\r
+\r
+**/\r
+STATIC\r
+UINT64\r
+IoioExitInfo (\r
+  IN     EFI_SYSTEM_CONTEXT_X64   *Regs,\r
+  IN OUT SEV_ES_INSTRUCTION_DATA  *InstructionData\r
+  )\r
+{\r
+  UINT64  ExitInfo;\r
+\r
+  ExitInfo = 0;\r
+\r
+  switch (*(InstructionData->OpCodes)) {\r
+    //\r
+    // INS opcodes\r
+    //\r
+    case 0x6C:\r
+    case 0x6D:\r
+      ExitInfo |= IOIO_TYPE_INS;\r
+      ExitInfo |= IOIO_SEG_ES;\r
+      ExitInfo |= ((Regs->Rdx & 0xffff) << 16);\r
+      break;\r
+\r
+    //\r
+    // OUTS opcodes\r
+    //\r
+    case 0x6E:\r
+    case 0x6F:\r
+      ExitInfo |= IOIO_TYPE_OUTS;\r
+      ExitInfo |= IOIO_SEG_DS;\r
+      ExitInfo |= ((Regs->Rdx & 0xffff) << 16);\r
+      break;\r
+\r
+    //\r
+    // IN immediate opcodes\r
+    //\r
+    case 0xE4:\r
+    case 0xE5:\r
+      InstructionData->ImmediateSize = 1;\r
+      InstructionData->End++;\r
+      ExitInfo |= IOIO_TYPE_IN;\r
+      ExitInfo |= ((*(InstructionData->OpCodes + 1)) << 16);\r
+      break;\r
+\r
+    //\r
+    // OUT immediate opcodes\r
+    //\r
+    case 0xE6:\r
+    case 0xE7:\r
+      InstructionData->ImmediateSize = 1;\r
+      InstructionData->End++;\r
+      ExitInfo |= IOIO_TYPE_OUT;\r
+      ExitInfo |= ((*(InstructionData->OpCodes + 1)) << 16) | IOIO_TYPE_OUT;\r
+      break;\r
+\r
+    //\r
+    // IN register opcodes\r
+    //\r
+    case 0xEC:\r
+    case 0xED:\r
+      ExitInfo |= IOIO_TYPE_IN;\r
+      ExitInfo |= ((Regs->Rdx & 0xffff) << 16);\r
+      break;\r
+\r
+    //\r
+    // OUT register opcodes\r
+    //\r
+    case 0xEE:\r
+    case 0xEF:\r
+      ExitInfo |= IOIO_TYPE_OUT;\r
+      ExitInfo |= ((Regs->Rdx & 0xffff) << 16);\r
+      break;\r
+\r
+    default:\r
+      return 0;\r
+  }\r
+\r
+  switch (*(InstructionData->OpCodes)) {\r
+    //\r
+    // Single-byte opcodes\r
+    //\r
+    case 0x6C:\r
+    case 0x6E:\r
+    case 0xE4:\r
+    case 0xE6:\r
+    case 0xEC:\r
+    case 0xEE:\r
+      ExitInfo |= IOIO_DATA_8;\r
+      break;\r
+\r
+    //\r
+    // Length determined by instruction parsing\r
+    //\r
+    default:\r
+      ExitInfo |= (InstructionData->DataSize == Size16Bits) ? IOIO_DATA_16\r
+                                                          : IOIO_DATA_32;\r
+  }\r
+\r
+  switch (InstructionData->AddrSize) {\r
+    case Size16Bits:\r
+      ExitInfo |= IOIO_ADDR_16;\r
+      break;\r
+\r
+    case Size32Bits:\r
+      ExitInfo |= IOIO_ADDR_32;\r
+      break;\r
+\r
+    case Size64Bits:\r
+      ExitInfo |= IOIO_ADDR_64;\r
+      break;\r
+\r
+    default:\r
+      break;\r
+  }\r
+\r
+  if (InstructionData->RepMode != 0) {\r
+    ExitInfo |= IOIO_REP;\r
+  }\r
+\r
+  return ExitInfo;\r
+}\r
+\r
+/**\r
+  Handle an IOIO event.\r
+\r
+  Use the VMGEXIT instruction to handle an IOIO event.\r
+\r
+  @param[in, out] Ghcb             Pointer to the Guest-Hypervisor Communication\r
+                                   Block\r
+  @param[in, out] Regs             x64 processor context\r
+  @param[in]      InstructionData  Instruction parsing context\r
+\r
+  @retval 0                        Event handled successfully\r
+  @return                          New exception value to propagate\r
+\r
+**/\r
+STATIC\r
+UINT64\r
+IoioExit (\r
+  IN OUT GHCB                     *Ghcb,\r
+  IN OUT EFI_SYSTEM_CONTEXT_X64   *Regs,\r
+  IN     SEV_ES_INSTRUCTION_DATA  *InstructionData\r
+  )\r
+{\r
+  UINT64   ExitInfo1, ExitInfo2, Status;\r
+  BOOLEAN  IsString;\r
+\r
+  ExitInfo1 = IoioExitInfo (Regs, InstructionData);\r
+  if (ExitInfo1 == 0) {\r
+    return UnsupportedExit (Ghcb, Regs, InstructionData);\r
+  }\r
+\r
+  IsString = ((ExitInfo1 & IOIO_TYPE_STR) != 0) ? TRUE : FALSE;\r
+  if (IsString) {\r
+    UINTN  IoBytes, VmgExitBytes;\r
+    UINTN  GhcbCount, OpCount;\r
+\r
+    Status = 0;\r
+\r
+    IoBytes   = IOIO_DATA_BYTES (ExitInfo1);\r
+    GhcbCount = sizeof (Ghcb->SharedBuffer) / IoBytes;\r
+\r
+    OpCount = ((ExitInfo1 & IOIO_REP) != 0) ? Regs->Rcx : 1;\r
+    while (OpCount != 0) {\r
+      ExitInfo2    = MIN (OpCount, GhcbCount);\r
+      VmgExitBytes = ExitInfo2 * IoBytes;\r
+\r
+      if ((ExitInfo1 & IOIO_TYPE_IN) == 0) {\r
+        CopyMem (Ghcb->SharedBuffer, (VOID *)Regs->Rsi, VmgExitBytes);\r
+        Regs->Rsi += VmgExitBytes;\r
+      }\r
+\r
+      Ghcb->SaveArea.SwScratch = (UINT64)Ghcb->SharedBuffer;\r
+      VmgSetOffsetValid (Ghcb, GhcbSwScratch);\r
+      Status = VmgExit (Ghcb, SVM_EXIT_IOIO_PROT, ExitInfo1, ExitInfo2);\r
+      if (Status != 0) {\r
+        return Status;\r
+      }\r
+\r
+      if ((ExitInfo1 & IOIO_TYPE_IN) != 0) {\r
+        CopyMem ((VOID *)Regs->Rdi, Ghcb->SharedBuffer, VmgExitBytes);\r
+        Regs->Rdi += VmgExitBytes;\r
+      }\r
+\r
+      if ((ExitInfo1 & IOIO_REP) != 0) {\r
+        Regs->Rcx -= ExitInfo2;\r
+      }\r
+\r
+      OpCount -= ExitInfo2;\r
+    }\r
+  } else {\r
+    if ((ExitInfo1 & IOIO_TYPE_IN) != 0) {\r
+      Ghcb->SaveArea.Rax = 0;\r
+    } else {\r
+      CopyMem (&Ghcb->SaveArea.Rax, &Regs->Rax, IOIO_DATA_BYTES (ExitInfo1));\r
+    }\r
+\r
+    VmgSetOffsetValid (Ghcb, GhcbRax);\r
+\r
+    Status = VmgExit (Ghcb, SVM_EXIT_IOIO_PROT, ExitInfo1, 0);\r
+    if (Status != 0) {\r
+      return Status;\r
+    }\r
+\r
+    if ((ExitInfo1 & IOIO_TYPE_IN) != 0) {\r
+      if (!VmgIsOffsetValid (Ghcb, GhcbRax)) {\r
+        return UnsupportedExit (Ghcb, Regs, InstructionData);\r
+      }\r
+\r
+      CopyMem (&Regs->Rax, &Ghcb->SaveArea.Rax, IOIO_DATA_BYTES (ExitInfo1));\r
+    }\r
+  }\r
+\r
+  return 0;\r
+}\r
+\r
+/**\r
+  Handle a INVD event.\r
+\r
+  Use the VMGEXIT instruction to handle a INVD event.\r
+\r
+  @param[in, out] Ghcb             Pointer to the Guest-Hypervisor Communication\r
+                                   Block\r
+  @param[in, out] Regs             x64 processor context\r
+  @param[in]      InstructionData  Instruction parsing context\r
+\r
+  @retval 0                        Event handled successfully\r
+  @return                          New exception value to propagate\r
+\r
+**/\r
+STATIC\r
+UINT64\r
+InvdExit (\r
+  IN OUT GHCB                     *Ghcb,\r
+  IN OUT EFI_SYSTEM_CONTEXT_X64   *Regs,\r
+  IN     SEV_ES_INSTRUCTION_DATA  *InstructionData\r
+  )\r
+{\r
+  return VmgExit (Ghcb, SVM_EXIT_INVD, 0, 0);\r
+}\r
+\r
+/**\r
+  Fetch CPUID leaf/function via hypervisor/VMGEXIT.\r
+\r
+  @param[in, out] Ghcb         Pointer to the Guest-Hypervisor Communication\r
+                               Block\r
+  @param[in]      EaxIn        EAX input for cpuid instruction\r
+  @param[in]      EcxIn        ECX input for cpuid instruction\r
+  @param[in]      Xcr0In       XCR0 at time of cpuid instruction\r
+  @param[in, out] Eax          Pointer to store leaf's EAX value\r
+  @param[in, out] Ebx          Pointer to store leaf's EBX value\r
+  @param[in, out] Ecx          Pointer to store leaf's ECX value\r
+  @param[in, out] Edx          Pointer to store leaf's EDX value\r
+  @param[in, out] Status       Pointer to store status from VMGEXIT (always 0\r
+                               unless return value indicates failure)\r
+  @param[in, out] Unsupported  Pointer to store indication of unsupported\r
+                               VMGEXIT (always false unless return value\r
+                               indicates failure)\r
+\r
+  @retval TRUE                 CPUID leaf fetch successfully.\r
+  @retval FALSE                Error occurred while fetching CPUID leaf. Callers\r
+                               should Status and Unsupported and handle\r
+                               accordingly if they indicate a more precise\r
+                               error condition.\r
+\r
+**/\r
+STATIC\r
+BOOLEAN\r
+GetCpuidHyp (\r
+  IN OUT GHCB     *Ghcb,\r
+  IN     UINT32   EaxIn,\r
+  IN     UINT32   EcxIn,\r
+  IN     UINT64   XCr0,\r
+  IN OUT UINT32   *Eax,\r
+  IN OUT UINT32   *Ebx,\r
+  IN OUT UINT32   *Ecx,\r
+  IN OUT UINT32   *Edx,\r
+  IN OUT UINT64   *Status,\r
+  IN OUT BOOLEAN  *UnsupportedExit\r
+  )\r
+{\r
+  *UnsupportedExit   = FALSE;\r
+  Ghcb->SaveArea.Rax = EaxIn;\r
+  VmgSetOffsetValid (Ghcb, GhcbRax);\r
+  Ghcb->SaveArea.Rcx = EcxIn;\r
+  VmgSetOffsetValid (Ghcb, GhcbRcx);\r
+  if (EaxIn == CPUID_EXTENDED_STATE) {\r
+    Ghcb->SaveArea.XCr0 = XCr0;\r
+    VmgSetOffsetValid (Ghcb, GhcbXCr0);\r
+  }\r
+\r
+  *Status = VmgExit (Ghcb, SVM_EXIT_CPUID, 0, 0);\r
+  if (*Status != 0) {\r
+    return FALSE;\r
+  }\r
+\r
+  if (!VmgIsOffsetValid (Ghcb, GhcbRax) ||\r
+      !VmgIsOffsetValid (Ghcb, GhcbRbx) ||\r
+      !VmgIsOffsetValid (Ghcb, GhcbRcx) ||\r
+      !VmgIsOffsetValid (Ghcb, GhcbRdx))\r
+  {\r
+    *UnsupportedExit = TRUE;\r
+    return FALSE;\r
+  }\r
+\r
+  if (Eax) {\r
+    *Eax = (UINT32)(UINTN)Ghcb->SaveArea.Rax;\r
+  }\r
+\r
+  if (Ebx) {\r
+    *Ebx = (UINT32)(UINTN)Ghcb->SaveArea.Rbx;\r
+  }\r
+\r
+  if (Ecx) {\r
+    *Ecx = (UINT32)(UINTN)Ghcb->SaveArea.Rcx;\r
+  }\r
+\r
+  if (Edx) {\r
+    *Edx = (UINT32)(UINTN)Ghcb->SaveArea.Rdx;\r
+  }\r
+\r
+  return TRUE;\r
+}\r
+\r
+/**\r
+  Check if SEV-SNP enabled.\r
+\r
+  @retval TRUE      SEV-SNP is enabled.\r
+  @retval FALSE     SEV-SNP is disabled.\r
+\r
+**/\r
+STATIC\r
+BOOLEAN\r
+SnpEnabled (\r
+  VOID\r
+  )\r
+{\r
+  MSR_SEV_STATUS_REGISTER  Msr;\r
+\r
+  Msr.Uint32 = AsmReadMsr32 (MSR_SEV_STATUS);\r
+\r
+  return !!Msr.Bits.SevSnpBit;\r
+}\r
+\r
+/**\r
+  Calculate the total XSAVE area size for enabled XSAVE areas\r
+\r
+  @param[in]      XFeaturesEnabled  Bit-mask of enabled XSAVE features/areas as\r
+                                    indicated by XCR0/MSR_IA32_XSS bits\r
+  @param[in]      XSaveBaseSize     Base/legacy XSAVE area size (e.g. when\r
+                                    XCR0 is 1)\r
+  @param[in, out] XSaveSize         Pointer to storage for calculated XSAVE area\r
+                                    size\r
+  @param[in]      Compacted         Whether or not the calculation is for the\r
+                                    normal XSAVE area size (leaf 0xD,0x0,EBX) or\r
+                                    compacted XSAVE area size (leaf 0xD,0x1,EBX)\r
+\r
+\r
+  @retval TRUE                      XSAVE size calculation was successful.\r
+  @retval FALSE                     XSAVE size calculation was unsuccessful.\r
+**/\r
+STATIC\r
+BOOLEAN\r
+GetCpuidXSaveSize (\r
+  IN     UINT64   XFeaturesEnabled,\r
+  IN     UINT32   XSaveBaseSize,\r
+  IN OUT UINT32   *XSaveSize,\r
+  IN     BOOLEAN  Compacted\r
+  )\r
+{\r
+  SEV_SNP_CPUID_INFO  *CpuidInfo;\r
+  UINT64              XFeaturesFound = 0;\r
+  UINT32              Idx;\r
+\r
+  *XSaveSize = XSaveBaseSize;\r
+  CpuidInfo  = (SEV_SNP_CPUID_INFO *)(UINT64)PcdGet32 (PcdOvmfCpuidBase);\r
+\r
+  for (Idx = 0; Idx < CpuidInfo->Count; Idx++) {\r
+    SEV_SNP_CPUID_FUNCTION  *CpuidFn = &CpuidInfo->function[Idx];\r
+\r
+    if (!((CpuidFn->EaxIn == 0xD) &&\r
+          ((CpuidFn->EcxIn == 0) || (CpuidFn->EcxIn == 1))))\r
+    {\r
+      continue;\r
+    }\r
+\r
+    if (XFeaturesFound & (1ULL << CpuidFn->EcxIn) ||\r
+        !(XFeaturesEnabled & (1ULL << CpuidFn->EcxIn)))\r
+    {\r
+      continue;\r
+    }\r
+\r
+    XFeaturesFound |= (1ULL << CpuidFn->EcxIn);\r
+    if (Compacted) {\r
+      *XSaveSize += CpuidFn->Eax;\r
+    } else {\r
+      *XSaveSize = MAX (*XSaveSize, CpuidFn->Eax + CpuidFn->Ebx);\r
+    }\r
+  }\r
+\r
+  /*\r
+   * Either the guest set unsupported XCR0/XSS bits, or the corresponding\r
+   * entries in the CPUID table were not present. This is an invalid state.\r
+   */\r
+  if (XFeaturesFound != (XFeaturesEnabled & ~3UL)) {\r
+    return FALSE;\r
+  }\r
+\r
+  return TRUE;\r
+}\r
+\r
+/**\r
+  Check if a CPUID leaf/function is indexed via ECX sub-leaf/sub-function\r
+\r
+  @param[in]      EaxIn        EAX input for cpuid instruction\r
+\r
+  @retval FALSE                cpuid leaf/function is not indexed by ECX input\r
+  @retval TRUE                 cpuid leaf/function is indexed by ECX input\r
+\r
+**/\r
+STATIC\r
+BOOLEAN\r
+IsFunctionIndexed (\r
+  IN     UINT32  EaxIn\r
+  )\r
+{\r
+  switch (EaxIn) {\r
+    case CPUID_CACHE_PARAMS:\r
+    case CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS:\r
+    case CPUID_EXTENDED_TOPOLOGY:\r
+    case CPUID_EXTENDED_STATE:\r
+    case CPUID_INTEL_RDT_MONITORING:\r
+    case CPUID_INTEL_RDT_ALLOCATION:\r
+    case CPUID_INTEL_SGX:\r
+    case CPUID_INTEL_PROCESSOR_TRACE:\r
+    case CPUID_DETERMINISTIC_ADDRESS_TRANSLATION_PARAMETERS:\r
+    case CPUID_V2_EXTENDED_TOPOLOGY:\r
+    case 0x8000001D: /* Cache Topology Information */\r
+      return TRUE;\r
+  }\r
+\r
+  return FALSE;\r
+}\r
+\r
+/**\r
+  Fetch CPUID leaf/function via SEV-SNP CPUID table.\r
+\r
+  @param[in, out] Ghcb         Pointer to the Guest-Hypervisor Communication\r
+                               Block\r
+  @param[in]      EaxIn        EAX input for cpuid instruction\r
+  @param[in]      EcxIn        ECX input for cpuid instruction\r
+  @param[in]      Xcr0In       XCR0 at time of cpuid instruction\r
+  @param[in, out] Eax          Pointer to store leaf's EAX value\r
+  @param[in, out] Ebx          Pointer to store leaf's EBX value\r
+  @param[in, out] Ecx          Pointer to store leaf's ECX value\r
+  @param[in, out] Edx          Pointer to store leaf's EDX value\r
+  @param[in, out] Status       Pointer to store status from VMGEXIT (always 0\r
+                               unless return value indicates failure)\r
+  @param[in, out] Unsupported  Pointer to store indication of unsupported\r
+                               VMGEXIT (always false unless return value\r
+                               indicates failure)\r
+\r
+  @retval TRUE                 CPUID leaf fetch successfully.\r
+  @retval FALSE                Error occurred while fetching CPUID leaf. Callers\r
+                               should Status and Unsupported and handle\r
+                               accordingly if they indicate a more precise\r
+                               error condition.\r
+\r
+**/\r
+STATIC\r
+BOOLEAN\r
+GetCpuidFw (\r
+  IN OUT GHCB     *Ghcb,\r
+  IN     UINT32   EaxIn,\r
+  IN     UINT32   EcxIn,\r
+  IN     UINT64   XCr0,\r
+  IN OUT UINT32   *Eax,\r
+  IN OUT UINT32   *Ebx,\r
+  IN OUT UINT32   *Ecx,\r
+  IN OUT UINT32   *Edx,\r
+  IN OUT UINT64   *Status,\r
+  IN OUT BOOLEAN  *Unsupported\r
+  )\r
+{\r
+  SEV_SNP_CPUID_INFO  *CpuidInfo;\r
+  BOOLEAN             Found;\r
+  UINT32              Idx;\r
+\r
+  CpuidInfo = (SEV_SNP_CPUID_INFO *)(UINT64)PcdGet32 (PcdOvmfCpuidBase);\r
+  Found     = FALSE;\r
+\r
+  for (Idx = 0; Idx < CpuidInfo->Count; Idx++) {\r
+    SEV_SNP_CPUID_FUNCTION  *CpuidFn = &CpuidInfo->function[Idx];\r
+\r
+    if (CpuidFn->EaxIn != EaxIn) {\r
+      continue;\r
+    }\r
+\r
+    if (IsFunctionIndexed (CpuidFn->EaxIn) && (CpuidFn->EcxIn != EcxIn)) {\r
+      continue;\r
+    }\r
+\r
+    *Eax = CpuidFn->Eax;\r
+    *Ebx = CpuidFn->Ebx;\r
+    *Ecx = CpuidFn->Ecx;\r
+    *Edx = CpuidFn->Edx;\r
+\r
+    Found = TRUE;\r
+    break;\r
+  }\r
+\r
+  if (!Found) {\r
+    *Eax = *Ebx = *Ecx = *Edx = 0;\r
+    goto Out;\r
+  }\r
+\r
+  if (EaxIn == CPUID_VERSION_INFO) {\r
+    IA32_CR4  Cr4;\r
+    UINT32    Ebx2;\r
+    UINT32    Edx2;\r
+\r
+    if (!GetCpuidHyp (\r
+           Ghcb,\r
+           EaxIn,\r
+           EcxIn,\r
+           XCr0,\r
+           NULL,\r
+           &Ebx2,\r
+           NULL,\r
+           &Edx2,\r
+           Status,\r
+           Unsupported\r
+           ))\r
+    {\r
+      return FALSE;\r
+    }\r
+\r
+    /* initial APIC ID */\r
+    *Ebx = (*Ebx & 0x00FFFFFF) | (Ebx2 & 0xFF000000);\r
+    /* APIC enabled bit */\r
+    *Edx = (*Edx & ~BIT9) | (Edx2 & BIT9);\r
+    /* OSXSAVE enabled bit */\r
+    Cr4.UintN = AsmReadCr4 ();\r
+    *Ecx      = (Cr4.Bits.OSXSAVE) ? (*Ecx & ~BIT27) | (*Ecx & BIT27)\r
+                              : (*Ecx & ~BIT27);\r
+  } else if (EaxIn == CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS) {\r
+    IA32_CR4  Cr4;\r
+\r
+    Cr4.UintN = AsmReadCr4 ();\r
+    /* OSPKE enabled bit */\r
+    *Ecx = (Cr4.Bits.PKE) ? (*Ecx | BIT4) : (*Ecx & ~BIT4);\r
+  } else if (EaxIn == CPUID_EXTENDED_TOPOLOGY) {\r
+    if (!GetCpuidHyp (\r
+           Ghcb,\r
+           EaxIn,\r
+           EcxIn,\r
+           XCr0,\r
+           NULL,\r
+           NULL,\r
+           NULL,\r
+           Edx,\r
+           Status,\r
+           Unsupported\r
+           ))\r
+    {\r
+      return FALSE;\r
+    }\r
+  } else if ((EaxIn == CPUID_EXTENDED_STATE) && ((EcxIn == 0) || (EcxIn == 1))) {\r
+    MSR_IA32_XSS_REGISTER  XssMsr;\r
+    BOOLEAN                Compacted;\r
+    UINT32                 XSaveSize;\r
+\r
+    XssMsr.Uint64 = 0;\r
+    Compacted     = FALSE;\r
+    if (EcxIn == 1) {\r
+      /*\r
+       * The PPR and APM aren't clear on what size should be encoded in\r
+       * 0xD:0x1:EBX when compaction is not enabled by either XSAVEC or\r
+       * XSAVES, as these are generally fixed to 1 on real CPUs. Report\r
+       * this undefined case as an error.\r
+       */\r
+      if (!(*Eax & (BIT3 | BIT1))) {\r
+        /* (XSAVES | XSAVEC) */\r
+        return FALSE;\r
+      }\r
+\r
+      Compacted     = TRUE;\r
+      XssMsr.Uint64 = AsmReadMsr64 (MSR_IA32_XSS);\r
+    }\r
+\r
+    if (!GetCpuidXSaveSize (\r
+           XCr0 | XssMsr.Uint64,\r
+           *Ebx,\r
+           &XSaveSize,\r
+           Compacted\r
+           ))\r
+    {\r
+      return FALSE;\r
+    }\r
+\r
+    *Ebx = XSaveSize;\r
+  } else if (EaxIn == 0x8000001E) {\r
+    UINT32  Ebx2;\r
+    UINT32  Ecx2;\r
+\r
+    /* extended APIC ID */\r
+    if (!GetCpuidHyp (\r
+           Ghcb,\r
+           EaxIn,\r
+           EcxIn,\r
+           XCr0,\r
+           Eax,\r
+           &Ebx2,\r
+           &Ecx2,\r
+           NULL,\r
+           Status,\r
+           Unsupported\r
+           ))\r
+    {\r
+      return FALSE;\r
+    }\r
+\r
+    /* compute ID */\r
+    *Ebx = (*Ebx & 0xFFFFFF00) | (Ebx2 & 0x000000FF);\r
+    /* node ID */\r
+    *Ecx = (*Ecx & 0xFFFFFF00) | (Ecx2 & 0x000000FF);\r
+  }\r
+\r
+Out:\r
+  *Status      = 0;\r
+  *Unsupported = FALSE;\r
+  return TRUE;\r
+}\r
+\r
+/**\r
+  Handle a CPUID event.\r
+\r
+  Use VMGEXIT instruction or CPUID table to handle a CPUID event.\r
+\r
+  @param[in, out] Ghcb             Pointer to the Guest-Hypervisor Communication\r
+                                   Block\r
+  @param[in, out] Regs             x64 processor context\r
+  @param[in]      InstructionData  Instruction parsing context\r
+\r
+  @retval 0                        Event handled successfully\r
+  @return                          New exception value to propagate\r
+\r
+**/\r
+STATIC\r
+UINT64\r
+CpuidExit (\r
+  IN OUT GHCB                     *Ghcb,\r
+  IN OUT EFI_SYSTEM_CONTEXT_X64   *Regs,\r
+  IN     SEV_ES_INSTRUCTION_DATA  *InstructionData\r
+  )\r
+{\r
+  BOOLEAN  Unsupported;\r
+  UINT64   Status;\r
+  UINT32   EaxIn;\r
+  UINT32   EcxIn;\r
+  UINT64   XCr0;\r
+  UINT32   Eax;\r
+  UINT32   Ebx;\r
+  UINT32   Ecx;\r
+  UINT32   Edx;\r
+\r
+  EaxIn = (UINT32)(UINTN)Regs->Rax;\r
+  EcxIn = (UINT32)(UINTN)Regs->Rcx;\r
+\r
+  if (EaxIn == CPUID_EXTENDED_STATE) {\r
+    IA32_CR4  Cr4;\r
+\r
+    Cr4.UintN           = AsmReadCr4 ();\r
+    Ghcb->SaveArea.XCr0 = (Cr4.Bits.OSXSAVE == 1) ? AsmXGetBv (0) : 1;\r
+    XCr0                = (Cr4.Bits.OSXSAVE == 1) ? AsmXGetBv (0) : 1;\r
+  }\r
+\r
+  if (SnpEnabled ()) {\r
+    if (!GetCpuidFw (\r
+           Ghcb,\r
+           EaxIn,\r
+           EcxIn,\r
+           XCr0,\r
+           &Eax,\r
+           &Ebx,\r
+           &Ecx,\r
+           &Edx,\r
+           &Status,\r
+           &Unsupported\r
+           ))\r
+    {\r
+      goto CpuidFail;\r
+    }\r
+  } else {\r
+    if (!GetCpuidHyp (\r
+           Ghcb,\r
+           EaxIn,\r
+           EcxIn,\r
+           XCr0,\r
+           &Eax,\r
+           &Ebx,\r
+           &Ecx,\r
+           &Edx,\r
+           &Status,\r
+           &Unsupported\r
+           ))\r
+    {\r
+      goto CpuidFail;\r
+    }\r
+  }\r
+\r
+  Regs->Rax = Eax;\r
+  Regs->Rbx = Ebx;\r
+  Regs->Rcx = Ecx;\r
+  Regs->Rdx = Edx;\r
+\r
+  return 0;\r
+\r
+CpuidFail:\r
+  if (Unsupported) {\r
+    return UnsupportedExit (Ghcb, Regs, InstructionData);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Handle a RDPMC event.\r
+\r
+  Use the VMGEXIT instruction to handle a RDPMC event.\r
+\r
+  @param[in, out] Ghcb             Pointer to the Guest-Hypervisor Communication\r
+                                   Block\r
+  @param[in, out] Regs             x64 processor context\r
+  @param[in]      InstructionData  Instruction parsing context\r
+\r
+  @retval 0                        Event handled successfully\r
+  @return                          New exception value to propagate\r
+\r
+**/\r
+STATIC\r
+UINT64\r
+RdpmcExit (\r
+  IN OUT GHCB                     *Ghcb,\r
+  IN OUT EFI_SYSTEM_CONTEXT_X64   *Regs,\r
+  IN     SEV_ES_INSTRUCTION_DATA  *InstructionData\r
+  )\r
+{\r
+  UINT64  Status;\r
+\r
+  Ghcb->SaveArea.Rcx = Regs->Rcx;\r
+  VmgSetOffsetValid (Ghcb, GhcbRcx);\r
+\r
+  Status = VmgExit (Ghcb, SVM_EXIT_RDPMC, 0, 0);\r
+  if (Status != 0) {\r
+    return Status;\r
+  }\r
+\r
+  if (!VmgIsOffsetValid (Ghcb, GhcbRax) ||\r
+      !VmgIsOffsetValid (Ghcb, GhcbRdx))\r
+  {\r
+    return UnsupportedExit (Ghcb, Regs, InstructionData);\r
+  }\r
+\r
+  Regs->Rax = Ghcb->SaveArea.Rax;\r
+  Regs->Rdx = Ghcb->SaveArea.Rdx;\r
+\r
+  return 0;\r
+}\r
+\r
+/**\r
+  Handle a RDTSC event.\r
+\r
+  Use the VMGEXIT instruction to handle a RDTSC event.\r
+\r
+  @param[in, out] Ghcb             Pointer to the Guest-Hypervisor Communication\r
+                                   Block\r
+  @param[in, out] Regs             x64 processor context\r
+  @param[in]      InstructionData  Instruction parsing context\r
+\r
+  @retval 0                        Event handled successfully\r
+  @return                          New exception value to propagate\r
+\r
+**/\r
+STATIC\r
+UINT64\r
+RdtscExit (\r
+  IN OUT GHCB                     *Ghcb,\r
+  IN OUT EFI_SYSTEM_CONTEXT_X64   *Regs,\r
+  IN     SEV_ES_INSTRUCTION_DATA  *InstructionData\r
+  )\r
+{\r
+  UINT64  Status;\r
+\r
+  Status = VmgExit (Ghcb, SVM_EXIT_RDTSC, 0, 0);\r
+  if (Status != 0) {\r
+    return Status;\r
+  }\r
+\r
+  if (!VmgIsOffsetValid (Ghcb, GhcbRax) ||\r
+      !VmgIsOffsetValid (Ghcb, GhcbRdx))\r
+  {\r
+    return UnsupportedExit (Ghcb, Regs, InstructionData);\r
+  }\r
+\r
+  Regs->Rax = Ghcb->SaveArea.Rax;\r
+  Regs->Rdx = Ghcb->SaveArea.Rdx;\r
+\r
+  return 0;\r
+}\r
+\r
+/**\r
+  Handle a DR7 register write event.\r
+\r
+  Use the VMGEXIT instruction to handle a DR7 write event.\r
+\r
+  @param[in, out] Ghcb             Pointer to the Guest-Hypervisor Communication\r
+                                   Block\r
+  @param[in, out] Regs             x64 processor context\r
+  @param[in]      InstructionData  Instruction parsing context\r
+\r
+  @retval 0                        Event handled successfully\r
+  @return                          New exception value to propagate\r
+\r
+**/\r
+STATIC\r
+UINT64\r
+Dr7WriteExit (\r
+  IN OUT GHCB                     *Ghcb,\r
+  IN OUT EFI_SYSTEM_CONTEXT_X64   *Regs,\r
+  IN     SEV_ES_INSTRUCTION_DATA  *InstructionData\r
+  )\r
+{\r
+  SEV_ES_INSTRUCTION_OPCODE_EXT  *Ext;\r
+  SEV_ES_PER_CPU_DATA            *SevEsData;\r
+  UINT64                         *Register;\r
+  UINT64                         Status;\r
+\r
+  Ext       = &InstructionData->Ext;\r
+  SevEsData = (SEV_ES_PER_CPU_DATA *)(Ghcb + 1);\r
+\r
+  DecodeModRm (Regs, InstructionData);\r
+\r
+  //\r
+  // MOV DRn always treats MOD == 3 no matter how encoded\r
+  //\r
+  Register = GetRegisterPointer (Regs, Ext->ModRm.Rm);\r
+\r
+  //\r
+  // Using a value of 0 for ExitInfo1 means RAX holds the value\r
+  //\r
+  Ghcb->SaveArea.Rax = *Register;\r
+  VmgSetOffsetValid (Ghcb, GhcbRax);\r
+\r
+  Status = VmgExit (Ghcb, SVM_EXIT_DR7_WRITE, 0, 0);\r
+  if (Status != 0) {\r
+    return Status;\r
+  }\r
+\r
+  SevEsData->Dr7       = *Register;\r
+  SevEsData->Dr7Cached = 1;\r
+\r
+  return 0;\r
+}\r
+\r
+/**\r
+  Handle a DR7 register read event.\r
+\r
+  Use the VMGEXIT instruction to handle a DR7 read event.\r
+\r
+  @param[in, out] Ghcb             Pointer to the Guest-Hypervisor Communication\r
+                                   Block\r
+  @param[in, out] Regs             x64 processor context\r
+  @param[in]      InstructionData  Instruction parsing context\r
+\r
+  @retval 0                        Event handled successfully\r
+\r
+**/\r
+STATIC\r
+UINT64\r
+Dr7ReadExit (\r
+  IN OUT GHCB                     *Ghcb,\r
+  IN OUT EFI_SYSTEM_CONTEXT_X64   *Regs,\r
+  IN     SEV_ES_INSTRUCTION_DATA  *InstructionData\r
+  )\r
+{\r
+  SEV_ES_INSTRUCTION_OPCODE_EXT  *Ext;\r
+  SEV_ES_PER_CPU_DATA            *SevEsData;\r
+  UINT64                         *Register;\r
+\r
+  Ext       = &InstructionData->Ext;\r
+  SevEsData = (SEV_ES_PER_CPU_DATA *)(Ghcb + 1);\r
+\r
+  DecodeModRm (Regs, InstructionData);\r
+\r
+  //\r
+  // MOV DRn always treats MOD == 3 no matter how encoded\r
+  //\r
+  Register = GetRegisterPointer (Regs, Ext->ModRm.Rm);\r
+\r
+  //\r
+  // If there is a cached valued for DR7, return that. Otherwise return the\r
+  // DR7 standard reset value of 0x400 (no debug breakpoints set).\r
+  //\r
+  *Register = (SevEsData->Dr7Cached == 1) ? SevEsData->Dr7 : 0x400;\r
+\r
+  return 0;\r
+}\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
+  EFI_SYSTEM_CONTEXT_X64   *Regs;\r
+  NAE_EXIT                 NaeExit;\r
+  SEV_ES_INSTRUCTION_DATA  InstructionData;\r
+  UINT64                   ExitCode, Status;\r
+  EFI_STATUS               VcRet;\r
+  BOOLEAN                  InterruptState;\r
+\r
+  VcRet = EFI_SUCCESS;\r
+\r
+  Regs = SystemContext.SystemContextX64;\r
+\r
+  VmgInit (Ghcb, &InterruptState);\r
+\r
+  ExitCode = Regs->ExceptionData;\r
+  switch (ExitCode) {\r
+    case SVM_EXIT_DR7_READ:\r
+      NaeExit = Dr7ReadExit;\r
+      break;\r
+\r
+    case SVM_EXIT_DR7_WRITE:\r
+      NaeExit = Dr7WriteExit;\r
+      break;\r
+\r
+    case SVM_EXIT_RDTSC:\r
+      NaeExit = RdtscExit;\r
+      break;\r
+\r
+    case SVM_EXIT_RDPMC:\r
+      NaeExit = RdpmcExit;\r
+      break;\r
+\r
+    case SVM_EXIT_CPUID:\r
+      NaeExit = CpuidExit;\r
+      break;\r
+\r
+    case SVM_EXIT_INVD:\r
+      NaeExit = InvdExit;\r
+      break;\r
+\r
+    case SVM_EXIT_IOIO_PROT:\r
+      NaeExit = IoioExit;\r
+      break;\r
+\r
+    case SVM_EXIT_MSR:\r
+      NaeExit = MsrExit;\r
+      break;\r
+\r
+    case SVM_EXIT_VMMCALL:\r
+      NaeExit = VmmCallExit;\r
+      break;\r
+\r
+    case SVM_EXIT_RDTSCP:\r
+      NaeExit = RdtscpExit;\r
+      break;\r
+\r
+    case SVM_EXIT_WBINVD:\r
+      NaeExit = WbinvdExit;\r
+      break;\r
+\r
+    case SVM_EXIT_MONITOR:\r
+      NaeExit = MonitorExit;\r
+      break;\r
+\r
+    case SVM_EXIT_MWAIT:\r
+      NaeExit = MwaitExit;\r
+      break;\r
+\r
+    case SVM_EXIT_NPF:\r
+      NaeExit = MmioExit;\r
+      break;\r
+\r
+    default:\r
+      NaeExit = UnsupportedExit;\r
+  }\r
+\r
+  InitInstructionData (&InstructionData, Ghcb, Regs);\r
+\r
+  Status = NaeExit (Ghcb, Regs, &InstructionData);\r
+  if (Status == 0) {\r
+    Regs->Rip += InstructionLength (&InstructionData);\r
+  } else {\r
+    GHCB_EVENT_INJECTION  Event;\r
+\r
+    Event.Uint64 = Status;\r
+    if (Event.Elements.ErrorCodeValid != 0) {\r
+      Regs->ExceptionData = Event.Elements.ErrorCode;\r
+    } else {\r
+      Regs->ExceptionData = 0;\r
+    }\r
+\r
+    *ExceptionType = Event.Elements.Vector;\r
+\r
+    VcRet = EFI_PROTOCOL_ERROR;\r
+  }\r
+\r
+  VmgDone (Ghcb, InterruptState);\r
+\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/CcExitLib/CcExitVcHandler.h b/OvmfPkg/Library/CcExitLib/CcExitVcHandler.h
new file mode 100644 (file)
index 0000000..464591f
--- /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 CC_EXIT_VC_HANDLER_H_\r
+#define CC_EXIT_VC_HANDLER_H_\r
+\r
+#include <Base.h>\r
+#include <Uefi.h>\r
+#include <Library/CcExitLib.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
diff --git a/OvmfPkg/Library/CcExitLib/CcExitVeHandler.c b/OvmfPkg/Library/CcExitLib/CcExitVeHandler.c
new file mode 100644 (file)
index 0000000..08e92c6
--- /dev/null
@@ -0,0 +1,577 @@
+/** @file\r
+\r
+  Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>\r
+\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#include <Library/BaseLib.h>\r
+#include <Library/DebugLib.h>\r
+#include "CcExitTd.h"\r
+#include <Library/CcExitLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <IndustryStandard/Tdx.h>\r
+#include <IndustryStandard/InstructionParsing.h>\r
+\r
+typedef union {\r
+  struct {\r
+    UINT32    Eax;\r
+    UINT32    Edx;\r
+  } Regs;\r
+  UINT64    Val;\r
+} MSR_DATA;\r
+\r
+typedef union {\r
+  UINT8    Val;\r
+  struct {\r
+    UINT8    B : 1;\r
+    UINT8    X : 1;\r
+    UINT8    R : 1;\r
+    UINT8    W : 1;\r
+  } Bits;\r
+} REX;\r
+\r
+typedef union {\r
+  UINT8    Val;\r
+  struct {\r
+    UINT8    Rm  : 3;\r
+    UINT8    Reg : 3;\r
+    UINT8    Mod : 2;\r
+  } Bits;\r
+} MODRM;\r
+\r
+typedef struct {\r
+  UINT64    Regs[4];\r
+} CPUID_DATA;\r
+\r
+/**\r
+  Handle an CPUID event.\r
+\r
+  Use the TDVMCALL instruction to handle cpuid #ve\r
+\r
+  @param[in, out] Regs             x64 processor context\r
+  @param[in]      Veinfo           VE Info\r
+\r
+  @retval 0                        Event handled successfully\r
+  @return                          New exception value to propagate\r
+**/\r
+STATIC\r
+UINT64\r
+EFIAPI\r
+CpuIdExit (\r
+  IN EFI_SYSTEM_CONTEXT_X64     *Regs,\r
+  IN TDCALL_VEINFO_RETURN_DATA  *Veinfo\r
+  )\r
+{\r
+  CPUID_DATA  CpuIdData;\r
+  UINT64      Status;\r
+\r
+  Status = TdVmCallCpuid (Regs->Rax, Regs->Rcx, &CpuIdData);\r
+\r
+  if (Status == 0) {\r
+    Regs->Rax = CpuIdData.Regs[0];\r
+    Regs->Rbx = CpuIdData.Regs[1];\r
+    Regs->Rcx = CpuIdData.Regs[2];\r
+    Regs->Rdx = CpuIdData.Regs[3];\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Handle an IO event.\r
+\r
+  Use the TDVMCALL instruction to handle either an IO read or an IO write.\r
+\r
+  @param[in, out] Regs             x64 processor context\r
+  @param[in]      Veinfo           VE Info\r
+\r
+  @retval 0                        Event handled successfully\r
+  @return                          New exception value to propagate\r
+**/\r
+STATIC\r
+UINT64\r
+EFIAPI\r
+IoExit (\r
+  IN OUT EFI_SYSTEM_CONTEXT_X64  *Regs,\r
+  IN TDCALL_VEINFO_RETURN_DATA   *Veinfo\r
+  )\r
+{\r
+  BOOLEAN  Write;\r
+  UINTN    Size;\r
+  UINTN    Port;\r
+  UINT64   Val;\r
+  UINT64   RepCnt;\r
+  UINT64   Status;\r
+\r
+  Val   = 0;\r
+  Write = Veinfo->ExitQualification.Io.Direction ? FALSE : TRUE;\r
+  Size  = Veinfo->ExitQualification.Io.Size + 1;\r
+  Port  = Veinfo->ExitQualification.Io.Port;\r
+\r
+  if (Veinfo->ExitQualification.Io.String) {\r
+    //\r
+    // If REP is set, get rep-cnt from Rcx\r
+    //\r
+    RepCnt = Veinfo->ExitQualification.Io.Rep ? Regs->Rcx : 1;\r
+\r
+    while (RepCnt) {\r
+      Val = 0;\r
+      if (Write == TRUE) {\r
+        CopyMem (&Val, (VOID *)Regs->Rsi, Size);\r
+        Regs->Rsi += Size;\r
+      }\r
+\r
+      Status = TdVmCall (EXIT_REASON_IO_INSTRUCTION, Size, Write, Port, Val, (Write ? NULL : &Val));\r
+      if (Status != 0) {\r
+        break;\r
+      }\r
+\r
+      if (Write == FALSE) {\r
+        CopyMem ((VOID *)Regs->Rdi, &Val, Size);\r
+        Regs->Rdi += Size;\r
+      }\r
+\r
+      if (Veinfo->ExitQualification.Io.Rep) {\r
+        Regs->Rcx -= 1;\r
+      }\r
+\r
+      RepCnt -= 1;\r
+    }\r
+  } else {\r
+    if (Write == TRUE) {\r
+      CopyMem (&Val, (VOID *)&Regs->Rax, Size);\r
+    }\r
+\r
+    Status = TdVmCall (EXIT_REASON_IO_INSTRUCTION, Size, Write, Port, Val, (Write ? NULL : &Val));\r
+    if ((Status == 0) && (Write == FALSE)) {\r
+      CopyMem ((VOID *)&Regs->Rax, &Val, Size);\r
+    }\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Handle an READ MSR event.\r
+\r
+  Use the TDVMCALL instruction to handle msr read\r
+\r
+  @param[in, out] Regs             x64 processor context\r
+  @param[in]      Veinfo           VE Info\r
+\r
+  @retval 0                        Event handled successfully\r
+  @return                          New exception value to propagate\r
+**/\r
+STATIC\r
+UINT64\r
+ReadMsrExit (\r
+  IN OUT EFI_SYSTEM_CONTEXT_X64  *Regs,\r
+  IN TDCALL_VEINFO_RETURN_DATA   *Veinfo\r
+  )\r
+{\r
+  MSR_DATA  Data;\r
+  UINT64    Status;\r
+\r
+  Status = TdVmCall (EXIT_REASON_MSR_READ, Regs->Rcx, 0, 0, 0, &Data);\r
+  if (Status == 0) {\r
+    Regs->Rax = Data.Regs.Eax;\r
+    Regs->Rdx = Data.Regs.Edx;\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Handle an WRITE MSR event.\r
+\r
+  Use the TDVMCALL instruction to handle msr write\r
+\r
+  @param[in, out] Regs             x64 processor context\r
+  @param[in]      Veinfo           VE Info\r
+\r
+  @retval 0                        Event handled successfully\r
+  @return                          New exception value to propagate\r
+**/\r
+STATIC\r
+UINT64\r
+WriteMsrExit (\r
+  IN OUT EFI_SYSTEM_CONTEXT_X64  *Regs,\r
+  IN TDCALL_VEINFO_RETURN_DATA   *Veinfo\r
+  )\r
+{\r
+  UINT64    Status;\r
+  MSR_DATA  Data;\r
+\r
+  Data.Regs.Eax = (UINT32)Regs->Rax;\r
+  Data.Regs.Edx = (UINT32)Regs->Rdx;\r
+\r
+  Status =  TdVmCall (EXIT_REASON_MSR_WRITE, Regs->Rcx, Data.Val, 0, 0, NULL);\r
+\r
+  return Status;\r
+}\r
+\r
+STATIC\r
+VOID\r
+EFIAPI\r
+TdxDecodeInstruction (\r
+  IN UINT8  *Rip\r
+  )\r
+{\r
+  UINTN  i;\r
+\r
+  DEBUG ((DEBUG_INFO, "TDX: #TD[EPT] instruction (%p):", Rip));\r
+  for (i = 0; i < 15; i++) {\r
+    DEBUG ((DEBUG_INFO, "%02x:", Rip[i]));\r
+  }\r
+\r
+  DEBUG ((DEBUG_INFO, "\n"));\r
+}\r
+\r
+#define TDX_DECODER_BUG_ON(x)               \\r
+  if ((x)) {                                \\r
+    TdxDecodeInstruction(Rip);              \\r
+    TdVmCall(TDVMCALL_HALT, 0, 0, 0, 0, 0); \\r
+  }\r
+\r
+STATIC\r
+UINT64 *\r
+EFIAPI\r
+GetRegFromContext (\r
+  IN EFI_SYSTEM_CONTEXT_X64  *Regs,\r
+  IN UINTN                   RegIndex\r
+  )\r
+{\r
+  switch (RegIndex) {\r
+    case 0: return &Regs->Rax;\r
+      break;\r
+    case 1: return &Regs->Rcx;\r
+      break;\r
+    case 2: return &Regs->Rdx;\r
+      break;\r
+    case 3: return &Regs->Rbx;\r
+      break;\r
+    case 4: return &Regs->Rsp;\r
+      break;\r
+    case 5: return &Regs->Rbp;\r
+      break;\r
+    case 6: return &Regs->Rsi;\r
+      break;\r
+    case 7: return &Regs->Rdi;\r
+      break;\r
+    case 8: return &Regs->R8;\r
+      break;\r
+    case 9: return &Regs->R9;\r
+      break;\r
+    case 10: return &Regs->R10;\r
+      break;\r
+    case 11: return &Regs->R11;\r
+      break;\r
+    case 12: return &Regs->R12;\r
+      break;\r
+    case 13: return &Regs->R13;\r
+      break;\r
+    case 14: return &Regs->R14;\r
+      break;\r
+    case 15: return &Regs->R15;\r
+      break;\r
+  }\r
+\r
+  return NULL;\r
+}\r
+\r
+/**\r
+  Handle an MMIO event.\r
+\r
+  Use the TDVMCALL instruction to handle either an mmio read or an mmio write.\r
+\r
+  @param[in, out] Regs             x64 processor context\r
+  @param[in]      Veinfo           VE Info\r
+\r
+  @retval 0                        Event handled successfully\r
+  @return                          New exception value to propagate\r
+**/\r
+STATIC\r
+INTN\r
+EFIAPI\r
+MmioExit (\r
+  IN OUT EFI_SYSTEM_CONTEXT_X64  *Regs,\r
+  IN TDCALL_VEINFO_RETURN_DATA   *Veinfo\r
+  )\r
+{\r
+  UINT64          Status;\r
+  UINT32          MmioSize;\r
+  UINT32          RegSize;\r
+  UINT8           OpCode;\r
+  BOOLEAN         SeenRex;\r
+  UINT64          *Reg;\r
+  UINT8           *Rip;\r
+  UINT64          Val;\r
+  UINT32          OpSize;\r
+  MODRM           ModRm;\r
+  REX             Rex;\r
+  TD_RETURN_DATA  TdReturnData;\r
+  UINT8           Gpaw;\r
+  UINT64          TdSharedPageMask;\r
+\r
+  Rip     = (UINT8 *)Regs->Rip;\r
+  Val     = 0;\r
+  Rex.Val = 0;\r
+  SeenRex = FALSE;\r
+\r
+  Status = TdCall (TDCALL_TDINFO, 0, 0, 0, &TdReturnData);\r
+  if (Status == TDX_EXIT_REASON_SUCCESS) {\r
+    Gpaw             = (UINT8)(TdReturnData.TdInfo.Gpaw & 0x3f);\r
+    TdSharedPageMask = 1ULL << (Gpaw - 1);\r
+  } else {\r
+    DEBUG ((DEBUG_ERROR, "TDCALL failed with status=%llx\n", Status));\r
+    return Status;\r
+  }\r
+\r
+  if ((Veinfo->GuestPA & TdSharedPageMask) == 0) {\r
+    DEBUG ((DEBUG_ERROR, "EPT-violation #VE on private memory is not allowed!"));\r
+    TdVmCall (TDVMCALL_HALT, 0, 0, 0, 0, 0);\r
+    CpuDeadLoop ();\r
+  }\r
+\r
+  //\r
+  // Default to 32bit transfer\r
+  //\r
+  OpSize = 4;\r
+\r
+  do {\r
+    OpCode = *Rip++;\r
+    if (OpCode == 0x66) {\r
+      OpSize = 2;\r
+    } else if ((OpCode == 0x64) || (OpCode == 0x65) || (OpCode == 0x67)) {\r
+      continue;\r
+    } else if ((OpCode >= 0x40) && (OpCode <= 0x4f)) {\r
+      SeenRex = TRUE;\r
+      Rex.Val = OpCode;\r
+    } else {\r
+      break;\r
+    }\r
+  } while (TRUE);\r
+\r
+  //\r
+  // We need to have at least 2 more bytes for this instruction\r
+  //\r
+  TDX_DECODER_BUG_ON (((UINT64)Rip - Regs->Rip) > 13);\r
+\r
+  OpCode = *Rip++;\r
+  //\r
+  // Two-byte opecode, get next byte\r
+  //\r
+  if (OpCode == 0x0F) {\r
+    OpCode = *Rip++;\r
+  }\r
+\r
+  switch (OpCode) {\r
+    case 0x88:\r
+    case 0x8A:\r
+    case 0xB6:\r
+      MmioSize = 1;\r
+      break;\r
+    case 0xB7:\r
+      MmioSize = 2;\r
+      break;\r
+    default:\r
+      MmioSize = Rex.Bits.W ? 8 : OpSize;\r
+      break;\r
+  }\r
+\r
+  /* Punt on AH/BH/CH/DH unless it shows up. */\r
+  ModRm.Val = *Rip++;\r
+  TDX_DECODER_BUG_ON (MmioSize == 1 && ModRm.Bits.Reg > 4 && !SeenRex && OpCode != 0xB6);\r
+  Reg = GetRegFromContext (Regs, ModRm.Bits.Reg | ((int)Rex.Bits.R << 3));\r
+  TDX_DECODER_BUG_ON (!Reg);\r
+\r
+  if (ModRm.Bits.Rm == 4) {\r
+    ++Rip; /* SIB byte */\r
+  }\r
+\r
+  if ((ModRm.Bits.Mod == 2) || ((ModRm.Bits.Mod == 0) && (ModRm.Bits.Rm == 5))) {\r
+    Rip += 4; /* DISP32 */\r
+  } else if (ModRm.Bits.Mod == 1) {\r
+    ++Rip;  /* DISP8 */\r
+  }\r
+\r
+  switch (OpCode) {\r
+    case 0x88:\r
+    case 0x89:\r
+      CopyMem ((void *)&Val, Reg, MmioSize);\r
+      Status = TdVmCall (TDVMCALL_MMIO, MmioSize, 1, Veinfo->GuestPA, Val, 0);\r
+      break;\r
+    case 0xC7:\r
+      CopyMem ((void *)&Val, Rip, OpSize);\r
+      Status = TdVmCall (TDVMCALL_MMIO, MmioSize, 1, Veinfo->GuestPA, Val, 0);\r
+      Rip   += OpSize;\r
+    default:\r
+      //\r
+      // 32-bit write registers are zero extended to the full register\r
+      // Hence 'MOVZX r[32/64], r/m16' is\r
+      // hardcoded to reg size 8, and the straight MOV case has a reg\r
+      // size of 8 in the 32-bit read case.\r
+      //\r
+      switch (OpCode) {\r
+        case 0xB6:\r
+          RegSize = Rex.Bits.W ? 8 : OpSize;\r
+          break;\r
+        case 0xB7:\r
+          RegSize =  8;\r
+          break;\r
+        default:\r
+          RegSize = MmioSize == 4 ? 8 : MmioSize;\r
+          break;\r
+      }\r
+\r
+      Status = TdVmCall (TDVMCALL_MMIO, MmioSize, 0, Veinfo->GuestPA, 0, &Val);\r
+      if (Status == 0) {\r
+        ZeroMem (Reg, RegSize);\r
+        CopyMem (Reg, (void *)&Val, MmioSize);\r
+      }\r
+  }\r
+\r
+  if (Status == 0) {\r
+    TDX_DECODER_BUG_ON (((UINT64)Rip - Regs->Rip) > 15);\r
+\r
+    //\r
+    // We change instruction length to reflect true size so handler can\r
+    // bump rip\r
+    //\r
+    Veinfo->ExitInstructionLength =  (UINT32)((UINT64)Rip - Regs->Rip);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Handle a #VE exception.\r
+\r
+  Performs the necessary processing to handle a #VE 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        #VE not supported, (new) exception value to\r
+                                  propagate provided\r
+  @retval  EFI_PROTOCOL_ERROR     #VE handling failed, (new) exception value to\r
+                                  propagate provided\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+VmTdExitHandleVe (\r
+  IN OUT EFI_EXCEPTION_TYPE  *ExceptionType,\r
+  IN OUT EFI_SYSTEM_CONTEXT  SystemContext\r
+  )\r
+{\r
+  UINT64                  Status;\r
+  TD_RETURN_DATA          ReturnData;\r
+  EFI_SYSTEM_CONTEXT_X64  *Regs;\r
+\r
+  Regs   = SystemContext.SystemContextX64;\r
+  Status = TdCall (TDCALL_TDGETVEINFO, 0, 0, 0, &ReturnData);\r
+  ASSERT (Status == 0);\r
+  if (Status != 0) {\r
+    DEBUG ((DEBUG_ERROR, "#VE happened. TDGETVEINFO failed with Status = 0x%llx\n", Status));\r
+    TdVmCall (TDVMCALL_HALT, 0, 0, 0, 0, 0);\r
+  }\r
+\r
+  switch (ReturnData.VeInfo.ExitReason) {\r
+    case EXIT_REASON_CPUID:\r
+      Status = CpuIdExit (Regs, &ReturnData.VeInfo);\r
+      DEBUG ((\r
+        DEBUG_VERBOSE,\r
+        "CPUID #VE happened, ExitReasion is %d, ExitQualification = 0x%x.\n",\r
+        ReturnData.VeInfo.ExitReason,\r
+        ReturnData.VeInfo.ExitQualification.Val\r
+        ));\r
+      break;\r
+\r
+    case EXIT_REASON_HLT:\r
+      Status = TdVmCall (EXIT_REASON_HLT, 0, 0, 0, 0, 0);\r
+      break;\r
+\r
+    case EXIT_REASON_IO_INSTRUCTION:\r
+      Status = IoExit (Regs, &ReturnData.VeInfo);\r
+      DEBUG ((\r
+        DEBUG_VERBOSE,\r
+        "IO_Instruction #VE happened, ExitReasion is %d, ExitQualification = 0x%x.\n",\r
+        ReturnData.VeInfo.ExitReason,\r
+        ReturnData.VeInfo.ExitQualification.Val\r
+        ));\r
+      break;\r
+\r
+    case EXIT_REASON_MSR_READ:\r
+      Status = ReadMsrExit (Regs, &ReturnData.VeInfo);\r
+      DEBUG ((\r
+        DEBUG_VERBOSE,\r
+        "RDMSR #VE happened, ExitReasion is %d, ExitQualification = 0x%x. Regs->Rcx=0x%llx, Status = 0x%llx\n",\r
+        ReturnData.VeInfo.ExitReason,\r
+        ReturnData.VeInfo.ExitQualification.Val,\r
+        Regs->Rcx,\r
+        Status\r
+        ));\r
+      break;\r
+\r
+    case EXIT_REASON_MSR_WRITE:\r
+      Status = WriteMsrExit (Regs, &ReturnData.VeInfo);\r
+      DEBUG ((\r
+        DEBUG_VERBOSE,\r
+        "WRMSR #VE happened, ExitReasion is %d, ExitQualification = 0x%x. Regs->Rcx=0x%llx, Status = 0x%llx\n",\r
+        ReturnData.VeInfo.ExitReason,\r
+        ReturnData.VeInfo.ExitQualification.Val,\r
+        Regs->Rcx,\r
+        Status\r
+        ));\r
+      break;\r
+\r
+    case EXIT_REASON_EPT_VIOLATION:\r
+      Status = MmioExit (Regs, &ReturnData.VeInfo);\r
+      DEBUG ((\r
+        DEBUG_VERBOSE,\r
+        "MMIO #VE happened, ExitReasion is %d, ExitQualification = 0x%x.\n",\r
+        ReturnData.VeInfo.ExitReason,\r
+        ReturnData.VeInfo.ExitQualification.Val\r
+        ));\r
+      break;\r
+\r
+    case EXIT_REASON_VMCALL:\r
+    case EXIT_REASON_MWAIT_INSTRUCTION:\r
+    case EXIT_REASON_MONITOR_INSTRUCTION:\r
+    case EXIT_REASON_WBINVD:\r
+    case EXIT_REASON_RDPMC:\r
+      /* Handle as nops. */\r
+      break;\r
+\r
+    default:\r
+      DEBUG ((\r
+        DEBUG_ERROR,\r
+        "Unsupported #VE happened, ExitReason is %d, ExitQualification = 0x%x.\n",\r
+        ReturnData.VeInfo.ExitReason,\r
+        ReturnData.VeInfo.ExitQualification.Val\r
+        ));\r
+\r
+      ASSERT (FALSE);\r
+      CpuDeadLoop ();\r
+  }\r
+\r
+  if (Status) {\r
+    DEBUG ((\r
+      DEBUG_ERROR,\r
+      "#VE Error (0x%llx) returned from host, ExitReason is %d, ExitQualification = 0x%x.\n",\r
+      Status,\r
+      ReturnData.VeInfo.ExitReason,\r
+      ReturnData.VeInfo.ExitQualification.Val\r
+      ));\r
+\r
+    TdVmCall (TDVMCALL_HALT, 0, 0, 0, 0, 0);\r
+  }\r
+\r
+  SystemContext.SystemContextX64->Rip += ReturnData.VeInfo.ExitInstructionLength;\r
+  return EFI_SUCCESS;\r
+}\r
diff --git a/OvmfPkg/Library/CcExitLib/PeiDxeCcExitVcHandler.c b/OvmfPkg/Library/CcExitLib/PeiDxeCcExitVcHandler.c
new file mode 100644 (file)
index 0000000..bb71816
--- /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/CcExitLib.h>\r
+#include <Register/Amd/Msr.h>\r
+\r
+#include "CcExitVcHandler.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/CcExitLib/SecCcExitLib.inf b/OvmfPkg/Library/CcExitLib/SecCcExitLib.inf
new file mode 100644 (file)
index 0000000..1ee22ce
--- /dev/null
@@ -0,0 +1,48 @@
+## @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                      = SecCcExitLib\r
+  FILE_GUID                      = dafff819-f86c-4cff-a70e-83161e5bcf9a\r
+  MODULE_TYPE                    = BASE\r
+  VERSION_STRING                 = 1.0\r
+  LIBRARY_CLASS                  = CcExitLib|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
+  CcExitLib.c\r
+  CcExitVcHandler.c\r
+  CcExitVcHandler.h\r
+  SecCcExitVcHandler.c\r
+  CcExitVeHandler.c\r
+  X64/TdVmcallCpuid.nasm\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
+  LocalApicLib\r
+  MemEncryptSevLib\r
+  PcdLib\r
+\r
+[FixedPcd]\r
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupBase\r
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupSize\r
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCpuidBase\r
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCpuidSize\r
diff --git a/OvmfPkg/Library/CcExitLib/SecCcExitVcHandler.c b/OvmfPkg/Library/CcExitLib/SecCcExitVcHandler.c
new file mode 100644 (file)
index 0000000..769e0b5
--- /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/CcExitLib.h>\r
+#include <Register/Amd/Msr.h>\r
+\r
+#include "CcExitVcHandler.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
diff --git a/OvmfPkg/Library/CcExitLib/X64/TdVmcallCpuid.nasm b/OvmfPkg/Library/CcExitLib/X64/TdVmcallCpuid.nasm
new file mode 100644 (file)
index 0000000..fa86440
--- /dev/null
@@ -0,0 +1,146 @@
+;------------------------------------------------------------------------------\r
+;*\r
+;* Copyright (c) 2020 - 2021, Intel Corporation. All rights reserved.<BR>\r
+;* SPDX-License-Identifier: BSD-2-Clause-Patent\r
+;*\r
+;*\r
+;------------------------------------------------------------------------------\r
+\r
+DEFAULT REL\r
+SECTION .text\r
+\r
+%define TDVMCALL_EXPOSE_REGS_MASK       0xffec\r
+%define TDVMCALL                        0x0\r
+%define EXIT_REASON_CPUID               0xa\r
+\r
+%macro tdcall 0\r
+    db 0x66,0x0f,0x01,0xcc\r
+%endmacro\r
+\r
+%macro tdcall_push_regs 0\r
+    push rbp\r
+    mov  rbp, rsp\r
+    push r15\r
+    push r14\r
+    push r13\r
+    push r12\r
+    push rbx\r
+    push rsi\r
+    push rdi\r
+%endmacro\r
+\r
+%macro tdcall_pop_regs 0\r
+    pop rdi\r
+    pop rsi\r
+    pop rbx\r
+    pop r12\r
+    pop r13\r
+    pop r14\r
+    pop r15\r
+    pop rbp\r
+%endmacro\r
+\r
+%define number_of_regs_pushed 8\r
+%define number_of_parameters  4\r
+\r
+;\r
+; Keep these in sync for push_regs/pop_regs, code below\r
+; uses them to find 5th or greater parameters\r
+;\r
+%define first_variable_on_stack_offset \\r
+  ((number_of_regs_pushed * 8) + (number_of_parameters * 8) + 8)\r
+%define second_variable_on_stack_offset \\r
+  ((first_variable_on_stack_offset) + 8)\r
+\r
+%macro tdcall_regs_preamble 2\r
+    mov rax, %1\r
+\r
+    xor rcx, rcx\r
+    mov ecx, %2\r
+\r
+    ; R10 = 0 (standard TDVMCALL)\r
+\r
+    xor r10d, r10d\r
+\r
+    ; Zero out unused (for standard TDVMCALL) registers to avoid leaking\r
+    ; secrets to the VMM.\r
+\r
+    xor ebx, ebx\r
+    xor esi, esi\r
+    xor edi, edi\r
+\r
+    xor edx, edx\r
+    xor ebp, ebp\r
+    xor r8d, r8d\r
+    xor r9d, r9d\r
+    xor r14, r14\r
+    xor r15, r15\r
+%endmacro\r
+\r
+%macro tdcall_regs_postamble 0\r
+    xor ebx, ebx\r
+    xor esi, esi\r
+    xor edi, edi\r
+\r
+    xor ecx, ecx\r
+    xor edx, edx\r
+    xor r8d,  r8d\r
+    xor r9d,  r9d\r
+    xor r10d, r10d\r
+    xor r11d, r11d\r
+%endmacro\r
+\r
+;------------------------------------------------------------------------------\r
+; 0   => RAX = TDCALL leaf / TDVMCALL\r
+; M   => RCX = TDVMCALL register behavior\r
+; 0xa => R11 = TDVMCALL function / CPUID\r
+; RCX => R12 = p1\r
+; RDX => R13 = p2\r
+;\r
+;  UINT64\r
+;  EFIAPI\r
+;  TdVmCallCpuid (\r
+;    UINT64  EaxIn,    // Rcx\r
+;    UINT64  EcxIn,    // Rdx\r
+;    UINT64  *Results  // R8\r
+;    )\r
+global ASM_PFX(TdVmCallCpuid)\r
+ASM_PFX(TdVmCallCpuid):\r
+       tdcall_push_regs\r
+\r
+       mov r11, EXIT_REASON_CPUID\r
+       mov r12, rcx\r
+       mov r13, rdx\r
+\r
+       ; Save *results pointers\r
+       push r8\r
+\r
+       tdcall_regs_preamble TDVMCALL, TDVMCALL_EXPOSE_REGS_MASK\r
+\r
+       tdcall\r
+\r
+       ; ignore return data if TDCALL reports failure.\r
+       test rax, rax\r
+       jnz .no_return_data\r
+\r
+       ; Propagate TDVMCALL success/failure to return value.\r
+       mov rax, r10\r
+       test rax, rax\r
+       jnz .no_return_data\r
+\r
+       ; Retrieve *Results\r
+       pop r8\r
+       test r8, r8\r
+       jz .no_return_data\r
+       ; Caller pass in buffer so store results r12-r15 contains eax-edx\r
+       mov [r8 +  0], r12\r
+       mov [r8 +  8], r13\r
+       mov [r8 + 16], r14\r
+       mov [r8 + 24], r15\r
+\r
+.no_return_data:\r
+       tdcall_regs_postamble\r
+\r
+       tdcall_pop_regs\r
+\r
+       ret\r
diff --git a/OvmfPkg/Library/VmgExitLib/PeiDxeVmgExitVcHandler.c b/OvmfPkg/Library/VmgExitLib/PeiDxeVmgExitVcHandler.c
deleted file mode 100644 (file)
index e3d0715..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-/** @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
deleted file mode 100644 (file)
index f9bd497..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-## @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
-  VmTdExitVeHandler.c\r
-  X64/TdVmcallCpuid.nasm\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
-  LocalApicLib\r
-  MemEncryptSevLib\r
-  PcdLib\r
-\r
-[FixedPcd]\r
-  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupBase\r
-  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupSize\r
-  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCpuidBase\r
-  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCpuidSize\r
diff --git a/OvmfPkg/Library/VmgExitLib/SecVmgExitVcHandler.c b/OvmfPkg/Library/VmgExitLib/SecVmgExitVcHandler.c
deleted file mode 100644 (file)
index fe8680f..0000000
+++ /dev/null
@@ -1,109 +0,0 @@
-/** @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
diff --git a/OvmfPkg/Library/VmgExitLib/VmTdExitHandler.h b/OvmfPkg/Library/VmgExitLib/VmTdExitHandler.h
deleted file mode 100644 (file)
index 7eacd08..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-/** @file\r
-\r
-  Copyright (c) 2020 - 2021, Intel Corporation. All rights reserved.<BR>\r
-  SPDX-License-Identifier: BSD-2-Clause-Patent\r
-\r
-**/\r
-\r
-#ifndef VMTD_EXIT_HANDLER_H_\r
-#define VMTD_EXIT_HANDLER_H_\r
-\r
-#include <Base.h>\r
-#include <Uefi.h>\r
-\r
-/**\r
-  This function enable the TD guest to request the VMM to emulate CPUID\r
-  operation, especially for non-architectural, CPUID leaves.\r
-\r
-  @param[in]  Eax        Main leaf of the CPUID\r
-  @param[in]  Ecx        Sub-leaf of the CPUID\r
-  @param[out] Results    Returned result of CPUID operation\r
-\r
-  @return EFI_SUCCESS\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-TdVmCallCpuid (\r
-  IN UINT64  Eax,\r
-  IN UINT64  Ecx,\r
-  OUT VOID   *Results\r
-  );\r
-\r
-#endif\r
diff --git a/OvmfPkg/Library/VmgExitLib/VmTdExitVeHandler.c b/OvmfPkg/Library/VmgExitLib/VmTdExitVeHandler.c
deleted file mode 100644 (file)
index c89268c..0000000
+++ /dev/null
@@ -1,577 +0,0 @@
-/** @file\r
-\r
-  Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>\r
-\r
-  SPDX-License-Identifier: BSD-2-Clause-Patent\r
-\r
-**/\r
-\r
-#include <Library/BaseLib.h>\r
-#include <Library/DebugLib.h>\r
-#include "VmTdExitHandler.h"\r
-#include <Library/VmgExitLib.h>\r
-#include <Library/BaseMemoryLib.h>\r
-#include <IndustryStandard/Tdx.h>\r
-#include <IndustryStandard/InstructionParsing.h>\r
-\r
-typedef union {\r
-  struct {\r
-    UINT32    Eax;\r
-    UINT32    Edx;\r
-  } Regs;\r
-  UINT64    Val;\r
-} MSR_DATA;\r
-\r
-typedef union {\r
-  UINT8    Val;\r
-  struct {\r
-    UINT8    B : 1;\r
-    UINT8    X : 1;\r
-    UINT8    R : 1;\r
-    UINT8    W : 1;\r
-  } Bits;\r
-} REX;\r
-\r
-typedef union {\r
-  UINT8    Val;\r
-  struct {\r
-    UINT8    Rm  : 3;\r
-    UINT8    Reg : 3;\r
-    UINT8    Mod : 2;\r
-  } Bits;\r
-} MODRM;\r
-\r
-typedef struct {\r
-  UINT64    Regs[4];\r
-} CPUID_DATA;\r
-\r
-/**\r
-  Handle an CPUID event.\r
-\r
-  Use the TDVMCALL instruction to handle cpuid #ve\r
-\r
-  @param[in, out] Regs             x64 processor context\r
-  @param[in]      Veinfo           VE Info\r
-\r
-  @retval 0                        Event handled successfully\r
-  @return                          New exception value to propagate\r
-**/\r
-STATIC\r
-UINT64\r
-EFIAPI\r
-CpuIdExit (\r
-  IN EFI_SYSTEM_CONTEXT_X64     *Regs,\r
-  IN TDCALL_VEINFO_RETURN_DATA  *Veinfo\r
-  )\r
-{\r
-  CPUID_DATA  CpuIdData;\r
-  UINT64      Status;\r
-\r
-  Status = TdVmCallCpuid (Regs->Rax, Regs->Rcx, &CpuIdData);\r
-\r
-  if (Status == 0) {\r
-    Regs->Rax = CpuIdData.Regs[0];\r
-    Regs->Rbx = CpuIdData.Regs[1];\r
-    Regs->Rcx = CpuIdData.Regs[2];\r
-    Regs->Rdx = CpuIdData.Regs[3];\r
-  }\r
-\r
-  return Status;\r
-}\r
-\r
-/**\r
-  Handle an IO event.\r
-\r
-  Use the TDVMCALL instruction to handle either an IO read or an IO write.\r
-\r
-  @param[in, out] Regs             x64 processor context\r
-  @param[in]      Veinfo           VE Info\r
-\r
-  @retval 0                        Event handled successfully\r
-  @return                          New exception value to propagate\r
-**/\r
-STATIC\r
-UINT64\r
-EFIAPI\r
-IoExit (\r
-  IN OUT EFI_SYSTEM_CONTEXT_X64  *Regs,\r
-  IN TDCALL_VEINFO_RETURN_DATA   *Veinfo\r
-  )\r
-{\r
-  BOOLEAN  Write;\r
-  UINTN    Size;\r
-  UINTN    Port;\r
-  UINT64   Val;\r
-  UINT64   RepCnt;\r
-  UINT64   Status;\r
-\r
-  Val   = 0;\r
-  Write = Veinfo->ExitQualification.Io.Direction ? FALSE : TRUE;\r
-  Size  = Veinfo->ExitQualification.Io.Size + 1;\r
-  Port  = Veinfo->ExitQualification.Io.Port;\r
-\r
-  if (Veinfo->ExitQualification.Io.String) {\r
-    //\r
-    // If REP is set, get rep-cnt from Rcx\r
-    //\r
-    RepCnt = Veinfo->ExitQualification.Io.Rep ? Regs->Rcx : 1;\r
-\r
-    while (RepCnt) {\r
-      Val = 0;\r
-      if (Write == TRUE) {\r
-        CopyMem (&Val, (VOID *)Regs->Rsi, Size);\r
-        Regs->Rsi += Size;\r
-      }\r
-\r
-      Status = TdVmCall (EXIT_REASON_IO_INSTRUCTION, Size, Write, Port, Val, (Write ? NULL : &Val));\r
-      if (Status != 0) {\r
-        break;\r
-      }\r
-\r
-      if (Write == FALSE) {\r
-        CopyMem ((VOID *)Regs->Rdi, &Val, Size);\r
-        Regs->Rdi += Size;\r
-      }\r
-\r
-      if (Veinfo->ExitQualification.Io.Rep) {\r
-        Regs->Rcx -= 1;\r
-      }\r
-\r
-      RepCnt -= 1;\r
-    }\r
-  } else {\r
-    if (Write == TRUE) {\r
-      CopyMem (&Val, (VOID *)&Regs->Rax, Size);\r
-    }\r
-\r
-    Status = TdVmCall (EXIT_REASON_IO_INSTRUCTION, Size, Write, Port, Val, (Write ? NULL : &Val));\r
-    if ((Status == 0) && (Write == FALSE)) {\r
-      CopyMem ((VOID *)&Regs->Rax, &Val, Size);\r
-    }\r
-  }\r
-\r
-  return Status;\r
-}\r
-\r
-/**\r
-  Handle an READ MSR event.\r
-\r
-  Use the TDVMCALL instruction to handle msr read\r
-\r
-  @param[in, out] Regs             x64 processor context\r
-  @param[in]      Veinfo           VE Info\r
-\r
-  @retval 0                        Event handled successfully\r
-  @return                          New exception value to propagate\r
-**/\r
-STATIC\r
-UINT64\r
-ReadMsrExit (\r
-  IN OUT EFI_SYSTEM_CONTEXT_X64  *Regs,\r
-  IN TDCALL_VEINFO_RETURN_DATA   *Veinfo\r
-  )\r
-{\r
-  MSR_DATA  Data;\r
-  UINT64    Status;\r
-\r
-  Status = TdVmCall (EXIT_REASON_MSR_READ, Regs->Rcx, 0, 0, 0, &Data);\r
-  if (Status == 0) {\r
-    Regs->Rax = Data.Regs.Eax;\r
-    Regs->Rdx = Data.Regs.Edx;\r
-  }\r
-\r
-  return Status;\r
-}\r
-\r
-/**\r
-  Handle an WRITE MSR event.\r
-\r
-  Use the TDVMCALL instruction to handle msr write\r
-\r
-  @param[in, out] Regs             x64 processor context\r
-  @param[in]      Veinfo           VE Info\r
-\r
-  @retval 0                        Event handled successfully\r
-  @return                          New exception value to propagate\r
-**/\r
-STATIC\r
-UINT64\r
-WriteMsrExit (\r
-  IN OUT EFI_SYSTEM_CONTEXT_X64  *Regs,\r
-  IN TDCALL_VEINFO_RETURN_DATA   *Veinfo\r
-  )\r
-{\r
-  UINT64    Status;\r
-  MSR_DATA  Data;\r
-\r
-  Data.Regs.Eax = (UINT32)Regs->Rax;\r
-  Data.Regs.Edx = (UINT32)Regs->Rdx;\r
-\r
-  Status =  TdVmCall (EXIT_REASON_MSR_WRITE, Regs->Rcx, Data.Val, 0, 0, NULL);\r
-\r
-  return Status;\r
-}\r
-\r
-STATIC\r
-VOID\r
-EFIAPI\r
-TdxDecodeInstruction (\r
-  IN UINT8  *Rip\r
-  )\r
-{\r
-  UINTN  i;\r
-\r
-  DEBUG ((DEBUG_INFO, "TDX: #TD[EPT] instruction (%p):", Rip));\r
-  for (i = 0; i < 15; i++) {\r
-    DEBUG ((DEBUG_INFO, "%02x:", Rip[i]));\r
-  }\r
-\r
-  DEBUG ((DEBUG_INFO, "\n"));\r
-}\r
-\r
-#define TDX_DECODER_BUG_ON(x)               \\r
-  if ((x)) {                                \\r
-    TdxDecodeInstruction(Rip);              \\r
-    TdVmCall(TDVMCALL_HALT, 0, 0, 0, 0, 0); \\r
-  }\r
-\r
-STATIC\r
-UINT64 *\r
-EFIAPI\r
-GetRegFromContext (\r
-  IN EFI_SYSTEM_CONTEXT_X64  *Regs,\r
-  IN UINTN                   RegIndex\r
-  )\r
-{\r
-  switch (RegIndex) {\r
-    case 0: return &Regs->Rax;\r
-      break;\r
-    case 1: return &Regs->Rcx;\r
-      break;\r
-    case 2: return &Regs->Rdx;\r
-      break;\r
-    case 3: return &Regs->Rbx;\r
-      break;\r
-    case 4: return &Regs->Rsp;\r
-      break;\r
-    case 5: return &Regs->Rbp;\r
-      break;\r
-    case 6: return &Regs->Rsi;\r
-      break;\r
-    case 7: return &Regs->Rdi;\r
-      break;\r
-    case 8: return &Regs->R8;\r
-      break;\r
-    case 9: return &Regs->R9;\r
-      break;\r
-    case 10: return &Regs->R10;\r
-      break;\r
-    case 11: return &Regs->R11;\r
-      break;\r
-    case 12: return &Regs->R12;\r
-      break;\r
-    case 13: return &Regs->R13;\r
-      break;\r
-    case 14: return &Regs->R14;\r
-      break;\r
-    case 15: return &Regs->R15;\r
-      break;\r
-  }\r
-\r
-  return NULL;\r
-}\r
-\r
-/**\r
-  Handle an MMIO event.\r
-\r
-  Use the TDVMCALL instruction to handle either an mmio read or an mmio write.\r
-\r
-  @param[in, out] Regs             x64 processor context\r
-  @param[in]      Veinfo           VE Info\r
-\r
-  @retval 0                        Event handled successfully\r
-  @return                          New exception value to propagate\r
-**/\r
-STATIC\r
-INTN\r
-EFIAPI\r
-MmioExit (\r
-  IN OUT EFI_SYSTEM_CONTEXT_X64  *Regs,\r
-  IN TDCALL_VEINFO_RETURN_DATA   *Veinfo\r
-  )\r
-{\r
-  UINT64          Status;\r
-  UINT32          MmioSize;\r
-  UINT32          RegSize;\r
-  UINT8           OpCode;\r
-  BOOLEAN         SeenRex;\r
-  UINT64          *Reg;\r
-  UINT8           *Rip;\r
-  UINT64          Val;\r
-  UINT32          OpSize;\r
-  MODRM           ModRm;\r
-  REX             Rex;\r
-  TD_RETURN_DATA  TdReturnData;\r
-  UINT8           Gpaw;\r
-  UINT64          TdSharedPageMask;\r
-\r
-  Rip     = (UINT8 *)Regs->Rip;\r
-  Val     = 0;\r
-  Rex.Val = 0;\r
-  SeenRex = FALSE;\r
-\r
-  Status = TdCall (TDCALL_TDINFO, 0, 0, 0, &TdReturnData);\r
-  if (Status == TDX_EXIT_REASON_SUCCESS) {\r
-    Gpaw             = (UINT8)(TdReturnData.TdInfo.Gpaw & 0x3f);\r
-    TdSharedPageMask = 1ULL << (Gpaw - 1);\r
-  } else {\r
-    DEBUG ((DEBUG_ERROR, "TDCALL failed with status=%llx\n", Status));\r
-    return Status;\r
-  }\r
-\r
-  if ((Veinfo->GuestPA & TdSharedPageMask) == 0) {\r
-    DEBUG ((DEBUG_ERROR, "EPT-violation #VE on private memory is not allowed!"));\r
-    TdVmCall (TDVMCALL_HALT, 0, 0, 0, 0, 0);\r
-    CpuDeadLoop ();\r
-  }\r
-\r
-  //\r
-  // Default to 32bit transfer\r
-  //\r
-  OpSize = 4;\r
-\r
-  do {\r
-    OpCode = *Rip++;\r
-    if (OpCode == 0x66) {\r
-      OpSize = 2;\r
-    } else if ((OpCode == 0x64) || (OpCode == 0x65) || (OpCode == 0x67)) {\r
-      continue;\r
-    } else if ((OpCode >= 0x40) && (OpCode <= 0x4f)) {\r
-      SeenRex = TRUE;\r
-      Rex.Val = OpCode;\r
-    } else {\r
-      break;\r
-    }\r
-  } while (TRUE);\r
-\r
-  //\r
-  // We need to have at least 2 more bytes for this instruction\r
-  //\r
-  TDX_DECODER_BUG_ON (((UINT64)Rip - Regs->Rip) > 13);\r
-\r
-  OpCode = *Rip++;\r
-  //\r
-  // Two-byte opecode, get next byte\r
-  //\r
-  if (OpCode == 0x0F) {\r
-    OpCode = *Rip++;\r
-  }\r
-\r
-  switch (OpCode) {\r
-    case 0x88:\r
-    case 0x8A:\r
-    case 0xB6:\r
-      MmioSize = 1;\r
-      break;\r
-    case 0xB7:\r
-      MmioSize = 2;\r
-      break;\r
-    default:\r
-      MmioSize = Rex.Bits.W ? 8 : OpSize;\r
-      break;\r
-  }\r
-\r
-  /* Punt on AH/BH/CH/DH unless it shows up. */\r
-  ModRm.Val = *Rip++;\r
-  TDX_DECODER_BUG_ON (MmioSize == 1 && ModRm.Bits.Reg > 4 && !SeenRex && OpCode != 0xB6);\r
-  Reg = GetRegFromContext (Regs, ModRm.Bits.Reg | ((int)Rex.Bits.R << 3));\r
-  TDX_DECODER_BUG_ON (!Reg);\r
-\r
-  if (ModRm.Bits.Rm == 4) {\r
-    ++Rip; /* SIB byte */\r
-  }\r
-\r
-  if ((ModRm.Bits.Mod == 2) || ((ModRm.Bits.Mod == 0) && (ModRm.Bits.Rm == 5))) {\r
-    Rip += 4; /* DISP32 */\r
-  } else if (ModRm.Bits.Mod == 1) {\r
-    ++Rip;  /* DISP8 */\r
-  }\r
-\r
-  switch (OpCode) {\r
-    case 0x88:\r
-    case 0x89:\r
-      CopyMem ((void *)&Val, Reg, MmioSize);\r
-      Status = TdVmCall (TDVMCALL_MMIO, MmioSize, 1, Veinfo->GuestPA, Val, 0);\r
-      break;\r
-    case 0xC7:\r
-      CopyMem ((void *)&Val, Rip, OpSize);\r
-      Status = TdVmCall (TDVMCALL_MMIO, MmioSize, 1, Veinfo->GuestPA, Val, 0);\r
-      Rip   += OpSize;\r
-    default:\r
-      //\r
-      // 32-bit write registers are zero extended to the full register\r
-      // Hence 'MOVZX r[32/64], r/m16' is\r
-      // hardcoded to reg size 8, and the straight MOV case has a reg\r
-      // size of 8 in the 32-bit read case.\r
-      //\r
-      switch (OpCode) {\r
-        case 0xB6:\r
-          RegSize = Rex.Bits.W ? 8 : OpSize;\r
-          break;\r
-        case 0xB7:\r
-          RegSize =  8;\r
-          break;\r
-        default:\r
-          RegSize = MmioSize == 4 ? 8 : MmioSize;\r
-          break;\r
-      }\r
-\r
-      Status = TdVmCall (TDVMCALL_MMIO, MmioSize, 0, Veinfo->GuestPA, 0, &Val);\r
-      if (Status == 0) {\r
-        ZeroMem (Reg, RegSize);\r
-        CopyMem (Reg, (void *)&Val, MmioSize);\r
-      }\r
-  }\r
-\r
-  if (Status == 0) {\r
-    TDX_DECODER_BUG_ON (((UINT64)Rip - Regs->Rip) > 15);\r
-\r
-    //\r
-    // We change instruction length to reflect true size so handler can\r
-    // bump rip\r
-    //\r
-    Veinfo->ExitInstructionLength =  (UINT32)((UINT64)Rip - Regs->Rip);\r
-  }\r
-\r
-  return Status;\r
-}\r
-\r
-/**\r
-  Handle a #VE exception.\r
-\r
-  Performs the necessary processing to handle a #VE 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        #VE not supported, (new) exception value to\r
-                                  propagate provided\r
-  @retval  EFI_PROTOCOL_ERROR     #VE handling failed, (new) exception value to\r
-                                  propagate provided\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-VmTdExitHandleVe (\r
-  IN OUT EFI_EXCEPTION_TYPE  *ExceptionType,\r
-  IN OUT EFI_SYSTEM_CONTEXT  SystemContext\r
-  )\r
-{\r
-  UINT64                  Status;\r
-  TD_RETURN_DATA          ReturnData;\r
-  EFI_SYSTEM_CONTEXT_X64  *Regs;\r
-\r
-  Regs   = SystemContext.SystemContextX64;\r
-  Status = TdCall (TDCALL_TDGETVEINFO, 0, 0, 0, &ReturnData);\r
-  ASSERT (Status == 0);\r
-  if (Status != 0) {\r
-    DEBUG ((DEBUG_ERROR, "#VE happened. TDGETVEINFO failed with Status = 0x%llx\n", Status));\r
-    TdVmCall (TDVMCALL_HALT, 0, 0, 0, 0, 0);\r
-  }\r
-\r
-  switch (ReturnData.VeInfo.ExitReason) {\r
-    case EXIT_REASON_CPUID:\r
-      Status = CpuIdExit (Regs, &ReturnData.VeInfo);\r
-      DEBUG ((\r
-        DEBUG_VERBOSE,\r
-        "CPUID #VE happened, ExitReasion is %d, ExitQualification = 0x%x.\n",\r
-        ReturnData.VeInfo.ExitReason,\r
-        ReturnData.VeInfo.ExitQualification.Val\r
-        ));\r
-      break;\r
-\r
-    case EXIT_REASON_HLT:\r
-      Status = TdVmCall (EXIT_REASON_HLT, 0, 0, 0, 0, 0);\r
-      break;\r
-\r
-    case EXIT_REASON_IO_INSTRUCTION:\r
-      Status = IoExit (Regs, &ReturnData.VeInfo);\r
-      DEBUG ((\r
-        DEBUG_VERBOSE,\r
-        "IO_Instruction #VE happened, ExitReasion is %d, ExitQualification = 0x%x.\n",\r
-        ReturnData.VeInfo.ExitReason,\r
-        ReturnData.VeInfo.ExitQualification.Val\r
-        ));\r
-      break;\r
-\r
-    case EXIT_REASON_MSR_READ:\r
-      Status = ReadMsrExit (Regs, &ReturnData.VeInfo);\r
-      DEBUG ((\r
-        DEBUG_VERBOSE,\r
-        "RDMSR #VE happened, ExitReasion is %d, ExitQualification = 0x%x. Regs->Rcx=0x%llx, Status = 0x%llx\n",\r
-        ReturnData.VeInfo.ExitReason,\r
-        ReturnData.VeInfo.ExitQualification.Val,\r
-        Regs->Rcx,\r
-        Status\r
-        ));\r
-      break;\r
-\r
-    case EXIT_REASON_MSR_WRITE:\r
-      Status = WriteMsrExit (Regs, &ReturnData.VeInfo);\r
-      DEBUG ((\r
-        DEBUG_VERBOSE,\r
-        "WRMSR #VE happened, ExitReasion is %d, ExitQualification = 0x%x. Regs->Rcx=0x%llx, Status = 0x%llx\n",\r
-        ReturnData.VeInfo.ExitReason,\r
-        ReturnData.VeInfo.ExitQualification.Val,\r
-        Regs->Rcx,\r
-        Status\r
-        ));\r
-      break;\r
-\r
-    case EXIT_REASON_EPT_VIOLATION:\r
-      Status = MmioExit (Regs, &ReturnData.VeInfo);\r
-      DEBUG ((\r
-        DEBUG_VERBOSE,\r
-        "MMIO #VE happened, ExitReasion is %d, ExitQualification = 0x%x.\n",\r
-        ReturnData.VeInfo.ExitReason,\r
-        ReturnData.VeInfo.ExitQualification.Val\r
-        ));\r
-      break;\r
-\r
-    case EXIT_REASON_VMCALL:\r
-    case EXIT_REASON_MWAIT_INSTRUCTION:\r
-    case EXIT_REASON_MONITOR_INSTRUCTION:\r
-    case EXIT_REASON_WBINVD:\r
-    case EXIT_REASON_RDPMC:\r
-      /* Handle as nops. */\r
-      break;\r
-\r
-    default:\r
-      DEBUG ((\r
-        DEBUG_ERROR,\r
-        "Unsupported #VE happened, ExitReason is %d, ExitQualification = 0x%x.\n",\r
-        ReturnData.VeInfo.ExitReason,\r
-        ReturnData.VeInfo.ExitQualification.Val\r
-        ));\r
-\r
-      ASSERT (FALSE);\r
-      CpuDeadLoop ();\r
-  }\r
-\r
-  if (Status) {\r
-    DEBUG ((\r
-      DEBUG_ERROR,\r
-      "#VE Error (0x%llx) returned from host, ExitReason is %d, ExitQualification = 0x%x.\n",\r
-      Status,\r
-      ReturnData.VeInfo.ExitReason,\r
-      ReturnData.VeInfo.ExitQualification.Val\r
-      ));\r
-\r
-    TdVmCall (TDVMCALL_HALT, 0, 0, 0, 0, 0);\r
-  }\r
-\r
-  SystemContext.SystemContextX64->Rip += ReturnData.VeInfo.ExitInstructionLength;\r
-  return EFI_SUCCESS;\r
-}\r
diff --git a/OvmfPkg/Library/VmgExitLib/VmgExitLib.c b/OvmfPkg/Library/VmgExitLib/VmgExitLib.c
deleted file mode 100644 (file)
index c205521..0000000
+++ /dev/null
@@ -1,238 +0,0 @@
-/** @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
-#include <Base.h>\r
-#include <Uefi.h>\r
-#include <Library/BaseMemoryLib.h>\r
-#include <Library/VmgExitLib.h>\r
-#include <Register/Amd/Msr.h>\r
-\r
-/**\r
-  Check for VMGEXIT error\r
-\r
-  Check if the hypervisor has returned an error after completion of the VMGEXIT\r
-  by examining the SwExitInfo1 field of the GHCB.\r
-\r
-  @param[in]  Ghcb       A pointer to the GHCB\r
-\r
-  @retval  0             VMGEXIT succeeded.\r
-  @return                Exception number to be propagated, VMGEXIT processing\r
-                         did not succeed.\r
-\r
-**/\r
-STATIC\r
-UINT64\r
-VmgExitErrorCheck (\r
-  IN GHCB  *Ghcb\r
-  )\r
-{\r
-  GHCB_EVENT_INJECTION  Event;\r
-  GHCB_EXIT_INFO        ExitInfo;\r
-  UINT64                Status;\r
-\r
-  ExitInfo.Uint64 = Ghcb->SaveArea.SwExitInfo1;\r
-  ASSERT (\r
-    (ExitInfo.Elements.Lower32Bits == 0) ||\r
-    (ExitInfo.Elements.Lower32Bits == 1)\r
-    );\r
-\r
-  Status = 0;\r
-  if (ExitInfo.Elements.Lower32Bits == 0) {\r
-    return Status;\r
-  }\r
-\r
-  if (ExitInfo.Elements.Lower32Bits == 1) {\r
-    ASSERT (Ghcb->SaveArea.SwExitInfo2 != 0);\r
-\r
-    //\r
-    // Check that the return event is valid\r
-    //\r
-    Event.Uint64 = Ghcb->SaveArea.SwExitInfo2;\r
-    if (Event.Elements.Valid &&\r
-        (Event.Elements.Type == GHCB_EVENT_INJECTION_TYPE_EXCEPTION))\r
-    {\r
-      switch (Event.Elements.Vector) {\r
-        case GP_EXCEPTION:\r
-        case UD_EXCEPTION:\r
-          //\r
-          // Use returned event as return code\r
-          //\r
-          Status = Event.Uint64;\r
-      }\r
-    }\r
-  }\r
-\r
-  if (Status == 0) {\r
-    GHCB_EVENT_INJECTION  GpEvent;\r
-\r
-    GpEvent.Uint64          = 0;\r
-    GpEvent.Elements.Vector = GP_EXCEPTION;\r
-    GpEvent.Elements.Type   = GHCB_EVENT_INJECTION_TYPE_EXCEPTION;\r
-    GpEvent.Elements.Valid  = 1;\r
-\r
-    Status = GpEvent.Uint64;\r
-  }\r
-\r
-  return Status;\r
-}\r
-\r
-/**\r
-  Perform VMGEXIT.\r
-\r
-  Sets the necessary fields of the GHCB, invokes the VMGEXIT instruction and\r
-  then handles the return actions.\r
-\r
-  @param[in, out]  Ghcb       A pointer to the GHCB\r
-  @param[in]       ExitCode   VMGEXIT code to be assigned to the SwExitCode\r
-                              field of the GHCB.\r
-  @param[in]       ExitInfo1  VMGEXIT information to be assigned to the\r
-                              SwExitInfo1 field of the GHCB.\r
-  @param[in]       ExitInfo2  VMGEXIT information to be assigned to the\r
-                              SwExitInfo2 field of the GHCB.\r
-\r
-  @retval  0                  VMGEXIT succeeded.\r
-  @return                     Exception number to be propagated, VMGEXIT\r
-                              processing did not succeed.\r
-\r
-**/\r
-UINT64\r
-EFIAPI\r
-VmgExit (\r
-  IN OUT GHCB    *Ghcb,\r
-  IN     UINT64  ExitCode,\r
-  IN     UINT64  ExitInfo1,\r
-  IN     UINT64  ExitInfo2\r
-  )\r
-{\r
-  Ghcb->SaveArea.SwExitCode  = ExitCode;\r
-  Ghcb->SaveArea.SwExitInfo1 = ExitInfo1;\r
-  Ghcb->SaveArea.SwExitInfo2 = ExitInfo2;\r
-\r
-  VmgSetOffsetValid (Ghcb, GhcbSwExitCode);\r
-  VmgSetOffsetValid (Ghcb, GhcbSwExitInfo1);\r
-  VmgSetOffsetValid (Ghcb, GhcbSwExitInfo2);\r
-\r
-  //\r
-  // Guest memory is used for the guest-hypervisor communication, so fence\r
-  // the invocation of the VMGEXIT instruction to ensure GHCB accesses are\r
-  // synchronized properly.\r
-  //\r
-  MemoryFence ();\r
-  AsmVmgExit ();\r
-  MemoryFence ();\r
-\r
-  return VmgExitErrorCheck (Ghcb);\r
-}\r
-\r
-/**\r
-  Perform pre-VMGEXIT initialization/preparation.\r
-\r
-  Performs the necessary steps in preparation for invoking VMGEXIT. Must be\r
-  called before setting any fields within the GHCB.\r
-\r
-  @param[in, out]  Ghcb            A pointer to the GHCB\r
-  @param[in, out]  InterruptState  A pointer to hold the current interrupt\r
-                                   state, used for restoring in VmgDone ()\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-VmgInit (\r
-  IN OUT GHCB     *Ghcb,\r
-  IN OUT BOOLEAN  *InterruptState\r
-  )\r
-{\r
-  //\r
-  // Be sure that an interrupt can't cause a #VC while the GHCB is\r
-  // being used.\r
-  //\r
-  *InterruptState = GetInterruptState ();\r
-  if (*InterruptState) {\r
-    DisableInterrupts ();\r
-  }\r
-\r
-  SetMem (&Ghcb->SaveArea, sizeof (Ghcb->SaveArea), 0);\r
-}\r
-\r
-/**\r
-  Perform post-VMGEXIT cleanup.\r
-\r
-  Performs the necessary steps to cleanup after invoking VMGEXIT. Must be\r
-  called after obtaining needed fields within the GHCB.\r
-\r
-  @param[in, out]  Ghcb            A pointer to the GHCB\r
-  @param[in]       InterruptState  An indicator to conditionally (re)enable\r
-                                   interrupts\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-VmgDone (\r
-  IN OUT GHCB     *Ghcb,\r
-  IN     BOOLEAN  InterruptState\r
-  )\r
-{\r
-  if (InterruptState) {\r
-    EnableInterrupts ();\r
-  }\r
-}\r
-\r
-/**\r
-  Marks a field at the specified offset as valid in the GHCB.\r
-\r
-  The ValidBitmap area represents the areas of the GHCB that have been marked\r
-  valid. Set the bit in ValidBitmap for the input offset.\r
-\r
-  @param[in, out] Ghcb    Pointer to the Guest-Hypervisor Communication Block\r
-  @param[in]      Offset  Qword offset in the GHCB to mark valid\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-VmgSetOffsetValid (\r
-  IN OUT GHCB           *Ghcb,\r
-  IN     GHCB_REGISTER  Offset\r
-  )\r
-{\r
-  UINT32  OffsetIndex;\r
-  UINT32  OffsetBit;\r
-\r
-  OffsetIndex = Offset / 8;\r
-  OffsetBit   = Offset % 8;\r
-\r
-  Ghcb->SaveArea.ValidBitmap[OffsetIndex] |= (1 << OffsetBit);\r
-}\r
-\r
-/**\r
-  Checks if a specified offset is valid in the GHCB.\r
-\r
-  The ValidBitmap area represents the areas of the GHCB that have been marked\r
-  valid. Return whether the bit in the ValidBitmap is set for the input offset.\r
-\r
-  @param[in]  Ghcb            A pointer to the GHCB\r
-  @param[in]  Offset          Qword offset in the GHCB to mark valid\r
-\r
-  @retval TRUE                Offset is marked valid in the GHCB\r
-  @retval FALSE               Offset is not marked valid in the GHCB\r
-\r
-**/\r
-BOOLEAN\r
-EFIAPI\r
-VmgIsOffsetValid (\r
-  IN GHCB           *Ghcb,\r
-  IN GHCB_REGISTER  Offset\r
-  )\r
-{\r
-  UINT32  OffsetIndex;\r
-  UINT32  OffsetBit;\r
-\r
-  OffsetIndex = Offset / 8;\r
-  OffsetBit   = Offset % 8;\r
-\r
-  return ((Ghcb->SaveArea.ValidBitmap[OffsetIndex] & (1 << OffsetBit)) != 0);\r
-}\r
diff --git a/OvmfPkg/Library/VmgExitLib/VmgExitLib.inf b/OvmfPkg/Library/VmgExitLib/VmgExitLib.inf
deleted file mode 100644 (file)
index 255b0c1..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-## @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                      = VmgExitLib\r
-  FILE_GUID                      = 0e923c25-13cd-430b-8714-ffe85652a97b\r
-  MODULE_TYPE                    = BASE\r
-  VERSION_STRING                 = 1.0\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
-#\r
-#  VALID_ARCHITECTURES           = X64\r
-#\r
-\r
-[Sources.common]\r
-  VmgExitLib.c\r
-  VmgExitVcHandler.c\r
-  VmgExitVcHandler.h\r
-  PeiDxeVmgExitVcHandler.c\r
-  VmTdExitVeHandler.c\r
-  X64/TdVmcallCpuid.nasm\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
-  LocalApicLib\r
-  MemEncryptSevLib\r
-\r
-[Pcd]\r
-  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCpuidBase\r
-  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCpuidSize\r
diff --git a/OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c b/OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c
deleted file mode 100644 (file)
index a4393df..0000000
+++ /dev/null
@@ -1,2356 +0,0 @@
-/** @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/LocalApicLib.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
-// #include <Library/MemEncryptSevLib.h>\r
-\r
-//\r
-// Instruction execution mode definition\r
-//\r
-typedef enum {\r
-  LongMode64Bit = 0,\r
-  LongModeCompat32Bit,\r
-  LongModeCompat16Bit,\r
-} SEV_ES_INSTRUCTION_MODE;\r
-\r
-//\r
-// Instruction size definition (for operand and address)\r
-//\r
-typedef enum {\r
-  Size8Bits = 0,\r
-  Size16Bits,\r
-  Size32Bits,\r
-  Size64Bits,\r
-} SEV_ES_INSTRUCTION_SIZE;\r
-\r
-//\r
-// Intruction segment definition\r
-//\r
-typedef enum {\r
-  SegmentEs = 0,\r
-  SegmentCs,\r
-  SegmentSs,\r
-  SegmentDs,\r
-  SegmentFs,\r
-  SegmentGs,\r
-} SEV_ES_INSTRUCTION_SEGMENT;\r
-\r
-//\r
-// Instruction rep function definition\r
-//\r
-typedef enum {\r
-  RepNone = 0,\r
-  RepZ,\r
-  RepNZ,\r
-} SEV_ES_INSTRUCTION_REP;\r
-\r
-typedef struct {\r
-  UINT8    Rm;\r
-  UINT8    Reg;\r
-  UINT8    Mod;\r
-} SEV_ES_INSTRUCTION_MODRM_EXT;\r
-\r
-typedef struct {\r
-  UINT8    Base;\r
-  UINT8    Index;\r
-  UINT8    Scale;\r
-} SEV_ES_INSTRUCTION_SIB_EXT;\r
-\r
-//\r
-// Instruction opcode definition\r
-//\r
-typedef struct {\r
-  SEV_ES_INSTRUCTION_MODRM_EXT    ModRm;\r
-\r
-  SEV_ES_INSTRUCTION_SIB_EXT      Sib;\r
-\r
-  UINTN                           RegData;\r
-  UINTN                           RmData;\r
-} SEV_ES_INSTRUCTION_OPCODE_EXT;\r
-\r
-//\r
-// Instruction parsing context definition\r
-//\r
-typedef struct {\r
-  GHCB                             *Ghcb;\r
-\r
-  SEV_ES_INSTRUCTION_MODE          Mode;\r
-  SEV_ES_INSTRUCTION_SIZE          DataSize;\r
-  SEV_ES_INSTRUCTION_SIZE          AddrSize;\r
-  BOOLEAN                          SegmentSpecified;\r
-  SEV_ES_INSTRUCTION_SEGMENT       Segment;\r
-  SEV_ES_INSTRUCTION_REP           RepMode;\r
-\r
-  UINT8                            *Begin;\r
-  UINT8                            *End;\r
-\r
-  UINT8                            *Prefixes;\r
-  UINT8                            *OpCodes;\r
-  UINT8                            *Displacement;\r
-  UINT8                            *Immediate;\r
-\r
-  INSTRUCTION_REX_PREFIX           RexPrefix;\r
-\r
-  BOOLEAN                          ModRmPresent;\r
-  INSTRUCTION_MODRM                ModRm;\r
-\r
-  BOOLEAN                          SibPresent;\r
-  INSTRUCTION_SIB                  Sib;\r
-\r
-  UINTN                            PrefixSize;\r
-  UINTN                            OpCodeSize;\r
-  UINTN                            DisplacementSize;\r
-  UINTN                            ImmediateSize;\r
-\r
-  SEV_ES_INSTRUCTION_OPCODE_EXT    Ext;\r
-} SEV_ES_INSTRUCTION_DATA;\r
-\r
-//\r
-// Non-automatic Exit function prototype\r
-//\r
-typedef\r
-UINT64\r
-(*NAE_EXIT) (\r
-  GHCB                     *Ghcb,\r
-  EFI_SYSTEM_CONTEXT_X64   *Regs,\r
-  SEV_ES_INSTRUCTION_DATA  *InstructionData\r
-  );\r
-\r
-//\r
-// SEV-SNP Cpuid table entry/function\r
-//\r
-typedef PACKED struct {\r
-  UINT32    EaxIn;\r
-  UINT32    EcxIn;\r
-  UINT64    Unused;\r
-  UINT64    Unused2;\r
-  UINT32    Eax;\r
-  UINT32    Ebx;\r
-  UINT32    Ecx;\r
-  UINT32    Edx;\r
-  UINT64    Reserved;\r
-} SEV_SNP_CPUID_FUNCTION;\r
-\r
-//\r
-// SEV-SNP Cpuid page format\r
-//\r
-typedef PACKED struct {\r
-  UINT32                    Count;\r
-  UINT32                    Reserved1;\r
-  UINT64                    Reserved2;\r
-  SEV_SNP_CPUID_FUNCTION    function[0];\r
-} SEV_SNP_CPUID_INFO;\r
-\r
-/**\r
-  Return a pointer to the contents of the specified register.\r
-\r
-  Based upon the input register, return a pointer to the registers contents\r
-  in the x86 processor context.\r
-\r
-  @param[in] Regs      x64 processor context\r
-  @param[in] Register  Register to obtain pointer for\r
-\r
-  @return              Pointer to the contents of the requested register\r
-\r
-**/\r
-STATIC\r
-UINT64 *\r
-GetRegisterPointer (\r
-  IN EFI_SYSTEM_CONTEXT_X64  *Regs,\r
-  IN UINT8                   Register\r
-  )\r
-{\r
-  UINT64  *Reg;\r
-\r
-  switch (Register) {\r
-    case 0:\r
-      Reg = &Regs->Rax;\r
-      break;\r
-    case 1:\r
-      Reg = &Regs->Rcx;\r
-      break;\r
-    case 2:\r
-      Reg = &Regs->Rdx;\r
-      break;\r
-    case 3:\r
-      Reg = &Regs->Rbx;\r
-      break;\r
-    case 4:\r
-      Reg = &Regs->Rsp;\r
-      break;\r
-    case 5:\r
-      Reg = &Regs->Rbp;\r
-      break;\r
-    case 6:\r
-      Reg = &Regs->Rsi;\r
-      break;\r
-    case 7:\r
-      Reg = &Regs->Rdi;\r
-      break;\r
-    case 8:\r
-      Reg = &Regs->R8;\r
-      break;\r
-    case 9:\r
-      Reg = &Regs->R9;\r
-      break;\r
-    case 10:\r
-      Reg = &Regs->R10;\r
-      break;\r
-    case 11:\r
-      Reg = &Regs->R11;\r
-      break;\r
-    case 12:\r
-      Reg = &Regs->R12;\r
-      break;\r
-    case 13:\r
-      Reg = &Regs->R13;\r
-      break;\r
-    case 14:\r
-      Reg = &Regs->R14;\r
-      break;\r
-    case 15:\r
-      Reg = &Regs->R15;\r
-      break;\r
-    default:\r
-      Reg = NULL;\r
-  }\r
-\r
-  ASSERT (Reg != NULL);\r
-\r
-  return Reg;\r
-}\r
-\r
-/**\r
-  Update the instruction parsing context for displacement bytes.\r
-\r
-  @param[in, out] InstructionData  Instruction parsing context\r
-  @param[in]      Size             The instruction displacement size\r
-\r
-**/\r
-STATIC\r
-VOID\r
-UpdateForDisplacement (\r
-  IN OUT SEV_ES_INSTRUCTION_DATA  *InstructionData,\r
-  IN     UINTN                    Size\r
-  )\r
-{\r
-  InstructionData->DisplacementSize = Size;\r
-  InstructionData->Immediate       += Size;\r
-  InstructionData->End             += Size;\r
-}\r
-\r
-/**\r
-  Determine if an instruction address if RIP relative.\r
-\r
-  Examine the instruction parsing context to determine if the address offset\r
-  is relative to the instruction pointer.\r
-\r
-  @param[in] InstructionData  Instruction parsing context\r
-\r
-  @retval TRUE                Instruction addressing is RIP relative\r
-  @retval FALSE               Instruction addressing is not RIP relative\r
-\r
-**/\r
-STATIC\r
-BOOLEAN\r
-IsRipRelative (\r
-  IN SEV_ES_INSTRUCTION_DATA  *InstructionData\r
-  )\r
-{\r
-  SEV_ES_INSTRUCTION_OPCODE_EXT  *Ext;\r
-\r
-  Ext = &InstructionData->Ext;\r
-\r
-  return ((InstructionData->Mode == LongMode64Bit) &&\r
-          (Ext->ModRm.Mod == 0) &&\r
-          (Ext->ModRm.Rm == 5)  &&\r
-          (InstructionData->SibPresent == FALSE));\r
-}\r
-\r
-/**\r
-  Return the effective address of a memory operand.\r
-\r
-  Examine the instruction parsing context to obtain the effective memory\r
-  address of a memory operand.\r
-\r
-  @param[in] Regs             x64 processor context\r
-  @param[in] InstructionData  Instruction parsing context\r
-\r
-  @return                     The memory operand effective address\r
-\r
-**/\r
-STATIC\r
-UINT64\r
-GetEffectiveMemoryAddress (\r
-  IN EFI_SYSTEM_CONTEXT_X64   *Regs,\r
-  IN SEV_ES_INSTRUCTION_DATA  *InstructionData\r
-  )\r
-{\r
-  SEV_ES_INSTRUCTION_OPCODE_EXT  *Ext;\r
-  UINT64                         EffectiveAddress;\r
-\r
-  Ext              = &InstructionData->Ext;\r
-  EffectiveAddress = 0;\r
-\r
-  if (IsRipRelative (InstructionData)) {\r
-    //\r
-    // RIP-relative displacement is a 32-bit signed value\r
-    //\r
-    INT32  RipRelative;\r
-\r
-    RipRelative = *(INT32 *)InstructionData->Displacement;\r
-\r
-    UpdateForDisplacement (InstructionData, 4);\r
-\r
-    //\r
-    // Negative displacement is handled by standard UINT64 wrap-around.\r
-    //\r
-    return Regs->Rip + (UINT64)RipRelative;\r
-  }\r
-\r
-  switch (Ext->ModRm.Mod) {\r
-    case 1:\r
-      UpdateForDisplacement (InstructionData, 1);\r
-      EffectiveAddress += (UINT64)(*(INT8 *)(InstructionData->Displacement));\r
-      break;\r
-    case 2:\r
-      switch (InstructionData->AddrSize) {\r
-        case Size16Bits:\r
-          UpdateForDisplacement (InstructionData, 2);\r
-          EffectiveAddress += (UINT64)(*(INT16 *)(InstructionData->Displacement));\r
-          break;\r
-        default:\r
-          UpdateForDisplacement (InstructionData, 4);\r
-          EffectiveAddress += (UINT64)(*(INT32 *)(InstructionData->Displacement));\r
-          break;\r
-      }\r
-\r
-      break;\r
-  }\r
-\r
-  if (InstructionData->SibPresent) {\r
-    INT64  Displacement;\r
-\r
-    if (Ext->Sib.Index != 4) {\r
-      CopyMem (\r
-        &Displacement,\r
-        GetRegisterPointer (Regs, Ext->Sib.Index),\r
-        sizeof (Displacement)\r
-        );\r
-      Displacement *= (INT64)(1 << Ext->Sib.Scale);\r
-\r
-      //\r
-      // Negative displacement is handled by standard UINT64 wrap-around.\r
-      //\r
-      EffectiveAddress += (UINT64)Displacement;\r
-    }\r
-\r
-    if ((Ext->Sib.Base != 5) || Ext->ModRm.Mod) {\r
-      EffectiveAddress += *GetRegisterPointer (Regs, Ext->Sib.Base);\r
-    } else {\r
-      UpdateForDisplacement (InstructionData, 4);\r
-      EffectiveAddress += (UINT64)(*(INT32 *)(InstructionData->Displacement));\r
-    }\r
-  } else {\r
-    EffectiveAddress += *GetRegisterPointer (Regs, Ext->ModRm.Rm);\r
-  }\r
-\r
-  return EffectiveAddress;\r
-}\r
-\r
-/**\r
-  Decode a ModRM byte.\r
-\r
-  Examine the instruction parsing context to decode a ModRM byte and the SIB\r
-  byte, if present.\r
-\r
-  @param[in]      Regs             x64 processor context\r
-  @param[in, out] InstructionData  Instruction parsing context\r
-\r
-**/\r
-STATIC\r
-VOID\r
-DecodeModRm (\r
-  IN     EFI_SYSTEM_CONTEXT_X64   *Regs,\r
-  IN OUT SEV_ES_INSTRUCTION_DATA  *InstructionData\r
-  )\r
-{\r
-  SEV_ES_INSTRUCTION_OPCODE_EXT  *Ext;\r
-  INSTRUCTION_REX_PREFIX         *RexPrefix;\r
-  INSTRUCTION_MODRM              *ModRm;\r
-  INSTRUCTION_SIB                *Sib;\r
-\r
-  RexPrefix = &InstructionData->RexPrefix;\r
-  Ext       = &InstructionData->Ext;\r
-  ModRm     = &InstructionData->ModRm;\r
-  Sib       = &InstructionData->Sib;\r
-\r
-  InstructionData->ModRmPresent = TRUE;\r
-  ModRm->Uint8                  = *(InstructionData->End);\r
-\r
-  InstructionData->Displacement++;\r
-  InstructionData->Immediate++;\r
-  InstructionData->End++;\r
-\r
-  Ext->ModRm.Mod = ModRm->Bits.Mod;\r
-  Ext->ModRm.Reg = (RexPrefix->Bits.BitR << 3) | ModRm->Bits.Reg;\r
-  Ext->ModRm.Rm  = (RexPrefix->Bits.BitB << 3) | ModRm->Bits.Rm;\r
-\r
-  Ext->RegData = *GetRegisterPointer (Regs, Ext->ModRm.Reg);\r
-\r
-  if (Ext->ModRm.Mod == 3) {\r
-    Ext->RmData = *GetRegisterPointer (Regs, Ext->ModRm.Rm);\r
-  } else {\r
-    if (ModRm->Bits.Rm == 4) {\r
-      InstructionData->SibPresent = TRUE;\r
-      Sib->Uint8                  = *(InstructionData->End);\r
-\r
-      InstructionData->Displacement++;\r
-      InstructionData->Immediate++;\r
-      InstructionData->End++;\r
-\r
-      Ext->Sib.Scale = Sib->Bits.Scale;\r
-      Ext->Sib.Index = (RexPrefix->Bits.BitX << 3) | Sib->Bits.Index;\r
-      Ext->Sib.Base  = (RexPrefix->Bits.BitB << 3) | Sib->Bits.Base;\r
-    }\r
-\r
-    Ext->RmData = GetEffectiveMemoryAddress (Regs, InstructionData);\r
-  }\r
-}\r
-\r
-/**\r
-  Decode instruction prefixes.\r
-\r
-  Parse the instruction data to track the instruction prefixes that have\r
-  been used.\r
-\r
-  @param[in]      Regs             x64 processor context\r
-  @param[in, out] InstructionData  Instruction parsing context\r
-\r
-**/\r
-STATIC\r
-VOID\r
-DecodePrefixes (\r
-  IN     EFI_SYSTEM_CONTEXT_X64   *Regs,\r
-  IN OUT SEV_ES_INSTRUCTION_DATA  *InstructionData\r
-  )\r
-{\r
-  SEV_ES_INSTRUCTION_MODE  Mode;\r
-  SEV_ES_INSTRUCTION_SIZE  ModeDataSize;\r
-  SEV_ES_INSTRUCTION_SIZE  ModeAddrSize;\r
-  UINT8                    *Byte;\r
-\r
-  //\r
-  // Always in 64-bit mode\r
-  //\r
-  Mode         = LongMode64Bit;\r
-  ModeDataSize = Size32Bits;\r
-  ModeAddrSize = Size64Bits;\r
-\r
-  InstructionData->Mode     = Mode;\r
-  InstructionData->DataSize = ModeDataSize;\r
-  InstructionData->AddrSize = ModeAddrSize;\r
-\r
-  InstructionData->Prefixes = InstructionData->Begin;\r
-\r
-  Byte = InstructionData->Prefixes;\r
-  for ( ; ; Byte++, InstructionData->PrefixSize++) {\r
-    //\r
-    // Check the 0x40 to 0x4F range using an if statement here since some\r
-    // compilers don't like the "case 0x40 ... 0x4F:" syntax. This avoids\r
-    // 16 case statements below.\r
-    //\r
-    if ((*Byte >= REX_PREFIX_START) && (*Byte <= REX_PREFIX_STOP)) {\r
-      InstructionData->RexPrefix.Uint8 = *Byte;\r
-      if ((*Byte & REX_64BIT_OPERAND_SIZE_MASK) != 0) {\r
-        InstructionData->DataSize = Size64Bits;\r
-      }\r
-\r
-      continue;\r
-    }\r
-\r
-    switch (*Byte) {\r
-      case OVERRIDE_SEGMENT_CS:\r
-      case OVERRIDE_SEGMENT_DS:\r
-      case OVERRIDE_SEGMENT_ES:\r
-      case OVERRIDE_SEGMENT_SS:\r
-        if (Mode != LongMode64Bit) {\r
-          InstructionData->SegmentSpecified = TRUE;\r
-          InstructionData->Segment          = (*Byte >> 3) & 3;\r
-        }\r
-\r
-        break;\r
-\r
-      case OVERRIDE_SEGMENT_FS:\r
-      case OVERRIDE_SEGMENT_GS:\r
-        InstructionData->SegmentSpecified = TRUE;\r
-        InstructionData->Segment          = *Byte & 7;\r
-        break;\r
-\r
-      case OVERRIDE_OPERAND_SIZE:\r
-        if (InstructionData->RexPrefix.Uint8 == 0) {\r
-          InstructionData->DataSize =\r
-            (Mode == LongMode64Bit)       ? Size16Bits :\r
-            (Mode == LongModeCompat32Bit) ? Size16Bits :\r
-            (Mode == LongModeCompat16Bit) ? Size32Bits : 0;\r
-        }\r
-\r
-        break;\r
-\r
-      case OVERRIDE_ADDRESS_SIZE:\r
-        InstructionData->AddrSize =\r
-          (Mode == LongMode64Bit)       ? Size32Bits :\r
-          (Mode == LongModeCompat32Bit) ? Size16Bits :\r
-          (Mode == LongModeCompat16Bit) ? Size32Bits : 0;\r
-        break;\r
-\r
-      case LOCK_PREFIX:\r
-        break;\r
-\r
-      case REPZ_PREFIX:\r
-        InstructionData->RepMode = RepZ;\r
-        break;\r
-\r
-      case REPNZ_PREFIX:\r
-        InstructionData->RepMode = RepNZ;\r
-        break;\r
-\r
-      default:\r
-        InstructionData->OpCodes    = Byte;\r
-        InstructionData->OpCodeSize = (*Byte == TWO_BYTE_OPCODE_ESCAPE) ? 2 : 1;\r
-\r
-        InstructionData->End          = Byte + InstructionData->OpCodeSize;\r
-        InstructionData->Displacement = InstructionData->End;\r
-        InstructionData->Immediate    = InstructionData->End;\r
-        return;\r
-    }\r
-  }\r
-}\r
-\r
-/**\r
-  Determine instruction length\r
-\r
-  Return the total length of the parsed instruction.\r
-\r
-  @param[in] InstructionData  Instruction parsing context\r
-\r
-  @return                     Length of parsed instruction\r
-\r
-**/\r
-STATIC\r
-UINT64\r
-InstructionLength (\r
-  IN SEV_ES_INSTRUCTION_DATA  *InstructionData\r
-  )\r
-{\r
-  return (UINT64)(InstructionData->End - InstructionData->Begin);\r
-}\r
-\r
-/**\r
-  Initialize the instruction parsing context.\r
-\r
-  Initialize the instruction parsing context, which includes decoding the\r
-  instruction prefixes.\r
-\r
-  @param[in, out] InstructionData  Instruction parsing context\r
-  @param[in]      Ghcb             Pointer to the Guest-Hypervisor Communication\r
-                                   Block\r
-  @param[in]      Regs             x64 processor context\r
-\r
-**/\r
-STATIC\r
-VOID\r
-InitInstructionData (\r
-  IN OUT SEV_ES_INSTRUCTION_DATA  *InstructionData,\r
-  IN     GHCB                     *Ghcb,\r
-  IN     EFI_SYSTEM_CONTEXT_X64   *Regs\r
-  )\r
-{\r
-  SetMem (InstructionData, sizeof (*InstructionData), 0);\r
-  InstructionData->Ghcb  = Ghcb;\r
-  InstructionData->Begin = (UINT8 *)Regs->Rip;\r
-  InstructionData->End   = (UINT8 *)Regs->Rip;\r
-\r
-  DecodePrefixes (Regs, InstructionData);\r
-}\r
-\r
-/**\r
-  Report an unsupported event to the hypervisor\r
-\r
-  Use the VMGEXIT support to report an unsupported event to the hypervisor.\r
-\r
-  @param[in] Ghcb             Pointer to the Guest-Hypervisor Communication\r
-                              Block\r
-  @param[in] Regs             x64 processor context\r
-  @param[in] InstructionData  Instruction parsing context\r
-\r
-  @return                     New exception value to propagate\r
-\r
-**/\r
-STATIC\r
-UINT64\r
-UnsupportedExit (\r
-  IN GHCB                     *Ghcb,\r
-  IN EFI_SYSTEM_CONTEXT_X64   *Regs,\r
-  IN SEV_ES_INSTRUCTION_DATA  *InstructionData\r
-  )\r
-{\r
-  UINT64  Status;\r
-\r
-  Status = VmgExit (Ghcb, SVM_EXIT_UNSUPPORTED, Regs->ExceptionData, 0);\r
-  if (Status == 0) {\r
-    GHCB_EVENT_INJECTION  Event;\r
-\r
-    Event.Uint64          = 0;\r
-    Event.Elements.Vector = GP_EXCEPTION;\r
-    Event.Elements.Type   = GHCB_EVENT_INJECTION_TYPE_EXCEPTION;\r
-    Event.Elements.Valid  = 1;\r
-\r
-    Status = Event.Uint64;\r
-  }\r
-\r
-  return Status;\r
-}\r
-\r
-/**\r
-  Validate that the MMIO memory access is not to encrypted memory.\r
-\r
-  Examine the pagetable entry for the memory specified. MMIO should not be\r
-  performed against encrypted memory. MMIO to the APIC page is always allowed.\r
-\r
-  @param[in] Ghcb           Pointer to the Guest-Hypervisor Communication Block\r
-  @param[in] MemoryAddress  Memory address to validate\r
-  @param[in] MemoryLength   Memory length to validate\r
-\r
-  @retval 0          Memory is not encrypted\r
-  @return            New exception value to propogate\r
-\r
-**/\r
-STATIC\r
-UINT64\r
-ValidateMmioMemory (\r
-  IN GHCB   *Ghcb,\r
-  IN UINTN  MemoryAddress,\r
-  IN UINTN  MemoryLength\r
-  )\r
-{\r
-  MEM_ENCRYPT_SEV_ADDRESS_RANGE_STATE  State;\r
-  GHCB_EVENT_INJECTION                 GpEvent;\r
-  UINTN                                Address;\r
-\r
-  //\r
-  // Allow APIC accesses (which will have the encryption bit set during\r
-  // SEC and PEI phases).\r
-  //\r
-  Address = MemoryAddress & ~(SIZE_4KB - 1);\r
-  if (Address == GetLocalApicBaseAddress ()) {\r
-    return 0;\r
-  }\r
-\r
-  State = MemEncryptSevGetAddressRangeState (\r
-            0,\r
-            MemoryAddress,\r
-            MemoryLength\r
-            );\r
-  if (State == MemEncryptSevAddressRangeUnencrypted) {\r
-    return 0;\r
-  }\r
-\r
-  //\r
-  // Any state other than unencrypted is an error, issue a #GP.\r
-  //\r
-  DEBUG ((\r
-    DEBUG_ERROR,\r
-    "MMIO using encrypted memory: %lx\n",\r
-    (UINT64)MemoryAddress\r
-    ));\r
-  GpEvent.Uint64          = 0;\r
-  GpEvent.Elements.Vector = GP_EXCEPTION;\r
-  GpEvent.Elements.Type   = GHCB_EVENT_INJECTION_TYPE_EXCEPTION;\r
-  GpEvent.Elements.Valid  = 1;\r
-\r
-  return GpEvent.Uint64;\r
-}\r
-\r
-/**\r
-  Handle an MMIO event.\r
-\r
-  Use the VMGEXIT instruction to handle either an MMIO read or an MMIO write.\r
-\r
-  @param[in, out] Ghcb             Pointer to the Guest-Hypervisor Communication\r
-                                   Block\r
-  @param[in, out] Regs             x64 processor context\r
-  @param[in, out] InstructionData  Instruction parsing context\r
-\r
-  @retval 0                        Event handled successfully\r
-  @return                          New exception value to propagate\r
-\r
-**/\r
-STATIC\r
-UINT64\r
-MmioExit (\r
-  IN OUT GHCB                     *Ghcb,\r
-  IN OUT EFI_SYSTEM_CONTEXT_X64   *Regs,\r
-  IN OUT SEV_ES_INSTRUCTION_DATA  *InstructionData\r
-  )\r
-{\r
-  UINT64  ExitInfo1, ExitInfo2, Status;\r
-  UINTN   Bytes;\r
-  UINT64  *Register;\r
-  UINT8   OpCode, SignByte;\r
-  UINTN   Address;\r
-\r
-  Bytes = 0;\r
-\r
-  OpCode = *(InstructionData->OpCodes);\r
-  if (OpCode == TWO_BYTE_OPCODE_ESCAPE) {\r
-    OpCode = *(InstructionData->OpCodes + 1);\r
-  }\r
-\r
-  switch (OpCode) {\r
-    //\r
-    // MMIO write (MOV reg/memX, regX)\r
-    //\r
-    case 0x88:\r
-      Bytes = 1;\r
-    //\r
-    // fall through\r
-    //\r
-    case 0x89:\r
-      DecodeModRm (Regs, InstructionData);\r
-      Bytes = ((Bytes != 0) ? Bytes :\r
-               (InstructionData->DataSize == Size16Bits) ? 2 :\r
-               (InstructionData->DataSize == Size32Bits) ? 4 :\r
-               (InstructionData->DataSize == Size64Bits) ? 8 :\r
-               0);\r
-\r
-      if (InstructionData->Ext.ModRm.Mod == 3) {\r
-        //\r
-        // NPF on two register operands???\r
-        //\r
-        return UnsupportedExit (Ghcb, Regs, InstructionData);\r
-      }\r
-\r
-      Status = ValidateMmioMemory (Ghcb, InstructionData->Ext.RmData, Bytes);\r
-      if (Status != 0) {\r
-        return Status;\r
-      }\r
-\r
-      ExitInfo1 = InstructionData->Ext.RmData;\r
-      ExitInfo2 = Bytes;\r
-      CopyMem (Ghcb->SharedBuffer, &InstructionData->Ext.RegData, Bytes);\r
-\r
-      Ghcb->SaveArea.SwScratch = (UINT64)Ghcb->SharedBuffer;\r
-      VmgSetOffsetValid (Ghcb, GhcbSwScratch);\r
-      Status = VmgExit (Ghcb, SVM_EXIT_MMIO_WRITE, ExitInfo1, ExitInfo2);\r
-      if (Status != 0) {\r
-        return Status;\r
-      }\r
-\r
-      break;\r
-\r
-    //\r
-    // MMIO write (MOV moffsetX, aX)\r
-    //\r
-    case 0xA2:\r
-      Bytes = 1;\r
-    //\r
-    // fall through\r
-    //\r
-    case 0xA3:\r
-      Bytes = ((Bytes != 0) ? Bytes :\r
-               (InstructionData->DataSize == Size16Bits) ? 2 :\r
-               (InstructionData->DataSize == Size32Bits) ? 4 :\r
-               (InstructionData->DataSize == Size64Bits) ? 8 :\r
-               0);\r
-\r
-      InstructionData->ImmediateSize = (UINTN)(1 << InstructionData->AddrSize);\r
-      InstructionData->End          += InstructionData->ImmediateSize;\r
-\r
-      //\r
-      // This code is X64 only, so a possible 8-byte copy to a UINTN is ok.\r
-      // Use a STATIC_ASSERT to be certain the code is being built as X64.\r
-      //\r
-      STATIC_ASSERT (\r
-        sizeof (UINTN) == sizeof (UINT64),\r
-        "sizeof (UINTN) != sizeof (UINT64), this file must be built as X64"\r
-        );\r
-\r
-      Address = 0;\r
-      CopyMem (\r
-        &Address,\r
-        InstructionData->Immediate,\r
-        InstructionData->ImmediateSize\r
-        );\r
-\r
-      Status = ValidateMmioMemory (Ghcb, Address, Bytes);\r
-      if (Status != 0) {\r
-        return Status;\r
-      }\r
-\r
-      ExitInfo1 = Address;\r
-      ExitInfo2 = Bytes;\r
-      CopyMem (Ghcb->SharedBuffer, &Regs->Rax, Bytes);\r
-\r
-      Ghcb->SaveArea.SwScratch = (UINT64)Ghcb->SharedBuffer;\r
-      VmgSetOffsetValid (Ghcb, GhcbSwScratch);\r
-      Status = VmgExit (Ghcb, SVM_EXIT_MMIO_WRITE, ExitInfo1, ExitInfo2);\r
-      if (Status != 0) {\r
-        return Status;\r
-      }\r
-\r
-      break;\r
-\r
-    //\r
-    // MMIO write (MOV reg/memX, immX)\r
-    //\r
-    case 0xC6:\r
-      Bytes = 1;\r
-    //\r
-    // fall through\r
-    //\r
-    case 0xC7:\r
-      DecodeModRm (Regs, InstructionData);\r
-      Bytes = ((Bytes != 0) ? Bytes :\r
-               (InstructionData->DataSize == Size16Bits) ? 2 :\r
-               (InstructionData->DataSize == Size32Bits) ? 4 :\r
-               0);\r
-\r
-      InstructionData->ImmediateSize = Bytes;\r
-      InstructionData->End          += Bytes;\r
-\r
-      Status = ValidateMmioMemory (Ghcb, InstructionData->Ext.RmData, Bytes);\r
-      if (Status != 0) {\r
-        return Status;\r
-      }\r
-\r
-      ExitInfo1 = InstructionData->Ext.RmData;\r
-      ExitInfo2 = Bytes;\r
-      CopyMem (Ghcb->SharedBuffer, InstructionData->Immediate, Bytes);\r
-\r
-      Ghcb->SaveArea.SwScratch = (UINT64)Ghcb->SharedBuffer;\r
-      VmgSetOffsetValid (Ghcb, GhcbSwScratch);\r
-      Status = VmgExit (Ghcb, SVM_EXIT_MMIO_WRITE, ExitInfo1, ExitInfo2);\r
-      if (Status != 0) {\r
-        return Status;\r
-      }\r
-\r
-      break;\r
-\r
-    //\r
-    // MMIO read (MOV regX, reg/memX)\r
-    //\r
-    case 0x8A:\r
-      Bytes = 1;\r
-    //\r
-    // fall through\r
-    //\r
-    case 0x8B:\r
-      DecodeModRm (Regs, InstructionData);\r
-      Bytes = ((Bytes != 0) ? Bytes :\r
-               (InstructionData->DataSize == Size16Bits) ? 2 :\r
-               (InstructionData->DataSize == Size32Bits) ? 4 :\r
-               (InstructionData->DataSize == Size64Bits) ? 8 :\r
-               0);\r
-      if (InstructionData->Ext.ModRm.Mod == 3) {\r
-        //\r
-        // NPF on two register operands???\r
-        //\r
-        return UnsupportedExit (Ghcb, Regs, InstructionData);\r
-      }\r
-\r
-      Status = ValidateMmioMemory (Ghcb, InstructionData->Ext.RmData, Bytes);\r
-      if (Status != 0) {\r
-        return Status;\r
-      }\r
-\r
-      ExitInfo1 = InstructionData->Ext.RmData;\r
-      ExitInfo2 = Bytes;\r
-\r
-      Ghcb->SaveArea.SwScratch = (UINT64)Ghcb->SharedBuffer;\r
-      VmgSetOffsetValid (Ghcb, GhcbSwScratch);\r
-      Status = VmgExit (Ghcb, SVM_EXIT_MMIO_READ, ExitInfo1, ExitInfo2);\r
-      if (Status != 0) {\r
-        return Status;\r
-      }\r
-\r
-      Register = GetRegisterPointer (Regs, InstructionData->Ext.ModRm.Reg);\r
-      if (Bytes == 4) {\r
-        //\r
-        // Zero-extend for 32-bit operation\r
-        //\r
-        *Register = 0;\r
-      }\r
-\r
-      CopyMem (Register, Ghcb->SharedBuffer, Bytes);\r
-      break;\r
-\r
-    //\r
-    // MMIO read (MOV aX, moffsetX)\r
-    //\r
-    case 0xA0:\r
-      Bytes = 1;\r
-    //\r
-    // fall through\r
-    //\r
-    case 0xA1:\r
-      Bytes = ((Bytes != 0) ? Bytes :\r
-               (InstructionData->DataSize == Size16Bits) ? 2 :\r
-               (InstructionData->DataSize == Size32Bits) ? 4 :\r
-               (InstructionData->DataSize == Size64Bits) ? 8 :\r
-               0);\r
-\r
-      InstructionData->ImmediateSize = (UINTN)(1 << InstructionData->AddrSize);\r
-      InstructionData->End          += InstructionData->ImmediateSize;\r
-\r
-      //\r
-      // This code is X64 only, so a possible 8-byte copy to a UINTN is ok.\r
-      // Use a STATIC_ASSERT to be certain the code is being built as X64.\r
-      //\r
-      STATIC_ASSERT (\r
-        sizeof (UINTN) == sizeof (UINT64),\r
-        "sizeof (UINTN) != sizeof (UINT64), this file must be built as X64"\r
-        );\r
-\r
-      Address = 0;\r
-      CopyMem (\r
-        &Address,\r
-        InstructionData->Immediate,\r
-        InstructionData->ImmediateSize\r
-        );\r
-\r
-      Status = ValidateMmioMemory (Ghcb, Address, Bytes);\r
-      if (Status != 0) {\r
-        return Status;\r
-      }\r
-\r
-      ExitInfo1 = Address;\r
-      ExitInfo2 = Bytes;\r
-\r
-      Ghcb->SaveArea.SwScratch = (UINT64)Ghcb->SharedBuffer;\r
-      VmgSetOffsetValid (Ghcb, GhcbSwScratch);\r
-      Status = VmgExit (Ghcb, SVM_EXIT_MMIO_READ, ExitInfo1, ExitInfo2);\r
-      if (Status != 0) {\r
-        return Status;\r
-      }\r
-\r
-      if (Bytes == 4) {\r
-        //\r
-        // Zero-extend for 32-bit operation\r
-        //\r
-        Regs->Rax = 0;\r
-      }\r
-\r
-      CopyMem (&Regs->Rax, Ghcb->SharedBuffer, Bytes);\r
-      break;\r
-\r
-    //\r
-    // MMIO read w/ zero-extension ((MOVZX regX, reg/memX)\r
-    //\r
-    case 0xB6:\r
-      Bytes = 1;\r
-    //\r
-    // fall through\r
-    //\r
-    case 0xB7:\r
-      DecodeModRm (Regs, InstructionData);\r
-      Bytes = (Bytes != 0) ? Bytes : 2;\r
-\r
-      Status = ValidateMmioMemory (Ghcb, InstructionData->Ext.RmData, Bytes);\r
-      if (Status != 0) {\r
-        return Status;\r
-      }\r
-\r
-      ExitInfo1 = InstructionData->Ext.RmData;\r
-      ExitInfo2 = Bytes;\r
-\r
-      Ghcb->SaveArea.SwScratch = (UINT64)Ghcb->SharedBuffer;\r
-      VmgSetOffsetValid (Ghcb, GhcbSwScratch);\r
-      Status = VmgExit (Ghcb, SVM_EXIT_MMIO_READ, ExitInfo1, ExitInfo2);\r
-      if (Status != 0) {\r
-        return Status;\r
-      }\r
-\r
-      Register = GetRegisterPointer (Regs, InstructionData->Ext.ModRm.Reg);\r
-      SetMem (Register, (UINTN)(1 << InstructionData->DataSize), 0);\r
-      CopyMem (Register, Ghcb->SharedBuffer, Bytes);\r
-      break;\r
-\r
-    //\r
-    // MMIO read w/ sign-extension (MOVSX regX, reg/memX)\r
-    //\r
-    case 0xBE:\r
-      Bytes = 1;\r
-    //\r
-    // fall through\r
-    //\r
-    case 0xBF:\r
-      DecodeModRm (Regs, InstructionData);\r
-      Bytes = (Bytes != 0) ? Bytes : 2;\r
-\r
-      Status = ValidateMmioMemory (Ghcb, InstructionData->Ext.RmData, Bytes);\r
-      if (Status != 0) {\r
-        return Status;\r
-      }\r
-\r
-      ExitInfo1 = InstructionData->Ext.RmData;\r
-      ExitInfo2 = Bytes;\r
-\r
-      Ghcb->SaveArea.SwScratch = (UINT64)Ghcb->SharedBuffer;\r
-      VmgSetOffsetValid (Ghcb, GhcbSwScratch);\r
-      Status = VmgExit (Ghcb, SVM_EXIT_MMIO_READ, ExitInfo1, ExitInfo2);\r
-      if (Status != 0) {\r
-        return Status;\r
-      }\r
-\r
-      if (Bytes == 1) {\r
-        UINT8  *Data;\r
-\r
-        Data     = (UINT8 *)Ghcb->SharedBuffer;\r
-        SignByte = ((*Data & BIT7) != 0) ? 0xFF : 0x00;\r
-      } else {\r
-        UINT16  *Data;\r
-\r
-        Data     = (UINT16 *)Ghcb->SharedBuffer;\r
-        SignByte = ((*Data & BIT15) != 0) ? 0xFF : 0x00;\r
-      }\r
-\r
-      Register = GetRegisterPointer (Regs, InstructionData->Ext.ModRm.Reg);\r
-      SetMem (Register, (UINTN)(1 << InstructionData->DataSize), SignByte);\r
-      CopyMem (Register, Ghcb->SharedBuffer, Bytes);\r
-      break;\r
-\r
-    default:\r
-      DEBUG ((DEBUG_ERROR, "Invalid MMIO opcode (%x)\n", OpCode));\r
-      Status = GP_EXCEPTION;\r
-      ASSERT (FALSE);\r
-  }\r
-\r
-  return Status;\r
-}\r
-\r
-/**\r
-  Handle a MWAIT event.\r
-\r
-  Use the VMGEXIT instruction to handle a MWAIT event.\r
-\r
-  @param[in, out] Ghcb             Pointer to the Guest-Hypervisor Communication\r
-                                   Block\r
-  @param[in, out] Regs             x64 processor context\r
-  @param[in]      InstructionData  Instruction parsing context\r
-\r
-  @retval 0                        Event handled successfully\r
-  @return                          New exception value to propagate\r
-\r
-**/\r
-STATIC\r
-UINT64\r
-MwaitExit (\r
-  IN OUT GHCB                     *Ghcb,\r
-  IN OUT EFI_SYSTEM_CONTEXT_X64   *Regs,\r
-  IN     SEV_ES_INSTRUCTION_DATA  *InstructionData\r
-  )\r
-{\r
-  DecodeModRm (Regs, InstructionData);\r
-\r
-  Ghcb->SaveArea.Rax = Regs->Rax;\r
-  VmgSetOffsetValid (Ghcb, GhcbRax);\r
-  Ghcb->SaveArea.Rcx = Regs->Rcx;\r
-  VmgSetOffsetValid (Ghcb, GhcbRcx);\r
-\r
-  return VmgExit (Ghcb, SVM_EXIT_MWAIT, 0, 0);\r
-}\r
-\r
-/**\r
-  Handle a MONITOR event.\r
-\r
-  Use the VMGEXIT instruction to handle a MONITOR event.\r
-\r
-  @param[in, out] Ghcb             Pointer to the Guest-Hypervisor Communication\r
-                                   Block\r
-  @param[in, out] Regs             x64 processor context\r
-  @param[in]      InstructionData  Instruction parsing context\r
-\r
-  @retval 0                        Event handled successfully\r
-  @return                          New exception value to propagate\r
-\r
-**/\r
-STATIC\r
-UINT64\r
-MonitorExit (\r
-  IN OUT GHCB                     *Ghcb,\r
-  IN OUT EFI_SYSTEM_CONTEXT_X64   *Regs,\r
-  IN     SEV_ES_INSTRUCTION_DATA  *InstructionData\r
-  )\r
-{\r
-  DecodeModRm (Regs, InstructionData);\r
-\r
-  Ghcb->SaveArea.Rax = Regs->Rax;  // Identity mapped, so VA = PA\r
-  VmgSetOffsetValid (Ghcb, GhcbRax);\r
-  Ghcb->SaveArea.Rcx = Regs->Rcx;\r
-  VmgSetOffsetValid (Ghcb, GhcbRcx);\r
-  Ghcb->SaveArea.Rdx = Regs->Rdx;\r
-  VmgSetOffsetValid (Ghcb, GhcbRdx);\r
-\r
-  return VmgExit (Ghcb, SVM_EXIT_MONITOR, 0, 0);\r
-}\r
-\r
-/**\r
-  Handle a WBINVD event.\r
-\r
-  Use the VMGEXIT instruction to handle a WBINVD event.\r
-\r
-  @param[in, out] Ghcb             Pointer to the Guest-Hypervisor Communication\r
-                                   Block\r
-  @param[in, out] Regs             x64 processor context\r
-  @param[in]      InstructionData  Instruction parsing context\r
-\r
-  @retval 0                        Event handled successfully\r
-  @return                          New exception value to propagate\r
-\r
-**/\r
-STATIC\r
-UINT64\r
-WbinvdExit (\r
-  IN OUT GHCB                     *Ghcb,\r
-  IN OUT EFI_SYSTEM_CONTEXT_X64   *Regs,\r
-  IN     SEV_ES_INSTRUCTION_DATA  *InstructionData\r
-  )\r
-{\r
-  return VmgExit (Ghcb, SVM_EXIT_WBINVD, 0, 0);\r
-}\r
-\r
-/**\r
-  Handle a RDTSCP event.\r
-\r
-  Use the VMGEXIT instruction to handle a RDTSCP event.\r
-\r
-  @param[in, out] Ghcb             Pointer to the Guest-Hypervisor Communication\r
-                                   Block\r
-  @param[in, out] Regs             x64 processor context\r
-  @param[in]      InstructionData  Instruction parsing context\r
-\r
-  @retval 0                        Event handled successfully\r
-  @return                          New exception value to propagate\r
-\r
-**/\r
-STATIC\r
-UINT64\r
-RdtscpExit (\r
-  IN OUT GHCB                     *Ghcb,\r
-  IN OUT EFI_SYSTEM_CONTEXT_X64   *Regs,\r
-  IN     SEV_ES_INSTRUCTION_DATA  *InstructionData\r
-  )\r
-{\r
-  UINT64  Status;\r
-\r
-  DecodeModRm (Regs, InstructionData);\r
-\r
-  Status = VmgExit (Ghcb, SVM_EXIT_RDTSCP, 0, 0);\r
-  if (Status != 0) {\r
-    return Status;\r
-  }\r
-\r
-  if (!VmgIsOffsetValid (Ghcb, GhcbRax) ||\r
-      !VmgIsOffsetValid (Ghcb, GhcbRcx) ||\r
-      !VmgIsOffsetValid (Ghcb, GhcbRdx))\r
-  {\r
-    return UnsupportedExit (Ghcb, Regs, InstructionData);\r
-  }\r
-\r
-  Regs->Rax = Ghcb->SaveArea.Rax;\r
-  Regs->Rcx = Ghcb->SaveArea.Rcx;\r
-  Regs->Rdx = Ghcb->SaveArea.Rdx;\r
-\r
-  return 0;\r
-}\r
-\r
-/**\r
-  Handle a VMMCALL event.\r
-\r
-  Use the VMGEXIT instruction to handle a VMMCALL event.\r
-\r
-  @param[in, out] Ghcb             Pointer to the Guest-Hypervisor Communication\r
-                                   Block\r
-  @param[in, out] Regs             x64 processor context\r
-  @param[in]      InstructionData  Instruction parsing context\r
-\r
-  @retval 0                        Event handled successfully\r
-  @return                          New exception value to propagate\r
-\r
-**/\r
-STATIC\r
-UINT64\r
-VmmCallExit (\r
-  IN OUT GHCB                     *Ghcb,\r
-  IN OUT EFI_SYSTEM_CONTEXT_X64   *Regs,\r
-  IN     SEV_ES_INSTRUCTION_DATA  *InstructionData\r
-  )\r
-{\r
-  UINT64  Status;\r
-\r
-  DecodeModRm (Regs, InstructionData);\r
-\r
-  Ghcb->SaveArea.Rax = Regs->Rax;\r
-  VmgSetOffsetValid (Ghcb, GhcbRax);\r
-  Ghcb->SaveArea.Cpl = (UINT8)(Regs->Cs & 0x3);\r
-  VmgSetOffsetValid (Ghcb, GhcbCpl);\r
-\r
-  Status = VmgExit (Ghcb, SVM_EXIT_VMMCALL, 0, 0);\r
-  if (Status != 0) {\r
-    return Status;\r
-  }\r
-\r
-  if (!VmgIsOffsetValid (Ghcb, GhcbRax)) {\r
-    return UnsupportedExit (Ghcb, Regs, InstructionData);\r
-  }\r
-\r
-  Regs->Rax = Ghcb->SaveArea.Rax;\r
-\r
-  return 0;\r
-}\r
-\r
-/**\r
-  Handle an MSR event.\r
-\r
-  Use the VMGEXIT instruction to handle either a RDMSR or WRMSR event.\r
-\r
-  @param[in, out] Ghcb             Pointer to the Guest-Hypervisor Communication\r
-                                   Block\r
-  @param[in, out] Regs             x64 processor context\r
-  @param[in]      InstructionData  Instruction parsing context\r
-\r
-  @retval 0                        Event handled successfully\r
-  @return                          New exception value to propagate\r
-\r
-**/\r
-STATIC\r
-UINT64\r
-MsrExit (\r
-  IN OUT GHCB                     *Ghcb,\r
-  IN OUT EFI_SYSTEM_CONTEXT_X64   *Regs,\r
-  IN     SEV_ES_INSTRUCTION_DATA  *InstructionData\r
-  )\r
-{\r
-  UINT64  ExitInfo1, Status;\r
-\r
-  ExitInfo1 = 0;\r
-\r
-  switch (*(InstructionData->OpCodes + 1)) {\r
-    case 0x30: // WRMSR\r
-      ExitInfo1          = 1;\r
-      Ghcb->SaveArea.Rax = Regs->Rax;\r
-      VmgSetOffsetValid (Ghcb, GhcbRax);\r
-      Ghcb->SaveArea.Rdx = Regs->Rdx;\r
-      VmgSetOffsetValid (Ghcb, GhcbRdx);\r
-    //\r
-    // fall through\r
-    //\r
-    case 0x32: // RDMSR\r
-      Ghcb->SaveArea.Rcx = Regs->Rcx;\r
-      VmgSetOffsetValid (Ghcb, GhcbRcx);\r
-      break;\r
-    default:\r
-      return UnsupportedExit (Ghcb, Regs, InstructionData);\r
-  }\r
-\r
-  Status = VmgExit (Ghcb, SVM_EXIT_MSR, ExitInfo1, 0);\r
-  if (Status != 0) {\r
-    return Status;\r
-  }\r
-\r
-  if (ExitInfo1 == 0) {\r
-    if (!VmgIsOffsetValid (Ghcb, GhcbRax) ||\r
-        !VmgIsOffsetValid (Ghcb, GhcbRdx))\r
-    {\r
-      return UnsupportedExit (Ghcb, Regs, InstructionData);\r
-    }\r
-\r
-    Regs->Rax = Ghcb->SaveArea.Rax;\r
-    Regs->Rdx = Ghcb->SaveArea.Rdx;\r
-  }\r
-\r
-  return 0;\r
-}\r
-\r
-/**\r
-  Build the IOIO event information.\r
-\r
-  The IOIO event information identifies the type of IO operation to be performed\r
-  by the hypervisor. Build this information based on the instruction data.\r
-\r
-  @param[in]       Regs             x64 processor context\r
-  @param[in, out]  InstructionData  Instruction parsing context\r
-\r
-  @return                           IOIO event information value\r
-\r
-**/\r
-STATIC\r
-UINT64\r
-IoioExitInfo (\r
-  IN     EFI_SYSTEM_CONTEXT_X64   *Regs,\r
-  IN OUT SEV_ES_INSTRUCTION_DATA  *InstructionData\r
-  )\r
-{\r
-  UINT64  ExitInfo;\r
-\r
-  ExitInfo = 0;\r
-\r
-  switch (*(InstructionData->OpCodes)) {\r
-    //\r
-    // INS opcodes\r
-    //\r
-    case 0x6C:\r
-    case 0x6D:\r
-      ExitInfo |= IOIO_TYPE_INS;\r
-      ExitInfo |= IOIO_SEG_ES;\r
-      ExitInfo |= ((Regs->Rdx & 0xffff) << 16);\r
-      break;\r
-\r
-    //\r
-    // OUTS opcodes\r
-    //\r
-    case 0x6E:\r
-    case 0x6F:\r
-      ExitInfo |= IOIO_TYPE_OUTS;\r
-      ExitInfo |= IOIO_SEG_DS;\r
-      ExitInfo |= ((Regs->Rdx & 0xffff) << 16);\r
-      break;\r
-\r
-    //\r
-    // IN immediate opcodes\r
-    //\r
-    case 0xE4:\r
-    case 0xE5:\r
-      InstructionData->ImmediateSize = 1;\r
-      InstructionData->End++;\r
-      ExitInfo |= IOIO_TYPE_IN;\r
-      ExitInfo |= ((*(InstructionData->OpCodes + 1)) << 16);\r
-      break;\r
-\r
-    //\r
-    // OUT immediate opcodes\r
-    //\r
-    case 0xE6:\r
-    case 0xE7:\r
-      InstructionData->ImmediateSize = 1;\r
-      InstructionData->End++;\r
-      ExitInfo |= IOIO_TYPE_OUT;\r
-      ExitInfo |= ((*(InstructionData->OpCodes + 1)) << 16) | IOIO_TYPE_OUT;\r
-      break;\r
-\r
-    //\r
-    // IN register opcodes\r
-    //\r
-    case 0xEC:\r
-    case 0xED:\r
-      ExitInfo |= IOIO_TYPE_IN;\r
-      ExitInfo |= ((Regs->Rdx & 0xffff) << 16);\r
-      break;\r
-\r
-    //\r
-    // OUT register opcodes\r
-    //\r
-    case 0xEE:\r
-    case 0xEF:\r
-      ExitInfo |= IOIO_TYPE_OUT;\r
-      ExitInfo |= ((Regs->Rdx & 0xffff) << 16);\r
-      break;\r
-\r
-    default:\r
-      return 0;\r
-  }\r
-\r
-  switch (*(InstructionData->OpCodes)) {\r
-    //\r
-    // Single-byte opcodes\r
-    //\r
-    case 0x6C:\r
-    case 0x6E:\r
-    case 0xE4:\r
-    case 0xE6:\r
-    case 0xEC:\r
-    case 0xEE:\r
-      ExitInfo |= IOIO_DATA_8;\r
-      break;\r
-\r
-    //\r
-    // Length determined by instruction parsing\r
-    //\r
-    default:\r
-      ExitInfo |= (InstructionData->DataSize == Size16Bits) ? IOIO_DATA_16\r
-                                                          : IOIO_DATA_32;\r
-  }\r
-\r
-  switch (InstructionData->AddrSize) {\r
-    case Size16Bits:\r
-      ExitInfo |= IOIO_ADDR_16;\r
-      break;\r
-\r
-    case Size32Bits:\r
-      ExitInfo |= IOIO_ADDR_32;\r
-      break;\r
-\r
-    case Size64Bits:\r
-      ExitInfo |= IOIO_ADDR_64;\r
-      break;\r
-\r
-    default:\r
-      break;\r
-  }\r
-\r
-  if (InstructionData->RepMode != 0) {\r
-    ExitInfo |= IOIO_REP;\r
-  }\r
-\r
-  return ExitInfo;\r
-}\r
-\r
-/**\r
-  Handle an IOIO event.\r
-\r
-  Use the VMGEXIT instruction to handle an IOIO event.\r
-\r
-  @param[in, out] Ghcb             Pointer to the Guest-Hypervisor Communication\r
-                                   Block\r
-  @param[in, out] Regs             x64 processor context\r
-  @param[in]      InstructionData  Instruction parsing context\r
-\r
-  @retval 0                        Event handled successfully\r
-  @return                          New exception value to propagate\r
-\r
-**/\r
-STATIC\r
-UINT64\r
-IoioExit (\r
-  IN OUT GHCB                     *Ghcb,\r
-  IN OUT EFI_SYSTEM_CONTEXT_X64   *Regs,\r
-  IN     SEV_ES_INSTRUCTION_DATA  *InstructionData\r
-  )\r
-{\r
-  UINT64   ExitInfo1, ExitInfo2, Status;\r
-  BOOLEAN  IsString;\r
-\r
-  ExitInfo1 = IoioExitInfo (Regs, InstructionData);\r
-  if (ExitInfo1 == 0) {\r
-    return UnsupportedExit (Ghcb, Regs, InstructionData);\r
-  }\r
-\r
-  IsString = ((ExitInfo1 & IOIO_TYPE_STR) != 0) ? TRUE : FALSE;\r
-  if (IsString) {\r
-    UINTN  IoBytes, VmgExitBytes;\r
-    UINTN  GhcbCount, OpCount;\r
-\r
-    Status = 0;\r
-\r
-    IoBytes   = IOIO_DATA_BYTES (ExitInfo1);\r
-    GhcbCount = sizeof (Ghcb->SharedBuffer) / IoBytes;\r
-\r
-    OpCount = ((ExitInfo1 & IOIO_REP) != 0) ? Regs->Rcx : 1;\r
-    while (OpCount != 0) {\r
-      ExitInfo2    = MIN (OpCount, GhcbCount);\r
-      VmgExitBytes = ExitInfo2 * IoBytes;\r
-\r
-      if ((ExitInfo1 & IOIO_TYPE_IN) == 0) {\r
-        CopyMem (Ghcb->SharedBuffer, (VOID *)Regs->Rsi, VmgExitBytes);\r
-        Regs->Rsi += VmgExitBytes;\r
-      }\r
-\r
-      Ghcb->SaveArea.SwScratch = (UINT64)Ghcb->SharedBuffer;\r
-      VmgSetOffsetValid (Ghcb, GhcbSwScratch);\r
-      Status = VmgExit (Ghcb, SVM_EXIT_IOIO_PROT, ExitInfo1, ExitInfo2);\r
-      if (Status != 0) {\r
-        return Status;\r
-      }\r
-\r
-      if ((ExitInfo1 & IOIO_TYPE_IN) != 0) {\r
-        CopyMem ((VOID *)Regs->Rdi, Ghcb->SharedBuffer, VmgExitBytes);\r
-        Regs->Rdi += VmgExitBytes;\r
-      }\r
-\r
-      if ((ExitInfo1 & IOIO_REP) != 0) {\r
-        Regs->Rcx -= ExitInfo2;\r
-      }\r
-\r
-      OpCount -= ExitInfo2;\r
-    }\r
-  } else {\r
-    if ((ExitInfo1 & IOIO_TYPE_IN) != 0) {\r
-      Ghcb->SaveArea.Rax = 0;\r
-    } else {\r
-      CopyMem (&Ghcb->SaveArea.Rax, &Regs->Rax, IOIO_DATA_BYTES (ExitInfo1));\r
-    }\r
-\r
-    VmgSetOffsetValid (Ghcb, GhcbRax);\r
-\r
-    Status = VmgExit (Ghcb, SVM_EXIT_IOIO_PROT, ExitInfo1, 0);\r
-    if (Status != 0) {\r
-      return Status;\r
-    }\r
-\r
-    if ((ExitInfo1 & IOIO_TYPE_IN) != 0) {\r
-      if (!VmgIsOffsetValid (Ghcb, GhcbRax)) {\r
-        return UnsupportedExit (Ghcb, Regs, InstructionData);\r
-      }\r
-\r
-      CopyMem (&Regs->Rax, &Ghcb->SaveArea.Rax, IOIO_DATA_BYTES (ExitInfo1));\r
-    }\r
-  }\r
-\r
-  return 0;\r
-}\r
-\r
-/**\r
-  Handle a INVD event.\r
-\r
-  Use the VMGEXIT instruction to handle a INVD event.\r
-\r
-  @param[in, out] Ghcb             Pointer to the Guest-Hypervisor Communication\r
-                                   Block\r
-  @param[in, out] Regs             x64 processor context\r
-  @param[in]      InstructionData  Instruction parsing context\r
-\r
-  @retval 0                        Event handled successfully\r
-  @return                          New exception value to propagate\r
-\r
-**/\r
-STATIC\r
-UINT64\r
-InvdExit (\r
-  IN OUT GHCB                     *Ghcb,\r
-  IN OUT EFI_SYSTEM_CONTEXT_X64   *Regs,\r
-  IN     SEV_ES_INSTRUCTION_DATA  *InstructionData\r
-  )\r
-{\r
-  return VmgExit (Ghcb, SVM_EXIT_INVD, 0, 0);\r
-}\r
-\r
-/**\r
-  Fetch CPUID leaf/function via hypervisor/VMGEXIT.\r
-\r
-  @param[in, out] Ghcb         Pointer to the Guest-Hypervisor Communication\r
-                               Block\r
-  @param[in]      EaxIn        EAX input for cpuid instruction\r
-  @param[in]      EcxIn        ECX input for cpuid instruction\r
-  @param[in]      Xcr0In       XCR0 at time of cpuid instruction\r
-  @param[in, out] Eax          Pointer to store leaf's EAX value\r
-  @param[in, out] Ebx          Pointer to store leaf's EBX value\r
-  @param[in, out] Ecx          Pointer to store leaf's ECX value\r
-  @param[in, out] Edx          Pointer to store leaf's EDX value\r
-  @param[in, out] Status       Pointer to store status from VMGEXIT (always 0\r
-                               unless return value indicates failure)\r
-  @param[in, out] Unsupported  Pointer to store indication of unsupported\r
-                               VMGEXIT (always false unless return value\r
-                               indicates failure)\r
-\r
-  @retval TRUE                 CPUID leaf fetch successfully.\r
-  @retval FALSE                Error occurred while fetching CPUID leaf. Callers\r
-                               should Status and Unsupported and handle\r
-                               accordingly if they indicate a more precise\r
-                               error condition.\r
-\r
-**/\r
-STATIC\r
-BOOLEAN\r
-GetCpuidHyp (\r
-  IN OUT GHCB     *Ghcb,\r
-  IN     UINT32   EaxIn,\r
-  IN     UINT32   EcxIn,\r
-  IN     UINT64   XCr0,\r
-  IN OUT UINT32   *Eax,\r
-  IN OUT UINT32   *Ebx,\r
-  IN OUT UINT32   *Ecx,\r
-  IN OUT UINT32   *Edx,\r
-  IN OUT UINT64   *Status,\r
-  IN OUT BOOLEAN  *UnsupportedExit\r
-  )\r
-{\r
-  *UnsupportedExit   = FALSE;\r
-  Ghcb->SaveArea.Rax = EaxIn;\r
-  VmgSetOffsetValid (Ghcb, GhcbRax);\r
-  Ghcb->SaveArea.Rcx = EcxIn;\r
-  VmgSetOffsetValid (Ghcb, GhcbRcx);\r
-  if (EaxIn == CPUID_EXTENDED_STATE) {\r
-    Ghcb->SaveArea.XCr0 = XCr0;\r
-    VmgSetOffsetValid (Ghcb, GhcbXCr0);\r
-  }\r
-\r
-  *Status = VmgExit (Ghcb, SVM_EXIT_CPUID, 0, 0);\r
-  if (*Status != 0) {\r
-    return FALSE;\r
-  }\r
-\r
-  if (!VmgIsOffsetValid (Ghcb, GhcbRax) ||\r
-      !VmgIsOffsetValid (Ghcb, GhcbRbx) ||\r
-      !VmgIsOffsetValid (Ghcb, GhcbRcx) ||\r
-      !VmgIsOffsetValid (Ghcb, GhcbRdx))\r
-  {\r
-    *UnsupportedExit = TRUE;\r
-    return FALSE;\r
-  }\r
-\r
-  if (Eax) {\r
-    *Eax = (UINT32)(UINTN)Ghcb->SaveArea.Rax;\r
-  }\r
-\r
-  if (Ebx) {\r
-    *Ebx = (UINT32)(UINTN)Ghcb->SaveArea.Rbx;\r
-  }\r
-\r
-  if (Ecx) {\r
-    *Ecx = (UINT32)(UINTN)Ghcb->SaveArea.Rcx;\r
-  }\r
-\r
-  if (Edx) {\r
-    *Edx = (UINT32)(UINTN)Ghcb->SaveArea.Rdx;\r
-  }\r
-\r
-  return TRUE;\r
-}\r
-\r
-/**\r
-  Check if SEV-SNP enabled.\r
-\r
-  @retval TRUE      SEV-SNP is enabled.\r
-  @retval FALSE     SEV-SNP is disabled.\r
-\r
-**/\r
-STATIC\r
-BOOLEAN\r
-SnpEnabled (\r
-  VOID\r
-  )\r
-{\r
-  MSR_SEV_STATUS_REGISTER  Msr;\r
-\r
-  Msr.Uint32 = AsmReadMsr32 (MSR_SEV_STATUS);\r
-\r
-  return !!Msr.Bits.SevSnpBit;\r
-}\r
-\r
-/**\r
-  Calculate the total XSAVE area size for enabled XSAVE areas\r
-\r
-  @param[in]      XFeaturesEnabled  Bit-mask of enabled XSAVE features/areas as\r
-                                    indicated by XCR0/MSR_IA32_XSS bits\r
-  @param[in]      XSaveBaseSize     Base/legacy XSAVE area size (e.g. when\r
-                                    XCR0 is 1)\r
-  @param[in, out] XSaveSize         Pointer to storage for calculated XSAVE area\r
-                                    size\r
-  @param[in]      Compacted         Whether or not the calculation is for the\r
-                                    normal XSAVE area size (leaf 0xD,0x0,EBX) or\r
-                                    compacted XSAVE area size (leaf 0xD,0x1,EBX)\r
-\r
-\r
-  @retval TRUE                      XSAVE size calculation was successful.\r
-  @retval FALSE                     XSAVE size calculation was unsuccessful.\r
-**/\r
-STATIC\r
-BOOLEAN\r
-GetCpuidXSaveSize (\r
-  IN     UINT64   XFeaturesEnabled,\r
-  IN     UINT32   XSaveBaseSize,\r
-  IN OUT UINT32   *XSaveSize,\r
-  IN     BOOLEAN  Compacted\r
-  )\r
-{\r
-  SEV_SNP_CPUID_INFO  *CpuidInfo;\r
-  UINT64              XFeaturesFound = 0;\r
-  UINT32              Idx;\r
-\r
-  *XSaveSize = XSaveBaseSize;\r
-  CpuidInfo  = (SEV_SNP_CPUID_INFO *)(UINT64)PcdGet32 (PcdOvmfCpuidBase);\r
-\r
-  for (Idx = 0; Idx < CpuidInfo->Count; Idx++) {\r
-    SEV_SNP_CPUID_FUNCTION  *CpuidFn = &CpuidInfo->function[Idx];\r
-\r
-    if (!((CpuidFn->EaxIn == 0xD) &&\r
-          ((CpuidFn->EcxIn == 0) || (CpuidFn->EcxIn == 1))))\r
-    {\r
-      continue;\r
-    }\r
-\r
-    if (XFeaturesFound & (1ULL << CpuidFn->EcxIn) ||\r
-        !(XFeaturesEnabled & (1ULL << CpuidFn->EcxIn)))\r
-    {\r
-      continue;\r
-    }\r
-\r
-    XFeaturesFound |= (1ULL << CpuidFn->EcxIn);\r
-    if (Compacted) {\r
-      *XSaveSize += CpuidFn->Eax;\r
-    } else {\r
-      *XSaveSize = MAX (*XSaveSize, CpuidFn->Eax + CpuidFn->Ebx);\r
-    }\r
-  }\r
-\r
-  /*\r
-   * Either the guest set unsupported XCR0/XSS bits, or the corresponding\r
-   * entries in the CPUID table were not present. This is an invalid state.\r
-   */\r
-  if (XFeaturesFound != (XFeaturesEnabled & ~3UL)) {\r
-    return FALSE;\r
-  }\r
-\r
-  return TRUE;\r
-}\r
-\r
-/**\r
-  Check if a CPUID leaf/function is indexed via ECX sub-leaf/sub-function\r
-\r
-  @param[in]      EaxIn        EAX input for cpuid instruction\r
-\r
-  @retval FALSE                cpuid leaf/function is not indexed by ECX input\r
-  @retval TRUE                 cpuid leaf/function is indexed by ECX input\r
-\r
-**/\r
-STATIC\r
-BOOLEAN\r
-IsFunctionIndexed (\r
-  IN     UINT32  EaxIn\r
-  )\r
-{\r
-  switch (EaxIn) {\r
-    case CPUID_CACHE_PARAMS:\r
-    case CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS:\r
-    case CPUID_EXTENDED_TOPOLOGY:\r
-    case CPUID_EXTENDED_STATE:\r
-    case CPUID_INTEL_RDT_MONITORING:\r
-    case CPUID_INTEL_RDT_ALLOCATION:\r
-    case CPUID_INTEL_SGX:\r
-    case CPUID_INTEL_PROCESSOR_TRACE:\r
-    case CPUID_DETERMINISTIC_ADDRESS_TRANSLATION_PARAMETERS:\r
-    case CPUID_V2_EXTENDED_TOPOLOGY:\r
-    case 0x8000001D: /* Cache Topology Information */\r
-      return TRUE;\r
-  }\r
-\r
-  return FALSE;\r
-}\r
-\r
-/**\r
-  Fetch CPUID leaf/function via SEV-SNP CPUID table.\r
-\r
-  @param[in, out] Ghcb         Pointer to the Guest-Hypervisor Communication\r
-                               Block\r
-  @param[in]      EaxIn        EAX input for cpuid instruction\r
-  @param[in]      EcxIn        ECX input for cpuid instruction\r
-  @param[in]      Xcr0In       XCR0 at time of cpuid instruction\r
-  @param[in, out] Eax          Pointer to store leaf's EAX value\r
-  @param[in, out] Ebx          Pointer to store leaf's EBX value\r
-  @param[in, out] Ecx          Pointer to store leaf's ECX value\r
-  @param[in, out] Edx          Pointer to store leaf's EDX value\r
-  @param[in, out] Status       Pointer to store status from VMGEXIT (always 0\r
-                               unless return value indicates failure)\r
-  @param[in, out] Unsupported  Pointer to store indication of unsupported\r
-                               VMGEXIT (always false unless return value\r
-                               indicates failure)\r
-\r
-  @retval TRUE                 CPUID leaf fetch successfully.\r
-  @retval FALSE                Error occurred while fetching CPUID leaf. Callers\r
-                               should Status and Unsupported and handle\r
-                               accordingly if they indicate a more precise\r
-                               error condition.\r
-\r
-**/\r
-STATIC\r
-BOOLEAN\r
-GetCpuidFw (\r
-  IN OUT GHCB     *Ghcb,\r
-  IN     UINT32   EaxIn,\r
-  IN     UINT32   EcxIn,\r
-  IN     UINT64   XCr0,\r
-  IN OUT UINT32   *Eax,\r
-  IN OUT UINT32   *Ebx,\r
-  IN OUT UINT32   *Ecx,\r
-  IN OUT UINT32   *Edx,\r
-  IN OUT UINT64   *Status,\r
-  IN OUT BOOLEAN  *Unsupported\r
-  )\r
-{\r
-  SEV_SNP_CPUID_INFO  *CpuidInfo;\r
-  BOOLEAN             Found;\r
-  UINT32              Idx;\r
-\r
-  CpuidInfo = (SEV_SNP_CPUID_INFO *)(UINT64)PcdGet32 (PcdOvmfCpuidBase);\r
-  Found     = FALSE;\r
-\r
-  for (Idx = 0; Idx < CpuidInfo->Count; Idx++) {\r
-    SEV_SNP_CPUID_FUNCTION  *CpuidFn = &CpuidInfo->function[Idx];\r
-\r
-    if (CpuidFn->EaxIn != EaxIn) {\r
-      continue;\r
-    }\r
-\r
-    if (IsFunctionIndexed (CpuidFn->EaxIn) && (CpuidFn->EcxIn != EcxIn)) {\r
-      continue;\r
-    }\r
-\r
-    *Eax = CpuidFn->Eax;\r
-    *Ebx = CpuidFn->Ebx;\r
-    *Ecx = CpuidFn->Ecx;\r
-    *Edx = CpuidFn->Edx;\r
-\r
-    Found = TRUE;\r
-    break;\r
-  }\r
-\r
-  if (!Found) {\r
-    *Eax = *Ebx = *Ecx = *Edx = 0;\r
-    goto Out;\r
-  }\r
-\r
-  if (EaxIn == CPUID_VERSION_INFO) {\r
-    IA32_CR4  Cr4;\r
-    UINT32    Ebx2;\r
-    UINT32    Edx2;\r
-\r
-    if (!GetCpuidHyp (\r
-           Ghcb,\r
-           EaxIn,\r
-           EcxIn,\r
-           XCr0,\r
-           NULL,\r
-           &Ebx2,\r
-           NULL,\r
-           &Edx2,\r
-           Status,\r
-           Unsupported\r
-           ))\r
-    {\r
-      return FALSE;\r
-    }\r
-\r
-    /* initial APIC ID */\r
-    *Ebx = (*Ebx & 0x00FFFFFF) | (Ebx2 & 0xFF000000);\r
-    /* APIC enabled bit */\r
-    *Edx = (*Edx & ~BIT9) | (Edx2 & BIT9);\r
-    /* OSXSAVE enabled bit */\r
-    Cr4.UintN = AsmReadCr4 ();\r
-    *Ecx      = (Cr4.Bits.OSXSAVE) ? (*Ecx & ~BIT27) | (*Ecx & BIT27)\r
-                              : (*Ecx & ~BIT27);\r
-  } else if (EaxIn == CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS) {\r
-    IA32_CR4  Cr4;\r
-\r
-    Cr4.UintN = AsmReadCr4 ();\r
-    /* OSPKE enabled bit */\r
-    *Ecx = (Cr4.Bits.PKE) ? (*Ecx | BIT4) : (*Ecx & ~BIT4);\r
-  } else if (EaxIn == CPUID_EXTENDED_TOPOLOGY) {\r
-    if (!GetCpuidHyp (\r
-           Ghcb,\r
-           EaxIn,\r
-           EcxIn,\r
-           XCr0,\r
-           NULL,\r
-           NULL,\r
-           NULL,\r
-           Edx,\r
-           Status,\r
-           Unsupported\r
-           ))\r
-    {\r
-      return FALSE;\r
-    }\r
-  } else if ((EaxIn == CPUID_EXTENDED_STATE) && ((EcxIn == 0) || (EcxIn == 1))) {\r
-    MSR_IA32_XSS_REGISTER  XssMsr;\r
-    BOOLEAN                Compacted;\r
-    UINT32                 XSaveSize;\r
-\r
-    XssMsr.Uint64 = 0;\r
-    Compacted     = FALSE;\r
-    if (EcxIn == 1) {\r
-      /*\r
-       * The PPR and APM aren't clear on what size should be encoded in\r
-       * 0xD:0x1:EBX when compaction is not enabled by either XSAVEC or\r
-       * XSAVES, as these are generally fixed to 1 on real CPUs. Report\r
-       * this undefined case as an error.\r
-       */\r
-      if (!(*Eax & (BIT3 | BIT1))) {\r
-        /* (XSAVES | XSAVEC) */\r
-        return FALSE;\r
-      }\r
-\r
-      Compacted     = TRUE;\r
-      XssMsr.Uint64 = AsmReadMsr64 (MSR_IA32_XSS);\r
-    }\r
-\r
-    if (!GetCpuidXSaveSize (\r
-           XCr0 | XssMsr.Uint64,\r
-           *Ebx,\r
-           &XSaveSize,\r
-           Compacted\r
-           ))\r
-    {\r
-      return FALSE;\r
-    }\r
-\r
-    *Ebx = XSaveSize;\r
-  } else if (EaxIn == 0x8000001E) {\r
-    UINT32  Ebx2;\r
-    UINT32  Ecx2;\r
-\r
-    /* extended APIC ID */\r
-    if (!GetCpuidHyp (\r
-           Ghcb,\r
-           EaxIn,\r
-           EcxIn,\r
-           XCr0,\r
-           Eax,\r
-           &Ebx2,\r
-           &Ecx2,\r
-           NULL,\r
-           Status,\r
-           Unsupported\r
-           ))\r
-    {\r
-      return FALSE;\r
-    }\r
-\r
-    /* compute ID */\r
-    *Ebx = (*Ebx & 0xFFFFFF00) | (Ebx2 & 0x000000FF);\r
-    /* node ID */\r
-    *Ecx = (*Ecx & 0xFFFFFF00) | (Ecx2 & 0x000000FF);\r
-  }\r
-\r
-Out:\r
-  *Status      = 0;\r
-  *Unsupported = FALSE;\r
-  return TRUE;\r
-}\r
-\r
-/**\r
-  Handle a CPUID event.\r
-\r
-  Use VMGEXIT instruction or CPUID table to handle a CPUID event.\r
-\r
-  @param[in, out] Ghcb             Pointer to the Guest-Hypervisor Communication\r
-                                   Block\r
-  @param[in, out] Regs             x64 processor context\r
-  @param[in]      InstructionData  Instruction parsing context\r
-\r
-  @retval 0                        Event handled successfully\r
-  @return                          New exception value to propagate\r
-\r
-**/\r
-STATIC\r
-UINT64\r
-CpuidExit (\r
-  IN OUT GHCB                     *Ghcb,\r
-  IN OUT EFI_SYSTEM_CONTEXT_X64   *Regs,\r
-  IN     SEV_ES_INSTRUCTION_DATA  *InstructionData\r
-  )\r
-{\r
-  BOOLEAN  Unsupported;\r
-  UINT64   Status;\r
-  UINT32   EaxIn;\r
-  UINT32   EcxIn;\r
-  UINT64   XCr0;\r
-  UINT32   Eax;\r
-  UINT32   Ebx;\r
-  UINT32   Ecx;\r
-  UINT32   Edx;\r
-\r
-  EaxIn = (UINT32)(UINTN)Regs->Rax;\r
-  EcxIn = (UINT32)(UINTN)Regs->Rcx;\r
-\r
-  if (EaxIn == CPUID_EXTENDED_STATE) {\r
-    IA32_CR4  Cr4;\r
-\r
-    Cr4.UintN           = AsmReadCr4 ();\r
-    Ghcb->SaveArea.XCr0 = (Cr4.Bits.OSXSAVE == 1) ? AsmXGetBv (0) : 1;\r
-    XCr0                = (Cr4.Bits.OSXSAVE == 1) ? AsmXGetBv (0) : 1;\r
-  }\r
-\r
-  if (SnpEnabled ()) {\r
-    if (!GetCpuidFw (\r
-           Ghcb,\r
-           EaxIn,\r
-           EcxIn,\r
-           XCr0,\r
-           &Eax,\r
-           &Ebx,\r
-           &Ecx,\r
-           &Edx,\r
-           &Status,\r
-           &Unsupported\r
-           ))\r
-    {\r
-      goto CpuidFail;\r
-    }\r
-  } else {\r
-    if (!GetCpuidHyp (\r
-           Ghcb,\r
-           EaxIn,\r
-           EcxIn,\r
-           XCr0,\r
-           &Eax,\r
-           &Ebx,\r
-           &Ecx,\r
-           &Edx,\r
-           &Status,\r
-           &Unsupported\r
-           ))\r
-    {\r
-      goto CpuidFail;\r
-    }\r
-  }\r
-\r
-  Regs->Rax = Eax;\r
-  Regs->Rbx = Ebx;\r
-  Regs->Rcx = Ecx;\r
-  Regs->Rdx = Edx;\r
-\r
-  return 0;\r
-\r
-CpuidFail:\r
-  if (Unsupported) {\r
-    return UnsupportedExit (Ghcb, Regs, InstructionData);\r
-  }\r
-\r
-  return Status;\r
-}\r
-\r
-/**\r
-  Handle a RDPMC event.\r
-\r
-  Use the VMGEXIT instruction to handle a RDPMC event.\r
-\r
-  @param[in, out] Ghcb             Pointer to the Guest-Hypervisor Communication\r
-                                   Block\r
-  @param[in, out] Regs             x64 processor context\r
-  @param[in]      InstructionData  Instruction parsing context\r
-\r
-  @retval 0                        Event handled successfully\r
-  @return                          New exception value to propagate\r
-\r
-**/\r
-STATIC\r
-UINT64\r
-RdpmcExit (\r
-  IN OUT GHCB                     *Ghcb,\r
-  IN OUT EFI_SYSTEM_CONTEXT_X64   *Regs,\r
-  IN     SEV_ES_INSTRUCTION_DATA  *InstructionData\r
-  )\r
-{\r
-  UINT64  Status;\r
-\r
-  Ghcb->SaveArea.Rcx = Regs->Rcx;\r
-  VmgSetOffsetValid (Ghcb, GhcbRcx);\r
-\r
-  Status = VmgExit (Ghcb, SVM_EXIT_RDPMC, 0, 0);\r
-  if (Status != 0) {\r
-    return Status;\r
-  }\r
-\r
-  if (!VmgIsOffsetValid (Ghcb, GhcbRax) ||\r
-      !VmgIsOffsetValid (Ghcb, GhcbRdx))\r
-  {\r
-    return UnsupportedExit (Ghcb, Regs, InstructionData);\r
-  }\r
-\r
-  Regs->Rax = Ghcb->SaveArea.Rax;\r
-  Regs->Rdx = Ghcb->SaveArea.Rdx;\r
-\r
-  return 0;\r
-}\r
-\r
-/**\r
-  Handle a RDTSC event.\r
-\r
-  Use the VMGEXIT instruction to handle a RDTSC event.\r
-\r
-  @param[in, out] Ghcb             Pointer to the Guest-Hypervisor Communication\r
-                                   Block\r
-  @param[in, out] Regs             x64 processor context\r
-  @param[in]      InstructionData  Instruction parsing context\r
-\r
-  @retval 0                        Event handled successfully\r
-  @return                          New exception value to propagate\r
-\r
-**/\r
-STATIC\r
-UINT64\r
-RdtscExit (\r
-  IN OUT GHCB                     *Ghcb,\r
-  IN OUT EFI_SYSTEM_CONTEXT_X64   *Regs,\r
-  IN     SEV_ES_INSTRUCTION_DATA  *InstructionData\r
-  )\r
-{\r
-  UINT64  Status;\r
-\r
-  Status = VmgExit (Ghcb, SVM_EXIT_RDTSC, 0, 0);\r
-  if (Status != 0) {\r
-    return Status;\r
-  }\r
-\r
-  if (!VmgIsOffsetValid (Ghcb, GhcbRax) ||\r
-      !VmgIsOffsetValid (Ghcb, GhcbRdx))\r
-  {\r
-    return UnsupportedExit (Ghcb, Regs, InstructionData);\r
-  }\r
-\r
-  Regs->Rax = Ghcb->SaveArea.Rax;\r
-  Regs->Rdx = Ghcb->SaveArea.Rdx;\r
-\r
-  return 0;\r
-}\r
-\r
-/**\r
-  Handle a DR7 register write event.\r
-\r
-  Use the VMGEXIT instruction to handle a DR7 write event.\r
-\r
-  @param[in, out] Ghcb             Pointer to the Guest-Hypervisor Communication\r
-                                   Block\r
-  @param[in, out] Regs             x64 processor context\r
-  @param[in]      InstructionData  Instruction parsing context\r
-\r
-  @retval 0                        Event handled successfully\r
-  @return                          New exception value to propagate\r
-\r
-**/\r
-STATIC\r
-UINT64\r
-Dr7WriteExit (\r
-  IN OUT GHCB                     *Ghcb,\r
-  IN OUT EFI_SYSTEM_CONTEXT_X64   *Regs,\r
-  IN     SEV_ES_INSTRUCTION_DATA  *InstructionData\r
-  )\r
-{\r
-  SEV_ES_INSTRUCTION_OPCODE_EXT  *Ext;\r
-  SEV_ES_PER_CPU_DATA            *SevEsData;\r
-  UINT64                         *Register;\r
-  UINT64                         Status;\r
-\r
-  Ext       = &InstructionData->Ext;\r
-  SevEsData = (SEV_ES_PER_CPU_DATA *)(Ghcb + 1);\r
-\r
-  DecodeModRm (Regs, InstructionData);\r
-\r
-  //\r
-  // MOV DRn always treats MOD == 3 no matter how encoded\r
-  //\r
-  Register = GetRegisterPointer (Regs, Ext->ModRm.Rm);\r
-\r
-  //\r
-  // Using a value of 0 for ExitInfo1 means RAX holds the value\r
-  //\r
-  Ghcb->SaveArea.Rax = *Register;\r
-  VmgSetOffsetValid (Ghcb, GhcbRax);\r
-\r
-  Status = VmgExit (Ghcb, SVM_EXIT_DR7_WRITE, 0, 0);\r
-  if (Status != 0) {\r
-    return Status;\r
-  }\r
-\r
-  SevEsData->Dr7       = *Register;\r
-  SevEsData->Dr7Cached = 1;\r
-\r
-  return 0;\r
-}\r
-\r
-/**\r
-  Handle a DR7 register read event.\r
-\r
-  Use the VMGEXIT instruction to handle a DR7 read event.\r
-\r
-  @param[in, out] Ghcb             Pointer to the Guest-Hypervisor Communication\r
-                                   Block\r
-  @param[in, out] Regs             x64 processor context\r
-  @param[in]      InstructionData  Instruction parsing context\r
-\r
-  @retval 0                        Event handled successfully\r
-\r
-**/\r
-STATIC\r
-UINT64\r
-Dr7ReadExit (\r
-  IN OUT GHCB                     *Ghcb,\r
-  IN OUT EFI_SYSTEM_CONTEXT_X64   *Regs,\r
-  IN     SEV_ES_INSTRUCTION_DATA  *InstructionData\r
-  )\r
-{\r
-  SEV_ES_INSTRUCTION_OPCODE_EXT  *Ext;\r
-  SEV_ES_PER_CPU_DATA            *SevEsData;\r
-  UINT64                         *Register;\r
-\r
-  Ext       = &InstructionData->Ext;\r
-  SevEsData = (SEV_ES_PER_CPU_DATA *)(Ghcb + 1);\r
-\r
-  DecodeModRm (Regs, InstructionData);\r
-\r
-  //\r
-  // MOV DRn always treats MOD == 3 no matter how encoded\r
-  //\r
-  Register = GetRegisterPointer (Regs, Ext->ModRm.Rm);\r
-\r
-  //\r
-  // If there is a cached valued for DR7, return that. Otherwise return the\r
-  // DR7 standard reset value of 0x400 (no debug breakpoints set).\r
-  //\r
-  *Register = (SevEsData->Dr7Cached == 1) ? SevEsData->Dr7 : 0x400;\r
-\r
-  return 0;\r
-}\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
-  EFI_SYSTEM_CONTEXT_X64   *Regs;\r
-  NAE_EXIT                 NaeExit;\r
-  SEV_ES_INSTRUCTION_DATA  InstructionData;\r
-  UINT64                   ExitCode, Status;\r
-  EFI_STATUS               VcRet;\r
-  BOOLEAN                  InterruptState;\r
-\r
-  VcRet = EFI_SUCCESS;\r
-\r
-  Regs = SystemContext.SystemContextX64;\r
-\r
-  VmgInit (Ghcb, &InterruptState);\r
-\r
-  ExitCode = Regs->ExceptionData;\r
-  switch (ExitCode) {\r
-    case SVM_EXIT_DR7_READ:\r
-      NaeExit = Dr7ReadExit;\r
-      break;\r
-\r
-    case SVM_EXIT_DR7_WRITE:\r
-      NaeExit = Dr7WriteExit;\r
-      break;\r
-\r
-    case SVM_EXIT_RDTSC:\r
-      NaeExit = RdtscExit;\r
-      break;\r
-\r
-    case SVM_EXIT_RDPMC:\r
-      NaeExit = RdpmcExit;\r
-      break;\r
-\r
-    case SVM_EXIT_CPUID:\r
-      NaeExit = CpuidExit;\r
-      break;\r
-\r
-    case SVM_EXIT_INVD:\r
-      NaeExit = InvdExit;\r
-      break;\r
-\r
-    case SVM_EXIT_IOIO_PROT:\r
-      NaeExit = IoioExit;\r
-      break;\r
-\r
-    case SVM_EXIT_MSR:\r
-      NaeExit = MsrExit;\r
-      break;\r
-\r
-    case SVM_EXIT_VMMCALL:\r
-      NaeExit = VmmCallExit;\r
-      break;\r
-\r
-    case SVM_EXIT_RDTSCP:\r
-      NaeExit = RdtscpExit;\r
-      break;\r
-\r
-    case SVM_EXIT_WBINVD:\r
-      NaeExit = WbinvdExit;\r
-      break;\r
-\r
-    case SVM_EXIT_MONITOR:\r
-      NaeExit = MonitorExit;\r
-      break;\r
-\r
-    case SVM_EXIT_MWAIT:\r
-      NaeExit = MwaitExit;\r
-      break;\r
-\r
-    case SVM_EXIT_NPF:\r
-      NaeExit = MmioExit;\r
-      break;\r
-\r
-    default:\r
-      NaeExit = UnsupportedExit;\r
-  }\r
-\r
-  InitInstructionData (&InstructionData, Ghcb, Regs);\r
-\r
-  Status = NaeExit (Ghcb, Regs, &InstructionData);\r
-  if (Status == 0) {\r
-    Regs->Rip += InstructionLength (&InstructionData);\r
-  } else {\r
-    GHCB_EVENT_INJECTION  Event;\r
-\r
-    Event.Uint64 = Status;\r
-    if (Event.Elements.ErrorCodeValid != 0) {\r
-      Regs->ExceptionData = Event.Elements.ErrorCode;\r
-    } else {\r
-      Regs->ExceptionData = 0;\r
-    }\r
-\r
-    *ExceptionType = Event.Elements.Vector;\r
-\r
-    VcRet = EFI_PROTOCOL_ERROR;\r
-  }\r
-\r
-  VmgDone (Ghcb, InterruptState);\r
-\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
deleted file mode 100644 (file)
index 3a37cb0..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/** @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
diff --git a/OvmfPkg/Library/VmgExitLib/X64/TdVmcallCpuid.nasm b/OvmfPkg/Library/VmgExitLib/X64/TdVmcallCpuid.nasm
deleted file mode 100644 (file)
index fa86440..0000000
+++ /dev/null
@@ -1,146 +0,0 @@
-;------------------------------------------------------------------------------\r
-;*\r
-;* Copyright (c) 2020 - 2021, Intel Corporation. All rights reserved.<BR>\r
-;* SPDX-License-Identifier: BSD-2-Clause-Patent\r
-;*\r
-;*\r
-;------------------------------------------------------------------------------\r
-\r
-DEFAULT REL\r
-SECTION .text\r
-\r
-%define TDVMCALL_EXPOSE_REGS_MASK       0xffec\r
-%define TDVMCALL                        0x0\r
-%define EXIT_REASON_CPUID               0xa\r
-\r
-%macro tdcall 0\r
-    db 0x66,0x0f,0x01,0xcc\r
-%endmacro\r
-\r
-%macro tdcall_push_regs 0\r
-    push rbp\r
-    mov  rbp, rsp\r
-    push r15\r
-    push r14\r
-    push r13\r
-    push r12\r
-    push rbx\r
-    push rsi\r
-    push rdi\r
-%endmacro\r
-\r
-%macro tdcall_pop_regs 0\r
-    pop rdi\r
-    pop rsi\r
-    pop rbx\r
-    pop r12\r
-    pop r13\r
-    pop r14\r
-    pop r15\r
-    pop rbp\r
-%endmacro\r
-\r
-%define number_of_regs_pushed 8\r
-%define number_of_parameters  4\r
-\r
-;\r
-; Keep these in sync for push_regs/pop_regs, code below\r
-; uses them to find 5th or greater parameters\r
-;\r
-%define first_variable_on_stack_offset \\r
-  ((number_of_regs_pushed * 8) + (number_of_parameters * 8) + 8)\r
-%define second_variable_on_stack_offset \\r
-  ((first_variable_on_stack_offset) + 8)\r
-\r
-%macro tdcall_regs_preamble 2\r
-    mov rax, %1\r
-\r
-    xor rcx, rcx\r
-    mov ecx, %2\r
-\r
-    ; R10 = 0 (standard TDVMCALL)\r
-\r
-    xor r10d, r10d\r
-\r
-    ; Zero out unused (for standard TDVMCALL) registers to avoid leaking\r
-    ; secrets to the VMM.\r
-\r
-    xor ebx, ebx\r
-    xor esi, esi\r
-    xor edi, edi\r
-\r
-    xor edx, edx\r
-    xor ebp, ebp\r
-    xor r8d, r8d\r
-    xor r9d, r9d\r
-    xor r14, r14\r
-    xor r15, r15\r
-%endmacro\r
-\r
-%macro tdcall_regs_postamble 0\r
-    xor ebx, ebx\r
-    xor esi, esi\r
-    xor edi, edi\r
-\r
-    xor ecx, ecx\r
-    xor edx, edx\r
-    xor r8d,  r8d\r
-    xor r9d,  r9d\r
-    xor r10d, r10d\r
-    xor r11d, r11d\r
-%endmacro\r
-\r
-;------------------------------------------------------------------------------\r
-; 0   => RAX = TDCALL leaf / TDVMCALL\r
-; M   => RCX = TDVMCALL register behavior\r
-; 0xa => R11 = TDVMCALL function / CPUID\r
-; RCX => R12 = p1\r
-; RDX => R13 = p2\r
-;\r
-;  UINT64\r
-;  EFIAPI\r
-;  TdVmCallCpuid (\r
-;    UINT64  EaxIn,    // Rcx\r
-;    UINT64  EcxIn,    // Rdx\r
-;    UINT64  *Results  // R8\r
-;    )\r
-global ASM_PFX(TdVmCallCpuid)\r
-ASM_PFX(TdVmCallCpuid):\r
-       tdcall_push_regs\r
-\r
-       mov r11, EXIT_REASON_CPUID\r
-       mov r12, rcx\r
-       mov r13, rdx\r
-\r
-       ; Save *results pointers\r
-       push r8\r
-\r
-       tdcall_regs_preamble TDVMCALL, TDVMCALL_EXPOSE_REGS_MASK\r
-\r
-       tdcall\r
-\r
-       ; ignore return data if TDCALL reports failure.\r
-       test rax, rax\r
-       jnz .no_return_data\r
-\r
-       ; Propagate TDVMCALL success/failure to return value.\r
-       mov rax, r10\r
-       test rax, rax\r
-       jnz .no_return_data\r
-\r
-       ; Retrieve *Results\r
-       pop r8\r
-       test r8, r8\r
-       jz .no_return_data\r
-       ; Caller pass in buffer so store results r12-r15 contains eax-edx\r
-       mov [r8 +  0], r12\r
-       mov [r8 +  8], r13\r
-       mov [r8 + 16], r14\r
-       mov [r8 + 24], r15\r
-\r
-.no_return_data:\r
-       tdcall_regs_postamble\r
-\r
-       tdcall_pop_regs\r
-\r
-       ret\r
index 7eff8e2a88d9dadbffc9ca7f7cf38fb85e5dcf4a..994a02d301070216ae3666cd7d07cca0649f53d8 100644 (file)
 \r
 [LibraryClasses.common]\r
   BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf\r
-  VmgExitLib|OvmfPkg/Library/VmgExitLib/VmgExitLib.inf\r
+  CcExitLib|OvmfPkg/Library/CcExitLib/CcExitLib.inf\r
   SerialPortLib|MdeModulePkg/Library/BaseSerialPortLib16550/BaseSerialPortLib16550.inf\r
   PlatformHookLib|MdeModulePkg/Library/BasePlatformHookLibNull/BasePlatformHookLibNull.inf\r
   FdtLib|EmbeddedPkg/Library/FdtLib/FdtLib.inf\r
 !else\r
   CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf\r
 !endif\r
-  VmgExitLib|OvmfPkg/Library/VmgExitLib/SecVmgExitLib.inf\r
+  CcExitLib|OvmfPkg/Library/CcExitLib/SecCcExitLib.inf\r
   MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLib.inf\r
 \r
 [LibraryClasses.common.PEI_CORE]\r
index e9ba491237ae7543059f06cd0c82e7b8cc75aa7c..6f774baf90f530e1d712d1becfe7d0c4427e2e56 100644 (file)
 \r
 [LibraryClasses.common]\r
   BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf\r
-  VmgExitLib|UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.inf\r
+  CcExitLib|UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.inf\r
 \r
 [LibraryClasses.common.SEC]\r
   TimerLib|OvmfPkg/Library/AcpiTimerLib/BaseRomAcpiTimerLib.inf\r
   #\r
   OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FvbServicesSmm.inf {\r
     <LibraryClasses>\r
-    VmgExitLib|UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.inf\r
+    CcExitLib|UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.inf\r
   }\r
   MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.inf\r
   MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf {\r
index af566b953f362793a2bf0f670ddea923f217bcef..c851764dec0518b68b0f65d8ea728f2f79ca2727 100644 (file)
 \r
 [LibraryClasses.common]\r
   BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf\r
-  VmgExitLib|UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.inf\r
+  CcExitLib|UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.inf\r
   TdxLib|MdePkg/Library/TdxLib/TdxLib.inf\r
   TdxMailboxLib|OvmfPkg/Library/TdxMailboxLib/TdxMailboxLib.inf\r
 \r
   #\r
   OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FvbServicesSmm.inf {\r
     <LibraryClasses>\r
-    VmgExitLib|UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.inf\r
+    CcExitLib|UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.inf\r
   }\r
   MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.inf\r
   MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf {\r
index f39d9cd117e677633ea99c70f1ea8b0dcb364f00..63c3a47aea30f763c9bd8d887f251fd93642e3d9 100644 (file)
 \r
 [LibraryClasses.common]\r
   BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf\r
-  VmgExitLib|OvmfPkg/Library/VmgExitLib/VmgExitLib.inf\r
+  CcExitLib|OvmfPkg/Library/CcExitLib/CcExitLib.inf\r
   TdxLib|MdePkg/Library/TdxLib/TdxLib.inf\r
   TdxMailboxLib|OvmfPkg/Library/TdxMailboxLib/TdxMailboxLib.inf\r
 \r
 !else\r
   CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf\r
 !endif\r
-  VmgExitLib|OvmfPkg/Library/VmgExitLib/SecVmgExitLib.inf\r
+  CcExitLib|OvmfPkg/Library/CcExitLib/SecCcExitLib.inf\r
   MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLib.inf\r
   CcProbeLib|OvmfPkg/Library/CcProbeLib/SecPeiCcProbeLib.inf\r
 \r
   #\r
   OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FvbServicesSmm.inf {\r
     <LibraryClasses>\r
-    VmgExitLib|UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.inf\r
+    CcExitLib|UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.inf\r
   }\r
   MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.inf\r
   MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf {\r
index 58a7c97cddf702bfb506a8dee7b7c321e0dbd2e5..8bb497088bd29feb346d17adf5a2e9d1beb900d1 100644 (file)
 \r
 [LibraryClasses.common]\r
   BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf\r
-  VmgExitLib|UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.inf\r
+  CcExitLib|UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.inf\r
   TdxLib|MdePkg/Library/TdxLib/TdxLib.inf\r
 \r
 [LibraryClasses.common.SEC]\r
index 385562b44c4e837259c697f9d8638b7e9d14283d..80a1194ffcb9d7d9c8fc9fd692c4016a527ed183 100644 (file)
@@ -19,7 +19,7 @@
 #include <PiPei.h>\r
 #include <Register/Amd/Msr.h>\r
 #include <Register/Intel/SmramSaveStateMap.h>\r
-#include <Library/VmgExitLib.h>\r
+#include <Library/CcExitLib.h>\r
 #include <ConfidentialComputingGuestAttr.h>\r
 \r
 #include "Platform.h"\r
index 3cd83e6ec3e592952b942e4cf22a22a4733e864a..1fadadeb55657da42e04a3e01e76d079cbd70382 100644 (file)
@@ -63,7 +63,7 @@
   MtrrLib\r
   MemEncryptSevLib\r
   PcdLib\r
-  VmgExitLib\r
+  CcExitLib\r
   PlatformInitLib\r
 \r
 [Pcd]\r
index 8bb2325157eacee3003d205b5ce54a2f605ec749..f47170478900679342e922c2d010a62df128035c 100644 (file)
@@ -53,7 +53,7 @@
   UefiBootServicesTableLib\r
   UefiDriverEntryPoint\r
   UefiRuntimeLib\r
-  VmgExitLib\r
+  CcExitLib\r
 \r
 [Guids]\r
   gEfiEventVirtualAddressChangeGuid   # ALWAYS_CONSUMED\r
index 172d6a4267f8e1d511f21a99f9702106f49f5c7b..58bcad825d57574c22ffb52ab577ecd4e6eb735a 100644 (file)
@@ -11,7 +11,7 @@
 \r
 #include <Library/UefiRuntimeLib.h>\r
 #include <Library/MemEncryptSevLib.h>\r
-#include <Library/VmgExitLib.h>\r
+#include <Library/CcExitLib.h>\r
 #include <Register/Amd/Msr.h>\r
 \r
 #include "QemuFlash.h"\r
diff --git a/UefiCpuPkg/Include/Library/CcExitLib.h b/UefiCpuPkg/Include/Library/CcExitLib.h
new file mode 100644 (file)
index 0000000..1ae618c
--- /dev/null
@@ -0,0 +1,176 @@
+/** @file\r
+  Public header file for the CcExitLib.\r
+\r
+  This library class defines some routines used for below CcExit handler.\r
+   - Invoking the VMGEXIT instruction in support of SEV-ES and to handle\r
+     #VC exceptions.\r
+   - Handle #VE exception in TDX.\r
+\r
+  Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved.<BR>\r
+  Copyright (c) 2020 - 2022, Intel Corporation. All rights reserved.<BR>\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#ifndef CC_EXIT_LIB_H_\r
+#define CC_EXIT_LIB_H_\r
+\r
+#include <Protocol/DebugSupport.h>\r
+#include <Register/Amd/Ghcb.h>\r
+\r
+#define VE_EXCEPTION  20\r
+\r
+/**\r
+  Perform VMGEXIT.\r
+\r
+  Sets the necessary fields of the GHCB, invokes the VMGEXIT instruction and\r
+  then handles the return actions.\r
+\r
+  @param[in, out]  Ghcb       A pointer to the GHCB\r
+  @param[in]       ExitCode   VMGEXIT code to be assigned to the SwExitCode\r
+                              field of the GHCB.\r
+  @param[in]       ExitInfo1  VMGEXIT information to be assigned to the\r
+                              SwExitInfo1 field of the GHCB.\r
+  @param[in]       ExitInfo2  VMGEXIT information to be assigned to the\r
+                              SwExitInfo2 field of the GHCB.\r
+\r
+  @retval  0                  VMGEXIT succeeded.\r
+  @return                     Exception number to be propagated, VMGEXIT\r
+                              processing did not succeed.\r
+\r
+**/\r
+UINT64\r
+EFIAPI\r
+VmgExit (\r
+  IN OUT GHCB    *Ghcb,\r
+  IN     UINT64  ExitCode,\r
+  IN     UINT64  ExitInfo1,\r
+  IN     UINT64  ExitInfo2\r
+  );\r
+\r
+/**\r
+  Perform pre-VMGEXIT initialization/preparation.\r
+\r
+  Performs the necessary steps in preparation for invoking VMGEXIT. Must be\r
+  called before setting any fields within the GHCB.\r
+\r
+  @param[in, out]  Ghcb            A pointer to the GHCB\r
+  @param[in, out]  InterruptState  A pointer to hold the current interrupt\r
+                                   state, used for restoring in VmgDone ()\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+VmgInit (\r
+  IN OUT GHCB     *Ghcb,\r
+  IN OUT BOOLEAN  *InterruptState\r
+  );\r
+\r
+/**\r
+  Perform post-VMGEXIT cleanup.\r
+\r
+  Performs the necessary steps to cleanup after invoking VMGEXIT. Must be\r
+  called after obtaining needed fields within the GHCB.\r
+\r
+  @param[in, out]  Ghcb            A pointer to the GHCB\r
+  @param[in]       InterruptState  An indicator to conditionally (re)enable\r
+                                   interrupts\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+VmgDone (\r
+  IN OUT GHCB     *Ghcb,\r
+  IN     BOOLEAN  InterruptState\r
+  );\r
+\r
+/**\r
+  Marks a specified offset as valid in the GHCB.\r
+\r
+  The ValidBitmap area represents the areas of the GHCB that have been marked\r
+  valid. Set the bit in ValidBitmap for the input offset.\r
+\r
+  @param[in, out]  Ghcb       A pointer to the GHCB\r
+  @param[in]       Offset     Qword offset in the GHCB to mark valid\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+VmgSetOffsetValid (\r
+  IN OUT GHCB           *Ghcb,\r
+  IN     GHCB_REGISTER  Offset\r
+  );\r
+\r
+/**\r
+  Checks if a specified offset is valid in the GHCB.\r
+\r
+  The ValidBitmap area represents the areas of the GHCB that have been marked\r
+  valid. Return whether the bit in the ValidBitmap is set for the input offset.\r
+\r
+  @param[in]  Ghcb            A pointer to the GHCB\r
+  @param[in]  Offset          Qword offset in the GHCB to mark valid\r
+\r
+  @retval TRUE                Offset is marked valid in the GHCB\r
+  @retval FALSE               Offset is not marked valid in the GHCB\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+VmgIsOffsetValid (\r
+  IN GHCB           *Ghcb,\r
+  IN GHCB_REGISTER  Offset\r
+  );\r
+\r
+/**\r
+  Handle a #VC exception.\r
+\r
+  Performs the necessary processing to handle a #VC exception.\r
+\r
+  The base library function returns an error equal to VC_EXCEPTION,\r
+  to be propagated to the standard exception handling stack.\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
+/**\r
+  Handle a #VE exception.\r
+\r
+  Performs the necessary processing to handle a #VE exception.\r
+\r
+  The base library function returns an error equal to VE_EXCEPTION,\r
+  to be propagated to the standard exception handling stack.\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        #VE not supported, (new) exception value to\r
+                                  propagate provided\r
+  @retval  EFI_PROTOCOL_ERROR     #VE handling failed, (new) exception value to\r
+                                  propagate provided\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+VmTdExitHandleVe (\r
+  IN OUT EFI_EXCEPTION_TYPE  *ExceptionType,\r
+  IN OUT EFI_SYSTEM_CONTEXT  SystemContext\r
+  );\r
+\r
+#endif\r
diff --git a/UefiCpuPkg/Include/Library/VmgExitLib.h b/UefiCpuPkg/Include/Library/VmgExitLib.h
deleted file mode 100644 (file)
index f9f9110..0000000
+++ /dev/null
@@ -1,173 +0,0 @@
-/** @file\r
-  Public header file for the VMGEXIT Support library class.\r
-\r
-  This library class defines some routines used when invoking the VMGEXIT\r
-  instruction in support of SEV-ES and to handle #VC exceptions.\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_LIB_H__\r
-#define __VMG_EXIT_LIB_H__\r
-\r
-#include <Protocol/DebugSupport.h>\r
-#include <Register/Amd/Ghcb.h>\r
-\r
-#define VE_EXCEPTION  20\r
-\r
-/**\r
-  Perform VMGEXIT.\r
-\r
-  Sets the necessary fields of the GHCB, invokes the VMGEXIT instruction and\r
-  then handles the return actions.\r
-\r
-  @param[in, out]  Ghcb       A pointer to the GHCB\r
-  @param[in]       ExitCode   VMGEXIT code to be assigned to the SwExitCode\r
-                              field of the GHCB.\r
-  @param[in]       ExitInfo1  VMGEXIT information to be assigned to the\r
-                              SwExitInfo1 field of the GHCB.\r
-  @param[in]       ExitInfo2  VMGEXIT information to be assigned to the\r
-                              SwExitInfo2 field of the GHCB.\r
-\r
-  @retval  0                  VMGEXIT succeeded.\r
-  @return                     Exception number to be propagated, VMGEXIT\r
-                              processing did not succeed.\r
-\r
-**/\r
-UINT64\r
-EFIAPI\r
-VmgExit (\r
-  IN OUT GHCB    *Ghcb,\r
-  IN     UINT64  ExitCode,\r
-  IN     UINT64  ExitInfo1,\r
-  IN     UINT64  ExitInfo2\r
-  );\r
-\r
-/**\r
-  Perform pre-VMGEXIT initialization/preparation.\r
-\r
-  Performs the necessary steps in preparation for invoking VMGEXIT. Must be\r
-  called before setting any fields within the GHCB.\r
-\r
-  @param[in, out]  Ghcb            A pointer to the GHCB\r
-  @param[in, out]  InterruptState  A pointer to hold the current interrupt\r
-                                   state, used for restoring in VmgDone ()\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-VmgInit (\r
-  IN OUT GHCB     *Ghcb,\r
-  IN OUT BOOLEAN  *InterruptState\r
-  );\r
-\r
-/**\r
-  Perform post-VMGEXIT cleanup.\r
-\r
-  Performs the necessary steps to cleanup after invoking VMGEXIT. Must be\r
-  called after obtaining needed fields within the GHCB.\r
-\r
-  @param[in, out]  Ghcb            A pointer to the GHCB\r
-  @param[in]       InterruptState  An indicator to conditionally (re)enable\r
-                                   interrupts\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-VmgDone (\r
-  IN OUT GHCB     *Ghcb,\r
-  IN     BOOLEAN  InterruptState\r
-  );\r
-\r
-/**\r
-  Marks a specified offset as valid in the GHCB.\r
-\r
-  The ValidBitmap area represents the areas of the GHCB that have been marked\r
-  valid. Set the bit in ValidBitmap for the input offset.\r
-\r
-  @param[in, out]  Ghcb       A pointer to the GHCB\r
-  @param[in]       Offset     Qword offset in the GHCB to mark valid\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-VmgSetOffsetValid (\r
-  IN OUT GHCB           *Ghcb,\r
-  IN     GHCB_REGISTER  Offset\r
-  );\r
-\r
-/**\r
-  Checks if a specified offset is valid in the GHCB.\r
-\r
-  The ValidBitmap area represents the areas of the GHCB that have been marked\r
-  valid. Return whether the bit in the ValidBitmap is set for the input offset.\r
-\r
-  @param[in]  Ghcb            A pointer to the GHCB\r
-  @param[in]  Offset          Qword offset in the GHCB to mark valid\r
-\r
-  @retval TRUE                Offset is marked valid in the GHCB\r
-  @retval FALSE               Offset is not marked valid in the GHCB\r
-\r
-**/\r
-BOOLEAN\r
-EFIAPI\r
-VmgIsOffsetValid (\r
-  IN GHCB           *Ghcb,\r
-  IN GHCB_REGISTER  Offset\r
-  );\r
-\r
-/**\r
-  Handle a #VC exception.\r
-\r
-  Performs the necessary processing to handle a #VC exception.\r
-\r
-  The base library function returns an error equal to VC_EXCEPTION,\r
-  to be propagated to the standard exception handling stack.\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
-/**\r
-  Handle a #VE exception.\r
-\r
-  Performs the necessary processing to handle a #VE exception.\r
-\r
-  The base library function returns an error equal to VE_EXCEPTION,\r
-  to be propagated to the standard exception handling stack.\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        #VE not supported, (new) exception value to\r
-                                  propagate provided\r
-  @retval  EFI_PROTOCOL_ERROR     #VE handling failed, (new) exception value to\r
-                                  propagate provided\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-VmTdExitHandleVe (\r
-  IN OUT EFI_EXCEPTION_TYPE  *ExceptionType,\r
-  IN OUT EFI_SYSTEM_CONTEXT  SystemContext\r
-  );\r
-\r
-#endif\r
diff --git a/UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.c b/UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.c
new file mode 100644 (file)
index 0000000..79eca74
--- /dev/null
@@ -0,0 +1,194 @@
+/** @file\r
+  CcExit Base Support Library.\r
+\r
+  Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved.<BR>\r
+  Copyright (c) 2020 - 2022, Intel Corporation. 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/CcExitLib.h>\r
+\r
+/**\r
+  Perform VMGEXIT.\r
+\r
+  Sets the necessary fields of the GHCB, invokes the VMGEXIT instruction and\r
+  then handles the return actions.\r
+\r
+  The base library function returns an error in the form of a\r
+  GHCB_EVENT_INJECTION representing a GP_EXCEPTION.\r
+\r
+  @param[in, out]  Ghcb       A pointer to the GHCB\r
+  @param[in]       ExitCode   VMGEXIT code to be assigned to the SwExitCode\r
+                              field of the GHCB.\r
+  @param[in]       ExitInfo1  VMGEXIT information to be assigned to the\r
+                              SwExitInfo1 field of the GHCB.\r
+  @param[in]       ExitInfo2  VMGEXIT information to be assigned to the\r
+                              SwExitInfo2 field of the GHCB.\r
+\r
+  @retval  0                  VMGEXIT succeeded.\r
+  @return                     Exception number to be propagated, VMGEXIT\r
+                              processing did not succeed.\r
+\r
+**/\r
+UINT64\r
+EFIAPI\r
+VmgExit (\r
+  IN OUT GHCB    *Ghcb,\r
+  IN     UINT64  ExitCode,\r
+  IN     UINT64  ExitInfo1,\r
+  IN     UINT64  ExitInfo2\r
+  )\r
+{\r
+  GHCB_EVENT_INJECTION  Event;\r
+\r
+  Event.Uint64          = 0;\r
+  Event.Elements.Vector = GP_EXCEPTION;\r
+  Event.Elements.Type   = GHCB_EVENT_INJECTION_TYPE_EXCEPTION;\r
+  Event.Elements.Valid  = 1;\r
+\r
+  return Event.Uint64;\r
+}\r
+\r
+/**\r
+  Perform pre-VMGEXIT initialization/preparation.\r
+\r
+  Performs the necessary steps in preparation for invoking VMGEXIT. Must be\r
+  called before setting any fields within the GHCB.\r
+\r
+  @param[in, out]  Ghcb            A pointer to the GHCB\r
+  @param[in, out]  InterruptState  A pointer to hold the current interrupt\r
+                                   state, used for restoring in VmgDone ()\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+VmgInit (\r
+  IN OUT GHCB     *Ghcb,\r
+  IN OUT BOOLEAN  *InterruptState\r
+  )\r
+{\r
+}\r
+\r
+/**\r
+  Perform post-VMGEXIT cleanup.\r
+\r
+  Performs the necessary steps to cleanup after invoking VMGEXIT. Must be\r
+  called after obtaining needed fields within the GHCB.\r
+\r
+  @param[in, out]  Ghcb            A pointer to the GHCB\r
+  @param[in]       InterruptState  An indicator to conditionally (re)enable\r
+                                   interrupts\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+VmgDone (\r
+  IN OUT GHCB     *Ghcb,\r
+  IN     BOOLEAN  InterruptState\r
+  )\r
+{\r
+}\r
+\r
+/**\r
+  Marks a field at the specified offset as valid in the GHCB.\r
+\r
+  The ValidBitmap area represents the areas of the GHCB that have been marked\r
+  valid. Set the bit in ValidBitmap for the input offset.\r
+\r
+  @param[in, out] Ghcb    Pointer to the Guest-Hypervisor Communication Block\r
+  @param[in]      Offset  Qword offset in the GHCB to mark valid\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+VmgSetOffsetValid (\r
+  IN OUT GHCB           *Ghcb,\r
+  IN     GHCB_REGISTER  Offset\r
+  )\r
+{\r
+}\r
+\r
+/**\r
+  Checks if a specified offset is valid in the GHCB.\r
+\r
+  The ValidBitmap area represents the areas of the GHCB that have been marked\r
+  valid. Return whether the bit in the ValidBitmap is set for the input offset.\r
+\r
+  @param[in]  Ghcb            A pointer to the GHCB\r
+  @param[in]  Offset          Qword offset in the GHCB to mark valid\r
+\r
+  @retval TRUE                Offset is marked valid in the GHCB\r
+  @retval FALSE               Offset is not marked valid in the GHCB\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+VmgIsOffsetValid (\r
+  IN GHCB           *Ghcb,\r
+  IN GHCB_REGISTER  Offset\r
+  )\r
+{\r
+  return FALSE;\r
+}\r
+\r
+/**\r
+  Handle a #VC exception.\r
+\r
+  Performs the necessary processing to handle a #VC exception.\r
+\r
+  The base library function returns an error equal to VC_EXCEPTION,\r
+  to be propagated to the standard exception handling stack.\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
+  *ExceptionType = VC_EXCEPTION;\r
+\r
+  return EFI_UNSUPPORTED;\r
+}\r
+\r
+/**\r
+  Handle a #VE exception.\r
+\r
+  Performs the necessary processing to handle a #VE 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        #VE not supported, (new) exception value to\r
+                                  propagate provided\r
+  @retval  EFI_PROTOCOL_ERROR     #VE handling failed, (new) exception value to\r
+                                  propagate provided\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+VmTdExitHandleVe (\r
+  IN OUT EFI_EXCEPTION_TYPE  *ExceptionType,\r
+  IN OUT EFI_SYSTEM_CONTEXT  SystemContext\r
+  )\r
+{\r
+  *ExceptionType = VE_EXCEPTION;\r
+\r
+  return EFI_UNSUPPORTED;\r
+}\r
diff --git a/UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.inf b/UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.inf
new file mode 100644 (file)
index 0000000..ed7f611
--- /dev/null
@@ -0,0 +1,28 @@
+## @file\r
+#  CcExit Base Support Library.\r
+#\r
+#  Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved.<BR>\r
+#  Copyright (c) 2020 - 2022, Intel Corporation. All rights reserved.<BR>\r
+#  SPDX-License-Identifier: BSD-2-Clause-Patent\r
+#\r
+##\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = CcExitLibNull\r
+  MODULE_UNI_FILE                = CcExitLibNull.uni\r
+  FILE_GUID                      = 3cd7368f-ef9b-4a9b-9571-2ed93813677e\r
+  MODULE_TYPE                    = BASE\r
+  VERSION_STRING                 = 1.0\r
+  LIBRARY_CLASS                  = CcExitLib\r
+\r
+[Sources.common]\r
+  CcExitLibNull.c\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  UefiCpuPkg/UefiCpuPkg.dec\r
+\r
+[LibraryClasses]\r
+  BaseLib\r
+\r
diff --git a/UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.uni b/UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.uni
new file mode 100644 (file)
index 0000000..b18ae87
--- /dev/null
@@ -0,0 +1,14 @@
+// /** @file\r
+// CcExitLib instance.\r
+//\r
+// Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved.<BR>\r
+// Copyright (c) 2020 - 2022, Intel Corporation. All rights reserved.<BR>\r
+// SPDX-License-Identifier: BSD-2-Clause-Patent\r
+//\r
+// **/\r
+\r
+\r
+#string STR_MODULE_ABSTRACT             #language en-US "CcExitLib NULL instance"\r
+\r
+#string STR_MODULE_DESCRIPTION          #language en-US "CcExitLib NULL instance."\r
+\r
index e7a81bebdb13e94840f983f5fe9099390a07d8d4..d0f82095cf926e995470a35d0616724e25621115 100644 (file)
@@ -60,4 +60,4 @@
   PeCoffGetEntryPointLib\r
   MemoryAllocationLib\r
   DebugLib\r
-  VmgExitLib\r
+  CcExitLib\r
index 7c2ec3b2db4caf74ec709034564ee4de894eeddd..5339f8e60404580153bc64f4c4399bfdf73903d1 100644 (file)
@@ -52,7 +52,7 @@
   HobLib\r
   MemoryAllocationLib\r
   SynchronizationLib\r
-  VmgExitLib\r
+  CcExitLib\r
 \r
 [Pcd]\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard    # CONSUMES\r
index a7d0897ef1f903c85c66eae74feac0f5325e2825..2b6d9da5c7132cb6b6d4256cd3c5e1a37576c5d1 100644 (file)
@@ -7,7 +7,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 **/\r
 \r
 #include <Library/DebugLib.h>\r
-#include <Library/VmgExitLib.h>\r
+#include <Library/CcExitLib.h>\r
 #include "CpuExceptionCommon.h"\r
 \r
 /**\r
index ad5e0e9ed4f1f71b62e33733a5b40a853b4e7bc6..0a9ea79f52dcdf07786eb95f1a09b337f369c340 100644 (file)
@@ -7,7 +7,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 **/\r
 \r
 #include <PiPei.h>\r
-#include <Library/VmgExitLib.h>\r
+#include <Library/CcExitLib.h>\r
 #include "CpuExceptionCommon.h"\r
 \r
 CONST UINTN  mDoFarReturnFlag = 0;\r
index 6a170286c8fc7eac2db6e39391d4edff5e7c3ce8..df44371fe018e06dd8dec2b49edb1bc60d68b72f 100644 (file)
@@ -48,7 +48,7 @@
   PrintLib\r
   LocalApicLib\r
   PeCoffGetEntryPointLib\r
-  VmgExitLib\r
+  CcExitLib\r
 \r
 [Pcd]\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard\r
index 9dde07612a042da28984ad51d73ece503ff1972d..8f8a5dab79303f87ede512f61eb1cafdd51ee88e 100644 (file)
@@ -51,7 +51,7 @@
   LocalApicLib\r
   PeCoffGetEntryPointLib\r
   DebugLib\r
-  VmgExitLib\r
+  CcExitLib\r
 \r
 [Pcd]\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard\r
index 6d2f66504a5bc3d2c8fd388c290143703b2ed068..619b39d7f1de9ae397acb9b3a0d3a157b63f88dc 100644 (file)
@@ -53,7 +53,7 @@
   PrintLib\r
   LocalApicLib\r
   PeCoffGetEntryPointLib\r
-  VmgExitLib\r
+  CcExitLib\r
 \r
 [Pcd]\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard\r
index 4e4c63a52de40cedcb110b1219e47c125c5937eb..2dd8f4d74621aac1e3aa04dd70a2a8346fe4f29f 100644 (file)
@@ -8,7 +8,7 @@
 **/\r
 \r
 #include "MpLib.h"\r
-#include <Library/VmgExitLib.h>\r
+#include <Library/CcExitLib.h>\r
 \r
 /**\r
   Get Protected mode code segment with 16-bit default addressing\r
index e1cd0b35000831560d736a10b8f017597bbcae48..cd07de3a3c0bf8bb9c8b28b9d21cd0315fa78160 100644 (file)
@@ -54,7 +54,7 @@
   DebugAgentLib\r
   SynchronizationLib\r
   PcdLib\r
-  VmgExitLib\r
+  CcExitLib\r
   MicrocodeLib\r
 \r
 [Protocols]\r
index 78cc3e2b93fdf6934aee1539e0cd127ed7990eff..ef56af1f738b7eec67beea12a3bf8d011c5114e1 100644 (file)
@@ -12,7 +12,7 @@
 #include <Library/UefiBootServicesTableLib.h>\r
 #include <Library/DebugAgentLib.h>\r
 #include <Library/DxeServicesTableLib.h>\r
-#include <Library/VmgExitLib.h>\r
+#include <Library/CcExitLib.h>\r
 #include <Register/Amd/Fam17Msr.h>\r
 #include <Register/Amd/Ghcb.h>\r
 \r
index 1c053f87a4c64c5d8baef0feb2b2e2ebd600ab3d..e5dc852ed95fd23a6fbd6f437cbc1e062e42e969 100644 (file)
@@ -9,7 +9,7 @@
 **/\r
 \r
 #include "MpLib.h"\r
-#include <Library/VmgExitLib.h>\r
+#include <Library/CcExitLib.h>\r
 #include <Register/Amd/Fam17Msr.h>\r
 #include <Register/Amd/Ghcb.h>\r
 \r
index 5facf4db94997beb879e3ff5cfbae37b35b3c425..afd551bb0f64058c41e57015ef89821c866dd896 100644 (file)
@@ -53,7 +53,7 @@
   SynchronizationLib\r
   PeiServicesLib\r
   PcdLib\r
-  VmgExitLib\r
+  CcExitLib\r
   MicrocodeLib\r
 \r
 [Pcd]\r
index a3cd377ef600ec27e36d8ca2043c2f10a8fcfdb8..4c4f81af7c22b234d2ca1c42693b96db87b126dc 100644 (file)
@@ -9,7 +9,7 @@
 **/\r
 \r
 #include "MpLib.h"\r
-#include <Library/VmgExitLib.h>\r
+#include <Library/CcExitLib.h>\r
 #include <Register/Amd/Fam17Msr.h>\r
 #include <Register/Amd/Ghcb.h>\r
 \r
diff --git a/UefiCpuPkg/Library/VmgExitLibNull/VmTdExitNull.c b/UefiCpuPkg/Library/VmgExitLibNull/VmTdExitNull.c
deleted file mode 100644 (file)
index 6a4e808..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-/** @file\r
-\r
-  Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>\r
-\r
-  SPDX-License-Identifier: BSD-2-Clause-Patent\r
-\r
-**/\r
-#include <Base.h>\r
-#include <Uefi.h>\r
-#include <Library/VmgExitLib.h>\r
-\r
-/**\r
-  Handle a #VE exception.\r
-\r
-  Performs the necessary processing to handle a #VE 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        #VE not supported, (new) exception value to\r
-                                  propagate provided\r
-  @retval  EFI_PROTOCOL_ERROR     #VE handling failed, (new) exception value to\r
-                                  propagate provided\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-VmTdExitHandleVe (\r
-  IN OUT EFI_EXCEPTION_TYPE  *ExceptionType,\r
-  IN OUT EFI_SYSTEM_CONTEXT  SystemContext\r
-  )\r
-{\r
-  *ExceptionType = VE_EXCEPTION;\r
-\r
-  return EFI_UNSUPPORTED;\r
-}\r
diff --git a/UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.c b/UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.c
deleted file mode 100644 (file)
index d661d85..0000000
+++ /dev/null
@@ -1,165 +0,0 @@
-/** @file\r
-  VMGEXIT Base 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
-#include <Base.h>\r
-#include <Uefi.h>\r
-#include <Library/VmgExitLib.h>\r
-\r
-/**\r
-  Perform VMGEXIT.\r
-\r
-  Sets the necessary fields of the GHCB, invokes the VMGEXIT instruction and\r
-  then handles the return actions.\r
-\r
-  The base library function returns an error in the form of a\r
-  GHCB_EVENT_INJECTION representing a GP_EXCEPTION.\r
-\r
-  @param[in, out]  Ghcb       A pointer to the GHCB\r
-  @param[in]       ExitCode   VMGEXIT code to be assigned to the SwExitCode\r
-                              field of the GHCB.\r
-  @param[in]       ExitInfo1  VMGEXIT information to be assigned to the\r
-                              SwExitInfo1 field of the GHCB.\r
-  @param[in]       ExitInfo2  VMGEXIT information to be assigned to the\r
-                              SwExitInfo2 field of the GHCB.\r
-\r
-  @retval  0                  VMGEXIT succeeded.\r
-  @return                     Exception number to be propagated, VMGEXIT\r
-                              processing did not succeed.\r
-\r
-**/\r
-UINT64\r
-EFIAPI\r
-VmgExit (\r
-  IN OUT GHCB    *Ghcb,\r
-  IN     UINT64  ExitCode,\r
-  IN     UINT64  ExitInfo1,\r
-  IN     UINT64  ExitInfo2\r
-  )\r
-{\r
-  GHCB_EVENT_INJECTION  Event;\r
-\r
-  Event.Uint64          = 0;\r
-  Event.Elements.Vector = GP_EXCEPTION;\r
-  Event.Elements.Type   = GHCB_EVENT_INJECTION_TYPE_EXCEPTION;\r
-  Event.Elements.Valid  = 1;\r
-\r
-  return Event.Uint64;\r
-}\r
-\r
-/**\r
-  Perform pre-VMGEXIT initialization/preparation.\r
-\r
-  Performs the necessary steps in preparation for invoking VMGEXIT. Must be\r
-  called before setting any fields within the GHCB.\r
-\r
-  @param[in, out]  Ghcb            A pointer to the GHCB\r
-  @param[in, out]  InterruptState  A pointer to hold the current interrupt\r
-                                   state, used for restoring in VmgDone ()\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-VmgInit (\r
-  IN OUT GHCB     *Ghcb,\r
-  IN OUT BOOLEAN  *InterruptState\r
-  )\r
-{\r
-}\r
-\r
-/**\r
-  Perform post-VMGEXIT cleanup.\r
-\r
-  Performs the necessary steps to cleanup after invoking VMGEXIT. Must be\r
-  called after obtaining needed fields within the GHCB.\r
-\r
-  @param[in, out]  Ghcb            A pointer to the GHCB\r
-  @param[in]       InterruptState  An indicator to conditionally (re)enable\r
-                                   interrupts\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-VmgDone (\r
-  IN OUT GHCB     *Ghcb,\r
-  IN     BOOLEAN  InterruptState\r
-  )\r
-{\r
-}\r
-\r
-/**\r
-  Marks a field at the specified offset as valid in the GHCB.\r
-\r
-  The ValidBitmap area represents the areas of the GHCB that have been marked\r
-  valid. Set the bit in ValidBitmap for the input offset.\r
-\r
-  @param[in, out] Ghcb    Pointer to the Guest-Hypervisor Communication Block\r
-  @param[in]      Offset  Qword offset in the GHCB to mark valid\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-VmgSetOffsetValid (\r
-  IN OUT GHCB           *Ghcb,\r
-  IN     GHCB_REGISTER  Offset\r
-  )\r
-{\r
-}\r
-\r
-/**\r
-  Checks if a specified offset is valid in the GHCB.\r
-\r
-  The ValidBitmap area represents the areas of the GHCB that have been marked\r
-  valid. Return whether the bit in the ValidBitmap is set for the input offset.\r
-\r
-  @param[in]  Ghcb            A pointer to the GHCB\r
-  @param[in]  Offset          Qword offset in the GHCB to mark valid\r
-\r
-  @retval TRUE                Offset is marked valid in the GHCB\r
-  @retval FALSE               Offset is not marked valid in the GHCB\r
-\r
-**/\r
-BOOLEAN\r
-EFIAPI\r
-VmgIsOffsetValid (\r
-  IN GHCB           *Ghcb,\r
-  IN GHCB_REGISTER  Offset\r
-  )\r
-{\r
-  return FALSE;\r
-}\r
-\r
-/**\r
-  Handle a #VC exception.\r
-\r
-  Performs the necessary processing to handle a #VC exception.\r
-\r
-  The base library function returns an error equal to VC_EXCEPTION,\r
-  to be propagated to the standard exception handling stack.\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
-  *ExceptionType = VC_EXCEPTION;\r
-\r
-  return EFI_UNSUPPORTED;\r
-}\r
diff --git a/UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.inf b/UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.inf
deleted file mode 100644 (file)
index 4aab601..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-## @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                      = VmgExitLibNull\r
-  MODULE_UNI_FILE                = VmgExitLibNull.uni\r
-  FILE_GUID                      = 3cd7368f-ef9b-4a9b-9571-2ed93813677e\r
-  MODULE_TYPE                    = BASE\r
-  VERSION_STRING                 = 1.0\r
-  LIBRARY_CLASS                  = VmgExitLib\r
-\r
-[Sources.common]\r
-  VmgExitLibNull.c\r
-  VmTdExitNull.c\r
-\r
-[Packages]\r
-  MdePkg/MdePkg.dec\r
-  UefiCpuPkg/UefiCpuPkg.dec\r
-\r
-[LibraryClasses]\r
-  BaseLib\r
-\r
diff --git a/UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.uni b/UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.uni
deleted file mode 100644 (file)
index 8639bc0..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-// /** @file\r
-// VMGEXIT support library instance.\r
-//\r
-// VMGEXIT support library instance.\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
-\r
-#string STR_MODULE_ABSTRACT             #language en-US "VMGEXIT support NULL library instance"\r
-\r
-#string STR_MODULE_DESCRIPTION          #language en-US "VMGEXIT support NULL library instance."\r
-\r
index 718323d9042ca9b1ede3bc4f2409aeaac1c31b91..cff239d5283e61fa085003be9d263a27f365acc8 100644 (file)
@@ -53,8 +53,8 @@
   ##\r
   MpInitLib|Include/Library/MpInitLib.h\r
 \r
-  ##  @libraryclass  Provides function to support VMGEXIT processing.\r
-  VmgExitLib|Include/Library/VmgExitLib.h\r
+  ##  @libraryclass  Provides function to support CcExit processing.\r
+  CcExitLib|Include/Library/CcExitLib.h\r
 \r
   ##  @libraryclass  Provides function to get CPU cache information.\r
   CpuCacheInfoLib|Include/Library/CpuCacheInfoLib.h\r
index 0e1a99ddc09f51661024338af2a86ae4bfa17bcb..67b0ce46e455a0f4313c8b580b143c7aae48c08c 100644 (file)
@@ -59,7 +59,7 @@
   PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf\r
   PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf\r
   TpmMeasurementLib|MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.inf\r
-  VmgExitLib|UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.inf\r
+  CcExitLib|UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.inf\r
   MicrocodeLib|UefiCpuPkg/Library/MicrocodeLib/MicrocodeLib.inf\r
   SmmCpuRendezvousLib|UefiCpuPkg/Library/SmmCpuRendezvousLib/SmmCpuRendezvousLib.inf\r
   CpuPageTableLib|UefiCpuPkg/Library/CpuPageTableLib/CpuPageTableLib.inf\r
   UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLib.inf\r
   UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLibStm.inf\r
   UefiCpuPkg/Library/SmmCpuFeaturesLib/StandaloneMmCpuFeaturesLib.inf\r
-  UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.inf\r
+  UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.inf\r
   UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationPei.inf\r
   UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationSmm.inf\r
   UefiCpuPkg/SecCore/SecCore.inf\r
index 1150be6acd0e432c75afd3f41591d9573daed566..723a50a42284ec245af2bd84b10fbe512fce7276 100644 (file)
   VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf\r
   VariablePolicyHelperLib|MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.inf\r
   VariableFlashInfoLib|MdeModulePkg/Library/BaseVariableFlashInfoLib/BaseVariableFlashInfoLib.inf\r
-  VmgExitLib|UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.inf\r
+  CcExitLib|UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.inf\r
   ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf\r
 \r
 [LibraryClasses.common]\r