aboutsummaryrefslogtreecommitdiffstats
path: root/roms/edk2/OvmfPkg/AmdSevDxe/AmdSevDxe.c
diff options
context:
space:
mode:
Diffstat (limited to 'roms/edk2/OvmfPkg/AmdSevDxe/AmdSevDxe.c')
-rw-r--r--roms/edk2/OvmfPkg/AmdSevDxe/AmdSevDxe.c119
1 files changed, 119 insertions, 0 deletions
diff --git a/roms/edk2/OvmfPkg/AmdSevDxe/AmdSevDxe.c b/roms/edk2/OvmfPkg/AmdSevDxe/AmdSevDxe.c
new file mode 100644
index 000000000..595586617
--- /dev/null
+++ b/roms/edk2/OvmfPkg/AmdSevDxe/AmdSevDxe.c
@@ -0,0 +1,119 @@
+/** @file
+
+ AMD Sev Dxe driver. This driver is dispatched early in DXE, due to being list
+ in APRIORI. It clears C-bit from MMIO and NonExistent Memory space when SEV
+ is enabled.
+
+ Copyright (c) 2017, AMD Inc. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/MemEncryptSevLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+
+EFI_STATUS
+EFIAPI
+AmdSevDxeEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_GCD_MEMORY_SPACE_DESCRIPTOR *AllDescMap;
+ UINTN NumEntries;
+ UINTN Index;
+
+ //
+ // Do nothing when SEV is not enabled
+ //
+ if (!MemEncryptSevIsEnabled ()) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Iterate through the GCD map and clear the C-bit from MMIO and NonExistent
+ // memory space. The NonExistent memory space will be used for mapping the
+ // MMIO space added later (eg PciRootBridge). By clearing both known MMIO and
+ // NonExistent memory space can gurantee that current and furture MMIO adds
+ // will have C-bit cleared.
+ //
+ Status = gDS->GetMemorySpaceMap (&NumEntries, &AllDescMap);
+ if (!EFI_ERROR (Status)) {
+ for (Index = 0; Index < NumEntries; Index++) {
+ CONST EFI_GCD_MEMORY_SPACE_DESCRIPTOR *Desc;
+
+ Desc = &AllDescMap[Index];
+ if (Desc->GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo ||
+ Desc->GcdMemoryType == EfiGcdMemoryTypeNonExistent) {
+ Status = MemEncryptSevClearPageEncMask (
+ 0,
+ Desc->BaseAddress,
+ EFI_SIZE_TO_PAGES (Desc->Length),
+ FALSE
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+ }
+
+ FreePool (AllDescMap);
+ }
+
+ //
+ // When SMM is enabled, clear the C-bit from SMM Saved State Area
+ //
+ // NOTES: The SavedStateArea address cleared here is before SMBASE
+ // relocation. Currently, we do not clear the SavedStateArea address after
+ // SMBASE is relocated due to the following reasons:
+ //
+ // 1) Guest BIOS never access the relocated SavedStateArea.
+ //
+ // 2) The C-bit works on page-aligned address, but the SavedStateArea
+ // address is not a page-aligned. Theoretically, we could roundup the address
+ // and clear the C-bit of aligned address but looking carefully we found
+ // that some portion of the page contains code -- which will causes a bigger
+ // issues for SEV guest. When SEV is enabled, all the code must be encrypted
+ // otherwise hardware will cause trap.
+ //
+ // We restore the C-bit for this SMM Saved State Area after SMBASE relocation
+ // is completed (See OvmfPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLib.c).
+ //
+ if (FeaturePcdGet (PcdSmmSmramRequire)) {
+ UINTN MapPagesBase;
+ UINTN MapPagesCount;
+
+ Status = MemEncryptSevLocateInitialSmramSaveStateMapPages (
+ &MapPagesBase,
+ &MapPagesCount
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Although these pages were set aside (i.e., allocated) by PlatformPei, we
+ // could be after a warm reboot from the OS. Don't leak any stale OS data
+ // to the hypervisor.
+ //
+ ZeroMem ((VOID *)MapPagesBase, EFI_PAGES_TO_SIZE (MapPagesCount));
+
+ Status = MemEncryptSevClearPageEncMask (
+ 0, // Cr3BaseAddress -- use current CR3
+ MapPagesBase, // BaseAddress
+ MapPagesCount, // NumPages
+ TRUE // Flush
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a: MemEncryptSevClearPageEncMask(): %r\n",
+ __FUNCTION__, Status));
+ ASSERT (FALSE);
+ CpuDeadLoop ();
+ }
+ }
+
+ return EFI_SUCCESS;
+}