UINT64 EncryptionMask;\r
} SEC_SEV_ES_WORK_AREA;\r
\r
+//\r
+// Memory encryption address range states.\r
+//\r
+typedef enum {\r
+ MemEncryptSevAddressRangeUnencrypted,\r
+ MemEncryptSevAddressRangeEncrypted,\r
+ MemEncryptSevAddressRangeMixed,\r
+ MemEncryptSevAddressRangeError,\r
+} MEM_ENCRYPT_SEV_ADDRESS_RANGE_STATE;\r
+\r
/**\r
Returns a boolean to indicate whether SEV-ES is enabled.\r
\r
VOID\r
);\r
\r
+/**\r
+ Returns the encryption state of the specified virtual address range.\r
+\r
+ @param[in] Cr3BaseAddress Cr3 Base Address (if zero then use\r
+ current CR3)\r
+ @param[in] BaseAddress Base address to check\r
+ @param[in] Length Length of virtual address range\r
+\r
+ @retval MemEncryptSevAddressRangeUnencrypted Address range is mapped\r
+ unencrypted\r
+ @retval MemEncryptSevAddressRangeEncrypted Address range is mapped\r
+ encrypted\r
+ @retval MemEncryptSevAddressRangeMixed Address range is mapped mixed\r
+ @retval MemEncryptSevAddressRangeError Address range is not mapped\r
+**/\r
+MEM_ENCRYPT_SEV_ADDRESS_RANGE_STATE\r
+EFIAPI\r
+MemEncryptSevGetAddressRangeState (\r
+ IN PHYSICAL_ADDRESS Cr3BaseAddress,\r
+ IN PHYSICAL_ADDRESS BaseAddress,\r
+ IN UINTN Length\r
+ );\r
+\r
#endif // _MEM_ENCRYPT_SEV_LIB_H_\r
[Sources.X64]\r
X64/MemEncryptSevLib.c\r
X64/PeiDxeVirtualMemory.c\r
+ X64/VirtualMemory.c\r
X64/VirtualMemory.h\r
\r
[Sources.IA32]\r
\r
Secure Encrypted Virtualization (SEV) library helper function\r
\r
- Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>\r
+ Copyright (c) 2017 - 2020, AMD Incorporated. All rights reserved.<BR>\r
\r
SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
//\r
return RETURN_UNSUPPORTED;\r
}\r
+\r
+/**\r
+ Returns the encryption state of the specified virtual address range.\r
+\r
+ @param[in] Cr3BaseAddress Cr3 Base Address (if zero then use\r
+ current CR3)\r
+ @param[in] BaseAddress Base address to check\r
+ @param[in] Length Length of virtual address range\r
+\r
+ @retval MemEncryptSevAddressRangeUnencrypted Address range is mapped\r
+ unencrypted\r
+ @retval MemEncryptSevAddressRangeEncrypted Address range is mapped\r
+ encrypted\r
+ @retval MemEncryptSevAddressRangeMixed Address range is mapped mixed\r
+ @retval MemEncryptSevAddressRangeError Address range is not mapped\r
+**/\r
+MEM_ENCRYPT_SEV_ADDRESS_RANGE_STATE\r
+EFIAPI\r
+MemEncryptSevGetAddressRangeState (\r
+ IN PHYSICAL_ADDRESS Cr3BaseAddress,\r
+ IN PHYSICAL_ADDRESS BaseAddress,\r
+ IN UINTN Length\r
+ )\r
+{\r
+ //\r
+ // Memory is always encrypted in 32-bit mode\r
+ //\r
+ return MemEncryptSevAddressRangeEncrypted;\r
+}\r
[Sources.X64]\r
X64/MemEncryptSevLib.c\r
X64/PeiDxeVirtualMemory.c\r
+ X64/VirtualMemory.c\r
X64/VirtualMemory.h\r
\r
[Sources.IA32]\r
[Sources.X64]\r
X64/MemEncryptSevLib.c\r
X64/SecVirtualMemory.c\r
+ X64/VirtualMemory.c\r
X64/VirtualMemory.h\r
\r
[Sources.IA32]\r
\r
Secure Encrypted Virtualization (SEV) library helper function\r
\r
- Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>\r
+ Copyright (c) 2017 - 2020, AMD Incorporated. All rights reserved.<BR>\r
\r
SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
Flush\r
);\r
}\r
+\r
+/**\r
+ Returns the encryption state of the specified virtual address range.\r
+\r
+ @param[in] Cr3BaseAddress Cr3 Base Address (if zero then use\r
+ current CR3)\r
+ @param[in] BaseAddress Base address to check\r
+ @param[in] Length Length of virtual address range\r
+\r
+ @retval MemEncryptSevAddressRangeUnencrypted Address range is mapped\r
+ unencrypted\r
+ @retval MemEncryptSevAddressRangeEncrypted Address range is mapped\r
+ encrypted\r
+ @retval MemEncryptSevAddressRangeMixed Address range is mapped mixed\r
+ @retval MemEncryptSevAddressRangeError Address range is not mapped\r
+**/\r
+MEM_ENCRYPT_SEV_ADDRESS_RANGE_STATE\r
+EFIAPI\r
+MemEncryptSevGetAddressRangeState (\r
+ IN PHYSICAL_ADDRESS Cr3BaseAddress,\r
+ IN PHYSICAL_ADDRESS BaseAddress,\r
+ IN UINTN Length\r
+ )\r
+{\r
+ return InternalMemEncryptSevGetAddressRangeState (\r
+ Cr3BaseAddress,\r
+ BaseAddress,\r
+ Length\r
+ );\r
+}\r
} MAP_RANGE_MODE;\r
\r
/**\r
- Get the memory encryption mask\r
+ Return the pagetable memory encryption mask.\r
\r
- @param[out] EncryptionMask contains the pte mask.\r
+ @return The pagetable memory encryption mask.\r
\r
**/\r
-STATIC\r
UINT64\r
-GetMemEncryptionAddressMask (\r
+EFIAPI\r
+InternalGetMemEncryptionAddressMask (\r
VOID\r
)\r
{\r
\r
PageTableEntry1 = PageTableEntry;\r
\r
- AddressEncMask = GetMemEncryptionAddressMask ();\r
+ AddressEncMask = InternalGetMemEncryptionAddressMask ();\r
\r
ASSERT (PageTableEntry != NULL);\r
ASSERT (*PageEntry2M & AddressEncMask);\r
LevelSize[3] = SIZE_1GB;\r
LevelSize[4] = SIZE_512GB;\r
\r
- AddressEncMask = GetMemEncryptionAddressMask();\r
+ AddressEncMask = InternalGetMemEncryptionAddressMask();\r
PageTable = (UINT64 *)(UINTN)PageTableBase;\r
PoolUnitSize = PAGE_TABLE_POOL_UNIT_SIZE;\r
\r
\r
PageDirectoryEntry = AllocatePageTableMemory(1);\r
\r
- AddressEncMask = GetMemEncryptionAddressMask ();\r
+ AddressEncMask = InternalGetMemEncryptionAddressMask ();\r
ASSERT (PageDirectoryEntry != NULL);\r
ASSERT (*PageEntry1G & AddressEncMask);\r
//\r
{\r
UINT64 AddressEncMask;\r
\r
- AddressEncMask = GetMemEncryptionAddressMask ();\r
+ AddressEncMask = InternalGetMemEncryptionAddressMask ();\r
\r
if (Mode == SetCBit) {\r
*PageTablePointer |= AddressEncMask;\r
/**\r
Enable Write Protect on pages marked as read-only.\r
**/\r
+STATIC\r
VOID\r
EnableReadOnlyPageWriteProtect (\r
VOID\r
//\r
// Check if we have a valid memory encryption mask\r
//\r
- AddressEncMask = GetMemEncryptionAddressMask ();\r
+ AddressEncMask = InternalGetMemEncryptionAddressMask ();\r
if (!AddressEncMask) {\r
return RETURN_ACCESS_DENIED;\r
}\r
\r
#include "VirtualMemory.h"\r
\r
+/**\r
+ Return the pagetable memory encryption mask.\r
+\r
+ @return The pagetable memory encryption mask.\r
+\r
+**/\r
+UINT64\r
+EFIAPI\r
+InternalGetMemEncryptionAddressMask (\r
+ VOID\r
+ )\r
+{\r
+ UINT64 EncryptionMask;\r
+\r
+ EncryptionMask = MemEncryptSevGetEncryptionMask ();\r
+ EncryptionMask &= PAGING_1G_ADDRESS_MASK_64;\r
+\r
+ return EncryptionMask;\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
--- /dev/null
+/** @file\r
+\r
+ Virtual Memory Management Services to test an address range encryption state\r
+\r
+ Copyright (c) 2020, AMD Incorporated. All rights reserved.<BR>\r
+\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#include <Library/CpuLib.h>\r
+#include <Library/MemEncryptSevLib.h>\r
+\r
+#include "VirtualMemory.h"\r
+\r
+/**\r
+ Returns the (updated) address range state based upon the page table\r
+ entry.\r
+\r
+ @param[in] CurrentState The current address range state\r
+ @param[in] PageDirectoryEntry The page table entry to check\r
+ @param[in] AddressEncMask The encryption mask\r
+\r
+ @retval MemEncryptSevAddressRangeUnencrypted Address range is mapped\r
+ unencrypted\r
+ @retval MemEncryptSevAddressRangeEncrypted Address range is mapped\r
+ encrypted\r
+ @retval MemEncryptSevAddressRangeMixed Address range is mapped mixed\r
+**/\r
+STATIC\r
+MEM_ENCRYPT_SEV_ADDRESS_RANGE_STATE\r
+UpdateAddressState (\r
+ IN MEM_ENCRYPT_SEV_ADDRESS_RANGE_STATE CurrentState,\r
+ IN UINT64 PageDirectoryEntry,\r
+ IN UINT64 AddressEncMask\r
+ )\r
+{\r
+ if (CurrentState == MemEncryptSevAddressRangeEncrypted) {\r
+ if ((PageDirectoryEntry & AddressEncMask) == 0) {\r
+ CurrentState = MemEncryptSevAddressRangeMixed;\r
+ }\r
+ } else if (CurrentState == MemEncryptSevAddressRangeUnencrypted) {\r
+ if ((PageDirectoryEntry & AddressEncMask) != 0) {\r
+ CurrentState = MemEncryptSevAddressRangeMixed;\r
+ }\r
+ } else if (CurrentState == MemEncryptSevAddressRangeError) {\r
+ //\r
+ // First address check, set initial state\r
+ //\r
+ if ((PageDirectoryEntry & AddressEncMask) == 0) {\r
+ CurrentState = MemEncryptSevAddressRangeUnencrypted;\r
+ } else {\r
+ CurrentState = MemEncryptSevAddressRangeEncrypted;\r
+ }\r
+ }\r
+\r
+ return CurrentState;\r
+}\r
+\r
+/**\r
+ Returns the encryption state of the specified virtual address range.\r
+\r
+ @param[in] Cr3BaseAddress Cr3 Base Address (if zero then use\r
+ current CR3)\r
+ @param[in] BaseAddress Base address to check\r
+ @param[in] Length Length of virtual address range\r
+\r
+ @retval MemEncryptSevAddressRangeUnencrypted Address range is mapped\r
+ unencrypted\r
+ @retval MemEncryptSevAddressRangeEncrypted Address range is mapped\r
+ encrypted\r
+ @retval MemEncryptSevAddressRangeMixed Address range is mapped mixed\r
+ @retval MemEncryptSevAddressRangeError Address range is not mapped\r
+**/\r
+MEM_ENCRYPT_SEV_ADDRESS_RANGE_STATE\r
+EFIAPI\r
+InternalMemEncryptSevGetAddressRangeState (\r
+ IN PHYSICAL_ADDRESS Cr3BaseAddress,\r
+ IN PHYSICAL_ADDRESS BaseAddress,\r
+ IN UINTN Length\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 AddressEncMask;\r
+ UINT64 PgTableMask;\r
+ PHYSICAL_ADDRESS Address;\r
+ PHYSICAL_ADDRESS AddressEnd;\r
+ MEM_ENCRYPT_SEV_ADDRESS_RANGE_STATE State;\r
+\r
+ //\r
+ // If Cr3BaseAddress is not specified then read the current CR3\r
+ //\r
+ if (Cr3BaseAddress == 0) {\r
+ Cr3BaseAddress = AsmReadCr3();\r
+ }\r
+\r
+ AddressEncMask = MemEncryptSevGetEncryptionMask ();\r
+ AddressEncMask &= PAGING_1G_ADDRESS_MASK_64;\r
+\r
+ PgTableMask = AddressEncMask | EFI_PAGE_MASK;\r
+\r
+ State = MemEncryptSevAddressRangeError;\r
+\r
+ //\r
+ // Encryption is on a page basis, so start at the beginning of the\r
+ // virtual address page boundary and walk page-by-page.\r
+ //\r
+ Address = (PHYSICAL_ADDRESS) (UINTN) BaseAddress & ~EFI_PAGE_MASK;\r
+ AddressEnd = (PHYSICAL_ADDRESS)\r
+ (UINTN) (BaseAddress + Length);\r
+\r
+ while (Address < AddressEnd) {\r
+ PageMapLevel4Entry = (VOID*) (Cr3BaseAddress & ~PgTableMask);\r
+ PageMapLevel4Entry += PML4_OFFSET (Address);\r
+ if (!PageMapLevel4Entry->Bits.Present) {\r
+ return MemEncryptSevAddressRangeError;\r
+ }\r
+\r
+ PageDirectory1GEntry = (VOID *) (\r
+ (PageMapLevel4Entry->Bits.PageTableBaseAddress <<\r
+ 12) & ~PgTableMask\r
+ );\r
+ PageDirectory1GEntry += PDP_OFFSET (Address);\r
+ if (!PageDirectory1GEntry->Bits.Present) {\r
+ return MemEncryptSevAddressRangeError;\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
+ //\r
+ State = UpdateAddressState (\r
+ State,\r
+ PageDirectory1GEntry->Uint64,\r
+ AddressEncMask\r
+ );\r
+\r
+ Address += BIT30;\r
+ continue;\r
+ }\r
+\r
+ //\r
+ // Actually a PDP\r
+ //\r
+ PageUpperDirectoryPointerEntry =\r
+ (PAGE_MAP_AND_DIRECTORY_POINTER *) PageDirectory1GEntry;\r
+ PageDirectory2MEntry =\r
+ (VOID *) (\r
+ (PageUpperDirectoryPointerEntry->Bits.PageTableBaseAddress <<\r
+ 12) & ~PgTableMask\r
+ );\r
+ PageDirectory2MEntry += PDE_OFFSET (Address);\r
+ if (!PageDirectory2MEntry->Bits.Present) {\r
+ return MemEncryptSevAddressRangeError;\r
+ }\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
+ //\r
+ State = UpdateAddressState (\r
+ State,\r
+ PageDirectory2MEntry->Uint64,\r
+ AddressEncMask\r
+ );\r
+\r
+ Address += BIT21;\r
+ continue;\r
+ }\r
+\r
+ //\r
+ // Actually a PMD\r
+ //\r
+ PageDirectoryPointerEntry =\r
+ (PAGE_MAP_AND_DIRECTORY_POINTER *)PageDirectory2MEntry;\r
+ PageTableEntry =\r
+ (VOID *)(\r
+ (PageDirectoryPointerEntry->Bits.PageTableBaseAddress <<\r
+ 12) & ~PgTableMask\r
+ );\r
+ PageTableEntry += PTE_OFFSET (Address);\r
+ if (!PageTableEntry->Bits.Present) {\r
+ return MemEncryptSevAddressRangeError;\r
+ }\r
+\r
+ State = UpdateAddressState (\r
+ State,\r
+ PageTableEntry->Uint64,\r
+ AddressEncMask\r
+ );\r
+\r
+ Address += EFI_PAGE_SIZE;\r
+ }\r
+\r
+ return State;\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
+ Copyright (c) 2017 - 2020, AMD Incorporated. All rights reserved.<BR>\r
\r
SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
UINTN FreePages;\r
} PAGE_TABLE_POOL;\r
\r
+/**\r
+ Return the pagetable memory encryption mask.\r
\r
+ @return The pagetable memory encryption mask.\r
+\r
+**/\r
+UINT64\r
+EFIAPI\r
+InternalGetMemEncryptionAddressMask (\r
+ VOID\r
+ );\r
\r
/**\r
This function clears memory encryption bit for the memory region specified by\r
IN BOOLEAN Flush\r
);\r
\r
+/**\r
+ Returns the encryption state of the specified virtual address range.\r
+\r
+ @param[in] Cr3BaseAddress Cr3 Base Address (if zero then use\r
+ current CR3)\r
+ @param[in] BaseAddress Base address to check\r
+ @param[in] Length Length of virtual address range\r
+\r
+ @retval MemEncryptSevAddressRangeUnencrypted Address range is mapped\r
+ unencrypted\r
+ @retval MemEncryptSevAddressRangeEncrypted Address range is mapped\r
+ encrypted\r
+ @retval MemEncryptSevAddressRangeMixed Address range is mapped mixed\r
+ @retval MemEncryptSevAddressRangeError Address range is not mapped\r
+**/\r
+MEM_ENCRYPT_SEV_ADDRESS_RANGE_STATE\r
+EFIAPI\r
+InternalMemEncryptSevGetAddressRangeState (\r
+ IN PHYSICAL_ADDRESS Cr3BaseAddress,\r
+ IN PHYSICAL_ADDRESS BaseAddress,\r
+ IN UINTN Length\r
+ );\r
+\r
#endif\r