public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [PATCH V2 0/9] Rename VmgExitLib to CcExitLib
@ 2022-11-03 23:19 Min Xu
  2022-11-03 23:19 ` [PATCH V2 1/9] UefiCpuPkg: Add CcExitLib Min Xu
                   ` (9 more replies)
  0 siblings, 10 replies; 13+ messages in thread
From: Min Xu @ 2022-11-03 23:19 UTC (permalink / raw)
  To: devel
  Cc: Min Xu, Eric Dong, Ray Ni, Brijesh Singh, Erdem Aktas,
	Gerd Hoffmann, James Bottomley, Jiewen Yao, Tom Lendacky,
	Guo Dong, Sean Rhodes, James Lu, Gua Guo, Michael D Kinney,
	Liming Gao

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-set creates CcExitLib which is a simple copy of VmgExitLib
except some of the API names are renamed with a CcExitLib prefix. For
example VmgExit is renamed as CcExitLibVmgExit.

To make sure the build will not be broken by the renaming, this patch-set
first creates CcExitLib (Patch #1/2). Then VmgExitLib is replaced by
CcExitLib in UefiCpuPkg/UefiPayloadPkg/OvmfPkg (Patch #3/4/5/6). After
that VmgExitLib is deleted (Patch #7/8). At last Maintainers.txt
is updated (Patch #9).

Code: https://github.com/mxu9/edk2/tree/CcExitLib.v2

v2 changes:
 - Patch #3 is added to import CcExitLib in OvmfPkg's *.dsc. This is to
   prevent the building from being broken in the following patches.

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>
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: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <gaoliming@byosoft.com.cn>
Signed-off-by: Min Xu <min.m.xu@intel.com>

Min M Xu (9):
  UefiCpuPkg: Add CcExitLib
  OvmfPkg: Implement CcExitLib
  OvmfPkg: Add CcExitLib in *.dsc
  UefiCpuPkg: Use CcExitLib instead of VmgExitLib
  UefiPayloadPkg: Use CcExitLib instead of VmgExitLib
  OvmfPkg: Use CcExitLib instead of VmgExitLib
  OvmfPkg: Delete VmgExitLib
  UefiCpuPkg: Delete VmgExitLib
  Maintainers: Update the VmgExitLib to CcExitLib

 Maintainers.txt                               |   2 +-
 OvmfPkg/AmdSev/AmdSevX64.dsc                  |   4 +-
 OvmfPkg/Bhyve/BhyveX64.dsc                    |   2 +-
 OvmfPkg/CloudHv/CloudHvX64.dsc                |   6 +-
 OvmfPkg/IntelTdx/IntelTdxX64.dsc              |   4 +-
 .../DxeMemEncryptSevLib.inf                   |   2 +-
 .../PeiMemEncryptSevLib.inf                   |   2 +-
 .../SecMemEncryptSevLib.inf                   |   2 +-
 .../X64/SnpPageStateChangeInternal.c          |  10 +-
 .../VmgExitLib.c => CcExitLib/CcExitLib.c}    |  23 +--
 .../CcExitLib.inf}                            |  19 +--
 .../CcExitTd.h}                               |   6 +-
 .../CcExitVcHandler.c}                        | 133 +++++++++---------
 .../CcExitVcHandler.h}                        |  10 +-
 .../CcExitVeHandler.c}                        |   8 +-
 .../PeiDxeCcExitVcHandler.c}                  |  12 +-
 .../SecCcExitLib.inf}                         |  16 +--
 .../SecCcExitVcHandler.c}                     |  12 +-
 .../X64/TdVmcallCpuid.nasm                    |   4 +-
 OvmfPkg/Microvm/MicrovmX64.dsc                |   4 +-
 OvmfPkg/OvmfPkgIa32.dsc                       |   4 +-
 OvmfPkg/OvmfPkgIa32X64.dsc                    |   4 +-
 OvmfPkg/OvmfPkgX64.dsc                        |   6 +-
 OvmfPkg/OvmfXen.dsc                           |   2 +-
 OvmfPkg/PlatformPei/AmdSev.c                  |  10 +-
 OvmfPkg/PlatformPei/PlatformPei.inf           |   2 +-
 .../FvbServicesRuntimeDxe.inf                 |   2 +-
 .../QemuFlashDxe.c                            |  10 +-
 .../Library/{VmgExitLib.h => CcExitLib.h}     |  29 ++--
 .../CcExitLibNull.c}                          |  47 +++++--
 .../CcExitLibNull.inf}                        |  14 +-
 .../Library/CcExitLibNull/CcExitLibNull.uni   |  14 ++
 .../DxeCpuExceptionHandlerLib.inf             |   2 +-
 .../PeiCpuExceptionHandlerLib.inf             |   2 +-
 .../PeiDxeSmmCpuException.c                   |   6 +-
 .../SecPeiCpuException.c                      |   6 +-
 .../SecPeiCpuExceptionHandlerLib.inf          |   2 +-
 .../SmmCpuExceptionHandlerLib.inf             |   2 +-
 .../Xcode5SecPeiCpuExceptionHandlerLib.inf    |   2 +-
 UefiCpuPkg/Library/MpInitLib/AmdSev.c         |  10 +-
 UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf |   2 +-
 UefiCpuPkg/Library/MpInitLib/DxeMpLib.c       |   8 +-
 UefiCpuPkg/Library/MpInitLib/MpLib.c          |   2 +-
 UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf |   2 +-
 UefiCpuPkg/Library/MpInitLib/X64/AmdSev.c     |  10 +-
 .../Library/VmgExitLibNull/VmTdExitNull.c     |  38 -----
 .../Library/VmgExitLibNull/VmgExitLibNull.uni |  15 --
 UefiCpuPkg/UefiCpuPkg.dec                     |   4 +-
 UefiCpuPkg/UefiCpuPkg.dsc                     |   4 +-
 UefiPayloadPkg/UefiPayloadPkg.dsc             |   2 +-
 50 files changed, 269 insertions(+), 275 deletions(-)
 rename OvmfPkg/Library/{VmgExitLib/VmgExitLib.c => CcExitLib/CcExitLib.c} (89%)
 rename OvmfPkg/Library/{VmgExitLib/VmgExitLib.inf => CcExitLib/CcExitLib.inf} (60%)
 rename OvmfPkg/Library/{VmgExitLib/VmTdExitHandler.h => CcExitLib/CcExitTd.h} (84%)
 rename OvmfPkg/Library/{VmgExitLib/VmgExitVcHandler.c => CcExitLib/CcExitVcHandler.c} (90%)
 rename OvmfPkg/Library/{VmgExitLib/VmgExitVcHandler.h => CcExitLib/CcExitVcHandler.h} (85%)
 rename OvmfPkg/Library/{VmgExitLib/VmTdExitVeHandler.c => CcExitLib/CcExitVeHandler.c} (94%)
 rename OvmfPkg/Library/{VmgExitLib/PeiDxeVmgExitVcHandler.c => CcExitLib/PeiDxeCcExitVcHandler.c} (87%)
 rename OvmfPkg/Library/{VmgExitLib/SecVmgExitLib.inf => CcExitLib/SecCcExitLib.inf} (73%)
 rename OvmfPkg/Library/{VmgExitLib/SecVmgExitVcHandler.c => CcExitLib/SecCcExitVcHandler.c} (88%)
 rename OvmfPkg/Library/{VmgExitLib => CcExitLib}/X64/TdVmcallCpuid.nasm (93%)
 rename UefiCpuPkg/Include/Library/{VmgExitLib.h => CcExitLib.h} (86%)
 rename UefiCpuPkg/Library/{VmgExitLibNull/VmgExitLibNull.c => CcExitLibNull/CcExitLibNull.c} (76%)
 rename UefiCpuPkg/Library/{VmgExitLibNull/VmgExitLibNull.inf => CcExitLibNull/CcExitLibNull.inf} (50%)
 create mode 100644 UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.uni
 delete mode 100644 UefiCpuPkg/Library/VmgExitLibNull/VmTdExitNull.c
 delete mode 100644 UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.uni

-- 
2.29.2.windows.2


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH V2 1/9] UefiCpuPkg: Add CcExitLib
  2022-11-03 23:19 [PATCH V2 0/9] Rename VmgExitLib to CcExitLib Min Xu
@ 2022-11-03 23:19 ` Min Xu
  2022-11-04 14:34   ` [edk2-devel] " Lendacky, Thomas
  2022-11-03 23:19 ` [PATCH V2 2/9] OvmfPkg: Implement CcExitLib Min Xu
                   ` (8 subsequent siblings)
  9 siblings, 1 reply; 13+ messages in thread
From: Min Xu @ 2022-11-03 23:19 UTC (permalink / raw)
  To: devel
  Cc: Min M Xu, Eric Dong, Ray Ni, Brijesh Singh, Erdem Aktas,
	Gerd Hoffmann, James Bottomley, Jiewen Yao, Tom Lendacky

From: Min M Xu <min.m.xu@intel.com>

BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=4123

CcExitLib is designed to support handling #VC/#VE exceptions and issuing
VMGEXIT instructions. It can be used to perform these:
  - Handling #VC exceptions
  - Handling #VE exceptions
  - Preparing for and issuing a VMGEXIT
  - Performing MMIO-related write operations to support flash emulation
  - Performing AP related boot opeations

The base functions in this driver will not do anything and will return
an error if a return value is required. It is expected that other packages
(like OvmfPkg) will create a version of the library to fully support an
CC gueste (such as SEV-ES and TDX).

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>
Signed-off-by: Min Xu <min.m.xu@intel.com>
---
 UefiCpuPkg/Include/Library/CcExitLib.h        | 176 ++++++++++++++++
 .../Library/CcExitLibNull/CcExitLibNull.c     | 194 ++++++++++++++++++
 .../Library/CcExitLibNull/CcExitLibNull.inf   |  28 +++
 .../Library/CcExitLibNull/CcExitLibNull.uni   |  14 ++
 UefiCpuPkg/UefiCpuPkg.dec                     |   3 +
 5 files changed, 415 insertions(+)
 create mode 100644 UefiCpuPkg/Include/Library/CcExitLib.h
 create mode 100644 UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.c
 create mode 100644 UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.inf
 create mode 100644 UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.uni

diff --git a/UefiCpuPkg/Include/Library/CcExitLib.h b/UefiCpuPkg/Include/Library/CcExitLib.h
new file mode 100644
index 000000000000..40372e10b39e
--- /dev/null
+++ b/UefiCpuPkg/Include/Library/CcExitLib.h
@@ -0,0 +1,176 @@
+/** @file
+  Public header file for the CcExitLib.
+
+  This library class defines some routines used for below CcExit handler.
+   - Invoking the VMGEXIT instruction in support of SEV-ES and to handle
+     #VC exceptions.
+   - Handle #VE exception in TDX.
+
+  Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2020 - 2022, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef CC_EXIT_LIB_H_
+#define CC_EXIT_LIB_H_
+
+#include <Protocol/DebugSupport.h>
+#include <Register/Amd/Ghcb.h>
+
+#define VE_EXCEPTION  20
+
+/**
+  Perform VMGEXIT.
+
+  Sets the necessary fields of the GHCB, invokes the VMGEXIT instruction and
+  then handles the return actions.
+
+  @param[in, out]  Ghcb       A pointer to the GHCB
+  @param[in]       ExitCode   VMGEXIT code to be assigned to the SwExitCode
+                              field of the GHCB.
+  @param[in]       ExitInfo1  VMGEXIT information to be assigned to the
+                              SwExitInfo1 field of the GHCB.
+  @param[in]       ExitInfo2  VMGEXIT information to be assigned to the
+                              SwExitInfo2 field of the GHCB.
+
+  @retval  0                  VMGEXIT succeeded.
+  @return                     Exception number to be propagated, VMGEXIT
+                              processing did not succeed.
+
+**/
+UINT64
+EFIAPI
+CcExitLibVmgExit (
+  IN OUT GHCB    *Ghcb,
+  IN     UINT64  ExitCode,
+  IN     UINT64  ExitInfo1,
+  IN     UINT64  ExitInfo2
+  );
+
+/**
+  Perform pre-VMGEXIT initialization/preparation.
+
+  Performs the necessary steps in preparation for invoking VMGEXIT. Must be
+  called before setting any fields within the GHCB.
+
+  @param[in, out]  Ghcb            A pointer to the GHCB
+  @param[in, out]  InterruptState  A pointer to hold the current interrupt
+                                   state, used for restoring in CcExitLibVmgDone ()
+
+**/
+VOID
+EFIAPI
+CcExitLibVmgInit (
+  IN OUT GHCB     *Ghcb,
+  IN OUT BOOLEAN  *InterruptState
+  );
+
+/**
+  Perform post-VMGEXIT cleanup.
+
+  Performs the necessary steps to cleanup after invoking VMGEXIT. Must be
+  called after obtaining needed fields within the GHCB.
+
+  @param[in, out]  Ghcb            A pointer to the GHCB
+  @param[in]       InterruptState  An indicator to conditionally (re)enable
+                                   interrupts
+
+**/
+VOID
+EFIAPI
+CcExitLibVmgDone (
+  IN OUT GHCB     *Ghcb,
+  IN     BOOLEAN  InterruptState
+  );
+
+/**
+  Marks a specified offset as valid in the GHCB.
+
+  The ValidBitmap area represents the areas of the GHCB that have been marked
+  valid. Set the bit in ValidBitmap for the input offset.
+
+  @param[in, out]  Ghcb       A pointer to the GHCB
+  @param[in]       Offset     Qword offset in the GHCB to mark valid
+
+**/
+VOID
+EFIAPI
+CcExitLibVmgSetOffsetValid (
+  IN OUT GHCB           *Ghcb,
+  IN     GHCB_REGISTER  Offset
+  );
+
+/**
+  Checks if a specified offset is valid in the GHCB.
+
+  The ValidBitmap area represents the areas of the GHCB that have been marked
+  valid. Return whether the bit in the ValidBitmap is set for the input offset.
+
+  @param[in]  Ghcb            A pointer to the GHCB
+  @param[in]  Offset          Qword offset in the GHCB to mark valid
+
+  @retval TRUE                Offset is marked valid in the GHCB
+  @retval FALSE               Offset is not marked valid in the GHCB
+
+**/
+BOOLEAN
+EFIAPI
+CcExitLibVmgIsOffsetValid (
+  IN GHCB           *Ghcb,
+  IN GHCB_REGISTER  Offset
+  );
+
+/**
+  Handle a #VC exception.
+
+  Performs the necessary processing to handle a #VC exception.
+
+  The base library function returns an error equal to VC_EXCEPTION,
+  to be propagated to the standard exception handling stack.
+
+  @param[in, out]  ExceptionType  Pointer to an EFI_EXCEPTION_TYPE to be set
+                                  as value to use on error.
+  @param[in, out]  SystemContext  Pointer to EFI_SYSTEM_CONTEXT
+
+  @retval  EFI_SUCCESS            Exception handled
+  @retval  EFI_UNSUPPORTED        #VC not supported, (new) exception value to
+                                  propagate provided
+  @retval  EFI_PROTOCOL_ERROR     #VC handling failed, (new) exception value to
+                                  propagate provided
+
+**/
+EFI_STATUS
+EFIAPI
+CcExitHandleVc (
+  IN OUT EFI_EXCEPTION_TYPE  *ExceptionType,
+  IN OUT EFI_SYSTEM_CONTEXT  SystemContext
+  );
+
+/**
+  Handle a #VE exception.
+
+  Performs the necessary processing to handle a #VE exception.
+
+  The base library function returns an error equal to VE_EXCEPTION,
+  to be propagated to the standard exception handling stack.
+
+  @param[in, out]  ExceptionType  Pointer to an EFI_EXCEPTION_TYPE to be set
+                                  as value to use on error.
+  @param[in, out]  SystemContext  Pointer to EFI_SYSTEM_CONTEXT
+
+  @retval  EFI_SUCCESS            Exception handled
+  @retval  EFI_UNSUPPORTED        #VE not supported, (new) exception value to
+                                  propagate provided
+  @retval  EFI_PROTOCOL_ERROR     #VE handling failed, (new) exception value to
+                                  propagate provided
+
+**/
+EFI_STATUS
+EFIAPI
+CcExitHandleVe (
+  IN OUT EFI_EXCEPTION_TYPE  *ExceptionType,
+  IN OUT EFI_SYSTEM_CONTEXT  SystemContext
+  );
+
+#endif
diff --git a/UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.c b/UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.c
new file mode 100644
index 000000000000..bd23793f1e04
--- /dev/null
+++ b/UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.c
@@ -0,0 +1,194 @@
+/** @file
+  CcExit Base Support Library.
+
+  Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2020 - 2022, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Base.h>
+#include <Uefi.h>
+#include <Library/CcExitLib.h>
+
+/**
+  Perform VMGEXIT.
+
+  Sets the necessary fields of the GHCB, invokes the VMGEXIT instruction and
+  then handles the return actions.
+
+  The base library function returns an error in the form of a
+  GHCB_EVENT_INJECTION representing a GP_EXCEPTION.
+
+  @param[in, out]  Ghcb       A pointer to the GHCB
+  @param[in]       ExitCode   VMGEXIT code to be assigned to the SwExitCode
+                              field of the GHCB.
+  @param[in]       ExitInfo1  VMGEXIT information to be assigned to the
+                              SwExitInfo1 field of the GHCB.
+  @param[in]       ExitInfo2  VMGEXIT information to be assigned to the
+                              SwExitInfo2 field of the GHCB.
+
+  @retval  0                  VMGEXIT succeeded.
+  @return                     Exception number to be propagated, VMGEXIT
+                              processing did not succeed.
+
+**/
+UINT64
+EFIAPI
+CcExitLibVmgExit (
+  IN OUT GHCB    *Ghcb,
+  IN     UINT64  ExitCode,
+  IN     UINT64  ExitInfo1,
+  IN     UINT64  ExitInfo2
+  )
+{
+  GHCB_EVENT_INJECTION  Event;
+
+  Event.Uint64          = 0;
+  Event.Elements.Vector = GP_EXCEPTION;
+  Event.Elements.Type   = GHCB_EVENT_INJECTION_TYPE_EXCEPTION;
+  Event.Elements.Valid  = 1;
+
+  return Event.Uint64;
+}
+
+/**
+  Perform pre-VMGEXIT initialization/preparation.
+
+  Performs the necessary steps in preparation for invoking VMGEXIT. Must be
+  called before setting any fields within the GHCB.
+
+  @param[in, out]  Ghcb            A pointer to the GHCB
+  @param[in, out]  InterruptState  A pointer to hold the current interrupt
+                                   state, used for restoring in CcExitLibVmgDone ()
+
+**/
+VOID
+EFIAPI
+CcExitLibVmgInit (
+  IN OUT GHCB     *Ghcb,
+  IN OUT BOOLEAN  *InterruptState
+  )
+{
+}
+
+/**
+  Perform post-VMGEXIT cleanup.
+
+  Performs the necessary steps to cleanup after invoking VMGEXIT. Must be
+  called after obtaining needed fields within the GHCB.
+
+  @param[in, out]  Ghcb            A pointer to the GHCB
+  @param[in]       InterruptState  An indicator to conditionally (re)enable
+                                   interrupts
+
+**/
+VOID
+EFIAPI
+CcExitLibVmgDone (
+  IN OUT GHCB     *Ghcb,
+  IN     BOOLEAN  InterruptState
+  )
+{
+}
+
+/**
+  Marks a field at the specified offset as valid in the GHCB.
+
+  The ValidBitmap area represents the areas of the GHCB that have been marked
+  valid. Set the bit in ValidBitmap for the input offset.
+
+  @param[in, out] Ghcb    Pointer to the Guest-Hypervisor Communication Block
+  @param[in]      Offset  Qword offset in the GHCB to mark valid
+
+**/
+VOID
+EFIAPI
+CcExitLibVmgSetOffsetValid (
+  IN OUT GHCB           *Ghcb,
+  IN     GHCB_REGISTER  Offset
+  )
+{
+}
+
+/**
+  Checks if a specified offset is valid in the GHCB.
+
+  The ValidBitmap area represents the areas of the GHCB that have been marked
+  valid. Return whether the bit in the ValidBitmap is set for the input offset.
+
+  @param[in]  Ghcb            A pointer to the GHCB
+  @param[in]  Offset          Qword offset in the GHCB to mark valid
+
+  @retval TRUE                Offset is marked valid in the GHCB
+  @retval FALSE               Offset is not marked valid in the GHCB
+
+**/
+BOOLEAN
+EFIAPI
+CcExitLibVmgIsOffsetValid (
+  IN GHCB           *Ghcb,
+  IN GHCB_REGISTER  Offset
+  )
+{
+  return FALSE;
+}
+
+/**
+  Handle a #VC exception.
+
+  Performs the necessary processing to handle a #VC exception.
+
+  The base library function returns an error equal to VC_EXCEPTION,
+  to be propagated to the standard exception handling stack.
+
+  @param[in, out]  ExceptionType  Pointer to an EFI_EXCEPTION_TYPE to be set
+                                  as value to use on error.
+  @param[in, out]  SystemContext  Pointer to EFI_SYSTEM_CONTEXT
+
+  @retval  EFI_SUCCESS            Exception handled
+  @retval  EFI_UNSUPPORTED        #VC not supported, (new) exception value to
+                                  propagate provided
+  @retval  EFI_PROTOCOL_ERROR     #VC handling failed, (new) exception value to
+                                  propagate provided
+
+**/
+EFI_STATUS
+EFIAPI
+CcExitHandleVc (
+  IN OUT EFI_EXCEPTION_TYPE  *ExceptionType,
+  IN OUT EFI_SYSTEM_CONTEXT  SystemContext
+  )
+{
+  *ExceptionType = VC_EXCEPTION;
+
+  return EFI_UNSUPPORTED;
+}
+
+/**
+  Handle a #VE exception.
+
+  Performs the necessary processing to handle a #VE exception.
+
+  @param[in, out]  ExceptionType  Pointer to an EFI_EXCEPTION_TYPE to be set
+                                  as value to use on error.
+  @param[in, out]  SystemContext  Pointer to EFI_SYSTEM_CONTEXT
+
+  @retval  EFI_SUCCESS            Exception handled
+  @retval  EFI_UNSUPPORTED        #VE not supported, (new) exception value to
+                                  propagate provided
+  @retval  EFI_PROTOCOL_ERROR     #VE handling failed, (new) exception value to
+                                  propagate provided
+
+**/
+EFI_STATUS
+EFIAPI
+CcExitHandleVe (
+  IN OUT EFI_EXCEPTION_TYPE  *ExceptionType,
+  IN OUT EFI_SYSTEM_CONTEXT  SystemContext
+  )
+{
+  *ExceptionType = VE_EXCEPTION;
+
+  return EFI_UNSUPPORTED;
+}
diff --git a/UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.inf b/UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.inf
new file mode 100644
index 000000000000..c1f53e42dbe4
--- /dev/null
+++ b/UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.inf
@@ -0,0 +1,28 @@
+## @file
+#  CcExit Base Support Library.
+#
+#  Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved.<BR>
+#  Copyright (c) 2020 - 2022, Intel Corporation. All rights reserved.<BR>
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = CcExitLibNull
+  MODULE_UNI_FILE                = CcExitLibNull.uni
+  FILE_GUID                      = 4029bbf2-ed6c-4cf6-ac17-a0213684ae41
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = CcExitLib
+
+[Sources.common]
+  CcExitLibNull.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  UefiCpuPkg/UefiCpuPkg.dec
+
+[LibraryClasses]
+  BaseLib
+
diff --git a/UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.uni b/UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.uni
new file mode 100644
index 000000000000..b18ae8792ed7
--- /dev/null
+++ b/UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.uni
@@ -0,0 +1,14 @@
+// /** @file
+// CcExitLib instance.
+//
+// Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved.<BR>
+// Copyright (c) 2020 - 2022, Intel Corporation. All rights reserved.<BR>
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT             #language en-US "CcExitLib NULL instance"
+
+#string STR_MODULE_DESCRIPTION          #language en-US "CcExitLib NULL instance."
+
diff --git a/UefiCpuPkg/UefiCpuPkg.dec b/UefiCpuPkg/UefiCpuPkg.dec
index 718323d9042c..8058b679412f 100644
--- a/UefiCpuPkg/UefiCpuPkg.dec
+++ b/UefiCpuPkg/UefiCpuPkg.dec
@@ -56,6 +56,9 @@
   ##  @libraryclass  Provides function to support VMGEXIT processing.
   VmgExitLib|Include/Library/VmgExitLib.h
 
+  ##  @libraryclass  Provides function to support CcExit processing.
+  CcExitLib|Include/Library/CcExitLib.h
+
   ##  @libraryclass  Provides function to get CPU cache information.
   CpuCacheInfoLib|Include/Library/CpuCacheInfoLib.h
 
-- 
2.29.2.windows.2


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH V2 2/9] OvmfPkg: Implement CcExitLib
  2022-11-03 23:19 [PATCH V2 0/9] Rename VmgExitLib to CcExitLib Min Xu
  2022-11-03 23:19 ` [PATCH V2 1/9] UefiCpuPkg: Add CcExitLib Min Xu
@ 2022-11-03 23:19 ` Min Xu
  2022-11-03 23:19 ` [PATCH V2 3/9] OvmfPkg: Add CcExitLib in *.dsc Min Xu
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 13+ messages in thread
From: Min Xu @ 2022-11-03 23:19 UTC (permalink / raw)
  To: devel
  Cc: Min M Xu, Brijesh Singh, Erdem Aktas, Gerd Hoffmann,
	James Bottomley, Jiewen Yao, Tom Lendacky

From: Min M Xu <min.m.xu@intel.com>

https://bugzilla.tianocore.org/show_bug.cgi?id=4123

The base CcExitLib library provides a default limited interface. As it
does not provide full support, create an OVMF version of this library to
begin the process of providing full support of Cc guest (such as SEV-ES,
TDX) within OVMF.

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>
Signed-off-by: Min Xu <min.m.xu@intel.com>
---
 OvmfPkg/Library/CcExitLib/CcExitLib.c         |  239 ++
 OvmfPkg/Library/CcExitLib/CcExitLib.inf       |   46 +
 OvmfPkg/Library/CcExitLib/CcExitTd.h          |   32 +
 OvmfPkg/Library/CcExitLib/CcExitVcHandler.c   | 2355 +++++++++++++++++
 OvmfPkg/Library/CcExitLib/CcExitVcHandler.h   |   53 +
 OvmfPkg/Library/CcExitLib/CcExitVeHandler.c   |  559 ++++
 .../Library/CcExitLib/PeiDxeCcExitVcHandler.c |  103 +
 OvmfPkg/Library/CcExitLib/SecCcExitLib.inf    |   48 +
 .../Library/CcExitLib/SecCcExitVcHandler.c    |  109 +
 .../Library/CcExitLib/X64/TdVmcallCpuid.nasm  |  146 +
 10 files changed, 3690 insertions(+)
 create mode 100644 OvmfPkg/Library/CcExitLib/CcExitLib.c
 create mode 100644 OvmfPkg/Library/CcExitLib/CcExitLib.inf
 create mode 100644 OvmfPkg/Library/CcExitLib/CcExitTd.h
 create mode 100644 OvmfPkg/Library/CcExitLib/CcExitVcHandler.c
 create mode 100644 OvmfPkg/Library/CcExitLib/CcExitVcHandler.h
 create mode 100644 OvmfPkg/Library/CcExitLib/CcExitVeHandler.c
 create mode 100644 OvmfPkg/Library/CcExitLib/PeiDxeCcExitVcHandler.c
 create mode 100644 OvmfPkg/Library/CcExitLib/SecCcExitLib.inf
 create mode 100644 OvmfPkg/Library/CcExitLib/SecCcExitVcHandler.c
 create mode 100644 OvmfPkg/Library/CcExitLib/X64/TdVmcallCpuid.nasm

diff --git a/OvmfPkg/Library/CcExitLib/CcExitLib.c b/OvmfPkg/Library/CcExitLib/CcExitLib.c
new file mode 100644
index 000000000000..2e9ce141f33b
--- /dev/null
+++ b/OvmfPkg/Library/CcExitLib/CcExitLib.c
@@ -0,0 +1,239 @@
+/** @file
+  CcExitLib Support Library.
+
+  Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (C) 2020 - 2022, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Base.h>
+#include <Uefi.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/CcExitLib.h>
+#include <Register/Amd/Msr.h>
+
+/**
+  Check for VMGEXIT error
+
+  Check if the hypervisor has returned an error after completion of the VMGEXIT
+  by examining the SwExitInfo1 field of the GHCB.
+
+  @param[in]  Ghcb       A pointer to the GHCB
+
+  @retval  0             VMGEXIT succeeded.
+  @return                Exception number to be propagated, VMGEXIT processing
+                         did not succeed.
+
+**/
+STATIC
+UINT64
+VmgExitErrorCheck (
+  IN GHCB  *Ghcb
+  )
+{
+  GHCB_EVENT_INJECTION  Event;
+  GHCB_EXIT_INFO        ExitInfo;
+  UINT64                Status;
+
+  ExitInfo.Uint64 = Ghcb->SaveArea.SwExitInfo1;
+  ASSERT (
+    (ExitInfo.Elements.Lower32Bits == 0) ||
+    (ExitInfo.Elements.Lower32Bits == 1)
+    );
+
+  Status = 0;
+  if (ExitInfo.Elements.Lower32Bits == 0) {
+    return Status;
+  }
+
+  if (ExitInfo.Elements.Lower32Bits == 1) {
+    ASSERT (Ghcb->SaveArea.SwExitInfo2 != 0);
+
+    //
+    // Check that the return event is valid
+    //
+    Event.Uint64 = Ghcb->SaveArea.SwExitInfo2;
+    if (Event.Elements.Valid &&
+        (Event.Elements.Type == GHCB_EVENT_INJECTION_TYPE_EXCEPTION))
+    {
+      switch (Event.Elements.Vector) {
+        case GP_EXCEPTION:
+        case UD_EXCEPTION:
+          //
+          // Use returned event as return code
+          //
+          Status = Event.Uint64;
+      }
+    }
+  }
+
+  if (Status == 0) {
+    GHCB_EVENT_INJECTION  GpEvent;
+
+    GpEvent.Uint64          = 0;
+    GpEvent.Elements.Vector = GP_EXCEPTION;
+    GpEvent.Elements.Type   = GHCB_EVENT_INJECTION_TYPE_EXCEPTION;
+    GpEvent.Elements.Valid  = 1;
+
+    Status = GpEvent.Uint64;
+  }
+
+  return Status;
+}
+
+/**
+  Perform VMGEXIT.
+
+  Sets the necessary fields of the GHCB, invokes the VMGEXIT instruction and
+  then handles the return actions.
+
+  @param[in, out]  Ghcb       A pointer to the GHCB
+  @param[in]       ExitCode   VMGEXIT code to be assigned to the SwExitCode
+                              field of the GHCB.
+  @param[in]       ExitInfo1  VMGEXIT information to be assigned to the
+                              SwExitInfo1 field of the GHCB.
+  @param[in]       ExitInfo2  VMGEXIT information to be assigned to the
+                              SwExitInfo2 field of the GHCB.
+
+  @retval  0                  VMGEXIT succeeded.
+  @return                     Exception number to be propagated, VMGEXIT
+                              processing did not succeed.
+
+**/
+UINT64
+EFIAPI
+CcExitLibVmgExit (
+  IN OUT GHCB    *Ghcb,
+  IN     UINT64  ExitCode,
+  IN     UINT64  ExitInfo1,
+  IN     UINT64  ExitInfo2
+  )
+{
+  Ghcb->SaveArea.SwExitCode  = ExitCode;
+  Ghcb->SaveArea.SwExitInfo1 = ExitInfo1;
+  Ghcb->SaveArea.SwExitInfo2 = ExitInfo2;
+
+  CcExitLibVmgSetOffsetValid (Ghcb, GhcbSwExitCode);
+  CcExitLibVmgSetOffsetValid (Ghcb, GhcbSwExitInfo1);
+  CcExitLibVmgSetOffsetValid (Ghcb, GhcbSwExitInfo2);
+
+  //
+  // Guest memory is used for the guest-hypervisor communication, so fence
+  // the invocation of the VMGEXIT instruction to ensure GHCB accesses are
+  // synchronized properly.
+  //
+  MemoryFence ();
+  AsmVmgExit ();
+  MemoryFence ();
+
+  return VmgExitErrorCheck (Ghcb);
+}
+
+/**
+  Perform pre-VMGEXIT initialization/preparation.
+
+  Performs the necessary steps in preparation for invoking VMGEXIT. Must be
+  called before setting any fields within the GHCB.
+
+  @param[in, out]  Ghcb            A pointer to the GHCB
+  @param[in, out]  InterruptState  A pointer to hold the current interrupt
+                                   state, used for restoring in CcExitLibVmgDone ()
+
+**/
+VOID
+EFIAPI
+CcExitLibVmgInit (
+  IN OUT GHCB     *Ghcb,
+  IN OUT BOOLEAN  *InterruptState
+  )
+{
+  //
+  // Be sure that an interrupt can't cause a #VC while the GHCB is
+  // being used.
+  //
+  *InterruptState = GetInterruptState ();
+  if (*InterruptState) {
+    DisableInterrupts ();
+  }
+
+  SetMem (&Ghcb->SaveArea, sizeof (Ghcb->SaveArea), 0);
+}
+
+/**
+  Perform post-VMGEXIT cleanup.
+
+  Performs the necessary steps to cleanup after invoking VMGEXIT. Must be
+  called after obtaining needed fields within the GHCB.
+
+  @param[in, out]  Ghcb            A pointer to the GHCB
+  @param[in]       InterruptState  An indicator to conditionally (re)enable
+                                   interrupts
+
+**/
+VOID
+EFIAPI
+CcExitLibVmgDone (
+  IN OUT GHCB     *Ghcb,
+  IN     BOOLEAN  InterruptState
+  )
+{
+  if (InterruptState) {
+    EnableInterrupts ();
+  }
+}
+
+/**
+  Marks a field at the specified offset as valid in the GHCB.
+
+  The ValidBitmap area represents the areas of the GHCB that have been marked
+  valid. Set the bit in ValidBitmap for the input offset.
+
+  @param[in, out] Ghcb    Pointer to the Guest-Hypervisor Communication Block
+  @param[in]      Offset  Qword offset in the GHCB to mark valid
+
+**/
+VOID
+EFIAPI
+CcExitLibVmgSetOffsetValid (
+  IN OUT GHCB           *Ghcb,
+  IN     GHCB_REGISTER  Offset
+  )
+{
+  UINT32  OffsetIndex;
+  UINT32  OffsetBit;
+
+  OffsetIndex = Offset / 8;
+  OffsetBit   = Offset % 8;
+
+  Ghcb->SaveArea.ValidBitmap[OffsetIndex] |= (1 << OffsetBit);
+}
+
+/**
+  Checks if a specified offset is valid in the GHCB.
+
+  The ValidBitmap area represents the areas of the GHCB that have been marked
+  valid. Return whether the bit in the ValidBitmap is set for the input offset.
+
+  @param[in]  Ghcb            A pointer to the GHCB
+  @param[in]  Offset          Qword offset in the GHCB to mark valid
+
+  @retval TRUE                Offset is marked valid in the GHCB
+  @retval FALSE               Offset is not marked valid in the GHCB
+
+**/
+BOOLEAN
+EFIAPI
+CcExitLibVmgIsOffsetValid (
+  IN GHCB           *Ghcb,
+  IN GHCB_REGISTER  Offset
+  )
+{
+  UINT32  OffsetIndex;
+  UINT32  OffsetBit;
+
+  OffsetIndex = Offset / 8;
+  OffsetBit   = Offset % 8;
+
+  return ((Ghcb->SaveArea.ValidBitmap[OffsetIndex] & (1 << OffsetBit)) != 0);
+}
diff --git a/OvmfPkg/Library/CcExitLib/CcExitLib.inf b/OvmfPkg/Library/CcExitLib/CcExitLib.inf
new file mode 100644
index 000000000000..85906c831fbc
--- /dev/null
+++ b/OvmfPkg/Library/CcExitLib/CcExitLib.inf
@@ -0,0 +1,46 @@
+## @file
+#  CcExitLib Library.
+#
+#  Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved.<BR>
+#  Copyright (C) 2020 - 2022, Intel Corporation. All rights reserved.<BR>
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = CcExitLib
+  FILE_GUID                      = 6edfe409-72d0-4574-adcd-78c972d8fd87
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = CcExitLib|PEIM DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER UEFI_DRIVER
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = X64
+#
+
+[Sources.common]
+  CcExitLib.c
+  CcExitVcHandler.c
+  CcExitVcHandler.h
+  PeiDxeCcExitVcHandler.c
+  CcExitVeHandler.c
+  X64/TdVmcallCpuid.nasm
+
+[Packages]
+  MdePkg/MdePkg.dec
+  OvmfPkg/OvmfPkg.dec
+  UefiCpuPkg/UefiCpuPkg.dec
+
+[LibraryClasses]
+  BaseLib
+  BaseMemoryLib
+  DebugLib
+  LocalApicLib
+  MemEncryptSevLib
+
+[Pcd]
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCpuidBase
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCpuidSize
diff --git a/OvmfPkg/Library/CcExitLib/CcExitTd.h b/OvmfPkg/Library/CcExitLib/CcExitTd.h
new file mode 100644
index 000000000000..4afc5794d226
--- /dev/null
+++ b/OvmfPkg/Library/CcExitLib/CcExitTd.h
@@ -0,0 +1,32 @@
+/** @file
+
+  Copyright (c) 2020 - 2021, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef CC_EXIT_TD_H_
+#define CC_EXIT_TD_H_
+
+#include <Base.h>
+#include <Uefi.h>
+
+/**
+  This function enable the TD guest to request the VMM to emulate CPUID
+  operation, especially for non-architectural, CPUID leaves.
+
+  @param[in]  Eax        Main leaf of the CPUID
+  @param[in]  Ecx        Sub-leaf of the CPUID
+  @param[out] Results    Returned result of CPUID operation
+
+  @return EFI_SUCCESS
+**/
+EFI_STATUS
+EFIAPI
+CcExitLibTdVmCallCpuid (
+  IN UINT64  Eax,
+  IN UINT64  Ecx,
+  OUT VOID   *Results
+  );
+
+#endif
diff --git a/OvmfPkg/Library/CcExitLib/CcExitVcHandler.c b/OvmfPkg/Library/CcExitLib/CcExitVcHandler.c
new file mode 100644
index 000000000000..c4a0284d1b5e
--- /dev/null
+++ b/OvmfPkg/Library/CcExitLib/CcExitVcHandler.c
@@ -0,0 +1,2355 @@
+/** @file
+  X64 #VC Exception Handler functon.
+
+  Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Base.h>
+#include <Uefi.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/LocalApicLib.h>
+#include <Library/MemEncryptSevLib.h>
+#include <Library/CcExitLib.h>
+#include <Register/Amd/Msr.h>
+#include <Register/Intel/Cpuid.h>
+#include <IndustryStandard/InstructionParsing.h>
+
+#include "CcExitVcHandler.h"
+
+//
+// Instruction execution mode definition
+//
+typedef enum {
+  LongMode64Bit = 0,
+  LongModeCompat32Bit,
+  LongModeCompat16Bit,
+} SEV_ES_INSTRUCTION_MODE;
+
+//
+// Instruction size definition (for operand and address)
+//
+typedef enum {
+  Size8Bits = 0,
+  Size16Bits,
+  Size32Bits,
+  Size64Bits,
+} SEV_ES_INSTRUCTION_SIZE;
+
+//
+// Intruction segment definition
+//
+typedef enum {
+  SegmentEs = 0,
+  SegmentCs,
+  SegmentSs,
+  SegmentDs,
+  SegmentFs,
+  SegmentGs,
+} SEV_ES_INSTRUCTION_SEGMENT;
+
+//
+// Instruction rep function definition
+//
+typedef enum {
+  RepNone = 0,
+  RepZ,
+  RepNZ,
+} SEV_ES_INSTRUCTION_REP;
+
+typedef struct {
+  UINT8    Rm;
+  UINT8    Reg;
+  UINT8    Mod;
+} SEV_ES_INSTRUCTION_MODRM_EXT;
+
+typedef struct {
+  UINT8    Base;
+  UINT8    Index;
+  UINT8    Scale;
+} SEV_ES_INSTRUCTION_SIB_EXT;
+
+//
+// Instruction opcode definition
+//
+typedef struct {
+  SEV_ES_INSTRUCTION_MODRM_EXT    ModRm;
+
+  SEV_ES_INSTRUCTION_SIB_EXT      Sib;
+
+  UINTN                           RegData;
+  UINTN                           RmData;
+} SEV_ES_INSTRUCTION_OPCODE_EXT;
+
+//
+// Instruction parsing context definition
+//
+typedef struct {
+  GHCB                             *Ghcb;
+
+  SEV_ES_INSTRUCTION_MODE          Mode;
+  SEV_ES_INSTRUCTION_SIZE          DataSize;
+  SEV_ES_INSTRUCTION_SIZE          AddrSize;
+  BOOLEAN                          SegmentSpecified;
+  SEV_ES_INSTRUCTION_SEGMENT       Segment;
+  SEV_ES_INSTRUCTION_REP           RepMode;
+
+  UINT8                            *Begin;
+  UINT8                            *End;
+
+  UINT8                            *Prefixes;
+  UINT8                            *OpCodes;
+  UINT8                            *Displacement;
+  UINT8                            *Immediate;
+
+  INSTRUCTION_REX_PREFIX           RexPrefix;
+
+  BOOLEAN                          ModRmPresent;
+  INSTRUCTION_MODRM                ModRm;
+
+  BOOLEAN                          SibPresent;
+  INSTRUCTION_SIB                  Sib;
+
+  UINTN                            PrefixSize;
+  UINTN                            OpCodeSize;
+  UINTN                            DisplacementSize;
+  UINTN                            ImmediateSize;
+
+  SEV_ES_INSTRUCTION_OPCODE_EXT    Ext;
+} SEV_ES_INSTRUCTION_DATA;
+
+//
+// Non-automatic Exit function prototype
+//
+typedef
+UINT64
+(*NAE_EXIT) (
+  GHCB                     *Ghcb,
+  EFI_SYSTEM_CONTEXT_X64   *Regs,
+  SEV_ES_INSTRUCTION_DATA  *InstructionData
+  );
+
+//
+// SEV-SNP Cpuid table entry/function
+//
+typedef PACKED struct {
+  UINT32    EaxIn;
+  UINT32    EcxIn;
+  UINT64    Unused;
+  UINT64    Unused2;
+  UINT32    Eax;
+  UINT32    Ebx;
+  UINT32    Ecx;
+  UINT32    Edx;
+  UINT64    Reserved;
+} SEV_SNP_CPUID_FUNCTION;
+
+//
+// SEV-SNP Cpuid page format
+//
+typedef PACKED struct {
+  UINT32                    Count;
+  UINT32                    Reserved1;
+  UINT64                    Reserved2;
+  SEV_SNP_CPUID_FUNCTION    function[0];
+} SEV_SNP_CPUID_INFO;
+
+/**
+  Return a pointer to the contents of the specified register.
+
+  Based upon the input register, return a pointer to the registers contents
+  in the x86 processor context.
+
+  @param[in] Regs      x64 processor context
+  @param[in] Register  Register to obtain pointer for
+
+  @return              Pointer to the contents of the requested register
+
+**/
+STATIC
+UINT64 *
+GetRegisterPointer (
+  IN EFI_SYSTEM_CONTEXT_X64  *Regs,
+  IN UINT8                   Register
+  )
+{
+  UINT64  *Reg;
+
+  switch (Register) {
+    case 0:
+      Reg = &Regs->Rax;
+      break;
+    case 1:
+      Reg = &Regs->Rcx;
+      break;
+    case 2:
+      Reg = &Regs->Rdx;
+      break;
+    case 3:
+      Reg = &Regs->Rbx;
+      break;
+    case 4:
+      Reg = &Regs->Rsp;
+      break;
+    case 5:
+      Reg = &Regs->Rbp;
+      break;
+    case 6:
+      Reg = &Regs->Rsi;
+      break;
+    case 7:
+      Reg = &Regs->Rdi;
+      break;
+    case 8:
+      Reg = &Regs->R8;
+      break;
+    case 9:
+      Reg = &Regs->R9;
+      break;
+    case 10:
+      Reg = &Regs->R10;
+      break;
+    case 11:
+      Reg = &Regs->R11;
+      break;
+    case 12:
+      Reg = &Regs->R12;
+      break;
+    case 13:
+      Reg = &Regs->R13;
+      break;
+    case 14:
+      Reg = &Regs->R14;
+      break;
+    case 15:
+      Reg = &Regs->R15;
+      break;
+    default:
+      Reg = NULL;
+  }
+
+  ASSERT (Reg != NULL);
+
+  return Reg;
+}
+
+/**
+  Update the instruction parsing context for displacement bytes.
+
+  @param[in, out] InstructionData  Instruction parsing context
+  @param[in]      Size             The instruction displacement size
+
+**/
+STATIC
+VOID
+UpdateForDisplacement (
+  IN OUT SEV_ES_INSTRUCTION_DATA  *InstructionData,
+  IN     UINTN                    Size
+  )
+{
+  InstructionData->DisplacementSize = Size;
+  InstructionData->Immediate       += Size;
+  InstructionData->End             += Size;
+}
+
+/**
+  Determine if an instruction address if RIP relative.
+
+  Examine the instruction parsing context to determine if the address offset
+  is relative to the instruction pointer.
+
+  @param[in] InstructionData  Instruction parsing context
+
+  @retval TRUE                Instruction addressing is RIP relative
+  @retval FALSE               Instruction addressing is not RIP relative
+
+**/
+STATIC
+BOOLEAN
+IsRipRelative (
+  IN SEV_ES_INSTRUCTION_DATA  *InstructionData
+  )
+{
+  SEV_ES_INSTRUCTION_OPCODE_EXT  *Ext;
+
+  Ext = &InstructionData->Ext;
+
+  return ((InstructionData->Mode == LongMode64Bit) &&
+          (Ext->ModRm.Mod == 0) &&
+          (Ext->ModRm.Rm == 5)  &&
+          (InstructionData->SibPresent == FALSE));
+}
+
+/**
+  Return the effective address of a memory operand.
+
+  Examine the instruction parsing context to obtain the effective memory
+  address of a memory operand.
+
+  @param[in] Regs             x64 processor context
+  @param[in] InstructionData  Instruction parsing context
+
+  @return                     The memory operand effective address
+
+**/
+STATIC
+UINT64
+GetEffectiveMemoryAddress (
+  IN EFI_SYSTEM_CONTEXT_X64   *Regs,
+  IN SEV_ES_INSTRUCTION_DATA  *InstructionData
+  )
+{
+  SEV_ES_INSTRUCTION_OPCODE_EXT  *Ext;
+  UINT64                         EffectiveAddress;
+
+  Ext              = &InstructionData->Ext;
+  EffectiveAddress = 0;
+
+  if (IsRipRelative (InstructionData)) {
+    //
+    // RIP-relative displacement is a 32-bit signed value
+    //
+    INT32  RipRelative;
+
+    RipRelative = *(INT32 *)InstructionData->Displacement;
+
+    UpdateForDisplacement (InstructionData, 4);
+
+    //
+    // Negative displacement is handled by standard UINT64 wrap-around.
+    //
+    return Regs->Rip + (UINT64)RipRelative;
+  }
+
+  switch (Ext->ModRm.Mod) {
+    case 1:
+      UpdateForDisplacement (InstructionData, 1);
+      EffectiveAddress += (UINT64)(*(INT8 *)(InstructionData->Displacement));
+      break;
+    case 2:
+      switch (InstructionData->AddrSize) {
+        case Size16Bits:
+          UpdateForDisplacement (InstructionData, 2);
+          EffectiveAddress += (UINT64)(*(INT16 *)(InstructionData->Displacement));
+          break;
+        default:
+          UpdateForDisplacement (InstructionData, 4);
+          EffectiveAddress += (UINT64)(*(INT32 *)(InstructionData->Displacement));
+          break;
+      }
+
+      break;
+  }
+
+  if (InstructionData->SibPresent) {
+    INT64  Displacement;
+
+    if (Ext->Sib.Index != 4) {
+      CopyMem (
+        &Displacement,
+        GetRegisterPointer (Regs, Ext->Sib.Index),
+        sizeof (Displacement)
+        );
+      Displacement *= (INT64)(1 << Ext->Sib.Scale);
+
+      //
+      // Negative displacement is handled by standard UINT64 wrap-around.
+      //
+      EffectiveAddress += (UINT64)Displacement;
+    }
+
+    if ((Ext->Sib.Base != 5) || Ext->ModRm.Mod) {
+      EffectiveAddress += *GetRegisterPointer (Regs, Ext->Sib.Base);
+    } else {
+      UpdateForDisplacement (InstructionData, 4);
+      EffectiveAddress += (UINT64)(*(INT32 *)(InstructionData->Displacement));
+    }
+  } else {
+    EffectiveAddress += *GetRegisterPointer (Regs, Ext->ModRm.Rm);
+  }
+
+  return EffectiveAddress;
+}
+
+/**
+  Decode a ModRM byte.
+
+  Examine the instruction parsing context to decode a ModRM byte and the SIB
+  byte, if present.
+
+  @param[in]      Regs             x64 processor context
+  @param[in, out] InstructionData  Instruction parsing context
+
+**/
+STATIC
+VOID
+DecodeModRm (
+  IN     EFI_SYSTEM_CONTEXT_X64   *Regs,
+  IN OUT SEV_ES_INSTRUCTION_DATA  *InstructionData
+  )
+{
+  SEV_ES_INSTRUCTION_OPCODE_EXT  *Ext;
+  INSTRUCTION_REX_PREFIX         *RexPrefix;
+  INSTRUCTION_MODRM              *ModRm;
+  INSTRUCTION_SIB                *Sib;
+
+  RexPrefix = &InstructionData->RexPrefix;
+  Ext       = &InstructionData->Ext;
+  ModRm     = &InstructionData->ModRm;
+  Sib       = &InstructionData->Sib;
+
+  InstructionData->ModRmPresent = TRUE;
+  ModRm->Uint8                  = *(InstructionData->End);
+
+  InstructionData->Displacement++;
+  InstructionData->Immediate++;
+  InstructionData->End++;
+
+  Ext->ModRm.Mod = ModRm->Bits.Mod;
+  Ext->ModRm.Reg = (RexPrefix->Bits.BitR << 3) | ModRm->Bits.Reg;
+  Ext->ModRm.Rm  = (RexPrefix->Bits.BitB << 3) | ModRm->Bits.Rm;
+
+  Ext->RegData = *GetRegisterPointer (Regs, Ext->ModRm.Reg);
+
+  if (Ext->ModRm.Mod == 3) {
+    Ext->RmData = *GetRegisterPointer (Regs, Ext->ModRm.Rm);
+  } else {
+    if (ModRm->Bits.Rm == 4) {
+      InstructionData->SibPresent = TRUE;
+      Sib->Uint8                  = *(InstructionData->End);
+
+      InstructionData->Displacement++;
+      InstructionData->Immediate++;
+      InstructionData->End++;
+
+      Ext->Sib.Scale = Sib->Bits.Scale;
+      Ext->Sib.Index = (RexPrefix->Bits.BitX << 3) | Sib->Bits.Index;
+      Ext->Sib.Base  = (RexPrefix->Bits.BitB << 3) | Sib->Bits.Base;
+    }
+
+    Ext->RmData = GetEffectiveMemoryAddress (Regs, InstructionData);
+  }
+}
+
+/**
+  Decode instruction prefixes.
+
+  Parse the instruction data to track the instruction prefixes that have
+  been used.
+
+  @param[in]      Regs             x64 processor context
+  @param[in, out] InstructionData  Instruction parsing context
+
+**/
+STATIC
+VOID
+DecodePrefixes (
+  IN     EFI_SYSTEM_CONTEXT_X64   *Regs,
+  IN OUT SEV_ES_INSTRUCTION_DATA  *InstructionData
+  )
+{
+  SEV_ES_INSTRUCTION_MODE  Mode;
+  SEV_ES_INSTRUCTION_SIZE  ModeDataSize;
+  SEV_ES_INSTRUCTION_SIZE  ModeAddrSize;
+  UINT8                    *Byte;
+
+  //
+  // Always in 64-bit mode
+  //
+  Mode         = LongMode64Bit;
+  ModeDataSize = Size32Bits;
+  ModeAddrSize = Size64Bits;
+
+  InstructionData->Mode     = Mode;
+  InstructionData->DataSize = ModeDataSize;
+  InstructionData->AddrSize = ModeAddrSize;
+
+  InstructionData->Prefixes = InstructionData->Begin;
+
+  Byte = InstructionData->Prefixes;
+  for ( ; ; Byte++, InstructionData->PrefixSize++) {
+    //
+    // Check the 0x40 to 0x4F range using an if statement here since some
+    // compilers don't like the "case 0x40 ... 0x4F:" syntax. This avoids
+    // 16 case statements below.
+    //
+    if ((*Byte >= REX_PREFIX_START) && (*Byte <= REX_PREFIX_STOP)) {
+      InstructionData->RexPrefix.Uint8 = *Byte;
+      if ((*Byte & REX_64BIT_OPERAND_SIZE_MASK) != 0) {
+        InstructionData->DataSize = Size64Bits;
+      }
+
+      continue;
+    }
+
+    switch (*Byte) {
+      case OVERRIDE_SEGMENT_CS:
+      case OVERRIDE_SEGMENT_DS:
+      case OVERRIDE_SEGMENT_ES:
+      case OVERRIDE_SEGMENT_SS:
+        if (Mode != LongMode64Bit) {
+          InstructionData->SegmentSpecified = TRUE;
+          InstructionData->Segment          = (*Byte >> 3) & 3;
+        }
+
+        break;
+
+      case OVERRIDE_SEGMENT_FS:
+      case OVERRIDE_SEGMENT_GS:
+        InstructionData->SegmentSpecified = TRUE;
+        InstructionData->Segment          = *Byte & 7;
+        break;
+
+      case OVERRIDE_OPERAND_SIZE:
+        if (InstructionData->RexPrefix.Uint8 == 0) {
+          InstructionData->DataSize =
+            (Mode == LongMode64Bit)       ? Size16Bits :
+            (Mode == LongModeCompat32Bit) ? Size16Bits :
+            (Mode == LongModeCompat16Bit) ? Size32Bits : 0;
+        }
+
+        break;
+
+      case OVERRIDE_ADDRESS_SIZE:
+        InstructionData->AddrSize =
+          (Mode == LongMode64Bit)       ? Size32Bits :
+          (Mode == LongModeCompat32Bit) ? Size16Bits :
+          (Mode == LongModeCompat16Bit) ? Size32Bits : 0;
+        break;
+
+      case LOCK_PREFIX:
+        break;
+
+      case REPZ_PREFIX:
+        InstructionData->RepMode = RepZ;
+        break;
+
+      case REPNZ_PREFIX:
+        InstructionData->RepMode = RepNZ;
+        break;
+
+      default:
+        InstructionData->OpCodes    = Byte;
+        InstructionData->OpCodeSize = (*Byte == TWO_BYTE_OPCODE_ESCAPE) ? 2 : 1;
+
+        InstructionData->End          = Byte + InstructionData->OpCodeSize;
+        InstructionData->Displacement = InstructionData->End;
+        InstructionData->Immediate    = InstructionData->End;
+        return;
+    }
+  }
+}
+
+/**
+  Determine instruction length
+
+  Return the total length of the parsed instruction.
+
+  @param[in] InstructionData  Instruction parsing context
+
+  @return                     Length of parsed instruction
+
+**/
+STATIC
+UINT64
+InstructionLength (
+  IN SEV_ES_INSTRUCTION_DATA  *InstructionData
+  )
+{
+  return (UINT64)(InstructionData->End - InstructionData->Begin);
+}
+
+/**
+  Initialize the instruction parsing context.
+
+  Initialize the instruction parsing context, which includes decoding the
+  instruction prefixes.
+
+  @param[in, out] InstructionData  Instruction parsing context
+  @param[in]      Ghcb             Pointer to the Guest-Hypervisor Communication
+                                   Block
+  @param[in]      Regs             x64 processor context
+
+**/
+STATIC
+VOID
+InitInstructionData (
+  IN OUT SEV_ES_INSTRUCTION_DATA  *InstructionData,
+  IN     GHCB                     *Ghcb,
+  IN     EFI_SYSTEM_CONTEXT_X64   *Regs
+  )
+{
+  SetMem (InstructionData, sizeof (*InstructionData), 0);
+  InstructionData->Ghcb  = Ghcb;
+  InstructionData->Begin = (UINT8 *)Regs->Rip;
+  InstructionData->End   = (UINT8 *)Regs->Rip;
+
+  DecodePrefixes (Regs, InstructionData);
+}
+
+/**
+  Report an unsupported event to the hypervisor
+
+  Use the VMGEXIT support to report an unsupported event to the hypervisor.
+
+  @param[in] Ghcb             Pointer to the Guest-Hypervisor Communication
+                              Block
+  @param[in] Regs             x64 processor context
+  @param[in] InstructionData  Instruction parsing context
+
+  @return                     New exception value to propagate
+
+**/
+STATIC
+UINT64
+UnsupportedExit (
+  IN GHCB                     *Ghcb,
+  IN EFI_SYSTEM_CONTEXT_X64   *Regs,
+  IN SEV_ES_INSTRUCTION_DATA  *InstructionData
+  )
+{
+  UINT64  Status;
+
+  Status = CcExitLibVmgExit (Ghcb, SVM_EXIT_UNSUPPORTED, Regs->ExceptionData, 0);
+  if (Status == 0) {
+    GHCB_EVENT_INJECTION  Event;
+
+    Event.Uint64          = 0;
+    Event.Elements.Vector = GP_EXCEPTION;
+    Event.Elements.Type   = GHCB_EVENT_INJECTION_TYPE_EXCEPTION;
+    Event.Elements.Valid  = 1;
+
+    Status = Event.Uint64;
+  }
+
+  return Status;
+}
+
+/**
+  Validate that the MMIO memory access is not to encrypted memory.
+
+  Examine the pagetable entry for the memory specified. MMIO should not be
+  performed against encrypted memory. MMIO to the APIC page is always allowed.
+
+  @param[in] Ghcb           Pointer to the Guest-Hypervisor Communication Block
+  @param[in] MemoryAddress  Memory address to validate
+  @param[in] MemoryLength   Memory length to validate
+
+  @retval 0          Memory is not encrypted
+  @return            New exception value to propogate
+
+**/
+STATIC
+UINT64
+ValidateMmioMemory (
+  IN GHCB   *Ghcb,
+  IN UINTN  MemoryAddress,
+  IN UINTN  MemoryLength
+  )
+{
+  MEM_ENCRYPT_SEV_ADDRESS_RANGE_STATE  State;
+  GHCB_EVENT_INJECTION                 GpEvent;
+  UINTN                                Address;
+
+  //
+  // Allow APIC accesses (which will have the encryption bit set during
+  // SEC and PEI phases).
+  //
+  Address = MemoryAddress & ~(SIZE_4KB - 1);
+  if (Address == GetLocalApicBaseAddress ()) {
+    return 0;
+  }
+
+  State = MemEncryptSevGetAddressRangeState (
+            0,
+            MemoryAddress,
+            MemoryLength
+            );
+  if (State == MemEncryptSevAddressRangeUnencrypted) {
+    return 0;
+  }
+
+  //
+  // Any state other than unencrypted is an error, issue a #GP.
+  //
+  DEBUG ((
+    DEBUG_ERROR,
+    "MMIO using encrypted memory: %lx\n",
+    (UINT64)MemoryAddress
+    ));
+  GpEvent.Uint64          = 0;
+  GpEvent.Elements.Vector = GP_EXCEPTION;
+  GpEvent.Elements.Type   = GHCB_EVENT_INJECTION_TYPE_EXCEPTION;
+  GpEvent.Elements.Valid  = 1;
+
+  return GpEvent.Uint64;
+}
+
+/**
+  Handle an MMIO event.
+
+  Use the VMGEXIT instruction to handle either an MMIO read or an MMIO write.
+
+  @param[in, out] Ghcb             Pointer to the Guest-Hypervisor Communication
+                                   Block
+  @param[in, out] Regs             x64 processor context
+  @param[in, out] InstructionData  Instruction parsing context
+
+  @retval 0                        Event handled successfully
+  @return                          New exception value to propagate
+
+**/
+STATIC
+UINT64
+MmioExit (
+  IN OUT GHCB                     *Ghcb,
+  IN OUT EFI_SYSTEM_CONTEXT_X64   *Regs,
+  IN OUT SEV_ES_INSTRUCTION_DATA  *InstructionData
+  )
+{
+  UINT64  ExitInfo1, ExitInfo2, Status;
+  UINTN   Bytes;
+  UINT64  *Register;
+  UINT8   OpCode, SignByte;
+  UINTN   Address;
+
+  Bytes = 0;
+
+  OpCode = *(InstructionData->OpCodes);
+  if (OpCode == TWO_BYTE_OPCODE_ESCAPE) {
+    OpCode = *(InstructionData->OpCodes + 1);
+  }
+
+  switch (OpCode) {
+    //
+    // MMIO write (MOV reg/memX, regX)
+    //
+    case 0x88:
+      Bytes = 1;
+    //
+    // fall through
+    //
+    case 0x89:
+      DecodeModRm (Regs, InstructionData);
+      Bytes = ((Bytes != 0) ? Bytes :
+               (InstructionData->DataSize == Size16Bits) ? 2 :
+               (InstructionData->DataSize == Size32Bits) ? 4 :
+               (InstructionData->DataSize == Size64Bits) ? 8 :
+               0);
+
+      if (InstructionData->Ext.ModRm.Mod == 3) {
+        //
+        // NPF on two register operands???
+        //
+        return UnsupportedExit (Ghcb, Regs, InstructionData);
+      }
+
+      Status = ValidateMmioMemory (Ghcb, InstructionData->Ext.RmData, Bytes);
+      if (Status != 0) {
+        return Status;
+      }
+
+      ExitInfo1 = InstructionData->Ext.RmData;
+      ExitInfo2 = Bytes;
+      CopyMem (Ghcb->SharedBuffer, &InstructionData->Ext.RegData, Bytes);
+
+      Ghcb->SaveArea.SwScratch = (UINT64)Ghcb->SharedBuffer;
+      CcExitLibVmgSetOffsetValid (Ghcb, GhcbSwScratch);
+      Status = CcExitLibVmgExit (Ghcb, SVM_EXIT_MMIO_WRITE, ExitInfo1, ExitInfo2);
+      if (Status != 0) {
+        return Status;
+      }
+
+      break;
+
+    //
+    // MMIO write (MOV moffsetX, aX)
+    //
+    case 0xA2:
+      Bytes = 1;
+    //
+    // fall through
+    //
+    case 0xA3:
+      Bytes = ((Bytes != 0) ? Bytes :
+               (InstructionData->DataSize == Size16Bits) ? 2 :
+               (InstructionData->DataSize == Size32Bits) ? 4 :
+               (InstructionData->DataSize == Size64Bits) ? 8 :
+               0);
+
+      InstructionData->ImmediateSize = (UINTN)(1 << InstructionData->AddrSize);
+      InstructionData->End          += InstructionData->ImmediateSize;
+
+      //
+      // This code is X64 only, so a possible 8-byte copy to a UINTN is ok.
+      // Use a STATIC_ASSERT to be certain the code is being built as X64.
+      //
+      STATIC_ASSERT (
+        sizeof (UINTN) == sizeof (UINT64),
+        "sizeof (UINTN) != sizeof (UINT64), this file must be built as X64"
+        );
+
+      Address = 0;
+      CopyMem (
+        &Address,
+        InstructionData->Immediate,
+        InstructionData->ImmediateSize
+        );
+
+      Status = ValidateMmioMemory (Ghcb, Address, Bytes);
+      if (Status != 0) {
+        return Status;
+      }
+
+      ExitInfo1 = Address;
+      ExitInfo2 = Bytes;
+      CopyMem (Ghcb->SharedBuffer, &Regs->Rax, Bytes);
+
+      Ghcb->SaveArea.SwScratch = (UINT64)Ghcb->SharedBuffer;
+      CcExitLibVmgSetOffsetValid (Ghcb, GhcbSwScratch);
+      Status = CcExitLibVmgExit (Ghcb, SVM_EXIT_MMIO_WRITE, ExitInfo1, ExitInfo2);
+      if (Status != 0) {
+        return Status;
+      }
+
+      break;
+
+    //
+    // MMIO write (MOV reg/memX, immX)
+    //
+    case 0xC6:
+      Bytes = 1;
+    //
+    // fall through
+    //
+    case 0xC7:
+      DecodeModRm (Regs, InstructionData);
+      Bytes = ((Bytes != 0) ? Bytes :
+               (InstructionData->DataSize == Size16Bits) ? 2 :
+               (InstructionData->DataSize == Size32Bits) ? 4 :
+               0);
+
+      InstructionData->ImmediateSize = Bytes;
+      InstructionData->End          += Bytes;
+
+      Status = ValidateMmioMemory (Ghcb, InstructionData->Ext.RmData, Bytes);
+      if (Status != 0) {
+        return Status;
+      }
+
+      ExitInfo1 = InstructionData->Ext.RmData;
+      ExitInfo2 = Bytes;
+      CopyMem (Ghcb->SharedBuffer, InstructionData->Immediate, Bytes);
+
+      Ghcb->SaveArea.SwScratch = (UINT64)Ghcb->SharedBuffer;
+      CcExitLibVmgSetOffsetValid (Ghcb, GhcbSwScratch);
+      Status = CcExitLibVmgExit (Ghcb, SVM_EXIT_MMIO_WRITE, ExitInfo1, ExitInfo2);
+      if (Status != 0) {
+        return Status;
+      }
+
+      break;
+
+    //
+    // MMIO read (MOV regX, reg/memX)
+    //
+    case 0x8A:
+      Bytes = 1;
+    //
+    // fall through
+    //
+    case 0x8B:
+      DecodeModRm (Regs, InstructionData);
+      Bytes = ((Bytes != 0) ? Bytes :
+               (InstructionData->DataSize == Size16Bits) ? 2 :
+               (InstructionData->DataSize == Size32Bits) ? 4 :
+               (InstructionData->DataSize == Size64Bits) ? 8 :
+               0);
+      if (InstructionData->Ext.ModRm.Mod == 3) {
+        //
+        // NPF on two register operands???
+        //
+        return UnsupportedExit (Ghcb, Regs, InstructionData);
+      }
+
+      Status = ValidateMmioMemory (Ghcb, InstructionData->Ext.RmData, Bytes);
+      if (Status != 0) {
+        return Status;
+      }
+
+      ExitInfo1 = InstructionData->Ext.RmData;
+      ExitInfo2 = Bytes;
+
+      Ghcb->SaveArea.SwScratch = (UINT64)Ghcb->SharedBuffer;
+      CcExitLibVmgSetOffsetValid (Ghcb, GhcbSwScratch);
+      Status = CcExitLibVmgExit (Ghcb, SVM_EXIT_MMIO_READ, ExitInfo1, ExitInfo2);
+      if (Status != 0) {
+        return Status;
+      }
+
+      Register = GetRegisterPointer (Regs, InstructionData->Ext.ModRm.Reg);
+      if (Bytes == 4) {
+        //
+        // Zero-extend for 32-bit operation
+        //
+        *Register = 0;
+      }
+
+      CopyMem (Register, Ghcb->SharedBuffer, Bytes);
+      break;
+
+    //
+    // MMIO read (MOV aX, moffsetX)
+    //
+    case 0xA0:
+      Bytes = 1;
+    //
+    // fall through
+    //
+    case 0xA1:
+      Bytes = ((Bytes != 0) ? Bytes :
+               (InstructionData->DataSize == Size16Bits) ? 2 :
+               (InstructionData->DataSize == Size32Bits) ? 4 :
+               (InstructionData->DataSize == Size64Bits) ? 8 :
+               0);
+
+      InstructionData->ImmediateSize = (UINTN)(1 << InstructionData->AddrSize);
+      InstructionData->End          += InstructionData->ImmediateSize;
+
+      //
+      // This code is X64 only, so a possible 8-byte copy to a UINTN is ok.
+      // Use a STATIC_ASSERT to be certain the code is being built as X64.
+      //
+      STATIC_ASSERT (
+        sizeof (UINTN) == sizeof (UINT64),
+        "sizeof (UINTN) != sizeof (UINT64), this file must be built as X64"
+        );
+
+      Address = 0;
+      CopyMem (
+        &Address,
+        InstructionData->Immediate,
+        InstructionData->ImmediateSize
+        );
+
+      Status = ValidateMmioMemory (Ghcb, Address, Bytes);
+      if (Status != 0) {
+        return Status;
+      }
+
+      ExitInfo1 = Address;
+      ExitInfo2 = Bytes;
+
+      Ghcb->SaveArea.SwScratch = (UINT64)Ghcb->SharedBuffer;
+      CcExitLibVmgSetOffsetValid (Ghcb, GhcbSwScratch);
+      Status = CcExitLibVmgExit (Ghcb, SVM_EXIT_MMIO_READ, ExitInfo1, ExitInfo2);
+      if (Status != 0) {
+        return Status;
+      }
+
+      if (Bytes == 4) {
+        //
+        // Zero-extend for 32-bit operation
+        //
+        Regs->Rax = 0;
+      }
+
+      CopyMem (&Regs->Rax, Ghcb->SharedBuffer, Bytes);
+      break;
+
+    //
+    // MMIO read w/ zero-extension ((MOVZX regX, reg/memX)
+    //
+    case 0xB6:
+      Bytes = 1;
+    //
+    // fall through
+    //
+    case 0xB7:
+      DecodeModRm (Regs, InstructionData);
+      Bytes = (Bytes != 0) ? Bytes : 2;
+
+      Status = ValidateMmioMemory (Ghcb, InstructionData->Ext.RmData, Bytes);
+      if (Status != 0) {
+        return Status;
+      }
+
+      ExitInfo1 = InstructionData->Ext.RmData;
+      ExitInfo2 = Bytes;
+
+      Ghcb->SaveArea.SwScratch = (UINT64)Ghcb->SharedBuffer;
+      CcExitLibVmgSetOffsetValid (Ghcb, GhcbSwScratch);
+      Status = CcExitLibVmgExit (Ghcb, SVM_EXIT_MMIO_READ, ExitInfo1, ExitInfo2);
+      if (Status != 0) {
+        return Status;
+      }
+
+      Register = GetRegisterPointer (Regs, InstructionData->Ext.ModRm.Reg);
+      SetMem (Register, (UINTN)(1 << InstructionData->DataSize), 0);
+      CopyMem (Register, Ghcb->SharedBuffer, Bytes);
+      break;
+
+    //
+    // MMIO read w/ sign-extension (MOVSX regX, reg/memX)
+    //
+    case 0xBE:
+      Bytes = 1;
+    //
+    // fall through
+    //
+    case 0xBF:
+      DecodeModRm (Regs, InstructionData);
+      Bytes = (Bytes != 0) ? Bytes : 2;
+
+      Status = ValidateMmioMemory (Ghcb, InstructionData->Ext.RmData, Bytes);
+      if (Status != 0) {
+        return Status;
+      }
+
+      ExitInfo1 = InstructionData->Ext.RmData;
+      ExitInfo2 = Bytes;
+
+      Ghcb->SaveArea.SwScratch = (UINT64)Ghcb->SharedBuffer;
+      CcExitLibVmgSetOffsetValid (Ghcb, GhcbSwScratch);
+      Status = CcExitLibVmgExit (Ghcb, SVM_EXIT_MMIO_READ, ExitInfo1, ExitInfo2);
+      if (Status != 0) {
+        return Status;
+      }
+
+      if (Bytes == 1) {
+        UINT8  *Data;
+
+        Data     = (UINT8 *)Ghcb->SharedBuffer;
+        SignByte = ((*Data & BIT7) != 0) ? 0xFF : 0x00;
+      } else {
+        UINT16  *Data;
+
+        Data     = (UINT16 *)Ghcb->SharedBuffer;
+        SignByte = ((*Data & BIT15) != 0) ? 0xFF : 0x00;
+      }
+
+      Register = GetRegisterPointer (Regs, InstructionData->Ext.ModRm.Reg);
+      SetMem (Register, (UINTN)(1 << InstructionData->DataSize), SignByte);
+      CopyMem (Register, Ghcb->SharedBuffer, Bytes);
+      break;
+
+    default:
+      DEBUG ((DEBUG_ERROR, "Invalid MMIO opcode (%x)\n", OpCode));
+      Status = GP_EXCEPTION;
+      ASSERT (FALSE);
+  }
+
+  return Status;
+}
+
+/**
+  Handle a MWAIT event.
+
+  Use the VMGEXIT instruction to handle a MWAIT event.
+
+  @param[in, out] Ghcb             Pointer to the Guest-Hypervisor Communication
+                                   Block
+  @param[in, out] Regs             x64 processor context
+  @param[in]      InstructionData  Instruction parsing context
+
+  @retval 0                        Event handled successfully
+  @return                          New exception value to propagate
+
+**/
+STATIC
+UINT64
+MwaitExit (
+  IN OUT GHCB                     *Ghcb,
+  IN OUT EFI_SYSTEM_CONTEXT_X64   *Regs,
+  IN     SEV_ES_INSTRUCTION_DATA  *InstructionData
+  )
+{
+  DecodeModRm (Regs, InstructionData);
+
+  Ghcb->SaveArea.Rax = Regs->Rax;
+  CcExitLibVmgSetOffsetValid (Ghcb, GhcbRax);
+  Ghcb->SaveArea.Rcx = Regs->Rcx;
+  CcExitLibVmgSetOffsetValid (Ghcb, GhcbRcx);
+
+  return CcExitLibVmgExit (Ghcb, SVM_EXIT_MWAIT, 0, 0);
+}
+
+/**
+  Handle a MONITOR event.
+
+  Use the VMGEXIT instruction to handle a MONITOR event.
+
+  @param[in, out] Ghcb             Pointer to the Guest-Hypervisor Communication
+                                   Block
+  @param[in, out] Regs             x64 processor context
+  @param[in]      InstructionData  Instruction parsing context
+
+  @retval 0                        Event handled successfully
+  @return                          New exception value to propagate
+
+**/
+STATIC
+UINT64
+MonitorExit (
+  IN OUT GHCB                     *Ghcb,
+  IN OUT EFI_SYSTEM_CONTEXT_X64   *Regs,
+  IN     SEV_ES_INSTRUCTION_DATA  *InstructionData
+  )
+{
+  DecodeModRm (Regs, InstructionData);
+
+  Ghcb->SaveArea.Rax = Regs->Rax;  // Identity mapped, so VA = PA
+  CcExitLibVmgSetOffsetValid (Ghcb, GhcbRax);
+  Ghcb->SaveArea.Rcx = Regs->Rcx;
+  CcExitLibVmgSetOffsetValid (Ghcb, GhcbRcx);
+  Ghcb->SaveArea.Rdx = Regs->Rdx;
+  CcExitLibVmgSetOffsetValid (Ghcb, GhcbRdx);
+
+  return CcExitLibVmgExit (Ghcb, SVM_EXIT_MONITOR, 0, 0);
+}
+
+/**
+  Handle a WBINVD event.
+
+  Use the VMGEXIT instruction to handle a WBINVD event.
+
+  @param[in, out] Ghcb             Pointer to the Guest-Hypervisor Communication
+                                   Block
+  @param[in, out] Regs             x64 processor context
+  @param[in]      InstructionData  Instruction parsing context
+
+  @retval 0                        Event handled successfully
+  @return                          New exception value to propagate
+
+**/
+STATIC
+UINT64
+WbinvdExit (
+  IN OUT GHCB                     *Ghcb,
+  IN OUT EFI_SYSTEM_CONTEXT_X64   *Regs,
+  IN     SEV_ES_INSTRUCTION_DATA  *InstructionData
+  )
+{
+  return CcExitLibVmgExit (Ghcb, SVM_EXIT_WBINVD, 0, 0);
+}
+
+/**
+  Handle a RDTSCP event.
+
+  Use the VMGEXIT instruction to handle a RDTSCP event.
+
+  @param[in, out] Ghcb             Pointer to the Guest-Hypervisor Communication
+                                   Block
+  @param[in, out] Regs             x64 processor context
+  @param[in]      InstructionData  Instruction parsing context
+
+  @retval 0                        Event handled successfully
+  @return                          New exception value to propagate
+
+**/
+STATIC
+UINT64
+RdtscpExit (
+  IN OUT GHCB                     *Ghcb,
+  IN OUT EFI_SYSTEM_CONTEXT_X64   *Regs,
+  IN     SEV_ES_INSTRUCTION_DATA  *InstructionData
+  )
+{
+  UINT64  Status;
+
+  DecodeModRm (Regs, InstructionData);
+
+  Status = CcExitLibVmgExit (Ghcb, SVM_EXIT_RDTSCP, 0, 0);
+  if (Status != 0) {
+    return Status;
+  }
+
+  if (!CcExitLibVmgIsOffsetValid (Ghcb, GhcbRax) ||
+      !CcExitLibVmgIsOffsetValid (Ghcb, GhcbRcx) ||
+      !CcExitLibVmgIsOffsetValid (Ghcb, GhcbRdx))
+  {
+    return UnsupportedExit (Ghcb, Regs, InstructionData);
+  }
+
+  Regs->Rax = Ghcb->SaveArea.Rax;
+  Regs->Rcx = Ghcb->SaveArea.Rcx;
+  Regs->Rdx = Ghcb->SaveArea.Rdx;
+
+  return 0;
+}
+
+/**
+  Handle a VMMCALL event.
+
+  Use the VMGEXIT instruction to handle a VMMCALL event.
+
+  @param[in, out] Ghcb             Pointer to the Guest-Hypervisor Communication
+                                   Block
+  @param[in, out] Regs             x64 processor context
+  @param[in]      InstructionData  Instruction parsing context
+
+  @retval 0                        Event handled successfully
+  @return                          New exception value to propagate
+
+**/
+STATIC
+UINT64
+VmmCallExit (
+  IN OUT GHCB                     *Ghcb,
+  IN OUT EFI_SYSTEM_CONTEXT_X64   *Regs,
+  IN     SEV_ES_INSTRUCTION_DATA  *InstructionData
+  )
+{
+  UINT64  Status;
+
+  DecodeModRm (Regs, InstructionData);
+
+  Ghcb->SaveArea.Rax = Regs->Rax;
+  CcExitLibVmgSetOffsetValid (Ghcb, GhcbRax);
+  Ghcb->SaveArea.Cpl = (UINT8)(Regs->Cs & 0x3);
+  CcExitLibVmgSetOffsetValid (Ghcb, GhcbCpl);
+
+  Status = CcExitLibVmgExit (Ghcb, SVM_EXIT_VMMCALL, 0, 0);
+  if (Status != 0) {
+    return Status;
+  }
+
+  if (!CcExitLibVmgIsOffsetValid (Ghcb, GhcbRax)) {
+    return UnsupportedExit (Ghcb, Regs, InstructionData);
+  }
+
+  Regs->Rax = Ghcb->SaveArea.Rax;
+
+  return 0;
+}
+
+/**
+  Handle an MSR event.
+
+  Use the VMGEXIT instruction to handle either a RDMSR or WRMSR event.
+
+  @param[in, out] Ghcb             Pointer to the Guest-Hypervisor Communication
+                                   Block
+  @param[in, out] Regs             x64 processor context
+  @param[in]      InstructionData  Instruction parsing context
+
+  @retval 0                        Event handled successfully
+  @return                          New exception value to propagate
+
+**/
+STATIC
+UINT64
+MsrExit (
+  IN OUT GHCB                     *Ghcb,
+  IN OUT EFI_SYSTEM_CONTEXT_X64   *Regs,
+  IN     SEV_ES_INSTRUCTION_DATA  *InstructionData
+  )
+{
+  UINT64  ExitInfo1, Status;
+
+  ExitInfo1 = 0;
+
+  switch (*(InstructionData->OpCodes + 1)) {
+    case 0x30: // WRMSR
+      ExitInfo1          = 1;
+      Ghcb->SaveArea.Rax = Regs->Rax;
+      CcExitLibVmgSetOffsetValid (Ghcb, GhcbRax);
+      Ghcb->SaveArea.Rdx = Regs->Rdx;
+      CcExitLibVmgSetOffsetValid (Ghcb, GhcbRdx);
+    //
+    // fall through
+    //
+    case 0x32: // RDMSR
+      Ghcb->SaveArea.Rcx = Regs->Rcx;
+      CcExitLibVmgSetOffsetValid (Ghcb, GhcbRcx);
+      break;
+    default:
+      return UnsupportedExit (Ghcb, Regs, InstructionData);
+  }
+
+  Status = CcExitLibVmgExit (Ghcb, SVM_EXIT_MSR, ExitInfo1, 0);
+  if (Status != 0) {
+    return Status;
+  }
+
+  if (ExitInfo1 == 0) {
+    if (!CcExitLibVmgIsOffsetValid (Ghcb, GhcbRax) ||
+        !CcExitLibVmgIsOffsetValid (Ghcb, GhcbRdx))
+    {
+      return UnsupportedExit (Ghcb, Regs, InstructionData);
+    }
+
+    Regs->Rax = Ghcb->SaveArea.Rax;
+    Regs->Rdx = Ghcb->SaveArea.Rdx;
+  }
+
+  return 0;
+}
+
+/**
+  Build the IOIO event information.
+
+  The IOIO event information identifies the type of IO operation to be performed
+  by the hypervisor. Build this information based on the instruction data.
+
+  @param[in]       Regs             x64 processor context
+  @param[in, out]  InstructionData  Instruction parsing context
+
+  @return                           IOIO event information value
+
+**/
+STATIC
+UINT64
+IoioExitInfo (
+  IN     EFI_SYSTEM_CONTEXT_X64   *Regs,
+  IN OUT SEV_ES_INSTRUCTION_DATA  *InstructionData
+  )
+{
+  UINT64  ExitInfo;
+
+  ExitInfo = 0;
+
+  switch (*(InstructionData->OpCodes)) {
+    //
+    // INS opcodes
+    //
+    case 0x6C:
+    case 0x6D:
+      ExitInfo |= IOIO_TYPE_INS;
+      ExitInfo |= IOIO_SEG_ES;
+      ExitInfo |= ((Regs->Rdx & 0xffff) << 16);
+      break;
+
+    //
+    // OUTS opcodes
+    //
+    case 0x6E:
+    case 0x6F:
+      ExitInfo |= IOIO_TYPE_OUTS;
+      ExitInfo |= IOIO_SEG_DS;
+      ExitInfo |= ((Regs->Rdx & 0xffff) << 16);
+      break;
+
+    //
+    // IN immediate opcodes
+    //
+    case 0xE4:
+    case 0xE5:
+      InstructionData->ImmediateSize = 1;
+      InstructionData->End++;
+      ExitInfo |= IOIO_TYPE_IN;
+      ExitInfo |= ((*(InstructionData->OpCodes + 1)) << 16);
+      break;
+
+    //
+    // OUT immediate opcodes
+    //
+    case 0xE6:
+    case 0xE7:
+      InstructionData->ImmediateSize = 1;
+      InstructionData->End++;
+      ExitInfo |= IOIO_TYPE_OUT;
+      ExitInfo |= ((*(InstructionData->OpCodes + 1)) << 16) | IOIO_TYPE_OUT;
+      break;
+
+    //
+    // IN register opcodes
+    //
+    case 0xEC:
+    case 0xED:
+      ExitInfo |= IOIO_TYPE_IN;
+      ExitInfo |= ((Regs->Rdx & 0xffff) << 16);
+      break;
+
+    //
+    // OUT register opcodes
+    //
+    case 0xEE:
+    case 0xEF:
+      ExitInfo |= IOIO_TYPE_OUT;
+      ExitInfo |= ((Regs->Rdx & 0xffff) << 16);
+      break;
+
+    default:
+      return 0;
+  }
+
+  switch (*(InstructionData->OpCodes)) {
+    //
+    // Single-byte opcodes
+    //
+    case 0x6C:
+    case 0x6E:
+    case 0xE4:
+    case 0xE6:
+    case 0xEC:
+    case 0xEE:
+      ExitInfo |= IOIO_DATA_8;
+      break;
+
+    //
+    // Length determined by instruction parsing
+    //
+    default:
+      ExitInfo |= (InstructionData->DataSize == Size16Bits) ? IOIO_DATA_16
+                                                          : IOIO_DATA_32;
+  }
+
+  switch (InstructionData->AddrSize) {
+    case Size16Bits:
+      ExitInfo |= IOIO_ADDR_16;
+      break;
+
+    case Size32Bits:
+      ExitInfo |= IOIO_ADDR_32;
+      break;
+
+    case Size64Bits:
+      ExitInfo |= IOIO_ADDR_64;
+      break;
+
+    default:
+      break;
+  }
+
+  if (InstructionData->RepMode != 0) {
+    ExitInfo |= IOIO_REP;
+  }
+
+  return ExitInfo;
+}
+
+/**
+  Handle an IOIO event.
+
+  Use the VMGEXIT instruction to handle an IOIO event.
+
+  @param[in, out] Ghcb             Pointer to the Guest-Hypervisor Communication
+                                   Block
+  @param[in, out] Regs             x64 processor context
+  @param[in]      InstructionData  Instruction parsing context
+
+  @retval 0                        Event handled successfully
+  @return                          New exception value to propagate
+
+**/
+STATIC
+UINT64
+IoioExit (
+  IN OUT GHCB                     *Ghcb,
+  IN OUT EFI_SYSTEM_CONTEXT_X64   *Regs,
+  IN     SEV_ES_INSTRUCTION_DATA  *InstructionData
+  )
+{
+  UINT64   ExitInfo1, ExitInfo2, Status;
+  BOOLEAN  IsString;
+
+  ExitInfo1 = IoioExitInfo (Regs, InstructionData);
+  if (ExitInfo1 == 0) {
+    return UnsupportedExit (Ghcb, Regs, InstructionData);
+  }
+
+  IsString = ((ExitInfo1 & IOIO_TYPE_STR) != 0) ? TRUE : FALSE;
+  if (IsString) {
+    UINTN  IoBytes, VmgExitBytes;
+    UINTN  GhcbCount, OpCount;
+
+    Status = 0;
+
+    IoBytes   = IOIO_DATA_BYTES (ExitInfo1);
+    GhcbCount = sizeof (Ghcb->SharedBuffer) / IoBytes;
+
+    OpCount = ((ExitInfo1 & IOIO_REP) != 0) ? Regs->Rcx : 1;
+    while (OpCount != 0) {
+      ExitInfo2    = MIN (OpCount, GhcbCount);
+      VmgExitBytes = ExitInfo2 * IoBytes;
+
+      if ((ExitInfo1 & IOIO_TYPE_IN) == 0) {
+        CopyMem (Ghcb->SharedBuffer, (VOID *)Regs->Rsi, VmgExitBytes);
+        Regs->Rsi += VmgExitBytes;
+      }
+
+      Ghcb->SaveArea.SwScratch = (UINT64)Ghcb->SharedBuffer;
+      CcExitLibVmgSetOffsetValid (Ghcb, GhcbSwScratch);
+      Status = CcExitLibVmgExit (Ghcb, SVM_EXIT_IOIO_PROT, ExitInfo1, ExitInfo2);
+      if (Status != 0) {
+        return Status;
+      }
+
+      if ((ExitInfo1 & IOIO_TYPE_IN) != 0) {
+        CopyMem ((VOID *)Regs->Rdi, Ghcb->SharedBuffer, VmgExitBytes);
+        Regs->Rdi += VmgExitBytes;
+      }
+
+      if ((ExitInfo1 & IOIO_REP) != 0) {
+        Regs->Rcx -= ExitInfo2;
+      }
+
+      OpCount -= ExitInfo2;
+    }
+  } else {
+    if ((ExitInfo1 & IOIO_TYPE_IN) != 0) {
+      Ghcb->SaveArea.Rax = 0;
+    } else {
+      CopyMem (&Ghcb->SaveArea.Rax, &Regs->Rax, IOIO_DATA_BYTES (ExitInfo1));
+    }
+
+    CcExitLibVmgSetOffsetValid (Ghcb, GhcbRax);
+
+    Status = CcExitLibVmgExit (Ghcb, SVM_EXIT_IOIO_PROT, ExitInfo1, 0);
+    if (Status != 0) {
+      return Status;
+    }
+
+    if ((ExitInfo1 & IOIO_TYPE_IN) != 0) {
+      if (!CcExitLibVmgIsOffsetValid (Ghcb, GhcbRax)) {
+        return UnsupportedExit (Ghcb, Regs, InstructionData);
+      }
+
+      CopyMem (&Regs->Rax, &Ghcb->SaveArea.Rax, IOIO_DATA_BYTES (ExitInfo1));
+    }
+  }
+
+  return 0;
+}
+
+/**
+  Handle a INVD event.
+
+  Use the VMGEXIT instruction to handle a INVD event.
+
+  @param[in, out] Ghcb             Pointer to the Guest-Hypervisor Communication
+                                   Block
+  @param[in, out] Regs             x64 processor context
+  @param[in]      InstructionData  Instruction parsing context
+
+  @retval 0                        Event handled successfully
+  @return                          New exception value to propagate
+
+**/
+STATIC
+UINT64
+InvdExit (
+  IN OUT GHCB                     *Ghcb,
+  IN OUT EFI_SYSTEM_CONTEXT_X64   *Regs,
+  IN     SEV_ES_INSTRUCTION_DATA  *InstructionData
+  )
+{
+  return CcExitLibVmgExit (Ghcb, SVM_EXIT_INVD, 0, 0);
+}
+
+/**
+  Fetch CPUID leaf/function via hypervisor/VMGEXIT.
+
+  @param[in, out] Ghcb         Pointer to the Guest-Hypervisor Communication
+                               Block
+  @param[in]      EaxIn        EAX input for cpuid instruction
+  @param[in]      EcxIn        ECX input for cpuid instruction
+  @param[in]      Xcr0In       XCR0 at time of cpuid instruction
+  @param[in, out] Eax          Pointer to store leaf's EAX value
+  @param[in, out] Ebx          Pointer to store leaf's EBX value
+  @param[in, out] Ecx          Pointer to store leaf's ECX value
+  @param[in, out] Edx          Pointer to store leaf's EDX value
+  @param[in, out] Status       Pointer to store status from VMGEXIT (always 0
+                               unless return value indicates failure)
+  @param[in, out] Unsupported  Pointer to store indication of unsupported
+                               VMGEXIT (always false unless return value
+                               indicates failure)
+
+  @retval TRUE                 CPUID leaf fetch successfully.
+  @retval FALSE                Error occurred while fetching CPUID leaf. Callers
+                               should Status and Unsupported and handle
+                               accordingly if they indicate a more precise
+                               error condition.
+
+**/
+STATIC
+BOOLEAN
+GetCpuidHyp (
+  IN OUT GHCB     *Ghcb,
+  IN     UINT32   EaxIn,
+  IN     UINT32   EcxIn,
+  IN     UINT64   XCr0,
+  IN OUT UINT32   *Eax,
+  IN OUT UINT32   *Ebx,
+  IN OUT UINT32   *Ecx,
+  IN OUT UINT32   *Edx,
+  IN OUT UINT64   *Status,
+  IN OUT BOOLEAN  *UnsupportedExit
+  )
+{
+  *UnsupportedExit   = FALSE;
+  Ghcb->SaveArea.Rax = EaxIn;
+  CcExitLibVmgSetOffsetValid (Ghcb, GhcbRax);
+  Ghcb->SaveArea.Rcx = EcxIn;
+  CcExitLibVmgSetOffsetValid (Ghcb, GhcbRcx);
+  if (EaxIn == CPUID_EXTENDED_STATE) {
+    Ghcb->SaveArea.XCr0 = XCr0;
+    CcExitLibVmgSetOffsetValid (Ghcb, GhcbXCr0);
+  }
+
+  *Status = CcExitLibVmgExit (Ghcb, SVM_EXIT_CPUID, 0, 0);
+  if (*Status != 0) {
+    return FALSE;
+  }
+
+  if (!CcExitLibVmgIsOffsetValid (Ghcb, GhcbRax) ||
+      !CcExitLibVmgIsOffsetValid (Ghcb, GhcbRbx) ||
+      !CcExitLibVmgIsOffsetValid (Ghcb, GhcbRcx) ||
+      !CcExitLibVmgIsOffsetValid (Ghcb, GhcbRdx))
+  {
+    *UnsupportedExit = TRUE;
+    return FALSE;
+  }
+
+  if (Eax) {
+    *Eax = (UINT32)(UINTN)Ghcb->SaveArea.Rax;
+  }
+
+  if (Ebx) {
+    *Ebx = (UINT32)(UINTN)Ghcb->SaveArea.Rbx;
+  }
+
+  if (Ecx) {
+    *Ecx = (UINT32)(UINTN)Ghcb->SaveArea.Rcx;
+  }
+
+  if (Edx) {
+    *Edx = (UINT32)(UINTN)Ghcb->SaveArea.Rdx;
+  }
+
+  return TRUE;
+}
+
+/**
+  Check if SEV-SNP enabled.
+
+  @retval TRUE      SEV-SNP is enabled.
+  @retval FALSE     SEV-SNP is disabled.
+
+**/
+STATIC
+BOOLEAN
+SnpEnabled (
+  VOID
+  )
+{
+  MSR_SEV_STATUS_REGISTER  Msr;
+
+  Msr.Uint32 = AsmReadMsr32 (MSR_SEV_STATUS);
+
+  return !!Msr.Bits.SevSnpBit;
+}
+
+/**
+  Calculate the total XSAVE area size for enabled XSAVE areas
+
+  @param[in]      XFeaturesEnabled  Bit-mask of enabled XSAVE features/areas as
+                                    indicated by XCR0/MSR_IA32_XSS bits
+  @param[in]      XSaveBaseSize     Base/legacy XSAVE area size (e.g. when
+                                    XCR0 is 1)
+  @param[in, out] XSaveSize         Pointer to storage for calculated XSAVE area
+                                    size
+  @param[in]      Compacted         Whether or not the calculation is for the
+                                    normal XSAVE area size (leaf 0xD,0x0,EBX) or
+                                    compacted XSAVE area size (leaf 0xD,0x1,EBX)
+
+
+  @retval TRUE                      XSAVE size calculation was successful.
+  @retval FALSE                     XSAVE size calculation was unsuccessful.
+**/
+STATIC
+BOOLEAN
+GetCpuidXSaveSize (
+  IN     UINT64   XFeaturesEnabled,
+  IN     UINT32   XSaveBaseSize,
+  IN OUT UINT32   *XSaveSize,
+  IN     BOOLEAN  Compacted
+  )
+{
+  SEV_SNP_CPUID_INFO  *CpuidInfo;
+  UINT64              XFeaturesFound = 0;
+  UINT32              Idx;
+
+  *XSaveSize = XSaveBaseSize;
+  CpuidInfo  = (SEV_SNP_CPUID_INFO *)(UINT64)PcdGet32 (PcdOvmfCpuidBase);
+
+  for (Idx = 0; Idx < CpuidInfo->Count; Idx++) {
+    SEV_SNP_CPUID_FUNCTION  *CpuidFn = &CpuidInfo->function[Idx];
+
+    if (!((CpuidFn->EaxIn == 0xD) &&
+          ((CpuidFn->EcxIn == 0) || (CpuidFn->EcxIn == 1))))
+    {
+      continue;
+    }
+
+    if (XFeaturesFound & (1ULL << CpuidFn->EcxIn) ||
+        !(XFeaturesEnabled & (1ULL << CpuidFn->EcxIn)))
+    {
+      continue;
+    }
+
+    XFeaturesFound |= (1ULL << CpuidFn->EcxIn);
+    if (Compacted) {
+      *XSaveSize += CpuidFn->Eax;
+    } else {
+      *XSaveSize = MAX (*XSaveSize, CpuidFn->Eax + CpuidFn->Ebx);
+    }
+  }
+
+  /*
+   * Either the guest set unsupported XCR0/XSS bits, or the corresponding
+   * entries in the CPUID table were not present. This is an invalid state.
+   */
+  if (XFeaturesFound != (XFeaturesEnabled & ~3UL)) {
+    return FALSE;
+  }
+
+  return TRUE;
+}
+
+/**
+  Check if a CPUID leaf/function is indexed via ECX sub-leaf/sub-function
+
+  @param[in]      EaxIn        EAX input for cpuid instruction
+
+  @retval FALSE                cpuid leaf/function is not indexed by ECX input
+  @retval TRUE                 cpuid leaf/function is indexed by ECX input
+
+**/
+STATIC
+BOOLEAN
+IsFunctionIndexed (
+  IN     UINT32  EaxIn
+  )
+{
+  switch (EaxIn) {
+    case CPUID_CACHE_PARAMS:
+    case CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS:
+    case CPUID_EXTENDED_TOPOLOGY:
+    case CPUID_EXTENDED_STATE:
+    case CPUID_INTEL_RDT_MONITORING:
+    case CPUID_INTEL_RDT_ALLOCATION:
+    case CPUID_INTEL_SGX:
+    case CPUID_INTEL_PROCESSOR_TRACE:
+    case CPUID_DETERMINISTIC_ADDRESS_TRANSLATION_PARAMETERS:
+    case CPUID_V2_EXTENDED_TOPOLOGY:
+    case 0x8000001D: /* Cache Topology Information */
+      return TRUE;
+  }
+
+  return FALSE;
+}
+
+/**
+  Fetch CPUID leaf/function via SEV-SNP CPUID table.
+
+  @param[in, out] Ghcb         Pointer to the Guest-Hypervisor Communication
+                               Block
+  @param[in]      EaxIn        EAX input for cpuid instruction
+  @param[in]      EcxIn        ECX input for cpuid instruction
+  @param[in]      Xcr0In       XCR0 at time of cpuid instruction
+  @param[in, out] Eax          Pointer to store leaf's EAX value
+  @param[in, out] Ebx          Pointer to store leaf's EBX value
+  @param[in, out] Ecx          Pointer to store leaf's ECX value
+  @param[in, out] Edx          Pointer to store leaf's EDX value
+  @param[in, out] Status       Pointer to store status from VMGEXIT (always 0
+                               unless return value indicates failure)
+  @param[in, out] Unsupported  Pointer to store indication of unsupported
+                               VMGEXIT (always false unless return value
+                               indicates failure)
+
+  @retval TRUE                 CPUID leaf fetch successfully.
+  @retval FALSE                Error occurred while fetching CPUID leaf. Callers
+                               should Status and Unsupported and handle
+                               accordingly if they indicate a more precise
+                               error condition.
+
+**/
+STATIC
+BOOLEAN
+GetCpuidFw (
+  IN OUT GHCB     *Ghcb,
+  IN     UINT32   EaxIn,
+  IN     UINT32   EcxIn,
+  IN     UINT64   XCr0,
+  IN OUT UINT32   *Eax,
+  IN OUT UINT32   *Ebx,
+  IN OUT UINT32   *Ecx,
+  IN OUT UINT32   *Edx,
+  IN OUT UINT64   *Status,
+  IN OUT BOOLEAN  *Unsupported
+  )
+{
+  SEV_SNP_CPUID_INFO  *CpuidInfo;
+  BOOLEAN             Found;
+  UINT32              Idx;
+
+  CpuidInfo = (SEV_SNP_CPUID_INFO *)(UINT64)PcdGet32 (PcdOvmfCpuidBase);
+  Found     = FALSE;
+
+  for (Idx = 0; Idx < CpuidInfo->Count; Idx++) {
+    SEV_SNP_CPUID_FUNCTION  *CpuidFn = &CpuidInfo->function[Idx];
+
+    if (CpuidFn->EaxIn != EaxIn) {
+      continue;
+    }
+
+    if (IsFunctionIndexed (CpuidFn->EaxIn) && (CpuidFn->EcxIn != EcxIn)) {
+      continue;
+    }
+
+    *Eax = CpuidFn->Eax;
+    *Ebx = CpuidFn->Ebx;
+    *Ecx = CpuidFn->Ecx;
+    *Edx = CpuidFn->Edx;
+
+    Found = TRUE;
+    break;
+  }
+
+  if (!Found) {
+    *Eax = *Ebx = *Ecx = *Edx = 0;
+    goto Out;
+  }
+
+  if (EaxIn == CPUID_VERSION_INFO) {
+    IA32_CR4  Cr4;
+    UINT32    Ebx2;
+    UINT32    Edx2;
+
+    if (!GetCpuidHyp (
+           Ghcb,
+           EaxIn,
+           EcxIn,
+           XCr0,
+           NULL,
+           &Ebx2,
+           NULL,
+           &Edx2,
+           Status,
+           Unsupported
+           ))
+    {
+      return FALSE;
+    }
+
+    /* initial APIC ID */
+    *Ebx = (*Ebx & 0x00FFFFFF) | (Ebx2 & 0xFF000000);
+    /* APIC enabled bit */
+    *Edx = (*Edx & ~BIT9) | (Edx2 & BIT9);
+    /* OSXSAVE enabled bit */
+    Cr4.UintN = AsmReadCr4 ();
+    *Ecx      = (Cr4.Bits.OSXSAVE) ? (*Ecx & ~BIT27) | (*Ecx & BIT27)
+                              : (*Ecx & ~BIT27);
+  } else if (EaxIn == CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS) {
+    IA32_CR4  Cr4;
+
+    Cr4.UintN = AsmReadCr4 ();
+    /* OSPKE enabled bit */
+    *Ecx = (Cr4.Bits.PKE) ? (*Ecx | BIT4) : (*Ecx & ~BIT4);
+  } else if (EaxIn == CPUID_EXTENDED_TOPOLOGY) {
+    if (!GetCpuidHyp (
+           Ghcb,
+           EaxIn,
+           EcxIn,
+           XCr0,
+           NULL,
+           NULL,
+           NULL,
+           Edx,
+           Status,
+           Unsupported
+           ))
+    {
+      return FALSE;
+    }
+  } else if ((EaxIn == CPUID_EXTENDED_STATE) && ((EcxIn == 0) || (EcxIn == 1))) {
+    MSR_IA32_XSS_REGISTER  XssMsr;
+    BOOLEAN                Compacted;
+    UINT32                 XSaveSize;
+
+    XssMsr.Uint64 = 0;
+    Compacted     = FALSE;
+    if (EcxIn == 1) {
+      /*
+       * The PPR and APM aren't clear on what size should be encoded in
+       * 0xD:0x1:EBX when compaction is not enabled by either XSAVEC or
+       * XSAVES, as these are generally fixed to 1 on real CPUs. Report
+       * this undefined case as an error.
+       */
+      if (!(*Eax & (BIT3 | BIT1))) {
+        /* (XSAVES | XSAVEC) */
+        return FALSE;
+      }
+
+      Compacted     = TRUE;
+      XssMsr.Uint64 = AsmReadMsr64 (MSR_IA32_XSS);
+    }
+
+    if (!GetCpuidXSaveSize (
+           XCr0 | XssMsr.Uint64,
+           *Ebx,
+           &XSaveSize,
+           Compacted
+           ))
+    {
+      return FALSE;
+    }
+
+    *Ebx = XSaveSize;
+  } else if (EaxIn == 0x8000001E) {
+    UINT32  Ebx2;
+    UINT32  Ecx2;
+
+    /* extended APIC ID */
+    if (!GetCpuidHyp (
+           Ghcb,
+           EaxIn,
+           EcxIn,
+           XCr0,
+           Eax,
+           &Ebx2,
+           &Ecx2,
+           NULL,
+           Status,
+           Unsupported
+           ))
+    {
+      return FALSE;
+    }
+
+    /* compute ID */
+    *Ebx = (*Ebx & 0xFFFFFF00) | (Ebx2 & 0x000000FF);
+    /* node ID */
+    *Ecx = (*Ecx & 0xFFFFFF00) | (Ecx2 & 0x000000FF);
+  }
+
+Out:
+  *Status      = 0;
+  *Unsupported = FALSE;
+  return TRUE;
+}
+
+/**
+  Handle a CPUID event.
+
+  Use VMGEXIT instruction or CPUID table to handle a CPUID event.
+
+  @param[in, out] Ghcb             Pointer to the Guest-Hypervisor Communication
+                                   Block
+  @param[in, out] Regs             x64 processor context
+  @param[in]      InstructionData  Instruction parsing context
+
+  @retval 0                        Event handled successfully
+  @return                          New exception value to propagate
+
+**/
+STATIC
+UINT64
+CpuidExit (
+  IN OUT GHCB                     *Ghcb,
+  IN OUT EFI_SYSTEM_CONTEXT_X64   *Regs,
+  IN     SEV_ES_INSTRUCTION_DATA  *InstructionData
+  )
+{
+  BOOLEAN  Unsupported;
+  UINT64   Status;
+  UINT32   EaxIn;
+  UINT32   EcxIn;
+  UINT64   XCr0;
+  UINT32   Eax;
+  UINT32   Ebx;
+  UINT32   Ecx;
+  UINT32   Edx;
+
+  EaxIn = (UINT32)(UINTN)Regs->Rax;
+  EcxIn = (UINT32)(UINTN)Regs->Rcx;
+
+  if (EaxIn == CPUID_EXTENDED_STATE) {
+    IA32_CR4  Cr4;
+
+    Cr4.UintN           = AsmReadCr4 ();
+    Ghcb->SaveArea.XCr0 = (Cr4.Bits.OSXSAVE == 1) ? AsmXGetBv (0) : 1;
+    XCr0                = (Cr4.Bits.OSXSAVE == 1) ? AsmXGetBv (0) : 1;
+  }
+
+  if (SnpEnabled ()) {
+    if (!GetCpuidFw (
+           Ghcb,
+           EaxIn,
+           EcxIn,
+           XCr0,
+           &Eax,
+           &Ebx,
+           &Ecx,
+           &Edx,
+           &Status,
+           &Unsupported
+           ))
+    {
+      goto CpuidFail;
+    }
+  } else {
+    if (!GetCpuidHyp (
+           Ghcb,
+           EaxIn,
+           EcxIn,
+           XCr0,
+           &Eax,
+           &Ebx,
+           &Ecx,
+           &Edx,
+           &Status,
+           &Unsupported
+           ))
+    {
+      goto CpuidFail;
+    }
+  }
+
+  Regs->Rax = Eax;
+  Regs->Rbx = Ebx;
+  Regs->Rcx = Ecx;
+  Regs->Rdx = Edx;
+
+  return 0;
+
+CpuidFail:
+  if (Unsupported) {
+    return UnsupportedExit (Ghcb, Regs, InstructionData);
+  }
+
+  return Status;
+}
+
+/**
+  Handle a RDPMC event.
+
+  Use the VMGEXIT instruction to handle a RDPMC event.
+
+  @param[in, out] Ghcb             Pointer to the Guest-Hypervisor Communication
+                                   Block
+  @param[in, out] Regs             x64 processor context
+  @param[in]      InstructionData  Instruction parsing context
+
+  @retval 0                        Event handled successfully
+  @return                          New exception value to propagate
+
+**/
+STATIC
+UINT64
+RdpmcExit (
+  IN OUT GHCB                     *Ghcb,
+  IN OUT EFI_SYSTEM_CONTEXT_X64   *Regs,
+  IN     SEV_ES_INSTRUCTION_DATA  *InstructionData
+  )
+{
+  UINT64  Status;
+
+  Ghcb->SaveArea.Rcx = Regs->Rcx;
+  CcExitLibVmgSetOffsetValid (Ghcb, GhcbRcx);
+
+  Status = CcExitLibVmgExit (Ghcb, SVM_EXIT_RDPMC, 0, 0);
+  if (Status != 0) {
+    return Status;
+  }
+
+  if (!CcExitLibVmgIsOffsetValid (Ghcb, GhcbRax) ||
+      !CcExitLibVmgIsOffsetValid (Ghcb, GhcbRdx))
+  {
+    return UnsupportedExit (Ghcb, Regs, InstructionData);
+  }
+
+  Regs->Rax = Ghcb->SaveArea.Rax;
+  Regs->Rdx = Ghcb->SaveArea.Rdx;
+
+  return 0;
+}
+
+/**
+  Handle a RDTSC event.
+
+  Use the VMGEXIT instruction to handle a RDTSC event.
+
+  @param[in, out] Ghcb             Pointer to the Guest-Hypervisor Communication
+                                   Block
+  @param[in, out] Regs             x64 processor context
+  @param[in]      InstructionData  Instruction parsing context
+
+  @retval 0                        Event handled successfully
+  @return                          New exception value to propagate
+
+**/
+STATIC
+UINT64
+RdtscExit (
+  IN OUT GHCB                     *Ghcb,
+  IN OUT EFI_SYSTEM_CONTEXT_X64   *Regs,
+  IN     SEV_ES_INSTRUCTION_DATA  *InstructionData
+  )
+{
+  UINT64  Status;
+
+  Status = CcExitLibVmgExit (Ghcb, SVM_EXIT_RDTSC, 0, 0);
+  if (Status != 0) {
+    return Status;
+  }
+
+  if (!CcExitLibVmgIsOffsetValid (Ghcb, GhcbRax) ||
+      !CcExitLibVmgIsOffsetValid (Ghcb, GhcbRdx))
+  {
+    return UnsupportedExit (Ghcb, Regs, InstructionData);
+  }
+
+  Regs->Rax = Ghcb->SaveArea.Rax;
+  Regs->Rdx = Ghcb->SaveArea.Rdx;
+
+  return 0;
+}
+
+/**
+  Handle a DR7 register write event.
+
+  Use the VMGEXIT instruction to handle a DR7 write event.
+
+  @param[in, out] Ghcb             Pointer to the Guest-Hypervisor Communication
+                                   Block
+  @param[in, out] Regs             x64 processor context
+  @param[in]      InstructionData  Instruction parsing context
+
+  @retval 0                        Event handled successfully
+  @return                          New exception value to propagate
+
+**/
+STATIC
+UINT64
+Dr7WriteExit (
+  IN OUT GHCB                     *Ghcb,
+  IN OUT EFI_SYSTEM_CONTEXT_X64   *Regs,
+  IN     SEV_ES_INSTRUCTION_DATA  *InstructionData
+  )
+{
+  SEV_ES_INSTRUCTION_OPCODE_EXT  *Ext;
+  SEV_ES_PER_CPU_DATA            *SevEsData;
+  UINT64                         *Register;
+  UINT64                         Status;
+
+  Ext       = &InstructionData->Ext;
+  SevEsData = (SEV_ES_PER_CPU_DATA *)(Ghcb + 1);
+
+  DecodeModRm (Regs, InstructionData);
+
+  //
+  // MOV DRn always treats MOD == 3 no matter how encoded
+  //
+  Register = GetRegisterPointer (Regs, Ext->ModRm.Rm);
+
+  //
+  // Using a value of 0 for ExitInfo1 means RAX holds the value
+  //
+  Ghcb->SaveArea.Rax = *Register;
+  CcExitLibVmgSetOffsetValid (Ghcb, GhcbRax);
+
+  Status = CcExitLibVmgExit (Ghcb, SVM_EXIT_DR7_WRITE, 0, 0);
+  if (Status != 0) {
+    return Status;
+  }
+
+  SevEsData->Dr7       = *Register;
+  SevEsData->Dr7Cached = 1;
+
+  return 0;
+}
+
+/**
+  Handle a DR7 register read event.
+
+  Use the VMGEXIT instruction to handle a DR7 read event.
+
+  @param[in, out] Ghcb             Pointer to the Guest-Hypervisor Communication
+                                   Block
+  @param[in, out] Regs             x64 processor context
+  @param[in]      InstructionData  Instruction parsing context
+
+  @retval 0                        Event handled successfully
+
+**/
+STATIC
+UINT64
+Dr7ReadExit (
+  IN OUT GHCB                     *Ghcb,
+  IN OUT EFI_SYSTEM_CONTEXT_X64   *Regs,
+  IN     SEV_ES_INSTRUCTION_DATA  *InstructionData
+  )
+{
+  SEV_ES_INSTRUCTION_OPCODE_EXT  *Ext;
+  SEV_ES_PER_CPU_DATA            *SevEsData;
+  UINT64                         *Register;
+
+  Ext       = &InstructionData->Ext;
+  SevEsData = (SEV_ES_PER_CPU_DATA *)(Ghcb + 1);
+
+  DecodeModRm (Regs, InstructionData);
+
+  //
+  // MOV DRn always treats MOD == 3 no matter how encoded
+  //
+  Register = GetRegisterPointer (Regs, Ext->ModRm.Rm);
+
+  //
+  // If there is a cached valued for DR7, return that. Otherwise return the
+  // DR7 standard reset value of 0x400 (no debug breakpoints set).
+  //
+  *Register = (SevEsData->Dr7Cached == 1) ? SevEsData->Dr7 : 0x400;
+
+  return 0;
+}
+
+/**
+  Handle a #VC exception.
+
+  Performs the necessary processing to handle a #VC exception.
+
+  @param[in, out]  Ghcb           Pointer to the GHCB
+  @param[in, out]  ExceptionType  Pointer to an EFI_EXCEPTION_TYPE to be set
+                                  as value to use on error.
+  @param[in, out]  SystemContext  Pointer to EFI_SYSTEM_CONTEXT
+
+  @retval  EFI_SUCCESS            Exception handled
+  @retval  EFI_UNSUPPORTED        #VC not supported, (new) exception value to
+                                  propagate provided
+  @retval  EFI_PROTOCOL_ERROR     #VC handling failed, (new) exception value to
+                                  propagate provided
+
+**/
+EFI_STATUS
+EFIAPI
+CcExitLibInternalVmgExitHandleVc (
+  IN OUT GHCB                *Ghcb,
+  IN OUT EFI_EXCEPTION_TYPE  *ExceptionType,
+  IN OUT EFI_SYSTEM_CONTEXT  SystemContext
+  )
+{
+  EFI_SYSTEM_CONTEXT_X64   *Regs;
+  NAE_EXIT                 NaeExit;
+  SEV_ES_INSTRUCTION_DATA  InstructionData;
+  UINT64                   ExitCode, Status;
+  EFI_STATUS               VcRet;
+  BOOLEAN                  InterruptState;
+
+  VcRet = EFI_SUCCESS;
+
+  Regs = SystemContext.SystemContextX64;
+
+  CcExitLibVmgInit (Ghcb, &InterruptState);
+
+  ExitCode = Regs->ExceptionData;
+  switch (ExitCode) {
+    case SVM_EXIT_DR7_READ:
+      NaeExit = Dr7ReadExit;
+      break;
+
+    case SVM_EXIT_DR7_WRITE:
+      NaeExit = Dr7WriteExit;
+      break;
+
+    case SVM_EXIT_RDTSC:
+      NaeExit = RdtscExit;
+      break;
+
+    case SVM_EXIT_RDPMC:
+      NaeExit = RdpmcExit;
+      break;
+
+    case SVM_EXIT_CPUID:
+      NaeExit = CpuidExit;
+      break;
+
+    case SVM_EXIT_INVD:
+      NaeExit = InvdExit;
+      break;
+
+    case SVM_EXIT_IOIO_PROT:
+      NaeExit = IoioExit;
+      break;
+
+    case SVM_EXIT_MSR:
+      NaeExit = MsrExit;
+      break;
+
+    case SVM_EXIT_VMMCALL:
+      NaeExit = VmmCallExit;
+      break;
+
+    case SVM_EXIT_RDTSCP:
+      NaeExit = RdtscpExit;
+      break;
+
+    case SVM_EXIT_WBINVD:
+      NaeExit = WbinvdExit;
+      break;
+
+    case SVM_EXIT_MONITOR:
+      NaeExit = MonitorExit;
+      break;
+
+    case SVM_EXIT_MWAIT:
+      NaeExit = MwaitExit;
+      break;
+
+    case SVM_EXIT_NPF:
+      NaeExit = MmioExit;
+      break;
+
+    default:
+      NaeExit = UnsupportedExit;
+  }
+
+  InitInstructionData (&InstructionData, Ghcb, Regs);
+
+  Status = NaeExit (Ghcb, Regs, &InstructionData);
+  if (Status == 0) {
+    Regs->Rip += InstructionLength (&InstructionData);
+  } else {
+    GHCB_EVENT_INJECTION  Event;
+
+    Event.Uint64 = Status;
+    if (Event.Elements.ErrorCodeValid != 0) {
+      Regs->ExceptionData = Event.Elements.ErrorCode;
+    } else {
+      Regs->ExceptionData = 0;
+    }
+
+    *ExceptionType = Event.Elements.Vector;
+
+    VcRet = EFI_PROTOCOL_ERROR;
+  }
+
+  CcExitLibVmgDone (Ghcb, InterruptState);
+
+  return VcRet;
+}
+
+/**
+  Routine to allow ASSERT from within #VC.
+
+  @param[in, out]  SevEsData  Pointer to the per-CPU data
+
+**/
+VOID
+EFIAPI
+CcExitLibVmgExitIssueAssert (
+  IN OUT SEV_ES_PER_CPU_DATA  *SevEsData
+  )
+{
+  //
+  // Progress will be halted, so set VcCount to allow for ASSERT output
+  // to be seen.
+  //
+  SevEsData->VcCount = 0;
+
+  ASSERT (FALSE);
+  CpuDeadLoop ();
+}
diff --git a/OvmfPkg/Library/CcExitLib/CcExitVcHandler.h b/OvmfPkg/Library/CcExitLib/CcExitVcHandler.h
new file mode 100644
index 000000000000..d8084130fae4
--- /dev/null
+++ b/OvmfPkg/Library/CcExitLib/CcExitVcHandler.h
@@ -0,0 +1,53 @@
+/** @file
+  X64 #VC Exception Handler functon header file.
+
+  Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef CC_EXIT_VC_HANDLER_H_
+#define CC_EXIT_VC_HANDLER_H_
+
+#include <Base.h>
+#include <Uefi.h>
+#include <Library/CcExitLib.h>
+
+/**
+  Handle a #VC exception.
+
+  Performs the necessary processing to handle a #VC exception.
+
+  @param[in, out]  Ghcb           Pointer to the GHCB
+  @param[in, out]  ExceptionType  Pointer to an EFI_EXCEPTION_TYPE to be set
+                                  as value to use on error.
+  @param[in, out]  SystemContext  Pointer to EFI_SYSTEM_CONTEXT
+
+  @retval  EFI_SUCCESS            Exception handled
+  @retval  EFI_UNSUPPORTED        #VC not supported, (new) exception value to
+                                  propagate provided
+  @retval  EFI_PROTOCOL_ERROR     #VC handling failed, (new) exception value to
+                                  propagate provided
+
+**/
+EFI_STATUS
+EFIAPI
+CcExitLibInternalVmgExitHandleVc (
+  IN OUT GHCB                *Ghcb,
+  IN OUT EFI_EXCEPTION_TYPE  *ExceptionType,
+  IN OUT EFI_SYSTEM_CONTEXT  SystemContext
+  );
+
+/**
+  Routine to allow ASSERT from within #VC.
+
+  @param[in, out]  SevEsData  Pointer to the per-CPU data
+
+**/
+VOID
+EFIAPI
+CcExitLibVmgExitIssueAssert (
+  IN OUT SEV_ES_PER_CPU_DATA  *SevEsData
+  );
+
+#endif
diff --git a/OvmfPkg/Library/CcExitLib/CcExitVeHandler.c b/OvmfPkg/Library/CcExitLib/CcExitVeHandler.c
new file mode 100644
index 000000000000..28bb0af82205
--- /dev/null
+++ b/OvmfPkg/Library/CcExitLib/CcExitVeHandler.c
@@ -0,0 +1,559 @@
+/** @file
+
+  Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include "CcExitTd.h"
+#include <Library/CcExitLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <IndustryStandard/Tdx.h>
+#include <IndustryStandard/InstructionParsing.h>
+
+typedef union {
+  struct {
+    UINT32    Eax;
+    UINT32    Edx;
+  } Regs;
+  UINT64    Val;
+} MSR_DATA;
+
+typedef union {
+  UINT8    Val;
+  struct {
+    UINT8    B : 1;
+    UINT8    X : 1;
+    UINT8    R : 1;
+    UINT8    W : 1;
+  } Bits;
+} REX;
+
+typedef union {
+  UINT8    Val;
+  struct {
+    UINT8    Rm  : 3;
+    UINT8    Reg : 3;
+    UINT8    Mod : 2;
+  } Bits;
+} MODRM;
+
+typedef struct {
+  UINT64    Regs[4];
+} CPUID_DATA;
+
+/**
+  Handle an CPUID event.
+
+  Use the TDVMCALL instruction to handle cpuid #ve
+
+  @param[in, out] Regs             x64 processor context
+  @param[in]      Veinfo           VE Info
+
+  @retval 0                        Event handled successfully
+  @return                          New exception value to propagate
+**/
+STATIC
+UINT64
+EFIAPI
+CpuIdExit (
+  IN EFI_SYSTEM_CONTEXT_X64     *Regs,
+  IN TDCALL_VEINFO_RETURN_DATA  *Veinfo
+  )
+{
+  CPUID_DATA  CpuIdData;
+  UINT64      Status;
+
+  Status = CcExitLibTdVmCallCpuid (Regs->Rax, Regs->Rcx, &CpuIdData);
+
+  if (Status == 0) {
+    Regs->Rax = CpuIdData.Regs[0];
+    Regs->Rbx = CpuIdData.Regs[1];
+    Regs->Rcx = CpuIdData.Regs[2];
+    Regs->Rdx = CpuIdData.Regs[3];
+  }
+
+  return Status;
+}
+
+/**
+  Handle an IO event.
+
+  Use the TDVMCALL instruction to handle either an IO read or an IO write.
+
+  @param[in, out] Regs             x64 processor context
+  @param[in]      Veinfo           VE Info
+
+  @retval 0                        Event handled successfully
+  @return                          New exception value to propagate
+**/
+STATIC
+UINT64
+EFIAPI
+IoExit (
+  IN OUT EFI_SYSTEM_CONTEXT_X64  *Regs,
+  IN TDCALL_VEINFO_RETURN_DATA   *Veinfo
+  )
+{
+  BOOLEAN  Write;
+  UINTN    Size;
+  UINTN    Port;
+  UINT64   Val;
+  UINT64   RepCnt;
+  UINT64   Status;
+
+  Val   = 0;
+  Write = Veinfo->ExitQualification.Io.Direction ? FALSE : TRUE;
+  Size  = Veinfo->ExitQualification.Io.Size + 1;
+  Port  = Veinfo->ExitQualification.Io.Port;
+
+  if (Veinfo->ExitQualification.Io.String) {
+    //
+    // If REP is set, get rep-cnt from Rcx
+    //
+    RepCnt = Veinfo->ExitQualification.Io.Rep ? Regs->Rcx : 1;
+
+    while (RepCnt) {
+      Val = 0;
+      if (Write == TRUE) {
+        CopyMem (&Val, (VOID *)Regs->Rsi, Size);
+        Regs->Rsi += Size;
+      }
+
+      Status = TdVmCall (EXIT_REASON_IO_INSTRUCTION, Size, Write, Port, Val, (Write ? NULL : &Val));
+      if (Status != 0) {
+        break;
+      }
+
+      if (Write == FALSE) {
+        CopyMem ((VOID *)Regs->Rdi, &Val, Size);
+        Regs->Rdi += Size;
+      }
+
+      if (Veinfo->ExitQualification.Io.Rep) {
+        Regs->Rcx -= 1;
+      }
+
+      RepCnt -= 1;
+    }
+  } else {
+    if (Write == TRUE) {
+      CopyMem (&Val, (VOID *)&Regs->Rax, Size);
+    }
+
+    Status = TdVmCall (EXIT_REASON_IO_INSTRUCTION, Size, Write, Port, Val, (Write ? NULL : &Val));
+    if ((Status == 0) && (Write == FALSE)) {
+      CopyMem ((VOID *)&Regs->Rax, &Val, Size);
+    }
+  }
+
+  return Status;
+}
+
+/**
+  Handle an READ MSR event.
+
+  Use the TDVMCALL instruction to handle msr read
+
+  @param[in, out] Regs             x64 processor context
+  @param[in]      Veinfo           VE Info
+
+  @retval 0                        Event handled successfully
+  @return                          New exception value to propagate
+**/
+STATIC
+UINT64
+ReadMsrExit (
+  IN OUT EFI_SYSTEM_CONTEXT_X64  *Regs,
+  IN TDCALL_VEINFO_RETURN_DATA   *Veinfo
+  )
+{
+  MSR_DATA  Data;
+  UINT64    Status;
+
+  Status = TdVmCall (EXIT_REASON_MSR_READ, Regs->Rcx, 0, 0, 0, &Data);
+  if (Status == 0) {
+    Regs->Rax = Data.Regs.Eax;
+    Regs->Rdx = Data.Regs.Edx;
+  }
+
+  return Status;
+}
+
+/**
+  Handle an WRITE MSR event.
+
+  Use the TDVMCALL instruction to handle msr write
+
+  @param[in, out] Regs             x64 processor context
+  @param[in]      Veinfo           VE Info
+
+  @retval 0                        Event handled successfully
+  @return                          New exception value to propagate
+**/
+STATIC
+UINT64
+WriteMsrExit (
+  IN OUT EFI_SYSTEM_CONTEXT_X64  *Regs,
+  IN TDCALL_VEINFO_RETURN_DATA   *Veinfo
+  )
+{
+  UINT64    Status;
+  MSR_DATA  Data;
+
+  Data.Regs.Eax = (UINT32)Regs->Rax;
+  Data.Regs.Edx = (UINT32)Regs->Rdx;
+
+  Status =  TdVmCall (EXIT_REASON_MSR_WRITE, Regs->Rcx, Data.Val, 0, 0, NULL);
+
+  return Status;
+}
+
+STATIC
+VOID
+EFIAPI
+TdxDecodeInstruction (
+  IN UINT8  *Rip
+  )
+{
+  UINTN  i;
+
+  DEBUG ((DEBUG_INFO, "TDX: #TD[EPT] instruction (%p):", Rip));
+  for (i = 0; i < 15; i++) {
+    DEBUG ((DEBUG_INFO, "%02x:", Rip[i]));
+  }
+
+  DEBUG ((DEBUG_INFO, "\n"));
+}
+
+#define TDX_DECODER_BUG_ON(x)               \
+  if ((x)) {                                \
+    TdxDecodeInstruction(Rip);              \
+    TdVmCall(TDVMCALL_HALT, 0, 0, 0, 0, 0); \
+  }
+
+STATIC
+UINT64 *
+EFIAPI
+GetRegFromContext (
+  IN EFI_SYSTEM_CONTEXT_X64  *Regs,
+  IN UINTN                   RegIndex
+  )
+{
+  switch (RegIndex) {
+    case 0: return &Regs->Rax;
+      break;
+    case 1: return &Regs->Rcx;
+      break;
+    case 2: return &Regs->Rdx;
+      break;
+    case 3: return &Regs->Rbx;
+      break;
+    case 4: return &Regs->Rsp;
+      break;
+    case 5: return &Regs->Rbp;
+      break;
+    case 6: return &Regs->Rsi;
+      break;
+    case 7: return &Regs->Rdi;
+      break;
+    case 8: return &Regs->R8;
+      break;
+    case 9: return &Regs->R9;
+      break;
+    case 10: return &Regs->R10;
+      break;
+    case 11: return &Regs->R11;
+      break;
+    case 12: return &Regs->R12;
+      break;
+    case 13: return &Regs->R13;
+      break;
+    case 14: return &Regs->R14;
+      break;
+    case 15: return &Regs->R15;
+      break;
+  }
+
+  return NULL;
+}
+
+/**
+  Handle an MMIO event.
+
+  Use the TDVMCALL instruction to handle either an mmio read or an mmio write.
+
+  @param[in, out] Regs             x64 processor context
+  @param[in]      Veinfo           VE Info
+
+  @retval 0                        Event handled successfully
+  @return                          New exception value to propagate
+**/
+STATIC
+INTN
+EFIAPI
+MmioExit (
+  IN OUT EFI_SYSTEM_CONTEXT_X64  *Regs,
+  IN TDCALL_VEINFO_RETURN_DATA   *Veinfo
+  )
+{
+  UINT64   Status;
+  UINT32   MmioSize;
+  UINT32   RegSize;
+  UINT8    OpCode;
+  BOOLEAN  SeenRex;
+  UINT64   *Reg;
+  UINT8    *Rip;
+  UINT64   Val;
+  UINT32   OpSize;
+  MODRM    ModRm;
+  REX      Rex;
+
+  Rip     = (UINT8 *)Regs->Rip;
+  Val     = 0;
+  Rex.Val = 0;
+  SeenRex = FALSE;
+
+  //
+  // Default to 32bit transfer
+  //
+  OpSize = 4;
+
+  do {
+    OpCode = *Rip++;
+    if (OpCode == 0x66) {
+      OpSize = 2;
+    } else if ((OpCode == 0x64) || (OpCode == 0x65) || (OpCode == 0x67)) {
+      continue;
+    } else if ((OpCode >= 0x40) && (OpCode <= 0x4f)) {
+      SeenRex = TRUE;
+      Rex.Val = OpCode;
+    } else {
+      break;
+    }
+  } while (TRUE);
+
+  //
+  // We need to have at least 2 more bytes for this instruction
+  //
+  TDX_DECODER_BUG_ON (((UINT64)Rip - Regs->Rip) > 13);
+
+  OpCode = *Rip++;
+  //
+  // Two-byte opecode, get next byte
+  //
+  if (OpCode == 0x0F) {
+    OpCode = *Rip++;
+  }
+
+  switch (OpCode) {
+    case 0x88:
+    case 0x8A:
+    case 0xB6:
+      MmioSize = 1;
+      break;
+    case 0xB7:
+      MmioSize = 2;
+      break;
+    default:
+      MmioSize = Rex.Bits.W ? 8 : OpSize;
+      break;
+  }
+
+  /* Punt on AH/BH/CH/DH unless it shows up. */
+  ModRm.Val = *Rip++;
+  TDX_DECODER_BUG_ON (MmioSize == 1 && ModRm.Bits.Reg > 4 && !SeenRex && OpCode != 0xB6);
+  Reg = GetRegFromContext (Regs, ModRm.Bits.Reg | ((int)Rex.Bits.R << 3));
+  TDX_DECODER_BUG_ON (!Reg);
+
+  if (ModRm.Bits.Rm == 4) {
+    ++Rip; /* SIB byte */
+  }
+
+  if ((ModRm.Bits.Mod == 2) || ((ModRm.Bits.Mod == 0) && (ModRm.Bits.Rm == 5))) {
+    Rip += 4; /* DISP32 */
+  } else if (ModRm.Bits.Mod == 1) {
+    ++Rip;  /* DISP8 */
+  }
+
+  switch (OpCode) {
+    case 0x88:
+    case 0x89:
+      CopyMem ((void *)&Val, Reg, MmioSize);
+      Status = TdVmCall (TDVMCALL_MMIO, MmioSize, 1, Veinfo->GuestPA, Val, 0);
+      break;
+    case 0xC7:
+      CopyMem ((void *)&Val, Rip, OpSize);
+      Status = TdVmCall (TDVMCALL_MMIO, MmioSize, 1, Veinfo->GuestPA, Val, 0);
+      Rip   += OpSize;
+    default:
+      //
+      // 32-bit write registers are zero extended to the full register
+      // Hence 'MOVZX r[32/64], r/m16' is
+      // hardcoded to reg size 8, and the straight MOV case has a reg
+      // size of 8 in the 32-bit read case.
+      //
+      switch (OpCode) {
+        case 0xB6:
+          RegSize = Rex.Bits.W ? 8 : OpSize;
+          break;
+        case 0xB7:
+          RegSize =  8;
+          break;
+        default:
+          RegSize = MmioSize == 4 ? 8 : MmioSize;
+          break;
+      }
+
+      Status = TdVmCall (TDVMCALL_MMIO, MmioSize, 0, Veinfo->GuestPA, 0, &Val);
+      if (Status == 0) {
+        ZeroMem (Reg, RegSize);
+        CopyMem (Reg, (void *)&Val, MmioSize);
+      }
+  }
+
+  if (Status == 0) {
+    TDX_DECODER_BUG_ON (((UINT64)Rip - Regs->Rip) > 15);
+
+    //
+    // We change instruction length to reflect true size so handler can
+    // bump rip
+    //
+    Veinfo->ExitInstructionLength =  (UINT32)((UINT64)Rip - Regs->Rip);
+  }
+
+  return Status;
+}
+
+/**
+  Handle a #VE exception.
+
+  Performs the necessary processing to handle a #VE exception.
+
+  @param[in, out]  ExceptionType  Pointer to an EFI_EXCEPTION_TYPE to be set
+                                  as value to use on error.
+  @param[in, out]  SystemContext  Pointer to EFI_SYSTEM_CONTEXT
+
+  @retval  EFI_SUCCESS            Exception handled
+  @retval  EFI_UNSUPPORTED        #VE not supported, (new) exception value to
+                                  propagate provided
+  @retval  EFI_PROTOCOL_ERROR     #VE handling failed, (new) exception value to
+                                  propagate provided
+
+**/
+EFI_STATUS
+EFIAPI
+CcExitHandleVe (
+  IN OUT EFI_EXCEPTION_TYPE  *ExceptionType,
+  IN OUT EFI_SYSTEM_CONTEXT  SystemContext
+  )
+{
+  UINT64                  Status;
+  TD_RETURN_DATA          ReturnData;
+  EFI_SYSTEM_CONTEXT_X64  *Regs;
+
+  Regs   = SystemContext.SystemContextX64;
+  Status = TdCall (TDCALL_TDGETVEINFO, 0, 0, 0, &ReturnData);
+  ASSERT (Status == 0);
+  if (Status != 0) {
+    DEBUG ((DEBUG_ERROR, "#VE happened. TDGETVEINFO failed with Status = 0x%llx\n", Status));
+    TdVmCall (TDVMCALL_HALT, 0, 0, 0, 0, 0);
+  }
+
+  switch (ReturnData.VeInfo.ExitReason) {
+    case EXIT_REASON_CPUID:
+      Status = CpuIdExit (Regs, &ReturnData.VeInfo);
+      DEBUG ((
+        DEBUG_VERBOSE,
+        "CPUID #VE happened, ExitReasion is %d, ExitQualification = 0x%x.\n",
+        ReturnData.VeInfo.ExitReason,
+        ReturnData.VeInfo.ExitQualification.Val
+        ));
+      break;
+
+    case EXIT_REASON_HLT:
+      Status = TdVmCall (EXIT_REASON_HLT, 0, 0, 0, 0, 0);
+      break;
+
+    case EXIT_REASON_IO_INSTRUCTION:
+      Status = IoExit (Regs, &ReturnData.VeInfo);
+      DEBUG ((
+        DEBUG_VERBOSE,
+        "IO_Instruction #VE happened, ExitReasion is %d, ExitQualification = 0x%x.\n",
+        ReturnData.VeInfo.ExitReason,
+        ReturnData.VeInfo.ExitQualification.Val
+        ));
+      break;
+
+    case EXIT_REASON_MSR_READ:
+      Status = ReadMsrExit (Regs, &ReturnData.VeInfo);
+      DEBUG ((
+        DEBUG_VERBOSE,
+        "RDMSR #VE happened, ExitReasion is %d, ExitQualification = 0x%x. Regs->Rcx=0x%llx, Status = 0x%llx\n",
+        ReturnData.VeInfo.ExitReason,
+        ReturnData.VeInfo.ExitQualification.Val,
+        Regs->Rcx,
+        Status
+        ));
+      break;
+
+    case EXIT_REASON_MSR_WRITE:
+      Status = WriteMsrExit (Regs, &ReturnData.VeInfo);
+      DEBUG ((
+        DEBUG_VERBOSE,
+        "WRMSR #VE happened, ExitReasion is %d, ExitQualification = 0x%x. Regs->Rcx=0x%llx, Status = 0x%llx\n",
+        ReturnData.VeInfo.ExitReason,
+        ReturnData.VeInfo.ExitQualification.Val,
+        Regs->Rcx,
+        Status
+        ));
+      break;
+
+    case EXIT_REASON_EPT_VIOLATION:
+      Status = MmioExit (Regs, &ReturnData.VeInfo);
+      DEBUG ((
+        DEBUG_VERBOSE,
+        "MMIO #VE happened, ExitReasion is %d, ExitQualification = 0x%x.\n",
+        ReturnData.VeInfo.ExitReason,
+        ReturnData.VeInfo.ExitQualification.Val
+        ));
+      break;
+
+    case EXIT_REASON_VMCALL:
+    case EXIT_REASON_MWAIT_INSTRUCTION:
+    case EXIT_REASON_MONITOR_INSTRUCTION:
+    case EXIT_REASON_WBINVD:
+    case EXIT_REASON_RDPMC:
+      /* Handle as nops. */
+      break;
+
+    default:
+      DEBUG ((
+        DEBUG_ERROR,
+        "Unsupported #VE happened, ExitReason is %d, ExitQualification = 0x%x.\n",
+        ReturnData.VeInfo.ExitReason,
+        ReturnData.VeInfo.ExitQualification.Val
+        ));
+
+      ASSERT (FALSE);
+      CpuDeadLoop ();
+  }
+
+  if (Status) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "#VE Error (0x%llx) returned from host, ExitReason is %d, ExitQualification = 0x%x.\n",
+      Status,
+      ReturnData.VeInfo.ExitReason,
+      ReturnData.VeInfo.ExitQualification.Val
+      ));
+
+    TdVmCall (TDVMCALL_HALT, 0, 0, 0, 0, 0);
+  }
+
+  SystemContext.SystemContextX64->Rip += ReturnData.VeInfo.ExitInstructionLength;
+  return EFI_SUCCESS;
+}
diff --git a/OvmfPkg/Library/CcExitLib/PeiDxeCcExitVcHandler.c b/OvmfPkg/Library/CcExitLib/PeiDxeCcExitVcHandler.c
new file mode 100644
index 000000000000..d8f78040c2e8
--- /dev/null
+++ b/OvmfPkg/Library/CcExitLib/PeiDxeCcExitVcHandler.c
@@ -0,0 +1,103 @@
+/** @file
+  X64 #VC Exception Handler functon.
+
+  Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Base.h>
+#include <Uefi.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemEncryptSevLib.h>
+#include <Library/CcExitLib.h>
+#include <Register/Amd/Msr.h>
+
+#include "CcExitVcHandler.h"
+
+/**
+  Handle a #VC exception.
+
+  Performs the necessary processing to handle a #VC exception.
+
+  @param[in, out]  ExceptionType  Pointer to an EFI_EXCEPTION_TYPE to be set
+                                  as value to use on error.
+  @param[in, out]  SystemContext  Pointer to EFI_SYSTEM_CONTEXT
+
+  @retval  EFI_SUCCESS            Exception handled
+  @retval  EFI_UNSUPPORTED        #VC not supported, (new) exception value to
+                                  propagate provided
+  @retval  EFI_PROTOCOL_ERROR     #VC handling failed, (new) exception value to
+                                  propagate provided
+
+**/
+EFI_STATUS
+EFIAPI
+CcExitHandleVc (
+  IN OUT EFI_EXCEPTION_TYPE  *ExceptionType,
+  IN OUT EFI_SYSTEM_CONTEXT  SystemContext
+  )
+{
+  MSR_SEV_ES_GHCB_REGISTER  Msr;
+  GHCB                      *Ghcb;
+  GHCB                      *GhcbBackup;
+  EFI_STATUS                VcRet;
+  BOOLEAN                   InterruptState;
+  SEV_ES_PER_CPU_DATA       *SevEsData;
+
+  InterruptState = GetInterruptState ();
+  if (InterruptState) {
+    DisableInterrupts ();
+  }
+
+  Msr.GhcbPhysicalAddress = AsmReadMsr64 (MSR_SEV_ES_GHCB);
+  ASSERT (Msr.GhcbInfo.Function == 0);
+  ASSERT (Msr.Ghcb != 0);
+
+  Ghcb       = Msr.Ghcb;
+  GhcbBackup = NULL;
+
+  SevEsData = (SEV_ES_PER_CPU_DATA *)(Ghcb + 1);
+  SevEsData->VcCount++;
+
+  //
+  // Check for maximum PEI/DXE #VC nesting.
+  //
+  if (SevEsData->VcCount > VMGEXIT_MAXIMUM_VC_COUNT) {
+    CcExitLibVmgExitIssueAssert (SevEsData);
+  } else if (SevEsData->VcCount > 1) {
+    //
+    // Nested #VC
+    //
+    if (SevEsData->GhcbBackupPages == NULL) {
+      CcExitLibVmgExitIssueAssert (SevEsData);
+    }
+
+    //
+    // Save the active GHCB to a backup page.
+    //   To access the correct backup page, increment the backup page pointer
+    //   based on the current VcCount.
+    //
+    GhcbBackup  = (GHCB *)SevEsData->GhcbBackupPages;
+    GhcbBackup += (SevEsData->VcCount - 2);
+
+    CopyMem (GhcbBackup, Ghcb, sizeof (*Ghcb));
+  }
+
+  VcRet = CcExitLibInternalVmgExitHandleVc (Ghcb, ExceptionType, SystemContext);
+
+  if (GhcbBackup != NULL) {
+    //
+    // Restore the active GHCB from the backup page.
+    //
+    CopyMem (Ghcb, GhcbBackup, sizeof (*Ghcb));
+  }
+
+  SevEsData->VcCount--;
+
+  if (InterruptState) {
+    EnableInterrupts ();
+  }
+
+  return VcRet;
+}
diff --git a/OvmfPkg/Library/CcExitLib/SecCcExitLib.inf b/OvmfPkg/Library/CcExitLib/SecCcExitLib.inf
new file mode 100644
index 000000000000..c4425eed5fef
--- /dev/null
+++ b/OvmfPkg/Library/CcExitLib/SecCcExitLib.inf
@@ -0,0 +1,48 @@
+## @file
+#  VMGEXIT Support Library.
+#
+#  Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved.<BR>
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = SecCcExitLib
+  FILE_GUID                      = 325cb20c-90e2-42a1-8667-56752d0b149c
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = CcExitLib|SEC
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = X64
+#
+
+[Sources.common]
+  CcExitLib.c
+  CcExitVcHandler.c
+  CcExitVcHandler.h
+  SecCcExitVcHandler.c
+  CcExitVeHandler.c
+  X64/TdVmcallCpuid.nasm
+
+[Packages]
+  MdePkg/MdePkg.dec
+  OvmfPkg/OvmfPkg.dec
+  UefiCpuPkg/UefiCpuPkg.dec
+
+[LibraryClasses]
+  BaseLib
+  BaseMemoryLib
+  DebugLib
+  LocalApicLib
+  MemEncryptSevLib
+  PcdLib
+
+[FixedPcd]
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupBase
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupSize
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCpuidBase
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCpuidSize
diff --git a/OvmfPkg/Library/CcExitLib/SecCcExitVcHandler.c b/OvmfPkg/Library/CcExitLib/SecCcExitVcHandler.c
new file mode 100644
index 000000000000..4a748ed9dec8
--- /dev/null
+++ b/OvmfPkg/Library/CcExitLib/SecCcExitVcHandler.c
@@ -0,0 +1,109 @@
+/** @file
+  X64 #VC Exception Handler functon.
+
+  Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Base.h>
+#include <Uefi.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemEncryptSevLib.h>
+#include <Library/CcExitLib.h>
+#include <Register/Amd/Msr.h>
+
+#include "CcExitVcHandler.h"
+
+/**
+  Handle a #VC exception.
+
+  Performs the necessary processing to handle a #VC exception.
+
+  @param[in, out]  ExceptionType  Pointer to an EFI_EXCEPTION_TYPE to be set
+                                  as value to use on error.
+  @param[in, out]  SystemContext  Pointer to EFI_SYSTEM_CONTEXT
+
+  @retval  EFI_SUCCESS            Exception handled
+  @retval  EFI_UNSUPPORTED        #VC not supported, (new) exception value to
+                                  propagate provided
+  @retval  EFI_PROTOCOL_ERROR     #VC handling failed, (new) exception value to
+                                  propagate provided
+
+**/
+EFI_STATUS
+EFIAPI
+CcExitHandleVc (
+  IN OUT EFI_EXCEPTION_TYPE  *ExceptionType,
+  IN OUT EFI_SYSTEM_CONTEXT  SystemContext
+  )
+{
+  MSR_SEV_ES_GHCB_REGISTER  Msr;
+  GHCB                      *Ghcb;
+  GHCB                      *GhcbBackup;
+  EFI_STATUS                VcRet;
+  BOOLEAN                   InterruptState;
+  SEV_ES_PER_CPU_DATA       *SevEsData;
+
+  InterruptState = GetInterruptState ();
+  if (InterruptState) {
+    DisableInterrupts ();
+  }
+
+  Msr.GhcbPhysicalAddress = AsmReadMsr64 (MSR_SEV_ES_GHCB);
+  ASSERT (Msr.GhcbInfo.Function == 0);
+  ASSERT (Msr.Ghcb != 0);
+
+  Ghcb       = Msr.Ghcb;
+  GhcbBackup = NULL;
+
+  SevEsData = (SEV_ES_PER_CPU_DATA *)(Ghcb + 1);
+  SevEsData->VcCount++;
+
+  //
+  // Check for maximum SEC #VC nesting.
+  //
+  if (SevEsData->VcCount > VMGEXIT_MAXIMUM_VC_COUNT) {
+    CcExitLibVmgExitIssueAssert (SevEsData);
+  } else if (SevEsData->VcCount > 1) {
+    UINTN  GhcbBackupSize;
+
+    //
+    // Be sure that the proper amount of pages are allocated
+    //
+    GhcbBackupSize = (VMGEXIT_MAXIMUM_VC_COUNT - 1) * sizeof (*Ghcb);
+    if (GhcbBackupSize > FixedPcdGet32 (PcdOvmfSecGhcbBackupSize)) {
+      //
+      // Not enough SEC backup pages allocated.
+      //
+      CcExitLibVmgExitIssueAssert (SevEsData);
+    }
+
+    //
+    // Save the active GHCB to a backup page.
+    //   To access the correct backup page, increment the backup page pointer
+    //   based on the current VcCount.
+    //
+    GhcbBackup  = (GHCB *)FixedPcdGet32 (PcdOvmfSecGhcbBackupBase);
+    GhcbBackup += (SevEsData->VcCount - 2);
+
+    CopyMem (GhcbBackup, Ghcb, sizeof (*Ghcb));
+  }
+
+  VcRet = CcExitLibInternalVmgExitHandleVc (Ghcb, ExceptionType, SystemContext);
+
+  if (GhcbBackup != NULL) {
+    //
+    // Restore the active GHCB from the backup page.
+    //
+    CopyMem (Ghcb, GhcbBackup, sizeof (*Ghcb));
+  }
+
+  SevEsData->VcCount--;
+
+  if (InterruptState) {
+    EnableInterrupts ();
+  }
+
+  return VcRet;
+}
diff --git a/OvmfPkg/Library/CcExitLib/X64/TdVmcallCpuid.nasm b/OvmfPkg/Library/CcExitLib/X64/TdVmcallCpuid.nasm
new file mode 100644
index 000000000000..e7e79885d472
--- /dev/null
+++ b/OvmfPkg/Library/CcExitLib/X64/TdVmcallCpuid.nasm
@@ -0,0 +1,146 @@
+;------------------------------------------------------------------------------
+;*
+;* Copyright (c) 2020 - 2021, Intel Corporation. All rights reserved.<BR>
+;* SPDX-License-Identifier: BSD-2-Clause-Patent
+;*
+;*
+;------------------------------------------------------------------------------
+
+DEFAULT REL
+SECTION .text
+
+%define TDVMCALL_EXPOSE_REGS_MASK       0xffec
+%define TDVMCALL                        0x0
+%define EXIT_REASON_CPUID               0xa
+
+%macro tdcall 0
+    db 0x66,0x0f,0x01,0xcc
+%endmacro
+
+%macro tdcall_push_regs 0
+    push rbp
+    mov  rbp, rsp
+    push r15
+    push r14
+    push r13
+    push r12
+    push rbx
+    push rsi
+    push rdi
+%endmacro
+
+%macro tdcall_pop_regs 0
+    pop rdi
+    pop rsi
+    pop rbx
+    pop r12
+    pop r13
+    pop r14
+    pop r15
+    pop rbp
+%endmacro
+
+%define number_of_regs_pushed 8
+%define number_of_parameters  4
+
+;
+; Keep these in sync for push_regs/pop_regs, code below
+; uses them to find 5th or greater parameters
+;
+%define first_variable_on_stack_offset \
+  ((number_of_regs_pushed * 8) + (number_of_parameters * 8) + 8)
+%define second_variable_on_stack_offset \
+  ((first_variable_on_stack_offset) + 8)
+
+%macro tdcall_regs_preamble 2
+    mov rax, %1
+
+    xor rcx, rcx
+    mov ecx, %2
+
+    ; R10 = 0 (standard TDVMCALL)
+
+    xor r10d, r10d
+
+    ; Zero out unused (for standard TDVMCALL) registers to avoid leaking
+    ; secrets to the VMM.
+
+    xor ebx, ebx
+    xor esi, esi
+    xor edi, edi
+
+    xor edx, edx
+    xor ebp, ebp
+    xor r8d, r8d
+    xor r9d, r9d
+    xor r14, r14
+    xor r15, r15
+%endmacro
+
+%macro tdcall_regs_postamble 0
+    xor ebx, ebx
+    xor esi, esi
+    xor edi, edi
+
+    xor ecx, ecx
+    xor edx, edx
+    xor r8d,  r8d
+    xor r9d,  r9d
+    xor r10d, r10d
+    xor r11d, r11d
+%endmacro
+
+;------------------------------------------------------------------------------
+; 0   => RAX = TDCALL leaf / TDVMCALL
+; M   => RCX = TDVMCALL register behavior
+; 0xa => R11 = TDVMCALL function / CPUID
+; RCX => R12 = p1
+; RDX => R13 = p2
+;
+;  UINT64
+;  EFIAPI
+;  TdVmCallCpuid (
+;    UINT64  EaxIn,    // Rcx
+;    UINT64  EcxIn,    // Rdx
+;    UINT64  *Results  // R8
+;    )
+global ASM_PFX(CcExitLibTdVmCallCpuid)
+ASM_PFX(CcExitLibTdVmCallCpuid):
+       tdcall_push_regs
+
+       mov r11, EXIT_REASON_CPUID
+       mov r12, rcx
+       mov r13, rdx
+
+       ; Save *results pointers
+       push r8
+
+       tdcall_regs_preamble TDVMCALL, TDVMCALL_EXPOSE_REGS_MASK
+
+       tdcall
+
+       ; ignore return data if TDCALL reports failure.
+       test rax, rax
+       jnz .no_return_data
+
+       ; Propagate TDVMCALL success/failure to return value.
+       mov rax, r10
+       test rax, rax
+       jnz .no_return_data
+
+       ; Retrieve *Results
+       pop r8
+       test r8, r8
+       jz .no_return_data
+       ; Caller pass in buffer so store results r12-r15 contains eax-edx
+       mov [r8 +  0], r12
+       mov [r8 +  8], r13
+       mov [r8 + 16], r14
+       mov [r8 + 24], r15
+
+.no_return_data:
+       tdcall_regs_postamble
+
+       tdcall_pop_regs
+
+       ret
-- 
2.29.2.windows.2


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH V2 3/9] OvmfPkg: Add CcExitLib in *.dsc
  2022-11-03 23:19 [PATCH V2 0/9] Rename VmgExitLib to CcExitLib Min Xu
  2022-11-03 23:19 ` [PATCH V2 1/9] UefiCpuPkg: Add CcExitLib Min Xu
  2022-11-03 23:19 ` [PATCH V2 2/9] OvmfPkg: Implement CcExitLib Min Xu
@ 2022-11-03 23:19 ` Min Xu
  2022-11-03 23:19 ` [PATCH V2 4/9] UefiCpuPkg: Use CcExitLib instead of VmgExitLib Min Xu
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 13+ messages in thread
From: Min Xu @ 2022-11-03 23:19 UTC (permalink / raw)
  To: devel
  Cc: Min M Xu, Brijesh Singh, Erdem Aktas, Gerd Hoffmann,
	James Bottomley, Jiewen Yao, Tom Lendacky

From: Min M Xu <min.m.xu@intel.com>

https://bugzilla.tianocore.org/show_bug.cgi?id=4123

CcExitLib is designed to replace VmgExitLib. This patch adds CcExitLib in
*.dsc which import VmgExitLib. VmgExitLib in these *.dsc will be deleted
in the follwing patch so that the build will not be broken.

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>
Signed-off-by: Min Xu <min.m.xu@intel.com>
---
 OvmfPkg/AmdSev/AmdSevX64.dsc     | 2 ++
 OvmfPkg/Bhyve/BhyveX64.dsc       | 1 +
 OvmfPkg/CloudHv/CloudHvX64.dsc   | 3 +++
 OvmfPkg/IntelTdx/IntelTdxX64.dsc | 2 ++
 OvmfPkg/Microvm/MicrovmX64.dsc   | 2 ++
 OvmfPkg/OvmfPkgIa32.dsc          | 2 ++
 OvmfPkg/OvmfPkgIa32X64.dsc       | 2 ++
 OvmfPkg/OvmfPkgX64.dsc           | 3 +++
 OvmfPkg/OvmfXen.dsc              | 1 +
 9 files changed, 18 insertions(+)

diff --git a/OvmfPkg/AmdSev/AmdSevX64.dsc b/OvmfPkg/AmdSev/AmdSevX64.dsc
index 90e8a213ef77..1b324fa48d09 100644
--- a/OvmfPkg/AmdSev/AmdSevX64.dsc
+++ b/OvmfPkg/AmdSev/AmdSevX64.dsc
@@ -204,6 +204,7 @@
 
 [LibraryClasses.common]
   BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
+  CcExitLib|OvmfPkg/Library/CcExitLib/CcExitLib.inf
   VmgExitLib|OvmfPkg/Library/VmgExitLib/VmgExitLib.inf
   TdxLib|MdePkg/Library/TdxLib/TdxLib.inf
 
@@ -229,6 +230,7 @@
 !else
   CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf
 !endif
+  CcExitLib|OvmfPkg/Library/CcExitLib/SecCcExitLib.inf
   VmgExitLib|OvmfPkg/Library/VmgExitLib/SecVmgExitLib.inf
   MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLib.inf
 
diff --git a/OvmfPkg/Bhyve/BhyveX64.dsc b/OvmfPkg/Bhyve/BhyveX64.dsc
index 475b88b21a4c..3e90ae365682 100644
--- a/OvmfPkg/Bhyve/BhyveX64.dsc
+++ b/OvmfPkg/Bhyve/BhyveX64.dsc
@@ -232,6 +232,7 @@
 
 [LibraryClasses.common]
   BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
+  CcExitLib|UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.inf
   VmgExitLib|UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.inf
   TdxLib|MdePkg/Library/TdxLib/TdxLib.inf
 
diff --git a/OvmfPkg/CloudHv/CloudHvX64.dsc b/OvmfPkg/CloudHv/CloudHvX64.dsc
index 10b16104acd7..56d061464dbf 100644
--- a/OvmfPkg/CloudHv/CloudHvX64.dsc
+++ b/OvmfPkg/CloudHv/CloudHvX64.dsc
@@ -251,6 +251,7 @@
 
 [LibraryClasses.common]
   BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
+  CcExitLib|OvmfPkg/Library/CcExitLib/CcExitLib.inf
   VmgExitLib|OvmfPkg/Library/VmgExitLib/VmgExitLib.inf
   TdxLib|MdePkg/Library/TdxLib/TdxLib.inf
 
@@ -275,6 +276,7 @@
 !else
   CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf
 !endif
+  CcExitLib|OvmfPkg/Library/CcExitLib/SecCcExitLib.inf
   VmgExitLib|OvmfPkg/Library/VmgExitLib/SecVmgExitLib.inf
   MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLib.inf
 
@@ -915,6 +917,7 @@
   #
   OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FvbServicesSmm.inf {
     <LibraryClasses>
+    CcExitLib|UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.inf
     VmgExitLib|UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.inf
   }
   MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.inf
diff --git a/OvmfPkg/IntelTdx/IntelTdxX64.dsc b/OvmfPkg/IntelTdx/IntelTdxX64.dsc
index c0c1a15b0926..8c6edfbc2363 100644
--- a/OvmfPkg/IntelTdx/IntelTdxX64.dsc
+++ b/OvmfPkg/IntelTdx/IntelTdxX64.dsc
@@ -215,6 +215,7 @@
 
 [LibraryClasses.common]
   BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
+  CcExitLib|OvmfPkg/Library/CcExitLib/CcExitLib.inf
   VmgExitLib|OvmfPkg/Library/VmgExitLib/VmgExitLib.inf
   TdxLib|MdePkg/Library/TdxLib/TdxLib.inf
   TdxMailboxLib|OvmfPkg/Library/TdxMailboxLib/TdxMailboxLib.inf
@@ -237,6 +238,7 @@
 !else
   CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf
 !endif
+  CcExitLib|OvmfPkg/Library/CcExitLib/SecCcExitLib.inf
   VmgExitLib|OvmfPkg/Library/VmgExitLib/SecVmgExitLib.inf
   MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLib.inf
   PrePiHobListPointerLib|OvmfPkg/IntelTdx/PrePiHobListPointerLibTdx/PrePiHobListPointerLibTdx.inf
diff --git a/OvmfPkg/Microvm/MicrovmX64.dsc b/OvmfPkg/Microvm/MicrovmX64.dsc
index 7eff8e2a88d9..98da7a3c9138 100644
--- a/OvmfPkg/Microvm/MicrovmX64.dsc
+++ b/OvmfPkg/Microvm/MicrovmX64.dsc
@@ -249,6 +249,7 @@
 
 [LibraryClasses.common]
   BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
+  CcExitLib|OvmfPkg/Library/CcExitLib/CcExitLib.inf
   VmgExitLib|OvmfPkg/Library/VmgExitLib/VmgExitLib.inf
   SerialPortLib|MdeModulePkg/Library/BaseSerialPortLib16550/BaseSerialPortLib16550.inf
   PlatformHookLib|MdeModulePkg/Library/BasePlatformHookLibNull/BasePlatformHookLibNull.inf
@@ -277,6 +278,7 @@
 !else
   CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf
 !endif
+  CcExitLib|OvmfPkg/Library/CcExitLib/SecCcExitLib.inf
   VmgExitLib|OvmfPkg/Library/VmgExitLib/SecVmgExitLib.inf
   MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLib.inf
 
diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc
index e9ba491237ae..ae002b6c9f23 100644
--- a/OvmfPkg/OvmfPkgIa32.dsc
+++ b/OvmfPkg/OvmfPkgIa32.dsc
@@ -256,6 +256,7 @@
 
 [LibraryClasses.common]
   BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
+  CcExitLib|UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.inf
   VmgExitLib|UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.inf
 
 [LibraryClasses.common.SEC]
@@ -985,6 +986,7 @@
   OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FvbServicesSmm.inf {
     <LibraryClasses>
     VmgExitLib|UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.inf
+    CcExitLib|UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.inf
   }
   MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.inf
   MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf {
diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc
index af566b953f36..753486bf7798 100644
--- a/OvmfPkg/OvmfPkgIa32X64.dsc
+++ b/OvmfPkg/OvmfPkgIa32X64.dsc
@@ -260,6 +260,7 @@
 
 [LibraryClasses.common]
   BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
+  CcExitLib|UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.inf
   VmgExitLib|UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.inf
   TdxLib|MdePkg/Library/TdxLib/TdxLib.inf
   TdxMailboxLib|OvmfPkg/Library/TdxMailboxLib/TdxMailboxLib.inf
@@ -1002,6 +1003,7 @@
   #
   OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FvbServicesSmm.inf {
     <LibraryClasses>
+    CcExitLib|UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.inf
     VmgExitLib|UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.inf
   }
   MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.inf
diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc
index f39d9cd117e6..61998d33dc78 100644
--- a/OvmfPkg/OvmfPkgX64.dsc
+++ b/OvmfPkg/OvmfPkgX64.dsc
@@ -276,6 +276,7 @@
 
 [LibraryClasses.common]
   BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
+  CcExitLib|OvmfPkg/Library/CcExitLib/CcExitLib.inf
   VmgExitLib|OvmfPkg/Library/VmgExitLib/VmgExitLib.inf
   TdxLib|MdePkg/Library/TdxLib/TdxLib.inf
   TdxMailboxLib|OvmfPkg/Library/TdxMailboxLib/TdxMailboxLib.inf
@@ -302,6 +303,7 @@
 !else
   CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf
 !endif
+  CcExitLib|OvmfPkg/Library/CcExitLib/SecCcExitLib.inf
   VmgExitLib|OvmfPkg/Library/VmgExitLib/SecVmgExitLib.inf
   MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLib.inf
   CcProbeLib|OvmfPkg/Library/CcProbeLib/SecPeiCcProbeLib.inf
@@ -1072,6 +1074,7 @@
   #
   OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FvbServicesSmm.inf {
     <LibraryClasses>
+    CcExitLib|UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.inf
     VmgExitLib|UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.inf
   }
   MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.inf
diff --git a/OvmfPkg/OvmfXen.dsc b/OvmfPkg/OvmfXen.dsc
index 58a7c97cddf7..ce298bbce25c 100644
--- a/OvmfPkg/OvmfXen.dsc
+++ b/OvmfPkg/OvmfXen.dsc
@@ -231,6 +231,7 @@
 
 [LibraryClasses.common]
   BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
+  CcExitLib|UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.inf
   VmgExitLib|UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.inf
   TdxLib|MdePkg/Library/TdxLib/TdxLib.inf
 
-- 
2.29.2.windows.2


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH V2 4/9] UefiCpuPkg: Use CcExitLib instead of VmgExitLib
  2022-11-03 23:19 [PATCH V2 0/9] Rename VmgExitLib to CcExitLib Min Xu
                   ` (2 preceding siblings ...)
  2022-11-03 23:19 ` [PATCH V2 3/9] OvmfPkg: Add CcExitLib in *.dsc Min Xu
@ 2022-11-03 23:19 ` Min Xu
  2022-11-03 23:19 ` [PATCH V2 5/9] UefiPayloadPkg: " Min Xu
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 13+ messages in thread
From: Min Xu @ 2022-11-03 23:19 UTC (permalink / raw)
  To: devel
  Cc: Min M Xu, Eric Dong, Ray Ni, Brijesh Singh, Erdem Aktas,
	Gerd Hoffmann, James Bottomley, Jiewen Yao, Tom Lendacky

From: Min M Xu <min.m.xu@intel.com>

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. So VmgExitLib is replaced
by CcExitLib.

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>
Signed-off-by: Min Xu <min.m.xu@intel.com>
---
 .../DxeCpuExceptionHandlerLib.inf                      |  2 +-
 .../PeiCpuExceptionHandlerLib.inf                      |  2 +-
 .../CpuExceptionHandlerLib/PeiDxeSmmCpuException.c     |  6 +++---
 .../CpuExceptionHandlerLib/SecPeiCpuException.c        |  6 +++---
 .../SecPeiCpuExceptionHandlerLib.inf                   |  2 +-
 .../SmmCpuExceptionHandlerLib.inf                      |  2 +-
 .../Xcode5SecPeiCpuExceptionHandlerLib.inf             |  2 +-
 UefiCpuPkg/Library/MpInitLib/AmdSev.c                  | 10 +++++-----
 UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf          |  2 +-
 UefiCpuPkg/Library/MpInitLib/DxeMpLib.c                |  8 ++++----
 UefiCpuPkg/Library/MpInitLib/MpLib.c                   |  2 +-
 UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf          |  2 +-
 UefiCpuPkg/Library/MpInitLib/X64/AmdSev.c              | 10 +++++-----
 UefiCpuPkg/UefiCpuPkg.dsc                              |  2 ++
 14 files changed, 30 insertions(+), 28 deletions(-)

diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf b/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf
index e7a81bebdb13..d0f82095cf92 100644
--- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf
+++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf
@@ -60,4 +60,4 @@
   PeCoffGetEntryPointLib
   MemoryAllocationLib
   DebugLib
-  VmgExitLib
+  CcExitLib
diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiCpuExceptionHandlerLib.inf b/UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiCpuExceptionHandlerLib.inf
index 7c2ec3b2db4c..5339f8e60404 100644
--- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiCpuExceptionHandlerLib.inf
+++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiCpuExceptionHandlerLib.inf
@@ -52,7 +52,7 @@
   HobLib
   MemoryAllocationLib
   SynchronizationLib
-  VmgExitLib
+  CcExitLib
 
 [Pcd]
   gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard    # CONSUMES
diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiDxeSmmCpuException.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiDxeSmmCpuException.c
index a7d0897ef1f9..748cf8d3bfc6 100644
--- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiDxeSmmCpuException.c
+++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiDxeSmmCpuException.c
@@ -7,7 +7,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 **/
 
 #include <Library/DebugLib.h>
-#include <Library/VmgExitLib.h>
+#include <Library/CcExitLib.h>
 #include "CpuExceptionCommon.h"
 
 /**
@@ -40,7 +40,7 @@ CommonExceptionHandlerWorker (
       //   On other       - ExceptionType contains (possibly new) exception
       //                    value
       //
-      Status = VmgExitHandleVc (&ExceptionType, SystemContext);
+      Status = CcExitHandleVc (&ExceptionType, SystemContext);
       if (!EFI_ERROR (Status)) {
         return;
       }
@@ -57,7 +57,7 @@ CommonExceptionHandlerWorker (
       //   On other       - ExceptionType contains (possibly new) exception
       //                    value
       //
-      Status = VmTdExitHandleVe (&ExceptionType, SystemContext);
+      Status = CcExitHandleVe (&ExceptionType, SystemContext);
       if (!EFI_ERROR (Status)) {
         return;
       }
diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuException.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuException.c
index ad5e0e9ed4f1..497cd1649930 100644
--- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuException.c
+++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuException.c
@@ -7,7 +7,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 **/
 
 #include <PiPei.h>
-#include <Library/VmgExitLib.h>
+#include <Library/CcExitLib.h>
 #include "CpuExceptionCommon.h"
 
 CONST UINTN  mDoFarReturnFlag = 0;
@@ -39,7 +39,7 @@ CommonExceptionHandler (
       //   On other       - ExceptionType contains (possibly new) exception
       //                    value
       //
-      Status = VmgExitHandleVc (&ExceptionType, SystemContext);
+      Status = CcExitHandleVc (&ExceptionType, SystemContext);
       if (!EFI_ERROR (Status)) {
         return;
       }
@@ -57,7 +57,7 @@ CommonExceptionHandler (
       //   On other       - ExceptionType contains (possibly new) exception
       //                    value
       //
-      Status = VmTdExitHandleVe (&ExceptionType, SystemContext);
+      Status = CcExitHandleVe (&ExceptionType, SystemContext);
       if (!EFI_ERROR (Status)) {
         return;
       }
diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf b/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf
index 6a170286c8fc..df44371fe018 100644
--- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf
+++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf
@@ -48,7 +48,7 @@
   PrintLib
   LocalApicLib
   PeCoffGetEntryPointLib
-  VmgExitLib
+  CcExitLib
 
 [Pcd]
   gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard
diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/SmmCpuExceptionHandlerLib.inf b/UefiCpuPkg/Library/CpuExceptionHandlerLib/SmmCpuExceptionHandlerLib.inf
index 9dde07612a04..8f8a5dab7930 100644
--- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/SmmCpuExceptionHandlerLib.inf
+++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/SmmCpuExceptionHandlerLib.inf
@@ -51,7 +51,7 @@
   LocalApicLib
   PeCoffGetEntryPointLib
   DebugLib
-  VmgExitLib
+  CcExitLib
 
 [Pcd]
   gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard
diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/Xcode5SecPeiCpuExceptionHandlerLib.inf b/UefiCpuPkg/Library/CpuExceptionHandlerLib/Xcode5SecPeiCpuExceptionHandlerLib.inf
index 6d2f66504a5b..619b39d7f1de 100644
--- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/Xcode5SecPeiCpuExceptionHandlerLib.inf
+++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/Xcode5SecPeiCpuExceptionHandlerLib.inf
@@ -53,7 +53,7 @@
   PrintLib
   LocalApicLib
   PeCoffGetEntryPointLib
-  VmgExitLib
+  CcExitLib
 
 [Pcd]
   gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard
diff --git a/UefiCpuPkg/Library/MpInitLib/AmdSev.c b/UefiCpuPkg/Library/MpInitLib/AmdSev.c
index 4e4c63a52de4..9af108fcb5ff 100644
--- a/UefiCpuPkg/Library/MpInitLib/AmdSev.c
+++ b/UefiCpuPkg/Library/MpInitLib/AmdSev.c
@@ -8,7 +8,7 @@
 **/
 
 #include "MpLib.h"
-#include <Library/VmgExitLib.h>
+#include <Library/CcExitLib.h>
 
 /**
   Get Protected mode code segment with 16-bit default addressing
@@ -209,7 +209,7 @@ SevEsPlaceApHlt (
     Msr.GhcbPhysicalAddress = AsmReadMsr64 (MSR_SEV_ES_GHCB);
     Ghcb                    = Msr.Ghcb;
 
-    VmgInit (Ghcb, &InterruptState);
+    CcExitLibVmgInit (Ghcb, &InterruptState);
 
     if (DoDecrement) {
       DoDecrement = FALSE;
@@ -221,13 +221,13 @@ SevEsPlaceApHlt (
       InterlockedDecrement ((UINT32 *)&CpuMpData->MpCpuExchangeInfo->NumApsExecuting);
     }
 
-    Status = VmgExit (Ghcb, SVM_EXIT_AP_RESET_HOLD, 0, 0);
+    Status = CcExitLibVmgExit (Ghcb, SVM_EXIT_AP_RESET_HOLD, 0, 0);
     if ((Status == 0) && (Ghcb->SaveArea.SwExitInfo2 != 0)) {
-      VmgDone (Ghcb, InterruptState);
+      CcExitLibVmgDone (Ghcb, InterruptState);
       break;
     }
 
-    VmgDone (Ghcb, InterruptState);
+    CcExitLibVmgDone (Ghcb, InterruptState);
   }
 
   //
diff --git a/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf b/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf
index e1cd0b350008..cd07de3a3c0b 100644
--- a/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf
+++ b/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf
@@ -54,7 +54,7 @@
   DebugAgentLib
   SynchronizationLib
   PcdLib
-  VmgExitLib
+  CcExitLib
   MicrocodeLib
 
 [Protocols]
diff --git a/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c b/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c
index 78cc3e2b93fd..8c7a131a0a3f 100644
--- a/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c
+++ b/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c
@@ -12,7 +12,7 @@
 #include <Library/UefiBootServicesTableLib.h>
 #include <Library/DebugAgentLib.h>
 #include <Library/DxeServicesTableLib.h>
-#include <Library/VmgExitLib.h>
+#include <Library/CcExitLib.h>
 #include <Register/Amd/Fam17Msr.h>
 #include <Register/Amd/Ghcb.h>
 
@@ -222,9 +222,9 @@ GetSevEsAPMemory (
   Msr.GhcbPhysicalAddress = AsmReadMsr64 (MSR_SEV_ES_GHCB);
   Ghcb                    = Msr.Ghcb;
 
-  VmgInit (Ghcb, &InterruptState);
-  VmgExit (Ghcb, SVM_EXIT_AP_JUMP_TABLE, 0, (UINT64)(UINTN)StartAddress);
-  VmgDone (Ghcb, InterruptState);
+  CcExitLibVmgInit (Ghcb, &InterruptState);
+  CcExitLibVmgExit (Ghcb, SVM_EXIT_AP_JUMP_TABLE, 0, (UINT64)(UINTN)StartAddress);
+  CcExitLibVmgDone (Ghcb, InterruptState);
 
   return (UINTN)StartAddress;
 }
diff --git a/UefiCpuPkg/Library/MpInitLib/MpLib.c b/UefiCpuPkg/Library/MpInitLib/MpLib.c
index 1c053f87a4c6..e5dc852ed95f 100644
--- a/UefiCpuPkg/Library/MpInitLib/MpLib.c
+++ b/UefiCpuPkg/Library/MpInitLib/MpLib.c
@@ -9,7 +9,7 @@
 **/
 
 #include "MpLib.h"
-#include <Library/VmgExitLib.h>
+#include <Library/CcExitLib.h>
 #include <Register/Amd/Fam17Msr.h>
 #include <Register/Amd/Ghcb.h>
 
diff --git a/UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf b/UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf
index 5facf4db9499..afd551bb0f64 100644
--- a/UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf
+++ b/UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf
@@ -53,7 +53,7 @@
   SynchronizationLib
   PeiServicesLib
   PcdLib
-  VmgExitLib
+  CcExitLib
   MicrocodeLib
 
 [Pcd]
diff --git a/UefiCpuPkg/Library/MpInitLib/X64/AmdSev.c b/UefiCpuPkg/Library/MpInitLib/X64/AmdSev.c
index a3cd377ef600..933f765f3f5e 100644
--- a/UefiCpuPkg/Library/MpInitLib/X64/AmdSev.c
+++ b/UefiCpuPkg/Library/MpInitLib/X64/AmdSev.c
@@ -9,7 +9,7 @@
 **/
 
 #include "MpLib.h"
-#include <Library/VmgExitLib.h>
+#include <Library/CcExitLib.h>
 #include <Register/Amd/Fam17Msr.h>
 #include <Register/Amd/Ghcb.h>
 
@@ -150,16 +150,16 @@ SevSnpCreateSaveArea (
   Msr.GhcbPhysicalAddress = AsmReadMsr64 (MSR_SEV_ES_GHCB);
   Ghcb                    = Msr.Ghcb;
 
-  VmgInit (Ghcb, &InterruptState);
+  CcExitLibVmgInit (Ghcb, &InterruptState);
   Ghcb->SaveArea.Rax = SaveArea->SevFeatures;
-  VmgSetOffsetValid (Ghcb, GhcbRax);
-  VmgExitStatus = VmgExit (
+  CcExitLibVmgSetOffsetValid (Ghcb, GhcbRax);
+  VmgExitStatus = CcExitLibVmgExit (
                     Ghcb,
                     SVM_EXIT_SNP_AP_CREATION,
                     ExitInfo1,
                     ExitInfo2
                     );
-  VmgDone (Ghcb, InterruptState);
+  CcExitLibVmgDone (Ghcb, InterruptState);
 
   ASSERT (VmgExitStatus == 0);
   if (VmgExitStatus != 0) {
diff --git a/UefiCpuPkg/UefiCpuPkg.dsc b/UefiCpuPkg/UefiCpuPkg.dsc
index 0e1a99ddc09f..57c74ba844d2 100644
--- a/UefiCpuPkg/UefiCpuPkg.dsc
+++ b/UefiCpuPkg/UefiCpuPkg.dsc
@@ -60,6 +60,7 @@
   PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf
   TpmMeasurementLib|MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.inf
   VmgExitLib|UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.inf
+  CcExitLib|UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.inf
   MicrocodeLib|UefiCpuPkg/Library/MicrocodeLib/MicrocodeLib.inf
   SmmCpuRendezvousLib|UefiCpuPkg/Library/SmmCpuRendezvousLib/SmmCpuRendezvousLib.inf
   CpuPageTableLib|UefiCpuPkg/Library/CpuPageTableLib/CpuPageTableLib.inf
@@ -164,6 +165,7 @@
   UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLibStm.inf
   UefiCpuPkg/Library/SmmCpuFeaturesLib/StandaloneMmCpuFeaturesLib.inf
   UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.inf
+  UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.inf
   UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationPei.inf
   UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationSmm.inf
   UefiCpuPkg/SecCore/SecCore.inf
-- 
2.29.2.windows.2


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH V2 5/9] UefiPayloadPkg: Use CcExitLib instead of VmgExitLib
  2022-11-03 23:19 [PATCH V2 0/9] Rename VmgExitLib to CcExitLib Min Xu
                   ` (3 preceding siblings ...)
  2022-11-03 23:19 ` [PATCH V2 4/9] UefiCpuPkg: Use CcExitLib instead of VmgExitLib Min Xu
@ 2022-11-03 23:19 ` Min Xu
  2022-11-03 23:19 ` [PATCH V2 6/9] OvmfPkg: " Min Xu
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 13+ messages in thread
From: Min Xu @ 2022-11-03 23:19 UTC (permalink / raw)
  To: devel; +Cc: Min M Xu, Guo Dong, Ray Ni, Sean Rhodes, James Lu, Gua Guo

From: Min M Xu <min.m.xu@intel.com>

BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=4123

VmgExitLib is renamed as CcExitLib. So UefiPayloadPkg.dsc should be
updated as well.

Cc: Guo Dong <guo.dong@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Cc: Sean Rhodes <sean@starlabs.systems>
Cc: James Lu <james.lu@intel.com>
Cc: Gua Guo <gua.guo@intel.com>
Reviewed-by: James Lu <james.lu@intel.com>
Reviewed-by: Gua Guo <gua.guo@intel.com>
Signed-off-by: Min Xu <min.m.xu@intel.com>
---
 UefiPayloadPkg/UefiPayloadPkg.dsc | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/UefiPayloadPkg/UefiPayloadPkg.dsc b/UefiPayloadPkg/UefiPayloadPkg.dsc
index 1150be6acd0e..723a50a42284 100644
--- a/UefiPayloadPkg/UefiPayloadPkg.dsc
+++ b/UefiPayloadPkg/UefiPayloadPkg.dsc
@@ -301,7 +301,7 @@
   VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf
   VariablePolicyHelperLib|MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.inf
   VariableFlashInfoLib|MdeModulePkg/Library/BaseVariableFlashInfoLib/BaseVariableFlashInfoLib.inf
-  VmgExitLib|UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.inf
+  CcExitLib|UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.inf
   ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf
 
 [LibraryClasses.common]
-- 
2.29.2.windows.2


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH V2 6/9] OvmfPkg: Use CcExitLib instead of VmgExitLib
  2022-11-03 23:19 [PATCH V2 0/9] Rename VmgExitLib to CcExitLib Min Xu
                   ` (4 preceding siblings ...)
  2022-11-03 23:19 ` [PATCH V2 5/9] UefiPayloadPkg: " Min Xu
@ 2022-11-03 23:19 ` Min Xu
  2022-11-03 23:19 ` [PATCH V2 7/9] OvmfPkg: Delete VmgExitLib Min Xu
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 13+ messages in thread
From: Min Xu @ 2022-11-03 23:19 UTC (permalink / raw)
  To: devel
  Cc: Min M Xu, Brijesh Singh, Erdem Aktas, Gerd Hoffmann,
	James Bottomley, Jiewen Yao, Tom Lendacky

From: Min M Xu <min.m.xu@intel.com>

BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=4123

VmgExitLib is renamed as CcExitLib. See the description in BZ4123.
So OvmfPkg should be updated to this rename.

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>
Signed-off-by: Min Xu <min.m.xu@intel.com>
---
 OvmfPkg/AmdSev/AmdSevX64.dsc                           |  2 --
 OvmfPkg/Bhyve/BhyveX64.dsc                             |  1 -
 OvmfPkg/CloudHv/CloudHvX64.dsc                         |  3 ---
 OvmfPkg/IntelTdx/IntelTdxX64.dsc                       |  2 --
 .../BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf       |  2 +-
 .../BaseMemEncryptSevLib/PeiMemEncryptSevLib.inf       |  2 +-
 .../BaseMemEncryptSevLib/SecMemEncryptSevLib.inf       |  2 +-
 .../X64/SnpPageStateChangeInternal.c                   | 10 +++++-----
 OvmfPkg/Microvm/MicrovmX64.dsc                         |  2 --
 OvmfPkg/OvmfPkgIa32.dsc                                |  2 --
 OvmfPkg/OvmfPkgIa32X64.dsc                             |  2 --
 OvmfPkg/OvmfPkgX64.dsc                                 |  3 ---
 OvmfPkg/OvmfXen.dsc                                    |  1 -
 OvmfPkg/PlatformPei/AmdSev.c                           | 10 +++++-----
 OvmfPkg/PlatformPei/PlatformPei.inf                    |  2 +-
 .../FvbServicesRuntimeDxe.inf                          |  2 +-
 OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlashDxe.c  | 10 +++++-----
 17 files changed, 20 insertions(+), 38 deletions(-)

diff --git a/OvmfPkg/AmdSev/AmdSevX64.dsc b/OvmfPkg/AmdSev/AmdSevX64.dsc
index 1b324fa48d09..8f7cae787e97 100644
--- a/OvmfPkg/AmdSev/AmdSevX64.dsc
+++ b/OvmfPkg/AmdSev/AmdSevX64.dsc
@@ -205,7 +205,6 @@
 [LibraryClasses.common]
   BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
   CcExitLib|OvmfPkg/Library/CcExitLib/CcExitLib.inf
-  VmgExitLib|OvmfPkg/Library/VmgExitLib/VmgExitLib.inf
   TdxLib|MdePkg/Library/TdxLib/TdxLib.inf
 
 [LibraryClasses.common.SEC]
@@ -231,7 +230,6 @@
   CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf
 !endif
   CcExitLib|OvmfPkg/Library/CcExitLib/SecCcExitLib.inf
-  VmgExitLib|OvmfPkg/Library/VmgExitLib/SecVmgExitLib.inf
   MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLib.inf
 
 [LibraryClasses.common.PEI_CORE]
diff --git a/OvmfPkg/Bhyve/BhyveX64.dsc b/OvmfPkg/Bhyve/BhyveX64.dsc
index 3e90ae365682..e3bb367b6bf6 100644
--- a/OvmfPkg/Bhyve/BhyveX64.dsc
+++ b/OvmfPkg/Bhyve/BhyveX64.dsc
@@ -233,7 +233,6 @@
 [LibraryClasses.common]
   BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
   CcExitLib|UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.inf
-  VmgExitLib|UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.inf
   TdxLib|MdePkg/Library/TdxLib/TdxLib.inf
 
 [LibraryClasses.common.SEC]
diff --git a/OvmfPkg/CloudHv/CloudHvX64.dsc b/OvmfPkg/CloudHv/CloudHvX64.dsc
index 56d061464dbf..ce277cb2398b 100644
--- a/OvmfPkg/CloudHv/CloudHvX64.dsc
+++ b/OvmfPkg/CloudHv/CloudHvX64.dsc
@@ -252,7 +252,6 @@
 [LibraryClasses.common]
   BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
   CcExitLib|OvmfPkg/Library/CcExitLib/CcExitLib.inf
-  VmgExitLib|OvmfPkg/Library/VmgExitLib/VmgExitLib.inf
   TdxLib|MdePkg/Library/TdxLib/TdxLib.inf
 
 [LibraryClasses.common.SEC]
@@ -277,7 +276,6 @@
   CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf
 !endif
   CcExitLib|OvmfPkg/Library/CcExitLib/SecCcExitLib.inf
-  VmgExitLib|OvmfPkg/Library/VmgExitLib/SecVmgExitLib.inf
   MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLib.inf
 
 [LibraryClasses.common.PEI_CORE]
@@ -918,7 +916,6 @@
   OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FvbServicesSmm.inf {
     <LibraryClasses>
     CcExitLib|UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.inf
-    VmgExitLib|UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.inf
   }
   MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.inf
   MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf {
diff --git a/OvmfPkg/IntelTdx/IntelTdxX64.dsc b/OvmfPkg/IntelTdx/IntelTdxX64.dsc
index 8c6edfbc2363..345892651520 100644
--- a/OvmfPkg/IntelTdx/IntelTdxX64.dsc
+++ b/OvmfPkg/IntelTdx/IntelTdxX64.dsc
@@ -216,7 +216,6 @@
 [LibraryClasses.common]
   BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
   CcExitLib|OvmfPkg/Library/CcExitLib/CcExitLib.inf
-  VmgExitLib|OvmfPkg/Library/VmgExitLib/VmgExitLib.inf
   TdxLib|MdePkg/Library/TdxLib/TdxLib.inf
   TdxMailboxLib|OvmfPkg/Library/TdxMailboxLib/TdxMailboxLib.inf
   PlatformInitLib|OvmfPkg/Library/PlatformInitLib/PlatformInitLib.inf
@@ -239,7 +238,6 @@
   CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf
 !endif
   CcExitLib|OvmfPkg/Library/CcExitLib/SecCcExitLib.inf
-  VmgExitLib|OvmfPkg/Library/VmgExitLib/SecVmgExitLib.inf
   MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLib.inf
   PrePiHobListPointerLib|OvmfPkg/IntelTdx/PrePiHobListPointerLibTdx/PrePiHobListPointerLibTdx.inf
   HobLib|EmbeddedPkg/Library/PrePiHobLib/PrePiHobLib.inf
diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf b/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf
index 35b7d519d938..cc24961c9265 100644
--- a/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf
+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf
@@ -51,7 +51,7 @@
   DebugLib
   MemoryAllocationLib
   PcdLib
-  VmgExitLib
+  CcExitLib
 
 [FeaturePcd]
   gUefiOvmfPkgTokenSpaceGuid.PcdSmmSmramRequire
diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLib.inf b/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLib.inf
index 714da3323765..8f56783da55e 100644
--- a/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLib.inf
+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLib.inf
@@ -51,7 +51,7 @@
   DebugLib
   MemoryAllocationLib
   PcdLib
-  VmgExitLib
+  CcExitLib
 
 [FeaturePcd]
   gUefiOvmfPkgTokenSpaceGuid.PcdSmmSmramRequire
diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLib.inf b/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLib.inf
index 284e5acc1177..b6d76e7e630f 100644
--- a/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLib.inf
+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLib.inf
@@ -48,7 +48,7 @@
   CpuLib
   DebugLib
   PcdLib
-  VmgExitLib
+  CcExitLib
 
 [FixedPcd]
   gUefiCpuPkgTokenSpaceGuid.PcdSevEsWorkAreaBase
diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/SnpPageStateChangeInternal.c b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/SnpPageStateChangeInternal.c
index d11aafae8472..7fa39e06a658 100644
--- a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/SnpPageStateChangeInternal.c
+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/SnpPageStateChangeInternal.c
@@ -13,7 +13,7 @@
 #include <Library/BaseMemoryLib.h>
 #include <Library/MemEncryptSevLib.h>
 #include <Library/DebugLib.h>
-#include <Library/VmgExitLib.h>
+#include <Library/CcExitLib.h>
 
 #include <Register/Amd/Ghcb.h>
 #include <Register/Amd/Msr.h>
@@ -193,9 +193,9 @@ PageStateChangeVmgExit (
   //
   while (Info->Header.CurrentEntry <= Info->Header.EndEntry) {
     Ghcb->SaveArea.SwScratch = (UINT64)Ghcb->SharedBuffer;
-    VmgSetOffsetValid (Ghcb, GhcbSwScratch);
+    CcExitLibVmgSetOffsetValid (Ghcb, GhcbSwScratch);
 
-    Status = VmgExit (Ghcb, SVM_EXIT_SNP_PAGE_STATE_CHANGE, 0, 0);
+    Status = CcExitLibVmgExit (Ghcb, SVM_EXIT_SNP_PAGE_STATE_CHANGE, 0, 0);
 
     //
     // The Page State Change VMGEXIT can pass the failure through the
@@ -251,7 +251,7 @@ InternalSetPageState (
     //
     // Initialize the GHCB
     //
-    VmgInit (Ghcb, &InterruptState);
+    CcExitLibVmgInit (Ghcb, &InterruptState);
 
     //
     // Build the page state structure
@@ -293,7 +293,7 @@ InternalSetPageState (
       PvalidateRange (Info, CurrentEntry, EndEntry, TRUE);
     }
 
-    VmgDone (Ghcb, InterruptState);
+    CcExitLibVmgDone (Ghcb, InterruptState);
 
     BaseAddress = NextAddress;
   }
diff --git a/OvmfPkg/Microvm/MicrovmX64.dsc b/OvmfPkg/Microvm/MicrovmX64.dsc
index 98da7a3c9138..994a02d30107 100644
--- a/OvmfPkg/Microvm/MicrovmX64.dsc
+++ b/OvmfPkg/Microvm/MicrovmX64.dsc
@@ -250,7 +250,6 @@
 [LibraryClasses.common]
   BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
   CcExitLib|OvmfPkg/Library/CcExitLib/CcExitLib.inf
-  VmgExitLib|OvmfPkg/Library/VmgExitLib/VmgExitLib.inf
   SerialPortLib|MdeModulePkg/Library/BaseSerialPortLib16550/BaseSerialPortLib16550.inf
   PlatformHookLib|MdeModulePkg/Library/BasePlatformHookLibNull/BasePlatformHookLibNull.inf
   FdtLib|EmbeddedPkg/Library/FdtLib/FdtLib.inf
@@ -279,7 +278,6 @@
   CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf
 !endif
   CcExitLib|OvmfPkg/Library/CcExitLib/SecCcExitLib.inf
-  VmgExitLib|OvmfPkg/Library/VmgExitLib/SecVmgExitLib.inf
   MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLib.inf
 
 [LibraryClasses.common.PEI_CORE]
diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc
index ae002b6c9f23..6f774baf90f5 100644
--- a/OvmfPkg/OvmfPkgIa32.dsc
+++ b/OvmfPkg/OvmfPkgIa32.dsc
@@ -257,7 +257,6 @@
 [LibraryClasses.common]
   BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
   CcExitLib|UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.inf
-  VmgExitLib|UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.inf
 
 [LibraryClasses.common.SEC]
   TimerLib|OvmfPkg/Library/AcpiTimerLib/BaseRomAcpiTimerLib.inf
@@ -985,7 +984,6 @@
   #
   OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FvbServicesSmm.inf {
     <LibraryClasses>
-    VmgExitLib|UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.inf
     CcExitLib|UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.inf
   }
   MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.inf
diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc
index 753486bf7798..c851764dec05 100644
--- a/OvmfPkg/OvmfPkgIa32X64.dsc
+++ b/OvmfPkg/OvmfPkgIa32X64.dsc
@@ -261,7 +261,6 @@
 [LibraryClasses.common]
   BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
   CcExitLib|UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.inf
-  VmgExitLib|UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.inf
   TdxLib|MdePkg/Library/TdxLib/TdxLib.inf
   TdxMailboxLib|OvmfPkg/Library/TdxMailboxLib/TdxMailboxLib.inf
 
@@ -1004,7 +1003,6 @@
   OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FvbServicesSmm.inf {
     <LibraryClasses>
     CcExitLib|UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.inf
-    VmgExitLib|UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.inf
   }
   MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.inf
   MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf {
diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc
index 61998d33dc78..63c3a47aea30 100644
--- a/OvmfPkg/OvmfPkgX64.dsc
+++ b/OvmfPkg/OvmfPkgX64.dsc
@@ -277,7 +277,6 @@
 [LibraryClasses.common]
   BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
   CcExitLib|OvmfPkg/Library/CcExitLib/CcExitLib.inf
-  VmgExitLib|OvmfPkg/Library/VmgExitLib/VmgExitLib.inf
   TdxLib|MdePkg/Library/TdxLib/TdxLib.inf
   TdxMailboxLib|OvmfPkg/Library/TdxMailboxLib/TdxMailboxLib.inf
 
@@ -304,7 +303,6 @@
   CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf
 !endif
   CcExitLib|OvmfPkg/Library/CcExitLib/SecCcExitLib.inf
-  VmgExitLib|OvmfPkg/Library/VmgExitLib/SecVmgExitLib.inf
   MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLib.inf
   CcProbeLib|OvmfPkg/Library/CcProbeLib/SecPeiCcProbeLib.inf
 
@@ -1075,7 +1073,6 @@
   OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FvbServicesSmm.inf {
     <LibraryClasses>
     CcExitLib|UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.inf
-    VmgExitLib|UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.inf
   }
   MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.inf
   MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf {
diff --git a/OvmfPkg/OvmfXen.dsc b/OvmfPkg/OvmfXen.dsc
index ce298bbce25c..8bb497088bd2 100644
--- a/OvmfPkg/OvmfXen.dsc
+++ b/OvmfPkg/OvmfXen.dsc
@@ -232,7 +232,6 @@
 [LibraryClasses.common]
   BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
   CcExitLib|UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.inf
-  VmgExitLib|UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.inf
   TdxLib|MdePkg/Library/TdxLib/TdxLib.inf
 
 [LibraryClasses.common.SEC]
diff --git a/OvmfPkg/PlatformPei/AmdSev.c b/OvmfPkg/PlatformPei/AmdSev.c
index 385562b44c4e..d16db053b012 100644
--- a/OvmfPkg/PlatformPei/AmdSev.c
+++ b/OvmfPkg/PlatformPei/AmdSev.c
@@ -19,7 +19,7 @@
 #include <PiPei.h>
 #include <Register/Amd/Msr.h>
 #include <Register/Intel/SmramSaveStateMap.h>
-#include <Library/VmgExitLib.h>
+#include <Library/CcExitLib.h>
 #include <ConfidentialComputingGuestAttr.h>
 
 #include "Platform.h"
@@ -50,7 +50,7 @@ AmdSevSnpInitialize (
   }
 
   //
-  // Query the hypervisor feature using the VmgExit and set the value in the
+  // Query the hypervisor feature using the CcExitLibVmgExit and set the value in the
   // hypervisor features PCD.
   //
   HvFeatures = GetHypervisorFeature ();
@@ -129,19 +129,19 @@ GetHypervisorFeature (
   //
   // Initialize the GHCB
   //
-  VmgInit (Ghcb, &InterruptState);
+  CcExitLibVmgInit (Ghcb, &InterruptState);
 
   //
   // Query the Hypervisor Features.
   //
-  Status = VmgExit (Ghcb, SVM_EXIT_HYPERVISOR_FEATURES, 0, 0);
+  Status = CcExitLibVmgExit (Ghcb, SVM_EXIT_HYPERVISOR_FEATURES, 0, 0);
   if ((Status != 0)) {
     SevEsProtocolFailure (GHCB_TERMINATE_GHCB_GENERAL);
   }
 
   Features = Ghcb->SaveArea.SwExitInfo2;
 
-  VmgDone (Ghcb, InterruptState);
+  CcExitLibVmgDone (Ghcb, InterruptState);
 
   return Features;
 }
diff --git a/OvmfPkg/PlatformPei/PlatformPei.inf b/OvmfPkg/PlatformPei/PlatformPei.inf
index 3cd83e6ec3e5..1fadadeb5565 100644
--- a/OvmfPkg/PlatformPei/PlatformPei.inf
+++ b/OvmfPkg/PlatformPei/PlatformPei.inf
@@ -63,7 +63,7 @@
   MtrrLib
   MemEncryptSevLib
   PcdLib
-  VmgExitLib
+  CcExitLib
   PlatformInitLib
 
 [Pcd]
diff --git a/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FvbServicesRuntimeDxe.inf b/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FvbServicesRuntimeDxe.inf
index 8bb2325157ea..f47170478900 100644
--- a/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FvbServicesRuntimeDxe.inf
+++ b/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FvbServicesRuntimeDxe.inf
@@ -53,7 +53,7 @@
   UefiBootServicesTableLib
   UefiDriverEntryPoint
   UefiRuntimeLib
-  VmgExitLib
+  CcExitLib
 
 [Guids]
   gEfiEventVirtualAddressChangeGuid   # ALWAYS_CONSUMED
diff --git a/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlashDxe.c b/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlashDxe.c
index 172d6a4267f8..2b3596637e16 100644
--- a/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlashDxe.c
+++ b/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlashDxe.c
@@ -11,7 +11,7 @@
 
 #include <Library/UefiRuntimeLib.h>
 #include <Library/MemEncryptSevLib.h>
-#include <Library/VmgExitLib.h>
+#include <Library/CcExitLib.h>
 #include <Register/Amd/Msr.h>
 
 #include "QemuFlash.h"
@@ -82,12 +82,12 @@ QemuFlashPtrWrite (
     // #VC exception. Instead, use the VMGEXIT MMIO write support directly
     // to perform the update.
     //
-    VmgInit (Ghcb, &InterruptState);
+    CcExitLibVmgInit (Ghcb, &InterruptState);
     Ghcb->SharedBuffer[0]    = Value;
     Ghcb->SaveArea.SwScratch = (UINT64)(UINTN)Ghcb->SharedBuffer;
-    VmgSetOffsetValid (Ghcb, GhcbSwScratch);
-    VmgExit (Ghcb, SVM_EXIT_MMIO_WRITE, PhysAddr, 1);
-    VmgDone (Ghcb, InterruptState);
+    CcExitLibVmgSetOffsetValid (Ghcb, GhcbSwScratch);
+    CcExitLibVmgExit (Ghcb, SVM_EXIT_MMIO_WRITE, PhysAddr, 1);
+    CcExitLibVmgDone (Ghcb, InterruptState);
   } else {
     *Ptr = Value;
   }
-- 
2.29.2.windows.2


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH V2 7/9] OvmfPkg: Delete VmgExitLib
  2022-11-03 23:19 [PATCH V2 0/9] Rename VmgExitLib to CcExitLib Min Xu
                   ` (5 preceding siblings ...)
  2022-11-03 23:19 ` [PATCH V2 6/9] OvmfPkg: " Min Xu
@ 2022-11-03 23:19 ` Min Xu
  2022-11-03 23:19 ` [PATCH V2 8/9] UefiCpuPkg: " Min Xu
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 13+ messages in thread
From: Min Xu @ 2022-11-03 23:19 UTC (permalink / raw)
  To: devel
  Cc: Min M Xu, Brijesh Singh, Erdem Aktas, Gerd Hoffmann,
	James Bottomley, Jiewen Yao, Tom Lendacky

From: Min M Xu <min.m.xu@intel.com>

BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=4123

Delete VmgExitLib because it is replaced by CcExitLib.

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>
Signed-off-by: Min Xu <min.m.xu@intel.com>
---
 .../VmgExitLib/PeiDxeVmgExitVcHandler.c       |  103 -
 OvmfPkg/Library/VmgExitLib/SecVmgExitLib.inf  |   48 -
 .../Library/VmgExitLib/SecVmgExitVcHandler.c  |  109 -
 OvmfPkg/Library/VmgExitLib/VmTdExitHandler.h  |   32 -
 .../Library/VmgExitLib/VmTdExitVeHandler.c    |  559 ----
 OvmfPkg/Library/VmgExitLib/VmgExitLib.c       |  238 --
 OvmfPkg/Library/VmgExitLib/VmgExitLib.inf     |   45 -
 OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c | 2356 -----------------
 OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.h |   53 -
 .../Library/VmgExitLib/X64/TdVmcallCpuid.nasm |  146 -
 10 files changed, 3689 deletions(-)
 delete mode 100644 OvmfPkg/Library/VmgExitLib/PeiDxeVmgExitVcHandler.c
 delete mode 100644 OvmfPkg/Library/VmgExitLib/SecVmgExitLib.inf
 delete mode 100644 OvmfPkg/Library/VmgExitLib/SecVmgExitVcHandler.c
 delete mode 100644 OvmfPkg/Library/VmgExitLib/VmTdExitHandler.h
 delete mode 100644 OvmfPkg/Library/VmgExitLib/VmTdExitVeHandler.c
 delete mode 100644 OvmfPkg/Library/VmgExitLib/VmgExitLib.c
 delete mode 100644 OvmfPkg/Library/VmgExitLib/VmgExitLib.inf
 delete mode 100644 OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c
 delete mode 100644 OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.h
 delete mode 100644 OvmfPkg/Library/VmgExitLib/X64/TdVmcallCpuid.nasm

diff --git a/OvmfPkg/Library/VmgExitLib/PeiDxeVmgExitVcHandler.c b/OvmfPkg/Library/VmgExitLib/PeiDxeVmgExitVcHandler.c
deleted file mode 100644
index e3d071583750..000000000000
--- a/OvmfPkg/Library/VmgExitLib/PeiDxeVmgExitVcHandler.c
+++ /dev/null
@@ -1,103 +0,0 @@
-/** @file
-  X64 #VC Exception Handler functon.
-
-  Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved.<BR>
-  SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#include <Base.h>
-#include <Uefi.h>
-#include <Library/BaseMemoryLib.h>
-#include <Library/MemEncryptSevLib.h>
-#include <Library/VmgExitLib.h>
-#include <Register/Amd/Msr.h>
-
-#include "VmgExitVcHandler.h"
-
-/**
-  Handle a #VC exception.
-
-  Performs the necessary processing to handle a #VC exception.
-
-  @param[in, out]  ExceptionType  Pointer to an EFI_EXCEPTION_TYPE to be set
-                                  as value to use on error.
-  @param[in, out]  SystemContext  Pointer to EFI_SYSTEM_CONTEXT
-
-  @retval  EFI_SUCCESS            Exception handled
-  @retval  EFI_UNSUPPORTED        #VC not supported, (new) exception value to
-                                  propagate provided
-  @retval  EFI_PROTOCOL_ERROR     #VC handling failed, (new) exception value to
-                                  propagate provided
-
-**/
-EFI_STATUS
-EFIAPI
-VmgExitHandleVc (
-  IN OUT EFI_EXCEPTION_TYPE  *ExceptionType,
-  IN OUT EFI_SYSTEM_CONTEXT  SystemContext
-  )
-{
-  MSR_SEV_ES_GHCB_REGISTER  Msr;
-  GHCB                      *Ghcb;
-  GHCB                      *GhcbBackup;
-  EFI_STATUS                VcRet;
-  BOOLEAN                   InterruptState;
-  SEV_ES_PER_CPU_DATA       *SevEsData;
-
-  InterruptState = GetInterruptState ();
-  if (InterruptState) {
-    DisableInterrupts ();
-  }
-
-  Msr.GhcbPhysicalAddress = AsmReadMsr64 (MSR_SEV_ES_GHCB);
-  ASSERT (Msr.GhcbInfo.Function == 0);
-  ASSERT (Msr.Ghcb != 0);
-
-  Ghcb       = Msr.Ghcb;
-  GhcbBackup = NULL;
-
-  SevEsData = (SEV_ES_PER_CPU_DATA *)(Ghcb + 1);
-  SevEsData->VcCount++;
-
-  //
-  // Check for maximum PEI/DXE #VC nesting.
-  //
-  if (SevEsData->VcCount > VMGEXIT_MAXIMUM_VC_COUNT) {
-    VmgExitIssueAssert (SevEsData);
-  } else if (SevEsData->VcCount > 1) {
-    //
-    // Nested #VC
-    //
-    if (SevEsData->GhcbBackupPages == NULL) {
-      VmgExitIssueAssert (SevEsData);
-    }
-
-    //
-    // Save the active GHCB to a backup page.
-    //   To access the correct backup page, increment the backup page pointer
-    //   based on the current VcCount.
-    //
-    GhcbBackup  = (GHCB *)SevEsData->GhcbBackupPages;
-    GhcbBackup += (SevEsData->VcCount - 2);
-
-    CopyMem (GhcbBackup, Ghcb, sizeof (*Ghcb));
-  }
-
-  VcRet = InternalVmgExitHandleVc (Ghcb, ExceptionType, SystemContext);
-
-  if (GhcbBackup != NULL) {
-    //
-    // Restore the active GHCB from the backup page.
-    //
-    CopyMem (Ghcb, GhcbBackup, sizeof (*Ghcb));
-  }
-
-  SevEsData->VcCount--;
-
-  if (InterruptState) {
-    EnableInterrupts ();
-  }
-
-  return VcRet;
-}
diff --git a/OvmfPkg/Library/VmgExitLib/SecVmgExitLib.inf b/OvmfPkg/Library/VmgExitLib/SecVmgExitLib.inf
deleted file mode 100644
index f9bd4974f6dc..000000000000
--- a/OvmfPkg/Library/VmgExitLib/SecVmgExitLib.inf
+++ /dev/null
@@ -1,48 +0,0 @@
-## @file
-#  VMGEXIT Support Library.
-#
-#  Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved.<BR>
-#  SPDX-License-Identifier: BSD-2-Clause-Patent
-#
-##
-
-[Defines]
-  INF_VERSION                    = 0x00010005
-  BASE_NAME                      = SecVmgExitLib
-  FILE_GUID                      = dafff819-f86c-4cff-a70e-83161e5bcf9a
-  MODULE_TYPE                    = BASE
-  VERSION_STRING                 = 1.0
-  LIBRARY_CLASS                  = VmgExitLib|SEC
-
-#
-# The following information is for reference only and not required by the build tools.
-#
-#  VALID_ARCHITECTURES           = X64
-#
-
-[Sources.common]
-  VmgExitLib.c
-  VmgExitVcHandler.c
-  VmgExitVcHandler.h
-  SecVmgExitVcHandler.c
-  VmTdExitVeHandler.c
-  X64/TdVmcallCpuid.nasm
-
-[Packages]
-  MdePkg/MdePkg.dec
-  OvmfPkg/OvmfPkg.dec
-  UefiCpuPkg/UefiCpuPkg.dec
-
-[LibraryClasses]
-  BaseLib
-  BaseMemoryLib
-  DebugLib
-  LocalApicLib
-  MemEncryptSevLib
-  PcdLib
-
-[FixedPcd]
-  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupBase
-  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupSize
-  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCpuidBase
-  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCpuidSize
diff --git a/OvmfPkg/Library/VmgExitLib/SecVmgExitVcHandler.c b/OvmfPkg/Library/VmgExitLib/SecVmgExitVcHandler.c
deleted file mode 100644
index fe8680f831d9..000000000000
--- a/OvmfPkg/Library/VmgExitLib/SecVmgExitVcHandler.c
+++ /dev/null
@@ -1,109 +0,0 @@
-/** @file
-  X64 #VC Exception Handler functon.
-
-  Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved.<BR>
-  SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#include <Base.h>
-#include <Uefi.h>
-#include <Library/BaseMemoryLib.h>
-#include <Library/MemEncryptSevLib.h>
-#include <Library/VmgExitLib.h>
-#include <Register/Amd/Msr.h>
-
-#include "VmgExitVcHandler.h"
-
-/**
-  Handle a #VC exception.
-
-  Performs the necessary processing to handle a #VC exception.
-
-  @param[in, out]  ExceptionType  Pointer to an EFI_EXCEPTION_TYPE to be set
-                                  as value to use on error.
-  @param[in, out]  SystemContext  Pointer to EFI_SYSTEM_CONTEXT
-
-  @retval  EFI_SUCCESS            Exception handled
-  @retval  EFI_UNSUPPORTED        #VC not supported, (new) exception value to
-                                  propagate provided
-  @retval  EFI_PROTOCOL_ERROR     #VC handling failed, (new) exception value to
-                                  propagate provided
-
-**/
-EFI_STATUS
-EFIAPI
-VmgExitHandleVc (
-  IN OUT EFI_EXCEPTION_TYPE  *ExceptionType,
-  IN OUT EFI_SYSTEM_CONTEXT  SystemContext
-  )
-{
-  MSR_SEV_ES_GHCB_REGISTER  Msr;
-  GHCB                      *Ghcb;
-  GHCB                      *GhcbBackup;
-  EFI_STATUS                VcRet;
-  BOOLEAN                   InterruptState;
-  SEV_ES_PER_CPU_DATA       *SevEsData;
-
-  InterruptState = GetInterruptState ();
-  if (InterruptState) {
-    DisableInterrupts ();
-  }
-
-  Msr.GhcbPhysicalAddress = AsmReadMsr64 (MSR_SEV_ES_GHCB);
-  ASSERT (Msr.GhcbInfo.Function == 0);
-  ASSERT (Msr.Ghcb != 0);
-
-  Ghcb       = Msr.Ghcb;
-  GhcbBackup = NULL;
-
-  SevEsData = (SEV_ES_PER_CPU_DATA *)(Ghcb + 1);
-  SevEsData->VcCount++;
-
-  //
-  // Check for maximum SEC #VC nesting.
-  //
-  if (SevEsData->VcCount > VMGEXIT_MAXIMUM_VC_COUNT) {
-    VmgExitIssueAssert (SevEsData);
-  } else if (SevEsData->VcCount > 1) {
-    UINTN  GhcbBackupSize;
-
-    //
-    // Be sure that the proper amount of pages are allocated
-    //
-    GhcbBackupSize = (VMGEXIT_MAXIMUM_VC_COUNT - 1) * sizeof (*Ghcb);
-    if (GhcbBackupSize > FixedPcdGet32 (PcdOvmfSecGhcbBackupSize)) {
-      //
-      // Not enough SEC backup pages allocated.
-      //
-      VmgExitIssueAssert (SevEsData);
-    }
-
-    //
-    // Save the active GHCB to a backup page.
-    //   To access the correct backup page, increment the backup page pointer
-    //   based on the current VcCount.
-    //
-    GhcbBackup  = (GHCB *)FixedPcdGet32 (PcdOvmfSecGhcbBackupBase);
-    GhcbBackup += (SevEsData->VcCount - 2);
-
-    CopyMem (GhcbBackup, Ghcb, sizeof (*Ghcb));
-  }
-
-  VcRet = InternalVmgExitHandleVc (Ghcb, ExceptionType, SystemContext);
-
-  if (GhcbBackup != NULL) {
-    //
-    // Restore the active GHCB from the backup page.
-    //
-    CopyMem (Ghcb, GhcbBackup, sizeof (*Ghcb));
-  }
-
-  SevEsData->VcCount--;
-
-  if (InterruptState) {
-    EnableInterrupts ();
-  }
-
-  return VcRet;
-}
diff --git a/OvmfPkg/Library/VmgExitLib/VmTdExitHandler.h b/OvmfPkg/Library/VmgExitLib/VmTdExitHandler.h
deleted file mode 100644
index 7eacd0872f46..000000000000
--- a/OvmfPkg/Library/VmgExitLib/VmTdExitHandler.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/** @file
-
-  Copyright (c) 2020 - 2021, Intel Corporation. All rights reserved.<BR>
-  SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#ifndef VMTD_EXIT_HANDLER_H_
-#define VMTD_EXIT_HANDLER_H_
-
-#include <Base.h>
-#include <Uefi.h>
-
-/**
-  This function enable the TD guest to request the VMM to emulate CPUID
-  operation, especially for non-architectural, CPUID leaves.
-
-  @param[in]  Eax        Main leaf of the CPUID
-  @param[in]  Ecx        Sub-leaf of the CPUID
-  @param[out] Results    Returned result of CPUID operation
-
-  @return EFI_SUCCESS
-**/
-EFI_STATUS
-EFIAPI
-TdVmCallCpuid (
-  IN UINT64  Eax,
-  IN UINT64  Ecx,
-  OUT VOID   *Results
-  );
-
-#endif
diff --git a/OvmfPkg/Library/VmgExitLib/VmTdExitVeHandler.c b/OvmfPkg/Library/VmgExitLib/VmTdExitVeHandler.c
deleted file mode 100644
index b73e877c093b..000000000000
--- a/OvmfPkg/Library/VmgExitLib/VmTdExitVeHandler.c
+++ /dev/null
@@ -1,559 +0,0 @@
-/** @file
-
-  Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
-
-  SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#include <Library/BaseLib.h>
-#include <Library/DebugLib.h>
-#include "VmTdExitHandler.h"
-#include <Library/VmgExitLib.h>
-#include <Library/BaseMemoryLib.h>
-#include <IndustryStandard/Tdx.h>
-#include <IndustryStandard/InstructionParsing.h>
-
-typedef union {
-  struct {
-    UINT32    Eax;
-    UINT32    Edx;
-  } Regs;
-  UINT64    Val;
-} MSR_DATA;
-
-typedef union {
-  UINT8    Val;
-  struct {
-    UINT8    B : 1;
-    UINT8    X : 1;
-    UINT8    R : 1;
-    UINT8    W : 1;
-  } Bits;
-} REX;
-
-typedef union {
-  UINT8    Val;
-  struct {
-    UINT8    Rm  : 3;
-    UINT8    Reg : 3;
-    UINT8    Mod : 2;
-  } Bits;
-} MODRM;
-
-typedef struct {
-  UINT64    Regs[4];
-} CPUID_DATA;
-
-/**
-  Handle an CPUID event.
-
-  Use the TDVMCALL instruction to handle cpuid #ve
-
-  @param[in, out] Regs             x64 processor context
-  @param[in]      Veinfo           VE Info
-
-  @retval 0                        Event handled successfully
-  @return                          New exception value to propagate
-**/
-STATIC
-UINT64
-EFIAPI
-CpuIdExit (
-  IN EFI_SYSTEM_CONTEXT_X64     *Regs,
-  IN TDCALL_VEINFO_RETURN_DATA  *Veinfo
-  )
-{
-  CPUID_DATA  CpuIdData;
-  UINT64      Status;
-
-  Status = TdVmCallCpuid (Regs->Rax, Regs->Rcx, &CpuIdData);
-
-  if (Status == 0) {
-    Regs->Rax = CpuIdData.Regs[0];
-    Regs->Rbx = CpuIdData.Regs[1];
-    Regs->Rcx = CpuIdData.Regs[2];
-    Regs->Rdx = CpuIdData.Regs[3];
-  }
-
-  return Status;
-}
-
-/**
-  Handle an IO event.
-
-  Use the TDVMCALL instruction to handle either an IO read or an IO write.
-
-  @param[in, out] Regs             x64 processor context
-  @param[in]      Veinfo           VE Info
-
-  @retval 0                        Event handled successfully
-  @return                          New exception value to propagate
-**/
-STATIC
-UINT64
-EFIAPI
-IoExit (
-  IN OUT EFI_SYSTEM_CONTEXT_X64  *Regs,
-  IN TDCALL_VEINFO_RETURN_DATA   *Veinfo
-  )
-{
-  BOOLEAN  Write;
-  UINTN    Size;
-  UINTN    Port;
-  UINT64   Val;
-  UINT64   RepCnt;
-  UINT64   Status;
-
-  Val   = 0;
-  Write = Veinfo->ExitQualification.Io.Direction ? FALSE : TRUE;
-  Size  = Veinfo->ExitQualification.Io.Size + 1;
-  Port  = Veinfo->ExitQualification.Io.Port;
-
-  if (Veinfo->ExitQualification.Io.String) {
-    //
-    // If REP is set, get rep-cnt from Rcx
-    //
-    RepCnt = Veinfo->ExitQualification.Io.Rep ? Regs->Rcx : 1;
-
-    while (RepCnt) {
-      Val = 0;
-      if (Write == TRUE) {
-        CopyMem (&Val, (VOID *)Regs->Rsi, Size);
-        Regs->Rsi += Size;
-      }
-
-      Status = TdVmCall (EXIT_REASON_IO_INSTRUCTION, Size, Write, Port, Val, (Write ? NULL : &Val));
-      if (Status != 0) {
-        break;
-      }
-
-      if (Write == FALSE) {
-        CopyMem ((VOID *)Regs->Rdi, &Val, Size);
-        Regs->Rdi += Size;
-      }
-
-      if (Veinfo->ExitQualification.Io.Rep) {
-        Regs->Rcx -= 1;
-      }
-
-      RepCnt -= 1;
-    }
-  } else {
-    if (Write == TRUE) {
-      CopyMem (&Val, (VOID *)&Regs->Rax, Size);
-    }
-
-    Status = TdVmCall (EXIT_REASON_IO_INSTRUCTION, Size, Write, Port, Val, (Write ? NULL : &Val));
-    if ((Status == 0) && (Write == FALSE)) {
-      CopyMem ((VOID *)&Regs->Rax, &Val, Size);
-    }
-  }
-
-  return Status;
-}
-
-/**
-  Handle an READ MSR event.
-
-  Use the TDVMCALL instruction to handle msr read
-
-  @param[in, out] Regs             x64 processor context
-  @param[in]      Veinfo           VE Info
-
-  @retval 0                        Event handled successfully
-  @return                          New exception value to propagate
-**/
-STATIC
-UINT64
-ReadMsrExit (
-  IN OUT EFI_SYSTEM_CONTEXT_X64  *Regs,
-  IN TDCALL_VEINFO_RETURN_DATA   *Veinfo
-  )
-{
-  MSR_DATA  Data;
-  UINT64    Status;
-
-  Status = TdVmCall (EXIT_REASON_MSR_READ, Regs->Rcx, 0, 0, 0, &Data);
-  if (Status == 0) {
-    Regs->Rax = Data.Regs.Eax;
-    Regs->Rdx = Data.Regs.Edx;
-  }
-
-  return Status;
-}
-
-/**
-  Handle an WRITE MSR event.
-
-  Use the TDVMCALL instruction to handle msr write
-
-  @param[in, out] Regs             x64 processor context
-  @param[in]      Veinfo           VE Info
-
-  @retval 0                        Event handled successfully
-  @return                          New exception value to propagate
-**/
-STATIC
-UINT64
-WriteMsrExit (
-  IN OUT EFI_SYSTEM_CONTEXT_X64  *Regs,
-  IN TDCALL_VEINFO_RETURN_DATA   *Veinfo
-  )
-{
-  UINT64    Status;
-  MSR_DATA  Data;
-
-  Data.Regs.Eax = (UINT32)Regs->Rax;
-  Data.Regs.Edx = (UINT32)Regs->Rdx;
-
-  Status =  TdVmCall (EXIT_REASON_MSR_WRITE, Regs->Rcx, Data.Val, 0, 0, NULL);
-
-  return Status;
-}
-
-STATIC
-VOID
-EFIAPI
-TdxDecodeInstruction (
-  IN UINT8  *Rip
-  )
-{
-  UINTN  i;
-
-  DEBUG ((DEBUG_INFO, "TDX: #TD[EPT] instruction (%p):", Rip));
-  for (i = 0; i < 15; i++) {
-    DEBUG ((DEBUG_INFO, "%02x:", Rip[i]));
-  }
-
-  DEBUG ((DEBUG_INFO, "\n"));
-}
-
-#define TDX_DECODER_BUG_ON(x)               \
-  if ((x)) {                                \
-    TdxDecodeInstruction(Rip);              \
-    TdVmCall(TDVMCALL_HALT, 0, 0, 0, 0, 0); \
-  }
-
-STATIC
-UINT64 *
-EFIAPI
-GetRegFromContext (
-  IN EFI_SYSTEM_CONTEXT_X64  *Regs,
-  IN UINTN                   RegIndex
-  )
-{
-  switch (RegIndex) {
-    case 0: return &Regs->Rax;
-      break;
-    case 1: return &Regs->Rcx;
-      break;
-    case 2: return &Regs->Rdx;
-      break;
-    case 3: return &Regs->Rbx;
-      break;
-    case 4: return &Regs->Rsp;
-      break;
-    case 5: return &Regs->Rbp;
-      break;
-    case 6: return &Regs->Rsi;
-      break;
-    case 7: return &Regs->Rdi;
-      break;
-    case 8: return &Regs->R8;
-      break;
-    case 9: return &Regs->R9;
-      break;
-    case 10: return &Regs->R10;
-      break;
-    case 11: return &Regs->R11;
-      break;
-    case 12: return &Regs->R12;
-      break;
-    case 13: return &Regs->R13;
-      break;
-    case 14: return &Regs->R14;
-      break;
-    case 15: return &Regs->R15;
-      break;
-  }
-
-  return NULL;
-}
-
-/**
-  Handle an MMIO event.
-
-  Use the TDVMCALL instruction to handle either an mmio read or an mmio write.
-
-  @param[in, out] Regs             x64 processor context
-  @param[in]      Veinfo           VE Info
-
-  @retval 0                        Event handled successfully
-  @return                          New exception value to propagate
-**/
-STATIC
-INTN
-EFIAPI
-MmioExit (
-  IN OUT EFI_SYSTEM_CONTEXT_X64  *Regs,
-  IN TDCALL_VEINFO_RETURN_DATA   *Veinfo
-  )
-{
-  UINT64   Status;
-  UINT32   MmioSize;
-  UINT32   RegSize;
-  UINT8    OpCode;
-  BOOLEAN  SeenRex;
-  UINT64   *Reg;
-  UINT8    *Rip;
-  UINT64   Val;
-  UINT32   OpSize;
-  MODRM    ModRm;
-  REX      Rex;
-
-  Rip     = (UINT8 *)Regs->Rip;
-  Val     = 0;
-  Rex.Val = 0;
-  SeenRex = FALSE;
-
-  //
-  // Default to 32bit transfer
-  //
-  OpSize = 4;
-
-  do {
-    OpCode = *Rip++;
-    if (OpCode == 0x66) {
-      OpSize = 2;
-    } else if ((OpCode == 0x64) || (OpCode == 0x65) || (OpCode == 0x67)) {
-      continue;
-    } else if ((OpCode >= 0x40) && (OpCode <= 0x4f)) {
-      SeenRex = TRUE;
-      Rex.Val = OpCode;
-    } else {
-      break;
-    }
-  } while (TRUE);
-
-  //
-  // We need to have at least 2 more bytes for this instruction
-  //
-  TDX_DECODER_BUG_ON (((UINT64)Rip - Regs->Rip) > 13);
-
-  OpCode = *Rip++;
-  //
-  // Two-byte opecode, get next byte
-  //
-  if (OpCode == 0x0F) {
-    OpCode = *Rip++;
-  }
-
-  switch (OpCode) {
-    case 0x88:
-    case 0x8A:
-    case 0xB6:
-      MmioSize = 1;
-      break;
-    case 0xB7:
-      MmioSize = 2;
-      break;
-    default:
-      MmioSize = Rex.Bits.W ? 8 : OpSize;
-      break;
-  }
-
-  /* Punt on AH/BH/CH/DH unless it shows up. */
-  ModRm.Val = *Rip++;
-  TDX_DECODER_BUG_ON (MmioSize == 1 && ModRm.Bits.Reg > 4 && !SeenRex && OpCode != 0xB6);
-  Reg = GetRegFromContext (Regs, ModRm.Bits.Reg | ((int)Rex.Bits.R << 3));
-  TDX_DECODER_BUG_ON (!Reg);
-
-  if (ModRm.Bits.Rm == 4) {
-    ++Rip; /* SIB byte */
-  }
-
-  if ((ModRm.Bits.Mod == 2) || ((ModRm.Bits.Mod == 0) && (ModRm.Bits.Rm == 5))) {
-    Rip += 4; /* DISP32 */
-  } else if (ModRm.Bits.Mod == 1) {
-    ++Rip;  /* DISP8 */
-  }
-
-  switch (OpCode) {
-    case 0x88:
-    case 0x89:
-      CopyMem ((void *)&Val, Reg, MmioSize);
-      Status = TdVmCall (TDVMCALL_MMIO, MmioSize, 1, Veinfo->GuestPA, Val, 0);
-      break;
-    case 0xC7:
-      CopyMem ((void *)&Val, Rip, OpSize);
-      Status = TdVmCall (TDVMCALL_MMIO, MmioSize, 1, Veinfo->GuestPA, Val, 0);
-      Rip   += OpSize;
-    default:
-      //
-      // 32-bit write registers are zero extended to the full register
-      // Hence 'MOVZX r[32/64], r/m16' is
-      // hardcoded to reg size 8, and the straight MOV case has a reg
-      // size of 8 in the 32-bit read case.
-      //
-      switch (OpCode) {
-        case 0xB6:
-          RegSize = Rex.Bits.W ? 8 : OpSize;
-          break;
-        case 0xB7:
-          RegSize =  8;
-          break;
-        default:
-          RegSize = MmioSize == 4 ? 8 : MmioSize;
-          break;
-      }
-
-      Status = TdVmCall (TDVMCALL_MMIO, MmioSize, 0, Veinfo->GuestPA, 0, &Val);
-      if (Status == 0) {
-        ZeroMem (Reg, RegSize);
-        CopyMem (Reg, (void *)&Val, MmioSize);
-      }
-  }
-
-  if (Status == 0) {
-    TDX_DECODER_BUG_ON (((UINT64)Rip - Regs->Rip) > 15);
-
-    //
-    // We change instruction length to reflect true size so handler can
-    // bump rip
-    //
-    Veinfo->ExitInstructionLength =  (UINT32)((UINT64)Rip - Regs->Rip);
-  }
-
-  return Status;
-}
-
-/**
-  Handle a #VE exception.
-
-  Performs the necessary processing to handle a #VE exception.
-
-  @param[in, out]  ExceptionType  Pointer to an EFI_EXCEPTION_TYPE to be set
-                                  as value to use on error.
-  @param[in, out]  SystemContext  Pointer to EFI_SYSTEM_CONTEXT
-
-  @retval  EFI_SUCCESS            Exception handled
-  @retval  EFI_UNSUPPORTED        #VE not supported, (new) exception value to
-                                  propagate provided
-  @retval  EFI_PROTOCOL_ERROR     #VE handling failed, (new) exception value to
-                                  propagate provided
-
-**/
-EFI_STATUS
-EFIAPI
-VmTdExitHandleVe (
-  IN OUT EFI_EXCEPTION_TYPE  *ExceptionType,
-  IN OUT EFI_SYSTEM_CONTEXT  SystemContext
-  )
-{
-  UINT64                  Status;
-  TD_RETURN_DATA          ReturnData;
-  EFI_SYSTEM_CONTEXT_X64  *Regs;
-
-  Regs   = SystemContext.SystemContextX64;
-  Status = TdCall (TDCALL_TDGETVEINFO, 0, 0, 0, &ReturnData);
-  ASSERT (Status == 0);
-  if (Status != 0) {
-    DEBUG ((DEBUG_ERROR, "#VE happened. TDGETVEINFO failed with Status = 0x%llx\n", Status));
-    TdVmCall (TDVMCALL_HALT, 0, 0, 0, 0, 0);
-  }
-
-  switch (ReturnData.VeInfo.ExitReason) {
-    case EXIT_REASON_CPUID:
-      Status = CpuIdExit (Regs, &ReturnData.VeInfo);
-      DEBUG ((
-        DEBUG_VERBOSE,
-        "CPUID #VE happened, ExitReasion is %d, ExitQualification = 0x%x.\n",
-        ReturnData.VeInfo.ExitReason,
-        ReturnData.VeInfo.ExitQualification.Val
-        ));
-      break;
-
-    case EXIT_REASON_HLT:
-      Status = TdVmCall (EXIT_REASON_HLT, 0, 0, 0, 0, 0);
-      break;
-
-    case EXIT_REASON_IO_INSTRUCTION:
-      Status = IoExit (Regs, &ReturnData.VeInfo);
-      DEBUG ((
-        DEBUG_VERBOSE,
-        "IO_Instruction #VE happened, ExitReasion is %d, ExitQualification = 0x%x.\n",
-        ReturnData.VeInfo.ExitReason,
-        ReturnData.VeInfo.ExitQualification.Val
-        ));
-      break;
-
-    case EXIT_REASON_MSR_READ:
-      Status = ReadMsrExit (Regs, &ReturnData.VeInfo);
-      DEBUG ((
-        DEBUG_VERBOSE,
-        "RDMSR #VE happened, ExitReasion is %d, ExitQualification = 0x%x. Regs->Rcx=0x%llx, Status = 0x%llx\n",
-        ReturnData.VeInfo.ExitReason,
-        ReturnData.VeInfo.ExitQualification.Val,
-        Regs->Rcx,
-        Status
-        ));
-      break;
-
-    case EXIT_REASON_MSR_WRITE:
-      Status = WriteMsrExit (Regs, &ReturnData.VeInfo);
-      DEBUG ((
-        DEBUG_VERBOSE,
-        "WRMSR #VE happened, ExitReasion is %d, ExitQualification = 0x%x. Regs->Rcx=0x%llx, Status = 0x%llx\n",
-        ReturnData.VeInfo.ExitReason,
-        ReturnData.VeInfo.ExitQualification.Val,
-        Regs->Rcx,
-        Status
-        ));
-      break;
-
-    case EXIT_REASON_EPT_VIOLATION:
-      Status = MmioExit (Regs, &ReturnData.VeInfo);
-      DEBUG ((
-        DEBUG_VERBOSE,
-        "MMIO #VE happened, ExitReasion is %d, ExitQualification = 0x%x.\n",
-        ReturnData.VeInfo.ExitReason,
-        ReturnData.VeInfo.ExitQualification.Val
-        ));
-      break;
-
-    case EXIT_REASON_VMCALL:
-    case EXIT_REASON_MWAIT_INSTRUCTION:
-    case EXIT_REASON_MONITOR_INSTRUCTION:
-    case EXIT_REASON_WBINVD:
-    case EXIT_REASON_RDPMC:
-      /* Handle as nops. */
-      break;
-
-    default:
-      DEBUG ((
-        DEBUG_ERROR,
-        "Unsupported #VE happened, ExitReason is %d, ExitQualification = 0x%x.\n",
-        ReturnData.VeInfo.ExitReason,
-        ReturnData.VeInfo.ExitQualification.Val
-        ));
-
-      ASSERT (FALSE);
-      CpuDeadLoop ();
-  }
-
-  if (Status) {
-    DEBUG ((
-      DEBUG_ERROR,
-      "#VE Error (0x%llx) returned from host, ExitReason is %d, ExitQualification = 0x%x.\n",
-      Status,
-      ReturnData.VeInfo.ExitReason,
-      ReturnData.VeInfo.ExitQualification.Val
-      ));
-
-    TdVmCall (TDVMCALL_HALT, 0, 0, 0, 0, 0);
-  }
-
-  SystemContext.SystemContextX64->Rip += ReturnData.VeInfo.ExitInstructionLength;
-  return EFI_SUCCESS;
-}
diff --git a/OvmfPkg/Library/VmgExitLib/VmgExitLib.c b/OvmfPkg/Library/VmgExitLib/VmgExitLib.c
deleted file mode 100644
index c20552187074..000000000000
--- a/OvmfPkg/Library/VmgExitLib/VmgExitLib.c
+++ /dev/null
@@ -1,238 +0,0 @@
-/** @file
-  VMGEXIT Support Library.
-
-  Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved.<BR>
-  SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#include <Base.h>
-#include <Uefi.h>
-#include <Library/BaseMemoryLib.h>
-#include <Library/VmgExitLib.h>
-#include <Register/Amd/Msr.h>
-
-/**
-  Check for VMGEXIT error
-
-  Check if the hypervisor has returned an error after completion of the VMGEXIT
-  by examining the SwExitInfo1 field of the GHCB.
-
-  @param[in]  Ghcb       A pointer to the GHCB
-
-  @retval  0             VMGEXIT succeeded.
-  @return                Exception number to be propagated, VMGEXIT processing
-                         did not succeed.
-
-**/
-STATIC
-UINT64
-VmgExitErrorCheck (
-  IN GHCB  *Ghcb
-  )
-{
-  GHCB_EVENT_INJECTION  Event;
-  GHCB_EXIT_INFO        ExitInfo;
-  UINT64                Status;
-
-  ExitInfo.Uint64 = Ghcb->SaveArea.SwExitInfo1;
-  ASSERT (
-    (ExitInfo.Elements.Lower32Bits == 0) ||
-    (ExitInfo.Elements.Lower32Bits == 1)
-    );
-
-  Status = 0;
-  if (ExitInfo.Elements.Lower32Bits == 0) {
-    return Status;
-  }
-
-  if (ExitInfo.Elements.Lower32Bits == 1) {
-    ASSERT (Ghcb->SaveArea.SwExitInfo2 != 0);
-
-    //
-    // Check that the return event is valid
-    //
-    Event.Uint64 = Ghcb->SaveArea.SwExitInfo2;
-    if (Event.Elements.Valid &&
-        (Event.Elements.Type == GHCB_EVENT_INJECTION_TYPE_EXCEPTION))
-    {
-      switch (Event.Elements.Vector) {
-        case GP_EXCEPTION:
-        case UD_EXCEPTION:
-          //
-          // Use returned event as return code
-          //
-          Status = Event.Uint64;
-      }
-    }
-  }
-
-  if (Status == 0) {
-    GHCB_EVENT_INJECTION  GpEvent;
-
-    GpEvent.Uint64          = 0;
-    GpEvent.Elements.Vector = GP_EXCEPTION;
-    GpEvent.Elements.Type   = GHCB_EVENT_INJECTION_TYPE_EXCEPTION;
-    GpEvent.Elements.Valid  = 1;
-
-    Status = GpEvent.Uint64;
-  }
-
-  return Status;
-}
-
-/**
-  Perform VMGEXIT.
-
-  Sets the necessary fields of the GHCB, invokes the VMGEXIT instruction and
-  then handles the return actions.
-
-  @param[in, out]  Ghcb       A pointer to the GHCB
-  @param[in]       ExitCode   VMGEXIT code to be assigned to the SwExitCode
-                              field of the GHCB.
-  @param[in]       ExitInfo1  VMGEXIT information to be assigned to the
-                              SwExitInfo1 field of the GHCB.
-  @param[in]       ExitInfo2  VMGEXIT information to be assigned to the
-                              SwExitInfo2 field of the GHCB.
-
-  @retval  0                  VMGEXIT succeeded.
-  @return                     Exception number to be propagated, VMGEXIT
-                              processing did not succeed.
-
-**/
-UINT64
-EFIAPI
-VmgExit (
-  IN OUT GHCB    *Ghcb,
-  IN     UINT64  ExitCode,
-  IN     UINT64  ExitInfo1,
-  IN     UINT64  ExitInfo2
-  )
-{
-  Ghcb->SaveArea.SwExitCode  = ExitCode;
-  Ghcb->SaveArea.SwExitInfo1 = ExitInfo1;
-  Ghcb->SaveArea.SwExitInfo2 = ExitInfo2;
-
-  VmgSetOffsetValid (Ghcb, GhcbSwExitCode);
-  VmgSetOffsetValid (Ghcb, GhcbSwExitInfo1);
-  VmgSetOffsetValid (Ghcb, GhcbSwExitInfo2);
-
-  //
-  // Guest memory is used for the guest-hypervisor communication, so fence
-  // the invocation of the VMGEXIT instruction to ensure GHCB accesses are
-  // synchronized properly.
-  //
-  MemoryFence ();
-  AsmVmgExit ();
-  MemoryFence ();
-
-  return VmgExitErrorCheck (Ghcb);
-}
-
-/**
-  Perform pre-VMGEXIT initialization/preparation.
-
-  Performs the necessary steps in preparation for invoking VMGEXIT. Must be
-  called before setting any fields within the GHCB.
-
-  @param[in, out]  Ghcb            A pointer to the GHCB
-  @param[in, out]  InterruptState  A pointer to hold the current interrupt
-                                   state, used for restoring in VmgDone ()
-
-**/
-VOID
-EFIAPI
-VmgInit (
-  IN OUT GHCB     *Ghcb,
-  IN OUT BOOLEAN  *InterruptState
-  )
-{
-  //
-  // Be sure that an interrupt can't cause a #VC while the GHCB is
-  // being used.
-  //
-  *InterruptState = GetInterruptState ();
-  if (*InterruptState) {
-    DisableInterrupts ();
-  }
-
-  SetMem (&Ghcb->SaveArea, sizeof (Ghcb->SaveArea), 0);
-}
-
-/**
-  Perform post-VMGEXIT cleanup.
-
-  Performs the necessary steps to cleanup after invoking VMGEXIT. Must be
-  called after obtaining needed fields within the GHCB.
-
-  @param[in, out]  Ghcb            A pointer to the GHCB
-  @param[in]       InterruptState  An indicator to conditionally (re)enable
-                                   interrupts
-
-**/
-VOID
-EFIAPI
-VmgDone (
-  IN OUT GHCB     *Ghcb,
-  IN     BOOLEAN  InterruptState
-  )
-{
-  if (InterruptState) {
-    EnableInterrupts ();
-  }
-}
-
-/**
-  Marks a field at the specified offset as valid in the GHCB.
-
-  The ValidBitmap area represents the areas of the GHCB that have been marked
-  valid. Set the bit in ValidBitmap for the input offset.
-
-  @param[in, out] Ghcb    Pointer to the Guest-Hypervisor Communication Block
-  @param[in]      Offset  Qword offset in the GHCB to mark valid
-
-**/
-VOID
-EFIAPI
-VmgSetOffsetValid (
-  IN OUT GHCB           *Ghcb,
-  IN     GHCB_REGISTER  Offset
-  )
-{
-  UINT32  OffsetIndex;
-  UINT32  OffsetBit;
-
-  OffsetIndex = Offset / 8;
-  OffsetBit   = Offset % 8;
-
-  Ghcb->SaveArea.ValidBitmap[OffsetIndex] |= (1 << OffsetBit);
-}
-
-/**
-  Checks if a specified offset is valid in the GHCB.
-
-  The ValidBitmap area represents the areas of the GHCB that have been marked
-  valid. Return whether the bit in the ValidBitmap is set for the input offset.
-
-  @param[in]  Ghcb            A pointer to the GHCB
-  @param[in]  Offset          Qword offset in the GHCB to mark valid
-
-  @retval TRUE                Offset is marked valid in the GHCB
-  @retval FALSE               Offset is not marked valid in the GHCB
-
-**/
-BOOLEAN
-EFIAPI
-VmgIsOffsetValid (
-  IN GHCB           *Ghcb,
-  IN GHCB_REGISTER  Offset
-  )
-{
-  UINT32  OffsetIndex;
-  UINT32  OffsetBit;
-
-  OffsetIndex = Offset / 8;
-  OffsetBit   = Offset % 8;
-
-  return ((Ghcb->SaveArea.ValidBitmap[OffsetIndex] & (1 << OffsetBit)) != 0);
-}
diff --git a/OvmfPkg/Library/VmgExitLib/VmgExitLib.inf b/OvmfPkg/Library/VmgExitLib/VmgExitLib.inf
deleted file mode 100644
index 255b0c1a2f7f..000000000000
--- a/OvmfPkg/Library/VmgExitLib/VmgExitLib.inf
+++ /dev/null
@@ -1,45 +0,0 @@
-## @file
-#  VMGEXIT Support Library.
-#
-#  Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved.<BR>
-#  SPDX-License-Identifier: BSD-2-Clause-Patent
-#
-##
-
-[Defines]
-  INF_VERSION                    = 0x00010005
-  BASE_NAME                      = VmgExitLib
-  FILE_GUID                      = 0e923c25-13cd-430b-8714-ffe85652a97b
-  MODULE_TYPE                    = BASE
-  VERSION_STRING                 = 1.0
-  LIBRARY_CLASS                  = VmgExitLib|PEIM DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER UEFI_DRIVER
-
-#
-# The following information is for reference only and not required by the build tools.
-#
-#  VALID_ARCHITECTURES           = X64
-#
-
-[Sources.common]
-  VmgExitLib.c
-  VmgExitVcHandler.c
-  VmgExitVcHandler.h
-  PeiDxeVmgExitVcHandler.c
-  VmTdExitVeHandler.c
-  X64/TdVmcallCpuid.nasm
-
-[Packages]
-  MdePkg/MdePkg.dec
-  OvmfPkg/OvmfPkg.dec
-  UefiCpuPkg/UefiCpuPkg.dec
-
-[LibraryClasses]
-  BaseLib
-  BaseMemoryLib
-  DebugLib
-  LocalApicLib
-  MemEncryptSevLib
-
-[Pcd]
-  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCpuidBase
-  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCpuidSize
diff --git a/OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c b/OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c
deleted file mode 100644
index a4393dffbd63..000000000000
--- a/OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c
+++ /dev/null
@@ -1,2356 +0,0 @@
-/** @file
-  X64 #VC Exception Handler functon.
-
-  Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved.<BR>
-  SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#include <Base.h>
-#include <Uefi.h>
-#include <Library/BaseMemoryLib.h>
-#include <Library/LocalApicLib.h>
-#include <Library/MemEncryptSevLib.h>
-#include <Library/VmgExitLib.h>
-#include <Register/Amd/Msr.h>
-#include <Register/Intel/Cpuid.h>
-#include <IndustryStandard/InstructionParsing.h>
-
-#include "VmgExitVcHandler.h"
-// #include <Library/MemEncryptSevLib.h>
-
-//
-// Instruction execution mode definition
-//
-typedef enum {
-  LongMode64Bit = 0,
-  LongModeCompat32Bit,
-  LongModeCompat16Bit,
-} SEV_ES_INSTRUCTION_MODE;
-
-//
-// Instruction size definition (for operand and address)
-//
-typedef enum {
-  Size8Bits = 0,
-  Size16Bits,
-  Size32Bits,
-  Size64Bits,
-} SEV_ES_INSTRUCTION_SIZE;
-
-//
-// Intruction segment definition
-//
-typedef enum {
-  SegmentEs = 0,
-  SegmentCs,
-  SegmentSs,
-  SegmentDs,
-  SegmentFs,
-  SegmentGs,
-} SEV_ES_INSTRUCTION_SEGMENT;
-
-//
-// Instruction rep function definition
-//
-typedef enum {
-  RepNone = 0,
-  RepZ,
-  RepNZ,
-} SEV_ES_INSTRUCTION_REP;
-
-typedef struct {
-  UINT8    Rm;
-  UINT8    Reg;
-  UINT8    Mod;
-} SEV_ES_INSTRUCTION_MODRM_EXT;
-
-typedef struct {
-  UINT8    Base;
-  UINT8    Index;
-  UINT8    Scale;
-} SEV_ES_INSTRUCTION_SIB_EXT;
-
-//
-// Instruction opcode definition
-//
-typedef struct {
-  SEV_ES_INSTRUCTION_MODRM_EXT    ModRm;
-
-  SEV_ES_INSTRUCTION_SIB_EXT      Sib;
-
-  UINTN                           RegData;
-  UINTN                           RmData;
-} SEV_ES_INSTRUCTION_OPCODE_EXT;
-
-//
-// Instruction parsing context definition
-//
-typedef struct {
-  GHCB                             *Ghcb;
-
-  SEV_ES_INSTRUCTION_MODE          Mode;
-  SEV_ES_INSTRUCTION_SIZE          DataSize;
-  SEV_ES_INSTRUCTION_SIZE          AddrSize;
-  BOOLEAN                          SegmentSpecified;
-  SEV_ES_INSTRUCTION_SEGMENT       Segment;
-  SEV_ES_INSTRUCTION_REP           RepMode;
-
-  UINT8                            *Begin;
-  UINT8                            *End;
-
-  UINT8                            *Prefixes;
-  UINT8                            *OpCodes;
-  UINT8                            *Displacement;
-  UINT8                            *Immediate;
-
-  INSTRUCTION_REX_PREFIX           RexPrefix;
-
-  BOOLEAN                          ModRmPresent;
-  INSTRUCTION_MODRM                ModRm;
-
-  BOOLEAN                          SibPresent;
-  INSTRUCTION_SIB                  Sib;
-
-  UINTN                            PrefixSize;
-  UINTN                            OpCodeSize;
-  UINTN                            DisplacementSize;
-  UINTN                            ImmediateSize;
-
-  SEV_ES_INSTRUCTION_OPCODE_EXT    Ext;
-} SEV_ES_INSTRUCTION_DATA;
-
-//
-// Non-automatic Exit function prototype
-//
-typedef
-UINT64
-(*NAE_EXIT) (
-  GHCB                     *Ghcb,
-  EFI_SYSTEM_CONTEXT_X64   *Regs,
-  SEV_ES_INSTRUCTION_DATA  *InstructionData
-  );
-
-//
-// SEV-SNP Cpuid table entry/function
-//
-typedef PACKED struct {
-  UINT32    EaxIn;
-  UINT32    EcxIn;
-  UINT64    Unused;
-  UINT64    Unused2;
-  UINT32    Eax;
-  UINT32    Ebx;
-  UINT32    Ecx;
-  UINT32    Edx;
-  UINT64    Reserved;
-} SEV_SNP_CPUID_FUNCTION;
-
-//
-// SEV-SNP Cpuid page format
-//
-typedef PACKED struct {
-  UINT32                    Count;
-  UINT32                    Reserved1;
-  UINT64                    Reserved2;
-  SEV_SNP_CPUID_FUNCTION    function[0];
-} SEV_SNP_CPUID_INFO;
-
-/**
-  Return a pointer to the contents of the specified register.
-
-  Based upon the input register, return a pointer to the registers contents
-  in the x86 processor context.
-
-  @param[in] Regs      x64 processor context
-  @param[in] Register  Register to obtain pointer for
-
-  @return              Pointer to the contents of the requested register
-
-**/
-STATIC
-UINT64 *
-GetRegisterPointer (
-  IN EFI_SYSTEM_CONTEXT_X64  *Regs,
-  IN UINT8                   Register
-  )
-{
-  UINT64  *Reg;
-
-  switch (Register) {
-    case 0:
-      Reg = &Regs->Rax;
-      break;
-    case 1:
-      Reg = &Regs->Rcx;
-      break;
-    case 2:
-      Reg = &Regs->Rdx;
-      break;
-    case 3:
-      Reg = &Regs->Rbx;
-      break;
-    case 4:
-      Reg = &Regs->Rsp;
-      break;
-    case 5:
-      Reg = &Regs->Rbp;
-      break;
-    case 6:
-      Reg = &Regs->Rsi;
-      break;
-    case 7:
-      Reg = &Regs->Rdi;
-      break;
-    case 8:
-      Reg = &Regs->R8;
-      break;
-    case 9:
-      Reg = &Regs->R9;
-      break;
-    case 10:
-      Reg = &Regs->R10;
-      break;
-    case 11:
-      Reg = &Regs->R11;
-      break;
-    case 12:
-      Reg = &Regs->R12;
-      break;
-    case 13:
-      Reg = &Regs->R13;
-      break;
-    case 14:
-      Reg = &Regs->R14;
-      break;
-    case 15:
-      Reg = &Regs->R15;
-      break;
-    default:
-      Reg = NULL;
-  }
-
-  ASSERT (Reg != NULL);
-
-  return Reg;
-}
-
-/**
-  Update the instruction parsing context for displacement bytes.
-
-  @param[in, out] InstructionData  Instruction parsing context
-  @param[in]      Size             The instruction displacement size
-
-**/
-STATIC
-VOID
-UpdateForDisplacement (
-  IN OUT SEV_ES_INSTRUCTION_DATA  *InstructionData,
-  IN     UINTN                    Size
-  )
-{
-  InstructionData->DisplacementSize = Size;
-  InstructionData->Immediate       += Size;
-  InstructionData->End             += Size;
-}
-
-/**
-  Determine if an instruction address if RIP relative.
-
-  Examine the instruction parsing context to determine if the address offset
-  is relative to the instruction pointer.
-
-  @param[in] InstructionData  Instruction parsing context
-
-  @retval TRUE                Instruction addressing is RIP relative
-  @retval FALSE               Instruction addressing is not RIP relative
-
-**/
-STATIC
-BOOLEAN
-IsRipRelative (
-  IN SEV_ES_INSTRUCTION_DATA  *InstructionData
-  )
-{
-  SEV_ES_INSTRUCTION_OPCODE_EXT  *Ext;
-
-  Ext = &InstructionData->Ext;
-
-  return ((InstructionData->Mode == LongMode64Bit) &&
-          (Ext->ModRm.Mod == 0) &&
-          (Ext->ModRm.Rm == 5)  &&
-          (InstructionData->SibPresent == FALSE));
-}
-
-/**
-  Return the effective address of a memory operand.
-
-  Examine the instruction parsing context to obtain the effective memory
-  address of a memory operand.
-
-  @param[in] Regs             x64 processor context
-  @param[in] InstructionData  Instruction parsing context
-
-  @return                     The memory operand effective address
-
-**/
-STATIC
-UINT64
-GetEffectiveMemoryAddress (
-  IN EFI_SYSTEM_CONTEXT_X64   *Regs,
-  IN SEV_ES_INSTRUCTION_DATA  *InstructionData
-  )
-{
-  SEV_ES_INSTRUCTION_OPCODE_EXT  *Ext;
-  UINT64                         EffectiveAddress;
-
-  Ext              = &InstructionData->Ext;
-  EffectiveAddress = 0;
-
-  if (IsRipRelative (InstructionData)) {
-    //
-    // RIP-relative displacement is a 32-bit signed value
-    //
-    INT32  RipRelative;
-
-    RipRelative = *(INT32 *)InstructionData->Displacement;
-
-    UpdateForDisplacement (InstructionData, 4);
-
-    //
-    // Negative displacement is handled by standard UINT64 wrap-around.
-    //
-    return Regs->Rip + (UINT64)RipRelative;
-  }
-
-  switch (Ext->ModRm.Mod) {
-    case 1:
-      UpdateForDisplacement (InstructionData, 1);
-      EffectiveAddress += (UINT64)(*(INT8 *)(InstructionData->Displacement));
-      break;
-    case 2:
-      switch (InstructionData->AddrSize) {
-        case Size16Bits:
-          UpdateForDisplacement (InstructionData, 2);
-          EffectiveAddress += (UINT64)(*(INT16 *)(InstructionData->Displacement));
-          break;
-        default:
-          UpdateForDisplacement (InstructionData, 4);
-          EffectiveAddress += (UINT64)(*(INT32 *)(InstructionData->Displacement));
-          break;
-      }
-
-      break;
-  }
-
-  if (InstructionData->SibPresent) {
-    INT64  Displacement;
-
-    if (Ext->Sib.Index != 4) {
-      CopyMem (
-        &Displacement,
-        GetRegisterPointer (Regs, Ext->Sib.Index),
-        sizeof (Displacement)
-        );
-      Displacement *= (INT64)(1 << Ext->Sib.Scale);
-
-      //
-      // Negative displacement is handled by standard UINT64 wrap-around.
-      //
-      EffectiveAddress += (UINT64)Displacement;
-    }
-
-    if ((Ext->Sib.Base != 5) || Ext->ModRm.Mod) {
-      EffectiveAddress += *GetRegisterPointer (Regs, Ext->Sib.Base);
-    } else {
-      UpdateForDisplacement (InstructionData, 4);
-      EffectiveAddress += (UINT64)(*(INT32 *)(InstructionData->Displacement));
-    }
-  } else {
-    EffectiveAddress += *GetRegisterPointer (Regs, Ext->ModRm.Rm);
-  }
-
-  return EffectiveAddress;
-}
-
-/**
-  Decode a ModRM byte.
-
-  Examine the instruction parsing context to decode a ModRM byte and the SIB
-  byte, if present.
-
-  @param[in]      Regs             x64 processor context
-  @param[in, out] InstructionData  Instruction parsing context
-
-**/
-STATIC
-VOID
-DecodeModRm (
-  IN     EFI_SYSTEM_CONTEXT_X64   *Regs,
-  IN OUT SEV_ES_INSTRUCTION_DATA  *InstructionData
-  )
-{
-  SEV_ES_INSTRUCTION_OPCODE_EXT  *Ext;
-  INSTRUCTION_REX_PREFIX         *RexPrefix;
-  INSTRUCTION_MODRM              *ModRm;
-  INSTRUCTION_SIB                *Sib;
-
-  RexPrefix = &InstructionData->RexPrefix;
-  Ext       = &InstructionData->Ext;
-  ModRm     = &InstructionData->ModRm;
-  Sib       = &InstructionData->Sib;
-
-  InstructionData->ModRmPresent = TRUE;
-  ModRm->Uint8                  = *(InstructionData->End);
-
-  InstructionData->Displacement++;
-  InstructionData->Immediate++;
-  InstructionData->End++;
-
-  Ext->ModRm.Mod = ModRm->Bits.Mod;
-  Ext->ModRm.Reg = (RexPrefix->Bits.BitR << 3) | ModRm->Bits.Reg;
-  Ext->ModRm.Rm  = (RexPrefix->Bits.BitB << 3) | ModRm->Bits.Rm;
-
-  Ext->RegData = *GetRegisterPointer (Regs, Ext->ModRm.Reg);
-
-  if (Ext->ModRm.Mod == 3) {
-    Ext->RmData = *GetRegisterPointer (Regs, Ext->ModRm.Rm);
-  } else {
-    if (ModRm->Bits.Rm == 4) {
-      InstructionData->SibPresent = TRUE;
-      Sib->Uint8                  = *(InstructionData->End);
-
-      InstructionData->Displacement++;
-      InstructionData->Immediate++;
-      InstructionData->End++;
-
-      Ext->Sib.Scale = Sib->Bits.Scale;
-      Ext->Sib.Index = (RexPrefix->Bits.BitX << 3) | Sib->Bits.Index;
-      Ext->Sib.Base  = (RexPrefix->Bits.BitB << 3) | Sib->Bits.Base;
-    }
-
-    Ext->RmData = GetEffectiveMemoryAddress (Regs, InstructionData);
-  }
-}
-
-/**
-  Decode instruction prefixes.
-
-  Parse the instruction data to track the instruction prefixes that have
-  been used.
-
-  @param[in]      Regs             x64 processor context
-  @param[in, out] InstructionData  Instruction parsing context
-
-**/
-STATIC
-VOID
-DecodePrefixes (
-  IN     EFI_SYSTEM_CONTEXT_X64   *Regs,
-  IN OUT SEV_ES_INSTRUCTION_DATA  *InstructionData
-  )
-{
-  SEV_ES_INSTRUCTION_MODE  Mode;
-  SEV_ES_INSTRUCTION_SIZE  ModeDataSize;
-  SEV_ES_INSTRUCTION_SIZE  ModeAddrSize;
-  UINT8                    *Byte;
-
-  //
-  // Always in 64-bit mode
-  //
-  Mode         = LongMode64Bit;
-  ModeDataSize = Size32Bits;
-  ModeAddrSize = Size64Bits;
-
-  InstructionData->Mode     = Mode;
-  InstructionData->DataSize = ModeDataSize;
-  InstructionData->AddrSize = ModeAddrSize;
-
-  InstructionData->Prefixes = InstructionData->Begin;
-
-  Byte = InstructionData->Prefixes;
-  for ( ; ; Byte++, InstructionData->PrefixSize++) {
-    //
-    // Check the 0x40 to 0x4F range using an if statement here since some
-    // compilers don't like the "case 0x40 ... 0x4F:" syntax. This avoids
-    // 16 case statements below.
-    //
-    if ((*Byte >= REX_PREFIX_START) && (*Byte <= REX_PREFIX_STOP)) {
-      InstructionData->RexPrefix.Uint8 = *Byte;
-      if ((*Byte & REX_64BIT_OPERAND_SIZE_MASK) != 0) {
-        InstructionData->DataSize = Size64Bits;
-      }
-
-      continue;
-    }
-
-    switch (*Byte) {
-      case OVERRIDE_SEGMENT_CS:
-      case OVERRIDE_SEGMENT_DS:
-      case OVERRIDE_SEGMENT_ES:
-      case OVERRIDE_SEGMENT_SS:
-        if (Mode != LongMode64Bit) {
-          InstructionData->SegmentSpecified = TRUE;
-          InstructionData->Segment          = (*Byte >> 3) & 3;
-        }
-
-        break;
-
-      case OVERRIDE_SEGMENT_FS:
-      case OVERRIDE_SEGMENT_GS:
-        InstructionData->SegmentSpecified = TRUE;
-        InstructionData->Segment          = *Byte & 7;
-        break;
-
-      case OVERRIDE_OPERAND_SIZE:
-        if (InstructionData->RexPrefix.Uint8 == 0) {
-          InstructionData->DataSize =
-            (Mode == LongMode64Bit)       ? Size16Bits :
-            (Mode == LongModeCompat32Bit) ? Size16Bits :
-            (Mode == LongModeCompat16Bit) ? Size32Bits : 0;
-        }
-
-        break;
-
-      case OVERRIDE_ADDRESS_SIZE:
-        InstructionData->AddrSize =
-          (Mode == LongMode64Bit)       ? Size32Bits :
-          (Mode == LongModeCompat32Bit) ? Size16Bits :
-          (Mode == LongModeCompat16Bit) ? Size32Bits : 0;
-        break;
-
-      case LOCK_PREFIX:
-        break;
-
-      case REPZ_PREFIX:
-        InstructionData->RepMode = RepZ;
-        break;
-
-      case REPNZ_PREFIX:
-        InstructionData->RepMode = RepNZ;
-        break;
-
-      default:
-        InstructionData->OpCodes    = Byte;
-        InstructionData->OpCodeSize = (*Byte == TWO_BYTE_OPCODE_ESCAPE) ? 2 : 1;
-
-        InstructionData->End          = Byte + InstructionData->OpCodeSize;
-        InstructionData->Displacement = InstructionData->End;
-        InstructionData->Immediate    = InstructionData->End;
-        return;
-    }
-  }
-}
-
-/**
-  Determine instruction length
-
-  Return the total length of the parsed instruction.
-
-  @param[in] InstructionData  Instruction parsing context
-
-  @return                     Length of parsed instruction
-
-**/
-STATIC
-UINT64
-InstructionLength (
-  IN SEV_ES_INSTRUCTION_DATA  *InstructionData
-  )
-{
-  return (UINT64)(InstructionData->End - InstructionData->Begin);
-}
-
-/**
-  Initialize the instruction parsing context.
-
-  Initialize the instruction parsing context, which includes decoding the
-  instruction prefixes.
-
-  @param[in, out] InstructionData  Instruction parsing context
-  @param[in]      Ghcb             Pointer to the Guest-Hypervisor Communication
-                                   Block
-  @param[in]      Regs             x64 processor context
-
-**/
-STATIC
-VOID
-InitInstructionData (
-  IN OUT SEV_ES_INSTRUCTION_DATA  *InstructionData,
-  IN     GHCB                     *Ghcb,
-  IN     EFI_SYSTEM_CONTEXT_X64   *Regs
-  )
-{
-  SetMem (InstructionData, sizeof (*InstructionData), 0);
-  InstructionData->Ghcb  = Ghcb;
-  InstructionData->Begin = (UINT8 *)Regs->Rip;
-  InstructionData->End   = (UINT8 *)Regs->Rip;
-
-  DecodePrefixes (Regs, InstructionData);
-}
-
-/**
-  Report an unsupported event to the hypervisor
-
-  Use the VMGEXIT support to report an unsupported event to the hypervisor.
-
-  @param[in] Ghcb             Pointer to the Guest-Hypervisor Communication
-                              Block
-  @param[in] Regs             x64 processor context
-  @param[in] InstructionData  Instruction parsing context
-
-  @return                     New exception value to propagate
-
-**/
-STATIC
-UINT64
-UnsupportedExit (
-  IN GHCB                     *Ghcb,
-  IN EFI_SYSTEM_CONTEXT_X64   *Regs,
-  IN SEV_ES_INSTRUCTION_DATA  *InstructionData
-  )
-{
-  UINT64  Status;
-
-  Status = VmgExit (Ghcb, SVM_EXIT_UNSUPPORTED, Regs->ExceptionData, 0);
-  if (Status == 0) {
-    GHCB_EVENT_INJECTION  Event;
-
-    Event.Uint64          = 0;
-    Event.Elements.Vector = GP_EXCEPTION;
-    Event.Elements.Type   = GHCB_EVENT_INJECTION_TYPE_EXCEPTION;
-    Event.Elements.Valid  = 1;
-
-    Status = Event.Uint64;
-  }
-
-  return Status;
-}
-
-/**
-  Validate that the MMIO memory access is not to encrypted memory.
-
-  Examine the pagetable entry for the memory specified. MMIO should not be
-  performed against encrypted memory. MMIO to the APIC page is always allowed.
-
-  @param[in] Ghcb           Pointer to the Guest-Hypervisor Communication Block
-  @param[in] MemoryAddress  Memory address to validate
-  @param[in] MemoryLength   Memory length to validate
-
-  @retval 0          Memory is not encrypted
-  @return            New exception value to propogate
-
-**/
-STATIC
-UINT64
-ValidateMmioMemory (
-  IN GHCB   *Ghcb,
-  IN UINTN  MemoryAddress,
-  IN UINTN  MemoryLength
-  )
-{
-  MEM_ENCRYPT_SEV_ADDRESS_RANGE_STATE  State;
-  GHCB_EVENT_INJECTION                 GpEvent;
-  UINTN                                Address;
-
-  //
-  // Allow APIC accesses (which will have the encryption bit set during
-  // SEC and PEI phases).
-  //
-  Address = MemoryAddress & ~(SIZE_4KB - 1);
-  if (Address == GetLocalApicBaseAddress ()) {
-    return 0;
-  }
-
-  State = MemEncryptSevGetAddressRangeState (
-            0,
-            MemoryAddress,
-            MemoryLength
-            );
-  if (State == MemEncryptSevAddressRangeUnencrypted) {
-    return 0;
-  }
-
-  //
-  // Any state other than unencrypted is an error, issue a #GP.
-  //
-  DEBUG ((
-    DEBUG_ERROR,
-    "MMIO using encrypted memory: %lx\n",
-    (UINT64)MemoryAddress
-    ));
-  GpEvent.Uint64          = 0;
-  GpEvent.Elements.Vector = GP_EXCEPTION;
-  GpEvent.Elements.Type   = GHCB_EVENT_INJECTION_TYPE_EXCEPTION;
-  GpEvent.Elements.Valid  = 1;
-
-  return GpEvent.Uint64;
-}
-
-/**
-  Handle an MMIO event.
-
-  Use the VMGEXIT instruction to handle either an MMIO read or an MMIO write.
-
-  @param[in, out] Ghcb             Pointer to the Guest-Hypervisor Communication
-                                   Block
-  @param[in, out] Regs             x64 processor context
-  @param[in, out] InstructionData  Instruction parsing context
-
-  @retval 0                        Event handled successfully
-  @return                          New exception value to propagate
-
-**/
-STATIC
-UINT64
-MmioExit (
-  IN OUT GHCB                     *Ghcb,
-  IN OUT EFI_SYSTEM_CONTEXT_X64   *Regs,
-  IN OUT SEV_ES_INSTRUCTION_DATA  *InstructionData
-  )
-{
-  UINT64  ExitInfo1, ExitInfo2, Status;
-  UINTN   Bytes;
-  UINT64  *Register;
-  UINT8   OpCode, SignByte;
-  UINTN   Address;
-
-  Bytes = 0;
-
-  OpCode = *(InstructionData->OpCodes);
-  if (OpCode == TWO_BYTE_OPCODE_ESCAPE) {
-    OpCode = *(InstructionData->OpCodes + 1);
-  }
-
-  switch (OpCode) {
-    //
-    // MMIO write (MOV reg/memX, regX)
-    //
-    case 0x88:
-      Bytes = 1;
-    //
-    // fall through
-    //
-    case 0x89:
-      DecodeModRm (Regs, InstructionData);
-      Bytes = ((Bytes != 0) ? Bytes :
-               (InstructionData->DataSize == Size16Bits) ? 2 :
-               (InstructionData->DataSize == Size32Bits) ? 4 :
-               (InstructionData->DataSize == Size64Bits) ? 8 :
-               0);
-
-      if (InstructionData->Ext.ModRm.Mod == 3) {
-        //
-        // NPF on two register operands???
-        //
-        return UnsupportedExit (Ghcb, Regs, InstructionData);
-      }
-
-      Status = ValidateMmioMemory (Ghcb, InstructionData->Ext.RmData, Bytes);
-      if (Status != 0) {
-        return Status;
-      }
-
-      ExitInfo1 = InstructionData->Ext.RmData;
-      ExitInfo2 = Bytes;
-      CopyMem (Ghcb->SharedBuffer, &InstructionData->Ext.RegData, Bytes);
-
-      Ghcb->SaveArea.SwScratch = (UINT64)Ghcb->SharedBuffer;
-      VmgSetOffsetValid (Ghcb, GhcbSwScratch);
-      Status = VmgExit (Ghcb, SVM_EXIT_MMIO_WRITE, ExitInfo1, ExitInfo2);
-      if (Status != 0) {
-        return Status;
-      }
-
-      break;
-
-    //
-    // MMIO write (MOV moffsetX, aX)
-    //
-    case 0xA2:
-      Bytes = 1;
-    //
-    // fall through
-    //
-    case 0xA3:
-      Bytes = ((Bytes != 0) ? Bytes :
-               (InstructionData->DataSize == Size16Bits) ? 2 :
-               (InstructionData->DataSize == Size32Bits) ? 4 :
-               (InstructionData->DataSize == Size64Bits) ? 8 :
-               0);
-
-      InstructionData->ImmediateSize = (UINTN)(1 << InstructionData->AddrSize);
-      InstructionData->End          += InstructionData->ImmediateSize;
-
-      //
-      // This code is X64 only, so a possible 8-byte copy to a UINTN is ok.
-      // Use a STATIC_ASSERT to be certain the code is being built as X64.
-      //
-      STATIC_ASSERT (
-        sizeof (UINTN) == sizeof (UINT64),
-        "sizeof (UINTN) != sizeof (UINT64), this file must be built as X64"
-        );
-
-      Address = 0;
-      CopyMem (
-        &Address,
-        InstructionData->Immediate,
-        InstructionData->ImmediateSize
-        );
-
-      Status = ValidateMmioMemory (Ghcb, Address, Bytes);
-      if (Status != 0) {
-        return Status;
-      }
-
-      ExitInfo1 = Address;
-      ExitInfo2 = Bytes;
-      CopyMem (Ghcb->SharedBuffer, &Regs->Rax, Bytes);
-
-      Ghcb->SaveArea.SwScratch = (UINT64)Ghcb->SharedBuffer;
-      VmgSetOffsetValid (Ghcb, GhcbSwScratch);
-      Status = VmgExit (Ghcb, SVM_EXIT_MMIO_WRITE, ExitInfo1, ExitInfo2);
-      if (Status != 0) {
-        return Status;
-      }
-
-      break;
-
-    //
-    // MMIO write (MOV reg/memX, immX)
-    //
-    case 0xC6:
-      Bytes = 1;
-    //
-    // fall through
-    //
-    case 0xC7:
-      DecodeModRm (Regs, InstructionData);
-      Bytes = ((Bytes != 0) ? Bytes :
-               (InstructionData->DataSize == Size16Bits) ? 2 :
-               (InstructionData->DataSize == Size32Bits) ? 4 :
-               0);
-
-      InstructionData->ImmediateSize = Bytes;
-      InstructionData->End          += Bytes;
-
-      Status = ValidateMmioMemory (Ghcb, InstructionData->Ext.RmData, Bytes);
-      if (Status != 0) {
-        return Status;
-      }
-
-      ExitInfo1 = InstructionData->Ext.RmData;
-      ExitInfo2 = Bytes;
-      CopyMem (Ghcb->SharedBuffer, InstructionData->Immediate, Bytes);
-
-      Ghcb->SaveArea.SwScratch = (UINT64)Ghcb->SharedBuffer;
-      VmgSetOffsetValid (Ghcb, GhcbSwScratch);
-      Status = VmgExit (Ghcb, SVM_EXIT_MMIO_WRITE, ExitInfo1, ExitInfo2);
-      if (Status != 0) {
-        return Status;
-      }
-
-      break;
-
-    //
-    // MMIO read (MOV regX, reg/memX)
-    //
-    case 0x8A:
-      Bytes = 1;
-    //
-    // fall through
-    //
-    case 0x8B:
-      DecodeModRm (Regs, InstructionData);
-      Bytes = ((Bytes != 0) ? Bytes :
-               (InstructionData->DataSize == Size16Bits) ? 2 :
-               (InstructionData->DataSize == Size32Bits) ? 4 :
-               (InstructionData->DataSize == Size64Bits) ? 8 :
-               0);
-      if (InstructionData->Ext.ModRm.Mod == 3) {
-        //
-        // NPF on two register operands???
-        //
-        return UnsupportedExit (Ghcb, Regs, InstructionData);
-      }
-
-      Status = ValidateMmioMemory (Ghcb, InstructionData->Ext.RmData, Bytes);
-      if (Status != 0) {
-        return Status;
-      }
-
-      ExitInfo1 = InstructionData->Ext.RmData;
-      ExitInfo2 = Bytes;
-
-      Ghcb->SaveArea.SwScratch = (UINT64)Ghcb->SharedBuffer;
-      VmgSetOffsetValid (Ghcb, GhcbSwScratch);
-      Status = VmgExit (Ghcb, SVM_EXIT_MMIO_READ, ExitInfo1, ExitInfo2);
-      if (Status != 0) {
-        return Status;
-      }
-
-      Register = GetRegisterPointer (Regs, InstructionData->Ext.ModRm.Reg);
-      if (Bytes == 4) {
-        //
-        // Zero-extend for 32-bit operation
-        //
-        *Register = 0;
-      }
-
-      CopyMem (Register, Ghcb->SharedBuffer, Bytes);
-      break;
-
-    //
-    // MMIO read (MOV aX, moffsetX)
-    //
-    case 0xA0:
-      Bytes = 1;
-    //
-    // fall through
-    //
-    case 0xA1:
-      Bytes = ((Bytes != 0) ? Bytes :
-               (InstructionData->DataSize == Size16Bits) ? 2 :
-               (InstructionData->DataSize == Size32Bits) ? 4 :
-               (InstructionData->DataSize == Size64Bits) ? 8 :
-               0);
-
-      InstructionData->ImmediateSize = (UINTN)(1 << InstructionData->AddrSize);
-      InstructionData->End          += InstructionData->ImmediateSize;
-
-      //
-      // This code is X64 only, so a possible 8-byte copy to a UINTN is ok.
-      // Use a STATIC_ASSERT to be certain the code is being built as X64.
-      //
-      STATIC_ASSERT (
-        sizeof (UINTN) == sizeof (UINT64),
-        "sizeof (UINTN) != sizeof (UINT64), this file must be built as X64"
-        );
-
-      Address = 0;
-      CopyMem (
-        &Address,
-        InstructionData->Immediate,
-        InstructionData->ImmediateSize
-        );
-
-      Status = ValidateMmioMemory (Ghcb, Address, Bytes);
-      if (Status != 0) {
-        return Status;
-      }
-
-      ExitInfo1 = Address;
-      ExitInfo2 = Bytes;
-
-      Ghcb->SaveArea.SwScratch = (UINT64)Ghcb->SharedBuffer;
-      VmgSetOffsetValid (Ghcb, GhcbSwScratch);
-      Status = VmgExit (Ghcb, SVM_EXIT_MMIO_READ, ExitInfo1, ExitInfo2);
-      if (Status != 0) {
-        return Status;
-      }
-
-      if (Bytes == 4) {
-        //
-        // Zero-extend for 32-bit operation
-        //
-        Regs->Rax = 0;
-      }
-
-      CopyMem (&Regs->Rax, Ghcb->SharedBuffer, Bytes);
-      break;
-
-    //
-    // MMIO read w/ zero-extension ((MOVZX regX, reg/memX)
-    //
-    case 0xB6:
-      Bytes = 1;
-    //
-    // fall through
-    //
-    case 0xB7:
-      DecodeModRm (Regs, InstructionData);
-      Bytes = (Bytes != 0) ? Bytes : 2;
-
-      Status = ValidateMmioMemory (Ghcb, InstructionData->Ext.RmData, Bytes);
-      if (Status != 0) {
-        return Status;
-      }
-
-      ExitInfo1 = InstructionData->Ext.RmData;
-      ExitInfo2 = Bytes;
-
-      Ghcb->SaveArea.SwScratch = (UINT64)Ghcb->SharedBuffer;
-      VmgSetOffsetValid (Ghcb, GhcbSwScratch);
-      Status = VmgExit (Ghcb, SVM_EXIT_MMIO_READ, ExitInfo1, ExitInfo2);
-      if (Status != 0) {
-        return Status;
-      }
-
-      Register = GetRegisterPointer (Regs, InstructionData->Ext.ModRm.Reg);
-      SetMem (Register, (UINTN)(1 << InstructionData->DataSize), 0);
-      CopyMem (Register, Ghcb->SharedBuffer, Bytes);
-      break;
-
-    //
-    // MMIO read w/ sign-extension (MOVSX regX, reg/memX)
-    //
-    case 0xBE:
-      Bytes = 1;
-    //
-    // fall through
-    //
-    case 0xBF:
-      DecodeModRm (Regs, InstructionData);
-      Bytes = (Bytes != 0) ? Bytes : 2;
-
-      Status = ValidateMmioMemory (Ghcb, InstructionData->Ext.RmData, Bytes);
-      if (Status != 0) {
-        return Status;
-      }
-
-      ExitInfo1 = InstructionData->Ext.RmData;
-      ExitInfo2 = Bytes;
-
-      Ghcb->SaveArea.SwScratch = (UINT64)Ghcb->SharedBuffer;
-      VmgSetOffsetValid (Ghcb, GhcbSwScratch);
-      Status = VmgExit (Ghcb, SVM_EXIT_MMIO_READ, ExitInfo1, ExitInfo2);
-      if (Status != 0) {
-        return Status;
-      }
-
-      if (Bytes == 1) {
-        UINT8  *Data;
-
-        Data     = (UINT8 *)Ghcb->SharedBuffer;
-        SignByte = ((*Data & BIT7) != 0) ? 0xFF : 0x00;
-      } else {
-        UINT16  *Data;
-
-        Data     = (UINT16 *)Ghcb->SharedBuffer;
-        SignByte = ((*Data & BIT15) != 0) ? 0xFF : 0x00;
-      }
-
-      Register = GetRegisterPointer (Regs, InstructionData->Ext.ModRm.Reg);
-      SetMem (Register, (UINTN)(1 << InstructionData->DataSize), SignByte);
-      CopyMem (Register, Ghcb->SharedBuffer, Bytes);
-      break;
-
-    default:
-      DEBUG ((DEBUG_ERROR, "Invalid MMIO opcode (%x)\n", OpCode));
-      Status = GP_EXCEPTION;
-      ASSERT (FALSE);
-  }
-
-  return Status;
-}
-
-/**
-  Handle a MWAIT event.
-
-  Use the VMGEXIT instruction to handle a MWAIT event.
-
-  @param[in, out] Ghcb             Pointer to the Guest-Hypervisor Communication
-                                   Block
-  @param[in, out] Regs             x64 processor context
-  @param[in]      InstructionData  Instruction parsing context
-
-  @retval 0                        Event handled successfully
-  @return                          New exception value to propagate
-
-**/
-STATIC
-UINT64
-MwaitExit (
-  IN OUT GHCB                     *Ghcb,
-  IN OUT EFI_SYSTEM_CONTEXT_X64   *Regs,
-  IN     SEV_ES_INSTRUCTION_DATA  *InstructionData
-  )
-{
-  DecodeModRm (Regs, InstructionData);
-
-  Ghcb->SaveArea.Rax = Regs->Rax;
-  VmgSetOffsetValid (Ghcb, GhcbRax);
-  Ghcb->SaveArea.Rcx = Regs->Rcx;
-  VmgSetOffsetValid (Ghcb, GhcbRcx);
-
-  return VmgExit (Ghcb, SVM_EXIT_MWAIT, 0, 0);
-}
-
-/**
-  Handle a MONITOR event.
-
-  Use the VMGEXIT instruction to handle a MONITOR event.
-
-  @param[in, out] Ghcb             Pointer to the Guest-Hypervisor Communication
-                                   Block
-  @param[in, out] Regs             x64 processor context
-  @param[in]      InstructionData  Instruction parsing context
-
-  @retval 0                        Event handled successfully
-  @return                          New exception value to propagate
-
-**/
-STATIC
-UINT64
-MonitorExit (
-  IN OUT GHCB                     *Ghcb,
-  IN OUT EFI_SYSTEM_CONTEXT_X64   *Regs,
-  IN     SEV_ES_INSTRUCTION_DATA  *InstructionData
-  )
-{
-  DecodeModRm (Regs, InstructionData);
-
-  Ghcb->SaveArea.Rax = Regs->Rax;  // Identity mapped, so VA = PA
-  VmgSetOffsetValid (Ghcb, GhcbRax);
-  Ghcb->SaveArea.Rcx = Regs->Rcx;
-  VmgSetOffsetValid (Ghcb, GhcbRcx);
-  Ghcb->SaveArea.Rdx = Regs->Rdx;
-  VmgSetOffsetValid (Ghcb, GhcbRdx);
-
-  return VmgExit (Ghcb, SVM_EXIT_MONITOR, 0, 0);
-}
-
-/**
-  Handle a WBINVD event.
-
-  Use the VMGEXIT instruction to handle a WBINVD event.
-
-  @param[in, out] Ghcb             Pointer to the Guest-Hypervisor Communication
-                                   Block
-  @param[in, out] Regs             x64 processor context
-  @param[in]      InstructionData  Instruction parsing context
-
-  @retval 0                        Event handled successfully
-  @return                          New exception value to propagate
-
-**/
-STATIC
-UINT64
-WbinvdExit (
-  IN OUT GHCB                     *Ghcb,
-  IN OUT EFI_SYSTEM_CONTEXT_X64   *Regs,
-  IN     SEV_ES_INSTRUCTION_DATA  *InstructionData
-  )
-{
-  return VmgExit (Ghcb, SVM_EXIT_WBINVD, 0, 0);
-}
-
-/**
-  Handle a RDTSCP event.
-
-  Use the VMGEXIT instruction to handle a RDTSCP event.
-
-  @param[in, out] Ghcb             Pointer to the Guest-Hypervisor Communication
-                                   Block
-  @param[in, out] Regs             x64 processor context
-  @param[in]      InstructionData  Instruction parsing context
-
-  @retval 0                        Event handled successfully
-  @return                          New exception value to propagate
-
-**/
-STATIC
-UINT64
-RdtscpExit (
-  IN OUT GHCB                     *Ghcb,
-  IN OUT EFI_SYSTEM_CONTEXT_X64   *Regs,
-  IN     SEV_ES_INSTRUCTION_DATA  *InstructionData
-  )
-{
-  UINT64  Status;
-
-  DecodeModRm (Regs, InstructionData);
-
-  Status = VmgExit (Ghcb, SVM_EXIT_RDTSCP, 0, 0);
-  if (Status != 0) {
-    return Status;
-  }
-
-  if (!VmgIsOffsetValid (Ghcb, GhcbRax) ||
-      !VmgIsOffsetValid (Ghcb, GhcbRcx) ||
-      !VmgIsOffsetValid (Ghcb, GhcbRdx))
-  {
-    return UnsupportedExit (Ghcb, Regs, InstructionData);
-  }
-
-  Regs->Rax = Ghcb->SaveArea.Rax;
-  Regs->Rcx = Ghcb->SaveArea.Rcx;
-  Regs->Rdx = Ghcb->SaveArea.Rdx;
-
-  return 0;
-}
-
-/**
-  Handle a VMMCALL event.
-
-  Use the VMGEXIT instruction to handle a VMMCALL event.
-
-  @param[in, out] Ghcb             Pointer to the Guest-Hypervisor Communication
-                                   Block
-  @param[in, out] Regs             x64 processor context
-  @param[in]      InstructionData  Instruction parsing context
-
-  @retval 0                        Event handled successfully
-  @return                          New exception value to propagate
-
-**/
-STATIC
-UINT64
-VmmCallExit (
-  IN OUT GHCB                     *Ghcb,
-  IN OUT EFI_SYSTEM_CONTEXT_X64   *Regs,
-  IN     SEV_ES_INSTRUCTION_DATA  *InstructionData
-  )
-{
-  UINT64  Status;
-
-  DecodeModRm (Regs, InstructionData);
-
-  Ghcb->SaveArea.Rax = Regs->Rax;
-  VmgSetOffsetValid (Ghcb, GhcbRax);
-  Ghcb->SaveArea.Cpl = (UINT8)(Regs->Cs & 0x3);
-  VmgSetOffsetValid (Ghcb, GhcbCpl);
-
-  Status = VmgExit (Ghcb, SVM_EXIT_VMMCALL, 0, 0);
-  if (Status != 0) {
-    return Status;
-  }
-
-  if (!VmgIsOffsetValid (Ghcb, GhcbRax)) {
-    return UnsupportedExit (Ghcb, Regs, InstructionData);
-  }
-
-  Regs->Rax = Ghcb->SaveArea.Rax;
-
-  return 0;
-}
-
-/**
-  Handle an MSR event.
-
-  Use the VMGEXIT instruction to handle either a RDMSR or WRMSR event.
-
-  @param[in, out] Ghcb             Pointer to the Guest-Hypervisor Communication
-                                   Block
-  @param[in, out] Regs             x64 processor context
-  @param[in]      InstructionData  Instruction parsing context
-
-  @retval 0                        Event handled successfully
-  @return                          New exception value to propagate
-
-**/
-STATIC
-UINT64
-MsrExit (
-  IN OUT GHCB                     *Ghcb,
-  IN OUT EFI_SYSTEM_CONTEXT_X64   *Regs,
-  IN     SEV_ES_INSTRUCTION_DATA  *InstructionData
-  )
-{
-  UINT64  ExitInfo1, Status;
-
-  ExitInfo1 = 0;
-
-  switch (*(InstructionData->OpCodes + 1)) {
-    case 0x30: // WRMSR
-      ExitInfo1          = 1;
-      Ghcb->SaveArea.Rax = Regs->Rax;
-      VmgSetOffsetValid (Ghcb, GhcbRax);
-      Ghcb->SaveArea.Rdx = Regs->Rdx;
-      VmgSetOffsetValid (Ghcb, GhcbRdx);
-    //
-    // fall through
-    //
-    case 0x32: // RDMSR
-      Ghcb->SaveArea.Rcx = Regs->Rcx;
-      VmgSetOffsetValid (Ghcb, GhcbRcx);
-      break;
-    default:
-      return UnsupportedExit (Ghcb, Regs, InstructionData);
-  }
-
-  Status = VmgExit (Ghcb, SVM_EXIT_MSR, ExitInfo1, 0);
-  if (Status != 0) {
-    return Status;
-  }
-
-  if (ExitInfo1 == 0) {
-    if (!VmgIsOffsetValid (Ghcb, GhcbRax) ||
-        !VmgIsOffsetValid (Ghcb, GhcbRdx))
-    {
-      return UnsupportedExit (Ghcb, Regs, InstructionData);
-    }
-
-    Regs->Rax = Ghcb->SaveArea.Rax;
-    Regs->Rdx = Ghcb->SaveArea.Rdx;
-  }
-
-  return 0;
-}
-
-/**
-  Build the IOIO event information.
-
-  The IOIO event information identifies the type of IO operation to be performed
-  by the hypervisor. Build this information based on the instruction data.
-
-  @param[in]       Regs             x64 processor context
-  @param[in, out]  InstructionData  Instruction parsing context
-
-  @return                           IOIO event information value
-
-**/
-STATIC
-UINT64
-IoioExitInfo (
-  IN     EFI_SYSTEM_CONTEXT_X64   *Regs,
-  IN OUT SEV_ES_INSTRUCTION_DATA  *InstructionData
-  )
-{
-  UINT64  ExitInfo;
-
-  ExitInfo = 0;
-
-  switch (*(InstructionData->OpCodes)) {
-    //
-    // INS opcodes
-    //
-    case 0x6C:
-    case 0x6D:
-      ExitInfo |= IOIO_TYPE_INS;
-      ExitInfo |= IOIO_SEG_ES;
-      ExitInfo |= ((Regs->Rdx & 0xffff) << 16);
-      break;
-
-    //
-    // OUTS opcodes
-    //
-    case 0x6E:
-    case 0x6F:
-      ExitInfo |= IOIO_TYPE_OUTS;
-      ExitInfo |= IOIO_SEG_DS;
-      ExitInfo |= ((Regs->Rdx & 0xffff) << 16);
-      break;
-
-    //
-    // IN immediate opcodes
-    //
-    case 0xE4:
-    case 0xE5:
-      InstructionData->ImmediateSize = 1;
-      InstructionData->End++;
-      ExitInfo |= IOIO_TYPE_IN;
-      ExitInfo |= ((*(InstructionData->OpCodes + 1)) << 16);
-      break;
-
-    //
-    // OUT immediate opcodes
-    //
-    case 0xE6:
-    case 0xE7:
-      InstructionData->ImmediateSize = 1;
-      InstructionData->End++;
-      ExitInfo |= IOIO_TYPE_OUT;
-      ExitInfo |= ((*(InstructionData->OpCodes + 1)) << 16) | IOIO_TYPE_OUT;
-      break;
-
-    //
-    // IN register opcodes
-    //
-    case 0xEC:
-    case 0xED:
-      ExitInfo |= IOIO_TYPE_IN;
-      ExitInfo |= ((Regs->Rdx & 0xffff) << 16);
-      break;
-
-    //
-    // OUT register opcodes
-    //
-    case 0xEE:
-    case 0xEF:
-      ExitInfo |= IOIO_TYPE_OUT;
-      ExitInfo |= ((Regs->Rdx & 0xffff) << 16);
-      break;
-
-    default:
-      return 0;
-  }
-
-  switch (*(InstructionData->OpCodes)) {
-    //
-    // Single-byte opcodes
-    //
-    case 0x6C:
-    case 0x6E:
-    case 0xE4:
-    case 0xE6:
-    case 0xEC:
-    case 0xEE:
-      ExitInfo |= IOIO_DATA_8;
-      break;
-
-    //
-    // Length determined by instruction parsing
-    //
-    default:
-      ExitInfo |= (InstructionData->DataSize == Size16Bits) ? IOIO_DATA_16
-                                                          : IOIO_DATA_32;
-  }
-
-  switch (InstructionData->AddrSize) {
-    case Size16Bits:
-      ExitInfo |= IOIO_ADDR_16;
-      break;
-
-    case Size32Bits:
-      ExitInfo |= IOIO_ADDR_32;
-      break;
-
-    case Size64Bits:
-      ExitInfo |= IOIO_ADDR_64;
-      break;
-
-    default:
-      break;
-  }
-
-  if (InstructionData->RepMode != 0) {
-    ExitInfo |= IOIO_REP;
-  }
-
-  return ExitInfo;
-}
-
-/**
-  Handle an IOIO event.
-
-  Use the VMGEXIT instruction to handle an IOIO event.
-
-  @param[in, out] Ghcb             Pointer to the Guest-Hypervisor Communication
-                                   Block
-  @param[in, out] Regs             x64 processor context
-  @param[in]      InstructionData  Instruction parsing context
-
-  @retval 0                        Event handled successfully
-  @return                          New exception value to propagate
-
-**/
-STATIC
-UINT64
-IoioExit (
-  IN OUT GHCB                     *Ghcb,
-  IN OUT EFI_SYSTEM_CONTEXT_X64   *Regs,
-  IN     SEV_ES_INSTRUCTION_DATA  *InstructionData
-  )
-{
-  UINT64   ExitInfo1, ExitInfo2, Status;
-  BOOLEAN  IsString;
-
-  ExitInfo1 = IoioExitInfo (Regs, InstructionData);
-  if (ExitInfo1 == 0) {
-    return UnsupportedExit (Ghcb, Regs, InstructionData);
-  }
-
-  IsString = ((ExitInfo1 & IOIO_TYPE_STR) != 0) ? TRUE : FALSE;
-  if (IsString) {
-    UINTN  IoBytes, VmgExitBytes;
-    UINTN  GhcbCount, OpCount;
-
-    Status = 0;
-
-    IoBytes   = IOIO_DATA_BYTES (ExitInfo1);
-    GhcbCount = sizeof (Ghcb->SharedBuffer) / IoBytes;
-
-    OpCount = ((ExitInfo1 & IOIO_REP) != 0) ? Regs->Rcx : 1;
-    while (OpCount != 0) {
-      ExitInfo2    = MIN (OpCount, GhcbCount);
-      VmgExitBytes = ExitInfo2 * IoBytes;
-
-      if ((ExitInfo1 & IOIO_TYPE_IN) == 0) {
-        CopyMem (Ghcb->SharedBuffer, (VOID *)Regs->Rsi, VmgExitBytes);
-        Regs->Rsi += VmgExitBytes;
-      }
-
-      Ghcb->SaveArea.SwScratch = (UINT64)Ghcb->SharedBuffer;
-      VmgSetOffsetValid (Ghcb, GhcbSwScratch);
-      Status = VmgExit (Ghcb, SVM_EXIT_IOIO_PROT, ExitInfo1, ExitInfo2);
-      if (Status != 0) {
-        return Status;
-      }
-
-      if ((ExitInfo1 & IOIO_TYPE_IN) != 0) {
-        CopyMem ((VOID *)Regs->Rdi, Ghcb->SharedBuffer, VmgExitBytes);
-        Regs->Rdi += VmgExitBytes;
-      }
-
-      if ((ExitInfo1 & IOIO_REP) != 0) {
-        Regs->Rcx -= ExitInfo2;
-      }
-
-      OpCount -= ExitInfo2;
-    }
-  } else {
-    if ((ExitInfo1 & IOIO_TYPE_IN) != 0) {
-      Ghcb->SaveArea.Rax = 0;
-    } else {
-      CopyMem (&Ghcb->SaveArea.Rax, &Regs->Rax, IOIO_DATA_BYTES (ExitInfo1));
-    }
-
-    VmgSetOffsetValid (Ghcb, GhcbRax);
-
-    Status = VmgExit (Ghcb, SVM_EXIT_IOIO_PROT, ExitInfo1, 0);
-    if (Status != 0) {
-      return Status;
-    }
-
-    if ((ExitInfo1 & IOIO_TYPE_IN) != 0) {
-      if (!VmgIsOffsetValid (Ghcb, GhcbRax)) {
-        return UnsupportedExit (Ghcb, Regs, InstructionData);
-      }
-
-      CopyMem (&Regs->Rax, &Ghcb->SaveArea.Rax, IOIO_DATA_BYTES (ExitInfo1));
-    }
-  }
-
-  return 0;
-}
-
-/**
-  Handle a INVD event.
-
-  Use the VMGEXIT instruction to handle a INVD event.
-
-  @param[in, out] Ghcb             Pointer to the Guest-Hypervisor Communication
-                                   Block
-  @param[in, out] Regs             x64 processor context
-  @param[in]      InstructionData  Instruction parsing context
-
-  @retval 0                        Event handled successfully
-  @return                          New exception value to propagate
-
-**/
-STATIC
-UINT64
-InvdExit (
-  IN OUT GHCB                     *Ghcb,
-  IN OUT EFI_SYSTEM_CONTEXT_X64   *Regs,
-  IN     SEV_ES_INSTRUCTION_DATA  *InstructionData
-  )
-{
-  return VmgExit (Ghcb, SVM_EXIT_INVD, 0, 0);
-}
-
-/**
-  Fetch CPUID leaf/function via hypervisor/VMGEXIT.
-
-  @param[in, out] Ghcb         Pointer to the Guest-Hypervisor Communication
-                               Block
-  @param[in]      EaxIn        EAX input for cpuid instruction
-  @param[in]      EcxIn        ECX input for cpuid instruction
-  @param[in]      Xcr0In       XCR0 at time of cpuid instruction
-  @param[in, out] Eax          Pointer to store leaf's EAX value
-  @param[in, out] Ebx          Pointer to store leaf's EBX value
-  @param[in, out] Ecx          Pointer to store leaf's ECX value
-  @param[in, out] Edx          Pointer to store leaf's EDX value
-  @param[in, out] Status       Pointer to store status from VMGEXIT (always 0
-                               unless return value indicates failure)
-  @param[in, out] Unsupported  Pointer to store indication of unsupported
-                               VMGEXIT (always false unless return value
-                               indicates failure)
-
-  @retval TRUE                 CPUID leaf fetch successfully.
-  @retval FALSE                Error occurred while fetching CPUID leaf. Callers
-                               should Status and Unsupported and handle
-                               accordingly if they indicate a more precise
-                               error condition.
-
-**/
-STATIC
-BOOLEAN
-GetCpuidHyp (
-  IN OUT GHCB     *Ghcb,
-  IN     UINT32   EaxIn,
-  IN     UINT32   EcxIn,
-  IN     UINT64   XCr0,
-  IN OUT UINT32   *Eax,
-  IN OUT UINT32   *Ebx,
-  IN OUT UINT32   *Ecx,
-  IN OUT UINT32   *Edx,
-  IN OUT UINT64   *Status,
-  IN OUT BOOLEAN  *UnsupportedExit
-  )
-{
-  *UnsupportedExit   = FALSE;
-  Ghcb->SaveArea.Rax = EaxIn;
-  VmgSetOffsetValid (Ghcb, GhcbRax);
-  Ghcb->SaveArea.Rcx = EcxIn;
-  VmgSetOffsetValid (Ghcb, GhcbRcx);
-  if (EaxIn == CPUID_EXTENDED_STATE) {
-    Ghcb->SaveArea.XCr0 = XCr0;
-    VmgSetOffsetValid (Ghcb, GhcbXCr0);
-  }
-
-  *Status = VmgExit (Ghcb, SVM_EXIT_CPUID, 0, 0);
-  if (*Status != 0) {
-    return FALSE;
-  }
-
-  if (!VmgIsOffsetValid (Ghcb, GhcbRax) ||
-      !VmgIsOffsetValid (Ghcb, GhcbRbx) ||
-      !VmgIsOffsetValid (Ghcb, GhcbRcx) ||
-      !VmgIsOffsetValid (Ghcb, GhcbRdx))
-  {
-    *UnsupportedExit = TRUE;
-    return FALSE;
-  }
-
-  if (Eax) {
-    *Eax = (UINT32)(UINTN)Ghcb->SaveArea.Rax;
-  }
-
-  if (Ebx) {
-    *Ebx = (UINT32)(UINTN)Ghcb->SaveArea.Rbx;
-  }
-
-  if (Ecx) {
-    *Ecx = (UINT32)(UINTN)Ghcb->SaveArea.Rcx;
-  }
-
-  if (Edx) {
-    *Edx = (UINT32)(UINTN)Ghcb->SaveArea.Rdx;
-  }
-
-  return TRUE;
-}
-
-/**
-  Check if SEV-SNP enabled.
-
-  @retval TRUE      SEV-SNP is enabled.
-  @retval FALSE     SEV-SNP is disabled.
-
-**/
-STATIC
-BOOLEAN
-SnpEnabled (
-  VOID
-  )
-{
-  MSR_SEV_STATUS_REGISTER  Msr;
-
-  Msr.Uint32 = AsmReadMsr32 (MSR_SEV_STATUS);
-
-  return !!Msr.Bits.SevSnpBit;
-}
-
-/**
-  Calculate the total XSAVE area size for enabled XSAVE areas
-
-  @param[in]      XFeaturesEnabled  Bit-mask of enabled XSAVE features/areas as
-                                    indicated by XCR0/MSR_IA32_XSS bits
-  @param[in]      XSaveBaseSize     Base/legacy XSAVE area size (e.g. when
-                                    XCR0 is 1)
-  @param[in, out] XSaveSize         Pointer to storage for calculated XSAVE area
-                                    size
-  @param[in]      Compacted         Whether or not the calculation is for the
-                                    normal XSAVE area size (leaf 0xD,0x0,EBX) or
-                                    compacted XSAVE area size (leaf 0xD,0x1,EBX)
-
-
-  @retval TRUE                      XSAVE size calculation was successful.
-  @retval FALSE                     XSAVE size calculation was unsuccessful.
-**/
-STATIC
-BOOLEAN
-GetCpuidXSaveSize (
-  IN     UINT64   XFeaturesEnabled,
-  IN     UINT32   XSaveBaseSize,
-  IN OUT UINT32   *XSaveSize,
-  IN     BOOLEAN  Compacted
-  )
-{
-  SEV_SNP_CPUID_INFO  *CpuidInfo;
-  UINT64              XFeaturesFound = 0;
-  UINT32              Idx;
-
-  *XSaveSize = XSaveBaseSize;
-  CpuidInfo  = (SEV_SNP_CPUID_INFO *)(UINT64)PcdGet32 (PcdOvmfCpuidBase);
-
-  for (Idx = 0; Idx < CpuidInfo->Count; Idx++) {
-    SEV_SNP_CPUID_FUNCTION  *CpuidFn = &CpuidInfo->function[Idx];
-
-    if (!((CpuidFn->EaxIn == 0xD) &&
-          ((CpuidFn->EcxIn == 0) || (CpuidFn->EcxIn == 1))))
-    {
-      continue;
-    }
-
-    if (XFeaturesFound & (1ULL << CpuidFn->EcxIn) ||
-        !(XFeaturesEnabled & (1ULL << CpuidFn->EcxIn)))
-    {
-      continue;
-    }
-
-    XFeaturesFound |= (1ULL << CpuidFn->EcxIn);
-    if (Compacted) {
-      *XSaveSize += CpuidFn->Eax;
-    } else {
-      *XSaveSize = MAX (*XSaveSize, CpuidFn->Eax + CpuidFn->Ebx);
-    }
-  }
-
-  /*
-   * Either the guest set unsupported XCR0/XSS bits, or the corresponding
-   * entries in the CPUID table were not present. This is an invalid state.
-   */
-  if (XFeaturesFound != (XFeaturesEnabled & ~3UL)) {
-    return FALSE;
-  }
-
-  return TRUE;
-}
-
-/**
-  Check if a CPUID leaf/function is indexed via ECX sub-leaf/sub-function
-
-  @param[in]      EaxIn        EAX input for cpuid instruction
-
-  @retval FALSE                cpuid leaf/function is not indexed by ECX input
-  @retval TRUE                 cpuid leaf/function is indexed by ECX input
-
-**/
-STATIC
-BOOLEAN
-IsFunctionIndexed (
-  IN     UINT32  EaxIn
-  )
-{
-  switch (EaxIn) {
-    case CPUID_CACHE_PARAMS:
-    case CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS:
-    case CPUID_EXTENDED_TOPOLOGY:
-    case CPUID_EXTENDED_STATE:
-    case CPUID_INTEL_RDT_MONITORING:
-    case CPUID_INTEL_RDT_ALLOCATION:
-    case CPUID_INTEL_SGX:
-    case CPUID_INTEL_PROCESSOR_TRACE:
-    case CPUID_DETERMINISTIC_ADDRESS_TRANSLATION_PARAMETERS:
-    case CPUID_V2_EXTENDED_TOPOLOGY:
-    case 0x8000001D: /* Cache Topology Information */
-      return TRUE;
-  }
-
-  return FALSE;
-}
-
-/**
-  Fetch CPUID leaf/function via SEV-SNP CPUID table.
-
-  @param[in, out] Ghcb         Pointer to the Guest-Hypervisor Communication
-                               Block
-  @param[in]      EaxIn        EAX input for cpuid instruction
-  @param[in]      EcxIn        ECX input for cpuid instruction
-  @param[in]      Xcr0In       XCR0 at time of cpuid instruction
-  @param[in, out] Eax          Pointer to store leaf's EAX value
-  @param[in, out] Ebx          Pointer to store leaf's EBX value
-  @param[in, out] Ecx          Pointer to store leaf's ECX value
-  @param[in, out] Edx          Pointer to store leaf's EDX value
-  @param[in, out] Status       Pointer to store status from VMGEXIT (always 0
-                               unless return value indicates failure)
-  @param[in, out] Unsupported  Pointer to store indication of unsupported
-                               VMGEXIT (always false unless return value
-                               indicates failure)
-
-  @retval TRUE                 CPUID leaf fetch successfully.
-  @retval FALSE                Error occurred while fetching CPUID leaf. Callers
-                               should Status and Unsupported and handle
-                               accordingly if they indicate a more precise
-                               error condition.
-
-**/
-STATIC
-BOOLEAN
-GetCpuidFw (
-  IN OUT GHCB     *Ghcb,
-  IN     UINT32   EaxIn,
-  IN     UINT32   EcxIn,
-  IN     UINT64   XCr0,
-  IN OUT UINT32   *Eax,
-  IN OUT UINT32   *Ebx,
-  IN OUT UINT32   *Ecx,
-  IN OUT UINT32   *Edx,
-  IN OUT UINT64   *Status,
-  IN OUT BOOLEAN  *Unsupported
-  )
-{
-  SEV_SNP_CPUID_INFO  *CpuidInfo;
-  BOOLEAN             Found;
-  UINT32              Idx;
-
-  CpuidInfo = (SEV_SNP_CPUID_INFO *)(UINT64)PcdGet32 (PcdOvmfCpuidBase);
-  Found     = FALSE;
-
-  for (Idx = 0; Idx < CpuidInfo->Count; Idx++) {
-    SEV_SNP_CPUID_FUNCTION  *CpuidFn = &CpuidInfo->function[Idx];
-
-    if (CpuidFn->EaxIn != EaxIn) {
-      continue;
-    }
-
-    if (IsFunctionIndexed (CpuidFn->EaxIn) && (CpuidFn->EcxIn != EcxIn)) {
-      continue;
-    }
-
-    *Eax = CpuidFn->Eax;
-    *Ebx = CpuidFn->Ebx;
-    *Ecx = CpuidFn->Ecx;
-    *Edx = CpuidFn->Edx;
-
-    Found = TRUE;
-    break;
-  }
-
-  if (!Found) {
-    *Eax = *Ebx = *Ecx = *Edx = 0;
-    goto Out;
-  }
-
-  if (EaxIn == CPUID_VERSION_INFO) {
-    IA32_CR4  Cr4;
-    UINT32    Ebx2;
-    UINT32    Edx2;
-
-    if (!GetCpuidHyp (
-           Ghcb,
-           EaxIn,
-           EcxIn,
-           XCr0,
-           NULL,
-           &Ebx2,
-           NULL,
-           &Edx2,
-           Status,
-           Unsupported
-           ))
-    {
-      return FALSE;
-    }
-
-    /* initial APIC ID */
-    *Ebx = (*Ebx & 0x00FFFFFF) | (Ebx2 & 0xFF000000);
-    /* APIC enabled bit */
-    *Edx = (*Edx & ~BIT9) | (Edx2 & BIT9);
-    /* OSXSAVE enabled bit */
-    Cr4.UintN = AsmReadCr4 ();
-    *Ecx      = (Cr4.Bits.OSXSAVE) ? (*Ecx & ~BIT27) | (*Ecx & BIT27)
-                              : (*Ecx & ~BIT27);
-  } else if (EaxIn == CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS) {
-    IA32_CR4  Cr4;
-
-    Cr4.UintN = AsmReadCr4 ();
-    /* OSPKE enabled bit */
-    *Ecx = (Cr4.Bits.PKE) ? (*Ecx | BIT4) : (*Ecx & ~BIT4);
-  } else if (EaxIn == CPUID_EXTENDED_TOPOLOGY) {
-    if (!GetCpuidHyp (
-           Ghcb,
-           EaxIn,
-           EcxIn,
-           XCr0,
-           NULL,
-           NULL,
-           NULL,
-           Edx,
-           Status,
-           Unsupported
-           ))
-    {
-      return FALSE;
-    }
-  } else if ((EaxIn == CPUID_EXTENDED_STATE) && ((EcxIn == 0) || (EcxIn == 1))) {
-    MSR_IA32_XSS_REGISTER  XssMsr;
-    BOOLEAN                Compacted;
-    UINT32                 XSaveSize;
-
-    XssMsr.Uint64 = 0;
-    Compacted     = FALSE;
-    if (EcxIn == 1) {
-      /*
-       * The PPR and APM aren't clear on what size should be encoded in
-       * 0xD:0x1:EBX when compaction is not enabled by either XSAVEC or
-       * XSAVES, as these are generally fixed to 1 on real CPUs. Report
-       * this undefined case as an error.
-       */
-      if (!(*Eax & (BIT3 | BIT1))) {
-        /* (XSAVES | XSAVEC) */
-        return FALSE;
-      }
-
-      Compacted     = TRUE;
-      XssMsr.Uint64 = AsmReadMsr64 (MSR_IA32_XSS);
-    }
-
-    if (!GetCpuidXSaveSize (
-           XCr0 | XssMsr.Uint64,
-           *Ebx,
-           &XSaveSize,
-           Compacted
-           ))
-    {
-      return FALSE;
-    }
-
-    *Ebx = XSaveSize;
-  } else if (EaxIn == 0x8000001E) {
-    UINT32  Ebx2;
-    UINT32  Ecx2;
-
-    /* extended APIC ID */
-    if (!GetCpuidHyp (
-           Ghcb,
-           EaxIn,
-           EcxIn,
-           XCr0,
-           Eax,
-           &Ebx2,
-           &Ecx2,
-           NULL,
-           Status,
-           Unsupported
-           ))
-    {
-      return FALSE;
-    }
-
-    /* compute ID */
-    *Ebx = (*Ebx & 0xFFFFFF00) | (Ebx2 & 0x000000FF);
-    /* node ID */
-    *Ecx = (*Ecx & 0xFFFFFF00) | (Ecx2 & 0x000000FF);
-  }
-
-Out:
-  *Status      = 0;
-  *Unsupported = FALSE;
-  return TRUE;
-}
-
-/**
-  Handle a CPUID event.
-
-  Use VMGEXIT instruction or CPUID table to handle a CPUID event.
-
-  @param[in, out] Ghcb             Pointer to the Guest-Hypervisor Communication
-                                   Block
-  @param[in, out] Regs             x64 processor context
-  @param[in]      InstructionData  Instruction parsing context
-
-  @retval 0                        Event handled successfully
-  @return                          New exception value to propagate
-
-**/
-STATIC
-UINT64
-CpuidExit (
-  IN OUT GHCB                     *Ghcb,
-  IN OUT EFI_SYSTEM_CONTEXT_X64   *Regs,
-  IN     SEV_ES_INSTRUCTION_DATA  *InstructionData
-  )
-{
-  BOOLEAN  Unsupported;
-  UINT64   Status;
-  UINT32   EaxIn;
-  UINT32   EcxIn;
-  UINT64   XCr0;
-  UINT32   Eax;
-  UINT32   Ebx;
-  UINT32   Ecx;
-  UINT32   Edx;
-
-  EaxIn = (UINT32)(UINTN)Regs->Rax;
-  EcxIn = (UINT32)(UINTN)Regs->Rcx;
-
-  if (EaxIn == CPUID_EXTENDED_STATE) {
-    IA32_CR4  Cr4;
-
-    Cr4.UintN           = AsmReadCr4 ();
-    Ghcb->SaveArea.XCr0 = (Cr4.Bits.OSXSAVE == 1) ? AsmXGetBv (0) : 1;
-    XCr0                = (Cr4.Bits.OSXSAVE == 1) ? AsmXGetBv (0) : 1;
-  }
-
-  if (SnpEnabled ()) {
-    if (!GetCpuidFw (
-           Ghcb,
-           EaxIn,
-           EcxIn,
-           XCr0,
-           &Eax,
-           &Ebx,
-           &Ecx,
-           &Edx,
-           &Status,
-           &Unsupported
-           ))
-    {
-      goto CpuidFail;
-    }
-  } else {
-    if (!GetCpuidHyp (
-           Ghcb,
-           EaxIn,
-           EcxIn,
-           XCr0,
-           &Eax,
-           &Ebx,
-           &Ecx,
-           &Edx,
-           &Status,
-           &Unsupported
-           ))
-    {
-      goto CpuidFail;
-    }
-  }
-
-  Regs->Rax = Eax;
-  Regs->Rbx = Ebx;
-  Regs->Rcx = Ecx;
-  Regs->Rdx = Edx;
-
-  return 0;
-
-CpuidFail:
-  if (Unsupported) {
-    return UnsupportedExit (Ghcb, Regs, InstructionData);
-  }
-
-  return Status;
-}
-
-/**
-  Handle a RDPMC event.
-
-  Use the VMGEXIT instruction to handle a RDPMC event.
-
-  @param[in, out] Ghcb             Pointer to the Guest-Hypervisor Communication
-                                   Block
-  @param[in, out] Regs             x64 processor context
-  @param[in]      InstructionData  Instruction parsing context
-
-  @retval 0                        Event handled successfully
-  @return                          New exception value to propagate
-
-**/
-STATIC
-UINT64
-RdpmcExit (
-  IN OUT GHCB                     *Ghcb,
-  IN OUT EFI_SYSTEM_CONTEXT_X64   *Regs,
-  IN     SEV_ES_INSTRUCTION_DATA  *InstructionData
-  )
-{
-  UINT64  Status;
-
-  Ghcb->SaveArea.Rcx = Regs->Rcx;
-  VmgSetOffsetValid (Ghcb, GhcbRcx);
-
-  Status = VmgExit (Ghcb, SVM_EXIT_RDPMC, 0, 0);
-  if (Status != 0) {
-    return Status;
-  }
-
-  if (!VmgIsOffsetValid (Ghcb, GhcbRax) ||
-      !VmgIsOffsetValid (Ghcb, GhcbRdx))
-  {
-    return UnsupportedExit (Ghcb, Regs, InstructionData);
-  }
-
-  Regs->Rax = Ghcb->SaveArea.Rax;
-  Regs->Rdx = Ghcb->SaveArea.Rdx;
-
-  return 0;
-}
-
-/**
-  Handle a RDTSC event.
-
-  Use the VMGEXIT instruction to handle a RDTSC event.
-
-  @param[in, out] Ghcb             Pointer to the Guest-Hypervisor Communication
-                                   Block
-  @param[in, out] Regs             x64 processor context
-  @param[in]      InstructionData  Instruction parsing context
-
-  @retval 0                        Event handled successfully
-  @return                          New exception value to propagate
-
-**/
-STATIC
-UINT64
-RdtscExit (
-  IN OUT GHCB                     *Ghcb,
-  IN OUT EFI_SYSTEM_CONTEXT_X64   *Regs,
-  IN     SEV_ES_INSTRUCTION_DATA  *InstructionData
-  )
-{
-  UINT64  Status;
-
-  Status = VmgExit (Ghcb, SVM_EXIT_RDTSC, 0, 0);
-  if (Status != 0) {
-    return Status;
-  }
-
-  if (!VmgIsOffsetValid (Ghcb, GhcbRax) ||
-      !VmgIsOffsetValid (Ghcb, GhcbRdx))
-  {
-    return UnsupportedExit (Ghcb, Regs, InstructionData);
-  }
-
-  Regs->Rax = Ghcb->SaveArea.Rax;
-  Regs->Rdx = Ghcb->SaveArea.Rdx;
-
-  return 0;
-}
-
-/**
-  Handle a DR7 register write event.
-
-  Use the VMGEXIT instruction to handle a DR7 write event.
-
-  @param[in, out] Ghcb             Pointer to the Guest-Hypervisor Communication
-                                   Block
-  @param[in, out] Regs             x64 processor context
-  @param[in]      InstructionData  Instruction parsing context
-
-  @retval 0                        Event handled successfully
-  @return                          New exception value to propagate
-
-**/
-STATIC
-UINT64
-Dr7WriteExit (
-  IN OUT GHCB                     *Ghcb,
-  IN OUT EFI_SYSTEM_CONTEXT_X64   *Regs,
-  IN     SEV_ES_INSTRUCTION_DATA  *InstructionData
-  )
-{
-  SEV_ES_INSTRUCTION_OPCODE_EXT  *Ext;
-  SEV_ES_PER_CPU_DATA            *SevEsData;
-  UINT64                         *Register;
-  UINT64                         Status;
-
-  Ext       = &InstructionData->Ext;
-  SevEsData = (SEV_ES_PER_CPU_DATA *)(Ghcb + 1);
-
-  DecodeModRm (Regs, InstructionData);
-
-  //
-  // MOV DRn always treats MOD == 3 no matter how encoded
-  //
-  Register = GetRegisterPointer (Regs, Ext->ModRm.Rm);
-
-  //
-  // Using a value of 0 for ExitInfo1 means RAX holds the value
-  //
-  Ghcb->SaveArea.Rax = *Register;
-  VmgSetOffsetValid (Ghcb, GhcbRax);
-
-  Status = VmgExit (Ghcb, SVM_EXIT_DR7_WRITE, 0, 0);
-  if (Status != 0) {
-    return Status;
-  }
-
-  SevEsData->Dr7       = *Register;
-  SevEsData->Dr7Cached = 1;
-
-  return 0;
-}
-
-/**
-  Handle a DR7 register read event.
-
-  Use the VMGEXIT instruction to handle a DR7 read event.
-
-  @param[in, out] Ghcb             Pointer to the Guest-Hypervisor Communication
-                                   Block
-  @param[in, out] Regs             x64 processor context
-  @param[in]      InstructionData  Instruction parsing context
-
-  @retval 0                        Event handled successfully
-
-**/
-STATIC
-UINT64
-Dr7ReadExit (
-  IN OUT GHCB                     *Ghcb,
-  IN OUT EFI_SYSTEM_CONTEXT_X64   *Regs,
-  IN     SEV_ES_INSTRUCTION_DATA  *InstructionData
-  )
-{
-  SEV_ES_INSTRUCTION_OPCODE_EXT  *Ext;
-  SEV_ES_PER_CPU_DATA            *SevEsData;
-  UINT64                         *Register;
-
-  Ext       = &InstructionData->Ext;
-  SevEsData = (SEV_ES_PER_CPU_DATA *)(Ghcb + 1);
-
-  DecodeModRm (Regs, InstructionData);
-
-  //
-  // MOV DRn always treats MOD == 3 no matter how encoded
-  //
-  Register = GetRegisterPointer (Regs, Ext->ModRm.Rm);
-
-  //
-  // If there is a cached valued for DR7, return that. Otherwise return the
-  // DR7 standard reset value of 0x400 (no debug breakpoints set).
-  //
-  *Register = (SevEsData->Dr7Cached == 1) ? SevEsData->Dr7 : 0x400;
-
-  return 0;
-}
-
-/**
-  Handle a #VC exception.
-
-  Performs the necessary processing to handle a #VC exception.
-
-  @param[in, out]  Ghcb           Pointer to the GHCB
-  @param[in, out]  ExceptionType  Pointer to an EFI_EXCEPTION_TYPE to be set
-                                  as value to use on error.
-  @param[in, out]  SystemContext  Pointer to EFI_SYSTEM_CONTEXT
-
-  @retval  EFI_SUCCESS            Exception handled
-  @retval  EFI_UNSUPPORTED        #VC not supported, (new) exception value to
-                                  propagate provided
-  @retval  EFI_PROTOCOL_ERROR     #VC handling failed, (new) exception value to
-                                  propagate provided
-
-**/
-EFI_STATUS
-EFIAPI
-InternalVmgExitHandleVc (
-  IN OUT GHCB                *Ghcb,
-  IN OUT EFI_EXCEPTION_TYPE  *ExceptionType,
-  IN OUT EFI_SYSTEM_CONTEXT  SystemContext
-  )
-{
-  EFI_SYSTEM_CONTEXT_X64   *Regs;
-  NAE_EXIT                 NaeExit;
-  SEV_ES_INSTRUCTION_DATA  InstructionData;
-  UINT64                   ExitCode, Status;
-  EFI_STATUS               VcRet;
-  BOOLEAN                  InterruptState;
-
-  VcRet = EFI_SUCCESS;
-
-  Regs = SystemContext.SystemContextX64;
-
-  VmgInit (Ghcb, &InterruptState);
-
-  ExitCode = Regs->ExceptionData;
-  switch (ExitCode) {
-    case SVM_EXIT_DR7_READ:
-      NaeExit = Dr7ReadExit;
-      break;
-
-    case SVM_EXIT_DR7_WRITE:
-      NaeExit = Dr7WriteExit;
-      break;
-
-    case SVM_EXIT_RDTSC:
-      NaeExit = RdtscExit;
-      break;
-
-    case SVM_EXIT_RDPMC:
-      NaeExit = RdpmcExit;
-      break;
-
-    case SVM_EXIT_CPUID:
-      NaeExit = CpuidExit;
-      break;
-
-    case SVM_EXIT_INVD:
-      NaeExit = InvdExit;
-      break;
-
-    case SVM_EXIT_IOIO_PROT:
-      NaeExit = IoioExit;
-      break;
-
-    case SVM_EXIT_MSR:
-      NaeExit = MsrExit;
-      break;
-
-    case SVM_EXIT_VMMCALL:
-      NaeExit = VmmCallExit;
-      break;
-
-    case SVM_EXIT_RDTSCP:
-      NaeExit = RdtscpExit;
-      break;
-
-    case SVM_EXIT_WBINVD:
-      NaeExit = WbinvdExit;
-      break;
-
-    case SVM_EXIT_MONITOR:
-      NaeExit = MonitorExit;
-      break;
-
-    case SVM_EXIT_MWAIT:
-      NaeExit = MwaitExit;
-      break;
-
-    case SVM_EXIT_NPF:
-      NaeExit = MmioExit;
-      break;
-
-    default:
-      NaeExit = UnsupportedExit;
-  }
-
-  InitInstructionData (&InstructionData, Ghcb, Regs);
-
-  Status = NaeExit (Ghcb, Regs, &InstructionData);
-  if (Status == 0) {
-    Regs->Rip += InstructionLength (&InstructionData);
-  } else {
-    GHCB_EVENT_INJECTION  Event;
-
-    Event.Uint64 = Status;
-    if (Event.Elements.ErrorCodeValid != 0) {
-      Regs->ExceptionData = Event.Elements.ErrorCode;
-    } else {
-      Regs->ExceptionData = 0;
-    }
-
-    *ExceptionType = Event.Elements.Vector;
-
-    VcRet = EFI_PROTOCOL_ERROR;
-  }
-
-  VmgDone (Ghcb, InterruptState);
-
-  return VcRet;
-}
-
-/**
-  Routine to allow ASSERT from within #VC.
-
-  @param[in, out]  SevEsData  Pointer to the per-CPU data
-
-**/
-VOID
-EFIAPI
-VmgExitIssueAssert (
-  IN OUT SEV_ES_PER_CPU_DATA  *SevEsData
-  )
-{
-  //
-  // Progress will be halted, so set VcCount to allow for ASSERT output
-  // to be seen.
-  //
-  SevEsData->VcCount = 0;
-
-  ASSERT (FALSE);
-  CpuDeadLoop ();
-}
diff --git a/OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.h b/OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.h
deleted file mode 100644
index 3a37cb04f616..000000000000
--- a/OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/** @file
-  X64 #VC Exception Handler functon header file.
-
-  Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved.<BR>
-  SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#ifndef __VMG_EXIT_VC_HANDLER_H__
-#define __VMG_EXIT_VC_HANDLER_H__
-
-#include <Base.h>
-#include <Uefi.h>
-#include <Library/VmgExitLib.h>
-
-/**
-  Handle a #VC exception.
-
-  Performs the necessary processing to handle a #VC exception.
-
-  @param[in, out]  Ghcb           Pointer to the GHCB
-  @param[in, out]  ExceptionType  Pointer to an EFI_EXCEPTION_TYPE to be set
-                                  as value to use on error.
-  @param[in, out]  SystemContext  Pointer to EFI_SYSTEM_CONTEXT
-
-  @retval  EFI_SUCCESS            Exception handled
-  @retval  EFI_UNSUPPORTED        #VC not supported, (new) exception value to
-                                  propagate provided
-  @retval  EFI_PROTOCOL_ERROR     #VC handling failed, (new) exception value to
-                                  propagate provided
-
-**/
-EFI_STATUS
-EFIAPI
-InternalVmgExitHandleVc (
-  IN OUT GHCB                *Ghcb,
-  IN OUT EFI_EXCEPTION_TYPE  *ExceptionType,
-  IN OUT EFI_SYSTEM_CONTEXT  SystemContext
-  );
-
-/**
-  Routine to allow ASSERT from within #VC.
-
-  @param[in, out]  SevEsData  Pointer to the per-CPU data
-
-**/
-VOID
-EFIAPI
-VmgExitIssueAssert (
-  IN OUT SEV_ES_PER_CPU_DATA  *SevEsData
-  );
-
-#endif
diff --git a/OvmfPkg/Library/VmgExitLib/X64/TdVmcallCpuid.nasm b/OvmfPkg/Library/VmgExitLib/X64/TdVmcallCpuid.nasm
deleted file mode 100644
index fa86440904fe..000000000000
--- a/OvmfPkg/Library/VmgExitLib/X64/TdVmcallCpuid.nasm
+++ /dev/null
@@ -1,146 +0,0 @@
-;------------------------------------------------------------------------------
-;*
-;* Copyright (c) 2020 - 2021, Intel Corporation. All rights reserved.<BR>
-;* SPDX-License-Identifier: BSD-2-Clause-Patent
-;*
-;*
-;------------------------------------------------------------------------------
-
-DEFAULT REL
-SECTION .text
-
-%define TDVMCALL_EXPOSE_REGS_MASK       0xffec
-%define TDVMCALL                        0x0
-%define EXIT_REASON_CPUID               0xa
-
-%macro tdcall 0
-    db 0x66,0x0f,0x01,0xcc
-%endmacro
-
-%macro tdcall_push_regs 0
-    push rbp
-    mov  rbp, rsp
-    push r15
-    push r14
-    push r13
-    push r12
-    push rbx
-    push rsi
-    push rdi
-%endmacro
-
-%macro tdcall_pop_regs 0
-    pop rdi
-    pop rsi
-    pop rbx
-    pop r12
-    pop r13
-    pop r14
-    pop r15
-    pop rbp
-%endmacro
-
-%define number_of_regs_pushed 8
-%define number_of_parameters  4
-
-;
-; Keep these in sync for push_regs/pop_regs, code below
-; uses them to find 5th or greater parameters
-;
-%define first_variable_on_stack_offset \
-  ((number_of_regs_pushed * 8) + (number_of_parameters * 8) + 8)
-%define second_variable_on_stack_offset \
-  ((first_variable_on_stack_offset) + 8)
-
-%macro tdcall_regs_preamble 2
-    mov rax, %1
-
-    xor rcx, rcx
-    mov ecx, %2
-
-    ; R10 = 0 (standard TDVMCALL)
-
-    xor r10d, r10d
-
-    ; Zero out unused (for standard TDVMCALL) registers to avoid leaking
-    ; secrets to the VMM.
-
-    xor ebx, ebx
-    xor esi, esi
-    xor edi, edi
-
-    xor edx, edx
-    xor ebp, ebp
-    xor r8d, r8d
-    xor r9d, r9d
-    xor r14, r14
-    xor r15, r15
-%endmacro
-
-%macro tdcall_regs_postamble 0
-    xor ebx, ebx
-    xor esi, esi
-    xor edi, edi
-
-    xor ecx, ecx
-    xor edx, edx
-    xor r8d,  r8d
-    xor r9d,  r9d
-    xor r10d, r10d
-    xor r11d, r11d
-%endmacro
-
-;------------------------------------------------------------------------------
-; 0   => RAX = TDCALL leaf / TDVMCALL
-; M   => RCX = TDVMCALL register behavior
-; 0xa => R11 = TDVMCALL function / CPUID
-; RCX => R12 = p1
-; RDX => R13 = p2
-;
-;  UINT64
-;  EFIAPI
-;  TdVmCallCpuid (
-;    UINT64  EaxIn,    // Rcx
-;    UINT64  EcxIn,    // Rdx
-;    UINT64  *Results  // R8
-;    )
-global ASM_PFX(TdVmCallCpuid)
-ASM_PFX(TdVmCallCpuid):
-       tdcall_push_regs
-
-       mov r11, EXIT_REASON_CPUID
-       mov r12, rcx
-       mov r13, rdx
-
-       ; Save *results pointers
-       push r8
-
-       tdcall_regs_preamble TDVMCALL, TDVMCALL_EXPOSE_REGS_MASK
-
-       tdcall
-
-       ; ignore return data if TDCALL reports failure.
-       test rax, rax
-       jnz .no_return_data
-
-       ; Propagate TDVMCALL success/failure to return value.
-       mov rax, r10
-       test rax, rax
-       jnz .no_return_data
-
-       ; Retrieve *Results
-       pop r8
-       test r8, r8
-       jz .no_return_data
-       ; Caller pass in buffer so store results r12-r15 contains eax-edx
-       mov [r8 +  0], r12
-       mov [r8 +  8], r13
-       mov [r8 + 16], r14
-       mov [r8 + 24], r15
-
-.no_return_data:
-       tdcall_regs_postamble
-
-       tdcall_pop_regs
-
-       ret
-- 
2.29.2.windows.2


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH V2 8/9] UefiCpuPkg: Delete VmgExitLib
  2022-11-03 23:19 [PATCH V2 0/9] Rename VmgExitLib to CcExitLib Min Xu
                   ` (6 preceding siblings ...)
  2022-11-03 23:19 ` [PATCH V2 7/9] OvmfPkg: Delete VmgExitLib Min Xu
@ 2022-11-03 23:19 ` Min Xu
  2022-11-03 23:19 ` [PATCH V2 9/9] Maintainers: Update the VmgExitLib to CcExitLib Min Xu
  2022-11-04  2:04 ` [PATCH V2 0/9] Rename " Yao, Jiewen
  9 siblings, 0 replies; 13+ messages in thread
From: Min Xu @ 2022-11-03 23:19 UTC (permalink / raw)
  To: devel; +Cc: Min M Xu, Guo Dong, Ray Ni

From: Min M Xu <min.m.xu@intel.com>

BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=4123

VmgExitLib is replaced by CcExitLib. So it is deleted from UefiCpuPkg.

Cc: Guo Dong <guo.dong@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Signed-off-by: Min Xu <min.m.xu@intel.com>
---
 UefiCpuPkg/Include/Library/VmgExitLib.h       | 173 ------------------
 .../Library/VmgExitLibNull/VmTdExitNull.c     |  38 ----
 .../Library/VmgExitLibNull/VmgExitLibNull.c   | 165 -----------------
 .../Library/VmgExitLibNull/VmgExitLibNull.inf |  28 ---
 .../Library/VmgExitLibNull/VmgExitLibNull.uni |  15 --
 UefiCpuPkg/UefiCpuPkg.dec                     |   3 -
 UefiCpuPkg/UefiCpuPkg.dsc                     |   2 -
 7 files changed, 424 deletions(-)
 delete mode 100644 UefiCpuPkg/Include/Library/VmgExitLib.h
 delete mode 100644 UefiCpuPkg/Library/VmgExitLibNull/VmTdExitNull.c
 delete mode 100644 UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.c
 delete mode 100644 UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.inf
 delete mode 100644 UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.uni

diff --git a/UefiCpuPkg/Include/Library/VmgExitLib.h b/UefiCpuPkg/Include/Library/VmgExitLib.h
deleted file mode 100644
index f9f911099a7b..000000000000
--- a/UefiCpuPkg/Include/Library/VmgExitLib.h
+++ /dev/null
@@ -1,173 +0,0 @@
-/** @file
-  Public header file for the VMGEXIT Support library class.
-
-  This library class defines some routines used when invoking the VMGEXIT
-  instruction in support of SEV-ES and to handle #VC exceptions.
-
-  Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved.<BR>
-  SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#ifndef __VMG_EXIT_LIB_H__
-#define __VMG_EXIT_LIB_H__
-
-#include <Protocol/DebugSupport.h>
-#include <Register/Amd/Ghcb.h>
-
-#define VE_EXCEPTION  20
-
-/**
-  Perform VMGEXIT.
-
-  Sets the necessary fields of the GHCB, invokes the VMGEXIT instruction and
-  then handles the return actions.
-
-  @param[in, out]  Ghcb       A pointer to the GHCB
-  @param[in]       ExitCode   VMGEXIT code to be assigned to the SwExitCode
-                              field of the GHCB.
-  @param[in]       ExitInfo1  VMGEXIT information to be assigned to the
-                              SwExitInfo1 field of the GHCB.
-  @param[in]       ExitInfo2  VMGEXIT information to be assigned to the
-                              SwExitInfo2 field of the GHCB.
-
-  @retval  0                  VMGEXIT succeeded.
-  @return                     Exception number to be propagated, VMGEXIT
-                              processing did not succeed.
-
-**/
-UINT64
-EFIAPI
-VmgExit (
-  IN OUT GHCB    *Ghcb,
-  IN     UINT64  ExitCode,
-  IN     UINT64  ExitInfo1,
-  IN     UINT64  ExitInfo2
-  );
-
-/**
-  Perform pre-VMGEXIT initialization/preparation.
-
-  Performs the necessary steps in preparation for invoking VMGEXIT. Must be
-  called before setting any fields within the GHCB.
-
-  @param[in, out]  Ghcb            A pointer to the GHCB
-  @param[in, out]  InterruptState  A pointer to hold the current interrupt
-                                   state, used for restoring in VmgDone ()
-
-**/
-VOID
-EFIAPI
-VmgInit (
-  IN OUT GHCB     *Ghcb,
-  IN OUT BOOLEAN  *InterruptState
-  );
-
-/**
-  Perform post-VMGEXIT cleanup.
-
-  Performs the necessary steps to cleanup after invoking VMGEXIT. Must be
-  called after obtaining needed fields within the GHCB.
-
-  @param[in, out]  Ghcb            A pointer to the GHCB
-  @param[in]       InterruptState  An indicator to conditionally (re)enable
-                                   interrupts
-
-**/
-VOID
-EFIAPI
-VmgDone (
-  IN OUT GHCB     *Ghcb,
-  IN     BOOLEAN  InterruptState
-  );
-
-/**
-  Marks a specified offset as valid in the GHCB.
-
-  The ValidBitmap area represents the areas of the GHCB that have been marked
-  valid. Set the bit in ValidBitmap for the input offset.
-
-  @param[in, out]  Ghcb       A pointer to the GHCB
-  @param[in]       Offset     Qword offset in the GHCB to mark valid
-
-**/
-VOID
-EFIAPI
-VmgSetOffsetValid (
-  IN OUT GHCB           *Ghcb,
-  IN     GHCB_REGISTER  Offset
-  );
-
-/**
-  Checks if a specified offset is valid in the GHCB.
-
-  The ValidBitmap area represents the areas of the GHCB that have been marked
-  valid. Return whether the bit in the ValidBitmap is set for the input offset.
-
-  @param[in]  Ghcb            A pointer to the GHCB
-  @param[in]  Offset          Qword offset in the GHCB to mark valid
-
-  @retval TRUE                Offset is marked valid in the GHCB
-  @retval FALSE               Offset is not marked valid in the GHCB
-
-**/
-BOOLEAN
-EFIAPI
-VmgIsOffsetValid (
-  IN GHCB           *Ghcb,
-  IN GHCB_REGISTER  Offset
-  );
-
-/**
-  Handle a #VC exception.
-
-  Performs the necessary processing to handle a #VC exception.
-
-  The base library function returns an error equal to VC_EXCEPTION,
-  to be propagated to the standard exception handling stack.
-
-  @param[in, out]  ExceptionType  Pointer to an EFI_EXCEPTION_TYPE to be set
-                                  as value to use on error.
-  @param[in, out]  SystemContext  Pointer to EFI_SYSTEM_CONTEXT
-
-  @retval  EFI_SUCCESS            Exception handled
-  @retval  EFI_UNSUPPORTED        #VC not supported, (new) exception value to
-                                  propagate provided
-  @retval  EFI_PROTOCOL_ERROR     #VC handling failed, (new) exception value to
-                                  propagate provided
-
-**/
-EFI_STATUS
-EFIAPI
-VmgExitHandleVc (
-  IN OUT EFI_EXCEPTION_TYPE  *ExceptionType,
-  IN OUT EFI_SYSTEM_CONTEXT  SystemContext
-  );
-
-/**
-  Handle a #VE exception.
-
-  Performs the necessary processing to handle a #VE exception.
-
-  The base library function returns an error equal to VE_EXCEPTION,
-  to be propagated to the standard exception handling stack.
-
-  @param[in, out]  ExceptionType  Pointer to an EFI_EXCEPTION_TYPE to be set
-                                  as value to use on error.
-  @param[in, out]  SystemContext  Pointer to EFI_SYSTEM_CONTEXT
-
-  @retval  EFI_SUCCESS            Exception handled
-  @retval  EFI_UNSUPPORTED        #VE not supported, (new) exception value to
-                                  propagate provided
-  @retval  EFI_PROTOCOL_ERROR     #VE handling failed, (new) exception value to
-                                  propagate provided
-
-**/
-EFI_STATUS
-EFIAPI
-VmTdExitHandleVe (
-  IN OUT EFI_EXCEPTION_TYPE  *ExceptionType,
-  IN OUT EFI_SYSTEM_CONTEXT  SystemContext
-  );
-
-#endif
diff --git a/UefiCpuPkg/Library/VmgExitLibNull/VmTdExitNull.c b/UefiCpuPkg/Library/VmgExitLibNull/VmTdExitNull.c
deleted file mode 100644
index 6a4e8087cb89..000000000000
--- a/UefiCpuPkg/Library/VmgExitLibNull/VmTdExitNull.c
+++ /dev/null
@@ -1,38 +0,0 @@
-/** @file
-
-  Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
-
-  SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-#include <Base.h>
-#include <Uefi.h>
-#include <Library/VmgExitLib.h>
-
-/**
-  Handle a #VE exception.
-
-  Performs the necessary processing to handle a #VE exception.
-
-  @param[in, out]  ExceptionType  Pointer to an EFI_EXCEPTION_TYPE to be set
-                                  as value to use on error.
-  @param[in, out]  SystemContext  Pointer to EFI_SYSTEM_CONTEXT
-
-  @retval  EFI_SUCCESS            Exception handled
-  @retval  EFI_UNSUPPORTED        #VE not supported, (new) exception value to
-                                  propagate provided
-  @retval  EFI_PROTOCOL_ERROR     #VE handling failed, (new) exception value to
-                                  propagate provided
-
-**/
-EFI_STATUS
-EFIAPI
-VmTdExitHandleVe (
-  IN OUT EFI_EXCEPTION_TYPE  *ExceptionType,
-  IN OUT EFI_SYSTEM_CONTEXT  SystemContext
-  )
-{
-  *ExceptionType = VE_EXCEPTION;
-
-  return EFI_UNSUPPORTED;
-}
diff --git a/UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.c b/UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.c
deleted file mode 100644
index d661d8597434..000000000000
--- a/UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.c
+++ /dev/null
@@ -1,165 +0,0 @@
-/** @file
-  VMGEXIT Base Support Library.
-
-  Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved.<BR>
-  SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#include <Base.h>
-#include <Uefi.h>
-#include <Library/VmgExitLib.h>
-
-/**
-  Perform VMGEXIT.
-
-  Sets the necessary fields of the GHCB, invokes the VMGEXIT instruction and
-  then handles the return actions.
-
-  The base library function returns an error in the form of a
-  GHCB_EVENT_INJECTION representing a GP_EXCEPTION.
-
-  @param[in, out]  Ghcb       A pointer to the GHCB
-  @param[in]       ExitCode   VMGEXIT code to be assigned to the SwExitCode
-                              field of the GHCB.
-  @param[in]       ExitInfo1  VMGEXIT information to be assigned to the
-                              SwExitInfo1 field of the GHCB.
-  @param[in]       ExitInfo2  VMGEXIT information to be assigned to the
-                              SwExitInfo2 field of the GHCB.
-
-  @retval  0                  VMGEXIT succeeded.
-  @return                     Exception number to be propagated, VMGEXIT
-                              processing did not succeed.
-
-**/
-UINT64
-EFIAPI
-VmgExit (
-  IN OUT GHCB    *Ghcb,
-  IN     UINT64  ExitCode,
-  IN     UINT64  ExitInfo1,
-  IN     UINT64  ExitInfo2
-  )
-{
-  GHCB_EVENT_INJECTION  Event;
-
-  Event.Uint64          = 0;
-  Event.Elements.Vector = GP_EXCEPTION;
-  Event.Elements.Type   = GHCB_EVENT_INJECTION_TYPE_EXCEPTION;
-  Event.Elements.Valid  = 1;
-
-  return Event.Uint64;
-}
-
-/**
-  Perform pre-VMGEXIT initialization/preparation.
-
-  Performs the necessary steps in preparation for invoking VMGEXIT. Must be
-  called before setting any fields within the GHCB.
-
-  @param[in, out]  Ghcb            A pointer to the GHCB
-  @param[in, out]  InterruptState  A pointer to hold the current interrupt
-                                   state, used for restoring in VmgDone ()
-
-**/
-VOID
-EFIAPI
-VmgInit (
-  IN OUT GHCB     *Ghcb,
-  IN OUT BOOLEAN  *InterruptState
-  )
-{
-}
-
-/**
-  Perform post-VMGEXIT cleanup.
-
-  Performs the necessary steps to cleanup after invoking VMGEXIT. Must be
-  called after obtaining needed fields within the GHCB.
-
-  @param[in, out]  Ghcb            A pointer to the GHCB
-  @param[in]       InterruptState  An indicator to conditionally (re)enable
-                                   interrupts
-
-**/
-VOID
-EFIAPI
-VmgDone (
-  IN OUT GHCB     *Ghcb,
-  IN     BOOLEAN  InterruptState
-  )
-{
-}
-
-/**
-  Marks a field at the specified offset as valid in the GHCB.
-
-  The ValidBitmap area represents the areas of the GHCB that have been marked
-  valid. Set the bit in ValidBitmap for the input offset.
-
-  @param[in, out] Ghcb    Pointer to the Guest-Hypervisor Communication Block
-  @param[in]      Offset  Qword offset in the GHCB to mark valid
-
-**/
-VOID
-EFIAPI
-VmgSetOffsetValid (
-  IN OUT GHCB           *Ghcb,
-  IN     GHCB_REGISTER  Offset
-  )
-{
-}
-
-/**
-  Checks if a specified offset is valid in the GHCB.
-
-  The ValidBitmap area represents the areas of the GHCB that have been marked
-  valid. Return whether the bit in the ValidBitmap is set for the input offset.
-
-  @param[in]  Ghcb            A pointer to the GHCB
-  @param[in]  Offset          Qword offset in the GHCB to mark valid
-
-  @retval TRUE                Offset is marked valid in the GHCB
-  @retval FALSE               Offset is not marked valid in the GHCB
-
-**/
-BOOLEAN
-EFIAPI
-VmgIsOffsetValid (
-  IN GHCB           *Ghcb,
-  IN GHCB_REGISTER  Offset
-  )
-{
-  return FALSE;
-}
-
-/**
-  Handle a #VC exception.
-
-  Performs the necessary processing to handle a #VC exception.
-
-  The base library function returns an error equal to VC_EXCEPTION,
-  to be propagated to the standard exception handling stack.
-
-  @param[in, out]  ExceptionType  Pointer to an EFI_EXCEPTION_TYPE to be set
-                                  as value to use on error.
-  @param[in, out]  SystemContext  Pointer to EFI_SYSTEM_CONTEXT
-
-  @retval  EFI_SUCCESS            Exception handled
-  @retval  EFI_UNSUPPORTED        #VC not supported, (new) exception value to
-                                  propagate provided
-  @retval  EFI_PROTOCOL_ERROR     #VC handling failed, (new) exception value to
-                                  propagate provided
-
-**/
-EFI_STATUS
-EFIAPI
-VmgExitHandleVc (
-  IN OUT EFI_EXCEPTION_TYPE  *ExceptionType,
-  IN OUT EFI_SYSTEM_CONTEXT  SystemContext
-  )
-{
-  *ExceptionType = VC_EXCEPTION;
-
-  return EFI_UNSUPPORTED;
-}
diff --git a/UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.inf b/UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.inf
deleted file mode 100644
index 4aab601939ff..000000000000
--- a/UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.inf
+++ /dev/null
@@ -1,28 +0,0 @@
-## @file
-#  VMGEXIT Support Library.
-#
-#  Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved.<BR>
-#  SPDX-License-Identifier: BSD-2-Clause-Patent
-#
-##
-
-[Defines]
-  INF_VERSION                    = 0x00010005
-  BASE_NAME                      = VmgExitLibNull
-  MODULE_UNI_FILE                = VmgExitLibNull.uni
-  FILE_GUID                      = 3cd7368f-ef9b-4a9b-9571-2ed93813677e
-  MODULE_TYPE                    = BASE
-  VERSION_STRING                 = 1.0
-  LIBRARY_CLASS                  = VmgExitLib
-
-[Sources.common]
-  VmgExitLibNull.c
-  VmTdExitNull.c
-
-[Packages]
-  MdePkg/MdePkg.dec
-  UefiCpuPkg/UefiCpuPkg.dec
-
-[LibraryClasses]
-  BaseLib
-
diff --git a/UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.uni b/UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.uni
deleted file mode 100644
index 8639bc0e8ce9..000000000000
--- a/UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.uni
+++ /dev/null
@@ -1,15 +0,0 @@
-// /** @file
-// VMGEXIT support library instance.
-//
-// VMGEXIT support library instance.
-//
-// Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved.<BR>
-// SPDX-License-Identifier: BSD-2-Clause-Patent
-//
-// **/
-
-
-#string STR_MODULE_ABSTRACT             #language en-US "VMGEXIT support NULL library instance"
-
-#string STR_MODULE_DESCRIPTION          #language en-US "VMGEXIT support NULL library instance."
-
diff --git a/UefiCpuPkg/UefiCpuPkg.dec b/UefiCpuPkg/UefiCpuPkg.dec
index 8058b679412f..cff239d5283e 100644
--- a/UefiCpuPkg/UefiCpuPkg.dec
+++ b/UefiCpuPkg/UefiCpuPkg.dec
@@ -53,9 +53,6 @@
   ##
   MpInitLib|Include/Library/MpInitLib.h
 
-  ##  @libraryclass  Provides function to support VMGEXIT processing.
-  VmgExitLib|Include/Library/VmgExitLib.h
-
   ##  @libraryclass  Provides function to support CcExit processing.
   CcExitLib|Include/Library/CcExitLib.h
 
diff --git a/UefiCpuPkg/UefiCpuPkg.dsc b/UefiCpuPkg/UefiCpuPkg.dsc
index 57c74ba844d2..67b0ce46e455 100644
--- a/UefiCpuPkg/UefiCpuPkg.dsc
+++ b/UefiCpuPkg/UefiCpuPkg.dsc
@@ -59,7 +59,6 @@
   PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
   PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf
   TpmMeasurementLib|MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.inf
-  VmgExitLib|UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.inf
   CcExitLib|UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.inf
   MicrocodeLib|UefiCpuPkg/Library/MicrocodeLib/MicrocodeLib.inf
   SmmCpuRendezvousLib|UefiCpuPkg/Library/SmmCpuRendezvousLib/SmmCpuRendezvousLib.inf
@@ -164,7 +163,6 @@
   UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLib.inf
   UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLibStm.inf
   UefiCpuPkg/Library/SmmCpuFeaturesLib/StandaloneMmCpuFeaturesLib.inf
-  UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.inf
   UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.inf
   UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationPei.inf
   UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationSmm.inf
-- 
2.29.2.windows.2


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH V2 9/9] Maintainers: Update the VmgExitLib to CcExitLib
  2022-11-03 23:19 [PATCH V2 0/9] Rename VmgExitLib to CcExitLib Min Xu
                   ` (7 preceding siblings ...)
  2022-11-03 23:19 ` [PATCH V2 8/9] UefiCpuPkg: " Min Xu
@ 2022-11-03 23:19 ` Min Xu
  2022-11-04  2:04 ` [PATCH V2 0/9] Rename " Yao, Jiewen
  9 siblings, 0 replies; 13+ messages in thread
From: Min Xu @ 2022-11-03 23:19 UTC (permalink / raw)
  To: devel
  Cc: Min M Xu, Michael D Kinney, Liming Gao, Erdem Aktas,
	Gerd Hoffmann, James Bottomley, Jiewen Yao, Tom Lendacky

From: Min M Xu <min.m.xu@intel.com>

BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=4123

VmgExitLib is renamed as CcExitLib. The related section in
Maintainers.txt should be updated as well.

Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <gaoliming@byosoft.com.cn>
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: Michael D Kinney <michael.d.kinney@intel.com>
Signed-off-by: Min Xu <min.m.xu@intel.com>
---
 Maintainers.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Maintainers.txt b/Maintainers.txt
index 889990fa566f..454b93420da4 100644
--- a/Maintainers.txt
+++ b/Maintainers.txt
@@ -475,7 +475,7 @@ F: OvmfPkg/Include/Library/MemEncryptSevLib.h
 F: OvmfPkg/IoMmuDxe/AmdSevIoMmu.*
 F: OvmfPkg/Library/BaseMemEncryptSevLib/
 F: OvmfPkg/Library/PlatformBootManagerLibGrub/
-F: OvmfPkg/Library/VmgExitLib/
+F: OvmfPkg/Library/CcExitLib/
 F: OvmfPkg/PlatformPei/AmdSev.c
 F: OvmfPkg/ResetVector/
 F: OvmfPkg/Sec/
-- 
2.29.2.windows.2


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [PATCH V2 0/9] Rename VmgExitLib to CcExitLib
  2022-11-03 23:19 [PATCH V2 0/9] Rename VmgExitLib to CcExitLib Min Xu
                   ` (8 preceding siblings ...)
  2022-11-03 23:19 ` [PATCH V2 9/9] Maintainers: Update the VmgExitLib to CcExitLib Min Xu
@ 2022-11-04  2:04 ` Yao, Jiewen
  9 siblings, 0 replies; 13+ messages in thread
From: Yao, Jiewen @ 2022-11-04  2:04 UTC (permalink / raw)
  To: Xu, Min M, devel@edk2.groups.io
  Cc: Dong, Eric, Ni, Ray, Brijesh Singh, Aktas, Erdem, Gerd Hoffmann,
	James Bottomley, Tom Lendacky, Dong, Guo, Rhodes, Sean, Lu, James,
	Guo, Gua, Kinney, Michael D, Gao, Liming

For the series, reviewed-by: Jiewen Yao <jiewen.yao@Intel.com>

> -----Original Message-----
> From: Xu, Min M <min.m.xu@intel.com>
> Sent: Friday, November 4, 2022 7:20 AM
> To: devel@edk2.groups.io
> Cc: Xu, Min M <min.m.xu@intel.com>; Dong, Eric <eric.dong@intel.com>;
> Ni, Ray <ray.ni@intel.com>; Brijesh Singh <brijesh.singh@amd.com>; Aktas,
> Erdem <erdemaktas@google.com>; Gerd Hoffmann <kraxel@redhat.com>;
> James Bottomley <jejb@linux.ibm.com>; Yao, Jiewen
> <jiewen.yao@intel.com>; Tom Lendacky <thomas.lendacky@amd.com>;
> Dong, Guo <guo.dong@intel.com>; Rhodes, Sean <sean@starlabs.systems>;
> Lu, James <james.lu@intel.com>; Guo, Gua <gua.guo@intel.com>; Kinney,
> Michael D <michael.d.kinney@intel.com>; Gao, Liming
> <gaoliming@byosoft.com.cn>
> Subject: [PATCH V2 0/9] Rename VmgExitLib to CcExitLib
> 
> 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-set creates CcExitLib which is a simple copy of VmgExitLib
> except some of the API names are renamed with a CcExitLib prefix. For
> example VmgExit is renamed as CcExitLibVmgExit.
> 
> To make sure the build will not be broken by the renaming, this patch-set
> first creates CcExitLib (Patch #1/2). Then VmgExitLib is replaced by
> CcExitLib in UefiCpuPkg/UefiPayloadPkg/OvmfPkg (Patch #3/4/5/6). After
> that VmgExitLib is deleted (Patch #7/8). At last Maintainers.txt
> is updated (Patch #9).
> 
> Code: https://github.com/mxu9/edk2/tree/CcExitLib.v2
> 
> v2 changes:
>  - Patch #3 is added to import CcExitLib in OvmfPkg's *.dsc. This is to
>    prevent the building from being broken in the following patches.
> 
> 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>
> 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: Michael D Kinney <michael.d.kinney@intel.com>
> Cc: Liming Gao <gaoliming@byosoft.com.cn>
> Signed-off-by: Min Xu <min.m.xu@intel.com>
> 
> Min M Xu (9):
>   UefiCpuPkg: Add CcExitLib
>   OvmfPkg: Implement CcExitLib
>   OvmfPkg: Add CcExitLib in *.dsc
>   UefiCpuPkg: Use CcExitLib instead of VmgExitLib
>   UefiPayloadPkg: Use CcExitLib instead of VmgExitLib
>   OvmfPkg: Use CcExitLib instead of VmgExitLib
>   OvmfPkg: Delete VmgExitLib
>   UefiCpuPkg: Delete VmgExitLib
>   Maintainers: Update the VmgExitLib to CcExitLib
> 
>  Maintainers.txt                               |   2 +-
>  OvmfPkg/AmdSev/AmdSevX64.dsc                  |   4 +-
>  OvmfPkg/Bhyve/BhyveX64.dsc                    |   2 +-
>  OvmfPkg/CloudHv/CloudHvX64.dsc                |   6 +-
>  OvmfPkg/IntelTdx/IntelTdxX64.dsc              |   4 +-
>  .../DxeMemEncryptSevLib.inf                   |   2 +-
>  .../PeiMemEncryptSevLib.inf                   |   2 +-
>  .../SecMemEncryptSevLib.inf                   |   2 +-
>  .../X64/SnpPageStateChangeInternal.c          |  10 +-
>  .../VmgExitLib.c => CcExitLib/CcExitLib.c}    |  23 +--
>  .../CcExitLib.inf}                            |  19 +--
>  .../CcExitTd.h}                               |   6 +-
>  .../CcExitVcHandler.c}                        | 133 +++++++++---------
>  .../CcExitVcHandler.h}                        |  10 +-
>  .../CcExitVeHandler.c}                        |   8 +-
>  .../PeiDxeCcExitVcHandler.c}                  |  12 +-
>  .../SecCcExitLib.inf}                         |  16 +--
>  .../SecCcExitVcHandler.c}                     |  12 +-
>  .../X64/TdVmcallCpuid.nasm                    |   4 +-
>  OvmfPkg/Microvm/MicrovmX64.dsc                |   4 +-
>  OvmfPkg/OvmfPkgIa32.dsc                       |   4 +-
>  OvmfPkg/OvmfPkgIa32X64.dsc                    |   4 +-
>  OvmfPkg/OvmfPkgX64.dsc                        |   6 +-
>  OvmfPkg/OvmfXen.dsc                           |   2 +-
>  OvmfPkg/PlatformPei/AmdSev.c                  |  10 +-
>  OvmfPkg/PlatformPei/PlatformPei.inf           |   2 +-
>  .../FvbServicesRuntimeDxe.inf                 |   2 +-
>  .../QemuFlashDxe.c                            |  10 +-
>  .../Library/{VmgExitLib.h => CcExitLib.h}     |  29 ++--
>  .../CcExitLibNull.c}                          |  47 +++++--
>  .../CcExitLibNull.inf}                        |  14 +-
>  .../Library/CcExitLibNull/CcExitLibNull.uni   |  14 ++
>  .../DxeCpuExceptionHandlerLib.inf             |   2 +-
>  .../PeiCpuExceptionHandlerLib.inf             |   2 +-
>  .../PeiDxeSmmCpuException.c                   |   6 +-
>  .../SecPeiCpuException.c                      |   6 +-
>  .../SecPeiCpuExceptionHandlerLib.inf          |   2 +-
>  .../SmmCpuExceptionHandlerLib.inf             |   2 +-
>  .../Xcode5SecPeiCpuExceptionHandlerLib.inf    |   2 +-
>  UefiCpuPkg/Library/MpInitLib/AmdSev.c         |  10 +-
>  UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf |   2 +-
>  UefiCpuPkg/Library/MpInitLib/DxeMpLib.c       |   8 +-
>  UefiCpuPkg/Library/MpInitLib/MpLib.c          |   2 +-
>  UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf |   2 +-
>  UefiCpuPkg/Library/MpInitLib/X64/AmdSev.c     |  10 +-
>  .../Library/VmgExitLibNull/VmTdExitNull.c     |  38 -----
>  .../Library/VmgExitLibNull/VmgExitLibNull.uni |  15 --
>  UefiCpuPkg/UefiCpuPkg.dec                     |   4 +-
>  UefiCpuPkg/UefiCpuPkg.dsc                     |   4 +-
>  UefiPayloadPkg/UefiPayloadPkg.dsc             |   2 +-
>  50 files changed, 269 insertions(+), 275 deletions(-)
>  rename OvmfPkg/Library/{VmgExitLib/VmgExitLib.c => CcExitLib/CcExitLib.c}
> (89%)
>  rename OvmfPkg/Library/{VmgExitLib/VmgExitLib.inf =>
> CcExitLib/CcExitLib.inf} (60%)
>  rename OvmfPkg/Library/{VmgExitLib/VmTdExitHandler.h =>
> CcExitLib/CcExitTd.h} (84%)
>  rename OvmfPkg/Library/{VmgExitLib/VmgExitVcHandler.c =>
> CcExitLib/CcExitVcHandler.c} (90%)
>  rename OvmfPkg/Library/{VmgExitLib/VmgExitVcHandler.h =>
> CcExitLib/CcExitVcHandler.h} (85%)
>  rename OvmfPkg/Library/{VmgExitLib/VmTdExitVeHandler.c =>
> CcExitLib/CcExitVeHandler.c} (94%)
>  rename OvmfPkg/Library/{VmgExitLib/PeiDxeVmgExitVcHandler.c =>
> CcExitLib/PeiDxeCcExitVcHandler.c} (87%)
>  rename OvmfPkg/Library/{VmgExitLib/SecVmgExitLib.inf =>
> CcExitLib/SecCcExitLib.inf} (73%)
>  rename OvmfPkg/Library/{VmgExitLib/SecVmgExitVcHandler.c =>
> CcExitLib/SecCcExitVcHandler.c} (88%)
>  rename OvmfPkg/Library/{VmgExitLib =>
> CcExitLib}/X64/TdVmcallCpuid.nasm (93%)
>  rename UefiCpuPkg/Include/Library/{VmgExitLib.h => CcExitLib.h} (86%)
>  rename UefiCpuPkg/Library/{VmgExitLibNull/VmgExitLibNull.c =>
> CcExitLibNull/CcExitLibNull.c} (76%)
>  rename UefiCpuPkg/Library/{VmgExitLibNull/VmgExitLibNull.inf =>
> CcExitLibNull/CcExitLibNull.inf} (50%)
>  create mode 100644 UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.uni
>  delete mode 100644 UefiCpuPkg/Library/VmgExitLibNull/VmTdExitNull.c
>  delete mode 100644
> UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.uni
> 
> --
> 2.29.2.windows.2


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [edk2-devel] [PATCH V2 1/9] UefiCpuPkg: Add CcExitLib
  2022-11-03 23:19 ` [PATCH V2 1/9] UefiCpuPkg: Add CcExitLib Min Xu
@ 2022-11-04 14:34   ` Lendacky, Thomas
  2022-11-05  1:33     ` Min Xu
  0 siblings, 1 reply; 13+ messages in thread
From: Lendacky, Thomas @ 2022-11-04 14:34 UTC (permalink / raw)
  To: devel, min.m.xu
  Cc: Eric Dong, Ray Ni, Brijesh Singh, Erdem Aktas, Gerd Hoffmann,
	James Bottomley, Jiewen Yao

On 11/3/22 18:19, Min Xu via groups.io wrote:
> From: Min M Xu <min.m.xu@intel.com>
> 
> BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=4123
> 
> CcExitLib is designed to support handling #VC/#VE exceptions and issuing
> VMGEXIT instructions. It can be used to perform these:
>    - Handling #VC exceptions
>    - Handling #VE exceptions
>    - Preparing for and issuing a VMGEXIT
>    - Performing MMIO-related write operations to support flash emulation
>    - Performing AP related boot opeations
> 
> The base functions in this driver will not do anything and will return
> an error if a return value is required. It is expected that other packages
> (like OvmfPkg) will create a version of the library to fully support an
> CC gueste (such as SEV-ES and TDX).
> 
> 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>
> Signed-off-by: Min Xu <min.m.xu@intel.com>
> ---
>   UefiCpuPkg/Include/Library/CcExitLib.h        | 176 ++++++++++++++++
>   .../Library/CcExitLibNull/CcExitLibNull.c     | 194 ++++++++++++++++++
>   .../Library/CcExitLibNull/CcExitLibNull.inf   |  28 +++
>   .../Library/CcExitLibNull/CcExitLibNull.uni   |  14 ++
>   UefiCpuPkg/UefiCpuPkg.dec                     |   3 +
>   5 files changed, 415 insertions(+)
>   create mode 100644 UefiCpuPkg/Include/Library/CcExitLib.h
>   create mode 100644 UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.c
>   create mode 100644 UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.inf
>   create mode 100644 UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.uni
> 
> diff --git a/UefiCpuPkg/Include/Library/CcExitLib.h b/UefiCpuPkg/Include/Library/CcExitLib.h
> new file mode 100644
> index 000000000000..40372e10b39e
> --- /dev/null
> +++ b/UefiCpuPkg/Include/Library/CcExitLib.h
> @@ -0,0 +1,176 @@
> +/** @file
> +  Public header file for the CcExitLib.
> +
> +  This library class defines some routines used for below CcExit handler.
> +   - Invoking the VMGEXIT instruction in support of SEV-ES and to handle
> +     #VC exceptions.
> +   - Handle #VE exception in TDX.
> +
> +  Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved.<BR>
> +  Copyright (c) 2020 - 2022, Intel Corporation. All rights reserved.<BR>
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#ifndef CC_EXIT_LIB_H_
> +#define CC_EXIT_LIB_H_
> +
> +#include <Protocol/DebugSupport.h>
> +#include <Register/Amd/Ghcb.h>
> +
> +#define VE_EXCEPTION  20
> +
> +/**
> +  Perform VMGEXIT.
> +
> +  Sets the necessary fields of the GHCB, invokes the VMGEXIT instruction and
> +  then handles the return actions.
> +
> +  @param[in, out]  Ghcb       A pointer to the GHCB
> +  @param[in]       ExitCode   VMGEXIT code to be assigned to the SwExitCode
> +                              field of the GHCB.
> +  @param[in]       ExitInfo1  VMGEXIT information to be assigned to the
> +                              SwExitInfo1 field of the GHCB.
> +  @param[in]       ExitInfo2  VMGEXIT information to be assigned to the
> +                              SwExitInfo2 field of the GHCB.
> +
> +  @retval  0                  VMGEXIT succeeded.
> +  @return                     Exception number to be propagated, VMGEXIT
> +                              processing did not succeed.
> +
> +**/
> +UINT64
> +EFIAPI
> +CcExitLibVmgExit (
> +  IN OUT GHCB    *Ghcb,
> +  IN     UINT64  ExitCode,
> +  IN     UINT64  ExitInfo1,
> +  IN     UINT64  ExitInfo2
> +  );
> +
> +/**
> +  Perform pre-VMGEXIT initialization/preparation.
> +
> +  Performs the necessary steps in preparation for invoking VMGEXIT. Must be
> +  called before setting any fields within the GHCB.
> +
> +  @param[in, out]  Ghcb            A pointer to the GHCB
> +  @param[in, out]  InterruptState  A pointer to hold the current interrupt
> +                                   state, used for restoring in CcExitLibVmgDone ()
> +
> +**/
> +VOID
> +EFIAPI
> +CcExitLibVmgInit (
> +  IN OUT GHCB     *Ghcb,
> +  IN OUT BOOLEAN  *InterruptState
> +  );
> +
> +/**
> +  Perform post-VMGEXIT cleanup.
> +
> +  Performs the necessary steps to cleanup after invoking VMGEXIT. Must be
> +  called after obtaining needed fields within the GHCB.
> +
> +  @param[in, out]  Ghcb            A pointer to the GHCB
> +  @param[in]       InterruptState  An indicator to conditionally (re)enable
> +                                   interrupts
> +
> +**/
> +VOID
> +EFIAPI
> +CcExitLibVmgDone (
> +  IN OUT GHCB     *Ghcb,
> +  IN     BOOLEAN  InterruptState
> +  );
> +
> +/**
> +  Marks a specified offset as valid in the GHCB.
> +
> +  The ValidBitmap area represents the areas of the GHCB that have been marked
> +  valid. Set the bit in ValidBitmap for the input offset.
> +
> +  @param[in, out]  Ghcb       A pointer to the GHCB
> +  @param[in]       Offset     Qword offset in the GHCB to mark valid
> +
> +**/
> +VOID
> +EFIAPI
> +CcExitLibVmgSetOffsetValid (
> +  IN OUT GHCB           *Ghcb,
> +  IN     GHCB_REGISTER  Offset
> +  );
> +
> +/**
> +  Checks if a specified offset is valid in the GHCB.
> +
> +  The ValidBitmap area represents the areas of the GHCB that have been marked
> +  valid. Return whether the bit in the ValidBitmap is set for the input offset.
> +
> +  @param[in]  Ghcb            A pointer to the GHCB
> +  @param[in]  Offset          Qword offset in the GHCB to mark valid
> +
> +  @retval TRUE                Offset is marked valid in the GHCB
> +  @retval FALSE               Offset is not marked valid in the GHCB
> +
> +**/
> +BOOLEAN
> +EFIAPI
> +CcExitLibVmgIsOffsetValid (
> +  IN GHCB           *Ghcb,
> +  IN GHCB_REGISTER  Offset
> +  );
> +
> +/**
> +  Handle a #VC exception.
> +
> +  Performs the necessary processing to handle a #VC exception.
> +
> +  The base library function returns an error equal to VC_EXCEPTION,
> +  to be propagated to the standard exception handling stack.
> +
> +  @param[in, out]  ExceptionType  Pointer to an EFI_EXCEPTION_TYPE to be set
> +                                  as value to use on error.
> +  @param[in, out]  SystemContext  Pointer to EFI_SYSTEM_CONTEXT
> +
> +  @retval  EFI_SUCCESS            Exception handled
> +  @retval  EFI_UNSUPPORTED        #VC not supported, (new) exception value to
> +                                  propagate provided
> +  @retval  EFI_PROTOCOL_ERROR     #VC handling failed, (new) exception value to
> +                                  propagate provided
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +CcExitHandleVc (

Sorry I didn't pick up on this before, but any reason this isn't 
CcExitLibHandleVc() to match the other APIs or have the other APIs just be 
CcExit (since the "Lib" part seems a bit excessive)?

(Same for CcExitHandleVe below)

Thanks,
Tom

> +  IN OUT EFI_EXCEPTION_TYPE  *ExceptionType,
> +  IN OUT EFI_SYSTEM_CONTEXT  SystemContext
> +  );
> +
> +/**
> +  Handle a #VE exception.
> +
> +  Performs the necessary processing to handle a #VE exception.
> +
> +  The base library function returns an error equal to VE_EXCEPTION,
> +  to be propagated to the standard exception handling stack.
> +
> +  @param[in, out]  ExceptionType  Pointer to an EFI_EXCEPTION_TYPE to be set
> +                                  as value to use on error.
> +  @param[in, out]  SystemContext  Pointer to EFI_SYSTEM_CONTEXT
> +
> +  @retval  EFI_SUCCESS            Exception handled
> +  @retval  EFI_UNSUPPORTED        #VE not supported, (new) exception value to
> +                                  propagate provided
> +  @retval  EFI_PROTOCOL_ERROR     #VE handling failed, (new) exception value to
> +                                  propagate provided
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +CcExitHandleVe (
> +  IN OUT EFI_EXCEPTION_TYPE  *ExceptionType,
> +  IN OUT EFI_SYSTEM_CONTEXT  SystemContext
> +  );
> +
> +#endif
> diff --git a/UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.c b/UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.c
> new file mode 100644
> index 000000000000..bd23793f1e04
> --- /dev/null
> +++ b/UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.c
> @@ -0,0 +1,194 @@
> +/** @file
> +  CcExit Base Support Library.
> +
> +  Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved.<BR>
> +  Copyright (c) 2020 - 2022, Intel Corporation. All rights reserved.<BR>
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#include <Base.h>
> +#include <Uefi.h>
> +#include <Library/CcExitLib.h>
> +
> +/**
> +  Perform VMGEXIT.
> +
> +  Sets the necessary fields of the GHCB, invokes the VMGEXIT instruction and
> +  then handles the return actions.
> +
> +  The base library function returns an error in the form of a
> +  GHCB_EVENT_INJECTION representing a GP_EXCEPTION.
> +
> +  @param[in, out]  Ghcb       A pointer to the GHCB
> +  @param[in]       ExitCode   VMGEXIT code to be assigned to the SwExitCode
> +                              field of the GHCB.
> +  @param[in]       ExitInfo1  VMGEXIT information to be assigned to the
> +                              SwExitInfo1 field of the GHCB.
> +  @param[in]       ExitInfo2  VMGEXIT information to be assigned to the
> +                              SwExitInfo2 field of the GHCB.
> +
> +  @retval  0                  VMGEXIT succeeded.
> +  @return                     Exception number to be propagated, VMGEXIT
> +                              processing did not succeed.
> +
> +**/
> +UINT64
> +EFIAPI
> +CcExitLibVmgExit (
> +  IN OUT GHCB    *Ghcb,
> +  IN     UINT64  ExitCode,
> +  IN     UINT64  ExitInfo1,
> +  IN     UINT64  ExitInfo2
> +  )
> +{
> +  GHCB_EVENT_INJECTION  Event;
> +
> +  Event.Uint64          = 0;
> +  Event.Elements.Vector = GP_EXCEPTION;
> +  Event.Elements.Type   = GHCB_EVENT_INJECTION_TYPE_EXCEPTION;
> +  Event.Elements.Valid  = 1;
> +
> +  return Event.Uint64;
> +}
> +
> +/**
> +  Perform pre-VMGEXIT initialization/preparation.
> +
> +  Performs the necessary steps in preparation for invoking VMGEXIT. Must be
> +  called before setting any fields within the GHCB.
> +
> +  @param[in, out]  Ghcb            A pointer to the GHCB
> +  @param[in, out]  InterruptState  A pointer to hold the current interrupt
> +                                   state, used for restoring in CcExitLibVmgDone ()
> +
> +**/
> +VOID
> +EFIAPI
> +CcExitLibVmgInit (
> +  IN OUT GHCB     *Ghcb,
> +  IN OUT BOOLEAN  *InterruptState
> +  )
> +{
> +}
> +
> +/**
> +  Perform post-VMGEXIT cleanup.
> +
> +  Performs the necessary steps to cleanup after invoking VMGEXIT. Must be
> +  called after obtaining needed fields within the GHCB.
> +
> +  @param[in, out]  Ghcb            A pointer to the GHCB
> +  @param[in]       InterruptState  An indicator to conditionally (re)enable
> +                                   interrupts
> +
> +**/
> +VOID
> +EFIAPI
> +CcExitLibVmgDone (
> +  IN OUT GHCB     *Ghcb,
> +  IN     BOOLEAN  InterruptState
> +  )
> +{
> +}
> +
> +/**
> +  Marks a field at the specified offset as valid in the GHCB.
> +
> +  The ValidBitmap area represents the areas of the GHCB that have been marked
> +  valid. Set the bit in ValidBitmap for the input offset.
> +
> +  @param[in, out] Ghcb    Pointer to the Guest-Hypervisor Communication Block
> +  @param[in]      Offset  Qword offset in the GHCB to mark valid
> +
> +**/
> +VOID
> +EFIAPI
> +CcExitLibVmgSetOffsetValid (
> +  IN OUT GHCB           *Ghcb,
> +  IN     GHCB_REGISTER  Offset
> +  )
> +{
> +}
> +
> +/**
> +  Checks if a specified offset is valid in the GHCB.
> +
> +  The ValidBitmap area represents the areas of the GHCB that have been marked
> +  valid. Return whether the bit in the ValidBitmap is set for the input offset.
> +
> +  @param[in]  Ghcb            A pointer to the GHCB
> +  @param[in]  Offset          Qword offset in the GHCB to mark valid
> +
> +  @retval TRUE                Offset is marked valid in the GHCB
> +  @retval FALSE               Offset is not marked valid in the GHCB
> +
> +**/
> +BOOLEAN
> +EFIAPI
> +CcExitLibVmgIsOffsetValid (
> +  IN GHCB           *Ghcb,
> +  IN GHCB_REGISTER  Offset
> +  )
> +{
> +  return FALSE;
> +}
> +
> +/**
> +  Handle a #VC exception.
> +
> +  Performs the necessary processing to handle a #VC exception.
> +
> +  The base library function returns an error equal to VC_EXCEPTION,
> +  to be propagated to the standard exception handling stack.
> +
> +  @param[in, out]  ExceptionType  Pointer to an EFI_EXCEPTION_TYPE to be set
> +                                  as value to use on error.
> +  @param[in, out]  SystemContext  Pointer to EFI_SYSTEM_CONTEXT
> +
> +  @retval  EFI_SUCCESS            Exception handled
> +  @retval  EFI_UNSUPPORTED        #VC not supported, (new) exception value to
> +                                  propagate provided
> +  @retval  EFI_PROTOCOL_ERROR     #VC handling failed, (new) exception value to
> +                                  propagate provided
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +CcExitHandleVc (
> +  IN OUT EFI_EXCEPTION_TYPE  *ExceptionType,
> +  IN OUT EFI_SYSTEM_CONTEXT  SystemContext
> +  )
> +{
> +  *ExceptionType = VC_EXCEPTION;
> +
> +  return EFI_UNSUPPORTED;
> +}
> +
> +/**
> +  Handle a #VE exception.
> +
> +  Performs the necessary processing to handle a #VE exception.
> +
> +  @param[in, out]  ExceptionType  Pointer to an EFI_EXCEPTION_TYPE to be set
> +                                  as value to use on error.
> +  @param[in, out]  SystemContext  Pointer to EFI_SYSTEM_CONTEXT
> +
> +  @retval  EFI_SUCCESS            Exception handled
> +  @retval  EFI_UNSUPPORTED        #VE not supported, (new) exception value to
> +                                  propagate provided
> +  @retval  EFI_PROTOCOL_ERROR     #VE handling failed, (new) exception value to
> +                                  propagate provided
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +CcExitHandleVe (
> +  IN OUT EFI_EXCEPTION_TYPE  *ExceptionType,
> +  IN OUT EFI_SYSTEM_CONTEXT  SystemContext
> +  )
> +{
> +  *ExceptionType = VE_EXCEPTION;
> +
> +  return EFI_UNSUPPORTED;
> +}
> diff --git a/UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.inf b/UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.inf
> new file mode 100644
> index 000000000000..c1f53e42dbe4
> --- /dev/null
> +++ b/UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.inf
> @@ -0,0 +1,28 @@
> +## @file
> +#  CcExit Base Support Library.
> +#
> +#  Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved.<BR>
> +#  Copyright (c) 2020 - 2022, Intel Corporation. All rights reserved.<BR>
> +#  SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +[Defines]
> +  INF_VERSION                    = 0x00010005
> +  BASE_NAME                      = CcExitLibNull
> +  MODULE_UNI_FILE                = CcExitLibNull.uni
> +  FILE_GUID                      = 4029bbf2-ed6c-4cf6-ac17-a0213684ae41
> +  MODULE_TYPE                    = BASE
> +  VERSION_STRING                 = 1.0
> +  LIBRARY_CLASS                  = CcExitLib
> +
> +[Sources.common]
> +  CcExitLibNull.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  UefiCpuPkg/UefiCpuPkg.dec
> +
> +[LibraryClasses]
> +  BaseLib
> +
> diff --git a/UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.uni b/UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.uni
> new file mode 100644
> index 000000000000..b18ae8792ed7
> --- /dev/null
> +++ b/UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.uni
> @@ -0,0 +1,14 @@
> +// /** @file
> +// CcExitLib instance.
> +//
> +// Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved.<BR>
> +// Copyright (c) 2020 - 2022, Intel Corporation. All rights reserved.<BR>
> +// SPDX-License-Identifier: BSD-2-Clause-Patent
> +//
> +// **/
> +
> +
> +#string STR_MODULE_ABSTRACT             #language en-US "CcExitLib NULL instance"
> +
> +#string STR_MODULE_DESCRIPTION          #language en-US "CcExitLib NULL instance."
> +
> diff --git a/UefiCpuPkg/UefiCpuPkg.dec b/UefiCpuPkg/UefiCpuPkg.dec
> index 718323d9042c..8058b679412f 100644
> --- a/UefiCpuPkg/UefiCpuPkg.dec
> +++ b/UefiCpuPkg/UefiCpuPkg.dec
> @@ -56,6 +56,9 @@
>     ##  @libraryclass  Provides function to support VMGEXIT processing.
>     VmgExitLib|Include/Library/VmgExitLib.h
>   
> +  ##  @libraryclass  Provides function to support CcExit processing.
> +  CcExitLib|Include/Library/CcExitLib.h
> +
>     ##  @libraryclass  Provides function to get CPU cache information.
>     CpuCacheInfoLib|Include/Library/CpuCacheInfoLib.h
>   

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [edk2-devel] [PATCH V2 1/9] UefiCpuPkg: Add CcExitLib
  2022-11-04 14:34   ` [edk2-devel] " Lendacky, Thomas
@ 2022-11-05  1:33     ` Min Xu
  0 siblings, 0 replies; 13+ messages in thread
From: Min Xu @ 2022-11-05  1:33 UTC (permalink / raw)
  To: Tom Lendacky, devel@edk2.groups.io
  Cc: Dong, Eric, Ni, Ray, Brijesh Singh, Aktas, Erdem, Gerd Hoffmann,
	James Bottomley, Yao, Jiewen

On November 4, 2022 10:35 PM, Tom Lendacky wrote:
> On 11/3/22 18:19, Min Xu via groups.io wrote:
> > From: Min M Xu <min.m.xu@intel.com>
> >
> > BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=4123
> >
> > +
> > +/**
> > +  Handle a #VC exception.
> > +
> > +  Performs the necessary processing to handle a #VC exception.
> > +
> > +  The base library function returns an error equal to VC_EXCEPTION,
> > + to be propagated to the standard exception handling stack.
> > +
> > +  @param[in, out]  ExceptionType  Pointer to an EFI_EXCEPTION_TYPE to
> be set
> > +                                  as value to use on error.
> > +  @param[in, out]  SystemContext  Pointer to EFI_SYSTEM_CONTEXT
> > +
> > +  @retval  EFI_SUCCESS            Exception handled
> > +  @retval  EFI_UNSUPPORTED        #VC not supported, (new) exception
> value to
> > +                                  propagate provided
> > +  @retval  EFI_PROTOCOL_ERROR     #VC handling failed, (new) exception
> value to
> > +                                  propagate provided
> > +
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +CcExitHandleVc (
> 
> Sorry I didn't pick up on this before, but any reason this isn't
> CcExitLibHandleVc() to match the other APIs or have the other APIs just be
> CcExit (since the "Lib" part seems a bit excessive)?
> 
> (Same for CcExitHandleVe below)
> 
Ah it is my fault. It will should be the same as other APIs. They will be updated in the next version.

Thanks
Min

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2022-11-05  1:34 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-11-03 23:19 [PATCH V2 0/9] Rename VmgExitLib to CcExitLib Min Xu
2022-11-03 23:19 ` [PATCH V2 1/9] UefiCpuPkg: Add CcExitLib Min Xu
2022-11-04 14:34   ` [edk2-devel] " Lendacky, Thomas
2022-11-05  1:33     ` Min Xu
2022-11-03 23:19 ` [PATCH V2 2/9] OvmfPkg: Implement CcExitLib Min Xu
2022-11-03 23:19 ` [PATCH V2 3/9] OvmfPkg: Add CcExitLib in *.dsc Min Xu
2022-11-03 23:19 ` [PATCH V2 4/9] UefiCpuPkg: Use CcExitLib instead of VmgExitLib Min Xu
2022-11-03 23:19 ` [PATCH V2 5/9] UefiPayloadPkg: " Min Xu
2022-11-03 23:19 ` [PATCH V2 6/9] OvmfPkg: " Min Xu
2022-11-03 23:19 ` [PATCH V2 7/9] OvmfPkg: Delete VmgExitLib Min Xu
2022-11-03 23:19 ` [PATCH V2 8/9] UefiCpuPkg: " Min Xu
2022-11-03 23:19 ` [PATCH V2 9/9] Maintainers: Update the VmgExitLib to CcExitLib Min Xu
2022-11-04  2:04 ` [PATCH V2 0/9] Rename " Yao, Jiewen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox