X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=OvmfPkg%2FPlatformPei%2FAmdSev.c;h=3991edfd1e82b1edfe4f6e1a59f6eeeaec778227;hb=ac0a286f4d747a4c6c603a7b225917293cbe1e9f;hp=4dc5340caa7a2814e8914ecfa7a3a6deb12acbd8;hpb=cf845a749a1cc25c6b63586de08ea69cd8832bc9;p=mirror_edk2.git
diff --git a/OvmfPkg/PlatformPei/AmdSev.c b/OvmfPkg/PlatformPei/AmdSev.c
index 4dc5340caa..3991edfd1e 100644
--- a/OvmfPkg/PlatformPei/AmdSev.c
+++ b/OvmfPkg/PlatformPei/AmdSev.c
@@ -1,7 +1,7 @@
/**@file
Initialize Secure Encrypted Virtualization (SEV) support
- Copyright (c) 2017, Advanced Micro Devices. All rights reserved.
+ Copyright (c) 2017 - 2020, Advanced Micro Devices. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -10,13 +10,14 @@
// The package level header files this module uses
//
#include
+#include
#include
#include
#include
+#include
#include
#include
-#include
-#include
+#include
#include
#include "Platform.h"
@@ -32,7 +33,17 @@ AmdSevEsInitialize (
VOID
)
{
- RETURN_STATUS PcdStatus;
+ UINT8 *GhcbBase;
+ PHYSICAL_ADDRESS GhcbBasePa;
+ UINTN GhcbPageCount;
+ UINT8 *GhcbBackupBase;
+ UINT8 *GhcbBackupPages;
+ UINTN GhcbBackupPageCount;
+ SEV_ES_PER_CPU_DATA *SevEsData;
+ UINTN PageCount;
+ RETURN_STATUS PcdStatus, DecryptStatus;
+ IA32_DESCRIPTOR Gdtr;
+ VOID *Gdt;
if (!MemEncryptSevEsIsEnabled ()) {
return;
@@ -40,6 +51,87 @@ AmdSevEsInitialize (
PcdStatus = PcdSetBoolS (PcdSevEsIsEnabled, TRUE);
ASSERT_RETURN_ERROR (PcdStatus);
+
+ //
+ // Allocate GHCB and per-CPU variable pages.
+ // Since the pages must survive across the UEFI to OS transition
+ // make them reserved.
+ //
+ GhcbPageCount = mMaxCpuCount * 2;
+ GhcbBase = AllocateReservedPages (GhcbPageCount);
+ ASSERT (GhcbBase != NULL);
+
+ GhcbBasePa = (PHYSICAL_ADDRESS)(UINTN)GhcbBase;
+
+ //
+ // Each vCPU gets two consecutive pages, the first is the GHCB and the
+ // second is the per-CPU variable page. Loop through the allocation and
+ // only clear the encryption mask for the GHCB pages.
+ //
+ for (PageCount = 0; PageCount < GhcbPageCount; PageCount += 2) {
+ DecryptStatus = MemEncryptSevClearPageEncMask (
+ 0,
+ GhcbBasePa + EFI_PAGES_TO_SIZE (PageCount),
+ 1
+ );
+ ASSERT_RETURN_ERROR (DecryptStatus);
+ }
+
+ ZeroMem (GhcbBase, EFI_PAGES_TO_SIZE (GhcbPageCount));
+
+ PcdStatus = PcdSet64S (PcdGhcbBase, GhcbBasePa);
+ ASSERT_RETURN_ERROR (PcdStatus);
+ PcdStatus = PcdSet64S (PcdGhcbSize, EFI_PAGES_TO_SIZE (GhcbPageCount));
+ ASSERT_RETURN_ERROR (PcdStatus);
+
+ DEBUG ((
+ DEBUG_INFO,
+ "SEV-ES is enabled, %lu GHCB pages allocated starting at 0x%p\n",
+ (UINT64)GhcbPageCount,
+ GhcbBase
+ ));
+
+ //
+ // Allocate #VC recursion backup pages. The number of backup pages needed is
+ // one less than the maximum VC count.
+ //
+ GhcbBackupPageCount = mMaxCpuCount * (VMGEXIT_MAXIMUM_VC_COUNT - 1);
+ GhcbBackupBase = AllocatePages (GhcbBackupPageCount);
+ ASSERT (GhcbBackupBase != NULL);
+
+ GhcbBackupPages = GhcbBackupBase;
+ for (PageCount = 1; PageCount < GhcbPageCount; PageCount += 2) {
+ SevEsData =
+ (SEV_ES_PER_CPU_DATA *)(GhcbBase + EFI_PAGES_TO_SIZE (PageCount));
+ SevEsData->GhcbBackupPages = GhcbBackupPages;
+
+ GhcbBackupPages += EFI_PAGE_SIZE * (VMGEXIT_MAXIMUM_VC_COUNT - 1);
+ }
+
+ DEBUG ((
+ DEBUG_INFO,
+ "SEV-ES is enabled, %lu GHCB backup pages allocated starting at 0x%p\n",
+ (UINT64)GhcbBackupPageCount,
+ GhcbBackupBase
+ ));
+
+ AsmWriteMsr64 (MSR_SEV_ES_GHCB, GhcbBasePa);
+
+ //
+ // The SEV support will clear the C-bit from non-RAM areas. The early GDT
+ // lives in a non-RAM area, so when an exception occurs (like a #VC) the GDT
+ // will be read as un-encrypted even though it was created before the C-bit
+ // was cleared (encrypted). This will result in a failure to be able to
+ // handle the exception.
+ //
+ AsmReadGdtr (&Gdtr);
+
+ Gdt = AllocatePages (EFI_SIZE_TO_PAGES ((UINTN)Gdtr.Limit + 1));
+ ASSERT (Gdt != NULL);
+
+ CopyMem (Gdt, (VOID *)Gdtr.Base, Gdtr.Limit + 1);
+ Gdtr.Base = (UINTN)Gdt;
+ AsmWriteGdtr (&Gdtr);
}
/**
@@ -53,9 +145,8 @@ AmdSevInitialize (
VOID
)
{
- CPUID_MEMORY_ENCRYPTION_INFO_EBX Ebx;
- UINT64 EncryptionMask;
- RETURN_STATUS PcdStatus;
+ UINT64 EncryptionMask;
+ RETURN_STATUS PcdStatus;
//
// Check if SEV is enabled
@@ -64,16 +155,11 @@ AmdSevInitialize (
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);
+ EncryptionMask = MemEncryptSevGetEncryptionMask ();
+ PcdStatus = PcdSet64S (PcdPteMemoryEncryptionAddressOrMask, EncryptionMask);
ASSERT_RETURN_ERROR (PcdStatus);
DEBUG ((DEBUG_INFO, "SEV is enabled (mask 0x%lx)\n", EncryptionMask));
@@ -96,9 +182,9 @@ AmdSevInitialize (
// hypervisor.
//
if (FeaturePcdGet (PcdSmmSmramRequire) && (mBootMode != BOOT_ON_S3_RESUME)) {
- RETURN_STATUS LocateMapStatus;
- UINTN MapPagesBase;
- UINTN MapPagesCount;
+ RETURN_STATUS LocateMapStatus;
+ UINTN MapPagesBase;
+ UINTN MapPagesCount;
LocateMapStatus = MemEncryptSevLocateInitialSmramSaveStateMapPages (
&MapPagesBase,