From: "Laszlo Ersek" <lersek@redhat.com>
To: devel@edk2.groups.io, thomas.lendacky@amd.com
Cc: Brijesh Singh <brijesh.singh@amd.com>,
James Bottomley <jejb@linux.ibm.com>,
Jordan Justen <jordan.l.justen@intel.com>,
Ard Biesheuvel <ard.biesheuvel@arm.com>
Subject: Re: [edk2-devel] [PATCH 10/12] OvmfPkg/VmgExitLib: Support nested #VCs
Date: Tue, 5 Jan 2021 11:08:35 +0100 [thread overview]
Message-ID: <714c5653-b500-1ba5-36aa-f75246b034e4@redhat.com> (raw)
In-Reply-To: <8d981134522af3a1efa222b12f36d5e831f88f2e.1608065471.git.thomas.lendacky@amd.com>
On 12/15/20 21:51, Lendacky, Thomas wrote:
> From: Tom Lendacky <thomas.lendacky@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@intel.com>
> Cc: Laszlo Ersek <lersek@redhat.com>
> Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>
> Cc: Brijesh Singh <brijesh.singh@amd.com>
> Signed-off-by: Tom Lendacky <thomas.lendacky@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@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);
>
> //
>
next prev parent reply other threads:[~2021-01-05 10:08 UTC|newest]
Thread overview: 38+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-12-15 20:50 [PATCH 00/12] SEV-ES security mitigations Lendacky, Thomas
2020-12-15 20:51 ` [PATCH 01/12] Ovmf/ResetVector: Simplify and consolidate the SEV features checks Lendacky, Thomas
2021-01-04 18:58 ` [edk2-devel] " Laszlo Ersek
2020-12-15 20:51 ` [PATCH 02/12] OvmfPkg/Sec: Move SEV-ES SEC workarea definition to common header file Lendacky, Thomas
2021-01-04 19:02 ` [edk2-devel] " Laszlo Ersek
2020-12-15 20:51 ` [PATCH 03/12] OvmfPkg/ResetVector: Validate the encryption bit position for SEV/SEV-ES Lendacky, Thomas
2021-01-04 19:59 ` [edk2-devel] " Laszlo Ersek
2021-01-04 20:45 ` Lendacky, Thomas
2020-12-15 20:51 ` [PATCH 04/12] OvmfPkg/ResetVector: Perform a simple SEV-ES sanity check Lendacky, Thomas
2021-01-04 20:00 ` [edk2-devel] " Laszlo Ersek
2021-01-04 20:48 ` Lendacky, Thomas
2020-12-15 20:51 ` [PATCH 05/12] OvmfPkg/MemEncryptSevLib: Add an interface to retrieve the encryption mask Lendacky, Thomas
2021-01-04 20:34 ` [edk2-devel] " Laszlo Ersek
2021-01-04 21:09 ` Lendacky, Thomas
2020-12-15 20:51 ` [PATCH 06/12] OvmfPkg/AmdSevDxe: Clear encryption bit on PCIe MMCONFIG range Lendacky, Thomas
2021-01-04 21:04 ` [edk2-devel] " Laszlo Ersek
2021-01-05 22:48 ` Lendacky, Thomas
2021-01-06 15:38 ` Laszlo Ersek
2020-12-15 20:51 ` [PATCH 07/12] OvmfPkg/VmgExitLib: Check for an explicit DR7 cached value Lendacky, Thomas
2021-01-04 21:05 ` [edk2-devel] " Laszlo Ersek
2020-12-15 20:51 ` [PATCH 08/12] OvmfPkg/MemEncryptSevLib: Make the MemEncryptSevLib available for SEC Lendacky, Thomas
2021-01-05 9:40 ` [edk2-devel] " Laszlo Ersek
2021-01-05 14:34 ` Lendacky, Thomas
2021-01-05 15:38 ` Lendacky, Thomas
2021-01-06 14:22 ` Laszlo Ersek
2021-01-06 14:21 ` Laszlo Ersek
2020-12-15 20:51 ` [PATCH 09/12] OvmfPkg/MemEncryptSevLib: Address range encryption state interface Lendacky, Thomas
2021-01-05 9:48 ` [edk2-devel] " Laszlo Ersek
2020-12-15 20:51 ` [PATCH 10/12] OvmfPkg/VmgExitLib: Support nested #VCs Lendacky, Thomas
2021-01-05 10:08 ` Laszlo Ersek [this message]
2020-12-15 20:51 ` [PATCH 11/12] OvmfPkg/PlatformPei: Reserve GHCB backup pages if S3 is supported Lendacky, Thomas
2021-01-05 10:13 ` [edk2-devel] " Laszlo Ersek
2021-01-05 14:40 ` Lendacky, Thomas
2020-12-15 20:51 ` [PATCH 12/12] OvfmPkg/VmgExitLib: Validate #VC MMIO is to un-encrypted memory Lendacky, Thomas
2021-01-05 10:28 ` [edk2-devel] " Laszlo Ersek
2021-01-05 14:45 ` Lendacky, Thomas
2020-12-17 14:23 ` [PATCH 00/12] SEV-ES security mitigations Laszlo Ersek
2020-12-21 15:02 ` [edk2-devel] " Laszlo Ersek
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=714c5653-b500-1ba5-36aa-f75246b034e4@redhat.com \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox