From ffa480d69aeac1de9a86dd4ea1db28662fb3dad6 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Thu, 30 Oct 2025 20:14:02 +0100 Subject: [PATCH 001/166] 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; } -- 2.52.0 From f6dac120572661e3d34aa134c46787df10c608f5 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Thu, 30 Oct 2025 20:19:35 +0100 Subject: [PATCH 002/166] Add missing EmptyPteList field to MMPAGEMAP_INFO --- sdk/xtdk/amd64/mmtypes.h | 1 + sdk/xtdk/i686/mmtypes.h | 1 + 2 files changed, 2 insertions(+) diff --git a/sdk/xtdk/amd64/mmtypes.h b/sdk/xtdk/amd64/mmtypes.h index 3b8db1f..367f7b6 100644 --- a/sdk/xtdk/amd64/mmtypes.h +++ b/sdk/xtdk/amd64/mmtypes.h @@ -99,6 +99,7 @@ typedef struct _HARDWARE_PTE typedef struct _MMPAGEMAP_INFO { BOOLEAN Xpa; + ULONGLONG EmptyPteList; ULONGLONG PteBase; ULONGLONG PdeBase; ULONGLONG PpeBase; diff --git a/sdk/xtdk/i686/mmtypes.h b/sdk/xtdk/i686/mmtypes.h index 027fc1a..656e855 100644 --- a/sdk/xtdk/i686/mmtypes.h +++ b/sdk/xtdk/i686/mmtypes.h @@ -115,6 +115,7 @@ typedef union _HARDWARE_PTE typedef struct _MMPAGEMAP_INFO { BOOLEAN Xpa; + ULONG EmptyPteList; ULONG PteBase; ULONG PdeBase; ULONG PdiShift; -- 2.52.0 From 1150b9ecdb93ffbf79a42bd74348a361d0342068 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Thu, 30 Oct 2025 22:03:25 +0100 Subject: [PATCH 003/166] Add PTE management routines --- xtoskrnl/includes/mm/paging.hh | 11 +++ xtoskrnl/mm/amd64/pagemap.cc | 1 + xtoskrnl/mm/paging.cc | 161 +++++++++++++++++++++++++++++++++ 3 files changed, 173 insertions(+) diff --git a/xtoskrnl/includes/mm/paging.hh b/xtoskrnl/includes/mm/paging.hh index 2f261f3..b6210f2 100644 --- a/xtoskrnl/includes/mm/paging.hh +++ b/xtoskrnl/includes/mm/paging.hh @@ -21,13 +21,24 @@ namespace MM STATIC PPAGEMAP PmlRoutines; public: + STATIC XTAPI PMMPTE AdvancePte(PMMPTE Pte, + ULONG Count); STATIC XTAPI VOID ClearPte(PHARDWARE_PTE PtePointer); STATIC XTAPI VOID FlushTlb(VOID); + STATIC XTAPI ULONG_PTR GetEmptyPteList(VOID); + STATIC XTAPI ULONG_PTR GetNextEntry(PMMPTE Pte); + STATIC XTAPI PMMPTE GetNextPte(PMMPTE Pte); + STATIC XTAPI BOOLEAN GetOneEntry(PMMPTE Pte); STATIC XTAPI PMMPDE GetPdeAddress(PVOID Address); STATIC XTAPI PMMPPE GetPpeAddress(PVOID Address); STATIC XTAPI PMMPTE GetPteAddress(PVOID Address); + STATIC XTAPI ULONG GetPteSize(VOID); STATIC XTAPI VOID InitializePageMapSupport(VOID); STATIC XTAPI BOOLEAN PteValid(PHARDWARE_PTE PtePointer); + STATIC XTAPI VOID SetNextEntry(PMMPTE Pte, + ULONG_PTR Value); + STATIC XTAPI VOID SetOneEntry(PMMPTE Pte, + BOOLEAN Value); STATIC 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 6ede720..127d6ed 100644 --- a/xtoskrnl/mm/amd64/pagemap.cc +++ b/xtoskrnl/mm/amd64/pagemap.cc @@ -27,6 +27,7 @@ PMMPTE MM::PageMap::AdvancePte(PMMPTE Pte, ULONG Count) { + /* Return advanced PTE pointer */ return (PMMPTE)((ULONG_PTR)Pte + (Count * sizeof(MMPTE))); } diff --git a/xtoskrnl/mm/paging.cc b/xtoskrnl/mm/paging.cc index 58833b1..e78c9f8 100644 --- a/xtoskrnl/mm/paging.cc +++ b/xtoskrnl/mm/paging.cc @@ -9,6 +9,28 @@ #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::Paging::AdvancePte(PMMPTE Pte, + ULONG Count) +{ + /* Return advanced PTE pointer */ + return PmlRoutines->AdvancePte(Pte, Count); +} + /** * Clears the contents of a page table entry (PTE). * @@ -23,6 +45,7 @@ XTAPI VOID MM::Paging::ClearPte(PHARDWARE_PTE PtePointer) { + /* Clear PTE */ PmlRoutines->ClearPte(PtePointer); } @@ -78,6 +101,75 @@ MM::Paging::FlushTlb(VOID) } } +/** + * 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_PTR +MM::Paging::GetEmptyPteList(VOID) +{ + /* Return empty PTE list mask */ + return (ULONG_PTR)PmlRoutines->GetEmptyPteList(); +} + +/** + * 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::Paging::GetNextEntry(PMMPTE Pte) +{ + /* Return next entry in PTE list */ + return PmlRoutines->GetNextEntry(Pte); +} + +/** + * 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::Paging::GetNextPte(PMMPTE Pte) +{ + /* Return advanced PTE pointer */ + return PmlRoutines->GetNextPte(Pte); +} + +/** + * 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::Paging::GetOneEntry(PMMPTE Pte) +{ + /* Return one entry status */ + return PmlRoutines->GetOneEntry(Pte); +} + /** * Gets the page map routines for basic paging mode (non-XPA). * @@ -90,6 +182,8 @@ MM::PPAGEMAP MM::Paging::GetPageMapBasicRoutines(VOID) { static MM::PageMapBasic PageMapBasicRoutines; + + /* Return non-XPA page map routines */ return &PageMapBasicRoutines; } @@ -105,6 +199,8 @@ MM::PPAGEMAP MM::Paging::GetPageMapXpaRoutines(VOID) { static MM::PageMapXpa PageMapXpaRoutines; + + /* Return XPA page map routines */ return &PageMapXpaRoutines; } @@ -122,6 +218,7 @@ XTAPI PMMPDE MM::Paging::GetPdeAddress(PVOID Address) { + /* Return PDE address */ return PmlRoutines->GetPdeAddress(Address); } @@ -139,6 +236,7 @@ XTAPI PMMPPE MM::Paging::GetPpeAddress(PVOID Address) { + /* Return PPE address */ return PmlRoutines->GetPpeAddress(Address); } @@ -156,9 +254,25 @@ XTAPI PMMPTE MM::Paging::GetPteAddress(PVOID Address) { + /* Return PTE address */ return PmlRoutines->GetPteAddress(Address); } +/** + * Gets the size of a PTE. + * + * @return This routine returns the size of a PTE. + * + * @since XT 1.0 + */ +XTAPI +ULONG +MM::Paging::GetPteSize(VOID) +{ + /* Return the size of MMPTE */ + return PmlRoutines->GetPteSize(); +} + /** * Detects if eXtended Physical Addressing (XPA) is enabled and initializes page map support. * @@ -200,9 +314,54 @@ XTAPI BOOLEAN MM::Paging::PteValid(PHARDWARE_PTE PtePointer) { + /* Check if PTE is valid */ return PmlRoutines->PteValid(PtePointer); } +/** + * 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::Paging::SetNextEntry(PMMPTE Pte, + ULONG_PTR Value) +{ + /* Set next entry in PTE list */ + PmlRoutines->SetNextEntry(Pte, 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::Paging::SetOneEntry(PMMPTE Pte, + BOOLEAN Value) +{ + /* Set one entry status */ + PmlRoutines->SetOneEntry(Pte, Value); +} + /** * Sets a PML2 page table entry (PTE) with the specified physical page and access flags. * @@ -225,6 +384,7 @@ MM::Paging::SetPte(PHARDWARE_PTE PtePointer, PFN_NUMBER PageFrameNumber, BOOLEAN Writable) { + /* Set PTE */ PmlRoutines->SetPte(PtePointer, PageFrameNumber, Writable); } @@ -250,5 +410,6 @@ MM::Paging::SetPteCaching(PHARDWARE_PTE PtePointer, BOOLEAN CacheDisable, BOOLEAN WriteThrough) { + /* Set caching attributes */ PmlRoutines->SetPteCaching(PtePointer, CacheDisable, WriteThrough); } -- 2.52.0 From dfb028442736f59ca04f28d9f0c5b2228cdcf235 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Mon, 3 Nov 2025 16:00:46 +0100 Subject: [PATCH 004/166] Add input qualifiers to paging interface definitions --- xtoskrnl/includes/mm/paging.hh | 40 +++++++++++++++---------------- xtoskrnl/mm/paging.cc | 44 +++++++++++++++++----------------- 2 files changed, 42 insertions(+), 42 deletions(-) diff --git a/xtoskrnl/includes/mm/paging.hh b/xtoskrnl/includes/mm/paging.hh index b6210f2..f7b7e53 100644 --- a/xtoskrnl/includes/mm/paging.hh +++ b/xtoskrnl/includes/mm/paging.hh @@ -21,30 +21,30 @@ namespace MM STATIC PPAGEMAP PmlRoutines; public: - STATIC XTAPI PMMPTE AdvancePte(PMMPTE Pte, - ULONG Count); - STATIC XTAPI VOID ClearPte(PHARDWARE_PTE PtePointer); + STATIC XTAPI PMMPTE AdvancePte(IN PMMPTE Pte, + IN ULONG Count); + STATIC XTAPI VOID ClearPte(IN PHARDWARE_PTE PtePointer); STATIC XTAPI VOID FlushTlb(VOID); STATIC XTAPI ULONG_PTR GetEmptyPteList(VOID); - STATIC XTAPI ULONG_PTR GetNextEntry(PMMPTE Pte); - STATIC XTAPI PMMPTE GetNextPte(PMMPTE Pte); - STATIC XTAPI BOOLEAN GetOneEntry(PMMPTE Pte); - STATIC XTAPI PMMPDE GetPdeAddress(PVOID Address); - STATIC XTAPI PMMPPE GetPpeAddress(PVOID Address); - STATIC XTAPI PMMPTE GetPteAddress(PVOID Address); + STATIC XTAPI ULONG_PTR GetNextEntry(IN PMMPTE Pte); + STATIC XTAPI PMMPTE GetNextPte(IN PMMPTE Pte); + STATIC XTAPI BOOLEAN GetOneEntry(IN PMMPTE Pte); + STATIC XTAPI PMMPDE GetPdeAddress(IN PVOID Address); + STATIC XTAPI PMMPPE GetPpeAddress(IN PVOID Address); + STATIC XTAPI PMMPTE GetPteAddress(IN PVOID Address); STATIC XTAPI ULONG GetPteSize(VOID); STATIC XTAPI VOID InitializePageMapSupport(VOID); - STATIC XTAPI BOOLEAN PteValid(PHARDWARE_PTE PtePointer); - STATIC XTAPI VOID SetNextEntry(PMMPTE Pte, - ULONG_PTR Value); - STATIC XTAPI VOID SetOneEntry(PMMPTE Pte, - BOOLEAN Value); - STATIC XTAPI VOID SetPte(PHARDWARE_PTE PtePointer, - PFN_NUMBER PageFrameNumber, - BOOLEAN Writable); - STATIC XTAPI VOID SetPteCaching(PHARDWARE_PTE PtePointer, - BOOLEAN CacheDisable, - BOOLEAN WriteThrough); + STATIC XTAPI BOOLEAN PteValid(IN PHARDWARE_PTE PtePointer); + STATIC XTAPI VOID SetNextEntry(IN PMMPTE Pte, + IN ULONG_PTR Value); + STATIC XTAPI VOID SetOneEntry(IN PMMPTE Pte, + IN BOOLEAN Value); + STATIC XTAPI VOID SetPte(IN PHARDWARE_PTE PtePointer, + IN PFN_NUMBER PageFrameNumber, + IN BOOLEAN Writable); + STATIC XTAPI VOID SetPteCaching(IN PHARDWARE_PTE PtePointer, + IN BOOLEAN CacheDisable, + IN BOOLEAN WriteThrough); STATIC XTFASTCALL VOID ZeroPages(IN PVOID Address, IN ULONG Size); diff --git a/xtoskrnl/mm/paging.cc b/xtoskrnl/mm/paging.cc index e78c9f8..9bd9a2d 100644 --- a/xtoskrnl/mm/paging.cc +++ b/xtoskrnl/mm/paging.cc @@ -24,8 +24,8 @@ */ XTAPI PMMPTE -MM::Paging::AdvancePte(PMMPTE Pte, - ULONG Count) +MM::Paging::AdvancePte(IN PMMPTE Pte, + IN ULONG Count) { /* Return advanced PTE pointer */ return PmlRoutines->AdvancePte(Pte, Count); @@ -43,7 +43,7 @@ MM::Paging::AdvancePte(PMMPTE Pte, */ XTAPI VOID -MM::Paging::ClearPte(PHARDWARE_PTE PtePointer) +MM::Paging::ClearPte(IN PHARDWARE_PTE PtePointer) { /* Clear PTE */ PmlRoutines->ClearPte(PtePointer); @@ -128,7 +128,7 @@ MM::Paging::GetEmptyPteList(VOID) */ XTAPI ULONG_PTR -MM::Paging::GetNextEntry(PMMPTE Pte) +MM::Paging::GetNextEntry(IN PMMPTE Pte) { /* Return next entry in PTE list */ return PmlRoutines->GetNextEntry(Pte); @@ -146,7 +146,7 @@ MM::Paging::GetNextEntry(PMMPTE Pte) */ XTAPI PMMPTE -MM::Paging::GetNextPte(PMMPTE Pte) +MM::Paging::GetNextPte(IN PMMPTE Pte) { /* Return advanced PTE pointer */ return PmlRoutines->GetNextPte(Pte); @@ -164,7 +164,7 @@ MM::Paging::GetNextPte(PMMPTE Pte) */ XTAPI BOOLEAN -MM::Paging::GetOneEntry(PMMPTE Pte) +MM::Paging::GetOneEntry(IN PMMPTE Pte) { /* Return one entry status */ return PmlRoutines->GetOneEntry(Pte); @@ -216,7 +216,7 @@ MM::Paging::GetPageMapXpaRoutines(VOID) */ XTAPI PMMPDE -MM::Paging::GetPdeAddress(PVOID Address) +MM::Paging::GetPdeAddress(IN PVOID Address) { /* Return PDE address */ return PmlRoutines->GetPdeAddress(Address); @@ -234,7 +234,7 @@ MM::Paging::GetPdeAddress(PVOID Address) */ XTAPI PMMPPE -MM::Paging::GetPpeAddress(PVOID Address) +MM::Paging::GetPpeAddress(IN PVOID Address) { /* Return PPE address */ return PmlRoutines->GetPpeAddress(Address); @@ -252,7 +252,7 @@ MM::Paging::GetPpeAddress(PVOID Address) */ XTAPI PMMPTE -MM::Paging::GetPteAddress(PVOID Address) +MM::Paging::GetPteAddress(IN PVOID Address) { /* Return PTE address */ return PmlRoutines->GetPteAddress(Address); @@ -312,7 +312,7 @@ MM::Paging::InitializePageMapSupport(VOID) */ XTAPI BOOLEAN -MM::Paging::PteValid(PHARDWARE_PTE PtePointer) +MM::Paging::PteValid(IN PHARDWARE_PTE PtePointer) { /* Check if PTE is valid */ return PmlRoutines->PteValid(PtePointer); @@ -333,8 +333,8 @@ MM::Paging::PteValid(PHARDWARE_PTE PtePointer) */ XTAPI VOID -MM::Paging::SetNextEntry(PMMPTE Pte, - ULONG_PTR Value) +MM::Paging::SetNextEntry(IN PMMPTE Pte, + IN ULONG_PTR Value) { /* Set next entry in PTE list */ PmlRoutines->SetNextEntry(Pte, Value); @@ -355,15 +355,15 @@ MM::Paging::SetNextEntry(PMMPTE Pte, */ XTAPI VOID -MM::Paging::SetOneEntry(PMMPTE Pte, - BOOLEAN Value) +MM::Paging::SetOneEntry(IN PMMPTE Pte, + IN BOOLEAN Value) { /* Set one entry status */ PmlRoutines->SetOneEntry(Pte, Value); } /** - * Sets a PML2 page table entry (PTE) with the specified physical page and access flags. + * Sets a Page Table Entry (PTE) with the specified physical page and access flags. * * @param PtePointer * Pointer to the page table entry (PTE) to set. @@ -380,12 +380,12 @@ MM::Paging::SetOneEntry(PMMPTE Pte, */ XTAPI VOID -MM::Paging::SetPte(PHARDWARE_PTE PtePointer, - PFN_NUMBER PageFrameNumber, - BOOLEAN Writable) +MM::Paging::SetPte(IN PHARDWARE_PTE PtePointer, + IN PFN_NUMBER PageFrameNumber, + IN BOOLEAN Writable) { /* Set PTE */ - PmlRoutines->SetPte(PtePointer, PageFrameNumber, Writable); + PmlRoutines->SetPte(PtePointer, PageFrameNumber, (BOOLEAN)Writable); } /** @@ -406,9 +406,9 @@ MM::Paging::SetPte(PHARDWARE_PTE PtePointer, */ XTAPI VOID -MM::Paging::SetPteCaching(PHARDWARE_PTE PtePointer, - BOOLEAN CacheDisable, - BOOLEAN WriteThrough) +MM::Paging::SetPteCaching(IN PHARDWARE_PTE PtePointer, + IN BOOLEAN CacheDisable, + IN BOOLEAN WriteThrough) { /* Set caching attributes */ PmlRoutines->SetPteCaching(PtePointer, CacheDisable, WriteThrough); -- 2.52.0 From c28c3f83447b39b8f481eb929451049506be25f2 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Mon, 3 Nov 2025 20:04:21 +0100 Subject: [PATCH 005/166] Add input qualifiers to page map interface definitions --- xtoskrnl/includes/mm/amd64/pagemap.hh | 64 +++++++------- xtoskrnl/includes/mm/i686/pagemap.hh | 116 +++++++++++++------------- xtoskrnl/mm/amd64/pagemap.cc | 64 +++++++------- xtoskrnl/mm/i686/pagemap.cc | 84 +++++++++---------- 4 files changed, 164 insertions(+), 164 deletions(-) diff --git a/xtoskrnl/includes/mm/amd64/pagemap.hh b/xtoskrnl/includes/mm/amd64/pagemap.hh index e59a729..717f374 100644 --- a/xtoskrnl/includes/mm/amd64/pagemap.hh +++ b/xtoskrnl/includes/mm/amd64/pagemap.hh @@ -21,41 +21,41 @@ namespace MM MMPAGEMAP_INFO PageMapInfo; public: - XTAPI PMMPTE AdvancePte(PMMPTE Pte, - ULONG Count); - XTAPI VOID ClearPte(PHARDWARE_PTE PtePointer); + XTAPI PMMPTE AdvancePte(IN PMMPTE Pte, + IN ULONG Count); + XTAPI VOID ClearPte(IN 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_PTR GetNextEntry(IN PMMPTE Pte); + XTAPI PMMPTE GetNextPte(IN PMMPTE Pte); + XTAPI BOOLEAN GetOneEntry(IN PMMPTE Pte); + XTAPI PMMP5E GetP5eAddress(IN PVOID Address); + XTAPI ULONG GetP5eIndex(IN PVOID Address); + XTAPI PVOID GetP5eVirtualAddress(IN PMMP5E P5ePointer); + XTAPI PMMPDE GetPdeAddress(IN PVOID Address); + XTAPI ULONG GetPdeIndex(IN PVOID Address); + XTAPI PVOID GetPdeVirtualAddress(IN PMMPDE PdePointer); + XTAPI PMMPPE GetPpeAddress(IN PVOID Address); + XTAPI ULONG GetPpeIndex(IN PVOID Address); + XTAPI PVOID GetPpeVirtualAddress(IN PMMPPE PpePointer); + XTAPI PMMPTE GetPteAddress(IN PVOID Address); + XTAPI ULONG GetPteIndex(IN PVOID Address); XTAPI ULONG GetPteSize(VOID); - XTAPI PVOID GetPteVirtualAddress(PMMPTE PtePointer); - XTAPI PMMPXE GetPxeAddress(PVOID Address); - XTAPI ULONG GetPxeIndex(PVOID Address); - XTAPI PVOID GetPxeVirtualAddress(PMMPXE PxePointer); + XTAPI PVOID GetPteVirtualAddress(IN PMMPTE PtePointer); + XTAPI PMMPXE GetPxeAddress(IN PVOID Address); + XTAPI ULONG GetPxeIndex(IN PVOID Address); + XTAPI PVOID GetPxeVirtualAddress(IN 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); - XTAPI VOID SetPteCaching(PHARDWARE_PTE PtePointer, - BOOLEAN CacheDisable, - BOOLEAN WriteThrough); + XTAPI BOOLEAN PteValid(IN PHARDWARE_PTE PtePointer); + XTAPI VOID SetNextEntry(IN PMMPTE Pte, + IN ULONG_PTR Value); + XTAPI VOID SetOneEntry(IN PMMPTE Pte, + IN BOOLEAN Value); + XTAPI VOID SetPte(IN PHARDWARE_PTE PtePointer, + IN PFN_NUMBER PageFrameNumber, + IN BOOLEAN Writable); + XTAPI VOID SetPteCaching(IN PHARDWARE_PTE PtePointer, + IN BOOLEAN CacheDisable, + IN BOOLEAN WriteThrough); } PAGEMAP, *PPAGEMAP; class PageMapBasic final : public PageMap diff --git a/xtoskrnl/includes/mm/i686/pagemap.hh b/xtoskrnl/includes/mm/i686/pagemap.hh index bd47426..89df0cd 100644 --- a/xtoskrnl/includes/mm/i686/pagemap.hh +++ b/xtoskrnl/includes/mm/i686/pagemap.hh @@ -21,81 +21,81 @@ namespace MM MMPAGEMAP_INFO PageMapInfo; public: - VIRTUAL XTAPI PMMPTE AdvancePte(PMMPTE Pte, - ULONG Count) = 0; - XTAPI VOID ClearPte(PHARDWARE_PTE PtePointer); + VIRTUAL XTAPI PMMPTE AdvancePte(IN PMMPTE Pte, + IN ULONG Count) = 0; + XTAPI VOID ClearPte(IN 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); - XTAPI ULONG GetPteIndex(PVOID Address); + VIRTUAL XTAPI ULONG_PTR GetNextEntry(IN PMMPTE Pte) = 0; + VIRTUAL XTAPI PMMPTE GetNextPte(IN PMMPTE Pte) = 0; + VIRTUAL XTAPI BOOLEAN GetOneEntry(IN PMMPTE Pte) = 0; + XTAPI PMMPDE GetPdeAddress(IN PVOID Address); + XTAPI ULONG GetPdeIndex(IN PVOID Address); + XTAPI PVOID GetPdeVirtualAddress(IN PMMPDE PdePointer); + XTAPI PMMPPE GetPpeAddress(IN PVOID Address); + XTAPI ULONG GetPpeIndex(IN PVOID Address); + XTAPI PVOID GetPpeVirtualAddress(IN PMMPPE PpePointer); + XTAPI PMMPTE GetPteAddress(IN PVOID Address); + XTAPI ULONG GetPteIndex(IN PVOID Address); VIRTUAL XTAPI ULONG GetPteSize(VOID) = 0; - XTAPI PVOID GetPteVirtualAddress(PMMPTE PtePointer); + XTAPI PVOID GetPteVirtualAddress(IN 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, - BOOLEAN CacheDisable, - BOOLEAN WriteThrough) = 0; + VIRTUAL XTAPI BOOLEAN PteValid(IN PHARDWARE_PTE PtePointer) = 0; + VIRTUAL XTAPI VOID SetNextEntry(IN PMMPTE Pte, + IN ULONG_PTR Value) = 0; + VIRTUAL XTAPI VOID SetOneEntry(IN PMMPTE Pte, + IN BOOLEAN Value) = 0; + VIRTUAL XTAPI VOID SetPte(IN PHARDWARE_PTE PtePointer, + IN PFN_NUMBER PageFrameNumber, + IN BOOLEAN Writable) = 0; + VIRTUAL XTAPI VOID SetPteCaching(IN PHARDWARE_PTE PtePointer, + IN BOOLEAN CacheDisable, + IN BOOLEAN WriteThrough) = 0; } PAGEMAP, *PPAGEMAP; 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 PMMPTE AdvancePte(IN PMMPTE Pte, + IN ULONG Count); + XTAPI ULONG_PTR GetNextEntry(IN PMMPTE Pte); + XTAPI PMMPTE GetNextPte(IN PMMPTE Pte); + XTAPI BOOLEAN GetOneEntry(IN 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); - XTAPI VOID SetPteCaching(PHARDWARE_PTE PtePointer, - BOOLEAN CacheDisable, - BOOLEAN WriteThrough); + XTAPI BOOLEAN PteValid(IN PHARDWARE_PTE PtePointer); + XTAPI VOID SetNextEntry(IN PMMPTE Pte, + IN ULONG_PTR Value); + XTAPI VOID SetOneEntry(IN PMMPTE Pte, + IN BOOLEAN Value); + XTAPI VOID SetPte(IN PHARDWARE_PTE PtePointer, + IN PFN_NUMBER PageFrameNumber, + IN BOOLEAN Writable); + XTAPI VOID SetPteCaching(IN PHARDWARE_PTE PtePointer, + IN BOOLEAN CacheDisable, + IN BOOLEAN WriteThrough); }; 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 PMMPTE AdvancePte(IN PMMPTE Pte, + IN ULONG Count); + XTAPI ULONG_PTR GetNextEntry(IN PMMPTE Pte); + XTAPI PMMPTE GetNextPte(IN PMMPTE Pte); + XTAPI BOOLEAN GetOneEntry(IN 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); - XTAPI VOID SetPteCaching(PHARDWARE_PTE PtePointer, - BOOLEAN CacheDisable, - BOOLEAN WriteThrough); + XTAPI BOOLEAN PteValid(IN PHARDWARE_PTE PtePointer); + XTAPI VOID SetNextEntry(IN PMMPTE Pte, + IN ULONG_PTR Value); + XTAPI VOID SetOneEntry(IN PMMPTE Pte, + IN BOOLEAN Value); + XTAPI VOID SetPte(IN PHARDWARE_PTE PtePointer, + IN PFN_NUMBER PageFrameNumber, + IN BOOLEAN Writable); + XTAPI VOID SetPteCaching(IN PHARDWARE_PTE PtePointer, + IN BOOLEAN CacheDisable, + IN BOOLEAN WriteThrough); }; } diff --git a/xtoskrnl/mm/amd64/pagemap.cc b/xtoskrnl/mm/amd64/pagemap.cc index 127d6ed..3f16933 100644 --- a/xtoskrnl/mm/amd64/pagemap.cc +++ b/xtoskrnl/mm/amd64/pagemap.cc @@ -24,8 +24,8 @@ */ XTAPI PMMPTE -MM::PageMap::AdvancePte(PMMPTE Pte, - ULONG Count) +MM::PageMap::AdvancePte(IN PMMPTE Pte, + IN ULONG Count) { /* Return advanced PTE pointer */ return (PMMPTE)((ULONG_PTR)Pte + (Count * sizeof(MMPTE))); @@ -43,7 +43,7 @@ MM::PageMap::AdvancePte(PMMPTE Pte, */ XTAPI VOID -MM::PageMap::ClearPte(PHARDWARE_PTE PtePointer) +MM::PageMap::ClearPte(IN PHARDWARE_PTE PtePointer) { /* Clear PTE */ PtePointer->CacheDisable = 0; @@ -80,7 +80,7 @@ MM::PageMap::GetEmptyPteList(VOID) */ XTAPI ULONG_PTR -MM::PageMap::GetNextEntry(PMMPTE Pte) +MM::PageMap::GetNextEntry(IN PMMPTE Pte) { /* Return next entry in PTE list */ return Pte->List.NextEntry; @@ -98,7 +98,7 @@ MM::PageMap::GetNextEntry(PMMPTE Pte) */ XTAPI PMMPTE -MM::PageMap::GetNextPte(PMMPTE Pte) +MM::PageMap::GetNextPte(IN PMMPTE Pte) { /* Return advanced PTE pointer */ return AdvancePte(Pte, 1); @@ -116,7 +116,7 @@ MM::PageMap::GetNextPte(PMMPTE Pte) */ XTAPI BOOLEAN -MM::PageMap::GetOneEntry(PMMPTE Pte) +MM::PageMap::GetOneEntry(IN PMMPTE Pte) { /* Return one entry status */ return Pte->List.OneEntry; @@ -134,7 +134,7 @@ MM::PageMap::GetOneEntry(PMMPTE Pte) */ XTAPI PMMP5E -MM::PageMap::GetP5eAddress(PVOID Address) +MM::PageMap::GetP5eAddress(IN PVOID Address) { ULONGLONG Offset; @@ -155,7 +155,7 @@ MM::PageMap::GetP5eAddress(PVOID Address) */ XTAPI ULONG -MM::PageMap::GetP5eIndex(PVOID Address) +MM::PageMap::GetP5eIndex(IN PVOID Address) { return (((((ULONGLONG)Address) >> MM_P5I_SHIFT) & 0x1FF) * PageMapInfo.Xpa); } @@ -172,7 +172,7 @@ MM::PageMap::GetP5eIndex(PVOID Address) */ XTAPI PVOID -MM::PageMap::GetP5eVirtualAddress(PMMP5E P5ePointer) +MM::PageMap::GetP5eVirtualAddress(IN PMMP5E P5ePointer) { return (PVOID)((((LONGLONG)P5ePointer << 61) >> 16) * PageMapInfo.Xpa); } @@ -189,7 +189,7 @@ MM::PageMap::GetP5eVirtualAddress(PMMP5E P5ePointer) */ XTAPI PMMPDE -MM::PageMap::GetPdeAddress(PVOID Address) +MM::PageMap::GetPdeAddress(IN PVOID Address) { ULONGLONG Offset; @@ -210,7 +210,7 @@ MM::PageMap::GetPdeAddress(PVOID Address) */ XTAPI ULONG -MM::PageMap::GetPdeIndex(PVOID Address) +MM::PageMap::GetPdeIndex(IN PVOID Address) { /* Return PDE index */ return ((((ULONGLONG)Address) >> MM_PDI_SHIFT) & 0x1FF); @@ -228,7 +228,7 @@ MM::PageMap::GetPdeIndex(PVOID Address) */ XTAPI PVOID -MM::PageMap::GetPdeVirtualAddress(PMMPDE PdePointer) +MM::PageMap::GetPdeVirtualAddress(IN PMMPDE PdePointer) { /* Return PDE virtual address */ return (PVOID)(((LONGLONG)PdePointer << 34) >> 16); @@ -246,7 +246,7 @@ MM::PageMap::GetPdeVirtualAddress(PMMPDE PdePointer) */ XTAPI PMMPPE -MM::PageMap::GetPpeAddress(PVOID Address) +MM::PageMap::GetPpeAddress(IN PVOID Address) { ULONGLONG Offset; @@ -267,7 +267,7 @@ MM::PageMap::GetPpeAddress(PVOID Address) */ XTAPI ULONG -MM::PageMap::GetPpeIndex(PVOID Address) +MM::PageMap::GetPpeIndex(IN PVOID Address) { /* Return PPE index */ return ((((ULONGLONG)Address) >> MM_PPI_SHIFT) & 0x1FF); @@ -285,7 +285,7 @@ MM::PageMap::GetPpeIndex(PVOID Address) */ XTAPI PVOID -MM::PageMap::GetPpeVirtualAddress(PMMPPE PpePointer) +MM::PageMap::GetPpeVirtualAddress(IN PMMPPE PpePointer) { /* Return PPE virtual address */ return (PVOID)(((LONGLONG)PpePointer << 43) >> 16); @@ -303,7 +303,7 @@ MM::PageMap::GetPpeVirtualAddress(PMMPPE PpePointer) */ XTAPI PMMPTE -MM::PageMap::GetPteAddress(PVOID Address) +MM::PageMap::GetPteAddress(IN PVOID Address) { ULONGLONG Offset; @@ -324,7 +324,7 @@ MM::PageMap::GetPteAddress(PVOID Address) */ XTAPI ULONG -MM::PageMap::GetPteIndex(PVOID Address) +MM::PageMap::GetPteIndex(IN PVOID Address) { /* Return PTE index */ return ((((ULONGLONG)Address) >> MM_PTI_SHIFT) & 0x1FF); @@ -357,7 +357,7 @@ MM::PageMap::GetPteSize(VOID) */ XTAPI PVOID -MM::PageMap::GetPteVirtualAddress(PMMPTE PtePointer) +MM::PageMap::GetPteVirtualAddress(IN PMMPTE PtePointer) { /* Return PTE virtual address */ return (PVOID)(((LONGLONG)PtePointer << 25) >> 16); @@ -375,7 +375,7 @@ MM::PageMap::GetPteVirtualAddress(PMMPTE PtePointer) */ XTAPI PMMPXE -MM::PageMap::GetPxeAddress(PVOID Address) +MM::PageMap::GetPxeAddress(IN PVOID Address) { ULONGLONG Offset; @@ -396,7 +396,7 @@ MM::PageMap::GetPxeAddress(PVOID Address) */ XTAPI ULONG -MM::PageMap::GetPxeIndex(PVOID Address) +MM::PageMap::GetPxeIndex(IN PVOID Address) { /* Return PXE index */ return ((((ULONGLONG)Address) >> MM_PXI_SHIFT) & 0x1FF); @@ -414,7 +414,7 @@ MM::PageMap::GetPxeIndex(PVOID Address) */ XTAPI PVOID -MM::PageMap::GetPxeVirtualAddress(PMMPXE PxePointer) +MM::PageMap::GetPxeVirtualAddress(IN PMMPXE PxePointer) { /* Return PXE virtual address */ return (PVOID)(((LONGLONG)PxePointer << 52) >> 16); @@ -432,7 +432,7 @@ MM::PageMap::GetPxeVirtualAddress(PMMPXE PxePointer) */ XTAPI BOOLEAN -MM::PageMap::PteValid(PHARDWARE_PTE PtePointer) +MM::PageMap::PteValid(IN PHARDWARE_PTE PtePointer) { /* Check if PTE is valid */ return (BOOLEAN)PtePointer->Valid; @@ -453,8 +453,8 @@ MM::PageMap::PteValid(PHARDWARE_PTE PtePointer) */ XTAPI VOID -MM::PageMap::SetNextEntry(PMMPTE Pte, - ULONG_PTR Value) +MM::PageMap::SetNextEntry(IN PMMPTE Pte, + IN ULONG_PTR Value) { /* Set next entry in PTE list */ Pte->List.NextEntry = Value; @@ -475,8 +475,8 @@ MM::PageMap::SetNextEntry(PMMPTE Pte, */ XTAPI VOID -MM::PageMap::SetOneEntry(PMMPTE Pte, - BOOLEAN Value) +MM::PageMap::SetOneEntry(IN PMMPTE Pte, + IN BOOLEAN Value) { /* Set one entry status */ Pte->List.OneEntry = Value; @@ -500,9 +500,9 @@ MM::PageMap::SetOneEntry(PMMPTE Pte, */ XTAPI VOID -MM::PageMap::SetPte(PHARDWARE_PTE PtePointer, - PFN_NUMBER PageFrameNumber, - BOOLEAN Writable) +MM::PageMap::SetPte(IN PHARDWARE_PTE PtePointer, + IN PFN_NUMBER PageFrameNumber, + IN BOOLEAN Writable) { /* Set PTE */ PtePointer->PageFrameNumber = PageFrameNumber; @@ -528,9 +528,9 @@ MM::PageMap::SetPte(PHARDWARE_PTE PtePointer, */ XTAPI VOID -MM::PageMap::SetPteCaching(PHARDWARE_PTE PtePointer, - BOOLEAN CacheDisable, - BOOLEAN WriteThrough) +MM::PageMap::SetPteCaching(IN PHARDWARE_PTE PtePointer, + IN BOOLEAN CacheDisable, + IN BOOLEAN WriteThrough) { /* Set caching attributes */ PtePointer->CacheDisable = CacheDisable; diff --git a/xtoskrnl/mm/i686/pagemap.cc b/xtoskrnl/mm/i686/pagemap.cc index 15faa54..81d5f10 100644 --- a/xtoskrnl/mm/i686/pagemap.cc +++ b/xtoskrnl/mm/i686/pagemap.cc @@ -21,7 +21,7 @@ */ XTAPI VOID -MM::PageMap::ClearPte(PHARDWARE_PTE PtePointer) +MM::PageMap::ClearPte(IN PHARDWARE_PTE PtePointer) { /* Clear PTE */ PtePointer->Long = 0; @@ -54,7 +54,7 @@ MM::PageMap::GetEmptyPteList(VOID) */ XTAPI PMMPDE -MM::PageMap::GetPdeAddress(PVOID Address) +MM::PageMap::GetPdeAddress(IN PVOID Address) { ULONG Offset; @@ -75,7 +75,7 @@ MM::PageMap::GetPdeAddress(PVOID Address) */ XTAPI ULONG -MM::PageMap::GetPdeIndex(PVOID Address) +MM::PageMap::GetPdeIndex(IN PVOID Address) { /* Return PDE index */ return ((((ULONG_PTR)(Address)) >> PageMapInfo.PdiShift) & (PageMapInfo.Xpa ? 0x1FF : 0x3FF)); @@ -93,7 +93,7 @@ MM::PageMap::GetPdeIndex(PVOID Address) */ XTAPI PVOID -MM::PageMap::GetPdeVirtualAddress(PMMPDE PdePointer) +MM::PageMap::GetPdeVirtualAddress(IN PMMPDE PdePointer) { /* Return PDE virtual address */ return ((PVOID)((ULONG)(PdePointer) << 20)); @@ -111,7 +111,7 @@ MM::PageMap::GetPdeVirtualAddress(PMMPDE PdePointer) */ XTAPI PMMPPE -MM::PageMap::GetPpeAddress(PVOID Address) +MM::PageMap::GetPpeAddress(IN PVOID Address) { /* Return zero */ return (PMMPPE)0; @@ -129,7 +129,7 @@ MM::PageMap::GetPpeAddress(PVOID Address) */ XTAPI ULONG -MM::PageMap::GetPpeIndex(PVOID Address) +MM::PageMap::GetPpeIndex(IN PVOID Address) { /* Return PPE index */ return ((((ULONG_PTR)(Address)) >> MM_PPI_SHIFT) & 0x3) * PageMapInfo.Xpa; @@ -147,7 +147,7 @@ MM::PageMap::GetPpeIndex(PVOID Address) */ XTAPI PVOID -MM::PageMap::GetPpeVirtualAddress(PMMPPE PpePointer) +MM::PageMap::GetPpeVirtualAddress(IN PMMPPE PpePointer) { /* Return PPE virtual address */ return (PVOID)((ULONG)(PpePointer) << 30); @@ -165,7 +165,7 @@ MM::PageMap::GetPpeVirtualAddress(PMMPPE PpePointer) */ XTAPI PMMPTE -MM::PageMap::GetPteAddress(PVOID Address) +MM::PageMap::GetPteAddress(IN PVOID Address) { ULONG Offset; @@ -186,7 +186,7 @@ MM::PageMap::GetPteAddress(PVOID Address) */ XTAPI ULONG -MM::PageMap::GetPteIndex(PVOID Address) +MM::PageMap::GetPteIndex(IN PVOID Address) { /* Return PTE index */ return ((((ULONG_PTR)(Address)) >> MM_PTI_SHIFT) & (PageMapInfo.Xpa ? 0x1FF : 0x3FF)); @@ -204,7 +204,7 @@ MM::PageMap::GetPteIndex(PVOID Address) */ XTAPI PVOID -MM::PageMap::GetPteVirtualAddress(PMMPTE PtePointer) +MM::PageMap::GetPteVirtualAddress(IN PMMPTE PtePointer) { /* Return PTE virtual address */ return ((PVOID)((ULONG)(PtePointer) << 10)); @@ -225,8 +225,8 @@ MM::PageMap::GetPteVirtualAddress(PMMPTE PtePointer) */ XTAPI PMMPTE -MM::PageMapBasic::AdvancePte(PMMPTE Pte, - ULONG Count) +MM::PageMapBasic::AdvancePte(IN PMMPTE Pte, + IN ULONG Count) { /* Return advanced PTE pointer */ return (PMMPTE)((ULONG_PTR)Pte + (Count * sizeof(MMPML2_PTE))); @@ -244,7 +244,7 @@ MM::PageMapBasic::AdvancePte(PMMPTE Pte, */ XTAPI ULONG_PTR -MM::PageMapBasic::GetNextEntry(PMMPTE Pte) +MM::PageMapBasic::GetNextEntry(IN PMMPTE Pte) { /* Return next entry in PTE list */ return Pte->Pml2.List.NextEntry; @@ -262,7 +262,7 @@ MM::PageMapBasic::GetNextEntry(PMMPTE Pte) */ XTAPI PMMPTE -MM::PageMapBasic::GetNextPte(PMMPTE Pte) +MM::PageMapBasic::GetNextPte(IN PMMPTE Pte) { /* Return advanced PTE pointer */ return AdvancePte(Pte, 1); @@ -280,7 +280,7 @@ MM::PageMapBasic::GetNextPte(PMMPTE Pte) */ XTAPI BOOLEAN -MM::PageMapBasic::GetOneEntry(PMMPTE Pte) +MM::PageMapBasic::GetOneEntry(IN PMMPTE Pte) { /* Return one entry status */ return Pte->Pml2.List.OneEntry; @@ -339,7 +339,7 @@ MM::PageMapBasic::InitializePageMapInfo(VOID) */ XTAPI BOOLEAN -MM::PageMapBasic::PteValid(PHARDWARE_PTE PtePointer) +MM::PageMapBasic::PteValid(IN PHARDWARE_PTE PtePointer) { /* Check if PTE is valid */ return (BOOLEAN)PtePointer->Pml2.Valid; @@ -360,8 +360,8 @@ MM::PageMapBasic::PteValid(PHARDWARE_PTE PtePointer) */ XTAPI VOID -MM::PageMapBasic::SetNextEntry(PMMPTE Pte, - ULONG_PTR Value) +MM::PageMapBasic::SetNextEntry(IN PMMPTE Pte, + IN ULONG_PTR Value) { /* Set next entry in PTE list */ Pte->Pml2.List.NextEntry = Value; @@ -382,8 +382,8 @@ MM::PageMapBasic::SetNextEntry(PMMPTE Pte, */ XTAPI VOID -MM::PageMapBasic::SetOneEntry(PMMPTE Pte, - BOOLEAN Value) +MM::PageMapBasic::SetOneEntry(IN PMMPTE Pte, + IN BOOLEAN Value) { /* Set one entry status */ Pte->Pml2.List.OneEntry = Value; @@ -407,9 +407,9 @@ MM::PageMapBasic::SetOneEntry(PMMPTE Pte, */ XTAPI VOID -MM::PageMapBasic::SetPte(PHARDWARE_PTE PtePointer, - PFN_NUMBER PageFrameNumber, - BOOLEAN Writable) +MM::PageMapBasic::SetPte(IN PHARDWARE_PTE PtePointer, + IN PFN_NUMBER PageFrameNumber, + IN BOOLEAN Writable) { /* Set PTE */ PtePointer->Pml2.PageFrameNumber = PageFrameNumber; @@ -435,9 +435,9 @@ MM::PageMapBasic::SetPte(PHARDWARE_PTE PtePointer, */ XTAPI VOID -MM::PageMapBasic::SetPteCaching(PHARDWARE_PTE PtePointer, - BOOLEAN CacheDisable, - BOOLEAN WriteThrough) +MM::PageMapBasic::SetPteCaching(IN PHARDWARE_PTE PtePointer, + IN BOOLEAN CacheDisable, + IN BOOLEAN WriteThrough) { /* Set caching attributes */ PtePointer->Pml2.CacheDisable = CacheDisable; @@ -459,8 +459,8 @@ MM::PageMapBasic::SetPteCaching(PHARDWARE_PTE PtePointer, */ XTAPI PMMPTE -MM::PageMapXpa::AdvancePte(PMMPTE Pte, - ULONG Count) +MM::PageMapXpa::AdvancePte(IN PMMPTE Pte, + IN ULONG Count) { /* Return advanced PTE pointer */ return (PMMPTE)((ULONG_PTR)Pte + (Count * sizeof(MMPML3_PTE))); @@ -478,7 +478,7 @@ MM::PageMapXpa::AdvancePte(PMMPTE Pte, */ XTAPI ULONG_PTR -MM::PageMapXpa::GetNextEntry(PMMPTE Pte) +MM::PageMapXpa::GetNextEntry(IN PMMPTE Pte) { /* Return next entry in PTE list */ return Pte->Pml3.List.NextEntry; @@ -496,7 +496,7 @@ MM::PageMapXpa::GetNextEntry(PMMPTE Pte) */ XTAPI PMMPTE -MM::PageMapXpa::GetNextPte(PMMPTE Pte) +MM::PageMapXpa::GetNextPte(IN PMMPTE Pte) { /* Return advanced PTE pointer */ return AdvancePte(Pte, 1); @@ -514,7 +514,7 @@ MM::PageMapXpa::GetNextPte(PMMPTE Pte) */ XTAPI BOOLEAN -MM::PageMapXpa::GetOneEntry(PMMPTE Pte) +MM::PageMapXpa::GetOneEntry(IN PMMPTE Pte) { /* Return one entry status */ return Pte->Pml3.List.OneEntry; @@ -573,7 +573,7 @@ MM::PageMapXpa::InitializePageMapInfo(VOID) */ XTAPI BOOLEAN -MM::PageMapXpa::PteValid(PHARDWARE_PTE PtePointer) +MM::PageMapXpa::PteValid(IN PHARDWARE_PTE PtePointer) { return (BOOLEAN)PtePointer->Pml3.Valid; } @@ -593,8 +593,8 @@ MM::PageMapXpa::PteValid(PHARDWARE_PTE PtePointer) */ XTAPI VOID -MM::PageMapXpa::SetNextEntry(PMMPTE Pte, - ULONG_PTR Value) +MM::PageMapXpa::SetNextEntry(IN PMMPTE Pte, + IN ULONG_PTR Value) { /* Set next entry in PTE list */ Pte->Pml3.List.NextEntry = Value; @@ -615,8 +615,8 @@ MM::PageMapXpa::SetNextEntry(PMMPTE Pte, */ XTAPI VOID -MM::PageMapXpa::SetOneEntry(PMMPTE Pte, - BOOLEAN Value) +MM::PageMapXpa::SetOneEntry(IN PMMPTE Pte, + IN BOOLEAN Value) { /* Set one entry status */ Pte->Pml3.List.OneEntry = Value; @@ -640,9 +640,9 @@ MM::PageMapXpa::SetOneEntry(PMMPTE Pte, */ XTAPI VOID -MM::PageMapXpa::SetPte(PHARDWARE_PTE PtePointer, - PFN_NUMBER PageFrameNumber, - BOOLEAN Writable) +MM::PageMapXpa::SetPte(IN PHARDWARE_PTE PtePointer, + IN PFN_NUMBER PageFrameNumber, + IN BOOLEAN Writable) { /* Set PTE */ PtePointer->Pml3.PageFrameNumber = PageFrameNumber; @@ -668,9 +668,9 @@ MM::PageMapXpa::SetPte(PHARDWARE_PTE PtePointer, */ XTAPI VOID -MM::PageMapXpa::SetPteCaching(PHARDWARE_PTE PtePointer, - BOOLEAN CacheDisable, - BOOLEAN WriteThrough) +MM::PageMapXpa::SetPteCaching(IN PHARDWARE_PTE PtePointer, + IN BOOLEAN CacheDisable, + IN BOOLEAN WriteThrough) { /* Set caching attributes */ PtePointer->Pml3.CacheDisable = CacheDisable; -- 2.52.0 From fd130914769e70da93daa2b5d4f53045140a1880 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Mon, 3 Nov 2025 22:02:59 +0100 Subject: [PATCH 006/166] Unify MMPML2_PTE field naming convention --- sdk/xtdk/i686/mmtypes.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sdk/xtdk/i686/mmtypes.h b/sdk/xtdk/i686/mmtypes.h index 656e855..98fced0 100644 --- a/sdk/xtdk/i686/mmtypes.h +++ b/sdk/xtdk/i686/mmtypes.h @@ -203,11 +203,11 @@ typedef union _MMPML2_PTE { ULONG Long; HARDWARE_PTE Flush; - MMPML2_PTE_HARDWARE Hard; - MMPML2_PTE_PROTOTYPE Proto; - MMPML2_PTE_SOFTWARE Soft; - MMPML2_PTE_TRANSITION Trans; - MMPML2_PTE_SUBSECTION Subsect; + MMPML2_PTE_HARDWARE Hardware; + MMPML2_PTE_PROTOTYPE Prototype; + MMPML2_PTE_SOFTWARE Software; + MMPML2_PTE_TRANSITION Transition; + MMPML2_PTE_SUBSECTION Subsection; MMPML2_PTE_LIST List; } MMPML2_PTE, *PMMPML2_PTE; -- 2.52.0 From cb2da54956532b3676afa82366d1471a1dd3509d Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Mon, 3 Nov 2025 22:13:32 +0100 Subject: [PATCH 007/166] Unify PTE pointer types across MM subsystem --- xtoskrnl/includes/mm/amd64/pagemap.hh | 8 +++--- xtoskrnl/includes/mm/i686/pagemap.hh | 20 +++++++------- xtoskrnl/includes/mm/paging.hh | 8 +++--- xtoskrnl/mm/amd64/pagemap.cc | 26 ++++++++---------- xtoskrnl/mm/hlpool.cc | 20 +++++++------- xtoskrnl/mm/i686/pagemap.cc | 38 +++++++++++++-------------- xtoskrnl/mm/paging.cc | 8 +++--- 7 files changed, 62 insertions(+), 66 deletions(-) diff --git a/xtoskrnl/includes/mm/amd64/pagemap.hh b/xtoskrnl/includes/mm/amd64/pagemap.hh index 717f374..28f67c2 100644 --- a/xtoskrnl/includes/mm/amd64/pagemap.hh +++ b/xtoskrnl/includes/mm/amd64/pagemap.hh @@ -23,7 +23,7 @@ namespace MM public: XTAPI PMMPTE AdvancePte(IN PMMPTE Pte, IN ULONG Count); - XTAPI VOID ClearPte(IN PHARDWARE_PTE PtePointer); + XTAPI VOID ClearPte(IN PMMPTE PtePointer); XTAPI ULONGLONG GetEmptyPteList(VOID); XTAPI ULONG_PTR GetNextEntry(IN PMMPTE Pte); XTAPI PMMPTE GetNextPte(IN PMMPTE Pte); @@ -45,15 +45,15 @@ namespace MM XTAPI ULONG GetPxeIndex(IN PVOID Address); XTAPI PVOID GetPxeVirtualAddress(IN PMMPXE PxePointer); VIRTUAL XTAPI VOID InitializePageMapInfo(VOID) = 0; - XTAPI BOOLEAN PteValid(IN PHARDWARE_PTE PtePointer); + XTAPI BOOLEAN PteValid(IN PMMPTE PtePointer); XTAPI VOID SetNextEntry(IN PMMPTE Pte, IN ULONG_PTR Value); XTAPI VOID SetOneEntry(IN PMMPTE Pte, IN BOOLEAN Value); - XTAPI VOID SetPte(IN PHARDWARE_PTE PtePointer, + XTAPI VOID SetPte(IN PMMPTE PtePointer, IN PFN_NUMBER PageFrameNumber, IN BOOLEAN Writable); - XTAPI VOID SetPteCaching(IN PHARDWARE_PTE PtePointer, + XTAPI VOID SetPteCaching(IN PMMPTE PtePointer, IN BOOLEAN CacheDisable, IN BOOLEAN WriteThrough); } PAGEMAP, *PPAGEMAP; diff --git a/xtoskrnl/includes/mm/i686/pagemap.hh b/xtoskrnl/includes/mm/i686/pagemap.hh index 89df0cd..df5bb91 100644 --- a/xtoskrnl/includes/mm/i686/pagemap.hh +++ b/xtoskrnl/includes/mm/i686/pagemap.hh @@ -23,7 +23,7 @@ namespace MM public: VIRTUAL XTAPI PMMPTE AdvancePte(IN PMMPTE Pte, IN ULONG Count) = 0; - XTAPI VOID ClearPte(IN PHARDWARE_PTE PtePointer); + XTAPI VOID ClearPte(IN PMMPTE PtePointer); XTAPI ULONG GetEmptyPteList(VOID); VIRTUAL XTAPI ULONG_PTR GetNextEntry(IN PMMPTE Pte) = 0; VIRTUAL XTAPI PMMPTE GetNextPte(IN PMMPTE Pte) = 0; @@ -39,15 +39,15 @@ namespace MM VIRTUAL XTAPI ULONG GetPteSize(VOID) = 0; XTAPI PVOID GetPteVirtualAddress(IN PMMPTE PtePointer); VIRTUAL XTAPI VOID InitializePageMapInfo(VOID) = 0; - VIRTUAL XTAPI BOOLEAN PteValid(IN PHARDWARE_PTE PtePointer) = 0; + VIRTUAL XTAPI BOOLEAN PteValid(IN PMMPTE PtePointer) = 0; VIRTUAL XTAPI VOID SetNextEntry(IN PMMPTE Pte, IN ULONG_PTR Value) = 0; VIRTUAL XTAPI VOID SetOneEntry(IN PMMPTE Pte, IN BOOLEAN Value) = 0; - VIRTUAL XTAPI VOID SetPte(IN PHARDWARE_PTE PtePointer, + VIRTUAL XTAPI VOID SetPte(IN PMMPTE PtePointer, IN PFN_NUMBER PageFrameNumber, IN BOOLEAN Writable) = 0; - VIRTUAL XTAPI VOID SetPteCaching(IN PHARDWARE_PTE PtePointer, + VIRTUAL XTAPI VOID SetPteCaching(IN PMMPTE PtePointer, IN BOOLEAN CacheDisable, IN BOOLEAN WriteThrough) = 0; } PAGEMAP, *PPAGEMAP; @@ -62,15 +62,15 @@ namespace MM XTAPI BOOLEAN GetOneEntry(IN PMMPTE Pte); XTAPI ULONG GetPteSize(VOID); XTAPI VOID InitializePageMapInfo(VOID); - XTAPI BOOLEAN PteValid(IN PHARDWARE_PTE PtePointer); + XTAPI BOOLEAN PteValid(IN PMMPTE PtePointer); XTAPI VOID SetNextEntry(IN PMMPTE Pte, IN ULONG_PTR Value); XTAPI VOID SetOneEntry(IN PMMPTE Pte, IN BOOLEAN Value); - XTAPI VOID SetPte(IN PHARDWARE_PTE PtePointer, + XTAPI VOID SetPte(IN PMMPTE PtePointer, IN PFN_NUMBER PageFrameNumber, IN BOOLEAN Writable); - XTAPI VOID SetPteCaching(IN PHARDWARE_PTE PtePointer, + XTAPI VOID SetPteCaching(IN PMMPTE PtePointer, IN BOOLEAN CacheDisable, IN BOOLEAN WriteThrough); }; @@ -85,15 +85,15 @@ namespace MM XTAPI BOOLEAN GetOneEntry(IN PMMPTE Pte); XTAPI ULONG GetPteSize(VOID); XTAPI VOID InitializePageMapInfo(VOID); - XTAPI BOOLEAN PteValid(IN PHARDWARE_PTE PtePointer); + XTAPI BOOLEAN PteValid(IN PMMPTE PtePointer); XTAPI VOID SetNextEntry(IN PMMPTE Pte, IN ULONG_PTR Value); XTAPI VOID SetOneEntry(IN PMMPTE Pte, IN BOOLEAN Value); - XTAPI VOID SetPte(IN PHARDWARE_PTE PtePointer, + XTAPI VOID SetPte(IN PMMPTE PtePointer, IN PFN_NUMBER PageFrameNumber, IN BOOLEAN Writable); - XTAPI VOID SetPteCaching(IN PHARDWARE_PTE PtePointer, + XTAPI VOID SetPteCaching(IN PMMPTE PtePointer, IN BOOLEAN CacheDisable, IN BOOLEAN WriteThrough); }; diff --git a/xtoskrnl/includes/mm/paging.hh b/xtoskrnl/includes/mm/paging.hh index f7b7e53..76adf99 100644 --- a/xtoskrnl/includes/mm/paging.hh +++ b/xtoskrnl/includes/mm/paging.hh @@ -23,7 +23,7 @@ namespace MM public: STATIC XTAPI PMMPTE AdvancePte(IN PMMPTE Pte, IN ULONG Count); - STATIC XTAPI VOID ClearPte(IN PHARDWARE_PTE PtePointer); + STATIC XTAPI VOID ClearPte(IN PMMPTE PtePointer); STATIC XTAPI VOID FlushTlb(VOID); STATIC XTAPI ULONG_PTR GetEmptyPteList(VOID); STATIC XTAPI ULONG_PTR GetNextEntry(IN PMMPTE Pte); @@ -34,15 +34,15 @@ namespace MM STATIC XTAPI PMMPTE GetPteAddress(IN PVOID Address); STATIC XTAPI ULONG GetPteSize(VOID); STATIC XTAPI VOID InitializePageMapSupport(VOID); - STATIC XTAPI BOOLEAN PteValid(IN PHARDWARE_PTE PtePointer); + STATIC XTAPI BOOLEAN PteValid(IN PMMPTE PtePointer); STATIC XTAPI VOID SetNextEntry(IN PMMPTE Pte, IN ULONG_PTR Value); STATIC XTAPI VOID SetOneEntry(IN PMMPTE Pte, IN BOOLEAN Value); - STATIC XTAPI VOID SetPte(IN PHARDWARE_PTE PtePointer, + STATIC XTAPI VOID SetPte(IN PMMPTE PtePointer, IN PFN_NUMBER PageFrameNumber, IN BOOLEAN Writable); - STATIC XTAPI VOID SetPteCaching(IN PHARDWARE_PTE PtePointer, + STATIC XTAPI VOID SetPteCaching(IN PMMPTE PtePointer, IN BOOLEAN CacheDisable, IN BOOLEAN WriteThrough); STATIC XTFASTCALL VOID ZeroPages(IN PVOID Address, diff --git a/xtoskrnl/mm/amd64/pagemap.cc b/xtoskrnl/mm/amd64/pagemap.cc index 3f16933..be54c3f 100644 --- a/xtoskrnl/mm/amd64/pagemap.cc +++ b/xtoskrnl/mm/amd64/pagemap.cc @@ -43,14 +43,10 @@ MM::PageMap::AdvancePte(IN PMMPTE Pte, */ XTAPI VOID -MM::PageMap::ClearPte(IN PHARDWARE_PTE PtePointer) +MM::PageMap::ClearPte(IN PMMPTE PtePointer) { /* Clear PTE */ - PtePointer->CacheDisable = 0; - PtePointer->PageFrameNumber = 0; - PtePointer->Valid = 0; - PtePointer->Writable = 0; - PtePointer->WriteThrough = 0; + PtePointer->Long = 0; } /** @@ -432,10 +428,10 @@ MM::PageMap::GetPxeVirtualAddress(IN PMMPXE PxePointer) */ XTAPI BOOLEAN -MM::PageMap::PteValid(IN PHARDWARE_PTE PtePointer) +MM::PageMap::PteValid(IN PMMPTE PtePointer) { /* Check if PTE is valid */ - return (BOOLEAN)PtePointer->Valid; + return (BOOLEAN)PtePointer->Hardware.Valid; } /** @@ -500,14 +496,14 @@ MM::PageMap::SetOneEntry(IN PMMPTE Pte, */ XTAPI VOID -MM::PageMap::SetPte(IN PHARDWARE_PTE PtePointer, +MM::PageMap::SetPte(IN PMMPTE PtePointer, IN PFN_NUMBER PageFrameNumber, IN BOOLEAN Writable) { /* Set PTE */ - PtePointer->PageFrameNumber = PageFrameNumber; - PtePointer->Valid = 1; - PtePointer->Writable = Writable; + PtePointer->Hardware.PageFrameNumber = PageFrameNumber; + PtePointer->Hardware.Valid = 1; + PtePointer->Hardware.Writable = Writable; } /** @@ -528,13 +524,13 @@ MM::PageMap::SetPte(IN PHARDWARE_PTE PtePointer, */ XTAPI VOID -MM::PageMap::SetPteCaching(IN PHARDWARE_PTE PtePointer, +MM::PageMap::SetPteCaching(IN PMMPTE PtePointer, IN BOOLEAN CacheDisable, IN BOOLEAN WriteThrough) { /* Set caching attributes */ - PtePointer->CacheDisable = CacheDisable; - PtePointer->WriteThrough = WriteThrough; + PtePointer->Hardware.CacheDisable = CacheDisable; + PtePointer->Hardware.WriteThrough = WriteThrough; } /** diff --git a/xtoskrnl/mm/hlpool.cc b/xtoskrnl/mm/hlpool.cc index 8728b8f..9c1d612 100644 --- a/xtoskrnl/mm/hlpool.cc +++ b/xtoskrnl/mm/hlpool.cc @@ -170,7 +170,7 @@ MM::HardwarePool::MapHardwareMemory(IN PHYSICAL_ADDRESS PhysicalAddress, { PVOID BaseAddress, ReturnAddress; PFN_NUMBER MappedPages; - PHARDWARE_PTE PtePointer; + PMMPTE PtePointer; /* Initialize variables */ BaseAddress = HardwareHeapStart; @@ -189,7 +189,7 @@ MM::HardwarePool::MapHardwareMemory(IN PHYSICAL_ADDRESS PhysicalAddress, } /* Get PTE pointer and advance to next page */ - PtePointer = (PHARDWARE_PTE)MM::Paging::GetPteAddress(ReturnAddress); + PtePointer = MM::Paging::GetPteAddress(ReturnAddress); ReturnAddress = (PVOID)((ULONG_PTR)ReturnAddress + MM_PAGE_SIZE); /* Check if PTE is valid */ @@ -219,7 +219,7 @@ MM::HardwarePool::MapHardwareMemory(IN PHYSICAL_ADDRESS PhysicalAddress, while(MappedPages--) { /* Get PTE pointer */ - PtePointer = (PHARDWARE_PTE)MM::Paging::GetPteAddress(BaseAddress); + PtePointer = MM::Paging::GetPteAddress(BaseAddress); /* Fill the PTE */ MM::Paging::SetPte(PtePointer, (PFN_NUMBER)(PhysicalAddress.QuadPart >> MM_PAGE_SHIFT), TRUE); @@ -259,18 +259,18 @@ VOID MM::HardwarePool::MarkHardwareMemoryWriteThrough(IN PVOID VirtualAddress, IN PFN_NUMBER PageCount) { - PHARDWARE_PTE PtePointer; + PMMPTE PtePointer; PFN_NUMBER Page; /* Get PTE address from virtual address */ - PtePointer = (PHARDWARE_PTE)MM::Paging::GetPteAddress(VirtualAddress); + PtePointer = MM::Paging::GetPteAddress(VirtualAddress); /* Iterate through mapped pages */ for(Page = 0; Page < PageCount; Page++) { /* Mark pages as CD/WT */ MM::Paging::SetPteCaching(PtePointer, TRUE, TRUE); - PtePointer++; + MM::Paging::GetNextEntry(PtePointer); } } @@ -296,10 +296,10 @@ MM::HardwarePool::RemapHardwareMemory(IN PVOID VirtualAddress, IN PHYSICAL_ADDRESS PhysicalAddress, IN BOOLEAN FlushTlb) { - PHARDWARE_PTE PtePointer; + PMMPTE PtePointer; /* Get PTE address from virtual address */ - PtePointer = (PHARDWARE_PTE)MM::Paging::GetPteAddress(VirtualAddress); + PtePointer = MM::Paging::GetPteAddress(VirtualAddress); /* Remap the PTE */ MM::Paging::SetPte(PtePointer, (PFN_NUMBER)(PhysicalAddress.QuadPart >> MM_PAGE_SHIFT), TRUE); @@ -334,7 +334,7 @@ MM::HardwarePool::UnmapHardwareMemory(IN PVOID VirtualAddress, IN PFN_NUMBER PageCount, IN BOOLEAN FlushTlb) { - PHARDWARE_PTE PtePointer; + PMMPTE PtePointer; PFN_NUMBER Page; /* Check if address is valid hardware memory */ @@ -348,7 +348,7 @@ MM::HardwarePool::UnmapHardwareMemory(IN PVOID VirtualAddress, VirtualAddress = (PVOID)((ULONG_PTR)VirtualAddress & ~(MM_PAGE_SIZE - 1)); /* Get PTE address from virtual address */ - PtePointer = (PHARDWARE_PTE)MM::Paging::GetPteAddress(VirtualAddress); + PtePointer = MM::Paging::GetPteAddress(VirtualAddress); /* Iterate through mapped pages */ for(Page = 0; Page < PageCount; Page++) diff --git a/xtoskrnl/mm/i686/pagemap.cc b/xtoskrnl/mm/i686/pagemap.cc index 81d5f10..d30fa68 100644 --- a/xtoskrnl/mm/i686/pagemap.cc +++ b/xtoskrnl/mm/i686/pagemap.cc @@ -21,7 +21,7 @@ */ XTAPI VOID -MM::PageMap::ClearPte(IN PHARDWARE_PTE PtePointer) +MM::PageMap::ClearPte(IN PMMPTE PtePointer) { /* Clear PTE */ PtePointer->Long = 0; @@ -339,10 +339,10 @@ MM::PageMapBasic::InitializePageMapInfo(VOID) */ XTAPI BOOLEAN -MM::PageMapBasic::PteValid(IN PHARDWARE_PTE PtePointer) +MM::PageMapBasic::PteValid(IN PMMPTE PtePointer) { /* Check if PTE is valid */ - return (BOOLEAN)PtePointer->Pml2.Valid; + return (BOOLEAN)PtePointer->Pml2.Hardware.Valid; } /** @@ -407,14 +407,14 @@ MM::PageMapBasic::SetOneEntry(IN PMMPTE Pte, */ XTAPI VOID -MM::PageMapBasic::SetPte(IN PHARDWARE_PTE PtePointer, +MM::PageMapBasic::SetPte(IN PMMPTE PtePointer, IN PFN_NUMBER PageFrameNumber, IN BOOLEAN Writable) { /* Set PTE */ - PtePointer->Pml2.PageFrameNumber = PageFrameNumber; - PtePointer->Pml2.Valid = 1; - PtePointer->Pml2.Writable = Writable; + PtePointer->Pml2.Hardware.PageFrameNumber = PageFrameNumber; + PtePointer->Pml2.Hardware.Valid = 1; + PtePointer->Pml2.Hardware.Writable = Writable; } /** @@ -435,13 +435,13 @@ MM::PageMapBasic::SetPte(IN PHARDWARE_PTE PtePointer, */ XTAPI VOID -MM::PageMapBasic::SetPteCaching(IN PHARDWARE_PTE PtePointer, +MM::PageMapBasic::SetPteCaching(IN PMMPTE PtePointer, IN BOOLEAN CacheDisable, IN BOOLEAN WriteThrough) { /* Set caching attributes */ - PtePointer->Pml2.CacheDisable = CacheDisable; - PtePointer->Pml2.WriteThrough = WriteThrough; + PtePointer->Pml2.Hardware.CacheDisable = CacheDisable; + PtePointer->Pml2.Hardware.WriteThrough = WriteThrough; } /** @@ -573,9 +573,9 @@ MM::PageMapXpa::InitializePageMapInfo(VOID) */ XTAPI BOOLEAN -MM::PageMapXpa::PteValid(IN PHARDWARE_PTE PtePointer) +MM::PageMapXpa::PteValid(IN PMMPTE PtePointer) { - return (BOOLEAN)PtePointer->Pml3.Valid; + return (BOOLEAN)PtePointer->Pml3.Hardware.Valid; } /** @@ -640,14 +640,14 @@ MM::PageMapXpa::SetOneEntry(IN PMMPTE Pte, */ XTAPI VOID -MM::PageMapXpa::SetPte(IN PHARDWARE_PTE PtePointer, +MM::PageMapXpa::SetPte(IN PMMPTE PtePointer, IN PFN_NUMBER PageFrameNumber, IN BOOLEAN Writable) { /* Set PTE */ - PtePointer->Pml3.PageFrameNumber = PageFrameNumber; - PtePointer->Pml3.Valid = 1; - PtePointer->Pml3.Writable = Writable; + PtePointer->Pml3.Hardware.PageFrameNumber = PageFrameNumber; + PtePointer->Pml3.Hardware.Valid = 1; + PtePointer->Pml3.Hardware.Writable = Writable; } /** @@ -668,11 +668,11 @@ MM::PageMapXpa::SetPte(IN PHARDWARE_PTE PtePointer, */ XTAPI VOID -MM::PageMapXpa::SetPteCaching(IN PHARDWARE_PTE PtePointer, +MM::PageMapXpa::SetPteCaching(IN PMMPTE PtePointer, IN BOOLEAN CacheDisable, IN BOOLEAN WriteThrough) { /* Set caching attributes */ - PtePointer->Pml3.CacheDisable = CacheDisable; - PtePointer->Pml3.WriteThrough = WriteThrough; + PtePointer->Pml3.Hardware.CacheDisable = CacheDisable; + PtePointer->Pml3.Hardware.WriteThrough = WriteThrough; } diff --git a/xtoskrnl/mm/paging.cc b/xtoskrnl/mm/paging.cc index 9bd9a2d..41f060b 100644 --- a/xtoskrnl/mm/paging.cc +++ b/xtoskrnl/mm/paging.cc @@ -43,7 +43,7 @@ MM::Paging::AdvancePte(IN PMMPTE Pte, */ XTAPI VOID -MM::Paging::ClearPte(IN PHARDWARE_PTE PtePointer) +MM::Paging::ClearPte(IN PMMPTE PtePointer) { /* Clear PTE */ PmlRoutines->ClearPte(PtePointer); @@ -312,7 +312,7 @@ MM::Paging::InitializePageMapSupport(VOID) */ XTAPI BOOLEAN -MM::Paging::PteValid(IN PHARDWARE_PTE PtePointer) +MM::Paging::PteValid(IN PMMPTE PtePointer) { /* Check if PTE is valid */ return PmlRoutines->PteValid(PtePointer); @@ -380,7 +380,7 @@ MM::Paging::SetOneEntry(IN PMMPTE Pte, */ XTAPI VOID -MM::Paging::SetPte(IN PHARDWARE_PTE PtePointer, +MM::Paging::SetPte(IN PMMPTE PtePointer, IN PFN_NUMBER PageFrameNumber, IN BOOLEAN Writable) { @@ -406,7 +406,7 @@ MM::Paging::SetPte(IN PHARDWARE_PTE PtePointer, */ XTAPI VOID -MM::Paging::SetPteCaching(IN PHARDWARE_PTE PtePointer, +MM::Paging::SetPteCaching(IN PMMPTE PtePointer, IN BOOLEAN CacheDisable, IN BOOLEAN WriteThrough) { -- 2.52.0 From dda8f88830965c8f099fb5a4d7cbb1ce9d3f6225 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Tue, 4 Nov 2025 17:26:47 +0100 Subject: [PATCH 008/166] Add PTE attribute definitions --- sdk/xtdk/amd64/mmtypes.h | 34 ++++++++++++++++++++++++++++++++++ sdk/xtdk/i686/mmtypes.h | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+) diff --git a/sdk/xtdk/amd64/mmtypes.h b/sdk/xtdk/amd64/mmtypes.h index 367f7b6..b92236b 100644 --- a/sdk/xtdk/amd64/mmtypes.h +++ b/sdk/xtdk/amd64/mmtypes.h @@ -45,6 +45,40 @@ #define MM_PPE_PER_PAGE 512 #define MM_PXE_PER_PAGE 512 +/* PTE state flags */ +#define MM_PTE_VALID 0x0000000000000001ULL +#define MM_PTE_ACCESSED 0x0000000000000020ULL +#define MM_PTE_DIRTY 0x0000000000000040ULL + +/* PTE scope flags */ +#define MM_PTE_LARGE_PAGE 0x0000000000000080ULL +#define MM_PTE_GLOBAL 0x0000000000000100ULL + +/* PTE access flags */ +#define MM_PTE_NOACCESS 0x0000000000000000ULL +#define MM_PTE_READONLY 0x0000000000000000ULL +#define MM_PTE_EXECUTE 0x0000000000000000ULL +#define MM_PTE_EXECUTE_READ 0x0000000000000000ULL +#define MM_PTE_READWRITE 0x8000000000000002ULL +#define MM_PTE_WRITECOPY 0x8000000000000200ULL +#define MM_PTE_EXECUTE_READWRITE 0x0000000000000002ULL +#define MM_PTE_EXECUTE_WRITECOPY 0x0000000000000200ULL + +/* PTE protection flags */ +#define MM_PTE_NOEXECUTE 0x8000000000000000ULL +#define MM_PTE_PROTECT 0x8000000000000612ULL + +/* PTE cache flags */ +#define MM_PTE_CACHE_ENABLE 0x0000000000000000ULL +#define MM_PTE_CACHE_DISABLE 0x0000000000000010ULL +#define MM_PTE_CACHE_WRITECOMBINED 0x0000000000000010ULL +#define MM_PTE_CACHE_WRITETHROUGH 0x0000000000000008ULL + +/* PTE software flags */ +#define MM_PTE_COPY_ON_WRITE 0x0000000000000200ULL +#define MM_PTE_PROTOTYPE 0x0000000000000400ULL +#define MM_PTE_TRANSITION 0x0000000000000800ULL + /* Minimum number of physical pages needed by the system */ #define MM_MINIMUM_PHYSICAL_PAGES 2048 diff --git a/sdk/xtdk/i686/mmtypes.h b/sdk/xtdk/i686/mmtypes.h index 98fced0..b90b5b2 100644 --- a/sdk/xtdk/i686/mmtypes.h +++ b/sdk/xtdk/i686/mmtypes.h @@ -35,6 +35,40 @@ #define MM_PTE_LEGACY_SHIFT 2 #define MM_PDI_LEGACY_SHIFT 22 +/* PTE state flags */ +#define MM_PTE_VALID 0x00000001 +#define MM_PTE_ACCESSED 0x00000020 +#define MM_PTE_DIRTY 0x00000040 + +/* PTE scope flags */ +#define MM_PTE_LARGE_PAGE 0x00000080 +#define MM_PTE_GLOBAL 0x00000100 + +/* PTE access flags */ +#define MM_PTE_NOACCESS 0x00000000 +#define MM_PTE_READONLY 0x00000000 +#define MM_PTE_EXECUTE 0x00000000 +#define MM_PTE_EXECUTE_READ 0x00000000 +#define MM_PTE_READWRITE 0x00000002 +#define MM_PTE_WRITECOPY 0x00000200 +#define MM_PTE_EXECUTE_READWRITE 0x00000002 +#define MM_PTE_EXECUTE_WRITECOPY 0x00000200 + +/* PTE protection flags */ +#define MM_PTE_NOEXECUTE 0x00000000 +#define MM_PTE_PROTECT 0x00000612 + +/* PTE cache flags */ +#define MM_PTE_CACHE_ENABLE 0x00000000 +#define MM_PTE_CACHE_DISABLE 0x00000010 +#define MM_PTE_CACHE_WRITECOMBINED 0x00000010 +#define MM_PTE_CACHE_WRITETHROUGH 0x00000008 + +/* PTE software flags */ +#define MM_PTE_COPY_ON_WRITE 0x00000200 +#define MM_PTE_PROTOTYPE 0x00000400 +#define MM_PTE_TRANSITION 0x00000800 + /* Minimum number of physical pages needed by the system */ #define MM_MINIMUM_PHYSICAL_PAGES 1100 -- 2.52.0 From 071c840ca853e3216ae7024d4e9b5ab94c00210c Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Tue, 4 Nov 2025 17:34:49 +0100 Subject: [PATCH 009/166] Replace writable flag with AttributesMask in PTE setup --- xtoskrnl/includes/mm/amd64/pagemap.hh | 2 +- xtoskrnl/includes/mm/i686/pagemap.hh | 6 +++--- xtoskrnl/includes/mm/paging.hh | 2 +- xtoskrnl/mm/amd64/pagemap.cc | 8 ++++---- xtoskrnl/mm/hlpool.cc | 4 ++-- xtoskrnl/mm/i686/pagemap.cc | 16 ++++++++-------- xtoskrnl/mm/paging.cc | 8 ++++---- 7 files changed, 23 insertions(+), 23 deletions(-) diff --git a/xtoskrnl/includes/mm/amd64/pagemap.hh b/xtoskrnl/includes/mm/amd64/pagemap.hh index 28f67c2..99f09b0 100644 --- a/xtoskrnl/includes/mm/amd64/pagemap.hh +++ b/xtoskrnl/includes/mm/amd64/pagemap.hh @@ -52,7 +52,7 @@ namespace MM IN BOOLEAN Value); XTAPI VOID SetPte(IN PMMPTE PtePointer, IN PFN_NUMBER PageFrameNumber, - IN BOOLEAN Writable); + IN ULONG_PTR AttributesMask); XTAPI VOID SetPteCaching(IN PMMPTE PtePointer, IN BOOLEAN CacheDisable, IN BOOLEAN WriteThrough); diff --git a/xtoskrnl/includes/mm/i686/pagemap.hh b/xtoskrnl/includes/mm/i686/pagemap.hh index df5bb91..9868836 100644 --- a/xtoskrnl/includes/mm/i686/pagemap.hh +++ b/xtoskrnl/includes/mm/i686/pagemap.hh @@ -46,7 +46,7 @@ namespace MM IN BOOLEAN Value) = 0; VIRTUAL XTAPI VOID SetPte(IN PMMPTE PtePointer, IN PFN_NUMBER PageFrameNumber, - IN BOOLEAN Writable) = 0; + IN ULONG_PTR AttributesMask) = 0; VIRTUAL XTAPI VOID SetPteCaching(IN PMMPTE PtePointer, IN BOOLEAN CacheDisable, IN BOOLEAN WriteThrough) = 0; @@ -69,7 +69,7 @@ namespace MM IN BOOLEAN Value); XTAPI VOID SetPte(IN PMMPTE PtePointer, IN PFN_NUMBER PageFrameNumber, - IN BOOLEAN Writable); + IN ULONG_PTR AttributesMask); XTAPI VOID SetPteCaching(IN PMMPTE PtePointer, IN BOOLEAN CacheDisable, IN BOOLEAN WriteThrough); @@ -92,7 +92,7 @@ namespace MM IN BOOLEAN Value); XTAPI VOID SetPte(IN PMMPTE PtePointer, IN PFN_NUMBER PageFrameNumber, - IN BOOLEAN Writable); + IN ULONG_PTR AttributesMask); XTAPI VOID SetPteCaching(IN PMMPTE PtePointer, IN BOOLEAN CacheDisable, IN BOOLEAN WriteThrough); diff --git a/xtoskrnl/includes/mm/paging.hh b/xtoskrnl/includes/mm/paging.hh index 76adf99..304fa99 100644 --- a/xtoskrnl/includes/mm/paging.hh +++ b/xtoskrnl/includes/mm/paging.hh @@ -41,7 +41,7 @@ namespace MM IN BOOLEAN Value); STATIC XTAPI VOID SetPte(IN PMMPTE PtePointer, IN PFN_NUMBER PageFrameNumber, - IN BOOLEAN Writable); + IN ULONG_PTR AttributesMask); STATIC XTAPI VOID SetPteCaching(IN PMMPTE PtePointer, IN BOOLEAN CacheDisable, IN BOOLEAN WriteThrough); diff --git a/xtoskrnl/mm/amd64/pagemap.cc b/xtoskrnl/mm/amd64/pagemap.cc index be54c3f..f7774f3 100644 --- a/xtoskrnl/mm/amd64/pagemap.cc +++ b/xtoskrnl/mm/amd64/pagemap.cc @@ -487,8 +487,8 @@ MM::PageMap::SetOneEntry(IN PMMPTE Pte, * @param PageFrameNumber * Physical frame number to map. * - * @param Writable - * Indicates whether the page should be writable. + * @param AttributesMask + * Specifies the attributes mask to apply to the PTE. * * @return This routine does not return any value. * @@ -498,12 +498,12 @@ XTAPI VOID MM::PageMap::SetPte(IN PMMPTE PtePointer, IN PFN_NUMBER PageFrameNumber, - IN BOOLEAN Writable) + IN ULONG_PTR AttributesMask) { /* Set PTE */ PtePointer->Hardware.PageFrameNumber = PageFrameNumber; PtePointer->Hardware.Valid = 1; - PtePointer->Hardware.Writable = Writable; + PtePointer->Long |= AttributesMask; } /** diff --git a/xtoskrnl/mm/hlpool.cc b/xtoskrnl/mm/hlpool.cc index 9c1d612..2504f8b 100644 --- a/xtoskrnl/mm/hlpool.cc +++ b/xtoskrnl/mm/hlpool.cc @@ -222,7 +222,7 @@ MM::HardwarePool::MapHardwareMemory(IN PHYSICAL_ADDRESS PhysicalAddress, PtePointer = MM::Paging::GetPteAddress(BaseAddress); /* Fill the PTE */ - MM::Paging::SetPte(PtePointer, (PFN_NUMBER)(PhysicalAddress.QuadPart >> MM_PAGE_SHIFT), TRUE); + MM::Paging::SetPte(PtePointer, (PFN_NUMBER)(PhysicalAddress.QuadPart >> MM_PAGE_SHIFT), MM_PTE_READWRITE); /* Advance to the next address */ PhysicalAddress.QuadPart += MM_PAGE_SIZE; @@ -302,7 +302,7 @@ MM::HardwarePool::RemapHardwareMemory(IN PVOID VirtualAddress, PtePointer = MM::Paging::GetPteAddress(VirtualAddress); /* Remap the PTE */ - MM::Paging::SetPte(PtePointer, (PFN_NUMBER)(PhysicalAddress.QuadPart >> MM_PAGE_SHIFT), TRUE); + MM::Paging::SetPte(PtePointer, (PFN_NUMBER)(PhysicalAddress.QuadPart >> MM_PAGE_SHIFT), MM_PTE_READWRITE); /* Check if TLB needs to be flushed */ if(FlushTlb) diff --git a/xtoskrnl/mm/i686/pagemap.cc b/xtoskrnl/mm/i686/pagemap.cc index d30fa68..67bf253 100644 --- a/xtoskrnl/mm/i686/pagemap.cc +++ b/xtoskrnl/mm/i686/pagemap.cc @@ -398,8 +398,8 @@ MM::PageMapBasic::SetOneEntry(IN PMMPTE Pte, * @param PageFrameNumber * Physical frame number to map. * - * @param Writable - * Indicates whether the page should be writable. + * @param AttributesMask + * Specifies the attributes mask to apply to the PTE. * * @return This routine does not return any value. * @@ -409,12 +409,12 @@ XTAPI VOID MM::PageMapBasic::SetPte(IN PMMPTE PtePointer, IN PFN_NUMBER PageFrameNumber, - IN BOOLEAN Writable) + IN ULONG_PTR AttributesMask) { /* Set PTE */ PtePointer->Pml2.Hardware.PageFrameNumber = PageFrameNumber; PtePointer->Pml2.Hardware.Valid = 1; - PtePointer->Pml2.Hardware.Writable = Writable; + PtePointer->Long |= AttributesMask; } /** @@ -631,8 +631,8 @@ MM::PageMapXpa::SetOneEntry(IN PMMPTE Pte, * @param PageFrameNumber * Physical frame number to map. * - * @param Writable - * Indicates whether the page should be writable. + * @param AttributesMask + * Specifies the attributes mask to apply to the PTE. * * @return This routine does not return any value. * @@ -642,12 +642,12 @@ XTAPI VOID MM::PageMapXpa::SetPte(IN PMMPTE PtePointer, IN PFN_NUMBER PageFrameNumber, - IN BOOLEAN Writable) + IN ULONG_PTR AttributesMask) { /* Set PTE */ PtePointer->Pml3.Hardware.PageFrameNumber = PageFrameNumber; PtePointer->Pml3.Hardware.Valid = 1; - PtePointer->Pml3.Hardware.Writable = Writable; + PtePointer->Long |= AttributesMask; } /** diff --git a/xtoskrnl/mm/paging.cc b/xtoskrnl/mm/paging.cc index 41f060b..78d3278 100644 --- a/xtoskrnl/mm/paging.cc +++ b/xtoskrnl/mm/paging.cc @@ -371,8 +371,8 @@ MM::Paging::SetOneEntry(IN PMMPTE Pte, * @param PageFrameNumber * Physical frame number to map. * - * @param Writable - * Indicates whether the page should be writable. + * @param AttributesMask + * Specifies the attributes mask to apply to the PTE. * * @return This routine does not return any value. * @@ -382,10 +382,10 @@ XTAPI VOID MM::Paging::SetPte(IN PMMPTE PtePointer, IN PFN_NUMBER PageFrameNumber, - IN BOOLEAN Writable) + IN ULONG_PTR AttributesMask) { /* Set PTE */ - PmlRoutines->SetPte(PtePointer, PageFrameNumber, (BOOLEAN)Writable); + PmlRoutines->SetPte(PtePointer, PageFrameNumber, AttributesMask); } /** -- 2.52.0 From 10b8ab347a76c2244acc7cac6240c26542aad7d0 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Tue, 4 Nov 2025 22:51:34 +0100 Subject: [PATCH 010/166] Make MM::Paging::GetExtendedPhysicalAddressingStatus public --- xtoskrnl/includes/mm/paging.hh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xtoskrnl/includes/mm/paging.hh b/xtoskrnl/includes/mm/paging.hh index 304fa99..7662dec 100644 --- a/xtoskrnl/includes/mm/paging.hh +++ b/xtoskrnl/includes/mm/paging.hh @@ -26,6 +26,7 @@ namespace MM STATIC XTAPI VOID ClearPte(IN PMMPTE PtePointer); STATIC XTAPI VOID FlushTlb(VOID); STATIC XTAPI ULONG_PTR GetEmptyPteList(VOID); + STATIC XTAPI BOOLEAN GetExtendedPhysicalAddressingStatus(VOID); STATIC XTAPI ULONG_PTR GetNextEntry(IN PMMPTE Pte); STATIC XTAPI PMMPTE GetNextPte(IN PMMPTE Pte); STATIC XTAPI BOOLEAN GetOneEntry(IN PMMPTE Pte); @@ -49,7 +50,6 @@ namespace MM IN ULONG Size); private: - STATIC XTAPI BOOLEAN GetExtendedPhysicalAddressingStatus(VOID); STATIC XTAPI PPAGEMAP GetPageMapBasicRoutines(VOID); STATIC XTAPI PPAGEMAP GetPageMapXpaRoutines(VOID); }; -- 2.52.0 From 66f27e4b9a8d736389ab7b16bf22e216c9bb1536 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Tue, 4 Nov 2025 23:03:47 +0100 Subject: [PATCH 011/166] Add GetPageFrameNumber() to PTE interfaces --- xtoskrnl/includes/mm/amd64/pagemap.hh | 1 + xtoskrnl/includes/mm/i686/pagemap.hh | 3 +++ xtoskrnl/includes/mm/paging.hh | 1 + xtoskrnl/mm/amd64/pagemap.cc | 17 ++++++++++++++ xtoskrnl/mm/i686/pagemap.cc | 34 +++++++++++++++++++++++++++ xtoskrnl/mm/paging.cc | 17 ++++++++++++++ 6 files changed, 73 insertions(+) diff --git a/xtoskrnl/includes/mm/amd64/pagemap.hh b/xtoskrnl/includes/mm/amd64/pagemap.hh index 99f09b0..14d32a7 100644 --- a/xtoskrnl/includes/mm/amd64/pagemap.hh +++ b/xtoskrnl/includes/mm/amd64/pagemap.hh @@ -31,6 +31,7 @@ namespace MM XTAPI PMMP5E GetP5eAddress(IN PVOID Address); XTAPI ULONG GetP5eIndex(IN PVOID Address); XTAPI PVOID GetP5eVirtualAddress(IN PMMP5E P5ePointer); + XTAPI PFN_NUMBER GetPageFrameNumber(IN PMMPTE Pte); XTAPI PMMPDE GetPdeAddress(IN PVOID Address); XTAPI ULONG GetPdeIndex(IN PVOID Address); XTAPI PVOID GetPdeVirtualAddress(IN PMMPDE PdePointer); diff --git a/xtoskrnl/includes/mm/i686/pagemap.hh b/xtoskrnl/includes/mm/i686/pagemap.hh index 9868836..2ae64d1 100644 --- a/xtoskrnl/includes/mm/i686/pagemap.hh +++ b/xtoskrnl/includes/mm/i686/pagemap.hh @@ -28,6 +28,7 @@ namespace MM VIRTUAL XTAPI ULONG_PTR GetNextEntry(IN PMMPTE Pte) = 0; VIRTUAL XTAPI PMMPTE GetNextPte(IN PMMPTE Pte) = 0; VIRTUAL XTAPI BOOLEAN GetOneEntry(IN PMMPTE Pte) = 0; + VIRTUAL XTAPI PFN_NUMBER GetPageFrameNumber(IN PMMPTE Pte) = 0; XTAPI PMMPDE GetPdeAddress(IN PVOID Address); XTAPI ULONG GetPdeIndex(IN PVOID Address); XTAPI PVOID GetPdeVirtualAddress(IN PMMPDE PdePointer); @@ -60,6 +61,7 @@ namespace MM XTAPI ULONG_PTR GetNextEntry(IN PMMPTE Pte); XTAPI PMMPTE GetNextPte(IN PMMPTE Pte); XTAPI BOOLEAN GetOneEntry(IN PMMPTE Pte); + XTAPI PFN_NUMBER GetPageFrameNumber(IN PMMPTE Pte); XTAPI ULONG GetPteSize(VOID); XTAPI VOID InitializePageMapInfo(VOID); XTAPI BOOLEAN PteValid(IN PMMPTE PtePointer); @@ -83,6 +85,7 @@ namespace MM XTAPI ULONG_PTR GetNextEntry(IN PMMPTE Pte); XTAPI PMMPTE GetNextPte(IN PMMPTE Pte); XTAPI BOOLEAN GetOneEntry(IN PMMPTE Pte); + XTAPI PFN_NUMBER GetPageFrameNumber(IN PMMPTE Pte); XTAPI ULONG GetPteSize(VOID); XTAPI VOID InitializePageMapInfo(VOID); XTAPI BOOLEAN PteValid(IN PMMPTE PtePointer); diff --git a/xtoskrnl/includes/mm/paging.hh b/xtoskrnl/includes/mm/paging.hh index 7662dec..17b65a6 100644 --- a/xtoskrnl/includes/mm/paging.hh +++ b/xtoskrnl/includes/mm/paging.hh @@ -30,6 +30,7 @@ namespace MM STATIC XTAPI ULONG_PTR GetNextEntry(IN PMMPTE Pte); STATIC XTAPI PMMPTE GetNextPte(IN PMMPTE Pte); STATIC XTAPI BOOLEAN GetOneEntry(IN PMMPTE Pte); + STATIC XTAPI PFN_NUMBER GetPageFrameNumber(IN PMMPTE Pte); STATIC XTAPI PMMPDE GetPdeAddress(IN PVOID Address); STATIC XTAPI PMMPPE GetPpeAddress(IN PVOID Address); STATIC XTAPI PMMPTE GetPteAddress(IN PVOID Address); diff --git a/xtoskrnl/mm/amd64/pagemap.cc b/xtoskrnl/mm/amd64/pagemap.cc index f7774f3..e807467 100644 --- a/xtoskrnl/mm/amd64/pagemap.cc +++ b/xtoskrnl/mm/amd64/pagemap.cc @@ -173,6 +173,23 @@ MM::PageMap::GetP5eVirtualAddress(IN PMMP5E P5ePointer) return (PVOID)((((LONGLONG)P5ePointer << 61) >> 16) * PageMapInfo.Xpa); } +/** + * Gets the page frame number from a corresponding PTE. + * + * @param Pte + * The PTE pointer to get the page frame number from. + * + * @return This routine returns the page frame number. + * + * @since XT 1.0 + */ +XTAPI +PFN_NUMBER +MM::PageMap::GetPageFrameNumber(IN PMMPTE Pte) +{ + return Pte->Hardware.PageFrameNumber; +} + /** * Gets the address of the PDE (Page Directory Entry), that maps given address. * diff --git a/xtoskrnl/mm/i686/pagemap.cc b/xtoskrnl/mm/i686/pagemap.cc index 67bf253..278351a 100644 --- a/xtoskrnl/mm/i686/pagemap.cc +++ b/xtoskrnl/mm/i686/pagemap.cc @@ -286,6 +286,23 @@ MM::PageMapBasic::GetOneEntry(IN PMMPTE Pte) return Pte->Pml2.List.OneEntry; } +/** + * Gets the page frame number from a corresponding PTE. + * + * @param Pte + * The PTE pointer to get the page frame number from. + * + * @return This routine returns the page frame number. + * + * @since XT 1.0 + */ +XTAPI +PFN_NUMBER +MM::PageMapBasic::GetPageFrameNumber(IN PMMPTE Pte) +{ + return Pte->Pml2.Hardware.PageFrameNumber; +} + /** * Gets the size of a PTE for basic paging (PML2). * @@ -520,6 +537,23 @@ MM::PageMapXpa::GetOneEntry(IN PMMPTE Pte) return Pte->Pml3.List.OneEntry; } +/** + * Gets the page frame number from a corresponding PTE. + * + * @param Pte + * The PTE pointer to get the page frame number from. + * + * @return This routine returns the page frame number. + * + * @since XT 1.0 + */ +XTAPI +PFN_NUMBER +MM::PageMapBasic::GetPageFrameNumber(IN PMMPTE Pte) +{ + return Pte->Pml3.Hardware.PageFrameNumber; +} + /** * Gets the size of a PTE for XPA paging (PML3). * diff --git a/xtoskrnl/mm/paging.cc b/xtoskrnl/mm/paging.cc index 78d3278..c85744e 100644 --- a/xtoskrnl/mm/paging.cc +++ b/xtoskrnl/mm/paging.cc @@ -170,6 +170,23 @@ MM::Paging::GetOneEntry(IN PMMPTE Pte) return PmlRoutines->GetOneEntry(Pte); } +/** + * Gets the page frame number from a corresponding PTE. + * + * @param Pte + * The PTE pointer to get the page frame number from. + * + * @return This routine returns the page frame number. + * + * @since XT 1.0 + */ +XTAPI +PFN_NUMBER +MM::Paging::GetPageFrameNumber(IN PMMPTE Pte) +{ + return PmlRoutines->GetPageFrameNumber(Pte); +} + /** * Gets the page map routines for basic paging mode (non-XPA). * -- 2.52.0 From 0cf178a648196a33a61b5fc73ea2034d3272fc6d Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Tue, 4 Nov 2025 23:10:02 +0100 Subject: [PATCH 012/166] Fix class name --- xtoskrnl/mm/i686/pagemap.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xtoskrnl/mm/i686/pagemap.cc b/xtoskrnl/mm/i686/pagemap.cc index 278351a..f4b6b3b 100644 --- a/xtoskrnl/mm/i686/pagemap.cc +++ b/xtoskrnl/mm/i686/pagemap.cc @@ -549,7 +549,7 @@ MM::PageMapXpa::GetOneEntry(IN PMMPTE Pte) */ XTAPI PFN_NUMBER -MM::PageMapBasic::GetPageFrameNumber(IN PMMPTE Pte) +MM::PageMapXpa::GetPageFrameNumber(IN PMMPTE Pte) { return Pte->Pml3.Hardware.PageFrameNumber; } -- 2.52.0 From 7b11a8feb11cb253a860472b4da845eb30fde3a1 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Thu, 6 Nov 2025 06:55:31 +0100 Subject: [PATCH 013/166] Add page list and PTE pool type enums --- sdk/xtdk/mmtypes.h | 30 ++++++++++++++++++++++++++++++ sdk/xtdk/xtstruct.h | 3 +++ 2 files changed, 33 insertions(+) diff --git a/sdk/xtdk/mmtypes.h b/sdk/xtdk/mmtypes.h index 2cddd97..010b33a 100644 --- a/sdk/xtdk/mmtypes.h +++ b/sdk/xtdk/mmtypes.h @@ -13,6 +13,27 @@ #include ARCH_HEADER(xtstruct.h) +/* Memory manager page lists */ +typedef enum _MMPAGELISTS +{ + ZeroedPageList = 0, + FreePageList = 1, + StandbyPageList = 2, + ModifiedPageList = 3, + ModifiedNoWritePageList = 4, + BadPageList = 5, + ActiveAndValid = 6, + TransitionPage = 7 +} MMPAGELISTS, *PMMPAGELISTS; + +/* Page table pool types */ +typedef enum _MMSYSTEM_PTE_POOL_TYPE +{ + SystemPteSpace, + NonPagedPoolExpansion, + MaximumPtePoolTypes +} MMSYSTEM_PTE_POOL_TYPE, *PMMSYSTEM_PTE_POOL_TYPE; + /* Page map routines structure definition */ typedef CONST STRUCT _CMMPAGEMAP_ROUTINES { @@ -45,4 +66,13 @@ typedef struct _MMPFNENTRY USHORT ParityError:1; } MMPFNENTRY, *PMMPFNENTRY; +/* Page Frame List structure definition */ +typedef struct _MMPFNLIST +{ + PFN_NUMBER Total; + MMPAGELISTS ListName; + PFN_NUMBER Flink; + PFN_NUMBER Blink; +} MMPFNLIST, *PMMPFNLIST; + #endif /* __XTDK_MMTYPES_H */ diff --git a/sdk/xtdk/xtstruct.h b/sdk/xtdk/xtstruct.h index 62fa2f8..64442b4 100644 --- a/sdk/xtdk/xtstruct.h +++ b/sdk/xtdk/xtstruct.h @@ -48,6 +48,8 @@ typedef enum _KTHREAD_STATE KTHREAD_STATE, *PKTHREAD_STATE; typedef enum _KTIMER_TYPE KTIMER_TYPE, *PKTIMER_TYPE; typedef enum _KUBSAN_DATA_TYPE KUBSAN_DATA_TYPE, *PKUBSAN_DATA_TYPE; typedef enum _LOADER_MEMORY_TYPE LOADER_MEMORY_TYPE, *PLOADER_MEMORY_TYPE; +typedef enum _MMPAGELISTS MMPAGELISTS, *PMMPAGELISTS; +typedef enum _MMSYSTEM_PTE_POOL_TYPE MMSYSTEM_PTE_POOL_TYPE, *PMMSYSTEM_PTE_POOL_TYPE; typedef enum _MODE MODE, *PMODE; typedef enum _RTL_VARIABLE_TYPE RTL_VARIABLE_TYPE, *PRTL_VARIABLE_TYPE; typedef enum _SYSTEM_FIRMWARE_TYPE SYSTEM_FIRMWARE_TYPE, *PSYSTEM_FIRMWARE_TYPE; @@ -275,6 +277,7 @@ typedef struct _LOADER_MEMORY_DESCRIPTOR LOADER_MEMORY_DESCRIPTOR, *PLOADER_MEMO typedef struct _M128 M128, *PM128; typedef struct _MMCOLOR_TABLES MMCOLOR_TABLES, *PMMCOLOR_TABLES; typedef struct _MMPFNENTRY MMPFNENTRY, *PMMPFNENTRY; +typedef struct _MMPFNLIST MMPFNLIST, *PMMPFNLIST; typedef struct _PCAT_FIRMWARE_INFORMATION PCAT_FIRMWARE_INFORMATION, *PPCAT_FIRMWARE_INFORMATION; typedef struct _PCI_BRIDGE_CONTROL_REGISTER PCI_BRIDGE_CONTROL_REGISTER, *PPCI_BRIDGE_CONTROL_REGISTER; typedef struct _PCI_COMMON_CONFIG PCI_COMMON_CONFIG, *PPCI_COMMON_CONFIG; -- 2.52.0 From 35523a230a5227c41072375019102edf855718b4 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Mon, 17 Nov 2025 23:15:22 +0100 Subject: [PATCH 014/166] Prevent duplicate object generation by linking xtoskrnl with libxtos --- xtoskrnl/CMakeLists.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/xtoskrnl/CMakeLists.txt b/xtoskrnl/CMakeLists.txt index 07f9468..72e7bb8 100644 --- a/xtoskrnl/CMakeLists.txt +++ b/xtoskrnl/CMakeLists.txt @@ -82,11 +82,12 @@ add_library(libxtos ${XTOSKRNL_SOURCE}) # Link kernel executable add_executable(xtoskrnl - ${XTOSKRNL_SOURCE} ${CMAKE_CURRENT_BINARY_DIR}/xtoskrnl.def) # Add linker libraries -target_link_libraries(xtoskrnl) +target_link_libraries(xtoskrnl + PRIVATE + libxtos) # Set proper binary name and install target set_target_properties(xtoskrnl PROPERTIES SUFFIX .exe) -- 2.52.0 From 20b0bfdfada799838cd1e9343d3e3b6a0d969c97 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Mon, 17 Nov 2025 23:19:16 +0100 Subject: [PATCH 015/166] Add kernel parameters section and fix minor formatting issues --- xtoskrnl/README.md | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/xtoskrnl/README.md b/xtoskrnl/README.md index 9112f64..e9600bf 100644 --- a/xtoskrnl/README.md +++ b/xtoskrnl/README.md @@ -4,6 +4,18 @@ within the XTOS kernel space. It is responsible for various core services, such management, and process scheduling. The kernel contains the scheduler (sometimes referred to as the Dispatcher), the cache, object, and memory managers, the security manager, and other executive components described below. + +## Kernel Parameters +Kernel parameters are XTOS boot-time options used to ensure proper initialization and handling of hardware peripherals. +These parameters can be configured either temporarily by editing the boot entry in the bootloader’s selection menu, or +permanently by modifying the XTLDR configuration file. + +The following is a consolidated list of available kernel parameters: + * **NOXPA**: Disables PAE or LA57 support, depending on the CPU architecture. This parameter is handled by the + bootloader, which configures paging and selects the appropriate Page Map Level (PML) before transferring control to + the kernel. + +## Source Code The source code of the kernel is organized into subsystem-specific directories. Each directory name also defines the corresponding C++ namespace in which the subsystem's classes and routines reside. These subsystems include: @@ -68,8 +80,8 @@ routine: For all C++ code inside the kernel the naming model has evolved. Consider the **KE::KThread::InitializeThread()** routine: * **KE** - The namespace replaces the prefix and indicates the subsystem. Namespaces are written in uppercase and no - longer use the trailing p for private routines, because classes use C++ visibility to control access. + longer use the trailing p for private routines, because classes use C++ visibility to control access. * **KThread** - Within each namespace, related functionality is grouped into classes, which encapsulate variables and - methods. + methods. * **InitializeThread** - Method names follow the `` pattern. \ No newline at end of file -- 2.52.0 From 0097cb88d75a01feff6d327183b958afbef68743 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Sat, 29 Nov 2025 23:11:54 +0100 Subject: [PATCH 016/166] Correct LA57 paging base addresses, add self-map constants and extend PTE structures --- sdk/xtdk/amd64/mmtypes.h | 26 ++++++++++++++++++-------- sdk/xtdk/i686/mmtypes.h | 6 ++++++ 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/sdk/xtdk/amd64/mmtypes.h b/sdk/xtdk/amd64/mmtypes.h index b92236b..c6211c7 100644 --- a/sdk/xtdk/amd64/mmtypes.h +++ b/sdk/xtdk/amd64/mmtypes.h @@ -25,11 +25,15 @@ #define MM_PXE_BASE 0xFFFFF6FB7DBED000ULL /* Page directory and page base addresses for 5-level paging */ -#define MM_PTE_LA57_BASE 0xFFFF000000000000ULL -#define MM_PDE_LA57_BASE 0xFFFF010000000000ULL -#define MM_PPE_LA57_BASE 0xFFFF010800000000ULL -#define MM_PXE_LA57_BASE 0xFFFF010840000000ULL -#define MM_P5E_LA57_BASE 0xFFFF010840200000ULL +#define MM_PTE_LA57_BASE 0xFFED000000000000ULL +#define MM_PDE_LA57_BASE 0xFFEDF68000000000ULL +#define MM_PPE_LA57_BASE 0xFFEDF6FB40000000ULL +#define MM_PXE_LA57_BASE 0xFFEDF6FB7DA00000ULL +#define MM_P5E_LA57_BASE 0xFFEDF6FB7DBED000ULL + +/* Self map address */ +#define MM_PML4_SELF_MAP_ADDRESS 0xFFFFF6FB7DBEDF68ULL +#define MM_PML5_SELF_MAP_ADDRESS 0xFFEDF6FB7DBEDF68ULL /* PTE shift values */ #define MM_PTE_SHIFT 3 @@ -79,6 +83,12 @@ #define MM_PTE_PROTOTYPE 0x0000000000000400ULL #define MM_PTE_TRANSITION 0x0000000000000800ULL +/* PTE protection bits */ +#define MM_PTE_PROTECTION_BITS 5 + +/* Base address of the system page table */ +#define MM_SYSTEM_PTE_BASE KSEG0_BASE + /* Minimum number of physical pages needed by the system */ #define MM_MINIMUM_PHYSICAL_PAGES 2048 @@ -287,6 +297,7 @@ typedef struct _MMPFN USHORT ReferenceCount; } e2; } u3; + ULONG UsedPageTableEntries; union { MMPTE OriginalPte; @@ -297,12 +308,11 @@ typedef struct _MMPFN ULONG_PTR EntireFrame; struct { - ULONG_PTR PteFrame:58; + ULONG_PTR PteFrame:57; ULONG_PTR InPageError:1; ULONG_PTR VerifierAllocation:1; ULONG_PTR AweAllocation:1; - ULONG_PTR LockCharged:1; - ULONG_PTR KernelStack:1; + ULONG_PTR Priority:3; ULONG_PTR MustBeCached:1; }; } u4; diff --git a/sdk/xtdk/i686/mmtypes.h b/sdk/xtdk/i686/mmtypes.h index b90b5b2..2f549ff 100644 --- a/sdk/xtdk/i686/mmtypes.h +++ b/sdk/xtdk/i686/mmtypes.h @@ -69,6 +69,12 @@ #define MM_PTE_PROTOTYPE 0x00000400 #define MM_PTE_TRANSITION 0x00000800 +/* PTE protection bits */ +#define MM_PTE_PROTECTION_BITS 5 + +/* Base address of the system page table */ +#define MM_SYSTEM_PTE_BASE NULLPTR + /* Minimum number of physical pages needed by the system */ #define MM_MINIMUM_PHYSICAL_PAGES 1100 -- 2.52.0 From c099882866271f2e6b52c1fe3ce1fff6e2af93a2 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Sat, 29 Nov 2025 23:14:30 +0100 Subject: [PATCH 017/166] Add PFN_COUNT typedef --- sdk/xtdk/xtbase.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sdk/xtdk/xtbase.h b/sdk/xtdk/xtbase.h index eb6790d..96282c7 100644 --- a/sdk/xtdk/xtbase.h +++ b/sdk/xtdk/xtbase.h @@ -29,6 +29,9 @@ typedef UCHAR KRUNLEVEL, *PKRUNLEVEL; /* Spin locks synchronization mechanism */ typedef ULONG_PTR KSPIN_LOCK, *PKSPIN_LOCK; +/* Page Frame Number count */ +typedef ULONG PFN_COUNT; + /* Page Frame Number */ typedef ULONG_PTR PFN_NUMBER, *PPFN_NUMBER; -- 2.52.0 From 931586eebd812620d0b6e41f34314633f2ae72dc Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Sat, 29 Nov 2025 23:37:08 +0100 Subject: [PATCH 018/166] Refactor PageMap to enable architecture-specific VA translation --- xtoskrnl/includes/mm/amd64/pagemap.hh | 27 ++-- xtoskrnl/mm/amd64/pagemap.cc | 216 ++++++++++++++++++-------- 2 files changed, 169 insertions(+), 74 deletions(-) diff --git a/xtoskrnl/includes/mm/amd64/pagemap.hh b/xtoskrnl/includes/mm/amd64/pagemap.hh index 14d32a7..fce9480 100644 --- a/xtoskrnl/includes/mm/amd64/pagemap.hh +++ b/xtoskrnl/includes/mm/amd64/pagemap.hh @@ -1,13 +1,13 @@ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory - * FILE: xtoskrnl/includes/mm/pagemap.hh + * FILE: xtoskrnl/includes/mm/amd64/pagemap.hh * DESCRIPTION: Low-level support for page map manipulation * DEVELOPERS: Aiken Harris */ -#ifndef __XTOSKRNL_MM_PAGEMAP_HH -#define __XTOSKRNL_MM_PAGEMAP_HH +#ifndef __XTOSKRNL_MM_AMD64_PAGEMAP_HH +#define __XTOSKRNL_MM_AMD64_PAGEMAP_HH #include @@ -22,7 +22,7 @@ namespace MM public: XTAPI PMMPTE AdvancePte(IN PMMPTE Pte, - IN ULONG Count); + IN LONG Count); XTAPI VOID ClearPte(IN PMMPTE PtePointer); XTAPI ULONGLONG GetEmptyPteList(VOID); XTAPI ULONG_PTR GetNextEntry(IN PMMPTE Pte); @@ -34,17 +34,18 @@ namespace MM XTAPI PFN_NUMBER GetPageFrameNumber(IN PMMPTE Pte); XTAPI PMMPDE GetPdeAddress(IN PVOID Address); XTAPI ULONG GetPdeIndex(IN PVOID Address); - XTAPI PVOID GetPdeVirtualAddress(IN PMMPDE PdePointer); + VIRTUAL XTAPI PVOID GetPdeVirtualAddress(IN PMMPDE PdePointer) = 0; XTAPI PMMPPE GetPpeAddress(IN PVOID Address); XTAPI ULONG GetPpeIndex(IN PVOID Address); - XTAPI PVOID GetPpeVirtualAddress(IN PMMPPE PpePointer); + VIRTUAL XTAPI PVOID GetPpeVirtualAddress(IN PMMPPE PpePointer) = 0; XTAPI PMMPTE GetPteAddress(IN PVOID Address); XTAPI ULONG GetPteIndex(IN PVOID Address); XTAPI ULONG GetPteSize(VOID); - XTAPI PVOID GetPteVirtualAddress(IN PMMPTE PtePointer); + VIRTUAL XTAPI PVOID GetPteVirtualAddress(IN PMMPTE PtePointer) = 0; XTAPI PMMPXE GetPxeAddress(IN PVOID Address); XTAPI ULONG GetPxeIndex(IN PVOID Address); - XTAPI PVOID GetPxeVirtualAddress(IN PMMPXE PxePointer); + VIRTUAL XTAPI PVOID GetPxeVirtualAddress(IN PMMPXE PxePointer) = 0; + XTAPI BOOLEAN GetXpaStatus(); VIRTUAL XTAPI VOID InitializePageMapInfo(VOID) = 0; XTAPI BOOLEAN PteValid(IN PMMPTE PtePointer); XTAPI VOID SetNextEntry(IN PMMPTE Pte, @@ -62,14 +63,22 @@ namespace MM class PageMapBasic final : public PageMap { public: + XTAPI PVOID GetPdeVirtualAddress(IN PMMPDE PdePointer); + XTAPI PVOID GetPpeVirtualAddress(IN PMMPPE PpePointer); + XTAPI PVOID GetPteVirtualAddress(IN PMMPTE PtePointer); + XTAPI PVOID GetPxeVirtualAddress(IN PMMPXE PxePointer); XTAPI VOID InitializePageMapInfo(VOID); }; class PageMapXpa final : public PageMap { public: + XTAPI PVOID GetPdeVirtualAddress(IN PMMPDE PdePointer); + XTAPI PVOID GetPpeVirtualAddress(IN PMMPPE PpePointer); + XTAPI PVOID GetPteVirtualAddress(IN PMMPTE PtePointer); + XTAPI PVOID GetPxeVirtualAddress(IN PMMPXE PxePointer); XTAPI VOID InitializePageMapInfo(VOID); }; } -#endif /* __XTOSKRNL_MM_PAGEMAP_HH */ +#endif /* __XTOSKRNL_MM_AMD64_PAGEMAP_HH */ diff --git a/xtoskrnl/mm/amd64/pagemap.cc b/xtoskrnl/mm/amd64/pagemap.cc index e807467..7384835 100644 --- a/xtoskrnl/mm/amd64/pagemap.cc +++ b/xtoskrnl/mm/amd64/pagemap.cc @@ -25,7 +25,7 @@ XTAPI PMMPTE MM::PageMap::AdvancePte(IN PMMPTE Pte, - IN ULONG Count) + IN LONG Count) { /* Return advanced PTE pointer */ return (PMMPTE)((ULONG_PTR)Pte + (Count * sizeof(MMPTE))); @@ -170,7 +170,7 @@ XTAPI PVOID MM::PageMap::GetP5eVirtualAddress(IN PMMP5E P5ePointer) { - return (PVOID)((((LONGLONG)P5ePointer << 61) >> 16) * PageMapInfo.Xpa); + return (PVOID)((((LONGLONG)P5ePointer << 52) >> 7) * PageMapInfo.Xpa); } /** @@ -229,24 +229,6 @@ MM::PageMap::GetPdeIndex(IN PVOID Address) 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(IN 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. * @@ -286,24 +268,6 @@ MM::PageMap::GetPpeIndex(IN PVOID Address) 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(IN 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. * @@ -358,24 +322,6 @@ MM::PageMap::GetPteSize(VOID) 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(IN 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. * @@ -416,21 +362,17 @@ MM::PageMap::GetPxeIndex(IN PVOID Address) } /** - * Gets the virtual address that is mapped by a given Extended Page Entry. + * Gets the status of Extended Paging Address (XPA) mode. * - * @param PxePointer - * Specifies the address of the PXE. - * - * @return This routine returns the virtual address mapped by the PXE. + * @return This routine returns TRUE if XPA is enabled, FALSE otherwise. * * @since XT 1.0 */ XTAPI -PVOID -MM::PageMap::GetPxeVirtualAddress(IN PMMPXE PxePointer) +BOOLEAN +MM::PageMap::GetXpaStatus() { - /* Return PXE virtual address */ - return (PVOID)(((LONGLONG)PxePointer << 52) >> 16); + return PageMapInfo.Xpa; } /** @@ -550,6 +492,78 @@ MM::PageMap::SetPteCaching(IN PMMPTE PtePointer, PtePointer->Hardware.WriteThrough = WriteThrough; } +/** + * Gets the virtual address that is mapped by a given Page Directory Entry (PML4). + * + * @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::PageMapBasic::GetPdeVirtualAddress(IN PMMPDE PdePointer) +{ + /* Return PDE virtual address */ + return (PVOID)(((LONGLONG)PdePointer << 34) >> 16); +} + +/** + * Gets the virtual address that is mapped by a given Page Directory Pointer Table Entry (PML4). + * + * @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::PageMapBasic::GetPpeVirtualAddress(IN PMMPPE PpePointer) +{ + /* Return PPE virtual address */ + return (PVOID)(((LONGLONG)PpePointer << 43) >> 16); +} + +/** + * Gets the virtual address that is mapped by a given Page Table Entry (PML4). + * + * @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::PageMapBasic::GetPteVirtualAddress(IN PMMPTE PtePointer) +{ + /* Return PTE virtual address */ + return (PVOID)(((LONGLONG)PtePointer << 25) >> 16); +} + +/** + * Gets the virtual address that is mapped by a given Extended Page Entry (PML4). + * + * @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::PageMapBasic::GetPxeVirtualAddress(IN PMMPXE PxePointer) +{ + /* Return PXE virtual address */ + return (PVOID)(((LONGLONG)PxePointer << 52) >> 16); +} + /** * Initializes page map information for basic paging (PML4). * @@ -578,6 +592,78 @@ MM::PageMapBasic::InitializePageMapInfo(VOID) PageMapInfo.VaBits = 48; } +/** + * Gets the virtual address that is mapped by a given Page Directory Entry (PML5). + * + * @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::PageMapXpa::GetPdeVirtualAddress(IN PMMPDE PdePointer) +{ + /* Return PDE virtual address */ + return (PVOID)(((LONGLONG)PdePointer << 25) >> 7); +} + +/** + * Gets the virtual address that is mapped by a given Page Directory Pointer Table Entry (PML5). + * + * @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::PageMapXpa::GetPpeVirtualAddress(IN PMMPPE PpePointer) +{ + /* Return PPE virtual address */ + return (PVOID)(((LONGLONG)PpePointer << 34) >> 7); +} + +/** + * Gets the virtual address that is mapped by a given Page Table Entry (PML5). + * + * @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::PageMapXpa::GetPteVirtualAddress(IN PMMPTE PtePointer) +{ + /* Return PTE virtual address */ + return (PVOID)(((LONGLONG)PtePointer << 16) >> 7); +} + +/** + * Gets the virtual address that is mapped by a given Extended Page Entry (PML5). + * + * @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::PageMapXpa::GetPxeVirtualAddress(IN PMMPXE PxePointer) +{ + /* Return PXE virtual address */ + return (PVOID)(((LONGLONG)PxePointer << 43) >> 7); +} + /** * Initializes page map information for XPA paging (PML5). * -- 2.52.0 From 4265ae92d09c675a2b6c3fb449ae147843d5e0f0 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Sat, 29 Nov 2025 23:45:00 +0100 Subject: [PATCH 019/166] Add MM::PageMap::GetXpaStatus() for querying PML level --- xtoskrnl/includes/mm/i686/pagemap.hh | 1 + xtoskrnl/mm/i686/pagemap.cc | 14 ++++++++++++++ 2 files changed, 15 insertions(+) diff --git a/xtoskrnl/includes/mm/i686/pagemap.hh b/xtoskrnl/includes/mm/i686/pagemap.hh index 2ae64d1..59a4d6a 100644 --- a/xtoskrnl/includes/mm/i686/pagemap.hh +++ b/xtoskrnl/includes/mm/i686/pagemap.hh @@ -39,6 +39,7 @@ namespace MM XTAPI ULONG GetPteIndex(IN PVOID Address); VIRTUAL XTAPI ULONG GetPteSize(VOID) = 0; XTAPI PVOID GetPteVirtualAddress(IN PMMPTE PtePointer); + XTAPI BOOLEAN GetXpaStatus(); VIRTUAL XTAPI VOID InitializePageMapInfo(VOID) = 0; VIRTUAL XTAPI BOOLEAN PteValid(IN PMMPTE PtePointer) = 0; VIRTUAL XTAPI VOID SetNextEntry(IN PMMPTE Pte, diff --git a/xtoskrnl/mm/i686/pagemap.cc b/xtoskrnl/mm/i686/pagemap.cc index f4b6b3b..cb38fa4 100644 --- a/xtoskrnl/mm/i686/pagemap.cc +++ b/xtoskrnl/mm/i686/pagemap.cc @@ -210,6 +210,20 @@ MM::PageMap::GetPteVirtualAddress(IN PMMPTE PtePointer) return ((PVOID)((ULONG)(PtePointer) << 10)); } +/** + * Gets the status of Extended Paging Address (XPA) mode. + * + * @return This routine returns TRUE if XPA is enabled, FALSE otherwise. + * + * @since XT 1.0 + */ +XTAPI +BOOLEAN +MM::PageMap::GetXpaStatus() +{ + return PageMapInfo.Xpa; +} + /** * Advances a PTE pointer by a given number of entries, considering the actual PTE size for PML2. * -- 2.52.0 From d4287198b062176f95dc1d616252589eec8cdc2d Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Sun, 30 Nov 2025 18:23:51 +0100 Subject: [PATCH 020/166] Implement virtual address resolvers for all page map levels and add XPA status accessor --- xtoskrnl/includes/mm/paging.hh | 11 ++- xtoskrnl/mm/paging.cc | 142 ++++++++++++++++++++++++++++++++- 2 files changed, 151 insertions(+), 2 deletions(-) diff --git a/xtoskrnl/includes/mm/paging.hh b/xtoskrnl/includes/mm/paging.hh index 17b65a6..84e41ec 100644 --- a/xtoskrnl/includes/mm/paging.hh +++ b/xtoskrnl/includes/mm/paging.hh @@ -22,7 +22,7 @@ namespace MM public: STATIC XTAPI PMMPTE AdvancePte(IN PMMPTE Pte, - IN ULONG Count); + IN LONG Count); STATIC XTAPI VOID ClearPte(IN PMMPTE PtePointer); STATIC XTAPI VOID FlushTlb(VOID); STATIC XTAPI ULONG_PTR GetEmptyPteList(VOID); @@ -30,11 +30,20 @@ namespace MM STATIC XTAPI ULONG_PTR GetNextEntry(IN PMMPTE Pte); STATIC XTAPI PMMPTE GetNextPte(IN PMMPTE Pte); STATIC XTAPI BOOLEAN GetOneEntry(IN PMMPTE Pte); + STATIC XTAPI PMMPDE GetP5eAddress(IN PVOID Address); + STATIC XTAPI PVOID GetP5eVirtualAddress(IN PMMPTE P5ePointer); STATIC XTAPI PFN_NUMBER GetPageFrameNumber(IN PMMPTE Pte); STATIC XTAPI PMMPDE GetPdeAddress(IN PVOID Address); + STATIC XTAPI PVOID GetPdeVirtualAddress(IN PMMPXE PdePointer); STATIC XTAPI PMMPPE GetPpeAddress(IN PVOID Address); + STATIC XTAPI PVOID GetPpeVirtualAddress(IN PMMPXE PpePointer); STATIC XTAPI PMMPTE GetPteAddress(IN PVOID Address); STATIC XTAPI ULONG GetPteSize(VOID); + STATIC XTAPI PVOID GetPteVirtualAddress(IN PMMPXE PtePointer); + STATIC XTAPI PMMPXE GetPxeAddress(IN PVOID Address); + STATIC XTAPI PVOID GetPxeVirtualAddress(IN PMMPXE PxePointer); + STATIC XTAPI BOOLEAN GetXpaStatus(); + STATIC XTAPI VOID InitializeSystemSpaceMapping(VOID); STATIC XTAPI VOID InitializePageMapSupport(VOID); STATIC XTAPI BOOLEAN PteValid(IN PMMPTE PtePointer); STATIC XTAPI VOID SetNextEntry(IN PMMPTE Pte, diff --git a/xtoskrnl/mm/paging.cc b/xtoskrnl/mm/paging.cc index c85744e..69a2c21 100644 --- a/xtoskrnl/mm/paging.cc +++ b/xtoskrnl/mm/paging.cc @@ -25,7 +25,7 @@ XTAPI PMMPTE MM::Paging::AdvancePte(IN PMMPTE Pte, - IN ULONG Count) + IN LONG Count) { /* Return advanced PTE pointer */ return PmlRoutines->AdvancePte(Pte, Count); @@ -170,6 +170,42 @@ MM::Paging::GetOneEntry(IN PMMPTE Pte) return PmlRoutines->GetOneEntry(Pte); } +/** + * Gets the address 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 address of the P5E, or NULLPTR if LA57 is not enabled. + * + * @since XT 1.0 + */ +XTAPI +PMMPDE +MM::Paging::GetP5eAddress(IN PVOID Address) +{ + /* Return PDE address */ + return PmlRoutines->GetP5eAddress(Address); +} + +/** + * 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::Paging::GetP5eVirtualAddress(IN PMMPTE P5ePointer) +{ + /* Return PTE virtual address */ + return PmlRoutines->GetP5eVirtualAddress(P5ePointer); +} + /** * Gets the page frame number from a corresponding PTE. * @@ -239,6 +275,24 @@ MM::Paging::GetPdeAddress(IN PVOID Address) return PmlRoutines->GetPdeAddress(Address); } +/** + * 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::Paging::GetPdeVirtualAddress(IN PMMPTE PdePointer) +{ + /* Return PTE virtual address */ + return PmlRoutines->GetPdeVirtualAddress(PdePointer); +} + /** * Gets the address of the PPE (Page Directory Pointer Table Entry), that maps given address. * @@ -257,6 +311,24 @@ MM::Paging::GetPpeAddress(IN PVOID Address) return PmlRoutines->GetPpeAddress(Address); } +/** + * 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::Paging::GetPpeVirtualAddress(IN PMMPTE PpePointer) +{ + /* Return PTE virtual address */ + return PmlRoutines->GetPpeVirtualAddress(PpePointer); +} + /** * Gets the address of the PTE (Page Table Entry), that maps given address. * @@ -290,6 +362,74 @@ MM::Paging::GetPteSize(VOID) return PmlRoutines->GetPteSize(); } +/** + * 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::Paging::GetPteVirtualAddress(IN PMMPTE PtePointer) +{ + /* Return PTE virtual address */ + return PmlRoutines->GetPteVirtualAddress(PtePointer); +} + +/** + * Gets the address 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 address of the PXE. + * + * @since XT 1.0 + */ +XTAPI +PMMPXE +MM::Paging::GetPxeAddress(IN PVOID Address) +{ + /* Return PXE address */ + return PmlRoutines->GetPxeAddress(Address); +} + +/** + * 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::Paging::GetPxeVirtualAddress(IN PMMPXE PxePointer) +{ + /* Return PXE virtual address */ + return PmlRoutines->GetPxeVirtualAddress(PxePointer); +} + +/** + * Gets the status of Extended Paging Address (XPA) mode. + * + * @return This routine returns TRUE if XPA is enabled, FALSE otherwise. + * + * @since XT 1.0 + */ +XTAPI +BOOLEAN +MM::Paging::GetXpaStatus() +{ + return PmlRoutines->GetXpaStatus(); +} + /** * Detects if eXtended Physical Addressing (XPA) is enabled and initializes page map support. * -- 2.52.0 From 4a7494ad3f245568a251dd4e0ea26c01f0cac153 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Sun, 30 Nov 2025 19:19:32 +0100 Subject: [PATCH 021/166] Split paging interface into arch-specific code --- xtoskrnl/includes/mm.hh | 2 +- xtoskrnl/includes/mm/{ => amd64}/paging.hh | 13 ++- xtoskrnl/includes/mm/i686/paging.hh | 63 +++++++++++++ xtoskrnl/mm/amd64/paging.cc | 72 +++++++++++++++ xtoskrnl/mm/paging.cc | 100 +++------------------ 5 files changed, 156 insertions(+), 94 deletions(-) rename xtoskrnl/includes/mm/{ => amd64}/paging.hh (89%) create mode 100644 xtoskrnl/includes/mm/i686/paging.hh diff --git a/xtoskrnl/includes/mm.hh b/xtoskrnl/includes/mm.hh index 8dbdfb5..3ac8950 100644 --- a/xtoskrnl/includes/mm.hh +++ b/xtoskrnl/includes/mm.hh @@ -12,10 +12,10 @@ #include #include XTOS_ARCH_HEADER(mm, pagemap.hh) +#include XTOS_ARCH_HEADER(mm, paging.hh) #include #include #include -#include #endif /* __XTOSKRNL_MM_HH */ diff --git a/xtoskrnl/includes/mm/paging.hh b/xtoskrnl/includes/mm/amd64/paging.hh similarity index 89% rename from xtoskrnl/includes/mm/paging.hh rename to xtoskrnl/includes/mm/amd64/paging.hh index 84e41ec..a010825 100644 --- a/xtoskrnl/includes/mm/paging.hh +++ b/xtoskrnl/includes/mm/amd64/paging.hh @@ -1,13 +1,13 @@ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory - * FILE: xtoskrnl/includes/mm/paging.hh - * DESCRIPTION: Low level page management support + * FILE: xtoskrnl/includes/mm/amd64/paging.hh + * DESCRIPTION: Low level page management support for AMD64 * DEVELOPERS: Aiken Harris */ -#ifndef __XTOSKRNL_MM_PAGING_HH -#define __XTOSKRNL_MM_PAGING_HH +#ifndef __XTOSKRNL_MM_AMD64_PAGING_HH +#define __XTOSKRNL_MM_AMD64_PAGING_HH #include @@ -32,6 +32,7 @@ namespace MM STATIC XTAPI BOOLEAN GetOneEntry(IN PMMPTE Pte); STATIC XTAPI PMMPDE GetP5eAddress(IN PVOID Address); STATIC XTAPI PVOID GetP5eVirtualAddress(IN PMMPTE P5ePointer); + STATIC XTAPI USHORT GetPageMapLevel(); STATIC XTAPI PFN_NUMBER GetPageFrameNumber(IN PMMPTE Pte); STATIC XTAPI PMMPDE GetPdeAddress(IN PVOID Address); STATIC XTAPI PVOID GetPdeVirtualAddress(IN PMMPXE PdePointer); @@ -42,8 +43,6 @@ namespace MM STATIC XTAPI PVOID GetPteVirtualAddress(IN PMMPXE PtePointer); STATIC XTAPI PMMPXE GetPxeAddress(IN PVOID Address); STATIC XTAPI PVOID GetPxeVirtualAddress(IN PMMPXE PxePointer); - STATIC XTAPI BOOLEAN GetXpaStatus(); - STATIC XTAPI VOID InitializeSystemSpaceMapping(VOID); STATIC XTAPI VOID InitializePageMapSupport(VOID); STATIC XTAPI BOOLEAN PteValid(IN PMMPTE PtePointer); STATIC XTAPI VOID SetNextEntry(IN PMMPTE Pte, @@ -65,4 +64,4 @@ namespace MM }; } -#endif /* __XTOSKRNL_MM_PAGING_HH */ +#endif /* __XTOSKRNL_MM_AMD64_PAGING_HH */ diff --git a/xtoskrnl/includes/mm/i686/paging.hh b/xtoskrnl/includes/mm/i686/paging.hh new file mode 100644 index 0000000..9d2cdaa --- /dev/null +++ b/xtoskrnl/includes/mm/i686/paging.hh @@ -0,0 +1,63 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: xtoskrnl/includes/mm/i686/paging.hh + * DESCRIPTION: Low level page management support for i686 + * DEVELOPERS: Aiken Harris + */ + +#ifndef __XTOSKRNL_MM_I686_PAGING_HH +#define __XTOSKRNL_MM_I686_PAGING_HH + +#include + + +/* Memory Manager */ +namespace MM +{ + class Paging + { + private: + STATIC PPAGEMAP PmlRoutines; + + public: + STATIC XTAPI PMMPTE AdvancePte(IN PMMPTE Pte, + IN LONG Count); + STATIC XTAPI VOID ClearPte(IN PMMPTE PtePointer); + STATIC XTAPI VOID FlushTlb(VOID); + STATIC XTAPI ULONG_PTR GetEmptyPteList(VOID); + STATIC XTAPI BOOLEAN GetExtendedPhysicalAddressingStatus(VOID); + STATIC XTAPI ULONG_PTR GetNextEntry(IN PMMPTE Pte); + STATIC XTAPI PMMPTE GetNextPte(IN PMMPTE Pte); + STATIC XTAPI BOOLEAN GetOneEntry(IN PMMPTE Pte); + STATIC XTAPI USHORT GetPageMapLevel(); + STATIC XTAPI PFN_NUMBER GetPageFrameNumber(IN PMMPTE Pte); + STATIC XTAPI PMMPDE GetPdeAddress(IN PVOID Address); + STATIC XTAPI PVOID GetPdeVirtualAddress(IN PMMPXE PdePointer); + STATIC XTAPI PMMPPE GetPpeAddress(IN PVOID Address); + STATIC XTAPI PVOID GetPpeVirtualAddress(IN PMMPXE PpePointer); + STATIC XTAPI PMMPTE GetPteAddress(IN PVOID Address); + STATIC XTAPI ULONG GetPteSize(VOID); + STATIC XTAPI PVOID GetPteVirtualAddress(IN PMMPXE PtePointer); + STATIC XTAPI VOID InitializePageMapSupport(VOID); + STATIC XTAPI BOOLEAN PteValid(IN PMMPTE PtePointer); + STATIC XTAPI VOID SetNextEntry(IN PMMPTE Pte, + IN ULONG_PTR Value); + STATIC XTAPI VOID SetOneEntry(IN PMMPTE Pte, + IN BOOLEAN Value); + STATIC XTAPI VOID SetPte(IN PMMPTE PtePointer, + IN PFN_NUMBER PageFrameNumber, + IN ULONG_PTR AttributesMask); + STATIC XTAPI VOID SetPteCaching(IN PMMPTE PtePointer, + IN BOOLEAN CacheDisable, + IN BOOLEAN WriteThrough); + STATIC XTFASTCALL VOID ZeroPages(IN PVOID Address, + IN ULONG Size); + + private: + STATIC XTAPI PPAGEMAP GetPageMapBasicRoutines(VOID); + STATIC XTAPI PPAGEMAP GetPageMapXpaRoutines(VOID); + }; +} + +#endif /* __XTOSKRNL_MM_I686_PAGING_HH */ diff --git a/xtoskrnl/mm/amd64/paging.cc b/xtoskrnl/mm/amd64/paging.cc index 0ab73ef..eccee73 100644 --- a/xtoskrnl/mm/amd64/paging.cc +++ b/xtoskrnl/mm/amd64/paging.cc @@ -25,6 +25,78 @@ MM::Paging::GetExtendedPhysicalAddressingStatus(VOID) return ((AR::CpuFunc::ReadControlRegister(4) & CR4_LA57) != 0) ? TRUE : FALSE; } +/** + * Gets the address 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 address of the P5E, or NULLPTR if LA57 is not enabled. + * + * @since XT 1.0 + */ +XTAPI +PMMPDE +MM::Paging::GetP5eAddress(IN PVOID Address) +{ + /* Return PDE address */ + return PmlRoutines->GetP5eAddress(Address); +} + +/** + * 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::Paging::GetP5eVirtualAddress(IN PMMPTE P5ePointer) +{ + /* Return PTE virtual address */ + return PmlRoutines->GetP5eVirtualAddress(P5ePointer); +} + +/** + * Gets the address 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 address of the PXE. + * + * @since XT 1.0 + */ +XTAPI +PMMPXE +MM::Paging::GetPxeAddress(IN PVOID Address) +{ + /* Return PXE address */ + return PmlRoutines->GetPxeAddress(Address); +} + +/** + * 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::Paging::GetPxeVirtualAddress(IN PMMPXE PxePointer) +{ + /* Return PXE virtual address */ + return PmlRoutines->GetPxeVirtualAddress(PxePointer); +} + /** * Fills a section of memory with zeroes like RtlZeroMemory(), but in more efficient way. * diff --git a/xtoskrnl/mm/paging.cc b/xtoskrnl/mm/paging.cc index 69a2c21..4641cce 100644 --- a/xtoskrnl/mm/paging.cc +++ b/xtoskrnl/mm/paging.cc @@ -170,42 +170,6 @@ MM::Paging::GetOneEntry(IN PMMPTE Pte) return PmlRoutines->GetOneEntry(Pte); } -/** - * Gets the address 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 address of the P5E, or NULLPTR if LA57 is not enabled. - * - * @since XT 1.0 - */ -XTAPI -PMMPDE -MM::Paging::GetP5eAddress(IN PVOID Address) -{ - /* Return PDE address */ - return PmlRoutines->GetP5eAddress(Address); -} - -/** - * 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::Paging::GetP5eVirtualAddress(IN PMMPTE P5ePointer) -{ - /* Return PTE virtual address */ - return PmlRoutines->GetP5eVirtualAddress(P5ePointer); -} - /** * Gets the page frame number from a corresponding PTE. * @@ -240,6 +204,20 @@ MM::Paging::GetPageMapBasicRoutines(VOID) return &PageMapBasicRoutines; } +/** + * Gets the current paging mode level. + * + * @return This routine returns 5 if 5-level paging (XPA) is enabled, otherwise 4 for 4-level paging. + * + * @since XT 1.0 + */ +XTAPI +USHORT +MM::Paging::GetPageMapLevel() +{ + return PmlRoutines->GetXpaStatus() ? 5 : 4; +} + /** * Gets the page map routines for eXtended Physical Addressing (XPA) mode. * @@ -380,56 +358,6 @@ MM::Paging::GetPteVirtualAddress(IN PMMPTE PtePointer) return PmlRoutines->GetPteVirtualAddress(PtePointer); } -/** - * Gets the address 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 address of the PXE. - * - * @since XT 1.0 - */ -XTAPI -PMMPXE -MM::Paging::GetPxeAddress(IN PVOID Address) -{ - /* Return PXE address */ - return PmlRoutines->GetPxeAddress(Address); -} - -/** - * 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::Paging::GetPxeVirtualAddress(IN PMMPXE PxePointer) -{ - /* Return PXE virtual address */ - return PmlRoutines->GetPxeVirtualAddress(PxePointer); -} - -/** - * Gets the status of Extended Paging Address (XPA) mode. - * - * @return This routine returns TRUE if XPA is enabled, FALSE otherwise. - * - * @since XT 1.0 - */ -XTAPI -BOOLEAN -MM::Paging::GetXpaStatus() -{ - return PmlRoutines->GetXpaStatus(); -} - /** * Detects if eXtended Physical Addressing (XPA) is enabled and initializes page map support. * -- 2.52.0 From 86aa22e5f88b5aca11767e233c9a19b864b0a5da Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Sun, 30 Nov 2025 20:03:12 +0100 Subject: [PATCH 022/166] Fix incorrect pointer types --- xtoskrnl/includes/mm/amd64/paging.hh | 8 ++++---- xtoskrnl/includes/mm/i686/paging.hh | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/xtoskrnl/includes/mm/amd64/paging.hh b/xtoskrnl/includes/mm/amd64/paging.hh index a010825..613c70c 100644 --- a/xtoskrnl/includes/mm/amd64/paging.hh +++ b/xtoskrnl/includes/mm/amd64/paging.hh @@ -31,16 +31,16 @@ namespace MM STATIC XTAPI PMMPTE GetNextPte(IN PMMPTE Pte); STATIC XTAPI BOOLEAN GetOneEntry(IN PMMPTE Pte); STATIC XTAPI PMMPDE GetP5eAddress(IN PVOID Address); - STATIC XTAPI PVOID GetP5eVirtualAddress(IN PMMPTE P5ePointer); + STATIC XTAPI PVOID GetP5eVirtualAddress(IN PMMP5E P5ePointer); STATIC XTAPI USHORT GetPageMapLevel(); STATIC XTAPI PFN_NUMBER GetPageFrameNumber(IN PMMPTE Pte); STATIC XTAPI PMMPDE GetPdeAddress(IN PVOID Address); - STATIC XTAPI PVOID GetPdeVirtualAddress(IN PMMPXE PdePointer); + STATIC XTAPI PVOID GetPdeVirtualAddress(IN PMMPDE PdePointer); STATIC XTAPI PMMPPE GetPpeAddress(IN PVOID Address); - STATIC XTAPI PVOID GetPpeVirtualAddress(IN PMMPXE PpePointer); + STATIC XTAPI PVOID GetPpeVirtualAddress(IN PMMPPE PpePointer); STATIC XTAPI PMMPTE GetPteAddress(IN PVOID Address); STATIC XTAPI ULONG GetPteSize(VOID); - STATIC XTAPI PVOID GetPteVirtualAddress(IN PMMPXE PtePointer); + STATIC XTAPI PVOID GetPteVirtualAddress(IN PMMPTE PtePointer); STATIC XTAPI PMMPXE GetPxeAddress(IN PVOID Address); STATIC XTAPI PVOID GetPxeVirtualAddress(IN PMMPXE PxePointer); STATIC XTAPI VOID InitializePageMapSupport(VOID); diff --git a/xtoskrnl/includes/mm/i686/paging.hh b/xtoskrnl/includes/mm/i686/paging.hh index 9d2cdaa..97c099e 100644 --- a/xtoskrnl/includes/mm/i686/paging.hh +++ b/xtoskrnl/includes/mm/i686/paging.hh @@ -33,12 +33,12 @@ namespace MM STATIC XTAPI USHORT GetPageMapLevel(); STATIC XTAPI PFN_NUMBER GetPageFrameNumber(IN PMMPTE Pte); STATIC XTAPI PMMPDE GetPdeAddress(IN PVOID Address); - STATIC XTAPI PVOID GetPdeVirtualAddress(IN PMMPXE PdePointer); + STATIC XTAPI PVOID GetPdeVirtualAddress(IN PMMPDE PdePointer); STATIC XTAPI PMMPPE GetPpeAddress(IN PVOID Address); - STATIC XTAPI PVOID GetPpeVirtualAddress(IN PMMPXE PpePointer); + STATIC XTAPI PVOID GetPpeVirtualAddress(IN PMMPPE PpePointer); STATIC XTAPI PMMPTE GetPteAddress(IN PVOID Address); STATIC XTAPI ULONG GetPteSize(VOID); - STATIC XTAPI PVOID GetPteVirtualAddress(IN PMMPXE PtePointer); + STATIC XTAPI PVOID GetPteVirtualAddress(IN PMMPTE PtePointer); STATIC XTAPI VOID InitializePageMapSupport(VOID); STATIC XTAPI BOOLEAN PteValid(IN PMMPTE PtePointer); STATIC XTAPI VOID SetNextEntry(IN PMMPTE Pte, -- 2.52.0 From 8054bb915aaab2e373ebbdac7ef6535a7302f3d4 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Sun, 30 Nov 2025 20:06:51 +0100 Subject: [PATCH 023/166] Fix incorrect pointer types --- xtoskrnl/mm/amd64/paging.cc | 2 +- xtoskrnl/mm/paging.cc | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/xtoskrnl/mm/amd64/paging.cc b/xtoskrnl/mm/amd64/paging.cc index eccee73..f5bf042 100644 --- a/xtoskrnl/mm/amd64/paging.cc +++ b/xtoskrnl/mm/amd64/paging.cc @@ -55,7 +55,7 @@ MM::Paging::GetP5eAddress(IN PVOID Address) */ XTAPI PVOID -MM::Paging::GetP5eVirtualAddress(IN PMMPTE P5ePointer) +MM::Paging::GetP5eVirtualAddress(IN PMMP5E P5ePointer) { /* Return PTE virtual address */ return PmlRoutines->GetP5eVirtualAddress(P5ePointer); diff --git a/xtoskrnl/mm/paging.cc b/xtoskrnl/mm/paging.cc index 4641cce..225d758 100644 --- a/xtoskrnl/mm/paging.cc +++ b/xtoskrnl/mm/paging.cc @@ -265,7 +265,7 @@ MM::Paging::GetPdeAddress(IN PVOID Address) */ XTAPI PVOID -MM::Paging::GetPdeVirtualAddress(IN PMMPTE PdePointer) +MM::Paging::GetPdeVirtualAddress(IN PMMPDE PdePointer) { /* Return PTE virtual address */ return PmlRoutines->GetPdeVirtualAddress(PdePointer); @@ -301,7 +301,7 @@ MM::Paging::GetPpeAddress(IN PVOID Address) */ XTAPI PVOID -MM::Paging::GetPpeVirtualAddress(IN PMMPTE PpePointer) +MM::Paging::GetPpeVirtualAddress(IN PMMPPE PpePointer) { /* Return PTE virtual address */ return PmlRoutines->GetPpeVirtualAddress(PpePointer); -- 2.52.0 From c710ec4688d03f18c9de4387b0045cf3c0f63d35 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Thu, 4 Dec 2025 23:07:59 +0100 Subject: [PATCH 024/166] Refactor XPA detection API --- xtoskrnl/includes/mm/amd64/paging.hh | 4 ++-- xtoskrnl/includes/mm/i686/paging.hh | 4 ++-- xtoskrnl/mm/paging.cc | 28 ++++++++++++++-------------- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/xtoskrnl/includes/mm/amd64/paging.hh b/xtoskrnl/includes/mm/amd64/paging.hh index 613c70c..91dcfff 100644 --- a/xtoskrnl/includes/mm/amd64/paging.hh +++ b/xtoskrnl/includes/mm/amd64/paging.hh @@ -26,13 +26,11 @@ namespace MM STATIC XTAPI VOID ClearPte(IN PMMPTE PtePointer); STATIC XTAPI VOID FlushTlb(VOID); STATIC XTAPI ULONG_PTR GetEmptyPteList(VOID); - STATIC XTAPI BOOLEAN GetExtendedPhysicalAddressingStatus(VOID); STATIC XTAPI ULONG_PTR GetNextEntry(IN PMMPTE Pte); STATIC XTAPI PMMPTE GetNextPte(IN PMMPTE Pte); STATIC XTAPI BOOLEAN GetOneEntry(IN PMMPTE Pte); STATIC XTAPI PMMPDE GetP5eAddress(IN PVOID Address); STATIC XTAPI PVOID GetP5eVirtualAddress(IN PMMP5E P5ePointer); - STATIC XTAPI USHORT GetPageMapLevel(); STATIC XTAPI PFN_NUMBER GetPageFrameNumber(IN PMMPTE Pte); STATIC XTAPI PMMPDE GetPdeAddress(IN PVOID Address); STATIC XTAPI PVOID GetPdeVirtualAddress(IN PMMPDE PdePointer); @@ -43,6 +41,7 @@ namespace MM STATIC XTAPI PVOID GetPteVirtualAddress(IN PMMPTE PtePointer); STATIC XTAPI PMMPXE GetPxeAddress(IN PVOID Address); STATIC XTAPI PVOID GetPxeVirtualAddress(IN PMMPXE PxePointer); + STATIC XTAPI BOOLEAN GetXpaStatus(VOID); STATIC XTAPI VOID InitializePageMapSupport(VOID); STATIC XTAPI BOOLEAN PteValid(IN PMMPTE PtePointer); STATIC XTAPI VOID SetNextEntry(IN PMMPTE Pte, @@ -59,6 +58,7 @@ namespace MM IN ULONG Size); private: + STATIC XTAPI BOOLEAN GetExtendedPhysicalAddressingStatus(VOID); STATIC XTAPI PPAGEMAP GetPageMapBasicRoutines(VOID); STATIC XTAPI PPAGEMAP GetPageMapXpaRoutines(VOID); }; diff --git a/xtoskrnl/includes/mm/i686/paging.hh b/xtoskrnl/includes/mm/i686/paging.hh index 97c099e..819cfa6 100644 --- a/xtoskrnl/includes/mm/i686/paging.hh +++ b/xtoskrnl/includes/mm/i686/paging.hh @@ -26,11 +26,9 @@ namespace MM STATIC XTAPI VOID ClearPte(IN PMMPTE PtePointer); STATIC XTAPI VOID FlushTlb(VOID); STATIC XTAPI ULONG_PTR GetEmptyPteList(VOID); - STATIC XTAPI BOOLEAN GetExtendedPhysicalAddressingStatus(VOID); STATIC XTAPI ULONG_PTR GetNextEntry(IN PMMPTE Pte); STATIC XTAPI PMMPTE GetNextPte(IN PMMPTE Pte); STATIC XTAPI BOOLEAN GetOneEntry(IN PMMPTE Pte); - STATIC XTAPI USHORT GetPageMapLevel(); STATIC XTAPI PFN_NUMBER GetPageFrameNumber(IN PMMPTE Pte); STATIC XTAPI PMMPDE GetPdeAddress(IN PVOID Address); STATIC XTAPI PVOID GetPdeVirtualAddress(IN PMMPDE PdePointer); @@ -39,6 +37,7 @@ namespace MM STATIC XTAPI PMMPTE GetPteAddress(IN PVOID Address); STATIC XTAPI ULONG GetPteSize(VOID); STATIC XTAPI PVOID GetPteVirtualAddress(IN PMMPTE PtePointer); + STATIC XTAPI BOOLEAN GetXpaStatus(VOID); STATIC XTAPI VOID InitializePageMapSupport(VOID); STATIC XTAPI BOOLEAN PteValid(IN PMMPTE PtePointer); STATIC XTAPI VOID SetNextEntry(IN PMMPTE Pte, @@ -55,6 +54,7 @@ namespace MM IN ULONG Size); private: + STATIC XTAPI BOOLEAN GetExtendedPhysicalAddressingStatus(VOID); STATIC XTAPI PPAGEMAP GetPageMapBasicRoutines(VOID); STATIC XTAPI PPAGEMAP GetPageMapXpaRoutines(VOID); }; diff --git a/xtoskrnl/mm/paging.cc b/xtoskrnl/mm/paging.cc index 225d758..5c5316f 100644 --- a/xtoskrnl/mm/paging.cc +++ b/xtoskrnl/mm/paging.cc @@ -204,20 +204,6 @@ MM::Paging::GetPageMapBasicRoutines(VOID) return &PageMapBasicRoutines; } -/** - * Gets the current paging mode level. - * - * @return This routine returns 5 if 5-level paging (XPA) is enabled, otherwise 4 for 4-level paging. - * - * @since XT 1.0 - */ -XTAPI -USHORT -MM::Paging::GetPageMapLevel() -{ - return PmlRoutines->GetXpaStatus() ? 5 : 4; -} - /** * Gets the page map routines for eXtended Physical Addressing (XPA) mode. * @@ -358,6 +344,20 @@ MM::Paging::GetPteVirtualAddress(IN PMMPTE PtePointer) return PmlRoutines->GetPteVirtualAddress(PtePointer); } +/** + * Gets current status of eXtended Physical Addressing (XPA). + * + * @return This routine returns TRUE if PAE or LA57 (XPA) is enabled, or FALSE otherwise. + * + * @since XT 1.0 + */ +XTAPI +BOOLEAN +MM::Paging::GetXpaStatus() +{ + return PmlRoutines->GetXpaStatus(); +} + /** * Detects if eXtended Physical Addressing (XPA) is enabled and initializes page map support. * -- 2.52.0 From 7694df7744a93dcb70f26646745fe3613120ce2b Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Sat, 6 Dec 2025 00:19:24 +0100 Subject: [PATCH 025/166] Add architecture-specific GetPteDistance --- xtoskrnl/includes/mm/amd64/pagemap.hh | 2 ++ xtoskrnl/includes/mm/amd64/paging.hh | 2 ++ xtoskrnl/includes/mm/i686/pagemap.hh | 4 +++ xtoskrnl/includes/mm/i686/paging.hh | 2 ++ xtoskrnl/mm/amd64/pagemap.cc | 22 ++++++++++++++ xtoskrnl/mm/i686/pagemap.cc | 44 +++++++++++++++++++++++++++ xtoskrnl/mm/paging.cc | 22 ++++++++++++++ 7 files changed, 98 insertions(+) diff --git a/xtoskrnl/includes/mm/amd64/pagemap.hh b/xtoskrnl/includes/mm/amd64/pagemap.hh index fce9480..9aee6cf 100644 --- a/xtoskrnl/includes/mm/amd64/pagemap.hh +++ b/xtoskrnl/includes/mm/amd64/pagemap.hh @@ -39,6 +39,8 @@ namespace MM XTAPI ULONG GetPpeIndex(IN PVOID Address); VIRTUAL XTAPI PVOID GetPpeVirtualAddress(IN PMMPPE PpePointer) = 0; XTAPI PMMPTE GetPteAddress(IN PVOID Address); + XTAPI LONG GetPteDistance(PMMPTE EndPte, + PMMPTE StartPte); XTAPI ULONG GetPteIndex(IN PVOID Address); XTAPI ULONG GetPteSize(VOID); VIRTUAL XTAPI PVOID GetPteVirtualAddress(IN PMMPTE PtePointer) = 0; diff --git a/xtoskrnl/includes/mm/amd64/paging.hh b/xtoskrnl/includes/mm/amd64/paging.hh index 91dcfff..64e7a9e 100644 --- a/xtoskrnl/includes/mm/amd64/paging.hh +++ b/xtoskrnl/includes/mm/amd64/paging.hh @@ -37,6 +37,8 @@ namespace MM STATIC XTAPI PMMPPE GetPpeAddress(IN PVOID Address); STATIC XTAPI PVOID GetPpeVirtualAddress(IN PMMPPE PpePointer); STATIC XTAPI PMMPTE GetPteAddress(IN PVOID Address); + STATIC XTAPI LONG GetPteDistance(PMMPTE EndPte, + PMMPTE StartPte); STATIC XTAPI ULONG GetPteSize(VOID); STATIC XTAPI PVOID GetPteVirtualAddress(IN PMMPTE PtePointer); STATIC XTAPI PMMPXE GetPxeAddress(IN PVOID Address); diff --git a/xtoskrnl/includes/mm/i686/pagemap.hh b/xtoskrnl/includes/mm/i686/pagemap.hh index 59a4d6a..0ce296f 100644 --- a/xtoskrnl/includes/mm/i686/pagemap.hh +++ b/xtoskrnl/includes/mm/i686/pagemap.hh @@ -63,6 +63,8 @@ namespace MM XTAPI PMMPTE GetNextPte(IN PMMPTE Pte); XTAPI BOOLEAN GetOneEntry(IN PMMPTE Pte); XTAPI PFN_NUMBER GetPageFrameNumber(IN PMMPTE Pte); + XTAPI LONG GetPteDistance(PMMPTE EndPte, + PMMPTE StartPte); XTAPI ULONG GetPteSize(VOID); XTAPI VOID InitializePageMapInfo(VOID); XTAPI BOOLEAN PteValid(IN PMMPTE PtePointer); @@ -87,6 +89,8 @@ namespace MM XTAPI PMMPTE GetNextPte(IN PMMPTE Pte); XTAPI BOOLEAN GetOneEntry(IN PMMPTE Pte); XTAPI PFN_NUMBER GetPageFrameNumber(IN PMMPTE Pte); + XTAPI LONG GetPteDistance(PMMPTE EndPte, + PMMPTE StartPte); XTAPI ULONG GetPteSize(VOID); XTAPI VOID InitializePageMapInfo(VOID); XTAPI BOOLEAN PteValid(IN PMMPTE PtePointer); diff --git a/xtoskrnl/includes/mm/i686/paging.hh b/xtoskrnl/includes/mm/i686/paging.hh index 819cfa6..a1b13ad 100644 --- a/xtoskrnl/includes/mm/i686/paging.hh +++ b/xtoskrnl/includes/mm/i686/paging.hh @@ -35,6 +35,8 @@ namespace MM STATIC XTAPI PMMPPE GetPpeAddress(IN PVOID Address); STATIC XTAPI PVOID GetPpeVirtualAddress(IN PMMPPE PpePointer); STATIC XTAPI PMMPTE GetPteAddress(IN PVOID Address); + STATIC XTAPI LONG GetPteDistance(PMMPTE EndPte, + PMMPTE StartPte); STATIC XTAPI ULONG GetPteSize(VOID); STATIC XTAPI PVOID GetPteVirtualAddress(IN PMMPTE PtePointer); STATIC XTAPI BOOLEAN GetXpaStatus(VOID); diff --git a/xtoskrnl/mm/amd64/pagemap.cc b/xtoskrnl/mm/amd64/pagemap.cc index 7384835..290f880 100644 --- a/xtoskrnl/mm/amd64/pagemap.cc +++ b/xtoskrnl/mm/amd64/pagemap.cc @@ -289,6 +289,28 @@ MM::PageMap::GetPteAddress(IN PVOID Address) return (PMMPTE)(PageMapInfo.PteBase + Offset); } +/** + * Calculates the distance between two PTE pointers. + * + * @param EndPte + * Pointer to the ending Page Table Entry. + * + * @param StartPte + * Pointer to the starting Page Table Entry. + * + * @return This routine returns a signed value representing the number of PTEs between EndPte and StartPte. + * + * @since XT 1.0 + */ +XTAPI +LONG +MM::PageMap::GetPteDistance(PMMPTE EndPte, + PMMPTE StartPte) +{ + /* Return distance between PTE pointers */ + return ((ULONG_PTR)EndPte - (ULONG_PTR)StartPte) / sizeof(MMPTE); +} + /** * Gets the index of the PTE (Page Table Entry), that maps given address. * diff --git a/xtoskrnl/mm/i686/pagemap.cc b/xtoskrnl/mm/i686/pagemap.cc index cb38fa4..d695fe8 100644 --- a/xtoskrnl/mm/i686/pagemap.cc +++ b/xtoskrnl/mm/i686/pagemap.cc @@ -317,6 +317,28 @@ MM::PageMapBasic::GetPageFrameNumber(IN PMMPTE Pte) return Pte->Pml2.Hardware.PageFrameNumber; } +/** + * Calculates the distance between two PTE pointers. + * + * @param EndPte + * Pointer to the ending Page Table Entry. + * + * @param StartPte + * Pointer to the starting Page Table Entry. + * + * @return This routine returns a signed value representing the number of PTEs between EndPte and StartPte. + * + * @since XT 1.0 + */ +XTAPI +LONG +MM::PageMapBasic::GetPteDistance(PMMPTE EndPte, + PMMPTE StartPte) +{ + /* Return distance between PTE pointers */ + return ((ULONG_PTR)EndPte - (ULONG_PTR)StartPte) / sizeof(MMPML2_PTE); +} + /** * Gets the size of a PTE for basic paging (PML2). * @@ -568,6 +590,28 @@ MM::PageMapXpa::GetPageFrameNumber(IN PMMPTE Pte) return Pte->Pml3.Hardware.PageFrameNumber; } +/** + * Calculates the distance between two PTE pointers. + * + * @param EndPte + * Pointer to the ending Page Table Entry. + * + * @param StartPte + * Pointer to the starting Page Table Entry. + * + * @return This routine returns a signed value representing the number of PTEs between EndPte and StartPte. + * + * @since XT 1.0 + */ +XTAPI +LONG +MM::PageMapXpa::GetPteDistance(PMMPTE EndPte, + PMMPTE StartPte) +{ + /* Return distance between PTE pointers */ + return ((ULONG_PTR)EndPte - (ULONG_PTR)StartPte) / sizeof(MMPML3_PTE); +} + /** * Gets the size of a PTE for XPA paging (PML3). * diff --git a/xtoskrnl/mm/paging.cc b/xtoskrnl/mm/paging.cc index 5c5316f..18c24d2 100644 --- a/xtoskrnl/mm/paging.cc +++ b/xtoskrnl/mm/paging.cc @@ -311,6 +311,28 @@ MM::Paging::GetPteAddress(IN PVOID Address) return PmlRoutines->GetPteAddress(Address); } +/** + * Calculates the distance between two PTE pointers. + * + * @param EndPte + * Pointer to the ending Page Table Entry. + * + * @param StartPte + * Pointer to the starting Page Table Entry. + * + * @return This routine returns a signed value representing the number of PTEs between EndPte and StartPte. + * + * @since XT 1.0 + */ +XTAPI +LONG +MM::Paging::GetPteDistance(PMMPTE EndPte, + PMMPTE StartPte) +{ + /* Return distance between PTE pointers */ + return PmlRoutines->GetPteDistance(EndPte, StartPte); +} + /** * Gets the size of a PTE. * -- 2.52.0 From 63c27a149a4be9fbdb42610130c65ea0cc4631e9 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Sat, 6 Dec 2025 00:29:51 +0100 Subject: [PATCH 026/166] Add missing virtual GetPteDistance to pagemap interface --- xtoskrnl/includes/mm/i686/pagemap.hh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/xtoskrnl/includes/mm/i686/pagemap.hh b/xtoskrnl/includes/mm/i686/pagemap.hh index 0ce296f..9233f2b 100644 --- a/xtoskrnl/includes/mm/i686/pagemap.hh +++ b/xtoskrnl/includes/mm/i686/pagemap.hh @@ -37,6 +37,8 @@ namespace MM XTAPI PVOID GetPpeVirtualAddress(IN PMMPPE PpePointer); XTAPI PMMPTE GetPteAddress(IN PVOID Address); XTAPI ULONG GetPteIndex(IN PVOID Address); + VIRTUAL XTAPI LONG GetPteDistance(PMMPTE EndPte, + PMMPTE StartPte) = 0; VIRTUAL XTAPI ULONG GetPteSize(VOID) = 0; XTAPI PVOID GetPteVirtualAddress(IN PMMPTE PtePointer); XTAPI BOOLEAN GetXpaStatus(); -- 2.52.0 From ee9514fd5c1a7e80cd1300d316d1000d09676099 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Sat, 13 Dec 2025 19:58:49 +0100 Subject: [PATCH 027/166] Fix GetP5eAddress return type --- xtoskrnl/includes/mm/amd64/paging.hh | 2 +- xtoskrnl/mm/amd64/paging.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/xtoskrnl/includes/mm/amd64/paging.hh b/xtoskrnl/includes/mm/amd64/paging.hh index 64e7a9e..6795add 100644 --- a/xtoskrnl/includes/mm/amd64/paging.hh +++ b/xtoskrnl/includes/mm/amd64/paging.hh @@ -29,7 +29,7 @@ namespace MM STATIC XTAPI ULONG_PTR GetNextEntry(IN PMMPTE Pte); STATIC XTAPI PMMPTE GetNextPte(IN PMMPTE Pte); STATIC XTAPI BOOLEAN GetOneEntry(IN PMMPTE Pte); - STATIC XTAPI PMMPDE GetP5eAddress(IN PVOID Address); + STATIC XTAPI PMMP5E GetP5eAddress(IN PVOID Address); STATIC XTAPI PVOID GetP5eVirtualAddress(IN PMMP5E P5ePointer); STATIC XTAPI PFN_NUMBER GetPageFrameNumber(IN PMMPTE Pte); STATIC XTAPI PMMPDE GetPdeAddress(IN PVOID Address); diff --git a/xtoskrnl/mm/amd64/paging.cc b/xtoskrnl/mm/amd64/paging.cc index f5bf042..a04e007 100644 --- a/xtoskrnl/mm/amd64/paging.cc +++ b/xtoskrnl/mm/amd64/paging.cc @@ -36,7 +36,7 @@ MM::Paging::GetExtendedPhysicalAddressingStatus(VOID) * @since XT 1.0 */ XTAPI -PMMPDE +PMMP5E MM::Paging::GetP5eAddress(IN PVOID Address) { /* Return PDE address */ -- 2.52.0 From 237f6a297424840ca92c42a36681747f41586321 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Sat, 13 Dec 2025 20:21:08 +0100 Subject: [PATCH 028/166] Refactor memory manager initialization into MM::Manager --- xtoskrnl/CMakeLists.txt | 2 +- xtoskrnl/includes/mm.hh | 2 +- xtoskrnl/includes/mm/{init.hh => mmgr.hh} | 12 ++++++------ xtoskrnl/mm/{init.cc => mmgr.cc} | 13 +++++++------ 4 files changed, 15 insertions(+), 14 deletions(-) rename xtoskrnl/includes/mm/{init.hh => mmgr.hh} (82%) rename xtoskrnl/mm/{init.cc => mmgr.cc} (92%) diff --git a/xtoskrnl/CMakeLists.txt b/xtoskrnl/CMakeLists.txt index 72e7bb8..64841e8 100644 --- a/xtoskrnl/CMakeLists.txt +++ b/xtoskrnl/CMakeLists.txt @@ -56,8 +56,8 @@ list(APPEND XTOSKRNL_SOURCE ${XTOSKRNL_SOURCE_DIR}/mm/${ARCH}/paging.cc ${XTOSKRNL_SOURCE_DIR}/mm/data.cc ${XTOSKRNL_SOURCE_DIR}/mm/hlpool.cc - ${XTOSKRNL_SOURCE_DIR}/mm/init.cc ${XTOSKRNL_SOURCE_DIR}/mm/kpool.cc + ${XTOSKRNL_SOURCE_DIR}/mm/mmgr.cc ${XTOSKRNL_SOURCE_DIR}/mm/paging.cc ${XTOSKRNL_SOURCE_DIR}/po/idle.cc ${XTOSKRNL_SOURCE_DIR}/rtl/${ARCH}/dispatch.cc diff --git a/xtoskrnl/includes/mm.hh b/xtoskrnl/includes/mm.hh index 3ac8950..2e3ef60 100644 --- a/xtoskrnl/includes/mm.hh +++ b/xtoskrnl/includes/mm.hh @@ -15,7 +15,7 @@ #include XTOS_ARCH_HEADER(mm, paging.hh) #include -#include #include +#include #endif /* __XTOSKRNL_MM_HH */ diff --git a/xtoskrnl/includes/mm/init.hh b/xtoskrnl/includes/mm/mmgr.hh similarity index 82% rename from xtoskrnl/includes/mm/init.hh rename to xtoskrnl/includes/mm/mmgr.hh index e606876..2fc0e84 100644 --- a/xtoskrnl/includes/mm/init.hh +++ b/xtoskrnl/includes/mm/mmgr.hh @@ -1,13 +1,13 @@ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory - * FILE: xtoskrnl/includes/mm/init.hh - * DESCRIPTION: Memory Manager initialization + * FILE: xtoskrnl/includes/mm/mmgr.hh + * DESCRIPTION: Memory Manager * DEVELOPERS: Aiken Harris */ -#ifndef __XTOSKRNL_MM_INIT_HH -#define __XTOSKRNL_MM_INIT_HH +#ifndef __XTOSKRNL_MM_MMGR_HH +#define __XTOSKRNL_MM_MMGR_HH #include @@ -15,7 +15,7 @@ /* Memory Manager */ namespace MM { - class Init + class Manager { private: STATIC PLOADER_MEMORY_DESCRIPTOR FreeDescriptor; @@ -36,4 +36,4 @@ namespace MM }; } -#endif /* __XTOSKRNL_MM_INIT_HH */ +#endif /* __XTOSKRNL_MM_MMGR_HH */ diff --git a/xtoskrnl/mm/init.cc b/xtoskrnl/mm/mmgr.cc similarity index 92% rename from xtoskrnl/mm/init.cc rename to xtoskrnl/mm/mmgr.cc index d7694d8..24135a5 100644 --- a/xtoskrnl/mm/init.cc +++ b/xtoskrnl/mm/mmgr.cc @@ -1,9 +1,10 @@ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory - * FILE: xtoskrnl/mm/init.cc - * DESCRIPTION: Memory Manager initialization routines + * FILE: xtoskrnl/mm/mmgr.cc + * DESCRIPTION: Memory Manager * DEVELOPERS: Rafal Kupiec + * Aiken Harris */ #include @@ -18,7 +19,7 @@ */ XTAPI VOID -MM::Init::InitializeMemoryManager(VOID) +MM::Manager::InitializeMemoryManager(VOID) { /* Scan memory descriptors provided by the boot loader */ ScanMemoryDescriptors(); @@ -44,7 +45,7 @@ MM::Init::InitializeMemoryManager(VOID) */ XTAPI VOID -MM::Init::ScanMemoryDescriptors(VOID) +MM::Manager::ScanMemoryDescriptors(VOID) { PLIST_ENTRY LoaderMemoryDescriptors, MemoryMappings; PLOADER_MEMORY_DESCRIPTOR MemoryDescriptor; @@ -124,7 +125,7 @@ MM::Init::ScanMemoryDescriptors(VOID) */ XTAPI BOOLEAN -MM::Init::VerifyMemoryTypeFree(LOADER_MEMORY_TYPE MemoryType) +MM::Manager::VerifyMemoryTypeFree(LOADER_MEMORY_TYPE MemoryType) { return ((MemoryType == LoaderFree) || (MemoryType == LoaderFirmwareTemporary) || (MemoryType == LoaderLoadedProgram) || (MemoryType == LoaderOsloaderStack)); @@ -142,7 +143,7 @@ MM::Init::VerifyMemoryTypeFree(LOADER_MEMORY_TYPE MemoryType) */ XTAPI BOOLEAN -MM::Init::VerifyMemoryTypeInvisible(LOADER_MEMORY_TYPE MemoryType) +MM::Manager::VerifyMemoryTypeInvisible(LOADER_MEMORY_TYPE MemoryType) { return ((MemoryType == LoaderFirmwarePermanent) || (MemoryType == LoaderSpecialMemory) || -- 2.52.0 From 783a9eea3a49d880ffaafa401d36adea72c4bb2d Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Sat, 13 Dec 2025 20:42:48 +0100 Subject: [PATCH 029/166] Extract PFN management into separate module --- xtoskrnl/CMakeLists.txt | 2 +- xtoskrnl/includes/mm.hh | 1 + xtoskrnl/includes/mm/mmgr.hh | 10 ---- xtoskrnl/includes/mm/pfn.hh | 32 +++++++++++++ xtoskrnl/mm/amd64/init.cc | 25 ---------- xtoskrnl/mm/data.cc | 14 +++--- xtoskrnl/mm/i686/init.cc | 25 ---------- xtoskrnl/mm/mmgr.cc | 81 -------------------------------- xtoskrnl/mm/pfn.cc | 89 ++++++++++++++++++++++++++++++++++++ 9 files changed, 130 insertions(+), 149 deletions(-) create mode 100644 xtoskrnl/includes/mm/pfn.hh delete mode 100644 xtoskrnl/mm/amd64/init.cc delete mode 100644 xtoskrnl/mm/i686/init.cc create mode 100644 xtoskrnl/mm/pfn.cc diff --git a/xtoskrnl/CMakeLists.txt b/xtoskrnl/CMakeLists.txt index 64841e8..082b386 100644 --- a/xtoskrnl/CMakeLists.txt +++ b/xtoskrnl/CMakeLists.txt @@ -51,7 +51,6 @@ list(APPEND XTOSKRNL_SOURCE ${XTOSKRNL_SOURCE_DIR}/ke/spinlock.cc ${XTOSKRNL_SOURCE_DIR}/ke/sysres.cc ${XTOSKRNL_SOURCE_DIR}/ke/timer.cc - ${XTOSKRNL_SOURCE_DIR}/mm/${ARCH}/init.cc ${XTOSKRNL_SOURCE_DIR}/mm/${ARCH}/pagemap.cc ${XTOSKRNL_SOURCE_DIR}/mm/${ARCH}/paging.cc ${XTOSKRNL_SOURCE_DIR}/mm/data.cc @@ -59,6 +58,7 @@ list(APPEND XTOSKRNL_SOURCE ${XTOSKRNL_SOURCE_DIR}/mm/kpool.cc ${XTOSKRNL_SOURCE_DIR}/mm/mmgr.cc ${XTOSKRNL_SOURCE_DIR}/mm/paging.cc + ${XTOSKRNL_SOURCE_DIR}/mm/pfn.cc ${XTOSKRNL_SOURCE_DIR}/po/idle.cc ${XTOSKRNL_SOURCE_DIR}/rtl/${ARCH}/dispatch.cc ${XTOSKRNL_SOURCE_DIR}/rtl/${ARCH}/exsup.cc diff --git a/xtoskrnl/includes/mm.hh b/xtoskrnl/includes/mm.hh index 2e3ef60..2a25fd6 100644 --- a/xtoskrnl/includes/mm.hh +++ b/xtoskrnl/includes/mm.hh @@ -17,5 +17,6 @@ #include #include #include +#include #endif /* __XTOSKRNL_MM_HH */ diff --git a/xtoskrnl/includes/mm/mmgr.hh b/xtoskrnl/includes/mm/mmgr.hh index 2fc0e84..9a05a9d 100644 --- a/xtoskrnl/includes/mm/mmgr.hh +++ b/xtoskrnl/includes/mm/mmgr.hh @@ -17,20 +17,10 @@ namespace MM { class Manager { - private: - STATIC PLOADER_MEMORY_DESCRIPTOR FreeDescriptor; - STATIC ULONG_PTR HighestPhysicalPage; - STATIC ULONG_PTR LowestPhysicalPage; - STATIC ULONG NumberOfPhysicalPages; - STATIC LOADER_MEMORY_DESCRIPTOR OldFreeDescriptor; - public: STATIC XTAPI VOID InitializeMemoryManager(VOID); - STATIC XTAPI VOID InitializePageMapSupport(VOID); - STATIC XTAPI VOID ScanMemoryDescriptors(VOID); private: - STATIC XTAPI VOID InitializeArchitecture(VOID); STATIC XTAPI BOOLEAN VerifyMemoryTypeFree(LOADER_MEMORY_TYPE MemoryType); STATIC XTAPI BOOLEAN VerifyMemoryTypeInvisible(LOADER_MEMORY_TYPE MemoryType); }; diff --git a/xtoskrnl/includes/mm/pfn.hh b/xtoskrnl/includes/mm/pfn.hh new file mode 100644 index 0000000..d8806d9 --- /dev/null +++ b/xtoskrnl/includes/mm/pfn.hh @@ -0,0 +1,32 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: xtoskrnl/includes/mm/pfn.hh + * DESCRIPTION: Physical Frame Number (PFN) support + * DEVELOPERS: Aiken Harris + */ + +#ifndef __XTOSKRNL_MM_PFN_HH +#define __XTOSKRNL_MM_PFN_HH + +#include + + +/* Memory Manager */ +namespace MM +{ + class Pfn + { + private: + STATIC PLOADER_MEMORY_DESCRIPTOR FreeDescriptor; + STATIC ULONG_PTR HighestPhysicalPage; + STATIC ULONG_PTR LowestPhysicalPage; + STATIC ULONG NumberOfPhysicalPages; + STATIC LOADER_MEMORY_DESCRIPTOR OldFreeDescriptor; + + public: + STATIC XTAPI VOID ScanMemoryDescriptors(VOID); + }; +} + +#endif /* __XTOSKRNL_MM_PFN_HH */ diff --git a/xtoskrnl/mm/amd64/init.cc b/xtoskrnl/mm/amd64/init.cc deleted file mode 100644 index 7e7a9d8..0000000 --- a/xtoskrnl/mm/amd64/init.cc +++ /dev/null @@ -1,25 +0,0 @@ -/** - * PROJECT: ExectOS - * COPYRIGHT: See COPYING.md in the top level directory - * FILE: xtoskrnl/mm/amd64/init.cc - * DESCRIPTION: Architecture specific Memory Manager initialization routines - * DEVELOPERS: Rafal Kupiec - * Aiken Harris - */ - -#include - - -/** - * Performs architecture specific initialization of the XTOS Memory Manager. - * - * @return This routine does not return any value. - * - * @since XT 1.0 - */ -XTAPI -VOID -MM::Init::InitializeArchitecture(VOID) -{ - UNIMPLEMENTED; -} diff --git a/xtoskrnl/mm/data.cc b/xtoskrnl/mm/data.cc index 7869827..19ea38c 100644 --- a/xtoskrnl/mm/data.cc +++ b/xtoskrnl/mm/data.cc @@ -18,23 +18,23 @@ PVOID MM::HardwarePool::HardwareHeapStart = MM_HARDWARE_HEAP_START_ADDRESS; /* Number of used hardware allocation descriptors */ ULONG MM::HardwarePool::UsedHardwareAllocationDescriptors = 0; +/* Processor structures data (THIS IS A TEMPORARY HACK) */ +UCHAR MM::KernelPool::ProcessorStructuresData[MAXIMUM_PROCESSORS][KPROCESSOR_STRUCTURES_SIZE] = {{0}}; + /* Biggest free memory descriptor */ PLOADER_MEMORY_DESCRIPTOR MM::Init::FreeDescriptor; /* Highest physical page number */ -ULONG_PTR MM::Init::HighestPhysicalPage; +ULONG_PTR MM::Pfn::HighestPhysicalPage; /* Lowest physical page number */ -ULONG_PTR MM::Init::LowestPhysicalPage = -1; +ULONG_PTR MM::Pfn::LowestPhysicalPage = -1; /* Number of physical pages */ -ULONG MM::Init::NumberOfPhysicalPages; +ULONG MM::Pfn::NumberOfPhysicalPages; /* Old biggest free memory descriptor */ -LOADER_MEMORY_DESCRIPTOR MM::Init::OldFreeDescriptor; - -/* Processor structures data (THIS IS A TEMPORARY HACK) */ -UCHAR MM::KernelPool::ProcessorStructuresData[MAXIMUM_PROCESSORS][KPROCESSOR_STRUCTURES_SIZE] = {{0}}; +LOADER_MEMORY_DESCRIPTOR MM::Pfn::OldFreeDescriptor; /* Instance of the page map routines for the current PML level */ MM::PPAGEMAP MM::Paging::PmlRoutines; diff --git a/xtoskrnl/mm/i686/init.cc b/xtoskrnl/mm/i686/init.cc deleted file mode 100644 index ab1892d..0000000 --- a/xtoskrnl/mm/i686/init.cc +++ /dev/null @@ -1,25 +0,0 @@ -/** - * PROJECT: ExectOS - * COPYRIGHT: See COPYING.md in the top level directory - * FILE: xtoskrnl/mm/i686/init.cc - * DESCRIPTION: Architecture specific Memory Manager initialization routines - * DEVELOPERS: Rafal Kupiec - * Aiken Harris - */ - -#include - - -/** - * Performs architecture specific initialization of the XTOS Memory Manager. - * - * @return This routine does not return any value. - * - * @since XT 1.0 - */ -XTAPI -VOID -MM::Init::InitializeArchitecture(VOID) -{ - UNIMPLEMENTED; -} diff --git a/xtoskrnl/mm/mmgr.cc b/xtoskrnl/mm/mmgr.cc index 24135a5..218eab9 100644 --- a/xtoskrnl/mm/mmgr.cc +++ b/xtoskrnl/mm/mmgr.cc @@ -31,87 +31,6 @@ MM::Manager::InitializeMemoryManager(VOID) DebugPrint(L"Insufficient physical pages! Install additional memory\n"); KE::Crash::Panic(0); } - - /* Proceed with architecture specific initialization */ - InitializeArchitecture(); -} - -/** - * Scans memory descriptors provided by the boot loader. - * - * @return This routine does not return any value. - * - * @since XT 1.0 - */ -XTAPI -VOID -MM::Manager::ScanMemoryDescriptors(VOID) -{ - PLIST_ENTRY LoaderMemoryDescriptors, MemoryMappings; - PLOADER_MEMORY_DESCRIPTOR MemoryDescriptor; - PFN_NUMBER FreePages; - - /* Initially, set number of free pages to 0 */ - FreePages = 0; - - /* Get a list of memory descriptors provided by the boot loader */ - LoaderMemoryDescriptors = KE::BootInformation::GetMemoryDescriptors(); - - /* Iterate through memory mappings provided by the boot loader */ - MemoryMappings = LoaderMemoryDescriptors->Flink; - while(MemoryMappings != LoaderMemoryDescriptors) - { - /* Get memory descriptor */ - MemoryDescriptor = CONTAIN_RECORD(MemoryMappings, LOADER_MEMORY_DESCRIPTOR, ListEntry); - - /* Check if memory type is invisible or cached */ - if(VerifyMemoryTypeInvisible(MemoryDescriptor->MemoryType) || - (MemoryDescriptor->MemoryType == LoaderHardwareCachedMemory)) - { - /* Skip this mapping */ - MemoryMappings = MemoryMappings->Flink; - continue; - } - - /* Make sure that memory type is not bad */ - if(MemoryDescriptor->MemoryType != LoaderBad) - { - /* Increment number of physical pages */ - NumberOfPhysicalPages += MemoryDescriptor->PageCount; - } - - /* Find lowest physical page */ - if(MemoryDescriptor->BasePage < LowestPhysicalPage) - { - /* Update lowest physical page */ - LowestPhysicalPage = MemoryDescriptor->BasePage; - } - - /* Find highest physical page */ - if(MemoryDescriptor->BasePage + MemoryDescriptor->PageCount > HighestPhysicalPage) - { - /* Update highest physical page */ - HighestPhysicalPage = (MemoryDescriptor->BasePage + MemoryDescriptor->PageCount) - 1; - } - - /* Check if memory type should be considered as free */ - if(VerifyMemoryTypeFree(MemoryDescriptor->MemoryType)) - { - /* Check if this descriptor contains more free pages */ - if(MemoryDescriptor->PageCount >= FreePages) - { - /* Update free descriptor */ - FreePages = MemoryDescriptor->PageCount; - FreeDescriptor = MemoryDescriptor; - } - } - - /* Get next memory descriptor */ - MemoryMappings = MemoryMappings->Flink; - } - - /* Store original free descriptor */ - RTL::Memory::CopyMemory(&OldFreeDescriptor, FreeDescriptor, sizeof(LOADER_MEMORY_DESCRIPTOR)); } /** Checks whether the specified memory type should be considered as free. diff --git a/xtoskrnl/mm/pfn.cc b/xtoskrnl/mm/pfn.cc new file mode 100644 index 0000000..78f6713 --- /dev/null +++ b/xtoskrnl/mm/pfn.cc @@ -0,0 +1,89 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: xtoskrnl/mm/pfn.cc + * DESCRIPTION: Physical Frame Number (PFN) support + * DEVELOPERS: Aiken Harris + * Rafal Kupiec + */ + +#include + + +/** + * Scans memory descriptors provided by the boot loader. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::Pfn::ScanMemoryDescriptors(VOID) +{ + PLIST_ENTRY LoaderMemoryDescriptors, MemoryMappings; + PLOADER_MEMORY_DESCRIPTOR MemoryDescriptor; + PFN_NUMBER FreePages; + + /* Initially, set number of free pages to 0 */ + FreePages = 0; + + /* Get a list of memory descriptors provided by the boot loader */ + LoaderMemoryDescriptors = KE::BootInformation::GetMemoryDescriptors(); + + /* Iterate through memory mappings provided by the boot loader */ + MemoryMappings = LoaderMemoryDescriptors->Flink; + while(MemoryMappings != LoaderMemoryDescriptors) + { + /* Get memory descriptor */ + MemoryDescriptor = CONTAIN_RECORD(MemoryMappings, LOADER_MEMORY_DESCRIPTOR, ListEntry); + + /* Check if memory type is invisible or cached */ + if(VerifyMemoryTypeInvisible(MemoryDescriptor->MemoryType) || + (MemoryDescriptor->MemoryType == LoaderHardwareCachedMemory)) + { + /* Skip this mapping */ + MemoryMappings = MemoryMappings->Flink; + continue; + } + + /* Make sure that memory type is not bad */ + if(MemoryDescriptor->MemoryType != LoaderBad) + { + /* Increment number of physical pages */ + NumberOfPhysicalPages += MemoryDescriptor->PageCount; + } + + /* Find lowest physical page */ + if(MemoryDescriptor->BasePage < LowestPhysicalPage) + { + /* Update lowest physical page */ + LowestPhysicalPage = MemoryDescriptor->BasePage; + } + + /* Find highest physical page */ + if(MemoryDescriptor->BasePage + MemoryDescriptor->PageCount > HighestPhysicalPage) + { + /* Update highest physical page */ + HighestPhysicalPage = (MemoryDescriptor->BasePage + MemoryDescriptor->PageCount) - 1; + } + + /* Check if memory type should be considered as free */ + if(VerifyMemoryTypeFree(MemoryDescriptor->MemoryType)) + { + /* Check if this descriptor contains more free pages */ + if(MemoryDescriptor->PageCount >= FreePages) + { + /* Update free descriptor */ + FreePages = MemoryDescriptor->PageCount; + FreeDescriptor = MemoryDescriptor; + } + } + + /* Get next memory descriptor */ + MemoryMappings = MemoryMappings->Flink; + } + + /* Store original free descriptor */ + RTL::Memory::CopyMemory(&OldFreeDescriptor, FreeDescriptor, sizeof(LOADER_MEMORY_DESCRIPTOR)); +} -- 2.52.0 From 17b564936227c0af714d4ece3d70e1ad43c86714 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Sat, 13 Dec 2025 20:50:32 +0100 Subject: [PATCH 030/166] Make memory type verification helpers accessible to PFN --- xtoskrnl/includes/mm/mmgr.hh | 2 -- xtoskrnl/mm/mmgr.cc | 2 +- xtoskrnl/mm/pfn.cc | 4 ++-- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/xtoskrnl/includes/mm/mmgr.hh b/xtoskrnl/includes/mm/mmgr.hh index 9a05a9d..8ae98f9 100644 --- a/xtoskrnl/includes/mm/mmgr.hh +++ b/xtoskrnl/includes/mm/mmgr.hh @@ -19,8 +19,6 @@ namespace MM { public: STATIC XTAPI VOID InitializeMemoryManager(VOID); - - private: STATIC XTAPI BOOLEAN VerifyMemoryTypeFree(LOADER_MEMORY_TYPE MemoryType); STATIC XTAPI BOOLEAN VerifyMemoryTypeInvisible(LOADER_MEMORY_TYPE MemoryType); }; diff --git a/xtoskrnl/mm/mmgr.cc b/xtoskrnl/mm/mmgr.cc index 218eab9..4a77196 100644 --- a/xtoskrnl/mm/mmgr.cc +++ b/xtoskrnl/mm/mmgr.cc @@ -22,7 +22,7 @@ VOID MM::Manager::InitializeMemoryManager(VOID) { /* Scan memory descriptors provided by the boot loader */ - ScanMemoryDescriptors(); + MM::Pfn::ScanMemoryDescriptors(); /* Check if there are enough physical pages */ if(NumberOfPhysicalPages < MM_MINIMUM_PHYSICAL_PAGES) diff --git a/xtoskrnl/mm/pfn.cc b/xtoskrnl/mm/pfn.cc index 78f6713..555fc3b 100644 --- a/xtoskrnl/mm/pfn.cc +++ b/xtoskrnl/mm/pfn.cc @@ -39,7 +39,7 @@ MM::Pfn::ScanMemoryDescriptors(VOID) MemoryDescriptor = CONTAIN_RECORD(MemoryMappings, LOADER_MEMORY_DESCRIPTOR, ListEntry); /* Check if memory type is invisible or cached */ - if(VerifyMemoryTypeInvisible(MemoryDescriptor->MemoryType) || + if(MM::Manager::VerifyMemoryTypeInvisible(MemoryDescriptor->MemoryType) || (MemoryDescriptor->MemoryType == LoaderHardwareCachedMemory)) { /* Skip this mapping */ @@ -69,7 +69,7 @@ MM::Pfn::ScanMemoryDescriptors(VOID) } /* Check if memory type should be considered as free */ - if(VerifyMemoryTypeFree(MemoryDescriptor->MemoryType)) + if(MM::Manager::VerifyMemoryTypeFree(MemoryDescriptor->MemoryType)) { /* Check if this descriptor contains more free pages */ if(MemoryDescriptor->PageCount >= FreePages) -- 2.52.0 From eae48320f33dd586190272a677522f0674f5f90a Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Sat, 13 Dec 2025 21:01:13 +0100 Subject: [PATCH 031/166] Harden PFN initialization and expose page count --- xtoskrnl/includes/mm/pfn.hh | 3 +- xtoskrnl/mm/data.cc | 4 +-- xtoskrnl/mm/mmgr.cc | 2 +- xtoskrnl/mm/pfn.cc | 58 +++++++++++++++++++++++++------------ 4 files changed, 45 insertions(+), 22 deletions(-) diff --git a/xtoskrnl/includes/mm/pfn.hh b/xtoskrnl/includes/mm/pfn.hh index d8806d9..543d958 100644 --- a/xtoskrnl/includes/mm/pfn.hh +++ b/xtoskrnl/includes/mm/pfn.hh @@ -22,9 +22,10 @@ namespace MM STATIC ULONG_PTR HighestPhysicalPage; STATIC ULONG_PTR LowestPhysicalPage; STATIC ULONG NumberOfPhysicalPages; - STATIC LOADER_MEMORY_DESCRIPTOR OldFreeDescriptor; + STATIC LOADER_MEMORY_DESCRIPTOR OriginalFreeDescriptor; public: + STATIC XTAPI ULONG GetNumberOfPhysicalPages(VOID); STATIC XTAPI VOID ScanMemoryDescriptors(VOID); }; } diff --git a/xtoskrnl/mm/data.cc b/xtoskrnl/mm/data.cc index 19ea38c..c8715b2 100644 --- a/xtoskrnl/mm/data.cc +++ b/xtoskrnl/mm/data.cc @@ -22,7 +22,7 @@ ULONG MM::HardwarePool::UsedHardwareAllocationDescriptors = 0; UCHAR MM::KernelPool::ProcessorStructuresData[MAXIMUM_PROCESSORS][KPROCESSOR_STRUCTURES_SIZE] = {{0}}; /* Biggest free memory descriptor */ -PLOADER_MEMORY_DESCRIPTOR MM::Init::FreeDescriptor; +PLOADER_MEMORY_DESCRIPTOR MM::Pfn::FreeDescriptor; /* Highest physical page number */ ULONG_PTR MM::Pfn::HighestPhysicalPage; @@ -34,7 +34,7 @@ ULONG_PTR MM::Pfn::LowestPhysicalPage = -1; ULONG MM::Pfn::NumberOfPhysicalPages; /* Old biggest free memory descriptor */ -LOADER_MEMORY_DESCRIPTOR MM::Pfn::OldFreeDescriptor; +LOADER_MEMORY_DESCRIPTOR MM::Pfn::OriginalFreeDescriptor; /* Instance of the page map routines for the current PML level */ MM::PPAGEMAP MM::Paging::PmlRoutines; diff --git a/xtoskrnl/mm/mmgr.cc b/xtoskrnl/mm/mmgr.cc index 4a77196..ab192ab 100644 --- a/xtoskrnl/mm/mmgr.cc +++ b/xtoskrnl/mm/mmgr.cc @@ -25,7 +25,7 @@ MM::Manager::InitializeMemoryManager(VOID) MM::Pfn::ScanMemoryDescriptors(); /* Check if there are enough physical pages */ - if(NumberOfPhysicalPages < MM_MINIMUM_PHYSICAL_PAGES) + if(MM::Pfn::GetNumberOfPhysicalPages() < MM_MINIMUM_PHYSICAL_PAGES) { /* Insufficient physical pages, kernel panic */ DebugPrint(L"Insufficient physical pages! Install additional memory\n"); diff --git a/xtoskrnl/mm/pfn.cc b/xtoskrnl/mm/pfn.cc index 555fc3b..ac58496 100644 --- a/xtoskrnl/mm/pfn.cc +++ b/xtoskrnl/mm/pfn.cc @@ -10,6 +10,21 @@ #include +/** + * Retrieves the total number of physical pages managed by the system. + * + * @return Returns the total count of physical memory pages. + * + * @since XT 1.0 + */ +XTAPI +ULONG +MM::Pfn::GetNumberOfPhysicalPages(VOID) +{ + /* Return the number of physical pages */ + return NumberOfPhysicalPages; +} + /** * Scans memory descriptors provided by the boot loader. * @@ -28,53 +43,53 @@ MM::Pfn::ScanMemoryDescriptors(VOID) /* Initially, set number of free pages to 0 */ FreePages = 0; - /* Get a list of memory descriptors provided by the boot loader */ + /* Get the list head of memory descriptors */ LoaderMemoryDescriptors = KE::BootInformation::GetMemoryDescriptors(); - /* Iterate through memory mappings provided by the boot loader */ + /* Iterate through the memory descriptors */ MemoryMappings = LoaderMemoryDescriptors->Flink; while(MemoryMappings != LoaderMemoryDescriptors) { - /* Get memory descriptor */ + /* Get the memory descriptor */ MemoryDescriptor = CONTAIN_RECORD(MemoryMappings, LOADER_MEMORY_DESCRIPTOR, ListEntry); - /* Check if memory type is invisible or cached */ + /* Skip invisible or hardware cached memory regions */ if(MM::Manager::VerifyMemoryTypeInvisible(MemoryDescriptor->MemoryType) || - (MemoryDescriptor->MemoryType == LoaderHardwareCachedMemory)) + (MemoryDescriptor->MemoryType == LoaderHardwareCachedMemory)) { - /* Skip this mapping */ + /* Move to the next descriptor and skip further processing */ MemoryMappings = MemoryMappings->Flink; continue; } - /* Make sure that memory type is not bad */ + /* Count the number of physical pages, excluding bad memory */ if(MemoryDescriptor->MemoryType != LoaderBad) { - /* Increment number of physical pages */ + /* Add the pages from this descriptor to the total count */ NumberOfPhysicalPages += MemoryDescriptor->PageCount; } - /* Find lowest physical page */ + /* Check if this physical page is the lowest one yet */ if(MemoryDescriptor->BasePage < LowestPhysicalPage) { - /* Update lowest physical page */ + /* Update the lowest physical page number found so far */ LowestPhysicalPage = MemoryDescriptor->BasePage; } - /* Find highest physical page */ - if(MemoryDescriptor->BasePage + MemoryDescriptor->PageCount > HighestPhysicalPage) + /* Check if this physical page is the highest one yet */ + if((MemoryDescriptor->BasePage + MemoryDescriptor->PageCount) > HighestPhysicalPage) { - /* Update highest physical page */ + /* Update the highest physical page number found so far */ HighestPhysicalPage = (MemoryDescriptor->BasePage + MemoryDescriptor->PageCount) - 1; } - /* Check if memory type should be considered as free */ + /* Identify the largest block of free memory */ if(MM::Manager::VerifyMemoryTypeFree(MemoryDescriptor->MemoryType)) { - /* Check if this descriptor contains more free pages */ + /* Check if this free memory block is the largest one yet */ if(MemoryDescriptor->PageCount >= FreePages) { - /* Update free descriptor */ + /* Update the largest free block size and save the descriptor */ FreePages = MemoryDescriptor->PageCount; FreeDescriptor = MemoryDescriptor; } @@ -84,6 +99,13 @@ MM::Pfn::ScanMemoryDescriptors(VOID) MemoryMappings = MemoryMappings->Flink; } - /* Store original free descriptor */ - RTL::Memory::CopyMemory(&OldFreeDescriptor, FreeDescriptor, sizeof(LOADER_MEMORY_DESCRIPTOR)); + /* Ensure a free memory descriptor was found */ + if(!FreeDescriptor) + { + /* No free memory available to bootstrap the system */ + KE::Crash::Panic(0); + } + + /* Save a copy of the original free descriptor before it gets modified */ + RTL::Memory::CopyMemory(&OriginalFreeDescriptor, FreeDescriptor, sizeof(LOADER_MEMORY_DESCRIPTOR)); } -- 2.52.0 From b7bbf9ffa8d31c02721bf04bbc3ec134183666be Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Sat, 13 Dec 2025 21:04:55 +0100 Subject: [PATCH 032/166] Tidy up memory type verification helpers --- xtoskrnl/mm/mmgr.cc | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/xtoskrnl/mm/mmgr.cc b/xtoskrnl/mm/mmgr.cc index ab192ab..5297ab8 100644 --- a/xtoskrnl/mm/mmgr.cc +++ b/xtoskrnl/mm/mmgr.cc @@ -33,7 +33,8 @@ MM::Manager::InitializeMemoryManager(VOID) } } -/** Checks whether the specified memory type should be considered as free. +/** + * Checks whether the specified memory type should be considered as free. * * @param MemoryType * Specifies the memory type to verify. @@ -46,8 +47,10 @@ XTAPI BOOLEAN MM::Manager::VerifyMemoryTypeFree(LOADER_MEMORY_TYPE MemoryType) { - return ((MemoryType == LoaderFree) || (MemoryType == LoaderFirmwareTemporary) || - (MemoryType == LoaderLoadedProgram) || (MemoryType == LoaderOsloaderStack)); + return ((MemoryType == LoaderFirmwareTemporary) || + (MemoryType == LoaderFree) || + (MemoryType == LoaderLoadedProgram) || + (MemoryType == LoaderOsloaderStack)); } /** @@ -64,7 +67,7 @@ XTAPI BOOLEAN MM::Manager::VerifyMemoryTypeInvisible(LOADER_MEMORY_TYPE MemoryType) { - return ((MemoryType == LoaderFirmwarePermanent) || - (MemoryType == LoaderSpecialMemory) || - (MemoryType == LoaderBBTMemory)); + return ((MemoryType == LoaderBBTMemory) || + (MemoryType == LoaderFirmwarePermanent) || + (MemoryType == LoaderSpecialMemory)); } -- 2.52.0 From 5224dc315f41d6354d9c12c9304aa79013eed935 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Sat, 13 Dec 2025 22:50:27 +0100 Subject: [PATCH 033/166] Compute PFN database size during MM initialization --- xtoskrnl/includes/mm/pfn.hh | 3 +++ xtoskrnl/mm/mmgr.cc | 3 +++ xtoskrnl/mm/pfn.cc | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 38 insertions(+) diff --git a/xtoskrnl/includes/mm/pfn.hh b/xtoskrnl/includes/mm/pfn.hh index 543d958..8682d0d 100644 --- a/xtoskrnl/includes/mm/pfn.hh +++ b/xtoskrnl/includes/mm/pfn.hh @@ -23,9 +23,12 @@ namespace MM STATIC ULONG_PTR LowestPhysicalPage; STATIC ULONG NumberOfPhysicalPages; STATIC LOADER_MEMORY_DESCRIPTOR OriginalFreeDescriptor; + STATIC PFN_NUMBER PfnDatabaseSize; public: + STATIC XTAPI VOID ComputePfnDatabaseSize(VOID); STATIC XTAPI ULONG GetNumberOfPhysicalPages(VOID); + STATIC XTAPI PFN_NUMBER GetPfnDatabaseSize(VOID); STATIC XTAPI VOID ScanMemoryDescriptors(VOID); }; } diff --git a/xtoskrnl/mm/mmgr.cc b/xtoskrnl/mm/mmgr.cc index 5297ab8..9c9aea1 100644 --- a/xtoskrnl/mm/mmgr.cc +++ b/xtoskrnl/mm/mmgr.cc @@ -31,6 +31,9 @@ MM::Manager::InitializeMemoryManager(VOID) DebugPrint(L"Insufficient physical pages! Install additional memory\n"); KE::Crash::Panic(0); } + + /* Compute allocation size for the PFN database */ + MM::Pfn::ComputePfnDatabaseSize(); } /** diff --git a/xtoskrnl/mm/pfn.cc b/xtoskrnl/mm/pfn.cc index ac58496..84ead54 100644 --- a/xtoskrnl/mm/pfn.cc +++ b/xtoskrnl/mm/pfn.cc @@ -10,6 +10,23 @@ #include +/** + * Calculates the total number of pages required for the PFN database and its associated color tables. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::Pfn::ComputePfnDatabaseSize(VOID) +{ + /* Calculate the total number of pages required for the PFN database */ + PfnDatabaseSize = (HighestPhysicalPage + 1) * sizeof(MMPFN); + PfnDatabaseSize = ROUND_UP(PfnDatabaseSize, MM_PAGE_SIZE); + PfnDatabaseSize >>= MM_PAGE_SHIFT; +} + /** * Retrieves the total number of physical pages managed by the system. * @@ -25,6 +42,21 @@ MM::Pfn::GetNumberOfPhysicalPages(VOID) return NumberOfPhysicalPages; } +/** + * Gets the size of the PFN database and its associated structures, in pages. + * + * @return This routine returns the total number of pages required for the PFN database and its associated structures. + * + * @since XT 1.0 + */ +XTAPI +PFN_NUMBER +MM::Pfn::GetPfnDatabaseSize(VOID) +{ + /* Return the pre-calculated size of the PFN database in pages */ + return PfnDatabaseSize; +} + /** * Scans memory descriptors provided by the boot loader. * -- 2.52.0 From 070c508e4217f7968999036b377da12056284355 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Sun, 14 Dec 2025 15:35:24 +0100 Subject: [PATCH 034/166] Introduce kernel virtual memory layout --- sdk/xtdk/mmtypes.h | 12 +++++++ sdk/xtdk/xtstruct.h | 1 + xtoskrnl/includes/mm/mmgr.hh | 7 ++++- xtoskrnl/mm/mmgr.cc | 61 ++++++++++++++++++++++++++++++++++++ 4 files changed, 80 insertions(+), 1 deletion(-) diff --git a/sdk/xtdk/mmtypes.h b/sdk/xtdk/mmtypes.h index 010b33a..efb218c 100644 --- a/sdk/xtdk/mmtypes.h +++ b/sdk/xtdk/mmtypes.h @@ -4,6 +4,7 @@ * FILE: sdk/xtdk/mmtypes.h * DESCRIPTION: Memory management data structures * DEVELOPERS: Rafal Kupiec + * Aiken Harris */ #ifndef __XTDK_MMTYPES_H @@ -51,6 +52,17 @@ typedef struct _MMCOLOR_TABLES ULONG_PTR Count; } MMCOLOR_TABLES, *PMMCOLOR_TABLES; +/* Memory layout structure definition */ +typedef struct _MMMEMORY_LAYOUT +{ + PMMPFN PfnDatabaseAddress; + PVOID SelfMapAddress; + PVOID NonPagedPoolStart; + PVOID NonPagedPoolEnd; + PVOID PagedPoolStart; + PVOID PagedPoolEnd; +} MMMEMORY_LAYOUT, *PMMMEMORY_LAYOUT; + /* Page Frame Entry structure definition */ typedef struct _MMPFNENTRY { diff --git a/sdk/xtdk/xtstruct.h b/sdk/xtdk/xtstruct.h index 64442b4..3b2203d 100644 --- a/sdk/xtdk/xtstruct.h +++ b/sdk/xtdk/xtstruct.h @@ -276,6 +276,7 @@ typedef struct _LOADER_INFORMATION_BLOCK LOADER_INFORMATION_BLOCK, *PLOADER_INFO typedef struct _LOADER_MEMORY_DESCRIPTOR LOADER_MEMORY_DESCRIPTOR, *PLOADER_MEMORY_DESCRIPTOR; typedef struct _M128 M128, *PM128; typedef struct _MMCOLOR_TABLES MMCOLOR_TABLES, *PMMCOLOR_TABLES; +typedef struct _MMMEMORY_LAYOUT MMMEMORY_LAYOUT, *PMMMEMORY_LAYOUT; typedef struct _MMPFNENTRY MMPFNENTRY, *PMMPFNENTRY; typedef struct _MMPFNLIST MMPFNLIST, *PMMPFNLIST; typedef struct _PCAT_FIRMWARE_INFORMATION PCAT_FIRMWARE_INFORMATION, *PPCAT_FIRMWARE_INFORMATION; diff --git a/xtoskrnl/includes/mm/mmgr.hh b/xtoskrnl/includes/mm/mmgr.hh index 8ae98f9..7794b72 100644 --- a/xtoskrnl/includes/mm/mmgr.hh +++ b/xtoskrnl/includes/mm/mmgr.hh @@ -2,7 +2,7 @@ * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/mm/mmgr.hh - * DESCRIPTION: Memory Manager + * DESCRIPTION: Memory manager * DEVELOPERS: Aiken Harris */ @@ -17,7 +17,12 @@ namespace MM { class Manager { + private: + STATIC MMMEMORY_LAYOUT MemoryLayout; + public: + STATIC XTAPI PMMMEMORY_LAYOUT GetMemoryLayout(VOID); + STATIC XTAPI VOID InitializeMemoryLayout(VOID); STATIC XTAPI VOID InitializeMemoryManager(VOID); STATIC XTAPI BOOLEAN VerifyMemoryTypeFree(LOADER_MEMORY_TYPE MemoryType); STATIC XTAPI BOOLEAN VerifyMemoryTypeInvisible(LOADER_MEMORY_TYPE MemoryType); diff --git a/xtoskrnl/mm/mmgr.cc b/xtoskrnl/mm/mmgr.cc index 9c9aea1..f08e6a6 100644 --- a/xtoskrnl/mm/mmgr.cc +++ b/xtoskrnl/mm/mmgr.cc @@ -10,6 +10,64 @@ #include +/** + * Retrieves a pointer to the system's virtual memory layout structure. + * + * @return This routine returns a pointer to the memory layout structure. + * + * @since XT 1.0 + */ +XTAPI +PMMMEMORY_LAYOUT +MM::Manager::GetMemoryLayout(VOID) +{ + /* Return a pointer to the global memory layout structure */ + return &MemoryLayout; +} + +/** + * Initializes the kernel's virtual memory layout. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::Manager::InitializeMemoryLayout(VOID) +{ + ULONG_PTR PagedPoolSize, PteCount; + PFN_NUMBER PfnDatabaseSize; + + /* Calculate size of paged pool (at least 32MiB) */ + PteCount = ((SIZE_TO_PAGES(33554432) + (MM_PTE_PER_PAGE - 1)) / MM_PTE_PER_PAGE); + PagedPoolSize = PteCount * MM_PTE_PER_PAGE * MM_PAGE_SIZE; + + /* Retrieve the PFN database size */ + PfnDatabaseSize = MM::Pfn::GetPfnDatabaseSize(); + + if(MM::Paging::GetXpaStatus()) + { + MemoryLayout.PfnDatabaseAddress = (PMMPFN)0xFFFEFA8000000000ULL; + MemoryLayout.SelfMapAddress = (PVOID)0xFFEDF6FB7DBEDF68ULL; + + MemoryLayout.NonPagedPoolStart = (PVOID)((ULONG_PTR)MemoryLayout.PfnDatabaseAddress + PfnDatabaseSize * MM_PAGE_SIZE); + MemoryLayout.NonPagedPoolEnd = (PVOID)0xFFFEFFFFFFBFFFFFULL; + MemoryLayout.PagedPoolStart = (PVOID)0xFFFEF8A000000000ULL; + MemoryLayout.PagedPoolEnd = (PVOID)(((ULONG_PTR)MemoryLayout.PagedPoolStart + PagedPoolSize) - 1); + } + else + { + MemoryLayout.PfnDatabaseAddress = (PMMPFN)0xFFFFFA8000000000ULL; + MemoryLayout.SelfMapAddress = (PVOID)0xFFFFF6FB7DBEDF68ULL; + + MemoryLayout.NonPagedPoolStart = (PVOID)((ULONG_PTR)MemoryLayout.PfnDatabaseAddress + PfnDatabaseSize * MM_PAGE_SIZE); + MemoryLayout.NonPagedPoolEnd = (PVOID)0xFFFFFFFFFFBFFFFFULL; + MemoryLayout.PagedPoolStart = (PVOID)0xFFFFF8A000000000ULL; + MemoryLayout.PagedPoolEnd = (PVOID)(((ULONG_PTR)MemoryLayout.PagedPoolStart + PagedPoolSize) - 1); + } +} + /** * Performs an early initialization of the XTOS Memory Manager. * @@ -34,6 +92,9 @@ MM::Manager::InitializeMemoryManager(VOID) /* Compute allocation size for the PFN database */ MM::Pfn::ComputePfnDatabaseSize(); + + /* Initialize memory layout */ + InitializeMemoryLayout(); } /** -- 2.52.0 From 5cf3dfa8447cc939a7389ec8e0397e35dd051507 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Mon, 15 Dec 2025 12:38:08 +0100 Subject: [PATCH 035/166] Add bootstrap physical page allocator --- xtoskrnl/includes/mm/pfn.hh | 1 + xtoskrnl/mm/pfn.cc | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/xtoskrnl/includes/mm/pfn.hh b/xtoskrnl/includes/mm/pfn.hh index 8682d0d..3fc0eff 100644 --- a/xtoskrnl/includes/mm/pfn.hh +++ b/xtoskrnl/includes/mm/pfn.hh @@ -26,6 +26,7 @@ namespace MM STATIC PFN_NUMBER PfnDatabaseSize; public: + STATIC XTAPI PFN_NUMBER AllocateBootstrapPages(IN PFN_NUMBER NumberOfPages); STATIC XTAPI VOID ComputePfnDatabaseSize(VOID); STATIC XTAPI ULONG GetNumberOfPhysicalPages(VOID); STATIC XTAPI PFN_NUMBER GetPfnDatabaseSize(VOID); diff --git a/xtoskrnl/mm/pfn.cc b/xtoskrnl/mm/pfn.cc index 84ead54..324f569 100644 --- a/xtoskrnl/mm/pfn.cc +++ b/xtoskrnl/mm/pfn.cc @@ -10,6 +10,39 @@ #include +/** + * Allocates a block of physical pages for early kernel initialization. + * + * @param NumberOfPages + * The number of physical pages to allocate. + * + * @return This routine returns the base page frame number (PFN) of the allocated block. + * + * @since XT 1.0 + */ +XTAPI +PFN_NUMBER +MM::Pfn::AllocateBootstrapPages(IN PFN_NUMBER NumberOfPages) +{ + PFN_NUMBER Pfn; + + /* Check if the largest free memory block has enough pages */ + if(NumberOfPages > FreeDescriptor->PageCount) + { + /* Not enough physical memory available, kernel panic */ + DebugPrint(L"Insufficient physical pages! Install additional memory\n"); + KE::Crash::Panic(0); + } + + /* Allocate pages from the beginning of the free descriptor */ + Pfn = FreeDescriptor->BasePage; + FreeDescriptor->BasePage += NumberOfPages; + FreeDescriptor->PageCount -= NumberOfPages; + + /* Return the base page frame number of the allocated block */ + return Pfn; +} + /** * Calculates the total number of pages required for the PFN database and its associated color tables. * -- 2.52.0 From 36c273ea13f0d341cb3fcdb16d7eb094e81c2430 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Mon, 15 Dec 2025 13:24:02 +0100 Subject: [PATCH 036/166] Implement early page table mapping routines --- xtoskrnl/CMakeLists.txt | 1 + xtoskrnl/includes/mm.hh | 1 + xtoskrnl/includes/mm/pte.hh | 39 ++++++ xtoskrnl/mm/pte.cc | 245 ++++++++++++++++++++++++++++++++++++ 4 files changed, 286 insertions(+) create mode 100644 xtoskrnl/includes/mm/pte.hh create mode 100644 xtoskrnl/mm/pte.cc diff --git a/xtoskrnl/CMakeLists.txt b/xtoskrnl/CMakeLists.txt index 082b386..08266ea 100644 --- a/xtoskrnl/CMakeLists.txt +++ b/xtoskrnl/CMakeLists.txt @@ -59,6 +59,7 @@ list(APPEND XTOSKRNL_SOURCE ${XTOSKRNL_SOURCE_DIR}/mm/mmgr.cc ${XTOSKRNL_SOURCE_DIR}/mm/paging.cc ${XTOSKRNL_SOURCE_DIR}/mm/pfn.cc + ${XTOSKRNL_SOURCE_DIR}/mm/pte.cc ${XTOSKRNL_SOURCE_DIR}/po/idle.cc ${XTOSKRNL_SOURCE_DIR}/rtl/${ARCH}/dispatch.cc ${XTOSKRNL_SOURCE_DIR}/rtl/${ARCH}/exsup.cc diff --git a/xtoskrnl/includes/mm.hh b/xtoskrnl/includes/mm.hh index 2a25fd6..a8cb42e 100644 --- a/xtoskrnl/includes/mm.hh +++ b/xtoskrnl/includes/mm.hh @@ -18,5 +18,6 @@ #include #include #include +#include #endif /* __XTOSKRNL_MM_HH */ diff --git a/xtoskrnl/includes/mm/pte.hh b/xtoskrnl/includes/mm/pte.hh new file mode 100644 index 0000000..fc7f96f --- /dev/null +++ b/xtoskrnl/includes/mm/pte.hh @@ -0,0 +1,39 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: xtoskrnl/includes/mm/pte.hh + * DESCRIPTION: Page table entry (PTE) support + * DEVELOPERS: Aiken Harris + */ + +#ifndef __XTOSKRNL_MM_PTE_HH +#define __XTOSKRNL_MM_PTE_HH + +#include + + +/* Memory Manager */ +namespace MM +{ + class Pte + { + public: + STATIC XTAPI VOID MapP5E(PVOID StartAddress, + PVOID EndAddress, + PMMP5E TemplateP5e); + STATIC XTAPI VOID MapPDE(PVOID StartAddress, + PVOID EndAddress, + PMMPDE TemplatePde); + STATIC XTAPI VOID MapPPE(PVOID StartAddress, + PVOID EndAddress, + PMMPPE TemplatePpe); + STATIC XTAPI VOID MapPTE(PVOID StartAddress, + PVOID EndAddress, + PMMPTE TemplatePte); + STATIC XTAPI VOID MapPXE(PVOID StartAddress, + PVOID EndAddress, + PMMPXE TemplatePxe); + }; +} + +#endif /* __XTOSKRNL_MM_PTE_HH */ diff --git a/xtoskrnl/mm/pte.cc b/xtoskrnl/mm/pte.cc new file mode 100644 index 0000000..c460807 --- /dev/null +++ b/xtoskrnl/mm/pte.cc @@ -0,0 +1,245 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: xtoskrnl/mm/pte.cc + * DESCRIPTION: Page table entry (PTE) support + * DEVELOPERS: Aiken Harris + */ + +#include + + +/** + * Maps a range of virtual addresses at the P5E (PML5) level. + * + * @param StartAddress + * The beginning of the virtual address range to map. + * + * @param EndAddress + * The end of the virtual address range to map. + * + * @param TemplateP5e + * A template P5E to use for creating new entries. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::Pte::MapP5E(PVOID StartAddress, + PVOID EndAddress, + PMMP5E TemplateP5e) +{ + PMMP5E EndSpace, PointerP5e; + + /* Get P5E addresses */ + PointerP5e = MM::Paging::GetP5eAddress(StartAddress); + EndSpace = MM::Paging::GetP5eAddress(EndAddress); + + /* Iterate over all P5Es */ + while(PointerP5e <= EndSpace) + { + /* Check if P5E is already mapped */ + if(!MM::Paging::PteValid(PointerP5e)) + { + /* Map P5E */ + MM::Paging::SetPte(TemplateP5e, MM::Pfn::AllocateBootstrapPages(1), 0); + *PointerP5e = *TemplateP5e; + + /* Clear the page table */ + RtlZeroMemory(MM::Paging::GetPteVirtualAddress(PointerP5e), MM_PAGE_SIZE); + } + + /* Get next table entry */ + PointerP5e = MM::Paging::GetNextPte(PointerP5e); + } +} + +/** + * Maps a range of virtual addresses at the PDE (Page Directory Entry) level. + * + * @param StartAddress + * The beginning of the virtual address range to map. + * + * @param EndAddress + * The end of the virtual address range to map. + * + * @param TemplatePde + * A template PDE to use for creating new entries. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::Pte::MapPDE(PVOID StartAddress, + PVOID EndAddress, + PMMPDE TemplatePde) +{ + PMMPDE EndSpace, PointerPde; + + /* Get PDE addresses */ + PointerPde = MM::Paging::GetPdeAddress(StartAddress); + EndSpace = MM::Paging::GetPdeAddress(EndAddress); + + /* Iterate over all PDEs */ + while(PointerPde <= EndSpace) + { + /* Check if PDE is already mapped */ + if(!MM::Paging::PteValid(PointerPde)) + { + /* Map PDE */ + MM::Paging::SetPte(TemplatePde, MM::Pfn::AllocateBootstrapPages(1), 0); + *PointerPde = *TemplatePde; + + /* Clear the page table */ + RtlZeroMemory(MM::Paging::GetPteVirtualAddress(PointerPde), MM_PAGE_SIZE); + } + + /* Get next table entry */ + PointerPde = MM::Paging::GetNextPte(PointerPde); + } +} + +/** + * Maps a range of virtual addresses at the PPE (Page Directory Pointer Entry) level. + * + * @param StartAddress + * The beginning of the virtual address range to map. + * + * @param EndAddress + * The end of the virtual address range to map. + * + * @param TemplatePpe + * A template PPE to use for creating new entries. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::Pte::MapPPE(PVOID StartAddress, + PVOID EndAddress, + PMMPPE TemplatePpe) +{ + PMMPPE EndSpace, PointerPpe; + + /* Get PPE addresses */ + PointerPpe = MM::Paging::GetPpeAddress(StartAddress); + EndSpace = MM::Paging::GetPpeAddress(EndAddress); + + /* Iterate over all PPEs */ + while(PointerPpe <= EndSpace) + { + /* Check if PPE is already mapped */ + if(!MM::Paging::PteValid(PointerPpe)) + { + /* Map PPE */ + MM::Paging::SetPte(TemplatePpe, MM::Pfn::AllocateBootstrapPages(1), 0); + *PointerPpe = *TemplatePpe; + + /* Clear the page table */ + RtlZeroMemory(MM::Paging::GetPteVirtualAddress(PointerPpe), MM_PAGE_SIZE); + } + + /* Get next table entry */ + PointerPpe = MM::Paging::GetNextPte(PointerPpe); + } +} + +/** + * Maps a range of virtual addresses at the PTE (Page Table Entry) level. + * + * @param StartAddress + * The beginning of the virtual address range to map. + * + * @param EndAddress + * The end of the virtual address range to map. + * + * @param TemplatePte + * A template PTE to use for creating new entries. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::Pte::MapPTE(PVOID StartAddress, + PVOID EndAddress, + PMMPTE TemplatePte) +{ + PMMPTE EndSpace, PointerPte; + + /* Get PTE addresses */ + PointerPte = MM::Paging::GetPteAddress(StartAddress); + EndSpace = MM::Paging::GetPteAddress(EndAddress); + + /* Iterate over all PTEs */ + while(PointerPte <= EndSpace) + { + /* Check if PTE is already mapped */ + if(!MM::Paging::PteValid(PointerPte)) + { + /* Map PTE */ + MM::Paging::SetPte(TemplatePte, MM::Pfn::AllocateBootstrapPages(1), 0); + *PointerPte = *TemplatePte; + + /* Clear the page table */ + RtlZeroMemory(MM::Paging::GetPteVirtualAddress(PointerPte), MM_PAGE_SIZE); + } + + /* Get next table entry */ + PointerPte = MM::Paging::GetNextPte(PointerPte); + } +} + +/** + * Maps a range of virtual addresses at the PXE (PML4) level. + * + * @param StartAddress + * The beginning of the virtual address range to map. + * + * @param EndAddress + * The end of the virtual address range to map. + * + * @param TemplatePxe + * A template PXE to use for creating new entries. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::Pte::MapPXE(PVOID StartAddress, + PVOID EndAddress, + PMMPXE TemplatePxe) +{ + PMMPXE EndSpace, PointerPxe; + + /* Get PXE addresses */ + PointerPxe = MM::Paging::GetPxeAddress(StartAddress); + EndSpace = MM::Paging::GetPxeAddress(EndAddress); + + /* Iterate over all PTEs */ + while(PointerPxe <= EndSpace) + { + /* Check if PTE is already mapped */ + if(!MM::Paging::PteValid(PointerPxe)) + { + /* Map PTE */ + MM::Paging::SetPte(TemplatePxe, MM::Pfn::AllocateBootstrapPages(1), 0); + *PointerPxe = *TemplatePxe; + + /* Clear the page table */ + RtlZeroMemory(MM::Paging::GetPteVirtualAddress(PointerPxe), MM_PAGE_SIZE); + } + + /* Get next table entry */ + PointerPxe = MM::Paging::GetNextPte(PointerPxe); + } +} -- 2.52.0 From 7f0ca6a948cff47c563425f95a0f71a617448335 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Mon, 15 Dec 2025 13:56:39 +0100 Subject: [PATCH 037/166] Compute PTE count per page from entry size --- sdk/xtdk/amd64/mmtypes.h | 6 ------ xtoskrnl/includes/mm/pte.hh | 1 + xtoskrnl/mm/mmgr.cc | 8 +++++--- xtoskrnl/mm/pte.cc | 15 +++++++++++++++ 4 files changed, 21 insertions(+), 9 deletions(-) diff --git a/sdk/xtdk/amd64/mmtypes.h b/sdk/xtdk/amd64/mmtypes.h index c6211c7..9479175 100644 --- a/sdk/xtdk/amd64/mmtypes.h +++ b/sdk/xtdk/amd64/mmtypes.h @@ -43,12 +43,6 @@ #define MM_PXI_SHIFT 39 #define MM_P5I_SHIFT 48 -/* Number of PTEs per page */ -#define MM_PTE_PER_PAGE 512 -#define MM_PDE_PER_PAGE 512 -#define MM_PPE_PER_PAGE 512 -#define MM_PXE_PER_PAGE 512 - /* PTE state flags */ #define MM_PTE_VALID 0x0000000000000001ULL #define MM_PTE_ACCESSED 0x0000000000000020ULL diff --git a/xtoskrnl/includes/mm/pte.hh b/xtoskrnl/includes/mm/pte.hh index fc7f96f..e43d1fe 100644 --- a/xtoskrnl/includes/mm/pte.hh +++ b/xtoskrnl/includes/mm/pte.hh @@ -18,6 +18,7 @@ namespace MM class Pte { public: + STATIC XTAPI ULONG GetPtesPerPage(VOID); STATIC XTAPI VOID MapP5E(PVOID StartAddress, PVOID EndAddress, PMMP5E TemplateP5e); diff --git a/xtoskrnl/mm/mmgr.cc b/xtoskrnl/mm/mmgr.cc index f08e6a6..79af5a4 100644 --- a/xtoskrnl/mm/mmgr.cc +++ b/xtoskrnl/mm/mmgr.cc @@ -38,10 +38,12 @@ MM::Manager::InitializeMemoryLayout(VOID) { ULONG_PTR PagedPoolSize, PteCount; PFN_NUMBER PfnDatabaseSize; + ULONG PtesPerPage; - /* Calculate size of paged pool (at least 32MiB) */ - PteCount = ((SIZE_TO_PAGES(33554432) + (MM_PTE_PER_PAGE - 1)) / MM_PTE_PER_PAGE); - PagedPoolSize = PteCount * MM_PTE_PER_PAGE * MM_PAGE_SIZE; + /* Get the number of PTEs per page and calculate size of paged pool (at least 32MiB) */ + PtesPerPage = MM::Pte::GetPtesPerPage(); + PteCount = ((SIZE_TO_PAGES(33554432) + (PtesPerPage - 1)) / PtesPerPage); + PagedPoolSize = PteCount * PtesPerPage * MM_PAGE_SIZE; /* Retrieve the PFN database size */ PfnDatabaseSize = MM::Pfn::GetPfnDatabaseSize(); diff --git a/xtoskrnl/mm/pte.cc b/xtoskrnl/mm/pte.cc index c460807..4d2614a 100644 --- a/xtoskrnl/mm/pte.cc +++ b/xtoskrnl/mm/pte.cc @@ -9,6 +9,21 @@ #include +/** + * Calculates the number of Page Table Entries (PTEs) that fit within a single page. + * + * @return This routine returns the number of PTEs per page. + * + * @since XT 1.0 + */ +XTAPI +ULONG +MM::Pte::GetPtesPerPage(VOID) +{ + /* Calculate and return the number of PTEs per page */ + return MM_PAGE_SIZE / MM::Paging::GetPteSize(); +} + /** * Maps a range of virtual addresses at the P5E (PML5) level. * -- 2.52.0 From dc23f911104866c708ad788cf48eda8c732fd9ce Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Tue, 16 Dec 2025 14:08:32 +0100 Subject: [PATCH 038/166] Split PTE implementation per architecture --- xtoskrnl/CMakeLists.txt | 1 + xtoskrnl/includes/mm.hh | 2 +- xtoskrnl/includes/mm/amd64/pte.hh | 40 ++++++++++ xtoskrnl/includes/mm/i686/pagemap.hh | 8 +- xtoskrnl/includes/mm/{ => i686}/pte.hh | 10 +-- xtoskrnl/mm/amd64/pte.cc | 104 +++++++++++++++++++++++++ xtoskrnl/mm/i686/pte.cc | 10 +++ xtoskrnl/mm/pte.cc | 94 ---------------------- 8 files changed, 165 insertions(+), 104 deletions(-) create mode 100644 xtoskrnl/includes/mm/amd64/pte.hh rename xtoskrnl/includes/mm/{ => i686}/pte.hh (84%) create mode 100644 xtoskrnl/mm/amd64/pte.cc create mode 100644 xtoskrnl/mm/i686/pte.cc diff --git a/xtoskrnl/CMakeLists.txt b/xtoskrnl/CMakeLists.txt index 08266ea..847c1e2 100644 --- a/xtoskrnl/CMakeLists.txt +++ b/xtoskrnl/CMakeLists.txt @@ -53,6 +53,7 @@ list(APPEND XTOSKRNL_SOURCE ${XTOSKRNL_SOURCE_DIR}/ke/timer.cc ${XTOSKRNL_SOURCE_DIR}/mm/${ARCH}/pagemap.cc ${XTOSKRNL_SOURCE_DIR}/mm/${ARCH}/paging.cc + ${XTOSKRNL_SOURCE_DIR}/mm/${ARCH}/pte.cc ${XTOSKRNL_SOURCE_DIR}/mm/data.cc ${XTOSKRNL_SOURCE_DIR}/mm/hlpool.cc ${XTOSKRNL_SOURCE_DIR}/mm/kpool.cc diff --git a/xtoskrnl/includes/mm.hh b/xtoskrnl/includes/mm.hh index a8cb42e..bd94683 100644 --- a/xtoskrnl/includes/mm.hh +++ b/xtoskrnl/includes/mm.hh @@ -13,11 +13,11 @@ #include XTOS_ARCH_HEADER(mm, pagemap.hh) #include XTOS_ARCH_HEADER(mm, paging.hh) +#include XTOS_ARCH_HEADER(mm, pte.hh) #include #include #include #include -#include #endif /* __XTOSKRNL_MM_HH */ diff --git a/xtoskrnl/includes/mm/amd64/pte.hh b/xtoskrnl/includes/mm/amd64/pte.hh new file mode 100644 index 0000000..50fefec --- /dev/null +++ b/xtoskrnl/includes/mm/amd64/pte.hh @@ -0,0 +1,40 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: xtoskrnl/includes/mm/amd64/pte.hh + * DESCRIPTION: Page table entry (PTE) for AMD64 support + * DEVELOPERS: Aiken Harris + */ + +#ifndef __XTOSKRNL_MM_AMD64_PTE_HH +#define __XTOSKRNL_MM_AMD64_PTE_HH + +#include + + +/* Memory Manager */ +namespace MM +{ + class Pte + { + public: + STATIC XTAPI ULONG GetPtesPerPage(VOID); + STATIC XTAPI VOID MapP5E(PVOID StartAddress, + PVOID EndAddress, + PMMP5E TemplateP5e); + STATIC XTAPI VOID MapPDE(PVOID StartAddress, + PVOID EndAddress, + PMMPDE TemplatePde); + STATIC XTAPI VOID MapPPE(PVOID StartAddress, + PVOID EndAddress, + PMMPPE TemplatePpe); + STATIC XTAPI VOID MapPTE(PVOID StartAddress, + PVOID EndAddress, + PMMPTE TemplatePte); + STATIC XTAPI VOID MapPXE(PVOID StartAddress, + PVOID EndAddress, + PMMPXE TemplatePxe); + }; +} + +#endif /* __XTOSKRNL_MM_AMD64_PTE_HH */ diff --git a/xtoskrnl/includes/mm/i686/pagemap.hh b/xtoskrnl/includes/mm/i686/pagemap.hh index 9233f2b..5d94662 100644 --- a/xtoskrnl/includes/mm/i686/pagemap.hh +++ b/xtoskrnl/includes/mm/i686/pagemap.hh @@ -1,13 +1,13 @@ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory - * FILE: xtoskrnl/includes/mm/pagemap.hh + * FILE: xtoskrnl/includes/mm/i686/pagemap.hh * DESCRIPTION: Low-level support for page map manipulation * DEVELOPERS: Aiken Harris */ -#ifndef __XTOSKRNL_MM_PAGEMAP_HH -#define __XTOSKRNL_MM_PAGEMAP_HH +#ifndef __XTOSKRNL_MM_I686_PAGEMAP_HH +#define __XTOSKRNL_MM_I686_PAGEMAP_HH #include @@ -109,4 +109,4 @@ namespace MM }; } -#endif /* __XTOSKRNL_MM_PAGEMAP_HH */ +#endif /* __XTOSKRNL_MM_I686_PAGEMAP_HH */ diff --git a/xtoskrnl/includes/mm/pte.hh b/xtoskrnl/includes/mm/i686/pte.hh similarity index 84% rename from xtoskrnl/includes/mm/pte.hh rename to xtoskrnl/includes/mm/i686/pte.hh index e43d1fe..1fca7b2 100644 --- a/xtoskrnl/includes/mm/pte.hh +++ b/xtoskrnl/includes/mm/i686/pte.hh @@ -1,13 +1,13 @@ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory - * FILE: xtoskrnl/includes/mm/pte.hh - * DESCRIPTION: Page table entry (PTE) support + * FILE: xtoskrnl/includes/mm/i686/pte.hh + * DESCRIPTION: Page table entry (PTE) for i686 support * DEVELOPERS: Aiken Harris */ -#ifndef __XTOSKRNL_MM_PTE_HH -#define __XTOSKRNL_MM_PTE_HH +#ifndef __XTOSKRNL_MM_I686_PTE_HH +#define __XTOSKRNL_MM_I686_PTE_HH #include @@ -37,4 +37,4 @@ namespace MM }; } -#endif /* __XTOSKRNL_MM_PTE_HH */ +#endif /* __XTOSKRNL_MM_I686_PTE_HH */ diff --git a/xtoskrnl/mm/amd64/pte.cc b/xtoskrnl/mm/amd64/pte.cc new file mode 100644 index 0000000..d74156a --- /dev/null +++ b/xtoskrnl/mm/amd64/pte.cc @@ -0,0 +1,104 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: xtoskrnl/mm/amd64/pte.cc + * DESCRIPTION: Page Table Entry (PTE) for AMD64 support + * DEVELOPERS: Aiken Harris + */ + +#include + + +/** + * Maps a range of virtual addresses at the P5E (PML5) level. + * + * @param StartAddress + * The beginning of the virtual address range to map. + * + * @param EndAddress + * The end of the virtual address range to map. + * + * @param TemplateP5e + * A template P5E to use for creating new entries. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::Pte::MapP5E(PVOID StartAddress, + PVOID EndAddress, + PMMP5E TemplateP5e) +{ + PMMP5E EndSpace, PointerP5e; + + /* Get P5E addresses */ + PointerP5e = MM::Paging::GetP5eAddress(StartAddress); + EndSpace = MM::Paging::GetP5eAddress(EndAddress); + + /* Iterate over all P5Es */ + while(PointerP5e <= EndSpace) + { + /* Check if P5E is already mapped */ + if(!MM::Paging::PteValid(PointerP5e)) + { + /* Map P5E */ + MM::Paging::SetPte(TemplateP5e, MM::Pfn::AllocateBootstrapPages(1), 0); + *PointerP5e = *TemplateP5e; + + /* Clear the page table */ + RtlZeroMemory(MM::Paging::GetPteVirtualAddress(PointerP5e), MM_PAGE_SIZE); + } + + /* Get next table entry */ + PointerP5e = MM::Paging::GetNextPte(PointerP5e); + } +} + +/** + * Maps a range of virtual addresses at the PXE (PML4) level. + * + * @param StartAddress + * The beginning of the virtual address range to map. + * + * @param EndAddress + * The end of the virtual address range to map. + * + * @param TemplatePxe + * A template PXE to use for creating new entries. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::Pte::MapPXE(PVOID StartAddress, + PVOID EndAddress, + PMMPXE TemplatePxe) +{ + PMMPXE EndSpace, PointerPxe; + + /* Get PXE addresses */ + PointerPxe = MM::Paging::GetPxeAddress(StartAddress); + EndSpace = MM::Paging::GetPxeAddress(EndAddress); + + /* Iterate over all PTEs */ + while(PointerPxe <= EndSpace) + { + /* Check if PTE is already mapped */ + if(!MM::Paging::PteValid(PointerPxe)) + { + /* Map PTE */ + MM::Paging::SetPte(TemplatePxe, MM::Pfn::AllocateBootstrapPages(1), 0); + *PointerPxe = *TemplatePxe; + + /* Clear the page table */ + RtlZeroMemory(MM::Paging::GetPteVirtualAddress(PointerPxe), MM_PAGE_SIZE); + } + + /* Get next table entry */ + PointerPxe = MM::Paging::GetNextPte(PointerPxe); + } +} diff --git a/xtoskrnl/mm/i686/pte.cc b/xtoskrnl/mm/i686/pte.cc new file mode 100644 index 0000000..97db714 --- /dev/null +++ b/xtoskrnl/mm/i686/pte.cc @@ -0,0 +1,10 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: xtoskrnl/mm/i686/pte.cc + * DESCRIPTION: Page Table Entry (PTE) for i686 support + * DEVELOPERS: Aiken Harris + */ + +#include + diff --git a/xtoskrnl/mm/pte.cc b/xtoskrnl/mm/pte.cc index 4d2614a..5123d12 100644 --- a/xtoskrnl/mm/pte.cc +++ b/xtoskrnl/mm/pte.cc @@ -24,53 +24,6 @@ MM::Pte::GetPtesPerPage(VOID) return MM_PAGE_SIZE / MM::Paging::GetPteSize(); } -/** - * Maps a range of virtual addresses at the P5E (PML5) level. - * - * @param StartAddress - * The beginning of the virtual address range to map. - * - * @param EndAddress - * The end of the virtual address range to map. - * - * @param TemplateP5e - * A template P5E to use for creating new entries. - * - * @return This routine does not return any value. - * - * @since XT 1.0 - */ -XTAPI -VOID -MM::Pte::MapP5E(PVOID StartAddress, - PVOID EndAddress, - PMMP5E TemplateP5e) -{ - PMMP5E EndSpace, PointerP5e; - - /* Get P5E addresses */ - PointerP5e = MM::Paging::GetP5eAddress(StartAddress); - EndSpace = MM::Paging::GetP5eAddress(EndAddress); - - /* Iterate over all P5Es */ - while(PointerP5e <= EndSpace) - { - /* Check if P5E is already mapped */ - if(!MM::Paging::PteValid(PointerP5e)) - { - /* Map P5E */ - MM::Paging::SetPte(TemplateP5e, MM::Pfn::AllocateBootstrapPages(1), 0); - *PointerP5e = *TemplateP5e; - - /* Clear the page table */ - RtlZeroMemory(MM::Paging::GetPteVirtualAddress(PointerP5e), MM_PAGE_SIZE); - } - - /* Get next table entry */ - PointerP5e = MM::Paging::GetNextPte(PointerP5e); - } -} - /** * Maps a range of virtual addresses at the PDE (Page Directory Entry) level. * @@ -211,50 +164,3 @@ MM::Pte::MapPTE(PVOID StartAddress, PointerPte = MM::Paging::GetNextPte(PointerPte); } } - -/** - * Maps a range of virtual addresses at the PXE (PML4) level. - * - * @param StartAddress - * The beginning of the virtual address range to map. - * - * @param EndAddress - * The end of the virtual address range to map. - * - * @param TemplatePxe - * A template PXE to use for creating new entries. - * - * @return This routine does not return any value. - * - * @since XT 1.0 - */ -XTAPI -VOID -MM::Pte::MapPXE(PVOID StartAddress, - PVOID EndAddress, - PMMPXE TemplatePxe) -{ - PMMPXE EndSpace, PointerPxe; - - /* Get PXE addresses */ - PointerPxe = MM::Paging::GetPxeAddress(StartAddress); - EndSpace = MM::Paging::GetPxeAddress(EndAddress); - - /* Iterate over all PTEs */ - while(PointerPxe <= EndSpace) - { - /* Check if PTE is already mapped */ - if(!MM::Paging::PteValid(PointerPxe)) - { - /* Map PTE */ - MM::Paging::SetPte(TemplatePxe, MM::Pfn::AllocateBootstrapPages(1), 0); - *PointerPxe = *TemplatePxe; - - /* Clear the page table */ - RtlZeroMemory(MM::Paging::GetPteVirtualAddress(PointerPxe), MM_PAGE_SIZE); - } - - /* Get next table entry */ - PointerPxe = MM::Paging::GetNextPte(PointerPxe); - } -} -- 2.52.0 From 2265a4a5225c46bc5e9bbb4c6b9c02450a672623 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Tue, 16 Dec 2025 14:13:55 +0100 Subject: [PATCH 039/166] Remove unsupported PML4/PML5 PTE interfaces --- xtoskrnl/includes/mm/i686/pte.hh | 6 ------ 1 file changed, 6 deletions(-) diff --git a/xtoskrnl/includes/mm/i686/pte.hh b/xtoskrnl/includes/mm/i686/pte.hh index 1fca7b2..34eaa14 100644 --- a/xtoskrnl/includes/mm/i686/pte.hh +++ b/xtoskrnl/includes/mm/i686/pte.hh @@ -19,9 +19,6 @@ namespace MM { public: STATIC XTAPI ULONG GetPtesPerPage(VOID); - STATIC XTAPI VOID MapP5E(PVOID StartAddress, - PVOID EndAddress, - PMMP5E TemplateP5e); STATIC XTAPI VOID MapPDE(PVOID StartAddress, PVOID EndAddress, PMMPDE TemplatePde); @@ -31,9 +28,6 @@ namespace MM STATIC XTAPI VOID MapPTE(PVOID StartAddress, PVOID EndAddress, PMMPTE TemplatePte); - STATIC XTAPI VOID MapPXE(PVOID StartAddress, - PVOID EndAddress, - PMMPXE TemplatePxe); }; } -- 2.52.0 From 020b7c7676d96390a6a71cc42c8cd60e186a54e3 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Tue, 16 Dec 2025 18:37:28 +0100 Subject: [PATCH 040/166] Extend memory layout --- sdk/xtdk/mmtypes.h | 5 +++++ xtoskrnl/mm/mmgr.cc | 12 ++++++++++++ 2 files changed, 17 insertions(+) diff --git a/sdk/xtdk/mmtypes.h b/sdk/xtdk/mmtypes.h index efb218c..193ca8f 100644 --- a/sdk/xtdk/mmtypes.h +++ b/sdk/xtdk/mmtypes.h @@ -57,10 +57,15 @@ typedef struct _MMMEMORY_LAYOUT { PMMPFN PfnDatabaseAddress; PVOID SelfMapAddress; + PVOID HyperSpaceStart; + PVOID HyperSpaceEnd; PVOID NonPagedPoolStart; PVOID NonPagedPoolEnd; PVOID PagedPoolStart; PVOID PagedPoolEnd; + PVOID SystemSpaceStart; + PVOID SystemSpaceEnd; + PVOID UserSpaceEnd; } MMMEMORY_LAYOUT, *PMMMEMORY_LAYOUT; /* Page Frame Entry structure definition */ diff --git a/xtoskrnl/mm/mmgr.cc b/xtoskrnl/mm/mmgr.cc index 79af5a4..93ff272 100644 --- a/xtoskrnl/mm/mmgr.cc +++ b/xtoskrnl/mm/mmgr.cc @@ -57,6 +57,12 @@ MM::Manager::InitializeMemoryLayout(VOID) MemoryLayout.NonPagedPoolEnd = (PVOID)0xFFFEFFFFFFBFFFFFULL; MemoryLayout.PagedPoolStart = (PVOID)0xFFFEF8A000000000ULL; MemoryLayout.PagedPoolEnd = (PVOID)(((ULONG_PTR)MemoryLayout.PagedPoolStart + PagedPoolSize) - 1); + + MemoryLayout.HyperSpaceStart = (PVOID)0xFFFEF70000000000ULL; + MemoryLayout.HyperSpaceEnd = (PVOID)0xFFFEF77FFFFFFFFFULL; + MemoryLayout.SystemSpaceStart = (PVOID)0xFFFEF88000000000ULL; + MemoryLayout.SystemSpaceEnd = (PVOID)((ULONG_PTR)MemoryLayout.SystemSpaceStart + (MM_NUMBER_SYSTEM_PTES + 1) * MM_PAGE_SIZE); + MemoryLayout.UserSpaceEnd = (PVOID)0x07FFFFFFFFFFFFFULL; } else { @@ -67,6 +73,12 @@ MM::Manager::InitializeMemoryLayout(VOID) MemoryLayout.NonPagedPoolEnd = (PVOID)0xFFFFFFFFFFBFFFFFULL; MemoryLayout.PagedPoolStart = (PVOID)0xFFFFF8A000000000ULL; MemoryLayout.PagedPoolEnd = (PVOID)(((ULONG_PTR)MemoryLayout.PagedPoolStart + PagedPoolSize) - 1); + + MemoryLayout.HyperSpaceStart = (PVOID)0xFFFFF70000000000ULL; + MemoryLayout.HyperSpaceEnd = (PVOID)0xFFFFF77FFFFFFFFFULL; + MemoryLayout.SystemSpaceStart = (PVOID)0xFFFFF88000000000ULL; + MemoryLayout.SystemSpaceEnd = (PVOID)((ULONG_PTR)MemoryLayout.SystemSpaceStart + (MM_NUMBER_SYSTEM_PTES + 1) * MM_PAGE_SIZE); + MemoryLayout.UserSpaceEnd = (PVOID)0x000007FFFFFEFFFFULL; } } -- 2.52.0 From 00d428d8deb6abb1ecbb601e46cd6869e934be9d Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Tue, 16 Dec 2025 20:05:51 +0100 Subject: [PATCH 041/166] Architecture-specific system PTE limits --- sdk/xtdk/amd64/mmtypes.h | 6 ++++++ sdk/xtdk/i686/mmtypes.h | 8 ++++++++ xtoskrnl/includes/mm/mmgr.hh | 2 ++ xtoskrnl/mm/data.cc | 6 ++++++ xtoskrnl/mm/mmgr.cc | 20 ++++++++++++++++++-- 5 files changed, 40 insertions(+), 2 deletions(-) diff --git a/sdk/xtdk/amd64/mmtypes.h b/sdk/xtdk/amd64/mmtypes.h index 9479175..8ad783d 100644 --- a/sdk/xtdk/amd64/mmtypes.h +++ b/sdk/xtdk/amd64/mmtypes.h @@ -86,6 +86,9 @@ /* Minimum number of physical pages needed by the system */ #define MM_MINIMUM_PHYSICAL_PAGES 2048 +/* Number of system PTEs */ +#define MM_DEFAULT_NUMBER_SYSTEM_PTES 22000 + /* Default number of secondary colors */ #define MM_DEFAULT_SECONDARY_COLORS 64 @@ -101,6 +104,9 @@ /* Maximum physical address used by HAL allocations */ #define MM_MAXIMUM_PHYSICAL_ADDRESS 0x00000000FFFFFFFFULL +/* Highest system address */ +#define MM_HIGHEST_SYSTEM_ADDRESS 0xFFFFFFFFFFFFFFFFULL + /* Trampoline code address */ #define MM_TRAMPOLINE_ADDRESS 0x80000 diff --git a/sdk/xtdk/i686/mmtypes.h b/sdk/xtdk/i686/mmtypes.h index 2f549ff..8cf0ad7 100644 --- a/sdk/xtdk/i686/mmtypes.h +++ b/sdk/xtdk/i686/mmtypes.h @@ -78,6 +78,11 @@ /* Minimum number of physical pages needed by the system */ #define MM_MINIMUM_PHYSICAL_PAGES 1100 +/* Number of system PTEs */ +#define MM_MINIMUM_NUMBER_SYSTEM_PTES 7000 +#define MM_DEFAULT_NUMBER_SYSTEM_PTES 11000 +#define MM_MAXIMUM_NUMBER_SYSTEM_PTES 22000 + /* Default number of secondary colors */ #define MM_DEFAULT_SECONDARY_COLORS 64 @@ -93,6 +98,9 @@ /* Maximum physical address used by HAL allocations */ #define MM_MAXIMUM_PHYSICAL_ADDRESS 0xFFFFFFFF +/* Highest system address */ +#define MM_HIGHEST_SYSTEM_ADDRESS 0xFFFFFFFF + /* Trampoline code address */ #define MM_TRAMPOLINE_ADDRESS 0x80000 diff --git a/xtoskrnl/includes/mm/mmgr.hh b/xtoskrnl/includes/mm/mmgr.hh index 7794b72..de943d5 100644 --- a/xtoskrnl/includes/mm/mmgr.hh +++ b/xtoskrnl/includes/mm/mmgr.hh @@ -19,9 +19,11 @@ namespace MM { private: STATIC MMMEMORY_LAYOUT MemoryLayout; + STATIC PFN_NUMBER NumberOfSystemPtes; public: STATIC XTAPI PMMMEMORY_LAYOUT GetMemoryLayout(VOID); + STATIC XTAPI PFN_NUMBER GetNumberOfSystemPtes(); STATIC XTAPI VOID InitializeMemoryLayout(VOID); STATIC XTAPI VOID InitializeMemoryManager(VOID); STATIC XTAPI BOOLEAN VerifyMemoryTypeFree(LOADER_MEMORY_TYPE MemoryType); diff --git a/xtoskrnl/mm/data.cc b/xtoskrnl/mm/data.cc index c8715b2..93a8c4f 100644 --- a/xtoskrnl/mm/data.cc +++ b/xtoskrnl/mm/data.cc @@ -30,9 +30,15 @@ ULONG_PTR MM::Pfn::HighestPhysicalPage; /* Lowest physical page number */ ULONG_PTR MM::Pfn::LowestPhysicalPage = -1; +/* Memory layout */ +MMMEMORY_LAYOUT MM::Manager::MemoryLayout; + /* Number of physical pages */ ULONG MM::Pfn::NumberOfPhysicalPages; +/* Number of system PTEs */ +PFN_NUMBER MM::Manager::NumberOfSystemPtes; + /* Old biggest free memory descriptor */ LOADER_MEMORY_DESCRIPTOR MM::Pfn::OriginalFreeDescriptor; diff --git a/xtoskrnl/mm/mmgr.cc b/xtoskrnl/mm/mmgr.cc index 93ff272..1f189df 100644 --- a/xtoskrnl/mm/mmgr.cc +++ b/xtoskrnl/mm/mmgr.cc @@ -25,6 +25,13 @@ MM::Manager::GetMemoryLayout(VOID) return &MemoryLayout; } +XTAPI +PFN_NUMBER +MM::Manager::GetNumberOfSystemPtes() +{ + return NumberOfSystemPtes; +} + /** * Initializes the kernel's virtual memory layout. * @@ -48,36 +55,45 @@ MM::Manager::InitializeMemoryLayout(VOID) /* Retrieve the PFN database size */ PfnDatabaseSize = MM::Pfn::GetPfnDatabaseSize(); + /* Define the number of system PTEs */ + NumberOfSystemPtes = MM_DEFAULT_NUMBER_SYSTEM_PTES; + if(MM::Paging::GetXpaStatus()) { + /* Configure memory layout for 5-level paging, using 57bit address space and providing a 128 PB address space */ MemoryLayout.PfnDatabaseAddress = (PMMPFN)0xFFFEFA8000000000ULL; MemoryLayout.SelfMapAddress = (PVOID)0xFFEDF6FB7DBEDF68ULL; + /* Define the non-paged and paged pool regions */ MemoryLayout.NonPagedPoolStart = (PVOID)((ULONG_PTR)MemoryLayout.PfnDatabaseAddress + PfnDatabaseSize * MM_PAGE_SIZE); MemoryLayout.NonPagedPoolEnd = (PVOID)0xFFFEFFFFFFBFFFFFULL; MemoryLayout.PagedPoolStart = (PVOID)0xFFFEF8A000000000ULL; MemoryLayout.PagedPoolEnd = (PVOID)(((ULONG_PTR)MemoryLayout.PagedPoolStart + PagedPoolSize) - 1); + /* Define hyperspace, system PTE space, and the user space limit */ MemoryLayout.HyperSpaceStart = (PVOID)0xFFFEF70000000000ULL; MemoryLayout.HyperSpaceEnd = (PVOID)0xFFFEF77FFFFFFFFFULL; MemoryLayout.SystemSpaceStart = (PVOID)0xFFFEF88000000000ULL; - MemoryLayout.SystemSpaceEnd = (PVOID)((ULONG_PTR)MemoryLayout.SystemSpaceStart + (MM_NUMBER_SYSTEM_PTES + 1) * MM_PAGE_SIZE); + MemoryLayout.SystemSpaceEnd = (PVOID)((ULONG_PTR)MemoryLayout.SystemSpaceStart + (NumberOfSystemPtes + 1) * MM_PAGE_SIZE); MemoryLayout.UserSpaceEnd = (PVOID)0x07FFFFFFFFFFFFFULL; } else { + /* Configure memory layout for 4-level paging, using 48bit address space and providing a 128 TB address space */ MemoryLayout.PfnDatabaseAddress = (PMMPFN)0xFFFFFA8000000000ULL; MemoryLayout.SelfMapAddress = (PVOID)0xFFFFF6FB7DBEDF68ULL; + /* Define the non-paged and paged pool regions */ MemoryLayout.NonPagedPoolStart = (PVOID)((ULONG_PTR)MemoryLayout.PfnDatabaseAddress + PfnDatabaseSize * MM_PAGE_SIZE); MemoryLayout.NonPagedPoolEnd = (PVOID)0xFFFFFFFFFFBFFFFFULL; MemoryLayout.PagedPoolStart = (PVOID)0xFFFFF8A000000000ULL; MemoryLayout.PagedPoolEnd = (PVOID)(((ULONG_PTR)MemoryLayout.PagedPoolStart + PagedPoolSize) - 1); + /* Define hyperspace, system PTE space, and the user space limit */ MemoryLayout.HyperSpaceStart = (PVOID)0xFFFFF70000000000ULL; MemoryLayout.HyperSpaceEnd = (PVOID)0xFFFFF77FFFFFFFFFULL; MemoryLayout.SystemSpaceStart = (PVOID)0xFFFFF88000000000ULL; - MemoryLayout.SystemSpaceEnd = (PVOID)((ULONG_PTR)MemoryLayout.SystemSpaceStart + (MM_NUMBER_SYSTEM_PTES + 1) * MM_PAGE_SIZE); + MemoryLayout.SystemSpaceEnd = (PVOID)((ULONG_PTR)MemoryLayout.SystemSpaceStart + (NumberOfSystemPtes + 1) * MM_PAGE_SIZE); MemoryLayout.UserSpaceEnd = (PVOID)0x000007FFFFFEFFFFULL; } } -- 2.52.0 From 728241f998849037a05951c20ba771f7fc0440ab Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Tue, 16 Dec 2025 20:36:16 +0100 Subject: [PATCH 042/166] Move memory layout initialization to architecture-specific code --- xtoskrnl/CMakeLists.txt | 1 + xtoskrnl/mm/amd64/mmgr.cc | 77 +++++++++++++++++++++++++++++++++++++++ xtoskrnl/mm/i686/mmgr.cc | 55 ++++++++++++++++++++++++++++ xtoskrnl/mm/mmgr.cc | 66 --------------------------------- 4 files changed, 133 insertions(+), 66 deletions(-) create mode 100644 xtoskrnl/mm/amd64/mmgr.cc create mode 100644 xtoskrnl/mm/i686/mmgr.cc diff --git a/xtoskrnl/CMakeLists.txt b/xtoskrnl/CMakeLists.txt index 847c1e2..e2a7144 100644 --- a/xtoskrnl/CMakeLists.txt +++ b/xtoskrnl/CMakeLists.txt @@ -51,6 +51,7 @@ list(APPEND XTOSKRNL_SOURCE ${XTOSKRNL_SOURCE_DIR}/ke/spinlock.cc ${XTOSKRNL_SOURCE_DIR}/ke/sysres.cc ${XTOSKRNL_SOURCE_DIR}/ke/timer.cc + ${XTOSKRNL_SOURCE_DIR}/mm/${ARCH}/mmgr.cc ${XTOSKRNL_SOURCE_DIR}/mm/${ARCH}/pagemap.cc ${XTOSKRNL_SOURCE_DIR}/mm/${ARCH}/paging.cc ${XTOSKRNL_SOURCE_DIR}/mm/${ARCH}/pte.cc diff --git a/xtoskrnl/mm/amd64/mmgr.cc b/xtoskrnl/mm/amd64/mmgr.cc new file mode 100644 index 0000000..f7b862a --- /dev/null +++ b/xtoskrnl/mm/amd64/mmgr.cc @@ -0,0 +1,77 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: xtoskrnl/mm/amd64/mmgr.cc + * DESCRIPTION: Memory Manager + * DEVELOPERS: Aiken Harris + */ + +#include + + +/** + * Initializes the kernel's virtual memory layout. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::Manager::InitializeMemoryLayout(VOID) +{ + ULONG_PTR PagedPoolSize, PteCount; + PFN_NUMBER PfnDatabaseSize; + ULONG PtesPerPage; + + /* Get the number of PTEs per page and calculate size of paged pool (at least 32MiB) */ + PtesPerPage = MM::Pte::GetPtesPerPage(); + PteCount = ((SIZE_TO_PAGES(33554432) + (PtesPerPage - 1)) / PtesPerPage); + PagedPoolSize = PteCount * PtesPerPage * MM_PAGE_SIZE; + + /* Retrieve the PFN database size */ + PfnDatabaseSize = MM::Pfn::GetPfnDatabaseSize(); + + /* Define the number of system PTEs */ + NumberOfSystemPtes = MM_DEFAULT_NUMBER_SYSTEM_PTES; + + /* Check if 5-level paging (LA57) is enabled */ + if(MM::Paging::GetXpaStatus()) + { + /* Configure memory layout for 5-level paging, using 57bit address space and providing a 128 PB address space */ + MemoryLayout.PfnDatabaseAddress = (PMMPFN)0xFFFEFA8000000000ULL; + MemoryLayout.SelfMapAddress = (PVOID)MM_PML5_SELF_MAP_ADDRESS; + + /* Define the non-paged and paged pool regions */ + MemoryLayout.NonPagedPoolStart = (PVOID)((ULONG_PTR)MemoryLayout.PfnDatabaseAddress + PfnDatabaseSize * MM_PAGE_SIZE); + MemoryLayout.NonPagedPoolEnd = (PVOID)0xFFFEFFFFFFBFFFFFULL; + MemoryLayout.PagedPoolStart = (PVOID)0xFFFEF8A000000000ULL; + MemoryLayout.PagedPoolEnd = (PVOID)(((ULONG_PTR)MemoryLayout.PagedPoolStart + PagedPoolSize) - 1); + + /* Define hyperspace, system PTE space, and the user space limit */ + MemoryLayout.HyperSpaceStart = (PVOID)0xFFFEF70000000000ULL; + MemoryLayout.HyperSpaceEnd = (PVOID)0xFFFEF77FFFFFFFFFULL; + MemoryLayout.SystemSpaceStart = (PVOID)0xFFFEF88000000000ULL; + MemoryLayout.SystemSpaceEnd = (PVOID)((ULONG_PTR)MemoryLayout.SystemSpaceStart + (NumberOfSystemPtes + 1) * MM_PAGE_SIZE); + MemoryLayout.UserSpaceEnd = (PVOID)0x07FFFFFFFFFFFFFULL; + } + else + { + /* Configure memory layout for 4-level paging, using 48bit address space and providing a 128 TB address space */ + MemoryLayout.PfnDatabaseAddress = (PMMPFN)0xFFFFFA8000000000ULL; + MemoryLayout.SelfMapAddress = (PVOID)MM_PML4_SELF_MAP_ADDRESS; + + /* Define the non-paged and paged pool regions */ + MemoryLayout.NonPagedPoolStart = (PVOID)((ULONG_PTR)MemoryLayout.PfnDatabaseAddress + PfnDatabaseSize * MM_PAGE_SIZE); + MemoryLayout.NonPagedPoolEnd = (PVOID)0xFFFFFFFFFFBFFFFFULL; + MemoryLayout.PagedPoolStart = (PVOID)0xFFFFF8A000000000ULL; + MemoryLayout.PagedPoolEnd = (PVOID)(((ULONG_PTR)MemoryLayout.PagedPoolStart + PagedPoolSize) - 1); + + /* Define hyperspace, system PTE space, and the user space limit */ + MemoryLayout.HyperSpaceStart = (PVOID)0xFFFFF70000000000ULL; + MemoryLayout.HyperSpaceEnd = (PVOID)0xFFFFF77FFFFFFFFFULL; + MemoryLayout.SystemSpaceStart = (PVOID)0xFFFFF88000000000ULL; + MemoryLayout.SystemSpaceEnd = (PVOID)((ULONG_PTR)MemoryLayout.SystemSpaceStart + (NumberOfSystemPtes + 1) * MM_PAGE_SIZE); + MemoryLayout.UserSpaceEnd = (PVOID)0x000007FFFFFEFFFFULL; + } +} diff --git a/xtoskrnl/mm/i686/mmgr.cc b/xtoskrnl/mm/i686/mmgr.cc new file mode 100644 index 0000000..fcd3dc6 --- /dev/null +++ b/xtoskrnl/mm/i686/mmgr.cc @@ -0,0 +1,55 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: xtoskrnl/mm/i686/mmgr.cc + * DESCRIPTION: Memory Manager + * DEVELOPERS: Aiken Harris + */ + +#include + + +/** + * Initializes the kernel's virtual memory layout. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::Manager::InitializeMemoryLayout(VOID) +{ + ULONG PhysicalPages; + + /* Not finished yet */ + UNIMPLEMENTED; + + /* Define the number of system PTEs */ + NumberOfSystemPtes = MM_DEFAULT_NUMBER_SYSTEM_PTES; + + /* Retrieve the number of physical pages */ + PhysicalPages = MM::Pfn::GetNumberOfPhysicalPages(); + + /* Verify the number of physical pages */ + if(PhysicalPages < 8192) + { + /* Less than 32MiB of physical memory (8192 pages), use the minimum number of system PTEs */ + NumberOfSystemPtes = MM_MINIMUM_NUMBER_SYSTEM_PTES; + } + else if(PhysicalPages > 32768) + { + /* More than 128MiB of physical memory (32768 pages), use the maximum number of system PTEs */ + NumberOfSystemPtes = MM_MAXIMUM_NUMBER_SYSTEM_PTES; + } + + /* Check if 3-level paging (PAE) is enabled */ + if(MM::Paging::GetXpaStatus()) + { + /* Configure memory layout for 3-level paging, using 36bit address space and providing a 64 GB address space */ + } + else + { + /* Configure memory layout for 2-level paging, using 32bit address space and providing a 4 GB address space */ + } +} diff --git a/xtoskrnl/mm/mmgr.cc b/xtoskrnl/mm/mmgr.cc index 1f189df..3e3bd2b 100644 --- a/xtoskrnl/mm/mmgr.cc +++ b/xtoskrnl/mm/mmgr.cc @@ -32,72 +32,6 @@ MM::Manager::GetNumberOfSystemPtes() return NumberOfSystemPtes; } -/** - * Initializes the kernel's virtual memory layout. - * - * @return This routine does not return any value. - * - * @since XT 1.0 - */ -XTAPI -VOID -MM::Manager::InitializeMemoryLayout(VOID) -{ - ULONG_PTR PagedPoolSize, PteCount; - PFN_NUMBER PfnDatabaseSize; - ULONG PtesPerPage; - - /* Get the number of PTEs per page and calculate size of paged pool (at least 32MiB) */ - PtesPerPage = MM::Pte::GetPtesPerPage(); - PteCount = ((SIZE_TO_PAGES(33554432) + (PtesPerPage - 1)) / PtesPerPage); - PagedPoolSize = PteCount * PtesPerPage * MM_PAGE_SIZE; - - /* Retrieve the PFN database size */ - PfnDatabaseSize = MM::Pfn::GetPfnDatabaseSize(); - - /* Define the number of system PTEs */ - NumberOfSystemPtes = MM_DEFAULT_NUMBER_SYSTEM_PTES; - - if(MM::Paging::GetXpaStatus()) - { - /* Configure memory layout for 5-level paging, using 57bit address space and providing a 128 PB address space */ - MemoryLayout.PfnDatabaseAddress = (PMMPFN)0xFFFEFA8000000000ULL; - MemoryLayout.SelfMapAddress = (PVOID)0xFFEDF6FB7DBEDF68ULL; - - /* Define the non-paged and paged pool regions */ - MemoryLayout.NonPagedPoolStart = (PVOID)((ULONG_PTR)MemoryLayout.PfnDatabaseAddress + PfnDatabaseSize * MM_PAGE_SIZE); - MemoryLayout.NonPagedPoolEnd = (PVOID)0xFFFEFFFFFFBFFFFFULL; - MemoryLayout.PagedPoolStart = (PVOID)0xFFFEF8A000000000ULL; - MemoryLayout.PagedPoolEnd = (PVOID)(((ULONG_PTR)MemoryLayout.PagedPoolStart + PagedPoolSize) - 1); - - /* Define hyperspace, system PTE space, and the user space limit */ - MemoryLayout.HyperSpaceStart = (PVOID)0xFFFEF70000000000ULL; - MemoryLayout.HyperSpaceEnd = (PVOID)0xFFFEF77FFFFFFFFFULL; - MemoryLayout.SystemSpaceStart = (PVOID)0xFFFEF88000000000ULL; - MemoryLayout.SystemSpaceEnd = (PVOID)((ULONG_PTR)MemoryLayout.SystemSpaceStart + (NumberOfSystemPtes + 1) * MM_PAGE_SIZE); - MemoryLayout.UserSpaceEnd = (PVOID)0x07FFFFFFFFFFFFFULL; - } - else - { - /* Configure memory layout for 4-level paging, using 48bit address space and providing a 128 TB address space */ - MemoryLayout.PfnDatabaseAddress = (PMMPFN)0xFFFFFA8000000000ULL; - MemoryLayout.SelfMapAddress = (PVOID)0xFFFFF6FB7DBEDF68ULL; - - /* Define the non-paged and paged pool regions */ - MemoryLayout.NonPagedPoolStart = (PVOID)((ULONG_PTR)MemoryLayout.PfnDatabaseAddress + PfnDatabaseSize * MM_PAGE_SIZE); - MemoryLayout.NonPagedPoolEnd = (PVOID)0xFFFFFFFFFFBFFFFFULL; - MemoryLayout.PagedPoolStart = (PVOID)0xFFFFF8A000000000ULL; - MemoryLayout.PagedPoolEnd = (PVOID)(((ULONG_PTR)MemoryLayout.PagedPoolStart + PagedPoolSize) - 1); - - /* Define hyperspace, system PTE space, and the user space limit */ - MemoryLayout.HyperSpaceStart = (PVOID)0xFFFFF70000000000ULL; - MemoryLayout.HyperSpaceEnd = (PVOID)0xFFFFF77FFFFFFFFFULL; - MemoryLayout.SystemSpaceStart = (PVOID)0xFFFFF88000000000ULL; - MemoryLayout.SystemSpaceEnd = (PVOID)((ULONG_PTR)MemoryLayout.SystemSpaceStart + (NumberOfSystemPtes + 1) * MM_PAGE_SIZE); - MemoryLayout.UserSpaceEnd = (PVOID)0x000007FFFFFEFFFFULL; - } -} - /** * Performs an early initialization of the XTOS Memory Manager. * -- 2.52.0 From cb4d113e312c77b1a6f2c9915ae6cdb739ddbce9 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Tue, 16 Dec 2025 22:31:15 +0100 Subject: [PATCH 043/166] Add virtual address validation and system PTE helpers --- xtoskrnl/includes/mm/amd64/pte.hh | 3 ++ xtoskrnl/includes/mm/i686/pte.hh | 3 ++ xtoskrnl/mm/amd64/pte.cc | 83 +++++++++++++++++++++++++++++++ xtoskrnl/mm/i686/pte.cc | 65 ++++++++++++++++++++++++ 4 files changed, 154 insertions(+) diff --git a/xtoskrnl/includes/mm/amd64/pte.hh b/xtoskrnl/includes/mm/amd64/pte.hh index 50fefec..c5d4f6b 100644 --- a/xtoskrnl/includes/mm/amd64/pte.hh +++ b/xtoskrnl/includes/mm/amd64/pte.hh @@ -18,7 +18,10 @@ namespace MM class Pte { public: + STATIC XTAPI BOOLEAN AddressValid(IN PVOID VirtualAddress); STATIC XTAPI ULONG GetPtesPerPage(VOID); + STATIC XTAPI PMMPTE GetSystemPteBaseAddress(VOID); + STATIC XTAPI VOID InitializePageTable(VOID); STATIC XTAPI VOID MapP5E(PVOID StartAddress, PVOID EndAddress, PMMP5E TemplateP5e); diff --git a/xtoskrnl/includes/mm/i686/pte.hh b/xtoskrnl/includes/mm/i686/pte.hh index 34eaa14..b29f91a 100644 --- a/xtoskrnl/includes/mm/i686/pte.hh +++ b/xtoskrnl/includes/mm/i686/pte.hh @@ -18,7 +18,10 @@ namespace MM class Pte { public: + STATIC XTAPI BOOLEAN AddressValid(IN PVOID VirtualAddress); STATIC XTAPI ULONG GetPtesPerPage(VOID); + STATIC XTAPI PMMPTE GetSystemPteBaseAddress(VOID); + STATIC XTAPI VOID InitializePageTable(VOID); STATIC XTAPI VOID MapPDE(PVOID StartAddress, PVOID EndAddress, PMMPDE TemplatePde); diff --git a/xtoskrnl/mm/amd64/pte.cc b/xtoskrnl/mm/amd64/pte.cc index d74156a..796cd45 100644 --- a/xtoskrnl/mm/amd64/pte.cc +++ b/xtoskrnl/mm/amd64/pte.cc @@ -9,6 +9,89 @@ #include +/** + * Checks if the virtual address is valid and mapped in the page tables. + * + * @param VirtualAddress + * The virtual address to check. + * + * @return This routine returns TRUE if the address is valid, or FALSE otherwise. + * + * @since XT 1.0 + */ +XTAPI +BOOLEAN +MM::Pte::AddressValid(IN PVOID VirtualAddress) +{ + /* Check XPA status */ + if(MM::Paging::GetXpaStatus()) + { + /* Check if the P5E is valid */ + if(!MM::Paging::PteValid(MM::Paging::GetP5eAddress(VirtualAddress))) + { + /* Invalid P5E, return FALSE */ + return FALSE; + } + } + + /* Check if PXE, PPE, PDE and PTE are valid */ + if(!MM::Paging::PteValid(MM::Paging::GetPxeAddress(VirtualAddress)) || + !MM::Paging::PteValid(MM::Paging::GetPpeAddress(VirtualAddress)) || + !MM::Paging::PteValid(MM::Paging::GetPdeAddress(VirtualAddress)) || + !MM::Paging::PteValid(MM::Paging::GetPteAddress(VirtualAddress))) + { + /* Invalid PXE, PPE, PDE or PTE, return FALSE */ + return FALSE; + } + + /* Address is valid, return TRUE */ + return TRUE; +} + +/** + * Retrieves the base virtual address of the system PTEs. + * + * @return This routine returns a pointer to the first PTE in the system PTE space. + * + * @since XT 1.0 + */ +XTAPI +PMMPTE +MM::Pte::GetSystemPteBaseAddress(VOID) +{ + PMMMEMORY_LAYOUT MemoryLayout; + + /* Retrieve the system's memory layout */ + MemoryLayout = MM::Manager::GetMemoryLayout(); + + /* Determine the base address for system PTEs based on the paging mode */ + if(MM::Paging::GetXpaStatus()) + { + /* For 5-level paging, system PTEs start at the beginning of system space */ + return MM::Paging::GetPteAddress((PVOID)MemoryLayout->SystemSpaceStart); + } + else + { + /* For 4-level paging, system PTEs start at the legacy KSEG0_BASE */ + return MM::Paging::GetPteAddress((PVOID)KSEG0_BASE); + } +} + + +/** + * Performs the initial setup of the system's page table hierarchy. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::Pte::InitializePageTable(VOID) +{ + UNIMPLEMENTED; +} + /** * Maps a range of virtual addresses at the P5E (PML5) level. * diff --git a/xtoskrnl/mm/i686/pte.cc b/xtoskrnl/mm/i686/pte.cc index 97db714..b425228 100644 --- a/xtoskrnl/mm/i686/pte.cc +++ b/xtoskrnl/mm/i686/pte.cc @@ -8,3 +8,68 @@ #include + +/** + * Checks if the virtual address is valid and mapped in the page tables. + * + * @param VirtualAddress + * The virtual address to check. + * + * @return This routine returns TRUE if the address is valid, or FALSE otherwise. + * + * @since XT 1.0 + */ +XTAPI +BOOLEAN +MM::Pte::AddressValid(IN PVOID VirtualAddress) +{ + /* Check XPA status */ + if(MM::Paging::GetXpaStatus()) + { + /* Check if the P5E is valid */ + if(!MM::Paging::PteValid(MM::Paging::GetPpeAddress(VirtualAddress))) + { + /* Invalid PPE, return FALSE */ + return FALSE; + } + } + + /* Check if PDE and PTE are valid */ + if(!MM::Paging::PteValid(MM::Paging::GetPdeAddress(VirtualAddress)) || + !MM::Paging::PteValid(MM::Paging::GetPteAddress(VirtualAddress))) + { + /* Invalid PDE or PTE, return FALSE */ + return FALSE; + } + + /* Address is valid, return TRUE */ + return TRUE; +} + +/** + * Retrieves the base virtual address of the system PTEs. + * + * @return This routine returns a pointer to the first PTE in the system PTE space. + * + * @since XT 1.0 + */ +XTAPI +PMMPTE +MM::Pte::GetSystemPteBaseAddress(VOID) +{ + return MM::Paging::GetPteAddress(NULLPTR); +} + +/** + * Performs the initial setup of the system's page table hierarchy. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::Pte::InitializePageTable(VOID) +{ + UNIMPLEMENTED; +} -- 2.52.0 From f1a76bc01a16c7421866bde6904baab911af76ae Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Tue, 16 Dec 2025 22:34:41 +0100 Subject: [PATCH 044/166] Call page table initialization --- xtoskrnl/mm/mmgr.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/xtoskrnl/mm/mmgr.cc b/xtoskrnl/mm/mmgr.cc index 3e3bd2b..5aa17ed 100644 --- a/xtoskrnl/mm/mmgr.cc +++ b/xtoskrnl/mm/mmgr.cc @@ -59,6 +59,9 @@ MM::Manager::InitializeMemoryManager(VOID) /* Initialize memory layout */ InitializeMemoryLayout(); + + /* Initialize page table */ + MM::Pte::InitializePageTable(); } /** -- 2.52.0 From 049c9c6bbd75813a90f328f96e1d222a7e6309ef Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Wed, 17 Dec 2025 20:35:28 +0100 Subject: [PATCH 045/166] Update SelfMapAddress --- sdk/xtdk/amd64/mmtypes.h | 4 ---- xtoskrnl/mm/amd64/mmgr.cc | 4 ++-- xtoskrnl/mm/i686/mmgr.cc | 30 ++++++++++++++++++++++++++++++ 3 files changed, 32 insertions(+), 6 deletions(-) diff --git a/sdk/xtdk/amd64/mmtypes.h b/sdk/xtdk/amd64/mmtypes.h index 8ad783d..f05f080 100644 --- a/sdk/xtdk/amd64/mmtypes.h +++ b/sdk/xtdk/amd64/mmtypes.h @@ -31,10 +31,6 @@ #define MM_PXE_LA57_BASE 0xFFEDF6FB7DA00000ULL #define MM_P5E_LA57_BASE 0xFFEDF6FB7DBED000ULL -/* Self map address */ -#define MM_PML4_SELF_MAP_ADDRESS 0xFFFFF6FB7DBEDF68ULL -#define MM_PML5_SELF_MAP_ADDRESS 0xFFEDF6FB7DBEDF68ULL - /* PTE shift values */ #define MM_PTE_SHIFT 3 #define MM_PTI_SHIFT 12 diff --git a/xtoskrnl/mm/amd64/mmgr.cc b/xtoskrnl/mm/amd64/mmgr.cc index f7b862a..b2c98bd 100644 --- a/xtoskrnl/mm/amd64/mmgr.cc +++ b/xtoskrnl/mm/amd64/mmgr.cc @@ -40,7 +40,7 @@ MM::Manager::InitializeMemoryLayout(VOID) { /* Configure memory layout for 5-level paging, using 57bit address space and providing a 128 PB address space */ MemoryLayout.PfnDatabaseAddress = (PMMPFN)0xFFFEFA8000000000ULL; - MemoryLayout.SelfMapAddress = (PVOID)MM_PML5_SELF_MAP_ADDRESS; + MemoryLayout.SelfMapAddress = (PVOID)MM_P5E_LA57_BASE; /* Define the non-paged and paged pool regions */ MemoryLayout.NonPagedPoolStart = (PVOID)((ULONG_PTR)MemoryLayout.PfnDatabaseAddress + PfnDatabaseSize * MM_PAGE_SIZE); @@ -59,7 +59,7 @@ MM::Manager::InitializeMemoryLayout(VOID) { /* Configure memory layout for 4-level paging, using 48bit address space and providing a 128 TB address space */ MemoryLayout.PfnDatabaseAddress = (PMMPFN)0xFFFFFA8000000000ULL; - MemoryLayout.SelfMapAddress = (PVOID)MM_PML4_SELF_MAP_ADDRESS; + MemoryLayout.SelfMapAddress = (PVOID)MM_PXE_BASE; /* Define the non-paged and paged pool regions */ MemoryLayout.NonPagedPoolStart = (PVOID)((ULONG_PTR)MemoryLayout.PfnDatabaseAddress + PfnDatabaseSize * MM_PAGE_SIZE); diff --git a/xtoskrnl/mm/i686/mmgr.cc b/xtoskrnl/mm/i686/mmgr.cc index fcd3dc6..e39aa82 100644 --- a/xtoskrnl/mm/i686/mmgr.cc +++ b/xtoskrnl/mm/i686/mmgr.cc @@ -47,9 +47,39 @@ MM::Manager::InitializeMemoryLayout(VOID) if(MM::Paging::GetXpaStatus()) { /* Configure memory layout for 3-level paging, using 36bit address space and providing a 64 GB address space */ + MemoryLayout.PfnDatabaseAddress = (PMMPFN)0xB0000000; + MemoryLayout.SelfMapAddress = (PVOID)MM_PTE_BASE; + + /* Define the non-paged and paged pool regions */ + MemoryLayout.NonPagedPoolStart = (PVOID)((ULONG_PTR)MemoryLayout.PfnDatabaseAddress + PfnDatabaseSize * MM_PAGE_SIZE); + MemoryLayout.NonPagedPoolEnd = (PVOID)0xEEFFFFFF; + MemoryLayout.PagedPoolStart = (PVOID)0xE2000000; + MemoryLayout.PagedPoolEnd = (PVOID)(((ULONG_PTR)MemoryLayout.PagedPoolStart + PagedPoolSize) - 1); + + /* Define hyperspace, system PTE space, and the user space limit */ + MemoryLayout.HyperSpaceStart = (PVOID)0xC0800000; + MemoryLayout.HyperSpaceEnd = (PVOID)0xC0BFFFFF; + MemoryLayout.SystemSpaceStart = (PVOID)0xC0C00000; + MemoryLayout.SystemSpaceEnd = (PVOID)((ULONG_PTR)MemoryLayout.SystemSpaceStart + (NumberOfSystemPtes + 1) * MM_PAGE_SIZE); + MemoryLayout.UserSpaceEnd = (PVOID)0x7FFEFFFF; } else { /* Configure memory layout for 2-level paging, using 32bit address space and providing a 4 GB address space */ + MemoryLayout.PfnDatabaseAddress = (PMMPFN)0xB0000000; + MemoryLayout.SelfMapAddress = (PVOID)MM_PTE_BASE; + + /* Define the non-paged and paged pool regions */ + MemoryLayout.NonPagedPoolStart = (PVOID)((ULONG_PTR)MemoryLayout.PfnDatabaseAddress + PfnDatabaseSize * MM_PAGE_SIZE); + MemoryLayout.NonPagedPoolEnd = (PVOID)0xFFBE0000; + MemoryLayout.PagedPoolStart = (PVOID)0xE1000000; + MemoryLayout.PagedPoolEnd = (PVOID)(((ULONG_PTR)MemoryLayout.PagedPoolStart + PagedPoolSize) - 1); + + /* Define hyperspace, system PTE space, and the user space limit */ + MemoryLayout.HyperSpaceStart = (PVOID)0xC0400000; + MemoryLayout.HyperSpaceEnd = (PVOID)0xC07FFFFF; + MemoryLayout.SystemSpaceStart = (PVOID)0xC0800000; + MemoryLayout.SystemSpaceEnd = (PVOID)((ULONG_PTR)MemoryLayout.SystemSpaceStart + (NumberOfSystemPtes + 1) * MM_PAGE_SIZE); + MemoryLayout.UserSpaceEnd = (PVOID)0x7FFEFFFF; } } -- 2.52.0 From 687c58d9232bc9bec3e5fe00c699a3cec0bbd9d6 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Wed, 17 Dec 2025 22:28:08 +0100 Subject: [PATCH 046/166] Implement initial virtual memory layout setup --- xtoskrnl/mm/i686/mmgr.cc | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/xtoskrnl/mm/i686/mmgr.cc b/xtoskrnl/mm/i686/mmgr.cc index e39aa82..478b228 100644 --- a/xtoskrnl/mm/i686/mmgr.cc +++ b/xtoskrnl/mm/i686/mmgr.cc @@ -20,10 +20,9 @@ XTAPI VOID MM::Manager::InitializeMemoryLayout(VOID) { - ULONG PhysicalPages; - - /* Not finished yet */ - UNIMPLEMENTED; + ULONG_PTR PagedPoolSize, PteCount; + PFN_NUMBER PfnDatabaseSize, PhysicalPages; + ULONG PtesPerPage; /* Define the number of system PTEs */ NumberOfSystemPtes = MM_DEFAULT_NUMBER_SYSTEM_PTES; -- 2.52.0 From b183d528061c35baec0122b05f080a7b3524bae5 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Thu, 18 Dec 2025 22:26:31 +0100 Subject: [PATCH 047/166] Fix paging abstraction for PDE/PTE virtual address calculation --- xtoskrnl/includes/mm/i686/pagemap.hh | 8 +- xtoskrnl/mm/i686/pagemap.cc | 116 ++++++++++++++++++--------- 2 files changed, 83 insertions(+), 41 deletions(-) diff --git a/xtoskrnl/includes/mm/i686/pagemap.hh b/xtoskrnl/includes/mm/i686/pagemap.hh index 5d94662..5ae935a 100644 --- a/xtoskrnl/includes/mm/i686/pagemap.hh +++ b/xtoskrnl/includes/mm/i686/pagemap.hh @@ -31,7 +31,7 @@ namespace MM VIRTUAL XTAPI PFN_NUMBER GetPageFrameNumber(IN PMMPTE Pte) = 0; XTAPI PMMPDE GetPdeAddress(IN PVOID Address); XTAPI ULONG GetPdeIndex(IN PVOID Address); - XTAPI PVOID GetPdeVirtualAddress(IN PMMPDE PdePointer); + VIRTUAL XTAPI PVOID GetPdeVirtualAddress(IN PMMPDE PdePointer) = 0; XTAPI PMMPPE GetPpeAddress(IN PVOID Address); XTAPI ULONG GetPpeIndex(IN PVOID Address); XTAPI PVOID GetPpeVirtualAddress(IN PMMPPE PpePointer); @@ -40,7 +40,7 @@ namespace MM VIRTUAL XTAPI LONG GetPteDistance(PMMPTE EndPte, PMMPTE StartPte) = 0; VIRTUAL XTAPI ULONG GetPteSize(VOID) = 0; - XTAPI PVOID GetPteVirtualAddress(IN PMMPTE PtePointer); + VIRTUAL XTAPI PVOID GetPteVirtualAddress(IN PMMPTE PtePointer) = 0; XTAPI BOOLEAN GetXpaStatus(); VIRTUAL XTAPI VOID InitializePageMapInfo(VOID) = 0; VIRTUAL XTAPI BOOLEAN PteValid(IN PMMPTE PtePointer) = 0; @@ -65,9 +65,11 @@ namespace MM XTAPI PMMPTE GetNextPte(IN PMMPTE Pte); XTAPI BOOLEAN GetOneEntry(IN PMMPTE Pte); XTAPI PFN_NUMBER GetPageFrameNumber(IN PMMPTE Pte); + XTAPI PVOID GetPdeVirtualAddress(IN PMMPDE PdePointer); XTAPI LONG GetPteDistance(PMMPTE EndPte, PMMPTE StartPte); XTAPI ULONG GetPteSize(VOID); + XTAPI PVOID GetPteVirtualAddress(IN PMMPTE PtePointer); XTAPI VOID InitializePageMapInfo(VOID); XTAPI BOOLEAN PteValid(IN PMMPTE PtePointer); XTAPI VOID SetNextEntry(IN PMMPTE Pte, @@ -91,9 +93,11 @@ namespace MM XTAPI PMMPTE GetNextPte(IN PMMPTE Pte); XTAPI BOOLEAN GetOneEntry(IN PMMPTE Pte); XTAPI PFN_NUMBER GetPageFrameNumber(IN PMMPTE Pte); + XTAPI PVOID GetPdeVirtualAddress(IN PMMPDE PdePointer); XTAPI LONG GetPteDistance(PMMPTE EndPte, PMMPTE StartPte); XTAPI ULONG GetPteSize(VOID); + XTAPI PVOID GetPteVirtualAddress(IN PMMPTE PtePointer); XTAPI VOID InitializePageMapInfo(VOID); XTAPI BOOLEAN PteValid(IN PMMPTE PtePointer); XTAPI VOID SetNextEntry(IN PMMPTE Pte, diff --git a/xtoskrnl/mm/i686/pagemap.cc b/xtoskrnl/mm/i686/pagemap.cc index d695fe8..c972336 100644 --- a/xtoskrnl/mm/i686/pagemap.cc +++ b/xtoskrnl/mm/i686/pagemap.cc @@ -81,23 +81,6 @@ MM::PageMap::GetPdeIndex(IN PVOID Address) 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(IN 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. @@ -123,7 +106,7 @@ MM::PageMap::GetPpeAddress(IN PVOID Address) * @param Address * Specifies the virtual address for which to retrieve the corresponding PPE. * - * @return This routine returns the index of the PPE. + * @return This routine returns the offset of the PPE. * * @since XT 1.0 */ @@ -131,8 +114,8 @@ XTAPI ULONG MM::PageMap::GetPpeIndex(IN PVOID Address) { - /* Return PPE index */ - return ((((ULONG_PTR)(Address)) >> MM_PPI_SHIFT) & 0x3) * PageMapInfo.Xpa; + /* Return zero */ + return 0; } /** @@ -149,8 +132,8 @@ XTAPI PVOID MM::PageMap::GetPpeVirtualAddress(IN PMMPPE PpePointer) { - /* Return PPE virtual address */ - return (PVOID)((ULONG)(PpePointer) << 30); + /* Return zero */ + return (PVOID)0; } /** @@ -192,23 +175,6 @@ MM::PageMap::GetPteIndex(IN PVOID Address) 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(IN PMMPTE PtePointer) -{ - /* Return PTE virtual address */ - return ((PVOID)((ULONG)(PtePointer) << 10)); -} /** * Gets the status of Extended Paging Address (XPA) mode. @@ -317,6 +283,24 @@ MM::PageMapBasic::GetPageFrameNumber(IN PMMPTE Pte) return Pte->Pml2.Hardware.PageFrameNumber; } +/** + * 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::PageMapBasic::GetPdeVirtualAddress(IN PMMPDE PdePointer) +{ + /* Return PDE virtual address */ + return ((PVOID)((ULONG)(PdePointer) << 20)); +} + /** * Calculates the distance between two PTE pointers. * @@ -354,6 +338,24 @@ MM::PageMapBasic::GetPteSize(VOID) return sizeof(MMPML2_PTE); } +/** + * 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::PageMapBasic::GetPteVirtualAddress(IN PMMPTE PtePointer) +{ + /* Return PTE virtual address */ + return ((PVOID)((ULONG)(PtePointer) << 10)); +} + /** * Initializes page map information for basic paging (PML2). * @@ -590,6 +592,24 @@ MM::PageMapXpa::GetPageFrameNumber(IN PMMPTE Pte) return Pte->Pml3.Hardware.PageFrameNumber; } +/** + * 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::PageMapXpa::GetPdeVirtualAddress(IN PMMPDE PdePointer) +{ + /* Return PDE virtual address */ + return ((PVOID)((ULONG)(PdePointer) << 18)); +} + /** * Calculates the distance between two PTE pointers. * @@ -627,6 +647,24 @@ MM::PageMapXpa::GetPteSize(VOID) return sizeof(MMPML3_PTE); } +/** + * 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::PageMapXpa::GetPteVirtualAddress(IN PMMPTE PtePointer) +{ + /* Return PTE virtual address */ + return ((PVOID)((ULONG)(PtePointer) << 9)); +} + /** * Initializes page map information for basic paging (PML3). * -- 2.52.0 From 570301bb35e2d6d3b1fa679b663571f511813e39 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Thu, 18 Dec 2025 22:38:59 +0100 Subject: [PATCH 048/166] Clarify page table entry offset semantics --- xtoskrnl/includes/mm/amd64/pagemap.hh | 10 +++---- xtoskrnl/includes/mm/i686/pagemap.hh | 6 ++--- xtoskrnl/mm/amd64/pagemap.cc | 39 ++++++++++++++------------- xtoskrnl/mm/i686/pagemap.cc | 20 +++++++------- 4 files changed, 38 insertions(+), 37 deletions(-) diff --git a/xtoskrnl/includes/mm/amd64/pagemap.hh b/xtoskrnl/includes/mm/amd64/pagemap.hh index 9aee6cf..19c62ae 100644 --- a/xtoskrnl/includes/mm/amd64/pagemap.hh +++ b/xtoskrnl/includes/mm/amd64/pagemap.hh @@ -29,23 +29,23 @@ namespace MM XTAPI PMMPTE GetNextPte(IN PMMPTE Pte); XTAPI BOOLEAN GetOneEntry(IN PMMPTE Pte); XTAPI PMMP5E GetP5eAddress(IN PVOID Address); - XTAPI ULONG GetP5eIndex(IN PVOID Address); + XTAPI ULONG GetP5eOffset(IN PVOID Address); XTAPI PVOID GetP5eVirtualAddress(IN PMMP5E P5ePointer); XTAPI PFN_NUMBER GetPageFrameNumber(IN PMMPTE Pte); XTAPI PMMPDE GetPdeAddress(IN PVOID Address); - XTAPI ULONG GetPdeIndex(IN PVOID Address); + XTAPI ULONG GetPdeOffset(IN PVOID Address); VIRTUAL XTAPI PVOID GetPdeVirtualAddress(IN PMMPDE PdePointer) = 0; XTAPI PMMPPE GetPpeAddress(IN PVOID Address); - XTAPI ULONG GetPpeIndex(IN PVOID Address); + XTAPI ULONG GetPpeOffset(IN PVOID Address); VIRTUAL XTAPI PVOID GetPpeVirtualAddress(IN PMMPPE PpePointer) = 0; XTAPI PMMPTE GetPteAddress(IN PVOID Address); XTAPI LONG GetPteDistance(PMMPTE EndPte, PMMPTE StartPte); - XTAPI ULONG GetPteIndex(IN PVOID Address); + XTAPI ULONG GetPteOffset(IN PVOID Address); XTAPI ULONG GetPteSize(VOID); VIRTUAL XTAPI PVOID GetPteVirtualAddress(IN PMMPTE PtePointer) = 0; XTAPI PMMPXE GetPxeAddress(IN PVOID Address); - XTAPI ULONG GetPxeIndex(IN PVOID Address); + XTAPI ULONG GetPxeOffset(IN PVOID Address); VIRTUAL XTAPI PVOID GetPxeVirtualAddress(IN PMMPXE PxePointer) = 0; XTAPI BOOLEAN GetXpaStatus(); VIRTUAL XTAPI VOID InitializePageMapInfo(VOID) = 0; diff --git a/xtoskrnl/includes/mm/i686/pagemap.hh b/xtoskrnl/includes/mm/i686/pagemap.hh index 5ae935a..e439fab 100644 --- a/xtoskrnl/includes/mm/i686/pagemap.hh +++ b/xtoskrnl/includes/mm/i686/pagemap.hh @@ -30,13 +30,13 @@ namespace MM VIRTUAL XTAPI BOOLEAN GetOneEntry(IN PMMPTE Pte) = 0; VIRTUAL XTAPI PFN_NUMBER GetPageFrameNumber(IN PMMPTE Pte) = 0; XTAPI PMMPDE GetPdeAddress(IN PVOID Address); - XTAPI ULONG GetPdeIndex(IN PVOID Address); + XTAPI ULONG GetPdeOffset(IN PVOID Address); VIRTUAL XTAPI PVOID GetPdeVirtualAddress(IN PMMPDE PdePointer) = 0; XTAPI PMMPPE GetPpeAddress(IN PVOID Address); - XTAPI ULONG GetPpeIndex(IN PVOID Address); + XTAPI ULONG GetPpeOffset(IN PVOID Address); XTAPI PVOID GetPpeVirtualAddress(IN PMMPPE PpePointer); XTAPI PMMPTE GetPteAddress(IN PVOID Address); - XTAPI ULONG GetPteIndex(IN PVOID Address); + XTAPI ULONG GetPteOffset(IN PVOID Address); VIRTUAL XTAPI LONG GetPteDistance(PMMPTE EndPte, PMMPTE StartPte) = 0; VIRTUAL XTAPI ULONG GetPteSize(VOID) = 0; diff --git a/xtoskrnl/mm/amd64/pagemap.cc b/xtoskrnl/mm/amd64/pagemap.cc index 290f880..fff7c91 100644 --- a/xtoskrnl/mm/amd64/pagemap.cc +++ b/xtoskrnl/mm/amd64/pagemap.cc @@ -140,19 +140,20 @@ MM::PageMap::GetP5eAddress(IN PVOID Address) } /** - * Gets the index of the P5E (Page Map Level 5 Entry), that maps given address. + * Gets the Offset 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. + * @return This routine returns the Offset of the P5E, or NULLPTR if LA57 is not enabled. * * @since XT 1.0 */ XTAPI ULONG -MM::PageMap::GetP5eIndex(IN PVOID Address) +MM::PageMap::GetP5eOffset(IN PVOID Address) { + /* Return P5E Offset */ return (((((ULONGLONG)Address) >> MM_P5I_SHIFT) & 0x1FF) * PageMapInfo.Xpa); } @@ -212,20 +213,20 @@ MM::PageMap::GetPdeAddress(IN PVOID Address) } /** - * Gets the index of the PDE (Page Directory Entry), that maps given address. + * Gets the Offset 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. + * @return This routine returns the Offset of the PDE. * * @since XT 1.0 */ XTAPI ULONG -MM::PageMap::GetPdeIndex(IN PVOID Address) +MM::PageMap::GetPdeOffset(IN PVOID Address) { - /* Return PDE index */ + /* Return PDE Offset */ return ((((ULONGLONG)Address) >> MM_PDI_SHIFT) & 0x1FF); } @@ -251,20 +252,20 @@ MM::PageMap::GetPpeAddress(IN PVOID Address) } /** - * Gets the index of the PPE (Page Directory Pointer Table Entry), that maps given address. + * Gets the Offset 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. + * @return This routine returns the Offset of the PPE. * * @since XT 1.0 */ XTAPI ULONG -MM::PageMap::GetPpeIndex(IN PVOID Address) +MM::PageMap::GetPpeOffset(IN PVOID Address) { - /* Return PPE index */ + /* Return PPE Offset */ return ((((ULONGLONG)Address) >> MM_PPI_SHIFT) & 0x1FF); } @@ -312,20 +313,20 @@ MM::PageMap::GetPteDistance(PMMPTE EndPte, } /** - * Gets the index of the PTE (Page Table Entry), that maps given address. + * Gets the Offset 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. + * @return This routine returns the Offset of the PTE. * * @since XT 1.0 */ XTAPI ULONG -MM::PageMap::GetPteIndex(IN PVOID Address) +MM::PageMap::GetPteOffset(IN PVOID Address) { - /* Return PTE index */ + /* Return PTE Offset */ return ((((ULONGLONG)Address) >> MM_PTI_SHIFT) & 0x1FF); } @@ -366,20 +367,20 @@ MM::PageMap::GetPxeAddress(IN PVOID Address) } /** - * Gets the index of the PXE (Extended Page Entry), that maps given address. + * Gets the Offset 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. + * @return This routine returns the Offset of the PXE. * * @since XT 1.0 */ XTAPI ULONG -MM::PageMap::GetPxeIndex(IN PVOID Address) +MM::PageMap::GetPxeOffset(IN PVOID Address) { - /* Return PXE index */ + /* Return PXE Offset */ return ((((ULONGLONG)Address) >> MM_PXI_SHIFT) & 0x1FF); } diff --git a/xtoskrnl/mm/i686/pagemap.cc b/xtoskrnl/mm/i686/pagemap.cc index c972336..553d3ed 100644 --- a/xtoskrnl/mm/i686/pagemap.cc +++ b/xtoskrnl/mm/i686/pagemap.cc @@ -64,20 +64,20 @@ MM::PageMap::GetPdeAddress(IN PVOID Address) } /** - * Gets the index of the PDE (Page Directory Entry), that maps given address. + * Gets the Offset 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. + * @return This routine returns the Offset of the PDE. * * @since XT 1.0 */ XTAPI ULONG -MM::PageMap::GetPdeIndex(IN PVOID Address) +MM::PageMap::GetPdeOffset(IN PVOID Address) { - /* Return PDE index */ + /* Return PDE Offset */ return ((((ULONG_PTR)(Address)) >> PageMapInfo.PdiShift) & (PageMapInfo.Xpa ? 0x1FF : 0x3FF)); } @@ -101,7 +101,7 @@ MM::PageMap::GetPpeAddress(IN PVOID Address) } /** - * Gets the index of the PPE (Page Directory Pointer Table Entry), that maps given address. + * Gets the offset 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. @@ -112,7 +112,7 @@ MM::PageMap::GetPpeAddress(IN PVOID Address) */ XTAPI ULONG -MM::PageMap::GetPpeIndex(IN PVOID Address) +MM::PageMap::GetPpeOffset(IN PVOID Address) { /* Return zero */ return 0; @@ -158,20 +158,20 @@ MM::PageMap::GetPteAddress(IN PVOID Address) } /** - * Gets the index of the PTE (Page Table Entry), that maps given address. + * Gets the Offset 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. + * @return This routine returns the Offset of the PTE. * * @since XT 1.0 */ XTAPI ULONG -MM::PageMap::GetPteIndex(IN PVOID Address) +MM::PageMap::GetPteOffset(IN PVOID Address) { - /* Return PTE index */ + /* Return PTE Offset */ return ((((ULONG_PTR)(Address)) >> MM_PTI_SHIFT) & (PageMapInfo.Xpa ? 0x1FF : 0x3FF)); } -- 2.52.0 From 7b93c39348c82d48a58926bb7b6ac5c2f6a7ed0c Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Fri, 19 Dec 2025 19:12:50 +0100 Subject: [PATCH 049/166] Add early spin lock initialization --- xtoskrnl/ke/amd64/krnlinit.cc | 4 ++++ xtoskrnl/ke/i686/krnlinit.cc | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/xtoskrnl/ke/amd64/krnlinit.cc b/xtoskrnl/ke/amd64/krnlinit.cc index 985d7d1..c837b1f 100644 --- a/xtoskrnl/ke/amd64/krnlinit.cc +++ b/xtoskrnl/ke/amd64/krnlinit.cc @@ -86,6 +86,10 @@ KE::KernelInit::StartKernel(VOID) /* Save processor state */ Processor::SaveProcessorState(&Prcb->ProcessorState); + /* Initialize spin locks */ + SpinLock::InitializeAllLocks(); + SpinLock::InitializeLockQueues(); + /* Lower to APC runlevel */ RunLevel::LowerRunLevel(APC_LEVEL); diff --git a/xtoskrnl/ke/i686/krnlinit.cc b/xtoskrnl/ke/i686/krnlinit.cc index c2a418a..6142846 100644 --- a/xtoskrnl/ke/i686/krnlinit.cc +++ b/xtoskrnl/ke/i686/krnlinit.cc @@ -86,6 +86,10 @@ KE::KernelInit::StartKernel(VOID) /* Save processor state */ Processor::SaveProcessorState(&Prcb->ProcessorState); + /* Initialize spin locks */ + SpinLock::InitializeAllLocks(); + SpinLock::InitializeLockQueues(); + /* Lower to APC runlevel */ RunLevel::LowerRunLevel(APC_LEVEL); -- 2.52.0 From 24dccf4bed63273a0c92527e5209ed42975ee78b Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Fri, 19 Dec 2025 20:25:43 +0100 Subject: [PATCH 050/166] Make PPE mapping architecture-specific --- xtoskrnl/mm/amd64/pte.cc | 47 ++++++++++++++++++++++++++++++++++++++++ xtoskrnl/mm/i686/pte.cc | 26 ++++++++++++++++++++++ xtoskrnl/mm/pte.cc | 47 ---------------------------------------- 3 files changed, 73 insertions(+), 47 deletions(-) diff --git a/xtoskrnl/mm/amd64/pte.cc b/xtoskrnl/mm/amd64/pte.cc index 796cd45..a077c27 100644 --- a/xtoskrnl/mm/amd64/pte.cc +++ b/xtoskrnl/mm/amd64/pte.cc @@ -139,6 +139,53 @@ MM::Pte::MapP5E(PVOID StartAddress, } } +/** + * Maps a range of virtual addresses at the PPE (Page Directory Pointer Entry) level. + * + * @param StartAddress + * The beginning of the virtual address range to map. + * + * @param EndAddress + * The end of the virtual address range to map. + * + * @param TemplatePpe + * A template PPE to use for creating new entries. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::Pte::MapPPE(PVOID StartAddress, + PVOID EndAddress, + PMMPPE TemplatePpe) +{ + PMMPPE EndSpace, PointerPpe; + + /* Get PPE addresses */ + PointerPpe = MM::Paging::GetPpeAddress(StartAddress); + EndSpace = MM::Paging::GetPpeAddress(EndAddress); + + /* Iterate over all PPEs */ + while(PointerPpe <= EndSpace) + { + /* Check if PPE is already mapped */ + if(!MM::Paging::PteValid(PointerPpe)) + { + /* Map PPE */ + MM::Paging::SetPte(TemplatePpe, MM::Pfn::AllocateBootstrapPages(1), 0); + *PointerPpe = *TemplatePpe; + + /* Clear the page table */ + RtlZeroMemory(MM::Paging::GetPteVirtualAddress(PointerPpe), MM_PAGE_SIZE); + } + + /* Get next table entry */ + PointerPpe = MM::Paging::GetNextPte(PointerPpe); + } +} + /** * Maps a range of virtual addresses at the PXE (PML4) level. * diff --git a/xtoskrnl/mm/i686/pte.cc b/xtoskrnl/mm/i686/pte.cc index b425228..81eb6e3 100644 --- a/xtoskrnl/mm/i686/pte.cc +++ b/xtoskrnl/mm/i686/pte.cc @@ -73,3 +73,29 @@ MM::Pte::InitializePageTable(VOID) { UNIMPLEMENTED; } + +/* + * Maps a range of virtual addresses at the PPE (Page Directory Pointer Entry) level. + * + * @param StartAddress + * The beginning of the virtual address range to map. + * + * @param EndAddress + * The end of the virtual address range to map. + * + * @param TemplatePpe + * A template PPE to use for creating new entries. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::Pte::MapPPE(PVOID StartAddress, + PVOID EndAddress, + PMMPPE TemplatePpe) +{ + /* Just a stub on i686 platform */ + return; +} diff --git a/xtoskrnl/mm/pte.cc b/xtoskrnl/mm/pte.cc index 5123d12..9874b2a 100644 --- a/xtoskrnl/mm/pte.cc +++ b/xtoskrnl/mm/pte.cc @@ -71,53 +71,6 @@ MM::Pte::MapPDE(PVOID StartAddress, } } -/** - * Maps a range of virtual addresses at the PPE (Page Directory Pointer Entry) level. - * - * @param StartAddress - * The beginning of the virtual address range to map. - * - * @param EndAddress - * The end of the virtual address range to map. - * - * @param TemplatePpe - * A template PPE to use for creating new entries. - * - * @return This routine does not return any value. - * - * @since XT 1.0 - */ -XTAPI -VOID -MM::Pte::MapPPE(PVOID StartAddress, - PVOID EndAddress, - PMMPPE TemplatePpe) -{ - PMMPPE EndSpace, PointerPpe; - - /* Get PPE addresses */ - PointerPpe = MM::Paging::GetPpeAddress(StartAddress); - EndSpace = MM::Paging::GetPpeAddress(EndAddress); - - /* Iterate over all PPEs */ - while(PointerPpe <= EndSpace) - { - /* Check if PPE is already mapped */ - if(!MM::Paging::PteValid(PointerPpe)) - { - /* Map PPE */ - MM::Paging::SetPte(TemplatePpe, MM::Pfn::AllocateBootstrapPages(1), 0); - *PointerPpe = *TemplatePpe; - - /* Clear the page table */ - RtlZeroMemory(MM::Paging::GetPteVirtualAddress(PointerPpe), MM_PAGE_SIZE); - } - - /* Get next table entry */ - PointerPpe = MM::Paging::GetNextPte(PointerPpe); - } -} - /** * Maps a range of virtual addresses at the PTE (Page Table Entry) level. * -- 2.52.0 From 755a167f2c84c77b2b0f8aed163e49a54b7f83d2 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Mon, 22 Dec 2025 00:07:48 +0100 Subject: [PATCH 051/166] Respect architecture-specific PTE layouts and write PTEs via PML-aware helpers --- sdk/xtdk/i686/mmtypes.h | 6 +- xtoskrnl/includes/mm/amd64/pagemap.hh | 2 + xtoskrnl/includes/mm/amd64/paging.hh | 2 + xtoskrnl/includes/mm/i686/pagemap.hh | 11 ++- xtoskrnl/includes/mm/i686/paging.hh | 2 + xtoskrnl/mm/amd64/pagemap.cc | 22 ++++++ xtoskrnl/mm/i686/pagemap.cc | 102 +++++++++++++++++++++----- xtoskrnl/mm/paging.cc | 22 ++++++ 8 files changed, 144 insertions(+), 25 deletions(-) diff --git a/sdk/xtdk/i686/mmtypes.h b/sdk/xtdk/i686/mmtypes.h index 8cf0ad7..2e1ba89 100644 --- a/sdk/xtdk/i686/mmtypes.h +++ b/sdk/xtdk/i686/mmtypes.h @@ -154,7 +154,6 @@ typedef struct _HARDWARE_MODERN_PTE /* Generic Page Table entry union to abstract PML2 and PML3 formats */ typedef union _HARDWARE_PTE { - ULONGLONG Long; HARDWARE_LEGACY_PTE Pml2; HARDWARE_MODERN_PTE Pml3; } HARDWARE_PTE, *PHARDWARE_PTE; @@ -250,7 +249,7 @@ typedef struct _MMPML2_PTE_TRANSITION typedef union _MMPML2_PTE { ULONG Long; - HARDWARE_PTE Flush; + HARDWARE_LEGACY_PTE Flush; MMPML2_PTE_HARDWARE Hardware; MMPML2_PTE_PROTOTYPE Prototype; MMPML2_PTE_SOFTWARE Software; @@ -345,7 +344,7 @@ typedef struct _MMPML3_PTE_TRANSITION typedef union _MMPML3_PTE { ULONGLONG Long; - HARDWARE_PTE Flush; + HARDWARE_MODERN_PTE Flush; MMPML3_PTE_HARDWARE Hardware; MMPML3_PTE_PROTOTYPE Prototype; MMPML3_PTE_SOFTWARE Software; @@ -357,7 +356,6 @@ typedef union _MMPML3_PTE /* Generic Page Table Entry union to abstract PML2 and PML3 formats */ typedef union _MMPTE { - ULONGLONG Long; MMPML2_PTE Pml2; MMPML3_PTE Pml3; } MMPTE, *PMMPTE; diff --git a/xtoskrnl/includes/mm/amd64/pagemap.hh b/xtoskrnl/includes/mm/amd64/pagemap.hh index 19c62ae..57b20e5 100644 --- a/xtoskrnl/includes/mm/amd64/pagemap.hh +++ b/xtoskrnl/includes/mm/amd64/pagemap.hh @@ -60,6 +60,8 @@ namespace MM XTAPI VOID SetPteCaching(IN PMMPTE PtePointer, IN BOOLEAN CacheDisable, IN BOOLEAN WriteThrough); + XTAPI VOID WritePte(IN PMMPTE Pte, + IN MMPTE Value); } PAGEMAP, *PPAGEMAP; class PageMapBasic final : public PageMap diff --git a/xtoskrnl/includes/mm/amd64/paging.hh b/xtoskrnl/includes/mm/amd64/paging.hh index 6795add..d2ccda0 100644 --- a/xtoskrnl/includes/mm/amd64/paging.hh +++ b/xtoskrnl/includes/mm/amd64/paging.hh @@ -56,6 +56,8 @@ namespace MM STATIC XTAPI VOID SetPteCaching(IN PMMPTE PtePointer, IN BOOLEAN CacheDisable, IN BOOLEAN WriteThrough); + STATIC XTAPI VOID WritePte(IN PMMPTE Pte, + IN MMPTE Value); STATIC XTFASTCALL VOID ZeroPages(IN PVOID Address, IN ULONG Size); diff --git a/xtoskrnl/includes/mm/i686/pagemap.hh b/xtoskrnl/includes/mm/i686/pagemap.hh index e439fab..64244ce 100644 --- a/xtoskrnl/includes/mm/i686/pagemap.hh +++ b/xtoskrnl/includes/mm/i686/pagemap.hh @@ -23,7 +23,7 @@ namespace MM public: VIRTUAL XTAPI PMMPTE AdvancePte(IN PMMPTE Pte, IN ULONG Count) = 0; - XTAPI VOID ClearPte(IN PMMPTE PtePointer); + VIRTUAL XTAPI VOID ClearPte(IN PMMPTE PtePointer) = 0; XTAPI ULONG GetEmptyPteList(VOID); VIRTUAL XTAPI ULONG_PTR GetNextEntry(IN PMMPTE Pte) = 0; VIRTUAL XTAPI PMMPTE GetNextPte(IN PMMPTE Pte) = 0; @@ -54,6 +54,9 @@ namespace MM VIRTUAL XTAPI VOID SetPteCaching(IN PMMPTE PtePointer, IN BOOLEAN CacheDisable, IN BOOLEAN WriteThrough) = 0; + VIRTUAL XTAPI VOID WritePte(IN PMMPTE Pte, + IN MMPTE Value) = 0; + } PAGEMAP, *PPAGEMAP; class PageMapBasic final : public PageMap @@ -61,6 +64,7 @@ namespace MM public: XTAPI PMMPTE AdvancePte(IN PMMPTE Pte, IN ULONG Count); + XTAPI VOID ClearPte(IN PMMPTE PtePointer); XTAPI ULONG_PTR GetNextEntry(IN PMMPTE Pte); XTAPI PMMPTE GetNextPte(IN PMMPTE Pte); XTAPI BOOLEAN GetOneEntry(IN PMMPTE Pte); @@ -82,6 +86,8 @@ namespace MM XTAPI VOID SetPteCaching(IN PMMPTE PtePointer, IN BOOLEAN CacheDisable, IN BOOLEAN WriteThrough); + XTAPI VOID WritePte(IN PMMPTE Pte, + IN MMPTE Value); }; class PageMapXpa final : public PageMap @@ -89,6 +95,7 @@ namespace MM public: XTAPI PMMPTE AdvancePte(IN PMMPTE Pte, IN ULONG Count); + XTAPI VOID ClearPte(IN PMMPTE PtePointer); XTAPI ULONG_PTR GetNextEntry(IN PMMPTE Pte); XTAPI PMMPTE GetNextPte(IN PMMPTE Pte); XTAPI BOOLEAN GetOneEntry(IN PMMPTE Pte); @@ -110,6 +117,8 @@ namespace MM XTAPI VOID SetPteCaching(IN PMMPTE PtePointer, IN BOOLEAN CacheDisable, IN BOOLEAN WriteThrough); + XTAPI VOID WritePte(IN PMMPTE Pte, + IN MMPTE Value); }; } diff --git a/xtoskrnl/includes/mm/i686/paging.hh b/xtoskrnl/includes/mm/i686/paging.hh index a1b13ad..b6c8209 100644 --- a/xtoskrnl/includes/mm/i686/paging.hh +++ b/xtoskrnl/includes/mm/i686/paging.hh @@ -52,6 +52,8 @@ namespace MM STATIC XTAPI VOID SetPteCaching(IN PMMPTE PtePointer, IN BOOLEAN CacheDisable, IN BOOLEAN WriteThrough); + STATIC XTAPI VOID WritePte(IN PMMPTE Pte, + IN MMPTE Value); STATIC XTFASTCALL VOID ZeroPages(IN PVOID Address, IN ULONG Size); diff --git a/xtoskrnl/mm/amd64/pagemap.cc b/xtoskrnl/mm/amd64/pagemap.cc index fff7c91..06d3e42 100644 --- a/xtoskrnl/mm/amd64/pagemap.cc +++ b/xtoskrnl/mm/amd64/pagemap.cc @@ -515,6 +515,28 @@ MM::PageMap::SetPteCaching(IN PMMPTE PtePointer, PtePointer->Hardware.WriteThrough = WriteThrough; } +/** + * Writes a Page Table Entry (PTE) with the specified value. + * + * @param Pte + * Pointer to the page table entry (PTE) to write. + * + * @param Value + * The value to write to the PTE. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::PageMap::WritePte(IN PMMPTE Pte, + IN MMPTE Value) +{ + /* Write PTE value */ + Pte->Long = Value.Long; +} + /** * Gets the virtual address that is mapped by a given Page Directory Entry (PML4). * diff --git a/xtoskrnl/mm/i686/pagemap.cc b/xtoskrnl/mm/i686/pagemap.cc index 553d3ed..7840274 100644 --- a/xtoskrnl/mm/i686/pagemap.cc +++ b/xtoskrnl/mm/i686/pagemap.cc @@ -9,24 +9,6 @@ #include -/** - * Clears the contents of a page table entry (PTE). - * - * @param PtePointer - * Pointer to the page table entry (PTE) to be cleared. - * - * @return This routine does not return any value. - * - * @since XT 1.0 - */ -XTAPI -VOID -MM::PageMap::ClearPte(IN PMMPTE PtePointer) -{ - /* Clear PTE */ - PtePointer->Long = 0; -} - /** * Gets the value representing an empty PTE list. * @@ -212,6 +194,24 @@ MM::PageMapBasic::AdvancePte(IN PMMPTE Pte, return (PMMPTE)((ULONG_PTR)Pte + (Count * sizeof(MMPML2_PTE))); } +/** + * Clears the contents of a page table entry (PTE). + * + * @param PtePointer + * Pointer to the page table entry (PTE) to be cleared. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::PageMapBasic::ClearPte(IN PMMPTE PtePointer) +{ + /* Clear PTE */ + PtePointer->Pml2.Long = 0; +} + /** * Gets the next entry in a PTE list. * @@ -469,7 +469,7 @@ MM::PageMapBasic::SetPte(IN PMMPTE PtePointer, /* Set PTE */ PtePointer->Pml2.Hardware.PageFrameNumber = PageFrameNumber; PtePointer->Pml2.Hardware.Valid = 1; - PtePointer->Long |= AttributesMask; + PtePointer->Pml2.Long |= AttributesMask; } /** @@ -499,6 +499,28 @@ MM::PageMapBasic::SetPteCaching(IN PMMPTE PtePointer, PtePointer->Pml2.Hardware.WriteThrough = WriteThrough; } +/** + * Writes a PML2 page table entry (PTE) with the specified value. + * + * @param Pte + * Pointer to the page table entry (PTE) to write. + * + * @param Value + * The value to write to the PTE. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::PageMapBasic::WritePte(IN PMMPTE Pte, + IN MMPTE Value) +{ + /* Write PTE value */ + Pte->Pml2.Long = Value.Pml2.Long; +} + /** * Advances a PTE pointer by a given number of entries, considering the actual PTE size for PML3. * @@ -521,6 +543,24 @@ MM::PageMapXpa::AdvancePte(IN PMMPTE Pte, return (PMMPTE)((ULONG_PTR)Pte + (Count * sizeof(MMPML3_PTE))); } +/** + * Clears the contents of a page table entry (PTE). + * + * @param PtePointer + * Pointer to the page table entry (PTE) to be cleared. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::PageMapXpa::ClearPte(IN PMMPTE PtePointer) +{ + /* Clear PTE */ + PtePointer->Pml3.Long = 0; +} + /** * Gets the next entry in a PTE list. * @@ -777,7 +817,7 @@ MM::PageMapXpa::SetPte(IN PMMPTE PtePointer, /* Set PTE */ PtePointer->Pml3.Hardware.PageFrameNumber = PageFrameNumber; PtePointer->Pml3.Hardware.Valid = 1; - PtePointer->Long |= AttributesMask; + PtePointer->Pml3.Long |= AttributesMask; } /** @@ -806,3 +846,25 @@ MM::PageMapXpa::SetPteCaching(IN PMMPTE PtePointer, PtePointer->Pml3.Hardware.CacheDisable = CacheDisable; PtePointer->Pml3.Hardware.WriteThrough = WriteThrough; } + +/** + * Writes a PML3 page table entry (PTE) with the specified value. + * + * @param Pte + * Pointer to the page table entry (PTE) to write. + * + * @param Value + * The value to write to the PTE. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::PageMapXpa::WritePte(IN PMMPTE Pte, + IN MMPTE Value) +{ + /* Write PTE value */ + Pte->Pml3.Long = Value.Pml3.Long; +} \ No newline at end of file diff --git a/xtoskrnl/mm/paging.cc b/xtoskrnl/mm/paging.cc index 18c24d2..331d9f5 100644 --- a/xtoskrnl/mm/paging.cc +++ b/xtoskrnl/mm/paging.cc @@ -520,3 +520,25 @@ MM::Paging::SetPteCaching(IN PMMPTE PtePointer, /* Set caching attributes */ PmlRoutines->SetPteCaching(PtePointer, CacheDisable, WriteThrough); } + +/** + * Writes a Page Table Entry (PTE) with the specified value. + * + * @param Pte + * Pointer to the page table entry (PTE) to write. + * + * @param Value + * The value to write to the PTE. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::Paging::WritePte(IN PMMPTE Pte, + IN MMPTE Value) +{ + /* Assign PTE value */ + PmlRoutines->WritePte(Pte, Value); +} -- 2.52.0 From e237a944cc71dded30228b627d8c8e259512309c Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Mon, 22 Dec 2025 08:21:43 +0100 Subject: [PATCH 052/166] Extend PTE helpers with raw read and write support --- xtoskrnl/includes/mm/amd64/pagemap.hh | 3 ++ xtoskrnl/includes/mm/amd64/paging.hh | 3 ++ xtoskrnl/includes/mm/i686/pagemap.hh | 9 ++++ xtoskrnl/includes/mm/i686/paging.hh | 3 ++ xtoskrnl/mm/amd64/pagemap.cc | 41 +++++++++++++- xtoskrnl/mm/i686/pagemap.cc | 77 +++++++++++++++++++++++++++ xtoskrnl/mm/paging.cc | 39 ++++++++++++++ 7 files changed, 174 insertions(+), 1 deletion(-) diff --git a/xtoskrnl/includes/mm/amd64/pagemap.hh b/xtoskrnl/includes/mm/amd64/pagemap.hh index 57b20e5..9cc6d7e 100644 --- a/xtoskrnl/includes/mm/amd64/pagemap.hh +++ b/xtoskrnl/includes/mm/amd64/pagemap.hh @@ -38,6 +38,7 @@ namespace MM XTAPI PMMPPE GetPpeAddress(IN PVOID Address); XTAPI ULONG GetPpeOffset(IN PVOID Address); VIRTUAL XTAPI PVOID GetPpeVirtualAddress(IN PMMPPE PpePointer) = 0; + XTAPI ULONG_PTR GetPte(IN PMMPTE PtePointer); XTAPI PMMPTE GetPteAddress(IN PVOID Address); XTAPI LONG GetPteDistance(PMMPTE EndPte, PMMPTE StartPte); @@ -57,6 +58,8 @@ namespace MM XTAPI VOID SetPte(IN PMMPTE PtePointer, IN PFN_NUMBER PageFrameNumber, IN ULONG_PTR AttributesMask); + XTAPI VOID SetPte(IN PMMPTE PtePointer, + IN ULONG_PTR Attributes); XTAPI VOID SetPteCaching(IN PMMPTE PtePointer, IN BOOLEAN CacheDisable, IN BOOLEAN WriteThrough); diff --git a/xtoskrnl/includes/mm/amd64/paging.hh b/xtoskrnl/includes/mm/amd64/paging.hh index d2ccda0..efbfe83 100644 --- a/xtoskrnl/includes/mm/amd64/paging.hh +++ b/xtoskrnl/includes/mm/amd64/paging.hh @@ -36,6 +36,7 @@ namespace MM STATIC XTAPI PVOID GetPdeVirtualAddress(IN PMMPDE PdePointer); STATIC XTAPI PMMPPE GetPpeAddress(IN PVOID Address); STATIC XTAPI PVOID GetPpeVirtualAddress(IN PMMPPE PpePointer); + STATIC XTAPI ULONG_PTR GetPte(IN PMMPTE PtePointer); STATIC XTAPI PMMPTE GetPteAddress(IN PVOID Address); STATIC XTAPI LONG GetPteDistance(PMMPTE EndPte, PMMPTE StartPte); @@ -53,6 +54,8 @@ namespace MM STATIC XTAPI VOID SetPte(IN PMMPTE PtePointer, IN PFN_NUMBER PageFrameNumber, IN ULONG_PTR AttributesMask); + STATIC XTAPI VOID SetPte(IN PMMPTE PtePointer, + IN ULONG_PTR Attributes); STATIC XTAPI VOID SetPteCaching(IN PMMPTE PtePointer, IN BOOLEAN CacheDisable, IN BOOLEAN WriteThrough); diff --git a/xtoskrnl/includes/mm/i686/pagemap.hh b/xtoskrnl/includes/mm/i686/pagemap.hh index 64244ce..30de3b6 100644 --- a/xtoskrnl/includes/mm/i686/pagemap.hh +++ b/xtoskrnl/includes/mm/i686/pagemap.hh @@ -35,6 +35,7 @@ namespace MM XTAPI PMMPPE GetPpeAddress(IN PVOID Address); XTAPI ULONG GetPpeOffset(IN PVOID Address); XTAPI PVOID GetPpeVirtualAddress(IN PMMPPE PpePointer); + VIRTUAL XTAPI ULONG_PTR GetPte(IN PMMPTE PtePointer) = 0; XTAPI PMMPTE GetPteAddress(IN PVOID Address); XTAPI ULONG GetPteOffset(IN PVOID Address); VIRTUAL XTAPI LONG GetPteDistance(PMMPTE EndPte, @@ -51,6 +52,8 @@ namespace MM VIRTUAL XTAPI VOID SetPte(IN PMMPTE PtePointer, IN PFN_NUMBER PageFrameNumber, IN ULONG_PTR AttributesMask) = 0; + VIRTUAL XTAPI VOID SetPte(IN PMMPTE PtePointer, + IN ULONG_PTR Attributes) = 0; VIRTUAL XTAPI VOID SetPteCaching(IN PMMPTE PtePointer, IN BOOLEAN CacheDisable, IN BOOLEAN WriteThrough) = 0; @@ -70,6 +73,7 @@ namespace MM XTAPI BOOLEAN GetOneEntry(IN PMMPTE Pte); XTAPI PFN_NUMBER GetPageFrameNumber(IN PMMPTE Pte); XTAPI PVOID GetPdeVirtualAddress(IN PMMPDE PdePointer); + XTAPI ULONG_PTR GetPte(IN PMMPTE PtePointer); XTAPI LONG GetPteDistance(PMMPTE EndPte, PMMPTE StartPte); XTAPI ULONG GetPteSize(VOID); @@ -83,6 +87,8 @@ namespace MM XTAPI VOID SetPte(IN PMMPTE PtePointer, IN PFN_NUMBER PageFrameNumber, IN ULONG_PTR AttributesMask); + XTAPI VOID SetPte(IN PMMPTE PtePointer, + IN ULONG_PTR Attributes); XTAPI VOID SetPteCaching(IN PMMPTE PtePointer, IN BOOLEAN CacheDisable, IN BOOLEAN WriteThrough); @@ -101,6 +107,7 @@ namespace MM XTAPI BOOLEAN GetOneEntry(IN PMMPTE Pte); XTAPI PFN_NUMBER GetPageFrameNumber(IN PMMPTE Pte); XTAPI PVOID GetPdeVirtualAddress(IN PMMPDE PdePointer); + XTAPI ULONG_PTR GetPte(IN PMMPTE PtePointer); XTAPI LONG GetPteDistance(PMMPTE EndPte, PMMPTE StartPte); XTAPI ULONG GetPteSize(VOID); @@ -114,6 +121,8 @@ namespace MM XTAPI VOID SetPte(IN PMMPTE PtePointer, IN PFN_NUMBER PageFrameNumber, IN ULONG_PTR AttributesMask); + XTAPI VOID SetPte(IN PMMPTE PtePointer, + IN ULONG_PTR Attributes); XTAPI VOID SetPteCaching(IN PMMPTE PtePointer, IN BOOLEAN CacheDisable, IN BOOLEAN WriteThrough); diff --git a/xtoskrnl/includes/mm/i686/paging.hh b/xtoskrnl/includes/mm/i686/paging.hh index b6c8209..2c06d3c 100644 --- a/xtoskrnl/includes/mm/i686/paging.hh +++ b/xtoskrnl/includes/mm/i686/paging.hh @@ -34,6 +34,7 @@ namespace MM STATIC XTAPI PVOID GetPdeVirtualAddress(IN PMMPDE PdePointer); STATIC XTAPI PMMPPE GetPpeAddress(IN PVOID Address); STATIC XTAPI PVOID GetPpeVirtualAddress(IN PMMPPE PpePointer); + STATIC XTAPI ULONG_PTR GetPte(IN PMMPTE PtePointer); STATIC XTAPI PMMPTE GetPteAddress(IN PVOID Address); STATIC XTAPI LONG GetPteDistance(PMMPTE EndPte, PMMPTE StartPte); @@ -49,6 +50,8 @@ namespace MM STATIC XTAPI VOID SetPte(IN PMMPTE PtePointer, IN PFN_NUMBER PageFrameNumber, IN ULONG_PTR AttributesMask); + STATIC XTAPI VOID SetPte(IN PMMPTE PtePointer, + IN ULONG_PTR Attributes); STATIC XTAPI VOID SetPteCaching(IN PMMPTE PtePointer, IN BOOLEAN CacheDisable, IN BOOLEAN WriteThrough); diff --git a/xtoskrnl/mm/amd64/pagemap.cc b/xtoskrnl/mm/amd64/pagemap.cc index 06d3e42..e89b05b 100644 --- a/xtoskrnl/mm/amd64/pagemap.cc +++ b/xtoskrnl/mm/amd64/pagemap.cc @@ -269,6 +269,24 @@ MM::PageMap::GetPpeOffset(IN PVOID Address) return ((((ULONGLONG)Address) >> MM_PPI_SHIFT) & 0x1FF); } + /** + * Gets the entire contents of a Page Table Entry (PTE) as a single value. + * + * @param PtePointer + * Pointer to the Page Table Entry (PTE) to read. + * + * @return This routine returns the contents of the PTE as a single value. + * + * @since XT 1.0 + */ +XTAPI +ULONG_PTR +MM::PageMap::GetPte(IN PMMPTE PtePointer) +{ + /* Return PTE value */ + return PtePointer->Long; +} + /** * Gets the address of the PTE (Page Table Entry), that maps given address. * @@ -461,7 +479,7 @@ MM::PageMap::SetOneEntry(IN PMMPTE Pte, } /** - * Sets a PML2 page table entry (PTE) with the specified physical page and access flags. + * Sets a Page Table Entry (PTE) with the specified physical page and access flags. * * @param PtePointer * Pointer to the page table entry (PTE) to set. @@ -488,6 +506,27 @@ MM::PageMap::SetPte(IN PMMPTE PtePointer, PtePointer->Long |= AttributesMask; } +/** + * Sets a Page Table Entry (PTE) with the specified attributes. + * + * @param PtePointer + * Pointer to the page table entry (PTE) to set. + * + * @param Attributes + * Specifies the attributes to apply to the PTE. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::PageMap::SetPte(IN PMMPTE PtePointer, + IN ULONG_PTR Attributes) +{ + PtePointer->Long = Attributes; +} + /** * Sets caching attributes for a PML2 page table entry (PTE). * diff --git a/xtoskrnl/mm/i686/pagemap.cc b/xtoskrnl/mm/i686/pagemap.cc index 7840274..2ca3cd6 100644 --- a/xtoskrnl/mm/i686/pagemap.cc +++ b/xtoskrnl/mm/i686/pagemap.cc @@ -301,6 +301,23 @@ MM::PageMapBasic::GetPdeVirtualAddress(IN PMMPDE PdePointer) return ((PVOID)((ULONG)(PdePointer) << 20)); } + /** + * Gets the entire contents of a PML2 Page Table Entry (PTE) as a single value. + * + * @param PtePointer + * Pointer to the Page Table Entry (PTE) to read. + * + * @return This routine returns the contents of the PTE as a single value. + * + * @since XT 1.0 + */ +XTAPI +ULONG_PTR +MM::PageMapBasic::GetPte(IN PMMPTE PtePointer) +{ + /* Return PTE value */ + return PtePointer->Pml2.Long; +} /** * Calculates the distance between two PTE pointers. * @@ -472,6 +489,27 @@ MM::PageMapBasic::SetPte(IN PMMPTE PtePointer, PtePointer->Pml2.Long |= AttributesMask; } +/** + * Sets a PML2 page table entry (PTE) with the specified attributes. + * + * @param PtePointer + * Pointer to the page table entry (PTE) to set. + * + * @param Attributes + * Specifies the attributes to apply to the PTE. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::PageMapBasic::SetPte(IN PMMPTE PtePointer, + IN ULONG_PTR Attributes) +{ + PtePointer->Pml2.Long = Attributes; +} + /** * Sets caching attributes for a PML2 page table entry (PTE). * @@ -650,6 +688,24 @@ MM::PageMapXpa::GetPdeVirtualAddress(IN PMMPDE PdePointer) return ((PVOID)((ULONG)(PdePointer) << 18)); } + /** + * Gets the entire contents of a PML3 Page Table Entry (PTE) as a single value. + * + * @param PtePointer + * Pointer to the Page Table Entry (PTE) to read. + * + * @return This routine returns the contents of the PTE as a single value. + * + * @since XT 1.0 + */ +XTAPI +ULONG_PTR +MM::PageMapXpa::GetPte(IN PMMPTE PtePointer) +{ + /* Return PTE value */ + return PtePointer->Pml3.Long; +} + /** * Calculates the distance between two PTE pointers. * @@ -820,6 +876,27 @@ MM::PageMapXpa::SetPte(IN PMMPTE PtePointer, PtePointer->Pml3.Long |= AttributesMask; } +/** + * Sets a PML3 page table entry (PTE) with the specified attributes. + * + * @param PtePointer + * Pointer to the page table entry (PTE) to set. + * + * @param Attributes + * Specifies the attributes to apply to the PTE. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::PageMapXpa::SetPte(IN PMMPTE PtePointer, + IN ULONG_PTR Attributes) +{ + PtePointer->Pml3.Long = Attributes; +} + /** * Sets caching attributes for a PML3 page table entry (PTE). * diff --git a/xtoskrnl/mm/paging.cc b/xtoskrnl/mm/paging.cc index 331d9f5..5a9562d 100644 --- a/xtoskrnl/mm/paging.cc +++ b/xtoskrnl/mm/paging.cc @@ -293,6 +293,24 @@ MM::Paging::GetPpeVirtualAddress(IN PMMPPE PpePointer) return PmlRoutines->GetPpeVirtualAddress(PpePointer); } + /** + * Gets the entire contents of a Page Table Entry (PTE) as a single value. + * + * @param PtePointer + * Pointer to the Page Table Entry (PTE) to read. + * + * @return This routine returns the contents of the PTE as a single value. + * + * @since XT 1.0 + */ +XTAPI +ULONG_PTR +MM::Paging::GetPte(IN PMMPTE PtePointer) +{ + /* Return PTE value */ + return PmlRoutines->GetPte(PtePointer); +} + /** * Gets the address of the PTE (Page Table Entry), that maps given address. * @@ -495,6 +513,27 @@ MM::Paging::SetPte(IN PMMPTE PtePointer, PmlRoutines->SetPte(PtePointer, PageFrameNumber, AttributesMask); } +/** + * Sets a Page Table Entry (PTE) with the specified attributes. + * + * @param PtePointer + * Pointer to the page table entry (PTE) to set. + * + * @param Attributes + * Specifies the attributes to apply to the PTE. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::Paging::SetPte(IN PMMPTE PtePointer, + IN ULONG_PTR Attributes) +{ + PmlRoutines->SetPte(PtePointer, Attributes); +} + /** * Sets caching attributes for a PML2 page table entry (PTE). * -- 2.52.0 From 6aa148784b658271342d03b15331b8188ba3cc1d Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Mon, 22 Dec 2025 10:14:11 +0100 Subject: [PATCH 053/166] Select correct self-map base for PAE and non-PAE paging --- boot/xtldr/modules/xtos_o/i686/memory.cc | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/boot/xtldr/modules/xtos_o/i686/memory.cc b/boot/xtldr/modules/xtos_o/i686/memory.cc index c2b2e1c..44ee233 100644 --- a/boot/xtldr/modules/xtos_o/i686/memory.cc +++ b/boot/xtldr/modules/xtos_o/i686/memory.cc @@ -59,9 +59,22 @@ EFI_STATUS Xtos::EnablePaging(IN PXTBL_PAGE_MAPPING PageMap) { EFI_STATUS Status; + ULONG_PTR SelfMapAddress; + + /* Initialize self map address */ + if(PageMap->PageMapLevel == 3) + { + /* For PML3 (PAE) use PTE base address */ + SelfMapAddress = MM_PTE_BASE; + } + else + { + /* For PML2 (PAE disabled) use legacy PDE base address */ + SelfMapAddress = MM_PDE_LEGACY_BASE; + } /* Build page map */ - Status = XtLdrProtocol->Memory.BuildPageMap(PageMap, MM_PTE_BASE); + Status = XtLdrProtocol->Memory.BuildPageMap(PageMap, SelfMapAddress); if(Status != STATUS_EFI_SUCCESS) { /* Failed to build page map */ -- 2.52.0 From 643fd0d1e81003d08ec1b1c26ae77c0ef119dc70 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Mon, 22 Dec 2025 15:00:14 +0100 Subject: [PATCH 054/166] Fix PTE free list sentinel handling --- xtoskrnl/mm/i686/pagemap.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/xtoskrnl/mm/i686/pagemap.cc b/xtoskrnl/mm/i686/pagemap.cc index 2ca3cd6..ee66229 100644 --- a/xtoskrnl/mm/i686/pagemap.cc +++ b/xtoskrnl/mm/i686/pagemap.cc @@ -226,8 +226,8 @@ XTAPI ULONG_PTR MM::PageMapBasic::GetNextEntry(IN PMMPTE Pte) { - /* Return next entry in PTE list */ - return Pte->Pml2.List.NextEntry; + /* Return next entry in PTE list, translating the hardware limit (0xFFFFF) to the logical sentinel (MAXULONG) */ + return (Pte->Pml2.List.NextEntry == 0xFFFFF) ? MAXULONG : Pte->Pml2.List.NextEntry; } /** @@ -435,8 +435,8 @@ VOID MM::PageMapBasic::SetNextEntry(IN PMMPTE Pte, IN ULONG_PTR Value) { - /* Set next entry in PTE list */ - Pte->Pml2.List.NextEntry = Value; + /* Set next entry in PTE list, translating the logical sentinel (MAXULONG) to the 20-bit hardware limit (0xFFFFF) */ + Pte->Pml2.List.NextEntry = (Value == MAXULONG) ? 0xFFFFF : Value; } /** -- 2.52.0 From 7575526f07a1b60f6d6efa192e5640f05bbc2552 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Mon, 22 Dec 2025 23:32:54 +0100 Subject: [PATCH 055/166] Fix physical page count overflow by using 64-bit type --- xtoskrnl/includes/mm/pfn.hh | 4 ++-- xtoskrnl/mm/data.cc | 2 +- xtoskrnl/mm/pfn.cc | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/xtoskrnl/includes/mm/pfn.hh b/xtoskrnl/includes/mm/pfn.hh index 3fc0eff..6473f1a 100644 --- a/xtoskrnl/includes/mm/pfn.hh +++ b/xtoskrnl/includes/mm/pfn.hh @@ -21,14 +21,14 @@ namespace MM STATIC PLOADER_MEMORY_DESCRIPTOR FreeDescriptor; STATIC ULONG_PTR HighestPhysicalPage; STATIC ULONG_PTR LowestPhysicalPage; - STATIC ULONG NumberOfPhysicalPages; + STATIC ULONGLONG NumberOfPhysicalPages; STATIC LOADER_MEMORY_DESCRIPTOR OriginalFreeDescriptor; STATIC PFN_NUMBER PfnDatabaseSize; public: STATIC XTAPI PFN_NUMBER AllocateBootstrapPages(IN PFN_NUMBER NumberOfPages); STATIC XTAPI VOID ComputePfnDatabaseSize(VOID); - STATIC XTAPI ULONG GetNumberOfPhysicalPages(VOID); + STATIC XTAPI ULONGLONG GetNumberOfPhysicalPages(VOID); STATIC XTAPI PFN_NUMBER GetPfnDatabaseSize(VOID); STATIC XTAPI VOID ScanMemoryDescriptors(VOID); }; diff --git a/xtoskrnl/mm/data.cc b/xtoskrnl/mm/data.cc index 93a8c4f..39733e1 100644 --- a/xtoskrnl/mm/data.cc +++ b/xtoskrnl/mm/data.cc @@ -34,7 +34,7 @@ ULONG_PTR MM::Pfn::LowestPhysicalPage = -1; MMMEMORY_LAYOUT MM::Manager::MemoryLayout; /* Number of physical pages */ -ULONG MM::Pfn::NumberOfPhysicalPages; +ULONGLONG MM::Pfn::NumberOfPhysicalPages; /* Number of system PTEs */ PFN_NUMBER MM::Manager::NumberOfSystemPtes; diff --git a/xtoskrnl/mm/pfn.cc b/xtoskrnl/mm/pfn.cc index 324f569..68e3337 100644 --- a/xtoskrnl/mm/pfn.cc +++ b/xtoskrnl/mm/pfn.cc @@ -68,7 +68,7 @@ MM::Pfn::ComputePfnDatabaseSize(VOID) * @since XT 1.0 */ XTAPI -ULONG +ULONGLONG MM::Pfn::GetNumberOfPhysicalPages(VOID) { /* Return the number of physical pages */ -- 2.52.0 From f0a06db7d2012c951fbdf807da9cfa5e1d80a4a8 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Mon, 22 Dec 2025 23:48:04 +0100 Subject: [PATCH 056/166] Bring up i686 page table initialization --- xtoskrnl/mm/i686/pte.cc | 40 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/xtoskrnl/mm/i686/pte.cc b/xtoskrnl/mm/i686/pte.cc index 81eb6e3..3ca5b1f 100644 --- a/xtoskrnl/mm/i686/pte.cc +++ b/xtoskrnl/mm/i686/pte.cc @@ -71,7 +71,45 @@ XTAPI VOID MM::Pte::InitializePageTable(VOID) { - UNIMPLEMENTED; + PMMPTE EndSpacePte, PointerPte; + PMMMEMORY_LAYOUT MemoryLayout; + CPUID_REGISTERS CpuRegisters; + MMPTE TemplatePte; + + /* Retrieve current paging mode and memory layout */ + MemoryLayout = MM::Manager::GetMemoryLayout(); + + /* Get CPU features */ + CpuRegisters.Leaf = CPUID_GET_STANDARD1_FEATURES; + AR::CpuFunc::CpuId(&CpuRegisters); + + /* Check if Paging Global Extensions (PGE) is supported */ + if(CpuRegisters.Edx & CPUID_FEATURES_EDX_PGE) + { + /* Enable the Global Paging (PGE) feature */ + AR::CpuFunc::WriteControlRegister(4, AR::CpuFunc::ReadControlRegister(4) | CR4_PGE); + } + + /* Get the PD user-space range for both legacy and PAE paging */ + PointerPte = (PMMPTE)MM::Paging::GetPdeAddress(0); + EndSpacePte = (PMMPTE)MM::Paging::GetPdeAddress(MemoryLayout->UserSpaceEnd); + + /* Clear all top-level entries mapping the user address space */ + while(PointerPte <= EndSpacePte) + { + MM::Paging::ClearPte(PointerPte); + PointerPte = MM::Paging::GetNextPte(PointerPte); + } + + /* Flush the TLB to invalidate all non-global entries */ + AR::CpuFunc::FlushTlb(); + + /* Create a template PTE for mapping kernel pages */ + MM::Paging::ClearPte(&TemplatePte); + MM::Paging::SetPte(&TemplatePte, 0, MM_PTE_READWRITE | MM_PTE_CACHE_ENABLE); + + /* Map the kernel's PD entries */ + MM::Pte::MapPDE(MemoryLayout->SystemSpaceStart, (PVOID)MM_HIGHEST_SYSTEM_ADDRESS, &TemplatePte); } /* -- 2.52.0 From 560cd43b3429483f2a6de80696018de44d967a81 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Tue, 23 Dec 2025 12:04:43 +0100 Subject: [PATCH 057/166] Update memory manager type definitions and constants --- sdk/xtdk/amd64/mmtypes.h | 3 +++ sdk/xtdk/i686/mmtypes.h | 9 ++++++--- sdk/xtdk/mmtypes.h | 21 +++++++++++++++++++++ sdk/xtdk/xtstruct.h | 1 + 4 files changed, 31 insertions(+), 3 deletions(-) diff --git a/sdk/xtdk/amd64/mmtypes.h b/sdk/xtdk/amd64/mmtypes.h index f05f080..0562244 100644 --- a/sdk/xtdk/amd64/mmtypes.h +++ b/sdk/xtdk/amd64/mmtypes.h @@ -73,6 +73,9 @@ #define MM_PTE_PROTOTYPE 0x0000000000000400ULL #define MM_PTE_TRANSITION 0x0000000000000800ULL +/* PTE frame bits */ +#define MM_PTE_FRAME_BITS 57 + /* PTE protection bits */ #define MM_PTE_PROTECTION_BITS 5 diff --git a/sdk/xtdk/i686/mmtypes.h b/sdk/xtdk/i686/mmtypes.h index 2e1ba89..469a708 100644 --- a/sdk/xtdk/i686/mmtypes.h +++ b/sdk/xtdk/i686/mmtypes.h @@ -69,6 +69,9 @@ #define MM_PTE_PROTOTYPE 0x00000400 #define MM_PTE_TRANSITION 0x00000800 +/* PTE frame bits */ +#define MM_PTE_FRAME_BITS 25 + /* PTE protection bits */ #define MM_PTE_PROTECTION_BITS 5 @@ -386,6 +389,7 @@ typedef struct _MMPFN USHORT ReferenceCount; } e2; } u3; + ULONG UsedPageTableEntries; union { MMPTE OriginalPte; @@ -396,12 +400,11 @@ typedef struct _MMPFN ULONG_PTR EntireFrame; struct { - ULONG_PTR PteFrame:26; + ULONG_PTR PteFrame:25; ULONG_PTR InPageError:1; ULONG_PTR VerifierAllocation:1; ULONG_PTR AweAllocation:1; - ULONG_PTR LockCharged:1; - ULONG_PTR KernelStack:1; + ULONG_PTR Priority:3; ULONG_PTR MustBeCached:1; }; } u4; diff --git a/sdk/xtdk/mmtypes.h b/sdk/xtdk/mmtypes.h index 193ca8f..1c0f8a5 100644 --- a/sdk/xtdk/mmtypes.h +++ b/sdk/xtdk/mmtypes.h @@ -14,6 +14,18 @@ #include ARCH_HEADER(xtstruct.h) +/* Number of hyper space pages */ +#define MM_HYPERSPACE_PAGE_COUNT 255 + +/* Number of paging colors */ +#define MM_PAGING_COLORS 64 + +/* PTE frame mask definition */ +#define MM_PFN_PTE_FRAME (((ULONG_PTR)1 << MM_PTE_FRAME_BITS) - 1) + +/* Number of reserved zeroed PTEs */ +#define MM_RESERVED_ZERO_PTES 32 + /* Memory manager page lists */ typedef enum _MMPAGELISTS { @@ -27,6 +39,15 @@ typedef enum _MMPAGELISTS TransitionPage = 7 } MMPAGELISTS, *PMMPAGELISTS; +/* Page cache attributes */ +typedef enum _MMPFN_CACHE_ATTRIBUTE +{ + PfnNonCached, + PfnCached, + PfnWriteCombined, + PfnNotMapped +} MMPFN_CACHE_ATTRIBUTE, *PMMPFN_CACHE_ATTRIBUTE; + /* Page table pool types */ typedef enum _MMSYSTEM_PTE_POOL_TYPE { diff --git a/sdk/xtdk/xtstruct.h b/sdk/xtdk/xtstruct.h index 3b2203d..50c57c0 100644 --- a/sdk/xtdk/xtstruct.h +++ b/sdk/xtdk/xtstruct.h @@ -49,6 +49,7 @@ typedef enum _KTIMER_TYPE KTIMER_TYPE, *PKTIMER_TYPE; typedef enum _KUBSAN_DATA_TYPE KUBSAN_DATA_TYPE, *PKUBSAN_DATA_TYPE; typedef enum _LOADER_MEMORY_TYPE LOADER_MEMORY_TYPE, *PLOADER_MEMORY_TYPE; typedef enum _MMPAGELISTS MMPAGELISTS, *PMMPAGELISTS; +typedef enum _MMPFN_CACHE_ATTRIBUTE MMPFN_CACHE_ATTRIBUTE, *PMMPFN_CACHE_ATTRIBUTE; typedef enum _MMSYSTEM_PTE_POOL_TYPE MMSYSTEM_PTE_POOL_TYPE, *PMMSYSTEM_PTE_POOL_TYPE; typedef enum _MODE MODE, *PMODE; typedef enum _RTL_VARIABLE_TYPE RTL_VARIABLE_TYPE, *PRTL_VARIABLE_TYPE; -- 2.52.0 From 0fd2b8b729d65a8d082876d175453854d4774951 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Tue, 23 Dec 2025 13:55:42 +0100 Subject: [PATCH 058/166] Update modified page list enum terminology --- sdk/xtdk/mmtypes.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/xtdk/mmtypes.h b/sdk/xtdk/mmtypes.h index 1c0f8a5..4c9620d 100644 --- a/sdk/xtdk/mmtypes.h +++ b/sdk/xtdk/mmtypes.h @@ -33,7 +33,7 @@ typedef enum _MMPAGELISTS FreePageList = 1, StandbyPageList = 2, ModifiedPageList = 3, - ModifiedNoWritePageList = 4, + ModifiedReadOnlyPageList = 4, BadPageList = 5, ActiveAndValid = 6, TransitionPage = 7 -- 2.52.0 From b8e81e22237fe0e0f56f9e4294d2fe5fb7b54465 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Tue, 23 Dec 2025 14:05:07 +0100 Subject: [PATCH 059/166] Initialize memory manager during kernel startup --- xtoskrnl/ke/amd64/krnlinit.cc | 3 +++ xtoskrnl/ke/i686/krnlinit.cc | 3 +++ 2 files changed, 6 insertions(+) diff --git a/xtoskrnl/ke/amd64/krnlinit.cc b/xtoskrnl/ke/amd64/krnlinit.cc index c837b1f..3c612e8 100644 --- a/xtoskrnl/ke/amd64/krnlinit.cc +++ b/xtoskrnl/ke/amd64/krnlinit.cc @@ -112,6 +112,9 @@ KE::KernelInit::StartKernel(VOID) CurrentThread->WaitRunLevel = DISPATCH_LEVEL; CurrentProcess->ActiveProcessors |= (ULONG_PTR)1 << Prcb->CpuNumber; + /* Initialize Memory Manager */ + MM::Manager::InitializeMemoryManager(); + /* Enter infinite loop */ DebugPrint(L"KernelInit::StartKernel() finished. Entering infinite loop.\n"); Crash::HaltSystem(); diff --git a/xtoskrnl/ke/i686/krnlinit.cc b/xtoskrnl/ke/i686/krnlinit.cc index 6142846..8ee661a 100644 --- a/xtoskrnl/ke/i686/krnlinit.cc +++ b/xtoskrnl/ke/i686/krnlinit.cc @@ -112,6 +112,9 @@ KE::KernelInit::StartKernel(VOID) CurrentThread->WaitRunLevel = DISPATCH_LEVEL; CurrentProcess->ActiveProcessors |= (ULONG_PTR)1 << Prcb->CpuNumber; + /* Initialize Memory Manager */ + MM::Manager::InitializeMemoryManager(); + /* Enter infinite loop */ DebugPrint(L"KernelInit::StartKernel() finished. Entering infinite loop.\n"); Crash::HaltSystem(); -- 2.52.0 From c7cc536685fa68073d26e96baf4fa89e8bc04637 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Tue, 23 Dec 2025 14:13:33 +0100 Subject: [PATCH 060/166] Add storage for PFN database size --- xtoskrnl/mm/data.cc | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/xtoskrnl/mm/data.cc b/xtoskrnl/mm/data.cc index 39733e1..296c0d4 100644 --- a/xtoskrnl/mm/data.cc +++ b/xtoskrnl/mm/data.cc @@ -21,6 +21,15 @@ ULONG MM::HardwarePool::UsedHardwareAllocationDescriptors = 0; /* Processor structures data (THIS IS A TEMPORARY HACK) */ UCHAR MM::KernelPool::ProcessorStructuresData[MAXIMUM_PROCESSORS][KPROCESSOR_STRUCTURES_SIZE] = {{0}}; +/* Memory layout */ +MMMEMORY_LAYOUT MM::Manager::MemoryLayout; + +/* Number of system PTEs */ +PFN_NUMBER MM::Manager::NumberOfSystemPtes; + +/* Instance of the page map routines for the current PML level */ +MM::PPAGEMAP MM::Paging::PmlRoutines; + /* Biggest free memory descriptor */ PLOADER_MEMORY_DESCRIPTOR MM::Pfn::FreeDescriptor; @@ -30,17 +39,11 @@ ULONG_PTR MM::Pfn::HighestPhysicalPage; /* Lowest physical page number */ ULONG_PTR MM::Pfn::LowestPhysicalPage = -1; -/* Memory layout */ -MMMEMORY_LAYOUT MM::Manager::MemoryLayout; - /* Number of physical pages */ ULONGLONG MM::Pfn::NumberOfPhysicalPages; -/* Number of system PTEs */ -PFN_NUMBER MM::Manager::NumberOfSystemPtes; - /* Old biggest free memory descriptor */ LOADER_MEMORY_DESCRIPTOR MM::Pfn::OriginalFreeDescriptor; -/* Instance of the page map routines for the current PML level */ -MM::PPAGEMAP MM::Paging::PmlRoutines; +/* Size of the PFN database in pages */ +PFN_NUMBER MM::Pfn::PfnDatabaseSize; -- 2.52.0 From 288b2f8b248afab372240954c2d0f82417b50cd1 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Tue, 23 Dec 2025 14:27:12 +0100 Subject: [PATCH 061/166] Introduce page coloring support to memory manager --- xtoskrnl/includes/mm.hh | 1 + xtoskrnl/includes/mm/colors.hh | 35 +++++++++++++ xtoskrnl/mm/colors.cc | 95 ++++++++++++++++++++++++++++++++++ xtoskrnl/mm/data.cc | 9 ++++ xtoskrnl/mm/mmgr.cc | 3 ++ 5 files changed, 143 insertions(+) create mode 100644 xtoskrnl/includes/mm/colors.hh create mode 100644 xtoskrnl/mm/colors.cc diff --git a/xtoskrnl/includes/mm.hh b/xtoskrnl/includes/mm.hh index bd94683..b34863d 100644 --- a/xtoskrnl/includes/mm.hh +++ b/xtoskrnl/includes/mm.hh @@ -15,6 +15,7 @@ #include XTOS_ARCH_HEADER(mm, paging.hh) #include XTOS_ARCH_HEADER(mm, pte.hh) +#include #include #include #include diff --git a/xtoskrnl/includes/mm/colors.hh b/xtoskrnl/includes/mm/colors.hh new file mode 100644 index 0000000..229b649 --- /dev/null +++ b/xtoskrnl/includes/mm/colors.hh @@ -0,0 +1,35 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: xtoskrnl/includes/mm/colors.hh + * DESCRIPTION: Memory manager page coloring subsystem + * DEVELOPERS: Aiken Harris + */ + +#ifndef __XTOSKRNL_MM_COLORS_HH +#define __XTOSKRNL_MM_COLORS_HH + +#include + + +/* Memory Manager */ +namespace MM +{ + class Colors + { + private: + STATIC PMMCOLOR_TABLES FreePages[FreePageList + 1]; + STATIC ULONG PagingColors; + STATIC ULONG PagingColorsMask; + + public: + STATIC XTAPI VOID ComputePageColoring(VOID); + STATIC XTAPI PMMCOLOR_TABLES GetFreePages(MMPAGELISTS PageList, + ULONG Color); + STATIC XTAPI ULONG GetNextColor(); + STATIC XTAPI ULONG GetPagingColors(); + STATIC XTAPI ULONG GetPagingColorsMask(); + }; +} + +#endif /* __XTOSKRNL_MM_PFN_HH */ diff --git a/xtoskrnl/mm/colors.cc b/xtoskrnl/mm/colors.cc new file mode 100644 index 0000000..e225846 --- /dev/null +++ b/xtoskrnl/mm/colors.cc @@ -0,0 +1,95 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: xtoskrnl/mm/colors.cc + * DESCRIPTION: Memory manager page coloring subsystem + * DEVELOPERS: Aiken Harris + */ + +#include + + +/** + * Computes & initializes the system's page coloring. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::Colors::ComputePageColoring(VOID) +{ + UNIMPLEMENTED; + + /* Compute L2 paging colors and mask */ + PagingColors = MM_PAGING_COLORS; + PagingColorsMask = PagingColors - 1; +} + +/** + * Retrieves a pointer to the color table for a specific page list and color. + * + * @param PageList + * The page list type (e.g., FreePageList, ZeroedPageList). + * + * @param Color + * Supplies the specific color index. + * + * @return This routine returns a pointer to the corresponding MMCOLOR_TABLES structure. + * + * @since XT 1.0 + */ +XTAPI +PMMCOLOR_TABLES +MM::Colors::GetFreePages(MMPAGELISTS PageList, + ULONG Color) +{ + /* Return a pointer to the requested color table entry */ + return &FreePages[PageList][Color]; +} + +/** + * Retrieves the next available color for page coloring. + * + * @return This routine returns the next color value, ensuring it stays within the valid color range. + * + * @since XT 1.0 + */ +XTAPI +ULONG +MM::Colors::GetNextColor() +{ + /* Increment the color counter and wrap it around using the mask */ + return ((++PagingColors) & PagingColorsMask); +} + +/** + * Retrieves the total number of page colors configured in the system. + * + * @return This routine returns the number of page colors. + * + * @since XT 1.0 + */ +XTAPI +ULONG +MM::Colors::GetPagingColors() +{ + /* Return the total number of page colors */ + return PagingColors; +} + +/** + * Retrieves the bitmask used for calculating a page's color. + * + * @return This routine returns the page color mask. + * + * @since XT 1.0 + */ +XTAPI +ULONG +MM::Colors::GetPagingColorsMask() +{ + /* Return the mask used for page coloring calculations */ + return PagingColorsMask; +} diff --git a/xtoskrnl/mm/data.cc b/xtoskrnl/mm/data.cc index 296c0d4..de5fe41 100644 --- a/xtoskrnl/mm/data.cc +++ b/xtoskrnl/mm/data.cc @@ -9,6 +9,15 @@ #include +/* Array of free page lists segregated by cache color */ +PMMCOLOR_TABLES MM::Colors::FreePages[FreePageList + 1]; + +/* Number of supported page colors */ +ULONG MM::Colors::PagingColors; + +/* Bitmask used to calculate the cache color index */ +ULONG MM::Colors::PagingColorsMask; + /* Allocation descriptors dedicated for hardware layer */ LOADER_MEMORY_DESCRIPTOR MM::HardwarePool::HardwareAllocationDescriptors[MM_HARDWARE_ALLOCATION_DESCRIPTORS]; diff --git a/xtoskrnl/mm/mmgr.cc b/xtoskrnl/mm/mmgr.cc index 5aa17ed..c305c04 100644 --- a/xtoskrnl/mm/mmgr.cc +++ b/xtoskrnl/mm/mmgr.cc @@ -54,6 +54,9 @@ MM::Manager::InitializeMemoryManager(VOID) KE::Crash::Panic(0); } + /* Compute page colors to reduce CPU cache conflicts */ + MM::Colors::ComputePageColoring(); + /* Compute allocation size for the PFN database */ MM::Pfn::ComputePfnDatabaseSize(); -- 2.52.0 From b3b874d3ce979cced79e38df8729db7f9ff36226 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Tue, 23 Dec 2025 14:29:26 +0100 Subject: [PATCH 062/166] Include mm/colors.cc in kernel build configuration --- xtoskrnl/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/xtoskrnl/CMakeLists.txt b/xtoskrnl/CMakeLists.txt index e2a7144..8c881cb 100644 --- a/xtoskrnl/CMakeLists.txt +++ b/xtoskrnl/CMakeLists.txt @@ -55,6 +55,7 @@ list(APPEND XTOSKRNL_SOURCE ${XTOSKRNL_SOURCE_DIR}/mm/${ARCH}/pagemap.cc ${XTOSKRNL_SOURCE_DIR}/mm/${ARCH}/paging.cc ${XTOSKRNL_SOURCE_DIR}/mm/${ARCH}/pte.cc + ${XTOSKRNL_SOURCE_DIR}/mm/colors.cc ${XTOSKRNL_SOURCE_DIR}/mm/data.cc ${XTOSKRNL_SOURCE_DIR}/mm/hlpool.cc ${XTOSKRNL_SOURCE_DIR}/mm/kpool.cc -- 2.52.0 From 1e3917882c258a5f04265ac2523a94791c95f785 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Tue, 23 Dec 2025 18:03:02 +0100 Subject: [PATCH 063/166] Initialize system page tables and configure kernel mappings --- xtoskrnl/includes/mm/amd64/pte.hh | 3 ++ xtoskrnl/includes/mm/i686/pte.hh | 3 ++ xtoskrnl/mm/amd64/pte.cc | 64 ++++++++++++++++++++++++++++++- xtoskrnl/mm/data.cc | 3 ++ 4 files changed, 72 insertions(+), 1 deletion(-) diff --git a/xtoskrnl/includes/mm/amd64/pte.hh b/xtoskrnl/includes/mm/amd64/pte.hh index c5d4f6b..891d29a 100644 --- a/xtoskrnl/includes/mm/amd64/pte.hh +++ b/xtoskrnl/includes/mm/amd64/pte.hh @@ -17,6 +17,9 @@ namespace MM { class Pte { + private: + STATIC MMPTE ValidPte; + public: STATIC XTAPI BOOLEAN AddressValid(IN PVOID VirtualAddress); STATIC XTAPI ULONG GetPtesPerPage(VOID); diff --git a/xtoskrnl/includes/mm/i686/pte.hh b/xtoskrnl/includes/mm/i686/pte.hh index b29f91a..de7cdf7 100644 --- a/xtoskrnl/includes/mm/i686/pte.hh +++ b/xtoskrnl/includes/mm/i686/pte.hh @@ -17,6 +17,9 @@ namespace MM { class Pte { + private: + STATIC MMPTE ValidPte; + public: STATIC XTAPI BOOLEAN AddressValid(IN PVOID VirtualAddress); STATIC XTAPI ULONG GetPtesPerPage(VOID); diff --git a/xtoskrnl/mm/amd64/pte.cc b/xtoskrnl/mm/amd64/pte.cc index a077c27..8d86882 100644 --- a/xtoskrnl/mm/amd64/pte.cc +++ b/xtoskrnl/mm/amd64/pte.cc @@ -89,7 +89,69 @@ XTAPI VOID MM::Pte::InitializePageTable(VOID) { - UNIMPLEMENTED; + PMMPTE EndSpacePte, PointerPte; + PMMMEMORY_LAYOUT MemoryLayout; + PVOID MappingRange; + MMPTE TemplatePte; + BOOLEAN Xpa; + + /* Retrieve current paging mode and memory layout */ + Xpa = MM::Paging::GetXpaStatus(); + MemoryLayout = MM::Manager::GetMemoryLayout(); + + /* Enable the Global Paging (PGE) feature */ + AR::CpuFunc::WriteControlRegister(4, AR::CpuFunc::ReadControlRegister(4) | CR4_PGE); + + /* Check XPA status */ + if(Xpa) + { + /* Get the PML5 user-space range if 5-level paging is active */ + PointerPte = MM::Paging::GetP5eAddress(0); + EndSpacePte = MM::Paging::GetP5eAddress(MemoryLayout->UserSpaceEnd); + } + else + { + /* Otherwise, get the PML4 user-space range for 4-level paging */ + PointerPte = MM::Paging::GetPxeAddress(0); + EndSpacePte = MM::Paging::GetPxeAddress(MemoryLayout->UserSpaceEnd); + } + + /* Clear all top-level entries mapping the user address space */ + while(PointerPte <= EndSpacePte) + { + MM::Paging::ClearPte(PointerPte); + PointerPte = MM::Paging::GetNextPte(PointerPte); + } + + /* Flush the TLB to invalidate all non-global entries */ + AR::CpuFunc::FlushTlb(); + + /* Create a template PTE for mapping kernel pages */ + MM::Paging::ClearPte(&TemplatePte); + MM::Paging::SetPte(&TemplatePte, 0, MM_PTE_READWRITE | MM_PTE_CACHE_ENABLE); + + /* Check XPA status */ + if(Xpa) + { + /* Map the kernel's PML5 entries if 5-level paging is active */ + MM::Pte::MapP5E(MemoryLayout->HyperSpaceStart, (PVOID)MM_HIGHEST_SYSTEM_ADDRESS, &TemplatePte); + } + + /* Map the kernel's PML4 entries */ + MM::Pte::MapPXE(MemoryLayout->HyperSpaceStart, (PVOID)MM_HIGHEST_SYSTEM_ADDRESS, &TemplatePte); + + /* Calculate the end address of the hyperspace working set mapping */ + MappingRange = (PVOID)((ULONG_PTR)MemoryLayout->HyperSpaceStart + MM_HYPERSPACE_PAGE_COUNT * MM_PAGE_SIZE); + + /* Map the PDPT entries for paged pool and hyperspace */ + MM::Pte::MapPPE(MemoryLayout->PagedPoolStart, MemoryLayout->PagedPoolEnd, &ValidPte); + MM::Pte::MapPPE(MemoryLayout->HyperSpaceStart, MemoryLayout->HyperSpaceEnd, &ValidPte); + + /* Map the PDEs for the hyperspace working set */ + MM::Pte::MapPDE(MemoryLayout->HyperSpaceStart, MappingRange, &ValidPte); + + /* Set the hyperspace working set's PTE with the total PTE count */ + MM::Paging::SetPte(MM::Paging::GetPteAddress((PVOID)MemoryLayout->HyperSpaceStart), MM_HYPERSPACE_PAGE_COUNT, 0); } /** diff --git a/xtoskrnl/mm/data.cc b/xtoskrnl/mm/data.cc index de5fe41..8124fe3 100644 --- a/xtoskrnl/mm/data.cc +++ b/xtoskrnl/mm/data.cc @@ -56,3 +56,6 @@ LOADER_MEMORY_DESCRIPTOR MM::Pfn::OriginalFreeDescriptor; /* Size of the PFN database in pages */ PFN_NUMBER MM::Pfn::PfnDatabaseSize; + +/* Template PTE entry containing standard flags for a valid, present kernel page */ +MMPTE MM::Pte::ValidPte = {MM_PTE_VALID|MM_PTE_EXECUTE_READWRITE|MM_PTE_DIRTY|MM_PTE_ACCESSED}; -- 2.52.0 From 5012c8dc37ea7d7b541e6f46da76b0879a6bb9d7 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Tue, 23 Dec 2025 20:16:08 +0100 Subject: [PATCH 064/166] Initialize system PTE pools and implement reservation routines --- xtoskrnl/includes/mm/amd64/pte.hh | 19 ++ xtoskrnl/includes/mm/i686/pte.hh | 19 ++ xtoskrnl/mm/data.cc | 15 ++ xtoskrnl/mm/mmgr.cc | 3 + xtoskrnl/mm/pte.cc | 276 ++++++++++++++++++++++++++++++ 5 files changed, 332 insertions(+) diff --git a/xtoskrnl/includes/mm/amd64/pte.hh b/xtoskrnl/includes/mm/amd64/pte.hh index 891d29a..ca2932d 100644 --- a/xtoskrnl/includes/mm/amd64/pte.hh +++ b/xtoskrnl/includes/mm/amd64/pte.hh @@ -18,6 +18,11 @@ namespace MM class Pte { private: + STATIC MMPTE FirstSystemFreePte[MaximumPtePoolTypes]; + STATIC PMMPTE SystemPteBase; + STATIC PMMPTE SystemPtesEnd[MaximumPtePoolTypes]; + STATIC PMMPTE SystemPtesStart[MaximumPtePoolTypes]; + STATIC ULONG TotalSystemFreePtes[MaximumPtePoolTypes]; STATIC MMPTE ValidPte; public: @@ -25,6 +30,7 @@ namespace MM STATIC XTAPI ULONG GetPtesPerPage(VOID); STATIC XTAPI PMMPTE GetSystemPteBaseAddress(VOID); STATIC XTAPI VOID InitializePageTable(VOID); + STATIC XTAPI VOID InitializeSystemPteSpace(VOID); STATIC XTAPI VOID MapP5E(PVOID StartAddress, PVOID EndAddress, PMMP5E TemplateP5e); @@ -40,6 +46,19 @@ namespace MM STATIC XTAPI VOID MapPXE(PVOID StartAddress, PVOID EndAddress, PMMPXE TemplatePxe); + STATIC XTAPI PMMPTE ReserveSystemPtes(IN ULONG NumberOfPtes, + IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType, + IN ULONG Alignment); + + private: + STATIC XTAPI BOOLEAN FindFreeCluster(IN ULONG NumberOfPtes, + IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType, + OUT PMMPTE *FoundCluster, + OUT PMMPTE *PreviousClusterNode); + STATIC XTAPI ULONG GetClusterSize(IN PMMPTE Pte); + STATIC XTAPI VOID InitializeSystemPtePool(IN PMMPTE StartingPte, + IN ULONG NumberOfPtes, + IN MMSYSTEM_PTE_POOL_TYPE PoolType); }; } diff --git a/xtoskrnl/includes/mm/i686/pte.hh b/xtoskrnl/includes/mm/i686/pte.hh index de7cdf7..9bf4661 100644 --- a/xtoskrnl/includes/mm/i686/pte.hh +++ b/xtoskrnl/includes/mm/i686/pte.hh @@ -18,6 +18,11 @@ namespace MM class Pte { private: + STATIC MMPTE FirstSystemFreePte[MaximumPtePoolTypes]; + STATIC PMMPTE SystemPteBase; + STATIC PMMPTE SystemPtesEnd[MaximumPtePoolTypes]; + STATIC PMMPTE SystemPtesStart[MaximumPtePoolTypes]; + STATIC ULONG TotalSystemFreePtes[MaximumPtePoolTypes]; STATIC MMPTE ValidPte; public: @@ -25,6 +30,7 @@ namespace MM STATIC XTAPI ULONG GetPtesPerPage(VOID); STATIC XTAPI PMMPTE GetSystemPteBaseAddress(VOID); STATIC XTAPI VOID InitializePageTable(VOID); + STATIC XTAPI VOID InitializeSystemPteSpace(VOID); STATIC XTAPI VOID MapPDE(PVOID StartAddress, PVOID EndAddress, PMMPDE TemplatePde); @@ -34,6 +40,19 @@ namespace MM STATIC XTAPI VOID MapPTE(PVOID StartAddress, PVOID EndAddress, PMMPTE TemplatePte); + STATIC XTAPI PMMPTE ReserveSystemPtes(IN ULONG NumberOfPtes, + IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType, + IN ULONG Alignment); + + private: + STATIC XTAPI BOOLEAN FindFreeCluster(IN ULONG NumberOfPtes, + IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType, + OUT PMMPTE *FoundCluster, + OUT PMMPTE *PreviousClusterNode); + STATIC XTAPI ULONG GetClusterSize(IN PMMPTE Pte); + STATIC XTAPI VOID InitializeSystemPtePool(IN PMMPTE StartingPte, + IN ULONG NumberOfPtes, + IN MMSYSTEM_PTE_POOL_TYPE PoolType); }; } diff --git a/xtoskrnl/mm/data.cc b/xtoskrnl/mm/data.cc index 8124fe3..be173b1 100644 --- a/xtoskrnl/mm/data.cc +++ b/xtoskrnl/mm/data.cc @@ -57,5 +57,20 @@ LOADER_MEMORY_DESCRIPTOR MM::Pfn::OriginalFreeDescriptor; /* Size of the PFN database in pages */ PFN_NUMBER MM::Pfn::PfnDatabaseSize; +/* Array of lists for available System PTEs, separated by pool type */ +MMPTE MM::Pte::FirstSystemFreePte[MaximumPtePoolTypes]; + +/* Virtual base address of the System PTE space */ +PMMPTE MM::Pte::SystemPteBase; + +/* End addresses for the System PTE ranges */ +PMMPTE MM::Pte::SystemPtesEnd[MaximumPtePoolTypes]; + +/* Start addresses for the System PTE ranges */ +PMMPTE MM::Pte::SystemPtesStart[MaximumPtePoolTypes]; + +/* Total count of available System PTEs */ +ULONG MM::Pte::TotalSystemFreePtes[MaximumPtePoolTypes]; + /* Template PTE entry containing standard flags for a valid, present kernel page */ MMPTE MM::Pte::ValidPte = {MM_PTE_VALID|MM_PTE_EXECUTE_READWRITE|MM_PTE_DIRTY|MM_PTE_ACCESSED}; diff --git a/xtoskrnl/mm/mmgr.cc b/xtoskrnl/mm/mmgr.cc index c305c04..a8a4dbf 100644 --- a/xtoskrnl/mm/mmgr.cc +++ b/xtoskrnl/mm/mmgr.cc @@ -65,6 +65,9 @@ MM::Manager::InitializeMemoryManager(VOID) /* Initialize page table */ MM::Pte::InitializePageTable(); + + /* Initialize system PTE space */ + MM::Pte::InitializeSystemPteSpace(); } /** diff --git a/xtoskrnl/mm/pte.cc b/xtoskrnl/mm/pte.cc index 9874b2a..a2a3f6f 100644 --- a/xtoskrnl/mm/pte.cc +++ b/xtoskrnl/mm/pte.cc @@ -9,6 +9,86 @@ #include +/** + * Finds a free cluster of system PTEs that can satisfy a given size. + * + * @param NumberOfPtes + * The number of contiguous PTEs required. + * + * @param SystemPtePoolType + * Specifies the system PTE pool to search within. + * + * @param FoundCluster + * On success, receives a pointer to the first PTE of the found cluster. + * + * @param PreviousClusterNode + * On success, receives a pointer to the list node that precedes the found cluster. + * + * @return This routine returns TRUE if a suitable cluster was found, FALSE otherwise. + * + * @since XT 1.0 + */ +XTAPI +BOOLEAN +MM::Pte::FindFreeCluster(IN ULONG NumberOfPtes, + IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType, + OUT PMMPTE *FoundCluster, + OUT PMMPTE *PreviousClusterNode) +{ + PMMPTE CurrentCluster; + PMMPTE PreviousNode = &FirstSystemFreePte[SystemPtePoolType]; + ULONG ClusterSize; + + /* Find a free PTE cluster large enough for the request */ + while(MM::Paging::GetNextEntry(PreviousNode) != MAXULONG) + { + /* Retrieve the cluster and its size */ + CurrentCluster = MM::Paging::AdvancePte(SystemPteBase, MM::Paging::GetNextEntry(PreviousNode)); + ClusterSize = GetClusterSize(CurrentCluster); + + /* Check if this cluster is large enough */ + if(NumberOfPtes <= ClusterSize) + { + /* Found a suitable cluster */ + *FoundCluster = CurrentCluster; + *PreviousClusterNode = PreviousNode; + return TRUE; + } + + /* This cluster is too small, check the next one */ + PreviousNode = CurrentCluster; + } + + /* No suitable cluster was found */ + return FALSE; +} + +/** + * Decodes and returns the size of a free PTE cluster. + * + * @param Pte + * Supplies a pointer to the first PTE of the free cluster to inspect. + * + * @return This routine returns the total number of contiguous PTEs in the free cluster. + * + * @since XT 1.0 + */ +XTAPI +ULONG +MM::Pte::GetClusterSize(IN PMMPTE Pte) +{ + /* A special flag in the first PTE indicates a free cluster of size one */ + if(MM::Paging::GetOneEntry(Pte)) + { + /* Flag is set, so the cluster size is 1 by definition */ + return 1; + } + + /* For larger clusters, the size is encoded in the second PTE of the block */ + Pte = MM::Paging::GetNextPte(Pte); + return MM::Paging::GetNextEntry(Pte); +} + /** * Calculates the number of Page Table Entries (PTEs) that fit within a single page. * @@ -24,6 +104,86 @@ MM::Pte::GetPtesPerPage(VOID) return MM_PAGE_SIZE / MM::Paging::GetPteSize(); } +/** + * Formats a range of PTEs into a freelist-based pool for system allocations. + * + * @param StartingPte + * Supplies a pointer to the start of the PTE range to be formatted. + * + * @param NumberOfPtes + * Supplies the total number of PTEs in the contiguous range. + * + * @param PoolType + * The system PTE pool type that this range will be used for. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::Pte::InitializeSystemPtePool(IN PMMPTE StartingPte, + IN ULONG NumberOfPtes, + IN MMSYSTEM_PTE_POOL_TYPE PoolType) +{ + /* Set the system PTE base address */ + SystemPteBase = GetSystemPteBaseAddress(); + + /* Record the boundaries of this new PTE pool */ + SystemPtesStart[PoolType] = StartingPte; + SystemPtesEnd[PoolType] = MM::Paging::AdvancePte(StartingPte, NumberOfPtes - 1); + + /* Zero the memory for the new PTE pool before use */ + RTL::Memory::ZeroMemory(StartingPte, NumberOfPtes * MM::Paging::GetPteSize()); + + /* Build the free list head to point to the start of the pool */ + MM::Paging::SetNextEntry(StartingPte, MAXULONG); + MM::Paging::ClearPte(&FirstSystemFreePte[PoolType]); + MM::Paging::SetNextEntry(&FirstSystemFreePte[PoolType], MM::Paging::GetPteDistance(StartingPte, SystemPteBase)); + + /* Use the second PTE slot to store the total size of this pool */ + StartingPte = MM::Paging::GetNextPte(StartingPte); + MM::Paging::ClearPte(StartingPte); + MM::Paging::SetNextEntry(StartingPte, NumberOfPtes); + + /* Record the total number of free PTEs in this pool */ + TotalSystemFreePtes[PoolType] = NumberOfPtes; +} + +/** + * Sets up the entire system PTE address space. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::Pte::InitializeSystemPteSpace(VOID) +{ + PMMPTE PointerPte; + PMMPTE FirstZeroingPte; + PMMMEMORY_LAYOUT MemoryLayout; + + /* Retrieve the system's memory layout */ + MemoryLayout = MM::Manager::GetMemoryLayout(); + + /* Map the page table hierarchy for the entire system PTE space */ + MM::Pte::MapPPE(MemoryLayout->SystemSpaceStart, MemoryLayout->SystemSpaceEnd, &ValidPte); + MM::Pte::MapPDE(MemoryLayout->SystemSpaceStart, MemoryLayout->SystemSpaceEnd, &ValidPte); + + /* Format the main block of system PTEs into a free list pool */ + PointerPte = MM::Paging::GetPteAddress(MemoryLayout->SystemSpaceStart); + InitializeSystemPtePool(PointerPte, MM::Manager::GetNumberOfSystemPtes(), SystemPteSpace); + + /* Reserve and zero a dedicated block of system PTEs */ + FirstZeroingPte = ReserveSystemPtes(MM_RESERVED_ZERO_PTES + 1, SystemPteSpace, 0); + RTL::Memory::ZeroMemory(FirstZeroingPte, (MM_RESERVED_ZERO_PTES + 1) * MM::Paging::GetPteSize()); + + /* Use the first PTE of this block as a counter for available zeroing PTEs */ + MM::Paging::SetPte(FirstZeroingPte, MM_RESERVED_ZERO_PTES, 0); +} + /** * Maps a range of virtual addresses at the PDE (Page Directory Entry) level. * @@ -117,3 +277,119 @@ MM::Pte::MapPTE(PVOID StartAddress, PointerPte = MM::Paging::GetNextPte(PointerPte); } } + +/** + * Reserves a contiguous block of system PTEs from a specified pool. + * + * @param NumberOfPtes + * The number of contiguous PTEs to reserve. + * + * @param SystemPtePoolType + * Specifies the system PTE pool from which to allocate. + * + * @param Alignment + * This parameter is currently unused. + * + * @return This routine returns a pointer to the beginning of the reserved block, + * or NULLPTR if not enough contiguous PTEs are available. + * + * @since XT 1.0 + */ +XTAPI +PMMPTE +MM::Pte::ReserveSystemPtes(IN ULONG NumberOfPtes, + IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType, + IN ULONG Alignment) +{ + PMMPTE PreviousPte, NextPte, ReservedPte; + ULONG ClusterSize; + + /* Raise runlevel and acquire lock to protect the PTE pool */ + KE::RaiseRunLevel RunLevel(DISPATCH_LEVEL); + KE::QueuedSpinLockGuard SpinLock(SystemSpaceLock); + + /* Find a free PTE cluster large enough for the request */ + if(!FindFreeCluster(NumberOfPtes, SystemPtePoolType, &NextPte, &PreviousPte)) + { + /* Out of system PTEs for this pool, return NULLPTR */ + return NULLPTR; + } + + /* We have the cluster, now get its size for the allocation logic below */ + ClusterSize = GetClusterSize(NextPte); + + /* Unlink the found cluster from the free list for processing */ + MM::Paging::SetNextEntry(PreviousPte, MM::Paging::GetNextEntry(NextPte)); + + /* Handle the allocation based on whether the cluster size is an exact match */ + if(ClusterSize == NumberOfPtes) + { + /* Exact match, allocate the entire cluster */ + ReservedPte = NextPte; + + /* Handle metadata cleanup for a single-PTE cluster */ + if(MM::Paging::GetOneEntry(NextPte)) + { + /* Clear the PTE that held the list metadata */ + MM::Paging::ClearPte(NextPte); + NextPte = MM::Paging::GetNextPte(NextPte); + } + + /* Clear the PTE that held the cluster size */ + MM::Paging::ClearPte(NextPte); + } + else + { + /* Cluster is larger than needed, so it will be split */ + ClusterSize -= NumberOfPtes; + ReservedPte = MM::Paging::AdvancePte(NextPte, ClusterSize); + + /* Update metadata for the new, smaller leftover cluster */ + if(ClusterSize == 1) + { + /* The leftover fragment is a single PTE */ + MM::Paging::SetOneEntry(NextPte, 1); + MM::Paging::ClearPte(ReservedPte); + } + else + { + /* The leftover fragment is larger than one PTE */ + NextPte = MM::Paging::GetNextPte(NextPte); + MM::Paging::SetNextEntry(NextPte, ClusterSize); + } + + /* Find the correct sorted position to re-insert the leftover fragment */ + PreviousPte = &FirstSystemFreePte[SystemPtePoolType]; + while(MM::Paging::GetNextEntry(PreviousPte) != MAXULONG) + { + /* Get the next free cluster to check its size */ + NextPte = MM::Paging::AdvancePte(SystemPteBase, MM::Paging::GetNextEntry(PreviousPte)); + + /* Check if the leftover fragment should be inserted here */ + if(ClusterSize <= GetClusterSize(NextPte)) + { + /* Found the correct sorted position */ + break; + } + + /* Advance to the next entry */ + PreviousPte = NextPte; + } + + /* Get a pointer to the start of the leftover fragment */ + NextPte = MM::Paging::AdvancePte(ReservedPte, -ClusterSize); + + /* Insert the leftover fragment back into the free list at its sorted position */ + MM::Paging::SetNextEntry(NextPte, MM::Paging::GetNextEntry(PreviousPte)); + MM::Paging::SetNextEntry(PreviousPte, MM::Paging::GetPteDistance(NextPte, SystemPteBase)); + } + + /* Decrement the total number of available PTEs in this pool */ + TotalSystemFreePtes[SystemPtePoolType] -= NumberOfPtes; + + /* Flush the TLB to ensure address translation consistency */ + AR::CpuFunc::FlushTlb(); + + /* Return a pointer to the start of the reserved PTE block */ + return ReservedPte; +} -- 2.52.0 From b7c004528a83d83ecee443d6e0705ab2d63c9b40 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Tue, 23 Dec 2025 22:13:09 +0100 Subject: [PATCH 065/166] Implement tracking of available physical pages --- xtoskrnl/includes/mm/pfn.hh | 5 +++++ xtoskrnl/mm/data.cc | 3 +++ xtoskrnl/mm/pfn.cc | 30 ++++++++++++++++++++++++++++++ 3 files changed, 38 insertions(+) diff --git a/xtoskrnl/includes/mm/pfn.hh b/xtoskrnl/includes/mm/pfn.hh index 6473f1a..6546b2f 100644 --- a/xtoskrnl/includes/mm/pfn.hh +++ b/xtoskrnl/includes/mm/pfn.hh @@ -18,6 +18,7 @@ namespace MM class Pfn { private: + STATIC PFN_NUMBER AvailablePages; STATIC PLOADER_MEMORY_DESCRIPTOR FreeDescriptor; STATIC ULONG_PTR HighestPhysicalPage; STATIC ULONG_PTR LowestPhysicalPage; @@ -31,6 +32,10 @@ namespace MM STATIC XTAPI ULONGLONG GetNumberOfPhysicalPages(VOID); STATIC XTAPI PFN_NUMBER GetPfnDatabaseSize(VOID); STATIC XTAPI VOID ScanMemoryDescriptors(VOID); + + private: + STATIC XTAPI VOID DecrementAvailablePages(VOID); + STATIC XTAPI VOID IncrementAvailablePages(VOID); }; } diff --git a/xtoskrnl/mm/data.cc b/xtoskrnl/mm/data.cc index be173b1..3c26171 100644 --- a/xtoskrnl/mm/data.cc +++ b/xtoskrnl/mm/data.cc @@ -39,6 +39,9 @@ PFN_NUMBER MM::Manager::NumberOfSystemPtes; /* Instance of the page map routines for the current PML level */ MM::PPAGEMAP MM::Paging::PmlRoutines; +/* Total number of physical pages available for allocation */ +PFN_NUMBER MM::Pfn::AvailablePages; + /* Biggest free memory descriptor */ PLOADER_MEMORY_DESCRIPTOR MM::Pfn::FreeDescriptor; diff --git a/xtoskrnl/mm/pfn.cc b/xtoskrnl/mm/pfn.cc index 68e3337..5a8d20e 100644 --- a/xtoskrnl/mm/pfn.cc +++ b/xtoskrnl/mm/pfn.cc @@ -60,6 +60,21 @@ MM::Pfn::ComputePfnDatabaseSize(VOID) PfnDatabaseSize >>= MM_PAGE_SHIFT; } +/** + * Decrements the global count of available pages. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::Pfn::DecrementAvailablePages(VOID) +{ + /* Decrement the global count of available pages */ + AvailablePages--; +} + /** * Retrieves the total number of physical pages managed by the system. * @@ -90,6 +105,21 @@ MM::Pfn::GetPfnDatabaseSize(VOID) return PfnDatabaseSize; } +/** + * Increments the global count of available pages. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::Pfn::IncrementAvailablePages(VOID) +{ + /* Increment the global count of available pages */ + AvailablePages++; +} + /** * Scans memory descriptors provided by the boot loader. * -- 2.52.0 From 4593a89a9b08e041332182ff8f48521dd09f3f7f Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Sun, 28 Dec 2025 21:18:17 +0100 Subject: [PATCH 066/166] Expose PFN database lookup via GetPfnEntry --- xtoskrnl/includes/mm/pfn.hh | 1 + xtoskrnl/mm/pfn.cc | 30 ++++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/xtoskrnl/includes/mm/pfn.hh b/xtoskrnl/includes/mm/pfn.hh index 6546b2f..9f98251 100644 --- a/xtoskrnl/includes/mm/pfn.hh +++ b/xtoskrnl/includes/mm/pfn.hh @@ -31,6 +31,7 @@ namespace MM STATIC XTAPI VOID ComputePfnDatabaseSize(VOID); STATIC XTAPI ULONGLONG GetNumberOfPhysicalPages(VOID); STATIC XTAPI PFN_NUMBER GetPfnDatabaseSize(VOID); + STATIC XTAPI PMMPFN GetPfnEntry(IN PFN_NUMBER Pfn); STATIC XTAPI VOID ScanMemoryDescriptors(VOID); private: diff --git a/xtoskrnl/mm/pfn.cc b/xtoskrnl/mm/pfn.cc index 5a8d20e..966572e 100644 --- a/xtoskrnl/mm/pfn.cc +++ b/xtoskrnl/mm/pfn.cc @@ -105,6 +105,36 @@ MM::Pfn::GetPfnDatabaseSize(VOID) return PfnDatabaseSize; } +/** + * Retrieves a pointer to the PFN database entry for a given physical page. + * + * @param Pfn + * The Page Frame Number (PFN) to look up. + * + * @return This routine returns a pointer to the MMPFN structure for the given PFN, or NULLPTR if the PFN is invalid. + * + * @since XT 1.0 + */ +XTAPI +PMMPFN +MM::Pfn::GetPfnEntry(IN PFN_NUMBER Pfn) +{ + PMMMEMORY_LAYOUT MemoryLayout; + + /* Validate that the PFN is within the range of managed physical memory */ + if(Pfn > HighestPhysicalPage) + { + /* The requested page number is outside the bounds, return NULLPTR */ + return NULLPTR; + } + + /* Get the memory layout */ + MemoryLayout = MM::Manager::GetMemoryLayout(); + + /* Calculate the address of the PFN entry by indexing into the PFN database array and return it */ + return &((PMMPFN)MemoryLayout->PfnDatabaseAddress)[Pfn]; +} + /** * Increments the global count of available pages. * -- 2.52.0 From 0880a0f344b0e6009fdb04309b181ed4533b2c02 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Sun, 28 Dec 2025 23:25:07 +0100 Subject: [PATCH 067/166] Implement PFN database initialization and memory descriptor processing --- xtoskrnl/CMakeLists.txt | 1 + xtoskrnl/includes/mm/amd64/pte.hh | 1 + xtoskrnl/includes/mm/colors.hh | 1 + xtoskrnl/includes/mm/i686/pte.hh | 1 + xtoskrnl/includes/mm/pfn.hh | 12 ++ xtoskrnl/mm/amd64/pfn.cc | 249 +++++++++++++++++++++++++++++ xtoskrnl/mm/colors.cc | 66 ++++++++ xtoskrnl/mm/data.cc | 3 + xtoskrnl/mm/i686/pfn.cc | 234 +++++++++++++++++++++++++++ xtoskrnl/mm/mmgr.cc | 3 + xtoskrnl/mm/pfn.cc | 255 ++++++++++++++++++++++++++++++ xtoskrnl/mm/pte.cc | 15 ++ 12 files changed, 841 insertions(+) create mode 100644 xtoskrnl/mm/amd64/pfn.cc create mode 100644 xtoskrnl/mm/i686/pfn.cc diff --git a/xtoskrnl/CMakeLists.txt b/xtoskrnl/CMakeLists.txt index 8c881cb..e879b97 100644 --- a/xtoskrnl/CMakeLists.txt +++ b/xtoskrnl/CMakeLists.txt @@ -54,6 +54,7 @@ list(APPEND XTOSKRNL_SOURCE ${XTOSKRNL_SOURCE_DIR}/mm/${ARCH}/mmgr.cc ${XTOSKRNL_SOURCE_DIR}/mm/${ARCH}/pagemap.cc ${XTOSKRNL_SOURCE_DIR}/mm/${ARCH}/paging.cc + ${XTOSKRNL_SOURCE_DIR}/mm/${ARCH}/pfn.cc ${XTOSKRNL_SOURCE_DIR}/mm/${ARCH}/pte.cc ${XTOSKRNL_SOURCE_DIR}/mm/colors.cc ${XTOSKRNL_SOURCE_DIR}/mm/data.cc diff --git a/xtoskrnl/includes/mm/amd64/pte.hh b/xtoskrnl/includes/mm/amd64/pte.hh index ca2932d..9c43665 100644 --- a/xtoskrnl/includes/mm/amd64/pte.hh +++ b/xtoskrnl/includes/mm/amd64/pte.hh @@ -29,6 +29,7 @@ namespace MM STATIC XTAPI BOOLEAN AddressValid(IN PVOID VirtualAddress); STATIC XTAPI ULONG GetPtesPerPage(VOID); STATIC XTAPI PMMPTE GetSystemPteBaseAddress(VOID); + STATIC XTAPI PMMPTE GetValidPte(VOID); STATIC XTAPI VOID InitializePageTable(VOID); STATIC XTAPI VOID InitializeSystemPteSpace(VOID); STATIC XTAPI VOID MapP5E(PVOID StartAddress, diff --git a/xtoskrnl/includes/mm/colors.hh b/xtoskrnl/includes/mm/colors.hh index 229b649..d48c3d9 100644 --- a/xtoskrnl/includes/mm/colors.hh +++ b/xtoskrnl/includes/mm/colors.hh @@ -29,6 +29,7 @@ namespace MM STATIC XTAPI ULONG GetNextColor(); STATIC XTAPI ULONG GetPagingColors(); STATIC XTAPI ULONG GetPagingColorsMask(); + STATIC XTAPI VOID InitializeColorTables(VOID); }; } diff --git a/xtoskrnl/includes/mm/i686/pte.hh b/xtoskrnl/includes/mm/i686/pte.hh index 9bf4661..70393f9 100644 --- a/xtoskrnl/includes/mm/i686/pte.hh +++ b/xtoskrnl/includes/mm/i686/pte.hh @@ -29,6 +29,7 @@ namespace MM STATIC XTAPI BOOLEAN AddressValid(IN PVOID VirtualAddress); STATIC XTAPI ULONG GetPtesPerPage(VOID); STATIC XTAPI PMMPTE GetSystemPteBaseAddress(VOID); + STATIC XTAPI PMMPTE GetValidPte(VOID); STATIC XTAPI VOID InitializePageTable(VOID); STATIC XTAPI VOID InitializeSystemPteSpace(VOID); STATIC XTAPI VOID MapPDE(PVOID StartAddress, diff --git a/xtoskrnl/includes/mm/pfn.hh b/xtoskrnl/includes/mm/pfn.hh index 9f98251..1832a78 100644 --- a/xtoskrnl/includes/mm/pfn.hh +++ b/xtoskrnl/includes/mm/pfn.hh @@ -20,6 +20,7 @@ namespace MM private: STATIC PFN_NUMBER AvailablePages; STATIC PLOADER_MEMORY_DESCRIPTOR FreeDescriptor; + STATIC MMPFNLIST FreePagesList; STATIC ULONG_PTR HighestPhysicalPage; STATIC ULONG_PTR LowestPhysicalPage; STATIC ULONGLONG NumberOfPhysicalPages; @@ -29,14 +30,25 @@ namespace MM public: STATIC XTAPI PFN_NUMBER AllocateBootstrapPages(IN PFN_NUMBER NumberOfPages); STATIC XTAPI VOID ComputePfnDatabaseSize(VOID); + STATIC XTAPI ULONG_PTR GetHighestPhysicalPage(VOID); STATIC XTAPI ULONGLONG GetNumberOfPhysicalPages(VOID); STATIC XTAPI PFN_NUMBER GetPfnDatabaseSize(VOID); STATIC XTAPI PMMPFN GetPfnEntry(IN PFN_NUMBER Pfn); + STATIC XTAPI VOID InitializePfnDatabase(VOID); STATIC XTAPI VOID ScanMemoryDescriptors(VOID); private: STATIC XTAPI VOID DecrementAvailablePages(VOID); STATIC XTAPI VOID IncrementAvailablePages(VOID); + STATIC XTAPI VOID InitializePageTablePfns(VOID); + STATIC XTAPI VOID LinkFreePage(IN PFN_NUMBER PageFrameIndex); + STATIC XTAPI VOID LinkPfnForPageTable(PFN_NUMBER PageFrameIndex, + PMMPTE PointerPte); + STATIC XTAPI VOID ProcessMemoryDescriptor(PFN_NUMBER BasePage, + PFN_NUMBER PageCount, + LOADER_MEMORY_TYPE MemoryType); + STATIC XTAPI VOID ScanPageTable(IN PMMPTE PointerPte, + ULONG Level); }; } diff --git a/xtoskrnl/mm/amd64/pfn.cc b/xtoskrnl/mm/amd64/pfn.cc new file mode 100644 index 0000000..caa864f --- /dev/null +++ b/xtoskrnl/mm/amd64/pfn.cc @@ -0,0 +1,249 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: xtoskrnl/mm/amd64/pfn.cc + * DESCRIPTION: Physical Frame Number for AMD64 support + * DEVELOPERS: Aiken Harris + * Rafal Kupiec + */ + +#include + + +/** + * Initializes the PFN database by mapping virtual memory and populating entries. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::Pfn::InitializePfnDatabase(VOID) +{ + PKERNEL_INITIALIZATION_BLOCK InitializationBlock; + PLIST_ENTRY ListEntry; + PLOADER_MEMORY_DESCRIPTOR Descriptor; + PFN_NUMBER BasePage, PageCount; + PUCHAR PfnDatabaseEnd; + PMMMEMORY_LAYOUT MemoryLayout; + PMMPTE ValidPte; + + /* Raise runlevel and acquire the PFN lock */ + KE::RaiseRunLevel RunLevel(DISPATCH_LEVEL); + KE::QueuedSpinLockGuard SpinLock(SystemSpaceLock); + + /* Get the kernel initialization block */ + InitializationBlock = KE::BootInformation::GetInitializationBlock(); + + /* Get the memory layout */ + MemoryLayout = MM::Manager::GetMemoryLayout(); + + /* Get the PFN database size and calculate the end of the PFN database virtual address space */ + PfnDatabaseEnd = (PUCHAR)MemoryLayout->PfnDatabaseAddress + (PfnDatabaseSize * MM_PAGE_SIZE) - 1; + + /* Get a template PTE for mapping the PFN database pages */ + ValidPte = MM::Pte::GetValidPte(); + + /* Map the Page Directory and Page Directory Pointer tables for the PFN database */ + MM::Pte::MapPPE(MemoryLayout->PfnDatabaseAddress, PfnDatabaseEnd, ValidPte); + MM::Pte::MapPDE(MemoryLayout->PfnDatabaseAddress, PfnDatabaseEnd, ValidPte); + + /* Initialize the color tables */ + MM::Colors::InitializeColorTables(); + + /* Iterate over memory descriptors to map the PFN database and initialize entries */ + ListEntry = InitializationBlock->MemoryDescriptorListHead.Flink; + while(ListEntry != &InitializationBlock->MemoryDescriptorListHead) + { + /* Get the descriptor */ + Descriptor = CONTAIN_RECORD(ListEntry, LOADER_MEMORY_DESCRIPTOR, ListEntry); + + /* Skip invisible memory regions */ + if(MM::Manager::VerifyMemoryTypeInvisible(Descriptor->MemoryType)) + { + /* Move to the next descriptor and continue */ + ListEntry = ListEntry->Flink; + continue; + } + + /* Determine the physical page range to process */ + if(Descriptor == FreeDescriptor) + { + BasePage = OriginalFreeDescriptor.BasePage; + PageCount = OriginalFreeDescriptor.PageCount; + } + else + { + BasePage = Descriptor->BasePage; + PageCount = Descriptor->PageCount; + } + + /* Map PFN database entries for this physical range */ + MM::Pte::MapPTE(&((PMMPFN)MemoryLayout->PfnDatabaseAddress)[BasePage], + (PUCHAR)&((PMMPFN)MemoryLayout->PfnDatabaseAddress)[BasePage + PageCount] - 1, + ValidPte); + + /* Split PFN database allocation out of the free descriptor */ + if(Descriptor == FreeDescriptor) + { + /* Initialize PFNs for the remaining free memory */ + ProcessMemoryDescriptor(BasePage + PfnDatabaseSize, PageCount - PfnDatabaseSize, LoaderFree); + + /* Initialize PFNs for the physical pages backing the PFN database */ + ProcessMemoryDescriptor(BasePage, PfnDatabaseSize, LoaderMemoryData); + } + else + { + /* Initialize PFNs for this memory range */ + ProcessMemoryDescriptor(BasePage, PageCount, Descriptor->MemoryType); + } + + /* Move to the next descriptor */ + ListEntry = ListEntry->Flink; + } + + /* Restore original free descriptor */ + *FreeDescriptor = OriginalFreeDescriptor; + + /* Initialize PFNs backing page tables */ + InitializePageTablePfns(); +} + +/** + * Initializes PFN database entries for the system page tables. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::Pfn::InitializePageTablePfns(VOID) +{ + PFN_NUMBER PageFrameIndex; + PMMPFN Pfn; + ULONG RootLevel; + PMMPTE RootPte; + + /* Determine root structure based on paging mode */ + if(MM::Paging::GetXpaStatus()) + { + /* XPA enabled, 5-level paging (LA57) */ + RootLevel = 5; + + /* Retrieve the PFN of the PML5 table and its virtual base address */ + PageFrameIndex = MM::Paging::GetPageFrameNumber(MM::Paging::GetPteAddress((PVOID)MM_P5E_LA57_BASE)); + RootPte = (PMMPTE)MM::Paging::GetP5eAddress(NULLPTR); + } + else + { + /* XPA disabled, 4-level paging */ + RootLevel = 4; + + /* Retrieve the PFN of the PML4 table and its virtual base address */ + PageFrameIndex = MM::Paging::GetPageFrameNumber(MM::Paging::GetPteAddress((PVOID)MM_PXE_BASE)); + RootPte = (PMMPTE)MM::Paging::GetPxeAddress(NULLPTR); + } + + /* Initialize the PFN entry for the root page table itself */ + Pfn = GetPfnEntry(PageFrameIndex); + if(Pfn) + { + /* Initialize the PFN entry */ + Pfn->PteAddress = NULLPTR; + Pfn->u1.WsIndex = 0; + Pfn->u2.ShareCount = 1; + Pfn->u3.e1.CacheAttribute = PfnNonCached; + Pfn->u3.e2.ReferenceCount = 1; + Pfn->u4.PteFrame = 0; + } + + /* Start recursive scan from the top level */ + if(RootPte) + { + /* Scan the root page table */ + ScanPageTable(RootPte, RootLevel); + } +} + +/** + * Recursively scans a page table to initialize PFN database entries for active pages. + * + * @param PointerPte + * Pointer to the base of the page table to scan. + * + * @param Level + * The paging level of the table being scanned. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::Pfn::ScanPageTable(IN PMMPTE PointerPte, + IN ULONG Level) +{ + PVOID Address; + ULONG Index; + PMMPTE NextLevelPte; + ULONG PtesPerPage; + + /* Get the number of PTEs per page */ + PtesPerPage = MM::Pte::GetPtesPerPage(); + + /* Iterate through all entries in the current page table */ + for(Index = 0; Index < PtesPerPage; Index++) + { + /* Check if the page table entry is present */ + if(MM::Paging::PteValid(PointerPte)) + { + /* Mark the PFN pointed to by this entry as active */ + LinkPfnForPageTable(MM::Paging::GetPageFrameNumber(PointerPte), PointerPte); + + /* Recurse to the next level, if this is not a leaf node (PTE) */ + if(Level > 1) + { + /* Calculate the virtual address mapped by this entry to find the next table */ + switch(Level) + { + case 5: + /* Calculate PXE */ + Address = MM::Paging::GetP5eVirtualAddress((PMMP5E)PointerPte); + NextLevelPte = (PMMPTE)MM::Paging::GetPxeAddress(Address); + break; + case 4: + /* Calculate PPE */ + Address = MM::Paging::GetPxeVirtualAddress((PMMPXE)PointerPte); + NextLevelPte = (PMMPTE)MM::Paging::GetPpeAddress(Address); + break; + case 3: + /* Calculate PDE */ + Address = MM::Paging::GetPpeVirtualAddress((PMMPPE)PointerPte); + NextLevelPte = (PMMPTE)MM::Paging::GetPdeAddress(Address); + break; + case 2: + /* Calculate PTE */ + Address = MM::Paging::GetPdeVirtualAddress((PMMPDE)PointerPte); + NextLevelPte = MM::Paging::GetPteAddress(Address); + break; + default: + /* Nothing to calculate, return NULLPTR */ + NextLevelPte = NULLPTR; + break; + } + + /* Recurse deeper if not at the bottom level (PTE) already */ + if(NextLevelPte) + { + /* Recursively scan the next level page table */ + ScanPageTable(NextLevelPte, Level - 1); + } + } + } + + /* Move to the next entry in the current table */ + PointerPte = MM::Paging::GetNextPte(PointerPte); + } +} diff --git a/xtoskrnl/mm/colors.cc b/xtoskrnl/mm/colors.cc index e225846..5774785 100644 --- a/xtoskrnl/mm/colors.cc +++ b/xtoskrnl/mm/colors.cc @@ -93,3 +93,69 @@ MM::Colors::GetPagingColorsMask() /* Return the mask used for page coloring calculations */ return PagingColorsMask; } + +/** + * Initializes the data structures for page coloring. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::Colors::InitializeColorTables(VOID) +{ + PMMMEMORY_LAYOUT MemoryLayout; + PMMPTE PointerPte, LastPte; + ULONG Color; + PMMPTE ValidPte; + + /* Get the memory layout */ + MemoryLayout = MM::Manager::GetMemoryLayout(); + + /* Set the base address of the color tables to start right after the PFN database */ + FreePages[0] = (PMMCOLOR_TABLES)&((PMMPFN)MemoryLayout->PfnDatabaseAddress)[MM::Pfn::GetHighestPhysicalPage() + 1]; + + /* Calculate the virtual address range for both color tables */ + PointerPte = MM::Paging::GetPteAddress(&FreePages[0][0]); + LastPte = MM::Paging::GetPteAddress((PVOID)((ULONG_PTR)FreePages[0] + + (2 * PagingColors * sizeof(MMCOLOR_TABLES)) - 1)); + + /* Get a pointer to a PTE template */ + ValidPte = MM::Pte::GetValidPte(); + + /* Ensure the entire virtual address range for the color tables is mapped */ + while(PointerPte <= LastPte) + { + /* Check if a page in the range is not mapped */ + if(!MM::Paging::PteValid(PointerPte)) + { + /* Use the bootstrap allocator to get a physical page */ + MM::Paging::SetPte(ValidPte, MM::Pfn::AllocateBootstrapPages(1), 0); + *PointerPte = *ValidPte; + + /* Zero out the newly mapped page */ + RTL::Memory::ZeroMemory(MM::Paging::GetPteVirtualAddress(PointerPte), MM_PAGE_SIZE); + } + + /* Move to the next PTE in the range */ + PointerPte = MM::Paging::GetNextPte(PointerPte); + } + + /* Set the pointer for the second list */ + FreePages[1] = &FreePages[0][PagingColors]; + + /* Initialize all entries in both color tables */ + for(Color = 0; Color < PagingColors; Color++) + { + /* Initialize the FreePageList entry for the current color */ + FreePages[FreePageList][Color].Flink = MAXULONG_PTR; + FreePages[FreePageList][Color].Blink = (PVOID)MAXULONG_PTR; + FreePages[FreePageList][Color].Count = 0; + + /* Initialize the ZeroedPageList entry for the current color */ + FreePages[ZeroedPageList][Color].Flink = MAXULONG_PTR; + FreePages[ZeroedPageList][Color].Blink = (PVOID)MAXULONG_PTR; + FreePages[ZeroedPageList][Color].Count = 0; + } +} diff --git a/xtoskrnl/mm/data.cc b/xtoskrnl/mm/data.cc index 3c26171..886a78a 100644 --- a/xtoskrnl/mm/data.cc +++ b/xtoskrnl/mm/data.cc @@ -45,6 +45,9 @@ PFN_NUMBER MM::Pfn::AvailablePages; /* Biggest free memory descriptor */ PLOADER_MEMORY_DESCRIPTOR MM::Pfn::FreeDescriptor; +/* List containing free physical pages */ +MMPFNLIST MM::Pfn::FreePagesList = {0, FreePageList, MAXULONG_PTR, MAXULONG_PTR}; + /* Highest physical page number */ ULONG_PTR MM::Pfn::HighestPhysicalPage; diff --git a/xtoskrnl/mm/i686/pfn.cc b/xtoskrnl/mm/i686/pfn.cc new file mode 100644 index 0000000..030f97c --- /dev/null +++ b/xtoskrnl/mm/i686/pfn.cc @@ -0,0 +1,234 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: xtoskrnl/mm/i686/pfn.cc + * DESCRIPTION: Physical Frame Number for i686 support + * DEVELOPERS: Aiken Harris + * Rafal Kupiec + */ + +#include + + +/** + * Initializes the PFN database by mapping virtual memory and populating entries. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::Pfn::InitializePfnDatabase(VOID) +{ + PLOADER_MEMORY_DESCRIPTOR Descriptor; + PKERNEL_INITIALIZATION_BLOCK InitializationBlock; + PLIST_ENTRY ListEntry; + PMMMEMORY_LAYOUT MemoryLayout; + PUCHAR PfnDatabaseEnd; + PMMPTE ValidPte; + + /* Raise runlevel and acquire PFN lock */ + KE::RaiseRunLevel RunLevel(DISPATCH_LEVEL); + KE::QueuedSpinLockGuard SpinLock(SystemSpaceLock); + + /* Get the kernel initialization block */ + InitializationBlock = KE::BootInformation::GetInitializationBlock(); + + /* Get memory layout */ + MemoryLayout = MM::Manager::GetMemoryLayout(); + + /* Get the PFN database size and calculate the end of the PFN database virtual address space */ + PfnDatabaseEnd = (PUCHAR)MemoryLayout->PfnDatabaseAddress + (PfnDatabaseSize * MM_PAGE_SIZE) - 1; + + /* Get a template PTE for mapping the PFN database pages */ + ValidPte = MM::Pte::GetValidPte(); + + /* Map the Page Directory and Page Directory Pointer tables for the PFN database */ + MM::Pte::MapPDE(MemoryLayout->PfnDatabaseAddress, PfnDatabaseEnd, ValidPte); + MM::Pte::MapPTE(MemoryLayout->PfnDatabaseAddress, PfnDatabaseEnd, ValidPte); + + /* Zero PFN database virtual space */ + RTL::Memory::ZeroMemory(MemoryLayout->PfnDatabaseAddress, PfnDatabaseSize * MM_PAGE_SIZE); + + /* Initialize the color tables */ + MM::Colors::InitializeColorTables(); + + /* Iterate over memory descriptors to map the PFN database and initialize entries */ + ListEntry = InitializationBlock->MemoryDescriptorListHead.Flink; + while(ListEntry != &InitializationBlock->MemoryDescriptorListHead) + { + /* Get the descriptor */ + Descriptor = CONTAIN_RECORD(ListEntry, LOADER_MEMORY_DESCRIPTOR, ListEntry); + + /* Skip invisible memory regions */ + if(MM::Manager::VerifyMemoryTypeInvisible(Descriptor->MemoryType)) + { + /* Move to the next descriptor and continue */ + ListEntry = ListEntry->Flink; + continue; + } + + /* Split PFN DB allocation out of free descriptor */ + if(Descriptor == FreeDescriptor) + { + /* Initialize PFNs for the remaining free memory after the PFN database */ + ProcessMemoryDescriptor(OriginalFreeDescriptor.BasePage + PfnDatabaseSize, + OriginalFreeDescriptor.PageCount - PfnDatabaseSize, + LoaderFree); + + /* Initialize PFNs for the physical pages backing the PFN database itself */ + ProcessMemoryDescriptor(OriginalFreeDescriptor.BasePage, PfnDatabaseSize, LoaderMemoryData); + } + else + { + /* Initialize PFNs for the physical pages described by this descriptor */ + ProcessMemoryDescriptor(Descriptor->BasePage, Descriptor->PageCount, Descriptor->MemoryType); + } + + /* Move to the next descriptor */ + ListEntry = ListEntry->Flink; + } + + /* Restore original free descriptor */ + *FreeDescriptor = OriginalFreeDescriptor; + + /* Initialize PFNs backing page tables */ + InitializePageTablePfns(); +} + +/** + * Initializes PFN database entries for the system page tables. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::Pfn::InitializePageTablePfns(VOID) +{ + PFN_NUMBER PageFrameIndex; + PMMPFN Pfn; + ULONG RootLevel; + PMMPTE RootPte; + + /* Determine root structure based on paging mode */ + if(MM::Paging::GetXpaStatus()) + { + /* XPA enabled, 3-level paging (PAE) */ + RootLevel = 3; + + /* Retrieve the PFN of the PML3 table and its virtual base address */ + PageFrameIndex = AR::CpuFunc::ReadControlRegister(3) >> MM_PAGE_SHIFT; + RootPte = (PMMPTE)MM::Paging::GetPpeAddress(NULLPTR); + } + else + { + /* XPA disabled, 2-level paging */ + RootLevel = 2; + + /* Retrieve the PFN of the PML2 table and its virtual base address */ + PageFrameIndex = AR::CpuFunc::ReadControlRegister(3) >> MM_PAGE_SHIFT; + RootPte = (PMMPTE)MM::Paging::GetPdeAddress(NULLPTR); + } + + /* Initialize the PFN entry for the root page table itself */ + Pfn = GetPfnEntry(PageFrameIndex); + if(Pfn) + { + /* Initialize the PFN entry */ + Pfn->PteAddress = NULLPTR; + Pfn->u1.WsIndex = 0; + Pfn->u2.ShareCount = 1; + Pfn->u3.e1.CacheAttribute = PfnNonCached; + Pfn->u3.e1.PageLocation = ActiveAndValid; + Pfn->u3.e2.ReferenceCount = 1; + Pfn->u4.PteFrame = 0; + } + + /* Start recursive scan from the top level */ + if(RootPte) + { + /* Scan the root page table */ + ScanPageTable(RootPte, RootLevel); + } +} + +/** + * Recursively scans a page table to initialize PFN database entries for active pages. + * + * @param PointerPte + * Pointer to the base of the page table to scan. + * + * @param Level + * The paging level of the table being scanned. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::Pfn::ScanPageTable(IN PMMPTE PointerPte, + IN ULONG Level) +{ + PVOID Address; + ULONG Index; + PMMPTE NextLevelPte; + ULONG PtesPerPage; + + /* Get the number of PTEs per page */ + PtesPerPage = MM::Pte::GetPtesPerPage(); + + /* Check if PML3 is enabled and current level is PDPT */ + if(Level == 3) + { + /* PAE PDPT has only 4 entries */ + PtesPerPage = 4; + } + + /* Iterate through all entries in the current page table */ + for(Index = 0; Index < PtesPerPage; Index++) + { + /* Check if the page table entry is present */ + if(MM::Paging::PteValid(PointerPte)) + { + /* Mark the PFN pointed to by this entry as active */ + LinkPfnForPageTable(MM::Paging::GetPageFrameNumber(PointerPte), PointerPte); + + /* Recurse to the next level, if this is not a leaf node (PTE) */ + if(Level > 1) + { + /* Calculate the virtual address mapped by this entry to find the next table */ + switch(Level) + { + case 3: + /* Calculate PDE */ + Address = MM::Paging::GetPpeVirtualAddress(PointerPte); + NextLevelPte = (PMMPTE)MM::Paging::GetPdeAddress(Address); + break; + case 2: + /* Calculate PTE */ + Address = MM::Paging::GetPdeVirtualAddress(PointerPte); + NextLevelPte = (PMMPTE)MM::Paging::GetPteAddress(Address); + break; + default: + /* Nothing to calculate, return NULLPTR */ + NextLevelPte = NULLPTR; + break; + } + + /* Recurse deeper if not at the bottom level (PTE) already */ + if(NextLevelPte) + { + /* Recursively scan the next level page table */ + ScanPageTable(NextLevelPte, Level - 1); + } + } + } + + /* Move to the next entry in the current table */ + PointerPte = MM::Paging::GetNextPte(PointerPte); + } +} diff --git a/xtoskrnl/mm/mmgr.cc b/xtoskrnl/mm/mmgr.cc index a8a4dbf..bf00683 100644 --- a/xtoskrnl/mm/mmgr.cc +++ b/xtoskrnl/mm/mmgr.cc @@ -68,6 +68,9 @@ MM::Manager::InitializeMemoryManager(VOID) /* Initialize system PTE space */ MM::Pte::InitializeSystemPteSpace(); + + /* Initialize PFN database */ + MM::Pfn::InitializePfnDatabase(); } /** diff --git a/xtoskrnl/mm/pfn.cc b/xtoskrnl/mm/pfn.cc index 966572e..6bd0648 100644 --- a/xtoskrnl/mm/pfn.cc +++ b/xtoskrnl/mm/pfn.cc @@ -75,6 +75,21 @@ MM::Pfn::DecrementAvailablePages(VOID) AvailablePages--; } +/** + * Retrieves the highest physical page number (PFN) detected in the system. + * + * @return This routine returns the highest physical page number. + * + * @since XT 1.0 + */ +XTAPI +ULONG_PTR +MM::Pfn::GetHighestPhysicalPage() +{ + /* Return the highest physical page number */ + return HighestPhysicalPage; +} + /** * Retrieves the total number of physical pages managed by the system. * @@ -150,6 +165,246 @@ MM::Pfn::IncrementAvailablePages(VOID) AvailablePages++; } +/** + * Links a physical page to the appropriate free lists. + * + * @param PageFrameIndex + * The Page Frame Number (PFN) of the page to link. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::Pfn::LinkFreePage(IN PFN_NUMBER PageFrameIndex) +{ + ULONG Color; + PMMPFNLIST ListHead; + PFN_NUMBER LastPage; + PMMPFN ColoredPfn, PfnEntry; + PMMCOLOR_TABLES ColorTable; + PMMMEMORY_LAYOUT MemoryLayout; + + /* Get the PFN database entry for the page */ + PfnEntry = GetPfnEntry(PageFrameIndex); + + /* Check if the page is part of a ROM image */ + if(PfnEntry->u3.e1.Rom == 1) + { + /* Mark the page as inactive and clear its links */ + PfnEntry->u1.Flink = 0; + PfnEntry->u3.e1.PageLocation = 0; + + /* Do not free ROM pages */ + return; + } + + /* Check if the page is marked for removal */ + if(PfnEntry->u3.e1.RemovalRequested == 1) + { + /* Update cache attribute to not mapped */ + PfnEntry->u3.e1.CacheAttribute = PfnNotMapped; + + /* Do not add it to the free list */ + return; + } + + /* Insert the page into the global free list */ + ListHead = &FreePagesList; + ListHead->Total++; + + /* Get the current last page on the list */ + LastPage = ListHead->Blink; + + /* Check if the list is not empty */ + if(LastPage != MAXULONG_PTR) + { + /* Link with the previous last page */ + GetPfnEntry(LastPage)->u1.Flink = PageFrameIndex; + } + else + { + /* Put the page as the first entry */ + ListHead->Flink = PageFrameIndex; + } + + /* Set the page as the new tail of the list */ + ListHead->Blink = PageFrameIndex; + PfnEntry->u1.Flink = MAXULONG_PTR; + PfnEntry->u2.Blink = LastPage; + PfnEntry->u3.e1.CacheAttribute = PfnNotMapped; + PfnEntry->u3.e1.PageLocation = FreePageList; + PfnEntry->u4.AweAllocation = 0; + PfnEntry->u4.InPageError = 0; + PfnEntry->u4.Priority = 3; + + /* Insert the page into the colored free list */ + Color = PageFrameIndex & MM::Colors::GetPagingColorsMask(); + ColorTable = MM::Colors::GetFreePages(FreePageList, Color); + + /* Get the memory layout */ + MemoryLayout = MM::Manager::GetMemoryLayout(); + + /* Check if the colored list is empty */ + if(ColorTable->Flink == MAXULONG_PTR) + { + /* Put the page as the first entry */ + ColorTable->Flink = PageFrameIndex; + PfnEntry->u4.PteFrame = MM_PFN_PTE_FRAME; + } + else + { + /* Get the current last page on the colored list */ + ColoredPfn = (PMMPFN)ColorTable->Blink; + + /* Link with the previous last page */ + MM::Paging::SetPte(&ColoredPfn->OriginalPte, PageFrameIndex); + PfnEntry->u4.PteFrame = ColoredPfn - (PMMPFN)MemoryLayout->PfnDatabaseAddress; + } + + /* Set the page as the new tail of the colored list */ + ColorTable->Blink = PfnEntry; + ColorTable->Count++; + MM::Paging::SetPte(&PfnEntry->OriginalPte, MAXULONG_PTR); + + /* Increment number of available pages */ + IncrementAvailablePages(); +} + +/** + * Initializes the PFN database entry for a physical page that is used as a page table. + * + * @param PageFrameIndex + * The page frame number of the physical page being used as a page table. + * + * @param PointerPte + * A pointer to the higher-level PTE that maps this page table page. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::Pfn::LinkPfnForPageTable(PFN_NUMBER PageFrameIndex, + PMMPTE PointerPte) +{ + PMMPFN Pfn; + PMMPDE PointerPde; + PVOID EndAddress; + + /* Retrieve the PFN database entry for the physical page of the page table */ + Pfn = GetPfnEntry(PageFrameIndex); + + /* Calculate the end address of the PFN entry to ensure it's mapped */ + EndAddress = (PUCHAR)(Pfn + 1) - 1; + + /* Validate that the PFN entry corresponds to a valid, active physical page */ + if((PageFrameIndex <= HighestPhysicalPage) && (MM::Pte::AddressValid(Pfn)) && + (MM::Pte::AddressValid(EndAddress)) && (Pfn->u3.e1.PageLocation == ActiveAndValid)) + { + /* Initialize the PFN entry for this page table page */ + Pfn->u1.WsIndex = 0; + Pfn->u2.ShareCount++; + Pfn->PteAddress = PointerPte; + Pfn->OriginalPte = *PointerPte; + Pfn->u3.e1.PageLocation = ActiveAndValid; + Pfn->u3.e1.CacheAttribute = PfnNonCached; + Pfn->u3.e2.ReferenceCount = 1; + Pfn->u4.PteFrame = MM::Paging::GetPageFrameNumber(MM::Paging::GetPteAddress(PointerPte)); + } + + /* Increment the share count of the parent page table that contains the mapping */ + PointerPde = MM::Paging::GetPdeAddress(MM::Paging::GetPteVirtualAddress(PointerPte)); + Pfn = GetPfnEntry(MM::Paging::GetPageFrameNumber(PointerPde)); + Pfn->u2.ShareCount++; +} + +/** + * Processes a memory descriptor and initializes the corresponding PFN database entries + * + * @param BasePage + * The starting physical page number of the memory run + * + * @param PageCount + * The number of pages in the memory run + * + * @param MemoryType + * The type of memory as reported by the bootloader (e.g., free, ROM, in-use) + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::Pfn::ProcessMemoryDescriptor(IN PFN_NUMBER BasePage, + IN PFN_NUMBER PageCount, + IN LOADER_MEMORY_TYPE MemoryType) +{ + PFN_NUMBER CurrentPage, PageNumber; + PMMPFN Pfn; + + /* Check if the memory descriptor describes a free memory region */ + if(MM::Manager::VerifyMemoryTypeFree(MemoryType)) + { + /* Iterate over each page in this free memory run */ + for(PageNumber = 0; PageNumber < PageCount; PageNumber++) + { + /* Get the PFN entry for the current page and set its initial cache attribute */ + CurrentPage = BasePage + PageNumber; + Pfn = GetPfnEntry(CurrentPage); + Pfn->u3.e1.CacheAttribute = PfnNonCached; + + /* Add the page to the free list to make it available for allocation */ + LinkFreePage(CurrentPage); + } + } + else + { + /* Handle all other (non-free) memory types */ + switch(MemoryType) + { + case LoaderBad: + /* This memory is marked as bad and should not be used */ + UNIMPLEMENTED; + break; + case LoaderXIPRom: + /* This memory range contains Read-Only Memory (ROM) */ + for(PageNumber = 0; PageNumber < PageCount; PageNumber++) + { + /* Get the PFN entry for the current ROM page */ + Pfn = GetPfnEntry(BasePage + PageNumber); + + /* Initialize the PFN entry to represent a ROM page */ + Pfn->PteAddress = 0; + Pfn->u1.Flink = 0; + Pfn->u2.ShareCount = 0; + Pfn->u3.e1.CacheAttribute = PfnNonCached; + Pfn->u3.e1.PageLocation = 0; + Pfn->u3.e1.PrototypePte = 1; + Pfn->u3.e2.ReferenceCount = 0; + Pfn->u3.e1.Rom = 1; + Pfn->u4.InPageError = 0; + Pfn->u4.PteFrame = 0; + } + break; + default: + /* All other types are considered in-use (ie, by the kernel, ACPI, etc) */ + for(PageNumber = 0; PageNumber < PageCount; PageNumber++) + { + /* Get the PFN entry for the current in-use page */ + Pfn = GetPfnEntry(BasePage + PageNumber); + + /* Mark the PFN as active and valid to prevent it from being allocated */ + Pfn->u3.e1.PageLocation = ActiveAndValid; + } + break; + } + } +} + /** * Scans memory descriptors provided by the boot loader. * diff --git a/xtoskrnl/mm/pte.cc b/xtoskrnl/mm/pte.cc index a2a3f6f..c6a181d 100644 --- a/xtoskrnl/mm/pte.cc +++ b/xtoskrnl/mm/pte.cc @@ -104,6 +104,21 @@ MM::Pte::GetPtesPerPage(VOID) return MM_PAGE_SIZE / MM::Paging::GetPteSize(); } +/** + * Returns a pointer to the valid PTE. + * + * @return This routine returns a pointer to the valid PTE. + * + * @since XT 1.0 + */ +XTAPI +PMMPTE +MM::Pte::GetValidPte() +{ + /* Return a pointer to the valid PTE */ + return &ValidPte; +} + /** * Formats a range of PTEs into a freelist-based pool for system allocations. * -- 2.52.0 From 04599161da371fd2a0fa0578642d984c2e35a22c Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Sun, 28 Dec 2025 23:36:20 +0100 Subject: [PATCH 068/166] Refactor memory clearing calls and cleanup code style --- xtoskrnl/mm/amd64/pte.cc | 7 +++---- xtoskrnl/mm/i686/pte.cc | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/xtoskrnl/mm/amd64/pte.cc b/xtoskrnl/mm/amd64/pte.cc index 8d86882..71fba17 100644 --- a/xtoskrnl/mm/amd64/pte.cc +++ b/xtoskrnl/mm/amd64/pte.cc @@ -77,7 +77,6 @@ MM::Pte::GetSystemPteBaseAddress(VOID) } } - /** * Performs the initial setup of the system's page table hierarchy. * @@ -193,7 +192,7 @@ MM::Pte::MapP5E(PVOID StartAddress, *PointerP5e = *TemplateP5e; /* Clear the page table */ - RtlZeroMemory(MM::Paging::GetPteVirtualAddress(PointerP5e), MM_PAGE_SIZE); + RTL::Memory::ZeroMemory(MM::Paging::GetPteVirtualAddress(PointerP5e), MM_PAGE_SIZE); } /* Get next table entry */ @@ -240,7 +239,7 @@ MM::Pte::MapPPE(PVOID StartAddress, *PointerPpe = *TemplatePpe; /* Clear the page table */ - RtlZeroMemory(MM::Paging::GetPteVirtualAddress(PointerPpe), MM_PAGE_SIZE); + RTL::Memory::ZeroMemory(MM::Paging::GetPteVirtualAddress(PointerPpe), MM_PAGE_SIZE); } /* Get next table entry */ @@ -287,7 +286,7 @@ MM::Pte::MapPXE(PVOID StartAddress, *PointerPxe = *TemplatePxe; /* Clear the page table */ - RtlZeroMemory(MM::Paging::GetPteVirtualAddress(PointerPxe), MM_PAGE_SIZE); + RTL::Memory::ZeroMemory(MM::Paging::GetPteVirtualAddress(PointerPxe), MM_PAGE_SIZE); } /* Get next table entry */ diff --git a/xtoskrnl/mm/i686/pte.cc b/xtoskrnl/mm/i686/pte.cc index 3ca5b1f..60bc935 100644 --- a/xtoskrnl/mm/i686/pte.cc +++ b/xtoskrnl/mm/i686/pte.cc @@ -112,7 +112,7 @@ MM::Pte::InitializePageTable(VOID) MM::Pte::MapPDE(MemoryLayout->SystemSpaceStart, (PVOID)MM_HIGHEST_SYSTEM_ADDRESS, &TemplatePte); } -/* +/** * Maps a range of virtual addresses at the PPE (Page Directory Pointer Entry) level. * * @param StartAddress -- 2.52.0 From d891088b1a7d9daa3b6c085eb0b14824120a3198 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Sun, 28 Dec 2025 23:39:08 +0100 Subject: [PATCH 069/166] Update PTE support to use safe write accessors --- xtoskrnl/mm/pte.cc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/xtoskrnl/mm/pte.cc b/xtoskrnl/mm/pte.cc index c6a181d..fbec00b 100644 --- a/xtoskrnl/mm/pte.cc +++ b/xtoskrnl/mm/pte.cc @@ -2,7 +2,7 @@ * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/mm/pte.cc - * DESCRIPTION: Page table entry (PTE) support + * DESCRIPTION: Page Table Entry (PTE) support * DEVELOPERS: Aiken Harris */ @@ -235,10 +235,10 @@ MM::Pte::MapPDE(PVOID StartAddress, { /* Map PDE */ MM::Paging::SetPte(TemplatePde, MM::Pfn::AllocateBootstrapPages(1), 0); - *PointerPde = *TemplatePde; + MM::Paging::WritePte(PointerPde, *TemplatePde); /* Clear the page table */ - RtlZeroMemory(MM::Paging::GetPteVirtualAddress(PointerPde), MM_PAGE_SIZE); + RTL::Memory::ZeroMemory(MM::Paging::GetPteVirtualAddress(PointerPde), MM_PAGE_SIZE); } /* Get next table entry */ @@ -282,10 +282,10 @@ MM::Pte::MapPTE(PVOID StartAddress, { /* Map PTE */ MM::Paging::SetPte(TemplatePte, MM::Pfn::AllocateBootstrapPages(1), 0); - *PointerPte = *TemplatePte; + MM::Paging::WritePte(PointerPte, *TemplatePte); /* Clear the page table */ - RtlZeroMemory(MM::Paging::GetPteVirtualAddress(PointerPte), MM_PAGE_SIZE); + RTL::Memory::ZeroMemory(MM::Paging::GetPteVirtualAddress(PointerPte), MM_PAGE_SIZE); } /* Get next table entry */ -- 2.52.0 From 200e9132b166488549d818f68ba9246e41000b23 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Sun, 28 Dec 2025 23:51:34 +0100 Subject: [PATCH 070/166] Minor style fixes in MM includes --- xtoskrnl/includes/mm/amd64/pte.hh | 2 +- xtoskrnl/includes/mm/i686/pte.hh | 2 +- xtoskrnl/includes/mm/mmgr.hh | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/xtoskrnl/includes/mm/amd64/pte.hh b/xtoskrnl/includes/mm/amd64/pte.hh index 9c43665..1c02731 100644 --- a/xtoskrnl/includes/mm/amd64/pte.hh +++ b/xtoskrnl/includes/mm/amd64/pte.hh @@ -2,7 +2,7 @@ * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/mm/amd64/pte.hh - * DESCRIPTION: Page table entry (PTE) for AMD64 support + * DESCRIPTION: Page Table Entry (PTE) for AMD64 support * DEVELOPERS: Aiken Harris */ diff --git a/xtoskrnl/includes/mm/i686/pte.hh b/xtoskrnl/includes/mm/i686/pte.hh index 70393f9..0ad0ba5 100644 --- a/xtoskrnl/includes/mm/i686/pte.hh +++ b/xtoskrnl/includes/mm/i686/pte.hh @@ -2,7 +2,7 @@ * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/mm/i686/pte.hh - * DESCRIPTION: Page table entry (PTE) for i686 support + * DESCRIPTION: Page Table Entry (PTE) for i686 support * DEVELOPERS: Aiken Harris */ diff --git a/xtoskrnl/includes/mm/mmgr.hh b/xtoskrnl/includes/mm/mmgr.hh index de943d5..8d4254a 100644 --- a/xtoskrnl/includes/mm/mmgr.hh +++ b/xtoskrnl/includes/mm/mmgr.hh @@ -2,7 +2,7 @@ * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/mm/mmgr.hh - * DESCRIPTION: Memory manager + * DESCRIPTION: Memory Manager * DEVELOPERS: Aiken Harris */ -- 2.52.0 From 7cb3d1764b9fd83a80c64644034012af705e18f0 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Mon, 29 Dec 2025 10:28:12 +0100 Subject: [PATCH 071/166] Initialize paged pool sizing logic --- xtoskrnl/mm/i686/mmgr.cc | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/xtoskrnl/mm/i686/mmgr.cc b/xtoskrnl/mm/i686/mmgr.cc index 478b228..a064930 100644 --- a/xtoskrnl/mm/i686/mmgr.cc +++ b/xtoskrnl/mm/i686/mmgr.cc @@ -42,6 +42,14 @@ MM::Manager::InitializeMemoryLayout(VOID) NumberOfSystemPtes = MM_MAXIMUM_NUMBER_SYSTEM_PTES; } + /* Calculate size of paged pool */ + PtesPerPage = MM::Pte::GetPtesPerPage(); + PteCount = (SIZE_TO_PAGES(33554432) + (PtesPerPage - 1)) / PtesPerPage; + PagedPoolSize = PteCount * PtesPerPage * MM_PAGE_SIZE; + + /* Retrieve the PFN database size */ + PfnDatabaseSize = MM::Pfn::GetPfnDatabaseSize(); + /* Check if 3-level paging (PAE) is enabled */ if(MM::Paging::GetXpaStatus()) { -- 2.52.0 From 28f49dd54512ecfe519f047cc7f152b21f1e5063 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Mon, 29 Dec 2025 10:56:43 +0100 Subject: [PATCH 072/166] Ensure page map structures are self-mapped --- boot/xtldr/arch/amd64/memory.cc | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/boot/xtldr/arch/amd64/memory.cc b/boot/xtldr/arch/amd64/memory.cc index ed12532..3f8f049 100644 --- a/boot/xtldr/arch/amd64/memory.cc +++ b/boot/xtldr/arch/amd64/memory.cc @@ -44,6 +44,14 @@ Memory::BuildPageMap(IN PXTBL_PAGE_MAPPING PageMap, return Status; } + /* Add new memory mapping for the page map itself */ + Status = MapVirtualMemory(PageMap, (PVOID)(UINT_PTR)Address, (PVOID)(UINT_PTR)Address, 1, LoaderMemoryData); + if(Status != STATUS_EFI_SUCCESS) + { + /* Memory mapping failure */ + return Status; + } + /* Assign and zero-fill memory used by page mappings */ PageMap->PtePointer = (PVOID)(UINT_PTR)Address; RTL::Memory::ZeroMemory(PageMap->PtePointer, EFI_PAGE_SIZE); @@ -193,7 +201,7 @@ Memory::GetNextPageTable(IN PXTBL_PAGE_MAPPING PageMap, } /* Add new memory mapping */ - Status = MapVirtualMemory(PageMap, NULLPTR, (PVOID)(UINT_PTR)Address, 1, LoaderMemoryData); + Status = MapVirtualMemory(PageMap, (PVOID)(UINT_PTR)Address, (PVOID)(UINT_PTR)Address, 1, LoaderMemoryData); if(Status != STATUS_EFI_SUCCESS) { /* Memory mapping failure */ -- 2.52.0 From 49e97fb8b46a0a51b3538a2d02598b739b60015f Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Mon, 29 Dec 2025 13:17:41 +0100 Subject: [PATCH 073/166] Reserve space for color tables to fix invalid memory access --- xtoskrnl/mm/pfn.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/xtoskrnl/mm/pfn.cc b/xtoskrnl/mm/pfn.cc index 6bd0648..9138ac1 100644 --- a/xtoskrnl/mm/pfn.cc +++ b/xtoskrnl/mm/pfn.cc @@ -56,6 +56,7 @@ MM::Pfn::ComputePfnDatabaseSize(VOID) { /* Calculate the total number of pages required for the PFN database */ PfnDatabaseSize = (HighestPhysicalPage + 1) * sizeof(MMPFN); + PfnDatabaseSize += (MM::Colors::GetPagingColors() * sizeof(MMCOLOR_TABLES) * 2); PfnDatabaseSize = ROUND_UP(PfnDatabaseSize, MM_PAGE_SIZE); PfnDatabaseSize >>= MM_PAGE_SHIFT; } -- 2.52.0 From 0d2d41dcdac5a269c2f473d238fcc93c5026f242 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Mon, 29 Dec 2025 14:52:04 +0100 Subject: [PATCH 074/166] Introduce page fault handling infrastructure --- xtoskrnl/CMakeLists.txt | 1 + xtoskrnl/includes/mm.hh | 1 + xtoskrnl/includes/mm/pfault.hh | 25 +++++++++++++++++++++++ xtoskrnl/mm/amd64/pfault.cc | 26 ++++++++++++++++++++++++ xtoskrnl/mm/i686/pfault.cc | 36 ++++++++++++++++++++++++++++++++++ 5 files changed, 89 insertions(+) create mode 100644 xtoskrnl/includes/mm/pfault.hh create mode 100644 xtoskrnl/mm/amd64/pfault.cc create mode 100644 xtoskrnl/mm/i686/pfault.cc diff --git a/xtoskrnl/CMakeLists.txt b/xtoskrnl/CMakeLists.txt index e879b97..bd31b8e 100644 --- a/xtoskrnl/CMakeLists.txt +++ b/xtoskrnl/CMakeLists.txt @@ -54,6 +54,7 @@ list(APPEND XTOSKRNL_SOURCE ${XTOSKRNL_SOURCE_DIR}/mm/${ARCH}/mmgr.cc ${XTOSKRNL_SOURCE_DIR}/mm/${ARCH}/pagemap.cc ${XTOSKRNL_SOURCE_DIR}/mm/${ARCH}/paging.cc + ${XTOSKRNL_SOURCE_DIR}/mm/${ARCH}/pfault.cc ${XTOSKRNL_SOURCE_DIR}/mm/${ARCH}/pfn.cc ${XTOSKRNL_SOURCE_DIR}/mm/${ARCH}/pte.cc ${XTOSKRNL_SOURCE_DIR}/mm/colors.cc diff --git a/xtoskrnl/includes/mm.hh b/xtoskrnl/includes/mm.hh index b34863d..5c2e568 100644 --- a/xtoskrnl/includes/mm.hh +++ b/xtoskrnl/includes/mm.hh @@ -19,6 +19,7 @@ #include #include #include +#include #include #endif /* __XTOSKRNL_MM_HH */ diff --git a/xtoskrnl/includes/mm/pfault.hh b/xtoskrnl/includes/mm/pfault.hh new file mode 100644 index 0000000..30e2e49 --- /dev/null +++ b/xtoskrnl/includes/mm/pfault.hh @@ -0,0 +1,25 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: xtoskrnl/includes/mm/pfault.hh + * DESCRIPTION: Page fault support + * DEVELOPERS: Aiken Harris + */ + +#ifndef __XTOSKRNL_MM_PFAULT_HH +#define __XTOSKRNL_MM_PFAULT_HH + +#include + + +/* Memory Manager */ +namespace MM +{ + class PageFault + { + public: + STATIC XTFASTCALL XTSTATUS CheckPdeForPagedPool(IN PVOID VirtualAddress); + }; +} + +#endif /* __XTOSKRNL_MM_PFAULT_HH */ diff --git a/xtoskrnl/mm/amd64/pfault.cc b/xtoskrnl/mm/amd64/pfault.cc new file mode 100644 index 0000000..a3d5b9d --- /dev/null +++ b/xtoskrnl/mm/amd64/pfault.cc @@ -0,0 +1,26 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: xtoskrnl/mm/amd64/pfault.cc + * DESCRIPTION: Page fault support for AMD64 architecture + * DEVELOPERS: Aiken Harris + */ + +#include + + +/** + * Evaluates the PDE for for paged pool and per-session mappings. + * + * @param VirtualAddress + * Specifies the virtual address to verify. + * + * @return This routine returns ACCESS_VIOLATION regardless PML4 or PML5 is used. + */ +XTFASTCALL +XTSTATUS +MM::PageFault::CheckPdeForPagedPool(IN PVOID VirtualAddress) +{ + /* Return access violation */ + return STATUS_ACCESS_VIOLATION; +} diff --git a/xtoskrnl/mm/i686/pfault.cc b/xtoskrnl/mm/i686/pfault.cc new file mode 100644 index 0000000..3b6a8e6 --- /dev/null +++ b/xtoskrnl/mm/i686/pfault.cc @@ -0,0 +1,36 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: xtoskrnl/mm/i686/pfault.cc + * DESCRIPTION: Page fault support for i686 architecture + * DEVELOPERS: Aiken Harris + */ + +#include + + +/** + * Evaluates the PDE for for paged pool and per-session mappings. + * + * @param VirtualAddress + * Specifies the virtual address to verify. + * + * @return This routine returns ACCESS_VIOLATION on PML3 or status code on PML2. + */ +XTFASTCALL +XTSTATUS +MM::PageFault::CheckPdeForPagedPool(IN PVOID VirtualAddress) +{ + /* Check if XPA is enabled */ + if(MM::Paging::GetXpaStatus()) + { + /* Access violation for PML3 */ + return STATUS_ACCESS_VIOLATION; + } + + /* Unimplemented path for PML2 */ + UNIMPLEMENTED; + + /* Temporarily, just return access violation */ + return STATUS_ACCESS_VIOLATION; +} -- 2.52.0 From 4a00179af2328138f0b641f136eff014e4638ae7 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Mon, 29 Dec 2025 18:31:16 +0100 Subject: [PATCH 075/166] Implement logic to link physical pages to PTEs --- xtoskrnl/includes/mm/pfn.hh | 25 +++- xtoskrnl/mm/data.cc | 29 ++++- xtoskrnl/mm/pfn.cc | 247 +++++++++++++++++++++++++++++++++++- 3 files changed, 286 insertions(+), 15 deletions(-) diff --git a/xtoskrnl/includes/mm/pfn.hh b/xtoskrnl/includes/mm/pfn.hh index 1832a78..cd4386e 100644 --- a/xtoskrnl/includes/mm/pfn.hh +++ b/xtoskrnl/includes/mm/pfn.hh @@ -19,22 +19,33 @@ namespace MM { private: STATIC PFN_NUMBER AvailablePages; + STATIC MMPFNLIST BadPagesList; STATIC PLOADER_MEMORY_DESCRIPTOR FreeDescriptor; STATIC MMPFNLIST FreePagesList; STATIC ULONG_PTR HighestPhysicalPage; + STATIC PVOID HighestUserAddress; STATIC ULONG_PTR LowestPhysicalPage; + STATIC MMPFNLIST ModifiedPagesList; + STATIC MMPFNLIST ModifiedReadOnlyPagesList; STATIC ULONGLONG NumberOfPhysicalPages; STATIC LOADER_MEMORY_DESCRIPTOR OriginalFreeDescriptor; + STATIC PMMPFNLIST PageLocationList[]; STATIC PFN_NUMBER PfnDatabaseSize; + STATIC MMPFNLIST StandbyPagesList; + STATIC MMPFNLIST ZeroedPagesList; public: STATIC XTAPI PFN_NUMBER AllocateBootstrapPages(IN PFN_NUMBER NumberOfPages); + STATIC XTAPI PFN_NUMBER AllocatePhysicalPage(IN ULONG Color); STATIC XTAPI VOID ComputePfnDatabaseSize(VOID); STATIC XTAPI ULONG_PTR GetHighestPhysicalPage(VOID); STATIC XTAPI ULONGLONG GetNumberOfPhysicalPages(VOID); STATIC XTAPI PFN_NUMBER GetPfnDatabaseSize(VOID); STATIC XTAPI PMMPFN GetPfnEntry(IN PFN_NUMBER Pfn); STATIC XTAPI VOID InitializePfnDatabase(VOID); + STATIC VOID XTAPI LinkPfnToPte(IN PFN_NUMBER PageFrameIndex, + IN PMMPTE PointerPte, + IN BOOLEAN Modified); STATIC XTAPI VOID ScanMemoryDescriptors(VOID); private: @@ -42,13 +53,15 @@ namespace MM STATIC XTAPI VOID IncrementAvailablePages(VOID); STATIC XTAPI VOID InitializePageTablePfns(VOID); STATIC XTAPI VOID LinkFreePage(IN PFN_NUMBER PageFrameIndex); - STATIC XTAPI VOID LinkPfnForPageTable(PFN_NUMBER PageFrameIndex, - PMMPTE PointerPte); - STATIC XTAPI VOID ProcessMemoryDescriptor(PFN_NUMBER BasePage, - PFN_NUMBER PageCount, - LOADER_MEMORY_TYPE MemoryType); + STATIC XTAPI VOID LinkPfnForPageTable(IN PFN_NUMBER PageFrameIndex, + IN PMMPTE PointerPte); + STATIC XTAPI VOID ProcessMemoryDescriptor(IN PFN_NUMBER BasePage, + IN PFN_NUMBER PageCount, + IN LOADER_MEMORY_TYPE MemoryType); STATIC XTAPI VOID ScanPageTable(IN PMMPTE PointerPte, - ULONG Level); + IN ULONG Level); + STATIC XTAPI PFN_NUMBER UnlinkFreePage(IN PFN_NUMBER PageFrameIndex, + IN ULONG Color); }; } diff --git a/xtoskrnl/mm/data.cc b/xtoskrnl/mm/data.cc index 886a78a..d775ba4 100644 --- a/xtoskrnl/mm/data.cc +++ b/xtoskrnl/mm/data.cc @@ -30,10 +30,10 @@ ULONG MM::HardwarePool::UsedHardwareAllocationDescriptors = 0; /* Processor structures data (THIS IS A TEMPORARY HACK) */ UCHAR MM::KernelPool::ProcessorStructuresData[MAXIMUM_PROCESSORS][KPROCESSOR_STRUCTURES_SIZE] = {{0}}; -/* Memory layout */ +/* Global structure describing the virtual memory layout of the system */ MMMEMORY_LAYOUT MM::Manager::MemoryLayout; -/* Number of system PTEs */ +/* Total number of PTEs reserved for system space mapping */ PFN_NUMBER MM::Manager::NumberOfSystemPtes; /* Instance of the page map routines for the current PML level */ @@ -42,6 +42,9 @@ MM::PPAGEMAP MM::Paging::PmlRoutines; /* Total number of physical pages available for allocation */ PFN_NUMBER MM::Pfn::AvailablePages; +/* Head of the list containing physical pages marked as defective */ +MMPFNLIST MM::Pfn::BadPagesList = {0, BadPageList, MAXULONG_PTR, MAXULONG_PTR}; + /* Biggest free memory descriptor */ PLOADER_MEMORY_DESCRIPTOR MM::Pfn::FreeDescriptor; @@ -54,15 +57,37 @@ ULONG_PTR MM::Pfn::HighestPhysicalPage; /* Lowest physical page number */ ULONG_PTR MM::Pfn::LowestPhysicalPage = -1; +/* List containing modified pages */ +MMPFNLIST MM::Pfn::ModifiedPagesList = {0, ModifiedPageList, MAXULONG_PTR, MAXULONG_PTR}; + +/* List containing modified pages mapped as read-only */ +MMPFNLIST MM::Pfn::ModifiedReadOnlyPagesList = {0, ModifiedReadOnlyPageList, MAXULONG_PTR, MAXULONG_PTR}; + /* Number of physical pages */ ULONGLONG MM::Pfn::NumberOfPhysicalPages; /* Old biggest free memory descriptor */ LOADER_MEMORY_DESCRIPTOR MM::Pfn::OriginalFreeDescriptor; +/* List containing standby pages (clean, can be reclaimed or repurposed) */ +MMPFNLIST MM::Pfn::StandbyPagesList = {0, StandbyPageList, MAXULONG_PTR, MAXULONG_PTR}; + +/* Array of pointers to PFN lists */ +PMMPFNLIST MM::Pfn::PageLocationList[] = {&ZeroedPagesList, + &FreePagesList, + &StandbyPagesList, + &ModifiedPagesList, + &ModifiedReadOnlyPagesList, + &BadPagesList, + NULLPTR, + NULLPTR}; + /* Size of the PFN database in pages */ PFN_NUMBER MM::Pfn::PfnDatabaseSize; +/* List containing free physical pages that have been zeroed out */ +MMPFNLIST MM::Pfn::ZeroedPagesList = {0, ZeroedPageList, MAXULONG_PTR, MAXULONG_PTR}; + /* Array of lists for available System PTEs, separated by pool type */ MMPTE MM::Pte::FirstSystemFreePte[MaximumPtePoolTypes]; diff --git a/xtoskrnl/mm/pfn.cc b/xtoskrnl/mm/pfn.cc index 9138ac1..93379f7 100644 --- a/xtoskrnl/mm/pfn.cc +++ b/xtoskrnl/mm/pfn.cc @@ -43,6 +43,59 @@ MM::Pfn::AllocateBootstrapPages(IN PFN_NUMBER NumberOfPages) return Pfn; } +/** + * Allocates a physical page frame (PFN) from one of the system's free page lists. + * + * @param Color + * The preferred page color, used to optimize CPU cache alignment and reduce cache contention. + * + * @return This routine returns the Page Frame Number (PFN) of the allocated page. + * + * @since XT 1.0 + */ +XTAPI +PFN_NUMBER +MM::Pfn::AllocatePhysicalPage(IN ULONG Color) +{ + PFN_NUMBER PageNumber; + ULONG PagingColorsMask; + + /* Check if any physical pages are available in the system */ + if(!AvailablePages) + { + /* No physical pages are available in the system, return 0 */ + return 0; + } + + /* Retrieve the bitmask used for calculating a page's color */ + PagingColorsMask = MM::Colors::GetPagingColorsMask(); + + /* Attempt to retrieve a page from the colored free page list */ + PageNumber = MM::Colors::GetFreePages(FreePageList, Color)->Flink; + if(PageNumber == MAXULONG_PTR) + { + /* No page was found in the colored free page list, check the colored zero page list */ + PageNumber = MM::Colors::GetFreePages(ZeroedPageList, Color)->Flink; + } + + /* Attempt to retrieve a page from the colored zero list */ + if(PageNumber == MAXULONG_PTR) + { + /* No page was found in the colored zero page list, check the global free page list */ + PageNumber = FreePagesList.Flink; + } + + /* Attempt to retrieve a page from the global free page list */ + if(PageNumber == MAXULONG_PTR) + { + /* No page was found in the global free page list, check the global zero page list */ + PageNumber = ZeroedPagesList.Flink; + } + + /* Remove the page from its list and return its PFN */ + return UnlinkFreePage(PageNumber, PageNumber & PagingColorsMask); +} + /** * Calculates the total number of pages required for the PFN database and its associated color tables. * @@ -85,7 +138,7 @@ MM::Pfn::DecrementAvailablePages(VOID) */ XTAPI ULONG_PTR -MM::Pfn::GetHighestPhysicalPage() +MM::Pfn::GetHighestPhysicalPage(VOID) { /* Return the highest physical page number */ return HighestPhysicalPage; @@ -288,8 +341,8 @@ MM::Pfn::LinkFreePage(IN PFN_NUMBER PageFrameIndex) */ XTAPI VOID -MM::Pfn::LinkPfnForPageTable(PFN_NUMBER PageFrameIndex, - PMMPTE PointerPte) +MM::Pfn::LinkPfnForPageTable(IN PFN_NUMBER PageFrameIndex, + IN PMMPTE PointerPte) { PMMPFN Pfn; PMMPDE PointerPde; @@ -306,12 +359,12 @@ MM::Pfn::LinkPfnForPageTable(PFN_NUMBER PageFrameIndex, (MM::Pte::AddressValid(EndAddress)) && (Pfn->u3.e1.PageLocation == ActiveAndValid)) { /* Initialize the PFN entry for this page table page */ + Pfn->OriginalPte = *PointerPte; + Pfn->PteAddress = PointerPte; Pfn->u1.WsIndex = 0; Pfn->u2.ShareCount++; - Pfn->PteAddress = PointerPte; - Pfn->OriginalPte = *PointerPte; - Pfn->u3.e1.PageLocation = ActiveAndValid; Pfn->u3.e1.CacheAttribute = PfnNonCached; + Pfn->u3.e1.PageLocation = ActiveAndValid; Pfn->u3.e2.ReferenceCount = 1; Pfn->u4.PteFrame = MM::Paging::GetPageFrameNumber(MM::Paging::GetPteAddress(PointerPte)); } @@ -322,6 +375,84 @@ MM::Pfn::LinkPfnForPageTable(PFN_NUMBER PageFrameIndex, Pfn->u2.ShareCount++; } +/** + * Links a PFN entry to its corresponding PTE and ensures the page table that contains the PTE is resident in memory. + * + * @param PageFrameIndex + * Supplies the index into the PFN database for the page being initialized. + * + * @param PointerPte + * Supplies the pointer to the PTE which maps the physical page. + * + * @param Modified + * Supplies a flag indicating if the page's initial state is modified. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::Pfn::LinkPfnToPte(IN PFN_NUMBER PageFrameIndex, + IN PMMPTE PointerPte, + IN BOOLEAN Modified) +{ + PMMMEMORY_LAYOUT MemoryLayout; + XTSTATUS Status; + PMMPFN Pfn; + PMMPTE Pte; + + /* Get the memory layout */ + MemoryLayout = MM::Manager::GetMemoryLayout(); + + /* Point the PFN to its PTE */ + Pfn = &((PMMPFN)MemoryLayout->PfnDatabaseAddress)[PageFrameIndex]; + Pfn->PteAddress = PointerPte; + + /* Check if the page is already mapped and in use */ + if(MM::Paging::PteValid(PointerPte)) + { + /* Clear the original PTE information */ + MM::Paging::SetPte(&Pfn->OriginalPte, 0, MM_PTE_READWRITE | MM_PTE_CACHE_ENABLE); + } + else + { + /* Page is not resident, so save the PTE contents for later use */ + Pfn->OriginalPte = *PointerPte; + } + + /* Initialize the PFN database entry for this page */ + Pfn->u2.ShareCount = 1; + Pfn->u3.e1.Modified = Modified; + Pfn->u3.e1.PageLocation = ActiveAndValid; + Pfn->u3.e2.ReferenceCount = 1; + + /* Get the PDE that maps the page table containing this PTE */ + Pte = MM::Paging::GetPteAddress(PointerPte); + if(!MM::Paging::PteValid(Pte)) + { + /* Check if page table is resident */ + Status = MM::PageFault::CheckPdeForPagedPool(PointerPte); + if(Status != STATUS_SUCCESS) + { + /* Could not make the page table resident, crash system */ + KE::Crash::PanicEx(0x1, + (ULONG_PTR)0x61940, + (ULONG_PTR)PointerPte, + MM::Paging::GetPageFrameNumber(PointerPte), + (ULONG_PTR)MM::Paging::GetPteVirtualAddress(PointerPte)); + } + } + + /* Record the page frame of the page table itself */ + PageFrameIndex = MM::Paging::GetPageFrameNumber(Pte); + Pfn->u4.PteFrame = PageFrameIndex; + + /* Pin the page table in memory by incrementing its PFN share count */ + Pfn = &((PMMPFN)MemoryLayout->PfnDatabaseAddress)[PageFrameIndex]; + Pfn->u2.ShareCount++; +} + /** * Processes a memory descriptor and initializes the corresponding PFN database entries * @@ -385,8 +516,8 @@ MM::Pfn::ProcessMemoryDescriptor(IN PFN_NUMBER BasePage, Pfn->u3.e1.CacheAttribute = PfnNonCached; Pfn->u3.e1.PageLocation = 0; Pfn->u3.e1.PrototypePte = 1; - Pfn->u3.e2.ReferenceCount = 0; Pfn->u3.e1.Rom = 1; + Pfn->u3.e2.ReferenceCount = 0; Pfn->u4.InPageError = 0; Pfn->u4.PteFrame = 0; } @@ -490,3 +621,105 @@ MM::Pfn::ScanMemoryDescriptors(VOID) /* Save a copy of the original free descriptor before it gets modified */ RTL::Memory::CopyMemory(&OriginalFreeDescriptor, FreeDescriptor, sizeof(LOADER_MEMORY_DESCRIPTOR)); } + +/** + * Unlinks a physical page from its corresponding list. + * + * @param PageIndex + * The Page Frame Number (PFN) of the page to unlink. + * + * @param Color + * The color of the page, used to find the correct colored list. + * + * @return This routine returns the PFN of the page that was unlinked. + */ +XTAPI +PFN_NUMBER +MM::Pfn::UnlinkFreePage(IN PFN_NUMBER PageFrameIndex, + IN ULONG Color) +{ + PMMPFN Pfn; + PMMPFNLIST PfnList; + MMPAGELISTS PageList; + ULONG NodeColor; + PMMCOLOR_TABLES ColorTable; + PFN_NUMBER NextPage, PrevPage; + + /* Get the PFN database entry for the target page */ + Pfn = GetPfnEntry(PageFrameIndex); + + /* Identify which list the page belongs to (FreePageList or ZeroedPageList) */ + PfnList = PageLocationList[Pfn->u3.e1.PageLocation]; + PageList = PfnList->ListName; + + /* Update the forward link of the previous page */ + if(Pfn->u2.Blink != MAXULONG_PTR) + { + /* The page is not the head of the list; update the previous page's Flink */ + GetPfnEntry(Pfn->u2.Blink)->u1.Flink = Pfn->u1.Flink; + } + else + { + /* This is the first page in the list; update the list head's Flink */ + PfnList->Flink = Pfn->u1.Flink; + } + + /* Update the backward link of the next page */ + if(Pfn->u1.Flink != MAXULONG_PTR) + { + /* The page is not the tail of the list; update the next page's Blink */ + GetPfnEntry(Pfn->u1.Flink)->u2.Blink = Pfn->u2.Blink; + } + else + { + /* This is the last page in the list; update the list head's Blink */ + PfnList->Blink = Pfn->u2.Blink; + } + + /* Get the first page on the color list */ + ColorTable = MM::Colors::GetFreePages(PageList, Color); + NodeColor = Pfn->u3.e1.PageColor; + PrevPage = Pfn->u4.PteFrame; + NextPage = MM::Paging::GetPte(&Pfn->OriginalPte); + + /* Decrement the count of pages for this specific color and total page count for this list */ + ColorTable->Count--; + PfnList->Total--; + + /* Update the forward link of the previous colored page */ + if(PrevPage != MM_PFN_PTE_FRAME) + { + /* This is not the first page; update the previous page's Flink */ + MM::Paging::SetPte(&GetPfnEntry(PrevPage)->OriginalPte, NextPage); + } + else + { + /* This was the first page; update the color table's Flink */ + ColorTable->Flink = NextPage; + } + + /* Update the backward link of the next colored page */ + if (NextPage != MAXULONG_PTR) + { + /* This is not the last page; update the next page's Blink */ + GetPfnEntry(NextPage)->u4.PteFrame = PrevPage; + } + else + { + /* This was the last page; update the color table's Blink */ + ColorTable->Blink = (PVOID)PrevPage; + } + + /* Clear the list pointers and flags, but preserve the color and cache attributes */ + Pfn->u1.Flink = 0; + Pfn->u2.Blink = 0; + Pfn->u3.e1.CacheAttribute = PfnNotMapped; + Pfn->u3.e1.PageColor = NodeColor; + Pfn->u3.e2.ShortFlags = 0; + + /* Decrement the global count of available pages */ + DecrementAvailablePages(); + + /* Return the page that was just unlinked */ + return PageFrameIndex; +} -- 2.52.0 From 4c7c914a1c779bd10b74e32d326a7b02230426d6 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Mon, 29 Dec 2025 19:10:25 +0100 Subject: [PATCH 076/166] Implement kernel stack allocation logic --- xtoskrnl/includes/mm/kpool.hh | 9 +++-- xtoskrnl/mm/kpool.cc | 68 +++++++++++++++++++++++++++++++---- 2 files changed, 66 insertions(+), 11 deletions(-) diff --git a/xtoskrnl/includes/mm/kpool.hh b/xtoskrnl/includes/mm/kpool.hh index 2e94881..58afda6 100644 --- a/xtoskrnl/includes/mm/kpool.hh +++ b/xtoskrnl/includes/mm/kpool.hh @@ -21,13 +21,12 @@ namespace MM STATIC UCHAR ProcessorStructuresData[MAXIMUM_PROCESSORS][KPROCESSOR_STRUCTURES_SIZE]; public: - STATIC XTAPI XTSTATUS AllocateKernelStack(IN PVOID *Stack, - IN BOOLEAN LargeStack, - IN UCHAR SystemNode); + STATIC XTAPI XTSTATUS AllocateKernelStack(OUT PVOID *Stack, + IN ULONG StackSize); STATIC XTAPI XTSTATUS AllocateProcessorStructures(IN ULONG CpuNumber, - OUT PVOID *StructuresData); + OUT PVOID *StructuresData); STATIC XTAPI VOID FreeKernelStack(IN PVOID Stack, - IN BOOLEAN LargeStack); + IN ULONG StackSize); STATIC XTAPI VOID FreeProcessorStructures(IN PVOID StructuresData); }; } diff --git a/xtoskrnl/mm/kpool.cc b/xtoskrnl/mm/kpool.cc index 190c7da..eb7f228 100644 --- a/xtoskrnl/mm/kpool.cc +++ b/xtoskrnl/mm/kpool.cc @@ -27,12 +27,68 @@ */ XTAPI XTSTATUS -MM::KernelPool::AllocateKernelStack(IN PVOID *Stack, - IN BOOLEAN LargeStack, - IN UCHAR SystemNode) +MM::KernelPool::AllocateKernelStack(OUT PVOID *Stack, + IN ULONG StackSize) { - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; + PFN_COUNT StackPtes, StackPages; + PMMPTE PointerPte, StackPte; + MMPTE TempPte, InvalidPte; + PFN_NUMBER PageFrameIndex; + ULONG Index; + + /* Initialize the output stack pointer to NULLPTR */ + *Stack = NULLPTR; + + /* Convert the requested stack size into a page count */ + StackPtes = SIZE_TO_PAGES(StackSize); + StackPages = StackPtes; + + /* Reserve PTEs for the stack pages, plus a guard page */ + StackPte = MM::Pte::ReserveSystemPtes(StackPtes + 1, SystemPteSpace, 0); + if(!StackPte) + { + /* Failed to reserve PTEs for the new kernel stack */ + return STATUS_INSUFFICIENT_RESOURCES; + } + + /* Set up a template for an invalid PTE */ + MM::Paging::SetPte(&InvalidPte, 0, 0x18); + + /* Set up a template for a valid, writable stack PTE */ + MM::Paging::ClearPte(&TempPte); + MM::Paging::SetPte(&TempPte, 0, MM_PTE_READWRITE | MM_PTE_CACHE_ENABLE); + + /* Acquire the PFN database lock and raise runlevel to DISPATCH_LEVEL */ + KE::RaiseRunLevel RunLevel(DISPATCH_LEVEL); + KE::QueuedSpinLockGuard SpinLock(SystemSpaceLock); + + /* Start iterating from the base of the reserved PTE block */ + PointerPte = StackPte; + + /* Loop through each page of the stack that needs to be allocated */ + for(Index = 0; Index < StackPages; Index++) + { + /* Advance to the next PTE */ + PointerPte = MM::Paging::GetNextPte(PointerPte); + + /* Allocate a physical page and temporarily mark the PTE as invalid */ + PageFrameIndex = MM::Pfn::AllocatePhysicalPage(MM::Colors::GetNextColor()); + *PointerPte = InvalidPte; + + /* Associate the physical page with its corresponding PTE in the PFN database */ + MM::Pfn::LinkPfnToPte(PageFrameIndex, PointerPte, 1); + + /* Make the PTE valid, mapping the virtual address to the physical page */ + MM::Paging::SetPte(&TempPte, PageFrameIndex, 0); + *PointerPte = TempPte; + } + + /* Zero the newly allocated stack memory, skipping the guard page */ + RTL::Memory::ZeroMemory(MM::Paging::GetPteVirtualAddress(MM::Paging::GetNextPte(StackPte)), MM_PAGE_SIZE * StackPtes); + + /* Return a pointer to the top of the new stack */ + *Stack = MM::Paging::GetPteVirtualAddress(MM::Paging::AdvancePte(StackPte, StackPtes + 1)); + return STATUS_SUCCESS; } /** @@ -96,7 +152,7 @@ MM::KernelPool::AllocateProcessorStructures(IN ULONG CpuNumber, XTAPI VOID MM::KernelPool::FreeKernelStack(IN PVOID Stack, - IN BOOLEAN LargeStack) + IN ULONG StackSize) { UNIMPLEMENTED; } -- 2.52.0 From f4c49e2f25a33052afd927d04de327dd5122cd5a Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Mon, 29 Dec 2025 19:14:49 +0100 Subject: [PATCH 077/166] Simplify stack page count calculation --- xtoskrnl/mm/kpool.cc | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/xtoskrnl/mm/kpool.cc b/xtoskrnl/mm/kpool.cc index eb7f228..c120231 100644 --- a/xtoskrnl/mm/kpool.cc +++ b/xtoskrnl/mm/kpool.cc @@ -30,7 +30,7 @@ XTSTATUS MM::KernelPool::AllocateKernelStack(OUT PVOID *Stack, IN ULONG StackSize) { - PFN_COUNT StackPtes, StackPages; + PFN_COUNT StackPages; PMMPTE PointerPte, StackPte; MMPTE TempPte, InvalidPte; PFN_NUMBER PageFrameIndex; @@ -40,11 +40,10 @@ MM::KernelPool::AllocateKernelStack(OUT PVOID *Stack, *Stack = NULLPTR; /* Convert the requested stack size into a page count */ - StackPtes = SIZE_TO_PAGES(StackSize); - StackPages = StackPtes; + StackPages = SIZE_TO_PAGES(StackSize); /* Reserve PTEs for the stack pages, plus a guard page */ - StackPte = MM::Pte::ReserveSystemPtes(StackPtes + 1, SystemPteSpace, 0); + StackPte = MM::Pte::ReserveSystemPtes(StackPages + 1, SystemPteSpace, 0); if(!StackPte) { /* Failed to reserve PTEs for the new kernel stack */ @@ -84,10 +83,10 @@ MM::KernelPool::AllocateKernelStack(OUT PVOID *Stack, } /* Zero the newly allocated stack memory, skipping the guard page */ - RTL::Memory::ZeroMemory(MM::Paging::GetPteVirtualAddress(MM::Paging::GetNextPte(StackPte)), MM_PAGE_SIZE * StackPtes); + RTL::Memory::ZeroMemory(MM::Paging::GetPteVirtualAddress(MM::Paging::GetNextPte(StackPte)), MM_PAGE_SIZE * StackPages); /* Return a pointer to the top of the new stack */ - *Stack = MM::Paging::GetPteVirtualAddress(MM::Paging::AdvancePte(StackPte, StackPtes + 1)); + *Stack = MM::Paging::GetPteVirtualAddress(MM::Paging::AdvancePte(StackPte, StackPages + 1)); return STATUS_SUCCESS; } -- 2.52.0 From d8fc2231405b1eaba49d3de97b21ac4a00c3f188 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Mon, 29 Dec 2025 19:16:13 +0100 Subject: [PATCH 078/166] Adjust thread initialization to match new stack allocator signature --- xtoskrnl/ke/kthread.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xtoskrnl/ke/kthread.cc b/xtoskrnl/ke/kthread.cc index 1e531f4..13755ba 100644 --- a/xtoskrnl/ke/kthread.cc +++ b/xtoskrnl/ke/kthread.cc @@ -152,7 +152,7 @@ KE::KThread::InitializeThread(IN PKPROCESS Process, if(!Stack) { /* Allocate new stack */ - Status = MM::KernelPool::AllocateKernelStack(&Stack, FALSE, 0); + Status = MM::KernelPool::AllocateKernelStack(&Stack, KERNEL_STACK_SIZE); if(Status != STATUS_SUCCESS || !Stack) { /* Stack allocation failed */ -- 2.52.0 From 53116b86a372221a37d90907e2282ec6c3b746c0 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Mon, 29 Dec 2025 19:19:45 +0100 Subject: [PATCH 079/166] Improve formatting --- xtoskrnl/mm/kpool.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/xtoskrnl/mm/kpool.cc b/xtoskrnl/mm/kpool.cc index c120231..e1cd326 100644 --- a/xtoskrnl/mm/kpool.cc +++ b/xtoskrnl/mm/kpool.cc @@ -4,6 +4,7 @@ * FILE: xtoskrnl/mm/kpool.cc * DESCRIPTION: Kernel pool memory management * DEVELOPERS: Rafal Kupiec + * Aiken Harris */ #include @@ -83,7 +84,8 @@ MM::KernelPool::AllocateKernelStack(OUT PVOID *Stack, } /* Zero the newly allocated stack memory, skipping the guard page */ - RTL::Memory::ZeroMemory(MM::Paging::GetPteVirtualAddress(MM::Paging::GetNextPte(StackPte)), MM_PAGE_SIZE * StackPages); + RTL::Memory::ZeroMemory(MM::Paging::GetPteVirtualAddress(MM::Paging::GetNextPte(StackPte)), + MM_PAGE_SIZE * StackPages); /* Return a pointer to the top of the new stack */ *Stack = MM::Paging::GetPteVirtualAddress(MM::Paging::AdvancePte(StackPte, StackPages + 1)); -- 2.52.0 From aced62e790f58501cb6ee2ba78dc288140efef36 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Mon, 29 Dec 2025 19:27:30 +0100 Subject: [PATCH 080/166] Prevent initialization of invisible memory ranges --- xtoskrnl/mm/pfn.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/xtoskrnl/mm/pfn.cc b/xtoskrnl/mm/pfn.cc index 93379f7..ac5d5a0 100644 --- a/xtoskrnl/mm/pfn.cc +++ b/xtoskrnl/mm/pfn.cc @@ -493,6 +493,10 @@ MM::Pfn::ProcessMemoryDescriptor(IN PFN_NUMBER BasePage, LinkFreePage(CurrentPage); } } + else if(MM::Manager::VerifyMemoryTypeInvisible(MemoryType)) + { + /* This memory range should never be used, skip it */ + } else { /* Handle all other (non-free) memory types */ -- 2.52.0 From dbda6bbb291720c449ae5e78542c10e9a20e59c3 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Mon, 29 Dec 2025 23:49:29 +0100 Subject: [PATCH 081/166] Initialize PTE template dynamically to resolve build warnings --- xtoskrnl/includes/mm/amd64/pte.hh | 1 + xtoskrnl/includes/mm/i686/pte.hh | 1 + xtoskrnl/mm/amd64/pte.cc | 14 ++++++++++++++ xtoskrnl/mm/data.cc | 2 +- xtoskrnl/mm/i686/pte.cc | 14 ++++++++++++++ xtoskrnl/mm/mmgr.cc | 3 +++ 6 files changed, 34 insertions(+), 1 deletion(-) diff --git a/xtoskrnl/includes/mm/amd64/pte.hh b/xtoskrnl/includes/mm/amd64/pte.hh index 1c02731..70c7c9d 100644 --- a/xtoskrnl/includes/mm/amd64/pte.hh +++ b/xtoskrnl/includes/mm/amd64/pte.hh @@ -31,6 +31,7 @@ namespace MM STATIC XTAPI PMMPTE GetSystemPteBaseAddress(VOID); STATIC XTAPI PMMPTE GetValidPte(VOID); STATIC XTAPI VOID InitializePageTable(VOID); + STATIC XTAPI VOID InitializePteTemplate(VOID); STATIC XTAPI VOID InitializeSystemPteSpace(VOID); STATIC XTAPI VOID MapP5E(PVOID StartAddress, PVOID EndAddress, diff --git a/xtoskrnl/includes/mm/i686/pte.hh b/xtoskrnl/includes/mm/i686/pte.hh index 0ad0ba5..4576f48 100644 --- a/xtoskrnl/includes/mm/i686/pte.hh +++ b/xtoskrnl/includes/mm/i686/pte.hh @@ -31,6 +31,7 @@ namespace MM STATIC XTAPI PMMPTE GetSystemPteBaseAddress(VOID); STATIC XTAPI PMMPTE GetValidPte(VOID); STATIC XTAPI VOID InitializePageTable(VOID); + STATIC XTAPI VOID InitializePteTemplate(VOID); STATIC XTAPI VOID InitializeSystemPteSpace(VOID); STATIC XTAPI VOID MapPDE(PVOID StartAddress, PVOID EndAddress, diff --git a/xtoskrnl/mm/amd64/pte.cc b/xtoskrnl/mm/amd64/pte.cc index 71fba17..540f40f 100644 --- a/xtoskrnl/mm/amd64/pte.cc +++ b/xtoskrnl/mm/amd64/pte.cc @@ -153,6 +153,20 @@ MM::Pte::InitializePageTable(VOID) MM::Paging::SetPte(MM::Paging::GetPteAddress((PVOID)MemoryLayout->HyperSpaceStart), MM_HYPERSPACE_PAGE_COUNT, 0); } +/** + * Initializes the PTE template. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::Pte::InitializePteTemplate(VOID) +{ + ValidPte = {MM_PTE_VALID|MM_PTE_EXECUTE_READWRITE|MM_PTE_DIRTY|MM_PTE_ACCESSED}; +} + /** * Maps a range of virtual addresses at the P5E (PML5) level. * diff --git a/xtoskrnl/mm/data.cc b/xtoskrnl/mm/data.cc index d775ba4..ead62f1 100644 --- a/xtoskrnl/mm/data.cc +++ b/xtoskrnl/mm/data.cc @@ -104,4 +104,4 @@ PMMPTE MM::Pte::SystemPtesStart[MaximumPtePoolTypes]; ULONG MM::Pte::TotalSystemFreePtes[MaximumPtePoolTypes]; /* Template PTE entry containing standard flags for a valid, present kernel page */ -MMPTE MM::Pte::ValidPte = {MM_PTE_VALID|MM_PTE_EXECUTE_READWRITE|MM_PTE_DIRTY|MM_PTE_ACCESSED}; +MMPTE MM::Pte::ValidPte; diff --git a/xtoskrnl/mm/i686/pte.cc b/xtoskrnl/mm/i686/pte.cc index 60bc935..e46a64f 100644 --- a/xtoskrnl/mm/i686/pte.cc +++ b/xtoskrnl/mm/i686/pte.cc @@ -112,6 +112,20 @@ MM::Pte::InitializePageTable(VOID) MM::Pte::MapPDE(MemoryLayout->SystemSpaceStart, (PVOID)MM_HIGHEST_SYSTEM_ADDRESS, &TemplatePte); } +/** + * Initializes the PTE template. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::Pte::InitializePteTemplate(VOID) +{ + ValidPte = {{MM_PTE_VALID|MM_PTE_EXECUTE_READWRITE|MM_PTE_DIRTY|MM_PTE_ACCESSED}}; +} + /** * Maps a range of virtual addresses at the PPE (Page Directory Pointer Entry) level. * diff --git a/xtoskrnl/mm/mmgr.cc b/xtoskrnl/mm/mmgr.cc index bf00683..50fd8ba 100644 --- a/xtoskrnl/mm/mmgr.cc +++ b/xtoskrnl/mm/mmgr.cc @@ -63,6 +63,9 @@ MM::Manager::InitializeMemoryManager(VOID) /* Initialize memory layout */ InitializeMemoryLayout(); + /* Initialize PTE template */ + MM::Pte::InitializePteTemplate(); + /* Initialize page table */ MM::Pte::InitializePageTable(); -- 2.52.0 From 00702bfb232ee8cc22680fa3a0447f401b81b93c Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Tue, 30 Dec 2025 13:10:32 +0100 Subject: [PATCH 082/166] Remove redundant check for invisible memory regions --- xtoskrnl/mm/pfn.cc | 4 ---- 1 file changed, 4 deletions(-) diff --git a/xtoskrnl/mm/pfn.cc b/xtoskrnl/mm/pfn.cc index ac5d5a0..93379f7 100644 --- a/xtoskrnl/mm/pfn.cc +++ b/xtoskrnl/mm/pfn.cc @@ -493,10 +493,6 @@ MM::Pfn::ProcessMemoryDescriptor(IN PFN_NUMBER BasePage, LinkFreePage(CurrentPage); } } - else if(MM::Manager::VerifyMemoryTypeInvisible(MemoryType)) - { - /* This memory range should never be used, skip it */ - } else { /* Handle all other (non-free) memory types */ -- 2.52.0 From 5ff0cad094dcbd9b25dd3e3cba5d7b205dbfe4fe Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Thu, 1 Jan 2026 16:46:26 +0100 Subject: [PATCH 083/166] Introduce per-page-color modified page lists --- xtoskrnl/includes/mm/colors.hh | 8 +++++--- xtoskrnl/mm/colors.cc | 23 ++++++++++++++++++++--- xtoskrnl/mm/data.cc | 3 +++ 3 files changed, 28 insertions(+), 6 deletions(-) diff --git a/xtoskrnl/includes/mm/colors.hh b/xtoskrnl/includes/mm/colors.hh index d48c3d9..e6e3183 100644 --- a/xtoskrnl/includes/mm/colors.hh +++ b/xtoskrnl/includes/mm/colors.hh @@ -19,6 +19,7 @@ namespace MM { private: STATIC PMMCOLOR_TABLES FreePages[FreePageList + 1]; + STATIC MMPFNLIST ModifiedPages[MM_PAGING_COLORS]; STATIC ULONG PagingColors; STATIC ULONG PagingColorsMask; @@ -26,9 +27,10 @@ namespace MM STATIC XTAPI VOID ComputePageColoring(VOID); STATIC XTAPI PMMCOLOR_TABLES GetFreePages(MMPAGELISTS PageList, ULONG Color); - STATIC XTAPI ULONG GetNextColor(); - STATIC XTAPI ULONG GetPagingColors(); - STATIC XTAPI ULONG GetPagingColorsMask(); + STATIC XTAPI PMMPFNLIST GetModifiedPages(IN ULONG Color); + STATIC XTAPI ULONG GetNextColor(VOID); + STATIC XTAPI ULONG GetPagingColors(VOID); + STATIC XTAPI ULONG GetPagingColorsMask(VOID); STATIC XTAPI VOID InitializeColorTables(VOID); }; } diff --git a/xtoskrnl/mm/colors.cc b/xtoskrnl/mm/colors.cc index 5774785..df39cc8 100644 --- a/xtoskrnl/mm/colors.cc +++ b/xtoskrnl/mm/colors.cc @@ -49,6 +49,23 @@ MM::Colors::GetFreePages(MMPAGELISTS PageList, return &FreePages[PageList][Color]; } +/** + * Retrieves a pointer to the modified pages list for a specific color. + * + * @param Color + * Supplies the specific color index. + * + * @return This routine returns a pointer to the corresponding MMPFNLIST structure. + * + * @since XT 1.0 + */ +XTAPI +PMMPFNLIST +MM::Colors::GetModifiedPages(IN ULONG Color) +{ + return &ModifiedPages[Color]; +} + /** * Retrieves the next available color for page coloring. * @@ -58,7 +75,7 @@ MM::Colors::GetFreePages(MMPAGELISTS PageList, */ XTAPI ULONG -MM::Colors::GetNextColor() +MM::Colors::GetNextColor(VOID) { /* Increment the color counter and wrap it around using the mask */ return ((++PagingColors) & PagingColorsMask); @@ -73,7 +90,7 @@ MM::Colors::GetNextColor() */ XTAPI ULONG -MM::Colors::GetPagingColors() +MM::Colors::GetPagingColors(VOID) { /* Return the total number of page colors */ return PagingColors; @@ -88,7 +105,7 @@ MM::Colors::GetPagingColors() */ XTAPI ULONG -MM::Colors::GetPagingColorsMask() +MM::Colors::GetPagingColorsMask(VOID) { /* Return the mask used for page coloring calculations */ return PagingColorsMask; diff --git a/xtoskrnl/mm/data.cc b/xtoskrnl/mm/data.cc index ead62f1..06bdf9b 100644 --- a/xtoskrnl/mm/data.cc +++ b/xtoskrnl/mm/data.cc @@ -12,6 +12,9 @@ /* Array of free page lists segregated by cache color */ PMMCOLOR_TABLES MM::Colors::FreePages[FreePageList + 1]; +/* Array of modified pages segregated by cache color */ +MMPFNLIST MM::Colors::ModifiedPages[MM_PAGING_COLORS]; + /* Number of supported page colors */ ULONG MM::Colors::PagingColors; -- 2.52.0 From c080f74714b0cb759280e719d6ed7c48af76198d Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Thu, 1 Jan 2026 19:40:10 +0100 Subject: [PATCH 084/166] Introduce helper functions for querying the software prototype and transition bits of PTE --- xtoskrnl/includes/mm/amd64/pagemap.hh | 2 + xtoskrnl/includes/mm/amd64/paging.hh | 2 + xtoskrnl/includes/mm/i686/pagemap.hh | 6 +++ xtoskrnl/includes/mm/i686/paging.hh | 2 + xtoskrnl/mm/amd64/pagemap.cc | 34 +++++++++++++ xtoskrnl/mm/i686/pagemap.cc | 70 ++++++++++++++++++++++++++- xtoskrnl/mm/paging.cc | 34 +++++++++++++ 7 files changed, 149 insertions(+), 1 deletion(-) diff --git a/xtoskrnl/includes/mm/amd64/pagemap.hh b/xtoskrnl/includes/mm/amd64/pagemap.hh index 9cc6d7e..d896ead 100644 --- a/xtoskrnl/includes/mm/amd64/pagemap.hh +++ b/xtoskrnl/includes/mm/amd64/pagemap.hh @@ -44,6 +44,8 @@ namespace MM PMMPTE StartPte); XTAPI ULONG GetPteOffset(IN PVOID Address); XTAPI ULONG GetPteSize(VOID); + XTAPI ULONG GetPteSoftwarePrototype(IN PMMPTE PtePointer); + XTAPI ULONG GetPteSoftwareTransition(IN PMMPTE PtePointer); VIRTUAL XTAPI PVOID GetPteVirtualAddress(IN PMMPTE PtePointer) = 0; XTAPI PMMPXE GetPxeAddress(IN PVOID Address); XTAPI ULONG GetPxeOffset(IN PVOID Address); diff --git a/xtoskrnl/includes/mm/amd64/paging.hh b/xtoskrnl/includes/mm/amd64/paging.hh index efbfe83..c8dc83a 100644 --- a/xtoskrnl/includes/mm/amd64/paging.hh +++ b/xtoskrnl/includes/mm/amd64/paging.hh @@ -41,6 +41,8 @@ namespace MM STATIC XTAPI LONG GetPteDistance(PMMPTE EndPte, PMMPTE StartPte); STATIC XTAPI ULONG GetPteSize(VOID); + STATIC XTAPI ULONG GetPteSoftwarePrototype(IN PMMPTE PtePointer); + STATIC XTAPI ULONG GetPteSoftwareTransition(IN PMMPTE PtePointer); STATIC XTAPI PVOID GetPteVirtualAddress(IN PMMPTE PtePointer); STATIC XTAPI PMMPXE GetPxeAddress(IN PVOID Address); STATIC XTAPI PVOID GetPxeVirtualAddress(IN PMMPXE PxePointer); diff --git a/xtoskrnl/includes/mm/i686/pagemap.hh b/xtoskrnl/includes/mm/i686/pagemap.hh index 30de3b6..1da4aeb 100644 --- a/xtoskrnl/includes/mm/i686/pagemap.hh +++ b/xtoskrnl/includes/mm/i686/pagemap.hh @@ -41,6 +41,8 @@ namespace MM VIRTUAL XTAPI LONG GetPteDistance(PMMPTE EndPte, PMMPTE StartPte) = 0; VIRTUAL XTAPI ULONG GetPteSize(VOID) = 0; + VIRTUAL XTAPI ULONG GetPteSoftwarePrototype(IN PMMPTE PtePointer) = 0; + VIRTUAL XTAPI ULONG GetPteSoftwareTransition(IN PMMPTE PtePointer) = 0; VIRTUAL XTAPI PVOID GetPteVirtualAddress(IN PMMPTE PtePointer) = 0; XTAPI BOOLEAN GetXpaStatus(); VIRTUAL XTAPI VOID InitializePageMapInfo(VOID) = 0; @@ -77,6 +79,8 @@ namespace MM XTAPI LONG GetPteDistance(PMMPTE EndPte, PMMPTE StartPte); XTAPI ULONG GetPteSize(VOID); + XTAPI ULONG GetPteSoftwarePrototype(IN PMMPTE PtePointer); + XTAPI ULONG GetPteSoftwareTransition(IN PMMPTE PtePointer); XTAPI PVOID GetPteVirtualAddress(IN PMMPTE PtePointer); XTAPI VOID InitializePageMapInfo(VOID); XTAPI BOOLEAN PteValid(IN PMMPTE PtePointer); @@ -111,6 +115,8 @@ namespace MM XTAPI LONG GetPteDistance(PMMPTE EndPte, PMMPTE StartPte); XTAPI ULONG GetPteSize(VOID); + XTAPI ULONG GetPteSoftwarePrototype(IN PMMPTE PtePointer); + XTAPI ULONG GetPteSoftwareTransition(IN PMMPTE PtePointer); XTAPI PVOID GetPteVirtualAddress(IN PMMPTE PtePointer); XTAPI VOID InitializePageMapInfo(VOID); XTAPI BOOLEAN PteValid(IN PMMPTE PtePointer); diff --git a/xtoskrnl/includes/mm/i686/paging.hh b/xtoskrnl/includes/mm/i686/paging.hh index 2c06d3c..69e8ced 100644 --- a/xtoskrnl/includes/mm/i686/paging.hh +++ b/xtoskrnl/includes/mm/i686/paging.hh @@ -39,6 +39,8 @@ namespace MM STATIC XTAPI LONG GetPteDistance(PMMPTE EndPte, PMMPTE StartPte); STATIC XTAPI ULONG GetPteSize(VOID); + STATIC XTAPI ULONG GetPteSoftwarePrototype(IN PMMPTE PtePointer); + STATIC XTAPI ULONG GetPteSoftwareTransition(IN PMMPTE PtePointer); STATIC XTAPI PVOID GetPteVirtualAddress(IN PMMPTE PtePointer); STATIC XTAPI BOOLEAN GetXpaStatus(VOID); STATIC XTAPI VOID InitializePageMapSupport(VOID); diff --git a/xtoskrnl/mm/amd64/pagemap.cc b/xtoskrnl/mm/amd64/pagemap.cc index e89b05b..5342d7e 100644 --- a/xtoskrnl/mm/amd64/pagemap.cc +++ b/xtoskrnl/mm/amd64/pagemap.cc @@ -363,6 +363,40 @@ MM::PageMap::GetPteSize(VOID) return sizeof(MMPTE); } +/** + * Gets the software prototype value of the corresponding Page Table Entry. + * + * @param PtePointer + * Specifies the address of the PTE. + * + * @return This routine returns the PTE software prototype value. + * + * @since XT 1.0 + */ +XTAPI +ULONG +MM::PageMap::GetPteSoftwarePrototype(IN PMMPTE PtePointer) +{ + return (ULONG)PtePointer->Software.Prototype; +} + +/** + * Gets the software transition value of the corresponding Page Table Entry. + * + * @param PtePointer + * Specifies the address of the PTE. + * + * @return This routine returns the PTE software transition value. + * + * @since XT 1.0 + */ +XTAPI +ULONG +MM::PageMap::GetPteSoftwareTransition(IN PMMPTE PtePointer) +{ + return (ULONG)PtePointer->Software.Transition; +} + /** * Gets the address of the PXE (Extended Page Entry), that maps given address. * diff --git a/xtoskrnl/mm/i686/pagemap.cc b/xtoskrnl/mm/i686/pagemap.cc index ee66229..2744f5c 100644 --- a/xtoskrnl/mm/i686/pagemap.cc +++ b/xtoskrnl/mm/i686/pagemap.cc @@ -355,6 +355,40 @@ MM::PageMapBasic::GetPteSize(VOID) return sizeof(MMPML2_PTE); } +/** + * Gets the software prototype value of the corresponding Page Table Entry. + * + * @param PtePointer + * Specifies the address of the PTE. + * + * @return This routine returns the PTE software prototype value. + * + * @since XT 1.0 + */ +XTAPI +ULONG +MM::PageMapBasic::GetPteSoftwarePrototype(IN PMMPTE PtePointer) +{ + return (ULONG)PtePointer->Pml2.Software.Prototype; +} + +/** + * Gets the software transition value of the corresponding Page Table Entry. + * + * @param PtePointer + * Specifies the address of the PTE. + * + * @return This routine returns the PTE software transition value. + * + * @since XT 1.0 + */ +XTAPI +ULONG +MM::PageMapBasic::GetPteSoftwareTransition(IN PMMPTE PtePointer) +{ + return (ULONG)PtePointer->Pml2.Software.Transition; +} + /** * Gets the virtual address that is mapped by a given Page Table Entry. * @@ -505,7 +539,7 @@ MM::PageMapBasic::SetPte(IN PMMPTE PtePointer, XTAPI VOID MM::PageMapBasic::SetPte(IN PMMPTE PtePointer, - IN ULONG_PTR Attributes) + IN ULONG_PTR Attributes) { PtePointer->Pml2.Long = Attributes; } @@ -743,6 +777,40 @@ MM::PageMapXpa::GetPteSize(VOID) return sizeof(MMPML3_PTE); } +/** + * Gets the software prototype value of the corresponding Page Table Entry. + * + * @param PtePointer + * Specifies the address of the PTE. + * + * @return This routine returns the PTE software prototype value. + * + * @since XT 1.0 + */ +XTAPI +ULONG +MM::PageMapXpa::GetPteSoftwarePrototype(IN PMMPTE PtePointer) +{ + return (ULONG)PtePointer->Pml3.Software.Prototype; +} + +/** + * Gets the software transition value of the corresponding Page Table Entry. + * + * @param PtePointer + * Specifies the address of the PTE. + * + * @return This routine returns the PTE software transition value. + * + * @since XT 1.0 + */ +XTAPI +ULONG +MM::PageMapXpa::GetPteSoftwareTransition(IN PMMPTE PtePointer) +{ + return (ULONG)PtePointer->Pml3.Software.Transition; +} + /** * Gets the virtual address that is mapped by a given Page Table Entry. * diff --git a/xtoskrnl/mm/paging.cc b/xtoskrnl/mm/paging.cc index 5a9562d..7196951 100644 --- a/xtoskrnl/mm/paging.cc +++ b/xtoskrnl/mm/paging.cc @@ -366,6 +366,40 @@ MM::Paging::GetPteSize(VOID) return PmlRoutines->GetPteSize(); } +/** + * Gets the software prototype value of the corresponding Page Table Entry. + * + * @param PtePointer + * Specifies the address of the PTE. + * + * @return This routine returns the PTE software prototype value. + * + * @since XT 1.0 + */ +XTAPI +ULONG +MM::Paging::GetPteSoftwarePrototype(IN PMMPTE PtePointer) +{ + return PmlRoutines->GetPteSoftwarePrototype(PtePointer); +} + +/** + * Gets the software transition value of the corresponding Page Table Entry. + * + * @param PtePointer + * Specifies the address of the PTE. + * + * @return This routine returns the PTE software transition value. + * + * @since XT 1.0 + */ +XTAPI +ULONG +MM::Paging::GetPteSoftwareTransition(IN PMMPTE PtePointer) +{ + return PmlRoutines->GetPteSoftwareTransition(PtePointer); +} + /** * Gets the virtual address that is mapped by a given Page Table Entry. * -- 2.52.0 From 7bcd78fdf39885ad2851859fd98d4032571858fc Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Thu, 1 Jan 2026 20:40:45 +0100 Subject: [PATCH 085/166] Implement generic PFN list linking function --- xtoskrnl/includes/mm/pfn.hh | 3 + xtoskrnl/mm/data.cc | 9 +- xtoskrnl/mm/pfn.cc | 194 ++++++++++++++++++++++++++++++++++++ 3 files changed, 203 insertions(+), 3 deletions(-) diff --git a/xtoskrnl/includes/mm/pfn.hh b/xtoskrnl/includes/mm/pfn.hh index cd4386e..a0b9c34 100644 --- a/xtoskrnl/includes/mm/pfn.hh +++ b/xtoskrnl/includes/mm/pfn.hh @@ -31,6 +31,7 @@ namespace MM STATIC LOADER_MEMORY_DESCRIPTOR OriginalFreeDescriptor; STATIC PMMPFNLIST PageLocationList[]; STATIC PFN_NUMBER PfnDatabaseSize; + STATIC MMPFNLIST RomPagesList; STATIC MMPFNLIST StandbyPagesList; STATIC MMPFNLIST ZeroedPagesList; @@ -53,6 +54,8 @@ namespace MM STATIC XTAPI VOID IncrementAvailablePages(VOID); STATIC XTAPI VOID InitializePageTablePfns(VOID); STATIC XTAPI VOID LinkFreePage(IN PFN_NUMBER PageFrameIndex); + STATIC XTAPI VOID LinkPage(IN PMMPFNLIST ListHead, + IN PFN_NUMBER PageFrameIndex); STATIC XTAPI VOID LinkPfnForPageTable(IN PFN_NUMBER PageFrameIndex, IN PMMPTE PointerPte); STATIC XTAPI VOID ProcessMemoryDescriptor(IN PFN_NUMBER BasePage, diff --git a/xtoskrnl/mm/data.cc b/xtoskrnl/mm/data.cc index 06bdf9b..b1ca086 100644 --- a/xtoskrnl/mm/data.cc +++ b/xtoskrnl/mm/data.cc @@ -72,9 +72,6 @@ ULONGLONG MM::Pfn::NumberOfPhysicalPages; /* Old biggest free memory descriptor */ LOADER_MEMORY_DESCRIPTOR MM::Pfn::OriginalFreeDescriptor; -/* List containing standby pages (clean, can be reclaimed or repurposed) */ -MMPFNLIST MM::Pfn::StandbyPagesList = {0, StandbyPageList, MAXULONG_PTR, MAXULONG_PTR}; - /* Array of pointers to PFN lists */ PMMPFNLIST MM::Pfn::PageLocationList[] = {&ZeroedPagesList, &FreePagesList, @@ -88,6 +85,12 @@ PMMPFNLIST MM::Pfn::PageLocationList[] = {&ZeroedPagesList, /* Size of the PFN database in pages */ PFN_NUMBER MM::Pfn::PfnDatabaseSize; +/* List containing pages mapped as Read-Only (ROM) */ +MMPFNLIST MM::Pfn::RomPagesList = {0, StandbyPageList, MAXULONG_PTR, MAXULONG_PTR}; + +/* List containing standby pages (clean, can be reclaimed or repurposed) */ +MMPFNLIST MM::Pfn::StandbyPagesList = {0, StandbyPageList, MAXULONG_PTR, MAXULONG_PTR}; + /* List containing free physical pages that have been zeroed out */ MMPFNLIST MM::Pfn::ZeroedPagesList = {0, ZeroedPageList, MAXULONG_PTR, MAXULONG_PTR}; diff --git a/xtoskrnl/mm/pfn.cc b/xtoskrnl/mm/pfn.cc index 93379f7..8fc1e7c 100644 --- a/xtoskrnl/mm/pfn.cc +++ b/xtoskrnl/mm/pfn.cc @@ -326,6 +326,200 @@ MM::Pfn::LinkFreePage(IN PFN_NUMBER PageFrameIndex) IncrementAvailablePages(); } + +/** + * Links a physical page to the appropriate list. + * + * @param ListHead + * Pointer to the list head. + * + * @param PageFrameIndex + * The Page Frame Number (PFN) of the page to link. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::Pfn::LinkPage(IN PMMPFNLIST ListHead, + IN PFN_NUMBER PageFrameIndex) +{ + PMMCOLOR_TABLES ColorHead; + MMPAGELISTS ListName; + PMMPFN PageFrame; + + /* Get the memory layout */ + PMMMEMORY_LAYOUT MemoryLayout = MM::Manager::GetMemoryLayout(); + + /* Get the PFN database entry for the target page */ + PageFrame = &((PMMPFN)MemoryLayout->PfnDatabaseAddress)[PageFrameIndex]; + + /* Get the list name */ + ListName = ListHead->ListName; + + /* Handle pages being linked to the modified or standby lists */ + if(ListName == ModifiedPageList || ListName == StandbyPageList) + { + /* Detect an invalid prototype/transition PTE state */ + if(!MM::Paging::GetPteSoftwarePrototype(&PageFrame->OriginalPte) && + MM::Paging::GetPteSoftwareTransition(&PageFrame->OriginalPte)) + { + /* Crash system due to corrupted PFN/PTE state */ + KE::Crash::PanicEx(0x71, 0x8888, 0, 0, 0); + } + } + + /* Check if the page is ROM */ + if(PageFrame->u3.e1.Rom == 1) + { + /* Link the page to the ROM list */ + ListHead = &RomPagesList; + ListHead->Total++; + + /* Append the page to the end of the ROM list */ + if(ListHead->Blink != MAXULONG_PTR) + { + /* Update the previous tail to point to this page */ + (&((PMMPFN)MemoryLayout->PfnDatabaseAddress)[ListHead->Blink])->u1.Flink = PageFrameIndex; + } + else + { + /* Initialize the list if it was empty */ + ListHead->Flink = PageFrameIndex; + } + + /* Update list tail and PFN linkage */ + ListHead->Blink = PageFrameIndex; + PageFrame->u1.Flink = MAXULONG_PTR; + PageFrame->u2.Blink = ListHead->Blink; + PageFrame->u3.e1.PageLocation = ListName; + + /* ROM pages require no further processing */ + return; + } + + /* Account for the page being inserted into the target list */ + ListHead->Total++; + + /* Redirect modified pages to the per-color modified list */ + if(ListHead == &ModifiedPagesList) + { + /* Select the modified list matching the page color */ + ListHead = MM::Colors::GetModifiedPages(PageFrame->u3.e1.PageColor); + ListHead->Total++; + } + else if((PageFrame->u3.e1.RemovalRequested == 1) && (ListName <= StandbyPageList)) + { + /* Undo the insertion into the current list */ + ListHead->Total--; + + /* Preserve the standby location for removed pages */ + if(ListName == StandbyPageList) + { + /* Keep the page marked as standby */ + PageFrame->u3.e1.PageLocation = StandbyPageList; + } + + /* Mark the page as no longer cache-mapped */ + PageFrame->u3.e1.CacheAttribute = PfnNotMapped; + + /* Move the page to the bad page list */ + ListHead = &BadPagesList; + ListHead->Total++; + ListName = BadPageList; + } + + /* Insert zeroed pages at the head of the list */ + if(ListName == ZeroedPageList) + { + /* Link the page as the new list head */ + ListHead->Flink = PageFrameIndex; + + /* Initialize PFN forward and backward links */ + PageFrame->u1.Flink = ListHead->Flink; + PageFrame->u2.Blink = MAXULONG_PTR; + + /* Update the previous head if it exists */ + if(ListHead->Flink != MAXULONG_PTR) + { + /* Fix up the backward link of the old head */ + (&((PMMPFN)MemoryLayout->PfnDatabaseAddress)[ListHead->Flink])->u2.Blink = PageFrameIndex; + } + else + { + /* Set the tail if the list was empty */ + ListHead->Blink = PageFrameIndex; + } + } + else + { + /* Append the page to the tail of the list */ + if(ListHead->Blink != MAXULONG_PTR) + { + /* Link the current tail to the new page */ + (&((PMMPFN)MemoryLayout->PfnDatabaseAddress)[ListHead->Blink])->u1.Flink = PageFrameIndex; + } + else + { + /* Initialize the list if it was empty */ + ListHead->Flink = PageFrameIndex; + } + + /* Update list tail */ + ListHead->Blink = PageFrameIndex; + + /* Terminate PFN forward link and set backward link */ + PageFrame->u1.Flink = MAXULONG_PTR; + PageFrame->u2.Blink = ListHead->Blink; + } + + /* Record the page’s current location */ + PageFrame->u3.e1.PageLocation = ListName; + + /* Handle pages that contribute to the available page count */ + if(ListName <= StandbyPageList) + { + /* Increment the system-wide available page counter */ + MM::Pfn::IncrementAvailablePages(); + + /* Select the free list matching the page color */ + ColorHead = MM::Colors::GetFreePages(ZeroedPageList, PageFrameIndex & MM::Colors::GetPagingColorsMask()); + + /* Store the color list linkage in the original PTE */ + MM::Paging::SetPte(&PageFrame->OriginalPte, ColorHead->Flink); + PageFrame->u4.PteFrame = MM_PFN_PTE_FRAME; + + /* Insert the page into the color free list */ + ColorHead->Flink = PageFrameIndex; + + /* Update the previous head or initialize the tail */ + if(ColorHead->Flink != MAXULONG_PTR) + { + /* Fix up the PTE frame of the previous entry */ + (&((PMMPFN)MemoryLayout->PfnDatabaseAddress)[ColorHead->Flink])->u4.PteFrame = PageFrameIndex; + } + else + { + /* Set the tail for an empty color list */ + ColorHead->Blink = (PVOID)PageFrame; + } + + /* Increment the color list page count */ + ColorHead->Count++; + } + else if(ListName == ModifiedPageList) + { + /* Modified page insertion logic not implemented yet */ + UNIMPLEMENTED; + } + else if(ListName == ModifiedReadOnlyPageList) + { + /* Modified read-only page handling not implemented yet */ + UNIMPLEMENTED; + } +} + /** * Initializes the PFN database entry for a physical page that is used as a page table. * -- 2.52.0 From f653b9f79c560e0af5a924cf2b7a1bd9f5f0f37a Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Thu, 1 Jan 2026 20:51:30 +0100 Subject: [PATCH 086/166] Properly handle bad physical pages --- xtoskrnl/mm/pfn.cc | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/xtoskrnl/mm/pfn.cc b/xtoskrnl/mm/pfn.cc index 8fc1e7c..dfc77e7 100644 --- a/xtoskrnl/mm/pfn.cc +++ b/xtoskrnl/mm/pfn.cc @@ -260,6 +260,9 @@ MM::Pfn::LinkFreePage(IN PFN_NUMBER PageFrameIndex) /* Update cache attribute to not mapped */ PfnEntry->u3.e1.CacheAttribute = PfnNotMapped; + /* Insert the page into the bad page list instead */ + LinkPage(&BadPagesList, PageFrameIndex); + /* Do not add it to the free list */ return; } @@ -693,8 +696,8 @@ MM::Pfn::ProcessMemoryDescriptor(IN PFN_NUMBER BasePage, switch(MemoryType) { case LoaderBad: - /* This memory is marked as bad and should not be used */ - UNIMPLEMENTED; + /* This memory is marked as bad and should not be used, add it to the bad pages list */ + LinkPage(&BadPagesList, BasePage); break; case LoaderXIPRom: /* This memory range contains Read-Only Memory (ROM) */ -- 2.52.0 From 0159262ee05b5a38a1a737b6741e016800a1e8bd Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Thu, 1 Jan 2026 20:59:31 +0100 Subject: [PATCH 087/166] Add explicit default initialization for MM::Colors::ModifiedPages list --- xtoskrnl/mm/data.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xtoskrnl/mm/data.cc b/xtoskrnl/mm/data.cc index b1ca086..be3c853 100644 --- a/xtoskrnl/mm/data.cc +++ b/xtoskrnl/mm/data.cc @@ -13,7 +13,7 @@ PMMCOLOR_TABLES MM::Colors::FreePages[FreePageList + 1]; /* Array of modified pages segregated by cache color */ -MMPFNLIST MM::Colors::ModifiedPages[MM_PAGING_COLORS]; +MMPFNLIST MM::Colors::ModifiedPages[MM_PAGING_COLORS] = {{0, ModifiedPageList, MAXULONG_PTR, MAXULONG_PTR}}; /* Number of supported page colors */ ULONG MM::Colors::PagingColors; -- 2.52.0 From cc76ea40eebef8e4e7ee03c7faedbc0b37a256b2 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Sat, 3 Jan 2026 00:41:56 +0100 Subject: [PATCH 088/166] Add support for transitioning PTE to invalid state --- xtoskrnl/includes/mm/amd64/pagemap.hh | 3 + xtoskrnl/includes/mm/amd64/paging.hh | 3 + xtoskrnl/includes/mm/i686/pagemap.hh | 9 +++ xtoskrnl/includes/mm/i686/paging.hh | 3 + xtoskrnl/mm/amd64/pagemap.cc | 51 +++++++++++++ xtoskrnl/mm/i686/pagemap.cc | 102 ++++++++++++++++++++++++++ xtoskrnl/mm/paging.cc | 42 +++++++++++ 7 files changed, 213 insertions(+) diff --git a/xtoskrnl/includes/mm/amd64/pagemap.hh b/xtoskrnl/includes/mm/amd64/pagemap.hh index d896ead..c92a8ee 100644 --- a/xtoskrnl/includes/mm/amd64/pagemap.hh +++ b/xtoskrnl/includes/mm/amd64/pagemap.hh @@ -44,6 +44,7 @@ namespace MM PMMPTE StartPte); XTAPI ULONG GetPteOffset(IN PVOID Address); XTAPI ULONG GetPteSize(VOID); + XTAPI ULONG GetPteSoftwareProtection(IN PMMPTE PtePointer); XTAPI ULONG GetPteSoftwarePrototype(IN PMMPTE PtePointer); XTAPI ULONG GetPteSoftwareTransition(IN PMMPTE PtePointer); VIRTUAL XTAPI PVOID GetPteVirtualAddress(IN PMMPTE PtePointer) = 0; @@ -65,6 +66,8 @@ namespace MM XTAPI VOID SetPteCaching(IN PMMPTE PtePointer, IN BOOLEAN CacheDisable, IN BOOLEAN WriteThrough); + XTAPI VOID TransitionPte(IN PMMPTE PointerPte, + IN ULONG_PTR Protection); XTAPI VOID WritePte(IN PMMPTE Pte, IN MMPTE Value); } PAGEMAP, *PPAGEMAP; diff --git a/xtoskrnl/includes/mm/amd64/paging.hh b/xtoskrnl/includes/mm/amd64/paging.hh index c8dc83a..a15d64b 100644 --- a/xtoskrnl/includes/mm/amd64/paging.hh +++ b/xtoskrnl/includes/mm/amd64/paging.hh @@ -41,6 +41,7 @@ namespace MM STATIC XTAPI LONG GetPteDistance(PMMPTE EndPte, PMMPTE StartPte); STATIC XTAPI ULONG GetPteSize(VOID); + STATIC XTAPI ULONG GetPteSoftwareProtection(IN PMMPTE PtePointer); STATIC XTAPI ULONG GetPteSoftwarePrototype(IN PMMPTE PtePointer); STATIC XTAPI ULONG GetPteSoftwareTransition(IN PMMPTE PtePointer); STATIC XTAPI PVOID GetPteVirtualAddress(IN PMMPTE PtePointer); @@ -63,6 +64,8 @@ namespace MM IN BOOLEAN WriteThrough); STATIC XTAPI VOID WritePte(IN PMMPTE Pte, IN MMPTE Value); + STATIC XTAPI VOID TransitionPte(IN PMMPTE PointerPte, + IN ULONG_PTR Protection); STATIC XTFASTCALL VOID ZeroPages(IN PVOID Address, IN ULONG Size); diff --git a/xtoskrnl/includes/mm/i686/pagemap.hh b/xtoskrnl/includes/mm/i686/pagemap.hh index 1da4aeb..6db0cb7 100644 --- a/xtoskrnl/includes/mm/i686/pagemap.hh +++ b/xtoskrnl/includes/mm/i686/pagemap.hh @@ -41,6 +41,7 @@ namespace MM VIRTUAL XTAPI LONG GetPteDistance(PMMPTE EndPte, PMMPTE StartPte) = 0; VIRTUAL XTAPI ULONG GetPteSize(VOID) = 0; + VIRTUAL XTAPI ULONG GetPteSoftwareProtection(IN PMMPTE PtePointer) = 0; VIRTUAL XTAPI ULONG GetPteSoftwarePrototype(IN PMMPTE PtePointer) = 0; VIRTUAL XTAPI ULONG GetPteSoftwareTransition(IN PMMPTE PtePointer) = 0; VIRTUAL XTAPI PVOID GetPteVirtualAddress(IN PMMPTE PtePointer) = 0; @@ -59,6 +60,8 @@ namespace MM VIRTUAL XTAPI VOID SetPteCaching(IN PMMPTE PtePointer, IN BOOLEAN CacheDisable, IN BOOLEAN WriteThrough) = 0; + VIRTUAL XTAPI VOID TransitionPte(IN PMMPTE PointerPte, + IN ULONG_PTR Protection) = 0; VIRTUAL XTAPI VOID WritePte(IN PMMPTE Pte, IN MMPTE Value) = 0; @@ -79,6 +82,7 @@ namespace MM XTAPI LONG GetPteDistance(PMMPTE EndPte, PMMPTE StartPte); XTAPI ULONG GetPteSize(VOID); + XTAPI ULONG GetPteSoftwareProtection(IN PMMPTE PtePointer); XTAPI ULONG GetPteSoftwarePrototype(IN PMMPTE PtePointer); XTAPI ULONG GetPteSoftwareTransition(IN PMMPTE PtePointer); XTAPI PVOID GetPteVirtualAddress(IN PMMPTE PtePointer); @@ -96,6 +100,8 @@ namespace MM XTAPI VOID SetPteCaching(IN PMMPTE PtePointer, IN BOOLEAN CacheDisable, IN BOOLEAN WriteThrough); + XTAPI VOID TransitionPte(IN PMMPTE PointerPte, + IN ULONG_PTR Protection); XTAPI VOID WritePte(IN PMMPTE Pte, IN MMPTE Value); }; @@ -115,6 +121,7 @@ namespace MM XTAPI LONG GetPteDistance(PMMPTE EndPte, PMMPTE StartPte); XTAPI ULONG GetPteSize(VOID); + XTAPI ULONG GetPteSoftwareProtection(IN PMMPTE PtePointer); XTAPI ULONG GetPteSoftwarePrototype(IN PMMPTE PtePointer); XTAPI ULONG GetPteSoftwareTransition(IN PMMPTE PtePointer); XTAPI PVOID GetPteVirtualAddress(IN PMMPTE PtePointer); @@ -132,6 +139,8 @@ namespace MM XTAPI VOID SetPteCaching(IN PMMPTE PtePointer, IN BOOLEAN CacheDisable, IN BOOLEAN WriteThrough); + XTAPI VOID TransitionPte(IN PMMPTE PointerPte, + IN ULONG_PTR Protection); XTAPI VOID WritePte(IN PMMPTE Pte, IN MMPTE Value); }; diff --git a/xtoskrnl/includes/mm/i686/paging.hh b/xtoskrnl/includes/mm/i686/paging.hh index 69e8ced..18c0964 100644 --- a/xtoskrnl/includes/mm/i686/paging.hh +++ b/xtoskrnl/includes/mm/i686/paging.hh @@ -39,6 +39,7 @@ namespace MM STATIC XTAPI LONG GetPteDistance(PMMPTE EndPte, PMMPTE StartPte); STATIC XTAPI ULONG GetPteSize(VOID); + STATIC XTAPI ULONG GetPteSoftwareProtection(IN PMMPTE PtePointer); STATIC XTAPI ULONG GetPteSoftwarePrototype(IN PMMPTE PtePointer); STATIC XTAPI ULONG GetPteSoftwareTransition(IN PMMPTE PtePointer); STATIC XTAPI PVOID GetPteVirtualAddress(IN PMMPTE PtePointer); @@ -59,6 +60,8 @@ namespace MM IN BOOLEAN WriteThrough); STATIC XTAPI VOID WritePte(IN PMMPTE Pte, IN MMPTE Value); + STATIC XTAPI VOID TransitionPte(IN PMMPTE PointerPte, + IN ULONG_PTR Protection); STATIC XTFASTCALL VOID ZeroPages(IN PVOID Address, IN ULONG Size); diff --git a/xtoskrnl/mm/amd64/pagemap.cc b/xtoskrnl/mm/amd64/pagemap.cc index 5342d7e..313e176 100644 --- a/xtoskrnl/mm/amd64/pagemap.cc +++ b/xtoskrnl/mm/amd64/pagemap.cc @@ -363,6 +363,24 @@ MM::PageMap::GetPteSize(VOID) return sizeof(MMPTE); } +/** + * Gets the software protection value of the corresponding Page Table Entry. + * + * @param PtePointer + * Specifies the address of the PTE. + * + * @return This routine returns the PTE software protection value. + * + * @since XT 1.0 + */ +XTAPI +ULONG +MM::PageMap::GetPteSoftwareProtection(IN PMMPTE PtePointer) +{ + /* Return PTE software protection value */ + return (ULONG)PtePointer->Software.Protection; +} + /** * Gets the software prototype value of the corresponding Page Table Entry. * @@ -377,6 +395,7 @@ XTAPI ULONG MM::PageMap::GetPteSoftwarePrototype(IN PMMPTE PtePointer) { + /* Return PTE software prototype value */ return (ULONG)PtePointer->Software.Prototype; } @@ -394,6 +413,7 @@ XTAPI ULONG MM::PageMap::GetPteSoftwareTransition(IN PMMPTE PtePointer) { + /* Return PTE software transition value */ return (ULONG)PtePointer->Software.Transition; } @@ -588,6 +608,37 @@ MM::PageMap::SetPteCaching(IN PMMPTE PtePointer, PtePointer->Hardware.WriteThrough = WriteThrough; } +/** + * Transitions a Page Table Entry (PTE) to invalid state + * + * @param PointerPte + * Pointer to the page table entry (PTE) to transition. + * + * @param Protection + * Specifies the protection attribute to apply to the PTE. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::PageMap::TransitionPte(IN PMMPTE PointerPte, + IN ULONG_PTR Protection) +{ + MMPTE TempPte; + + /* Set transition PTE */ + TempPte = *PointerPte; + TempPte.Software.Protection = Protection; + TempPte.Software.Prototype = 0; + TempPte.Software.Transition = 1; + TempPte.Software.Valid = 0; + + /* Write PTE value */ + *PointerPte = TempPte; +} + /** * Writes a Page Table Entry (PTE) with the specified value. * diff --git a/xtoskrnl/mm/i686/pagemap.cc b/xtoskrnl/mm/i686/pagemap.cc index 2744f5c..2473319 100644 --- a/xtoskrnl/mm/i686/pagemap.cc +++ b/xtoskrnl/mm/i686/pagemap.cc @@ -355,6 +355,24 @@ MM::PageMapBasic::GetPteSize(VOID) return sizeof(MMPML2_PTE); } +/** + * Gets the software protection value of the corresponding Page Table Entry. + * + * @param PtePointer + * Specifies the address of the PTE. + * + * @return This routine returns the PTE software protection value. + * + * @since XT 1.0 + */ +XTAPI +ULONG +MM::PageMapBasic::GetPteSoftwareProtection(IN PMMPTE PtePointer) +{ + /* Return PTE software protection value */ + return (ULONG)PtePointer->Pml2.Software.Protection; +} + /** * Gets the software prototype value of the corresponding Page Table Entry. * @@ -369,6 +387,7 @@ XTAPI ULONG MM::PageMapBasic::GetPteSoftwarePrototype(IN PMMPTE PtePointer) { + /* Return PTE software prototype value */ return (ULONG)PtePointer->Pml2.Software.Prototype; } @@ -386,6 +405,7 @@ XTAPI ULONG MM::PageMapBasic::GetPteSoftwareTransition(IN PMMPTE PtePointer) { + /* Return PTE software transition value */ return (ULONG)PtePointer->Pml2.Software.Transition; } @@ -571,6 +591,37 @@ MM::PageMapBasic::SetPteCaching(IN PMMPTE PtePointer, PtePointer->Pml2.Hardware.WriteThrough = WriteThrough; } +/** + * Transitions a Page Table Entry (PTE) to invalid state + * + * @param PointerPte + * Pointer to the page table entry (PTE) to transition. + * + * @param Protection + * Specifies the protection attribute to apply to the PTE. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::PageMapBasic::TransitionPte(IN PMMPTE PointerPte, + IN ULONG_PTR Protection) +{ + MMPTE TempPte; + + /* Set transition PTE */ + TempPte = *PointerPte; + TempPte.Pml2.Software.Protection = Protection; + TempPte.Pml2.Software.Prototype = 0; + TempPte.Pml2.Software.Transition = 1; + TempPte.Pml2.Software.Valid = 0; + + /* Write PTE value */ + *PointerPte = TempPte; +} + /** * Writes a PML2 page table entry (PTE) with the specified value. * @@ -777,6 +828,24 @@ MM::PageMapXpa::GetPteSize(VOID) return sizeof(MMPML3_PTE); } +/** + * Gets the software protection value of the corresponding Page Table Entry. + * + * @param PtePointer + * Specifies the address of the PTE. + * + * @return This routine returns the PTE software protection value. + * + * @since XT 1.0 + */ +XTAPI +ULONG +MM::PageMapXpa::GetPteSoftwareProtection(IN PMMPTE PtePointer) +{ + /* Return PTE software protection value */ + return (ULONG)PtePointer->Pml3.Software.Protection; +} + /** * Gets the software prototype value of the corresponding Page Table Entry. * @@ -791,6 +860,7 @@ XTAPI ULONG MM::PageMapXpa::GetPteSoftwarePrototype(IN PMMPTE PtePointer) { + /* Return PTE software prototype value */ return (ULONG)PtePointer->Pml3.Software.Prototype; } @@ -808,6 +878,7 @@ XTAPI ULONG MM::PageMapXpa::GetPteSoftwareTransition(IN PMMPTE PtePointer) { + /* Return PTE software transition value */ return (ULONG)PtePointer->Pml3.Software.Transition; } @@ -992,6 +1063,37 @@ MM::PageMapXpa::SetPteCaching(IN PMMPTE PtePointer, PtePointer->Pml3.Hardware.WriteThrough = WriteThrough; } +/** + * Transitions a Page Table Entry (PTE) to invalid state + * + * @param PointerPte + * Pointer to the page table entry (PTE) to transition. + * + * @param Protection + * Specifies the protection attribute to apply to the PTE. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::PageMapXpa::TransitionPte(IN PMMPTE PointerPte, + IN ULONG_PTR Protection) +{ + MMPTE TempPte; + + /* Set transition PTE */ + TempPte = *PointerPte; + TempPte.Pml3.Software.Protection = Protection; + TempPte.Pml3.Software.Prototype = 0; + TempPte.Pml3.Software.Transition = 1; + TempPte.Pml3.Software.Valid = 0; + + /* Write PTE value */ + *PointerPte = TempPte; +} + /** * Writes a PML3 page table entry (PTE) with the specified value. * diff --git a/xtoskrnl/mm/paging.cc b/xtoskrnl/mm/paging.cc index 7196951..34cde8e 100644 --- a/xtoskrnl/mm/paging.cc +++ b/xtoskrnl/mm/paging.cc @@ -366,6 +366,24 @@ MM::Paging::GetPteSize(VOID) return PmlRoutines->GetPteSize(); } +/** + * Gets the software protection value of the corresponding Page Table Entry. + * + * @param PtePointer + * Specifies the address of the PTE. + * + * @return This routine returns the PTE software protection value. + * + * @since XT 1.0 + */ +XTAPI +ULONG +MM::Paging::GetPteSoftwareProtection(IN PMMPTE PtePointer) +{ + /* Return PTE software protection value */ + return PmlRoutines->GetPteSoftwareProtection(PtePointer); +} + /** * Gets the software prototype value of the corresponding Page Table Entry. * @@ -380,6 +398,7 @@ XTAPI ULONG MM::Paging::GetPteSoftwarePrototype(IN PMMPTE PtePointer) { + /* Return PTE software prototype value */ return PmlRoutines->GetPteSoftwarePrototype(PtePointer); } @@ -397,6 +416,7 @@ XTAPI ULONG MM::Paging::GetPteSoftwareTransition(IN PMMPTE PtePointer) { + /* Return PTE software transition value */ return PmlRoutines->GetPteSoftwareTransition(PtePointer); } @@ -594,6 +614,28 @@ MM::Paging::SetPteCaching(IN PMMPTE PtePointer, PmlRoutines->SetPteCaching(PtePointer, CacheDisable, WriteThrough); } +/** + * Transitions a Page Table Entry (PTE) to invalid state + * + * @param PointerPte + * Pointer to the page table entry (PTE) to transition. + * + * @param Protection + * Specifies the protection attribute to apply to the PTE. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::Paging::TransitionPte(IN PMMPTE PointerPte, + IN ULONG_PTR Protection) +{ + /* Transition PTE */ + PmlRoutines->TransitionPte(PointerPte, Protection); +} + /** * Writes a Page Table Entry (PTE) with the specified value. * -- 2.52.0 From 329143b4f6f9b63ac3915be7e3885b606a774211 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Sat, 3 Jan 2026 21:03:14 +0100 Subject: [PATCH 089/166] Abstract PTE list terminator into paging layer --- xtoskrnl/includes/mm/amd64/pagemap.hh | 1 + xtoskrnl/includes/mm/amd64/paging.hh | 1 + xtoskrnl/includes/mm/i686/pagemap.hh | 3 +++ xtoskrnl/includes/mm/i686/paging.hh | 1 + xtoskrnl/mm/amd64/pagemap.cc | 15 ++++++++++++++ xtoskrnl/mm/i686/pagemap.cc | 30 +++++++++++++++++++++++++++ xtoskrnl/mm/paging.cc | 15 ++++++++++++++ 7 files changed, 66 insertions(+) diff --git a/xtoskrnl/includes/mm/amd64/pagemap.hh b/xtoskrnl/includes/mm/amd64/pagemap.hh index c92a8ee..2a3eb9e 100644 --- a/xtoskrnl/includes/mm/amd64/pagemap.hh +++ b/xtoskrnl/includes/mm/amd64/pagemap.hh @@ -42,6 +42,7 @@ namespace MM XTAPI PMMPTE GetPteAddress(IN PVOID Address); XTAPI LONG GetPteDistance(PMMPTE EndPte, PMMPTE StartPte); + XTAPI ULONG_PTR GetPteListTerminator(VOID); XTAPI ULONG GetPteOffset(IN PVOID Address); XTAPI ULONG GetPteSize(VOID); XTAPI ULONG GetPteSoftwareProtection(IN PMMPTE PtePointer); diff --git a/xtoskrnl/includes/mm/amd64/paging.hh b/xtoskrnl/includes/mm/amd64/paging.hh index a15d64b..dd3cf29 100644 --- a/xtoskrnl/includes/mm/amd64/paging.hh +++ b/xtoskrnl/includes/mm/amd64/paging.hh @@ -40,6 +40,7 @@ namespace MM STATIC XTAPI PMMPTE GetPteAddress(IN PVOID Address); STATIC XTAPI LONG GetPteDistance(PMMPTE EndPte, PMMPTE StartPte); + STATIC XTAPI ULONG_PTR GetPteListTerminator(VOID); STATIC XTAPI ULONG GetPteSize(VOID); STATIC XTAPI ULONG GetPteSoftwareProtection(IN PMMPTE PtePointer); STATIC XTAPI ULONG GetPteSoftwarePrototype(IN PMMPTE PtePointer); diff --git a/xtoskrnl/includes/mm/i686/pagemap.hh b/xtoskrnl/includes/mm/i686/pagemap.hh index 6db0cb7..b014357 100644 --- a/xtoskrnl/includes/mm/i686/pagemap.hh +++ b/xtoskrnl/includes/mm/i686/pagemap.hh @@ -40,6 +40,7 @@ namespace MM XTAPI ULONG GetPteOffset(IN PVOID Address); VIRTUAL XTAPI LONG GetPteDistance(PMMPTE EndPte, PMMPTE StartPte) = 0; + VIRTUAL XTAPI ULONG_PTR GetPteListTerminator(VOID) = 0; VIRTUAL XTAPI ULONG GetPteSize(VOID) = 0; VIRTUAL XTAPI ULONG GetPteSoftwareProtection(IN PMMPTE PtePointer) = 0; VIRTUAL XTAPI ULONG GetPteSoftwarePrototype(IN PMMPTE PtePointer) = 0; @@ -81,6 +82,7 @@ namespace MM XTAPI ULONG_PTR GetPte(IN PMMPTE PtePointer); XTAPI LONG GetPteDistance(PMMPTE EndPte, PMMPTE StartPte); + XTAPI ULONG_PTR GetPteListTerminator(VOID); XTAPI ULONG GetPteSize(VOID); XTAPI ULONG GetPteSoftwareProtection(IN PMMPTE PtePointer); XTAPI ULONG GetPteSoftwarePrototype(IN PMMPTE PtePointer); @@ -120,6 +122,7 @@ namespace MM XTAPI ULONG_PTR GetPte(IN PMMPTE PtePointer); XTAPI LONG GetPteDistance(PMMPTE EndPte, PMMPTE StartPte); + XTAPI ULONG_PTR GetPteListTerminator(VOID); XTAPI ULONG GetPteSize(VOID); XTAPI ULONG GetPteSoftwareProtection(IN PMMPTE PtePointer); XTAPI ULONG GetPteSoftwarePrototype(IN PMMPTE PtePointer); diff --git a/xtoskrnl/includes/mm/i686/paging.hh b/xtoskrnl/includes/mm/i686/paging.hh index 18c0964..54c77cc 100644 --- a/xtoskrnl/includes/mm/i686/paging.hh +++ b/xtoskrnl/includes/mm/i686/paging.hh @@ -38,6 +38,7 @@ namespace MM STATIC XTAPI PMMPTE GetPteAddress(IN PVOID Address); STATIC XTAPI LONG GetPteDistance(PMMPTE EndPte, PMMPTE StartPte); + STATIC XTAPI ULONG_PTR GetPteListTerminator(VOID); STATIC XTAPI ULONG GetPteSize(VOID); STATIC XTAPI ULONG GetPteSoftwareProtection(IN PMMPTE PtePointer); STATIC XTAPI ULONG GetPteSoftwarePrototype(IN PMMPTE PtePointer); diff --git a/xtoskrnl/mm/amd64/pagemap.cc b/xtoskrnl/mm/amd64/pagemap.cc index 313e176..9e6454e 100644 --- a/xtoskrnl/mm/amd64/pagemap.cc +++ b/xtoskrnl/mm/amd64/pagemap.cc @@ -330,6 +330,21 @@ MM::PageMap::GetPteDistance(PMMPTE EndPte, return ((ULONG_PTR)EndPte - (ULONG_PTR)StartPte) / sizeof(MMPTE); } +/** + * Gets the terminator value for a PTE list. + * + * @return This routine returns the terminator value for a PTE list. + * + * @since XT 1.0 + */ +XTAPI +ULONG_PTR +MM::PageMap::GetPteListTerminator(VOID) +{ + /* Return PTE list terminator value */ + return 0xFFFFFFFF; +} + /** * Gets the Offset of the PTE (Page Table Entry), that maps given address. * diff --git a/xtoskrnl/mm/i686/pagemap.cc b/xtoskrnl/mm/i686/pagemap.cc index 2473319..6551fd3 100644 --- a/xtoskrnl/mm/i686/pagemap.cc +++ b/xtoskrnl/mm/i686/pagemap.cc @@ -340,6 +340,21 @@ MM::PageMapBasic::GetPteDistance(PMMPTE EndPte, return ((ULONG_PTR)EndPte - (ULONG_PTR)StartPte) / sizeof(MMPML2_PTE); } +/** + * Gets the terminator value for a PTE list (PML2). + * + * @return This routine returns the terminator value for a PTE list. + * + * @since XT 1.0 + */ +XTAPI +ULONG_PTR +MM::PageMapBasic::GetPteListTerminator(VOID) +{ + /* Return PTE list terminator value for PML2 */ + return 0xFFFFF; +} + /** * Gets the size of a PTE for basic paging (PML2). * @@ -813,6 +828,21 @@ MM::PageMapXpa::GetPteDistance(PMMPTE EndPte, return ((ULONG_PTR)EndPte - (ULONG_PTR)StartPte) / sizeof(MMPML3_PTE); } +/** + * Gets the terminator value for a PTE list (PML3). + * + * @return This routine returns the terminator value for a PTE list. + * + * @since XT 1.0 + */ +XTAPI +ULONG_PTR +MM::PageMapXpa::GetPteListTerminator(VOID) +{ + /* Return PTE list terminator value for PML3 */ + return 0xFFFFFFFF; +} + /** * Gets the size of a PTE for XPA paging (PML3). * diff --git a/xtoskrnl/mm/paging.cc b/xtoskrnl/mm/paging.cc index 34cde8e..b22fe38 100644 --- a/xtoskrnl/mm/paging.cc +++ b/xtoskrnl/mm/paging.cc @@ -351,6 +351,21 @@ MM::Paging::GetPteDistance(PMMPTE EndPte, return PmlRoutines->GetPteDistance(EndPte, StartPte); } +/** + * Gets the terminator value for a PTE list. + * + * @return This routine returns the terminator value for a PTE list. + * + * @since XT 1.0 + */ +XTAPI +ULONG_PTR +MM::Paging::GetPteListTerminator(VOID) +{ + /* Return PTE list terminator value */ + return PmlRoutines->GetPteListTerminator(); +} + /** * Gets the size of a PTE. * -- 2.52.0 From 5e5b4a83929c551d4cab4ea660a85028bb420486 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Sat, 3 Jan 2026 21:11:29 +0100 Subject: [PATCH 090/166] Initialize system PTEs with arch-specific list terminator --- xtoskrnl/includes/mm/amd64/pte.hh | 3 ++- xtoskrnl/includes/mm/i686/pte.hh | 3 ++- xtoskrnl/mm/amd64/pte.cc | 8 ++++++-- xtoskrnl/mm/data.cc | 3 +++ xtoskrnl/mm/i686/pte.cc | 8 ++++++-- xtoskrnl/mm/mmgr.cc | 2 +- 6 files changed, 20 insertions(+), 7 deletions(-) diff --git a/xtoskrnl/includes/mm/amd64/pte.hh b/xtoskrnl/includes/mm/amd64/pte.hh index 70c7c9d..d07ac04 100644 --- a/xtoskrnl/includes/mm/amd64/pte.hh +++ b/xtoskrnl/includes/mm/amd64/pte.hh @@ -19,6 +19,7 @@ namespace MM { private: STATIC MMPTE FirstSystemFreePte[MaximumPtePoolTypes]; + STATIC ULONG_PTR ListTerminator; STATIC PMMPTE SystemPteBase; STATIC PMMPTE SystemPtesEnd[MaximumPtePoolTypes]; STATIC PMMPTE SystemPtesStart[MaximumPtePoolTypes]; @@ -31,7 +32,7 @@ namespace MM STATIC XTAPI PMMPTE GetSystemPteBaseAddress(VOID); STATIC XTAPI PMMPTE GetValidPte(VOID); STATIC XTAPI VOID InitializePageTable(VOID); - STATIC XTAPI VOID InitializePteTemplate(VOID); + STATIC XTAPI VOID InitializeSystemPte(VOID); STATIC XTAPI VOID InitializeSystemPteSpace(VOID); STATIC XTAPI VOID MapP5E(PVOID StartAddress, PVOID EndAddress, diff --git a/xtoskrnl/includes/mm/i686/pte.hh b/xtoskrnl/includes/mm/i686/pte.hh index 4576f48..44bd064 100644 --- a/xtoskrnl/includes/mm/i686/pte.hh +++ b/xtoskrnl/includes/mm/i686/pte.hh @@ -19,6 +19,7 @@ namespace MM { private: STATIC MMPTE FirstSystemFreePte[MaximumPtePoolTypes]; + STATIC ULONG_PTR ListTerminator; STATIC PMMPTE SystemPteBase; STATIC PMMPTE SystemPtesEnd[MaximumPtePoolTypes]; STATIC PMMPTE SystemPtesStart[MaximumPtePoolTypes]; @@ -31,7 +32,7 @@ namespace MM STATIC XTAPI PMMPTE GetSystemPteBaseAddress(VOID); STATIC XTAPI PMMPTE GetValidPte(VOID); STATIC XTAPI VOID InitializePageTable(VOID); - STATIC XTAPI VOID InitializePteTemplate(VOID); + STATIC XTAPI VOID InitializeSystemPte(VOID); STATIC XTAPI VOID InitializeSystemPteSpace(VOID); STATIC XTAPI VOID MapPDE(PVOID StartAddress, PVOID EndAddress, diff --git a/xtoskrnl/mm/amd64/pte.cc b/xtoskrnl/mm/amd64/pte.cc index 540f40f..a095915 100644 --- a/xtoskrnl/mm/amd64/pte.cc +++ b/xtoskrnl/mm/amd64/pte.cc @@ -154,7 +154,7 @@ MM::Pte::InitializePageTable(VOID) } /** - * Initializes the PTE template. + * Initializes the system's PTE. * * @return This routine does not return any value. * @@ -162,9 +162,13 @@ MM::Pte::InitializePageTable(VOID) */ XTAPI VOID -MM::Pte::InitializePteTemplate(VOID) +MM::Pte::InitializeSystemPte(VOID) { + /* Initialize the PTE template */ ValidPte = {MM_PTE_VALID|MM_PTE_EXECUTE_READWRITE|MM_PTE_DIRTY|MM_PTE_ACCESSED}; + + /* Initialize the system's PTE list terminator */ + ListTerminator = MM::Paging::GetPteListTerminator(); } /** diff --git a/xtoskrnl/mm/data.cc b/xtoskrnl/mm/data.cc index be3c853..27a29b4 100644 --- a/xtoskrnl/mm/data.cc +++ b/xtoskrnl/mm/data.cc @@ -97,6 +97,9 @@ MMPFNLIST MM::Pfn::ZeroedPagesList = {0, ZeroedPageList, MAXULONG_PTR, MAXULONG_ /* Array of lists for available System PTEs, separated by pool type */ MMPTE MM::Pte::FirstSystemFreePte[MaximumPtePoolTypes]; +/* PTE list terminator */ +ULONG_PTR MM::Pte::ListTerminator; + /* Virtual base address of the System PTE space */ PMMPTE MM::Pte::SystemPteBase; diff --git a/xtoskrnl/mm/i686/pte.cc b/xtoskrnl/mm/i686/pte.cc index e46a64f..be5e591 100644 --- a/xtoskrnl/mm/i686/pte.cc +++ b/xtoskrnl/mm/i686/pte.cc @@ -113,7 +113,7 @@ MM::Pte::InitializePageTable(VOID) } /** - * Initializes the PTE template. + * Initializes the system's PTE. * * @return This routine does not return any value. * @@ -121,9 +121,13 @@ MM::Pte::InitializePageTable(VOID) */ XTAPI VOID -MM::Pte::InitializePteTemplate(VOID) +MM::Pte::InitializeSystemPte(VOID) { + /* Initialize the PTE template */ ValidPte = {{MM_PTE_VALID|MM_PTE_EXECUTE_READWRITE|MM_PTE_DIRTY|MM_PTE_ACCESSED}}; + + /* Initialize the system's PTE list terminator */ + ListTerminator = MM::Paging::GetPteListTerminator(); } /** diff --git a/xtoskrnl/mm/mmgr.cc b/xtoskrnl/mm/mmgr.cc index 50fd8ba..29fa31e 100644 --- a/xtoskrnl/mm/mmgr.cc +++ b/xtoskrnl/mm/mmgr.cc @@ -64,7 +64,7 @@ MM::Manager::InitializeMemoryManager(VOID) InitializeMemoryLayout(); /* Initialize PTE template */ - MM::Pte::InitializePteTemplate(); + MM::Pte::InitializeSystemPte(); /* Initialize page table */ MM::Pte::InitializePageTable(); -- 2.52.0 From 455349f2d7464222969f07e53ea443d34644dee5 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Sat, 3 Jan 2026 23:27:24 +0100 Subject: [PATCH 091/166] Remove dead code from paging and PTE management --- sdk/xtdk/amd64/mmtypes.h | 1 - sdk/xtdk/i686/mmtypes.h | 1 - xtoskrnl/includes/mm/amd64/pagemap.hh | 2 -- xtoskrnl/includes/mm/amd64/paging.hh | 2 -- xtoskrnl/includes/mm/amd64/pte.hh | 1 - xtoskrnl/includes/mm/i686/pagemap.hh | 4 --- xtoskrnl/includes/mm/i686/paging.hh | 2 -- xtoskrnl/includes/mm/i686/pte.hh | 1 - xtoskrnl/mm/amd64/pagemap.cc | 21 ----------- xtoskrnl/mm/amd64/pte.cc | 3 -- xtoskrnl/mm/data.cc | 3 -- xtoskrnl/mm/i686/pagemap.cc | 51 --------------------------- xtoskrnl/mm/i686/pte.cc | 3 -- xtoskrnl/mm/paging.cc | 30 ---------------- 14 files changed, 125 deletions(-) diff --git a/sdk/xtdk/amd64/mmtypes.h b/sdk/xtdk/amd64/mmtypes.h index 0562244..9eccd34 100644 --- a/sdk/xtdk/amd64/mmtypes.h +++ b/sdk/xtdk/amd64/mmtypes.h @@ -142,7 +142,6 @@ typedef struct _HARDWARE_PTE typedef struct _MMPAGEMAP_INFO { BOOLEAN Xpa; - ULONGLONG EmptyPteList; ULONGLONG PteBase; ULONGLONG PdeBase; ULONGLONG PpeBase; diff --git a/sdk/xtdk/i686/mmtypes.h b/sdk/xtdk/i686/mmtypes.h index 469a708..749caea 100644 --- a/sdk/xtdk/i686/mmtypes.h +++ b/sdk/xtdk/i686/mmtypes.h @@ -165,7 +165,6 @@ typedef union _HARDWARE_PTE typedef struct _MMPAGEMAP_INFO { BOOLEAN Xpa; - ULONG EmptyPteList; ULONG PteBase; ULONG PdeBase; ULONG PdiShift; diff --git a/xtoskrnl/includes/mm/amd64/pagemap.hh b/xtoskrnl/includes/mm/amd64/pagemap.hh index 2a3eb9e..febc7ce 100644 --- a/xtoskrnl/includes/mm/amd64/pagemap.hh +++ b/xtoskrnl/includes/mm/amd64/pagemap.hh @@ -24,7 +24,6 @@ namespace MM XTAPI PMMPTE AdvancePte(IN PMMPTE Pte, IN LONG Count); XTAPI VOID ClearPte(IN PMMPTE PtePointer); - XTAPI ULONGLONG GetEmptyPteList(VOID); XTAPI ULONG_PTR GetNextEntry(IN PMMPTE Pte); XTAPI PMMPTE GetNextPte(IN PMMPTE Pte); XTAPI BOOLEAN GetOneEntry(IN PMMPTE Pte); @@ -42,7 +41,6 @@ namespace MM XTAPI PMMPTE GetPteAddress(IN PVOID Address); XTAPI LONG GetPteDistance(PMMPTE EndPte, PMMPTE StartPte); - XTAPI ULONG_PTR GetPteListTerminator(VOID); XTAPI ULONG GetPteOffset(IN PVOID Address); XTAPI ULONG GetPteSize(VOID); XTAPI ULONG GetPteSoftwareProtection(IN PMMPTE PtePointer); diff --git a/xtoskrnl/includes/mm/amd64/paging.hh b/xtoskrnl/includes/mm/amd64/paging.hh index dd3cf29..9cec44a 100644 --- a/xtoskrnl/includes/mm/amd64/paging.hh +++ b/xtoskrnl/includes/mm/amd64/paging.hh @@ -25,7 +25,6 @@ namespace MM IN LONG Count); STATIC XTAPI VOID ClearPte(IN PMMPTE PtePointer); STATIC XTAPI VOID FlushTlb(VOID); - STATIC XTAPI ULONG_PTR GetEmptyPteList(VOID); STATIC XTAPI ULONG_PTR GetNextEntry(IN PMMPTE Pte); STATIC XTAPI PMMPTE GetNextPte(IN PMMPTE Pte); STATIC XTAPI BOOLEAN GetOneEntry(IN PMMPTE Pte); @@ -40,7 +39,6 @@ namespace MM STATIC XTAPI PMMPTE GetPteAddress(IN PVOID Address); STATIC XTAPI LONG GetPteDistance(PMMPTE EndPte, PMMPTE StartPte); - STATIC XTAPI ULONG_PTR GetPteListTerminator(VOID); STATIC XTAPI ULONG GetPteSize(VOID); STATIC XTAPI ULONG GetPteSoftwareProtection(IN PMMPTE PtePointer); STATIC XTAPI ULONG GetPteSoftwarePrototype(IN PMMPTE PtePointer); diff --git a/xtoskrnl/includes/mm/amd64/pte.hh b/xtoskrnl/includes/mm/amd64/pte.hh index d07ac04..089dbfc 100644 --- a/xtoskrnl/includes/mm/amd64/pte.hh +++ b/xtoskrnl/includes/mm/amd64/pte.hh @@ -19,7 +19,6 @@ namespace MM { private: STATIC MMPTE FirstSystemFreePte[MaximumPtePoolTypes]; - STATIC ULONG_PTR ListTerminator; STATIC PMMPTE SystemPteBase; STATIC PMMPTE SystemPtesEnd[MaximumPtePoolTypes]; STATIC PMMPTE SystemPtesStart[MaximumPtePoolTypes]; diff --git a/xtoskrnl/includes/mm/i686/pagemap.hh b/xtoskrnl/includes/mm/i686/pagemap.hh index b014357..bdfcb2d 100644 --- a/xtoskrnl/includes/mm/i686/pagemap.hh +++ b/xtoskrnl/includes/mm/i686/pagemap.hh @@ -24,7 +24,6 @@ namespace MM VIRTUAL XTAPI PMMPTE AdvancePte(IN PMMPTE Pte, IN ULONG Count) = 0; VIRTUAL XTAPI VOID ClearPte(IN PMMPTE PtePointer) = 0; - XTAPI ULONG GetEmptyPteList(VOID); VIRTUAL XTAPI ULONG_PTR GetNextEntry(IN PMMPTE Pte) = 0; VIRTUAL XTAPI PMMPTE GetNextPte(IN PMMPTE Pte) = 0; VIRTUAL XTAPI BOOLEAN GetOneEntry(IN PMMPTE Pte) = 0; @@ -40,7 +39,6 @@ namespace MM XTAPI ULONG GetPteOffset(IN PVOID Address); VIRTUAL XTAPI LONG GetPteDistance(PMMPTE EndPte, PMMPTE StartPte) = 0; - VIRTUAL XTAPI ULONG_PTR GetPteListTerminator(VOID) = 0; VIRTUAL XTAPI ULONG GetPteSize(VOID) = 0; VIRTUAL XTAPI ULONG GetPteSoftwareProtection(IN PMMPTE PtePointer) = 0; VIRTUAL XTAPI ULONG GetPteSoftwarePrototype(IN PMMPTE PtePointer) = 0; @@ -82,7 +80,6 @@ namespace MM XTAPI ULONG_PTR GetPte(IN PMMPTE PtePointer); XTAPI LONG GetPteDistance(PMMPTE EndPte, PMMPTE StartPte); - XTAPI ULONG_PTR GetPteListTerminator(VOID); XTAPI ULONG GetPteSize(VOID); XTAPI ULONG GetPteSoftwareProtection(IN PMMPTE PtePointer); XTAPI ULONG GetPteSoftwarePrototype(IN PMMPTE PtePointer); @@ -122,7 +119,6 @@ namespace MM XTAPI ULONG_PTR GetPte(IN PMMPTE PtePointer); XTAPI LONG GetPteDistance(PMMPTE EndPte, PMMPTE StartPte); - XTAPI ULONG_PTR GetPteListTerminator(VOID); XTAPI ULONG GetPteSize(VOID); XTAPI ULONG GetPteSoftwareProtection(IN PMMPTE PtePointer); XTAPI ULONG GetPteSoftwarePrototype(IN PMMPTE PtePointer); diff --git a/xtoskrnl/includes/mm/i686/paging.hh b/xtoskrnl/includes/mm/i686/paging.hh index 54c77cc..b9722d9 100644 --- a/xtoskrnl/includes/mm/i686/paging.hh +++ b/xtoskrnl/includes/mm/i686/paging.hh @@ -25,7 +25,6 @@ namespace MM IN LONG Count); STATIC XTAPI VOID ClearPte(IN PMMPTE PtePointer); STATIC XTAPI VOID FlushTlb(VOID); - STATIC XTAPI ULONG_PTR GetEmptyPteList(VOID); STATIC XTAPI ULONG_PTR GetNextEntry(IN PMMPTE Pte); STATIC XTAPI PMMPTE GetNextPte(IN PMMPTE Pte); STATIC XTAPI BOOLEAN GetOneEntry(IN PMMPTE Pte); @@ -38,7 +37,6 @@ namespace MM STATIC XTAPI PMMPTE GetPteAddress(IN PVOID Address); STATIC XTAPI LONG GetPteDistance(PMMPTE EndPte, PMMPTE StartPte); - STATIC XTAPI ULONG_PTR GetPteListTerminator(VOID); STATIC XTAPI ULONG GetPteSize(VOID); STATIC XTAPI ULONG GetPteSoftwareProtection(IN PMMPTE PtePointer); STATIC XTAPI ULONG GetPteSoftwarePrototype(IN PMMPTE PtePointer); diff --git a/xtoskrnl/includes/mm/i686/pte.hh b/xtoskrnl/includes/mm/i686/pte.hh index 44bd064..2704e2b 100644 --- a/xtoskrnl/includes/mm/i686/pte.hh +++ b/xtoskrnl/includes/mm/i686/pte.hh @@ -19,7 +19,6 @@ namespace MM { private: STATIC MMPTE FirstSystemFreePte[MaximumPtePoolTypes]; - STATIC ULONG_PTR ListTerminator; STATIC PMMPTE SystemPteBase; STATIC PMMPTE SystemPtesEnd[MaximumPtePoolTypes]; STATIC PMMPTE SystemPtesStart[MaximumPtePoolTypes]; diff --git a/xtoskrnl/mm/amd64/pagemap.cc b/xtoskrnl/mm/amd64/pagemap.cc index 9e6454e..932e586 100644 --- a/xtoskrnl/mm/amd64/pagemap.cc +++ b/xtoskrnl/mm/amd64/pagemap.cc @@ -49,21 +49,6 @@ MM::PageMap::ClearPte(IN PMMPTE PtePointer) 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 -ULONGLONG -MM::PageMap::GetEmptyPteList(VOID) -{ - /* Return empty PTE list mask */ - return PageMapInfo.EmptyPteList; -} - /** * Gets the next entry in a PTE list. * @@ -762,9 +747,6 @@ 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; @@ -862,9 +844,6 @@ 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/amd64/pte.cc b/xtoskrnl/mm/amd64/pte.cc index a095915..f255b07 100644 --- a/xtoskrnl/mm/amd64/pte.cc +++ b/xtoskrnl/mm/amd64/pte.cc @@ -166,9 +166,6 @@ MM::Pte::InitializeSystemPte(VOID) { /* Initialize the PTE template */ ValidPte = {MM_PTE_VALID|MM_PTE_EXECUTE_READWRITE|MM_PTE_DIRTY|MM_PTE_ACCESSED}; - - /* Initialize the system's PTE list terminator */ - ListTerminator = MM::Paging::GetPteListTerminator(); } /** diff --git a/xtoskrnl/mm/data.cc b/xtoskrnl/mm/data.cc index 27a29b4..be3c853 100644 --- a/xtoskrnl/mm/data.cc +++ b/xtoskrnl/mm/data.cc @@ -97,9 +97,6 @@ MMPFNLIST MM::Pfn::ZeroedPagesList = {0, ZeroedPageList, MAXULONG_PTR, MAXULONG_ /* Array of lists for available System PTEs, separated by pool type */ MMPTE MM::Pte::FirstSystemFreePte[MaximumPtePoolTypes]; -/* PTE list terminator */ -ULONG_PTR MM::Pte::ListTerminator; - /* Virtual base address of the System PTE space */ PMMPTE MM::Pte::SystemPteBase; diff --git a/xtoskrnl/mm/i686/pagemap.cc b/xtoskrnl/mm/i686/pagemap.cc index 6551fd3..1844115 100644 --- a/xtoskrnl/mm/i686/pagemap.cc +++ b/xtoskrnl/mm/i686/pagemap.cc @@ -9,21 +9,6 @@ #include -/** - * 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. * @@ -340,21 +325,6 @@ MM::PageMapBasic::GetPteDistance(PMMPTE EndPte, return ((ULONG_PTR)EndPte - (ULONG_PTR)StartPte) / sizeof(MMPML2_PTE); } -/** - * Gets the terminator value for a PTE list (PML2). - * - * @return This routine returns the terminator value for a PTE list. - * - * @since XT 1.0 - */ -XTAPI -ULONG_PTR -MM::PageMapBasic::GetPteListTerminator(VOID) -{ - /* Return PTE list terminator value for PML2 */ - return 0xFFFFF; -} - /** * Gets the size of a PTE for basic paging (PML2). * @@ -456,9 +426,6 @@ 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; @@ -828,21 +795,6 @@ MM::PageMapXpa::GetPteDistance(PMMPTE EndPte, return ((ULONG_PTR)EndPte - (ULONG_PTR)StartPte) / sizeof(MMPML3_PTE); } -/** - * Gets the terminator value for a PTE list (PML3). - * - * @return This routine returns the terminator value for a PTE list. - * - * @since XT 1.0 - */ -XTAPI -ULONG_PTR -MM::PageMapXpa::GetPteListTerminator(VOID) -{ - /* Return PTE list terminator value for PML3 */ - return 0xFFFFFFFF; -} - /** * Gets the size of a PTE for XPA paging (PML3). * @@ -944,9 +896,6 @@ MM::PageMapXpa::InitializePageMapInfo(VOID) /* Set PML3 page map information */ PageMapInfo.Xpa = TRUE; - /* Set PML3 empty PTE list mask */ - PageMapInfo.EmptyPteList = (ULONG)0xFFFFFFFF; - /* Set PML3 base addresses */ PageMapInfo.PteBase = MM_PTE_BASE; PageMapInfo.PdeBase = MM_PDE_BASE; diff --git a/xtoskrnl/mm/i686/pte.cc b/xtoskrnl/mm/i686/pte.cc index be5e591..ab83731 100644 --- a/xtoskrnl/mm/i686/pte.cc +++ b/xtoskrnl/mm/i686/pte.cc @@ -125,9 +125,6 @@ MM::Pte::InitializeSystemPte(VOID) { /* Initialize the PTE template */ ValidPte = {{MM_PTE_VALID|MM_PTE_EXECUTE_READWRITE|MM_PTE_DIRTY|MM_PTE_ACCESSED}}; - - /* Initialize the system's PTE list terminator */ - ListTerminator = MM::Paging::GetPteListTerminator(); } /** diff --git a/xtoskrnl/mm/paging.cc b/xtoskrnl/mm/paging.cc index b22fe38..426e574 100644 --- a/xtoskrnl/mm/paging.cc +++ b/xtoskrnl/mm/paging.cc @@ -101,21 +101,6 @@ MM::Paging::FlushTlb(VOID) } } -/** - * 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_PTR -MM::Paging::GetEmptyPteList(VOID) -{ - /* Return empty PTE list mask */ - return (ULONG_PTR)PmlRoutines->GetEmptyPteList(); -} - /** * Gets the next entry in a PTE list. * @@ -351,21 +336,6 @@ MM::Paging::GetPteDistance(PMMPTE EndPte, return PmlRoutines->GetPteDistance(EndPte, StartPte); } -/** - * Gets the terminator value for a PTE list. - * - * @return This routine returns the terminator value for a PTE list. - * - * @since XT 1.0 - */ -XTAPI -ULONG_PTR -MM::Paging::GetPteListTerminator(VOID) -{ - /* Return PTE list terminator value */ - return PmlRoutines->GetPteListTerminator(); -} - /** * Gets the size of a PTE. * -- 2.52.0 From 9f359c10edfb06fb5bb36f342116f488c9e46c21 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Sat, 3 Jan 2026 23:39:02 +0100 Subject: [PATCH 092/166] Clean up paging code --- xtoskrnl/mm/amd64/pagemap.cc | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/xtoskrnl/mm/amd64/pagemap.cc b/xtoskrnl/mm/amd64/pagemap.cc index 932e586..504cdcb 100644 --- a/xtoskrnl/mm/amd64/pagemap.cc +++ b/xtoskrnl/mm/amd64/pagemap.cc @@ -315,21 +315,6 @@ MM::PageMap::GetPteDistance(PMMPTE EndPte, return ((ULONG_PTR)EndPte - (ULONG_PTR)StartPte) / sizeof(MMPTE); } -/** - * Gets the terminator value for a PTE list. - * - * @return This routine returns the terminator value for a PTE list. - * - * @since XT 1.0 - */ -XTAPI -ULONG_PTR -MM::PageMap::GetPteListTerminator(VOID) -{ - /* Return PTE list terminator value */ - return 0xFFFFFFFF; -} - /** * Gets the Offset of the PTE (Page Table Entry), that maps given address. * -- 2.52.0 From 0a43a93f416831019e1fd01818265d27bbf97638 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Sun, 4 Jan 2026 21:11:33 +0100 Subject: [PATCH 093/166] Add mechanism to free system PTEs and merge adjacent clusters --- xtoskrnl/includes/mm/amd64/pte.hh | 6 +- xtoskrnl/includes/mm/i686/pte.hh | 6 +- xtoskrnl/mm/kpool.cc | 2 +- xtoskrnl/mm/pte.cc | 129 ++++++++++++++++++++++++++++-- 4 files changed, 131 insertions(+), 12 deletions(-) diff --git a/xtoskrnl/includes/mm/amd64/pte.hh b/xtoskrnl/includes/mm/amd64/pte.hh index 089dbfc..0470c7d 100644 --- a/xtoskrnl/includes/mm/amd64/pte.hh +++ b/xtoskrnl/includes/mm/amd64/pte.hh @@ -48,9 +48,11 @@ namespace MM STATIC XTAPI VOID MapPXE(PVOID StartAddress, PVOID EndAddress, PMMPXE TemplatePxe); + STATIC XTAPI VOID ReleaseSystemPtes(IN PMMPTE StartingPte, + IN ULONG NumberOfPtes, + IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType); STATIC XTAPI PMMPTE ReserveSystemPtes(IN ULONG NumberOfPtes, - IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType, - IN ULONG Alignment); + IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType); private: STATIC XTAPI BOOLEAN FindFreeCluster(IN ULONG NumberOfPtes, diff --git a/xtoskrnl/includes/mm/i686/pte.hh b/xtoskrnl/includes/mm/i686/pte.hh index 2704e2b..476b0b9 100644 --- a/xtoskrnl/includes/mm/i686/pte.hh +++ b/xtoskrnl/includes/mm/i686/pte.hh @@ -42,9 +42,11 @@ namespace MM STATIC XTAPI VOID MapPTE(PVOID StartAddress, PVOID EndAddress, PMMPTE TemplatePte); + STATIC XTAPI VOID ReleaseSystemPtes(IN PMMPTE StartingPte, + IN ULONG NumberOfPtes, + IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType); STATIC XTAPI PMMPTE ReserveSystemPtes(IN ULONG NumberOfPtes, - IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType, - IN ULONG Alignment); + IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType); private: STATIC XTAPI BOOLEAN FindFreeCluster(IN ULONG NumberOfPtes, diff --git a/xtoskrnl/mm/kpool.cc b/xtoskrnl/mm/kpool.cc index e1cd326..e9d3afe 100644 --- a/xtoskrnl/mm/kpool.cc +++ b/xtoskrnl/mm/kpool.cc @@ -44,7 +44,7 @@ MM::KernelPool::AllocateKernelStack(OUT PVOID *Stack, StackPages = SIZE_TO_PAGES(StackSize); /* Reserve PTEs for the stack pages, plus a guard page */ - StackPte = MM::Pte::ReserveSystemPtes(StackPages + 1, SystemPteSpace, 0); + StackPte = MM::Pte::ReserveSystemPtes(StackPages + 1, SystemPteSpace); if(!StackPte) { /* Failed to reserve PTEs for the new kernel stack */ diff --git a/xtoskrnl/mm/pte.cc b/xtoskrnl/mm/pte.cc index fbec00b..915461f 100644 --- a/xtoskrnl/mm/pte.cc +++ b/xtoskrnl/mm/pte.cc @@ -192,7 +192,7 @@ MM::Pte::InitializeSystemPteSpace(VOID) InitializeSystemPtePool(PointerPte, MM::Manager::GetNumberOfSystemPtes(), SystemPteSpace); /* Reserve and zero a dedicated block of system PTEs */ - FirstZeroingPte = ReserveSystemPtes(MM_RESERVED_ZERO_PTES + 1, SystemPteSpace, 0); + FirstZeroingPte = ReserveSystemPtes(MM_RESERVED_ZERO_PTES + 1, SystemPteSpace); RTL::Memory::ZeroMemory(FirstZeroingPte, (MM_RESERVED_ZERO_PTES + 1) * MM::Paging::GetPteSize()); /* Use the first PTE of this block as a counter for available zeroing PTEs */ @@ -293,6 +293,125 @@ MM::Pte::MapPTE(PVOID StartAddress, } } +/** + * Releases a block of system PTEs into a specified pool. + * + * @param StartingPte + * A pointer to the first PTE to release. + * + * @param NumberOfPtes + * The number of contiguous PTEs to release. + * + * @param SystemPtePoolType + * Specifies the system PTE pool to release into. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::Pte::ReleaseSystemPtes(IN PMMPTE StartingPte, + IN ULONG NumberOfPtes, + IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType) +{ + PMMPTE NextPte, PreviousPte, ReleasedPte; + ULONG ClusterSize; + + /* Raise runlevel and acquire lock to protect the PTE pool */ + KE::RaiseRunLevel RunLevel(DISPATCH_LEVEL); + KE::QueuedSpinLockGuard SpinLock(SystemSpaceLock); + + /* Increment the total number of available PTEs in this pool */ + TotalSystemFreePtes[SystemPtePoolType] += NumberOfPtes; + + /* Start at the head of the free list for this pool */ + PreviousPte = &FirstSystemFreePte[SystemPtePoolType]; + ReleasedPte = NULLPTR; + + /* Iterate through the free list to find adjacent blocks */ + while(MM::Paging::GetNextEntry(PreviousPte) != MAXULONG) + { + /* Get the next free cluster to check its size */ + NextPte = MM::Paging::AdvancePte(SystemPteBase, MM::Paging::GetNextEntry(PreviousPte)); + ClusterSize = GetClusterSize(NextPte); + + /* Check if the released block is adjacent to the current free block */ + if((MM::Paging::AdvancePte(NextPte, ClusterSize) == StartingPte) || + (MM::Paging::AdvancePte(StartingPte, NumberOfPtes) == NextPte)) + { + /* Merge the blocks by adding their sizes */ + NumberOfPtes += ClusterSize; + + /* Check if the current free block is before the released block */ + if(NextPte < StartingPte) + { + /* The new merged block starts at the current free block's address */ + StartingPte = NextPte; + } + + /* Unlink the current free block as it is being merged */ + MM::Paging::SetNextEntry(PreviousPte, MM::Paging::GetNextEntry(NextPte)); + + /* Check if the block represents more than one PTE */ + if(!MM::Paging::GetOneEntry(NextPte)) + { + /* Clear block header and move to the size PTE */ + MM::Paging::ClearPte(NextPte); + NextPte = MM::Paging::GetNextPte(NextPte); + } + + /* Clear the merged block */ + MM::Paging::ClearPte(NextPte); + + /* Reset insertion point since block size/address changed due to merge */ + ReleasedPte = NULLPTR; + } + else + { + /* Select the first free block large enough as insertion point */ + if((ReleasedPte == NULLPTR) && (NumberOfPtes <= ClusterSize)) + { + /* Mark this as the insertion point */ + ReleasedPte = PreviousPte; + } + + /* Advance to the next free block */ + PreviousPte = NextPte; + } + } + + /* Check if there is only one PTE to release */ + if(NumberOfPtes == 1) + { + /* Mark it as a single-PTE block */ + MM::Paging::SetOneEntry(StartingPte, 1); + } + else + { + /* Otherwise, mark it as a multi-PTE block */ + MM::Paging::SetOneEntry(StartingPte, 0); + + /* The next PTE stores the size of the block */ + NextPte = MM::Paging::GetNextPte(StartingPte); + MM::Paging::SetNextEntry(NextPte, NumberOfPtes); + } + + /* Check if no suitable insertion point was found */ + if(ReleasedPte == NULLPTR) + { + /* Insert at the end of the list */ + ReleasedPte = PreviousPte; + } + + /* Link the new block into the free list */ + MM::Paging::SetNextEntry(StartingPte, MM::Paging::GetNextEntry(ReleasedPte)); + MM::Paging::SetNextEntry(ReleasedPte, MM::Paging::GetPteDistance(StartingPte, SystemPteBase)); + + /* Flush the TLB to ensure address translation consistency */ + AR::CpuFunc::FlushTlb(); +} + /** * Reserves a contiguous block of system PTEs from a specified pool. * @@ -302,9 +421,6 @@ MM::Pte::MapPTE(PVOID StartAddress, * @param SystemPtePoolType * Specifies the system PTE pool from which to allocate. * - * @param Alignment - * This parameter is currently unused. - * * @return This routine returns a pointer to the beginning of the reserved block, * or NULLPTR if not enough contiguous PTEs are available. * @@ -313,10 +429,9 @@ MM::Pte::MapPTE(PVOID StartAddress, XTAPI PMMPTE MM::Pte::ReserveSystemPtes(IN ULONG NumberOfPtes, - IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType, - IN ULONG Alignment) + IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType) { - PMMPTE PreviousPte, NextPte, ReservedPte; + PMMPTE NextPte, PreviousPte, ReservedPte; ULONG ClusterSize; /* Raise runlevel and acquire lock to protect the PTE pool */ -- 2.52.0 From cb6efc648f4ca5a143746f3c8206fa390ad02ad5 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Mon, 5 Jan 2026 01:20:21 +0100 Subject: [PATCH 094/166] Implement kernel stack deallocation and physical page freeing logic --- xtoskrnl/includes/mm/pfn.hh | 5 + xtoskrnl/mm/kpool.cc | 30 +++++- xtoskrnl/mm/pfn.cc | 197 ++++++++++++++++++++++++++++++++++++ 3 files changed, 231 insertions(+), 1 deletion(-) diff --git a/xtoskrnl/includes/mm/pfn.hh b/xtoskrnl/includes/mm/pfn.hh index a0b9c34..072184e 100644 --- a/xtoskrnl/includes/mm/pfn.hh +++ b/xtoskrnl/includes/mm/pfn.hh @@ -39,6 +39,11 @@ namespace MM STATIC XTAPI PFN_NUMBER AllocateBootstrapPages(IN PFN_NUMBER NumberOfPages); STATIC XTAPI PFN_NUMBER AllocatePhysicalPage(IN ULONG Color); STATIC XTAPI VOID ComputePfnDatabaseSize(VOID); + STATIC XTAPI VOID DecrementReferenceCount(IN PMMPFN Pfn1, + IN PFN_NUMBER PageFrameIndex); + STATIC XTAPI VOID DecrementShareCount(IN PMMPFN Pfn1, + IN PFN_NUMBER PageFrameIndex); + STATIC XTAPI VOID FreePhysicalPage(IN PMMPTE PointerPte); STATIC XTAPI ULONG_PTR GetHighestPhysicalPage(VOID); STATIC XTAPI ULONGLONG GetNumberOfPhysicalPages(VOID); STATIC XTAPI PFN_NUMBER GetPfnDatabaseSize(VOID); diff --git a/xtoskrnl/mm/kpool.cc b/xtoskrnl/mm/kpool.cc index e9d3afe..2d650e9 100644 --- a/xtoskrnl/mm/kpool.cc +++ b/xtoskrnl/mm/kpool.cc @@ -155,7 +155,35 @@ VOID MM::KernelPool::FreeKernelStack(IN PVOID Stack, IN ULONG StackSize) { - UNIMPLEMENTED; + PFN_COUNT StackPages; + PMMPTE PointerPte; + ULONG Index; + + /* Get the PTE for the top of the stack, including the guard page */ + MM::Paging::AdvancePte(MM::Paging::GetPteAddress(Stack), -1); + + /* Convert the stack size into a page count */ + StackPages = SIZE_TO_PAGES(StackSize); + + /* Acquire the PFN database lock */ + KE::QueuedSpinLockGuard SpinLock(SystemSpaceLock); + + /* Loop through each page of the stack that needs to be freed */ + for(Index = 0; Index < StackPages; Index++) + { + /* Ensure the PTE is valid */ + if(MM::Paging::PteValid(PointerPte)) + { + /* Free the physical page */ + MM::Pfn::FreePhysicalPage(PointerPte); + } + + /* Advance to the next PTE */ + PointerPte = MM::Paging::AdvancePte(PointerPte, -1); + } + + /* Release all system PTEs used by the stack, including the guard page */ + MM::Pte::ReleaseSystemPtes(PointerPte, StackPages + 1, SystemPteSpace); } /** diff --git a/xtoskrnl/mm/pfn.cc b/xtoskrnl/mm/pfn.cc index dfc77e7..9a7a652 100644 --- a/xtoskrnl/mm/pfn.cc +++ b/xtoskrnl/mm/pfn.cc @@ -129,6 +129,203 @@ MM::Pfn::DecrementAvailablePages(VOID) AvailablePages--; } +/** + * Decrements the reference count of a PFN entry. + * + * @param PageFrameNumber + * A pointer to the PFN database entry for the physical page. + * + * @param PageFrameIndex + * The page frame number of the physical page. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::Pfn::DecrementReferenceCount(IN PMMPFN PageFrameNumber, + IN PFN_NUMBER PageFrameIndex) +{ + /* Decrement the PFN reference count */ + PageFrameNumber->u3.e2.ReferenceCount--; + + /* If other references exist, no further action is needed */ + if(PageFrameNumber->u3.e2.ReferenceCount) + { + /* No further action can be taken */ + return; + } + + /* If the reference count is zero, the share count should also be zero */ + if(PageFrameNumber->u2.ShareCount) + { + /* This indicates a bug; crash the system */ + KE::Crash::PanicEx(0x4E, + 0x07, + PageFrameIndex, + PageFrameNumber->u2.ShareCount, + 0); + } + + /* Check if the PTE is marked as being ready for removal */ + if(MM::Paging::GetPte(PageFrameNumber->PteAddress) & 0x1) + { + /* Check the page's cache attribute */ + if((PageFrameNumber->u3.e1.CacheAttribute != PfnCached) && + (PageFrameNumber->u3.e1.CacheAttribute != PfnNotMapped)) + { + UNIMPLEMENTED; + } + + /* The page is no longer needed, free it by linking it to the free list */ + LinkFreePage(PageFrameIndex); + + /* No further action is needed */ + return; + } + + /* The page is unreferenced and unmapped, so place it on the appropriate list */ + if(PageFrameNumber->u3.e1.Modified == 1) + { + /* Link dirty page to the modified list */ + LinkPage(&ModifiedPagesList, PageFrameIndex); + } + else + { + /* Check if the page has been marked for removal */ + if(PageFrameNumber->u3.e1.RemovalRequested == 1) + { + /* Update the page location and move it to the bad pages list */ + PageFrameNumber->u3.e1.PageLocation = StandbyPageList; + LinkPage(&BadPagesList, PageFrameIndex); + } + else + { + /* Link clean page to the standby list */ + LinkPage(&StandbyPagesList, PageFrameIndex) + } + } +} + +/** + * Decrements the share count of a PFN entry, which represents the number of PTEs mapping the page. + * + * @param PageFrameNumber + * A pointer to the PFN database entry for the physical page. + * + * @param PageFrameIndex + * The page frame number of the physical page. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::Pfn::DecrementShareCount(IN PMMPFN PageFrameNumber, + IN PFN_NUMBER PageFrameIndex) +{ + /* Ensure the page is in a valid state */ + if((PageFrameNumber->u3.e1.PageLocation != ActiveAndValid) && + (PageFrameNumber->u3.e1.PageLocation != StandbyPageList)) + { + /* This indicates a bug; crash the system */ + KE::Crash::PanicEx(0x4E, + 0x99, + PageFrameIndex, + PageFrameNumber->u3.e1.PageLocation, + 0); + } + + /* Decrement the PFN share count */ + PageFrameNumber->u2.ShareCount--; + + /* Check if the share count has dropped to zero */ + if(!PageFrameNumber->u2.ShareCount) + { + /* Check if this is a prototype PTE */ + if(PageFrameNumber->u3.e1.PrototypePte) + { + /* Transition the PTE to invalid state */ + MM::Paging::TransitionPte(PageFrameNumber->PteAddress, + MM::Paging::GetPteSoftwareProtection(&PageFrameNumber->OriginalPte)); + } + + /* Mark the page as being in a transition state */ + PageFrameNumber->u3.e1.PageLocation = TransitionPage; + + /* Check if there are still outstanding references */ + if(PageFrameNumber->u3.e2.ReferenceCount == 1) + { + /* Check if the PTE is marked as being ready for removal */ + if(MM::Paging::GetPte(PageFrameNumber->PteAddress) & 0x1) + { + /* Reset the reference count */ + PageFrameNumber->u3.e2.ReferenceCount = 0; + + /* Check the page's cache attribute */ + if((PageFrameNumber->u3.e1.CacheAttribute != PfnCached) && + (PageFrameNumber->u3.e1.CacheAttribute != PfnNotMapped)) + { + UNIMPLEMENTED; + } + + /* Mark the page as active and valid again */ + PageFrameNumber->u3.e1.PageLocation = ActiveAndValid; + + /* The page is no longer needed, free it by linking it to the free list */ + MM::Pfn::LinkFreePage(PageFrameIndex); + } + else + { + /* The PTE can not be removed yet, decrement the reference count */ + DecrementReferenceCount(PageFrameNumber, PageFrameIndex); + } + } + else + { + /* There are still some outstanding references, decrement the reference count */ + PageFrameNumber->u3.e2.ReferenceCount--; + } + } +} + +/** + * Frees a physical page that is mapped by a given PTE. + * + * @param PointerPte + * A pointer to the Page Table Entry (PTE) that maps the physical page to be freed. + * + * @return This routine does not return a value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::Pfn::FreePhysicalPage(IN PMMPTE PointerPte) +{ + PFN_COUNT PageFrameNumber, PageTableFrameNumber; + PMMPFN PageFrame, PageTableFrame; + + /* Get the page frame number from the PTE */ + PageFrameNumber = MM::Paging::GetPageFrameNumber(PointerPte); + PageFrame = MM::Pfn::GetPfnEntry(PageFrameNumber); + + /* Get the page table frame number corresponding to the PTE */ + PageTableFrameNumber = PageFrame->u4.PteFrame; + PageTableFrame = MM::Pfn::GetPfnEntry(PageTableFrameNumber); + + /* Decrement the share count of the page table */ + MM::Pfn::DecrementShareCount(PageTableFrame, PageTableFrameNumber); + + /* Mark the PTE as being ready for removal */ + MM::Paging::SetPte(PageFrame->PteAddress, MM::Paging::GetPte(PageFrame->PteAddress) | 1); + + /* Decrement the share count of the page */ + MM::Pfn::DecrementShareCount(PageFrame, PageFrameNumber); +} + /** * Retrieves the highest physical page number (PFN) detected in the system. * -- 2.52.0 From 46576398a220b1f4d03f8c1d6378921e9a1d5070 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Mon, 5 Jan 2026 01:22:41 +0100 Subject: [PATCH 095/166] Add missing semicolon --- xtoskrnl/mm/pfn.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xtoskrnl/mm/pfn.cc b/xtoskrnl/mm/pfn.cc index 9a7a652..5a03203 100644 --- a/xtoskrnl/mm/pfn.cc +++ b/xtoskrnl/mm/pfn.cc @@ -203,7 +203,7 @@ MM::Pfn::DecrementReferenceCount(IN PMMPFN PageFrameNumber, else { /* Link clean page to the standby list */ - LinkPage(&StandbyPagesList, PageFrameIndex) + LinkPage(&StandbyPagesList, PageFrameIndex); } } } -- 2.52.0 From e66baa0da054d66e7a15a916262d5d85ced78173 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Mon, 5 Jan 2026 01:28:09 +0100 Subject: [PATCH 096/166] Fix deadlock by reducing lock scope --- xtoskrnl/mm/kpool.cc | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/xtoskrnl/mm/kpool.cc b/xtoskrnl/mm/kpool.cc index 2d650e9..1e68a17 100644 --- a/xtoskrnl/mm/kpool.cc +++ b/xtoskrnl/mm/kpool.cc @@ -165,21 +165,24 @@ MM::KernelPool::FreeKernelStack(IN PVOID Stack, /* Convert the stack size into a page count */ StackPages = SIZE_TO_PAGES(StackSize); - /* Acquire the PFN database lock */ - KE::QueuedSpinLockGuard SpinLock(SystemSpaceLock); - - /* Loop through each page of the stack that needs to be freed */ - for(Index = 0; Index < StackPages; Index++) + /* Start guarded code block */ { - /* Ensure the PTE is valid */ - if(MM::Paging::PteValid(PointerPte)) - { - /* Free the physical page */ - MM::Pfn::FreePhysicalPage(PointerPte); - } + /* Acquire the PFN database lock */ + KE::QueuedSpinLockGuard SpinLock(SystemSpaceLock); - /* Advance to the next PTE */ - PointerPte = MM::Paging::AdvancePte(PointerPte, -1); + /* Loop through each page of the stack that needs to be freed */ + for(Index = 0; Index < StackPages; Index++) + { + /* Ensure the PTE is valid */ + if(MM::Paging::PteValid(PointerPte)) + { + /* Free the physical page */ + MM::Pfn::FreePhysicalPage(PointerPte); + } + + /* Advance to the next PTE */ + PointerPte = MM::Paging::AdvancePte(PointerPte, -1); + } } /* Release all system PTEs used by the stack, including the guard page */ -- 2.52.0 From 410286d0126698331af935747b336b5db67ee7ff Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Mon, 5 Jan 2026 16:48:26 +0100 Subject: [PATCH 097/166] Replace ULONG with PFN_COUNT in system PTE variables --- xtoskrnl/includes/mm/amd64/pte.hh | 12 ++++++------ xtoskrnl/includes/mm/i686/pte.hh | 12 ++++++------ xtoskrnl/mm/data.cc | 2 +- xtoskrnl/mm/pte.cc | 11 ++++++----- 4 files changed, 19 insertions(+), 18 deletions(-) diff --git a/xtoskrnl/includes/mm/amd64/pte.hh b/xtoskrnl/includes/mm/amd64/pte.hh index 0470c7d..23d44e1 100644 --- a/xtoskrnl/includes/mm/amd64/pte.hh +++ b/xtoskrnl/includes/mm/amd64/pte.hh @@ -22,12 +22,12 @@ namespace MM STATIC PMMPTE SystemPteBase; STATIC PMMPTE SystemPtesEnd[MaximumPtePoolTypes]; STATIC PMMPTE SystemPtesStart[MaximumPtePoolTypes]; - STATIC ULONG TotalSystemFreePtes[MaximumPtePoolTypes]; + STATIC PFN_COUNT TotalSystemFreePtes[MaximumPtePoolTypes]; STATIC MMPTE ValidPte; public: STATIC XTAPI BOOLEAN AddressValid(IN PVOID VirtualAddress); - STATIC XTAPI ULONG GetPtesPerPage(VOID); + STATIC XTAPI PFN_COUNT GetPtesPerPage(VOID); STATIC XTAPI PMMPTE GetSystemPteBaseAddress(VOID); STATIC XTAPI PMMPTE GetValidPte(VOID); STATIC XTAPI VOID InitializePageTable(VOID); @@ -49,19 +49,19 @@ namespace MM PVOID EndAddress, PMMPXE TemplatePxe); STATIC XTAPI VOID ReleaseSystemPtes(IN PMMPTE StartingPte, - IN ULONG NumberOfPtes, + IN PFN_COUNT NumberOfPtes, IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType); - STATIC XTAPI PMMPTE ReserveSystemPtes(IN ULONG NumberOfPtes, + STATIC XTAPI PMMPTE ReserveSystemPtes(IN PFN_COUNT NumberOfPtes, IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType); private: - STATIC XTAPI BOOLEAN FindFreeCluster(IN ULONG NumberOfPtes, + STATIC XTAPI BOOLEAN FindFreeCluster(IN PFN_COUNT NumberOfPtes, IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType, OUT PMMPTE *FoundCluster, OUT PMMPTE *PreviousClusterNode); STATIC XTAPI ULONG GetClusterSize(IN PMMPTE Pte); STATIC XTAPI VOID InitializeSystemPtePool(IN PMMPTE StartingPte, - IN ULONG NumberOfPtes, + IN PFN_COUNT NumberOfPtes, IN MMSYSTEM_PTE_POOL_TYPE PoolType); }; } diff --git a/xtoskrnl/includes/mm/i686/pte.hh b/xtoskrnl/includes/mm/i686/pte.hh index 476b0b9..879579b 100644 --- a/xtoskrnl/includes/mm/i686/pte.hh +++ b/xtoskrnl/includes/mm/i686/pte.hh @@ -22,12 +22,12 @@ namespace MM STATIC PMMPTE SystemPteBase; STATIC PMMPTE SystemPtesEnd[MaximumPtePoolTypes]; STATIC PMMPTE SystemPtesStart[MaximumPtePoolTypes]; - STATIC ULONG TotalSystemFreePtes[MaximumPtePoolTypes]; + STATIC PFN_COUNT TotalSystemFreePtes[MaximumPtePoolTypes]; STATIC MMPTE ValidPte; public: STATIC XTAPI BOOLEAN AddressValid(IN PVOID VirtualAddress); - STATIC XTAPI ULONG GetPtesPerPage(VOID); + STATIC XTAPI PFN_COUNT GetPtesPerPage(VOID); STATIC XTAPI PMMPTE GetSystemPteBaseAddress(VOID); STATIC XTAPI PMMPTE GetValidPte(VOID); STATIC XTAPI VOID InitializePageTable(VOID); @@ -43,19 +43,19 @@ namespace MM PVOID EndAddress, PMMPTE TemplatePte); STATIC XTAPI VOID ReleaseSystemPtes(IN PMMPTE StartingPte, - IN ULONG NumberOfPtes, + IN PFN_COUNT NumberOfPtes, IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType); - STATIC XTAPI PMMPTE ReserveSystemPtes(IN ULONG NumberOfPtes, + STATIC XTAPI PMMPTE ReserveSystemPtes(IN PFN_COUNT NumberOfPtes, IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType); private: - STATIC XTAPI BOOLEAN FindFreeCluster(IN ULONG NumberOfPtes, + STATIC XTAPI BOOLEAN FindFreeCluster(IN PFN_COUNT NumberOfPtes, IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType, OUT PMMPTE *FoundCluster, OUT PMMPTE *PreviousClusterNode); STATIC XTAPI ULONG GetClusterSize(IN PMMPTE Pte); STATIC XTAPI VOID InitializeSystemPtePool(IN PMMPTE StartingPte, - IN ULONG NumberOfPtes, + IN PFN_COUNT NumberOfPtes, IN MMSYSTEM_PTE_POOL_TYPE PoolType); }; } diff --git a/xtoskrnl/mm/data.cc b/xtoskrnl/mm/data.cc index be3c853..ffbd85a 100644 --- a/xtoskrnl/mm/data.cc +++ b/xtoskrnl/mm/data.cc @@ -107,7 +107,7 @@ PMMPTE MM::Pte::SystemPtesEnd[MaximumPtePoolTypes]; PMMPTE MM::Pte::SystemPtesStart[MaximumPtePoolTypes]; /* Total count of available System PTEs */ -ULONG MM::Pte::TotalSystemFreePtes[MaximumPtePoolTypes]; +PFN_COUNT MM::Pte::TotalSystemFreePtes[MaximumPtePoolTypes]; /* Template PTE entry containing standard flags for a valid, present kernel page */ MMPTE MM::Pte::ValidPte; diff --git a/xtoskrnl/mm/pte.cc b/xtoskrnl/mm/pte.cc index 915461f..8e715f3 100644 --- a/xtoskrnl/mm/pte.cc +++ b/xtoskrnl/mm/pte.cc @@ -30,7 +30,7 @@ */ XTAPI BOOLEAN -MM::Pte::FindFreeCluster(IN ULONG NumberOfPtes, +MM::Pte::FindFreeCluster(IN PFN_COUNT NumberOfPtes, IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType, OUT PMMPTE *FoundCluster, OUT PMMPTE *PreviousClusterNode) @@ -97,7 +97,7 @@ MM::Pte::GetClusterSize(IN PMMPTE Pte) * @since XT 1.0 */ XTAPI -ULONG +PFN_COUNT MM::Pte::GetPtesPerPage(VOID) { /* Calculate and return the number of PTEs per page */ @@ -138,7 +138,7 @@ MM::Pte::GetValidPte() XTAPI VOID MM::Pte::InitializeSystemPtePool(IN PMMPTE StartingPte, - IN ULONG NumberOfPtes, + IN PFN_COUNT NumberOfPtes, IN MMSYSTEM_PTE_POOL_TYPE PoolType) { /* Set the system PTE base address */ @@ -293,6 +293,7 @@ MM::Pte::MapPTE(PVOID StartAddress, } } + /** * Releases a block of system PTEs into a specified pool. * @@ -312,7 +313,7 @@ MM::Pte::MapPTE(PVOID StartAddress, XTAPI VOID MM::Pte::ReleaseSystemPtes(IN PMMPTE StartingPte, - IN ULONG NumberOfPtes, + IN PFN_COUNT NumberOfPtes, IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType) { PMMPTE NextPte, PreviousPte, ReleasedPte; @@ -428,7 +429,7 @@ MM::Pte::ReleaseSystemPtes(IN PMMPTE StartingPte, */ XTAPI PMMPTE -MM::Pte::ReserveSystemPtes(IN ULONG NumberOfPtes, +MM::Pte::ReserveSystemPtes(IN PFN_COUNT NumberOfPtes, IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType) { PMMPTE NextPte, PreviousPte, ReservedPte; -- 2.52.0 From 3a087766cc725a6fd265085a26ebb18ef60e426c Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Mon, 5 Jan 2026 16:59:35 +0100 Subject: [PATCH 098/166] Optimize system PTE deallocation by avoiding immediate and expensive TLB flush --- xtoskrnl/mm/pte.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/xtoskrnl/mm/pte.cc b/xtoskrnl/mm/pte.cc index 8e715f3..efa382e 100644 --- a/xtoskrnl/mm/pte.cc +++ b/xtoskrnl/mm/pte.cc @@ -319,6 +319,9 @@ MM::Pte::ReleaseSystemPtes(IN PMMPTE StartingPte, PMMPTE NextPte, PreviousPte, ReleasedPte; ULONG ClusterSize; + /* Clear the PTEs before releasing them */ + RtlZeroMemory(StartingPte, NumberOfPtes * MM::Paging::GetPteSize()); + /* Raise runlevel and acquire lock to protect the PTE pool */ KE::RaiseRunLevel RunLevel(DISPATCH_LEVEL); KE::QueuedSpinLockGuard SpinLock(SystemSpaceLock); @@ -408,9 +411,6 @@ MM::Pte::ReleaseSystemPtes(IN PMMPTE StartingPte, /* Link the new block into the free list */ MM::Paging::SetNextEntry(StartingPte, MM::Paging::GetNextEntry(ReleasedPte)); MM::Paging::SetNextEntry(ReleasedPte, MM::Paging::GetPteDistance(StartingPte, SystemPteBase)); - - /* Flush the TLB to ensure address translation consistency */ - AR::CpuFunc::FlushTlb(); } /** -- 2.52.0 From 154ca7be350a305203ceb211b4d298a2ac569c04 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Mon, 5 Jan 2026 19:36:12 +0100 Subject: [PATCH 099/166] Allow PFN insertion at the beginning of standby list --- xtoskrnl/includes/mm/pfn.hh | 6 ++++-- xtoskrnl/mm/pfn.cc | 28 ++++++++++++++++++++++------ 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/xtoskrnl/includes/mm/pfn.hh b/xtoskrnl/includes/mm/pfn.hh index 072184e..0839d80 100644 --- a/xtoskrnl/includes/mm/pfn.hh +++ b/xtoskrnl/includes/mm/pfn.hh @@ -40,9 +40,11 @@ namespace MM STATIC XTAPI PFN_NUMBER AllocatePhysicalPage(IN ULONG Color); STATIC XTAPI VOID ComputePfnDatabaseSize(VOID); STATIC XTAPI VOID DecrementReferenceCount(IN PMMPFN Pfn1, - IN PFN_NUMBER PageFrameIndex); + IN PFN_NUMBER PageFrameIndex, + IN BOOLEAN BeginStandbyList = FALSE); STATIC XTAPI VOID DecrementShareCount(IN PMMPFN Pfn1, - IN PFN_NUMBER PageFrameIndex); + IN PFN_NUMBER PageFrameIndex, + IN BOOLEAN BeginStandbyList = FALSE); STATIC XTAPI VOID FreePhysicalPage(IN PMMPTE PointerPte); STATIC XTAPI ULONG_PTR GetHighestPhysicalPage(VOID); STATIC XTAPI ULONGLONG GetNumberOfPhysicalPages(VOID); diff --git a/xtoskrnl/mm/pfn.cc b/xtoskrnl/mm/pfn.cc index 5a03203..40e5c30 100644 --- a/xtoskrnl/mm/pfn.cc +++ b/xtoskrnl/mm/pfn.cc @@ -138,6 +138,9 @@ MM::Pfn::DecrementAvailablePages(VOID) * @param PageFrameIndex * The page frame number of the physical page. * + * @param BeginStandbyList + * Determines whether the page should be added to the beginning of the standby list. + * * @return This routine does not return any value. * * @since XT 1.0 @@ -145,7 +148,8 @@ MM::Pfn::DecrementAvailablePages(VOID) XTAPI VOID MM::Pfn::DecrementReferenceCount(IN PMMPFN PageFrameNumber, - IN PFN_NUMBER PageFrameIndex) + IN PFN_NUMBER PageFrameIndex, + IN BOOLEAN BeginStandbyList) { /* Decrement the PFN reference count */ PageFrameNumber->u3.e2.ReferenceCount--; @@ -203,7 +207,15 @@ MM::Pfn::DecrementReferenceCount(IN PMMPFN PageFrameNumber, else { /* Link clean page to the standby list */ - LinkPage(&StandbyPagesList, PageFrameIndex); + if(BeginStandbyList) + { + UNIMPLEMENTED; + } + else + { + /* Link clean page to the end of the standby list */ + LinkPage(&StandbyPagesList, PageFrameIndex); + } } } } @@ -217,6 +229,9 @@ MM::Pfn::DecrementReferenceCount(IN PMMPFN PageFrameNumber, * @param PageFrameIndex * The page frame number of the physical page. * + * @param BeginStandbyList + * Determines whether the page should be added to the beginning of the standby list. + * * @return This routine does not return any value. * * @since XT 1.0 @@ -224,7 +239,8 @@ MM::Pfn::DecrementReferenceCount(IN PMMPFN PageFrameNumber, XTAPI VOID MM::Pfn::DecrementShareCount(IN PMMPFN PageFrameNumber, - IN PFN_NUMBER PageFrameIndex) + IN PFN_NUMBER PageFrameIndex, + IN BOOLEAN BeginStandbyList) { /* Ensure the page is in a valid state */ if((PageFrameNumber->u3.e1.PageLocation != ActiveAndValid) && @@ -280,7 +296,7 @@ MM::Pfn::DecrementShareCount(IN PMMPFN PageFrameNumber, else { /* The PTE can not be removed yet, decrement the reference count */ - DecrementReferenceCount(PageFrameNumber, PageFrameIndex); + DecrementReferenceCount(PageFrameNumber, PageFrameIndex, BeginStandbyList); } } else @@ -317,13 +333,13 @@ MM::Pfn::FreePhysicalPage(IN PMMPTE PointerPte) PageTableFrame = MM::Pfn::GetPfnEntry(PageTableFrameNumber); /* Decrement the share count of the page table */ - MM::Pfn::DecrementShareCount(PageTableFrame, PageTableFrameNumber); + MM::Pfn::DecrementShareCount(PageTableFrame, PageTableFrameNumber, FALSE); /* Mark the PTE as being ready for removal */ MM::Paging::SetPte(PageFrame->PteAddress, MM::Paging::GetPte(PageFrame->PteAddress) | 1); /* Decrement the share count of the page */ - MM::Pfn::DecrementShareCount(PageFrame, PageFrameNumber); + MM::Pfn::DecrementShareCount(PageFrame, PageFrameNumber, FALSE); } /** -- 2.52.0 From 4b50278ac939f56f0633a475d4bcbd3bda5e456f Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Mon, 5 Jan 2026 19:41:46 +0100 Subject: [PATCH 100/166] Add temporary fallback for BeginStandbyList insertion --- xtoskrnl/mm/pfn.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/xtoskrnl/mm/pfn.cc b/xtoskrnl/mm/pfn.cc index 40e5c30..0a58a71 100644 --- a/xtoskrnl/mm/pfn.cc +++ b/xtoskrnl/mm/pfn.cc @@ -210,6 +210,9 @@ MM::Pfn::DecrementReferenceCount(IN PMMPFN PageFrameNumber, if(BeginStandbyList) { UNIMPLEMENTED; + + /* Temporarily link clean page to the end of the standby list */ + LinkPage(&StandbyPagesList, PageFrameIndex); } else { -- 2.52.0 From bd1a3605d220b86dfa6921d6d4e998623f6845ed Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Mon, 5 Jan 2026 23:12:58 +0100 Subject: [PATCH 101/166] Add logic to insert pages at the head of standby list --- xtoskrnl/includes/mm/pfn.hh | 1 + xtoskrnl/mm/pfn.cc | 91 +++++++++++++++++++++++++++++++++++-- 2 files changed, 88 insertions(+), 4 deletions(-) diff --git a/xtoskrnl/includes/mm/pfn.hh b/xtoskrnl/includes/mm/pfn.hh index 0839d80..efca193 100644 --- a/xtoskrnl/includes/mm/pfn.hh +++ b/xtoskrnl/includes/mm/pfn.hh @@ -65,6 +65,7 @@ namespace MM IN PFN_NUMBER PageFrameIndex); STATIC XTAPI VOID LinkPfnForPageTable(IN PFN_NUMBER PageFrameIndex, IN PMMPTE PointerPte); + STATIC XTFASTCALL VOID LinkStandbyPage(IN PFN_NUMBER PageFrameIndex); STATIC XTAPI VOID ProcessMemoryDescriptor(IN PFN_NUMBER BasePage, IN PFN_NUMBER PageCount, IN LOADER_MEMORY_TYPE MemoryType); diff --git a/xtoskrnl/mm/pfn.cc b/xtoskrnl/mm/pfn.cc index 0a58a71..164526c 100644 --- a/xtoskrnl/mm/pfn.cc +++ b/xtoskrnl/mm/pfn.cc @@ -209,10 +209,8 @@ MM::Pfn::DecrementReferenceCount(IN PMMPFN PageFrameNumber, /* Link clean page to the standby list */ if(BeginStandbyList) { - UNIMPLEMENTED; - - /* Temporarily link clean page to the end of the standby list */ - LinkPage(&StandbyPagesList, PageFrameIndex); + /* Link clean page to the beginning of the standby list */ + LinkStandbyPage(PageFrameIndex); } else { @@ -866,6 +864,91 @@ MM::Pfn::LinkPfnToPte(IN PFN_NUMBER PageFrameIndex, Pfn->u2.ShareCount++; } +/** + * Links a page to the beginning of the appropriate standby or ROM list. + * + * @param PageFrameIndex + * The Page Frame Number (PFN) of the page to link. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ + +XTFASTCALL +VOID +MM::Pfn::LinkStandbyPage(IN PFN_NUMBER PageFrameIndex) +{ + PMMPFN AdjacentPageFrame, CurrentPageFrame; + PMMMEMORY_LAYOUT MemoryLayout; + PFN_NUMBER Flink; + + /* Get the memory layout */ + MemoryLayout = MM::Manager::GetMemoryLayout(); + + /* Get the PFN database entry for the target page */ + CurrentPageFrame = &((PMMPFN)MemoryLayout->PfnDatabaseAddress)[PageFrameIndex]; + + /* Check if the page is part of a ROM image */ + if(CurrentPageFrame->u3.e1.Rom == 1) + { + /* Increment the total number of ROM pages */ + RomPagesList.Total++; + + /* If the ROM list is not empty, link the new page */ + if(RomPagesList.Blink != (ULONG_PTR)-1) + { + /* Update the old tail to point to the new page */ + AdjacentPageFrame = &((PMMPFN)MemoryLayout->PfnDatabaseAddress)[RomPagesList.Blink]; + AdjacentPageFrame->u1.Flink = PageFrameIndex; + } + else + { + /* Otherwise, this page is now the head of the list */ + RomPagesList.Flink = PageFrameIndex; + } + + /* Set the new page as the tail and update its links */ + RomPagesList.Blink = PageFrameIndex; + CurrentPageFrame->u1.Flink = (ULONG_PTR)-1; + CurrentPageFrame->u2.Blink = RomPagesList.Blink; + CurrentPageFrame->u3.e1.PageLocation = StandbyPageList; + + /* ROM pages require no further processing */ + return; + } + + /* Increment the count of pages on the standby list */ + StandbyPagesList.Total++; + + /* Save the old head and set the current page as the new head */ + Flink = StandbyPagesList.Flink; + StandbyPagesList.Flink = PageFrameIndex; + + /* Point the new head to the old one, marking it as the list front */ + CurrentPageFrame->u1.Flink = Flink; + CurrentPageFrame->u2.Blink = MAXULONG_PTR; + + /* If the ROM list is not empty, link the new page */ + if(Flink != MAXULONG_PTR) + { + /* Update the old head to point to the new page */ + AdjacentPageFrame = &((PMMPFN)MemoryLayout->PfnDatabaseAddress)[Flink]; + AdjacentPageFrame->u2.Blink = PageFrameIndex; + } + else + { + /* Otherwise, this page is now the tail of the list */ + StandbyPagesList.Blink = PageFrameIndex; + } + + /* Update the page's location to the standby list */ + CurrentPageFrame->u3.e1.PageLocation = StandbyPageList; + + /* Increment number of available pages */ + IncrementAvailablePages(); +} + /** * Processes a memory descriptor and initializes the corresponding PFN database entries * -- 2.52.0 From 9027632c4f81a78edca7c6449f36b34d4e79181a Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Mon, 5 Jan 2026 23:39:42 +0100 Subject: [PATCH 102/166] Make memory descriptor processing architecture-dependent --- xtoskrnl/mm/amd64/pfn.cc | 84 ++++++++++++++++++++++++++++++++++++++++ xtoskrnl/mm/i686/pfn.cc | 84 ++++++++++++++++++++++++++++++++++++++++ xtoskrnl/mm/pfn.cc | 84 ---------------------------------------- 3 files changed, 168 insertions(+), 84 deletions(-) diff --git a/xtoskrnl/mm/amd64/pfn.cc b/xtoskrnl/mm/amd64/pfn.cc index caa864f..fd25f3c 100644 --- a/xtoskrnl/mm/amd64/pfn.cc +++ b/xtoskrnl/mm/amd64/pfn.cc @@ -167,6 +167,90 @@ MM::Pfn::InitializePageTablePfns(VOID) } } +/** + * Processes a memory descriptor and initializes the corresponding PFN database entries + * + * @param BasePage + * The starting physical page number of the memory run + * + * @param PageCount + * The number of pages in the memory run + * + * @param MemoryType + * The type of memory as reported by the bootloader (e.g., free, ROM, in-use) + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::Pfn::ProcessMemoryDescriptor(IN PFN_NUMBER BasePage, + IN PFN_NUMBER PageCount, + IN LOADER_MEMORY_TYPE MemoryType) +{ + PFN_NUMBER CurrentPage, PageNumber; + PMMPFN Pfn; + + /* Check if the memory descriptor describes a free memory region */ + if(MM::Manager::VerifyMemoryTypeFree(MemoryType)) + { + /* Iterate over each page in this free memory run */ + for(PageNumber = 0; PageNumber < PageCount; PageNumber++) + { + /* Get the PFN entry for the current page and set its initial cache attribute */ + CurrentPage = BasePage + PageNumber; + Pfn = GetPfnEntry(CurrentPage); + Pfn->u3.e1.CacheAttribute = PfnNonCached; + + /* Add the page to the free list to make it available for allocation */ + LinkFreePage(CurrentPage); + } + } + else + { + /* Handle all other (non-free) memory types */ + switch(MemoryType) + { + case LoaderBad: + /* This memory is marked as bad and should not be used, add it to the bad pages list */ + LinkPage(&BadPagesList, BasePage); + break; + case LoaderXIPRom: + /* This memory range contains Read-Only Memory (ROM) */ + for(PageNumber = 0; PageNumber < PageCount; PageNumber++) + { + /* Get the PFN entry for the current ROM page */ + Pfn = GetPfnEntry(BasePage + PageNumber); + + /* Initialize the PFN entry to represent a ROM page */ + Pfn->PteAddress = 0; + Pfn->u1.Flink = 0; + Pfn->u2.ShareCount = 0; + Pfn->u3.e1.CacheAttribute = PfnNonCached; + Pfn->u3.e1.PageLocation = 0; + Pfn->u3.e1.PrototypePte = 1; + Pfn->u3.e1.Rom = 1; + Pfn->u3.e2.ReferenceCount = 0; + Pfn->u4.InPageError = 0; + Pfn->u4.PteFrame = 0; + } + break; + default: + /* All other types are considered in-use (ie, by the kernel, ACPI, etc) */ + for(PageNumber = 0; PageNumber < PageCount; PageNumber++) + { + /* Get the PFN entry for the current in-use page */ + Pfn = GetPfnEntry(BasePage + PageNumber); + + /* Mark the PFN as active and valid to prevent it from being allocated */ + Pfn->u3.e1.PageLocation = ActiveAndValid; + } + break; + } + } +} + /** * Recursively scans a page table to initialize PFN database entries for active pages. * diff --git a/xtoskrnl/mm/i686/pfn.cc b/xtoskrnl/mm/i686/pfn.cc index 030f97c..5af5508 100644 --- a/xtoskrnl/mm/i686/pfn.cc +++ b/xtoskrnl/mm/i686/pfn.cc @@ -155,6 +155,90 @@ MM::Pfn::InitializePageTablePfns(VOID) } } +/** + * Processes a memory descriptor and initializes the corresponding PFN database entries + * + * @param BasePage + * The starting physical page number of the memory run + * + * @param PageCount + * The number of pages in the memory run + * + * @param MemoryType + * The type of memory as reported by the bootloader (e.g., free, ROM, in-use) + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::Pfn::ProcessMemoryDescriptor(IN PFN_NUMBER BasePage, + IN PFN_NUMBER PageCount, + IN LOADER_MEMORY_TYPE MemoryType) +{ + PFN_NUMBER CurrentPage, PageNumber; + PMMPFN Pfn; + + /* Check if the memory descriptor describes a free memory region */ + if(MM::Manager::VerifyMemoryTypeFree(MemoryType)) + { + /* Iterate over each page in this free memory run */ + for(PageNumber = 0; PageNumber < PageCount; PageNumber++) + { + /* Get the PFN entry for the current page and set its initial cache attribute */ + CurrentPage = BasePage + PageNumber; + Pfn = GetPfnEntry(CurrentPage); + Pfn->u3.e1.CacheAttribute = PfnNonCached; + + /* Add the page to the free list to make it available for allocation */ + LinkFreePage(CurrentPage); + } + } + else + { + /* Handle all other (non-free) memory types */ + switch(MemoryType) + { + case LoaderBad: + /* This memory is marked as bad and should not be used, add it to the bad pages list */ + LinkPage(&BadPagesList, BasePage); + break; + case LoaderXIPRom: + /* This memory range contains Read-Only Memory (ROM) */ + for(PageNumber = 0; PageNumber < PageCount; PageNumber++) + { + /* Get the PFN entry for the current ROM page */ + Pfn = GetPfnEntry(BasePage + PageNumber); + + /* Initialize the PFN entry to represent a ROM page */ + Pfn->PteAddress = 0; + Pfn->u1.Flink = 0; + Pfn->u2.ShareCount = 0; + Pfn->u3.e1.CacheAttribute = PfnNonCached; + Pfn->u3.e1.PageLocation = 0; + Pfn->u3.e1.PrototypePte = 1; + Pfn->u3.e1.Rom = 1; + Pfn->u3.e2.ReferenceCount = 0; + Pfn->u4.InPageError = 0; + Pfn->u4.PteFrame = 0; + } + break; + default: + /* All other types are considered in-use (ie, by the kernel, ACPI, etc) */ + for(PageNumber = 0; PageNumber < PageCount; PageNumber++) + { + /* Get the PFN entry for the current in-use page */ + Pfn = GetPfnEntry(BasePage + PageNumber); + + /* Mark the PFN as active and valid to prevent it from being allocated */ + Pfn->u3.e1.PageLocation = ActiveAndValid; + } + break; + } + } +} + /** * Recursively scans a page table to initialize PFN database entries for active pages. * diff --git a/xtoskrnl/mm/pfn.cc b/xtoskrnl/mm/pfn.cc index 164526c..5372154 100644 --- a/xtoskrnl/mm/pfn.cc +++ b/xtoskrnl/mm/pfn.cc @@ -949,90 +949,6 @@ MM::Pfn::LinkStandbyPage(IN PFN_NUMBER PageFrameIndex) IncrementAvailablePages(); } -/** - * Processes a memory descriptor and initializes the corresponding PFN database entries - * - * @param BasePage - * The starting physical page number of the memory run - * - * @param PageCount - * The number of pages in the memory run - * - * @param MemoryType - * The type of memory as reported by the bootloader (e.g., free, ROM, in-use) - * - * @return This routine does not return any value. - * - * @since XT 1.0 - */ -XTAPI -VOID -MM::Pfn::ProcessMemoryDescriptor(IN PFN_NUMBER BasePage, - IN PFN_NUMBER PageCount, - IN LOADER_MEMORY_TYPE MemoryType) -{ - PFN_NUMBER CurrentPage, PageNumber; - PMMPFN Pfn; - - /* Check if the memory descriptor describes a free memory region */ - if(MM::Manager::VerifyMemoryTypeFree(MemoryType)) - { - /* Iterate over each page in this free memory run */ - for(PageNumber = 0; PageNumber < PageCount; PageNumber++) - { - /* Get the PFN entry for the current page and set its initial cache attribute */ - CurrentPage = BasePage + PageNumber; - Pfn = GetPfnEntry(CurrentPage); - Pfn->u3.e1.CacheAttribute = PfnNonCached; - - /* Add the page to the free list to make it available for allocation */ - LinkFreePage(CurrentPage); - } - } - else - { - /* Handle all other (non-free) memory types */ - switch(MemoryType) - { - case LoaderBad: - /* This memory is marked as bad and should not be used, add it to the bad pages list */ - LinkPage(&BadPagesList, BasePage); - break; - case LoaderXIPRom: - /* This memory range contains Read-Only Memory (ROM) */ - for(PageNumber = 0; PageNumber < PageCount; PageNumber++) - { - /* Get the PFN entry for the current ROM page */ - Pfn = GetPfnEntry(BasePage + PageNumber); - - /* Initialize the PFN entry to represent a ROM page */ - Pfn->PteAddress = 0; - Pfn->u1.Flink = 0; - Pfn->u2.ShareCount = 0; - Pfn->u3.e1.CacheAttribute = PfnNonCached; - Pfn->u3.e1.PageLocation = 0; - Pfn->u3.e1.PrototypePte = 1; - Pfn->u3.e1.Rom = 1; - Pfn->u3.e2.ReferenceCount = 0; - Pfn->u4.InPageError = 0; - Pfn->u4.PteFrame = 0; - } - break; - default: - /* All other types are considered in-use (ie, by the kernel, ACPI, etc) */ - for(PageNumber = 0; PageNumber < PageCount; PageNumber++) - { - /* Get the PFN entry for the current in-use page */ - Pfn = GetPfnEntry(BasePage + PageNumber); - - /* Mark the PFN as active and valid to prevent it from being allocated */ - Pfn->u3.e1.PageLocation = ActiveAndValid; - } - break; - } - } -} - /** * Scans memory descriptors provided by the boot loader. * -- 2.52.0 From 36e53bfc8cd3ea4604156bd849efa39ece71e086 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Tue, 6 Jan 2026 14:05:09 +0100 Subject: [PATCH 103/166] Ensure every page in a bad memory region is marked as bad --- xtoskrnl/mm/amd64/pfn.cc | 8 ++++++-- xtoskrnl/mm/i686/pfn.cc | 8 ++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/xtoskrnl/mm/amd64/pfn.cc b/xtoskrnl/mm/amd64/pfn.cc index fd25f3c..3f5c952 100644 --- a/xtoskrnl/mm/amd64/pfn.cc +++ b/xtoskrnl/mm/amd64/pfn.cc @@ -213,8 +213,12 @@ MM::Pfn::ProcessMemoryDescriptor(IN PFN_NUMBER BasePage, switch(MemoryType) { case LoaderBad: - /* This memory is marked as bad and should not be used, add it to the bad pages list */ - LinkPage(&BadPagesList, BasePage); + /* This memory is marked as bad and should not be used */ + for(PageNumber = 0; PageNumber < PageCount; PageNumber++) + { + /* Link the page to the bad pages list */ + LinkPage(&BadPagesList, BasePage + PageNumber); + } break; case LoaderXIPRom: /* This memory range contains Read-Only Memory (ROM) */ diff --git a/xtoskrnl/mm/i686/pfn.cc b/xtoskrnl/mm/i686/pfn.cc index 5af5508..89403a7 100644 --- a/xtoskrnl/mm/i686/pfn.cc +++ b/xtoskrnl/mm/i686/pfn.cc @@ -201,8 +201,12 @@ MM::Pfn::ProcessMemoryDescriptor(IN PFN_NUMBER BasePage, switch(MemoryType) { case LoaderBad: - /* This memory is marked as bad and should not be used, add it to the bad pages list */ - LinkPage(&BadPagesList, BasePage); + /* This memory is marked as bad and should not be used */ + for(PageNumber = 0; PageNumber < PageCount; PageNumber++) + { + /* Link the page to the bad pages list */ + LinkPage(&BadPagesList, BasePage + PageNumber); + } break; case LoaderXIPRom: /* This memory range contains Read-Only Memory (ROM) */ -- 2.52.0 From bee91d0c71dba813d2b29a9801f187994f644fec Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Tue, 6 Jan 2026 14:49:30 +0100 Subject: [PATCH 104/166] Correctly setup PFN database for ROM and in-use pages --- xtoskrnl/mm/i686/pfn.cc | 55 ++++++++++++++++++++++++++--------------- 1 file changed, 35 insertions(+), 20 deletions(-) diff --git a/xtoskrnl/mm/i686/pfn.cc b/xtoskrnl/mm/i686/pfn.cc index 89403a7..c44949c 100644 --- a/xtoskrnl/mm/i686/pfn.cc +++ b/xtoskrnl/mm/i686/pfn.cc @@ -177,7 +177,8 @@ MM::Pfn::ProcessMemoryDescriptor(IN PFN_NUMBER BasePage, IN PFN_NUMBER PageCount, IN LOADER_MEMORY_TYPE MemoryType) { - PFN_NUMBER CurrentPage, PageNumber; + PFN_NUMBER PageNumber; + PMMPDE PointerPde; PMMPFN Pfn; /* Check if the memory descriptor describes a free memory region */ @@ -186,13 +187,8 @@ MM::Pfn::ProcessMemoryDescriptor(IN PFN_NUMBER BasePage, /* Iterate over each page in this free memory run */ for(PageNumber = 0; PageNumber < PageCount; PageNumber++) { - /* Get the PFN entry for the current page and set its initial cache attribute */ - CurrentPage = BasePage + PageNumber; - Pfn = GetPfnEntry(CurrentPage); - Pfn->u3.e1.CacheAttribute = PfnNonCached; - /* Add the page to the free list to make it available for allocation */ - LinkFreePage(CurrentPage); + LinkFreePage(BasePage + PageNumber); } } else @@ -215,17 +211,24 @@ MM::Pfn::ProcessMemoryDescriptor(IN PFN_NUMBER BasePage, /* Get the PFN entry for the current ROM page */ Pfn = GetPfnEntry(BasePage + PageNumber); - /* Initialize the PFN entry to represent a ROM page */ - Pfn->PteAddress = 0; - Pfn->u1.Flink = 0; - Pfn->u2.ShareCount = 0; - Pfn->u3.e1.CacheAttribute = PfnNonCached; - Pfn->u3.e1.PageLocation = 0; - Pfn->u3.e1.PrototypePte = 1; - Pfn->u3.e1.Rom = 1; - Pfn->u3.e2.ReferenceCount = 0; - Pfn->u4.InPageError = 0; - Pfn->u4.PteFrame = 0; + /* Ensure that the page is not already in-use */ + if(Pfn->u3.e2.ReferenceCount == 0) + { + /* Get the page directory entry for the current page */ + PointerPde = MM::Paging::GetPdeAddress((PVOID)(KSEG0_BASE + (BasePage << MM_PAGE_SHIFT))); + + /* Initialize the PFN entry to represent a ROM page */ + Pfn->PteAddress = MM::Paging::GetPteAddress((PVOID)(KSEG0_BASE + (BasePage << MM_PAGE_SHIFT))); + Pfn->u1.Flink = 0; + Pfn->u2.ShareCount = 0; + Pfn->u3.e1.CacheAttribute = PfnNonCached; + Pfn->u3.e1.PageLocation = 0; + Pfn->u3.e1.PrototypePte = 1; + Pfn->u3.e1.Rom = 1; + Pfn->u3.e2.ReferenceCount = 0; + Pfn->u4.InPageError = 0; + Pfn->u4.PteFrame = MM::Paging::GetPageFrameNumber(PointerPde); + } } break; default: @@ -235,8 +238,20 @@ MM::Pfn::ProcessMemoryDescriptor(IN PFN_NUMBER BasePage, /* Get the PFN entry for the current in-use page */ Pfn = GetPfnEntry(BasePage + PageNumber); - /* Mark the PFN as active and valid to prevent it from being allocated */ - Pfn->u3.e1.PageLocation = ActiveAndValid; + /* Ensure that the page is not already in-use */ + if(Pfn->u3.e2.ReferenceCount == 0) + { + /* Get the page directory entry for the current page */ + PointerPde = MM::Paging::GetPdeAddress((PVOID)(KSEG0_BASE + (BasePage << MM_PAGE_SHIFT))); + + /* Initialize the PFN entry to represent an in-use page and prevent it from being allocated */ + Pfn->PteAddress = MM::Paging::GetPteAddress((PVOID)(KSEG0_BASE + (BasePage << MM_PAGE_SHIFT))); + Pfn->u2.ShareCount++; + Pfn->u3.e1.CacheAttribute = PfnNonCached; + Pfn->u3.e1.PageLocation = ActiveAndValid; + Pfn->u3.e2.ReferenceCount = 1; + Pfn->u4.PteFrame = MM::Paging::GetPageFrameNumber(PointerPde); + } } break; } -- 2.52.0 From b91c79e0907af062e723280dbe347ef19711384a Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Tue, 6 Jan 2026 15:01:05 +0100 Subject: [PATCH 105/166] Prevent adding referenced pages to the free list --- xtoskrnl/mm/amd64/pfn.cc | 16 ++++++++-------- xtoskrnl/mm/i686/pfn.cc | 9 +++++++-- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/xtoskrnl/mm/amd64/pfn.cc b/xtoskrnl/mm/amd64/pfn.cc index 3f5c952..dd14489 100644 --- a/xtoskrnl/mm/amd64/pfn.cc +++ b/xtoskrnl/mm/amd64/pfn.cc @@ -189,7 +189,7 @@ MM::Pfn::ProcessMemoryDescriptor(IN PFN_NUMBER BasePage, IN PFN_NUMBER PageCount, IN LOADER_MEMORY_TYPE MemoryType) { - PFN_NUMBER CurrentPage, PageNumber; + PFN_NUMBER PageNumber; PMMPFN Pfn; /* Check if the memory descriptor describes a free memory region */ @@ -198,13 +198,13 @@ MM::Pfn::ProcessMemoryDescriptor(IN PFN_NUMBER BasePage, /* Iterate over each page in this free memory run */ for(PageNumber = 0; PageNumber < PageCount; PageNumber++) { - /* Get the PFN entry for the current page and set its initial cache attribute */ - CurrentPage = BasePage + PageNumber; - Pfn = GetPfnEntry(CurrentPage); - Pfn->u3.e1.CacheAttribute = PfnNonCached; - - /* Add the page to the free list to make it available for allocation */ - LinkFreePage(CurrentPage); + /* Get the PFN entry for the current page and ensure it is not referenced */ + Pfn = GetPfnEntry(BasePage + PageNumber); + if(Pfn->u3.e2.ReferenceCount == 0) + { + /* Add the page to the free list to make it available for allocation */ + LinkFreePage(BasePage + PageNumber); + } } } else diff --git a/xtoskrnl/mm/i686/pfn.cc b/xtoskrnl/mm/i686/pfn.cc index c44949c..9218e36 100644 --- a/xtoskrnl/mm/i686/pfn.cc +++ b/xtoskrnl/mm/i686/pfn.cc @@ -187,8 +187,13 @@ MM::Pfn::ProcessMemoryDescriptor(IN PFN_NUMBER BasePage, /* Iterate over each page in this free memory run */ for(PageNumber = 0; PageNumber < PageCount; PageNumber++) { - /* Add the page to the free list to make it available for allocation */ - LinkFreePage(BasePage + PageNumber); + /* Get the PFN entry for the current page and ensure it is not referenced */ + Pfn = GetPfnEntry(BasePage + PageNumber); + if(Pfn->u3.e2.ReferenceCount == 0) + { + /* Add the page to the free list to make it available for allocation */ + LinkFreePage(BasePage + PageNumber); + } } } else -- 2.52.0 From 9ed851ed1f99a2827b85a8a8c5d99b7d2c80a06b Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Fri, 9 Jan 2026 20:54:13 +0100 Subject: [PATCH 106/166] Temporary fix for PAE addressing limits and KSEG0 base mapping --- boot/xtldr/arch/amd64/memory.cc | 16 ++--- boot/xtldr/arch/i686/memory.cc | 14 ++-- boot/xtldr/includes/xtldr.hh | 10 +-- boot/xtldr/memory.cc | 104 ++++++++++++++---------------- boot/xtldr/modules/xtos_o/xtos.cc | 16 ++--- sdk/xtdk/bltypes.h | 8 +-- 6 files changed, 82 insertions(+), 86 deletions(-) diff --git a/boot/xtldr/arch/amd64/memory.cc b/boot/xtldr/arch/amd64/memory.cc index 3f8f049..ebe6f0b 100644 --- a/boot/xtldr/arch/amd64/memory.cc +++ b/boot/xtldr/arch/amd64/memory.cc @@ -45,7 +45,7 @@ Memory::BuildPageMap(IN PXTBL_PAGE_MAPPING PageMap, } /* Add new memory mapping for the page map itself */ - Status = MapVirtualMemory(PageMap, (PVOID)(UINT_PTR)Address, (PVOID)(UINT_PTR)Address, 1, LoaderMemoryData); + Status = MapVirtualMemory(PageMap, Address, Address, 1, LoaderMemoryData); if(Status != STATUS_EFI_SUCCESS) { /* Memory mapping failure */ @@ -65,7 +65,7 @@ Memory::BuildPageMap(IN PXTBL_PAGE_MAPPING PageMap, } /* Map the trampoline code area */ - Status = MapVirtualMemory(PageMap, (PVOID)MM_TRAMPOLINE_ADDRESS,(PVOID)MM_TRAMPOLINE_ADDRESS, + Status = MapVirtualMemory(PageMap, MM_TRAMPOLINE_ADDRESS,MM_TRAMPOLINE_ADDRESS, 1, LoaderFirmwareTemporary); if(Status != STATUS_EFI_SUCCESS) { @@ -82,7 +82,7 @@ Memory::BuildPageMap(IN PXTBL_PAGE_MAPPING PageMap, ModuleInfo = CONTAIN_RECORD(ModulesListEntry, XTBL_MODULE_INFO, Flink); /* Map module code */ - Status = MapVirtualMemory(PageMap, ModuleInfo->ModuleBase, ModuleInfo->ModuleBase, + Status = MapVirtualMemory(PageMap, (ULONGLONG)ModuleInfo->ModuleBase, (ULONGLONG)ModuleInfo->ModuleBase, EFI_SIZE_TO_PAGES(ModuleInfo->ModuleSize), LoaderFirmwareTemporary); /* Check if mapping succeeded */ @@ -103,7 +103,7 @@ Memory::BuildPageMap(IN PXTBL_PAGE_MAPPING PageMap, if(LoaderBase && LoaderSize) { /* Map boot loader code as well */ - Status = MapVirtualMemory(PageMap, LoaderBase, LoaderBase, + Status = MapVirtualMemory(PageMap, (ULONGLONG)LoaderBase, (ULONGLONG)LoaderBase, EFI_SIZE_TO_PAGES(LoaderSize), LoaderFirmwareTemporary); if(Status != STATUS_EFI_SUCCESS) { @@ -201,7 +201,7 @@ Memory::GetNextPageTable(IN PXTBL_PAGE_MAPPING PageMap, } /* Add new memory mapping */ - Status = MapVirtualMemory(PageMap, (PVOID)(UINT_PTR)Address, (PVOID)(UINT_PTR)Address, 1, LoaderMemoryData); + Status = MapVirtualMemory(PageMap, Address, Address, 1, LoaderMemoryData); if(Status != STATUS_EFI_SUCCESS) { /* Memory mapping failure */ @@ -247,9 +247,9 @@ Memory::GetNextPageTable(IN PXTBL_PAGE_MAPPING PageMap, XTCDECL EFI_STATUS Memory::MapPage(IN PXTBL_PAGE_MAPPING PageMap, - IN ULONG_PTR VirtualAddress, - IN ULONG_PTR PhysicalAddress, - IN ULONG NumberOfPages) + IN ULONGLONG VirtualAddress, + IN ULONGLONG PhysicalAddress, + IN ULONGLONG NumberOfPages) { PVOID Pml1, Pml2, Pml3, Pml4, Pml5; SIZE_T Pml1Entry, Pml2Entry, Pml3Entry, Pml4Entry, Pml5Entry; diff --git a/boot/xtldr/arch/i686/memory.cc b/boot/xtldr/arch/i686/memory.cc index a194d2d..a6c65da 100644 --- a/boot/xtldr/arch/i686/memory.cc +++ b/boot/xtldr/arch/i686/memory.cc @@ -93,7 +93,7 @@ Memory::BuildPageMap(IN PXTBL_PAGE_MAPPING PageMap, } /* Map the trampoline code area */ - Status = MapVirtualMemory(PageMap, (PVOID)MM_TRAMPOLINE_ADDRESS,(PVOID)MM_TRAMPOLINE_ADDRESS, + Status = MapVirtualMemory(PageMap, MM_TRAMPOLINE_ADDRESS,MM_TRAMPOLINE_ADDRESS, 1, LoaderFirmwareTemporary); if(Status != STATUS_EFI_SUCCESS) { @@ -110,7 +110,7 @@ Memory::BuildPageMap(IN PXTBL_PAGE_MAPPING PageMap, ModuleInfo = CONTAIN_RECORD(ModulesListEntry, XTBL_MODULE_INFO, Flink); /* Map module code */ - Status = MapVirtualMemory(PageMap, ModuleInfo->ModuleBase, ModuleInfo->ModuleBase, + Status = MapVirtualMemory(PageMap, (ULONGLONG)ModuleInfo->ModuleBase, (ULONGLONG)ModuleInfo->ModuleBase, EFI_SIZE_TO_PAGES(ModuleInfo->ModuleSize), LoaderFirmwareTemporary); /* Check if mapping succeeded */ @@ -131,7 +131,7 @@ Memory::BuildPageMap(IN PXTBL_PAGE_MAPPING PageMap, if(LoaderBase && LoaderSize) { /* Map boot loader code as well */ - Status = MapVirtualMemory(PageMap, LoaderBase, LoaderBase, + Status = MapVirtualMemory(PageMap, (ULONGLONG)LoaderBase, (ULONGLONG)LoaderBase, EFI_SIZE_TO_PAGES(LoaderSize), LoaderFirmwareTemporary); if(Status != STATUS_EFI_SUCCESS) { @@ -252,7 +252,7 @@ Memory::GetNextPageTable(IN PXTBL_PAGE_MAPPING PageMap, } /* Add new memory mapping */ - Status = MapVirtualMemory(PageMap, NULLPTR, (PVOID)(UINT_PTR)Address, 1, LoaderMemoryData); + Status = MapVirtualMemory(PageMap, (ULONGLONG)NULLPTR, Address, 1, LoaderMemoryData); if(Status != STATUS_EFI_SUCCESS) { /* Memory mapping failure */ @@ -313,9 +313,9 @@ Memory::GetNextPageTable(IN PXTBL_PAGE_MAPPING PageMap, XTCDECL EFI_STATUS Memory::MapPage(IN PXTBL_PAGE_MAPPING PageMap, - IN ULONG_PTR VirtualAddress, - IN ULONG_PTR PhysicalAddress, - IN ULONG NumberOfPages) + IN ULONGLONG VirtualAddress, + IN ULONGLONG PhysicalAddress, + IN ULONGLONG NumberOfPages) { SIZE_T PageFrameNumber; PVOID Pml1, Pml2, Pml3; diff --git a/boot/xtldr/includes/xtldr.hh b/boot/xtldr/includes/xtldr.hh index c8f71bd..cb91068 100644 --- a/boot/xtldr/includes/xtldr.hh +++ b/boot/xtldr/includes/xtldr.hh @@ -180,12 +180,12 @@ class Memory IN OUT PVOID *MemoryMapAddress, IN PBL_GET_MEMTYPE_ROUTINE GetMemoryTypeRoutine); STATIC XTCDECL EFI_STATUS MapPage(IN PXTBL_PAGE_MAPPING PageMap, - IN ULONG_PTR VirtualAddress, - IN ULONG_PTR PhysicalAddress, - IN ULONG NumberOfPages); + IN ULONGLONG VirtualAddress, + IN ULONGLONG PhysicalAddress, + IN ULONGLONG NumberOfPages); STATIC XTCDECL EFI_STATUS MapVirtualMemory(IN OUT PXTBL_PAGE_MAPPING PageMap, - IN PVOID VirtualAddress, - IN PVOID PhysicalAddress, + IN ULONGLONG VirtualAddress, + IN ULONGLONG PhysicalAddress, IN ULONGLONG NumberOfPages, IN LOADER_MEMORY_TYPE MemoryType); STATIC XTCDECL PVOID PhysicalAddressToVirtual(IN PVOID PhysicalAddress, diff --git a/boot/xtldr/memory.cc b/boot/xtldr/memory.cc index 91ff66d..89b9809 100644 --- a/boot/xtldr/memory.cc +++ b/boot/xtldr/memory.cc @@ -334,20 +334,10 @@ Memory::MapEfiMemory(IN OUT PXTBL_PAGE_MAPPING PageMap, LOADER_MEMORY_TYPE MemoryType; PEFI_MEMORY_MAP MemoryMap; SIZE_T DescriptorCount; - PUCHAR VirtualAddress; + ULONGLONG MaxAddress; EFI_STATUS Status; SIZE_T Index; - /* Set virtual address as specified in argument */ - VirtualAddress = (PUCHAR)*MemoryMapAddress; - - /* Check if custom memory type routine is specified */ - if(GetMemoryTypeRoutine == NULLPTR) - { - /* Use default memory type routine */ - GetMemoryTypeRoutine = GetLoaderMemoryType; - } - /* Allocate and zero-fill buffer for EFI memory map */ AllocatePool(sizeof(EFI_MEMORY_MAP), (PVOID*)&MemoryMap); RTL::Memory::ZeroMemory(MemoryMap, sizeof(EFI_MEMORY_MAP)); @@ -367,8 +357,37 @@ Memory::MapEfiMemory(IN OUT PXTBL_PAGE_MAPPING PageMap, /* Iterate through all descriptors from the memory map */ for(Index = 0; Index < DescriptorCount; Index++) { - /* Make sure descriptor does not start beyond lowest physical page */ - if(Descriptor->PhysicalStart <= MAXUINT_PTR) + /* Check page map level */ + if(PageMap->PageMapLevel == 2) + { + /* Limit physical address to 4GB in legacy mode */ + MaxAddress = 0xFFFFFFFF; + } + else if(PageMap->PageMapLevel == 3) + { + /* Limit physical address to 64GB in PAE mode */ + MaxAddress = 0xFFFFFFFFF; + } + + /* Check page map level */ + if(PageMap->PageMapLevel == 2 || PageMap->PageMapLevel == 3) + { + /* Check if physical address starts beyond 4GB */ + if(Descriptor->PhysicalStart > MaxAddress) + { + /* Go to the next descriptor */ + Descriptor = (PEFI_MEMORY_DESCRIPTOR)((PUCHAR)Descriptor + MemoryMap->DescriptorSize); + continue; + } + + /* Check if memory descriptor exceeds the lowest physical page */ + if(Descriptor->PhysicalStart + (Descriptor->NumberOfPages << EFI_PAGE_SHIFT) > MaxAddress) + { + /* Truncate memory descriptor to the 4GB */ + Descriptor->NumberOfPages = (((ULONGLONG)MaxAddress) - Descriptor->PhysicalStart) >> EFI_PAGE_SHIFT; + } + } + { /* Skip EFI reserved memory */ if(Descriptor->Type == EfiReservedMemoryType) @@ -378,48 +397,26 @@ Memory::MapEfiMemory(IN OUT PXTBL_PAGE_MAPPING PageMap, continue; } - /* Check if preparing page map level 2 (non-PAE i686) */ - if(PageMap->PageMapLevel == 2) - { - /* Check if physical address starts beyond 4GB */ - if(Descriptor->PhysicalStart > 0xFFFFFFFF) - { - /* Go to the next descriptor */ - Descriptor = (PEFI_MEMORY_DESCRIPTOR)((PUCHAR)Descriptor + MemoryMap->DescriptorSize); - continue; - } - - /* Check if memory descriptor exceeds the lowest physical page */ - if(Descriptor->PhysicalStart + (Descriptor->NumberOfPages << EFI_PAGE_SHIFT) > MAXULONG) - { - /* Truncate memory descriptor to the 4GB */ - Descriptor->NumberOfPages = (((ULONGLONG)MAXULONG + 1) - Descriptor->PhysicalStart) >> EFI_PAGE_SHIFT; - } - } - /* Convert EFI memory type into XTLDR memory type */ - MemoryType = GetMemoryTypeRoutine((EFI_MEMORY_TYPE)Descriptor->Type); + MemoryType = GetLoaderMemoryType((EFI_MEMORY_TYPE)Descriptor->Type); /* Do memory mappings depending on memory type */ if(MemoryType == LoaderFirmwareTemporary) { /* Map EFI firmware code */ - Status = MapVirtualMemory(PageMap, (PVOID)Descriptor->PhysicalStart, - (PVOID)Descriptor->PhysicalStart, Descriptor->NumberOfPages, MemoryType); + Status = MapVirtualMemory(PageMap, Descriptor->PhysicalStart, + Descriptor->PhysicalStart, Descriptor->NumberOfPages, MemoryType); } else if(MemoryType != LoaderFree) { /* Add any non-free memory mapping */ - Status = MapVirtualMemory(PageMap, VirtualAddress, (PVOID)Descriptor->PhysicalStart, + Status = MapVirtualMemory(PageMap, KSEG0_BASE + Descriptor->PhysicalStart, Descriptor->PhysicalStart, Descriptor->NumberOfPages, MemoryType); - - /* Calculate next valid virtual address */ - VirtualAddress += Descriptor->NumberOfPages * EFI_PAGE_SIZE; } else { /* Map all other memory as loader free */ - Status = MapVirtualMemory(PageMap, NULLPTR, (PVOID)Descriptor->PhysicalStart, + Status = MapVirtualMemory(PageMap, (ULONGLONG)NULLPTR, Descriptor->PhysicalStart, Descriptor->NumberOfPages, LoaderFree); } @@ -436,7 +433,7 @@ Memory::MapEfiMemory(IN OUT PXTBL_PAGE_MAPPING PageMap, } /* Always map first page */ - Status = MapVirtualMemory(PageMap, NULLPTR, (PVOID)0, 1, LoaderFirmwarePermanent); + Status = MapVirtualMemory(PageMap, (ULONGLONG)NULLPTR, 0, 1, LoaderFirmwarePermanent); if(Status != STATUS_EFI_SUCCESS) { /* Mapping failed */ @@ -444,7 +441,7 @@ Memory::MapEfiMemory(IN OUT PXTBL_PAGE_MAPPING PageMap, } /* Map BIOS ROM and VRAM */ - Status = MapVirtualMemory(PageMap, NULLPTR, (PVOID)0xA0000, 0x60, LoaderFirmwarePermanent); + Status = MapVirtualMemory(PageMap, (ULONGLONG)NULLPTR, 0xA0000, 0x60, LoaderFirmwarePermanent); if(Status != STATUS_EFI_SUCCESS) { /* Mapping failed */ @@ -452,7 +449,6 @@ Memory::MapEfiMemory(IN OUT PXTBL_PAGE_MAPPING PageMap, } /* Store next valid virtual address and return success */ - *MemoryMapAddress = VirtualAddress; return STATUS_EFI_SUCCESS; } @@ -481,13 +477,13 @@ Memory::MapEfiMemory(IN OUT PXTBL_PAGE_MAPPING PageMap, XTCDECL EFI_STATUS Memory::MapVirtualMemory(IN OUT PXTBL_PAGE_MAPPING PageMap, - IN PVOID VirtualAddress, - IN PVOID PhysicalAddress, + IN ULONGLONG VirtualAddress, + IN ULONGLONG PhysicalAddress, IN ULONGLONG NumberOfPages, IN LOADER_MEMORY_TYPE MemoryType) { PXTBL_MEMORY_MAPPING Mapping1, Mapping2, Mapping3; - PVOID PhysicalAddressEnd, PhysicalAddress2End; + ULONGLONG PhysicalAddressEnd, PhysicalAddress2End; PLIST_ENTRY ListEntry, MappingListEntry; SIZE_T NumberOfMappedPages; EFI_STATUS Status; @@ -507,7 +503,7 @@ Memory::MapVirtualMemory(IN OUT PXTBL_PAGE_MAPPING PageMap, Mapping1->MemoryType = MemoryType; /* Calculate the end of the physical address */ - PhysicalAddressEnd = (PVOID)((ULONG_PTR)PhysicalAddress + (NumberOfPages * EFI_PAGE_SIZE) - 1); + PhysicalAddressEnd = PhysicalAddress + (NumberOfPages * EFI_PAGE_SIZE) - 1; /* Iterate through all the mappings already set to insert new mapping at the correct place */ ListEntry = PageMap->MemoryMap.Flink; @@ -515,7 +511,7 @@ Memory::MapVirtualMemory(IN OUT PXTBL_PAGE_MAPPING PageMap, { /* Take a mapping from the list and calculate its end of physical address */ Mapping2 = CONTAIN_RECORD(ListEntry, XTBL_MEMORY_MAPPING, ListEntry); - PhysicalAddress2End = (PVOID)((ULONG_PTR)Mapping2->PhysicalAddress + (Mapping2->NumberOfPages * EFI_PAGE_SIZE) - 1); + PhysicalAddress2End = Mapping2->PhysicalAddress + (Mapping2->NumberOfPages * EFI_PAGE_SIZE) - 1; /* Check if new mapping is a subset of an existing mapping */ if(Mapping1->PhysicalAddress >= Mapping2->PhysicalAddress && PhysicalAddressEnd <= PhysicalAddress2End) @@ -539,7 +535,7 @@ Memory::MapVirtualMemory(IN OUT PXTBL_PAGE_MAPPING PageMap, } /* Calculate number of pages for this mapping */ - NumberOfMappedPages = ((PUCHAR)PhysicalAddress2End - (PUCHAR)PhysicalAddressEnd) / EFI_PAGE_SIZE; + NumberOfMappedPages = (PhysicalAddress2End - PhysicalAddressEnd) / EFI_PAGE_SIZE; if(NumberOfMappedPages > 0) { /* Pages associated to the mapping, allocate memory for it */ @@ -551,8 +547,8 @@ Memory::MapVirtualMemory(IN OUT PXTBL_PAGE_MAPPING PageMap, } /* Set mapping fields and insert it on the top */ - Mapping3->PhysicalAddress = (PUCHAR)PhysicalAddressEnd + 1; - Mapping3->VirtualAddress = NULLPTR; + Mapping3->PhysicalAddress = PhysicalAddressEnd + 1; + Mapping3->VirtualAddress = (ULONGLONG)NULLPTR; Mapping3->NumberOfPages = NumberOfMappedPages; Mapping3->MemoryType = Mapping2->MemoryType; RTL::LinkedList::InsertHeadList(&Mapping2->ListEntry, &Mapping3->ListEntry); @@ -561,7 +557,7 @@ Memory::MapVirtualMemory(IN OUT PXTBL_PAGE_MAPPING PageMap, /* Calculate number of pages and the end of the physical address */ Mapping2->NumberOfPages = ((PUCHAR)PhysicalAddressEnd + 1 - (PUCHAR)Mapping2->PhysicalAddress) / EFI_PAGE_SIZE; - PhysicalAddress2End = (PVOID)((ULONG_PTR)Mapping2->PhysicalAddress + (Mapping2->NumberOfPages * EFI_PAGE_SIZE) - 1); + PhysicalAddress2End = Mapping2->PhysicalAddress + (Mapping2->NumberOfPages * EFI_PAGE_SIZE) - 1; } /* Check if they overlap */ @@ -588,7 +584,7 @@ Memory::MapVirtualMemory(IN OUT PXTBL_PAGE_MAPPING PageMap, /* Set mapping fields and insert it on the top */ Mapping3->PhysicalAddress = Mapping1->PhysicalAddress; - Mapping3->VirtualAddress = NULLPTR; + Mapping3->VirtualAddress = (ULONGLONG)NULLPTR; Mapping3->NumberOfPages = NumberOfMappedPages; Mapping3->MemoryType = Mapping2->MemoryType; RTL::LinkedList::InsertHeadList(&Mapping2->ListEntry, &Mapping3->ListEntry); @@ -597,7 +593,7 @@ Memory::MapVirtualMemory(IN OUT PXTBL_PAGE_MAPPING PageMap, /* Calculate number of pages and the end of the physical address */ Mapping2->NumberOfPages = ((PUCHAR)Mapping1->PhysicalAddress - (PUCHAR)Mapping2->PhysicalAddress) / EFI_PAGE_SIZE; - PhysicalAddress2End = (PVOID)((ULONG_PTR)Mapping2->PhysicalAddress + (Mapping2->NumberOfPages * EFI_PAGE_SIZE) - 1); + PhysicalAddress2End = Mapping2->PhysicalAddress + (Mapping2->NumberOfPages * EFI_PAGE_SIZE) - 1; } /* Check if mapping is really needed */ diff --git a/boot/xtldr/modules/xtos_o/xtos.cc b/boot/xtldr/modules/xtos_o/xtos.cc index 2003161..3482003 100644 --- a/boot/xtldr/modules/xtos_o/xtos.cc +++ b/boot/xtldr/modules/xtos_o/xtos.cc @@ -206,7 +206,7 @@ Xtos::GetMemoryDescriptorList(IN PXTBL_PAGE_MAPPING PageMap, return Status; } - Status = XtLdrProtocol->Memory.MapVirtualMemory(PageMap, *VirtualAddress, (PVOID)Address, Pages, LoaderMemoryData); + Status = XtLdrProtocol->Memory.MapVirtualMemory(PageMap, (ULONGLONG)*VirtualAddress, Address, Pages, LoaderMemoryData); if(Status != STATUS_EFI_SUCCESS) { XtLdrProtocol->Memory.FreePages(Address, Pages); @@ -266,7 +266,7 @@ Xtos::GetSystemResourcesList(IN PXTBL_PAGE_MAPPING PageMap, { return Status; } - Status = XtLdrProtocol->Memory.MapVirtualMemory(PageMap, *VirtualAddress, (PVOID)Address, Pages, LoaderFirmwarePermanent); + Status = XtLdrProtocol->Memory.MapVirtualMemory(PageMap, (ULONGLONG)*VirtualAddress, Address, Pages, LoaderFirmwarePermanent); if(Status != STATUS_EFI_SUCCESS) { XtLdrProtocol->Memory.FreePages(Address, Pages); @@ -336,8 +336,8 @@ Xtos::GetSystemResourcesList(IN PXTBL_PAGE_MAPPING PageMap, FrameBufferResource->Header.VirtualAddress = *VirtualAddress; /* Map frame buffer memory */ - XtLdrProtocol->Memory.MapVirtualMemory(PageMap, FrameBufferResource->Header.VirtualAddress, - FrameBufferResource->Header.PhysicalAddress, + XtLdrProtocol->Memory.MapVirtualMemory(PageMap, (ULONGLONG)FrameBufferResource->Header.VirtualAddress, + (ULONGLONG)FrameBufferResource->Header.PhysicalAddress, FrameBufferPages, LoaderFirmwarePermanent); /* Close FrameBuffer protocol */ @@ -389,7 +389,7 @@ Xtos::InitializeApicBase(IN PXTBL_PAGE_MAPPING PageMap) } /* Map APIC base address */ - XtLdrProtocol->Memory.MapVirtualMemory(PageMap, (PVOID)APIC_BASE, ApicBaseAddress, 1, LoaderFirmwarePermanent); + XtLdrProtocol->Memory.MapVirtualMemory(PageMap, APIC_BASE, (ULONGLONG)ApicBaseAddress, 1, LoaderFirmwarePermanent); return STATUS_EFI_SUCCESS; } @@ -456,7 +456,7 @@ Xtos::InitializeLoaderBlock(IN PXTBL_PAGE_MAPPING PageMap, ParametersSize); /* Map kernel initialization block */ - XtLdrProtocol->Memory.MapVirtualMemory(PageMap, *VirtualAddress, (PVOID)LoaderBlock, + XtLdrProtocol->Memory.MapVirtualMemory(PageMap, (ULONGLONG)*VirtualAddress, (ULONGLONG)LoaderBlock, BlockPages, LoaderSystemBlock); /* Calculate next valid virtual address */ @@ -650,8 +650,8 @@ Xtos::RunBootSequence(IN PEFI_FILE_HANDLE BootDir, } /* Add kernel image memory mapping */ - Status = XtLdrProtocol->Memory.MapVirtualMemory(&PageMap, ImageContext->VirtualAddress, - ImageContext->PhysicalAddress, ImageContext->ImagePages, + Status = XtLdrProtocol->Memory.MapVirtualMemory(&PageMap, (ULONGLONG)ImageContext->VirtualAddress, + (ULONGLONG)ImageContext->PhysicalAddress, ImageContext->ImagePages, LoaderSystemCode); if(Status != STATUS_EFI_SUCCESS) { diff --git a/sdk/xtdk/bltypes.h b/sdk/xtdk/bltypes.h index 3ea3355..1f7f948 100644 --- a/sdk/xtdk/bltypes.h +++ b/sdk/xtdk/bltypes.h @@ -101,8 +101,8 @@ typedef VOID (XTCDECL *PBL_LLIST_INSERT_HEAD)(IN OUT PLIST_ENTRY ListHead, IN PL typedef VOID (XTCDECL *PBL_LLIST_INSERT_TAIL)(IN OUT PLIST_ENTRY ListHead, IN PLIST_ENTRY Entry); typedef VOID (XTCDECL *PBL_LLIST_REMOVE_ENTRY)(IN PLIST_ENTRY Entry); typedef EFI_STATUS (XTCDECL *PBL_MAP_EFI_MEMORY)(IN OUT PXTBL_PAGE_MAPPING PageMap, IN OUT PVOID *MemoryMapAddress, IN PBL_GET_MEMTYPE_ROUTINE GetMemoryTypeRoutine); -typedef EFI_STATUS (XTCDECL *PBL_MAP_PAGE)(IN PXTBL_PAGE_MAPPING PageMap, IN ULONG_PTR VirtualAddress, IN ULONG_PTR PhysicalAddress, IN ULONG NumberOfPages); -typedef EFI_STATUS (XTCDECL *PBL_MAP_VIRTUAL_MEMORY)(IN OUT PXTBL_PAGE_MAPPING PageMap, IN PVOID VirtualAddress, IN PVOID PhysicalAddress, IN ULONGLONG NumberOfPages, IN LOADER_MEMORY_TYPE MemoryType); +typedef EFI_STATUS (XTCDECL *PBL_MAP_PAGE)(IN PXTBL_PAGE_MAPPING PageMap, IN ULONGLONG VirtualAddress, IN ULONGLONG PhysicalAddress, IN ULONGLONG NumberOfPages); +typedef EFI_STATUS (XTCDECL *PBL_MAP_VIRTUAL_MEMORY)(IN OUT PXTBL_PAGE_MAPPING PageMap, IN ULONGLONG VirtualAddress, IN ULONGLONG PhysicalAddress, IN ULONGLONG NumberOfPages, IN LOADER_MEMORY_TYPE MemoryType); typedef VOID (XTAPI *PBL_MOVE_MEMORY)(IN OUT PVOID Destination, IN PCVOID Source, IN SIZE_T Length); typedef EFI_STATUS (XTCDECL *PBL_OPEN_VOLUME)(IN PEFI_DEVICE_PATH_PROTOCOL DevicePath, OUT PEFI_HANDLE DiskHandle, OUT PEFI_FILE_HANDLE *FsHandle); typedef EFI_STATUS (XTCDECL *PBL_OPEN_PROTOCOL)(OUT PEFI_HANDLE Handle, OUT PVOID *ProtocolHandler, IN PEFI_GUID ProtocolGuid); @@ -232,8 +232,8 @@ typedef struct _XTBL_KNOWN_BOOT_PROTOCOL typedef struct _XTBL_MEMORY_MAPPING { LIST_ENTRY ListEntry; - PVOID VirtualAddress; - PVOID PhysicalAddress; + ULONGLONG VirtualAddress; + ULONGLONG PhysicalAddress; ULONGLONG NumberOfPages; LOADER_MEMORY_TYPE MemoryType; } XTBL_MEMORY_MAPPING, *PXTBL_MEMORY_MAPPING; -- 2.52.0 From ec94e2341c124a89d97c2f78128d51900215b50d Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Sun, 11 Jan 2026 13:15:28 +0100 Subject: [PATCH 107/166] Relocate kernel and modules to KSEG0 memory space --- boot/xtldr/modules/pecoff/pecoff.cc | 2 +- boot/xtldr/modules/xtos_o/includes/xtos.hh | 21 ++----- boot/xtldr/modules/xtos_o/xtos.cc | 70 ++++++++++++++++++++-- 3 files changed, 70 insertions(+), 23 deletions(-) diff --git a/boot/xtldr/modules/pecoff/pecoff.cc b/boot/xtldr/modules/pecoff/pecoff.cc index 00f105a..7d9692c 100644 --- a/boot/xtldr/modules/pecoff/pecoff.cc +++ b/boot/xtldr/modules/pecoff/pecoff.cc @@ -729,11 +729,11 @@ PeCoff::RelocateLoadedImage(IN PPECOFF_IMAGE_CONTEXT Image) } else { - /* Check if loaded 32-bit PE32 image should be relocated */ /* Set relocation data directory and image base address */ DataDirectory = &Image->PeHeader->OptionalHeader32.DataDirectory[PECOFF_IMAGE_DIRECTORY_ENTRY_BASERELOC]; ImageBase = Image->PeHeader->OptionalHeader32.ImageBase; + /* Check if loaded 32-bit PE32 image should be relocated */ if(Image->PeHeader->OptionalHeader32.NumberOfRvaAndSizes <= PECOFF_IMAGE_DIRECTORY_ENTRY_BASERELOC || DataDirectory->VirtualAddress == 0 || DataDirectory->Size < sizeof(PECOFF_IMAGE_BASE_RELOCATION)) { diff --git a/boot/xtldr/modules/xtos_o/includes/xtos.hh b/boot/xtldr/modules/xtos_o/includes/xtos.hh index 4d70606..ea37111 100644 --- a/boot/xtldr/modules/xtos_o/includes/xtos.hh +++ b/boot/xtldr/modules/xtos_o/includes/xtos.hh @@ -33,12 +33,6 @@ class Xtos IN PEFI_SYSTEM_TABLE SystemTable); private: - STATIC XTCDECL EFI_STATUS AddVirtualMemoryMapping(IN PLIST_ENTRY MemoryMappings, - IN PVOID VirtualAddress, - IN PVOID PhysicalAddress, - IN UINT NumberOfPages, - IN LOADER_MEMORY_TYPE MemoryType); - STATIC XTCDECL LOADER_MEMORY_TYPE ConvertEfiMemoryType(IN EFI_MEMORY_TYPE EfiMemoryType); STATIC XTCDECL ULONG DeterminePagingLevel(IN CONST PWCHAR Parameters); STATIC XTCDECL EFI_STATUS EnablePaging(IN PXTBL_PAGE_MAPPING PageMap); STATIC XTCDECL VOID GetDisplayInformation(OUT PSYSTEM_RESOURCE_FRAMEBUFFER FrameBufferResource, @@ -51,26 +45,21 @@ class Xtos STATIC XTCDECL EFI_STATUS GetSystemResourcesList(IN PXTBL_PAGE_MAPPING PageMap, IN PVOID *VirtualAddress, OUT PLIST_ENTRY SystemResourcesList); - STATIC XTCDECL EFI_STATUS GetVirtualAddress(IN PLIST_ENTRY MemoryMappings, - IN PVOID PhysicalAddress, - OUT PVOID *VirtualAddress); STATIC XTCDECL EFI_STATUS InitializeApicBase(IN PXTBL_PAGE_MAPPING PageMap); STATIC XTCDECL EFI_STATUS InitializeLoaderBlock(IN PXTBL_PAGE_MAPPING PageMap, IN PVOID *VirtualAddress, IN PXTBL_BOOT_PARAMETERS Parameters); - STATIC XTCDECL EFI_STATUS InitializeVirtualMemory(IN OUT PLIST_ENTRY MemoryMappings, - IN OUT PVOID *MemoryMapAddress); STATIC XTCDECL EFI_STATUS LoadModule(IN PEFI_FILE_HANDLE BootDir, IN PWCHAR FileName, IN PVOID VirtualAddress, IN LOADER_MEMORY_TYPE MemoryType, OUT PPECOFF_IMAGE_CONTEXT *ImageContext); STATIC XTCDECL EFI_STATUS MapHardwareMemoryPool(IN PXTBL_PAGE_MAPPING PageMap); - STATIC XTCDECL EFI_STATUS MapVirtualMemory(IN PLIST_ENTRY MemoryMappings, - IN UINT_PTR VirtualAddress, - IN UINT_PTR PhysicalAddress, - IN UINT NumberOfPages, - IN OUT PVOID *PtePointer); + STATIC XTCDECL EFI_STATUS MapMemory(IN OUT PXTBL_PAGE_MAPPING PageMap, + IN ULONGLONG Address, + IN ULONG NumberOfPages, + IN LOADER_MEMORY_TYPE MemoryType, + IN BOOLEAN KernelMapping); STATIC XTCDECL EFI_STATUS RunBootSequence(IN PEFI_FILE_HANDLE BootDir, IN PXTBL_BOOT_PARAMETERS Parameters); }; diff --git a/boot/xtldr/modules/xtos_o/xtos.cc b/boot/xtldr/modules/xtos_o/xtos.cc index 3482003..e35331e 100644 --- a/boot/xtldr/modules/xtos_o/xtos.cc +++ b/boot/xtldr/modules/xtos_o/xtos.cc @@ -266,6 +266,7 @@ Xtos::GetSystemResourcesList(IN PXTBL_PAGE_MAPPING PageMap, { return Status; } + Status = XtLdrProtocol->Memory.MapVirtualMemory(PageMap, (ULONGLONG)*VirtualAddress, Address, Pages, LoaderFirmwarePermanent); if(Status != STATUS_EFI_SUCCESS) { @@ -545,8 +546,8 @@ Xtos::LoadModule(IN PEFI_FILE_HANDLE SystemDir, return Status; } - /* Load the PE/COFF image file */ - Status = PeCoffProtocol->LoadImage(ModuleHandle, MemoryType, VirtualAddress, (PVOID*)ImageContext); + /* Load the PE/COFF image file into memory */ + Status = PeCoffProtocol->LoadImage(ModuleHandle, MemoryType, NULLPTR, (PVOID*)ImageContext); if(Status != STATUS_EFI_SUCCESS) { /* Unable to load the file */ @@ -554,6 +555,15 @@ Xtos::LoadModule(IN PEFI_FILE_HANDLE SystemDir, return Status; } + /* Relocate the PE/COFF image file */ + Status = PeCoffProtocol->RelocateImage(*ImageContext, KSEG0_BASE + (ULONGLONG)(*ImageContext)->PhysicalAddress); + if(Status != STATUS_EFI_SUCCESS) + { + /* Unable to relocate the file */ + XtLdrProtocol->Debug.Print(L"ERROR: Failed to relocate '%S'\n", FileName); + return Status; + } + /* Close image file */ ModuleHandle->Close(ModuleHandle); @@ -577,12 +587,60 @@ Xtos::LoadModule(IN PEFI_FILE_HANDLE SystemDir, /* Print debug message */ XtLdrProtocol->Debug.Print(L"Loaded %S at PA: %P, VA: %P\n", FileName, - (*ImageContext)->PhysicalAddress, (*ImageContext)->VirtualAddress); + (*ImageContext)->PhysicalAddress, KSEG0_BASE + (ULONGLONG)(*ImageContext)->VirtualAddress); /* Return success */ return STATUS_EFI_SUCCESS; } +/** + * Adds a physical to virtual address mapping. + * + * @param PageMap + * Supplies a pointer to the page mapping structure. + * + * @param PhysicalAddress + * Supplies a physical address which will be mapped. + * + * @param NumberOfPages + * Supplies a number of pages that will be mapped. + * + * @param MemoryType + * Supplies the type of mapped memory that will be assigned to the memory descriptor. + * + * @param KernelMapping + * Supplies a flag that indicates if mapping should be done in kernel mode or if identity mapping should be used. + * + * @return This routine returns a status code. + * + * @since XT 1.0 + */ +XTCDECL +EFI_STATUS +Xtos::MapMemory(IN OUT PXTBL_PAGE_MAPPING PageMap, + IN ULONGLONG Address, + IN ULONG NumberOfPages, + IN LOADER_MEMORY_TYPE MemoryType, + IN BOOLEAN KernelMapping) +{ + ULONGLONG BaseAddress; + + /* Check if kernel mode mapping */ + if(KernelMapping) + { + /* Map memory based on kernel base address */ + BaseAddress = KSEG0_BASE; + } + else + { + /* Use identity mapping */ + BaseAddress = (ULONGLONG)NULLPTR; + } + + /* Map memory and return status code */ + return XtLdrProtocol->Memory.MapVirtualMemory(PageMap, BaseAddress + Address, Address, NumberOfPages, MemoryType); +} + /** * This routine initiates an XTOS boot sequence. * @@ -650,11 +708,11 @@ Xtos::RunBootSequence(IN PEFI_FILE_HANDLE BootDir, } /* Add kernel image memory mapping */ - Status = XtLdrProtocol->Memory.MapVirtualMemory(&PageMap, (ULONGLONG)ImageContext->VirtualAddress, - (ULONGLONG)ImageContext->PhysicalAddress, ImageContext->ImagePages, - LoaderSystemCode); + Status = MapMemory(&PageMap, (ULONGLONG)ImageContext->PhysicalAddress, + ImageContext->ImagePages, LoaderSystemCode, TRUE); if(Status != STATUS_EFI_SUCCESS) { + /* Failed to map kernel image memory */ return Status; } -- 2.52.0 From 5500192575925bc303b8f14d5b3660c5653e10f7 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Sun, 11 Jan 2026 23:14:10 +0100 Subject: [PATCH 108/166] Remove manual virtual address tracking from boot sequence --- boot/xtldr/modules/xtos_o/includes/xtos.hh | 8 +- boot/xtldr/modules/xtos_o/xtos.cc | 167 ++++++++++++++------- 2 files changed, 114 insertions(+), 61 deletions(-) diff --git a/boot/xtldr/modules/xtos_o/includes/xtos.hh b/boot/xtldr/modules/xtos_o/includes/xtos.hh index ea37111..e917d10 100644 --- a/boot/xtldr/modules/xtos_o/includes/xtos.hh +++ b/boot/xtldr/modules/xtos_o/includes/xtos.hh @@ -40,19 +40,17 @@ class Xtos IN PULONG_PTR FrameBufferSize, IN PXTBL_FRAMEBUFFER_MODE_INFORMATION FrameBufferModeInfo); STATIC XTCDECL EFI_STATUS GetMemoryDescriptorList(IN PXTBL_PAGE_MAPPING PageMap, - IN PVOID *VirtualAddress, OUT PLIST_ENTRY MemoryDescriptorList); STATIC XTCDECL EFI_STATUS GetSystemResourcesList(IN PXTBL_PAGE_MAPPING PageMap, - IN PVOID *VirtualAddress, OUT PLIST_ENTRY SystemResourcesList); STATIC XTCDECL EFI_STATUS InitializeApicBase(IN PXTBL_PAGE_MAPPING PageMap); STATIC XTCDECL EFI_STATUS InitializeLoaderBlock(IN PXTBL_PAGE_MAPPING PageMap, - IN PVOID *VirtualAddress, + OUT PKERNEL_INITIALIZATION_BLOCK *KernelParameters, IN PXTBL_BOOT_PARAMETERS Parameters); STATIC XTCDECL EFI_STATUS LoadModule(IN PEFI_FILE_HANDLE BootDir, IN PWCHAR FileName, - IN PVOID VirtualAddress, IN LOADER_MEMORY_TYPE MemoryType, + IN OUT PXTBL_PAGE_MAPPING PageMap, OUT PPECOFF_IMAGE_CONTEXT *ImageContext); STATIC XTCDECL EFI_STATUS MapHardwareMemoryPool(IN PXTBL_PAGE_MAPPING PageMap); STATIC XTCDECL EFI_STATUS MapMemory(IN OUT PXTBL_PAGE_MAPPING PageMap, @@ -60,6 +58,8 @@ class Xtos IN ULONG NumberOfPages, IN LOADER_MEMORY_TYPE MemoryType, IN BOOLEAN KernelMapping); + STATIC XTCDECL PVOID PhysicalAddressToVirtual(PVOID PhysicalAddress); + STATIC XTCDECL EFI_STATUS PhysicalListToVirtual(IN OUT PLIST_ENTRY ListHead); STATIC XTCDECL EFI_STATUS RunBootSequence(IN PEFI_FILE_HANDLE BootDir, IN PXTBL_BOOT_PARAMETERS Parameters); }; diff --git a/boot/xtldr/modules/xtos_o/xtos.cc b/boot/xtldr/modules/xtos_o/xtos.cc index e35331e..57d943b 100644 --- a/boot/xtldr/modules/xtos_o/xtos.cc +++ b/boot/xtldr/modules/xtos_o/xtos.cc @@ -191,7 +191,6 @@ Xtos::GetDisplayInformation(OUT PSYSTEM_RESOURCE_FRAMEBUFFER FrameBufferResource XTCDECL EFI_STATUS Xtos::GetMemoryDescriptorList(IN PXTBL_PAGE_MAPPING PageMap, - IN PVOID *VirtualAddress, OUT PLIST_ENTRY MemoryDescriptorList) { EFI_PHYSICAL_ADDRESS Address; @@ -206,7 +205,7 @@ Xtos::GetMemoryDescriptorList(IN PXTBL_PAGE_MAPPING PageMap, return Status; } - Status = XtLdrProtocol->Memory.MapVirtualMemory(PageMap, (ULONGLONG)*VirtualAddress, Address, Pages, LoaderMemoryData); + Status = MapMemory(PageMap, Address, Pages, LoaderMemoryData, TRUE); if(Status != STATUS_EFI_SUCCESS) { XtLdrProtocol->Memory.FreePages(Address, Pages); @@ -214,13 +213,14 @@ Xtos::GetMemoryDescriptorList(IN PXTBL_PAGE_MAPPING PageMap, } PVOID PhysicalBase = (PVOID)Address; + PVOID CurrentDescriptor = PhysicalBase; PLIST_ENTRY ListEntry; ListEntry = PageMap->MemoryMap.Flink; while(ListEntry != &PageMap->MemoryMap) { PXTBL_MEMORY_MAPPING MemoryMapping = CONTAIN_RECORD(ListEntry, XTBL_MEMORY_MAPPING, ListEntry); - PLOADER_MEMORY_DESCRIPTOR MemoryDescriptor = (PLOADER_MEMORY_DESCRIPTOR)Address; + PLOADER_MEMORY_DESCRIPTOR MemoryDescriptor = (PLOADER_MEMORY_DESCRIPTOR)CurrentDescriptor; MemoryDescriptor->MemoryType = MemoryMapping->MemoryType; MemoryDescriptor->BasePage = (UINT_PTR)MemoryMapping->PhysicalAddress / EFI_PAGE_SIZE; @@ -228,11 +228,12 @@ Xtos::GetMemoryDescriptorList(IN PXTBL_PAGE_MAPPING PageMap, XtLdrProtocol->LinkedList.InsertTail(MemoryDescriptorList, &MemoryDescriptor->ListEntry); - Address = Address + sizeof(LOADER_MEMORY_DESCRIPTOR); + CurrentDescriptor = (PUINT8)CurrentDescriptor + sizeof(LOADER_MEMORY_DESCRIPTOR); ListEntry = ListEntry->Flink; } - XtLdrProtocol->Memory.PhysicalListToVirtual(PageMap, MemoryDescriptorList, PhysicalBase, *VirtualAddress); + XtLdrProtocol->Debug.Print(L"Address: %llX, Pages: %llu\n", (ULONGLONG)PhysicalBase, Pages); + PhysicalListToVirtual(MemoryDescriptorList); return STATUS_EFI_SUCCESS; } @@ -240,7 +241,6 @@ Xtos::GetMemoryDescriptorList(IN PXTBL_PAGE_MAPPING PageMap, XTCDECL EFI_STATUS Xtos::GetSystemResourcesList(IN PXTBL_PAGE_MAPPING PageMap, - IN PVOID *VirtualAddress, OUT PLIST_ENTRY SystemResourcesList) { XTSTATUS Status; @@ -257,7 +257,6 @@ Xtos::GetSystemResourcesList(IN PXTBL_PAGE_MAPPING PageMap, PSYSTEM_RESOURCE_ACPI AcpiResource; ULONGLONG Pages; EFI_PHYSICAL_ADDRESS Address; - PVOID PhysicalBase, VirtualBase; Pages = (ULONGLONG)EFI_SIZE_TO_PAGES(sizeof(SYSTEM_RESOURCE_ACPI) + sizeof(SYSTEM_RESOURCE_FRAMEBUFFER)); @@ -267,19 +266,13 @@ Xtos::GetSystemResourcesList(IN PXTBL_PAGE_MAPPING PageMap, return Status; } - Status = XtLdrProtocol->Memory.MapVirtualMemory(PageMap, (ULONGLONG)*VirtualAddress, Address, Pages, LoaderFirmwarePermanent); + Status = MapMemory(PageMap, Address, Pages, LoaderFirmwarePermanent, TRUE); if(Status != STATUS_EFI_SUCCESS) { XtLdrProtocol->Memory.FreePages(Address, Pages); return Status; } - PhysicalBase = (PVOID)Address; - VirtualBase = *VirtualAddress; - - /* Calculate next valid virtual address */ - *VirtualAddress = (PUINT8)*VirtualAddress + (Pages * EFI_PAGE_SIZE); - AcpiResource = (PSYSTEM_RESOURCE_ACPI)Address; XtLdrProtocol->Memory.ZeroMemory(AcpiResource, sizeof(SYSTEM_RESOURCE_ACPI)); @@ -295,7 +288,7 @@ Xtos::GetSystemResourcesList(IN PXTBL_PAGE_MAPPING PageMap, AcpiResource->Header.ResourceSize = sizeof(SYSTEM_RESOURCE_ACPI); /* Get APIC and XSDP/RSDP addresses */ - AcpiProtocol->GetApicBase(&AcpiResource->ApicBase); + AcpiProtocol->GetApicBase((PVOID *)&AcpiResource->ApicBase); AcpiProtocol->GetAcpiDescriptionPointer(&AcpiResource->Header.PhysicalAddress); /* No need to map ACPI */ @@ -334,21 +327,19 @@ Xtos::GetSystemResourcesList(IN PXTBL_PAGE_MAPPING PageMap, FrameBufferPages = EFI_SIZE_TO_PAGES(FbSize); /* Rewrite framebuffer address by using virtual address */ - FrameBufferResource->Header.VirtualAddress = *VirtualAddress; + FrameBufferResource->Header.VirtualAddress = PhysicalAddressToVirtual(FrameBufferResource->Header.PhysicalAddress); /* Map frame buffer memory */ XtLdrProtocol->Memory.MapVirtualMemory(PageMap, (ULONGLONG)FrameBufferResource->Header.VirtualAddress, (ULONGLONG)FrameBufferResource->Header.PhysicalAddress, - FrameBufferPages, LoaderFirmwarePermanent); + FrameBufferPages, LoaderHardwareCachedMemory); /* Close FrameBuffer protocol */ XtLdrProtocol->Protocol.Close(&ProtocolHandle, &FrameBufGuid); - *VirtualAddress = (PUINT8)*VirtualAddress + (FrameBufferPages * EFI_PAGE_SIZE); - XtLdrProtocol->LinkedList.InsertTail(SystemResourcesList, &FrameBufferResource->Header.ListEntry); - XtLdrProtocol->Memory.PhysicalListToVirtual(PageMap, SystemResourcesList, PhysicalBase, VirtualBase); + PhysicalListToVirtual(SystemResourcesList); return STATUS_EFI_SUCCESS; } @@ -370,7 +361,7 @@ Xtos::InitializeApicBase(IN PXTBL_PAGE_MAPPING PageMap) EFI_GUID AcpiGuid = XT_ACPI_PROTOCOL_GUID; PXTBL_ACPI_PROTOCOL AcpiProtocol; EFI_HANDLE ProtocolHandle; - PVOID ApicBaseAddress; + EFI_PHYSICAL_ADDRESS ApicBaseAddress; EFI_STATUS Status; /* Open ACPI protocol */ @@ -382,7 +373,7 @@ Xtos::InitializeApicBase(IN PXTBL_PAGE_MAPPING PageMap) } /* Get APIC base address */ - Status = AcpiProtocol->GetApicBase(&ApicBaseAddress); + Status = AcpiProtocol->GetApicBase((PVOID *)&ApicBaseAddress); if(Status != STATUS_EFI_SUCCESS) { /* Failed to get APIC base address */ @@ -390,7 +381,7 @@ Xtos::InitializeApicBase(IN PXTBL_PAGE_MAPPING PageMap) } /* Map APIC base address */ - XtLdrProtocol->Memory.MapVirtualMemory(PageMap, APIC_BASE, (ULONGLONG)ApicBaseAddress, 1, LoaderFirmwarePermanent); + XtLdrProtocol->Memory.MapVirtualMemory(PageMap, APIC_BASE, ApicBaseAddress, 1, LoaderFirmwarePermanent); return STATUS_EFI_SUCCESS; } @@ -410,7 +401,7 @@ Xtos::InitializeApicBase(IN PXTBL_PAGE_MAPPING PageMap) XTCDECL EFI_STATUS Xtos::InitializeLoaderBlock(IN PXTBL_PAGE_MAPPING PageMap, - IN PVOID *VirtualAddress, + OUT PKERNEL_INITIALIZATION_BLOCK *KernelParameters, IN PXTBL_BOOT_PARAMETERS Parameters) { PKERNEL_INITIALIZATION_BLOCK LoaderBlock; @@ -418,6 +409,7 @@ Xtos::InitializeLoaderBlock(IN PXTBL_PAGE_MAPPING PageMap, EFI_STATUS Status; UINT BlockPages; UINT ParametersSize; + ULONGLONG LoaderBlockVa; /* Calculate size of parameters */ ParametersSize = (XtLdrProtocol->WideString.Length(Parameters->Parameters, 0) + 1) * sizeof(WCHAR); @@ -450,25 +442,29 @@ Xtos::InitializeLoaderBlock(IN PXTBL_PAGE_MAPPING PageMap, // LoaderBlock->FirmwareInformation.EfiFirmware.EfiVersion = EfiSystemTable->Hdr.Revision; LoaderBlock->FirmwareInformation.EfiFirmware.EfiRuntimeServices = NULLPTR; + /* Get the KSEG0-based virtual address for the loader block */ + LoaderBlockVa = (ULONGLONG)PhysicalAddressToVirtual(LoaderBlock); + *KernelParameters = (PKERNEL_INITIALIZATION_BLOCK)LoaderBlockVa; + /* Copy parameters to kernel initialization block */ - LoaderBlock->KernelParameters = (PWCHAR)((UINT_PTR)*VirtualAddress + sizeof(KERNEL_INITIALIZATION_BLOCK)); + LoaderBlock->KernelParameters = (PWCHAR)(LoaderBlockVa + sizeof(KERNEL_INITIALIZATION_BLOCK)); XtLdrProtocol->Memory.CopyMemory((PVOID)((UINT_PTR)LoaderBlock + sizeof(KERNEL_INITIALIZATION_BLOCK)), Parameters->Parameters, ParametersSize); /* Map kernel initialization block */ - XtLdrProtocol->Memory.MapVirtualMemory(PageMap, (ULONGLONG)*VirtualAddress, (ULONGLONG)LoaderBlock, - BlockPages, LoaderSystemBlock); - - /* Calculate next valid virtual address */ - *VirtualAddress = (PUINT8)*VirtualAddress + (BlockPages * EFI_PAGE_SIZE); + Status = MapMemory(PageMap, (ULONGLONG)LoaderBlock, BlockPages, LoaderSystemBlock, TRUE); + if(Status != STATUS_EFI_SUCCESS) + { + return Status; + } XtLdrProtocol->LinkedList.InitializeHead(&LoaderBlock->SystemResourcesListHead); - GetSystemResourcesList(PageMap, VirtualAddress, &LoaderBlock->SystemResourcesListHead); + GetSystemResourcesList(PageMap, &LoaderBlock->SystemResourcesListHead); /* Initialize memory descriptor list */ XtLdrProtocol->LinkedList.InitializeHead(&LoaderBlock->MemoryDescriptorListHead); - GetMemoryDescriptorList(PageMap, VirtualAddress, &LoaderBlock->MemoryDescriptorListHead); + GetMemoryDescriptorList(PageMap, &LoaderBlock->MemoryDescriptorListHead); /* Return success */ return STATUS_EFI_SUCCESS; @@ -526,8 +522,8 @@ XTCDECL EFI_STATUS Xtos::LoadModule(IN PEFI_FILE_HANDLE SystemDir, IN PWCHAR FileName, - IN PVOID VirtualAddress, IN LOADER_MEMORY_TYPE MemoryType, + IN OUT PXTBL_PAGE_MAPPING PageMap, OUT PPECOFF_IMAGE_CONTEXT *ImageContext) { PEFI_FILE_HANDLE ModuleHandle; @@ -585,9 +581,22 @@ Xtos::LoadModule(IN PEFI_FILE_HANDLE SystemDir, XtLdrProtocol->Debug.Print(L"WARNING: Loaded PE/COFF image with non-XT subsystem set\n"); } + /* Ensure that page map is provided */ + if(PageMap != NULLPTR) + { + /* Add kernel image memory mapping */ + Status = MapMemory(PageMap, (ULONGLONG)(*ImageContext)->PhysicalAddress, + (*ImageContext)->ImagePages, LoaderSystemCode, TRUE); + if(Status != STATUS_EFI_SUCCESS) + { + /* Failed to map kernel image memory */ + return Status; + } + } + /* Print debug message */ - XtLdrProtocol->Debug.Print(L"Loaded %S at PA: %P, VA: %P\n", FileName, - (*ImageContext)->PhysicalAddress, KSEG0_BASE + (ULONGLONG)(*ImageContext)->VirtualAddress); + XtLdrProtocol->Debug.Print(L"Loaded '%S' at PA: %P, VA: %P\n", FileName, (*ImageContext)->PhysicalAddress, + KSEG0_BASE + (ULONGLONG)(*ImageContext)->VirtualAddress); /* Return success */ return STATUS_EFI_SUCCESS; @@ -641,6 +650,69 @@ Xtos::MapMemory(IN OUT PXTBL_PAGE_MAPPING PageMap, return XtLdrProtocol->Memory.MapVirtualMemory(PageMap, BaseAddress + Address, Address, NumberOfPages, MemoryType); } +/** + * Converts physical address to virtual address. + * + * @param PhysicalAddress + * Specifies physical address that will be converted to virtual address. + * + * @return This routine returns a mapped virtual address. + * + * @since XT 1.0 + */ +XTCDECL +PVOID +Xtos::PhysicalAddressToVirtual(PVOID PhysicalAddress) +{ + return (PVOID)((ULONG_PTR)PhysicalAddress | KSEG0_BASE); +} + +/** + * Converts whole linked list addressing from physical to virtual for future use after enabling paging. + * + * @param ListHead + * Supplies a pointer to a structure that serves as the list header. + * + * @return This routine returns a status code. + * + * @since XT 1.0 + */ +XTCDECL +EFI_STATUS +Xtos::PhysicalListToVirtual(IN OUT PLIST_ENTRY ListHead) +{ + PLIST_ENTRY ListEntry, NextEntry; + + /* Make sure list is properly initialized */ + if(ListHead->Flink == 0 || ListHead->Blink == 0) + { + /* List not initialized, return error code */ + return STATUS_EFI_INVALID_PARAMETER; + } + + /* Iterate through the list */ + ListEntry = ListHead->Flink; + while(ListEntry != ListHead) + { + /* Store the next entry */ + NextEntry = ListEntry->Flink; + + /* Convert the list entry */ + ListEntry->Flink = (PLIST_ENTRY)PhysicalAddressToVirtual(ListEntry->Flink); + ListEntry->Blink = (PLIST_ENTRY)PhysicalAddressToVirtual(ListEntry->Blink); + + /* Get the next element */ + ListEntry = NextEntry; + } + + /* Convert the list head */ + ListHead->Flink = (PLIST_ENTRY)PhysicalAddressToVirtual(ListHead->Flink); + ListHead->Blink = (PLIST_ENTRY)PhysicalAddressToVirtual(ListHead->Blink); + + /* Return success */ + return STATUS_EFI_SUCCESS; +} + /** * This routine initiates an XTOS boot sequence. * @@ -665,7 +737,6 @@ Xtos::RunBootSequence(IN PEFI_FILE_HANDLE BootDir, PXTBL_FRAMEBUFFER_PROTOCOL FrameBufProtocol; PPECOFF_IMAGE_CONTEXT ImageContext = NULLPTR; PEFI_LOADED_IMAGE_PROTOCOL ImageProtocol; - PVOID VirtualAddress, VirtualMemoryArea; PXT_ENTRY_POINT KernelEntryPoint; EFI_HANDLE ProtocolHandle; EFI_STATUS Status; @@ -686,13 +757,10 @@ Xtos::RunBootSequence(IN PEFI_FILE_HANDLE BootDir, /* Close FrameBuffer protocol */ XtLdrProtocol->Protocol.Close(&ProtocolHandle, &FrameBufGuid); - /* Set base virtual memory area for the kernel mappings */ - VirtualMemoryArea = (PVOID)KSEG0_BASE; - VirtualAddress = (PVOID)(KSEG0_BASE + KSEG0_KERNEL_BASE); - /* Initialize virtual memory mappings */ XtLdrProtocol->Memory.InitializePageMap(&PageMap, DeterminePagingLevel(Parameters->Parameters), Size4K); + PVOID VirtualMemoryArea = (PVOID)KSEG0_BASE; Status = XtLdrProtocol->Memory.MapEfiMemory(&PageMap, &VirtualMemoryArea, NULLPTR); if(Status != STATUS_EFI_SUCCESS) { @@ -700,25 +768,13 @@ Xtos::RunBootSequence(IN PEFI_FILE_HANDLE BootDir, } /* Load the kernel */ - Status = LoadModule(BootDir, Parameters->KernelFile, VirtualAddress, LoaderSystemCode, &ImageContext); + Status = LoadModule(BootDir, Parameters->KernelFile, LoaderSystemCode, &PageMap, &ImageContext); if(Status != STATUS_EFI_SUCCESS) { /* Failed to load the kernel */ return Status; } - /* Add kernel image memory mapping */ - Status = MapMemory(&PageMap, (ULONGLONG)ImageContext->PhysicalAddress, - ImageContext->ImagePages, LoaderSystemCode, TRUE); - if(Status != STATUS_EFI_SUCCESS) - { - /* Failed to map kernel image memory */ - return Status; - } - - /* Set next valid virtual address right after the kernel */ - VirtualAddress = (PUINT8)VirtualAddress + (ImageContext->ImagePages * EFI_PAGE_SIZE); - /* Find and map APIC base address */ Status = InitializeApicBase(&PageMap); if(Status != STATUS_EFI_SUCCESS) @@ -728,11 +784,8 @@ Xtos::RunBootSequence(IN PEFI_FILE_HANDLE BootDir, return Status; } - /* Store virtual address of kernel initialization block for future kernel call */ - KernelParameters = (PKERNEL_INITIALIZATION_BLOCK)VirtualAddress; - /* Setup and map kernel initialization block */ - Status = InitializeLoaderBlock(&PageMap, &VirtualAddress, Parameters); + Status = InitializeLoaderBlock(&PageMap, &KernelParameters, Parameters); if(Status != STATUS_EFI_SUCCESS) { /* Failed to setup kernel initialization block */ -- 2.52.0 From 032cab7f2f7e7778255525d2991b391a3f93fe52 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Mon, 12 Jan 2026 19:26:07 +0100 Subject: [PATCH 109/166] Update function documentation and remove debug prints --- boot/xtldr/modules/xtos_o/xtos.cc | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/boot/xtldr/modules/xtos_o/xtos.cc b/boot/xtldr/modules/xtos_o/xtos.cc index 57d943b..1d95823 100644 --- a/boot/xtldr/modules/xtos_o/xtos.cc +++ b/boot/xtldr/modules/xtos_o/xtos.cc @@ -232,7 +232,6 @@ Xtos::GetMemoryDescriptorList(IN PXTBL_PAGE_MAPPING PageMap, ListEntry = ListEntry->Flink; } - XtLdrProtocol->Debug.Print(L"Address: %llX, Pages: %llu\n", (ULONGLONG)PhysicalBase, Pages); PhysicalListToVirtual(MemoryDescriptorList); return STATUS_EFI_SUCCESS; @@ -388,11 +387,14 @@ Xtos::InitializeApicBase(IN PXTBL_PAGE_MAPPING PageMap) /** * Initializes and maps the kernel initialization block. * - * @param MemoryMappings - * Supplies a pointer to linked list containing all memory mappings. + * @param PageMap + * Supplies a pointer to the page map. * - * @param VirtualAddress - * Supplies a pointer to the next valid, free and available virtual address. + * @param KernelParameters + * Returns a pointer to the kernel initialization block. + * + * @param Parameters + * Supplies a list of input parameters passed to the kernel. * * @return This routine returns a status code. * @@ -505,12 +507,12 @@ Xtos::InitializeModule(IN EFI_HANDLE ImageHandle, * @param FileName * An on disk filename of the module that will be loaded. * - * @param VirtualAddress - * Optional virtual address pointing to the memory area where PE/COFF file will be loaded. - * * @param MemoryType * Supplies the type of memory to be assigned to the memory descriptor. * + * @param PageMap + * Supplies pointer to the memory area where memory mappings will be stored. + * * @param ImageContext * Supplies pointer to the memory area where loaded PE/COFF image context will be stored. * @@ -596,7 +598,7 @@ Xtos::LoadModule(IN PEFI_FILE_HANDLE SystemDir, /* Print debug message */ XtLdrProtocol->Debug.Print(L"Loaded '%S' at PA: %P, VA: %P\n", FileName, (*ImageContext)->PhysicalAddress, - KSEG0_BASE + (ULONGLONG)(*ImageContext)->VirtualAddress); + PhysicalAddressToVirtual((*ImageContext)->VirtualAddress)); /* Return success */ return STATUS_EFI_SUCCESS; -- 2.52.0 From 34c33a3b53051b490da1422333d20a3c5dcb0033 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Mon, 12 Jan 2026 19:40:27 +0100 Subject: [PATCH 110/166] Clean up unused physical-to-virtual conversion routines --- boot/xtldr/memory.cc | 102 ----------------------------------------- boot/xtldr/protocol.cc | 2 - sdk/xtdk/bltypes.h | 4 -- 3 files changed, 108 deletions(-) diff --git a/boot/xtldr/memory.cc b/boot/xtldr/memory.cc index 89b9809..06f0e40 100644 --- a/boot/xtldr/memory.cc +++ b/boot/xtldr/memory.cc @@ -638,105 +638,3 @@ Memory::MapVirtualMemory(IN OUT PXTBL_PAGE_MAPPING PageMap, /* Return success */ return STATUS_EFI_SUCCESS; } - -/** - * Converts physical address to virtual address based on physical base and virtual base. - * - * @param PhysicalAddress - * Specifies physical address that will be converted to virtual address. - * - * @param PhysicalBase - * Supplies a physical base address. - * - * @param VirtualBase - * Supplies a virtual base address. - * - * @return This routine returns a mapped virtual address. - * - * @since XT 1.0 - */ -XTCDECL -PVOID -Memory::PhysicalAddressToVirtual(IN PVOID PhysicalAddress, - IN PVOID PhysicalBase, - IN PVOID VirtualBase) -{ - /* Convert physical address to virtual address */ - return (PUCHAR)VirtualBase + ((PUCHAR)PhysicalAddress - (PUCHAR)PhysicalBase); -} - -/** - * Converts whole linked list addressing from physical to virtual for future use after enabling paging. - * - * @param PageMap - * Supplies a pointer to the page mapping structure. - * - * @param ListHead - * Supplies a pointer to a structure that serves as the list header. - * - * @param PhysicalBase - * Supplies a physical base address. - * - * @param VirtualBase - * Supplies a virtual base address. - * - * @return This routine returns a status code. - * - * @since XT 1.0 - */ -XTCDECL -EFI_STATUS -Memory::PhysicalListToVirtual(IN PXTBL_PAGE_MAPPING PageMap, - IN OUT PLIST_ENTRY ListHead, - IN PVOID PhysicalBase, - IN PVOID VirtualBase) -{ - PLIST_ENTRY ListEntry, NextEntry; - - /* Make sure list is properly initialized */ - if(ListHead->Flink == 0 || ListHead->Blink == 0) - { - /* List not initialized, return error code */ - return STATUS_EFI_INVALID_PARAMETER; - } - - /* Iterate through all elements */ - ListEntry = ListHead->Flink; - while(ListEntry != ListHead) - { - /* Save physical address of the next element */ - NextEntry = ListEntry->Flink; - - /* Convert the address of this element to VirtualAddress */ - if(ListEntry->Blink == ListHead) - { - /* Find virtual address of list head */ - ListEntry->Blink = (PLIST_ENTRY)GetVirtualAddress(PageMap, ListEntry->Blink); - } - else - { - /* Convert list entry */ - ListEntry->Blink = (PLIST_ENTRY)PhysicalAddressToVirtual(ListEntry->Blink, (PVOID)PhysicalBase, VirtualBase); - } - if(ListEntry->Flink == ListHead) - { - /* Convert list head */ - ListEntry->Flink = ListHead->Flink->Blink; - } - else - { - /* Convert list entry */ - ListEntry->Flink = (PLIST_ENTRY)PhysicalAddressToVirtual(ListEntry->Flink, (PVOID)PhysicalBase, VirtualBase); - } - - /* Get to the next element*/ - ListEntry = NextEntry; - } - - /* Convert list head */ - ListHead->Blink = (PLIST_ENTRY)PhysicalAddressToVirtual(ListHead->Blink, (PVOID)PhysicalBase, VirtualBase); - ListHead->Flink = (PLIST_ENTRY)PhysicalAddressToVirtual(ListHead->Flink, (PVOID)PhysicalBase, VirtualBase); - - /* Return success */ - return STATUS_EFI_SUCCESS; -} diff --git a/boot/xtldr/protocol.cc b/boot/xtldr/protocol.cc index 6593e4a..e8221d0 100644 --- a/boot/xtldr/protocol.cc +++ b/boot/xtldr/protocol.cc @@ -1066,8 +1066,6 @@ Protocol::InstallXtLoaderProtocol() LoaderProtocol.Memory.MapPage = Memory::MapPage; LoaderProtocol.Memory.MapVirtualMemory = Memory::MapVirtualMemory; LoaderProtocol.Memory.MoveMemory = RTL::Memory::MoveMemory; - LoaderProtocol.Memory.PhysicalAddressToVirtual = Memory::PhysicalAddressToVirtual; - LoaderProtocol.Memory.PhysicalListToVirtual = Memory::PhysicalListToVirtual; LoaderProtocol.Memory.SetMemory = RTL::Memory::SetMemory; LoaderProtocol.Memory.ZeroMemory = RTL::Memory::ZeroMemory; LoaderProtocol.Protocol.Close = CloseProtocol; diff --git a/sdk/xtdk/bltypes.h b/sdk/xtdk/bltypes.h index 1f7f948..6c6a7bc 100644 --- a/sdk/xtdk/bltypes.h +++ b/sdk/xtdk/bltypes.h @@ -107,14 +107,12 @@ typedef VOID (XTAPI *PBL_MOVE_MEMORY)(IN OUT PVOID Destination, IN PCVOID Source typedef EFI_STATUS (XTCDECL *PBL_OPEN_VOLUME)(IN PEFI_DEVICE_PATH_PROTOCOL DevicePath, OUT PEFI_HANDLE DiskHandle, OUT PEFI_FILE_HANDLE *FsHandle); typedef EFI_STATUS (XTCDECL *PBL_OPEN_PROTOCOL)(OUT PEFI_HANDLE Handle, OUT PVOID *ProtocolHandler, IN PEFI_GUID ProtocolGuid); typedef EFI_STATUS (XTCDECL *PBL_OPEN_PROTOCOL_HANDLE)(IN EFI_HANDLE Handle, OUT PVOID *ProtocolHandler, IN PEFI_GUID ProtocolGuid); -typedef PVOID (XTCDECL *PBL_PHYSICAL_ADDRESS_TO_VIRTUAL)(IN PVOID PhysicalAddress, IN PVOID PhysicalBase, IN PVOID VirtualBase); typedef UCHAR (XTCDECL *PBL_IOPORT_READ_8)(IN USHORT Port); typedef USHORT (XTCDECL *PBL_IOPORT_READ_16)(IN USHORT Port); typedef ULONG (XTCDECL *PBL_IOPORT_READ_32)(IN USHORT Port); typedef VOID (XTCDECL *PBL_IOPORT_WRITE_8)(IN USHORT Port, IN UCHAR Value); typedef VOID (XTCDECL *PBL_IOPORT_WRITE_16)(IN USHORT Port, IN USHORT Value); typedef VOID (XTCDECL *PBL_IOPORT_WRITE_32)(IN USHORT Port, IN ULONG Value); -typedef EFI_STATUS (XTCDECL *PBL_PHYSICAL_LIST_TO_VIRTUAL)(IN PXTBL_PAGE_MAPPING PageMap, IN OUT PLIST_ENTRY ListHead, IN PVOID PhysicalBase, IN PVOID VirtualBase); typedef EFI_STATUS (XTCDECL *PBL_POWER_SYSTEM)(); typedef EFI_STATUS (XTCDECL *PBL_READ_FILE)(IN PEFI_FILE_HANDLE DirHandle, IN PCWSTR FileName, OUT PVOID *FileData, OUT PSIZE_T FileSize); typedef EFI_STATUS (XTCDECL *PBL_REGISTER_BOOT_PROTOCOL)(IN PCWSTR SystemType, IN PEFI_GUID BootProtocolGuid); @@ -461,8 +459,6 @@ typedef struct _XTBL_LOADER_PROTOCOL PBL_MAP_PAGE MapPage; PBL_MAP_VIRTUAL_MEMORY MapVirtualMemory; PBL_MOVE_MEMORY MoveMemory; - PBL_PHYSICAL_ADDRESS_TO_VIRTUAL PhysicalAddressToVirtual; - PBL_PHYSICAL_LIST_TO_VIRTUAL PhysicalListToVirtual; PBL_SET_MEMORY SetMemory; PBL_ZERO_MEMORY ZeroMemory; } Memory; -- 2.52.0 From 15edd982422ef9f7fdc2578d5d7654979b509e5a Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Mon, 12 Jan 2026 22:46:04 +0100 Subject: [PATCH 111/166] Extract MapDescriptor logic and simplify memory mapping API --- boot/xtldr/includes/xtldr.hh | 15 ++-- boot/xtldr/memory.cc | 113 +++++++++++++++++------------- boot/xtldr/modules/xtos_o/xtos.cc | 3 +- sdk/xtdk/bltypes.h | 2 +- 4 files changed, 73 insertions(+), 60 deletions(-) diff --git a/boot/xtldr/includes/xtldr.hh b/boot/xtldr/includes/xtldr.hh index cb91068..8d8101c 100644 --- a/boot/xtldr/includes/xtldr.hh +++ b/boot/xtldr/includes/xtldr.hh @@ -168,6 +168,7 @@ class Memory STATIC XTCDECL EFI_STATUS FreePages(IN ULONGLONG NumberOfPages, IN EFI_PHYSICAL_ADDRESS Memory); STATIC XTCDECL EFI_STATUS FreePool(IN PVOID Memory); + STATIC XTCDECL LOADER_MEMORY_TYPE GetLoaderMemoryType(IN EFI_MEMORY_TYPE EfiMemoryType); STATIC XTCDECL VOID GetMappingsCount(IN PXTBL_PAGE_MAPPING PageMap, OUT PULONG NumberOfMappings); STATIC XTCDECL EFI_STATUS GetMemoryMap(OUT PEFI_MEMORY_MAP MemoryMap); @@ -177,8 +178,7 @@ class Memory IN SHORT PageMapLevel, IN PAGE_SIZE PageSize); STATIC XTCDECL EFI_STATUS MapEfiMemory(IN OUT PXTBL_PAGE_MAPPING PageMap, - IN OUT PVOID *MemoryMapAddress, - IN PBL_GET_MEMTYPE_ROUTINE GetMemoryTypeRoutine); + IN ULONG_PTR BaseAddress); STATIC XTCDECL EFI_STATUS MapPage(IN PXTBL_PAGE_MAPPING PageMap, IN ULONGLONG VirtualAddress, IN ULONGLONG PhysicalAddress, @@ -188,20 +188,15 @@ class Memory IN ULONGLONG PhysicalAddress, IN ULONGLONG NumberOfPages, IN LOADER_MEMORY_TYPE MemoryType); - STATIC XTCDECL PVOID PhysicalAddressToVirtual(IN PVOID PhysicalAddress, - IN PVOID PhysicalBase, - IN PVOID VirtualBase); - STATIC XTCDECL EFI_STATUS PhysicalListToVirtual(IN PXTBL_PAGE_MAPPING PageMap, - IN OUT PLIST_ENTRY ListHead, - IN PVOID PhysicalBase, - IN PVOID VirtualBase); private: - STATIC XTCDECL LOADER_MEMORY_TYPE GetLoaderMemoryType(IN EFI_MEMORY_TYPE EfiMemoryType); STATIC XTCDECL EFI_STATUS GetNextPageTable(IN PXTBL_PAGE_MAPPING PageMap, IN PVOID PageTable, IN SIZE_T Entry, OUT PVOID *NextPageTable); + STATIC XTCDECL EFI_STATUS MapDescriptor(IN OUT PXTBL_PAGE_MAPPING PageMap, + IN PEFI_MEMORY_DESCRIPTOR Descriptor, + IN ULONG_PTR BaseAddress); STATIC XTCDECL EFI_STATUS SelfMapPml(IN PXTBL_PAGE_MAPPING PageMap, IN ULONG_PTR SelfMapAddress); }; diff --git a/boot/xtldr/memory.cc b/boot/xtldr/memory.cc index 06f0e40..c0ad17f 100644 --- a/boot/xtldr/memory.cc +++ b/boot/xtldr/memory.cc @@ -4,6 +4,7 @@ * FILE: xtldr/memory.cc * DESCRIPTION: XT Boot Loader memory management * DEVELOPERS: Rafal Kupiec + * Aiken Harris */ #include @@ -308,17 +309,69 @@ Memory::InitializePageMap(OUT PXTBL_PAGE_MAPPING PageMap, PageMap->PageSize = PageSize; } +/** + * Maps memory descriptor to the page mapping structure. + * + * @param PageMap + * Supplies a pointer to the page mapping structure. + * + * @param Descriptor + * Supplies a pointer to EFI memory descriptor, which will be mapped. + * + * @param BaseAddress + * Supplies a base address, where EFI memory will be mapped. + * + * @return This routine returns a status code. + * + * @since XT 1.0 + */ +XTCDECL +EFI_STATUS +Memory::MapDescriptor(IN OUT PXTBL_PAGE_MAPPING PageMap, + IN PEFI_MEMORY_DESCRIPTOR Descriptor, + IN ULONG_PTR BaseAddress) +{ + LOADER_MEMORY_TYPE MemoryType; + + /* Skip EFI reserved memory */ + if(Descriptor->Type == EfiReservedMemoryType) + { + /* Skip EFI reserved memory */ + return STATUS_EFI_SUCCESS; + } + + /* Convert EFI memory type into XTLDR memory type */ + MemoryType = Memory::GetLoaderMemoryType((EFI_MEMORY_TYPE)Descriptor->Type); + + /* Do memory mappings depending on memory type */ + if(MemoryType == LoaderFirmwareTemporary) + { + /* Map EFI firmware code */ + return Memory::MapVirtualMemory(PageMap, Descriptor->PhysicalStart, + Descriptor->PhysicalStart, Descriptor->NumberOfPages, MemoryType); + } + else if(MemoryType != LoaderFree) + { + /* Add any non-free memory mappings based on provided base address */ + return Memory::MapVirtualMemory(PageMap, (BaseAddress | Descriptor->PhysicalStart), Descriptor->PhysicalStart, + Descriptor->NumberOfPages, MemoryType); + } + else + { + /* Map all other memory as loader free */ + return Memory::MapVirtualMemory(PageMap, (ULONGLONG)NULLPTR, Descriptor->PhysicalStart, + Descriptor->NumberOfPages, LoaderFree); + } +} + /** * Adds EFI memory mapping to the page mapping structure. * * @param PageMap * Supplies a pointer to the page mapping structure. * - * @param MemoryMapAddress - * Supplies a virtual address, where EFI memory will be mapped. - * - * @param GetMemoryTypeRoutine - * Supplies a pointer to the routine which will be used to match EFI memory type to the OS memory type. + * @param BaseAddress + * Supplies a base address, where EFI memory will be mapped. * * @return This routine returns a status code. * @@ -327,11 +380,9 @@ Memory::InitializePageMap(OUT PXTBL_PAGE_MAPPING PageMap, XTCDECL EFI_STATUS Memory::MapEfiMemory(IN OUT PXTBL_PAGE_MAPPING PageMap, - IN OUT PVOID *MemoryMapAddress, - IN PBL_GET_MEMTYPE_ROUTINE GetMemoryTypeRoutine) + IN ULONG_PTR BaseAddress) { PEFI_MEMORY_DESCRIPTOR Descriptor; - LOADER_MEMORY_TYPE MemoryType; PEFI_MEMORY_MAP MemoryMap; SIZE_T DescriptorCount; ULONGLONG MaxAddress; @@ -372,7 +423,7 @@ Memory::MapEfiMemory(IN OUT PXTBL_PAGE_MAPPING PageMap, /* Check page map level */ if(PageMap->PageMapLevel == 2 || PageMap->PageMapLevel == 3) { - /* Check if physical address starts beyond 4GB */ + /* Check if physical address starts beyond limit */ if(Descriptor->PhysicalStart > MaxAddress) { /* Go to the next descriptor */ @@ -383,49 +434,17 @@ Memory::MapEfiMemory(IN OUT PXTBL_PAGE_MAPPING PageMap, /* Check if memory descriptor exceeds the lowest physical page */ if(Descriptor->PhysicalStart + (Descriptor->NumberOfPages << EFI_PAGE_SHIFT) > MaxAddress) { - /* Truncate memory descriptor to the 4GB */ + /* Truncate memory descriptor to maximum supported address */ Descriptor->NumberOfPages = (((ULONGLONG)MaxAddress) - Descriptor->PhysicalStart) >> EFI_PAGE_SHIFT; } } + /* Map this descriptor and make sure it succeeded */ + Status = MapDescriptor(PageMap, Descriptor, BaseAddress); + if(Status != STATUS_EFI_SUCCESS) { - /* Skip EFI reserved memory */ - if(Descriptor->Type == EfiReservedMemoryType) - { - /* Go to the next descriptor */ - Descriptor = (PEFI_MEMORY_DESCRIPTOR)((PUCHAR)Descriptor + MemoryMap->DescriptorSize); - continue; - } - - /* Convert EFI memory type into XTLDR memory type */ - MemoryType = GetLoaderMemoryType((EFI_MEMORY_TYPE)Descriptor->Type); - - /* Do memory mappings depending on memory type */ - if(MemoryType == LoaderFirmwareTemporary) - { - /* Map EFI firmware code */ - Status = MapVirtualMemory(PageMap, Descriptor->PhysicalStart, - Descriptor->PhysicalStart, Descriptor->NumberOfPages, MemoryType); - } - else if(MemoryType != LoaderFree) - { - /* Add any non-free memory mapping */ - Status = MapVirtualMemory(PageMap, KSEG0_BASE + Descriptor->PhysicalStart, Descriptor->PhysicalStart, - Descriptor->NumberOfPages, MemoryType); - } - else - { - /* Map all other memory as loader free */ - Status = MapVirtualMemory(PageMap, (ULONGLONG)NULLPTR, Descriptor->PhysicalStart, - Descriptor->NumberOfPages, LoaderFree); - } - - /* Make sure memory mapping succeeded */ - if(Status != STATUS_EFI_SUCCESS) - { - /* Mapping failed */ - return Status; - } + /* Mapping failed */ + return Status; } /* Grab next descriptor */ diff --git a/boot/xtldr/modules/xtos_o/xtos.cc b/boot/xtldr/modules/xtos_o/xtos.cc index 1d95823..e720c07 100644 --- a/boot/xtldr/modules/xtos_o/xtos.cc +++ b/boot/xtldr/modules/xtos_o/xtos.cc @@ -762,8 +762,7 @@ Xtos::RunBootSequence(IN PEFI_FILE_HANDLE BootDir, /* Initialize virtual memory mappings */ XtLdrProtocol->Memory.InitializePageMap(&PageMap, DeterminePagingLevel(Parameters->Parameters), Size4K); - PVOID VirtualMemoryArea = (PVOID)KSEG0_BASE; - Status = XtLdrProtocol->Memory.MapEfiMemory(&PageMap, &VirtualMemoryArea, NULLPTR); + Status = XtLdrProtocol->Memory.MapEfiMemory(&PageMap, KSEG0_BASE); if(Status != STATUS_EFI_SUCCESS) { return Status; diff --git a/sdk/xtdk/bltypes.h b/sdk/xtdk/bltypes.h index 6c6a7bc..1851c8a 100644 --- a/sdk/xtdk/bltypes.h +++ b/sdk/xtdk/bltypes.h @@ -100,7 +100,7 @@ typedef VOID (XTCDECL *PBL_LLIST_INITIALIZE_HEAD)(IN PLIST_ENTRY ListHead); typedef VOID (XTCDECL *PBL_LLIST_INSERT_HEAD)(IN OUT PLIST_ENTRY ListHead, IN PLIST_ENTRY Entry); typedef VOID (XTCDECL *PBL_LLIST_INSERT_TAIL)(IN OUT PLIST_ENTRY ListHead, IN PLIST_ENTRY Entry); typedef VOID (XTCDECL *PBL_LLIST_REMOVE_ENTRY)(IN PLIST_ENTRY Entry); -typedef EFI_STATUS (XTCDECL *PBL_MAP_EFI_MEMORY)(IN OUT PXTBL_PAGE_MAPPING PageMap, IN OUT PVOID *MemoryMapAddress, IN PBL_GET_MEMTYPE_ROUTINE GetMemoryTypeRoutine); +typedef EFI_STATUS (XTCDECL *PBL_MAP_EFI_MEMORY)(IN OUT PXTBL_PAGE_MAPPING PageMap, IN ULONG_PTR BaseAddress); typedef EFI_STATUS (XTCDECL *PBL_MAP_PAGE)(IN PXTBL_PAGE_MAPPING PageMap, IN ULONGLONG VirtualAddress, IN ULONGLONG PhysicalAddress, IN ULONGLONG NumberOfPages); typedef EFI_STATUS (XTCDECL *PBL_MAP_VIRTUAL_MEMORY)(IN OUT PXTBL_PAGE_MAPPING PageMap, IN ULONGLONG VirtualAddress, IN ULONGLONG PhysicalAddress, IN ULONGLONG NumberOfPages, IN LOADER_MEMORY_TYPE MemoryType); typedef VOID (XTAPI *PBL_MOVE_MEMORY)(IN OUT PVOID Destination, IN PCVOID Source, IN SIZE_T Length); -- 2.52.0 From 11f7c25713c2d313fc7b32b46176b79a2a374df6 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Mon, 12 Jan 2026 23:03:13 +0100 Subject: [PATCH 112/166] Abstract base mapping address retrieval --- boot/xtldr/modules/xtos_o/amd64/memory.cc | 14 ++++++++++++++ boot/xtldr/modules/xtos_o/i686/memory.cc | 14 ++++++++++++++ boot/xtldr/modules/xtos_o/includes/xtos.hh | 1 + boot/xtldr/modules/xtos_o/xtos.cc | 8 ++++---- 4 files changed, 33 insertions(+), 4 deletions(-) diff --git a/boot/xtldr/modules/xtos_o/amd64/memory.cc b/boot/xtldr/modules/xtos_o/amd64/memory.cc index 02335aa..c5afa07 100644 --- a/boot/xtldr/modules/xtos_o/amd64/memory.cc +++ b/boot/xtldr/modules/xtos_o/amd64/memory.cc @@ -156,6 +156,20 @@ Xtos::EnablePaging(IN PXTBL_PAGE_MAPPING PageMap) return STATUS_EFI_SUCCESS; } +/** + * Returns the base address of the memory mapping. + * + * @return This routine returns the base address of the memory mapping. + * + * @since XT 1.0 + */ +XTCDECL +ULONG_PTR +Xtos::GetBaseMappingAddress(VOID) +{ + return KSEG0_BASE; +} + /** * Maps the page table for hardware layer addess space. * diff --git a/boot/xtldr/modules/xtos_o/i686/memory.cc b/boot/xtldr/modules/xtos_o/i686/memory.cc index 44ee233..08cf608 100644 --- a/boot/xtldr/modules/xtos_o/i686/memory.cc +++ b/boot/xtldr/modules/xtos_o/i686/memory.cc @@ -44,6 +44,20 @@ Xtos::DeterminePagingLevel(IN CONST PWCHAR Parameters) return 2; } +/** + * Returns the base address of the memory mapping. + * + * @return This routine returns the base address of the memory mapping. + * + * @since XT 1.0 + */ +XTCDECL +ULONG_PTR +Xtos::GetBaseMappingAddress(VOID) +{ + return KSEG0_BASE; +} + /** * Builds the actual memory mapping page table and enables paging. This routine exits EFI boot services as well. * diff --git a/boot/xtldr/modules/xtos_o/includes/xtos.hh b/boot/xtldr/modules/xtos_o/includes/xtos.hh index e917d10..8d4b31e 100644 --- a/boot/xtldr/modules/xtos_o/includes/xtos.hh +++ b/boot/xtldr/modules/xtos_o/includes/xtos.hh @@ -35,6 +35,7 @@ class Xtos private: STATIC XTCDECL ULONG DeterminePagingLevel(IN CONST PWCHAR Parameters); STATIC XTCDECL EFI_STATUS EnablePaging(IN PXTBL_PAGE_MAPPING PageMap); + STATIC XTCDECL ULONG_PTR GetBaseMappingAddress(VOID); STATIC XTCDECL VOID GetDisplayInformation(OUT PSYSTEM_RESOURCE_FRAMEBUFFER FrameBufferResource, IN PEFI_PHYSICAL_ADDRESS FrameBufferBase, IN PULONG_PTR FrameBufferSize, diff --git a/boot/xtldr/modules/xtos_o/xtos.cc b/boot/xtldr/modules/xtos_o/xtos.cc index e720c07..2edc751 100644 --- a/boot/xtldr/modules/xtos_o/xtos.cc +++ b/boot/xtldr/modules/xtos_o/xtos.cc @@ -554,7 +554,7 @@ Xtos::LoadModule(IN PEFI_FILE_HANDLE SystemDir, } /* Relocate the PE/COFF image file */ - Status = PeCoffProtocol->RelocateImage(*ImageContext, KSEG0_BASE + (ULONGLONG)(*ImageContext)->PhysicalAddress); + Status = PeCoffProtocol->RelocateImage(*ImageContext, GetBaseMappingAddress() | (ULONGLONG)(*ImageContext)->PhysicalAddress); if(Status != STATUS_EFI_SUCCESS) { /* Unable to relocate the file */ @@ -640,7 +640,7 @@ Xtos::MapMemory(IN OUT PXTBL_PAGE_MAPPING PageMap, if(KernelMapping) { /* Map memory based on kernel base address */ - BaseAddress = KSEG0_BASE; + BaseAddress = GetBaseMappingAddress(); } else { @@ -666,7 +666,7 @@ XTCDECL PVOID Xtos::PhysicalAddressToVirtual(PVOID PhysicalAddress) { - return (PVOID)((ULONG_PTR)PhysicalAddress | KSEG0_BASE); + return (PVOID)((ULONG_PTR)PhysicalAddress | GetBaseMappingAddress()); } /** @@ -762,7 +762,7 @@ Xtos::RunBootSequence(IN PEFI_FILE_HANDLE BootDir, /* Initialize virtual memory mappings */ XtLdrProtocol->Memory.InitializePageMap(&PageMap, DeterminePagingLevel(Parameters->Parameters), Size4K); - Status = XtLdrProtocol->Memory.MapEfiMemory(&PageMap, KSEG0_BASE); + Status = XtLdrProtocol->Memory.MapEfiMemory(&PageMap, GetBaseMappingAddress()); if(Status != STATUS_EFI_SUCCESS) { return Status; -- 2.52.0 From 0766eb456603b12cfcda8ac5ba38bb8a474a2e87 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Mon, 12 Jan 2026 23:05:01 +0100 Subject: [PATCH 113/166] Drop obsolete KSEG0_KERNEL_BASE definition --- sdk/xtdk/amd64/ketypes.h | 3 --- sdk/xtdk/i686/ketypes.h | 3 --- 2 files changed, 6 deletions(-) diff --git a/sdk/xtdk/amd64/ketypes.h b/sdk/xtdk/amd64/ketypes.h index 1299161..ccb7d9d 100644 --- a/sdk/xtdk/amd64/ketypes.h +++ b/sdk/xtdk/amd64/ketypes.h @@ -108,9 +108,6 @@ /* Static Kernel-Mode address start */ #define KSEG0_BASE 0xFFFFF80000000000 -/* XTOS Kernel address base */ -#define KSEG0_KERNEL_BASE 0x0000000800000000 - /* XTOS Kernel stack size */ #define KERNEL_STACK_SIZE 0x8000 diff --git a/sdk/xtdk/i686/ketypes.h b/sdk/xtdk/i686/ketypes.h index f62ff74..32697c4 100644 --- a/sdk/xtdk/i686/ketypes.h +++ b/sdk/xtdk/i686/ketypes.h @@ -128,9 +128,6 @@ /* Static Kernel-Mode address start */ #define KSEG0_BASE 0x80000000 -/* XTOS Kernel address base */ -#define KSEG0_KERNEL_BASE 0x01800000 - /* XTOS Kernel stack size */ #define KERNEL_STACK_SIZE 0x4000 -- 2.52.0 From 587b85d0a49074a8349a76f4f9e329d925716b87 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Tue, 13 Jan 2026 15:39:16 +0100 Subject: [PATCH 114/166] Annotate input parameters --- xtoskrnl/includes/mm/colors.hh | 4 ++-- xtoskrnl/mm/colors.cc | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/xtoskrnl/includes/mm/colors.hh b/xtoskrnl/includes/mm/colors.hh index e6e3183..06d1c40 100644 --- a/xtoskrnl/includes/mm/colors.hh +++ b/xtoskrnl/includes/mm/colors.hh @@ -25,8 +25,8 @@ namespace MM public: STATIC XTAPI VOID ComputePageColoring(VOID); - STATIC XTAPI PMMCOLOR_TABLES GetFreePages(MMPAGELISTS PageList, - ULONG Color); + STATIC XTAPI PMMCOLOR_TABLES GetFreePages(IN MMPAGELISTS PageList, + IN ULONG Color); STATIC XTAPI PMMPFNLIST GetModifiedPages(IN ULONG Color); STATIC XTAPI ULONG GetNextColor(VOID); STATIC XTAPI ULONG GetPagingColors(VOID); diff --git a/xtoskrnl/mm/colors.cc b/xtoskrnl/mm/colors.cc index df39cc8..2607ee4 100644 --- a/xtoskrnl/mm/colors.cc +++ b/xtoskrnl/mm/colors.cc @@ -42,8 +42,8 @@ MM::Colors::ComputePageColoring(VOID) */ XTAPI PMMCOLOR_TABLES -MM::Colors::GetFreePages(MMPAGELISTS PageList, - ULONG Color) +MM::Colors::GetFreePages(IN MMPAGELISTS PageList, + IN ULONG Color) { /* Return a pointer to the requested color table entry */ return &FreePages[PageList][Color]; -- 2.52.0 From 0f38d397058d7c670e11590af497c137898a45c9 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Wed, 14 Jan 2026 17:44:50 +0100 Subject: [PATCH 115/166] Correctly initialize PFN entries for pre-mapped KSEG0 based memory --- xtoskrnl/mm/amd64/pfn.cc | 46 ++++++++++++++++++++++++++++------------ 1 file changed, 33 insertions(+), 13 deletions(-) diff --git a/xtoskrnl/mm/amd64/pfn.cc b/xtoskrnl/mm/amd64/pfn.cc index dd14489..c858beb 100644 --- a/xtoskrnl/mm/amd64/pfn.cc +++ b/xtoskrnl/mm/amd64/pfn.cc @@ -190,6 +190,7 @@ MM::Pfn::ProcessMemoryDescriptor(IN PFN_NUMBER BasePage, IN LOADER_MEMORY_TYPE MemoryType) { PFN_NUMBER PageNumber; + PMMPDE PointerPde; PMMPFN Pfn; /* Check if the memory descriptor describes a free memory region */ @@ -227,17 +228,24 @@ MM::Pfn::ProcessMemoryDescriptor(IN PFN_NUMBER BasePage, /* Get the PFN entry for the current ROM page */ Pfn = GetPfnEntry(BasePage + PageNumber); - /* Initialize the PFN entry to represent a ROM page */ - Pfn->PteAddress = 0; - Pfn->u1.Flink = 0; - Pfn->u2.ShareCount = 0; - Pfn->u3.e1.CacheAttribute = PfnNonCached; - Pfn->u3.e1.PageLocation = 0; - Pfn->u3.e1.PrototypePte = 1; - Pfn->u3.e1.Rom = 1; - Pfn->u3.e2.ReferenceCount = 0; - Pfn->u4.InPageError = 0; - Pfn->u4.PteFrame = 0; + /* Ensure that the page is not already in-use */ + if(Pfn->u3.e2.ReferenceCount == 0) + { + /* Get the page directory entry for the current page */ + PointerPde = MM::Paging::GetPdeAddress((PVOID)(KSEG0_BASE + (BasePage << MM_PAGE_SHIFT))); + + /* Initialize the PFN entry to represent a ROM page */ + Pfn->PteAddress = MM::Paging::GetPteAddress((PVOID)(KSEG0_BASE + (BasePage << MM_PAGE_SHIFT))); + Pfn->u1.Flink = 0; + Pfn->u2.ShareCount = 0; + Pfn->u3.e1.CacheAttribute = PfnCached; + Pfn->u3.e1.PageLocation = 0; + Pfn->u3.e1.PrototypePte = 1; + Pfn->u3.e1.Rom = 1; + Pfn->u3.e2.ReferenceCount = 0; + Pfn->u4.InPageError = 0; + Pfn->u4.PteFrame = MM::Paging::GetPageFrameNumber(PointerPde); + } } break; default: @@ -247,8 +255,20 @@ MM::Pfn::ProcessMemoryDescriptor(IN PFN_NUMBER BasePage, /* Get the PFN entry for the current in-use page */ Pfn = GetPfnEntry(BasePage + PageNumber); - /* Mark the PFN as active and valid to prevent it from being allocated */ - Pfn->u3.e1.PageLocation = ActiveAndValid; + /* Ensure that the page is not already in-use */ + if(Pfn->u3.e2.ReferenceCount == 0) + { + /* Get the page directory entry for the current page */ + PointerPde = MM::Paging::GetPdeAddress((PVOID)(KSEG0_BASE + (BasePage << MM_PAGE_SHIFT))); + + /* Initialize the PFN entry to represent an in-use page and prevent it from being allocated */ + Pfn->PteAddress = MM::Paging::GetPteAddress((PVOID)(KSEG0_BASE + (BasePage << MM_PAGE_SHIFT))); + Pfn->u2.ShareCount++; + Pfn->u3.e1.CacheAttribute = PfnCached; + Pfn->u3.e1.PageLocation = ActiveAndValid; + Pfn->u3.e2.ReferenceCount = 1; + Pfn->u4.PteFrame = MM::Paging::GetPageFrameNumber(PointerPde); + } } break; } -- 2.52.0 From 7da6bcc75eb6886c824136eb72e7e1e4ae56d0de Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Wed, 14 Jan 2026 22:42:14 +0100 Subject: [PATCH 116/166] Standardize ValidPte setup across architectures --- xtoskrnl/mm/amd64/pte.cc | 15 --------------- xtoskrnl/mm/i686/pte.cc | 15 --------------- xtoskrnl/mm/pte.cc | 15 +++++++++++++++ 3 files changed, 15 insertions(+), 30 deletions(-) diff --git a/xtoskrnl/mm/amd64/pte.cc b/xtoskrnl/mm/amd64/pte.cc index f255b07..71fba17 100644 --- a/xtoskrnl/mm/amd64/pte.cc +++ b/xtoskrnl/mm/amd64/pte.cc @@ -153,21 +153,6 @@ MM::Pte::InitializePageTable(VOID) MM::Paging::SetPte(MM::Paging::GetPteAddress((PVOID)MemoryLayout->HyperSpaceStart), MM_HYPERSPACE_PAGE_COUNT, 0); } -/** - * Initializes the system's PTE. - * - * @return This routine does not return any value. - * - * @since XT 1.0 - */ -XTAPI -VOID -MM::Pte::InitializeSystemPte(VOID) -{ - /* Initialize the PTE template */ - ValidPte = {MM_PTE_VALID|MM_PTE_EXECUTE_READWRITE|MM_PTE_DIRTY|MM_PTE_ACCESSED}; -} - /** * Maps a range of virtual addresses at the P5E (PML5) level. * diff --git a/xtoskrnl/mm/i686/pte.cc b/xtoskrnl/mm/i686/pte.cc index ab83731..60bc935 100644 --- a/xtoskrnl/mm/i686/pte.cc +++ b/xtoskrnl/mm/i686/pte.cc @@ -112,21 +112,6 @@ MM::Pte::InitializePageTable(VOID) MM::Pte::MapPDE(MemoryLayout->SystemSpaceStart, (PVOID)MM_HIGHEST_SYSTEM_ADDRESS, &TemplatePte); } -/** - * Initializes the system's PTE. - * - * @return This routine does not return any value. - * - * @since XT 1.0 - */ -XTAPI -VOID -MM::Pte::InitializeSystemPte(VOID) -{ - /* Initialize the PTE template */ - ValidPte = {{MM_PTE_VALID|MM_PTE_EXECUTE_READWRITE|MM_PTE_DIRTY|MM_PTE_ACCESSED}}; -} - /** * Maps a range of virtual addresses at the PPE (Page Directory Pointer Entry) level. * diff --git a/xtoskrnl/mm/pte.cc b/xtoskrnl/mm/pte.cc index efa382e..e281ba4 100644 --- a/xtoskrnl/mm/pte.cc +++ b/xtoskrnl/mm/pte.cc @@ -119,6 +119,21 @@ MM::Pte::GetValidPte() return &ValidPte; } +/** + * Initializes the system's PTE. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::Pte::InitializeSystemPte(VOID) +{ + /* Initialize the PTE template */ + MM::Paging::SetPte(&ValidPte, MM_PTE_VALID | MM_PTE_EXECUTE_READWRITE | MM_PTE_DIRTY | MM_PTE_ACCESSED); +} + /** * Formats a range of PTEs into a freelist-based pool for system allocations. * -- 2.52.0 From c3607ea943c32cd54321e115a94bdbd6ee71e9e2 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Wed, 14 Jan 2026 22:48:25 +0100 Subject: [PATCH 117/166] Add missing annotations --- xtoskrnl/includes/mm/amd64/pte.hh | 30 +++++++++++++++--------------- xtoskrnl/includes/mm/i686/pte.hh | 18 +++++++++--------- xtoskrnl/mm/amd64/pte.cc | 18 +++++++++--------- xtoskrnl/mm/i686/pte.cc | 6 +++--- xtoskrnl/mm/pte.cc | 12 ++++++------ 5 files changed, 42 insertions(+), 42 deletions(-) diff --git a/xtoskrnl/includes/mm/amd64/pte.hh b/xtoskrnl/includes/mm/amd64/pte.hh index 23d44e1..3f9c3ff 100644 --- a/xtoskrnl/includes/mm/amd64/pte.hh +++ b/xtoskrnl/includes/mm/amd64/pte.hh @@ -33,21 +33,21 @@ namespace MM STATIC XTAPI VOID InitializePageTable(VOID); STATIC XTAPI VOID InitializeSystemPte(VOID); STATIC XTAPI VOID InitializeSystemPteSpace(VOID); - STATIC XTAPI VOID MapP5E(PVOID StartAddress, - PVOID EndAddress, - PMMP5E TemplateP5e); - STATIC XTAPI VOID MapPDE(PVOID StartAddress, - PVOID EndAddress, - PMMPDE TemplatePde); - STATIC XTAPI VOID MapPPE(PVOID StartAddress, - PVOID EndAddress, - PMMPPE TemplatePpe); - STATIC XTAPI VOID MapPTE(PVOID StartAddress, - PVOID EndAddress, - PMMPTE TemplatePte); - STATIC XTAPI VOID MapPXE(PVOID StartAddress, - PVOID EndAddress, - PMMPXE TemplatePxe); + STATIC XTAPI VOID MapP5E(IN PVOID StartAddress, + IN PVOID EndAddress, + IN PMMP5E TemplateP5e); + STATIC XTAPI VOID MapPDE(IN PVOID StartAddress, + IN PVOID EndAddress, + IN PMMPDE TemplatePde); + STATIC XTAPI VOID MapPPE(IN PVOID StartAddress, + IN PVOID EndAddress, + IN PMMPPE TemplatePpe); + STATIC XTAPI VOID MapPTE(IN PVOID StartAddress, + IN PVOID EndAddress, + IN PMMPTE TemplatePte); + STATIC XTAPI VOID MapPXE(IN PVOID StartAddress, + IN PVOID EndAddress, + IN PMMPXE TemplatePxe); STATIC XTAPI VOID ReleaseSystemPtes(IN PMMPTE StartingPte, IN PFN_COUNT NumberOfPtes, IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType); diff --git a/xtoskrnl/includes/mm/i686/pte.hh b/xtoskrnl/includes/mm/i686/pte.hh index 879579b..116a022 100644 --- a/xtoskrnl/includes/mm/i686/pte.hh +++ b/xtoskrnl/includes/mm/i686/pte.hh @@ -33,15 +33,15 @@ namespace MM STATIC XTAPI VOID InitializePageTable(VOID); STATIC XTAPI VOID InitializeSystemPte(VOID); STATIC XTAPI VOID InitializeSystemPteSpace(VOID); - STATIC XTAPI VOID MapPDE(PVOID StartAddress, - PVOID EndAddress, - PMMPDE TemplatePde); - STATIC XTAPI VOID MapPPE(PVOID StartAddress, - PVOID EndAddress, - PMMPPE TemplatePpe); - STATIC XTAPI VOID MapPTE(PVOID StartAddress, - PVOID EndAddress, - PMMPTE TemplatePte); + STATIC XTAPI VOID MapPDE(IN PVOID StartAddress, + IN PVOID EndAddress, + IN PMMPDE TemplatePde); + STATIC XTAPI VOID MapPPE(IN PVOID StartAddress, + IN PVOID EndAddress, + IN PMMPPE TemplatePpe); + STATIC XTAPI VOID MapPTE(IN PVOID StartAddress, + IN PVOID EndAddress, + IN PMMPTE TemplatePte); STATIC XTAPI VOID ReleaseSystemPtes(IN PMMPTE StartingPte, IN PFN_COUNT NumberOfPtes, IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType); diff --git a/xtoskrnl/mm/amd64/pte.cc b/xtoskrnl/mm/amd64/pte.cc index 71fba17..80742d0 100644 --- a/xtoskrnl/mm/amd64/pte.cc +++ b/xtoskrnl/mm/amd64/pte.cc @@ -171,9 +171,9 @@ MM::Pte::InitializePageTable(VOID) */ XTAPI VOID -MM::Pte::MapP5E(PVOID StartAddress, - PVOID EndAddress, - PMMP5E TemplateP5e) +MM::Pte::MapP5E(IN PVOID StartAddress, + IN PVOID EndAddress, + IN PMMP5E TemplateP5e) { PMMP5E EndSpace, PointerP5e; @@ -218,9 +218,9 @@ MM::Pte::MapP5E(PVOID StartAddress, */ XTAPI VOID -MM::Pte::MapPPE(PVOID StartAddress, - PVOID EndAddress, - PMMPPE TemplatePpe) +MM::Pte::MapPPE(IN PVOID StartAddress, + IN PVOID EndAddress, + IN PMMPPE TemplatePpe) { PMMPPE EndSpace, PointerPpe; @@ -265,9 +265,9 @@ MM::Pte::MapPPE(PVOID StartAddress, */ XTAPI VOID -MM::Pte::MapPXE(PVOID StartAddress, - PVOID EndAddress, - PMMPXE TemplatePxe) +MM::Pte::MapPXE(IN PVOID StartAddress, + IN PVOID EndAddress, + IN PMMPXE TemplatePxe) { PMMPXE EndSpace, PointerPxe; diff --git a/xtoskrnl/mm/i686/pte.cc b/xtoskrnl/mm/i686/pte.cc index 60bc935..04b4755 100644 --- a/xtoskrnl/mm/i686/pte.cc +++ b/xtoskrnl/mm/i686/pte.cc @@ -130,9 +130,9 @@ MM::Pte::InitializePageTable(VOID) */ XTAPI VOID -MM::Pte::MapPPE(PVOID StartAddress, - PVOID EndAddress, - PMMPPE TemplatePpe) +MM::Pte::MapPPE(IN PVOID StartAddress, + IN PVOID EndAddress, + IN PMMPPE TemplatePpe) { /* Just a stub on i686 platform */ return; diff --git a/xtoskrnl/mm/pte.cc b/xtoskrnl/mm/pte.cc index e281ba4..a7ce084 100644 --- a/xtoskrnl/mm/pte.cc +++ b/xtoskrnl/mm/pte.cc @@ -232,9 +232,9 @@ MM::Pte::InitializeSystemPteSpace(VOID) */ XTAPI VOID -MM::Pte::MapPDE(PVOID StartAddress, - PVOID EndAddress, - PMMPDE TemplatePde) +MM::Pte::MapPDE(IN PVOID StartAddress, + IN PVOID EndAddress, + IN PMMPDE TemplatePde) { PMMPDE EndSpace, PointerPde; @@ -279,9 +279,9 @@ MM::Pte::MapPDE(PVOID StartAddress, */ XTAPI VOID -MM::Pte::MapPTE(PVOID StartAddress, - PVOID EndAddress, - PMMPTE TemplatePte) +MM::Pte::MapPTE(IN PVOID StartAddress, + IN PVOID EndAddress, + IN PMMPTE TemplatePte) { PMMPTE EndSpace, PointerPte; -- 2.52.0 From 46c24e653e53a210bc609488366bf79ab5dd2ad9 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Thu, 15 Jan 2026 19:09:10 +0100 Subject: [PATCH 118/166] Add routine to retrieve installed memory size --- xtoskrnl/includes/mm/mmgr.hh | 1 + xtoskrnl/mm/mmgr.cc | 15 +++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/xtoskrnl/includes/mm/mmgr.hh b/xtoskrnl/includes/mm/mmgr.hh index 8d4254a..e33253b 100644 --- a/xtoskrnl/includes/mm/mmgr.hh +++ b/xtoskrnl/includes/mm/mmgr.hh @@ -22,6 +22,7 @@ namespace MM STATIC PFN_NUMBER NumberOfSystemPtes; public: + STATIC XTAPI ULONG_PTR GetInstalledMemorySize(VOID); STATIC XTAPI PMMMEMORY_LAYOUT GetMemoryLayout(VOID); STATIC XTAPI PFN_NUMBER GetNumberOfSystemPtes(); STATIC XTAPI VOID InitializeMemoryLayout(VOID); diff --git a/xtoskrnl/mm/mmgr.cc b/xtoskrnl/mm/mmgr.cc index 29fa31e..3c22c26 100644 --- a/xtoskrnl/mm/mmgr.cc +++ b/xtoskrnl/mm/mmgr.cc @@ -10,6 +10,21 @@ #include +/** + * Retrieves the amount of total available memory in the system. + * + * @return This routine returns the amount of available memory in the system in megabytes. + * + * @since XT 1.0 + */ +XTAPI +ULONG_PTR +MM::Manager::GetInstalledMemorySize(VOID) +{ + /* Return the amount of installed memory */ + return (MM::Pfn::GetNumberOfPhysicalPages() * MM_PAGE_SIZE) / 1048576; +} + /** * Retrieves a pointer to the system's virtual memory layout structure. * -- 2.52.0 From d3edfef53bf01004336df9f58bb7f89474250f0d Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Mon, 19 Jan 2026 11:16:59 +0100 Subject: [PATCH 119/166] Fix broken PPE check on i686 --- xtoskrnl/mm/i686/pte.cc | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/xtoskrnl/mm/i686/pte.cc b/xtoskrnl/mm/i686/pte.cc index 04b4755..a348d81 100644 --- a/xtoskrnl/mm/i686/pte.cc +++ b/xtoskrnl/mm/i686/pte.cc @@ -23,17 +23,6 @@ XTAPI BOOLEAN MM::Pte::AddressValid(IN PVOID VirtualAddress) { - /* Check XPA status */ - if(MM::Paging::GetXpaStatus()) - { - /* Check if the P5E is valid */ - if(!MM::Paging::PteValid(MM::Paging::GetPpeAddress(VirtualAddress))) - { - /* Invalid PPE, return FALSE */ - return FALSE; - } - } - /* Check if PDE and PTE are valid */ if(!MM::Paging::PteValid(MM::Paging::GetPdeAddress(VirtualAddress)) || !MM::Paging::PteValid(MM::Paging::GetPteAddress(VirtualAddress))) -- 2.52.0 From 0b1b76e9dfd657f3ac918a3ca5fca9d13c726811 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Tue, 20 Jan 2026 16:04:07 +0100 Subject: [PATCH 120/166] Rollback bootloader memory management changes --- boot/xtldr/includes/xtldr.hh | 15 +- boot/xtldr/memory.cc | 226 +++++++++++++------ boot/xtldr/modules/xtos_o/amd64/memory.cc | 14 -- boot/xtldr/modules/xtos_o/i686/memory.cc | 14 -- boot/xtldr/modules/xtos_o/includes/xtos.hh | 30 ++- boot/xtldr/modules/xtos_o/xtos.cc | 246 ++++++--------------- boot/xtldr/protocol.cc | 2 + sdk/xtdk/amd64/ketypes.h | 3 + sdk/xtdk/bltypes.h | 6 +- sdk/xtdk/i686/ketypes.h | 3 + 10 files changed, 270 insertions(+), 289 deletions(-) diff --git a/boot/xtldr/includes/xtldr.hh b/boot/xtldr/includes/xtldr.hh index 8d8101c..cb91068 100644 --- a/boot/xtldr/includes/xtldr.hh +++ b/boot/xtldr/includes/xtldr.hh @@ -168,7 +168,6 @@ class Memory STATIC XTCDECL EFI_STATUS FreePages(IN ULONGLONG NumberOfPages, IN EFI_PHYSICAL_ADDRESS Memory); STATIC XTCDECL EFI_STATUS FreePool(IN PVOID Memory); - STATIC XTCDECL LOADER_MEMORY_TYPE GetLoaderMemoryType(IN EFI_MEMORY_TYPE EfiMemoryType); STATIC XTCDECL VOID GetMappingsCount(IN PXTBL_PAGE_MAPPING PageMap, OUT PULONG NumberOfMappings); STATIC XTCDECL EFI_STATUS GetMemoryMap(OUT PEFI_MEMORY_MAP MemoryMap); @@ -178,7 +177,8 @@ class Memory IN SHORT PageMapLevel, IN PAGE_SIZE PageSize); STATIC XTCDECL EFI_STATUS MapEfiMemory(IN OUT PXTBL_PAGE_MAPPING PageMap, - IN ULONG_PTR BaseAddress); + IN OUT PVOID *MemoryMapAddress, + IN PBL_GET_MEMTYPE_ROUTINE GetMemoryTypeRoutine); STATIC XTCDECL EFI_STATUS MapPage(IN PXTBL_PAGE_MAPPING PageMap, IN ULONGLONG VirtualAddress, IN ULONGLONG PhysicalAddress, @@ -188,15 +188,20 @@ class Memory IN ULONGLONG PhysicalAddress, IN ULONGLONG NumberOfPages, IN LOADER_MEMORY_TYPE MemoryType); + STATIC XTCDECL PVOID PhysicalAddressToVirtual(IN PVOID PhysicalAddress, + IN PVOID PhysicalBase, + IN PVOID VirtualBase); + STATIC XTCDECL EFI_STATUS PhysicalListToVirtual(IN PXTBL_PAGE_MAPPING PageMap, + IN OUT PLIST_ENTRY ListHead, + IN PVOID PhysicalBase, + IN PVOID VirtualBase); private: + STATIC XTCDECL LOADER_MEMORY_TYPE GetLoaderMemoryType(IN EFI_MEMORY_TYPE EfiMemoryType); STATIC XTCDECL EFI_STATUS GetNextPageTable(IN PXTBL_PAGE_MAPPING PageMap, IN PVOID PageTable, IN SIZE_T Entry, OUT PVOID *NextPageTable); - STATIC XTCDECL EFI_STATUS MapDescriptor(IN OUT PXTBL_PAGE_MAPPING PageMap, - IN PEFI_MEMORY_DESCRIPTOR Descriptor, - IN ULONG_PTR BaseAddress); STATIC XTCDECL EFI_STATUS SelfMapPml(IN PXTBL_PAGE_MAPPING PageMap, IN ULONG_PTR SelfMapAddress); }; diff --git a/boot/xtldr/memory.cc b/boot/xtldr/memory.cc index c0ad17f..6591833 100644 --- a/boot/xtldr/memory.cc +++ b/boot/xtldr/memory.cc @@ -4,7 +4,6 @@ * FILE: xtldr/memory.cc * DESCRIPTION: XT Boot Loader memory management * DEVELOPERS: Rafal Kupiec - * Aiken Harris */ #include @@ -309,69 +308,17 @@ Memory::InitializePageMap(OUT PXTBL_PAGE_MAPPING PageMap, PageMap->PageSize = PageSize; } -/** - * Maps memory descriptor to the page mapping structure. - * - * @param PageMap - * Supplies a pointer to the page mapping structure. - * - * @param Descriptor - * Supplies a pointer to EFI memory descriptor, which will be mapped. - * - * @param BaseAddress - * Supplies a base address, where EFI memory will be mapped. - * - * @return This routine returns a status code. - * - * @since XT 1.0 - */ -XTCDECL -EFI_STATUS -Memory::MapDescriptor(IN OUT PXTBL_PAGE_MAPPING PageMap, - IN PEFI_MEMORY_DESCRIPTOR Descriptor, - IN ULONG_PTR BaseAddress) -{ - LOADER_MEMORY_TYPE MemoryType; - - /* Skip EFI reserved memory */ - if(Descriptor->Type == EfiReservedMemoryType) - { - /* Skip EFI reserved memory */ - return STATUS_EFI_SUCCESS; - } - - /* Convert EFI memory type into XTLDR memory type */ - MemoryType = Memory::GetLoaderMemoryType((EFI_MEMORY_TYPE)Descriptor->Type); - - /* Do memory mappings depending on memory type */ - if(MemoryType == LoaderFirmwareTemporary) - { - /* Map EFI firmware code */ - return Memory::MapVirtualMemory(PageMap, Descriptor->PhysicalStart, - Descriptor->PhysicalStart, Descriptor->NumberOfPages, MemoryType); - } - else if(MemoryType != LoaderFree) - { - /* Add any non-free memory mappings based on provided base address */ - return Memory::MapVirtualMemory(PageMap, (BaseAddress | Descriptor->PhysicalStart), Descriptor->PhysicalStart, - Descriptor->NumberOfPages, MemoryType); - } - else - { - /* Map all other memory as loader free */ - return Memory::MapVirtualMemory(PageMap, (ULONGLONG)NULLPTR, Descriptor->PhysicalStart, - Descriptor->NumberOfPages, LoaderFree); - } -} - /** * Adds EFI memory mapping to the page mapping structure. * * @param PageMap * Supplies a pointer to the page mapping structure. * - * @param BaseAddress - * Supplies a base address, where EFI memory will be mapped. + * @param MemoryMapAddress + * Supplies a virtual address, where EFI memory will be mapped. + * + * @param GetMemoryTypeRoutine + * Supplies a pointer to the routine which will be used to match EFI memory type to the OS memory type. * * @return This routine returns a status code. * @@ -380,15 +327,27 @@ Memory::MapDescriptor(IN OUT PXTBL_PAGE_MAPPING PageMap, XTCDECL EFI_STATUS Memory::MapEfiMemory(IN OUT PXTBL_PAGE_MAPPING PageMap, - IN ULONG_PTR BaseAddress) + IN OUT PVOID *MemoryMapAddress, + IN PBL_GET_MEMTYPE_ROUTINE GetMemoryTypeRoutine) { + ULONGLONG MaxAddress, VirtualAddress; PEFI_MEMORY_DESCRIPTOR Descriptor; + LOADER_MEMORY_TYPE MemoryType; PEFI_MEMORY_MAP MemoryMap; SIZE_T DescriptorCount; - ULONGLONG MaxAddress; EFI_STATUS Status; SIZE_T Index; + /* Set virtual address as specified in argument */ + VirtualAddress = (ULONGLONG)*MemoryMapAddress; + + /* Check if custom memory type routine is specified */ + if(GetMemoryTypeRoutine == NULLPTR) + { + /* Use default memory type routine */ + GetMemoryTypeRoutine = GetLoaderMemoryType; + } + /* Allocate and zero-fill buffer for EFI memory map */ AllocatePool(sizeof(EFI_MEMORY_MAP), (PVOID*)&MemoryMap); RTL::Memory::ZeroMemory(MemoryMap, sizeof(EFI_MEMORY_MAP)); @@ -434,17 +393,49 @@ Memory::MapEfiMemory(IN OUT PXTBL_PAGE_MAPPING PageMap, /* Check if memory descriptor exceeds the lowest physical page */ if(Descriptor->PhysicalStart + (Descriptor->NumberOfPages << EFI_PAGE_SHIFT) > MaxAddress) { - /* Truncate memory descriptor to maximum supported address */ + /* Truncate memory descriptor to the lowest supported physical page */ Descriptor->NumberOfPages = (((ULONGLONG)MaxAddress) - Descriptor->PhysicalStart) >> EFI_PAGE_SHIFT; } } - /* Map this descriptor and make sure it succeeded */ - Status = MapDescriptor(PageMap, Descriptor, BaseAddress); - if(Status != STATUS_EFI_SUCCESS) { - /* Mapping failed */ - return Status; + /* Skip EFI reserved memory */ + if(Descriptor->Type == EfiReservedMemoryType) + { + /* Go to the next descriptor */ + Descriptor = (PEFI_MEMORY_DESCRIPTOR)((PUCHAR)Descriptor + MemoryMap->DescriptorSize); + continue; + } + + /* Convert EFI memory type into XTLDR memory type */ + MemoryType = GetMemoryTypeRoutine((EFI_MEMORY_TYPE)Descriptor->Type); + + /* Do memory mappings depending on memory type */ + if(MemoryType == LoaderFirmwareTemporary) + { + /* Map EFI firmware code */ + Status = MapVirtualMemory(PageMap, Descriptor->PhysicalStart, + Descriptor->PhysicalStart, Descriptor->NumberOfPages, MemoryType); + } + else if(MemoryType != LoaderFree) + { + /* Add any non-free memory mapping */ + Status = MapVirtualMemory(PageMap, VirtualAddress, Descriptor->PhysicalStart, + Descriptor->NumberOfPages, MemoryType); + } + else + { + /* Map all other memory as loader free */ + Status = MapVirtualMemory(PageMap, (ULONGLONG)NULLPTR, Descriptor->PhysicalStart, + Descriptor->NumberOfPages, LoaderFree); + } + + /* Make sure memory mapping succeeded */ + if(Status != STATUS_EFI_SUCCESS) + { + /* Mapping failed */ + return Status; + } } /* Grab next descriptor */ @@ -468,6 +459,7 @@ Memory::MapEfiMemory(IN OUT PXTBL_PAGE_MAPPING PageMap, } /* Store next valid virtual address and return success */ + *MemoryMapAddress = (PVOID)VirtualAddress; return STATUS_EFI_SUCCESS; } @@ -657,3 +649,105 @@ Memory::MapVirtualMemory(IN OUT PXTBL_PAGE_MAPPING PageMap, /* Return success */ return STATUS_EFI_SUCCESS; } + +/** + * Converts physical address to virtual address based on physical base and virtual base. + * + * @param PhysicalAddress + * Specifies physical address that will be converted to virtual address. + * + * @param PhysicalBase + * Supplies a physical base address. + * + * @param VirtualBase + * Supplies a virtual base address. + * + * @return This routine returns a mapped virtual address. + * + * @since XT 1.0 + */ +XTCDECL +PVOID +Memory::PhysicalAddressToVirtual(IN PVOID PhysicalAddress, + IN PVOID PhysicalBase, + IN PVOID VirtualBase) +{ + /* Convert physical address to virtual address */ + return (PUCHAR)VirtualBase + ((PUCHAR)PhysicalAddress - (PUCHAR)PhysicalBase); +} + +/** + * Converts whole linked list addressing from physical to virtual for future use after enabling paging. + * + * @param PageMap + * Supplies a pointer to the page mapping structure. + * + * @param ListHead + * Supplies a pointer to a structure that serves as the list header. + * + * @param PhysicalBase + * Supplies a physical base address. + * + * @param VirtualBase + * Supplies a virtual base address. + * + * @return This routine returns a status code. + * + * @since XT 1.0 + */ +XTCDECL +EFI_STATUS +Memory::PhysicalListToVirtual(IN PXTBL_PAGE_MAPPING PageMap, + IN OUT PLIST_ENTRY ListHead, + IN PVOID PhysicalBase, + IN PVOID VirtualBase) +{ + PLIST_ENTRY ListEntry, NextEntry; + + /* Make sure list is properly initialized */ + if(ListHead->Flink == 0 || ListHead->Blink == 0) + { + /* List not initialized, return error code */ + return STATUS_EFI_INVALID_PARAMETER; + } + + /* Iterate through all elements */ + ListEntry = ListHead->Flink; + while(ListEntry != ListHead) + { + /* Save physical address of the next element */ + NextEntry = ListEntry->Flink; + + /* Convert the address of this element to VirtualAddress */ + if(ListEntry->Blink == ListHead) + { + /* Find virtual address of list head */ + ListEntry->Blink = (PLIST_ENTRY)GetVirtualAddress(PageMap, ListEntry->Blink); + } + else + { + /* Convert list entry */ + ListEntry->Blink = (PLIST_ENTRY)PhysicalAddressToVirtual(ListEntry->Blink, (PVOID)PhysicalBase, VirtualBase); + } + if(ListEntry->Flink == ListHead) + { + /* Convert list head */ + ListEntry->Flink = ListHead->Flink->Blink; + } + else + { + /* Convert list entry */ + ListEntry->Flink = (PLIST_ENTRY)PhysicalAddressToVirtual(ListEntry->Flink, (PVOID)PhysicalBase, VirtualBase); + } + + /* Get to the next element*/ + ListEntry = NextEntry; + } + + /* Convert list head */ + ListHead->Blink = (PLIST_ENTRY)PhysicalAddressToVirtual(ListHead->Blink, (PVOID)PhysicalBase, VirtualBase); + ListHead->Flink = (PLIST_ENTRY)PhysicalAddressToVirtual(ListHead->Flink, (PVOID)PhysicalBase, VirtualBase); + + /* Return success */ + return STATUS_EFI_SUCCESS; +} diff --git a/boot/xtldr/modules/xtos_o/amd64/memory.cc b/boot/xtldr/modules/xtos_o/amd64/memory.cc index c5afa07..02335aa 100644 --- a/boot/xtldr/modules/xtos_o/amd64/memory.cc +++ b/boot/xtldr/modules/xtos_o/amd64/memory.cc @@ -156,20 +156,6 @@ Xtos::EnablePaging(IN PXTBL_PAGE_MAPPING PageMap) return STATUS_EFI_SUCCESS; } -/** - * Returns the base address of the memory mapping. - * - * @return This routine returns the base address of the memory mapping. - * - * @since XT 1.0 - */ -XTCDECL -ULONG_PTR -Xtos::GetBaseMappingAddress(VOID) -{ - return KSEG0_BASE; -} - /** * Maps the page table for hardware layer addess space. * diff --git a/boot/xtldr/modules/xtos_o/i686/memory.cc b/boot/xtldr/modules/xtos_o/i686/memory.cc index 08cf608..44ee233 100644 --- a/boot/xtldr/modules/xtos_o/i686/memory.cc +++ b/boot/xtldr/modules/xtos_o/i686/memory.cc @@ -44,20 +44,6 @@ Xtos::DeterminePagingLevel(IN CONST PWCHAR Parameters) return 2; } -/** - * Returns the base address of the memory mapping. - * - * @return This routine returns the base address of the memory mapping. - * - * @since XT 1.0 - */ -XTCDECL -ULONG_PTR -Xtos::GetBaseMappingAddress(VOID) -{ - return KSEG0_BASE; -} - /** * Builds the actual memory mapping page table and enables paging. This routine exits EFI boot services as well. * diff --git a/boot/xtldr/modules/xtos_o/includes/xtos.hh b/boot/xtldr/modules/xtos_o/includes/xtos.hh index 8d4b31e..4d70606 100644 --- a/boot/xtldr/modules/xtos_o/includes/xtos.hh +++ b/boot/xtldr/modules/xtos_o/includes/xtos.hh @@ -33,34 +33,44 @@ class Xtos IN PEFI_SYSTEM_TABLE SystemTable); private: + STATIC XTCDECL EFI_STATUS AddVirtualMemoryMapping(IN PLIST_ENTRY MemoryMappings, + IN PVOID VirtualAddress, + IN PVOID PhysicalAddress, + IN UINT NumberOfPages, + IN LOADER_MEMORY_TYPE MemoryType); + STATIC XTCDECL LOADER_MEMORY_TYPE ConvertEfiMemoryType(IN EFI_MEMORY_TYPE EfiMemoryType); STATIC XTCDECL ULONG DeterminePagingLevel(IN CONST PWCHAR Parameters); STATIC XTCDECL EFI_STATUS EnablePaging(IN PXTBL_PAGE_MAPPING PageMap); - STATIC XTCDECL ULONG_PTR GetBaseMappingAddress(VOID); STATIC XTCDECL VOID GetDisplayInformation(OUT PSYSTEM_RESOURCE_FRAMEBUFFER FrameBufferResource, IN PEFI_PHYSICAL_ADDRESS FrameBufferBase, IN PULONG_PTR FrameBufferSize, IN PXTBL_FRAMEBUFFER_MODE_INFORMATION FrameBufferModeInfo); STATIC XTCDECL EFI_STATUS GetMemoryDescriptorList(IN PXTBL_PAGE_MAPPING PageMap, + IN PVOID *VirtualAddress, OUT PLIST_ENTRY MemoryDescriptorList); STATIC XTCDECL EFI_STATUS GetSystemResourcesList(IN PXTBL_PAGE_MAPPING PageMap, + IN PVOID *VirtualAddress, OUT PLIST_ENTRY SystemResourcesList); + STATIC XTCDECL EFI_STATUS GetVirtualAddress(IN PLIST_ENTRY MemoryMappings, + IN PVOID PhysicalAddress, + OUT PVOID *VirtualAddress); STATIC XTCDECL EFI_STATUS InitializeApicBase(IN PXTBL_PAGE_MAPPING PageMap); STATIC XTCDECL EFI_STATUS InitializeLoaderBlock(IN PXTBL_PAGE_MAPPING PageMap, - OUT PKERNEL_INITIALIZATION_BLOCK *KernelParameters, + IN PVOID *VirtualAddress, IN PXTBL_BOOT_PARAMETERS Parameters); + STATIC XTCDECL EFI_STATUS InitializeVirtualMemory(IN OUT PLIST_ENTRY MemoryMappings, + IN OUT PVOID *MemoryMapAddress); STATIC XTCDECL EFI_STATUS LoadModule(IN PEFI_FILE_HANDLE BootDir, IN PWCHAR FileName, + IN PVOID VirtualAddress, IN LOADER_MEMORY_TYPE MemoryType, - IN OUT PXTBL_PAGE_MAPPING PageMap, OUT PPECOFF_IMAGE_CONTEXT *ImageContext); STATIC XTCDECL EFI_STATUS MapHardwareMemoryPool(IN PXTBL_PAGE_MAPPING PageMap); - STATIC XTCDECL EFI_STATUS MapMemory(IN OUT PXTBL_PAGE_MAPPING PageMap, - IN ULONGLONG Address, - IN ULONG NumberOfPages, - IN LOADER_MEMORY_TYPE MemoryType, - IN BOOLEAN KernelMapping); - STATIC XTCDECL PVOID PhysicalAddressToVirtual(PVOID PhysicalAddress); - STATIC XTCDECL EFI_STATUS PhysicalListToVirtual(IN OUT PLIST_ENTRY ListHead); + STATIC XTCDECL EFI_STATUS MapVirtualMemory(IN PLIST_ENTRY MemoryMappings, + IN UINT_PTR VirtualAddress, + IN UINT_PTR PhysicalAddress, + IN UINT NumberOfPages, + IN OUT PVOID *PtePointer); STATIC XTCDECL EFI_STATUS RunBootSequence(IN PEFI_FILE_HANDLE BootDir, IN PXTBL_BOOT_PARAMETERS Parameters); }; diff --git a/boot/xtldr/modules/xtos_o/xtos.cc b/boot/xtldr/modules/xtos_o/xtos.cc index 2edc751..3482003 100644 --- a/boot/xtldr/modules/xtos_o/xtos.cc +++ b/boot/xtldr/modules/xtos_o/xtos.cc @@ -191,6 +191,7 @@ Xtos::GetDisplayInformation(OUT PSYSTEM_RESOURCE_FRAMEBUFFER FrameBufferResource XTCDECL EFI_STATUS Xtos::GetMemoryDescriptorList(IN PXTBL_PAGE_MAPPING PageMap, + IN PVOID *VirtualAddress, OUT PLIST_ENTRY MemoryDescriptorList) { EFI_PHYSICAL_ADDRESS Address; @@ -205,7 +206,7 @@ Xtos::GetMemoryDescriptorList(IN PXTBL_PAGE_MAPPING PageMap, return Status; } - Status = MapMemory(PageMap, Address, Pages, LoaderMemoryData, TRUE); + Status = XtLdrProtocol->Memory.MapVirtualMemory(PageMap, (ULONGLONG)*VirtualAddress, Address, Pages, LoaderMemoryData); if(Status != STATUS_EFI_SUCCESS) { XtLdrProtocol->Memory.FreePages(Address, Pages); @@ -213,14 +214,13 @@ Xtos::GetMemoryDescriptorList(IN PXTBL_PAGE_MAPPING PageMap, } PVOID PhysicalBase = (PVOID)Address; - PVOID CurrentDescriptor = PhysicalBase; PLIST_ENTRY ListEntry; ListEntry = PageMap->MemoryMap.Flink; while(ListEntry != &PageMap->MemoryMap) { PXTBL_MEMORY_MAPPING MemoryMapping = CONTAIN_RECORD(ListEntry, XTBL_MEMORY_MAPPING, ListEntry); - PLOADER_MEMORY_DESCRIPTOR MemoryDescriptor = (PLOADER_MEMORY_DESCRIPTOR)CurrentDescriptor; + PLOADER_MEMORY_DESCRIPTOR MemoryDescriptor = (PLOADER_MEMORY_DESCRIPTOR)Address; MemoryDescriptor->MemoryType = MemoryMapping->MemoryType; MemoryDescriptor->BasePage = (UINT_PTR)MemoryMapping->PhysicalAddress / EFI_PAGE_SIZE; @@ -228,11 +228,11 @@ Xtos::GetMemoryDescriptorList(IN PXTBL_PAGE_MAPPING PageMap, XtLdrProtocol->LinkedList.InsertTail(MemoryDescriptorList, &MemoryDescriptor->ListEntry); - CurrentDescriptor = (PUINT8)CurrentDescriptor + sizeof(LOADER_MEMORY_DESCRIPTOR); + Address = Address + sizeof(LOADER_MEMORY_DESCRIPTOR); ListEntry = ListEntry->Flink; } - PhysicalListToVirtual(MemoryDescriptorList); + XtLdrProtocol->Memory.PhysicalListToVirtual(PageMap, MemoryDescriptorList, PhysicalBase, *VirtualAddress); return STATUS_EFI_SUCCESS; } @@ -240,6 +240,7 @@ Xtos::GetMemoryDescriptorList(IN PXTBL_PAGE_MAPPING PageMap, XTCDECL EFI_STATUS Xtos::GetSystemResourcesList(IN PXTBL_PAGE_MAPPING PageMap, + IN PVOID *VirtualAddress, OUT PLIST_ENTRY SystemResourcesList) { XTSTATUS Status; @@ -256,6 +257,7 @@ Xtos::GetSystemResourcesList(IN PXTBL_PAGE_MAPPING PageMap, PSYSTEM_RESOURCE_ACPI AcpiResource; ULONGLONG Pages; EFI_PHYSICAL_ADDRESS Address; + PVOID PhysicalBase, VirtualBase; Pages = (ULONGLONG)EFI_SIZE_TO_PAGES(sizeof(SYSTEM_RESOURCE_ACPI) + sizeof(SYSTEM_RESOURCE_FRAMEBUFFER)); @@ -264,14 +266,19 @@ Xtos::GetSystemResourcesList(IN PXTBL_PAGE_MAPPING PageMap, { return Status; } - - Status = MapMemory(PageMap, Address, Pages, LoaderFirmwarePermanent, TRUE); + Status = XtLdrProtocol->Memory.MapVirtualMemory(PageMap, (ULONGLONG)*VirtualAddress, Address, Pages, LoaderFirmwarePermanent); if(Status != STATUS_EFI_SUCCESS) { XtLdrProtocol->Memory.FreePages(Address, Pages); return Status; } + PhysicalBase = (PVOID)Address; + VirtualBase = *VirtualAddress; + + /* Calculate next valid virtual address */ + *VirtualAddress = (PUINT8)*VirtualAddress + (Pages * EFI_PAGE_SIZE); + AcpiResource = (PSYSTEM_RESOURCE_ACPI)Address; XtLdrProtocol->Memory.ZeroMemory(AcpiResource, sizeof(SYSTEM_RESOURCE_ACPI)); @@ -287,7 +294,7 @@ Xtos::GetSystemResourcesList(IN PXTBL_PAGE_MAPPING PageMap, AcpiResource->Header.ResourceSize = sizeof(SYSTEM_RESOURCE_ACPI); /* Get APIC and XSDP/RSDP addresses */ - AcpiProtocol->GetApicBase((PVOID *)&AcpiResource->ApicBase); + AcpiProtocol->GetApicBase(&AcpiResource->ApicBase); AcpiProtocol->GetAcpiDescriptionPointer(&AcpiResource->Header.PhysicalAddress); /* No need to map ACPI */ @@ -326,19 +333,21 @@ Xtos::GetSystemResourcesList(IN PXTBL_PAGE_MAPPING PageMap, FrameBufferPages = EFI_SIZE_TO_PAGES(FbSize); /* Rewrite framebuffer address by using virtual address */ - FrameBufferResource->Header.VirtualAddress = PhysicalAddressToVirtual(FrameBufferResource->Header.PhysicalAddress); + FrameBufferResource->Header.VirtualAddress = *VirtualAddress; /* Map frame buffer memory */ XtLdrProtocol->Memory.MapVirtualMemory(PageMap, (ULONGLONG)FrameBufferResource->Header.VirtualAddress, (ULONGLONG)FrameBufferResource->Header.PhysicalAddress, - FrameBufferPages, LoaderHardwareCachedMemory); + FrameBufferPages, LoaderFirmwarePermanent); /* Close FrameBuffer protocol */ XtLdrProtocol->Protocol.Close(&ProtocolHandle, &FrameBufGuid); + *VirtualAddress = (PUINT8)*VirtualAddress + (FrameBufferPages * EFI_PAGE_SIZE); + XtLdrProtocol->LinkedList.InsertTail(SystemResourcesList, &FrameBufferResource->Header.ListEntry); - PhysicalListToVirtual(SystemResourcesList); + XtLdrProtocol->Memory.PhysicalListToVirtual(PageMap, SystemResourcesList, PhysicalBase, VirtualBase); return STATUS_EFI_SUCCESS; } @@ -360,7 +369,7 @@ Xtos::InitializeApicBase(IN PXTBL_PAGE_MAPPING PageMap) EFI_GUID AcpiGuid = XT_ACPI_PROTOCOL_GUID; PXTBL_ACPI_PROTOCOL AcpiProtocol; EFI_HANDLE ProtocolHandle; - EFI_PHYSICAL_ADDRESS ApicBaseAddress; + PVOID ApicBaseAddress; EFI_STATUS Status; /* Open ACPI protocol */ @@ -372,7 +381,7 @@ Xtos::InitializeApicBase(IN PXTBL_PAGE_MAPPING PageMap) } /* Get APIC base address */ - Status = AcpiProtocol->GetApicBase((PVOID *)&ApicBaseAddress); + Status = AcpiProtocol->GetApicBase(&ApicBaseAddress); if(Status != STATUS_EFI_SUCCESS) { /* Failed to get APIC base address */ @@ -380,21 +389,18 @@ Xtos::InitializeApicBase(IN PXTBL_PAGE_MAPPING PageMap) } /* Map APIC base address */ - XtLdrProtocol->Memory.MapVirtualMemory(PageMap, APIC_BASE, ApicBaseAddress, 1, LoaderFirmwarePermanent); + XtLdrProtocol->Memory.MapVirtualMemory(PageMap, APIC_BASE, (ULONGLONG)ApicBaseAddress, 1, LoaderFirmwarePermanent); return STATUS_EFI_SUCCESS; } /** * Initializes and maps the kernel initialization block. * - * @param PageMap - * Supplies a pointer to the page map. + * @param MemoryMappings + * Supplies a pointer to linked list containing all memory mappings. * - * @param KernelParameters - * Returns a pointer to the kernel initialization block. - * - * @param Parameters - * Supplies a list of input parameters passed to the kernel. + * @param VirtualAddress + * Supplies a pointer to the next valid, free and available virtual address. * * @return This routine returns a status code. * @@ -403,7 +409,7 @@ Xtos::InitializeApicBase(IN PXTBL_PAGE_MAPPING PageMap) XTCDECL EFI_STATUS Xtos::InitializeLoaderBlock(IN PXTBL_PAGE_MAPPING PageMap, - OUT PKERNEL_INITIALIZATION_BLOCK *KernelParameters, + IN PVOID *VirtualAddress, IN PXTBL_BOOT_PARAMETERS Parameters) { PKERNEL_INITIALIZATION_BLOCK LoaderBlock; @@ -411,7 +417,6 @@ Xtos::InitializeLoaderBlock(IN PXTBL_PAGE_MAPPING PageMap, EFI_STATUS Status; UINT BlockPages; UINT ParametersSize; - ULONGLONG LoaderBlockVa; /* Calculate size of parameters */ ParametersSize = (XtLdrProtocol->WideString.Length(Parameters->Parameters, 0) + 1) * sizeof(WCHAR); @@ -444,29 +449,25 @@ Xtos::InitializeLoaderBlock(IN PXTBL_PAGE_MAPPING PageMap, // LoaderBlock->FirmwareInformation.EfiFirmware.EfiVersion = EfiSystemTable->Hdr.Revision; LoaderBlock->FirmwareInformation.EfiFirmware.EfiRuntimeServices = NULLPTR; - /* Get the KSEG0-based virtual address for the loader block */ - LoaderBlockVa = (ULONGLONG)PhysicalAddressToVirtual(LoaderBlock); - *KernelParameters = (PKERNEL_INITIALIZATION_BLOCK)LoaderBlockVa; - /* Copy parameters to kernel initialization block */ - LoaderBlock->KernelParameters = (PWCHAR)(LoaderBlockVa + sizeof(KERNEL_INITIALIZATION_BLOCK)); + LoaderBlock->KernelParameters = (PWCHAR)((UINT_PTR)*VirtualAddress + sizeof(KERNEL_INITIALIZATION_BLOCK)); XtLdrProtocol->Memory.CopyMemory((PVOID)((UINT_PTR)LoaderBlock + sizeof(KERNEL_INITIALIZATION_BLOCK)), Parameters->Parameters, ParametersSize); /* Map kernel initialization block */ - Status = MapMemory(PageMap, (ULONGLONG)LoaderBlock, BlockPages, LoaderSystemBlock, TRUE); - if(Status != STATUS_EFI_SUCCESS) - { - return Status; - } + XtLdrProtocol->Memory.MapVirtualMemory(PageMap, (ULONGLONG)*VirtualAddress, (ULONGLONG)LoaderBlock, + BlockPages, LoaderSystemBlock); + + /* Calculate next valid virtual address */ + *VirtualAddress = (PUINT8)*VirtualAddress + (BlockPages * EFI_PAGE_SIZE); XtLdrProtocol->LinkedList.InitializeHead(&LoaderBlock->SystemResourcesListHead); - GetSystemResourcesList(PageMap, &LoaderBlock->SystemResourcesListHead); + GetSystemResourcesList(PageMap, VirtualAddress, &LoaderBlock->SystemResourcesListHead); /* Initialize memory descriptor list */ XtLdrProtocol->LinkedList.InitializeHead(&LoaderBlock->MemoryDescriptorListHead); - GetMemoryDescriptorList(PageMap, &LoaderBlock->MemoryDescriptorListHead); + GetMemoryDescriptorList(PageMap, VirtualAddress, &LoaderBlock->MemoryDescriptorListHead); /* Return success */ return STATUS_EFI_SUCCESS; @@ -507,12 +508,12 @@ Xtos::InitializeModule(IN EFI_HANDLE ImageHandle, * @param FileName * An on disk filename of the module that will be loaded. * + * @param VirtualAddress + * Optional virtual address pointing to the memory area where PE/COFF file will be loaded. + * * @param MemoryType * Supplies the type of memory to be assigned to the memory descriptor. * - * @param PageMap - * Supplies pointer to the memory area where memory mappings will be stored. - * * @param ImageContext * Supplies pointer to the memory area where loaded PE/COFF image context will be stored. * @@ -524,8 +525,8 @@ XTCDECL EFI_STATUS Xtos::LoadModule(IN PEFI_FILE_HANDLE SystemDir, IN PWCHAR FileName, + IN PVOID VirtualAddress, IN LOADER_MEMORY_TYPE MemoryType, - IN OUT PXTBL_PAGE_MAPPING PageMap, OUT PPECOFF_IMAGE_CONTEXT *ImageContext) { PEFI_FILE_HANDLE ModuleHandle; @@ -544,8 +545,8 @@ Xtos::LoadModule(IN PEFI_FILE_HANDLE SystemDir, return Status; } - /* Load the PE/COFF image file into memory */ - Status = PeCoffProtocol->LoadImage(ModuleHandle, MemoryType, NULLPTR, (PVOID*)ImageContext); + /* Load the PE/COFF image file */ + Status = PeCoffProtocol->LoadImage(ModuleHandle, MemoryType, VirtualAddress, (PVOID*)ImageContext); if(Status != STATUS_EFI_SUCCESS) { /* Unable to load the file */ @@ -553,15 +554,6 @@ Xtos::LoadModule(IN PEFI_FILE_HANDLE SystemDir, return Status; } - /* Relocate the PE/COFF image file */ - Status = PeCoffProtocol->RelocateImage(*ImageContext, GetBaseMappingAddress() | (ULONGLONG)(*ImageContext)->PhysicalAddress); - if(Status != STATUS_EFI_SUCCESS) - { - /* Unable to relocate the file */ - XtLdrProtocol->Debug.Print(L"ERROR: Failed to relocate '%S'\n", FileName); - return Status; - } - /* Close image file */ ModuleHandle->Close(ModuleHandle); @@ -583,133 +575,9 @@ Xtos::LoadModule(IN PEFI_FILE_HANDLE SystemDir, XtLdrProtocol->Debug.Print(L"WARNING: Loaded PE/COFF image with non-XT subsystem set\n"); } - /* Ensure that page map is provided */ - if(PageMap != NULLPTR) - { - /* Add kernel image memory mapping */ - Status = MapMemory(PageMap, (ULONGLONG)(*ImageContext)->PhysicalAddress, - (*ImageContext)->ImagePages, LoaderSystemCode, TRUE); - if(Status != STATUS_EFI_SUCCESS) - { - /* Failed to map kernel image memory */ - return Status; - } - } - /* Print debug message */ - XtLdrProtocol->Debug.Print(L"Loaded '%S' at PA: %P, VA: %P\n", FileName, (*ImageContext)->PhysicalAddress, - PhysicalAddressToVirtual((*ImageContext)->VirtualAddress)); - - /* Return success */ - return STATUS_EFI_SUCCESS; -} - -/** - * Adds a physical to virtual address mapping. - * - * @param PageMap - * Supplies a pointer to the page mapping structure. - * - * @param PhysicalAddress - * Supplies a physical address which will be mapped. - * - * @param NumberOfPages - * Supplies a number of pages that will be mapped. - * - * @param MemoryType - * Supplies the type of mapped memory that will be assigned to the memory descriptor. - * - * @param KernelMapping - * Supplies a flag that indicates if mapping should be done in kernel mode or if identity mapping should be used. - * - * @return This routine returns a status code. - * - * @since XT 1.0 - */ -XTCDECL -EFI_STATUS -Xtos::MapMemory(IN OUT PXTBL_PAGE_MAPPING PageMap, - IN ULONGLONG Address, - IN ULONG NumberOfPages, - IN LOADER_MEMORY_TYPE MemoryType, - IN BOOLEAN KernelMapping) -{ - ULONGLONG BaseAddress; - - /* Check if kernel mode mapping */ - if(KernelMapping) - { - /* Map memory based on kernel base address */ - BaseAddress = GetBaseMappingAddress(); - } - else - { - /* Use identity mapping */ - BaseAddress = (ULONGLONG)NULLPTR; - } - - /* Map memory and return status code */ - return XtLdrProtocol->Memory.MapVirtualMemory(PageMap, BaseAddress + Address, Address, NumberOfPages, MemoryType); -} - -/** - * Converts physical address to virtual address. - * - * @param PhysicalAddress - * Specifies physical address that will be converted to virtual address. - * - * @return This routine returns a mapped virtual address. - * - * @since XT 1.0 - */ -XTCDECL -PVOID -Xtos::PhysicalAddressToVirtual(PVOID PhysicalAddress) -{ - return (PVOID)((ULONG_PTR)PhysicalAddress | GetBaseMappingAddress()); -} - -/** - * Converts whole linked list addressing from physical to virtual for future use after enabling paging. - * - * @param ListHead - * Supplies a pointer to a structure that serves as the list header. - * - * @return This routine returns a status code. - * - * @since XT 1.0 - */ -XTCDECL -EFI_STATUS -Xtos::PhysicalListToVirtual(IN OUT PLIST_ENTRY ListHead) -{ - PLIST_ENTRY ListEntry, NextEntry; - - /* Make sure list is properly initialized */ - if(ListHead->Flink == 0 || ListHead->Blink == 0) - { - /* List not initialized, return error code */ - return STATUS_EFI_INVALID_PARAMETER; - } - - /* Iterate through the list */ - ListEntry = ListHead->Flink; - while(ListEntry != ListHead) - { - /* Store the next entry */ - NextEntry = ListEntry->Flink; - - /* Convert the list entry */ - ListEntry->Flink = (PLIST_ENTRY)PhysicalAddressToVirtual(ListEntry->Flink); - ListEntry->Blink = (PLIST_ENTRY)PhysicalAddressToVirtual(ListEntry->Blink); - - /* Get the next element */ - ListEntry = NextEntry; - } - - /* Convert the list head */ - ListHead->Flink = (PLIST_ENTRY)PhysicalAddressToVirtual(ListHead->Flink); - ListHead->Blink = (PLIST_ENTRY)PhysicalAddressToVirtual(ListHead->Blink); + XtLdrProtocol->Debug.Print(L"Loaded %S at PA: %P, VA: %P\n", FileName, + (*ImageContext)->PhysicalAddress, (*ImageContext)->VirtualAddress); /* Return success */ return STATUS_EFI_SUCCESS; @@ -739,6 +607,7 @@ Xtos::RunBootSequence(IN PEFI_FILE_HANDLE BootDir, PXTBL_FRAMEBUFFER_PROTOCOL FrameBufProtocol; PPECOFF_IMAGE_CONTEXT ImageContext = NULLPTR; PEFI_LOADED_IMAGE_PROTOCOL ImageProtocol; + PVOID VirtualAddress, VirtualMemoryArea; PXT_ENTRY_POINT KernelEntryPoint; EFI_HANDLE ProtocolHandle; EFI_STATUS Status; @@ -759,23 +628,39 @@ Xtos::RunBootSequence(IN PEFI_FILE_HANDLE BootDir, /* Close FrameBuffer protocol */ XtLdrProtocol->Protocol.Close(&ProtocolHandle, &FrameBufGuid); + /* Set base virtual memory area for the kernel mappings */ + VirtualMemoryArea = (PVOID)KSEG0_BASE; + VirtualAddress = (PVOID)(KSEG0_BASE + KSEG0_KERNEL_BASE); + /* Initialize virtual memory mappings */ XtLdrProtocol->Memory.InitializePageMap(&PageMap, DeterminePagingLevel(Parameters->Parameters), Size4K); - Status = XtLdrProtocol->Memory.MapEfiMemory(&PageMap, GetBaseMappingAddress()); + Status = XtLdrProtocol->Memory.MapEfiMemory(&PageMap, &VirtualMemoryArea, NULLPTR); if(Status != STATUS_EFI_SUCCESS) { return Status; } /* Load the kernel */ - Status = LoadModule(BootDir, Parameters->KernelFile, LoaderSystemCode, &PageMap, &ImageContext); + Status = LoadModule(BootDir, Parameters->KernelFile, VirtualAddress, LoaderSystemCode, &ImageContext); if(Status != STATUS_EFI_SUCCESS) { /* Failed to load the kernel */ return Status; } + /* Add kernel image memory mapping */ + Status = XtLdrProtocol->Memory.MapVirtualMemory(&PageMap, (ULONGLONG)ImageContext->VirtualAddress, + (ULONGLONG)ImageContext->PhysicalAddress, ImageContext->ImagePages, + LoaderSystemCode); + if(Status != STATUS_EFI_SUCCESS) + { + return Status; + } + + /* Set next valid virtual address right after the kernel */ + VirtualAddress = (PUINT8)VirtualAddress + (ImageContext->ImagePages * EFI_PAGE_SIZE); + /* Find and map APIC base address */ Status = InitializeApicBase(&PageMap); if(Status != STATUS_EFI_SUCCESS) @@ -785,8 +670,11 @@ Xtos::RunBootSequence(IN PEFI_FILE_HANDLE BootDir, return Status; } + /* Store virtual address of kernel initialization block for future kernel call */ + KernelParameters = (PKERNEL_INITIALIZATION_BLOCK)VirtualAddress; + /* Setup and map kernel initialization block */ - Status = InitializeLoaderBlock(&PageMap, &KernelParameters, Parameters); + Status = InitializeLoaderBlock(&PageMap, &VirtualAddress, Parameters); if(Status != STATUS_EFI_SUCCESS) { /* Failed to setup kernel initialization block */ diff --git a/boot/xtldr/protocol.cc b/boot/xtldr/protocol.cc index e8221d0..6593e4a 100644 --- a/boot/xtldr/protocol.cc +++ b/boot/xtldr/protocol.cc @@ -1066,6 +1066,8 @@ Protocol::InstallXtLoaderProtocol() LoaderProtocol.Memory.MapPage = Memory::MapPage; LoaderProtocol.Memory.MapVirtualMemory = Memory::MapVirtualMemory; LoaderProtocol.Memory.MoveMemory = RTL::Memory::MoveMemory; + LoaderProtocol.Memory.PhysicalAddressToVirtual = Memory::PhysicalAddressToVirtual; + LoaderProtocol.Memory.PhysicalListToVirtual = Memory::PhysicalListToVirtual; LoaderProtocol.Memory.SetMemory = RTL::Memory::SetMemory; LoaderProtocol.Memory.ZeroMemory = RTL::Memory::ZeroMemory; LoaderProtocol.Protocol.Close = CloseProtocol; diff --git a/sdk/xtdk/amd64/ketypes.h b/sdk/xtdk/amd64/ketypes.h index ccb7d9d..1299161 100644 --- a/sdk/xtdk/amd64/ketypes.h +++ b/sdk/xtdk/amd64/ketypes.h @@ -108,6 +108,9 @@ /* Static Kernel-Mode address start */ #define KSEG0_BASE 0xFFFFF80000000000 +/* XTOS Kernel address base */ +#define KSEG0_KERNEL_BASE 0x0000000800000000 + /* XTOS Kernel stack size */ #define KERNEL_STACK_SIZE 0x8000 diff --git a/sdk/xtdk/bltypes.h b/sdk/xtdk/bltypes.h index 1851c8a..1f7f948 100644 --- a/sdk/xtdk/bltypes.h +++ b/sdk/xtdk/bltypes.h @@ -100,19 +100,21 @@ typedef VOID (XTCDECL *PBL_LLIST_INITIALIZE_HEAD)(IN PLIST_ENTRY ListHead); typedef VOID (XTCDECL *PBL_LLIST_INSERT_HEAD)(IN OUT PLIST_ENTRY ListHead, IN PLIST_ENTRY Entry); typedef VOID (XTCDECL *PBL_LLIST_INSERT_TAIL)(IN OUT PLIST_ENTRY ListHead, IN PLIST_ENTRY Entry); typedef VOID (XTCDECL *PBL_LLIST_REMOVE_ENTRY)(IN PLIST_ENTRY Entry); -typedef EFI_STATUS (XTCDECL *PBL_MAP_EFI_MEMORY)(IN OUT PXTBL_PAGE_MAPPING PageMap, IN ULONG_PTR BaseAddress); +typedef EFI_STATUS (XTCDECL *PBL_MAP_EFI_MEMORY)(IN OUT PXTBL_PAGE_MAPPING PageMap, IN OUT PVOID *MemoryMapAddress, IN PBL_GET_MEMTYPE_ROUTINE GetMemoryTypeRoutine); typedef EFI_STATUS (XTCDECL *PBL_MAP_PAGE)(IN PXTBL_PAGE_MAPPING PageMap, IN ULONGLONG VirtualAddress, IN ULONGLONG PhysicalAddress, IN ULONGLONG NumberOfPages); typedef EFI_STATUS (XTCDECL *PBL_MAP_VIRTUAL_MEMORY)(IN OUT PXTBL_PAGE_MAPPING PageMap, IN ULONGLONG VirtualAddress, IN ULONGLONG PhysicalAddress, IN ULONGLONG NumberOfPages, IN LOADER_MEMORY_TYPE MemoryType); typedef VOID (XTAPI *PBL_MOVE_MEMORY)(IN OUT PVOID Destination, IN PCVOID Source, IN SIZE_T Length); typedef EFI_STATUS (XTCDECL *PBL_OPEN_VOLUME)(IN PEFI_DEVICE_PATH_PROTOCOL DevicePath, OUT PEFI_HANDLE DiskHandle, OUT PEFI_FILE_HANDLE *FsHandle); typedef EFI_STATUS (XTCDECL *PBL_OPEN_PROTOCOL)(OUT PEFI_HANDLE Handle, OUT PVOID *ProtocolHandler, IN PEFI_GUID ProtocolGuid); typedef EFI_STATUS (XTCDECL *PBL_OPEN_PROTOCOL_HANDLE)(IN EFI_HANDLE Handle, OUT PVOID *ProtocolHandler, IN PEFI_GUID ProtocolGuid); +typedef PVOID (XTCDECL *PBL_PHYSICAL_ADDRESS_TO_VIRTUAL)(IN PVOID PhysicalAddress, IN PVOID PhysicalBase, IN PVOID VirtualBase); typedef UCHAR (XTCDECL *PBL_IOPORT_READ_8)(IN USHORT Port); typedef USHORT (XTCDECL *PBL_IOPORT_READ_16)(IN USHORT Port); typedef ULONG (XTCDECL *PBL_IOPORT_READ_32)(IN USHORT Port); typedef VOID (XTCDECL *PBL_IOPORT_WRITE_8)(IN USHORT Port, IN UCHAR Value); typedef VOID (XTCDECL *PBL_IOPORT_WRITE_16)(IN USHORT Port, IN USHORT Value); typedef VOID (XTCDECL *PBL_IOPORT_WRITE_32)(IN USHORT Port, IN ULONG Value); +typedef EFI_STATUS (XTCDECL *PBL_PHYSICAL_LIST_TO_VIRTUAL)(IN PXTBL_PAGE_MAPPING PageMap, IN OUT PLIST_ENTRY ListHead, IN PVOID PhysicalBase, IN PVOID VirtualBase); typedef EFI_STATUS (XTCDECL *PBL_POWER_SYSTEM)(); typedef EFI_STATUS (XTCDECL *PBL_READ_FILE)(IN PEFI_FILE_HANDLE DirHandle, IN PCWSTR FileName, OUT PVOID *FileData, OUT PSIZE_T FileSize); typedef EFI_STATUS (XTCDECL *PBL_REGISTER_BOOT_PROTOCOL)(IN PCWSTR SystemType, IN PEFI_GUID BootProtocolGuid); @@ -459,6 +461,8 @@ typedef struct _XTBL_LOADER_PROTOCOL PBL_MAP_PAGE MapPage; PBL_MAP_VIRTUAL_MEMORY MapVirtualMemory; PBL_MOVE_MEMORY MoveMemory; + PBL_PHYSICAL_ADDRESS_TO_VIRTUAL PhysicalAddressToVirtual; + PBL_PHYSICAL_LIST_TO_VIRTUAL PhysicalListToVirtual; PBL_SET_MEMORY SetMemory; PBL_ZERO_MEMORY ZeroMemory; } Memory; diff --git a/sdk/xtdk/i686/ketypes.h b/sdk/xtdk/i686/ketypes.h index 32697c4..f62ff74 100644 --- a/sdk/xtdk/i686/ketypes.h +++ b/sdk/xtdk/i686/ketypes.h @@ -128,6 +128,9 @@ /* Static Kernel-Mode address start */ #define KSEG0_BASE 0x80000000 +/* XTOS Kernel address base */ +#define KSEG0_KERNEL_BASE 0x01800000 + /* XTOS Kernel stack size */ #define KERNEL_STACK_SIZE 0x4000 -- 2.52.0 From b5f220a2ae2c8eaa42e1764ec6cafcc79171b38e Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Fri, 23 Jan 2026 20:52:45 +0100 Subject: [PATCH 121/166] Correctly advance virtual address after mapping non-free regions --- boot/xtldr/memory.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/boot/xtldr/memory.cc b/boot/xtldr/memory.cc index 6591833..792330b 100644 --- a/boot/xtldr/memory.cc +++ b/boot/xtldr/memory.cc @@ -422,6 +422,9 @@ Memory::MapEfiMemory(IN OUT PXTBL_PAGE_MAPPING PageMap, /* Add any non-free memory mapping */ Status = MapVirtualMemory(PageMap, VirtualAddress, Descriptor->PhysicalStart, Descriptor->NumberOfPages, MemoryType); + + /* Update virtual address */ + VirtualAddress = VirtualAddress + (Descriptor->NumberOfPages * MM_PAGE_SIZE); } else { -- 2.52.0 From 31b0e4f4411bba3d688b4970771df62bf89c5c15 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Fri, 23 Jan 2026 20:55:56 +0100 Subject: [PATCH 122/166] Ensure contiguous virtual memory mapping --- boot/xtldr/modules/xtos_o/xtos.cc | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/boot/xtldr/modules/xtos_o/xtos.cc b/boot/xtldr/modules/xtos_o/xtos.cc index 3482003..7334693 100644 --- a/boot/xtldr/modules/xtos_o/xtos.cc +++ b/boot/xtldr/modules/xtos_o/xtos.cc @@ -607,7 +607,7 @@ Xtos::RunBootSequence(IN PEFI_FILE_HANDLE BootDir, PXTBL_FRAMEBUFFER_PROTOCOL FrameBufProtocol; PPECOFF_IMAGE_CONTEXT ImageContext = NULLPTR; PEFI_LOADED_IMAGE_PROTOCOL ImageProtocol; - PVOID VirtualAddress, VirtualMemoryArea; + PVOID VirtualAddress; PXT_ENTRY_POINT KernelEntryPoint; EFI_HANDLE ProtocolHandle; EFI_STATUS Status; @@ -629,13 +629,12 @@ Xtos::RunBootSequence(IN PEFI_FILE_HANDLE BootDir, XtLdrProtocol->Protocol.Close(&ProtocolHandle, &FrameBufGuid); /* Set base virtual memory area for the kernel mappings */ - VirtualMemoryArea = (PVOID)KSEG0_BASE; - VirtualAddress = (PVOID)(KSEG0_BASE + KSEG0_KERNEL_BASE); + VirtualAddress = (PVOID)(KSEG0_BASE); /* Initialize virtual memory mappings */ XtLdrProtocol->Memory.InitializePageMap(&PageMap, DeterminePagingLevel(Parameters->Parameters), Size4K); - Status = XtLdrProtocol->Memory.MapEfiMemory(&PageMap, &VirtualMemoryArea, NULLPTR); + Status = XtLdrProtocol->Memory.MapEfiMemory(&PageMap, &VirtualAddress, NULLPTR); if(Status != STATUS_EFI_SUCCESS) { return Status; -- 2.52.0 From 2c8eb6d692348989c71bf67069ecd481822828ef Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Fri, 23 Jan 2026 20:59:10 +0100 Subject: [PATCH 123/166] Remove unused kernel base address definition --- sdk/xtdk/amd64/ketypes.h | 3 --- sdk/xtdk/i686/ketypes.h | 3 --- 2 files changed, 6 deletions(-) diff --git a/sdk/xtdk/amd64/ketypes.h b/sdk/xtdk/amd64/ketypes.h index 1299161..ccb7d9d 100644 --- a/sdk/xtdk/amd64/ketypes.h +++ b/sdk/xtdk/amd64/ketypes.h @@ -108,9 +108,6 @@ /* Static Kernel-Mode address start */ #define KSEG0_BASE 0xFFFFF80000000000 -/* XTOS Kernel address base */ -#define KSEG0_KERNEL_BASE 0x0000000800000000 - /* XTOS Kernel stack size */ #define KERNEL_STACK_SIZE 0x8000 diff --git a/sdk/xtdk/i686/ketypes.h b/sdk/xtdk/i686/ketypes.h index f62ff74..32697c4 100644 --- a/sdk/xtdk/i686/ketypes.h +++ b/sdk/xtdk/i686/ketypes.h @@ -128,9 +128,6 @@ /* Static Kernel-Mode address start */ #define KSEG0_BASE 0x80000000 -/* XTOS Kernel address base */ -#define KSEG0_KERNEL_BASE 0x01800000 - /* XTOS Kernel stack size */ #define KERNEL_STACK_SIZE 0x4000 -- 2.52.0 From a4b9f495e5e3b55a4356c0c8bb95d661fb94266c Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Tue, 27 Jan 2026 16:50:11 +0100 Subject: [PATCH 124/166] Calculate total boot image size and pass it to kernel --- boot/xtldr/modules/xtos_o/xtos.cc | 6 ++++++ sdk/xtdk/xtfw.h | 1 + 2 files changed, 7 insertions(+) diff --git a/boot/xtldr/modules/xtos_o/xtos.cc b/boot/xtldr/modules/xtos_o/xtos.cc index 7334693..aabecb9 100644 --- a/boot/xtldr/modules/xtos_o/xtos.cc +++ b/boot/xtldr/modules/xtos_o/xtos.cc @@ -234,6 +234,9 @@ Xtos::GetMemoryDescriptorList(IN PXTBL_PAGE_MAPPING PageMap, XtLdrProtocol->Memory.PhysicalListToVirtual(PageMap, MemoryDescriptorList, PhysicalBase, *VirtualAddress); + /* Calculate next valid virtual address */ + *VirtualAddress = (PUINT8)*VirtualAddress + (Pages * EFI_PAGE_SIZE); + return STATUS_EFI_SUCCESS; } @@ -469,6 +472,9 @@ Xtos::InitializeLoaderBlock(IN PXTBL_PAGE_MAPPING PageMap, XtLdrProtocol->LinkedList.InitializeHead(&LoaderBlock->MemoryDescriptorListHead); GetMemoryDescriptorList(PageMap, VirtualAddress, &LoaderBlock->MemoryDescriptorListHead); + /* Set boot image size */ + LoaderBlock->BootImageSize = (PFN_NUMBER)(((ULONGLONG)*VirtualAddress - KSEG0_BASE) / EFI_PAGE_SIZE); + /* Return success */ return STATUS_EFI_SUCCESS; } diff --git a/sdk/xtdk/xtfw.h b/sdk/xtdk/xtfw.h index 1a4642a..fbe3965 100644 --- a/sdk/xtdk/xtfw.h +++ b/sdk/xtdk/xtfw.h @@ -107,6 +107,7 @@ typedef struct _KERNEL_INITIALIZATION_BLOCK ULONG BlockVersion; ULONG ProtocolVersion; PWCHAR KernelParameters; + PFN_NUMBER BootImageSize; LIST_ENTRY LoadOrderListHead; LIST_ENTRY MemoryDescriptorListHead; LIST_ENTRY BootDriverListHead; -- 2.52.0 From 446ce920ec741d4d1beb845fd61e5d660eeeb8bd Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Tue, 27 Jan 2026 16:56:40 +0100 Subject: [PATCH 125/166] Limit system PTE space mapping to calculated pool size --- xtoskrnl/mm/pte.cc | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/xtoskrnl/mm/pte.cc b/xtoskrnl/mm/pte.cc index a7ce084..98c5ebc 100644 --- a/xtoskrnl/mm/pte.cc +++ b/xtoskrnl/mm/pte.cc @@ -194,16 +194,21 @@ MM::Pte::InitializeSystemPteSpace(VOID) PMMPTE PointerPte; PMMPTE FirstZeroingPte; PMMMEMORY_LAYOUT MemoryLayout; + ULONGLONG NonPagedSystemPoolEnd; /* Retrieve the system's memory layout */ MemoryLayout = MM::Manager::GetMemoryLayout(); + NonPagedSystemPoolEnd = ((ULONGLONG)MemoryLayout->SystemSpaceStart + + MM::Manager::GetNumberOfSystemPtes() * MM_PAGE_SIZE); + /* Map the page table hierarchy for the entire system PTE space */ - MM::Pte::MapPPE(MemoryLayout->SystemSpaceStart, MemoryLayout->SystemSpaceEnd, &ValidPte); - MM::Pte::MapPDE(MemoryLayout->SystemSpaceStart, MemoryLayout->SystemSpaceEnd, &ValidPte); + MM::Pte::MapPPE(MemoryLayout->SystemSpaceStart, (PVOID)NonPagedSystemPoolEnd, &ValidPte); + MM::Pte::MapPDE(MemoryLayout->SystemSpaceStart, (PVOID)NonPagedSystemPoolEnd, &ValidPte); /* Format the main block of system PTEs into a free list pool */ PointerPte = MM::Paging::GetPteAddress(MemoryLayout->SystemSpaceStart); + InitializeSystemPtePool(PointerPte, MM::Manager::GetNumberOfSystemPtes(), SystemPteSpace); /* Reserve and zero a dedicated block of system PTEs */ -- 2.52.0 From fd29cf55ef766579d44624c5602ba90e576a898e Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Thu, 29 Jan 2026 19:49:54 +0100 Subject: [PATCH 126/166] Fix incorrect header guard comment --- xtoskrnl/includes/mm/colors.hh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xtoskrnl/includes/mm/colors.hh b/xtoskrnl/includes/mm/colors.hh index 06d1c40..fda6934 100644 --- a/xtoskrnl/includes/mm/colors.hh +++ b/xtoskrnl/includes/mm/colors.hh @@ -35,4 +35,4 @@ namespace MM }; } -#endif /* __XTOSKRNL_MM_PFN_HH */ +#endif /* __XTOSKRNL_MM_COLORS_HH */ -- 2.52.0 From 7f6114f8e5077aae0bde3f3f7dff768646ff6179 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Thu, 29 Jan 2026 20:00:09 +0100 Subject: [PATCH 127/166] Add skeleton for memory pool allocator --- xtoskrnl/CMakeLists.txt | 2 ++ xtoskrnl/includes/mm.hh | 1 + xtoskrnl/includes/mm/alloc.hh | 25 +++++++++++++++++++++++++ xtoskrnl/mm/alloc.cc | 11 +++++++++++ xtoskrnl/mm/amd64/alloc.cc | 29 +++++++++++++++++++++++++++++ xtoskrnl/mm/i686/alloc.cc | 17 +++++++++++++++++ 6 files changed, 85 insertions(+) create mode 100644 xtoskrnl/includes/mm/alloc.hh create mode 100644 xtoskrnl/mm/alloc.cc create mode 100644 xtoskrnl/mm/amd64/alloc.cc create mode 100644 xtoskrnl/mm/i686/alloc.cc diff --git a/xtoskrnl/CMakeLists.txt b/xtoskrnl/CMakeLists.txt index bd31b8e..dbfab46 100644 --- a/xtoskrnl/CMakeLists.txt +++ b/xtoskrnl/CMakeLists.txt @@ -51,12 +51,14 @@ list(APPEND XTOSKRNL_SOURCE ${XTOSKRNL_SOURCE_DIR}/ke/spinlock.cc ${XTOSKRNL_SOURCE_DIR}/ke/sysres.cc ${XTOSKRNL_SOURCE_DIR}/ke/timer.cc + ${XTOSKRNL_SOURCE_DIR}/mm/${ARCH}/alloc.cc ${XTOSKRNL_SOURCE_DIR}/mm/${ARCH}/mmgr.cc ${XTOSKRNL_SOURCE_DIR}/mm/${ARCH}/pagemap.cc ${XTOSKRNL_SOURCE_DIR}/mm/${ARCH}/paging.cc ${XTOSKRNL_SOURCE_DIR}/mm/${ARCH}/pfault.cc ${XTOSKRNL_SOURCE_DIR}/mm/${ARCH}/pfn.cc ${XTOSKRNL_SOURCE_DIR}/mm/${ARCH}/pte.cc + ${XTOSKRNL_SOURCE_DIR}/mm/alloc.cc ${XTOSKRNL_SOURCE_DIR}/mm/colors.cc ${XTOSKRNL_SOURCE_DIR}/mm/data.cc ${XTOSKRNL_SOURCE_DIR}/mm/hlpool.cc diff --git a/xtoskrnl/includes/mm.hh b/xtoskrnl/includes/mm.hh index 5c2e568..6045afe 100644 --- a/xtoskrnl/includes/mm.hh +++ b/xtoskrnl/includes/mm.hh @@ -15,6 +15,7 @@ #include XTOS_ARCH_HEADER(mm, paging.hh) #include XTOS_ARCH_HEADER(mm, pte.hh) +#include #include #include #include diff --git a/xtoskrnl/includes/mm/alloc.hh b/xtoskrnl/includes/mm/alloc.hh new file mode 100644 index 0000000..dc88bea --- /dev/null +++ b/xtoskrnl/includes/mm/alloc.hh @@ -0,0 +1,25 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: xtoskrnl/includes/mm/alloc.hh + * DESCRIPTION: Memory manager pool allocation + * DEVELOPERS: Aiken Harris + */ + +#ifndef __XTOSKRNL_MM_ALLOC_HH +#define __XTOSKRNL_MM_ALLOC_HH + +#include + + +/* Memory Manager */ +namespace MM +{ + class Allocator + { + public: + STATIC XTAPI VOID InitializeNonPagedPool(VOID); + }; +} + +#endif /* __XTOSKRNL_MM_ALLOC_HH */ diff --git a/xtoskrnl/mm/alloc.cc b/xtoskrnl/mm/alloc.cc new file mode 100644 index 0000000..306b3fb --- /dev/null +++ b/xtoskrnl/mm/alloc.cc @@ -0,0 +1,11 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: xtoskrnl/mm/alloc.cc + * DESCRIPTION: Memory manager pool allocation + * DEVELOPERS: Aiken Harris + */ + +#include + + diff --git a/xtoskrnl/mm/amd64/alloc.cc b/xtoskrnl/mm/amd64/alloc.cc new file mode 100644 index 0000000..8cdfab0 --- /dev/null +++ b/xtoskrnl/mm/amd64/alloc.cc @@ -0,0 +1,29 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: xtoskrnl/mm/amd64/alloc.cc + * DESCRIPTION: Memory manager pool allocation + * DEVELOPERS: Aiken Harris + */ + +#include + + +XTAPI +VOID +MM::Allocator::InitializeNonPagedPool(VOID) +{ + PMMMEMORY_LAYOUT MemoryLayout; + + UNIMPLEMENTED; + + /* Retrieve memory layout */ + MemoryLayout = MM::Manager::GetMemoryLayout(); + + /* Map PPE and PDE for whole non-paged pool */ + MM::Pte::MapPPE(MemoryLayout->NonPagedPoolStart, MemoryLayout->NonPagedExpansionPoolEnd, MM::Pte::GetValidPte()); + MM::Pte::MapPDE(MemoryLayout->NonPagedPoolStart, MemoryLayout->NonPagedExpansionPoolEnd, MM::Pte::GetValidPte()); + + /* Map PTE only for the base of the non-paged pool */ + MM::Pte::MapPTE(MemoryLayout->NonPagedPoolStart, (PCHAR)MemoryLayout->NonPagedPoolEnd - 1, MM::Pte::GetValidPte()); +} diff --git a/xtoskrnl/mm/i686/alloc.cc b/xtoskrnl/mm/i686/alloc.cc new file mode 100644 index 0000000..0987553 --- /dev/null +++ b/xtoskrnl/mm/i686/alloc.cc @@ -0,0 +1,17 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: xtoskrnl/mm/i686/alloc.cc + * DESCRIPTION: Memory manager pool allocation + * DEVELOPERS: Aiken Harris + */ + +#include + + +XTAPI +VOID +MM::Allocator::InitializeNonPagedPool(VOID) +{ + UNIMPLEMENTED; +} -- 2.52.0 From a7820ff5687e1852998be9607629aef2f2864cce Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Thu, 29 Jan 2026 20:08:27 +0100 Subject: [PATCH 128/166] Calculate aligned boot image size from loader parameters --- xtoskrnl/mm/mmgr.cc | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/xtoskrnl/mm/mmgr.cc b/xtoskrnl/mm/mmgr.cc index 3c22c26..23620b6 100644 --- a/xtoskrnl/mm/mmgr.cc +++ b/xtoskrnl/mm/mmgr.cc @@ -10,6 +10,39 @@ #include +/** + * Computes the size of the boot image. + * + * @param BootImageSize + * Supplies a pointer to a variable that will receive the size of the boot image in pages. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::Manager::ComputeBootImageSize(OUT PPFN_NUMBER BootImageSize) +{ + PKERNEL_INITIALIZATION_BLOCK InitializationBlock; + PFN_NUMBER ImageSize; + ULONG PteSize; + + /* Get the kernel initialization block */ + InitializationBlock = KE::BootInformation::GetInitializationBlock(); + + /* Get the size of a PTE */ + PteSize = MM::Paging::GetPteSize(); + + /* Calculate the size of the boot image */ + ImageSize = InitializationBlock->BootImageSize * MM_PAGE_SIZE; + ImageSize = (ImageSize + ((MM_PAGE_SIZE / PteSize) * MM_PAGE_SIZE) - 1) & + ~(((MM_PAGE_SIZE / PteSize) * MM_PAGE_SIZE) - 1); + + /* Return number of pages used by the boot image */ + *BootImageSize = ImageSize / MM_PAGE_SIZE; +} + /** * Retrieves the amount of total available memory in the system. * @@ -40,6 +73,13 @@ MM::Manager::GetMemoryLayout(VOID) return &MemoryLayout; } +/** + * Retrieves the number of system PTEs. + * + * @return This routine returns the number of system PTEs. + * + * @since XT 1.0 + */ XTAPI PFN_NUMBER MM::Manager::GetNumberOfSystemPtes() -- 2.52.0 From 72f34c82862829c08a4cf552a0cd9c26d361c630 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Thu, 29 Jan 2026 20:10:48 +0100 Subject: [PATCH 129/166] Add private helper declaration --- xtoskrnl/includes/mm/mmgr.hh | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/xtoskrnl/includes/mm/mmgr.hh b/xtoskrnl/includes/mm/mmgr.hh index e33253b..c53646d 100644 --- a/xtoskrnl/includes/mm/mmgr.hh +++ b/xtoskrnl/includes/mm/mmgr.hh @@ -27,9 +27,12 @@ namespace MM STATIC XTAPI PFN_NUMBER GetNumberOfSystemPtes(); STATIC XTAPI VOID InitializeMemoryLayout(VOID); STATIC XTAPI VOID InitializeMemoryManager(VOID); - STATIC XTAPI BOOLEAN VerifyMemoryTypeFree(LOADER_MEMORY_TYPE MemoryType); - STATIC XTAPI BOOLEAN VerifyMemoryTypeInvisible(LOADER_MEMORY_TYPE MemoryType); - }; + STATIC XTAPI BOOLEAN VerifyMemoryTypeFree(IN LOADER_MEMORY_TYPE MemoryType); + STATIC XTAPI BOOLEAN VerifyMemoryTypeInvisible(IN LOADER_MEMORY_TYPE MemoryType); + + private: + STATIC XTAPI VOID ComputeBootImageSize(OUT PPFN_NUMBER BootImageSize); + }; } #endif /* __XTOSKRNL_MM_MMGR_HH */ -- 2.52.0 From 58669d3074530332cf1d128538b26765f8bdd804 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Thu, 29 Jan 2026 22:10:26 +0100 Subject: [PATCH 130/166] Refactor memory layout structure --- sdk/xtdk/mmtypes.h | 34 +++++++++++++++++++++++++++++++--- xtoskrnl/mm/amd64/mmgr.cc | 12 ++++-------- xtoskrnl/mm/amd64/pfn.cc | 10 +++++----- xtoskrnl/mm/amd64/pte.cc | 2 +- xtoskrnl/mm/colors.cc | 2 +- xtoskrnl/mm/i686/mmgr.cc | 12 ++++-------- xtoskrnl/mm/i686/pfn.cc | 8 ++++---- xtoskrnl/mm/i686/pte.cc | 2 +- xtoskrnl/mm/pfn.cc | 24 ++++++++++++------------ xtoskrnl/mm/pte.cc | 8 ++++---- 10 files changed, 67 insertions(+), 47 deletions(-) diff --git a/sdk/xtdk/mmtypes.h b/sdk/xtdk/mmtypes.h index 4c9620d..bae2fb4 100644 --- a/sdk/xtdk/mmtypes.h +++ b/sdk/xtdk/mmtypes.h @@ -76,17 +76,45 @@ typedef struct _MMCOLOR_TABLES /* Memory layout structure definition */ typedef struct _MMMEMORY_LAYOUT { - PMMPFN PfnDatabaseAddress; + PMMPFN PfnDatabase; + PFN_NUMBER PfnDatabaseSize; PVOID SelfMapAddress; + PVOID HardwarePoolStart; + PVOID HardwarePoolEnd; PVOID HyperSpaceStart; PVOID HyperSpaceEnd; + PVOID LoaderMappingsStart; + PVOID LoaderMappingsEnd; + PFN_NUMBER LoaderMappingsSize; + PVOID NonCanonicalStart; + PVOID NonCanonicalEnd; PVOID NonPagedPoolStart; PVOID NonPagedPoolEnd; + PFN_NUMBER NonPagedPoolSize; + PVOID NonPagedExpansionPoolStart; + PVOID NonPagedExpansionPoolEnd; + PFN_NUMBER NonPagedExpansionPoolSize; + PVOID NonPagedSystemPoolStart; + PVOID NonPagedSystemPoolEnd; + PFN_NUMBER NonPagedSystemPoolSize; PVOID PagedPoolStart; PVOID PagedPoolEnd; - PVOID SystemSpaceStart; - PVOID SystemSpaceEnd; + PFN_NUMBER PagedPoolSize; + PVOID ReservedSystemPoolStart; + PVOID ReservedSystemPoolEnd; + PVOID SessionSpaceStart; + PVOID SessionSpaceEnd; + PFN_NUMBER SessionSpaceSize; + PVOID SharedSystemPageStart; + PVOID SharedSystemPageEnd; + PVOID SystemCacheStart; + PVOID SystemCacheEnd; + PVOID SystemWorkingSetStart; + PVOID SystemWorkingSetEnd; + PVOID UserSpaceStart; PVOID UserSpaceEnd; + PVOID PteSpaceStart; + PVOID PteSpaceEnd; } MMMEMORY_LAYOUT, *PMMMEMORY_LAYOUT; /* Page Frame Entry structure definition */ diff --git a/xtoskrnl/mm/amd64/mmgr.cc b/xtoskrnl/mm/amd64/mmgr.cc index b2c98bd..843039b 100644 --- a/xtoskrnl/mm/amd64/mmgr.cc +++ b/xtoskrnl/mm/amd64/mmgr.cc @@ -39,11 +39,11 @@ MM::Manager::InitializeMemoryLayout(VOID) if(MM::Paging::GetXpaStatus()) { /* Configure memory layout for 5-level paging, using 57bit address space and providing a 128 PB address space */ - MemoryLayout.PfnDatabaseAddress = (PMMPFN)0xFFFEFA8000000000ULL; + MemoryLayout.PfnDatabase = (PMMPFN)0xFFFEFA8000000000ULL; MemoryLayout.SelfMapAddress = (PVOID)MM_P5E_LA57_BASE; /* Define the non-paged and paged pool regions */ - MemoryLayout.NonPagedPoolStart = (PVOID)((ULONG_PTR)MemoryLayout.PfnDatabaseAddress + PfnDatabaseSize * MM_PAGE_SIZE); + MemoryLayout.NonPagedPoolStart = (PVOID)((ULONG_PTR)MemoryLayout.PfnDatabase + PfnDatabaseSize * MM_PAGE_SIZE); MemoryLayout.NonPagedPoolEnd = (PVOID)0xFFFEFFFFFFBFFFFFULL; MemoryLayout.PagedPoolStart = (PVOID)0xFFFEF8A000000000ULL; MemoryLayout.PagedPoolEnd = (PVOID)(((ULONG_PTR)MemoryLayout.PagedPoolStart + PagedPoolSize) - 1); @@ -51,18 +51,16 @@ MM::Manager::InitializeMemoryLayout(VOID) /* Define hyperspace, system PTE space, and the user space limit */ MemoryLayout.HyperSpaceStart = (PVOID)0xFFFEF70000000000ULL; MemoryLayout.HyperSpaceEnd = (PVOID)0xFFFEF77FFFFFFFFFULL; - MemoryLayout.SystemSpaceStart = (PVOID)0xFFFEF88000000000ULL; - MemoryLayout.SystemSpaceEnd = (PVOID)((ULONG_PTR)MemoryLayout.SystemSpaceStart + (NumberOfSystemPtes + 1) * MM_PAGE_SIZE); MemoryLayout.UserSpaceEnd = (PVOID)0x07FFFFFFFFFFFFFULL; } else { /* Configure memory layout for 4-level paging, using 48bit address space and providing a 128 TB address space */ - MemoryLayout.PfnDatabaseAddress = (PMMPFN)0xFFFFFA8000000000ULL; + MemoryLayout.PfnDatabase = (PMMPFN)0xFFFFFA8000000000ULL; MemoryLayout.SelfMapAddress = (PVOID)MM_PXE_BASE; /* Define the non-paged and paged pool regions */ - MemoryLayout.NonPagedPoolStart = (PVOID)((ULONG_PTR)MemoryLayout.PfnDatabaseAddress + PfnDatabaseSize * MM_PAGE_SIZE); + MemoryLayout.NonPagedPoolStart = (PVOID)((ULONG_PTR)MemoryLayout.PfnDatabase + PfnDatabaseSize * MM_PAGE_SIZE); MemoryLayout.NonPagedPoolEnd = (PVOID)0xFFFFFFFFFFBFFFFFULL; MemoryLayout.PagedPoolStart = (PVOID)0xFFFFF8A000000000ULL; MemoryLayout.PagedPoolEnd = (PVOID)(((ULONG_PTR)MemoryLayout.PagedPoolStart + PagedPoolSize) - 1); @@ -70,8 +68,6 @@ MM::Manager::InitializeMemoryLayout(VOID) /* Define hyperspace, system PTE space, and the user space limit */ MemoryLayout.HyperSpaceStart = (PVOID)0xFFFFF70000000000ULL; MemoryLayout.HyperSpaceEnd = (PVOID)0xFFFFF77FFFFFFFFFULL; - MemoryLayout.SystemSpaceStart = (PVOID)0xFFFFF88000000000ULL; - MemoryLayout.SystemSpaceEnd = (PVOID)((ULONG_PTR)MemoryLayout.SystemSpaceStart + (NumberOfSystemPtes + 1) * MM_PAGE_SIZE); MemoryLayout.UserSpaceEnd = (PVOID)0x000007FFFFFEFFFFULL; } } diff --git a/xtoskrnl/mm/amd64/pfn.cc b/xtoskrnl/mm/amd64/pfn.cc index c858beb..d9bbc7f 100644 --- a/xtoskrnl/mm/amd64/pfn.cc +++ b/xtoskrnl/mm/amd64/pfn.cc @@ -40,14 +40,14 @@ MM::Pfn::InitializePfnDatabase(VOID) MemoryLayout = MM::Manager::GetMemoryLayout(); /* Get the PFN database size and calculate the end of the PFN database virtual address space */ - PfnDatabaseEnd = (PUCHAR)MemoryLayout->PfnDatabaseAddress + (PfnDatabaseSize * MM_PAGE_SIZE) - 1; + PfnDatabaseEnd = (PUCHAR)MemoryLayout->PfnDatabase + (PfnDatabaseSize * MM_PAGE_SIZE) - 1; /* Get a template PTE for mapping the PFN database pages */ ValidPte = MM::Pte::GetValidPte(); /* Map the Page Directory and Page Directory Pointer tables for the PFN database */ - MM::Pte::MapPPE(MemoryLayout->PfnDatabaseAddress, PfnDatabaseEnd, ValidPte); - MM::Pte::MapPDE(MemoryLayout->PfnDatabaseAddress, PfnDatabaseEnd, ValidPte); + MM::Pte::MapPPE(MemoryLayout->PfnDatabase, PfnDatabaseEnd, ValidPte); + MM::Pte::MapPDE(MemoryLayout->PfnDatabase, PfnDatabaseEnd, ValidPte); /* Initialize the color tables */ MM::Colors::InitializeColorTables(); @@ -80,8 +80,8 @@ MM::Pfn::InitializePfnDatabase(VOID) } /* Map PFN database entries for this physical range */ - MM::Pte::MapPTE(&((PMMPFN)MemoryLayout->PfnDatabaseAddress)[BasePage], - (PUCHAR)&((PMMPFN)MemoryLayout->PfnDatabaseAddress)[BasePage + PageCount] - 1, + MM::Pte::MapPTE(&((PMMPFN)MemoryLayout->PfnDatabase)[BasePage], + (PUCHAR)&((PMMPFN)MemoryLayout->PfnDatabase)[BasePage + PageCount] - 1, ValidPte); /* Split PFN database allocation out of the free descriptor */ diff --git a/xtoskrnl/mm/amd64/pte.cc b/xtoskrnl/mm/amd64/pte.cc index 80742d0..2ebc9ff 100644 --- a/xtoskrnl/mm/amd64/pte.cc +++ b/xtoskrnl/mm/amd64/pte.cc @@ -68,7 +68,7 @@ MM::Pte::GetSystemPteBaseAddress(VOID) if(MM::Paging::GetXpaStatus()) { /* For 5-level paging, system PTEs start at the beginning of system space */ - return MM::Paging::GetPteAddress((PVOID)MemoryLayout->SystemSpaceStart); + return MM::Paging::GetPteAddress((PVOID)MemoryLayout->NonPagedSystemPoolStart); } else { diff --git a/xtoskrnl/mm/colors.cc b/xtoskrnl/mm/colors.cc index 2607ee4..45f2fc9 100644 --- a/xtoskrnl/mm/colors.cc +++ b/xtoskrnl/mm/colors.cc @@ -131,7 +131,7 @@ MM::Colors::InitializeColorTables(VOID) MemoryLayout = MM::Manager::GetMemoryLayout(); /* Set the base address of the color tables to start right after the PFN database */ - FreePages[0] = (PMMCOLOR_TABLES)&((PMMPFN)MemoryLayout->PfnDatabaseAddress)[MM::Pfn::GetHighestPhysicalPage() + 1]; + FreePages[0] = (PMMCOLOR_TABLES)&((PMMPFN)MemoryLayout->PfnDatabase)[MM::Pfn::GetHighestPhysicalPage() + 1]; /* Calculate the virtual address range for both color tables */ PointerPte = MM::Paging::GetPteAddress(&FreePages[0][0]); diff --git a/xtoskrnl/mm/i686/mmgr.cc b/xtoskrnl/mm/i686/mmgr.cc index a064930..c51b4db 100644 --- a/xtoskrnl/mm/i686/mmgr.cc +++ b/xtoskrnl/mm/i686/mmgr.cc @@ -54,11 +54,11 @@ MM::Manager::InitializeMemoryLayout(VOID) if(MM::Paging::GetXpaStatus()) { /* Configure memory layout for 3-level paging, using 36bit address space and providing a 64 GB address space */ - MemoryLayout.PfnDatabaseAddress = (PMMPFN)0xB0000000; + MemoryLayout.PfnDatabase = (PMMPFN)0xB0000000; MemoryLayout.SelfMapAddress = (PVOID)MM_PTE_BASE; /* Define the non-paged and paged pool regions */ - MemoryLayout.NonPagedPoolStart = (PVOID)((ULONG_PTR)MemoryLayout.PfnDatabaseAddress + PfnDatabaseSize * MM_PAGE_SIZE); + MemoryLayout.NonPagedPoolStart = (PVOID)((ULONG_PTR)MemoryLayout.PfnDatabase + PfnDatabaseSize * MM_PAGE_SIZE); MemoryLayout.NonPagedPoolEnd = (PVOID)0xEEFFFFFF; MemoryLayout.PagedPoolStart = (PVOID)0xE2000000; MemoryLayout.PagedPoolEnd = (PVOID)(((ULONG_PTR)MemoryLayout.PagedPoolStart + PagedPoolSize) - 1); @@ -66,18 +66,16 @@ MM::Manager::InitializeMemoryLayout(VOID) /* Define hyperspace, system PTE space, and the user space limit */ MemoryLayout.HyperSpaceStart = (PVOID)0xC0800000; MemoryLayout.HyperSpaceEnd = (PVOID)0xC0BFFFFF; - MemoryLayout.SystemSpaceStart = (PVOID)0xC0C00000; - MemoryLayout.SystemSpaceEnd = (PVOID)((ULONG_PTR)MemoryLayout.SystemSpaceStart + (NumberOfSystemPtes + 1) * MM_PAGE_SIZE); MemoryLayout.UserSpaceEnd = (PVOID)0x7FFEFFFF; } else { /* Configure memory layout for 2-level paging, using 32bit address space and providing a 4 GB address space */ - MemoryLayout.PfnDatabaseAddress = (PMMPFN)0xB0000000; + MemoryLayout.PfnDatabase = (PMMPFN)0xB0000000; MemoryLayout.SelfMapAddress = (PVOID)MM_PTE_BASE; /* Define the non-paged and paged pool regions */ - MemoryLayout.NonPagedPoolStart = (PVOID)((ULONG_PTR)MemoryLayout.PfnDatabaseAddress + PfnDatabaseSize * MM_PAGE_SIZE); + MemoryLayout.NonPagedPoolStart = (PVOID)((ULONG_PTR)MemoryLayout.PfnDatabase + PfnDatabaseSize * MM_PAGE_SIZE); MemoryLayout.NonPagedPoolEnd = (PVOID)0xFFBE0000; MemoryLayout.PagedPoolStart = (PVOID)0xE1000000; MemoryLayout.PagedPoolEnd = (PVOID)(((ULONG_PTR)MemoryLayout.PagedPoolStart + PagedPoolSize) - 1); @@ -85,8 +83,6 @@ MM::Manager::InitializeMemoryLayout(VOID) /* Define hyperspace, system PTE space, and the user space limit */ MemoryLayout.HyperSpaceStart = (PVOID)0xC0400000; MemoryLayout.HyperSpaceEnd = (PVOID)0xC07FFFFF; - MemoryLayout.SystemSpaceStart = (PVOID)0xC0800000; - MemoryLayout.SystemSpaceEnd = (PVOID)((ULONG_PTR)MemoryLayout.SystemSpaceStart + (NumberOfSystemPtes + 1) * MM_PAGE_SIZE); MemoryLayout.UserSpaceEnd = (PVOID)0x7FFEFFFF; } } diff --git a/xtoskrnl/mm/i686/pfn.cc b/xtoskrnl/mm/i686/pfn.cc index 9218e36..840066d 100644 --- a/xtoskrnl/mm/i686/pfn.cc +++ b/xtoskrnl/mm/i686/pfn.cc @@ -39,17 +39,17 @@ MM::Pfn::InitializePfnDatabase(VOID) MemoryLayout = MM::Manager::GetMemoryLayout(); /* Get the PFN database size and calculate the end of the PFN database virtual address space */ - PfnDatabaseEnd = (PUCHAR)MemoryLayout->PfnDatabaseAddress + (PfnDatabaseSize * MM_PAGE_SIZE) - 1; + PfnDatabaseEnd = (PUCHAR)MemoryLayout->PfnDatabase + (PfnDatabaseSize * MM_PAGE_SIZE) - 1; /* Get a template PTE for mapping the PFN database pages */ ValidPte = MM::Pte::GetValidPte(); /* Map the Page Directory and Page Directory Pointer tables for the PFN database */ - MM::Pte::MapPDE(MemoryLayout->PfnDatabaseAddress, PfnDatabaseEnd, ValidPte); - MM::Pte::MapPTE(MemoryLayout->PfnDatabaseAddress, PfnDatabaseEnd, ValidPte); + MM::Pte::MapPDE(MemoryLayout->PfnDatabase, PfnDatabaseEnd, ValidPte); + MM::Pte::MapPTE(MemoryLayout->PfnDatabase, PfnDatabaseEnd, ValidPte); /* Zero PFN database virtual space */ - RTL::Memory::ZeroMemory(MemoryLayout->PfnDatabaseAddress, PfnDatabaseSize * MM_PAGE_SIZE); + RTL::Memory::ZeroMemory(MemoryLayout->PfnDatabase, PfnDatabaseSize * MM_PAGE_SIZE); /* Initialize the color tables */ MM::Colors::InitializeColorTables(); diff --git a/xtoskrnl/mm/i686/pte.cc b/xtoskrnl/mm/i686/pte.cc index a348d81..0ed63bd 100644 --- a/xtoskrnl/mm/i686/pte.cc +++ b/xtoskrnl/mm/i686/pte.cc @@ -98,7 +98,7 @@ MM::Pte::InitializePageTable(VOID) MM::Paging::SetPte(&TemplatePte, 0, MM_PTE_READWRITE | MM_PTE_CACHE_ENABLE); /* Map the kernel's PD entries */ - MM::Pte::MapPDE(MemoryLayout->SystemSpaceStart, (PVOID)MM_HIGHEST_SYSTEM_ADDRESS, &TemplatePte); + MM::Pte::MapPDE(MemoryLayout->NonPagedSystemPoolStart, (PVOID)MM_HIGHEST_SYSTEM_ADDRESS, &TemplatePte); } /** diff --git a/xtoskrnl/mm/pfn.cc b/xtoskrnl/mm/pfn.cc index 5372154..6ce37be 100644 --- a/xtoskrnl/mm/pfn.cc +++ b/xtoskrnl/mm/pfn.cc @@ -415,7 +415,7 @@ MM::Pfn::GetPfnEntry(IN PFN_NUMBER Pfn) MemoryLayout = MM::Manager::GetMemoryLayout(); /* Calculate the address of the PFN entry by indexing into the PFN database array and return it */ - return &((PMMPFN)MemoryLayout->PfnDatabaseAddress)[Pfn]; + return &((PMMPFN)MemoryLayout->PfnDatabase)[Pfn]; } /** @@ -531,7 +531,7 @@ MM::Pfn::LinkFreePage(IN PFN_NUMBER PageFrameIndex) /* Link with the previous last page */ MM::Paging::SetPte(&ColoredPfn->OriginalPte, PageFrameIndex); - PfnEntry->u4.PteFrame = ColoredPfn - (PMMPFN)MemoryLayout->PfnDatabaseAddress; + PfnEntry->u4.PteFrame = ColoredPfn - (PMMPFN)MemoryLayout->PfnDatabase; } /* Set the page as the new tail of the colored list */ @@ -570,7 +570,7 @@ MM::Pfn::LinkPage(IN PMMPFNLIST ListHead, PMMMEMORY_LAYOUT MemoryLayout = MM::Manager::GetMemoryLayout(); /* Get the PFN database entry for the target page */ - PageFrame = &((PMMPFN)MemoryLayout->PfnDatabaseAddress)[PageFrameIndex]; + PageFrame = &((PMMPFN)MemoryLayout->PfnDatabase)[PageFrameIndex]; /* Get the list name */ ListName = ListHead->ListName; @@ -598,7 +598,7 @@ MM::Pfn::LinkPage(IN PMMPFNLIST ListHead, if(ListHead->Blink != MAXULONG_PTR) { /* Update the previous tail to point to this page */ - (&((PMMPFN)MemoryLayout->PfnDatabaseAddress)[ListHead->Blink])->u1.Flink = PageFrameIndex; + (&((PMMPFN)MemoryLayout->PfnDatabase)[ListHead->Blink])->u1.Flink = PageFrameIndex; } else { @@ -661,7 +661,7 @@ MM::Pfn::LinkPage(IN PMMPFNLIST ListHead, if(ListHead->Flink != MAXULONG_PTR) { /* Fix up the backward link of the old head */ - (&((PMMPFN)MemoryLayout->PfnDatabaseAddress)[ListHead->Flink])->u2.Blink = PageFrameIndex; + (&((PMMPFN)MemoryLayout->PfnDatabase)[ListHead->Flink])->u2.Blink = PageFrameIndex; } else { @@ -675,7 +675,7 @@ MM::Pfn::LinkPage(IN PMMPFNLIST ListHead, if(ListHead->Blink != MAXULONG_PTR) { /* Link the current tail to the new page */ - (&((PMMPFN)MemoryLayout->PfnDatabaseAddress)[ListHead->Blink])->u1.Flink = PageFrameIndex; + (&((PMMPFN)MemoryLayout->PfnDatabase)[ListHead->Blink])->u1.Flink = PageFrameIndex; } else { @@ -714,7 +714,7 @@ MM::Pfn::LinkPage(IN PMMPFNLIST ListHead, if(ColorHead->Flink != MAXULONG_PTR) { /* Fix up the PTE frame of the previous entry */ - (&((PMMPFN)MemoryLayout->PfnDatabaseAddress)[ColorHead->Flink])->u4.PteFrame = PageFrameIndex; + (&((PMMPFN)MemoryLayout->PfnDatabase)[ColorHead->Flink])->u4.PteFrame = PageFrameIndex; } else { @@ -817,7 +817,7 @@ MM::Pfn::LinkPfnToPte(IN PFN_NUMBER PageFrameIndex, MemoryLayout = MM::Manager::GetMemoryLayout(); /* Point the PFN to its PTE */ - Pfn = &((PMMPFN)MemoryLayout->PfnDatabaseAddress)[PageFrameIndex]; + Pfn = &((PMMPFN)MemoryLayout->PfnDatabase)[PageFrameIndex]; Pfn->PteAddress = PointerPte; /* Check if the page is already mapped and in use */ @@ -860,7 +860,7 @@ MM::Pfn::LinkPfnToPte(IN PFN_NUMBER PageFrameIndex, Pfn->u4.PteFrame = PageFrameIndex; /* Pin the page table in memory by incrementing its PFN share count */ - Pfn = &((PMMPFN)MemoryLayout->PfnDatabaseAddress)[PageFrameIndex]; + Pfn = &((PMMPFN)MemoryLayout->PfnDatabase)[PageFrameIndex]; Pfn->u2.ShareCount++; } @@ -887,7 +887,7 @@ MM::Pfn::LinkStandbyPage(IN PFN_NUMBER PageFrameIndex) MemoryLayout = MM::Manager::GetMemoryLayout(); /* Get the PFN database entry for the target page */ - CurrentPageFrame = &((PMMPFN)MemoryLayout->PfnDatabaseAddress)[PageFrameIndex]; + CurrentPageFrame = &((PMMPFN)MemoryLayout->PfnDatabase)[PageFrameIndex]; /* Check if the page is part of a ROM image */ if(CurrentPageFrame->u3.e1.Rom == 1) @@ -899,7 +899,7 @@ MM::Pfn::LinkStandbyPage(IN PFN_NUMBER PageFrameIndex) if(RomPagesList.Blink != (ULONG_PTR)-1) { /* Update the old tail to point to the new page */ - AdjacentPageFrame = &((PMMPFN)MemoryLayout->PfnDatabaseAddress)[RomPagesList.Blink]; + AdjacentPageFrame = &((PMMPFN)MemoryLayout->PfnDatabase)[RomPagesList.Blink]; AdjacentPageFrame->u1.Flink = PageFrameIndex; } else @@ -933,7 +933,7 @@ MM::Pfn::LinkStandbyPage(IN PFN_NUMBER PageFrameIndex) if(Flink != MAXULONG_PTR) { /* Update the old head to point to the new page */ - AdjacentPageFrame = &((PMMPFN)MemoryLayout->PfnDatabaseAddress)[Flink]; + AdjacentPageFrame = &((PMMPFN)MemoryLayout->PfnDatabase)[Flink]; AdjacentPageFrame->u2.Blink = PageFrameIndex; } else diff --git a/xtoskrnl/mm/pte.cc b/xtoskrnl/mm/pte.cc index 98c5ebc..6a47c48 100644 --- a/xtoskrnl/mm/pte.cc +++ b/xtoskrnl/mm/pte.cc @@ -199,15 +199,15 @@ MM::Pte::InitializeSystemPteSpace(VOID) /* Retrieve the system's memory layout */ MemoryLayout = MM::Manager::GetMemoryLayout(); - NonPagedSystemPoolEnd = ((ULONGLONG)MemoryLayout->SystemSpaceStart + + NonPagedSystemPoolEnd = ((ULONGLONG)MemoryLayout->NonPagedSystemPoolStart + MM::Manager::GetNumberOfSystemPtes() * MM_PAGE_SIZE); /* Map the page table hierarchy for the entire system PTE space */ - MM::Pte::MapPPE(MemoryLayout->SystemSpaceStart, (PVOID)NonPagedSystemPoolEnd, &ValidPte); - MM::Pte::MapPDE(MemoryLayout->SystemSpaceStart, (PVOID)NonPagedSystemPoolEnd, &ValidPte); + MM::Pte::MapPPE(MemoryLayout->NonPagedSystemPoolStart, (PVOID)NonPagedSystemPoolEnd, &ValidPte); + MM::Pte::MapPDE(MemoryLayout->NonPagedSystemPoolStart, (PVOID)NonPagedSystemPoolEnd, &ValidPte); /* Format the main block of system PTEs into a free list pool */ - PointerPte = MM::Paging::GetPteAddress(MemoryLayout->SystemSpaceStart); + PointerPte = MM::Paging::GetPteAddress(MemoryLayout->NonPagedSystemPoolStart); InitializeSystemPtePool(PointerPte, MM::Manager::GetNumberOfSystemPtes(), SystemPteSpace); -- 2.52.0 From 5e3fb7a5a31fe7e50397173991787cea35470bf5 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Thu, 29 Jan 2026 22:26:31 +0100 Subject: [PATCH 131/166] Move PFN database size tracking to memory layout --- xtoskrnl/includes/mm/pfn.hh | 4 +--- xtoskrnl/mm/amd64/mmgr.cc | 7 +++---- xtoskrnl/mm/amd64/pfn.cc | 7 ++++--- xtoskrnl/mm/data.cc | 3 --- xtoskrnl/mm/i686/mmgr.cc | 8 ++++---- xtoskrnl/mm/i686/pfn.cc | 10 +++++----- xtoskrnl/mm/mmgr.cc | 3 --- xtoskrnl/mm/pfn.cc | 25 +++++++++---------------- 8 files changed, 26 insertions(+), 41 deletions(-) diff --git a/xtoskrnl/includes/mm/pfn.hh b/xtoskrnl/includes/mm/pfn.hh index efca193..65996f7 100644 --- a/xtoskrnl/includes/mm/pfn.hh +++ b/xtoskrnl/includes/mm/pfn.hh @@ -30,7 +30,6 @@ namespace MM STATIC ULONGLONG NumberOfPhysicalPages; STATIC LOADER_MEMORY_DESCRIPTOR OriginalFreeDescriptor; STATIC PMMPFNLIST PageLocationList[]; - STATIC PFN_NUMBER PfnDatabaseSize; STATIC MMPFNLIST RomPagesList; STATIC MMPFNLIST StandbyPagesList; STATIC MMPFNLIST ZeroedPagesList; @@ -38,7 +37,7 @@ namespace MM public: STATIC XTAPI PFN_NUMBER AllocateBootstrapPages(IN PFN_NUMBER NumberOfPages); STATIC XTAPI PFN_NUMBER AllocatePhysicalPage(IN ULONG Color); - STATIC XTAPI VOID ComputePfnDatabaseSize(VOID); + STATIC XTAPI VOID ComputePfnDatabaseSize(OUT PPFN_NUMBER DatabaseSize); STATIC XTAPI VOID DecrementReferenceCount(IN PMMPFN Pfn1, IN PFN_NUMBER PageFrameIndex, IN BOOLEAN BeginStandbyList = FALSE); @@ -48,7 +47,6 @@ namespace MM STATIC XTAPI VOID FreePhysicalPage(IN PMMPTE PointerPte); STATIC XTAPI ULONG_PTR GetHighestPhysicalPage(VOID); STATIC XTAPI ULONGLONG GetNumberOfPhysicalPages(VOID); - STATIC XTAPI PFN_NUMBER GetPfnDatabaseSize(VOID); STATIC XTAPI PMMPFN GetPfnEntry(IN PFN_NUMBER Pfn); STATIC XTAPI VOID InitializePfnDatabase(VOID); STATIC VOID XTAPI LinkPfnToPte(IN PFN_NUMBER PageFrameIndex, diff --git a/xtoskrnl/mm/amd64/mmgr.cc b/xtoskrnl/mm/amd64/mmgr.cc index 843039b..ff6551a 100644 --- a/xtoskrnl/mm/amd64/mmgr.cc +++ b/xtoskrnl/mm/amd64/mmgr.cc @@ -21,7 +21,6 @@ VOID MM::Manager::InitializeMemoryLayout(VOID) { ULONG_PTR PagedPoolSize, PteCount; - PFN_NUMBER PfnDatabaseSize; ULONG PtesPerPage; /* Get the number of PTEs per page and calculate size of paged pool (at least 32MiB) */ @@ -30,7 +29,7 @@ MM::Manager::InitializeMemoryLayout(VOID) PagedPoolSize = PteCount * PtesPerPage * MM_PAGE_SIZE; /* Retrieve the PFN database size */ - PfnDatabaseSize = MM::Pfn::GetPfnDatabaseSize(); + MM::Pfn::GetPfnDatabaseSize(&MemoryLayout.PfnDatabaseSize); /* Define the number of system PTEs */ NumberOfSystemPtes = MM_DEFAULT_NUMBER_SYSTEM_PTES; @@ -43,7 +42,7 @@ MM::Manager::InitializeMemoryLayout(VOID) MemoryLayout.SelfMapAddress = (PVOID)MM_P5E_LA57_BASE; /* Define the non-paged and paged pool regions */ - MemoryLayout.NonPagedPoolStart = (PVOID)((ULONG_PTR)MemoryLayout.PfnDatabase + PfnDatabaseSize * MM_PAGE_SIZE); + MemoryLayout.NonPagedPoolStart = (PVOID)((ULONG_PTR)MemoryLayout.PfnDatabase + MemoryLayout.PfnDatabaseSize * MM_PAGE_SIZE); MemoryLayout.NonPagedPoolEnd = (PVOID)0xFFFEFFFFFFBFFFFFULL; MemoryLayout.PagedPoolStart = (PVOID)0xFFFEF8A000000000ULL; MemoryLayout.PagedPoolEnd = (PVOID)(((ULONG_PTR)MemoryLayout.PagedPoolStart + PagedPoolSize) - 1); @@ -60,7 +59,7 @@ MM::Manager::InitializeMemoryLayout(VOID) MemoryLayout.SelfMapAddress = (PVOID)MM_PXE_BASE; /* Define the non-paged and paged pool regions */ - MemoryLayout.NonPagedPoolStart = (PVOID)((ULONG_PTR)MemoryLayout.PfnDatabase + PfnDatabaseSize * MM_PAGE_SIZE); + MemoryLayout.NonPagedPoolStart = (PVOID)((ULONG_PTR)MemoryLayout.PfnDatabase + MemoryLayout.PfnDatabaseSize * MM_PAGE_SIZE); MemoryLayout.NonPagedPoolEnd = (PVOID)0xFFFFFFFFFFBFFFFFULL; MemoryLayout.PagedPoolStart = (PVOID)0xFFFFF8A000000000ULL; MemoryLayout.PagedPoolEnd = (PVOID)(((ULONG_PTR)MemoryLayout.PagedPoolStart + PagedPoolSize) - 1); diff --git a/xtoskrnl/mm/amd64/pfn.cc b/xtoskrnl/mm/amd64/pfn.cc index d9bbc7f..03f0183 100644 --- a/xtoskrnl/mm/amd64/pfn.cc +++ b/xtoskrnl/mm/amd64/pfn.cc @@ -40,7 +40,7 @@ MM::Pfn::InitializePfnDatabase(VOID) MemoryLayout = MM::Manager::GetMemoryLayout(); /* Get the PFN database size and calculate the end of the PFN database virtual address space */ - PfnDatabaseEnd = (PUCHAR)MemoryLayout->PfnDatabase + (PfnDatabaseSize * MM_PAGE_SIZE) - 1; + PfnDatabaseEnd = (PUCHAR)MemoryLayout->PfnDatabase + (MemoryLayout->PfnDatabaseSize * MM_PAGE_SIZE) - 1; /* Get a template PTE for mapping the PFN database pages */ ValidPte = MM::Pte::GetValidPte(); @@ -88,10 +88,11 @@ MM::Pfn::InitializePfnDatabase(VOID) if(Descriptor == FreeDescriptor) { /* Initialize PFNs for the remaining free memory */ - ProcessMemoryDescriptor(BasePage + PfnDatabaseSize, PageCount - PfnDatabaseSize, LoaderFree); + ProcessMemoryDescriptor(BasePage + MemoryLayout->PfnDatabaseSize, + PageCount - MemoryLayout->PfnDatabaseSize, LoaderFree); /* Initialize PFNs for the physical pages backing the PFN database */ - ProcessMemoryDescriptor(BasePage, PfnDatabaseSize, LoaderMemoryData); + ProcessMemoryDescriptor(BasePage, MemoryLayout->PfnDatabaseSize, LoaderMemoryData); } else { diff --git a/xtoskrnl/mm/data.cc b/xtoskrnl/mm/data.cc index ffbd85a..6586526 100644 --- a/xtoskrnl/mm/data.cc +++ b/xtoskrnl/mm/data.cc @@ -82,9 +82,6 @@ PMMPFNLIST MM::Pfn::PageLocationList[] = {&ZeroedPagesList, NULLPTR, NULLPTR}; -/* Size of the PFN database in pages */ -PFN_NUMBER MM::Pfn::PfnDatabaseSize; - /* List containing pages mapped as Read-Only (ROM) */ MMPFNLIST MM::Pfn::RomPagesList = {0, StandbyPageList, MAXULONG_PTR, MAXULONG_PTR}; diff --git a/xtoskrnl/mm/i686/mmgr.cc b/xtoskrnl/mm/i686/mmgr.cc index c51b4db..cc0032a 100644 --- a/xtoskrnl/mm/i686/mmgr.cc +++ b/xtoskrnl/mm/i686/mmgr.cc @@ -21,7 +21,7 @@ VOID MM::Manager::InitializeMemoryLayout(VOID) { ULONG_PTR PagedPoolSize, PteCount; - PFN_NUMBER PfnDatabaseSize, PhysicalPages; + PFN_NUMBER PhysicalPages; ULONG PtesPerPage; /* Define the number of system PTEs */ @@ -48,7 +48,7 @@ MM::Manager::InitializeMemoryLayout(VOID) PagedPoolSize = PteCount * PtesPerPage * MM_PAGE_SIZE; /* Retrieve the PFN database size */ - PfnDatabaseSize = MM::Pfn::GetPfnDatabaseSize(); + MM::Pfn::GetPfnDatabaseSize(&MemoryLayout.PfnDatabaseSize); /* Check if 3-level paging (PAE) is enabled */ if(MM::Paging::GetXpaStatus()) @@ -58,7 +58,7 @@ MM::Manager::InitializeMemoryLayout(VOID) MemoryLayout.SelfMapAddress = (PVOID)MM_PTE_BASE; /* Define the non-paged and paged pool regions */ - MemoryLayout.NonPagedPoolStart = (PVOID)((ULONG_PTR)MemoryLayout.PfnDatabase + PfnDatabaseSize * MM_PAGE_SIZE); + MemoryLayout.NonPagedPoolStart = (PVOID)((ULONG_PTR)MemoryLayout.PfnDatabase + MemoryLayout.PfnDatabaseSize * MM_PAGE_SIZE); MemoryLayout.NonPagedPoolEnd = (PVOID)0xEEFFFFFF; MemoryLayout.PagedPoolStart = (PVOID)0xE2000000; MemoryLayout.PagedPoolEnd = (PVOID)(((ULONG_PTR)MemoryLayout.PagedPoolStart + PagedPoolSize) - 1); @@ -75,7 +75,7 @@ MM::Manager::InitializeMemoryLayout(VOID) MemoryLayout.SelfMapAddress = (PVOID)MM_PTE_BASE; /* Define the non-paged and paged pool regions */ - MemoryLayout.NonPagedPoolStart = (PVOID)((ULONG_PTR)MemoryLayout.PfnDatabase + PfnDatabaseSize * MM_PAGE_SIZE); + MemoryLayout.NonPagedPoolStart = (PVOID)((ULONG_PTR)MemoryLayout.PfnDatabase + MemoryLayout.PfnDatabaseSize * MM_PAGE_SIZE); MemoryLayout.NonPagedPoolEnd = (PVOID)0xFFBE0000; MemoryLayout.PagedPoolStart = (PVOID)0xE1000000; MemoryLayout.PagedPoolEnd = (PVOID)(((ULONG_PTR)MemoryLayout.PagedPoolStart + PagedPoolSize) - 1); diff --git a/xtoskrnl/mm/i686/pfn.cc b/xtoskrnl/mm/i686/pfn.cc index 840066d..a939809 100644 --- a/xtoskrnl/mm/i686/pfn.cc +++ b/xtoskrnl/mm/i686/pfn.cc @@ -39,7 +39,7 @@ MM::Pfn::InitializePfnDatabase(VOID) MemoryLayout = MM::Manager::GetMemoryLayout(); /* Get the PFN database size and calculate the end of the PFN database virtual address space */ - PfnDatabaseEnd = (PUCHAR)MemoryLayout->PfnDatabase + (PfnDatabaseSize * MM_PAGE_SIZE) - 1; + PfnDatabaseEnd = (PUCHAR)MemoryLayout->PfnDatabase + (MemoryLayout->PfnDatabaseSize * MM_PAGE_SIZE) - 1; /* Get a template PTE for mapping the PFN database pages */ ValidPte = MM::Pte::GetValidPte(); @@ -49,7 +49,7 @@ MM::Pfn::InitializePfnDatabase(VOID) MM::Pte::MapPTE(MemoryLayout->PfnDatabase, PfnDatabaseEnd, ValidPte); /* Zero PFN database virtual space */ - RTL::Memory::ZeroMemory(MemoryLayout->PfnDatabase, PfnDatabaseSize * MM_PAGE_SIZE); + RTL::Memory::ZeroMemory(MemoryLayout->PfnDatabase, MemoryLayout->PfnDatabaseSize * MM_PAGE_SIZE); /* Initialize the color tables */ MM::Colors::InitializeColorTables(); @@ -73,12 +73,12 @@ MM::Pfn::InitializePfnDatabase(VOID) if(Descriptor == FreeDescriptor) { /* Initialize PFNs for the remaining free memory after the PFN database */ - ProcessMemoryDescriptor(OriginalFreeDescriptor.BasePage + PfnDatabaseSize, - OriginalFreeDescriptor.PageCount - PfnDatabaseSize, + ProcessMemoryDescriptor(OriginalFreeDescriptor.BasePage + MemoryLayout->PfnDatabaseSize, + OriginalFreeDescriptor.PageCount - MemoryLayout->PfnDatabaseSize, LoaderFree); /* Initialize PFNs for the physical pages backing the PFN database itself */ - ProcessMemoryDescriptor(OriginalFreeDescriptor.BasePage, PfnDatabaseSize, LoaderMemoryData); + ProcessMemoryDescriptor(OriginalFreeDescriptor.BasePage, MemoryLayout->PfnDatabaseSize, LoaderMemoryData); } else { diff --git a/xtoskrnl/mm/mmgr.cc b/xtoskrnl/mm/mmgr.cc index 23620b6..6d11779 100644 --- a/xtoskrnl/mm/mmgr.cc +++ b/xtoskrnl/mm/mmgr.cc @@ -112,9 +112,6 @@ MM::Manager::InitializeMemoryManager(VOID) /* Compute page colors to reduce CPU cache conflicts */ MM::Colors::ComputePageColoring(); - /* Compute allocation size for the PFN database */ - MM::Pfn::ComputePfnDatabaseSize(); - /* Initialize memory layout */ InitializeMemoryLayout(); diff --git a/xtoskrnl/mm/pfn.cc b/xtoskrnl/mm/pfn.cc index 6ce37be..c7de33e 100644 --- a/xtoskrnl/mm/pfn.cc +++ b/xtoskrnl/mm/pfn.cc @@ -99,19 +99,27 @@ MM::Pfn::AllocatePhysicalPage(IN ULONG Color) /** * Calculates the total number of pages required for the PFN database and its associated color tables. * + * @param DatabaseSize + * A pointer to a variable that will receive the number of pages required for the PFN database. + * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID -MM::Pfn::ComputePfnDatabaseSize(VOID) +MM::Pfn::ComputePfnDatabaseSize(OUT PPFN_NUMBER DatabaseSize) { + PFN_NUMBER PfnDatabaseSize; + /* Calculate the total number of pages required for the PFN database */ PfnDatabaseSize = (HighestPhysicalPage + 1) * sizeof(MMPFN); PfnDatabaseSize += (MM::Colors::GetPagingColors() * sizeof(MMCOLOR_TABLES) * 2); PfnDatabaseSize = ROUND_UP(PfnDatabaseSize, MM_PAGE_SIZE); PfnDatabaseSize >>= MM_PAGE_SHIFT; + + /* Return the PFN database size */ + *DatabaseSize = PfnDatabaseSize; } /** @@ -373,21 +381,6 @@ MM::Pfn::GetNumberOfPhysicalPages(VOID) return NumberOfPhysicalPages; } -/** - * Gets the size of the PFN database and its associated structures, in pages. - * - * @return This routine returns the total number of pages required for the PFN database and its associated structures. - * - * @since XT 1.0 - */ -XTAPI -PFN_NUMBER -MM::Pfn::GetPfnDatabaseSize(VOID) -{ - /* Return the pre-calculated size of the PFN database in pages */ - return PfnDatabaseSize; -} - /** * Retrieves a pointer to the PFN database entry for a given physical page. * -- 2.52.0 From 54e75c9345d1e8a9e8f368f71d7d23f584ca01c8 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Thu, 29 Jan 2026 22:29:02 +0100 Subject: [PATCH 132/166] Fix PFN database size calculation call sites --- xtoskrnl/mm/amd64/mmgr.cc | 2 +- xtoskrnl/mm/i686/mmgr.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/xtoskrnl/mm/amd64/mmgr.cc b/xtoskrnl/mm/amd64/mmgr.cc index ff6551a..a128cb6 100644 --- a/xtoskrnl/mm/amd64/mmgr.cc +++ b/xtoskrnl/mm/amd64/mmgr.cc @@ -29,7 +29,7 @@ MM::Manager::InitializeMemoryLayout(VOID) PagedPoolSize = PteCount * PtesPerPage * MM_PAGE_SIZE; /* Retrieve the PFN database size */ - MM::Pfn::GetPfnDatabaseSize(&MemoryLayout.PfnDatabaseSize); + MM::Pfn::ComputePfnDatabaseSize(&MemoryLayout.PfnDatabaseSize); /* Define the number of system PTEs */ NumberOfSystemPtes = MM_DEFAULT_NUMBER_SYSTEM_PTES; diff --git a/xtoskrnl/mm/i686/mmgr.cc b/xtoskrnl/mm/i686/mmgr.cc index cc0032a..6a060c9 100644 --- a/xtoskrnl/mm/i686/mmgr.cc +++ b/xtoskrnl/mm/i686/mmgr.cc @@ -48,7 +48,7 @@ MM::Manager::InitializeMemoryLayout(VOID) PagedPoolSize = PteCount * PtesPerPage * MM_PAGE_SIZE; /* Retrieve the PFN database size */ - MM::Pfn::GetPfnDatabaseSize(&MemoryLayout.PfnDatabaseSize); + MM::Pfn::ComputePfnDatabaseSize(&MemoryLayout.PfnDatabaseSize); /* Check if 3-level paging (PAE) is enabled */ if(MM::Paging::GetXpaStatus()) -- 2.52.0 From 726fd842412ce8e175e5e6de8699e6286f88ca48 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Thu, 29 Jan 2026 22:34:44 +0100 Subject: [PATCH 133/166] Enable non-paged pool setup --- xtoskrnl/mm/mmgr.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/xtoskrnl/mm/mmgr.cc b/xtoskrnl/mm/mmgr.cc index 6d11779..4860069 100644 --- a/xtoskrnl/mm/mmgr.cc +++ b/xtoskrnl/mm/mmgr.cc @@ -121,6 +121,9 @@ MM::Manager::InitializeMemoryManager(VOID) /* Initialize page table */ MM::Pte::InitializePageTable(); + /* Initialize non-paged pool */ + MM::Allocator::InitializeNonPagedPool(); + /* Initialize system PTE space */ MM::Pte::InitializeSystemPteSpace(); -- 2.52.0 From 6a7bc64ac7ce5fa6f567de2d850b4943bd8d1472 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Fri, 30 Jan 2026 14:47:13 +0100 Subject: [PATCH 134/166] Overhaul kernel memory layout initialization and pool sizing --- xtoskrnl/includes/mm/mmgr.hh | 6 + xtoskrnl/mm/amd64/mmgr.cc | 395 +++++++++++++++++++++++++++--- xtoskrnl/mm/i686/mmgr.cc | 459 +++++++++++++++++++++++++++++++---- 3 files changed, 774 insertions(+), 86 deletions(-) diff --git a/xtoskrnl/includes/mm/mmgr.hh b/xtoskrnl/includes/mm/mmgr.hh index c53646d..770491b 100644 --- a/xtoskrnl/includes/mm/mmgr.hh +++ b/xtoskrnl/includes/mm/mmgr.hh @@ -32,6 +32,12 @@ namespace MM private: STATIC XTAPI VOID ComputeBootImageSize(OUT PPFN_NUMBER BootImageSize); + STATIC XTAPI VOID ComputeMaximumNonPagedPoolSize(OUT PPFN_NUMBER PoolSize); + STATIC XTAPI VOID ComputeNonPagedPoolSize(OUT PPFN_NUMBER PoolSize); + STATIC XTAPI VOID ComputePagedPoolSize(OUT PPFN_NUMBER PoolSize); + STATIC XTAPI VOID ComputeSessionSpaceSize(OUT PPFN_NUMBER SpaceSize); + STATIC XTAPI VOID ComputeSystemPteSize(OUT PPFN_NUMBER PteSize); + STATIC XTAPI VOID DumpMemoryLayout(VOID); }; } diff --git a/xtoskrnl/mm/amd64/mmgr.cc b/xtoskrnl/mm/amd64/mmgr.cc index a128cb6..72adf3a 100644 --- a/xtoskrnl/mm/amd64/mmgr.cc +++ b/xtoskrnl/mm/amd64/mmgr.cc @@ -9,6 +9,249 @@ #include +/** + * Calculates the maximum possible size of the non-paged pool. + * + * @param PoolSize + * A pointer to a variable that will receive the number of pages available for the non-paged pool. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::Manager::ComputeMaximumNonPagedPoolSize(OUT PPFN_NUMBER PoolSize) +{ + ULONG_PTR MaximumNonPagedPoolSize; + + /* Start with the 1MiB and add 400KiB for each MiB above 16MiB */ + MaximumNonPagedPoolSize = 1048576 + (((MM::Pfn::GetNumberOfPhysicalPages() - 4096) / 256) * 409600); + + /* Check if non-paged pool does not exceed 128GiB */ + if(MaximumNonPagedPoolSize > 137438953472) + { + /* Limit non-paged pool size to 128GiB */ + MaximumNonPagedPoolSize = 137438953472; + } + + /* Return non-paged pool size */ + *PoolSize = SIZE_TO_PAGES(MaximumNonPagedPoolSize); +} + +/** + * Calculates the size of the non-paged pool. + * + * @param PoolSize + * A pointer to a variable that will receive the number of pages available for the non-paged pool. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::Manager::ComputeNonPagedPoolSize(OUT PPFN_NUMBER PoolSize) +{ + ULONG_PTR NonPagedPoolSize; + + /* Start with 1MiB and add 32KiB for each MiB above 16MiB */ + NonPagedPoolSize = 1048576 + (((MM::Pfn::GetNumberOfPhysicalPages() - 4096) / 256) * 32768); + + /* Check if non-paged pool does not exceed 128GiB */ + if(NonPagedPoolSize > 137438953472) + { + /* Limit non-paged pool size to 128GiB */ + NonPagedPoolSize = 137438953472; + } + + /* Return non-paged pool size in pages, aligned up to page size boundary */ + *PoolSize = SIZE_TO_PAGES(ROUND_UP(NonPagedPoolSize, MM_PAGE_SIZE)); +} + +/** + * Calculates the size of the paged pool. + * + * @param PoolSize + * A pointer to a variable that will receive the number of pages available for the paged pool. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::Manager::ComputePagedPoolSize(OUT PPFN_NUMBER PoolSize) +{ + ULONGLONG PagedPoolSize, PteCount; + ULONG PtesPerPage; + + /* Start with 4x maximum non-paged pool size and at least 48MiB */ + ComputeMaximumNonPagedPoolSize(&PagedPoolSize); + PagedPoolSize *= 4 * MM_PAGE_SIZE; + + /* Ensure that paged pool size is at least 48MiB */ + if(PagedPoolSize < 50331648) + { + /* Increase paged pool size to at least 48MiB */ + PagedPoolSize = 50331648; + } + + /* Check if paged pool does not overlap non-paged pool */ + if(PagedPoolSize > (ULONGLONG)MemoryLayout.NonPagedSystemPoolStart - (ULONGLONG)MemoryLayout.PagedPoolStart) + { + /* Limit paged pool size to maximum possible */ + PagedPoolSize = (ULONGLONG)MemoryLayout.NonPagedSystemPoolStart - (ULONGLONG)MemoryLayout.PagedPoolStart; + } + + /* Check if paged pool does not exceed 128GiB */ + if(PagedPoolSize > 137438953472) + { + /* Limit paged pool size to 128GiB */ + PagedPoolSize = 137438953472; + } + + /* Get the number of PTEs per page and calculate size of paged pool */ + PtesPerPage = MM::Pte::GetPtesPerPage(); + PteCount = ((SIZE_TO_PAGES(PagedPoolSize) + (PtesPerPage - 1)) / PtesPerPage); + + /* Return paged pool size */ + *PoolSize = PteCount * PtesPerPage; +} + +/** + * Calculates the size of the session space. + * + * @param SpaceSize + * A pointer to a variable that will receive the number of pages available by the session space. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::Manager::ComputeSessionSpaceSize(OUT PPFN_NUMBER SpaceSize) +{ + PFN_NUMBER SessionSpaceSize; + + /* Session Pool, Session View, Session Image, Session Working Set and System View takes 1120MiB */ + SessionSpaceSize = 1174405120; + + /* Return number of pages used by the session space */ + *SpaceSize = SessionSpaceSize / MM_PAGE_SIZE; +} + +/** + * Calculates the size of the system PTEs. + * + * @param PteSize + * A pointer to a variable that will receive the number of system PTEs. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::Manager::ComputeSystemPteSize(OUT PPFN_NUMBER PteSize) +{ + PFN_NUMBER SystemPteSize; + + /* Check if system has less than 24MiB of physical memory */ + if(MM::Pfn::GetNumberOfPhysicalPages() < 6144) + { + /* Set minimal system PTE size */ + SystemPteSize = 7000; + } + else + { + /* Use standard system PTE size */ + SystemPteSize = 11000; + + /* Check if system has more than 32MiB of physical memory */ + if(MM::Pfn::GetNumberOfPhysicalPages() > 8192) + { + /* Double system PTE size */ + SystemPteSize *= 2; + + /* Check if system has more than 256MiB of physical memory */ + if(MM::Pfn::GetNumberOfPhysicalPages() > 65536) + { + /* Double system PTE size */ + SystemPteSize *= 2; + } + } + } + + /* Return system PTE size */ + *PteSize = SystemPteSize; +} + +/** + * Dumps the kernel's memory layout. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::Manager::DumpMemoryLayout(VOID) +{ + /* Dump memory layout */ + DebugPrint(L"System with %zu MiB of installed memory:\n" + L"User Space: %.16P - %.16P\n" + L"Non-Canonical: %.16P - %.16P\n" + L"Reserved System Pool: %.16P - %.16P\n" + L"PTE Space: %.16P - %.16P\n" + L"Hyper Space: %.16P - %.16P\n" + L"Shared System Page: %.16P - %.16P\n" + L"System Working Set: %.16P - %.16P\n" + L"Loader Mappings: %.16P - %.16P\n" + L"Non-Paged System Pool: %.16P - %.16P\n" + L"Paged Pool: %.16P - %.16P\n" + L"Session Space: %.16P - %.16P\n" + L"System Cache: %.16P - %.16P\n" + L"PFN Database: %.16P - %.16P\n" + L"Non-Paged Pool: %.16P - %.16P\n" + L"Non-Paged Expansion Pool: %.16P - %.16P\n" + L"Hardware Pool: %.16P - %.16P\n", + GetInstalledMemorySize(), + MemoryLayout.UserSpaceStart, + MemoryLayout.UserSpaceEnd, + MemoryLayout.NonCanonicalStart, + MemoryLayout.NonCanonicalEnd, + MemoryLayout.ReservedSystemPoolStart, + MemoryLayout.ReservedSystemPoolEnd, + MemoryLayout.PteSpaceStart, + MemoryLayout.PteSpaceEnd, + MemoryLayout.HyperSpaceStart, + MemoryLayout.HyperSpaceEnd, + MemoryLayout.SharedSystemPageStart, + MemoryLayout.SharedSystemPageEnd, + MemoryLayout.SystemWorkingSetStart, + MemoryLayout.SystemWorkingSetEnd, + MemoryLayout.LoaderMappingsStart, + MemoryLayout.LoaderMappingsEnd, + MemoryLayout.NonPagedSystemPoolStart, + MemoryLayout.NonPagedSystemPoolEnd, + MemoryLayout.PagedPoolStart, + MemoryLayout.PagedPoolEnd, + MemoryLayout.SessionSpaceStart, + MemoryLayout.SessionSpaceEnd, + MemoryLayout.SystemCacheStart, + MemoryLayout.SystemCacheEnd, + MemoryLayout.PfnDatabase, + (PVOID)((ULONG_PTR)MemoryLayout.PfnDatabase + (ULONG_PTR)MemoryLayout.PfnDatabaseSize * MM_PAGE_SIZE), + MemoryLayout.NonPagedPoolStart, + MemoryLayout.NonPagedPoolEnd, + MemoryLayout.NonPagedExpansionPoolStart, + MemoryLayout.NonPagedExpansionPoolEnd, + MemoryLayout.HardwarePoolStart, + MemoryLayout.HardwarePoolEnd); +} + /** * Initializes the kernel's virtual memory layout. * @@ -20,53 +263,131 @@ XTAPI VOID MM::Manager::InitializeMemoryLayout(VOID) { - ULONG_PTR PagedPoolSize, PteCount; - ULONG PtesPerPage; - - /* Get the number of PTEs per page and calculate size of paged pool (at least 32MiB) */ - PtesPerPage = MM::Pte::GetPtesPerPage(); - PteCount = ((SIZE_TO_PAGES(33554432) + (PtesPerPage - 1)) / PtesPerPage); - PagedPoolSize = PteCount * PtesPerPage * MM_PAGE_SIZE; - - /* Retrieve the PFN database size */ - MM::Pfn::ComputePfnDatabaseSize(&MemoryLayout.PfnDatabaseSize); - - /* Define the number of system PTEs */ - NumberOfSystemPtes = MM_DEFAULT_NUMBER_SYSTEM_PTES; + PFN_NUMBER MaximumNonPagedPoolSize; + ULONG_PTR PfnDatabaseEnd; /* Check if 5-level paging (LA57) is enabled */ if(MM::Paging::GetXpaStatus()) { - /* Configure memory layout for 5-level paging, using 57bit address space and providing a 128 PB address space */ - MemoryLayout.PfnDatabase = (PMMPFN)0xFFFEFA8000000000ULL; + /* Set PML5 base address */ MemoryLayout.SelfMapAddress = (PVOID)MM_P5E_LA57_BASE; - /* Define the non-paged and paged pool regions */ - MemoryLayout.NonPagedPoolStart = (PVOID)((ULONG_PTR)MemoryLayout.PfnDatabase + MemoryLayout.PfnDatabaseSize * MM_PAGE_SIZE); - MemoryLayout.NonPagedPoolEnd = (PVOID)0xFFFEFFFFFFBFFFFFULL; - MemoryLayout.PagedPoolStart = (PVOID)0xFFFEF8A000000000ULL; - MemoryLayout.PagedPoolEnd = (PVOID)(((ULONG_PTR)MemoryLayout.PagedPoolStart + PagedPoolSize) - 1); - - /* Define hyperspace, system PTE space, and the user space limit */ - MemoryLayout.HyperSpaceStart = (PVOID)0xFFFEF70000000000ULL; - MemoryLayout.HyperSpaceEnd = (PVOID)0xFFFEF77FFFFFFFFFULL; - MemoryLayout.UserSpaceEnd = (PVOID)0x07FFFFFFFFFFFFFULL; + /* Define memory layout for 5-level paging */ + MemoryLayout.UserSpaceStart = (PVOID)0x0000000000010000; + MemoryLayout.UserSpaceEnd = (PVOID)0x00FFFFFFFFFEFFFF; + MemoryLayout.NonCanonicalStart = (PVOID)0x0080000000000000; + MemoryLayout.NonCanonicalEnd = (PVOID)0xFEFFFFFFFFFFFFFF; + MemoryLayout.ReservedSystemPoolStart = (PVOID)0xFF00000000000000; + MemoryLayout.ReservedSystemPoolEnd = (PVOID)0xFFECFFFFFFFFFFFF; + MemoryLayout.PteSpaceStart = (PVOID)0xFFED000000000000; + MemoryLayout.PteSpaceEnd = (PVOID)0xFFEDFFFFFFFFFFFF; + MemoryLayout.HyperSpaceStart = (PVOID)0xFFFFF70000000000; + MemoryLayout.HyperSpaceEnd = (PVOID)0xFFFFF77FFFFFFFFF; + MemoryLayout.SharedSystemPageStart = (PVOID)0xFFFFF78000000000; + MemoryLayout.SharedSystemPageEnd = (PVOID)0xFFFFF78000000FFF; + MemoryLayout.SystemWorkingSetStart = (PVOID)0xFFFFF78000001000; + MemoryLayout.SystemWorkingSetEnd = (PVOID)0xFFFFF7FFFFFFFFFF; + MemoryLayout.LoaderMappingsStart = (PVOID)0xFFFFF80000000000; + MemoryLayout.LoaderMappingsEnd = (PVOID)0xFFFFF87FFFFFFFFF; + MemoryLayout.NonPagedSystemPoolStart = (PVOID)0xFFFFF88000000000; + MemoryLayout.NonPagedSystemPoolEnd = (PVOID)0xFFFFF89FFFFFFFFF; + MemoryLayout.PagedPoolStart = (PVOID)0xFFFFF8A000000000; + MemoryLayout.PagedPoolEnd = (PVOID)0xFFFFF8BFFFFFFFFF; + MemoryLayout.SessionSpaceStart = (PVOID)0xFFFFF90000000000; + MemoryLayout.SessionSpaceEnd = (PVOID)0xFFFFF98000000000; + MemoryLayout.SystemCacheStart = (PVOID)0xFFFFF98000000000; + MemoryLayout.SystemCacheEnd = (PVOID)0xFFFFFA7FFFFFFFFF; + MemoryLayout.NonPagedPoolStart = (PVOID)0xFFFFFA8000000000; + MemoryLayout.NonPagedPoolEnd = (PVOID)0xFFFFFFFFFFBFFFFF; + MemoryLayout.HardwarePoolStart = (PVOID)0xFFFFFFFFFFC00000; + MemoryLayout.HardwarePoolEnd = (PVOID)0xFFFFFFFFFFFFFFFF; } else { - /* Configure memory layout for 4-level paging, using 48bit address space and providing a 128 TB address space */ - MemoryLayout.PfnDatabase = (PMMPFN)0xFFFFFA8000000000ULL; + /* Set PML4 base address */ MemoryLayout.SelfMapAddress = (PVOID)MM_PXE_BASE; - /* Define the non-paged and paged pool regions */ - MemoryLayout.NonPagedPoolStart = (PVOID)((ULONG_PTR)MemoryLayout.PfnDatabase + MemoryLayout.PfnDatabaseSize * MM_PAGE_SIZE); - MemoryLayout.NonPagedPoolEnd = (PVOID)0xFFFFFFFFFFBFFFFFULL; - MemoryLayout.PagedPoolStart = (PVOID)0xFFFFF8A000000000ULL; - MemoryLayout.PagedPoolEnd = (PVOID)(((ULONG_PTR)MemoryLayout.PagedPoolStart + PagedPoolSize) - 1); - - /* Define hyperspace, system PTE space, and the user space limit */ - MemoryLayout.HyperSpaceStart = (PVOID)0xFFFFF70000000000ULL; - MemoryLayout.HyperSpaceEnd = (PVOID)0xFFFFF77FFFFFFFFFULL; - MemoryLayout.UserSpaceEnd = (PVOID)0x000007FFFFFEFFFFULL; + /* Define memory layout for 4-level paging */ + MemoryLayout.UserSpaceStart = (PVOID)0x0000000000010000; + MemoryLayout.UserSpaceEnd = (PVOID)0x000007FFFFFEFFFF; + MemoryLayout.NonCanonicalStart = (PVOID)0x0000800000000000; + MemoryLayout.NonCanonicalEnd = (PVOID)0xFFFF7FFFFFFFFFFF; + MemoryLayout.ReservedSystemPoolStart = (PVOID)0xFFFF800000000000; + MemoryLayout.ReservedSystemPoolEnd = (PVOID)0xFFFFF67FFFFFFFFF; + MemoryLayout.PteSpaceStart = (PVOID)0xFFFFF68000000000; + MemoryLayout.PteSpaceEnd = (PVOID)0xFFFFF6FFFFFFFFFF; + MemoryLayout.HyperSpaceStart = (PVOID)0xFFFFF70000000000; + MemoryLayout.HyperSpaceEnd = (PVOID)0xFFFFF77FFFFFFFFF; + MemoryLayout.SharedSystemPageStart = (PVOID)0xFFFFF78000000000; + MemoryLayout.SharedSystemPageEnd = (PVOID)0xFFFFF78000000FFF; + MemoryLayout.SystemWorkingSetStart = (PVOID)0xFFFFF78000001000; + MemoryLayout.SystemWorkingSetEnd = (PVOID)0xFFFFF7FFFFFFFFFF; + MemoryLayout.LoaderMappingsStart = (PVOID)0xFFFFF80000000000; + MemoryLayout.LoaderMappingsEnd = (PVOID)0xFFFFF87FFFFFFFFF; + MemoryLayout.NonPagedSystemPoolStart = (PVOID)0xFFFFF88000000000; + MemoryLayout.NonPagedSystemPoolEnd = (PVOID)0xFFFFF89FFFFFFFFF; + MemoryLayout.PagedPoolStart = (PVOID)0xFFFFF8A000000000; + MemoryLayout.PagedPoolEnd = (PVOID)0xFFFFF8BFFFFFFFFF; + MemoryLayout.SessionSpaceStart = (PVOID)0xFFFFF90000000000; + MemoryLayout.SessionSpaceEnd = (PVOID)0xFFFFF98000000000; + MemoryLayout.SystemCacheStart = (PVOID)0xFFFFF98000000000; + MemoryLayout.SystemCacheEnd = (PVOID)0xFFFFFA7FFFFFFFFF; + MemoryLayout.NonPagedPoolStart = (PVOID)0xFFFFFA8000000000; + MemoryLayout.NonPagedPoolEnd = (PVOID)0xFFFFFFFFFFBFFFFF; + MemoryLayout.HardwarePoolStart = (PVOID)0xFFFFFFFFFFC00000; + MemoryLayout.HardwarePoolEnd = (PVOID)0xFFFFFFFFFFFFFFFF; } + + /* Compute allocation size for the PFN database */ + MM::Pfn::ComputePfnDatabaseSize(&MemoryLayout.PfnDatabaseSize); + + /* Compute boot image size */ + ComputeBootImageSize(&MemoryLayout.LoaderMappingsSize); + + /* Compute session space size */ + ComputeSessionSpaceSize(&MemoryLayout.SessionSpaceSize); + + /* Update loader mappings space end address */ + MemoryLayout.LoaderMappingsEnd = (PVOID)((ULONGLONG)MemoryLayout.LoaderMappingsStart + + MemoryLayout.LoaderMappingsSize * MM_PAGE_SIZE); + + /* Update session space start address */ + MemoryLayout.SessionSpaceStart = (PVOID)((ULONGLONG)MemoryLayout.SessionSpaceEnd - + MemoryLayout.SessionSpaceSize * MM_PAGE_SIZE); + + /* Compute system PTE size */ + ComputeSystemPteSize(&NumberOfSystemPtes); + + /* Compute non-paged pool size */ + ComputeNonPagedPoolSize(&MemoryLayout.NonPagedPoolSize); + ComputeMaximumNonPagedPoolSize(&MaximumNonPagedPoolSize); + + /* Compute paged pool size */ + ComputePagedPoolSize(&MemoryLayout.PagedPoolSize); + + /* Insert the PFN database at the beginning of the non-paged pool */ + MemoryLayout.PfnDatabase = (PMMPFN)MemoryLayout.NonPagedPoolStart; + + /* Compute the PFN database page-aligned end address */ + PfnDatabaseEnd = (ULONGLONG)MemoryLayout.PfnDatabase + (MemoryLayout.PfnDatabaseSize * MM_PAGE_SIZE); + PfnDatabaseEnd = ROUND_UP(PfnDatabaseEnd, MM_PAGE_SIZE); + + /* Shrink the non-paged pool to fit the PFN database */ + MemoryLayout.NonPagedPoolStart = (PVOID)PfnDatabaseEnd; + + /* Assign the rest of the non-paged pool to the expansion pool */ + MemoryLayout.NonPagedExpansionPoolStart = (PVOID)((ULONGLONG)MemoryLayout.NonPagedPoolStart + + MemoryLayout.NonPagedPoolSize * MM_PAGE_SIZE); + MemoryLayout.NonPagedPoolEnd = MemoryLayout.NonPagedExpansionPoolStart; + MemoryLayout.NonPagedExpansionPoolEnd = (PVOID)((ULONGLONG)MemoryLayout.NonPagedPoolStart + + MaximumNonPagedPoolSize * MM_PAGE_SIZE); + MemoryLayout.NonPagedExpansionPoolSize = ((ULONGLONG)MemoryLayout.NonPagedExpansionPoolEnd - + (ULONGLONG)MemoryLayout.NonPagedExpansionPoolStart) / MM_PAGE_SIZE; + + /* Update paged pool end address */ + MemoryLayout.PagedPoolEnd = (PVOID)(((ULONGLONG)MemoryLayout.PagedPoolStart + + MemoryLayout.PagedPoolSize * MM_PAGE_SIZE) - 1); + + /* Dump memory layout */ + DumpMemoryLayout(); } diff --git a/xtoskrnl/mm/i686/mmgr.cc b/xtoskrnl/mm/i686/mmgr.cc index 6a060c9..957895c 100644 --- a/xtoskrnl/mm/i686/mmgr.cc +++ b/xtoskrnl/mm/i686/mmgr.cc @@ -9,6 +9,283 @@ #include +/** + * Calculates the maximum possible size of the non-paged pool. + * + * @param PoolSize + * A pointer to a variable that will receive the number of pages available for the non-paged pool. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::Manager::ComputeMaximumNonPagedPoolSize(OUT PPFN_NUMBER PoolSize) +{ + ULONG_PTR MaximumNonPagedPoolSize; + ULONGLONG PhysicalPages; + + /* Get number of physical pages */ + PhysicalPages = MM::Pfn::GetNumberOfPhysicalPages(); + + /* Start with 1MiB and reserve space for PFN database */ + MaximumNonPagedPoolSize = 1048576; + + /* Check if system has at least 512MiB of physical memory */ + if(PhysicalPages >= 126976) + { + /* Add 200KiB for each MiB above 4MiB */ + MaximumNonPagedPoolSize += ((PhysicalPages - 1024)/256) * 204800; + + /* Check if non-paged pool has at least 128MiB */ + if(MaximumNonPagedPoolSize < 134217728) + { + /* Expand non-paged pool size to 128MiB */ + MaximumNonPagedPoolSize = 134217728; + } + } + else + { + /* Add 400KiB for each MiB above 4MiB */ + MaximumNonPagedPoolSize += ((PhysicalPages - 1024)/256) * 409600; + } + + /* Check if non-paged pool does not exceed 256MiB */ + if(MaximumNonPagedPoolSize > 268435456) + { + /* Limit non-paged pool size to 256MiB */ + MaximumNonPagedPoolSize = 268435456; + } + + /* Return maximum non-paged pool size in pages */ + *PoolSize = SIZE_TO_PAGES(MaximumNonPagedPoolSize); +} + +/** + * Calculates the size of the non-paged pool. + * + * @param PoolSize + * A pointer to a variable that will receive the number of pages available for the non-paged pool. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::Manager::ComputeNonPagedPoolSize(OUT PPFN_NUMBER PoolSize) +{ + ULONG_PTR NonPagedPoolSize; + ULONGLONG PhysicalPages; + + /* Get number of physical pages */ + PhysicalPages = MM::Pfn::GetNumberOfPhysicalPages(); + + /* Verify if system has less than 256MiB of physical memory */ + if(PhysicalPages <= 65536) + { + /* Reduce initial non-paged pool size to 2MiB to save memory */ + NonPagedPoolSize = 2097152; + } + else + { + /* Start with 256KiB and add 32KiB for each MiB above 4MiB */ + NonPagedPoolSize = 262144 + (((PhysicalPages - 1024) / 256) * 32768); + + if(NonPagedPoolSize > 134217728) + { + /* Limit non-paged pool size to 128MiB */ + NonPagedPoolSize = 134217728; + } + } + + /* Return non-paged pool size in pages, aligned down to page size boundary */ + *PoolSize = SIZE_TO_PAGES(ROUND_DOWN(NonPagedPoolSize, MM_PAGE_SIZE)); +} + +/** + * Calculates the size of the paged pool. + * + * @param PoolSize + * A pointer to a variable that will receive the number of pages available for the paged pool. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::Manager::ComputePagedPoolSize(OUT PPFN_NUMBER PoolSize) +{ + ULONG_PTR PagedPoolSize, PteCount; + ULONG PtesPerPage; + + /* Start with maximum non-paged pool size */ + ComputeMaximumNonPagedPoolSize(&PagedPoolSize); + PagedPoolSize *= MM_PAGE_SIZE; + + /* Check XPA status */ + if(MM::Paging::GetXpaStatus()) + { + /* Four times the non-paged pool size on PAE-enabled systems */ + PagedPoolSize *= 4; + } + else + { + /* Double the non-paged pool size on PAE-disabled systems */ + PagedPoolSize *= 2; + } + + /* Check if paged pool does not overlap non-paged pool */ + if(PagedPoolSize > (ULONG_PTR)MemoryLayout.NonPagedSystemPoolStart - (ULONG_PTR)MemoryLayout.PagedPoolStart) + { + /* Limit paged pool size to maximum possible */ + PagedPoolSize = (ULONG_PTR)MemoryLayout.NonPagedSystemPoolStart - (ULONG_PTR)MemoryLayout.PagedPoolStart; + } + + /* Ensure that paged pool size is at least 32MiB */ + if(PagedPoolSize < 33554432) + { + /* Increase paged pool size to at least 32MiB */ + PagedPoolSize = 33554432; + } + + /* Get the number of PTEs per page and calculate size of paged pool */ + PtesPerPage = MM::Pte::GetPtesPerPage(); + PteCount = ((SIZE_TO_PAGES(PagedPoolSize) + (PtesPerPage - 1)) / PtesPerPage); + + /* Return paged pool size */ + *PoolSize = (PFN_NUMBER)(PteCount * PtesPerPage); +} + +/** + * Calculates the size of the session space. + * + * @param SpaceSize + * A pointer to a variable that will receive the number of pages available by the session space. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::Manager::ComputeSessionSpaceSize(OUT PPFN_NUMBER SpaceSize) +{ + PFN_NUMBER SessionSpaceSize; + + /* Session Pool, Session View, Session Image, Session Working Set and System View takes 108MiB */ + SessionSpaceSize = 113246208; + + /* Return number of pages used by the session space */ + *SpaceSize = SessionSpaceSize / MM_PAGE_SIZE; +} + +/** + * Calculates the size of the system PTEs. + * + * @param PteSize + * A pointer to a variable that will receive the number of system PTEs. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::Manager::ComputeSystemPteSize(OUT PPFN_NUMBER PteSize) +{ + PFN_NUMBER SystemPteSize; + + /* Check if system has less than 19MiB of physical memory */ + if(MM::Pfn::GetNumberOfPhysicalPages() < 4864) + { + /* Set minimal system PTE size */ + SystemPteSize = 7000; + } + else + { + /* Use standard system PTE size */ + SystemPteSize = 11000; + + /* Check if system has more than 32MiB of physical memory */ + if(MM::Pfn::GetNumberOfPhysicalPages() > 8192) + { + /* Double system PTE size */ + SystemPteSize *= 2; + + /* Check if system has more than 256MiB of physical memory */ + if(MM::Pfn::GetNumberOfPhysicalPages() > 65536) + { + /* Double system PTE size */ + SystemPteSize *= 2; + } + } + } + + /* Return system PTE size */ + *PteSize = SystemPteSize; +} + +/** + * Dumps the kernel's memory layout. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::Manager::DumpMemoryLayout(VOID) +{ + /* Dump memory layout */ + DebugPrint(L"System with %zu MiB of installed memory:\n" + L"User Space: %.8P - %.8P\n" + L"Loader Mappings: %.8P - %.8P\n" + L"PFN Database: %.8P - %.8P\n" + L"Non-Paged Pool: %.8P - %.8P\n" + L"Session Space: %.8P - %.8P\n" + L"PTE Space: %.8P - %.8P\n" + L"Hyper Space: %.8P - %.8P\n" + L"System Working Set: %.8P - %.8P\n" + L"System Cache: %.8P - %.8P\n" + L"Paged Pool: %.8P - %.8P\n" + L"Non-Paged System Pool: %.8P - %.8P\n" + L"Non-Paged Expansion Pool: %.8P - %.8P\n" + L"Shared System Page: %.8P - %.8P\n" + L"Hardware Pool: %.8P - %.8P\n", + GetInstalledMemorySize(), + MemoryLayout.UserSpaceStart, + MemoryLayout.UserSpaceEnd, + MemoryLayout.LoaderMappingsStart, + MemoryLayout.LoaderMappingsEnd, + MemoryLayout.PfnDatabase, + (PVOID)((ULONG_PTR)MemoryLayout.PfnDatabase + (ULONG_PTR)MemoryLayout.PfnDatabaseSize * MM_PAGE_SIZE), + MemoryLayout.NonPagedPoolStart, + MemoryLayout.NonPagedPoolEnd, + MemoryLayout.SessionSpaceStart, + MemoryLayout.SessionSpaceEnd, + MemoryLayout.PteSpaceStart, + MemoryLayout.PteSpaceEnd, + MemoryLayout.HyperSpaceStart, + MemoryLayout.HyperSpaceEnd, + MemoryLayout.SystemWorkingSetStart, + MemoryLayout.SystemWorkingSetEnd, + MemoryLayout.SystemCacheStart, + MemoryLayout.SystemCacheEnd, + MemoryLayout.PagedPoolStart, + MemoryLayout.PagedPoolEnd, + MemoryLayout.NonPagedSystemPoolStart, + MemoryLayout.NonPagedSystemPoolEnd, + MemoryLayout.NonPagedExpansionPoolStart, + MemoryLayout.NonPagedExpansionPoolEnd, + MemoryLayout.SharedSystemPageStart, + MemoryLayout.SharedSystemPageEnd, + MemoryLayout.HardwarePoolStart, + MemoryLayout.HardwarePoolEnd); +} + /** * Initializes the kernel's virtual memory layout. * @@ -20,69 +297,153 @@ XTAPI VOID MM::Manager::InitializeMemoryLayout(VOID) { - ULONG_PTR PagedPoolSize, PteCount; - PFN_NUMBER PhysicalPages; - ULONG PtesPerPage; - - /* Define the number of system PTEs */ - NumberOfSystemPtes = MM_DEFAULT_NUMBER_SYSTEM_PTES; - - /* Retrieve the number of physical pages */ - PhysicalPages = MM::Pfn::GetNumberOfPhysicalPages(); - - /* Verify the number of physical pages */ - if(PhysicalPages < 8192) - { - /* Less than 32MiB of physical memory (8192 pages), use the minimum number of system PTEs */ - NumberOfSystemPtes = MM_MINIMUM_NUMBER_SYSTEM_PTES; - } - else if(PhysicalPages > 32768) - { - /* More than 128MiB of physical memory (32768 pages), use the maximum number of system PTEs */ - NumberOfSystemPtes = MM_MAXIMUM_NUMBER_SYSTEM_PTES; - } - - /* Calculate size of paged pool */ - PtesPerPage = MM::Pte::GetPtesPerPage(); - PteCount = (SIZE_TO_PAGES(33554432) + (PtesPerPage - 1)) / PtesPerPage; - PagedPoolSize = PteCount * PtesPerPage * MM_PAGE_SIZE; - - /* Retrieve the PFN database size */ - MM::Pfn::ComputePfnDatabaseSize(&MemoryLayout.PfnDatabaseSize); + PFN_NUMBER MaximumNonPagedPoolSize; + ULONG_PTR PfnDatabaseEnd; /* Check if 3-level paging (PAE) is enabled */ if(MM::Paging::GetXpaStatus()) { - /* Configure memory layout for 3-level paging, using 36bit address space and providing a 64 GB address space */ - MemoryLayout.PfnDatabase = (PMMPFN)0xB0000000; + /* Set PML3 base address */ MemoryLayout.SelfMapAddress = (PVOID)MM_PTE_BASE; - /* Define the non-paged and paged pool regions */ - MemoryLayout.NonPagedPoolStart = (PVOID)((ULONG_PTR)MemoryLayout.PfnDatabase + MemoryLayout.PfnDatabaseSize * MM_PAGE_SIZE); - MemoryLayout.NonPagedPoolEnd = (PVOID)0xEEFFFFFF; - MemoryLayout.PagedPoolStart = (PVOID)0xE2000000; - MemoryLayout.PagedPoolEnd = (PVOID)(((ULONG_PTR)MemoryLayout.PagedPoolStart + PagedPoolSize) - 1); - - /* Define hyperspace, system PTE space, and the user space limit */ + /* Define memory layout for 3-level paging */ + MemoryLayout.NonCanonicalStart = (PVOID)0x00000000; + MemoryLayout.NonCanonicalEnd = (PVOID)0x00000000; + MemoryLayout.ReservedSystemPoolStart = (PVOID)0x00000000; + MemoryLayout.ReservedSystemPoolEnd = (PVOID)0x00000000; + MemoryLayout.UserSpaceStart = (PVOID)0x00010000; + MemoryLayout.UserSpaceEnd = (PVOID)0x7FFEFFFF; + MemoryLayout.LoaderMappingsStart = (PVOID)0x80000000; + MemoryLayout.LoaderMappingsEnd = (PVOID)0x90000000; + MemoryLayout.NonPagedPoolStart = (PVOID)0x90000000; + MemoryLayout.NonPagedPoolEnd = (PVOID)0xB0000000; + MemoryLayout.SessionSpaceStart = (PVOID)0xB0000000; + MemoryLayout.SessionSpaceEnd = (PVOID)0xC0000000; + MemoryLayout.PteSpaceStart = (PVOID)0xC0000000; + MemoryLayout.PteSpaceEnd = (PVOID)0xC07FFFFF; MemoryLayout.HyperSpaceStart = (PVOID)0xC0800000; MemoryLayout.HyperSpaceEnd = (PVOID)0xC0BFFFFF; - MemoryLayout.UserSpaceEnd = (PVOID)0x7FFEFFFF; + MemoryLayout.SystemWorkingSetStart = (PVOID)0xC0C00000; + MemoryLayout.SystemWorkingSetEnd = (PVOID)0xC0FFFFFF; + MemoryLayout.SystemCacheStart = (PVOID)0xC1000000; + MemoryLayout.SystemCacheEnd = (PVOID)0xE0FFFFFF; + MemoryLayout.PagedPoolStart = (PVOID)0xE1000000; + MemoryLayout.PagedPoolEnd = (PVOID)0xECC00000; + MemoryLayout.NonPagedSystemPoolStart = (PVOID)0xECC00000; + MemoryLayout.NonPagedSystemPoolEnd = (PVOID)0xF7BE0000; + MemoryLayout.NonPagedExpansionPoolStart = (PVOID)0xF7BE0000; + MemoryLayout.NonPagedExpansionPoolEnd = (PVOID)0xFFBFF000; + MemoryLayout.SharedSystemPageStart = (PVOID)0xFFBFF000; + MemoryLayout.SharedSystemPageEnd = (PVOID)0xFFC00000; + MemoryLayout.HardwarePoolStart = (PVOID)0xFFC00000; + MemoryLayout.HardwarePoolEnd = (PVOID)0xFFFFFFFF; } else { - /* Configure memory layout for 2-level paging, using 32bit address space and providing a 4 GB address space */ - MemoryLayout.PfnDatabase = (PMMPFN)0xB0000000; + /* Set PML2 base address */ MemoryLayout.SelfMapAddress = (PVOID)MM_PTE_BASE; - /* Define the non-paged and paged pool regions */ - MemoryLayout.NonPagedPoolStart = (PVOID)((ULONG_PTR)MemoryLayout.PfnDatabase + MemoryLayout.PfnDatabaseSize * MM_PAGE_SIZE); - MemoryLayout.NonPagedPoolEnd = (PVOID)0xFFBE0000; - MemoryLayout.PagedPoolStart = (PVOID)0xE1000000; - MemoryLayout.PagedPoolEnd = (PVOID)(((ULONG_PTR)MemoryLayout.PagedPoolStart + PagedPoolSize) - 1); - - /* Define hyperspace, system PTE space, and the user space limit */ + /* Define memory layout for 2-level paging */ + MemoryLayout.NonCanonicalStart = (PVOID)0x00000000; + MemoryLayout.NonCanonicalEnd = (PVOID)0x00000000; + MemoryLayout.ReservedSystemPoolStart = (PVOID)0x00000000; + MemoryLayout.ReservedSystemPoolEnd = (PVOID)0x00000000; + MemoryLayout.UserSpaceStart = (PVOID)0x00010000; + MemoryLayout.UserSpaceEnd = (PVOID)0x7FFEFFFF; + MemoryLayout.LoaderMappingsStart = (PVOID)0x80000000; + MemoryLayout.LoaderMappingsEnd = (PVOID)0x90000000; + MemoryLayout.NonPagedPoolStart = (PVOID)0x90000000; + MemoryLayout.NonPagedPoolEnd = (PVOID)0xB0000000; + MemoryLayout.SessionSpaceStart = (PVOID)0xB0000000; + MemoryLayout.SessionSpaceEnd = (PVOID)0xC0000000; + MemoryLayout.PteSpaceStart = (PVOID)0xC0000000; + MemoryLayout.PteSpaceEnd = (PVOID)0xC03FFFFF; MemoryLayout.HyperSpaceStart = (PVOID)0xC0400000; MemoryLayout.HyperSpaceEnd = (PVOID)0xC07FFFFF; - MemoryLayout.UserSpaceEnd = (PVOID)0x7FFEFFFF; + MemoryLayout.SystemWorkingSetStart = (PVOID)0xC0C00000; + MemoryLayout.SystemWorkingSetEnd = (PVOID)0xC0FFFFFF; + MemoryLayout.SystemCacheStart = (PVOID)0xC1000000; + MemoryLayout.SystemCacheEnd = (PVOID)0xE0FFFFFF; + MemoryLayout.PagedPoolStart = (PVOID)0xE1000000; + MemoryLayout.PagedPoolEnd = (PVOID)0xECC00000; + MemoryLayout.NonPagedSystemPoolStart = (PVOID)0xECC00000; + MemoryLayout.NonPagedSystemPoolEnd = (PVOID)0xF7BE0000; + MemoryLayout.NonPagedExpansionPoolStart = (PVOID)0xF7BE0000; + MemoryLayout.NonPagedExpansionPoolEnd = (PVOID)0xFFBFF000; + MemoryLayout.SharedSystemPageStart = (PVOID)0xFFBFF000; + MemoryLayout.SharedSystemPageEnd = (PVOID)0xFFC00000; + MemoryLayout.HardwarePoolStart = (PVOID)0xFFC00000; + MemoryLayout.HardwarePoolEnd = (PVOID)0xFFFFFFFF; } + + /* Compute allocation size for the PFN database */ + MM::Pfn::ComputePfnDatabaseSize(&MemoryLayout.PfnDatabaseSize); + + /* Compute boot image size */ + ComputeBootImageSize(&MemoryLayout.LoaderMappingsSize); + + /* Compute session space size */ + ComputeSessionSpaceSize(&MemoryLayout.SessionSpaceSize); + + /* Update loader mappings space end address */ + MemoryLayout.LoaderMappingsEnd = (PVOID)((ULONG_PTR)MemoryLayout.LoaderMappingsStart + + MemoryLayout.LoaderMappingsSize * MM_PAGE_SIZE); + + /* Update session space start address */ + MemoryLayout.SessionSpaceStart = (PVOID)((ULONGLONG)MemoryLayout.SessionSpaceEnd - + MemoryLayout.SessionSpaceSize * MM_PAGE_SIZE); + + /* Compute system PTE size */ + ComputeSystemPteSize(&NumberOfSystemPtes); + + /* Compute non-paged pool size */ + ComputeNonPagedPoolSize(&MemoryLayout.NonPagedPoolSize); + ComputeMaximumNonPagedPoolSize(&MaximumNonPagedPoolSize); + + /* Compute paged pool size */ + ComputePagedPoolSize(&MemoryLayout.PagedPoolSize); + + /* Insert the PFN database right after the loader mappings */ + MemoryLayout.PfnDatabase = (PMMPFN)MemoryLayout.LoaderMappingsEnd; + + /* Compute the PFN database page-aligned end address */ + PfnDatabaseEnd = (ULONG_PTR)MemoryLayout.PfnDatabase + (MemoryLayout.PfnDatabaseSize * MM_PAGE_SIZE); + PfnDatabaseEnd = ROUND_UP(PfnDatabaseEnd, MM_PAGE_SIZE); + + /* Check in non-paged pool fits before session space */ + if(MemoryLayout.NonPagedPoolSize * MM_PAGE_SIZE <= ((ULONG_PTR)MemoryLayout.SessionSpaceStart - PfnDatabaseEnd)) + { + /* Set non-paged pool start and end addresses */ + MemoryLayout.NonPagedPoolStart = (PVOID)PfnDatabaseEnd; + MemoryLayout.NonPagedPoolEnd = (PVOID)(PfnDatabaseEnd + MemoryLayout.NonPagedPoolSize * MM_PAGE_SIZE); + + /* Check if non-paged expansion pool overflows */ + if((ULONG_PTR)MemoryLayout.NonPagedExpansionPoolStart + MaximumNonPagedPoolSize * + MM_PAGE_SIZE >= (ULONG_PTR)MemoryLayout.NonPagedExpansionPoolStart) + { + /* Check if non-paged expansion pool fits */ + if((ULONG_PTR)MemoryLayout.NonPagedExpansionPoolStart + MaximumNonPagedPoolSize * + MM_PAGE_SIZE <= (ULONG_PTR)MemoryLayout.NonPagedExpansionPoolEnd) + { + /* Set non-paged expansion pool end address */ + MemoryLayout.NonPagedExpansionPoolEnd = (PVOID)((ULONG_PTR)MemoryLayout.NonPagedExpansionPoolStart + + MaximumNonPagedPoolSize * MM_PAGE_SIZE); + } + } + + /* Compute non-paged expansion pool size */ + MemoryLayout.NonPagedExpansionPoolSize = ((ULONG_PTR)MemoryLayout.NonPagedExpansionPoolEnd - + (ULONG_PTR)MemoryLayout.NonPagedExpansionPoolStart) / MM_PAGE_SIZE; + } + else + { + /* Unfortunally non-paged pool does not fit before session space. What can we do? */ + } + + /* Update paged pool end address */ + MemoryLayout.PagedPoolEnd = (PVOID)(((ULONG_PTR)MemoryLayout.PagedPoolStart + + MemoryLayout.PagedPoolSize * MM_PAGE_SIZE) - 1); + + /* Dump memory layout */ + DumpMemoryLayout(); } -- 2.52.0 From 825de8b471b080c99d83f81e5b92642e9903421c Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Fri, 30 Jan 2026 17:46:20 +0100 Subject: [PATCH 135/166] Remove redundant PFN database alignment --- xtoskrnl/mm/i686/mmgr.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/xtoskrnl/mm/i686/mmgr.cc b/xtoskrnl/mm/i686/mmgr.cc index 957895c..ff41832 100644 --- a/xtoskrnl/mm/i686/mmgr.cc +++ b/xtoskrnl/mm/i686/mmgr.cc @@ -406,9 +406,8 @@ MM::Manager::InitializeMemoryLayout(VOID) /* Insert the PFN database right after the loader mappings */ MemoryLayout.PfnDatabase = (PMMPFN)MemoryLayout.LoaderMappingsEnd; - /* Compute the PFN database page-aligned end address */ + /* Compute the PFN database end address */ PfnDatabaseEnd = (ULONG_PTR)MemoryLayout.PfnDatabase + (MemoryLayout.PfnDatabaseSize * MM_PAGE_SIZE); - PfnDatabaseEnd = ROUND_UP(PfnDatabaseEnd, MM_PAGE_SIZE); /* Check in non-paged pool fits before session space */ if(MemoryLayout.NonPagedPoolSize * MM_PAGE_SIZE <= ((ULONG_PTR)MemoryLayout.SessionSpaceStart - PfnDatabaseEnd)) -- 2.52.0 From 19f5307be67b2111fd88a5e3491a6ea136b9083a Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Fri, 30 Jan 2026 18:38:54 +0100 Subject: [PATCH 136/166] Handle non-paged pool overflow --- xtoskrnl/mm/i686/mmgr.cc | 58 ++++++++++++++++++++-------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/xtoskrnl/mm/i686/mmgr.cc b/xtoskrnl/mm/i686/mmgr.cc index ff41832..179e303 100644 --- a/xtoskrnl/mm/i686/mmgr.cc +++ b/xtoskrnl/mm/i686/mmgr.cc @@ -396,52 +396,52 @@ MM::Manager::InitializeMemoryLayout(VOID) /* Compute system PTE size */ ComputeSystemPteSize(&NumberOfSystemPtes); - /* Compute non-paged pool size */ + /* Compute the initial and maximum non-paged pool sizes */ ComputeNonPagedPoolSize(&MemoryLayout.NonPagedPoolSize); ComputeMaximumNonPagedPoolSize(&MaximumNonPagedPoolSize); /* Compute paged pool size */ ComputePagedPoolSize(&MemoryLayout.PagedPoolSize); - /* Insert the PFN database right after the loader mappings */ + /* Position the PFN database right after the loader mappings */ MemoryLayout.PfnDatabase = (PMMPFN)MemoryLayout.LoaderMappingsEnd; /* Compute the PFN database end address */ PfnDatabaseEnd = (ULONG_PTR)MemoryLayout.PfnDatabase + (MemoryLayout.PfnDatabaseSize * MM_PAGE_SIZE); - /* Check in non-paged pool fits before session space */ - if(MemoryLayout.NonPagedPoolSize * MM_PAGE_SIZE <= ((ULONG_PTR)MemoryLayout.SessionSpaceStart - PfnDatabaseEnd)) - { - /* Set non-paged pool start and end addresses */ - MemoryLayout.NonPagedPoolStart = (PVOID)PfnDatabaseEnd; - MemoryLayout.NonPagedPoolEnd = (PVOID)(PfnDatabaseEnd + MemoryLayout.NonPagedPoolSize * MM_PAGE_SIZE); + /* Position the initial non-paged pool immediately after the PFN database */ + MemoryLayout.NonPagedPoolStart = (PVOID)PfnDatabaseEnd; - /* Check if non-paged expansion pool overflows */ + /* Check if the calculated non-paged pool size fits in the KVA */ + if((MemoryLayout.NonPagedPoolSize * MM_PAGE_SIZE) > + ((ULONG_PTR)MemoryLayout.SessionSpaceStart - (ULONG_PTR)MemoryLayout.NonPagedPoolStart)) + { + /* Set the final size for the non-paged pool */ + MemoryLayout.NonPagedPoolSize = ((ULONG_PTR)MemoryLayout.NonPagedPoolEnd - + (ULONG_PTR)MemoryLayout.NonPagedPoolStart) / MM_PAGE_SIZE; + } + + /* Set the final non-paged pool end address */ + MemoryLayout.NonPagedPoolEnd = (PVOID)((ULONG_PTR)MemoryLayout.NonPagedPoolStart + + MemoryLayout.NonPagedPoolSize * MM_PAGE_SIZE); + + /* Check if non-paged expansion pool overflows */ + if((ULONG_PTR)MemoryLayout.NonPagedExpansionPoolStart + MaximumNonPagedPoolSize * + MM_PAGE_SIZE >= (ULONG_PTR)MemoryLayout.NonPagedExpansionPoolStart) + { + /* Check if non-paged expansion pool fits */ if((ULONG_PTR)MemoryLayout.NonPagedExpansionPoolStart + MaximumNonPagedPoolSize * - MM_PAGE_SIZE >= (ULONG_PTR)MemoryLayout.NonPagedExpansionPoolStart) + MM_PAGE_SIZE <= (ULONG_PTR)MemoryLayout.NonPagedExpansionPoolEnd) { - /* Check if non-paged expansion pool fits */ - if((ULONG_PTR)MemoryLayout.NonPagedExpansionPoolStart + MaximumNonPagedPoolSize * - MM_PAGE_SIZE <= (ULONG_PTR)MemoryLayout.NonPagedExpansionPoolEnd) - { - /* Set non-paged expansion pool end address */ - MemoryLayout.NonPagedExpansionPoolEnd = (PVOID)((ULONG_PTR)MemoryLayout.NonPagedExpansionPoolStart + - MaximumNonPagedPoolSize * MM_PAGE_SIZE); - } + /* Set new non-paged expansion pool end address */ + MemoryLayout.NonPagedExpansionPoolEnd = (PVOID)((ULONG_PTR)MemoryLayout.NonPagedExpansionPoolStart + + MaximumNonPagedPoolSize * MM_PAGE_SIZE); } - - /* Compute non-paged expansion pool size */ - MemoryLayout.NonPagedExpansionPoolSize = ((ULONG_PTR)MemoryLayout.NonPagedExpansionPoolEnd - - (ULONG_PTR)MemoryLayout.NonPagedExpansionPoolStart) / MM_PAGE_SIZE; - } - else - { - /* Unfortunally non-paged pool does not fit before session space. What can we do? */ } - /* Update paged pool end address */ - MemoryLayout.PagedPoolEnd = (PVOID)(((ULONG_PTR)MemoryLayout.PagedPoolStart + - MemoryLayout.PagedPoolSize * MM_PAGE_SIZE) - 1); + /* Compute non-paged expansion pool size */ + MemoryLayout.NonPagedExpansionPoolSize = ((ULONG_PTR)MemoryLayout.NonPagedExpansionPoolEnd - + (ULONG_PTR)MemoryLayout.NonPagedExpansionPoolStart) / MM_PAGE_SIZE; /* Dump memory layout */ DumpMemoryLayout(); -- 2.52.0 From b16dbb19f861ffa9d218ec163fdc4d0aac88d496 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Fri, 30 Jan 2026 18:47:46 +0100 Subject: [PATCH 137/166] Centralize memory layout dumping --- xtoskrnl/mm/amd64/mmgr.cc | 3 --- xtoskrnl/mm/i686/mmgr.cc | 3 --- xtoskrnl/mm/mmgr.cc | 3 ++- 3 files changed, 2 insertions(+), 7 deletions(-) diff --git a/xtoskrnl/mm/amd64/mmgr.cc b/xtoskrnl/mm/amd64/mmgr.cc index 72adf3a..8219f1b 100644 --- a/xtoskrnl/mm/amd64/mmgr.cc +++ b/xtoskrnl/mm/amd64/mmgr.cc @@ -387,7 +387,4 @@ MM::Manager::InitializeMemoryLayout(VOID) /* Update paged pool end address */ MemoryLayout.PagedPoolEnd = (PVOID)(((ULONGLONG)MemoryLayout.PagedPoolStart + MemoryLayout.PagedPoolSize * MM_PAGE_SIZE) - 1); - - /* Dump memory layout */ - DumpMemoryLayout(); } diff --git a/xtoskrnl/mm/i686/mmgr.cc b/xtoskrnl/mm/i686/mmgr.cc index 179e303..1a65d53 100644 --- a/xtoskrnl/mm/i686/mmgr.cc +++ b/xtoskrnl/mm/i686/mmgr.cc @@ -442,7 +442,4 @@ MM::Manager::InitializeMemoryLayout(VOID) /* Compute non-paged expansion pool size */ MemoryLayout.NonPagedExpansionPoolSize = ((ULONG_PTR)MemoryLayout.NonPagedExpansionPoolEnd - (ULONG_PTR)MemoryLayout.NonPagedExpansionPoolStart) / MM_PAGE_SIZE; - - /* Dump memory layout */ - DumpMemoryLayout(); } diff --git a/xtoskrnl/mm/mmgr.cc b/xtoskrnl/mm/mmgr.cc index 4860069..fc8e633 100644 --- a/xtoskrnl/mm/mmgr.cc +++ b/xtoskrnl/mm/mmgr.cc @@ -112,8 +112,9 @@ MM::Manager::InitializeMemoryManager(VOID) /* Compute page colors to reduce CPU cache conflicts */ MM::Colors::ComputePageColoring(); - /* Initialize memory layout */ + /* Initialize and dump memory layout */ InitializeMemoryLayout(); + DumpMemoryLayout(); /* Initialize PTE template */ MM::Pte::InitializeSystemPte(); -- 2.52.0 From ba4ac6cec811255562acf565600ef2804e6a7195 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Sun, 1 Feb 2026 10:18:13 +0100 Subject: [PATCH 138/166] Fix PFN truncation on i686 with PAE enabled --- boot/xtldr/arch/i686/memory.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boot/xtldr/arch/i686/memory.cc b/boot/xtldr/arch/i686/memory.cc index a6c65da..877a8ac 100644 --- a/boot/xtldr/arch/i686/memory.cc +++ b/boot/xtldr/arch/i686/memory.cc @@ -317,7 +317,7 @@ Memory::MapPage(IN PXTBL_PAGE_MAPPING PageMap, IN ULONGLONG PhysicalAddress, IN ULONGLONG NumberOfPages) { - SIZE_T PageFrameNumber; + ULONGLONG PageFrameNumber; PVOID Pml1, Pml2, Pml3; SIZE_T Pml1Entry, Pml2Entry, Pml3Entry; PHARDWARE_LEGACY_PTE LegacyPmlTable; -- 2.52.0 From 7f0341bb8333f100d987037bdee0a71a8ac1a3ca Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Sun, 1 Feb 2026 11:11:59 +0100 Subject: [PATCH 139/166] Fix physical address limit checks --- boot/xtldr/memory.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/boot/xtldr/memory.cc b/boot/xtldr/memory.cc index 792330b..7a765b0 100644 --- a/boot/xtldr/memory.cc +++ b/boot/xtldr/memory.cc @@ -376,14 +376,14 @@ Memory::MapEfiMemory(IN OUT PXTBL_PAGE_MAPPING PageMap, else if(PageMap->PageMapLevel == 3) { /* Limit physical address to 64GB in PAE mode */ - MaxAddress = 0xFFFFFFFFF; + MaxAddress = 0xFFFFFFFFFULL; } /* Check page map level */ if(PageMap->PageMapLevel == 2 || PageMap->PageMapLevel == 3) { /* Check if physical address starts beyond limit */ - if(Descriptor->PhysicalStart > MaxAddress) + if(Descriptor->PhysicalStart >= MaxAddress) { /* Go to the next descriptor */ Descriptor = (PEFI_MEMORY_DESCRIPTOR)((PUCHAR)Descriptor + MemoryMap->DescriptorSize); @@ -394,7 +394,7 @@ Memory::MapEfiMemory(IN OUT PXTBL_PAGE_MAPPING PageMap, if(Descriptor->PhysicalStart + (Descriptor->NumberOfPages << EFI_PAGE_SHIFT) > MaxAddress) { /* Truncate memory descriptor to the lowest supported physical page */ - Descriptor->NumberOfPages = (((ULONGLONG)MaxAddress) - Descriptor->PhysicalStart) >> EFI_PAGE_SHIFT; + Descriptor->NumberOfPages = (MaxAddress - Descriptor->PhysicalStart) >> EFI_PAGE_SHIFT; } } -- 2.52.0 From 3d7f51237735a1020cc9689ac8262865da099a1e Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Sun, 1 Feb 2026 16:02:27 +0100 Subject: [PATCH 140/166] Use 64-bit format specifiers for memory mapping logs --- boot/xtldr/arch/i686/memory.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/boot/xtldr/arch/i686/memory.cc b/boot/xtldr/arch/i686/memory.cc index 877a8ac..cc9cdeb 100644 --- a/boot/xtldr/arch/i686/memory.cc +++ b/boot/xtldr/arch/i686/memory.cc @@ -157,8 +157,9 @@ Memory::BuildPageMap(IN PXTBL_PAGE_MAPPING PageMap, if(Mapping->VirtualAddress) { /* Dump memory mapping */ - Debug::Print(L" Type=%02lu, PhysicalBase=%.8P, VirtualBase=%.8P, Pages=%llu\n", Mapping->MemoryType, - Mapping->PhysicalAddress, Mapping->VirtualAddress, Mapping->NumberOfPages); + Debug::Print(L" Type=%02lu, PhysicalBase=0x%.8llX, VirtualBase=0x%.8llX, Pages=%llu\n", + Mapping->MemoryType, Mapping->PhysicalAddress, + Mapping->VirtualAddress, Mapping->NumberOfPages); /* Map memory */ Status = MapPage(PageMap, (UINT_PTR)Mapping->VirtualAddress, -- 2.52.0 From eb0957dbd4aaece2e6a078584143c67f67d58f86 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Mon, 2 Feb 2026 19:06:14 +0100 Subject: [PATCH 141/166] Refactor PFN initialization to ensure proper page table setup --- xtoskrnl/mm/amd64/pfn.cc | 49 +++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 26 deletions(-) diff --git a/xtoskrnl/mm/amd64/pfn.cc b/xtoskrnl/mm/amd64/pfn.cc index 03f0183..dd00670 100644 --- a/xtoskrnl/mm/amd64/pfn.cc +++ b/xtoskrnl/mm/amd64/pfn.cc @@ -24,7 +24,6 @@ MM::Pfn::InitializePfnDatabase(VOID) PKERNEL_INITIALIZATION_BLOCK InitializationBlock; PLIST_ENTRY ListEntry; PLOADER_MEMORY_DESCRIPTOR Descriptor; - PFN_NUMBER BasePage, PageCount; PUCHAR PfnDatabaseEnd; PMMMEMORY_LAYOUT MemoryLayout; PMMPTE ValidPte; @@ -67,43 +66,41 @@ MM::Pfn::InitializePfnDatabase(VOID) continue; } - /* Determine the physical page range to process */ + /* Check if this is the modified free descriptor */ if(Descriptor == FreeDescriptor) { - BasePage = OriginalFreeDescriptor.BasePage; - PageCount = OriginalFreeDescriptor.PageCount; + /* Switch to the original descriptor */ + Descriptor = &OriginalFreeDescriptor; } - else + + /* Map PFN database entries for this range */ + MM::Pte::MapPTE(&((PMMPFN)MemoryLayout->PfnDatabase)[Descriptor->BasePage], + (PUCHAR)&((PMMPFN)MemoryLayout->PfnDatabase)[Descriptor->BasePage + Descriptor->PageCount] - 1, + ValidPte); + + /* Check if the free memory block that was split is being processed */ + if(Descriptor == &OriginalFreeDescriptor) { - BasePage = Descriptor->BasePage; - PageCount = Descriptor->PageCount; + /* Skip loop processing, free memory is initialized separately */ + ListEntry = ListEntry->Flink; + continue; } /* Map PFN database entries for this physical range */ - MM::Pte::MapPTE(&((PMMPFN)MemoryLayout->PfnDatabase)[BasePage], - (PUCHAR)&((PMMPFN)MemoryLayout->PfnDatabase)[BasePage + PageCount] - 1, - ValidPte); - - /* Split PFN database allocation out of the free descriptor */ - if(Descriptor == FreeDescriptor) - { - /* Initialize PFNs for the remaining free memory */ - ProcessMemoryDescriptor(BasePage + MemoryLayout->PfnDatabaseSize, - PageCount - MemoryLayout->PfnDatabaseSize, LoaderFree); - - /* Initialize PFNs for the physical pages backing the PFN database */ - ProcessMemoryDescriptor(BasePage, MemoryLayout->PfnDatabaseSize, LoaderMemoryData); - } - else - { - /* Initialize PFNs for this memory range */ - ProcessMemoryDescriptor(BasePage, PageCount, Descriptor->MemoryType); - } + ProcessMemoryDescriptor(Descriptor->BasePage, Descriptor->PageCount, Descriptor->MemoryType); /* Move to the next descriptor */ ListEntry = ListEntry->Flink; } + /* Initialize PFNs for the free memory */ + ProcessMemoryDescriptor(FreeDescriptor->BasePage, FreeDescriptor->PageCount, LoaderFree); + + /* Initialize PFNs for the physical pages backing the PFN database */ + ProcessMemoryDescriptor(OriginalFreeDescriptor.BasePage, + FreeDescriptor->BasePage - OriginalFreeDescriptor.BasePage, + LoaderMemoryData); + /* Restore original free descriptor */ *FreeDescriptor = OriginalFreeDescriptor; -- 2.52.0 From fae72f53263e7cb76b76a6ba0d3951556410882a Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Tue, 3 Feb 2026 20:17:28 +0100 Subject: [PATCH 142/166] Fix missing assignment of PointerPte --- xtoskrnl/mm/kpool.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xtoskrnl/mm/kpool.cc b/xtoskrnl/mm/kpool.cc index 1e68a17..b026dc9 100644 --- a/xtoskrnl/mm/kpool.cc +++ b/xtoskrnl/mm/kpool.cc @@ -160,7 +160,7 @@ MM::KernelPool::FreeKernelStack(IN PVOID Stack, ULONG Index; /* Get the PTE for the top of the stack, including the guard page */ - MM::Paging::AdvancePte(MM::Paging::GetPteAddress(Stack), -1); + PointerPte = MM::Paging::AdvancePte(MM::Paging::GetPteAddress(Stack), -1); /* Convert the stack size into a page count */ StackPages = SIZE_TO_PAGES(StackSize); -- 2.52.0 From 7b6e284d394a2ba9f3e315abe116315aea9fa44e Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Tue, 3 Feb 2026 22:28:17 +0100 Subject: [PATCH 143/166] Refactor PFN database initialization loop on i686 --- xtoskrnl/mm/i686/pfn.cc | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/xtoskrnl/mm/i686/pfn.cc b/xtoskrnl/mm/i686/pfn.cc index a939809..e34db8a 100644 --- a/xtoskrnl/mm/i686/pfn.cc +++ b/xtoskrnl/mm/i686/pfn.cc @@ -69,27 +69,36 @@ MM::Pfn::InitializePfnDatabase(VOID) continue; } - /* Split PFN DB allocation out of free descriptor */ + /* Check if this is the modified free descriptor */ if(Descriptor == FreeDescriptor) { - /* Initialize PFNs for the remaining free memory after the PFN database */ - ProcessMemoryDescriptor(OriginalFreeDescriptor.BasePage + MemoryLayout->PfnDatabaseSize, - OriginalFreeDescriptor.PageCount - MemoryLayout->PfnDatabaseSize, - LoaderFree); + /* Switch to the original descriptor */ + Descriptor = &OriginalFreeDescriptor; + } - /* Initialize PFNs for the physical pages backing the PFN database itself */ - ProcessMemoryDescriptor(OriginalFreeDescriptor.BasePage, MemoryLayout->PfnDatabaseSize, LoaderMemoryData); - } - else + /* Check if the free memory block that was split is being processed */ + if(Descriptor == &OriginalFreeDescriptor) { - /* Initialize PFNs for the physical pages described by this descriptor */ - ProcessMemoryDescriptor(Descriptor->BasePage, Descriptor->PageCount, Descriptor->MemoryType); + /* Skip loop processing, free memory is initialized separately */ + ListEntry = ListEntry->Flink; + continue; } + /* Initialize PFNs for this memory range */ + ProcessMemoryDescriptor(Descriptor->BasePage, Descriptor->PageCount, Descriptor->MemoryType); + /* Move to the next descriptor */ ListEntry = ListEntry->Flink; } + /* Initialize PFNs for the free memory */ + ProcessMemoryDescriptor(FreeDescriptor->BasePage, FreeDescriptor->PageCount, LoaderFree); + + /* Initialize PFNs for the physical pages backing the PFN database */ + ProcessMemoryDescriptor(OriginalFreeDescriptor.BasePage, + FreeDescriptor->BasePage - OriginalFreeDescriptor.BasePage, + LoaderMemoryData); + /* Restore original free descriptor */ *FreeDescriptor = OriginalFreeDescriptor; -- 2.52.0 From bc391d6e1eecbd1b6f5a1d974467660cf087f700 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Tue, 3 Feb 2026 22:32:10 +0100 Subject: [PATCH 144/166] Map and zero entire PFN database upfront --- xtoskrnl/mm/amd64/pfn.cc | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/xtoskrnl/mm/amd64/pfn.cc b/xtoskrnl/mm/amd64/pfn.cc index dd00670..96e718a 100644 --- a/xtoskrnl/mm/amd64/pfn.cc +++ b/xtoskrnl/mm/amd64/pfn.cc @@ -47,6 +47,10 @@ MM::Pfn::InitializePfnDatabase(VOID) /* Map the Page Directory and Page Directory Pointer tables for the PFN database */ MM::Pte::MapPPE(MemoryLayout->PfnDatabase, PfnDatabaseEnd, ValidPte); MM::Pte::MapPDE(MemoryLayout->PfnDatabase, PfnDatabaseEnd, ValidPte); + MM::Pte::MapPTE(MemoryLayout->PfnDatabase, PfnDatabaseEnd, ValidPte); + + /* Zero PFN database virtual space */ + RTL::Memory::ZeroMemory(MemoryLayout->PfnDatabase, MemoryLayout->PfnDatabaseSize * MM_PAGE_SIZE); /* Initialize the color tables */ MM::Colors::InitializeColorTables(); @@ -73,11 +77,6 @@ MM::Pfn::InitializePfnDatabase(VOID) Descriptor = &OriginalFreeDescriptor; } - /* Map PFN database entries for this range */ - MM::Pte::MapPTE(&((PMMPFN)MemoryLayout->PfnDatabase)[Descriptor->BasePage], - (PUCHAR)&((PMMPFN)MemoryLayout->PfnDatabase)[Descriptor->BasePage + Descriptor->PageCount] - 1, - ValidPte); - /* Check if the free memory block that was split is being processed */ if(Descriptor == &OriginalFreeDescriptor) { -- 2.52.0 From 9b8417565b0f433e3295152c3432b77a5a4e9a6a Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Wed, 4 Feb 2026 19:19:06 +0100 Subject: [PATCH 145/166] Fix coding style --- boot/xtldr/arch/i686/memory.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/boot/xtldr/arch/i686/memory.cc b/boot/xtldr/arch/i686/memory.cc index cc9cdeb..8250b79 100644 --- a/boot/xtldr/arch/i686/memory.cc +++ b/boot/xtldr/arch/i686/memory.cc @@ -93,8 +93,7 @@ Memory::BuildPageMap(IN PXTBL_PAGE_MAPPING PageMap, } /* Map the trampoline code area */ - Status = MapVirtualMemory(PageMap, MM_TRAMPOLINE_ADDRESS,MM_TRAMPOLINE_ADDRESS, - 1, LoaderFirmwareTemporary); + Status = MapVirtualMemory(PageMap, MM_TRAMPOLINE_ADDRESS, MM_TRAMPOLINE_ADDRESS, 1, LoaderFirmwareTemporary); if(Status != STATUS_EFI_SUCCESS) { /* Mapping trampoline code failed */ -- 2.52.0 From 0590ad3bcd31ebcdf110306ce0cc5e6662daa234 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Wed, 4 Feb 2026 19:21:23 +0100 Subject: [PATCH 146/166] Remove explicit identity mapping for internal page tables --- boot/xtldr/arch/amd64/memory.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/boot/xtldr/arch/amd64/memory.cc b/boot/xtldr/arch/amd64/memory.cc index ebe6f0b..8f3659a 100644 --- a/boot/xtldr/arch/amd64/memory.cc +++ b/boot/xtldr/arch/amd64/memory.cc @@ -45,7 +45,7 @@ Memory::BuildPageMap(IN PXTBL_PAGE_MAPPING PageMap, } /* Add new memory mapping for the page map itself */ - Status = MapVirtualMemory(PageMap, Address, Address, 1, LoaderMemoryData); + Status = MapVirtualMemory(PageMap, (ULONGLONG)NULLPTR, Address, 1, LoaderMemoryData); if(Status != STATUS_EFI_SUCCESS) { /* Memory mapping failure */ @@ -201,7 +201,7 @@ Memory::GetNextPageTable(IN PXTBL_PAGE_MAPPING PageMap, } /* Add new memory mapping */ - Status = MapVirtualMemory(PageMap, Address, Address, 1, LoaderMemoryData); + Status = MapVirtualMemory(PageMap, (ULONGLONG)NULLPTR, Address, 1, LoaderMemoryData); if(Status != STATUS_EFI_SUCCESS) { /* Memory mapping failure */ -- 2.52.0 From b51f21f55c5760980aa601106b2275404a6062ae Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Fri, 6 Feb 2026 00:20:01 +0100 Subject: [PATCH 147/166] Introduce page directory initialization helper --- xtoskrnl/includes/mm/pfn.hh | 2 + xtoskrnl/mm/amd64/pfn.cc | 96 +++++++++++++++++++++++++++++++++++++ xtoskrnl/mm/i686/pfn.cc | 21 ++++++++ 3 files changed, 119 insertions(+) diff --git a/xtoskrnl/includes/mm/pfn.hh b/xtoskrnl/includes/mm/pfn.hh index 65996f7..3d61091 100644 --- a/xtoskrnl/includes/mm/pfn.hh +++ b/xtoskrnl/includes/mm/pfn.hh @@ -57,6 +57,8 @@ namespace MM private: STATIC XTAPI VOID DecrementAvailablePages(VOID); STATIC XTAPI VOID IncrementAvailablePages(VOID); + STATIC XTAPI VOID InitializePageDirectory(IN PMMPDE StartingPde, + IN PMMPDE EndingPde); STATIC XTAPI VOID InitializePageTablePfns(VOID); STATIC XTAPI VOID LinkFreePage(IN PFN_NUMBER PageFrameIndex); STATIC XTAPI VOID LinkPage(IN PMMPFNLIST ListHead, diff --git a/xtoskrnl/mm/amd64/pfn.cc b/xtoskrnl/mm/amd64/pfn.cc index 96e718a..3dcc017 100644 --- a/xtoskrnl/mm/amd64/pfn.cc +++ b/xtoskrnl/mm/amd64/pfn.cc @@ -10,6 +10,102 @@ #include +/** + * Allocates and initializes page directory structures for a range of PDEs. + * + * @param StartingPde + * Supplies a pointer to the first PDE in the range to initialize + * + * @param EndingPde + * Supplies a pointer to the last PDE in the range to initialize + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::Pfn::InitializePageDirectory(IN PMMPDE StartingPde, + IN PMMPDE EndingPde) +{ + PMMPTE ParentPte, ValidPte; + BOOLEAN PteValidated; + + /* Get a template PTE for mapping the PFN database pages */ + ValidPte = MM::Pte::GetValidPte(); + + /* Initialize validation flag */ + PteValidated = FALSE; + + /* Iterate through the range of PDEs to ensure the paging hierarchy is fully mapped */ + while(StartingPde <= EndingPde) + { + /* Check if there is a need to validate upper-level page table entries */ + if(!PteValidated || ((ULONG_PTR)StartingPde & (MM_PAGE_SIZE - 1)) == 0) + { + /* For LA57, ensure PML5 entry exists */ + if(MM::Paging::GetXpaStatus()) + { + /* Get the P5E that maps the PXE page containing this hierarchy */ + ParentPte = MM::Paging::GetPpeAddress(StartingPde); + + /* Check if P5E entry is valid */ + if(!MM::Paging::PteValid(ParentPte)) + { + /* Allocate a new PML4 page and map P5E to it */ + MM::Paging::SetPte(ValidPte, AllocateBootstrapPages(1), 0); + *ParentPte = *ValidPte; + + /* Clear the newly created page */ + RTL::Memory::ZeroMemory(MM::Paging::GetPteVirtualAddress(ParentPte), MM_PAGE_SIZE); + } + } + + /* Get the PXE that maps the PPE page containing PDE */ + ParentPte = MM::Paging::GetPdeAddress(StartingPde); + + /* Check if PXE entry is valid */ + if(!MM::Paging::PteValid(ParentPte)) + { + /* Allocate a new PPE page and map PXE to it */ + MM::Paging::SetPte(ValidPte, AllocateBootstrapPages(1), 0); + *ParentPte = *ValidPte; + + /* Clear the newly created page */ + RTL::Memory::ZeroMemory(MM::Paging::GetPteVirtualAddress(ParentPte), MM_PAGE_SIZE); + } + + /* Get the PPE that maps the PDE page containing PTE */ + ParentPte = MM::Paging::GetPteAddress(StartingPde); + + /* Check if PPE entry is valid */ + if(!MM::Paging::PteValid(ParentPte)) + { + /* Allocate a new PDE page and map PPE to it */ + MM::Paging::SetPte(ValidPte, AllocateBootstrapPages(1), 0); + *ParentPte = *ValidPte; + + /* Clear the newly created page */ + RTL::Memory::ZeroMemory(MM::Paging::GetPteVirtualAddress(ParentPte), MM_PAGE_SIZE); + } + + /* Upper levels for this PDE have been validated */ + PteValidated = TRUE; + } + + /* Ensure the PDE has a PTE page allocated */ + if(!MM::Paging::PteValid(StartingPde)) + { + /* Allocate a new PTE page and map PDE to it */ + MM::Paging::SetPte(ValidPte, AllocateBootstrapPages(1), 0); + *StartingPde = *ValidPte; + } + + /* Move to the next PDE */ + StartingPde = MM::Paging::GetNextPte(StartingPde); + } +} + /** * Initializes the PFN database by mapping virtual memory and populating entries. * diff --git a/xtoskrnl/mm/i686/pfn.cc b/xtoskrnl/mm/i686/pfn.cc index e34db8a..53e3f0a 100644 --- a/xtoskrnl/mm/i686/pfn.cc +++ b/xtoskrnl/mm/i686/pfn.cc @@ -10,6 +10,27 @@ #include +/** + * Allocates and initializes page directory structures for a range of PDEs. + * + * @param StartingPde + * Supplies a pointer to the first PDE in the range to initialize + * + * @param EndingPde + * Supplies a pointer to the last PDE in the range to initialize + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::Pfn::InitializePageDirectory(IN PMMPDE StartingPde, + IN PMMPDE EndingPde) +{ + /* Nothing to do */ +} + /** * Initializes the PFN database by mapping virtual memory and populating entries. * -- 2.52.0 From 0763a9522befcea23ce5f0646171707288e1a936 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Fri, 6 Feb 2026 08:40:24 +0100 Subject: [PATCH 148/166] Ensure paging hierarchy exists before processing memory descriptors --- xtoskrnl/mm/amd64/pfn.cc | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/xtoskrnl/mm/amd64/pfn.cc b/xtoskrnl/mm/amd64/pfn.cc index 3dcc017..87697cc 100644 --- a/xtoskrnl/mm/amd64/pfn.cc +++ b/xtoskrnl/mm/amd64/pfn.cc @@ -282,6 +282,7 @@ MM::Pfn::ProcessMemoryDescriptor(IN PFN_NUMBER BasePage, IN PFN_NUMBER PageCount, IN LOADER_MEMORY_TYPE MemoryType) { + PVOID VirtualRangeStart, VirtualRangeEnd; PFN_NUMBER PageNumber; PMMPDE PointerPde; PMMPFN Pfn; @@ -303,6 +304,10 @@ MM::Pfn::ProcessMemoryDescriptor(IN PFN_NUMBER BasePage, } else { + /* Calculate the virtual address range for this physical memory region */ + VirtualRangeStart = (PVOID)(KSEG0_BASE + (BasePage << MM_PAGE_SHIFT)); + VirtualRangeEnd = (PVOID)(KSEG0_BASE + ((BasePage + PageCount) << MM_PAGE_SHIFT)); + /* Handle all other (non-free) memory types */ switch(MemoryType) { @@ -315,6 +320,12 @@ MM::Pfn::ProcessMemoryDescriptor(IN PFN_NUMBER BasePage, } break; case LoaderXIPRom: + /* Get the page directory entry for the current page */ + PointerPde = MM::Paging::GetPdeAddress(VirtualRangeStart); + + /* Initialize the page directory entries covering this memory range */ + InitializePageDirectory(PointerPde, MM::Paging::GetPdeAddress(VirtualRangeEnd)); + /* This memory range contains Read-Only Memory (ROM) */ for(PageNumber = 0; PageNumber < PageCount; PageNumber++) { @@ -324,11 +335,8 @@ MM::Pfn::ProcessMemoryDescriptor(IN PFN_NUMBER BasePage, /* Ensure that the page is not already in-use */ if(Pfn->u3.e2.ReferenceCount == 0) { - /* Get the page directory entry for the current page */ - PointerPde = MM::Paging::GetPdeAddress((PVOID)(KSEG0_BASE + (BasePage << MM_PAGE_SHIFT))); - /* Initialize the PFN entry to represent a ROM page */ - Pfn->PteAddress = MM::Paging::GetPteAddress((PVOID)(KSEG0_BASE + (BasePage << MM_PAGE_SHIFT))); + Pfn->PteAddress = MM::Paging::GetPteAddress(VirtualRangeStart); Pfn->u1.Flink = 0; Pfn->u2.ShareCount = 0; Pfn->u3.e1.CacheAttribute = PfnCached; @@ -342,6 +350,12 @@ MM::Pfn::ProcessMemoryDescriptor(IN PFN_NUMBER BasePage, } break; default: + /* Get the page directory entry for the current page */ + PointerPde = MM::Paging::GetPdeAddress(VirtualRangeStart); + + /* Initialize the page directory entries covering this memory range */ + InitializePageDirectory(PointerPde, MM::Paging::GetPdeAddress(VirtualRangeEnd)); + /* All other types are considered in-use (ie, by the kernel, ACPI, etc) */ for(PageNumber = 0; PageNumber < PageCount; PageNumber++) { @@ -351,11 +365,8 @@ MM::Pfn::ProcessMemoryDescriptor(IN PFN_NUMBER BasePage, /* Ensure that the page is not already in-use */ if(Pfn->u3.e2.ReferenceCount == 0) { - /* Get the page directory entry for the current page */ - PointerPde = MM::Paging::GetPdeAddress((PVOID)(KSEG0_BASE + (BasePage << MM_PAGE_SHIFT))); - /* Initialize the PFN entry to represent an in-use page and prevent it from being allocated */ - Pfn->PteAddress = MM::Paging::GetPteAddress((PVOID)(KSEG0_BASE + (BasePage << MM_PAGE_SHIFT))); + Pfn->PteAddress = MM::Paging::GetPteAddress(VirtualRangeStart); Pfn->u2.ShareCount++; Pfn->u3.e1.CacheAttribute = PfnCached; Pfn->u3.e1.PageLocation = ActiveAndValid; -- 2.52.0 From a46f30045a05cd96f35a7649451dd5bf217e0e20 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Fri, 6 Feb 2026 08:51:23 +0100 Subject: [PATCH 149/166] Fix stale comment --- xtoskrnl/mm/amd64/pfn.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xtoskrnl/mm/amd64/pfn.cc b/xtoskrnl/mm/amd64/pfn.cc index 87697cc..476edb4 100644 --- a/xtoskrnl/mm/amd64/pfn.cc +++ b/xtoskrnl/mm/amd64/pfn.cc @@ -181,7 +181,7 @@ MM::Pfn::InitializePfnDatabase(VOID) continue; } - /* Map PFN database entries for this physical range */ + /* Initialize PFNs for this memory range */ ProcessMemoryDescriptor(Descriptor->BasePage, Descriptor->PageCount, Descriptor->MemoryType); /* Move to the next descriptor */ -- 2.52.0 From 0ce2741e186f1832edbee93961f518f644777ec8 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Fri, 6 Feb 2026 09:08:59 +0100 Subject: [PATCH 150/166] Deduplicate PFN descriptor processing logic across architectures --- xtoskrnl/mm/amd64/pfn.cc | 119 --------------------------------------- xtoskrnl/mm/i686/pfn.cc | 108 ----------------------------------- xtoskrnl/mm/pfn.cc | 119 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 119 insertions(+), 227 deletions(-) diff --git a/xtoskrnl/mm/amd64/pfn.cc b/xtoskrnl/mm/amd64/pfn.cc index 476edb4..4745580 100644 --- a/xtoskrnl/mm/amd64/pfn.cc +++ b/xtoskrnl/mm/amd64/pfn.cc @@ -260,125 +260,6 @@ MM::Pfn::InitializePageTablePfns(VOID) } } -/** - * Processes a memory descriptor and initializes the corresponding PFN database entries - * - * @param BasePage - * The starting physical page number of the memory run - * - * @param PageCount - * The number of pages in the memory run - * - * @param MemoryType - * The type of memory as reported by the bootloader (e.g., free, ROM, in-use) - * - * @return This routine does not return any value. - * - * @since XT 1.0 - */ -XTAPI -VOID -MM::Pfn::ProcessMemoryDescriptor(IN PFN_NUMBER BasePage, - IN PFN_NUMBER PageCount, - IN LOADER_MEMORY_TYPE MemoryType) -{ - PVOID VirtualRangeStart, VirtualRangeEnd; - PFN_NUMBER PageNumber; - PMMPDE PointerPde; - PMMPFN Pfn; - - /* Check if the memory descriptor describes a free memory region */ - if(MM::Manager::VerifyMemoryTypeFree(MemoryType)) - { - /* Iterate over each page in this free memory run */ - for(PageNumber = 0; PageNumber < PageCount; PageNumber++) - { - /* Get the PFN entry for the current page and ensure it is not referenced */ - Pfn = GetPfnEntry(BasePage + PageNumber); - if(Pfn->u3.e2.ReferenceCount == 0) - { - /* Add the page to the free list to make it available for allocation */ - LinkFreePage(BasePage + PageNumber); - } - } - } - else - { - /* Calculate the virtual address range for this physical memory region */ - VirtualRangeStart = (PVOID)(KSEG0_BASE + (BasePage << MM_PAGE_SHIFT)); - VirtualRangeEnd = (PVOID)(KSEG0_BASE + ((BasePage + PageCount) << MM_PAGE_SHIFT)); - - /* Handle all other (non-free) memory types */ - switch(MemoryType) - { - case LoaderBad: - /* This memory is marked as bad and should not be used */ - for(PageNumber = 0; PageNumber < PageCount; PageNumber++) - { - /* Link the page to the bad pages list */ - LinkPage(&BadPagesList, BasePage + PageNumber); - } - break; - case LoaderXIPRom: - /* Get the page directory entry for the current page */ - PointerPde = MM::Paging::GetPdeAddress(VirtualRangeStart); - - /* Initialize the page directory entries covering this memory range */ - InitializePageDirectory(PointerPde, MM::Paging::GetPdeAddress(VirtualRangeEnd)); - - /* This memory range contains Read-Only Memory (ROM) */ - for(PageNumber = 0; PageNumber < PageCount; PageNumber++) - { - /* Get the PFN entry for the current ROM page */ - Pfn = GetPfnEntry(BasePage + PageNumber); - - /* Ensure that the page is not already in-use */ - if(Pfn->u3.e2.ReferenceCount == 0) - { - /* Initialize the PFN entry to represent a ROM page */ - Pfn->PteAddress = MM::Paging::GetPteAddress(VirtualRangeStart); - Pfn->u1.Flink = 0; - Pfn->u2.ShareCount = 0; - Pfn->u3.e1.CacheAttribute = PfnCached; - Pfn->u3.e1.PageLocation = 0; - Pfn->u3.e1.PrototypePte = 1; - Pfn->u3.e1.Rom = 1; - Pfn->u3.e2.ReferenceCount = 0; - Pfn->u4.InPageError = 0; - Pfn->u4.PteFrame = MM::Paging::GetPageFrameNumber(PointerPde); - } - } - break; - default: - /* Get the page directory entry for the current page */ - PointerPde = MM::Paging::GetPdeAddress(VirtualRangeStart); - - /* Initialize the page directory entries covering this memory range */ - InitializePageDirectory(PointerPde, MM::Paging::GetPdeAddress(VirtualRangeEnd)); - - /* All other types are considered in-use (ie, by the kernel, ACPI, etc) */ - for(PageNumber = 0; PageNumber < PageCount; PageNumber++) - { - /* Get the PFN entry for the current in-use page */ - Pfn = GetPfnEntry(BasePage + PageNumber); - - /* Ensure that the page is not already in-use */ - if(Pfn->u3.e2.ReferenceCount == 0) - { - /* Initialize the PFN entry to represent an in-use page and prevent it from being allocated */ - Pfn->PteAddress = MM::Paging::GetPteAddress(VirtualRangeStart); - Pfn->u2.ShareCount++; - Pfn->u3.e1.CacheAttribute = PfnCached; - Pfn->u3.e1.PageLocation = ActiveAndValid; - Pfn->u3.e2.ReferenceCount = 1; - Pfn->u4.PteFrame = MM::Paging::GetPageFrameNumber(PointerPde); - } - } - break; - } - } -} - /** * Recursively scans a page table to initialize PFN database entries for active pages. * diff --git a/xtoskrnl/mm/i686/pfn.cc b/xtoskrnl/mm/i686/pfn.cc index 53e3f0a..bda0642 100644 --- a/xtoskrnl/mm/i686/pfn.cc +++ b/xtoskrnl/mm/i686/pfn.cc @@ -185,114 +185,6 @@ MM::Pfn::InitializePageTablePfns(VOID) } } -/** - * Processes a memory descriptor and initializes the corresponding PFN database entries - * - * @param BasePage - * The starting physical page number of the memory run - * - * @param PageCount - * The number of pages in the memory run - * - * @param MemoryType - * The type of memory as reported by the bootloader (e.g., free, ROM, in-use) - * - * @return This routine does not return any value. - * - * @since XT 1.0 - */ -XTAPI -VOID -MM::Pfn::ProcessMemoryDescriptor(IN PFN_NUMBER BasePage, - IN PFN_NUMBER PageCount, - IN LOADER_MEMORY_TYPE MemoryType) -{ - PFN_NUMBER PageNumber; - PMMPDE PointerPde; - PMMPFN Pfn; - - /* Check if the memory descriptor describes a free memory region */ - if(MM::Manager::VerifyMemoryTypeFree(MemoryType)) - { - /* Iterate over each page in this free memory run */ - for(PageNumber = 0; PageNumber < PageCount; PageNumber++) - { - /* Get the PFN entry for the current page and ensure it is not referenced */ - Pfn = GetPfnEntry(BasePage + PageNumber); - if(Pfn->u3.e2.ReferenceCount == 0) - { - /* Add the page to the free list to make it available for allocation */ - LinkFreePage(BasePage + PageNumber); - } - } - } - else - { - /* Handle all other (non-free) memory types */ - switch(MemoryType) - { - case LoaderBad: - /* This memory is marked as bad and should not be used */ - for(PageNumber = 0; PageNumber < PageCount; PageNumber++) - { - /* Link the page to the bad pages list */ - LinkPage(&BadPagesList, BasePage + PageNumber); - } - break; - case LoaderXIPRom: - /* This memory range contains Read-Only Memory (ROM) */ - for(PageNumber = 0; PageNumber < PageCount; PageNumber++) - { - /* Get the PFN entry for the current ROM page */ - Pfn = GetPfnEntry(BasePage + PageNumber); - - /* Ensure that the page is not already in-use */ - if(Pfn->u3.e2.ReferenceCount == 0) - { - /* Get the page directory entry for the current page */ - PointerPde = MM::Paging::GetPdeAddress((PVOID)(KSEG0_BASE + (BasePage << MM_PAGE_SHIFT))); - - /* Initialize the PFN entry to represent a ROM page */ - Pfn->PteAddress = MM::Paging::GetPteAddress((PVOID)(KSEG0_BASE + (BasePage << MM_PAGE_SHIFT))); - Pfn->u1.Flink = 0; - Pfn->u2.ShareCount = 0; - Pfn->u3.e1.CacheAttribute = PfnNonCached; - Pfn->u3.e1.PageLocation = 0; - Pfn->u3.e1.PrototypePte = 1; - Pfn->u3.e1.Rom = 1; - Pfn->u3.e2.ReferenceCount = 0; - Pfn->u4.InPageError = 0; - Pfn->u4.PteFrame = MM::Paging::GetPageFrameNumber(PointerPde); - } - } - break; - default: - /* All other types are considered in-use (ie, by the kernel, ACPI, etc) */ - for(PageNumber = 0; PageNumber < PageCount; PageNumber++) - { - /* Get the PFN entry for the current in-use page */ - Pfn = GetPfnEntry(BasePage + PageNumber); - - /* Ensure that the page is not already in-use */ - if(Pfn->u3.e2.ReferenceCount == 0) - { - /* Get the page directory entry for the current page */ - PointerPde = MM::Paging::GetPdeAddress((PVOID)(KSEG0_BASE + (BasePage << MM_PAGE_SHIFT))); - - /* Initialize the PFN entry to represent an in-use page and prevent it from being allocated */ - Pfn->PteAddress = MM::Paging::GetPteAddress((PVOID)(KSEG0_BASE + (BasePage << MM_PAGE_SHIFT))); - Pfn->u2.ShareCount++; - Pfn->u3.e1.CacheAttribute = PfnNonCached; - Pfn->u3.e1.PageLocation = ActiveAndValid; - Pfn->u3.e2.ReferenceCount = 1; - Pfn->u4.PteFrame = MM::Paging::GetPageFrameNumber(PointerPde); - } - } - break; - } - } -} - /** * Recursively scans a page table to initialize PFN database entries for active pages. * diff --git a/xtoskrnl/mm/pfn.cc b/xtoskrnl/mm/pfn.cc index c7de33e..80935db 100644 --- a/xtoskrnl/mm/pfn.cc +++ b/xtoskrnl/mm/pfn.cc @@ -942,6 +942,125 @@ MM::Pfn::LinkStandbyPage(IN PFN_NUMBER PageFrameIndex) IncrementAvailablePages(); } +/** + * Processes a memory descriptor and initializes the corresponding PFN database entries + * + * @param BasePage + * The starting physical page number of the memory run + * + * @param PageCount + * The number of pages in the memory run + * + * @param MemoryType + * The type of memory as reported by the bootloader (e.g., free, ROM, in-use) + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::Pfn::ProcessMemoryDescriptor(IN PFN_NUMBER BasePage, + IN PFN_NUMBER PageCount, + IN LOADER_MEMORY_TYPE MemoryType) +{ + PVOID VirtualRangeStart, VirtualRangeEnd; + PFN_NUMBER PageNumber; + PMMPDE PointerPde; + PMMPFN Pfn; + + /* Check if the memory descriptor describes a free memory region */ + if(MM::Manager::VerifyMemoryTypeFree(MemoryType)) + { + /* Iterate over each page in this free memory run */ + for(PageNumber = 0; PageNumber < PageCount; PageNumber++) + { + /* Get the PFN entry for the current page and ensure it is not referenced */ + Pfn = GetPfnEntry(BasePage + PageNumber); + if(Pfn->u3.e2.ReferenceCount == 0) + { + /* Add the page to the free list to make it available for allocation */ + LinkFreePage(BasePage + PageNumber); + } + } + } + else + { + /* Calculate the virtual address range for this physical memory region */ + VirtualRangeStart = (PVOID)(KSEG0_BASE + (BasePage << MM_PAGE_SHIFT)); + VirtualRangeEnd = (PVOID)(KSEG0_BASE + ((BasePage + PageCount) << MM_PAGE_SHIFT)); + + /* Handle all other (non-free) memory types */ + switch(MemoryType) + { + case LoaderBad: + /* This memory is marked as bad and should not be used */ + for(PageNumber = 0; PageNumber < PageCount; PageNumber++) + { + /* Link the page to the bad pages list */ + LinkPage(&BadPagesList, BasePage + PageNumber); + } + break; + case LoaderXIPRom: + /* Get the page directory entry for the current page */ + PointerPde = MM::Paging::GetPdeAddress(VirtualRangeStart); + + /* Initialize the page directory entries covering this memory range */ + InitializePageDirectory(PointerPde, MM::Paging::GetPdeAddress(VirtualRangeEnd)); + + /* This memory range contains Read-Only Memory (ROM) */ + for(PageNumber = 0; PageNumber < PageCount; PageNumber++) + { + /* Get the PFN entry for the current ROM page */ + Pfn = GetPfnEntry(BasePage + PageNumber); + + /* Ensure that the page is not already in-use */ + if(Pfn->u3.e2.ReferenceCount == 0) + { + /* Initialize the PFN entry to represent a ROM page */ + Pfn->PteAddress = MM::Paging::GetPteAddress(VirtualRangeStart); + Pfn->u1.Flink = 0; + Pfn->u2.ShareCount = 0; + Pfn->u3.e1.CacheAttribute = PfnCached; + Pfn->u3.e1.PageLocation = 0; + Pfn->u3.e1.PrototypePte = 1; + Pfn->u3.e1.Rom = 1; + Pfn->u3.e2.ReferenceCount = 0; + Pfn->u4.InPageError = 0; + Pfn->u4.PteFrame = MM::Paging::GetPageFrameNumber(PointerPde); + } + } + break; + default: + /* Get the page directory entry for the current page */ + PointerPde = MM::Paging::GetPdeAddress(VirtualRangeStart); + + /* Initialize the page directory entries covering this memory range */ + InitializePageDirectory(PointerPde, MM::Paging::GetPdeAddress(VirtualRangeEnd)); + + /* All other types are considered in-use (ie, by the kernel, ACPI, etc) */ + for(PageNumber = 0; PageNumber < PageCount; PageNumber++) + { + /* Get the PFN entry for the current in-use page */ + Pfn = GetPfnEntry(BasePage + PageNumber); + + /* Ensure that the page is not already in-use */ + if(Pfn->u3.e2.ReferenceCount == 0) + { + /* Initialize the PFN entry to represent an in-use page and prevent it from being allocated */ + Pfn->PteAddress = MM::Paging::GetPteAddress(VirtualRangeStart); + Pfn->u2.ShareCount++; + Pfn->u3.e1.CacheAttribute = PfnCached; + Pfn->u3.e1.PageLocation = ActiveAndValid; + Pfn->u3.e2.ReferenceCount = 1; + Pfn->u4.PteFrame = MM::Paging::GetPageFrameNumber(PointerPde); + } + } + break; + } + } +} + /** * Scans memory descriptors provided by the boot loader. * -- 2.52.0 From 2e0e085acb53e8ea5ac663570f2e5ec34bd031ee Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Fri, 6 Feb 2026 20:52:59 +0100 Subject: [PATCH 151/166] Minor style fixes --- xtoskrnl/mm/amd64/pfn.cc | 4 ++-- xtoskrnl/mm/i686/pfn.cc | 4 ++-- xtoskrnl/mm/pfn.cc | 10 +++++----- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/xtoskrnl/mm/amd64/pfn.cc b/xtoskrnl/mm/amd64/pfn.cc index 4745580..91e8d1d 100644 --- a/xtoskrnl/mm/amd64/pfn.cc +++ b/xtoskrnl/mm/amd64/pfn.cc @@ -14,10 +14,10 @@ * Allocates and initializes page directory structures for a range of PDEs. * * @param StartingPde - * Supplies a pointer to the first PDE in the range to initialize + * Supplies a pointer to the first PDE in the range to initialize. * * @param EndingPde - * Supplies a pointer to the last PDE in the range to initialize + * Supplies a pointer to the last PDE in the range to initialize. * * @return This routine does not return any value. * diff --git a/xtoskrnl/mm/i686/pfn.cc b/xtoskrnl/mm/i686/pfn.cc index bda0642..08815d6 100644 --- a/xtoskrnl/mm/i686/pfn.cc +++ b/xtoskrnl/mm/i686/pfn.cc @@ -14,10 +14,10 @@ * Allocates and initializes page directory structures for a range of PDEs. * * @param StartingPde - * Supplies a pointer to the first PDE in the range to initialize + * Supplies a pointer to the first PDE in the range to initialize. * * @param EndingPde - * Supplies a pointer to the last PDE in the range to initialize + * Supplies a pointer to the last PDE in the range to initialize. * * @return This routine does not return any value. * diff --git a/xtoskrnl/mm/pfn.cc b/xtoskrnl/mm/pfn.cc index 80935db..dfbd536 100644 --- a/xtoskrnl/mm/pfn.cc +++ b/xtoskrnl/mm/pfn.cc @@ -684,7 +684,7 @@ MM::Pfn::LinkPage(IN PMMPFNLIST ListHead, PageFrame->u2.Blink = ListHead->Blink; } - /* Record the page’s current location */ + /* Record the page's current location */ PageFrame->u3.e1.PageLocation = ListName; /* Handle pages that contribute to the available page count */ @@ -943,16 +943,16 @@ MM::Pfn::LinkStandbyPage(IN PFN_NUMBER PageFrameIndex) } /** - * Processes a memory descriptor and initializes the corresponding PFN database entries + * Processes a memory descriptor and initializes the corresponding PFN database entries. * * @param BasePage - * The starting physical page number of the memory run + * The starting physical page number of the memory run. * * @param PageCount - * The number of pages in the memory run + * The number of pages in the memory run. * * @param MemoryType - * The type of memory as reported by the bootloader (e.g., free, ROM, in-use) + * The type of memory as reported by the bootloader (e.g., free, ROM, in-use). * * @return This routine does not return any value. * -- 2.52.0 From 80ea0b49d05e91fbfab4cf5905f6a84ae6236351 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Sat, 7 Feb 2026 00:30:41 +0100 Subject: [PATCH 152/166] Fix boot image size alignment calculation --- xtoskrnl/mm/mmgr.cc | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/xtoskrnl/mm/mmgr.cc b/xtoskrnl/mm/mmgr.cc index fc8e633..0823ad4 100644 --- a/xtoskrnl/mm/mmgr.cc +++ b/xtoskrnl/mm/mmgr.cc @@ -26,18 +26,17 @@ MM::Manager::ComputeBootImageSize(OUT PPFN_NUMBER BootImageSize) { PKERNEL_INITIALIZATION_BLOCK InitializationBlock; PFN_NUMBER ImageSize; - ULONG PteSize; + ULONG_PTR Alignment; /* Get the kernel initialization block */ InitializationBlock = KE::BootInformation::GetInitializationBlock(); - /* Get the size of a PTE */ - PteSize = MM::Paging::GetPteSize(); + /* Calculate the alignment based on the PTE size */ + Alignment = ((MM_PAGE_SIZE / MM::Paging::GetPteSize()) * MM_PAGE_SIZE); /* Calculate the size of the boot image */ ImageSize = InitializationBlock->BootImageSize * MM_PAGE_SIZE; - ImageSize = (ImageSize + ((MM_PAGE_SIZE / PteSize) * MM_PAGE_SIZE) - 1) & - ~(((MM_PAGE_SIZE / PteSize) * MM_PAGE_SIZE) - 1); + ImageSize = (ImageSize + Alignment - 1) & ~(Alignment - 1); /* Return number of pages used by the boot image */ *BootImageSize = ImageSize / MM_PAGE_SIZE; -- 2.52.0 From fa645073501dc2a8c0f149a778534ee8f64e2296 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Sat, 7 Feb 2026 00:42:03 +0100 Subject: [PATCH 153/166] Refactor EFI memory mapping to support distinct mapping strategies --- boot/xtldr/includes/xtldr.hh | 3 +- boot/xtldr/memory.cc | 32 ++++++++++++++++------ boot/xtldr/modules/xtos_o/amd64/memory.cc | 15 ++++++++++ boot/xtldr/modules/xtos_o/i686/memory.cc | 15 ++++++++++ boot/xtldr/modules/xtos_o/includes/xtos.hh | 1 + boot/xtldr/modules/xtos_o/xtos.cc | 15 +++++++++- sdk/xtdk/bltypes.h | 2 +- 7 files changed, 71 insertions(+), 12 deletions(-) diff --git a/boot/xtldr/includes/xtldr.hh b/boot/xtldr/includes/xtldr.hh index cb91068..bc42aab 100644 --- a/boot/xtldr/includes/xtldr.hh +++ b/boot/xtldr/includes/xtldr.hh @@ -177,7 +177,8 @@ class Memory IN SHORT PageMapLevel, IN PAGE_SIZE PageSize); STATIC XTCDECL EFI_STATUS MapEfiMemory(IN OUT PXTBL_PAGE_MAPPING PageMap, - IN OUT PVOID *MemoryMapAddress, + IN OUT PVOID *BaseAddress, + IN BOOLEAN IdentityMapping, IN PBL_GET_MEMTYPE_ROUTINE GetMemoryTypeRoutine); STATIC XTCDECL EFI_STATUS MapPage(IN PXTBL_PAGE_MAPPING PageMap, IN ULONGLONG VirtualAddress, diff --git a/boot/xtldr/memory.cc b/boot/xtldr/memory.cc index 7a765b0..f3cc773 100644 --- a/boot/xtldr/memory.cc +++ b/boot/xtldr/memory.cc @@ -314,9 +314,12 @@ Memory::InitializePageMap(OUT PXTBL_PAGE_MAPPING PageMap, * @param PageMap * Supplies a pointer to the page mapping structure. * - * @param MemoryMapAddress + * @param BaseAddress * Supplies a virtual address, where EFI memory will be mapped. * + * @param IdentityMapping + * Specifies whether EFI non-free memory should be mapped by identity or sequential mapping. + * * @param GetMemoryTypeRoutine * Supplies a pointer to the routine which will be used to match EFI memory type to the OS memory type. * @@ -327,7 +330,8 @@ Memory::InitializePageMap(OUT PXTBL_PAGE_MAPPING PageMap, XTCDECL EFI_STATUS Memory::MapEfiMemory(IN OUT PXTBL_PAGE_MAPPING PageMap, - IN OUT PVOID *MemoryMapAddress, + IN OUT PVOID *BaseAddress, + IN BOOLEAN IdentityMapping, IN PBL_GET_MEMTYPE_ROUTINE GetMemoryTypeRoutine) { ULONGLONG MaxAddress, VirtualAddress; @@ -339,7 +343,7 @@ Memory::MapEfiMemory(IN OUT PXTBL_PAGE_MAPPING PageMap, SIZE_T Index; /* Set virtual address as specified in argument */ - VirtualAddress = (ULONGLONG)*MemoryMapAddress; + VirtualAddress = (ULONGLONG)*BaseAddress; /* Check if custom memory type routine is specified */ if(GetMemoryTypeRoutine == NULLPTR) @@ -419,12 +423,22 @@ Memory::MapEfiMemory(IN OUT PXTBL_PAGE_MAPPING PageMap, } else if(MemoryType != LoaderFree) { - /* Add any non-free memory mapping */ - Status = MapVirtualMemory(PageMap, VirtualAddress, Descriptor->PhysicalStart, - Descriptor->NumberOfPages, MemoryType); + /* Check mapping strategy */ + if(IdentityMapping) + { + /* Add any non-free memory using identity mapping */ + Status = MapVirtualMemory(PageMap, Descriptor->PhysicalStart + KSEG0_BASE, Descriptor->PhysicalStart, + Descriptor->NumberOfPages, MemoryType); + } + else + { + /* Add any non-free memory using sequential mapping */ + Status = MapVirtualMemory(PageMap, VirtualAddress, Descriptor->PhysicalStart, + Descriptor->NumberOfPages, MemoryType); - /* Update virtual address */ - VirtualAddress = VirtualAddress + (Descriptor->NumberOfPages * MM_PAGE_SIZE); + /* Update virtual address */ + VirtualAddress = VirtualAddress + (Descriptor->NumberOfPages * MM_PAGE_SIZE); + } } else { @@ -462,7 +476,7 @@ Memory::MapEfiMemory(IN OUT PXTBL_PAGE_MAPPING PageMap, } /* Store next valid virtual address and return success */ - *MemoryMapAddress = (PVOID)VirtualAddress; + *BaseAddress = (PVOID)VirtualAddress; return STATUS_EFI_SUCCESS; } diff --git a/boot/xtldr/modules/xtos_o/amd64/memory.cc b/boot/xtldr/modules/xtos_o/amd64/memory.cc index 02335aa..4ec271c 100644 --- a/boot/xtldr/modules/xtos_o/amd64/memory.cc +++ b/boot/xtldr/modules/xtos_o/amd64/memory.cc @@ -10,6 +10,21 @@ #include +/** + * Determines the appropriate EFI memory mapping strategy for the AMD64 architecture. + * + * @return This routine returns TRUE, what results in an identity mapping. + * + * @since XT 1.0 + */ +XTCDECL +BOOLEAN +Xtos::DetermineMappingStrategy() +{ + /* Use an identity mapping strategy */ + return TRUE; +} + /** * Determines the appropriate paging level (PML) for the AMD64 architecture. * diff --git a/boot/xtldr/modules/xtos_o/i686/memory.cc b/boot/xtldr/modules/xtos_o/i686/memory.cc index 44ee233..e4fbdf3 100644 --- a/boot/xtldr/modules/xtos_o/i686/memory.cc +++ b/boot/xtldr/modules/xtos_o/i686/memory.cc @@ -9,6 +9,21 @@ #include +/** + * Determines the appropriate EFI memory mapping strategy for the i686 architecture. + * + * @return This routine returns FALSE, what results in a sequential mapping. + * + * @since XT 1.0 + */ +XTCDECL +BOOLEAN +Xtos::DetermineMappingStrategy() +{ + /* Use a sequential mapping strategy */ + return FALSE; +} + /** * Determines the appropriate paging level (PML) for the i686 architecture. * diff --git a/boot/xtldr/modules/xtos_o/includes/xtos.hh b/boot/xtldr/modules/xtos_o/includes/xtos.hh index 4d70606..708ce14 100644 --- a/boot/xtldr/modules/xtos_o/includes/xtos.hh +++ b/boot/xtldr/modules/xtos_o/includes/xtos.hh @@ -39,6 +39,7 @@ class Xtos IN UINT NumberOfPages, IN LOADER_MEMORY_TYPE MemoryType); STATIC XTCDECL LOADER_MEMORY_TYPE ConvertEfiMemoryType(IN EFI_MEMORY_TYPE EfiMemoryType); + STATIC XTCDECL BOOLEAN DetermineMappingStrategy(); STATIC XTCDECL ULONG DeterminePagingLevel(IN CONST PWCHAR Parameters); STATIC XTCDECL EFI_STATUS EnablePaging(IN PXTBL_PAGE_MAPPING PageMap); STATIC XTCDECL VOID GetDisplayInformation(OUT PSYSTEM_RESOURCE_FRAMEBUFFER FrameBufferResource, diff --git a/boot/xtldr/modules/xtos_o/xtos.cc b/boot/xtldr/modules/xtos_o/xtos.cc index aabecb9..bf20174 100644 --- a/boot/xtldr/modules/xtos_o/xtos.cc +++ b/boot/xtldr/modules/xtos_o/xtos.cc @@ -618,6 +618,7 @@ Xtos::RunBootSequence(IN PEFI_FILE_HANDLE BootDir, EFI_HANDLE ProtocolHandle; EFI_STATUS Status; XTBL_PAGE_MAPPING PageMap; + BOOLEAN IdentityMapping; /* Initialize XTOS startup sequence */ XtLdrProtocol->Debug.Print(L"Initializing XTOS startup sequence\n"); @@ -634,18 +635,30 @@ Xtos::RunBootSequence(IN PEFI_FILE_HANDLE BootDir, /* Close FrameBuffer protocol */ XtLdrProtocol->Protocol.Close(&ProtocolHandle, &FrameBufGuid); + /* Determine whether to use a sequential or an identity mapping strategy */ + IdentityMapping = DetermineMappingStrategy(); + /* Set base virtual memory area for the kernel mappings */ VirtualAddress = (PVOID)(KSEG0_BASE); /* Initialize virtual memory mappings */ XtLdrProtocol->Memory.InitializePageMap(&PageMap, DeterminePagingLevel(Parameters->Parameters), Size4K); - Status = XtLdrProtocol->Memory.MapEfiMemory(&PageMap, &VirtualAddress, NULLPTR); + /* Map all EFI memory regions */ + Status = XtLdrProtocol->Memory.MapEfiMemory(&PageMap, &VirtualAddress, IdentityMapping, NULLPTR); if(Status != STATUS_EFI_SUCCESS) { + /* Mapping failed */ return Status; } + /* Check mapping strategy */ + if(IdentityMapping) + { + /* Adjust virtual address to skip the identity-mapped physical range */ + VirtualAddress = (PVOID)((ULONGLONG)VirtualAddress + 0x800000000); + } + /* Load the kernel */ Status = LoadModule(BootDir, Parameters->KernelFile, VirtualAddress, LoaderSystemCode, &ImageContext); if(Status != STATUS_EFI_SUCCESS) diff --git a/sdk/xtdk/bltypes.h b/sdk/xtdk/bltypes.h index 1f7f948..3cc2378 100644 --- a/sdk/xtdk/bltypes.h +++ b/sdk/xtdk/bltypes.h @@ -100,7 +100,7 @@ typedef VOID (XTCDECL *PBL_LLIST_INITIALIZE_HEAD)(IN PLIST_ENTRY ListHead); typedef VOID (XTCDECL *PBL_LLIST_INSERT_HEAD)(IN OUT PLIST_ENTRY ListHead, IN PLIST_ENTRY Entry); typedef VOID (XTCDECL *PBL_LLIST_INSERT_TAIL)(IN OUT PLIST_ENTRY ListHead, IN PLIST_ENTRY Entry); typedef VOID (XTCDECL *PBL_LLIST_REMOVE_ENTRY)(IN PLIST_ENTRY Entry); -typedef EFI_STATUS (XTCDECL *PBL_MAP_EFI_MEMORY)(IN OUT PXTBL_PAGE_MAPPING PageMap, IN OUT PVOID *MemoryMapAddress, IN PBL_GET_MEMTYPE_ROUTINE GetMemoryTypeRoutine); +typedef EFI_STATUS (XTCDECL *PBL_MAP_EFI_MEMORY)(IN OUT PXTBL_PAGE_MAPPING PageMap, IN OUT PVOID *BaseAddress, IN BOOLEAN IdentityMapping, IN PBL_GET_MEMTYPE_ROUTINE GetMemoryTypeRoutine); typedef EFI_STATUS (XTCDECL *PBL_MAP_PAGE)(IN PXTBL_PAGE_MAPPING PageMap, IN ULONGLONG VirtualAddress, IN ULONGLONG PhysicalAddress, IN ULONGLONG NumberOfPages); typedef EFI_STATUS (XTCDECL *PBL_MAP_VIRTUAL_MEMORY)(IN OUT PXTBL_PAGE_MAPPING PageMap, IN ULONGLONG VirtualAddress, IN ULONGLONG PhysicalAddress, IN ULONGLONG NumberOfPages, IN LOADER_MEMORY_TYPE MemoryType); typedef VOID (XTAPI *PBL_MOVE_MEMORY)(IN OUT PVOID Destination, IN PCVOID Source, IN SIZE_T Length); -- 2.52.0 From 9a5ef6fc004e0cd7c9ceb0535d05c08671a05e74 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Sat, 7 Feb 2026 20:01:17 +0100 Subject: [PATCH 154/166] Map PDE and PTE ranges for i686 non-paged pool --- xtoskrnl/mm/i686/alloc.cc | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/xtoskrnl/mm/i686/alloc.cc b/xtoskrnl/mm/i686/alloc.cc index 0987553..1189eef 100644 --- a/xtoskrnl/mm/i686/alloc.cc +++ b/xtoskrnl/mm/i686/alloc.cc @@ -13,5 +13,13 @@ XTAPI VOID MM::Allocator::InitializeNonPagedPool(VOID) { + PMMMEMORY_LAYOUT MemoryLayout; UNIMPLEMENTED; + + /* Retrieve memory layout */ + MemoryLayout = MM::Manager::GetMemoryLayout(); + + /* Map PDE and PTE for the base of the non-paged pool */ + MM::Pte::MapPDE(MemoryLayout->NonPagedPoolStart, (PCHAR)MemoryLayout->NonPagedPoolEnd - 1, MM::Pte::GetValidPte()); + MM::Pte::MapPTE(MemoryLayout->NonPagedPoolStart, (PCHAR)MemoryLayout->NonPagedPoolEnd - 1, MM::Pte::GetValidPte()); } -- 2.52.0 From 53f794577189b2c25f8a1e849cc211a9cd18dcb8 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Sat, 7 Feb 2026 20:37:23 +0100 Subject: [PATCH 155/166] Reorder initialization sequence and flush TLB --- xtoskrnl/mm/mmgr.cc | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/xtoskrnl/mm/mmgr.cc b/xtoskrnl/mm/mmgr.cc index 0823ad4..896cb8f 100644 --- a/xtoskrnl/mm/mmgr.cc +++ b/xtoskrnl/mm/mmgr.cc @@ -121,14 +121,17 @@ MM::Manager::InitializeMemoryManager(VOID) /* Initialize page table */ MM::Pte::InitializePageTable(); - /* Initialize non-paged pool */ - MM::Allocator::InitializeNonPagedPool(); - /* Initialize system PTE space */ MM::Pte::InitializeSystemPteSpace(); + /* Initialize non-paged pool */ + MM::Allocator::InitializeNonPagedPool(); + /* Initialize PFN database */ MM::Pfn::InitializePfnDatabase(); + + /* Flush TLB */ + AR::CpuFunc::FlushTlb(); } /** -- 2.52.0 From e2da6220f2c3a6683e19059d3adedb80bf51351a Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Mon, 9 Feb 2026 23:17:58 +0100 Subject: [PATCH 156/166] Fix PFN calculation truncation for memory above 4GB to prevent memory descriptor aliasing on PAE systems --- boot/xtldr/modules/xtos_o/xtos.cc | 38 +++++++++++++++++++++---------- 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/boot/xtldr/modules/xtos_o/xtos.cc b/boot/xtldr/modules/xtos_o/xtos.cc index bf20174..5b2b8a0 100644 --- a/boot/xtldr/modules/xtos_o/xtos.cc +++ b/boot/xtldr/modules/xtos_o/xtos.cc @@ -194,49 +194,63 @@ Xtos::GetMemoryDescriptorList(IN PXTBL_PAGE_MAPPING PageMap, IN PVOID *VirtualAddress, OUT PLIST_ENTRY MemoryDescriptorList) { + PLOADER_MEMORY_DESCRIPTOR Descriptor; + PXTBL_MEMORY_MAPPING MemoryMapping; EFI_PHYSICAL_ADDRESS Address; + PLIST_ENTRY ListEntry; EFI_STATUS Status; ULONGLONG Pages; + /* Calculate the number of pages required to store the memory descriptor array */ Pages = (ULONGLONG)EFI_SIZE_TO_PAGES((PageMap->MapSize + 1) * sizeof(LOADER_MEMORY_DESCRIPTOR)); + /* Allocate physical pages to hold the memory descriptor list */ Status = XtLdrProtocol->Memory.AllocatePages(AllocateAnyPages, Pages, &Address); if(Status != STATUS_EFI_SUCCESS) { + /* Page allocation failed, return the status code */ return Status; } + /* Create a virtual memory mapping for the allocated descriptor buffer */ Status = XtLdrProtocol->Memory.MapVirtualMemory(PageMap, (ULONGLONG)*VirtualAddress, Address, Pages, LoaderMemoryData); if(Status != STATUS_EFI_SUCCESS) { + /* Release the allocated pages as the virtual mapping failed and return status code */ XtLdrProtocol->Memory.FreePages(Address, Pages); return Status; } - PVOID PhysicalBase = (PVOID)Address; + /* Initialize the descriptor pointer to the start of the allocated physical buffer */ + Descriptor = (PLOADER_MEMORY_DESCRIPTOR)Address; - PLIST_ENTRY ListEntry; + /* Get the first entry from the internal boot loader memory map */ ListEntry = PageMap->MemoryMap.Flink; + + /* Iterate through the internal memory map and populate the loader descriptor list */ while(ListEntry != &PageMap->MemoryMap) { - PXTBL_MEMORY_MAPPING MemoryMapping = CONTAIN_RECORD(ListEntry, XTBL_MEMORY_MAPPING, ListEntry); - PLOADER_MEMORY_DESCRIPTOR MemoryDescriptor = (PLOADER_MEMORY_DESCRIPTOR)Address; + /* Retrieve the internal memory mapping record from the current list entry */ + MemoryMapping = CONTAIN_RECORD(ListEntry, XTBL_MEMORY_MAPPING, ListEntry); - MemoryDescriptor->MemoryType = MemoryMapping->MemoryType; - MemoryDescriptor->BasePage = (UINT_PTR)MemoryMapping->PhysicalAddress / EFI_PAGE_SIZE; - MemoryDescriptor->PageCount = MemoryMapping->NumberOfPages; + /* Transfer memory type and address information to the kernel descriptor */ + Descriptor->MemoryType = MemoryMapping->MemoryType; + Descriptor->BasePage = (UINT_PTR)(MemoryMapping->PhysicalAddress / EFI_PAGE_SIZE); + Descriptor->PageCount = (ULONG)MemoryMapping->NumberOfPages; - XtLdrProtocol->LinkedList.InsertTail(MemoryDescriptorList, &MemoryDescriptor->ListEntry); + /* Link the entry */ + XtLdrProtocol->LinkedList.InsertTail(MemoryDescriptorList, &Descriptor->ListEntry); - Address = Address + sizeof(LOADER_MEMORY_DESCRIPTOR); + /* Move to the next slot in the allocated buffer */ + Descriptor++; ListEntry = ListEntry->Flink; } - XtLdrProtocol->Memory.PhysicalListToVirtual(PageMap, MemoryDescriptorList, PhysicalBase, *VirtualAddress); + /* Convert all physical link pointers in the list to their corresponding virtual addresses */ + XtLdrProtocol->Memory.PhysicalListToVirtual(PageMap, MemoryDescriptorList, (PVOID)Address, *VirtualAddress); - /* Calculate next valid virtual address */ + /* Advance the virtual address pointer to the next available free region and return success */ *VirtualAddress = (PUINT8)*VirtualAddress + (Pages * EFI_PAGE_SIZE); - return STATUS_EFI_SUCCESS; } -- 2.52.0 From f7b7b61ea4f7cbe71b55679ade0bea5b26b3d27b Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Wed, 11 Feb 2026 20:23:24 +0100 Subject: [PATCH 157/166] Add interface to retrieve page map level (PML) --- xtoskrnl/includes/mm/amd64/pagemap.hh | 1 + xtoskrnl/includes/mm/amd64/paging.hh | 1 + xtoskrnl/includes/mm/i686/pagemap.hh | 1 + xtoskrnl/includes/mm/i686/paging.hh | 1 + xtoskrnl/mm/amd64/pagemap.cc | 14 ++++++++++++++ xtoskrnl/mm/i686/pagemap.cc | 14 ++++++++++++++ xtoskrnl/mm/paging.cc | 14 ++++++++++++++ 7 files changed, 46 insertions(+) diff --git a/xtoskrnl/includes/mm/amd64/pagemap.hh b/xtoskrnl/includes/mm/amd64/pagemap.hh index febc7ce..0d56e85 100644 --- a/xtoskrnl/includes/mm/amd64/pagemap.hh +++ b/xtoskrnl/includes/mm/amd64/pagemap.hh @@ -30,6 +30,7 @@ namespace MM XTAPI PMMP5E GetP5eAddress(IN PVOID Address); XTAPI ULONG GetP5eOffset(IN PVOID Address); XTAPI PVOID GetP5eVirtualAddress(IN PMMP5E P5ePointer); + XTAPI USHORT GetPageMapLevel(); XTAPI PFN_NUMBER GetPageFrameNumber(IN PMMPTE Pte); XTAPI PMMPDE GetPdeAddress(IN PVOID Address); XTAPI ULONG GetPdeOffset(IN PVOID Address); diff --git a/xtoskrnl/includes/mm/amd64/paging.hh b/xtoskrnl/includes/mm/amd64/paging.hh index 9cec44a..a0e5062 100644 --- a/xtoskrnl/includes/mm/amd64/paging.hh +++ b/xtoskrnl/includes/mm/amd64/paging.hh @@ -31,6 +31,7 @@ namespace MM STATIC XTAPI PMMP5E GetP5eAddress(IN PVOID Address); STATIC XTAPI PVOID GetP5eVirtualAddress(IN PMMP5E P5ePointer); STATIC XTAPI PFN_NUMBER GetPageFrameNumber(IN PMMPTE Pte); + STATIC XTAPI USHORT GetPageMapLevel(); STATIC XTAPI PMMPDE GetPdeAddress(IN PVOID Address); STATIC XTAPI PVOID GetPdeVirtualAddress(IN PMMPDE PdePointer); STATIC XTAPI PMMPPE GetPpeAddress(IN PVOID Address); diff --git a/xtoskrnl/includes/mm/i686/pagemap.hh b/xtoskrnl/includes/mm/i686/pagemap.hh index bdfcb2d..3552cda 100644 --- a/xtoskrnl/includes/mm/i686/pagemap.hh +++ b/xtoskrnl/includes/mm/i686/pagemap.hh @@ -28,6 +28,7 @@ namespace MM VIRTUAL XTAPI PMMPTE GetNextPte(IN PMMPTE Pte) = 0; VIRTUAL XTAPI BOOLEAN GetOneEntry(IN PMMPTE Pte) = 0; VIRTUAL XTAPI PFN_NUMBER GetPageFrameNumber(IN PMMPTE Pte) = 0; + XTAPI USHORT GetPageMapLevel(); XTAPI PMMPDE GetPdeAddress(IN PVOID Address); XTAPI ULONG GetPdeOffset(IN PVOID Address); VIRTUAL XTAPI PVOID GetPdeVirtualAddress(IN PMMPDE PdePointer) = 0; diff --git a/xtoskrnl/includes/mm/i686/paging.hh b/xtoskrnl/includes/mm/i686/paging.hh index b9722d9..cdc95ab 100644 --- a/xtoskrnl/includes/mm/i686/paging.hh +++ b/xtoskrnl/includes/mm/i686/paging.hh @@ -29,6 +29,7 @@ namespace MM STATIC XTAPI PMMPTE GetNextPte(IN PMMPTE Pte); STATIC XTAPI BOOLEAN GetOneEntry(IN PMMPTE Pte); STATIC XTAPI PFN_NUMBER GetPageFrameNumber(IN PMMPTE Pte); + STATIC XTAPI USHORT GetPageMapLevel(); STATIC XTAPI PMMPDE GetPdeAddress(IN PVOID Address); STATIC XTAPI PVOID GetPdeVirtualAddress(IN PMMPDE PdePointer); STATIC XTAPI PMMPPE GetPpeAddress(IN PVOID Address); diff --git a/xtoskrnl/mm/amd64/pagemap.cc b/xtoskrnl/mm/amd64/pagemap.cc index 504cdcb..2d349a3 100644 --- a/xtoskrnl/mm/amd64/pagemap.cc +++ b/xtoskrnl/mm/amd64/pagemap.cc @@ -176,6 +176,20 @@ MM::PageMap::GetPageFrameNumber(IN PMMPTE Pte) return Pte->Hardware.PageFrameNumber; } +/** + * Gets Page Map Level (PML) for current paging mode. + * + * @return This routine returns the page map level. + * + * @since XT 1.0 + */ +XTAPI +USHORT +MM::PageMap::GetPageMapLevel() +{ + return PageMapInfo.Xpa ? 5 : 4; +} + /** * Gets the address of the PDE (Page Directory Entry), that maps given address. * diff --git a/xtoskrnl/mm/i686/pagemap.cc b/xtoskrnl/mm/i686/pagemap.cc index 1844115..d4db9b7 100644 --- a/xtoskrnl/mm/i686/pagemap.cc +++ b/xtoskrnl/mm/i686/pagemap.cc @@ -9,6 +9,20 @@ #include +/** + * Gets Page Map Level (PML) for current paging mode. + * + * @return This routine returns the page map level. + * + * @since XT 1.0 + */ +XTAPI +USHORT +MM::PageMap::GetPageMapLevel() +{ + return PageMapInfo.Xpa ? 3 : 2; +} + /** * Gets the address of the PDE (Page Directory Entry), that maps given address. * diff --git a/xtoskrnl/mm/paging.cc b/xtoskrnl/mm/paging.cc index 426e574..69305a6 100644 --- a/xtoskrnl/mm/paging.cc +++ b/xtoskrnl/mm/paging.cc @@ -189,6 +189,20 @@ MM::Paging::GetPageMapBasicRoutines(VOID) return &PageMapBasicRoutines; } +/** + * Gets Page Map Level (PML) for current paging mode. + * + * @return This routine returns the page map level. + * + * @since XT 1.0 + */ +XTAPI +USHORT +MM::Paging::GetPageMapLevel() +{ + return PmlRoutines->GetPageMapLevel(); +} + /** * Gets the page map routines for eXtended Physical Addressing (XPA) mode. * -- 2.52.0 From 7a4490106414024454da4c85d6e1554d7cc75cae Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Wed, 25 Feb 2026 12:14:26 +0100 Subject: [PATCH 158/166] Add definition for guarded PTE flag and remove hardcoded value --- sdk/xtdk/amd64/mmtypes.h | 1 + sdk/xtdk/i686/mmtypes.h | 1 + xtoskrnl/mm/kpool.cc | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/sdk/xtdk/amd64/mmtypes.h b/sdk/xtdk/amd64/mmtypes.h index 9eccd34..7f7e84a 100644 --- a/sdk/xtdk/amd64/mmtypes.h +++ b/sdk/xtdk/amd64/mmtypes.h @@ -60,6 +60,7 @@ /* PTE protection flags */ #define MM_PTE_NOEXECUTE 0x8000000000000000ULL +#define MM_PTE_GUARDED 0x8000000000000018ULL #define MM_PTE_PROTECT 0x8000000000000612ULL /* PTE cache flags */ diff --git a/sdk/xtdk/i686/mmtypes.h b/sdk/xtdk/i686/mmtypes.h index 749caea..4445543 100644 --- a/sdk/xtdk/i686/mmtypes.h +++ b/sdk/xtdk/i686/mmtypes.h @@ -56,6 +56,7 @@ /* PTE protection flags */ #define MM_PTE_NOEXECUTE 0x00000000 +#define MM_PTE_GUARDED 0x00000018 #define MM_PTE_PROTECT 0x00000612 /* PTE cache flags */ diff --git a/xtoskrnl/mm/kpool.cc b/xtoskrnl/mm/kpool.cc index b026dc9..067219d 100644 --- a/xtoskrnl/mm/kpool.cc +++ b/xtoskrnl/mm/kpool.cc @@ -52,7 +52,7 @@ MM::KernelPool::AllocateKernelStack(OUT PVOID *Stack, } /* Set up a template for an invalid PTE */ - MM::Paging::SetPte(&InvalidPte, 0, 0x18); + MM::Paging::SetPte(&InvalidPte, 0, MM_PTE_GUARDED); /* Set up a template for a valid, writable stack PTE */ MM::Paging::ClearPte(&TempPte); -- 2.52.0 From bfdb7bc476dbd2710db2281762f4f007e814fd91 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Wed, 25 Feb 2026 19:27:53 +0100 Subject: [PATCH 159/166] Refactor PFN linking logic --- xtoskrnl/includes/mm/pfn.hh | 9 ++- xtoskrnl/mm/kpool.cc | 2 +- xtoskrnl/mm/pfn.cc | 149 ++++++++++++++++++++++++------------ 3 files changed, 109 insertions(+), 51 deletions(-) diff --git a/xtoskrnl/includes/mm/pfn.hh b/xtoskrnl/includes/mm/pfn.hh index 3d61091..1d6eae8 100644 --- a/xtoskrnl/includes/mm/pfn.hh +++ b/xtoskrnl/includes/mm/pfn.hh @@ -49,9 +49,12 @@ namespace MM STATIC XTAPI ULONGLONG GetNumberOfPhysicalPages(VOID); STATIC XTAPI PMMPFN GetPfnEntry(IN PFN_NUMBER Pfn); STATIC XTAPI VOID InitializePfnDatabase(VOID); - STATIC VOID XTAPI LinkPfnToPte(IN PFN_NUMBER PageFrameIndex, - IN PMMPTE PointerPte, - IN BOOLEAN Modified); + STATIC XTAPI VOID LinkPfn(IN PFN_NUMBER PageFrameIndex, + IN PMMPTE PointerPte, + IN BOOLEAN Modified); + STATIC XTAPI VOID LinkPfnWithParent(IN PFN_NUMBER PageFrameIndex, + IN PMMPTE PointerPte, + IN PFN_NUMBER ParentFrame); STATIC XTAPI VOID ScanMemoryDescriptors(VOID); private: diff --git a/xtoskrnl/mm/kpool.cc b/xtoskrnl/mm/kpool.cc index 067219d..b81599a 100644 --- a/xtoskrnl/mm/kpool.cc +++ b/xtoskrnl/mm/kpool.cc @@ -76,7 +76,7 @@ MM::KernelPool::AllocateKernelStack(OUT PVOID *Stack, *PointerPte = InvalidPte; /* Associate the physical page with its corresponding PTE in the PFN database */ - MM::Pfn::LinkPfnToPte(PageFrameIndex, PointerPte, 1); + MM::Pfn::LinkPfn(PageFrameIndex, PointerPte, TRUE); /* Make the PTE valid, mapping the virtual address to the physical page */ MM::Paging::SetPte(&TempPte, PageFrameIndex, 0); diff --git a/xtoskrnl/mm/pfn.cc b/xtoskrnl/mm/pfn.cc index dfbd536..4dcf258 100644 --- a/xtoskrnl/mm/pfn.cc +++ b/xtoskrnl/mm/pfn.cc @@ -730,6 +730,84 @@ MM::Pfn::LinkPage(IN PMMPFNLIST ListHead, } } +/** + * Links a PFN entry to its corresponding PTE and ensures the page table that contains the PTE is resident in memory. + * + * @param PageFrameIndex + * Supplies the index into the PFN database for the page being initialized. + * + * @param PointerPte + * Supplies the pointer to the PTE which maps the physical page. + * + * @param Modified + * Supplies a flag indicating if the page's initial state is modified. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::Pfn::LinkPfn(IN PFN_NUMBER PageFrameIndex, + IN PMMPTE PointerPte, + IN BOOLEAN Modified) +{ + PMMMEMORY_LAYOUT MemoryLayout; + XTSTATUS Status; + PMMPFN Pfn; + PMMPTE Pte; + + /* Get the memory layout */ + MemoryLayout = MM::Manager::GetMemoryLayout(); + + /* Point the PFN to its PTE */ + Pfn = &((PMMPFN)MemoryLayout->PfnDatabase)[PageFrameIndex]; + Pfn->PteAddress = PointerPte; + + /* Check if the page is already mapped and in use */ + if(MM::Paging::PteValid(PointerPte)) + { + /* Clear the original PTE information */ + MM::Paging::SetPte(&Pfn->OriginalPte, 0, MM_PTE_READWRITE | MM_PTE_CACHE_ENABLE); + } + else + { + /* Page is not resident, so save the PTE contents for later use */ + Pfn->OriginalPte = *PointerPte; + } + + /* Initialize the PFN database entry for this page */ + Pfn->u2.ShareCount = 1; + Pfn->u3.e1.Modified = Modified; + Pfn->u3.e1.PageLocation = ActiveAndValid; + Pfn->u3.e2.ReferenceCount = 1; + + /* Get the PDE that maps the page table containing this PTE */ + Pte = MM::Paging::GetPteAddress(PointerPte); + if(!MM::Paging::PteValid(Pte)) + { + /* Check if page table is resident */ + Status = MM::PageFault::CheckPdeForPagedPool(PointerPte); + if(Status != STATUS_SUCCESS) + { + /* Could not make the page table resident, crash system */ + KE::Crash::PanicEx(0x1, + (ULONG_PTR)0x61940, + (ULONG_PTR)PointerPte, + MM::Paging::GetPageFrameNumber(PointerPte), + (ULONG_PTR)MM::Paging::GetPteVirtualAddress(PointerPte)); + } + } + + /* Record the page frame of the page table itself */ + PageFrameIndex = MM::Paging::GetPageFrameNumber(Pte); + Pfn->u4.PteFrame = PageFrameIndex; + + /* Pin the page table in memory by incrementing its PFN share count */ + Pfn = &((PMMPFN)MemoryLayout->PfnDatabase)[PageFrameIndex]; + Pfn->u2.ShareCount++; +} + /** * Initializes the PFN database entry for a physical page that is used as a page table. * @@ -788,8 +866,8 @@ MM::Pfn::LinkPfnForPageTable(IN PFN_NUMBER PageFrameIndex, * @param PointerPte * Supplies the pointer to the PTE which maps the physical page. * - * @param Modified - * Supplies a flag indicating if the page's initial state is modified. + * @param ParentFrame + * Supplies the page frame number of the page table that contains the PTE. * * @return This routine does not return any value. * @@ -797,14 +875,12 @@ MM::Pfn::LinkPfnForPageTable(IN PFN_NUMBER PageFrameIndex, */ XTAPI VOID -MM::Pfn::LinkPfnToPte(IN PFN_NUMBER PageFrameIndex, - IN PMMPTE PointerPte, - IN BOOLEAN Modified) +MM::Pfn::LinkPfnWithParent(IN PFN_NUMBER PageFrameIndex, + IN PMMPTE PointerPte, + IN PFN_NUMBER ParentFrame) { PMMMEMORY_LAYOUT MemoryLayout; - XTSTATUS Status; PMMPFN Pfn; - PMMPTE Pte; /* Get the memory layout */ MemoryLayout = MM::Manager::GetMemoryLayout(); @@ -813,48 +889,27 @@ MM::Pfn::LinkPfnToPte(IN PFN_NUMBER PageFrameIndex, Pfn = &((PMMPFN)MemoryLayout->PfnDatabase)[PageFrameIndex]; Pfn->PteAddress = PointerPte; - /* Check if the page is already mapped and in use */ - if(MM::Paging::PteValid(PointerPte)) - { - /* Clear the original PTE information */ - MM::Paging::SetPte(&Pfn->OriginalPte, 0, MM_PTE_READWRITE | MM_PTE_CACHE_ENABLE); - } - else - { - /* Page is not resident, so save the PTE contents for later use */ - Pfn->OriginalPte = *PointerPte; - } + /* Initialize the PTE */ + MM::Paging::SetPte(&Pfn->OriginalPte, 0, MM_PTE_GUARDED); - /* Initialize the PFN database entry for this page */ - Pfn->u2.ShareCount = 1; - Pfn->u3.e1.Modified = Modified; - Pfn->u3.e1.PageLocation = ActiveAndValid; - Pfn->u3.e2.ReferenceCount = 1; - - /* Get the PDE that maps the page table containing this PTE */ - Pte = MM::Paging::GetPteAddress(PointerPte); - if(!MM::Paging::PteValid(Pte)) - { - /* Check if page table is resident */ - Status = MM::PageFault::CheckPdeForPagedPool(PointerPte); - if(Status != STATUS_SUCCESS) - { - /* Could not make the page table resident, crash system */ - KE::Crash::PanicEx(0x1, - (ULONG_PTR)0x61940, - (ULONG_PTR)PointerPte, - MM::Paging::GetPageFrameNumber(PointerPte), - (ULONG_PTR)MM::Paging::GetPteVirtualAddress(PointerPte)); - } - } - - /* Record the page frame of the page table itself */ - PageFrameIndex = MM::Paging::GetPageFrameNumber(Pte); - Pfn->u4.PteFrame = PageFrameIndex; - - /* Pin the page table in memory by incrementing its PFN share count */ - Pfn = &((PMMPFN)MemoryLayout->PfnDatabase)[PageFrameIndex]; + /* Initialize the PFN entry */ Pfn->u2.ShareCount++; + Pfn->u3.e1.CacheAttribute = PfnCached; + Pfn->u3.e1.Modified = TRUE; + Pfn->u3.e1.PageLocation = ActiveAndValid; + Pfn->u3.e2.ReferenceCount++; + Pfn->u4.InPageError = FALSE; + + /* Check if parent PTE frame exists */ + if(ParentFrame) + { + /* Link the page table to its parent */ + Pfn->u4.PteFrame = ParentFrame; + + /* Get the PFN entry for parent PTE and increment share count */ + Pfn = &((PMMPFN)MemoryLayout->PfnDatabase)[ParentFrame]; + Pfn->u2.ShareCount++; + } } /** -- 2.52.0 From 0658e98436ccc7f927bf1d51a642b231b1c502fb Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Wed, 25 Feb 2026 20:25:50 +0100 Subject: [PATCH 160/166] Expose the number of available physical pages --- xtoskrnl/includes/mm/pfn.hh | 1 + xtoskrnl/mm/pfn.cc | 15 +++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/xtoskrnl/includes/mm/pfn.hh b/xtoskrnl/includes/mm/pfn.hh index 1d6eae8..5b7a810 100644 --- a/xtoskrnl/includes/mm/pfn.hh +++ b/xtoskrnl/includes/mm/pfn.hh @@ -45,6 +45,7 @@ namespace MM IN PFN_NUMBER PageFrameIndex, IN BOOLEAN BeginStandbyList = FALSE); STATIC XTAPI VOID FreePhysicalPage(IN PMMPTE PointerPte); + STATIC XTAPI PFN_NUMBER GetAvailablePages(VOID); STATIC XTAPI ULONG_PTR GetHighestPhysicalPage(VOID); STATIC XTAPI ULONGLONG GetNumberOfPhysicalPages(VOID); STATIC XTAPI PMMPFN GetPfnEntry(IN PFN_NUMBER Pfn); diff --git a/xtoskrnl/mm/pfn.cc b/xtoskrnl/mm/pfn.cc index 4dcf258..ad94f0c 100644 --- a/xtoskrnl/mm/pfn.cc +++ b/xtoskrnl/mm/pfn.cc @@ -351,6 +351,21 @@ MM::Pfn::FreePhysicalPage(IN PMMPTE PointerPte) MM::Pfn::DecrementShareCount(PageFrame, PageFrameNumber, FALSE); } +/** + * Retrieves the number of available physical pages. + * + * @return This routine returns the number of available physical pages. + * + * @since XT 1.0 + */ +XTAPI +PFN_NUMBER +MM::Pfn::GetAvailablePages(VOID) +{ + /* Return the number of available pages */ + return AvailablePages; +} + /** * Retrieves the highest physical page number (PFN) detected in the system. * -- 2.52.0 From 278def3081ae609ffaee83565676d5decb80c861 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Thu, 26 Feb 2026 10:57:19 +0100 Subject: [PATCH 161/166] Correct comment phrasing --- xtoskrnl/mm/kpool.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xtoskrnl/mm/kpool.cc b/xtoskrnl/mm/kpool.cc index b81599a..a8c8835 100644 --- a/xtoskrnl/mm/kpool.cc +++ b/xtoskrnl/mm/kpool.cc @@ -165,7 +165,7 @@ MM::KernelPool::FreeKernelStack(IN PVOID Stack, /* Convert the stack size into a page count */ StackPages = SIZE_TO_PAGES(StackSize); - /* Start guarded code block */ + /* Start a guarded code block */ { /* Acquire the PFN database lock */ KE::QueuedSpinLockGuard SpinLock(SystemSpaceLock); -- 2.52.0 From 511dd15c0cd6d6eccc4135819ddcd9e4a648f47d Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Thu, 26 Feb 2026 13:42:58 +0100 Subject: [PATCH 162/166] Implement page allocation interface --- sdk/xtdk/mmtypes.h | 31 ++++++++ sdk/xtdk/xtstruct.h | 2 + xtoskrnl/includes/mm/alloc.hh | 11 +++ xtoskrnl/mm/alloc.cc | 130 ++++++++++++++++++++++++++++++++++ xtoskrnl/mm/amd64/alloc.cc | 11 ++- xtoskrnl/mm/i686/alloc.cc | 10 ++- 6 files changed, 190 insertions(+), 5 deletions(-) diff --git a/sdk/xtdk/mmtypes.h b/sdk/xtdk/mmtypes.h index bae2fb4..22dac32 100644 --- a/sdk/xtdk/mmtypes.h +++ b/sdk/xtdk/mmtypes.h @@ -17,12 +17,18 @@ /* Number of hyper space pages */ #define MM_HYPERSPACE_PAGE_COUNT 255 +/* Number of free page list heads */ +#define MM_MAX_FREE_PAGE_LIST_HEADS 4 + /* Number of paging colors */ #define MM_PAGING_COLORS 64 /* PTE frame mask definition */ #define MM_PFN_PTE_FRAME (((ULONG_PTR)1 << MM_PTE_FRAME_BITS) - 1) +/* Memory manager pool type mask definition */ +#define MM_POOL_TYPE_MASK 1 + /* Number of reserved zeroed PTEs */ #define MM_RESERVED_ZERO_PTES 32 @@ -48,6 +54,24 @@ typedef enum _MMPFN_CACHE_ATTRIBUTE PfnNotMapped } MMPFN_CACHE_ATTRIBUTE, *PMMPFN_CACHE_ATTRIBUTE; +/* Memory Manager pool types */ +typedef enum _MMPOOL_TYPE +{ + NonPagedPool = 0, + PagedPool = 1, + NonPagedPoolMustSucceed = 2, + NonPagedPoolCacheAligned = 4, + PagedPoolCacheAligned = 5, + NonPagedPoolCacheAlignedMustS = 6, + MaxPoolType = 7, + NonPagedPoolSession = 32, + PagedPoolSession = 33, + NonPagedPoolMustSucceedSession = 34, + NonPagedPoolCacheAlignedSession = 36, + PagedPoolCacheAlignedSession = 37, + NonPagedPoolCacheAlignedMustSSession = 38 +} MMPOOL_TYPE, *PMMPOOL_TYPE; + /* Page table pool types */ typedef enum _MMSYSTEM_PTE_POOL_TYPE { @@ -73,6 +97,13 @@ typedef struct _MMCOLOR_TABLES ULONG_PTR Count; } MMCOLOR_TABLES, *PMMCOLOR_TABLES; +/* Free pool entry structure definition */ +typedef struct _MMFREE_POOL_ENTRY +{ + LIST_ENTRY List; + PFN_COUNT Size; +} MMFREE_POOL_ENTRY, *PMMFREE_POOL_ENTRY; + /* Memory layout structure definition */ typedef struct _MMMEMORY_LAYOUT { diff --git a/sdk/xtdk/xtstruct.h b/sdk/xtdk/xtstruct.h index 50c57c0..7f95d8e 100644 --- a/sdk/xtdk/xtstruct.h +++ b/sdk/xtdk/xtstruct.h @@ -50,6 +50,7 @@ typedef enum _KUBSAN_DATA_TYPE KUBSAN_DATA_TYPE, *PKUBSAN_DATA_TYPE; typedef enum _LOADER_MEMORY_TYPE LOADER_MEMORY_TYPE, *PLOADER_MEMORY_TYPE; typedef enum _MMPAGELISTS MMPAGELISTS, *PMMPAGELISTS; typedef enum _MMPFN_CACHE_ATTRIBUTE MMPFN_CACHE_ATTRIBUTE, *PMMPFN_CACHE_ATTRIBUTE; +typedef enum _MMPOOL_TYPE MMPOOL_TYPE, *PMMPOOL_TYPE; typedef enum _MMSYSTEM_PTE_POOL_TYPE MMSYSTEM_PTE_POOL_TYPE, *PMMSYSTEM_PTE_POOL_TYPE; typedef enum _MODE MODE, *PMODE; typedef enum _RTL_VARIABLE_TYPE RTL_VARIABLE_TYPE, *PRTL_VARIABLE_TYPE; @@ -277,6 +278,7 @@ typedef struct _LOADER_INFORMATION_BLOCK LOADER_INFORMATION_BLOCK, *PLOADER_INFO typedef struct _LOADER_MEMORY_DESCRIPTOR LOADER_MEMORY_DESCRIPTOR, *PLOADER_MEMORY_DESCRIPTOR; typedef struct _M128 M128, *PM128; typedef struct _MMCOLOR_TABLES MMCOLOR_TABLES, *PMMCOLOR_TABLES; +typedef struct _MMFREE_POOL_ENTRY MMFREE_POOL_ENTRY, *PMMFREE_POOL_ENTRY; typedef struct _MMMEMORY_LAYOUT MMMEMORY_LAYOUT, *PMMMEMORY_LAYOUT; typedef struct _MMPFNENTRY MMPFNENTRY, *PMMPFNENTRY; typedef struct _MMPFNLIST MMPFNLIST, *PMMPFNLIST; diff --git a/xtoskrnl/includes/mm/alloc.hh b/xtoskrnl/includes/mm/alloc.hh index dc88bea..a2f133a 100644 --- a/xtoskrnl/includes/mm/alloc.hh +++ b/xtoskrnl/includes/mm/alloc.hh @@ -18,7 +18,18 @@ namespace MM class Allocator { public: + STATIC XTAPI XTSTATUS AllocatePages(IN MMPOOL_TYPE PoolType, + IN SIZE_T Bytes, + OUT PVOID *Memory); STATIC XTAPI VOID InitializeNonPagedPool(VOID); + STATIC XTAPI VOID InitializePagedPool(VOID); + + private: + STATIC XTAPI XTSTATUS AllocateNonPagedPoolPages(IN PFN_COUNT Pages, + OUT PVOID *Memory); + STATIC XTAPI XTSTATUS AllocatePagedPoolPages(IN PFN_COUNT Pages, + OUT PVOID *Memory); + STATIC XTAPI VOID MapNonPagedPool(VOID); }; } diff --git a/xtoskrnl/mm/alloc.cc b/xtoskrnl/mm/alloc.cc index 306b3fb..8bcd572 100644 --- a/xtoskrnl/mm/alloc.cc +++ b/xtoskrnl/mm/alloc.cc @@ -9,3 +9,133 @@ #include +/** + * Allocates pages from the non-paged pool. + * + * @param Pages + * Specifies the number of pages to allocate. + * + * @param Memory + * Supplies a pointer to the allocated pool. + * + * @return This routine returns a status code. + * + * @since XT 1.0 + */ +XTAPI +XTSTATUS +MM::Allocator::AllocateNonPagedPoolPages(IN PFN_COUNT Pages, + OUT PVOID *Memory) +{ + UNIMPLEMENTED; + + /* Return not implemented status code */ + return STATUS_NOT_IMPLEMENTED; +} + +/** + * Allocates pages from the paged pool. + * + * @param Pages + * Specifies the number of pages to allocate. + * + * @param Memory + * Supplies a pointer to the allocated pool. + * + * @return This routine returns a status code. + * + * @since XT 1.0 + */ +XTAPI +XTSTATUS +MM::Allocator::AllocatePagedPoolPages(IN PFN_COUNT Pages, + OUT PVOID *Memory) +{ + UNIMPLEMENTED; + + /* Return not implemented status code */ + return STATUS_NOT_IMPLEMENTED; +} + +/** + * Allocates pages from the specified pool type. + * + * @param PoolType + * Specifies the type of pool to allocate pages from. + * + * @param Bytes + * Specifies the number of bytes to allocate. + * + * @param Memory + * Supplies a pointer to the allocated pool. + * + * @return This routine returns a status code. + * + * @since XT 1.0 + */ +XTAPI +XTSTATUS +MM::Allocator::AllocatePages(IN MMPOOL_TYPE PoolType, + IN SIZE_T Bytes, + OUT PVOID *Memory) +{ + PFN_COUNT Pages; + + /* Initialize the output parameter */ + *Memory = NULLPTR; + + /* Convert bytes to pages */ + Pages = SIZE_TO_PAGES(Bytes); + + /* Check if there are any pages to allocate */ + if(!Pages) + { + /* Nothing to allocate, return NULLPTR */ + return STATUS_INVALID_PARAMETER; + } + + /* Switch on pool type */ + switch(PoolType & MM_POOL_TYPE_MASK) + { + case NonPagedPool: + /* Allocate non-paged pool */ + return AllocateNonPagedPoolPages(Pages, Memory); + case PagedPool: + /* Allocate paged pool */ + return AllocatePagedPoolPages(Pages, Memory); + } + + /* Invalid pool type specified, return error */ + return STATUS_INVALID_PARAMETER; +} + +/** + * Initializes the non-paged pool for memory allocator. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::Allocator::InitializeNonPagedPool(VOID) +{ + UNIMPLEMENTED; + + /* Map PTEs for the non-paged pool */ + MapNonPagedPool(); +} + +/** + * Initializes the non-paged pool for memory allocator. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::Allocator::InitializePagedPool(VOID) +{ + UNIMPLEMENTED; +} diff --git a/xtoskrnl/mm/amd64/alloc.cc b/xtoskrnl/mm/amd64/alloc.cc index 8cdfab0..bc2be3c 100644 --- a/xtoskrnl/mm/amd64/alloc.cc +++ b/xtoskrnl/mm/amd64/alloc.cc @@ -9,14 +9,19 @@ #include +/** + * Maps the PTE for the base of the non-paged pool. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ XTAPI VOID -MM::Allocator::InitializeNonPagedPool(VOID) +MM::Allocator::MapNonPagedPool(VOID) { PMMMEMORY_LAYOUT MemoryLayout; - UNIMPLEMENTED; - /* Retrieve memory layout */ MemoryLayout = MM::Manager::GetMemoryLayout(); diff --git a/xtoskrnl/mm/i686/alloc.cc b/xtoskrnl/mm/i686/alloc.cc index 1189eef..79b0abf 100644 --- a/xtoskrnl/mm/i686/alloc.cc +++ b/xtoskrnl/mm/i686/alloc.cc @@ -9,12 +9,18 @@ #include +/** + * Maps the PTE for the base of the non-paged pool. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ XTAPI VOID -MM::Allocator::InitializeNonPagedPool(VOID) +MM::Allocator::MapNonPagedPool(VOID) { PMMMEMORY_LAYOUT MemoryLayout; - UNIMPLEMENTED; /* Retrieve memory layout */ MemoryLayout = MM::Manager::GetMemoryLayout(); -- 2.52.0 From d7d125dd504bf966342d9b80d84b23c4f6cecf9a Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Thu, 26 Feb 2026 13:54:10 +0100 Subject: [PATCH 163/166] Initialize paged pool alongside non-paged pool --- xtoskrnl/mm/mmgr.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/xtoskrnl/mm/mmgr.cc b/xtoskrnl/mm/mmgr.cc index 896cb8f..48efa03 100644 --- a/xtoskrnl/mm/mmgr.cc +++ b/xtoskrnl/mm/mmgr.cc @@ -124,8 +124,9 @@ MM::Manager::InitializeMemoryManager(VOID) /* Initialize system PTE space */ MM::Pte::InitializeSystemPteSpace(); - /* Initialize non-paged pool */ + /* Initialize non-paged and paged pools */ MM::Allocator::InitializeNonPagedPool(); + MM::Allocator::InitializePagedPool(); /* Initialize PFN database */ MM::Pfn::InitializePfnDatabase(); -- 2.52.0 From 5778a761b591125e9db3852662e22071bd124d44 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Thu, 26 Feb 2026 16:42:18 +0100 Subject: [PATCH 164/166] Initialize paged pool after PFN database setup --- xtoskrnl/mm/mmgr.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/xtoskrnl/mm/mmgr.cc b/xtoskrnl/mm/mmgr.cc index 48efa03..b8116f2 100644 --- a/xtoskrnl/mm/mmgr.cc +++ b/xtoskrnl/mm/mmgr.cc @@ -124,13 +124,15 @@ MM::Manager::InitializeMemoryManager(VOID) /* Initialize system PTE space */ MM::Pte::InitializeSystemPteSpace(); - /* Initialize non-paged and paged pools */ + /* Initialize non-paged pool */ MM::Allocator::InitializeNonPagedPool(); - MM::Allocator::InitializePagedPool(); /* Initialize PFN database */ MM::Pfn::InitializePfnDatabase(); + /* Initialize paged pool */ + MM::Allocator::InitializePagedPool(); + /* Flush TLB */ AR::CpuFunc::FlushTlb(); } -- 2.52.0 From 7bdd0dfe2c5d132e4521b96cc88be7940a65bbbe Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Thu, 26 Feb 2026 20:10:03 +0100 Subject: [PATCH 165/166] Implement basic non-paged pool allocator --- xtoskrnl/includes/mm/alloc.hh | 3 + xtoskrnl/mm/alloc.cc | 180 +++++++++++++++++++++++++++++++++- xtoskrnl/mm/data.cc | 3 + 3 files changed, 182 insertions(+), 4 deletions(-) diff --git a/xtoskrnl/includes/mm/alloc.hh b/xtoskrnl/includes/mm/alloc.hh index a2f133a..2f3dc5b 100644 --- a/xtoskrnl/includes/mm/alloc.hh +++ b/xtoskrnl/includes/mm/alloc.hh @@ -17,6 +17,9 @@ namespace MM { class Allocator { + private: + STATIC LIST_ENTRY NonPagedPoolFreeList[MM_MAX_FREE_PAGE_LIST_HEADS]; + public: STATIC XTAPI XTSTATUS AllocatePages(IN MMPOOL_TYPE PoolType, IN SIZE_T Bytes, diff --git a/xtoskrnl/mm/alloc.cc b/xtoskrnl/mm/alloc.cc index 8bcd572..e60a18c 100644 --- a/xtoskrnl/mm/alloc.cc +++ b/xtoskrnl/mm/alloc.cc @@ -27,10 +27,155 @@ XTSTATUS MM::Allocator::AllocateNonPagedPoolPages(IN PFN_COUNT Pages, OUT PVOID *Memory) { - UNIMPLEMENTED; + PLIST_ENTRY Entry, LastHead, ListHead; + PMMPTE PointerPte, ValidPte; + PMMFREE_POOL_ENTRY FreePage; + PFN_NUMBER PageFrameNumber; + PVOID BaseAddress; + ULONG Index; + PMMPFN Pfn; - /* Return not implemented status code */ - return STATUS_NOT_IMPLEMENTED; + /* Calculate the free list index based on the requested page count, capped at the maximum list head index */ + Index = MIN(Pages, MM_MAX_FREE_PAGE_LIST_HEADS) - 1; + + /* Set the starting list head and the boundary for the search loop */ + ListHead = &NonPagedPoolFreeList[Index]; + LastHead = &NonPagedPoolFreeList[MM_MAX_FREE_PAGE_LIST_HEADS]; + + /* Start a guarded code block */ + { + /* Acquire the Non-Paged pool lock and raise runlevel to DISPATCH_LEVEL */ + KE::RaiseRunLevel RunLevel(DISPATCH_LEVEL); + KE::QueuedSpinLockGuard NonPagedPoolSpinLock(NonPagedPoolLock); + + /* Iterate through the free lists */ + do + { + /* Iterate through the free entries in the current list */ + Entry = ListHead->Flink; + while(Entry != ListHead) + { + /* Get the free pool entry structure from the list entry */ + FreePage = CONTAIN_RECORD(Entry, MMFREE_POOL_ENTRY, List); + + /* Check if this block is large enough to satisfy the request */ + if(FreePage->Size >= Pages) + { + /* Adjust the size of the free block to account for the allocated pages */ + FreePage->Size -= Pages; + + /* Calculate the base address of the allocated block */ + BaseAddress = (PVOID)((ULONG_PTR)FreePage + (FreePage->Size << MM_PAGE_SHIFT)); + + /* Remove the entry from the free list */ + RTL::LinkedList::RemoveEntryList(&FreePage->List); + + /* Check if there is remaining space in the entry */ + if(FreePage->Size != 0) + { + /* Calculate the new list index for the remaining fragment */ + Index = MIN(FreePage->Size, MM_MAX_FREE_PAGE_LIST_HEADS) - 1; + + /* Insert the entry into the free list */ + RTL::LinkedList::InsertTailList(&NonPagedPoolFreeList[Index], &FreePage->List); + } + + /* Get the Page Table Entry (PTE) for the allocated address */ + PointerPte = MM::Paging::GetPteAddress(BaseAddress); + + /* Get the Page Frame Number (PFN) database entry for the corresponding physical page */ + Pfn = MM::Pfn::GetPfnEntry(MM::Paging::GetPageFrameNumber(PointerPte)); + + /* Denote allocation boundaries */ + Pfn->u3.e1.ReadInProgress = 1; + + /* Check if multiple pages were requested */ + if(Pages != 1) + { + /* Advance to the PTE of the last page in the allocation */ + PointerPte = MM::Paging::AdvancePte(PointerPte, Pages - 1); + + /* Get the PFN entry for the last page */ + Pfn = MM::Pfn::GetPfnEntry(MM::Paging::GetPageFrameNumber(PointerPte)); + } + + /* Denote allocation boundaries */ + Pfn->u3.e1.WriteInProgress = 1; + + /* Set the allocated memory address and return success */ + *Memory = BaseAddress; + return STATUS_SUCCESS; + } + + /* Move to the next entry in the free list */ + Entry = FreePage->List.Flink; + } + } + while(++ListHead < LastHead); + } + + /* No suitable free block found; try to expand the pool by reserving system PTEs */ + PointerPte = MM::Pte::ReserveSystemPtes(Pages, NonPagedPoolExpansion); + if(PointerPte == NULLPTR) + { + /* PTE reservation failed, return insufficient resources */ + return STATUS_INSUFFICIENT_RESOURCES; + } + + /* Acquire the Non-Paged pool lock and raise runlevel to DISPATCH_LEVEL */ + KE::RaiseRunLevel RunLevel(DISPATCH_LEVEL); + KE::QueuedSpinLockGuard NonPagedPoolSpinLock(NonPagedPoolLock); + + /* Acquire the PFN database lock */ + KE::QueuedSpinLockGuard PfnSpinLock(PfnLock); + + /* Check if there are enough available physical pages to back the allocation */ + if(Pages >= MM::Pfn::GetAvailablePages()) + { + /* Not enough physical pages, release the reserved system PTEs */ + MM::Pte::ReleaseSystemPtes(PointerPte, Pages, NonPagedPoolExpansion); + + /* Return failure due to insufficient resources */ + return STATUS_INSUFFICIENT_RESOURCES; + } + + /* Get a template valid PTE and loop through the allocation to map physical pages */ + ValidPte = MM::Pte::GetValidPte(); + do + { + /* Allocate a physical page */ + PageFrameNumber = MM::Pfn::AllocatePhysicalPage(MM::Colors::GetNextColor()); + + /* Initialize the PFN entry for the allocated physical page */ + Pfn = MM::Pfn::GetPfnEntry(PageFrameNumber); + Pfn->PteAddress = PointerPte; + Pfn->u2.ShareCount = 1; + Pfn->u3.e1.PageLocation = ActiveAndValid; + Pfn->u3.e2.ReferenceCount = 1; + Pfn->u4.VerifierAllocation = 0; + + /* Build a valid PTE pointing to the allocated page frame */ + MM::Paging::SetPte(ValidPte, PageFrameNumber, 0); + + /* Write the valid PTE into the system PTE range */ + *(MM::Paging::GetNextPte(PointerPte)) = *ValidPte; + } + while(--Pages > 0); + + /* Dnote allocation boundaries */ + Pfn->u3.e1.WriteInProgress = 1; + + /* Get the PFN entry for the first page of the allocation */ + Pfn = MM::Pfn::GetPfnEntry(MM::Paging::GetPageFrameNumber(PointerPte)); + + /* Denote allocation boundaries */ + Pfn->u3.e1.ReadInProgress = 1; + + /* Convert the PTE address to the virtual address and store in the buffer */ + *Memory = MM::Paging::GetPteVirtualAddress(PointerPte); + + /* Return success */ + return STATUS_SUCCESS; } /** @@ -120,10 +265,37 @@ XTAPI VOID MM::Allocator::InitializeNonPagedPool(VOID) { - UNIMPLEMENTED; + PMMMEMORY_LAYOUT MemoryLayout; + PMMFREE_POOL_ENTRY FreeEntry; + ULONG Index; + + /* Retrieve memory layout */ + MemoryLayout = MM::Manager::GetMemoryLayout(); /* Map PTEs for the non-paged pool */ MapNonPagedPool(); + + /* Iterate over the free page list heads */ + for(Index = 0; Index < MM_MAX_FREE_PAGE_LIST_HEADS; Index++) + { + /* Initialize a free page list head */ + RTL::LinkedList::InitializeListHead(&NonPagedPoolFreeList[Index]); + } + + /* Take the first free page from the pool */ + FreeEntry = (PMMFREE_POOL_ENTRY)MemoryLayout->NonPagedPoolStart; + + /* Take number of pages in the pool */ + Index = (ULONG)(MemoryLayout->NonPagedPoolSize - 1); + if(Index >= MM_MAX_FREE_PAGE_LIST_HEADS) + { + /* Number of pages exceeds the number of free page list heads */ + Index = MM_MAX_FREE_PAGE_LIST_HEADS - 1; + } + + /* Insert the first free page into the free page list and set its size */ + RTL::LinkedList::InsertHeadList(&NonPagedPoolFreeList[Index], &FreeEntry->List); + FreeEntry->Size = MemoryLayout->NonPagedPoolSize; } /** diff --git a/xtoskrnl/mm/data.cc b/xtoskrnl/mm/data.cc index 6586526..91c32e8 100644 --- a/xtoskrnl/mm/data.cc +++ b/xtoskrnl/mm/data.cc @@ -9,6 +9,9 @@ #include +/* Array of non-paged pool free list heads */ +LIST_ENTRY MM::Allocator::NonPagedPoolFreeList[MM_MAX_FREE_PAGE_LIST_HEADS]; + /* Array of free page lists segregated by cache color */ PMMCOLOR_TABLES MM::Colors::FreePages[FreePageList + 1]; -- 2.52.0 From a72bfd3902da5553402240c5188f654e89c2c5ff Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Thu, 26 Feb 2026 20:12:28 +0100 Subject: [PATCH 166/166] Add MIN and MAX helper macros --- sdk/xtdk/xtdefs.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sdk/xtdk/xtdefs.h b/sdk/xtdk/xtdefs.h index a573847..62e3012 100644 --- a/sdk/xtdk/xtdefs.h +++ b/sdk/xtdk/xtdefs.h @@ -74,6 +74,10 @@ /* Macro for calculating size of a field in the structure */ #define FIELD_SIZE(Structure, Field) (sizeof(((Structure *)0)->Field)) +/* Macros for calculating minimum and maximum of two values */ +#define MIN(A, B) (((A) < (B)) ? (A) : (B)) +#define MAX(A, B) (((A) > (B)) ? (A) : (B)) + /* Macro that page-aligns a virtual address */ #define PAGE_ALIGN(VirtualAddress) ((PVOID)((ULONG_PTR)VirtualAddress & ~MM_PAGE_MASK)) -- 2.52.0