UINT64 *ReleasePageAddress;\r
IA32_CR4 Cr4;\r
BOOLEAN Enable5LevelPaging;\r
+ UINT64 PFAddress;\r
+ UINT64 PFAddressPml5Index;\r
+ UINT64 PFAddressPml4Index;\r
+ UINT64 PFAddressPdptIndex;\r
+ UINT64 PFAddressPdtIndex;\r
\r
Pml4 = NULL;\r
Pdpt = NULL;\r
MinPdt = (UINTN)-1;\r
Acc = 0;\r
ReleasePageAddress = 0;\r
+ PFAddress = AsmReadCr2 ();\r
+ PFAddressPml5Index = BitFieldRead64 (PFAddress, 48, 48 + 8);\r
+ PFAddressPml4Index = BitFieldRead64 (PFAddress, 39, 39 + 8);\r
+ PFAddressPdptIndex = BitFieldRead64 (PFAddress, 30, 30 + 8);\r
+ PFAddressPdtIndex = BitFieldRead64 (PFAddress, 21, 21 + 8);\r
\r
Cr4.UintN = AsmReadCr4 ();\r
Enable5LevelPaging = (BOOLEAN) (Cr4.Bits.LA57 == 1);\r
// we will find the entry has the smallest access record value\r
//\r
PDPTEIgnore = TRUE;\r
- Acc = GetAndUpdateAccNum (Pdt + PdtIndex);\r
+ if (PdtIndex != PFAddressPdtIndex || PdptIndex != PFAddressPdptIndex ||\r
+ Pml4Index != PFAddressPml4Index || Pml5Index != PFAddressPml5Index) {\r
+ Acc = GetAndUpdateAccNum (Pdt + PdtIndex);\r
+ if (Acc < MinAcc) {\r
+ //\r
+ // If the PD entry has the smallest access record value,\r
+ // save the Page address to be released\r
+ //\r
+ MinAcc = Acc;\r
+ MinPml5 = Pml5Index;\r
+ MinPml4 = Pml4Index;\r
+ MinPdpt = PdptIndex;\r
+ MinPdt = PdtIndex;\r
+ ReleasePageAddress = Pdt + PdtIndex;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ if (!PDPTEIgnore) {\r
+ //\r
+ // If this PDPT entry has no PDT entries pointer to 4 KByte pages,\r
+ // it should only has the entries point to 2 MByte Pages\r
+ //\r
+ if (PdptIndex != PFAddressPdptIndex || Pml4Index != PFAddressPml4Index ||\r
+ Pml5Index != PFAddressPml5Index) {\r
+ Acc = GetAndUpdateAccNum (Pdpt + PdptIndex);\r
if (Acc < MinAcc) {\r
//\r
- // If the PD entry has the smallest access record value,\r
+ // If the PDPT entry has the smallest access record value,\r
// save the Page address to be released\r
//\r
MinAcc = Acc;\r
MinPml5 = Pml5Index;\r
MinPml4 = Pml4Index;\r
MinPdpt = PdptIndex;\r
- MinPdt = PdtIndex;\r
- ReleasePageAddress = Pdt + PdtIndex;\r
+ MinPdt = (UINTN)-1;\r
+ ReleasePageAddress = Pdpt + PdptIndex;\r
}\r
}\r
}\r
- if (!PDPTEIgnore) {\r
- //\r
- // If this PDPT entry has no PDT entries pointer to 4 KByte pages,\r
- // it should only has the entries point to 2 MByte Pages\r
- //\r
- Acc = GetAndUpdateAccNum (Pdpt + PdptIndex);\r
- if (Acc < MinAcc) {\r
- //\r
- // If the PDPT entry has the smallest access record value,\r
- // save the Page address to be released\r
- //\r
- MinAcc = Acc;\r
- MinPml5 = Pml5Index;\r
- MinPml4 = Pml4Index;\r
- MinPdpt = PdptIndex;\r
- MinPdt = (UINTN)-1;\r
- ReleasePageAddress = Pdpt + PdptIndex;\r
- }\r
- }\r
}\r
}\r
if (!PML4EIgnore) {\r
// If PML4 entry has no the PDPT entry pointer to 2 MByte pages,\r
// it should only has the entries point to 1 GByte Pages\r
//\r
- Acc = GetAndUpdateAccNum (Pml4 + Pml4Index);\r
- if (Acc < MinAcc) {\r
- //\r
- // If the PML4 entry has the smallest access record value,\r
- // save the Page address to be released\r
- //\r
- MinAcc = Acc;\r
- MinPml5 = Pml5Index;\r
- MinPml4 = Pml4Index;\r
- MinPdpt = (UINTN)-1;\r
- MinPdt = (UINTN)-1;\r
- ReleasePageAddress = Pml4 + Pml4Index;\r
+ if (Pml4Index != PFAddressPml4Index || Pml5Index != PFAddressPml5Index) {\r
+ Acc = GetAndUpdateAccNum (Pml4 + Pml4Index);\r
+ if (Acc < MinAcc) {\r
+ //\r
+ // If the PML4 entry has the smallest access record value,\r
+ // save the Page address to be released\r
+ //\r
+ MinAcc = Acc;\r
+ MinPml5 = Pml5Index;\r
+ MinPml4 = Pml4Index;\r
+ MinPdpt = (UINTN)-1;\r
+ MinPdt = (UINTN)-1;\r
+ ReleasePageAddress = Pml4 + Pml4Index;\r
+ }\r
}\r
}\r
}\r
Pml4 = (UINT64 *) (UINTN) (Pml5[MinPml5] & gPhyMask);\r
Pdpt = (UINT64*)(UINTN)(Pml4[MinPml4] & ~mAddressEncMask & gPhyMask);\r
SubEntriesNum = GetSubEntriesNum(Pdpt + MinPdpt);\r
- if (SubEntriesNum == 0) {\r
+ if (SubEntriesNum == 0 &&\r
+ (MinPdpt != PFAddressPdptIndex || MinPml4 != PFAddressPml4Index || MinPml5 != PFAddressPml5Index)) {\r
//\r
// Release the empty Page Directory table if there was no more 4 KByte Page Table entry\r
// clear the Page directory entry\r
//\r
// Update the sub-entries filed in PDPT entry and exit\r
//\r
- SetSubEntriesNum (Pdpt + MinPdpt, SubEntriesNum - 1);\r
+ SetSubEntriesNum (Pdpt + MinPdpt, (SubEntriesNum - 1) & 0x1FF);\r
break;\r
}\r
if (MinPdpt != (UINTN)-1) {\r
// One 2MB Page Table is released or Page Directory table is released, check the PML4 entry\r
//\r
SubEntriesNum = GetSubEntriesNum (Pml4 + MinPml4);\r
- if (SubEntriesNum == 0) {\r
+ if (SubEntriesNum == 0 && (MinPml4 != PFAddressPml4Index || MinPml5 != PFAddressPml5Index)) {\r
//\r
// Release the empty PML4 table if there was no more 1G KByte Page Table entry\r
// clear the Page directory entry\r
//\r
// Update the sub-entries filed in PML4 entry and exit\r
//\r
- SetSubEntriesNum (Pml4 + MinPml4, SubEntriesNum - 1);\r
+ SetSubEntriesNum (Pml4 + MinPml4, (SubEntriesNum - 1) & 0x1FF);\r
break;\r
}\r
//\r
PageTable[PTIndex] = ((PFAddress | mAddressEncMask) & gPhyMask & ~((1ull << EndBit) - 1)) |\r
PageAttribute | IA32_PG_A | PAGE_ATTRIBUTE_BITS;\r
if (UpperEntry != NULL) {\r
- SetSubEntriesNum (UpperEntry, GetSubEntriesNum (UpperEntry) + 1);\r
+ SetSubEntriesNum (UpperEntry, (GetSubEntriesNum (UpperEntry) + 1) & 0x1FF);\r
}\r
//\r
// Get the next page address if we need to create more page tables\r