This commit is contained in:
John Berg 2026-08-26 22:51:21 +00:00 committed by GitHub
commit ee74747e92
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 104 additions and 145 deletions

View file

@ -40,6 +40,13 @@ typedef struct _CONFIDENTIAL_COMPUTING_WORK_AREA_HEADER {
// any changes must stay in sync with its usage.
//
typedef struct _SEC_SEV_ES_WORK_AREA {
//
// AP jump table - must be offset 0 since the AP's initial RIP points
// here. This buffer must at least be the size of struct SEV_ES_AP_JMP_FAR.
// See SetSevEsJumpTable()
//
UINT8 ApJumpBuffer[16];
//
// Hold the SevStatus MSR value read by OvmfPkg/ResetVector/Ia32/AmdSev.c
//

View file

@ -15,6 +15,7 @@
MODULE_TYPE = BASE
VERSION_STRING = 1.0
LIBRARY_CLASS = MemEncryptSevLib|DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER UEFI_DRIVER
CONSTRUCTOR = DxeMemEncryptSevLibConstructor
#
# The following information is for reference only and not required by the build
@ -32,6 +33,7 @@
[Sources]
DxeMemEncryptSevLibInternal.c
PeiDxeMemEncryptSevLibInternal.c
PeiDxeMemEncryptSevLibInternal.h
X64/DxeSnpSystemRamValidate.c
X64/MemEncryptSevLib.c
X64/PeiDxeVirtualMemory.c
@ -52,6 +54,6 @@
[FeaturePcd]
gUefiOvmfPkgTokenSpaceGuid.PcdSmmSmramRequire
[Pcd]
gEfiMdeModulePkgTokenSpaceGuid.PcdPteMemoryEncryptionAddressOrMask
gEfiMdePkgTokenSpaceGuid.PcdConfidentialComputingGuestAttr
[FixedPcd]
gUefiCpuPkgTokenSpaceGuid.PcdSevEsWorkAreaBase
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfWorkAreaBase

View file

@ -16,92 +16,48 @@
#include <Register/Amd/Msr.h>
#include <Register/Cpuid.h>
#include <Uefi/UefiBaseType.h>
#include <ConfidentialComputingGuestAttr.h>
#include "PeiDxeMemEncryptSevLibInternal.h"
STATIC UINT64 mCurrentAttr = 0;
STATIC BOOLEAN mCurrentAttrRead = FALSE;
STATIC UINT64 mSevEncryptionMask = 0;
STATIC BOOLEAN mSevEncryptionMaskSaved = FALSE;
STATIC BOOLEAN mSevSnpCoherencySfwNo = FALSE;
STATIC BOOLEAN mSevSnpCoherencySfwNoRead = FALSE;
STATIC UINT64 mSevEncryptionMask = 0;
STATIC BOOLEAN mSevIsEnabled = FALSE;
STATIC BOOLEAN mSevEsIsEnabled = FALSE;
STATIC BOOLEAN mSevSnpIsEnabled = FALSE;
STATIC BOOLEAN mSevDebugVirtualization = FALSE;
STATIC BOOLEAN mSevSnpCoherencySfwNo = FALSE;
/**
The function check if the specified Attr is set.
@param[in] CurrentAttr The current attribute.
@param[in] Attr The attribute to check.
@retval TRUE The specified Attr is set.
@retval FALSE The specified Attr is not set.
**/
STATIC
BOOLEAN
AmdMemEncryptionAttrCheck (
IN UINT64 CurrentAttr,
IN CONFIDENTIAL_COMPUTING_GUEST_ATTR Attr
)
{
UINT64 CurrentLevel;
CurrentLevel = CurrentAttr & CCAttrTypeMask;
switch (Attr) {
case CCAttrAmdSev:
//
// SEV is automatically enabled if SEV-ES or SEV-SNP is active.
//
return CurrentLevel >= CCAttrAmdSev;
case CCAttrAmdSevEs:
//
// SEV-ES is automatically enabled if SEV-SNP is active.
//
return CurrentLevel >= CCAttrAmdSevEs;
case CCAttrAmdSevSnp:
return CurrentLevel == CCAttrAmdSevSnp;
case CCAttrFeatureAmdSevEsDebugVirtualization:
return !!(CurrentAttr & CCAttrFeatureAmdSevEsDebugVirtualization);
default:
return FALSE;
}
}
/**
Check if the specified confidential computing attribute is active.
@param[in] Attr The attribute to check.
@retval TRUE The specified Attr is active.
@retval FALSE The specified Attr is not active.
**/
STATIC
BOOLEAN
RETURN_STATUS
EFIAPI
ConfidentialComputingGuestHas (
IN CONFIDENTIAL_COMPUTING_GUEST_ATTR Attr
DxeMemEncryptSevLibConstructor (
VOID
)
{
SEC_SEV_ES_WORK_AREA *SevEsWorkArea;
MSR_SEV_STATUS_REGISTER Msr;
//
// Get the current CC attribute.
// The work area should at least be EfiBootServicesData since the work area
// is also used for AP bring up to setup the AP jump table.
//
// We avoid reading the PCD on every check because this routine could be indirectly
// called during the virtual pointer conversion. And its not safe to access the
// PCDs during the virtual pointer conversion.
//
if (!mCurrentAttrRead) {
mCurrentAttr = PcdGet64 (PcdConfidentialComputingGuestAttr);
mCurrentAttrRead = TRUE;
SevEsWorkArea = GetSevEsWorkArea ();
if (SevEsWorkArea == NULL) {
return RETURN_SUCCESS;
}
//
// If attr is for the AMD group then call AMD specific checks.
// The work area will not be mapped at the expected physical address once
// SetVirtualAddressMap() is called. So fetch the values from the work area
// and store them in variables so the MemEncryptSev*() functions do not need
// to access the work area.
//
if (((RShiftU64 (mCurrentAttr, 8)) & 0xff) == 1) {
return AmdMemEncryptionAttrCheck (mCurrentAttr, Attr);
}
Msr.Uint32 = (UINT32)(UINTN)SevEsWorkArea->SevStatusMsrValue;
mSevEncryptionMask = SevEsWorkArea->EncryptionMask;
mSevIsEnabled = Msr.Bits.SevBit ? TRUE : FALSE;
mSevEsIsEnabled = Msr.Bits.SevEsBit ? TRUE : FALSE;
mSevSnpIsEnabled = Msr.Bits.SevSnpBit ? TRUE : FALSE;
mSevDebugVirtualization = Msr.Bits.DebugVirtualization ? TRUE : FALSE;
mSevSnpCoherencySfwNo = (SevEsWorkArea->Flags & SEV_ES_WORK_AREA_FLAG_CSFW_NO) != 0;
return (mCurrentAttr == Attr);
return RETURN_SUCCESS;
}
/**
@ -116,7 +72,7 @@ MemEncryptSevSnpIsEnabled (
VOID
)
{
return ConfidentialComputingGuestHas (CCAttrAmdSevSnp);
return mSevSnpIsEnabled;
}
/**
@ -131,7 +87,7 @@ MemEncryptSevEsIsEnabled (
VOID
)
{
return ConfidentialComputingGuestHas (CCAttrAmdSevEs);
return mSevEsIsEnabled;
}
/**
@ -146,7 +102,7 @@ MemEncryptSevIsEnabled (
VOID
)
{
return ConfidentialComputingGuestHas (CCAttrAmdSev);
return mSevIsEnabled;
}
/**
@ -160,11 +116,6 @@ MemEncryptSevGetEncryptionMask (
VOID
)
{
if (!mSevEncryptionMaskSaved) {
mSevEncryptionMask = PcdGet64 (PcdPteMemoryEncryptionAddressOrMask);
mSevEncryptionMaskSaved = TRUE;
}
return mSevEncryptionMask;
}
@ -180,34 +131,7 @@ MemEncryptSevEsDebugVirtualizationIsEnabled (
VOID
)
{
return ConfidentialComputingGuestHas (CCAttrFeatureAmdSevEsDebugVirtualization);
}
/**
Returns a boolean to indicate if the CPUID COHERENCY_SFW_NO bit is set.
@retval TRUE The COHERENCY_SFW_NO bit is set.
@retval FALSE The COHERENCY_SFW_NO bit is not set.
**/
STATIC
BOOLEAN
MemEncryptCoherencSfwNo (
VOID
)
{
CPUID_MEMORY_ENCRYPTION_INFO_EBX RegEbx;
if (!mSevSnpCoherencySfwNoRead) {
AsmCpuid (0x8000001F, NULL, &RegEbx.Uint32, NULL, NULL);
if (RegEbx.Bits.CoherencySfwNo == 1) {
mSevSnpCoherencySfwNo = TRUE;
}
mSevSnpCoherencySfwNoRead = TRUE;
}
return mSevSnpCoherencySfwNo;
return mSevDebugVirtualization;
}
/**
@ -224,5 +148,5 @@ MemEncryptSevSnpDoCoherencyMitigation (
VOID
)
{
return MemEncryptSevSnpIsEnabled () && !MemEncryptCoherencSfwNo ();
return MemEncryptSevSnpIsEnabled () && !mSevSnpCoherencySfwNo;
}

View file

@ -15,6 +15,32 @@
#include <Register/Amd/SmramSaveStateMap.h>
#include <Register/SmramSaveStateMap.h>
#include <Uefi/UefiBaseType.h>
#include "PeiDxeMemEncryptSevLibInternal.h"
/**
Read the workarea to determine whether SEV is enabled. If enabled,
then return the SevEsWorkArea pointer.
**/
SEC_SEV_ES_WORK_AREA *
EFIAPI
GetSevEsWorkArea (
VOID
)
{
OVMF_WORK_AREA *WorkArea;
WorkArea = (OVMF_WORK_AREA *)FixedPcdGet32 (PcdOvmfWorkAreaBase);
//
// If its not SEV guest then SevEsWorkArea is not valid.
//
if ((WorkArea == NULL) || (WorkArea->Header.GuestType != CcGuestTypeAmdSev)) {
return NULL;
}
return (SEC_SEV_ES_WORK_AREA *)FixedPcdGet32 (PcdSevEsWorkAreaBase);
}
/**
Locate the page range that covers the initial (pre-SMBASE-relocation) SMRAM

View file

@ -0,0 +1,24 @@
/** @file
Internal interfaces for the PEI and DXE MemEncryptSevLib instances.
Copyright (c) 2026, Amazon.com, Inc. or its affiliates. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#pragma once
#include <WorkArea.h>
/**
Read the workarea to determine whether SEV is enabled. If enabled,
then return the SevEsWorkArea pointer.
**/
SEC_SEV_ES_WORK_AREA *
EFIAPI
GetSevEsWorkArea (
VOID
);

View file

@ -31,6 +31,7 @@
[Sources]
PeiDxeMemEncryptSevLibInternal.c
PeiDxeMemEncryptSevLibInternal.h
PeiMemEncryptSevLibInternal.c
[Sources.X64]

View file

@ -16,32 +16,7 @@
#include <Register/Amd/Msr.h>
#include <Register/Cpuid.h>
#include <Uefi/UefiBaseType.h>
/**
Read the workarea to determine whether SEV is enabled. If enabled,
then return the SevEsWorkArea pointer.
**/
STATIC
SEC_SEV_ES_WORK_AREA *
EFIAPI
GetSevEsWorkArea (
VOID
)
{
OVMF_WORK_AREA *WorkArea;
WorkArea = (OVMF_WORK_AREA *)FixedPcdGet32 (PcdOvmfWorkAreaBase);
//
// If its not SEV guest then SevEsWorkArea is not valid.
//
if ((WorkArea == NULL) || (WorkArea->Header.GuestType != CcGuestTypeAmdSev)) {
return NULL;
}
return (SEC_SEV_ES_WORK_AREA *)FixedPcdGet32 (PcdSevEsWorkAreaBase);
}
#include "PeiDxeMemEncryptSevLibInternal.h"
/**
Read the SEV Status MSR value from the workarea

View file

@ -59,11 +59,11 @@
%define GHCB_BASE (FixedPcdGet32 (PcdOvmfSecGhcbBase))
%define GHCB_SIZE (FixedPcdGet32 (PcdOvmfSecGhcbSize))
%define SEV_ES_WORK_AREA (FixedPcdGet32 (PcdSevEsWorkAreaBase))
%define SEV_ES_WORK_AREA_SIZE 25
%define SEV_ES_WORK_AREA_STATUS_MSR (FixedPcdGet32 (PcdSevEsWorkAreaBase))
%define SEV_ES_WORK_AREA_RDRAND (FixedPcdGet32 (PcdSevEsWorkAreaBase) + 8)
%define SEV_ES_WORK_AREA_ENC_MASK (FixedPcdGet32 (PcdSevEsWorkAreaBase) + 16)
%define SEV_ES_WORK_AREA_FLAGS (FixedPcdGet32 (PcdSevEsWorkAreaBase) + 24)
%define SEV_ES_WORK_AREA_SIZE 41
%define SEV_ES_WORK_AREA_STATUS_MSR (FixedPcdGet32 (PcdSevEsWorkAreaBase) + 16)
%define SEV_ES_WORK_AREA_RDRAND (FixedPcdGet32 (PcdSevEsWorkAreaBase) + 24)
%define SEV_ES_WORK_AREA_ENC_MASK (FixedPcdGet32 (PcdSevEsWorkAreaBase) + 32)
%define SEV_ES_WORK_AREA_FLAGS (FixedPcdGet32 (PcdSevEsWorkAreaBase) + 40)
%define SEV_ES_WORK_AREA_FLAG_VC 0x01
%define SEV_ES_WORK_AREA_FLAG_CSFW_NO 0x02
%define SEV_ES_VC_TOP_OF_STACK (FixedPcdGet32 (PcdOvmfSecPeiTempRamBase) + FixedPcdGet32 (PcdOvmfSecPeiTempRamSize))