OvmfPkg/BaseMemcryptSevLib: Add SEV helper library
authorBrijesh Singh <brijesh.singh@amd.com>
Thu, 6 Jul 2017 13:21:12 +0000 (09:21 -0400)
committerJordan Justen <jordan.l.justen@intel.com>
Tue, 11 Jul 2017 04:17:27 +0000 (21:17 -0700)
Add Secure Encrypted Virtualization (SEV) helper library.
The library provides the routines to:
-  set or clear memory encryption bit for a given memory region.
-  query whether SEV is enabled.

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>
Acked-by: Jordan Justen <jordan.l.justen@intel.com>
OvmfPkg/Include/Library/MemEncryptSevLib.h [new file with mode: 0644]
OvmfPkg/Library/BaseMemEncryptSevLib/BaseMemEncryptSevLib.inf [new file with mode: 0644]
OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c [new file with mode: 0644]
OvmfPkg/Library/BaseMemEncryptSevLib/MemEncryptSevLibInternal.c [new file with mode: 0644]
OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c [new file with mode: 0644]
OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.c [new file with mode: 0644]
OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.h [new file with mode: 0644]
OvmfPkg/OvmfPkgIa32.dsc
OvmfPkg/OvmfPkgIa32X64.dsc
OvmfPkg/OvmfPkgX64.dsc

diff --git a/OvmfPkg/Include/Library/MemEncryptSevLib.h b/OvmfPkg/Include/Library/MemEncryptSevLib.h
new file mode 100644 (file)
index 0000000..b675376
--- /dev/null
@@ -0,0 +1,81 @@
+/** @file\r
+\r
+  Define Secure Encrypted Virtualization (SEV) base library helper function\r
+\r
+  Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>\r
+\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
+\r
+**/\r
+\r
+#ifndef _MEM_ENCRYPT_SEV_LIB_H_\r
+#define _MEM_ENCRYPT_SEV_LIB_H_\r
+\r
+#include <Base.h>\r
+\r
+/**\r
+  Returns a boolean to indicate whether SEV is enabled\r
+\r
+  @retval TRUE           SEV is active\r
+  @retval FALSE          SEV is not enabled\r
+  **/\r
+BOOLEAN\r
+EFIAPI\r
+MemEncryptSevIsEnabled (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  This function clears memory encryption bit for the memory region specified\r
+  by BaseAddress and Number of pages from the current page table context.\r
+\r
+  @param[in]  BaseAddress           The physical address that is the start address\r
+                                    of a memory region.\r
+  @param[in]  NumberOfPages         The number of pages from start memory region.\r
+  @param[in]  Flush                 Flush the caches before clearing the bit\r
+                                    (mostly TRUE except MMIO addresses)\r
+\r
+  @retval RETURN_SUCCESS            The attributes were cleared for the memory region.\r
+  @retval RETURN_INVALID_PARAMETER  Number of pages is zero.\r
+  @retval RETURN_UNSUPPORTED        Clearing memory encryption attribute is not\r
+                                    supported\r
+  **/\r
+RETURN_STATUS\r
+EFIAPI\r
+MemEncryptSevClearPageEncMask (\r
+  IN PHYSICAL_ADDRESS         Cr3BaseAddress,\r
+  IN PHYSICAL_ADDRESS         BaseAddress,\r
+  IN UINTN                    NumberOfPages,\r
+  IN BOOLEAN                  CacheFlush\r
+  );\r
+\r
+/**\r
+  This function sets memory encryption bit for the memory region specified by\r
+  BaseAddress and Number of pages from the current page table context.\r
+\r
+  @param[in]  BaseAddress           The physical address that is the start address\r
+                                    of a memory region.\r
+  @param[in]  NumberOfPages         The number of pages from start memory region.\r
+  @param[in]  Flush                 Flush the caches before clearing the bit\r
+                                    (mostly TRUE except MMIO addresses)\r
+\r
+  @retval RETURN_SUCCESS            The attributes were set for the memory region.\r
+  @retval RETURN_INVALID_PARAMETER  Number of pages is zero.\r
+  @retval RETURN_UNSUPPORTED        Clearing memory encryption attribute is not\r
+                                    supported\r
+  **/\r
+RETURN_STATUS\r
+EFIAPI\r
+MemEncryptSevSetPageEncMask (\r
+  IN PHYSICAL_ADDRESS         Cr3BaseAddress,\r
+  IN PHYSICAL_ADDRESS         BaseAddress,\r
+  IN UINTN                    NumberOfPages,\r
+  IN BOOLEAN                  CacheFlush\r
+  );\r
+#endif // _MEM_ENCRYPT_SEV_LIB_H_\r
diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/BaseMemEncryptSevLib.inf b/OvmfPkg/Library/BaseMemEncryptSevLib/BaseMemEncryptSevLib.inf
new file mode 100644 (file)
index 0000000..3cfd80a
--- /dev/null
@@ -0,0 +1,50 @@
+## @file\r
+#  Library provides the helper functions for SEV guest\r
+#\r
+# Copyright (c) 2017 Advanced Micro Devices. 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\r
+#  may be found at http://opensource.org/licenses/bsd-license.php\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
+#\r
+#\r
+##\r
+\r
+[Defines]\r
+  INF_VERSION                    = 1.25\r
+  BASE_NAME                      = MemEncryptSevLib\r
+  FILE_GUID                      = c1594631-3888-4be4-949f-9c630dbc842b\r
+  MODULE_TYPE                    = BASE\r
+  VERSION_STRING                 = 1.0\r
+  LIBRARY_CLASS                  = MemEncryptSevLib|PEIM DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER UEFI_DRIVER\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+# VALID_ARCHITECTURES           = IA32 X64\r
+#\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  MdeModulePkg/MdeModulePkg.dec\r
+  OvmfPkg/OvmfPkg.dec\r
+  UefiCpuPkg/UefiCpuPkg.dec\r
+\r
+[Sources.X64]\r
+  MemEncryptSevLibInternal.c\r
+  X64/MemEncryptSevLib.c\r
+  X64/VirtualMemory.c\r
+\r
+[Sources.IA32]\r
+  MemEncryptSevLibInternal.c\r
+  Ia32/MemEncryptSevLib.c\r
+\r
+[LibraryClasses]\r
+  BaseLib\r
+  CpuLib\r
+  CacheMaintenanceLib\r
+  DebugLib\r
+  MemoryAllocationLib\r
diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c b/OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c
new file mode 100644 (file)
index 0000000..a2ea990
--- /dev/null
@@ -0,0 +1,84 @@
+/** @file\r
+\r
+  Secure Encrypted Virtualization (SEV) library helper function\r
+\r
+  Copyright (c) 2017, AMD Incorporated. 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
+\r
+**/\r
+\r
+#include <Library/BaseLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Register/Cpuid.h>\r
+#include <Register/Amd/Cpuid.h>\r
+#include <Register/Amd/Msr.h>\r
+#include <Library/MemEncryptSevLib.h>\r
+\r
+/**\r
+  This function clears memory encryption bit for the memory region specified\r
+  by BaseAddress and Number of pages from the current page table context.\r
+\r
+  @param[in]  Cr3BaseAddress        Cr3 Base Address (if zero then use current CR3)\r
+  @param[in]  BaseAddress           The physical address that is the start address\r
+                                    of a memory region.\r
+  @param[in]  NumberOfPages         The number of pages from start memory region.\r
+  @param[in]  Flush                 Flush the caches before clearing the bit\r
+                                    (mostly TRUE except MMIO addresses)\r
+\r
+  @retval RETURN_SUCCESS            The attributes were cleared for the memory region.\r
+  @retval RETURN_INVALID_PARAMETER  Number of pages is zero.\r
+  @retval RETURN_UNSUPPORTED        Clearing memory encryption attribute is not\r
+                                    supported\r
+  **/\r
+RETURN_STATUS\r
+EFIAPI\r
+MemEncryptSevClearPageEncMask (\r
+  IN PHYSICAL_ADDRESS         Cr3BaseAddress,\r
+  IN PHYSICAL_ADDRESS         BaseAddress,\r
+  IN UINTN                    NumberOfPages,\r
+  IN BOOLEAN                  Flush\r
+  )\r
+{\r
+  //\r
+  // Memory encryption bit is not accessible in 32-bit mode\r
+  //\r
+  return RETURN_UNSUPPORTED;\r
+}\r
+\r
+/**\r
+  This function sets memory encryption bit for the memory region specified by\r
+  BaseAddress and Number of pages from the current page table context.\r
+\r
+  @param[in]  Cr3BaseAddress        Cr3 Base Address (if zero then use current CR3)\r
+  @param[in]  BaseAddress           The physical address that is the start address\r
+                                    of a memory region.\r
+  @param[in]  NumberOfPages         The number of pages from start memory region.\r
+  @param[in]  Flush                 Flush the caches before clearing the bit\r
+                                    (mostly TRUE except MMIO addresses)\r
+\r
+  @retval RETURN_SUCCESS            The attributes were set for the memory region.\r
+  @retval RETURN_INVALID_PARAMETER  Number of pages is zero.\r
+  @retval RETURN_UNSUPPORTED        Clearing memory encryption attribute is not\r
+                                    supported\r
+  **/\r
+RETURN_STATUS\r
+EFIAPI\r
+MemEncryptSevSetPageEncMask (\r
+  IN PHYSICAL_ADDRESS         Cr3BaseAddress,\r
+  IN PHYSICAL_ADDRESS         BaseAddress,\r
+  IN UINTN                    NumberOfPages,\r
+  IN BOOLEAN                  Flush\r
+  )\r
+{\r
+  //\r
+  // Memory encryption bit is not accessible in 32-bit mode\r
+  //\r
+  return RETURN_UNSUPPORTED;\r
+}\r
diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/MemEncryptSevLibInternal.c b/OvmfPkg/Library/BaseMemEncryptSevLib/MemEncryptSevLibInternal.c
new file mode 100644 (file)
index 0000000..002f079
--- /dev/null
@@ -0,0 +1,90 @@
+/** @file\r
+\r
+  Secure Encrypted Virtualization (SEV) library helper function\r
+\r
+  Copyright (c) 2017, AMD Incorporated. 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
+\r
+**/\r
+\r
+#include <Library/BaseLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Register/Cpuid.h>\r
+#include <Register/Amd/Cpuid.h>\r
+#include <Register/Amd/Msr.h>\r
+#include <Library/MemEncryptSevLib.h>\r
+\r
+STATIC BOOLEAN mSevStatus = FALSE;\r
+STATIC BOOLEAN mSevStatusChecked = FALSE;\r
+\r
+/**\r
+\r
+  Returns a boolean to indicate whether SEV is enabled\r
+\r
+  @retval TRUE           SEV is enabled\r
+  @retval FALSE          SEV is not enabled\r
+  **/\r
+STATIC\r
+BOOLEAN\r
+EFIAPI\r
+InternalMemEncryptSevIsEnabled (\r
+  VOID\r
+  )\r
+{\r
+  UINT32                            RegEax;\r
+  MSR_SEV_STATUS_REGISTER           Msr;\r
+  CPUID_MEMORY_ENCRYPTION_INFO_EAX  Eax;\r
+\r
+  //\r
+  // Check if memory encryption leaf exist\r
+  //\r
+  AsmCpuid (CPUID_EXTENDED_FUNCTION, &RegEax, NULL, NULL, NULL);\r
+  if (RegEax >= CPUID_MEMORY_ENCRYPTION_INFO) {\r
+    //\r
+    // CPUID Fn8000_001F[EAX] Bit 1 (Sev supported)\r
+    //\r
+    AsmCpuid (CPUID_MEMORY_ENCRYPTION_INFO, &Eax.Uint32, NULL, NULL, NULL);\r
+\r
+    if (Eax.Bits.SevBit) {\r
+      //\r
+      // Check MSR_0xC0010131 Bit 0 (Sev Enabled)\r
+      //\r
+      Msr.Uint32 = AsmReadMsr32 (MSR_SEV_STATUS);\r
+      if (Msr.Bits.SevBit) {\r
+        return TRUE;\r
+      }\r
+    }\r
+  }\r
+\r
+  return FALSE;\r
+}\r
+\r
+/**\r
+\r
+  Returns a boolean to indicate whether SEV is enabled\r
+\r
+  @retval TRUE           SEV is enabled\r
+  @retval FALSE          SEV is not enabled\r
+  **/\r
+BOOLEAN\r
+EFIAPI\r
+MemEncryptSevIsEnabled (\r
+  VOID\r
+  )\r
+{\r
+  if (mSevStatusChecked) {\r
+    return mSevStatus;\r
+  }\r
+\r
+  mSevStatus = InternalMemEncryptSevIsEnabled();\r
+  mSevStatusChecked = TRUE;\r
+\r
+  return mSevStatus;\r
+}\r
diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c
new file mode 100644 (file)
index 0000000..9ec7670
--- /dev/null
@@ -0,0 +1,84 @@
+/** @file\r
+\r
+  Secure Encrypted Virtualization (SEV) library helper function\r
+\r
+  Copyright (c) 2017, AMD Incorporated. 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
+\r
+**/\r
+\r
+#include <Library/BaseLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Register/Cpuid.h>\r
+#include <Register/Amd/Cpuid.h>\r
+#include <Register/Amd/Msr.h>\r
+#include <Library/MemEncryptSevLib.h>\r
+\r
+#include "VirtualMemory.h"\r
+\r
+/**\r
+\r
+  This function clears memory encryption bit for the memory region specified by\r
+  BaseAddress and Number of pages from the current page table context.\r
+\r
+  @param[in]  Cr3BaseAddress          Cr3 Base Address (if zero then use current CR3)\r
+  @param[in]  BaseAddress             The physical address that is the start address\r
+                                      of a memory region.\r
+  @param[in]  NumberOfPages           The number of pages from start memory region.\r
+  @param[in]  Flush                   Flush the caches before clearing the bit\r
+                                      (mostly TRUE except MMIO addresses)\r
+\r
+  @retval RETURN_SUCCESS              The attributes were cleared for the memory\r
+                                      region.\r
+  @retval RETURN_INVALID_PARAMETER    Number of pages is zero.\r
+  @retval RETURN_UNSUPPORTED          Clearing the memory encryption attribute is\r
+                                      not supported\r
+  **/\r
+RETURN_STATUS\r
+EFIAPI\r
+MemEncryptSevClearPageEncMask (\r
+  IN PHYSICAL_ADDRESS         Cr3BaseAddress,\r
+  IN PHYSICAL_ADDRESS         BaseAddress,\r
+  IN UINTN                    NumPages,\r
+  IN BOOLEAN                  Flush\r
+  )\r
+{\r
+  return InternalMemEncryptSevSetMemoryDecrypted (Cr3BaseAddress, BaseAddress, EFI_PAGES_TO_SIZE(NumPages), Flush);\r
+}\r
+\r
+/**\r
+\r
+  This function clears memory encryption bit for the memory region specified by\r
+  BaseAddress and Number of pages from the current page table context.\r
+\r
+  @param[in]  Cr3BaseAddress          Cr3 Base Address (if zero then use current CR3)\r
+  @param[in]  BaseAddress             The physical address that is the start address\r
+                                      of a memory region.\r
+  @param[in]  NumberOfPages           The number of pages from start memory region.\r
+  @param[in]  Flush                   Flush the caches before clearing the bit\r
+                                      (mostly TRUE except MMIO addresses)\r
+\r
+  @retval RETURN_SUCCESS              The attributes were cleared for the memory\r
+                                      region.\r
+  @retval RETURN_INVALID_PARAMETER    Number of pages is zero.\r
+  @retval RETURN_UNSUPPORTED          Clearing the memory encryption attribute is\r
+                                      not supported\r
+  **/\r
+RETURN_STATUS\r
+EFIAPI\r
+MemEncryptSevSetPageEncMask (\r
+  IN PHYSICAL_ADDRESS         Cr3BaseAddress,\r
+  IN PHYSICAL_ADDRESS         BaseAddress,\r
+  IN UINTN                    NumPages,\r
+  IN BOOLEAN                  Flush\r
+  )\r
+{\r
+  return InternalMemEncryptSevSetMemoryEncrypted (Cr3BaseAddress, BaseAddress, EFI_PAGES_TO_SIZE(NumPages), Flush);\r
+}\r
diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.c b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.c
new file mode 100644 (file)
index 0000000..7cbbf91
--- /dev/null
@@ -0,0 +1,439 @@
+/** @file\r
+\r
+  Virtual Memory Management Services to set or clear the memory encryption bit\r
+\r
+Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2017, AMD Incorporated. 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 License\r
+which accompanies this 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
+\r
+Code is derived from MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c\r
+\r
+**/\r
+\r
+#include <Library/CpuLib.h>\r
+#include <Register/Cpuid.h>\r
+#include <Register/Amd/Cpuid.h>\r
+\r
+#include "VirtualMemory.h"\r
+\r
+STATIC BOOLEAN mAddressEncMaskChecked = FALSE;\r
+STATIC UINT64  mAddressEncMask;\r
+\r
+typedef enum {\r
+   SetCBit,\r
+   ClearCBit\r
+} MAP_RANGE_MODE;\r
+\r
+/**\r
+  Get the memory encryption mask\r
+\r
+  @param[out]      EncryptionMask        contains the pte mask.\r
+\r
+**/\r
+STATIC\r
+UINT64\r
+GetMemEncryptionAddressMask (\r
+  VOID\r
+  )\r
+{\r
+  UINT64                            EncryptionMask;\r
+  CPUID_MEMORY_ENCRYPTION_INFO_EBX  Ebx;\r
+\r
+  if (mAddressEncMaskChecked) {\r
+    return mAddressEncMask;\r
+  }\r
+\r
+  //\r
+  // CPUID Fn8000_001F[EBX] Bit 0:5 (memory encryption bit position)\r
+  //\r
+  AsmCpuid (CPUID_MEMORY_ENCRYPTION_INFO, NULL, &Ebx.Uint32, NULL, NULL);\r
+  EncryptionMask = LShiftU64 (1, Ebx.Bits.PtePosBits);\r
+\r
+  mAddressEncMask = EncryptionMask & PAGING_1G_ADDRESS_MASK_64;\r
+  mAddressEncMaskChecked = TRUE;\r
+\r
+  return mAddressEncMask;\r
+}\r
+\r
+/**\r
+  Split 2M page to 4K.\r
+\r
+  @param[in]      PhysicalAddress       Start physical address the 2M page covered.\r
+  @param[in, out] PageEntry2M           Pointer to 2M page entry.\r
+  @param[in]      StackBase             Stack base address.\r
+  @param[in]      StackSize             Stack size.\r
+\r
+**/\r
+STATIC\r
+VOID\r
+Split2MPageTo4K (\r
+  IN        PHYSICAL_ADDRESS               PhysicalAddress,\r
+  IN  OUT   UINT64                        *PageEntry2M,\r
+  IN        PHYSICAL_ADDRESS               StackBase,\r
+  IN        UINTN                          StackSize\r
+  )\r
+{\r
+  PHYSICAL_ADDRESS                  PhysicalAddress4K;\r
+  UINTN                             IndexOfPageTableEntries;\r
+  PAGE_TABLE_4K_ENTRY               *PageTableEntry, *PageTableEntry1;\r
+  UINT64                            AddressEncMask;\r
+\r
+  PageTableEntry = AllocatePages(1);\r
+\r
+  PageTableEntry1 = PageTableEntry;\r
+\r
+  AddressEncMask = GetMemEncryptionAddressMask ();\r
+\r
+  ASSERT (PageTableEntry != NULL);\r
+  ASSERT (*PageEntry2M & AddressEncMask);\r
+\r
+  PhysicalAddress4K = PhysicalAddress;\r
+  for (IndexOfPageTableEntries = 0; IndexOfPageTableEntries < 512; IndexOfPageTableEntries++, PageTableEntry++, PhysicalAddress4K += SIZE_4KB) {\r
+    //\r
+    // Fill in the Page Table entries\r
+    //\r
+    PageTableEntry->Uint64 = (UINT64) PhysicalAddress4K | AddressEncMask;\r
+    PageTableEntry->Bits.ReadWrite = 1;\r
+    PageTableEntry->Bits.Present = 1;\r
+    if ((PhysicalAddress4K >= StackBase) && (PhysicalAddress4K < StackBase + StackSize)) {\r
+      //\r
+      // Set Nx bit for stack.\r
+      //\r
+      PageTableEntry->Bits.Nx = 1;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Fill in 2M page entry.\r
+  //\r
+  *PageEntry2M = (UINT64) (UINTN) PageTableEntry1 | IA32_PG_P | IA32_PG_RW | AddressEncMask;\r
+}\r
+\r
+/**\r
+  Split 1G page to 2M.\r
+\r
+  @param[in]      PhysicalAddress       Start physical address the 1G page covered.\r
+  @param[in, out] PageEntry1G           Pointer to 1G page entry.\r
+  @param[in]      StackBase             Stack base address.\r
+  @param[in]      StackSize             Stack size.\r
+\r
+**/\r
+STATIC\r
+VOID\r
+Split1GPageTo2M (\r
+  IN          PHYSICAL_ADDRESS               PhysicalAddress,\r
+  IN  OUT     UINT64                         *PageEntry1G,\r
+  IN          PHYSICAL_ADDRESS               StackBase,\r
+  IN          UINTN                          StackSize\r
+  )\r
+{\r
+  PHYSICAL_ADDRESS                  PhysicalAddress2M;\r
+  UINTN                             IndexOfPageDirectoryEntries;\r
+  PAGE_TABLE_ENTRY                  *PageDirectoryEntry;\r
+  UINT64                            AddressEncMask;\r
+\r
+  PageDirectoryEntry = AllocatePages(1);\r
+\r
+  AddressEncMask = GetMemEncryptionAddressMask ();\r
+  ASSERT (PageDirectoryEntry != NULL);\r
+  ASSERT (*PageEntry1G & GetMemEncryptionAddressMask ());\r
+  //\r
+  // Fill in 1G page entry.\r
+  //\r
+  *PageEntry1G = (UINT64) (UINTN) PageDirectoryEntry | IA32_PG_P | IA32_PG_RW | AddressEncMask;\r
+\r
+  PhysicalAddress2M = PhysicalAddress;\r
+  for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PhysicalAddress2M += SIZE_2MB) {\r
+    if ((PhysicalAddress2M < StackBase + StackSize) && ((PhysicalAddress2M + SIZE_2MB) > StackBase)) {\r
+      //\r
+      // Need to split this 2M page that covers stack range.\r
+      //\r
+      Split2MPageTo4K (PhysicalAddress2M, (UINT64 *) PageDirectoryEntry, StackBase, StackSize);\r
+    } else {\r
+      //\r
+      // Fill in the Page Directory entries\r
+      //\r
+      PageDirectoryEntry->Uint64 = (UINT64) PhysicalAddress2M | AddressEncMask;\r
+      PageDirectoryEntry->Bits.ReadWrite = 1;\r
+      PageDirectoryEntry->Bits.Present = 1;\r
+      PageDirectoryEntry->Bits.MustBe1 = 1;\r
+    }\r
+  }\r
+}\r
+\r
+\r
+/**\r
+  Set or Clear the memory encryption bit\r
+\r
+  @param[in]      PagetablePoint        Page table entry pointer (PTE).\r
+  @param[in]      Mode                  Set or Clear encryption bit\r
+\r
+**/\r
+STATIC VOID\r
+SetOrClearCBit(\r
+  IN   OUT     UINT64*            PageTablePointer,\r
+  IN           MAP_RANGE_MODE     Mode\r
+  )\r
+{\r
+  UINT64      AddressEncMask;\r
+\r
+  AddressEncMask = GetMemEncryptionAddressMask ();\r
+\r
+  if (Mode == SetCBit) {\r
+    *PageTablePointer |= AddressEncMask;\r
+  } else {\r
+    *PageTablePointer &= ~AddressEncMask;\r
+  }\r
+\r
+}\r
+\r
+/**\r
+  This function either sets or clears memory encryption bit for the memory region\r
+  specified by PhysicalAddress and length from the current page table context.\r
+\r
+  The function iterates through the physicalAddress one page at a time, and set\r
+  or clears the memory encryption mask in the page table. If it encounters\r
+  that a given physical address range is part of large page then it attempts to\r
+  change the attribute at one go (based on size), otherwise it splits the\r
+  large pages into smaller (e.g 2M page into 4K pages) and then try to set or\r
+  clear the encryption bit on the smallest page size.\r
+\r
+  @param[in]  PhysicalAddress         The physical address that is the start\r
+                                      address of a memory region.\r
+  @param[in]  Length                  The length of memory region\r
+  @param[in]  Mode                    Set or Clear mode\r
+  @param[in]  Flush                   Flush the caches before applying the\r
+                                      encryption mask\r
+\r
+  @retval RETURN_SUCCESS              The attributes were cleared for the memory\r
+                                      region.\r
+  @retval RETURN_INVALID_PARAMETER    Number of pages is zero.\r
+  @retval RETURN_UNSUPPORTED          Setting the memory encyrption attribute is\r
+                                      not supported\r
+**/\r
+\r
+STATIC\r
+RETURN_STATUS\r
+EFIAPI\r
+SetMemoryEncDec (\r
+  IN    PHYSICAL_ADDRESS         Cr3BaseAddress,\r
+  IN    PHYSICAL_ADDRESS         PhysicalAddress,\r
+  IN    UINTN                    Length,\r
+  IN    MAP_RANGE_MODE           Mode,\r
+  IN    BOOLEAN                  CacheFlush\r
+  )\r
+{\r
+  PAGE_MAP_AND_DIRECTORY_POINTER *PageMapLevel4Entry;\r
+  PAGE_MAP_AND_DIRECTORY_POINTER *PageUpperDirectoryPointerEntry;\r
+  PAGE_MAP_AND_DIRECTORY_POINTER *PageDirectoryPointerEntry;\r
+  PAGE_TABLE_1G_ENTRY            *PageDirectory1GEntry;\r
+  PAGE_TABLE_ENTRY               *PageDirectory2MEntry;\r
+  PAGE_TABLE_4K_ENTRY            *PageTableEntry;\r
+  UINT64                         PgTableMask;\r
+  UINT64                         AddressEncMask;\r
+\r
+  //\r
+  // Check if we have a valid memory encryption mask\r
+  //\r
+  AddressEncMask = GetMemEncryptionAddressMask ();\r
+  if (!AddressEncMask) {\r
+    return RETURN_ACCESS_DENIED;\r
+  }\r
+\r
+  PgTableMask = AddressEncMask | EFI_PAGE_MASK;\r
+\r
+  if (Length == 0) {\r
+    return RETURN_INVALID_PARAMETER;\r
+  }\r
+\r
+  //\r
+  // We are going to change the memory encryption attribute from C=0 -> C=1 or\r
+  // vice versa Flush the caches to ensure that data is written into memory with\r
+  // correct C-bit\r
+  //\r
+  if (CacheFlush) {\r
+    WriteBackInvalidateDataCacheRange((VOID*) (UINTN)PhysicalAddress, Length);\r
+  }\r
+\r
+  while (Length)\r
+  {\r
+    //\r
+    // If Cr3BaseAddress is not specified then read the current CR3\r
+    //\r
+    if (Cr3BaseAddress == 0) {\r
+      Cr3BaseAddress = AsmReadCr3();\r
+    }\r
+\r
+    PageMapLevel4Entry = (VOID*) (Cr3BaseAddress & ~PgTableMask);\r
+    PageMapLevel4Entry += PML4_OFFSET(PhysicalAddress);\r
+    if (!PageMapLevel4Entry->Bits.Present) {\r
+      DEBUG ((DEBUG_WARN,\r
+        "%a:%a ERROR bad PML4 for %lx\n", gEfiCallerBaseName, __FUNCTION__,\r
+        PhysicalAddress));\r
+      return RETURN_NO_MAPPING;\r
+    }\r
+\r
+    PageDirectory1GEntry = (VOID*) ((PageMapLevel4Entry->Bits.PageTableBaseAddress<<12) & ~PgTableMask);\r
+    PageDirectory1GEntry += PDP_OFFSET(PhysicalAddress);\r
+    if (!PageDirectory1GEntry->Bits.Present) {\r
+      DEBUG ((DEBUG_WARN,\r
+        "%a:%a ERROR bad PDPE for %lx\n", gEfiCallerBaseName,\r
+         __FUNCTION__, PhysicalAddress));\r
+      return RETURN_NO_MAPPING;\r
+    }\r
+\r
+    //\r
+    // If the MustBe1 bit is not 1, it's not actually a 1GB entry\r
+    //\r
+    if (PageDirectory1GEntry->Bits.MustBe1) {\r
+      //\r
+      // Valid 1GB page\r
+      // If we have at least 1GB to go, we can just update this entry\r
+      //\r
+      if (!(PhysicalAddress & (BIT30 - 1)) && Length >= BIT30) {\r
+        SetOrClearCBit(&PageDirectory1GEntry->Uint64, Mode);\r
+        DEBUG ((DEBUG_VERBOSE,\r
+          "%a:%a Updated 1GB entry for %lx\n", gEfiCallerBaseName,\r
+          __FUNCTION__, PhysicalAddress));\r
+        PhysicalAddress += BIT30;\r
+        Length -= BIT30;\r
+      } else {\r
+        //\r
+        // We must split the page\r
+        //\r
+        DEBUG ((DEBUG_VERBOSE,\r
+          "%a:%a Spliting 1GB page\n", gEfiCallerBaseName, __FUNCTION__));\r
+        Split1GPageTo2M(((UINT64)PageDirectory1GEntry->Bits.PageTableBaseAddress)<<30, (UINT64*) PageDirectory1GEntry, 0, 0);\r
+        continue;\r
+      }\r
+    } else {\r
+      //\r
+      // Actually a PDP\r
+      //\r
+      PageUpperDirectoryPointerEntry = (PAGE_MAP_AND_DIRECTORY_POINTER*) PageDirectory1GEntry;\r
+      PageDirectory2MEntry = (VOID*) ((PageUpperDirectoryPointerEntry->Bits.PageTableBaseAddress<<12) & ~PgTableMask);\r
+      PageDirectory2MEntry += PDE_OFFSET(PhysicalAddress);\r
+      if (!PageDirectory2MEntry->Bits.Present) {\r
+        DEBUG ((DEBUG_WARN,\r
+          "%a:%a ERROR bad PDE for %lx\n", gEfiCallerBaseName, __FUNCTION__,\r
+          PhysicalAddress));\r
+        return RETURN_NO_MAPPING;\r
+      }\r
+      //\r
+      // If the MustBe1 bit is not a 1, it's not a 2MB entry\r
+      //\r
+      if (PageDirectory2MEntry->Bits.MustBe1) {\r
+        //\r
+        // Valid 2MB page\r
+        // If we have at least 2MB left to go, we can just update this entry\r
+        //\r
+        if (!(PhysicalAddress & (BIT21-1)) && Length >= BIT21) {\r
+          SetOrClearCBit (&PageDirectory2MEntry->Uint64, Mode);\r
+          PhysicalAddress += BIT21;\r
+          Length -= BIT21;\r
+        } else {\r
+          //\r
+          // We must split up this page into 4K pages\r
+          //\r
+          DEBUG ((DEBUG_VERBOSE,\r
+            "%a:%a Spliting 2MB page at %lx\n", gEfiCallerBaseName,__FUNCTION__,\r
+            PhysicalAddress));\r
+          Split2MPageTo4K (((UINT64)PageDirectory2MEntry->Bits.PageTableBaseAddress) << 21, (UINT64*) PageDirectory2MEntry, 0, 0);\r
+          continue;\r
+        }\r
+      } else {\r
+        PageDirectoryPointerEntry = (PAGE_MAP_AND_DIRECTORY_POINTER*) PageDirectory2MEntry;\r
+        PageTableEntry = (VOID*) (PageDirectoryPointerEntry->Bits.PageTableBaseAddress<<12 & ~PgTableMask);\r
+        PageTableEntry += PTE_OFFSET(PhysicalAddress);\r
+        if (!PageTableEntry->Bits.Present) {\r
+          DEBUG ((DEBUG_WARN,\r
+            "%a:%a ERROR bad PTE for %lx\n", gEfiCallerBaseName,\r
+            __FUNCTION__, PhysicalAddress));\r
+          return RETURN_NO_MAPPING;\r
+        }\r
+        SetOrClearCBit (&PageTableEntry->Uint64, Mode);\r
+        PhysicalAddress += EFI_PAGE_SIZE;\r
+        Length -= EFI_PAGE_SIZE;\r
+      }\r
+    }\r
+  }\r
+\r
+  //\r
+  // Flush TLB\r
+  //\r
+  CpuFlushTlb();\r
+\r
+  return RETURN_SUCCESS;\r
+}\r
+\r
+/**\r
+  This function clears memory encryption bit for the memory region specified by\r
+  PhysicalAddress and length from the current page table context.\r
+\r
+  @param[in]  PhysicalAddress         The physical address that is the start\r
+                                      address of a memory region.\r
+  @param[in]  Length                  The length of memory region\r
+  @param[in]  Flush                   Flush the caches before applying the\r
+                                      encryption mask\r
+\r
+  @retval RETURN_SUCCESS              The attributes were cleared for the memory\r
+                                      region.\r
+  @retval RETURN_INVALID_PARAMETER    Number of pages is zero.\r
+  @retval RETURN_UNSUPPORTED          Setting the memory encyrption attribute is\r
+                                      not supported\r
+**/\r
+RETURN_STATUS\r
+EFIAPI\r
+InternalMemEncryptSevSetMemoryDecrypted (\r
+  IN  PHYSICAL_ADDRESS        Cr3BaseAddress,\r
+  IN  PHYSICAL_ADDRESS        PhysicalAddress,\r
+  IN  UINTN                   Length,\r
+  IN  BOOLEAN                 Flush\r
+  )\r
+{\r
+\r
+  DEBUG ((DEBUG_VERBOSE,\r
+    "%a:%a Clear C-bit Cr3 %Lx Base %Lx Length %Lx flush %d\n",\r
+    gEfiCallerBaseName, __FUNCTION__, Cr3BaseAddress, PhysicalAddress, Length,\r
+    Flush));\r
+  return SetMemoryEncDec (Cr3BaseAddress, PhysicalAddress, Length, ClearCBit, Flush);\r
+}\r
+\r
+/**\r
+  This function sets memory encryption bit for the memory region specified by\r
+  PhysicalAddress and length from the current page table context.\r
+\r
+  @param[in]  PhysicalAddress         The physical address that is the start address\r
+                                      of a memory region.\r
+  @param[in]  Length                  The length of memory region\r
+  @param[in]  Flush                   Flush the caches before applying the\r
+                                      encryption mask\r
+\r
+  @retval RETURN_SUCCESS              The attributes were cleared for the memory\r
+                                      region.\r
+  @retval RETURN_INVALID_PARAMETER    Number of pages is zero.\r
+  @retval RETURN_UNSUPPORTED          Setting the memory encyrption attribute is\r
+                                      not supported\r
+**/\r
+RETURN_STATUS\r
+EFIAPI\r
+InternalMemEncryptSevSetMemoryEncrypted (\r
+  IN  PHYSICAL_ADDRESS        Cr3BaseAddress,\r
+  IN  PHYSICAL_ADDRESS        PhysicalAddress,\r
+  IN  UINTN                   Length,\r
+  IN  BOOLEAN                 Flush\r
+  )\r
+{\r
+  DEBUG ((DEBUG_VERBOSE,\r
+    "%a:%a Set C-bit Cr3 %Lx Base %Lx Length %Lx flush %d\n",\r
+    gEfiCallerBaseName, __FUNCTION__, Cr3BaseAddress, PhysicalAddress, Length,\r
+    Flush));\r
+  return SetMemoryEncDec (Cr3BaseAddress, PhysicalAddress, Length, SetCBit, Flush);\r
+}\r
diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.h b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.h
new file mode 100644 (file)
index 0000000..70cd218
--- /dev/null
@@ -0,0 +1,184 @@
+/** @file\r
+\r
+  Virtual Memory Management Services to set or clear the memory encryption bit\r
+\r
+Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2017, AMD Incorporated. 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 License\r
+which accompanies this 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
+\r
+Code is derived from MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.h\r
+\r
+**/\r
+\r
+#ifndef __VIRTUAL_MEMORY__\r
+#define __VIRTUAL_MEMORY__\r
+\r
+#include <Uefi.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+\r
+#include <Library/CacheMaintenanceLib.h>\r
+#define SYS_CODE64_SEL 0x38\r
+\r
+#pragma pack(1)\r
+\r
+//\r
+// Page-Map Level-4 Offset (PML4) and\r
+// Page-Directory-Pointer Offset (PDPE) entries 4K & 2MB\r
+//\r
+\r
+typedef union {\r
+  struct {\r
+    UINT64  Present:1;                // 0 = Not present in memory, 1 = Present in memory\r
+    UINT64  ReadWrite:1;              // 0 = Read-Only, 1= Read/Write\r
+    UINT64  UserSupervisor:1;         // 0 = Supervisor, 1=User\r
+    UINT64  WriteThrough:1;           // 0 = Write-Back caching, 1=Write-Through caching\r
+    UINT64  CacheDisabled:1;          // 0 = Cached, 1=Non-Cached\r
+    UINT64  Accessed:1;               // 0 = Not accessed, 1 = Accessed (set by CPU)\r
+    UINT64  Reserved:1;               // Reserved\r
+    UINT64  MustBeZero:2;             // Must Be Zero\r
+    UINT64  Available:3;              // Available for use by system software\r
+    UINT64  PageTableBaseAddress:40;  // Page Table Base Address\r
+    UINT64  AvabilableHigh:11;        // Available for use by system software\r
+    UINT64  Nx:1;                     // No Execute bit\r
+  } Bits;\r
+  UINT64    Uint64;\r
+} PAGE_MAP_AND_DIRECTORY_POINTER;\r
+\r
+//\r
+// Page Table Entry 4KB\r
+//\r
+typedef union {\r
+  struct {\r
+    UINT64  Present:1;                // 0 = Not present in memory, 1 = Present in memory\r
+    UINT64  ReadWrite:1;              // 0 = Read-Only, 1= Read/Write\r
+    UINT64  UserSupervisor:1;         // 0 = Supervisor, 1=User\r
+    UINT64  WriteThrough:1;           // 0 = Write-Back caching, 1=Write-Through caching\r
+    UINT64  CacheDisabled:1;          // 0 = Cached, 1=Non-Cached\r
+    UINT64  Accessed:1;               // 0 = Not accessed, 1 = Accessed (set by CPU)\r
+    UINT64  Dirty:1;                  // 0 = Not Dirty, 1 = written by processor on access to page\r
+    UINT64  PAT:1;                    //\r
+    UINT64  Global:1;                 // 0 = Not global page, 1 = global page TLB not cleared on CR3 write\r
+    UINT64  Available:3;              // Available for use by system software\r
+    UINT64  PageTableBaseAddress:40;  // Page Table Base Address\r
+    UINT64  AvabilableHigh:11;        // Available for use by system software\r
+    UINT64  Nx:1;                     // 0 = Execute Code, 1 = No Code Execution\r
+  } Bits;\r
+  UINT64    Uint64;\r
+} PAGE_TABLE_4K_ENTRY;\r
+\r
+//\r
+// Page Table Entry 2MB\r
+//\r
+typedef union {\r
+  struct {\r
+    UINT64  Present:1;                // 0 = Not present in memory, 1 = Present in memory\r
+    UINT64  ReadWrite:1;              // 0 = Read-Only, 1= Read/Write\r
+    UINT64  UserSupervisor:1;         // 0 = Supervisor, 1=User\r
+    UINT64  WriteThrough:1;           // 0 = Write-Back caching, 1=Write-Through caching\r
+    UINT64  CacheDisabled:1;          // 0 = Cached, 1=Non-Cached\r
+    UINT64  Accessed:1;               // 0 = Not accessed, 1 = Accessed (set by CPU)\r
+    UINT64  Dirty:1;                  // 0 = Not Dirty, 1 = written by processor on access to page\r
+    UINT64  MustBe1:1;                // Must be 1\r
+    UINT64  Global:1;                 // 0 = Not global page, 1 = global page TLB not cleared on CR3 write\r
+    UINT64  Available:3;              // Available for use by system software\r
+    UINT64  PAT:1;                    //\r
+    UINT64  MustBeZero:8;             // Must be zero;\r
+    UINT64  PageTableBaseAddress:31;  // Page Table Base Address\r
+    UINT64  AvabilableHigh:11;        // Available for use by system software\r
+    UINT64  Nx:1;                     // 0 = Execute Code, 1 = No Code Execution\r
+  } Bits;\r
+  UINT64    Uint64;\r
+} PAGE_TABLE_ENTRY;\r
+\r
+//\r
+// Page Table Entry 1GB\r
+//\r
+typedef union {\r
+  struct {\r
+    UINT64  Present:1;                // 0 = Not present in memory, 1 = Present in memory\r
+    UINT64  ReadWrite:1;              // 0 = Read-Only, 1= Read/Write\r
+    UINT64  UserSupervisor:1;         // 0 = Supervisor, 1=User\r
+    UINT64  WriteThrough:1;           // 0 = Write-Back caching, 1=Write-Through caching\r
+    UINT64  CacheDisabled:1;          // 0 = Cached, 1=Non-Cached\r
+    UINT64  Accessed:1;               // 0 = Not accessed, 1 = Accessed (set by CPU)\r
+    UINT64  Dirty:1;                  // 0 = Not Dirty, 1 = written by processor on access to page\r
+    UINT64  MustBe1:1;                // Must be 1\r
+    UINT64  Global:1;                 // 0 = Not global page, 1 = global page TLB not cleared on CR3 write\r
+    UINT64  Available:3;              // Available for use by system software\r
+    UINT64  PAT:1;                    //\r
+    UINT64  MustBeZero:17;            // Must be zero;\r
+    UINT64  PageTableBaseAddress:22;  // Page Table Base Address\r
+    UINT64  AvabilableHigh:11;        // Available for use by system software\r
+    UINT64  Nx:1;                     // 0 = Execute Code, 1 = No Code Execution\r
+  } Bits;\r
+  UINT64    Uint64;\r
+} PAGE_TABLE_1G_ENTRY;\r
+\r
+#pragma pack()\r
+\r
+#define IA32_PG_P                   BIT0\r
+#define IA32_PG_RW                  BIT1\r
+\r
+#define PAGETABLE_ENTRY_MASK        ((1UL << 9) - 1)\r
+#define PML4_OFFSET(x)              ( (x >> 39) & PAGETABLE_ENTRY_MASK)\r
+#define PDP_OFFSET(x)               ( (x >> 30) & PAGETABLE_ENTRY_MASK)\r
+#define PDE_OFFSET(x)               ( (x >> 21) & PAGETABLE_ENTRY_MASK)\r
+#define PTE_OFFSET(x)               ( (x >> 12) & PAGETABLE_ENTRY_MASK)\r
+#define PAGING_1G_ADDRESS_MASK_64   0x000FFFFFC0000000ull\r
+\r
+/**\r
+  This function clears memory encryption bit for the memory region specified by PhysicalAddress\r
+  and length from the current page table context.\r
+\r
+  @param[in]  PhysicalAddress         The physical address that is the start address of a memory region.\r
+  @param[in]  Length                  The length of memory region\r
+  @param[in]  Flush                   Flush the caches before applying the encryption mask\r
+\r
+  @retval RETURN_SUCCESS              The attributes were cleared for the memory region.\r
+  @retval RETURN_INVALID_PARAMETER    Number of pages is zero.\r
+  @retval RETURN_UNSUPPORTED          Setting the memory encyrption attribute is not supported\r
+**/\r
+RETURN_STATUS\r
+EFIAPI\r
+InternalMemEncryptSevSetMemoryDecrypted (\r
+  IN  PHYSICAL_ADDRESS     Cr3BaseAddress,\r
+  IN  PHYSICAL_ADDRESS     PhysicalAddress,\r
+  IN  UINT64               Length,\r
+  IN  BOOLEAN              CacheFlush\r
+  );\r
+\r
+/**\r
+  This function sets memory encryption bit for the memory region specified by\r
+  PhysicalAddress and length from the current page table context.\r
+\r
+  @param[in]  PhysicalAddress         The physical address that is the start address\r
+                                      of a memory region.\r
+  @param[in]  Length                  The length of memory region\r
+  @param[in]  Flush                   Flush the caches before applying the\r
+                                      encryption mask\r
+\r
+  @retval RETURN_SUCCESS              The attributes were cleared for the memory region.\r
+  @retval RETURN_INVALID_PARAMETER    Number of pages is zero.\r
+  @retval RETURN_UNSUPPORTED          Setting the memory encyrption attribute is\r
+                                      not supported\r
+**/\r
+RETURN_STATUS\r
+EFIAPI\r
+InternalMemEncryptSevSetMemoryEncrypted (\r
+  IN  PHYSICAL_ADDRESS     Cr3BaseAddress,\r
+  IN  PHYSICAL_ADDRESS     PhysicalAddress,\r
+  IN  UINT64               Length,\r
+  IN  BOOLEAN              CacheFlush\r
+  );\r
+\r
+#endif\r
index c276a2c..29884b7 100644 (file)
   QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf\r
   VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf\r
   LoadLinuxLib|OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.inf\r
+  MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/BaseMemEncryptSevLib.inf\r
 !if $(SMM_REQUIRE) == FALSE\r
   LockBoxLib|OvmfPkg/Library/LockBoxLib/LockBoxBaseLib.inf\r
 !endif\r
index 7ec6687..2b646e4 100644 (file)
   QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf\r
   VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf\r
   LoadLinuxLib|OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.inf\r
+  MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/BaseMemEncryptSevLib.inf\r
 !if $(SMM_REQUIRE) == FALSE\r
   LockBoxLib|OvmfPkg/Library/LockBoxLib/LockBoxBaseLib.inf\r
 !endif\r
index 3b43622..32386de 100644 (file)
   QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf\r
   VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf\r
   LoadLinuxLib|OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.inf\r
+  MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/BaseMemEncryptSevLib.inf\r
 !if $(SMM_REQUIRE) == FALSE\r
   LockBoxLib|OvmfPkg/Library/LockBoxLib/LockBoxBaseLib.inf\r
 !endif\r