When OVMF runs in a SEV guest, the initial SMM Save State Map is (1) allocated as EfiBootServicesData type memory in OvmfPkg/PlatformPei, function AmdSevInitialize(), for preventing unintended information sharing with the hypervisor; (2) decrypted in AmdSevDxe; (3) re-encrypted in OvmfPkg/Library/SmmCpuFeaturesLib, function SmmCpuFeaturesSmmRelocationComplete(), which is called by PiSmmCpuDxeSmm right after initial SMBASE relocation; (4) released to DXE at the same location. The SMRAM at the default SMBASE is a superset of the initial Save State Map. The reserved memory allocation in InitializeRamRegions(), from the previous patch, must override the allocating and freeing in (1) and (4), respectively. (Note: the decrypting and re-encrypting in (2) and (3) are unaffected.) In AmdSevInitialize(), only assert the containment of the initial Save State Map, in the larger area already allocated by InitializeRamRegions(). In SmmCpuFeaturesSmmRelocationComplete(), preserve the allocation of the initial Save State Map into OS runtime, as part of the allocation done by InitializeRamRegions(). Only assert containment. These changes only affect the normal boot path (the UEFI memory map is untouched during S3 resume). Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org> Cc: Jordan Justen <jordan.l.justen@intel.com> Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=1512 Signed-off-by: Laszlo Ersek <lersek@redhat.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com> Message-Id: <20200129214412.2361-9-lersek@redhat.com> Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
107 lines
3.2 KiB
C
107 lines
3.2 KiB
C
/**@file
|
|
Initialize Secure Encrypted Virtualization (SEV) support
|
|
|
|
Copyright (c) 2017, Advanced Micro Devices. All rights reserved.<BR>
|
|
|
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
|
|
**/
|
|
//
|
|
// The package level header files this module uses
|
|
//
|
|
#include <IndustryStandard/Q35MchIch9.h>
|
|
#include <Library/DebugLib.h>
|
|
#include <Library/HobLib.h>
|
|
#include <Library/MemEncryptSevLib.h>
|
|
#include <Library/PcdLib.h>
|
|
#include <PiPei.h>
|
|
#include <Register/Amd/Cpuid.h>
|
|
#include <Register/Cpuid.h>
|
|
#include <Register/Intel/SmramSaveStateMap.h>
|
|
|
|
#include "Platform.h"
|
|
|
|
/**
|
|
|
|
Function checks if SEV support is available, if present then it sets
|
|
the dynamic PcdPteMemoryEncryptionAddressOrMask with memory encryption mask.
|
|
|
|
**/
|
|
VOID
|
|
AmdSevInitialize (
|
|
VOID
|
|
)
|
|
{
|
|
CPUID_MEMORY_ENCRYPTION_INFO_EBX Ebx;
|
|
UINT64 EncryptionMask;
|
|
RETURN_STATUS PcdStatus;
|
|
|
|
//
|
|
// Check if SEV is enabled
|
|
//
|
|
if (!MemEncryptSevIsEnabled ()) {
|
|
return;
|
|
}
|
|
|
|
//
|
|
// CPUID Fn8000_001F[EBX] Bit 0:5 (memory encryption bit position)
|
|
//
|
|
AsmCpuid (CPUID_MEMORY_ENCRYPTION_INFO, NULL, &Ebx.Uint32, NULL, NULL);
|
|
EncryptionMask = LShiftU64 (1, Ebx.Bits.PtePosBits);
|
|
|
|
//
|
|
// Set Memory Encryption Mask PCD
|
|
//
|
|
PcdStatus = PcdSet64S (PcdPteMemoryEncryptionAddressOrMask, EncryptionMask);
|
|
ASSERT_RETURN_ERROR (PcdStatus);
|
|
|
|
DEBUG ((DEBUG_INFO, "SEV is enabled (mask 0x%lx)\n", EncryptionMask));
|
|
|
|
//
|
|
// Set Pcd to Deny the execution of option ROM when security
|
|
// violation.
|
|
//
|
|
PcdStatus = PcdSet32S (PcdOptionRomImageVerificationPolicy, 0x4);
|
|
ASSERT_RETURN_ERROR (PcdStatus);
|
|
|
|
//
|
|
// When SMM is required, cover the pages containing the initial SMRAM Save
|
|
// State Map with a memory allocation HOB:
|
|
//
|
|
// There's going to be a time interval between our decrypting those pages for
|
|
// SMBASE relocation and re-encrypting the same pages after SMBASE
|
|
// relocation. We shall ensure that the DXE phase stay away from those pages
|
|
// until after re-encryption, in order to prevent an information leak to the
|
|
// hypervisor.
|
|
//
|
|
if (FeaturePcdGet (PcdSmmSmramRequire) && (mBootMode != BOOT_ON_S3_RESUME)) {
|
|
RETURN_STATUS LocateMapStatus;
|
|
UINTN MapPagesBase;
|
|
UINTN MapPagesCount;
|
|
|
|
LocateMapStatus = MemEncryptSevLocateInitialSmramSaveStateMapPages (
|
|
&MapPagesBase,
|
|
&MapPagesCount
|
|
);
|
|
ASSERT_RETURN_ERROR (LocateMapStatus);
|
|
|
|
if (mQ35SmramAtDefaultSmbase) {
|
|
//
|
|
// The initial SMRAM Save State Map has been covered as part of a larger
|
|
// reserved memory allocation in InitializeRamRegions().
|
|
//
|
|
ASSERT (SMM_DEFAULT_SMBASE <= MapPagesBase);
|
|
ASSERT (
|
|
(MapPagesBase + EFI_PAGES_TO_SIZE (MapPagesCount) <=
|
|
SMM_DEFAULT_SMBASE + MCH_DEFAULT_SMBASE_SIZE)
|
|
);
|
|
} else {
|
|
BuildMemoryAllocationHob (
|
|
MapPagesBase, // BaseAddress
|
|
EFI_PAGES_TO_SIZE (MapPagesCount), // Length
|
|
EfiBootServicesData // MemoryType
|
|
);
|
|
}
|
|
}
|
|
}
|