audk/OvmfPkg/Library/BaseMemEncryptSevLib/X64/SecSnpSystemRamValidate.c
Tom Lendacky 0afb874349 OvmfPkg/BaseMemEncryptLib: Check for presence of an SVSM when not at VMPL0
BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=4654

Currently, an SEV-SNP guest will terminate if it is not running at VMPL0.
The requirement for running at VMPL0 is removed if an SVSM is present.

Update the current VMPL0 check to additionally check for the presence of
an SVSM is the guest is not running at VMPL0.

Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Erdem Aktas <erdemaktas@google.com>
Cc: Gerd Hoffmann <kraxel@redhat.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Michael Roth <michael.roth@amd.com>
Cc: Min Xu <min.m.xu@intel.com>
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
2024-04-17 20:04:41 +00:00

98 lines
2.3 KiB
C

/** @file
SEV-SNP Page Validation functions.
Copyright (c) 2021 - 2024, AMD Incorporated. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include <Uefi/UefiBaseType.h>
#include <Library/BaseLib.h>
#include <Library/DebugLib.h>
#include <Library/MemEncryptSevLib.h>
#include <Library/AmdSvsmLib.h>
#include "SnpPageStateChange.h"
//
// The variable used for the VMPL check.
//
STATIC UINT8 gVmpl0Data[4096];
/**
The function checks whether SEV-SNP guest is booted under VMPL0.
@retval TRUE The guest is booted under VMPL0
@retval FALSE The guest is not booted under VMPL0
**/
STATIC
BOOLEAN
SevSnpIsVmpl0 (
VOID
)
{
UINT64 Rdx;
UINT32 Status;
//
// There is no straightforward way to query the current VMPL level.
// The simplest method is to use the RMPADJUST instruction to change
// a page permission to a VMPL level-1, and if the guest kernel is
// launched at a level <= 1, then RMPADJUST instruction will return
// an error.
//
Rdx = 1;
Status = AsmRmpAdjust ((UINT64)gVmpl0Data, 0, Rdx);
if (Status != 0) {
return FALSE;
}
return TRUE;
}
/**
Pre-validate the system RAM when SEV-SNP is enabled in the guest VM.
@param[in] BaseAddress Base address
@param[in] NumPages Number of pages starting from the base address
**/
VOID
EFIAPI
MemEncryptSevSnpPreValidateSystemRam (
IN PHYSICAL_ADDRESS BaseAddress,
IN UINTN NumPages
)
{
SEC_SEV_ES_WORK_AREA *SevEsWorkArea;
if (!MemEncryptSevSnpIsEnabled ()) {
return;
}
//
// The page state change uses the PVALIDATE instruction. The instruction
// can be run at VMPL-0 only. If its not a VMPL-0 guest, then an SVSM must
// be present to perform the operation on behalf of the guest. If the guest
// is not running at VMPL-0 and an SVSM is not present, then terminate the
// boot.
//
if (!SevSnpIsVmpl0 () && !AmdSvsmIsSvsmPresent ()) {
SnpPageStateFailureTerminate ();
}
SevEsWorkArea = (SEC_SEV_ES_WORK_AREA *)FixedPcdGet32 (PcdSevEsWorkAreaBase);
InternalSetPageState (
BaseAddress,
NumPages,
SevSnpPagePrivate,
TRUE,
SevEsWorkArea->WorkBuffer,
sizeof (SevEsWorkArea->WorkBuffer)
);
}