OvmfPkg/VmgExitLib: Support nested #VCs
BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3108 In order to be able to issue messages or make interface calls that cause another #VC (e.g. GetLocalApicBaseAddress () issues RDMSR), add support for nested #VCs. In order to support nested #VCs, GHCB backup pages are required. If a #VC is received while currently processing a #VC, a backup of the current GHCB content is made. This allows the #VC handler to continue processing the new #VC. Upon completion of the new #VC, the GHCB is restored from the backup page. The #VC recursion level is tracked in the per-vCPU variable area. Support is added to handle up to one nested #VC (or two #VCs total). If a second nested #VC is encountered, an ASSERT will be issued and the vCPU will enter CpuDeadLoop (). For SEC, the GHCB backup pages are reserved in the OvmfPkgX64.fdf memory layout, with two new fixed PCDs to provide the address and size of the backup area. For PEI/DXE, the GHCB backup pages are allocated as boot services pages using the memory allocation library. Cc: Jordan Justen <jordan.l.justen@intel.com> Cc: Laszlo Ersek <lersek@redhat.com> Cc: Ard Biesheuvel <ard.biesheuvel@arm.com> Cc: Brijesh Singh <brijesh.singh@amd.com> Acked-by: Laszlo Ersek <lersek@redhat.com> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com> Message-Id: <ac2e8203fc41a351b43f60d68bdad6b57c4fb106.1610045305.git.thomas.lendacky@amd.com>
This commit is contained in:
committed by
mergify[bot]
parent
c330af0246
commit
5667dc43d8
@@ -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 ();
|
||||
}
|
||||
|
Reference in New Issue
Block a user