From ffa480d69aeac1de9a86dd4ea1db28662fb3dad6 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Thu, 30 Oct 2025 20:14:02 +0100 Subject: [PATCH] Implement unified PTE accessors and management helpers --- xtoskrnl/includes/mm/amd64/pagemap.hh | 23 +- xtoskrnl/includes/mm/i686/pagemap.hh | 45 ++- xtoskrnl/mm/amd64/pagemap.cc | 340 ++++++++++++++++++++- xtoskrnl/mm/i686/pagemap.cc | 411 +++++++++++++++++++++++++- 4 files changed, 810 insertions(+), 9 deletions(-) diff --git a/xtoskrnl/includes/mm/amd64/pagemap.hh b/xtoskrnl/includes/mm/amd64/pagemap.hh index 79a4418..e59a729 100644 --- a/xtoskrnl/includes/mm/amd64/pagemap.hh +++ b/xtoskrnl/includes/mm/amd64/pagemap.hh @@ -21,14 +21,35 @@ namespace MM MMPAGEMAP_INFO PageMapInfo; public: + XTAPI PMMPTE AdvancePte(PMMPTE Pte, + ULONG Count); XTAPI VOID ClearPte(PHARDWARE_PTE PtePointer); + XTAPI ULONGLONG GetEmptyPteList(VOID); + XTAPI ULONG_PTR GetNextEntry(PMMPTE Pte); + XTAPI PMMPTE GetNextPte(PMMPTE Pte); + XTAPI BOOLEAN GetOneEntry(PMMPTE Pte); XTAPI PMMP5E GetP5eAddress(PVOID Address); + XTAPI ULONG GetP5eIndex(PVOID Address); + XTAPI PVOID GetP5eVirtualAddress(PMMP5E P5ePointer); XTAPI PMMPDE GetPdeAddress(PVOID Address); + XTAPI ULONG GetPdeIndex(PVOID Address); + XTAPI PVOID GetPdeVirtualAddress(PMMPDE PdePointer); XTAPI PMMPPE GetPpeAddress(PVOID Address); + XTAPI ULONG GetPpeIndex(PVOID Address); + XTAPI PVOID GetPpeVirtualAddress(PMMPPE PpePointer); XTAPI PMMPTE GetPteAddress(PVOID Address); + XTAPI ULONG GetPteIndex(PVOID Address); + XTAPI ULONG GetPteSize(VOID); + XTAPI PVOID GetPteVirtualAddress(PMMPTE PtePointer); XTAPI PMMPXE GetPxeAddress(PVOID Address); - virtual XTAPI VOID InitializePageMapInfo(VOID) = 0; + XTAPI ULONG GetPxeIndex(PVOID Address); + XTAPI PVOID GetPxeVirtualAddress(PMMPXE PxePointer); + VIRTUAL XTAPI VOID InitializePageMapInfo(VOID) = 0; XTAPI BOOLEAN PteValid(PHARDWARE_PTE PtePointer); + XTAPI VOID SetNextEntry(PMMPTE Pte, + ULONG_PTR Value); + XTAPI VOID SetOneEntry(PMMPTE Pte, + BOOLEAN Value); XTAPI VOID SetPte(PHARDWARE_PTE PtePointer, PFN_NUMBER PageFrameNumber, BOOLEAN Writable); diff --git a/xtoskrnl/includes/mm/i686/pagemap.hh b/xtoskrnl/includes/mm/i686/pagemap.hh index 0ca1616..bd47426 100644 --- a/xtoskrnl/includes/mm/i686/pagemap.hh +++ b/xtoskrnl/includes/mm/i686/pagemap.hh @@ -21,16 +21,33 @@ namespace MM MMPAGEMAP_INFO PageMapInfo; public: + VIRTUAL XTAPI PMMPTE AdvancePte(PMMPTE Pte, + ULONG Count) = 0; XTAPI VOID ClearPte(PHARDWARE_PTE PtePointer); + XTAPI ULONG GetEmptyPteList(VOID); + VIRTUAL XTAPI ULONG_PTR GetNextEntry(PMMPTE Pte) = 0; + VIRTUAL XTAPI PMMPTE GetNextPte(PMMPTE Pte) = 0; + VIRTUAL XTAPI BOOLEAN GetOneEntry(PMMPTE Pte) = 0; XTAPI PMMPDE GetPdeAddress(PVOID Address); + XTAPI ULONG GetPdeIndex(PVOID Address); + XTAPI PVOID GetPdeVirtualAddress(PMMPDE PdePointer); XTAPI PMMPPE GetPpeAddress(PVOID Address); + XTAPI ULONG GetPpeIndex(PVOID Address); + XTAPI PVOID GetPpeVirtualAddress(PMMPPE PpePointer); XTAPI PMMPTE GetPteAddress(PVOID Address); - virtual XTAPI VOID InitializePageMapInfo(VOID) = 0; - virtual XTAPI BOOLEAN PteValid(PHARDWARE_PTE PtePointer) = 0; - virtual XTAPI VOID SetPte(PHARDWARE_PTE PtePointer, + XTAPI ULONG GetPteIndex(PVOID Address); + VIRTUAL XTAPI ULONG GetPteSize(VOID) = 0; + XTAPI PVOID GetPteVirtualAddress(PMMPTE PtePointer); + VIRTUAL XTAPI VOID InitializePageMapInfo(VOID) = 0; + VIRTUAL XTAPI BOOLEAN PteValid(PHARDWARE_PTE PtePointer) = 0; + VIRTUAL XTAPI VOID SetNextEntry(PMMPTE Pte, + ULONG_PTR Value) = 0; + VIRTUAL XTAPI VOID SetOneEntry(PMMPTE Pte, + BOOLEAN Value) = 0; + VIRTUAL XTAPI VOID SetPte(PHARDWARE_PTE PtePointer, PFN_NUMBER PageFrameNumber, BOOLEAN Writable) = 0; - virtual XTAPI VOID SetPteCaching(PHARDWARE_PTE PtePointer, + VIRTUAL XTAPI VOID SetPteCaching(PHARDWARE_PTE PtePointer, BOOLEAN CacheDisable, BOOLEAN WriteThrough) = 0; } PAGEMAP, *PPAGEMAP; @@ -38,8 +55,18 @@ namespace MM class PageMapBasic final : public PageMap { public: + XTAPI PMMPTE AdvancePte(PMMPTE Pte, + ULONG Count); + XTAPI ULONG_PTR GetNextEntry(PMMPTE Pte); + XTAPI PMMPTE GetNextPte(PMMPTE Pte); + XTAPI BOOLEAN GetOneEntry(PMMPTE Pte); + XTAPI ULONG GetPteSize(VOID); XTAPI VOID InitializePageMapInfo(VOID); XTAPI BOOLEAN PteValid(PHARDWARE_PTE PtePointer); + XTAPI VOID SetNextEntry(PMMPTE Pte, + ULONG_PTR Value); + XTAPI VOID SetOneEntry(PMMPTE Pte, + BOOLEAN Value); XTAPI VOID SetPte(PHARDWARE_PTE PtePointer, PFN_NUMBER PageFrameNumber, BOOLEAN Writable); @@ -51,8 +78,18 @@ namespace MM class PageMapXpa final : public PageMap { public: + XTAPI PMMPTE AdvancePte(PMMPTE Pte, + ULONG Count); + XTAPI ULONG_PTR GetNextEntry(PMMPTE Pte); + XTAPI PMMPTE GetNextPte(PMMPTE Pte); + XTAPI BOOLEAN GetOneEntry(PMMPTE Pte); + XTAPI ULONG GetPteSize(VOID); XTAPI VOID InitializePageMapInfo(VOID); XTAPI BOOLEAN PteValid(PHARDWARE_PTE PtePointer); + XTAPI VOID SetNextEntry(PMMPTE Pte, + ULONG_PTR Value); + XTAPI VOID SetOneEntry(PMMPTE Pte, + BOOLEAN Value); XTAPI VOID SetPte(PHARDWARE_PTE PtePointer, PFN_NUMBER PageFrameNumber, BOOLEAN Writable); diff --git a/xtoskrnl/mm/amd64/pagemap.cc b/xtoskrnl/mm/amd64/pagemap.cc index 62fa00b..6ede720 100644 --- a/xtoskrnl/mm/amd64/pagemap.cc +++ b/xtoskrnl/mm/amd64/pagemap.cc @@ -9,6 +9,27 @@ #include +/** + * Advances a PTE pointer by a given number of entries, considering the actual PTE size. + * + * @param Pte + * The PTE pointer to advance. + * + * @param Count + * The number of PTE entries to advance by. + * + * @return The advanced PTE pointer. + * + * @since XT 1.0 + */ +XTAPI +PMMPTE +MM::PageMap::AdvancePte(PMMPTE Pte, + ULONG Count) +{ + return (PMMPTE)((ULONG_PTR)Pte + (Count * sizeof(MMPTE))); +} + /** * Clears the contents of a page table entry (PTE). * @@ -23,6 +44,7 @@ XTAPI VOID MM::PageMap::ClearPte(PHARDWARE_PTE PtePointer) { + /* Clear PTE */ PtePointer->CacheDisable = 0; PtePointer->PageFrameNumber = 0; PtePointer->Valid = 0; @@ -30,6 +52,75 @@ MM::PageMap::ClearPte(PHARDWARE_PTE PtePointer) PtePointer->WriteThrough = 0; } +/** + * Gets the value representing an empty PTE list. + * + * @return This routine returns the value representing an empty PTE list. + * + * @since XT 1.0 + */ +XTAPI +ULONGLONG +MM::PageMap::GetEmptyPteList(VOID) +{ + /* Return empty PTE list mask */ + return PageMapInfo.EmptyPteList; +} + +/** + * Gets the next entry in a PTE list. + * + * @param Pte + * The PTE pointer to get the next entry from. + * + * @return This routine returns the next entry in the PTE list. + * + * @since XT 1.0 + */ +XTAPI +ULONG_PTR +MM::PageMap::GetNextEntry(PMMPTE Pte) +{ + /* Return next entry in PTE list */ + return Pte->List.NextEntry; +} + +/** + * Advances a PTE pointer, considering the actual PTE size. + * + * @param Pte + * The PTE pointer to advance. + * + * @return The advanced PTE pointer. + * + * @since XT 1.0 + */ +XTAPI +PMMPTE +MM::PageMap::GetNextPte(PMMPTE Pte) +{ + /* Return advanced PTE pointer */ + return AdvancePte(Pte, 1); +} + +/** + * Checks if a PTE list contains only one entry. + * + * @param Pte + * The PTE pointer to check. + * + * @return This routine returns TRUE if the PTE list has only one entry, FALSE otherwise. + * + * @since XT 1.0 + */ +XTAPI +BOOLEAN +MM::PageMap::GetOneEntry(PMMPTE Pte) +{ + /* Return one entry status */ + return Pte->List.OneEntry; +} + /** * Gets the address of the P5E (Page Map Level 5 Entry), that maps given address. * @@ -51,6 +142,40 @@ MM::PageMap::GetP5eAddress(PVOID Address) return (PMMP5E)((PageMapInfo.P5eBase + Offset) * PageMapInfo.Xpa); } +/** + * Gets the index of the P5E (Page Map Level 5 Entry), that maps given address. + * + * @param Address + * Specifies the virtual address for which to retrieve the corresponding P5E. + * + * @return This routine returns the index of the P5E, or NULLPTR if LA57 is not enabled. + * + * @since XT 1.0 + */ +XTAPI +ULONG +MM::PageMap::GetP5eIndex(PVOID Address) +{ + return (((((ULONGLONG)Address) >> MM_P5I_SHIFT) & 0x1FF) * PageMapInfo.Xpa); +} + +/** + * Gets the virtual address that is mapped by a given Page Map Level 5 Entry. + * + * @param P5ePointer + * Specifies the address of the P5E. + * + * @return This routine returns the virtual address mapped by the P5E, or NULLPTR if LA57 is not enabled. + * + * @since XT 1.0 + */ +XTAPI +PVOID +MM::PageMap::GetP5eVirtualAddress(PMMP5E P5ePointer) +{ + return (PVOID)((((LONGLONG)P5ePointer << 61) >> 16) * PageMapInfo.Xpa); +} + /** * Gets the address of the PDE (Page Directory Entry), that maps given address. * @@ -73,11 +198,47 @@ MM::PageMap::GetPdeAddress(PVOID Address) } /** - * Gets the address of the PPE (Page Directory Pointer Table Entry), that maps given address. + * Gets the index of the PDE (Page Directory Entry), that maps given address. * * @param Address * Specifies the virtual address for which to retrieve the corresponding PDE. * + * @return This routine returns the index of the PDE. + * + * @since XT 1.0 + */ +XTAPI +ULONG +MM::PageMap::GetPdeIndex(PVOID Address) +{ + /* Return PDE index */ + return ((((ULONGLONG)Address) >> MM_PDI_SHIFT) & 0x1FF); +} + +/** + * Gets the virtual address that is mapped by a given Page Directory Entry. + * + * @param PdePointer + * Specifies the address of the PDE. + * + * @return This routine returns the virtual address mapped by the PDE. + * + * @since XT 1.0 + */ +XTAPI +PVOID +MM::PageMap::GetPdeVirtualAddress(PMMPDE PdePointer) +{ + /* Return PDE virtual address */ + return (PVOID)(((LONGLONG)PdePointer << 34) >> 16); +} + +/** + * Gets the address of the PPE (Page Directory Pointer Table Entry), that maps given address. + * + * @param Address + * Specifies the virtual address for which to retrieve the corresponding PPE. + * * @return This routine returns the address of the PPE. * * @since XT 1.0 @@ -93,6 +254,42 @@ MM::PageMap::GetPpeAddress(PVOID Address) return (PMMPPE)(PageMapInfo.PpeBase + Offset); } +/** + * Gets the index of the PPE (Page Directory Pointer Table Entry), that maps given address. + * + * @param Address + * Specifies the virtual address for which to retrieve the corresponding PPE. + * + * @return This routine returns the index of the PPE. + * + * @since XT 1.0 + */ +XTAPI +ULONG +MM::PageMap::GetPpeIndex(PVOID Address) +{ + /* Return PPE index */ + return ((((ULONGLONG)Address) >> MM_PPI_SHIFT) & 0x1FF); +} + +/** + * Gets the virtual address that is mapped by a given Page Directory Pointer Table Entry. + * + * @param PpePointer + * Specifies the address of the PPE. + * + * @return This routine returns the virtual address mapped by the PPE. + * + * @since XT 1.0 + */ +XTAPI +PVOID +MM::PageMap::GetPpeVirtualAddress(PMMPPE PpePointer) +{ + /* Return PPE virtual address */ + return (PVOID)(((LONGLONG)PpePointer << 43) >> 16); +} + /** * Gets the address of the PTE (Page Table Entry), that maps given address. * @@ -114,6 +311,57 @@ MM::PageMap::GetPteAddress(PVOID Address) return (PMMPTE)(PageMapInfo.PteBase + Offset); } +/** + * Gets the index of the PTE (Page Table Entry), that maps given address. + * + * @param Address + * Specifies the virtual address for which to retrieve the corresponding PTE. + * + * @return This routine returns the index of the PTE. + * + * @since XT 1.0 + */ +XTAPI +ULONG +MM::PageMap::GetPteIndex(PVOID Address) +{ + /* Return PTE index */ + return ((((ULONGLONG)Address) >> MM_PTI_SHIFT) & 0x1FF); +} + +/** + * Gets the size of a PTE. + * + * @return This routine returns the size of a PTE. + * + * @since XT 1.0 + */ +XTAPI +ULONG +MM::PageMap::GetPteSize(VOID) +{ + /* Return the size of MMPTE */ + return sizeof(MMPTE); +} + +/** + * Gets the virtual address that is mapped by a given Page Table Entry. + * + * @param PtePointer + * Specifies the address of the PTE. + * + * @return This routine returns the virtual address mapped by the PTE. + * + * @since XT 1.0 + */ +XTAPI +PVOID +MM::PageMap::GetPteVirtualAddress(PMMPTE PtePointer) +{ + /* Return PTE virtual address */ + return (PVOID)(((LONGLONG)PtePointer << 25) >> 16); +} + /** * Gets the address of the PXE (Extended Page Entry), that maps given address. * @@ -130,10 +378,47 @@ MM::PageMap::GetPxeAddress(PVOID Address) { ULONGLONG Offset; + /* Calculate offset and return PXE address */ Offset = ((((ULONGLONG)Address & (((ULONGLONG)1 << PageMapInfo.VaBits) - 1)) >> MM_PXI_SHIFT) << MM_PTE_SHIFT); return (PMMPXE)(PageMapInfo.PxeBase + Offset); } +/** + * Gets the index of the PXE (Extended Page Entry), that maps given address. + * + * @param Address + * Specifies the virtual address for which to retrieve the corresponding PXE. + * + * @return This routine returns the index of the PXE. + * + * @since XT 1.0 + */ +XTAPI +ULONG +MM::PageMap::GetPxeIndex(PVOID Address) +{ + /* Return PXE index */ + return ((((ULONGLONG)Address) >> MM_PXI_SHIFT) & 0x1FF); +} + +/** + * Gets the virtual address that is mapped by a given Extended Page Entry. + * + * @param PxePointer + * Specifies the address of the PXE. + * + * @return This routine returns the virtual address mapped by the PXE. + * + * @since XT 1.0 + */ +XTAPI +PVOID +MM::PageMap::GetPxeVirtualAddress(PMMPXE PxePointer) +{ + /* Return PXE virtual address */ + return (PVOID)(((LONGLONG)PxePointer << 52) >> 16); +} + /** * Checks whether the given PML2 page table entry (PTE) is valid. * @@ -148,9 +433,54 @@ XTAPI BOOLEAN MM::PageMap::PteValid(PHARDWARE_PTE PtePointer) { + /* Check if PTE is valid */ return (BOOLEAN)PtePointer->Valid; } +/** + * Sets the next entry in a PTE list. + * + * @param Pte + * The PTE pointer to modify. + * + * @param Value + * The value to set as the next entry. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::PageMap::SetNextEntry(PMMPTE Pte, + ULONG_PTR Value) +{ + /* Set next entry in PTE list */ + Pte->List.NextEntry = Value; +} + +/** + * Sets the flag indicating whether a PTE list contains only one entry. + * + * @param Pte + * The PTE pointer to modify. + * + * @param Value + * The value to set. TRUE if the list has only one entry, FALSE otherwise. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::PageMap::SetOneEntry(PMMPTE Pte, + BOOLEAN Value) +{ + /* Set one entry status */ + Pte->List.OneEntry = Value; +} + /** * Sets a PML2 page table entry (PTE) with the specified physical page and access flags. * @@ -173,6 +503,7 @@ MM::PageMap::SetPte(PHARDWARE_PTE PtePointer, PFN_NUMBER PageFrameNumber, BOOLEAN Writable) { + /* Set PTE */ PtePointer->PageFrameNumber = PageFrameNumber; PtePointer->Valid = 1; PtePointer->Writable = Writable; @@ -200,6 +531,7 @@ MM::PageMap::SetPteCaching(PHARDWARE_PTE PtePointer, BOOLEAN CacheDisable, BOOLEAN WriteThrough) { + /* Set caching attributes */ PtePointer->CacheDisable = CacheDisable; PtePointer->WriteThrough = WriteThrough; } @@ -218,6 +550,9 @@ MM::PageMapBasic::InitializePageMapInfo(VOID) /* Set PML4 page map information */ PageMapInfo.Xpa = FALSE; + /* Set PML4 empty PTE list mask */ + PageMapInfo.EmptyPteList = 0xFFFFFFFFUI64; + /* Set PML4 base addresses */ PageMapInfo.PteBase = MM_PTE_BASE; PageMapInfo.PdeBase = MM_PDE_BASE; @@ -243,6 +578,9 @@ MM::PageMapXpa::InitializePageMapInfo(VOID) /* Set PML5 page map information */ PageMapInfo.Xpa = TRUE; + /* Set PML5 empty PTE list mask */ + PageMapInfo.EmptyPteList = 0xFFFFFFFFUI64; + /* Set PML5 base addresses */ PageMapInfo.PteBase = MM_PTE_LA57_BASE; PageMapInfo.PdeBase = MM_PDE_LA57_BASE; diff --git a/xtoskrnl/mm/i686/pagemap.cc b/xtoskrnl/mm/i686/pagemap.cc index 3793387..15faa54 100644 --- a/xtoskrnl/mm/i686/pagemap.cc +++ b/xtoskrnl/mm/i686/pagemap.cc @@ -23,9 +23,25 @@ XTAPI VOID MM::PageMap::ClearPte(PHARDWARE_PTE PtePointer) { + /* Clear PTE */ PtePointer->Long = 0; } +/** + * Gets the value representing an empty PTE list. + * + * @return This routine returns the value representing an empty PTE list. + * + * @since XT 1.0 + */ +XTAPI +ULONG +MM::PageMap::GetEmptyPteList(VOID) +{ + /* Return empty PTE list mask */ + return PageMapInfo.EmptyPteList; +} + /** * Gets the address of the PDE (Page Directory Entry), that maps given address. * @@ -47,6 +63,42 @@ MM::PageMap::GetPdeAddress(PVOID Address) return (PMMPDE)(PageMapInfo.PdeBase + Offset); } +/** + * Gets the index of the PDE (Page Directory Entry), that maps given address. + * + * @param Address + * Specifies the virtual address for which to retrieve the corresponding PDE. + * + * @return This routine returns the index of the PDE. + * + * @since XT 1.0 + */ +XTAPI +ULONG +MM::PageMap::GetPdeIndex(PVOID Address) +{ + /* Return PDE index */ + return ((((ULONG_PTR)(Address)) >> PageMapInfo.PdiShift) & (PageMapInfo.Xpa ? 0x1FF : 0x3FF)); +} + +/** + * Gets the virtual address that is mapped by a given Page Directory Entry. + * + * @param PdePointer + * Specifies the address of the PDE. + * + * @return This routine returns the virtual address mapped by the PDE. + * + * @since XT 1.0 + */ +XTAPI +PVOID +MM::PageMap::GetPdeVirtualAddress(PMMPDE PdePointer) +{ + /* Return PDE virtual address */ + return ((PVOID)((ULONG)(PdePointer) << 20)); +} + /** * Gets the address of the PPE (Page Directory Pointer Table Entry), that maps given address. * @@ -65,6 +117,42 @@ MM::PageMap::GetPpeAddress(PVOID Address) return (PMMPPE)0; } +/** + * Gets the index of the PPE (Page Directory Pointer Table Entry), that maps given address. + * + * @param Address + * Specifies the virtual address for which to retrieve the corresponding PPE. + * + * @return This routine returns the index of the PPE. + * + * @since XT 1.0 + */ +XTAPI +ULONG +MM::PageMap::GetPpeIndex(PVOID Address) +{ + /* Return PPE index */ + return ((((ULONG_PTR)(Address)) >> MM_PPI_SHIFT) & 0x3) * PageMapInfo.Xpa; +} + +/** + * Gets the virtual address that is mapped by a given Page Directory Pointer Table Entry. + * + * @param PpePointer + * Specifies the virtual address of the PPE. + * + * @return This routine returns the virtual address mapped by the PPE. + * + * @since XT 1.0 + */ +XTAPI +PVOID +MM::PageMap::GetPpeVirtualAddress(PMMPPE PpePointer) +{ + /* Return PPE virtual address */ + return (PVOID)((ULONG)(PpePointer) << 30); +} + /** * Gets the address of the PTE (Page Table Entry), that maps given address. * @@ -86,6 +174,133 @@ MM::PageMap::GetPteAddress(PVOID Address) return (PMMPTE)(PageMapInfo.PteBase + Offset); } +/** + * Gets the index of the PTE (Page Table Entry), that maps given address. + * + * @param Address + * Specifies the virtual address for which to retrieve the corresponding PTE. + * + * @return This routine returns the index of the PTE. + * + * @since XT 1.0 + */ +XTAPI +ULONG +MM::PageMap::GetPteIndex(PVOID Address) +{ + /* Return PTE index */ + return ((((ULONG_PTR)(Address)) >> MM_PTI_SHIFT) & (PageMapInfo.Xpa ? 0x1FF : 0x3FF)); +} + +/** + * Gets the virtual address that is mapped by a given Page Table Entry. + * + * @param PtePointer + * Specifies the virtual address of the PTE. + * + * @return This routine returns the virtual address mapped by the PTE. + * + * @since XT 1.0 + */ +XTAPI +PVOID +MM::PageMap::GetPteVirtualAddress(PMMPTE PtePointer) +{ + /* Return PTE virtual address */ + return ((PVOID)((ULONG)(PtePointer) << 10)); +} + +/** + * Advances a PTE pointer by a given number of entries, considering the actual PTE size for PML2. + * + * @param Pte + * The PTE pointer to advance. + * + * @param Count + * The number of PTE entries to advance by. + * + * @return This routine returns the advanced PTE pointer. + * + * @since XT 1.0 + */ +XTAPI +PMMPTE +MM::PageMapBasic::AdvancePte(PMMPTE Pte, + ULONG Count) +{ + /* Return advanced PTE pointer */ + return (PMMPTE)((ULONG_PTR)Pte + (Count * sizeof(MMPML2_PTE))); +} + +/** + * Gets the next entry in a PTE list. + * + * @param Pte + * The PTE pointer to get the next entry from. + * + * @return This routine returns the next entry in the PTE list. + * + * @since XT 1.0 + */ +XTAPI +ULONG_PTR +MM::PageMapBasic::GetNextEntry(PMMPTE Pte) +{ + /* Return next entry in PTE list */ + return Pte->Pml2.List.NextEntry; +} + +/** + * Advances a PTE pointer, considering the actual PTE size for PML2. + * + * @param Pte + * The PTE pointer to advance. + * + * @return The advanced PTE pointer. + * + * @since XT 1.0 + */ +XTAPI +PMMPTE +MM::PageMapBasic::GetNextPte(PMMPTE Pte) +{ + /* Return advanced PTE pointer */ + return AdvancePte(Pte, 1); +} + +/** + * Checks if a PTE list contains only one entry. + * + * @param Pte + * The PTE pointer to check. + * + * @return This routine returns TRUE if the PTE list has only one entry, FALSE otherwise. + * + * @since XT 1.0 + */ +XTAPI +BOOLEAN +MM::PageMapBasic::GetOneEntry(PMMPTE Pte) +{ + /* Return one entry status */ + return Pte->Pml2.List.OneEntry; +} + +/** + * Gets the size of a PTE for basic paging (PML2). + * + * @return This routine returns the size of a PTE. + * + * @since XT 1.0 + */ +XTAPI +ULONG +MM::PageMapBasic::GetPteSize(VOID) +{ + /* Return the size of MMPTE */ + return sizeof(MMPML2_PTE); +} + /** * Initializes page map information for basic paging (PML2). * @@ -100,6 +315,9 @@ MM::PageMapBasic::InitializePageMapInfo(VOID) /* Set PML2 page map information */ PageMapInfo.Xpa = FALSE; + /* Set PML2 empty PTE list mask */ + PageMapInfo.EmptyPteList = (ULONG)0xFFFFF; + /* Set PML2 base addresses */ PageMapInfo.PteBase = MM_PTE_BASE; PageMapInfo.PdeBase = MM_PDE_LEGACY_BASE; @@ -123,9 +341,54 @@ XTAPI BOOLEAN MM::PageMapBasic::PteValid(PHARDWARE_PTE PtePointer) { + /* Check if PTE is valid */ return (BOOLEAN)PtePointer->Pml2.Valid; } +/** + * Sets the next entry in a PTE list. + * + * @param Pte + * The PTE pointer to modify. + * + * @param Value + * The value to set as the next entry. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::PageMapBasic::SetNextEntry(PMMPTE Pte, + ULONG_PTR Value) +{ + /* Set next entry in PTE list */ + Pte->Pml2.List.NextEntry = Value; +} + +/** + * Sets the flag indicating whether a PTE list contains only one entry. + * + * @param Pte + * The PTE pointer to modify. + * + * @param Value + * The value to set. TRUE if the list has only one entry, FALSE otherwise. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::PageMapBasic::SetOneEntry(PMMPTE Pte, + BOOLEAN Value) +{ + /* Set one entry status */ + Pte->Pml2.List.OneEntry = Value; +} + /** * Sets a PML2 page table entry (PTE) with the specified physical page and access flags. * @@ -148,6 +411,7 @@ MM::PageMapBasic::SetPte(PHARDWARE_PTE PtePointer, PFN_NUMBER PageFrameNumber, BOOLEAN Writable) { + /* Set PTE */ PtePointer->Pml2.PageFrameNumber = PageFrameNumber; PtePointer->Pml2.Valid = 1; PtePointer->Pml2.Writable = Writable; @@ -175,10 +439,102 @@ MM::PageMapBasic::SetPteCaching(PHARDWARE_PTE PtePointer, BOOLEAN CacheDisable, BOOLEAN WriteThrough) { + /* Set caching attributes */ PtePointer->Pml2.CacheDisable = CacheDisable; PtePointer->Pml2.WriteThrough = WriteThrough; } +/** + * Advances a PTE pointer by a given number of entries, considering the actual PTE size for PML3. + * + * @param Pte + * The PTE pointer to advance. + * + * @param Count + * The number of PTE entries to advance by. + * + * @return The advanced PTE pointer. + * + * @since XT 1.0 + */ +XTAPI +PMMPTE +MM::PageMapXpa::AdvancePte(PMMPTE Pte, + ULONG Count) +{ + /* Return advanced PTE pointer */ + return (PMMPTE)((ULONG_PTR)Pte + (Count * sizeof(MMPML3_PTE))); +} + +/** + * Gets the next entry in a PTE list. + * + * @param Pte + * The PTE pointer to get the next entry from. + * + * @return This routine returns the next entry in the PTE list. + * + * @since XT 1.0 + */ +XTAPI +ULONG_PTR +MM::PageMapXpa::GetNextEntry(PMMPTE Pte) +{ + /* Return next entry in PTE list */ + return Pte->Pml3.List.NextEntry; +} + +/** + * Advances a PTE pointer, considering the actual PTE size for PML3. + * + * @param Pte + * The PTE pointer to advance. + * + * @return The advanced PTE pointer. + * + * @since XT 1.0 + */ +XTAPI +PMMPTE +MM::PageMapXpa::GetNextPte(PMMPTE Pte) +{ + /* Return advanced PTE pointer */ + return AdvancePte(Pte, 1); +} + +/** + * Checks if a PTE list contains only one entry. + * + * @param Pte + * The PTE pointer to check. + * + * @return This routine returns TRUE if the PTE list has only one entry, FALSE otherwise. + * + * @since XT 1.0 + */ +XTAPI +BOOLEAN +MM::PageMapXpa::GetOneEntry(PMMPTE Pte) +{ + /* Return one entry status */ + return Pte->Pml3.List.OneEntry; +} + +/** + * Gets the size of a PTE for XPA paging (PML3). + * + * @return This routine returns the size of a PTE. + * + * @since XT 1.0 + */ +XTAPI +ULONG +MM::PageMapXpa::GetPteSize(VOID) +{ + /* Return the size of MMPTE */ + return sizeof(MMPML3_PTE); +} + /** * Initializes page map information for basic paging (PML3). * @@ -190,14 +546,17 @@ XTAPI VOID MM::PageMapXpa::InitializePageMapInfo(VOID) { - /* Set PML2 page map information */ + /* Set PML3 page map information */ PageMapInfo.Xpa = TRUE; - /* Set PML2 base addresses */ + /* Set PML3 empty PTE list mask */ + PageMapInfo.EmptyPteList = (ULONG)0xFFFFFFFF; + + /* Set PML3 base addresses */ PageMapInfo.PteBase = MM_PTE_BASE; PageMapInfo.PdeBase = MM_PDE_BASE; - /* Set PML2 shift values */ + /* Set PML3 shift values */ PageMapInfo.PdiShift = MM_PDI_SHIFT; PageMapInfo.PteShift = MM_PTE_SHIFT; } @@ -219,6 +578,50 @@ MM::PageMapXpa::PteValid(PHARDWARE_PTE PtePointer) return (BOOLEAN)PtePointer->Pml3.Valid; } +/** + * Sets the next entry in a PTE list. + * + * @param Pte + * The PTE pointer to modify. + * + * @param Value + * The value to set as the next entry. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::PageMapXpa::SetNextEntry(PMMPTE Pte, + ULONG_PTR Value) +{ + /* Set next entry in PTE list */ + Pte->Pml3.List.NextEntry = Value; +} + +/** + * Sets the flag indicating whether a PTE list contains only one entry. + * + * @param Pte + * The PTE pointer to modify. + * + * @param Value + * The value to set. TRUE if the list has only one entry, FALSE otherwise. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::PageMapXpa::SetOneEntry(PMMPTE Pte, + BOOLEAN Value) +{ + /* Set one entry status */ + Pte->Pml3.List.OneEntry = Value; +} + /** * Sets a PML3 page table entry (PTE) with the specified physical page and access flags. * @@ -241,6 +644,7 @@ MM::PageMapXpa::SetPte(PHARDWARE_PTE PtePointer, PFN_NUMBER PageFrameNumber, BOOLEAN Writable) { + /* Set PTE */ PtePointer->Pml3.PageFrameNumber = PageFrameNumber; PtePointer->Pml3.Valid = 1; PtePointer->Pml3.Writable = Writable; @@ -268,6 +672,7 @@ MM::PageMapXpa::SetPteCaching(PHARDWARE_PTE PtePointer, BOOLEAN CacheDisable, BOOLEAN WriteThrough) { + /* Set caching attributes */ PtePointer->Pml3.CacheDisable = CacheDisable; PtePointer->Pml3.WriteThrough = WriteThrough; }