23STATIC UINT64 mAddressEncMask;
45 UINT64 EncryptionMask;
47 if (mAddressEncMaskChecked) {
48 return mAddressEncMask;
53 mAddressEncMask = EncryptionMask & PAGING_1G_ADDRESS_MASK_64;
54 mAddressEncMaskChecked =
TRUE;
56 return mAddressEncMask;
90 PoolPages = ((PoolPages - 1) / PAGE_TABLE_POOL_UNIT_PAGES + 1) *
91 PAGE_TABLE_POOL_UNIT_PAGES;
94 DEBUG ((DEBUG_ERROR,
"ERROR: Out of aligned pages\r\n"));
101 if (mPageTablePool ==
NULL) {
102 mPageTablePool = Buffer;
103 mPageTablePool->NextPool = mPageTablePool;
106 mPageTablePool->NextPool = Buffer;
107 mPageTablePool = Buffer;
113 mPageTablePool->FreePages = PoolPages - 1;
152 if ((mPageTablePool ==
NULL) ||
153 (Pages > mPageTablePool->FreePages))
160 Buffer = (UINT8 *)mPageTablePool + mPageTablePool->Offset;
163 mPageTablePool->FreePages -= Pages;
167 "%a:%a: Buffer=0x%Lx Pages=%ld\n",
190 IN PHYSICAL_ADDRESS PhysicalAddress,
191 IN OUT UINT64 *PageEntry2M,
192 IN PHYSICAL_ADDRESS StackBase,
196 PHYSICAL_ADDRESS PhysicalAddress4K;
197 UINTN IndexOfPageTableEntries;
200 UINT64 AddressEncMask;
204 PageTableEntry1 = PageTableEntry;
208 ASSERT (PageTableEntry !=
NULL);
209 ASSERT (*PageEntry2M & AddressEncMask);
211 PhysicalAddress4K = PhysicalAddress;
212 for (IndexOfPageTableEntries = 0;
213 IndexOfPageTableEntries < 512;
214 (IndexOfPageTableEntries++,
216 PhysicalAddress4K += SIZE_4KB))
221 PageTableEntry->Uint64 = (UINT64)PhysicalAddress4K | AddressEncMask;
222 PageTableEntry->Bits.ReadWrite = 1;
223 PageTableEntry->Bits.Present = 1;
224 if ((PhysicalAddress4K >= StackBase) &&
225 (PhysicalAddress4K < StackBase + StackSize))
230 PageTableEntry->Bits.Nx = 1;
243 *PageEntry2M = ((UINT64)(
UINTN)PageTableEntry1 |
244 IA32_PG_P | IA32_PG_RW);
260 IN BOOLEAN Level4Paging
265 UINT64 AddressEncMask;
268 UINT64 *NewPageTable;
276 ASSERT (PageTableBase != 0);
283 Address = Address & PAGE_TABLE_POOL_ALIGN_MASK;
285 LevelShift[1] = PAGING_L1_ADDRESS_SHIFT;
286 LevelShift[2] = PAGING_L2_ADDRESS_SHIFT;
287 LevelShift[3] = PAGING_L3_ADDRESS_SHIFT;
288 LevelShift[4] = PAGING_L4_ADDRESS_SHIFT;
290 LevelMask[1] = PAGING_4K_ADDRESS_MASK_64;
291 LevelMask[2] = PAGING_2M_ADDRESS_MASK_64;
292 LevelMask[3] = PAGING_1G_ADDRESS_MASK_64;
293 LevelMask[4] = PAGING_1G_ADDRESS_MASK_64;
295 LevelSize[1] = SIZE_4KB;
296 LevelSize[2] = SIZE_2MB;
297 LevelSize[3] = SIZE_1GB;
298 LevelSize[4] = SIZE_512GB;
301 PageTable = (UINT64 *)(
UINTN)PageTableBase;
302 PoolUnitSize = PAGE_TABLE_POOL_UNIT_SIZE;
304 for (Level = (Level4Paging) ? 4 : 3; Level > 0; --Level) {
306 Index &= PAGING_PAE_INDEX_MASK;
308 PageAttr = PageTable[Index];
309 if ((PageAttr & IA32_PG_PS) == 0) {
313 PageTable = (UINT64 *)(
UINTN)(PageAttr & ~AddressEncMask &
314 PAGING_4K_ADDRESS_MASK_64);
318 if (PoolUnitSize >= LevelSize[Level]) {
323 if ((PageAttr & IA32_PG_RW) != 0) {
324 while (PoolUnitSize > 0) {
330 ASSERT (Index < EFI_PAGE_SIZE/
sizeof (UINT64));
332 PageTable[Index] &= ~(UINT64)IA32_PG_RW;
333 PoolUnitSize -= LevelSize[Level];
347 ASSERT (NewPageTable !=
NULL);
349 PhysicalAddress = PageAttr & LevelMask[Level];
351 EntryIndex < EFI_PAGE_SIZE/
sizeof (UINT64);
354 NewPageTable[EntryIndex] = PhysicalAddress | AddressEncMask |
355 IA32_PG_P | IA32_PG_RW;
357 NewPageTable[EntryIndex] |= IA32_PG_PS;
360 PhysicalAddress += LevelSize[Level - 1];
366 PageTable[Index] = (UINT64)(
UINTN)NewPageTable |
367 IA32_PG_P | IA32_PG_RW;
368 PageTable = NewPageTable;
384 IN BOOLEAN Level4Paging
392 if (mPageTablePool ==
NULL) {
400 HeadPool = mPageTablePool;
411 while (PoolSize > 0) {
413 Address += PAGE_TABLE_POOL_UNIT_SIZE;
414 PoolSize -= PAGE_TABLE_POOL_UNIT_SIZE;
417 Pool = Pool->NextPool;
418 }
while (Pool != HeadPool);
434 IN PHYSICAL_ADDRESS PhysicalAddress,
435 IN OUT UINT64 *PageEntry1G,
436 IN PHYSICAL_ADDRESS StackBase,
440 PHYSICAL_ADDRESS PhysicalAddress2M;
441 UINTN IndexOfPageDirectoryEntries;
443 UINT64 AddressEncMask;
448 ASSERT (PageDirectoryEntry !=
NULL);
449 ASSERT (*PageEntry1G & AddressEncMask);
455 *PageEntry1G = ((UINT64)(
UINTN)PageDirectoryEntry |
456 IA32_PG_P | IA32_PG_RW);
458 PhysicalAddress2M = PhysicalAddress;
459 for (IndexOfPageDirectoryEntries = 0;
460 IndexOfPageDirectoryEntries < 512;
461 (IndexOfPageDirectoryEntries++,
462 PageDirectoryEntry++,
463 PhysicalAddress2M += SIZE_2MB))
465 if ((PhysicalAddress2M < StackBase + StackSize) &&
466 ((PhysicalAddress2M + SIZE_2MB) > StackBase))
473 (UINT64 *)PageDirectoryEntry,
481 PageDirectoryEntry->Uint64 = (UINT64)PhysicalAddress2M | AddressEncMask;
482 PageDirectoryEntry->Bits.ReadWrite = 1;
483 PageDirectoryEntry->Bits.Present = 1;
484 PageDirectoryEntry->Bits.MustBe1 = 1;
498 IN OUT UINT64 *PageTablePointer,
499 IN MAP_RANGE_MODE Mode
502 UINT64 AddressEncMask;
506 if (Mode == SetCBit) {
507 *PageTablePointer |= AddressEncMask;
509 *PageTablePointer &= ~AddressEncMask;
556 IN PHYSICAL_ADDRESS Cr3BaseAddress,
557 IN PHYSICAL_ADDRESS PhysicalAddress,
564 UINT64 *NewPageTable;
565 UINT64 AddressEncMask;
567 RETURN_STATUS Status;
572 PageMapLevel4Entry =
NULL;
576 "%a:%a: Cr3Base=0x%Lx Physical=0x%Lx Length=0x%Lx\n",
592 if (!AddressEncMask) {
596 PgTableMask = AddressEncMask | EFI_PAGE_MASK;
612 if (Cr3BaseAddress == 0) {
616 PageMapLevel4Entry = (VOID *)(Cr3BaseAddress & ~PgTableMask);
617 PageMapLevel4Entry += PML4_OFFSET (PhysicalAddress);
618 if (!PageMapLevel4Entry->Bits.Present) {
620 if (NewPageTable ==
NULL) {
623 "%a:%a: failed to allocate a new PML4 entry\n",
631 SetMem (NewPageTable, EFI_PAGE_SIZE, 0);
636 PageMapLevel4Entry->Uint64 = (UINT64)(
UINTN)NewPageTable;
637 PageMapLevel4Entry->Bits.MustBeZero = 0;
638 PageMapLevel4Entry->Bits.ReadWrite = 1;
639 PageMapLevel4Entry->Bits.Present = 1;
642 PageDirectory1GEntry = (VOID *)(
643 (PageMapLevel4Entry->Bits.PageTableBaseAddress <<
646 PageDirectory1GEntry += PDP_OFFSET (PhysicalAddress);
647 if (!PageDirectory1GEntry->Bits.Present) {
648 PageDirectory1GEntry->Bits.Present = 1;
649 PageDirectory1GEntry->Bits.MustBe1 = 1;
650 PageDirectory1GEntry->Bits.MustBeZero = 0;
651 PageDirectory1GEntry->Bits.ReadWrite = 1;
652 PageDirectory1GEntry->Uint64 |= (UINT64)PhysicalAddress | AddressEncMask;
655 if (Length <= BIT30) {
661 PhysicalAddress += BIT30;
712 IN PHYSICAL_ADDRESS Cr3BaseAddress,
713 IN PHYSICAL_ADDRESS PhysicalAddress,
715 IN MAP_RANGE_MODE Mode,
716 IN BOOLEAN CacheFlush,
725 PHYSICAL_ADDRESS OrigPhysicalAddress;
728 UINT64 AddressEncMask;
731 RETURN_STATUS Status;
736 PageMapLevel4Entry =
NULL;
740 "%a:%a: Cr3Base=0x%Lx Physical=0x%Lx Length=0x%Lx Mode=%a CacheFlush=%u Mmio=%u\n",
746 (Mode == SetCBit) ?
"Encrypt" :
"Decrypt",
755 if (!AddressEncMask) {
759 PgTableMask = AddressEncMask | EFI_PAGE_MASK;
791 if (mPscBuffer ==
NULL) {
793 ASSERT (mPscBuffer !=
NULL);
810 OrigPhysicalAddress = PhysicalAddress;
812 while (Length != 0) {
816 if (Cr3BaseAddress == 0) {
820 PageMapLevel4Entry = (VOID *)(Cr3BaseAddress & ~PgTableMask);
821 PageMapLevel4Entry += PML4_OFFSET (PhysicalAddress);
822 if (!PageMapLevel4Entry->Bits.Present) {
825 "%a:%a: bad PML4 for Physical=0x%Lx\n",
834 PageDirectory1GEntry = (VOID *)(
835 (PageMapLevel4Entry->Bits.PageTableBaseAddress <<
838 PageDirectory1GEntry += PDP_OFFSET (PhysicalAddress);
839 if (!PageDirectory1GEntry->Bits.Present) {
842 "%a:%a: bad PDPE for Physical=0x%Lx\n",
854 if (PageDirectory1GEntry->Bits.MustBe1) {
859 if (((PhysicalAddress & (BIT30 - 1)) == 0) && (Length >= BIT30)) {
863 "%a:%a: updated 1GB entry for Physical=0x%Lx\n",
868 PhysicalAddress += BIT30;
876 "%a:%a: splitting 1GB page for Physical=0x%Lx\n",
882 (UINT64)PageDirectory1GEntry->Bits.PageTableBaseAddress << 30,
883 (UINT64 *)PageDirectory1GEntry,
893 PageUpperDirectoryPointerEntry =
895 PageDirectory2MEntry =
897 (PageUpperDirectoryPointerEntry->Bits.PageTableBaseAddress <<
900 PageDirectory2MEntry += PDE_OFFSET (PhysicalAddress);
901 if (!PageDirectory2MEntry->Bits.Present) {
904 "%a:%a: bad PDE for Physical=0x%Lx\n",
916 if (PageDirectory2MEntry->Bits.MustBe1) {
921 if (((PhysicalAddress & (BIT21-1)) == 0) && (Length >= BIT21)) {
923 PhysicalAddress += BIT21;
931 "%a:%a: splitting 2MB page for Physical=0x%Lx\n",
937 (UINT64)PageDirectory2MEntry->Bits.PageTableBaseAddress << 21,
938 (UINT64 *)PageDirectory2MEntry,
945 PageDirectoryPointerEntry =
949 (PageDirectoryPointerEntry->Bits.PageTableBaseAddress <<
952 PageTableEntry += PTE_OFFSET (PhysicalAddress);
953 if (!PageTableEntry->Bits.Present) {
956 "%a:%a: bad PTE for Physical=0x%Lx\n",
966 PhysicalAddress += EFI_PAGE_SIZE;
967 Length -= EFI_PAGE_SIZE;
992 if (mPscBuffer ==
NULL) {
994 ASSERT (mPscBuffer !=
NULL);
1037 IN PHYSICAL_ADDRESS Cr3BaseAddress,
1038 IN PHYSICAL_ADDRESS PhysicalAddress,
1071 IN PHYSICAL_ADDRESS Cr3BaseAddress,
1072 IN PHYSICAL_ADDRESS PhysicalAddress,
1105 IN PHYSICAL_ADDRESS Cr3BaseAddress,
1106 IN PHYSICAL_ADDRESS PhysicalAddress,
VOID *EFIAPI WriteBackInvalidateDataCacheRange(IN VOID *Address, IN UINTN Length)
UINT64 EFIAPI RShiftU64(IN UINT64 Operand, IN UINTN Count)
VOID *EFIAPI SetMem(OUT VOID *Buffer, IN UINTN Length, IN UINT8 Value)
VOID EFIAPI CpuFlushTlb(VOID)
VOID *EFIAPI AllocateReservedPages(IN UINTN Pages)
UINTN EFIAPI AsmReadCr3(VOID)
UINTN EFIAPI AsmReadCr0(VOID)
UINTN EFIAPI AsmWriteCr0(UINTN Cr0)
#define RETURN_ACCESS_DENIED
#define RETURN_NO_MAPPING
#define RETURN_INVALID_PARAMETER
#define DEBUG(Expression)
UINT64 EFIAPI MemEncryptSevGetEncryptionMask(VOID)
BOOLEAN EFIAPI MemEncryptSevSnpIsEnabled(VOID)
STATIC VOID SetPageTablePoolReadOnly(IN UINTN PageTableBase, IN EFI_PHYSICAL_ADDRESS Address, IN BOOLEAN Level4Paging)
STATIC RETURN_STATUS EFIAPI SetMemoryEncDec(IN PHYSICAL_ADDRESS Cr3BaseAddress, IN PHYSICAL_ADDRESS PhysicalAddress, IN UINTN Length, IN MAP_RANGE_MODE Mode, IN BOOLEAN CacheFlush, IN BOOLEAN Mmio)
STATIC VOID Split1GPageTo2M(IN PHYSICAL_ADDRESS PhysicalAddress, IN OUT UINT64 *PageEntry1G, IN PHYSICAL_ADDRESS StackBase, IN UINTN StackSize)
RETURN_STATUS EFIAPI InternalMemEncryptSevCreateIdentityMap1G(IN PHYSICAL_ADDRESS Cr3BaseAddress, IN PHYSICAL_ADDRESS PhysicalAddress, IN UINTN Length)
RETURN_STATUS EFIAPI InternalMemEncryptSevSetMemoryDecrypted(IN PHYSICAL_ADDRESS Cr3BaseAddress, IN PHYSICAL_ADDRESS PhysicalAddress, IN UINTN Length)
RETURN_STATUS EFIAPI InternalMemEncryptSevClearMmioPageEncMask(IN PHYSICAL_ADDRESS Cr3BaseAddress, IN PHYSICAL_ADDRESS PhysicalAddress, IN UINTN Length)
STATIC BOOLEAN InitializePageTablePool(IN UINTN PoolPages)
STATIC VOID *EFIAPI AllocatePageTableMemory(IN UINTN Pages)
UINT64 EFIAPI InternalGetMemEncryptionAddressMask(VOID)
STATIC VOID Split2MPageTo4K(IN PHYSICAL_ADDRESS PhysicalAddress, IN OUT UINT64 *PageEntry2M, IN PHYSICAL_ADDRESS StackBase, IN UINTN StackSize)
RETURN_STATUS EFIAPI InternalMemEncryptSevSetMemoryEncrypted(IN PHYSICAL_ADDRESS Cr3BaseAddress, IN PHYSICAL_ADDRESS PhysicalAddress, IN UINTN Length)
STATIC VOID DisableReadOnlyPageWriteProtect(VOID)
STATIC VOID SetOrClearCBit(IN OUT UINT64 *PageTablePointer, IN MAP_RANGE_MODE Mode)
STATIC VOID EnablePageTableProtection(IN UINTN PageTableBase, IN BOOLEAN Level4Paging)
STATIC VOID EnableReadOnlyPageWriteProtect(VOID)
STATIC BOOLEAN IsReadOnlyPageWriteProtected(VOID)
VOID *EFIAPI AllocateAlignedPages(IN UINTN Pages, IN UINTN Alignment)
VOID InternalSetPageState(IN EFI_PHYSICAL_ADDRESS BaseAddress, IN UINTN NumPages, IN SEV_SNP_PAGE_STATE State, IN BOOLEAN UseLargeEntry, IN VOID *PscBuffer, IN UINTN PscBufferSize)
UINT64 EFI_PHYSICAL_ADDRESS
#define EFI_PAGES_TO_SIZE(Pages)
#define EFI_SIZE_TO_PAGES(Size)