/** @file\r
\r
AMD Sev Dxe driver. This driver is dispatched early in DXE, due to being list\r
- in APRIORI. It clears C-bit from MMIO and NonExistent Memory space when SEV is\r
- enabled.\r
+ in APRIORI. It clears C-bit from MMIO and NonExistent Memory space when SEV\r
+ is enabled.\r
\r
Copyright (c) 2017, AMD Inc. All rights reserved.<BR>\r
\r
- This program and the accompanying materials\r
- are licensed and made available under the terms and conditions of the BSD\r
- License which accompanies this distribution. The full text of the license may\r
- be found at http://opensource.org/licenses/bsd-license.php\r
-\r
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
-#include <PiDxe.h>\r
-\r
#include <Library/BaseLib.h>\r
-#include <Library/DebugLib.h>\r
#include <Library/BaseMemoryLib.h>\r
-#include <Library/MemoryAllocationLib.h>\r
-#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/DebugLib.h>\r
#include <Library/DxeServicesTableLib.h>\r
#include <Library/MemEncryptSevLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/PcdLib.h>\r
\r
EFI_STATUS\r
EFIAPI\r
\r
//\r
// Iterate through the GCD map and clear the C-bit from MMIO and NonExistent\r
- // memory space. The NonExistent memory space will be used for mapping the MMIO\r
- // space added later (eg PciRootBridge). By clearing both known MMIO and\r
+ // memory space. The NonExistent memory space will be used for mapping the\r
+ // MMIO space added later (eg PciRootBridge). By clearing both known MMIO and\r
// NonExistent memory space can gurantee that current and furture MMIO adds\r
// will have C-bit cleared.\r
//\r
Desc = &AllDescMap[Index];\r
if (Desc->GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo ||\r
Desc->GcdMemoryType == EfiGcdMemoryTypeNonExistent) {\r
- Status = MemEncryptSevClearPageEncMask (0,\r
- Desc->BaseAddress,\r
- EFI_SIZE_TO_PAGES(Desc->Length),\r
- FALSE);\r
+ Status = MemEncryptSevClearPageEncMask (\r
+ 0,\r
+ Desc->BaseAddress,\r
+ EFI_SIZE_TO_PAGES (Desc->Length),\r
+ FALSE\r
+ );\r
ASSERT_EFI_ERROR (Status);\r
}\r
}\r
FreePool (AllDescMap);\r
}\r
\r
+ //\r
+ // When SMM is enabled, clear the C-bit from SMM Saved State Area\r
+ //\r
+ // NOTES: The SavedStateArea address cleared here is before SMBASE\r
+ // relocation. Currently, we do not clear the SavedStateArea address after\r
+ // SMBASE is relocated due to the following reasons:\r
+ //\r
+ // 1) Guest BIOS never access the relocated SavedStateArea.\r
+ //\r
+ // 2) The C-bit works on page-aligned address, but the SavedStateArea\r
+ // address is not a page-aligned. Theoretically, we could roundup the address\r
+ // and clear the C-bit of aligned address but looking carefully we found\r
+ // that some portion of the page contains code -- which will causes a bigger\r
+ // issues for SEV guest. When SEV is enabled, all the code must be encrypted\r
+ // otherwise hardware will cause trap.\r
+ //\r
+ // We restore the C-bit for this SMM Saved State Area after SMBASE relocation\r
+ // is completed (See OvmfPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLib.c).\r
+ //\r
+ if (FeaturePcdGet (PcdSmmSmramRequire)) {\r
+ UINTN MapPagesBase;\r
+ UINTN MapPagesCount;\r
+\r
+ Status = MemEncryptSevLocateInitialSmramSaveStateMapPages (\r
+ &MapPagesBase,\r
+ &MapPagesCount\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Although these pages were set aside (i.e., allocated) by PlatformPei, we\r
+ // could be after a warm reboot from the OS. Don't leak any stale OS data\r
+ // to the hypervisor.\r
+ //\r
+ ZeroMem ((VOID *)MapPagesBase, EFI_PAGES_TO_SIZE (MapPagesCount));\r
+\r
+ Status = MemEncryptSevClearPageEncMask (\r
+ 0, // Cr3BaseAddress -- use current CR3\r
+ MapPagesBase, // BaseAddress\r
+ MapPagesCount, // NumPages\r
+ TRUE // Flush\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_ERROR, "%a: MemEncryptSevClearPageEncMask(): %r\n",\r
+ __FUNCTION__, Status));\r
+ ASSERT (FALSE);\r
+ CpuDeadLoop ();\r
+ }\r
+ }\r
+\r
return EFI_SUCCESS;\r
}\r