OvmfPkg/AmdSevDxe: decrypt the pages of the initial SMRAM save state map
[mirror_edk2.git] / OvmfPkg / AmdSevDxe / AmdSevDxe.c
index e472096..c697580 100644 (file)
@@ -1,30 +1,28 @@
 /** @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
+  This program and the accompanying materials are licensed and made available\r
+  under the terms and conditions of the BSD License which accompanies this\r
+  distribution.  The full text of the license may be found at\r
+  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
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT\r
+  WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\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
@@ -47,8 +45,8 @@ AmdSevDxeEntryPoint (
 \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
@@ -60,10 +58,12 @@ AmdSevDxeEntryPoint (
       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
@@ -71,5 +71,55 @@ AmdSevDxeEntryPoint (
     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