31 LocalPte4K.Uint64 = Pte4K->Uint64;
32 if (Mask->Bits.PageTableBaseAddressLow || Mask->Bits.PageTableBaseAddressHigh) {
33 LocalPte4K.Uint64 = (IA32_MAP_ATTRIBUTE_PAGE_TABLE_BASE_ADDRESS (Attribute) + Offset) | (LocalPte4K.Uint64 & ~IA32_PE_BASE_ADDRESS_MASK_40);
36 if (Mask->Bits.Present) {
37 LocalPte4K.Bits.Present = Attribute->Bits.Present;
40 if (Mask->Bits.ReadWrite) {
41 LocalPte4K.Bits.ReadWrite = Attribute->Bits.ReadWrite;
44 if (Mask->Bits.UserSupervisor) {
45 LocalPte4K.Bits.UserSupervisor = Attribute->Bits.UserSupervisor;
48 if (Mask->Bits.WriteThrough) {
49 LocalPte4K.Bits.WriteThrough = Attribute->Bits.WriteThrough;
52 if (Mask->Bits.CacheDisabled) {
53 LocalPte4K.Bits.CacheDisabled = Attribute->Bits.CacheDisabled;
56 if (Mask->Bits.Accessed) {
57 LocalPte4K.Bits.Accessed = Attribute->Bits.Accessed;
60 if (Mask->Bits.Dirty) {
61 LocalPte4K.Bits.Dirty = Attribute->Bits.Dirty;
65 LocalPte4K.Bits.Pat = Attribute->Bits.Pat;
68 if (Mask->Bits.Global) {
69 LocalPte4K.Bits.Global = Attribute->Bits.Global;
72 if (Mask->Bits.ProtectionKey) {
73 LocalPte4K.Bits.ProtectionKey = Attribute->Bits.ProtectionKey;
77 LocalPte4K.Bits.Nx = Attribute->Bits.Nx;
80 if (Pte4K->Uint64 != LocalPte4K.Uint64) {
81 Pte4K->Uint64 = LocalPte4K.Uint64;
105 LocalPleB.Uint64 = PleB->Uint64;
106 if (Mask->Bits.PageTableBaseAddressLow || Mask->Bits.PageTableBaseAddressHigh) {
107 LocalPleB.Uint64 = (IA32_MAP_ATTRIBUTE_PAGE_TABLE_BASE_ADDRESS (Attribute) + Offset) | (LocalPleB.Uint64 & ~IA32_PE_BASE_ADDRESS_MASK_39);
110 LocalPleB.Bits.MustBeOne = 1;
112 if (Mask->Bits.Present) {
113 LocalPleB.Bits.Present = Attribute->Bits.Present;
116 if (Mask->Bits.ReadWrite) {
117 LocalPleB.Bits.ReadWrite = Attribute->Bits.ReadWrite;
120 if (Mask->Bits.UserSupervisor) {
121 LocalPleB.Bits.UserSupervisor = Attribute->Bits.UserSupervisor;
124 if (Mask->Bits.WriteThrough) {
125 LocalPleB.Bits.WriteThrough = Attribute->Bits.WriteThrough;
128 if (Mask->Bits.CacheDisabled) {
129 LocalPleB.Bits.CacheDisabled = Attribute->Bits.CacheDisabled;
132 if (Mask->Bits.Accessed) {
133 LocalPleB.Bits.Accessed = Attribute->Bits.Accessed;
136 if (Mask->Bits.Dirty) {
137 LocalPleB.Bits.Dirty = Attribute->Bits.Dirty;
140 if (Mask->Bits.Pat) {
141 LocalPleB.Bits.Pat = Attribute->Bits.Pat;
144 if (Mask->Bits.Global) {
145 LocalPleB.Bits.Global = Attribute->Bits.Global;
148 if (Mask->Bits.ProtectionKey) {
149 LocalPleB.Bits.ProtectionKey = Attribute->Bits.ProtectionKey;
153 LocalPleB.Bits.Nx = Attribute->Bits.Nx;
156 if (PleB->Uint64 != LocalPleB.Uint64) {
157 PleB->Uint64 = LocalPleB.Uint64;
184 ASSERT (Level == 2 || Level == 3);
205 LocalPnle.Uint64 = Pnle->Uint64;
206 if (Mask->Bits.Present) {
207 LocalPnle.Bits.Present = Attribute->Bits.Present;
210 if (Mask->Bits.ReadWrite) {
211 LocalPnle.Bits.ReadWrite = Attribute->Bits.ReadWrite;
214 if (Mask->Bits.UserSupervisor) {
215 LocalPnle.Bits.UserSupervisor = Attribute->Bits.UserSupervisor;
219 LocalPnle.Bits.Nx = Attribute->Bits.Nx;
222 LocalPnle.Bits.Accessed = 0;
223 LocalPnle.Bits.MustBeZero = 0;
231 LocalPnle.Bits.WriteThrough = 0;
232 LocalPnle.Bits.CacheDisabled = 0;
233 if (Pnle->Uint64 != LocalPnle.Uint64) {
234 Pnle->Uint64 = LocalPnle.Uint64;
256 if ((Mask->Bits.Present == 1) && (Attribute->Bits.Present == 1)) {
260 if ((Mask->Bits.ReadWrite == 0) || (Mask->Bits.UserSupervisor == 0) || (Mask->Bits.WriteThrough == 0) || (Mask->Bits.CacheDisabled == 0) ||
261 (Mask->Bits.Accessed == 0) || (Mask->Bits.Dirty == 0) || (Mask->Bits.Pat == 0) || (Mask->Bits.Global == 0) ||
262 ((Mask->Bits.PageTableBaseAddressLow == 0) && (Mask->Bits.PageTableBaseAddressHigh == 0)) || (Mask->Bits.ProtectionKey == 0) || (Mask->Bits.Nx == 0))
266 }
else if ((Mask->Bits.Present == 0) && (Mask->Uint64 > 1)) {
310 IN IA32_PAGE_LEVEL Level,
311 IN IA32_PAGE_LEVEL MaxLeafLevel,
312 IN UINT64 LinearAddress,
317 IN OUT BOOLEAN *IsModified
320 RETURN_STATUS Status;
324 UINTN PagingEntryIndex;
325 UINTN PagingEntryIndexEnd;
341 UINT64 PhysicalAddrInEntry;
342 UINT64 PhysicalAddrInAttr;
348 ASSERT ((Attribute !=
NULL) && (Mask !=
NULL));
351 AllOneMask.Uint64 = ~0ull;
353 NopAttribute.Uint64 = 0;
354 NopAttribute.Bits.Present = 1;
355 NopAttribute.Bits.ReadWrite = 1;
356 NopAttribute.Bits.UserSupervisor = 1;
358 LocalParentAttribute.Uint64 = ParentAttribute->Uint64;
359 ParentAttribute = &LocalParentAttribute;
361 OriginalParentPagingEntry.Uint64 = ParentPagingEntry->Uint64;
362 OneOfPagingEntry.Uint64 = 0;
363 TempPagingEntry.Uint64 = 0;
368 BitStart = 12 + (Level - 1) * 9;
369 PagingEntryIndex = (
UINTN)
BitFieldRead64 (LinearAddress + Offset, BitStart, BitStart + 9 - 1);
370 RegionLength = REGION_LENGTH (Level);
371 RegionMask = RegionLength - 1;
377 if ((ParentPagingEntry->Pce.Present == 0) ||
IsPle (ParentPagingEntry, Level + 1)) {
385 if (ParentPagingEntry->Pce.Present == 0) {
401 if ((IA32_MAP_ATTRIBUTE_ATTRIBUTES (&PleBAttribute) & IA32_MAP_ATTRIBUTE_ATTRIBUTES (Mask))
402 == (IA32_MAP_ATTRIBUTE_ATTRIBUTES (Attribute) & IA32_MAP_ATTRIBUTE_ATTRIBUTES (Mask)))
404 if ((Mask->Bits.PageTableBaseAddressLow == 0) && (Mask->Bits.PageTableBaseAddressHigh == 0)) {
413 ASSERT (ParentPagingEntry->Pce.Present == 1);
414 PhysicalAddrInEntry = IA32_MAP_ATTRIBUTE_PAGE_TABLE_BASE_ADDRESS (&PleBAttribute) +
MultU64x32 (RegionLength, (UINT32)PagingEntryIndex);
415 PhysicalAddrInAttr = (IA32_MAP_ATTRIBUTE_PAGE_TABLE_BASE_ADDRESS (Attribute) + Offset) & (~RegionMask);
416 if (PhysicalAddrInEntry == PhysicalAddrInAttr) {
421 ASSERT (Buffer ==
NULL || *BufferSize >= SIZE_4KB);
423 *BufferSize -= SIZE_4KB;
427 ZeroMem (PagingEntry, SIZE_4KB);
429 if (ParentPagingEntry->Pce.Present) {
433 for (SubOffset = 0, Index = 0; Index < 512; Index++) {
434 PagingEntry[Index].Uint64 = OneOfPagingEntry.Uint64 + SubOffset;
435 SubOffset += RegionLength;
447 TempPagingEntry.Uint64 = ParentPagingEntry->Uint64;
449 TempPagingEntry.Uint64 = ((
UINTN)(VOID *)PagingEntry) | (TempPagingEntry.Uint64 & (~IA32_PE_BASE_ADDRESS_MASK_40));
450 *(
volatile UINT64 *)&(ParentPagingEntry->Uint64) = TempPagingEntry.Uint64;
457 PagingEntryIndexEnd = (
BitFieldRead64 (LinearAddress + Length - 1, BitStart + 9, 63) !=
BitFieldRead64 (LinearAddress + Offset, BitStart + 9, 63)) ? 511 :
460 for (Index = PagingEntryIndex; Index <= PagingEntryIndexEnd; Index++) {
461 if (PagingEntry[Index].Pce.Present == 0) {
477 ChildAttribute.Uint64 = 0;
478 ChildMask.Uint64 = 0;
488 if ((ParentPagingEntry->Pnle.Bits.ReadWrite == 0) && (Mask->Bits.ReadWrite == 1) && (Attribute->Bits.ReadWrite == 1)) {
490 ParentPagingEntry->Pnle.Bits.ReadWrite = 1;
493 ChildAttribute.Bits.ReadWrite = 0;
494 ChildMask.Bits.ReadWrite = 1;
497 if ((ParentPagingEntry->Pnle.Bits.UserSupervisor == 0) && (Mask->Bits.UserSupervisor == 1) && (Attribute->Bits.UserSupervisor == 1)) {
499 ParentPagingEntry->Pnle.Bits.UserSupervisor = 1;
502 ChildAttribute.Bits.UserSupervisor = 0;
503 ChildMask.Bits.UserSupervisor = 1;
506 if ((ParentPagingEntry->Pnle.Bits.Nx == 1) && (Mask->Bits.Nx == 1) && (Attribute->Bits.Nx == 0)) {
508 ParentPagingEntry->Pnle.Bits.Nx = 0;
511 ChildAttribute.Bits.Nx = 1;
512 ChildMask.Bits.Nx = 1;
515 if (ChildMask.Uint64 != 0) {
521 for (Index = 0; Index < 512; Index++) {
522 if (PagingEntry[Index].Pce.Present == 0) {
526 if (
IsPle (&PagingEntry[Index], Level)) {
539 Index = PagingEntryIndex;
540 RegionStart = (LinearAddress + Offset) & ~RegionMask;
547 while (Offset < Length && Index < 512) {
548 CurrentPagingEntry = (!Modify && CreateNew) ? &OneOfPagingEntry : &PagingEntry[Index];
549 SubLength =
MIN (Length - Offset, RegionStart + RegionLength - (LinearAddress + Offset));
550 if ((Level <= MaxLeafLevel) &&
551 (((LinearAddress + Offset) & RegionMask) == 0) &&
552 (((IA32_MAP_ATTRIBUTE_PAGE_TABLE_BASE_ADDRESS (Attribute) + Offset) & RegionMask) == 0) &&
553 (SubLength == RegionLength) &&
554 ((CurrentPagingEntry->Pce.Present == 0) ||
IsPle (CurrentPagingEntry, Level))
568 CurrentMask.Uint64 = Mask->Uint64;
569 if (ParentAttribute->Bits.Present == 0) {
570 CurrentMask.Bits.Present = 0;
571 ASSERT (CreateNew || (Mask->Bits.Present == 0) || (Attribute->Bits.Present == 0));
574 if (ParentAttribute->Bits.ReadWrite == 0) {
575 CurrentMask.Bits.ReadWrite = 0;
576 ASSERT (CreateNew || (Mask->Bits.ReadWrite == 0) || (Attribute->Bits.ReadWrite == 0));
579 if (ParentAttribute->Bits.UserSupervisor == 0) {
580 CurrentMask.Bits.UserSupervisor = 0;
581 ASSERT (CreateNew || (Mask->Bits.UserSupervisor == 0) || (Attribute->Bits.UserSupervisor == 0));
584 if (ParentAttribute->Bits.Nx == 1) {
585 CurrentMask.Bits.Nx = 0;
586 ASSERT (CreateNew || (Mask->Bits.Nx == 0) || (Attribute->Bits.Nx == 1));
592 OriginalCurrentPagingEntry.Uint64 = CurrentPagingEntry->Uint64;
595 if (Modify && (OriginalCurrentPagingEntry.Uint64 != CurrentPagingEntry->Uint64)) {
632 RegionStart += RegionLength;
640 if (Modify && (OriginalParentPagingEntry.Uint64 != ParentPagingEntry->Uint64)) {
688 IN PAGING_MODE PagingMode,
691 IN UINT64 LinearAddress,
695 OUT BOOLEAN *IsModified OPTIONAL
698 RETURN_STATUS Status;
701 UINT64 MaxLinearAddress;
702 IA32_PAGE_LEVEL MaxLevel;
703 IA32_PAGE_LEVEL MaxLeafLevel;
705 BOOLEAN LocalIsModified;
708 UINT8 BufferInStack[SIZE_4KB - 1 + MAX_PAE_PDPTE_NUM *
sizeof (
IA32_PAGING_ENTRY)];
714 if ((PagingMode == Paging32bit) || (PagingMode >= PagingModeMax)) {
721 if ((PageTable ==
NULL) || (BufferSize ==
NULL) || (Attribute ==
NULL) || (Mask ==
NULL)) {
725 if (*BufferSize % SIZE_4KB != 0) {
732 if (((
UINTN)LinearAddress % SIZE_4KB != 0) || ((
UINTN)Length % SIZE_4KB != 0)) {
739 if ((*BufferSize != 0) && (Buffer ==
NULL)) {
747 if ((Attribute->Bits.Present == 0) && (Mask->Bits.Present == 1) && (Mask->Uint64 > 1)) {
751 MaxLeafLevel = (IA32_PAGE_LEVEL)(UINT8)PagingMode;
752 MaxLevel = (IA32_PAGE_LEVEL)(UINT8)(PagingMode >> 8);
753 MaxLinearAddress = (PagingMode == PagingPae) ?
LShiftU64 (1, 32) :
LShiftU64 (1, 12 + MaxLevel * 9);
755 if ((LinearAddress > MaxLinearAddress) || (Length > MaxLinearAddress - LinearAddress)) {
762 TopPagingEntry.Uintn = *PageTable;
763 if (TopPagingEntry.Uintn != 0) {
764 if (PagingMode == PagingPae) {
772 for (Index = 0; Index < MAX_PAE_PDPTE_NUM; Index++) {
773 PagingEntry[Index].Pnle.Bits.ReadWrite = 1;
774 PagingEntry[Index].Pnle.Bits.UserSupervisor = 1;
775 PagingEntry[Index].Pnle.Bits.Nx = 0;
779 TopPagingEntry.Pce.Present = 1;
780 TopPagingEntry.Pce.ReadWrite = 1;
781 TopPagingEntry.Pce.UserSupervisor = 1;
782 TopPagingEntry.Pce.Nx = 0;
785 if (IsModified ==
NULL) {
786 IsModified = &LocalIsModified;
791 ParentAttribute.Uint64 = 0;
792 ParentAttribute.Bits.PageTableBaseAddressLow = 1;
793 ParentAttribute.Bits.Present = 1;
794 ParentAttribute.Bits.ReadWrite = 1;
795 ParentAttribute.Bits.UserSupervisor = 1;
796 ParentAttribute.Bits.Nx = 0;
817 ASSERT (*IsModified ==
FALSE);
822 RequiredSize = -RequiredSize;
824 if ((
UINTN)RequiredSize > *BufferSize) {
825 *BufferSize = RequiredSize;
829 if ((RequiredSize != 0) && (Buffer ==
NULL)) {
855 if (PagingMode == PagingPae) {
859 for (Index = 0; Index < MAX_PAE_PDPTE_NUM; Index++) {
860 PagingEntry[Index].PdptePae.Bits.MustBeZero = 0;
861 PagingEntry[Index].PdptePae.Bits.MustBeZero2 = 0;
862 PagingEntry[Index].PdptePae.Bits.MustBeZero3 = 0;
865 if (*PageTable != 0) {
873 if (*PageTable == 0) {
878 *PageTable = (
UINTN)PagingEntry;
UINT64 EFIAPI MultU64x32(IN UINT64 Multiplicand, IN UINT32 Multiplier)
UINT64 EFIAPI BitFieldRead64(IN UINT64 Operand, IN UINTN StartBit, IN UINTN EndBit)
UINT64 EFIAPI LShiftU64(IN UINT64 Operand, IN UINTN Count)
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
RETURN_STATUS PageTableLibMapInLevel(IN IA32_PAGING_ENTRY *ParentPagingEntry, IN IA32_MAP_ATTRIBUTE *ParentAttribute, IN BOOLEAN Modify, IN VOID *Buffer, IN OUT INTN *BufferSize, IN IA32_PAGE_LEVEL Level, IN IA32_PAGE_LEVEL MaxLeafLevel, IN UINT64 LinearAddress, IN UINT64 Length, IN UINT64 Offset, IN IA32_MAP_ATTRIBUTE *Attribute, IN IA32_MAP_ATTRIBUTE *Mask, IN OUT BOOLEAN *IsModified)
VOID PageTableLibSetPnle(IN OUT volatile IA32_PAGE_NON_LEAF_ENTRY *Pnle, IN IA32_MAP_ATTRIBUTE *Attribute, IN IA32_MAP_ATTRIBUTE *Mask)
RETURN_STATUS IsAttributesAndMaskValidForNonPresentEntry(IN IA32_MAP_ATTRIBUTE *Attribute, IN IA32_MAP_ATTRIBUTE *Mask)
VOID PageTableLibSetPleB(IN OUT volatile IA32_PAGE_LEAF_ENTRY_BIG_PAGESIZE *PleB, IN UINT64 Offset, IN IA32_MAP_ATTRIBUTE *Attribute, IN IA32_MAP_ATTRIBUTE *Mask)
RETURN_STATUS EFIAPI PageTableMap(IN OUT UINTN *PageTable OPTIONAL, IN PAGING_MODE PagingMode, IN VOID *Buffer, IN OUT UINTN *BufferSize, IN UINT64 LinearAddress, IN UINT64 Length, IN IA32_MAP_ATTRIBUTE *Attribute, IN IA32_MAP_ATTRIBUTE *Mask, OUT BOOLEAN *IsModified OPTIONAL)
VOID PageTableLibSetPle(IN UINTN Level, IN OUT volatile IA32_PAGING_ENTRY *Ple, IN UINT64 Offset, IN IA32_MAP_ATTRIBUTE *Attribute, IN IA32_MAP_ATTRIBUTE *Mask)
VOID PageTableLibSetPte4K(IN OUT volatile IA32_PTE_4K *Pte4K, IN UINT64 Offset, IN IA32_MAP_ATTRIBUTE *Attribute, IN IA32_MAP_ATTRIBUTE *Mask)
UINT64 PageTableLibGetPnleMapAttribute(IN IA32_PAGE_NON_LEAF_ENTRY *Pnle, IN IA32_MAP_ATTRIBUTE *ParentMapAttribute)
UINT64 PageTableLibGetPleBMapAttribute(IN IA32_PAGE_LEAF_ENTRY_BIG_PAGESIZE *PleB, IN IA32_MAP_ATTRIBUTE *ParentMapAttribute)
BOOLEAN IsPle(IN IA32_PAGING_ENTRY *PagingEntry, IN UINTN Level)
#define RETURN_BUFFER_TOO_SMALL
#define RETURN_ERROR(StatusCode)
#define RETURN_UNSUPPORTED
#define ALIGN_VALUE(Value, Alignment)
#define RETURN_INVALID_PARAMETER