/** @file\r
\r
- Virtual Memory Management Services to set or clear the memory encryption bit\r
+ Virtual Memory Management Services to test an address range encryption state\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) 2020, 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
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
#include <Library/CpuLib.h>\r
-#include <Register/Cpuid.h>\r
-#include <Register/Amd/Cpuid.h>\r
+#include <Library/MemEncryptSevLib.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
+ 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
-UINT64\r
-GetMemEncryptionAddressMask (\r
- VOID\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
- 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
+ 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
- // Fill in the Page Table entries\r
+ // First address check, set initial state\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
+ if ((PageDirectoryEntry & AddressEncMask) == 0) {\r
+ CurrentState = MemEncryptSevAddressRangeUnencrypted;\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
+ CurrentState = MemEncryptSevAddressRangeEncrypted;\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
+ return CurrentState;\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
+ 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
-\r
-STATIC\r
-RETURN_STATUS\r
+MEM_ENCRYPT_SEV_ADDRESS_RANGE_STATE\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
+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 PgTableMask;\r
- UINT64 AddressEncMask;\r
-\r
- DEBUG ((\r
- DEBUG_VERBOSE,\r
- "%a:%a: Cr3Base=0x%Lx Physical=0x%Lx Length=0x%Lx Mode=%a CacheFlush=%u\n",\r
- gEfiCallerBaseName,\r
- __FUNCTION__,\r
- Cr3BaseAddress,\r
- PhysicalAddress,\r
- (UINT64)Length,\r
- (Mode == SetCBit) ? "Encrypt" : "Decrypt",\r
- (UINT32)CacheFlush\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
- // Check if we have a valid memory encryption mask\r
+ // If Cr3BaseAddress is not specified then read the current CR3\r
//\r
- AddressEncMask = GetMemEncryptionAddressMask ();\r
- if (!AddressEncMask) {\r
- return RETURN_ACCESS_DENIED;\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
- if (Length == 0) {\r
- return RETURN_INVALID_PARAMETER;\r
- }\r
+ State = MemEncryptSevAddressRangeError;\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
+ // 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
- 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
+ Address = (PHYSICAL_ADDRESS)(UINTN)BaseAddress & ~EFI_PAGE_MASK;\r
+ AddressEnd = (PHYSICAL_ADDRESS)\r
+ (UINTN)(BaseAddress + Length);\r
\r
- PageMapLevel4Entry = (VOID*) (Cr3BaseAddress & ~PgTableMask);\r
- PageMapLevel4Entry += PML4_OFFSET(PhysicalAddress);\r
+ while (Address < AddressEnd) {\r
+ PageMapLevel4Entry = (VOID *)(Cr3BaseAddress & ~PgTableMask);\r
+ PageMapLevel4Entry += PML4_OFFSET (Address);\r
if (!PageMapLevel4Entry->Bits.Present) {\r
- DEBUG ((\r
- DEBUG_WARN,\r
- "%a:%a: ERROR bad PML4 for Physical=0x%Lx\n",\r
- gEfiCallerBaseName,\r
- __FUNCTION__,\r
- PhysicalAddress\r
- ));\r
- return RETURN_NO_MAPPING;\r
+ return MemEncryptSevAddressRangeError;\r
}\r
\r
- PageDirectory1GEntry = (VOID*) ((PageMapLevel4Entry->Bits.PageTableBaseAddress<<12) & ~PgTableMask);\r
- PageDirectory1GEntry += PDP_OFFSET(PhysicalAddress);\r
+ PageDirectory1GEntry = (VOID *)(\r
+ (PageMapLevel4Entry->Bits.PageTableBaseAddress <<\r
+ 12) & ~PgTableMask\r
+ );\r
+ PageDirectory1GEntry += PDP_OFFSET (Address);\r
if (!PageDirectory1GEntry->Bits.Present) {\r
- DEBUG ((\r
- DEBUG_WARN,\r
- "%a:%a: ERROR bad PDPE for Physical=0x%Lx\n",\r
- gEfiCallerBaseName,\r
- __FUNCTION__,\r
- PhysicalAddress\r
- ));\r
- return RETURN_NO_MAPPING;\r
+ return MemEncryptSevAddressRangeError;\r
}\r
\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 ((\r
- DEBUG_VERBOSE,\r
- "%a:%a: Updated 1GB entry for Physical=0x%Lx\n",\r
- gEfiCallerBaseName,\r
- __FUNCTION__,\r
- PhysicalAddress\r
- ));\r
- PhysicalAddress += BIT30;\r
- Length -= BIT30;\r
- } else {\r
- //\r
- // We must split the page\r
- //\r
- DEBUG ((\r
- DEBUG_VERBOSE,\r
- "%a:%a: Spliting 1GB page for Physical=0x%Lx\n",\r
- gEfiCallerBaseName,\r
- __FUNCTION__,\r
- PhysicalAddress\r
- ));\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 ((\r
- DEBUG_WARN,\r
- "%a:%a: ERROR bad PDE for Physical=0x%Lx\n",\r
- gEfiCallerBaseName,\r
- __FUNCTION__,\r
- PhysicalAddress\r
- ));\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 ((\r
- DEBUG_VERBOSE,\r
- "%a:%a: Spliting 2MB page for Physical=0x%Lx\n",\r
- gEfiCallerBaseName,\r
- __FUNCTION__,\r
- PhysicalAddress\r
- ));\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 ((\r
- DEBUG_WARN,\r
- "%a:%a: ERROR bad PTE for Physical=0x%Lx\n",\r
- gEfiCallerBaseName,\r
- __FUNCTION__,\r
- PhysicalAddress\r
- ));\r
- return RETURN_NO_MAPPING;\r
- }\r
- SetOrClearCBit (&PageTableEntry->Uint64, Mode);\r
- PhysicalAddress += EFI_PAGE_SIZE;\r
- Length -= EFI_PAGE_SIZE;\r
- }\r
+ State = UpdateAddressState (\r
+ State,\r
+ PageDirectory1GEntry->Uint64,\r
+ AddressEncMask\r
+ );\r
+\r
+ Address += BIT30;\r
+ continue;\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
+ // 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
- @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
+ // 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
- return SetMemoryEncDec (Cr3BaseAddress, PhysicalAddress, Length, ClearCBit, Flush);\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
-/**\r
- This function sets memory encryption bit for the memory region specified by\r
- PhysicalAddress and length from the current page table context.\r
+ State = UpdateAddressState (\r
+ State,\r
+ PageTableEntry->Uint64,\r
+ AddressEncMask\r
+ );\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
+ Address += EFI_PAGE_SIZE;\r
+ }\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
- return SetMemoryEncDec (Cr3BaseAddress, PhysicalAddress, Length, SetCBit, Flush);\r
+ return State;\r
}\r