audk/OvmfPkg/PlatformPei/AmdSev.c

99 lines
3.0 KiB
C
Raw Normal View History

OvmfPkg/PlatformPei: Set memory encryption PCD when SEV is enabled Secure Encrypted Virtualization (SEV) guest VMs have the concept of private and shared memory. Private memory is encrypted with the guest-specific key, while shared memory may be encrypted with hypervisor key. Certain types of memory (namely instruction pages and guest page tables) are always treated as private memory by the hardware. For data memory, SEV guest VMs can choose which pages they would like to be private. The choice is done using the standard CPU page tables using the C-bit. When building the initial page table we mark all the memory as private. The patch sets the memory encryption PCD. The PCD is consumed by the following edk2 modules, which manipulate page tables: - PEI phase modules: CapsulePei, DxeIplPeim, S3Resume2Pei. CapsulePei is not used by OVMF. DxeIplPeim consumes the PCD at the end of the PEI phase, when it builds the initial page tables for the DXE core / DXE phase. S3Resume2Pei does not consume the PCD in its entry point function, only when DxeIplPeim branches to the S3 resume path at the end of the PEI phase, and calls S3Resume2Pei's EFI_PEI_S3_RESUME2_PPI.S3RestoreConfig2() member function. Therefore it is safe to set the PCD for these modules in PlatformPei. - DXE phase modules: BootScriptExecutorDxe, CpuDxe, PiSmmCpuDxeSmm. They are all dispatched after the PEI phase, so setting the PCD for them in PlatformPei is safe. (BootScriptExecutorDxe is launched "for real" in the PEI phase during S3 resume, but it caches the PCD into a static variable when its entry point is originally invoked in DXE.) Cc: Jordan Justen <jordan.l.justen@intel.com> Cc: Laszlo Ersek <lersek@redhat.com> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Brijesh Singh <brijesh.singh@amd.com> Reviewed-by: Laszlo Ersek <lersek@redhat.com> Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
2017-07-06 15:25:48 +02:00
/**@file
Initialize Secure Encrypted Virtualization (SEV) support
Copyright (c) 2017, Advanced Micro Devices. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD
License which accompanies this distribution. The full text of the license
may be found at http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
//
// The package level header files this module uses
//
#include <Library/DebugLib.h>
OvmfPkg/PlatformPei: SEV: allocate pages of initial SMRAM save state map In the next two patches, we'll temporarily decrypt the pages containing the initial SMRAM save state map, for SMBASE relocation. (Unlike the separate, relocated SMRAM save state map of each VCPU, the original, shared map behaves similarly to a "common buffer" between guest and host.) The decryption will occur near the beginning of the DXE phase, in AmdSevDxe, and the re-encryption will occur in PiSmmCpuDxeSmm, via OVMF's SmmCpuFeaturesLib instance. There is a non-trivial time gap between these two points, and the DXE phase might use the pages overlapping the initial SMRAM save state map for arbitrary purposes meanwhile. In order to prevent any information leak towards the hypervisor, make sure the DXE phase puts nothing in those pages until re-encryption is done. Creating a memalloc HOB for the area in question is safe: - the temporary SEC/PEI RAM (stack and heap) is based at PcdOvmfSecPeiTempRamBase, which is above 8MB, - the permanent PEI RAM (installed in PlatformPei's PublishPeiMemory() function) never starts below PcdOvmfDxeMemFvBase, which is also above 8MB. The allocated pages can be released to the DXE phase after SMBASE relocation and re-encryption are complete. Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org> Cc: Brijesh Singh <brijesh.singh@amd.com> Cc: Jordan Justen <jordan.l.justen@intel.com> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Laszlo Ersek <lersek@redhat.com> Tested-by: Brijesh Singh <brijesh.singh@amd.com> Reviewed-by: Brijesh Singh <brijesh.singh@amd.com>
2018-03-01 17:59:19 +01:00
#include <Library/HobLib.h>
#include <Library/MemEncryptSevLib.h>
OvmfPkg/PlatformPei: Set memory encryption PCD when SEV is enabled Secure Encrypted Virtualization (SEV) guest VMs have the concept of private and shared memory. Private memory is encrypted with the guest-specific key, while shared memory may be encrypted with hypervisor key. Certain types of memory (namely instruction pages and guest page tables) are always treated as private memory by the hardware. For data memory, SEV guest VMs can choose which pages they would like to be private. The choice is done using the standard CPU page tables using the C-bit. When building the initial page table we mark all the memory as private. The patch sets the memory encryption PCD. The PCD is consumed by the following edk2 modules, which manipulate page tables: - PEI phase modules: CapsulePei, DxeIplPeim, S3Resume2Pei. CapsulePei is not used by OVMF. DxeIplPeim consumes the PCD at the end of the PEI phase, when it builds the initial page tables for the DXE core / DXE phase. S3Resume2Pei does not consume the PCD in its entry point function, only when DxeIplPeim branches to the S3 resume path at the end of the PEI phase, and calls S3Resume2Pei's EFI_PEI_S3_RESUME2_PPI.S3RestoreConfig2() member function. Therefore it is safe to set the PCD for these modules in PlatformPei. - DXE phase modules: BootScriptExecutorDxe, CpuDxe, PiSmmCpuDxeSmm. They are all dispatched after the PEI phase, so setting the PCD for them in PlatformPei is safe. (BootScriptExecutorDxe is launched "for real" in the PEI phase during S3 resume, but it caches the PCD into a static variable when its entry point is originally invoked in DXE.) Cc: Jordan Justen <jordan.l.justen@intel.com> Cc: Laszlo Ersek <lersek@redhat.com> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Brijesh Singh <brijesh.singh@amd.com> Reviewed-by: Laszlo Ersek <lersek@redhat.com> Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
2017-07-06 15:25:48 +02:00
#include <Library/PcdLib.h>
#include <PiPei.h>
OvmfPkg/PlatformPei: Set memory encryption PCD when SEV is enabled Secure Encrypted Virtualization (SEV) guest VMs have the concept of private and shared memory. Private memory is encrypted with the guest-specific key, while shared memory may be encrypted with hypervisor key. Certain types of memory (namely instruction pages and guest page tables) are always treated as private memory by the hardware. For data memory, SEV guest VMs can choose which pages they would like to be private. The choice is done using the standard CPU page tables using the C-bit. When building the initial page table we mark all the memory as private. The patch sets the memory encryption PCD. The PCD is consumed by the following edk2 modules, which manipulate page tables: - PEI phase modules: CapsulePei, DxeIplPeim, S3Resume2Pei. CapsulePei is not used by OVMF. DxeIplPeim consumes the PCD at the end of the PEI phase, when it builds the initial page tables for the DXE core / DXE phase. S3Resume2Pei does not consume the PCD in its entry point function, only when DxeIplPeim branches to the S3 resume path at the end of the PEI phase, and calls S3Resume2Pei's EFI_PEI_S3_RESUME2_PPI.S3RestoreConfig2() member function. Therefore it is safe to set the PCD for these modules in PlatformPei. - DXE phase modules: BootScriptExecutorDxe, CpuDxe, PiSmmCpuDxeSmm. They are all dispatched after the PEI phase, so setting the PCD for them in PlatformPei is safe. (BootScriptExecutorDxe is launched "for real" in the PEI phase during S3 resume, but it caches the PCD into a static variable when its entry point is originally invoked in DXE.) Cc: Jordan Justen <jordan.l.justen@intel.com> Cc: Laszlo Ersek <lersek@redhat.com> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Brijesh Singh <brijesh.singh@amd.com> Reviewed-by: Laszlo Ersek <lersek@redhat.com> Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
2017-07-06 15:25:48 +02:00
#include <Register/Amd/Cpuid.h>
#include <Register/Cpuid.h>
OvmfPkg/PlatformPei: Set memory encryption PCD when SEV is enabled Secure Encrypted Virtualization (SEV) guest VMs have the concept of private and shared memory. Private memory is encrypted with the guest-specific key, while shared memory may be encrypted with hypervisor key. Certain types of memory (namely instruction pages and guest page tables) are always treated as private memory by the hardware. For data memory, SEV guest VMs can choose which pages they would like to be private. The choice is done using the standard CPU page tables using the C-bit. When building the initial page table we mark all the memory as private. The patch sets the memory encryption PCD. The PCD is consumed by the following edk2 modules, which manipulate page tables: - PEI phase modules: CapsulePei, DxeIplPeim, S3Resume2Pei. CapsulePei is not used by OVMF. DxeIplPeim consumes the PCD at the end of the PEI phase, when it builds the initial page tables for the DXE core / DXE phase. S3Resume2Pei does not consume the PCD in its entry point function, only when DxeIplPeim branches to the S3 resume path at the end of the PEI phase, and calls S3Resume2Pei's EFI_PEI_S3_RESUME2_PPI.S3RestoreConfig2() member function. Therefore it is safe to set the PCD for these modules in PlatformPei. - DXE phase modules: BootScriptExecutorDxe, CpuDxe, PiSmmCpuDxeSmm. They are all dispatched after the PEI phase, so setting the PCD for them in PlatformPei is safe. (BootScriptExecutorDxe is launched "for real" in the PEI phase during S3 resume, but it caches the PCD into a static variable when its entry point is originally invoked in DXE.) Cc: Jordan Justen <jordan.l.justen@intel.com> Cc: Laszlo Ersek <lersek@redhat.com> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Brijesh Singh <brijesh.singh@amd.com> Reviewed-by: Laszlo Ersek <lersek@redhat.com> Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
2017-07-06 15:25:48 +02:00
#include "Platform.h"
OvmfPkg/PlatformPei: Set memory encryption PCD when SEV is enabled Secure Encrypted Virtualization (SEV) guest VMs have the concept of private and shared memory. Private memory is encrypted with the guest-specific key, while shared memory may be encrypted with hypervisor key. Certain types of memory (namely instruction pages and guest page tables) are always treated as private memory by the hardware. For data memory, SEV guest VMs can choose which pages they would like to be private. The choice is done using the standard CPU page tables using the C-bit. When building the initial page table we mark all the memory as private. The patch sets the memory encryption PCD. The PCD is consumed by the following edk2 modules, which manipulate page tables: - PEI phase modules: CapsulePei, DxeIplPeim, S3Resume2Pei. CapsulePei is not used by OVMF. DxeIplPeim consumes the PCD at the end of the PEI phase, when it builds the initial page tables for the DXE core / DXE phase. S3Resume2Pei does not consume the PCD in its entry point function, only when DxeIplPeim branches to the S3 resume path at the end of the PEI phase, and calls S3Resume2Pei's EFI_PEI_S3_RESUME2_PPI.S3RestoreConfig2() member function. Therefore it is safe to set the PCD for these modules in PlatformPei. - DXE phase modules: BootScriptExecutorDxe, CpuDxe, PiSmmCpuDxeSmm. They are all dispatched after the PEI phase, so setting the PCD for them in PlatformPei is safe. (BootScriptExecutorDxe is launched "for real" in the PEI phase during S3 resume, but it caches the PCD into a static variable when its entry point is originally invoked in DXE.) Cc: Jordan Justen <jordan.l.justen@intel.com> Cc: Laszlo Ersek <lersek@redhat.com> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Brijesh Singh <brijesh.singh@amd.com> Reviewed-by: Laszlo Ersek <lersek@redhat.com> Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
2017-07-06 15:25:48 +02:00
/**
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);
OvmfPkg/PlatformPei: SEV: allocate pages of initial SMRAM save state map In the next two patches, we'll temporarily decrypt the pages containing the initial SMRAM save state map, for SMBASE relocation. (Unlike the separate, relocated SMRAM save state map of each VCPU, the original, shared map behaves similarly to a "common buffer" between guest and host.) The decryption will occur near the beginning of the DXE phase, in AmdSevDxe, and the re-encryption will occur in PiSmmCpuDxeSmm, via OVMF's SmmCpuFeaturesLib instance. There is a non-trivial time gap between these two points, and the DXE phase might use the pages overlapping the initial SMRAM save state map for arbitrary purposes meanwhile. In order to prevent any information leak towards the hypervisor, make sure the DXE phase puts nothing in those pages until re-encryption is done. Creating a memalloc HOB for the area in question is safe: - the temporary SEC/PEI RAM (stack and heap) is based at PcdOvmfSecPeiTempRamBase, which is above 8MB, - the permanent PEI RAM (installed in PlatformPei's PublishPeiMemory() function) never starts below PcdOvmfDxeMemFvBase, which is also above 8MB. The allocated pages can be released to the DXE phase after SMBASE relocation and re-encryption are complete. Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org> Cc: Brijesh Singh <brijesh.singh@amd.com> Cc: Jordan Justen <jordan.l.justen@intel.com> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Laszlo Ersek <lersek@redhat.com> Tested-by: Brijesh Singh <brijesh.singh@amd.com> Reviewed-by: Brijesh Singh <brijesh.singh@amd.com>
2018-03-01 17:59:19 +01:00
//
// 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);
BuildMemoryAllocationHob (
MapPagesBase, // BaseAddress
EFI_PAGES_TO_SIZE (MapPagesCount), // Length
EfiBootServicesData // MemoryType
);
}
OvmfPkg/PlatformPei: Set memory encryption PCD when SEV is enabled Secure Encrypted Virtualization (SEV) guest VMs have the concept of private and shared memory. Private memory is encrypted with the guest-specific key, while shared memory may be encrypted with hypervisor key. Certain types of memory (namely instruction pages and guest page tables) are always treated as private memory by the hardware. For data memory, SEV guest VMs can choose which pages they would like to be private. The choice is done using the standard CPU page tables using the C-bit. When building the initial page table we mark all the memory as private. The patch sets the memory encryption PCD. The PCD is consumed by the following edk2 modules, which manipulate page tables: - PEI phase modules: CapsulePei, DxeIplPeim, S3Resume2Pei. CapsulePei is not used by OVMF. DxeIplPeim consumes the PCD at the end of the PEI phase, when it builds the initial page tables for the DXE core / DXE phase. S3Resume2Pei does not consume the PCD in its entry point function, only when DxeIplPeim branches to the S3 resume path at the end of the PEI phase, and calls S3Resume2Pei's EFI_PEI_S3_RESUME2_PPI.S3RestoreConfig2() member function. Therefore it is safe to set the PCD for these modules in PlatformPei. - DXE phase modules: BootScriptExecutorDxe, CpuDxe, PiSmmCpuDxeSmm. They are all dispatched after the PEI phase, so setting the PCD for them in PlatformPei is safe. (BootScriptExecutorDxe is launched "for real" in the PEI phase during S3 resume, but it caches the PCD into a static variable when its entry point is originally invoked in DXE.) Cc: Jordan Justen <jordan.l.justen@intel.com> Cc: Laszlo Ersek <lersek@redhat.com> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Brijesh Singh <brijesh.singh@amd.com> Reviewed-by: Laszlo Ersek <lersek@redhat.com> Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
2017-07-06 15:25:48 +02:00
}