[edk2-devel] [PATCH 10/12] OvmfPkg/VmgExitLib: Support nested #VCs

Laszlo Ersek lersek at redhat.com
Tue Jan 5 10:08:35 UTC 2021


On 12/15/20 21:51, Lendacky, Thomas wrote:
> From: Tom Lendacky <thomas.lendacky at amd.com>
> 
> BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3108
> 
> In order to be able to issue messages or make interface calls that cause
> another #VC (e.g. GetLocalApicBaseAddress () issues RDMSR), add support
> for nested #VCs.
> 
> In order to support nested #VCs, GHCB backup pages are required. If a #VC
> is received while currently processing a #VC, a backup of the current GHCB
> content is made. This allows the #VC handler to continue processing the
> new #VC. Upon completion of the new #VC, the GHCB is restored from the
> backup page. The #VC recursion level is tracked in the per-vCPU variable
> area.
> 
> Support is added to handle up to one nested #VC (or two #VCs total). If
> a second nested #VC is encountered, an ASSERT will be issued and the vCPU
> will enter CpuDeadLoop ().
> 
> For SEC, the GHCB backup pages are reserved in the OvmfPkgX64.fdf memory
> layout, with two new fixed PCDs to provide the address and size of the
> backup area.
> 
> For PEI/DXE, the GHCB backup pages are allocated as boot services pages
> using the memory allocation library.
> 
> Cc: Jordan Justen <jordan.l.justen at intel.com>
> Cc: Laszlo Ersek <lersek at redhat.com>
> Cc: Ard Biesheuvel <ard.biesheuvel at arm.com>
> Cc: Brijesh Singh <brijesh.singh at amd.com>
> Signed-off-by: Tom Lendacky <thomas.lendacky at amd.com>
> ---
>  OvmfPkg/OvmfPkg.dec                           |   2 +
>  OvmfPkg/AmdSev/AmdSevX64.dsc                  |   1 +
>  OvmfPkg/OvmfPkgX64.dsc                        |   1 +
>  OvmfPkg/AmdSev/AmdSevX64.fdf                  |   3 +
>  OvmfPkg/OvmfPkgX64.fdf                        |   3 +
>  OvmfPkg/Library/VmgExitLib/SecVmgExitLib.inf  |  43 +++++++
>  OvmfPkg/Library/VmgExitLib/VmgExitLib.inf     |   4 +-
>  OvmfPkg/Include/Library/MemEncryptSevLib.h    |  23 ++++
>  OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.h |  53 +++++++++
>  .../VmgExitLib/PeiDxeVmgExitVcHandler.c       | 103 +++++++++++++++++
>  .../Library/VmgExitLib/SecVmgExitVcHandler.c  | 109 ++++++++++++++++++
>  OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c |  48 ++++----
>  OvmfPkg/PlatformPei/AmdSev.c                  |  38 +++++-
>  13 files changed, 404 insertions(+), 27 deletions(-)
>  create mode 100644 OvmfPkg/Library/VmgExitLib/SecVmgExitLib.inf
>  create mode 100644 OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.h
>  create mode 100644 OvmfPkg/Library/VmgExitLib/PeiDxeVmgExitVcHandler.c
>  create mode 100644 OvmfPkg/Library/VmgExitLib/SecVmgExitVcHandler.c

I've reviewed the higher-level structure of this patch; it seems OK.

Acked-by: Laszlo Ersek <lersek at redhat.com>

Thanks
Laszlo

> diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec
> index 8a294116efaa..9731f09381a9 100644
> --- a/OvmfPkg/OvmfPkg.dec
> +++ b/OvmfPkg/OvmfPkg.dec
> @@ -304,6 +304,8 @@ [PcdsFixedAtBuild]
>    ## The base address of the SEC GHCB page used by SEV-ES.
>    gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBase|0|UINT32|0x40
>    gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbSize|0|UINT32|0x41
> +  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupBase|0|UINT32|0x44
> +  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupSize|0|UINT32|0x45
>  
>    ## The base address and size of the SEV Launch Secret Area provisioned
>    #  after remote attestation.  If this is set in the .fdf, the platform
> diff --git a/OvmfPkg/AmdSev/AmdSevX64.dsc b/OvmfPkg/AmdSev/AmdSevX64.dsc
> index c742ec54cb57..3e5a3f648ad5 100644
> --- a/OvmfPkg/AmdSev/AmdSevX64.dsc
> +++ b/OvmfPkg/AmdSev/AmdSevX64.dsc
> @@ -236,6 +236,7 @@ [LibraryClasses.common.SEC]
>  !else
>    CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf
>  !endif
> +  VmgExitLib|OvmfPkg/Library/VmgExitLib/SecVmgExitLib.inf
>  
>  [LibraryClasses.common.PEI_CORE]
>    HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf
> diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc
> index 3e008855fbc1..226b576545a9 100644
> --- a/OvmfPkg/OvmfPkgX64.dsc
> +++ b/OvmfPkg/OvmfPkgX64.dsc
> @@ -264,6 +264,7 @@ [LibraryClasses.common.SEC]
>  !else
>    CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf
>  !endif
> +  VmgExitLib|OvmfPkg/Library/VmgExitLib/SecVmgExitLib.inf
>  
>  [LibraryClasses.common.PEI_CORE]
>    HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf
> diff --git a/OvmfPkg/AmdSev/AmdSevX64.fdf b/OvmfPkg/AmdSev/AmdSevX64.fdf
> index e8fd4b8c7b89..c0098502aa90 100644
> --- a/OvmfPkg/AmdSev/AmdSevX64.fdf
> +++ b/OvmfPkg/AmdSev/AmdSevX64.fdf
> @@ -62,6 +62,9 @@ [FD.MEMFD]
>  0x00C000|0x001000
>  gUefiOvmfPkgTokenSpaceGuid.PcdSevLaunchSecretBase|gUefiOvmfPkgTokenSpaceGuid.PcdSevLaunchSecretSize
>  
> +0x00D000|0x001000
> +gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupSize
> +
>  0x010000|0x010000
>  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize
>  
> diff --git a/OvmfPkg/OvmfPkgX64.fdf b/OvmfPkg/OvmfPkgX64.fdf
> index 17ba9e177ac3..31fe58566bb5 100644
> --- a/OvmfPkg/OvmfPkgX64.fdf
> +++ b/OvmfPkg/OvmfPkgX64.fdf
> @@ -85,6 +85,9 @@ [FD.MEMFD]
>  0x00B000|0x001000
>  gUefiCpuPkgTokenSpaceGuid.PcdSevEsWorkAreaBase|gUefiCpuPkgTokenSpaceGuid.PcdSevEsWorkAreaSize
>  
> +0x00C000|0x001000
> +gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupSize
> +
>  0x010000|0x010000
>  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize
>  
> diff --git a/OvmfPkg/Library/VmgExitLib/SecVmgExitLib.inf b/OvmfPkg/Library/VmgExitLib/SecVmgExitLib.inf
> new file mode 100644
> index 000000000000..df14de3c21bc
> --- /dev/null
> +++ b/OvmfPkg/Library/VmgExitLib/SecVmgExitLib.inf
> @@ -0,0 +1,43 @@
> +## @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
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  OvmfPkg/OvmfPkg.dec
> +  UefiCpuPkg/UefiCpuPkg.dec
> +
> +[LibraryClasses]
> +  BaseLib
> +  BaseMemoryLib
> +  DebugLib
> +  PcdLib
> +
> +[FixedPcd]
> +  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupBase
> +  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupSize
> +
> diff --git a/OvmfPkg/Library/VmgExitLib/VmgExitLib.inf b/OvmfPkg/Library/VmgExitLib/VmgExitLib.inf
> index d003ac63173e..b3c3e56ecff8 100644
> --- a/OvmfPkg/Library/VmgExitLib/VmgExitLib.inf
> +++ b/OvmfPkg/Library/VmgExitLib/VmgExitLib.inf
> @@ -12,7 +12,7 @@ [Defines]
>    FILE_GUID                      = 0e923c25-13cd-430b-8714-ffe85652a97b
>    MODULE_TYPE                    = BASE
>    VERSION_STRING                 = 1.0
> -  LIBRARY_CLASS                  = VmgExitLib
> +  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.
> @@ -23,6 +23,8 @@ [Defines]
>  [Sources.common]
>    VmgExitLib.c
>    VmgExitVcHandler.c
> +  VmgExitVcHandler.h
> +  PeiDxeVmgExitVcHandler.c
>  
>  [Packages]
>    MdePkg/MdePkg.dec
> diff --git a/OvmfPkg/Include/Library/MemEncryptSevLib.h b/OvmfPkg/Include/Library/MemEncryptSevLib.h
> index 421b2e2c2c1e..eb400387e8e2 100644
> --- a/OvmfPkg/Include/Library/MemEncryptSevLib.h
> +++ b/OvmfPkg/Include/Library/MemEncryptSevLib.h
> @@ -13,6 +13,29 @@
>  
>  #include <Base.h>
>  
> +//
> +// Define the maximum number of #VCs allowed (e.g. the level of nesting
> +// that is allowed => 2 allows for 1 nested #VCs). I this value is changed,
> +// be sure to increase the size of
> +//   gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupSize
> +// in any FDF file using this PCD.
> +//
> +#define VMGEXIT_MAXIMUM_VC_COUNT   2
> +
> +//
> +// Per-CPU data mapping structure
> +//   Use UINT32 for cached indicators and compare to a specific value
> +//   so that the hypervisor can't indicate a value is cached by just
> +//   writing random data to that area.
> +//
> +typedef struct {
> +  UINT32  Dr7Cached;
> +  UINT64  Dr7;
> +
> +  UINTN   VcCount;
> +  VOID    *GhcbBackupPages;
> +} SEV_ES_PER_CPU_DATA;
> +
>  //
>  // Internal structure for holding SEV-ES information needed during SEC phase
>  // and valid only during SEC phase and early PEI during platform
> diff --git a/OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.h b/OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.h
> new file mode 100644
> index 000000000000..3a37cb04f616
> --- /dev/null
> +++ b/OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.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 __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/PeiDxeVmgExitVcHandler.c b/OvmfPkg/Library/VmgExitLib/PeiDxeVmgExitVcHandler.c
> new file mode 100644
> index 000000000000..fb4942df37ca
> --- /dev/null
> +++ b/OvmfPkg/Library/VmgExitLib/PeiDxeVmgExitVcHandler.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/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/SecVmgExitVcHandler.c b/OvmfPkg/Library/VmgExitLib/SecVmgExitVcHandler.c
> new file mode 100644
> index 000000000000..85853d334b35
> --- /dev/null
> +++ b/OvmfPkg/Library/VmgExitLib/SecVmgExitVcHandler.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/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/VmgExitVcHandler.c b/OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c
> index 5149ab2bc989..ce577e4677eb 100644
> --- a/OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c
> +++ b/OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c
> @@ -9,11 +9,14 @@
>  #include <Base.h>
>  #include <Uefi.h>
>  #include <Library/BaseMemoryLib.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"
> +
>  //
>  // Instruction execution mode definition
>  //
> @@ -126,18 +129,6 @@ UINT64
>    SEV_ES_INSTRUCTION_DATA  *InstructionData
>    );
>  
> -//
> -// Per-CPU data mapping structure
> -//   Use UINT32 for cached indicators and compare to a specific value
> -//   so that the hypervisor can't indicate a value is cached by just
> -//   writing random data to that area.
> -//
> -typedef struct {
> -  UINT32  Dr7Cached;
> -  UINT64  Dr7;
> -} SEV_ES_PER_CPU_DATA;
> -
> -
>  /**
>    Return a pointer to the contents of the specified register.
>  
> @@ -1546,6 +1537,7 @@ Dr7ReadExit (
>  
>    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
> @@ -1559,14 +1551,13 @@ Dr7ReadExit (
>  **/
>  EFI_STATUS
>  EFIAPI
> -VmgExitHandleVc (
> +InternalVmgExitHandleVc (
> +  IN OUT GHCB                *Ghcb,
>    IN OUT EFI_EXCEPTION_TYPE  *ExceptionType,
>    IN OUT EFI_SYSTEM_CONTEXT  SystemContext
>    )
>  {
> -  MSR_SEV_ES_GHCB_REGISTER  Msr;
>    EFI_SYSTEM_CONTEXT_X64    *Regs;
> -  GHCB                      *Ghcb;
>    NAE_EXIT                  NaeExit;
>    SEV_ES_INSTRUCTION_DATA   InstructionData;
>    UINT64                    ExitCode, Status;
> @@ -1575,12 +1566,7 @@ VmgExitHandleVc (
>  
>    VcRet = EFI_SUCCESS;
>  
> -  Msr.GhcbPhysicalAddress = AsmReadMsr64 (MSR_SEV_ES_GHCB);
> -  ASSERT (Msr.GhcbInfo.Function == 0);
> -  ASSERT (Msr.Ghcb != 0);
> -
>    Regs = SystemContext.SystemContextX64;
> -  Ghcb = Msr.Ghcb;
>  
>    VmgInit (Ghcb, &InterruptState);
>  
> @@ -1670,3 +1656,25 @@ VmgExitHandleVc (
>  
>    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/PlatformPei/AmdSev.c b/OvmfPkg/PlatformPei/AmdSev.c
> index 954d53eba4e8..dddffdebda4b 100644
> --- a/OvmfPkg/PlatformPei/AmdSev.c
> +++ b/OvmfPkg/PlatformPei/AmdSev.c
> @@ -33,12 +33,17 @@ AmdSevEsInitialize (
>    VOID
>    )
>  {
> -  VOID              *GhcbBase;
> -  PHYSICAL_ADDRESS  GhcbBasePa;
> -  UINTN             GhcbPageCount, PageCount;
> -  RETURN_STATUS     PcdStatus, DecryptStatus;
> -  IA32_DESCRIPTOR   Gdtr;
> -  VOID              *Gdt;
> +  UINT8                *GhcbBase;
> +  PHYSICAL_ADDRESS     GhcbBasePa;
> +  UINTN                GhcbPageCount;
> +  UINT8                *GhcbBackupBase;
> +  UINT8                *GhcbBackupPages;
> +  UINTN                GhcbBackupPageCount;
> +  SEV_ES_PER_CPU_DATA  *SevEsData;
> +  UINTN                PageCount;
> +  RETURN_STATUS        PcdStatus, DecryptStatus;
> +  IA32_DESCRIPTOR      Gdtr;
> +  VOID                 *Gdt;
>  
>    if (!MemEncryptSevEsIsEnabled ()) {
>      return;
> @@ -84,6 +89,27 @@ AmdSevEsInitialize (
>      "SEV-ES is enabled, %lu GHCB pages allocated starting at 0x%p\n",
>      (UINT64)GhcbPageCount, GhcbBase));
>  
> +  //
> +  // Allocate #VC recursion backup pages. The number of backup pages needed is
> +  // one less than the maximum VC count.
> +  //
> +  GhcbBackupPageCount = mMaxCpuCount * (VMGEXIT_MAXIMUM_VC_COUNT - 1);
> +  GhcbBackupBase = AllocatePages (GhcbBackupPageCount);
> +  ASSERT (GhcbBackupBase != NULL);
> +
> +  GhcbBackupPages = GhcbBackupBase;
> +  for (PageCount = 1; PageCount < GhcbPageCount; PageCount += 2) {
> +    SevEsData =
> +      (SEV_ES_PER_CPU_DATA *)(GhcbBase + EFI_PAGES_TO_SIZE (PageCount));
> +    SevEsData->GhcbBackupPages = GhcbBackupPages;
> +
> +    GhcbBackupPages += EFI_PAGE_SIZE * (VMGEXIT_MAXIMUM_VC_COUNT - 1);
> +  }
> +
> +  DEBUG ((DEBUG_INFO,
> +    "SEV-ES is enabled, %lu GHCB backup pages allocated starting at 0x%p\n",
> +    (UINT64)GhcbBackupPageCount, GhcbBackupBase));
> +
>    AsmWriteMsr64 (MSR_SEV_ES_GHCB, GhcbBasePa);
>  
>    //
> 



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#69688): https://edk2.groups.io/g/devel/message/69688
Mute This Topic: https://groups.io/mt/78986180/1813853
Mute #vcs:https://edk2.groups.io/g/devel/mutehashtag/vcs
Group Owner: devel+owner at edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [edk2-devel-archive at redhat.com]
-=-=-=-=-=-=-=-=-=-=-=-





More information about the edk2-devel-archive mailing list