diff --git a/xtoskrnl/CMakeLists.txt b/xtoskrnl/CMakeLists.txt index 3e378b2..61d1c5c 100644 --- a/xtoskrnl/CMakeLists.txt +++ b/xtoskrnl/CMakeLists.txt @@ -51,12 +51,12 @@ 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}/pool.cc ${XTOSKRNL_SOURCE_DIR}/mm/${ARCH}/pte.cc ${XTOSKRNL_SOURCE_DIR}/mm/alloc.cc ${XTOSKRNL_SOURCE_DIR}/mm/colors.cc @@ -66,6 +66,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/pool.cc ${XTOSKRNL_SOURCE_DIR}/mm/pte.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 6045afe..01ead47 100644 --- a/xtoskrnl/includes/mm.hh +++ b/xtoskrnl/includes/mm.hh @@ -22,5 +22,6 @@ #include #include #include +#include #endif /* __XTOSKRNL_MM_HH */ diff --git a/xtoskrnl/includes/mm/alloc.hh b/xtoskrnl/includes/mm/alloc.hh index 1c82200..aaac9cd 100644 --- a/xtoskrnl/includes/mm/alloc.hh +++ b/xtoskrnl/includes/mm/alloc.hh @@ -2,7 +2,7 @@ * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/includes/mm/alloc.hh - * DESCRIPTION: Memory manager pool allocation + * DESCRIPTION: Memory Manager pool allocator * DEVELOPERS: Aiken Harris */ @@ -10,18 +10,14 @@ #define __XTOSKRNL_MM_ALLOC_HH #include +#include /* Memory Manager */ namespace MM { - class Allocator + class Allocator final : private Pool { - private: - STATIC PFN_NUMBER NonPagedPoolFrameEnd; - STATIC PFN_NUMBER NonPagedPoolFrameStart; - STATIC LIST_ENTRY NonPagedPoolFreeList[MM_MAX_FREE_PAGE_LIST_HEADS]; - public: STATIC XTAPI XTSTATUS AllocatePages(IN MMPOOL_TYPE PoolType, IN SIZE_T Bytes, @@ -34,23 +30,21 @@ namespace MM OUT PVOID *Memory, IN ULONG Tag); STATIC XTAPI XTSTATUS FreePages(IN PVOID VirtualAddress); + STATIC XTAPI XTSTATUS FreePages(IN PVOID VirtualAddress, + OUT PPFN_NUMBER PagesFreed); STATIC XTAPI XTSTATUS FreePool(IN PVOID VirtualAddress); STATIC XTAPI XTSTATUS FreePool(IN PVOID VirtualAddress, IN ULONG Tag); - 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 XTSTATUS FreeNonPagedPoolPages(IN PVOID VirtualAddress); - STATIC XTAPI XTSTATUS FreePagedPoolPages(IN PVOID VirtualAddress); - STATIC XTAPI VOID MapNonPagedPool(VOID); - STATIC XTINLINE VOID VerifyRunLevel(IN MMPOOL_TYPE PoolType, - IN SIZE_T Bytes, - IN PVOID Entry); + STATIC XTAPI XTSTATUS FreeNonPagedPoolPages(IN PVOID VirtualAddress, + OUT PPFN_NUMBER PagesFreed); + STATIC XTAPI XTSTATUS FreePagedPoolPages(IN PVOID VirtualAddress, + OUT PPFN_NUMBER PagesFreed); }; } diff --git a/xtoskrnl/includes/mm/pool.hh b/xtoskrnl/includes/mm/pool.hh new file mode 100644 index 0000000..988c73a --- /dev/null +++ b/xtoskrnl/includes/mm/pool.hh @@ -0,0 +1,39 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: xtoskrnl/includes/mm/pool.hh + * DESCRIPTION: Memory Manager pool manager + * DEVELOPERS: Aiken Harris + */ + +#ifndef __XTOSKRNL_MM_POOL_HH +#define __XTOSKRNL_MM_POOL_HH + +#include + + +/* Memory Manager */ +namespace MM +{ + class Pool + { + protected: + STATIC PFN_NUMBER NonPagedPoolFrameEnd; + STATIC PFN_NUMBER NonPagedPoolFrameStart; + STATIC LIST_ENTRY NonPagedPoolFreeList[MM_MAX_FREE_PAGE_LIST_HEADS]; + + public: + STATIC XTAPI VOID InitializeNonPagedPool(VOID); + STATIC XTAPI VOID InitializePagedPool(VOID); + + protected: + STATIC XTAPI VOID VerifyRunLevel(IN MMPOOL_TYPE PoolType, + IN SIZE_T Bytes, + IN PVOID Entry); + + private: + STATIC XTAPI VOID MapNonPagedPool(VOID); + }; +} + +#endif /* __XTOSKRNL_MM_POOL_HH */ diff --git a/xtoskrnl/mm/alloc.cc b/xtoskrnl/mm/alloc.cc index 9f81436..d6a59f9 100644 --- a/xtoskrnl/mm/alloc.cc +++ b/xtoskrnl/mm/alloc.cc @@ -2,7 +2,7 @@ * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/mm/alloc.cc - * DESCRIPTION: Memory manager pool allocation + * DESCRIPTION: Memory Manager pool allocator * DEVELOPERS: Aiken Harris */ @@ -332,13 +332,17 @@ MM::Allocator::AllocatePool(IN MMPOOL_TYPE PoolType, * @param VirtualAddress * Supplies the base virtual address of the non-paged pool pages allocation to free. * + * @param PagesFreed + * Supplies a pointer to a variable that will receive the number of pages freed. + * * @return This routine returns a status code. * * @since XT 1.0 */ XTAPI XTSTATUS -MM::Allocator::FreeNonPagedPoolPages(IN PVOID VirtualAddress) +MM::Allocator::FreeNonPagedPoolPages(IN PVOID VirtualAddress, + OUT PPFN_NUMBER PagesFreed) { PMMFREE_POOL_ENTRY FreePage, NextPage, LastPage; PFN_COUNT FreePages, Pages; @@ -505,6 +509,13 @@ MM::Allocator::FreeNonPagedPoolPages(IN PVOID VirtualAddress) NextPage = (PMMFREE_POOL_ENTRY)((ULONG_PTR)NextPage + MM_PAGE_SIZE); } + /* Check if a page count was requested */ + if(PagesFreed != NULLPTR) + { + /* Return the number of pages freed */ + *PagesFreed = FreePages; + } + /* Return success */ return STATUS_SUCCESS; } @@ -515,13 +526,17 @@ MM::Allocator::FreeNonPagedPoolPages(IN PVOID VirtualAddress) * @param VirtualAddress * Supplies the base virtual address of the paged pool pages allocation to free. * + * @param PagesFreed + * Supplies a pointer to a variable that will receive the number of pages freed. + * * @return This routine returns a status code. * * @since XT 1.0 */ XTAPI XTSTATUS -MM::Allocator::FreePagedPoolPages(IN PVOID VirtualAddress) +MM::Allocator::FreePagedPoolPages(IN PVOID VirtualAddress, + OUT PPFN_NUMBER PagesFreed) { UNIMPLEMENTED; @@ -542,6 +557,27 @@ MM::Allocator::FreePagedPoolPages(IN PVOID VirtualAddress) XTAPI XTSTATUS MM::Allocator::FreePages(IN PVOID VirtualAddress) +{ + return FreePages(VirtualAddress, NULLPTR); +} + +/** + * Frees a previously allocated block of pages. + * + * @param VirtualAddress + * Supplies the base virtual address of the pages allocation to free. + * + * @param PagesFreed + * Supplies a pointer to a variable that will receive the number of pages freed. + * + * @return This routine returns a status code. + * + * @since XT 1.0 + */ +XTAPI +XTSTATUS +MM::Allocator::FreePages(IN PVOID VirtualAddress, + OUT PPFN_NUMBER PagesFreed) { PMMMEMORY_LAYOUT MemoryLayout; @@ -552,12 +588,12 @@ MM::Allocator::FreePages(IN PVOID VirtualAddress) if(VirtualAddress >= MemoryLayout->PagedPoolStart && VirtualAddress < MemoryLayout->PagedPoolEnd) { /* Free pages from the paged pool */ - return FreePagedPoolPages(VirtualAddress); + return FreePagedPoolPages(VirtualAddress, PagesFreed); } else { /* Free pages from the non-paged pool */ - return FreeNonPagedPoolPages(VirtualAddress); + return FreeNonPagedPoolPages(VirtualAddress, PagesFreed); } } @@ -602,134 +638,3 @@ MM::Allocator::FreePool(IN PVOID VirtualAddress, /* Free pages */ return FreePages(VirtualAddress); } - -/** - * 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) -{ - PMMFREE_POOL_ENTRY FreePage, SetupPage; - PMMMEMORY_LAYOUT MemoryLayout; - 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 and set its size */ - FreePage = (PMMFREE_POOL_ENTRY)MemoryLayout->NonPagedPoolStart; - FreePage->Size = MemoryLayout->NonPagedPoolSize; - - /* 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 */ - RTL::LinkedList::InsertHeadList(&NonPagedPoolFreeList[Index], &FreePage->List); - - /* Create a free page for each page in the pool */ - SetupPage = FreePage; - for(Index = 0; Index < MemoryLayout->NonPagedPoolSize; Index++) - { - /* Initialize the owner for each page */ - SetupPage->Owner = FreePage; - SetupPage = (PMMFREE_POOL_ENTRY)((ULONG_PTR)SetupPage + MM_PAGE_SIZE); - } - - /* Store first and last allocated non-paged pool page */ - NonPagedPoolFrameStart = MM::Paging::GetPageFrameNumber(MM::Paging::GetPteAddress(MemoryLayout->NonPagedPoolStart)); - NonPagedPoolFrameEnd = MM::Paging::GetPageFrameNumber(MM::Paging::GetPteAddress(MemoryLayout->NonPagedPoolEnd)); - - /* Initialize system PTE pool for the non-paged expansion pool */ - Pte::InitializeSystemPtePool(Paging::GetNextPte(Paging::GetPteAddress(MemoryLayout->NonPagedExpansionPoolStart)), - MemoryLayout->NonPagedExpansionPoolSize - 2, - NonPagedPoolExpansion); -} - -/** - * 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; -} - -/** - * Validates the run level for the specified pool. If the run level is invalid, the kernel panics. - * - * @param PoolType - * Supplies the pool type. - * - * @param Bytes - * Supplies the size of the allocation. - * - * @param Entry - * Supplies a pointer to the allocation entry. - * - * @return This routine does not return any value. - * - * @since XT 1.0 - */ -XTINLINE -VOID -MM::Allocator::VerifyRunLevel(IN MMPOOL_TYPE PoolType, - IN SIZE_T Bytes, - IN PVOID Entry) -{ - KRUNLEVEL RunLevel; - - /* Get current run level */ - RunLevel = KE::RunLevel::GetCurrentRunLevel(); - - /* Validate run level */ - if((PoolType & MM_POOL_TYPE_MASK) == PagedPool) - { - /* Paged pool runs up to APC level */ - if(RunLevel <= APC_LEVEL) - { - /* Run level is valid */ - return; - } - } - else - { - /* Non-paged pool runs up to DISPATCH_LEVEL */ - if(RunLevel <= DISPATCH_LEVEL) - { - /* Run level is valid */ - return; - } - } - - /* Invalid run level for specified pool, kernel panic */ - KE::Crash::Panic(0xC2, - (Entry ? MM_POOL_INVALID_FREE_RUNLEVEL : MM_POOL_INVALID_ALLOC_RUNLEVEL), - RunLevel, - PoolType, - (Entry ? (ULONG_PTR)Entry : Bytes)); -} diff --git a/xtoskrnl/mm/amd64/alloc.cc b/xtoskrnl/mm/amd64/pool.cc similarity index 87% rename from xtoskrnl/mm/amd64/alloc.cc rename to xtoskrnl/mm/amd64/pool.cc index bc2be3c..a3bef23 100644 --- a/xtoskrnl/mm/amd64/alloc.cc +++ b/xtoskrnl/mm/amd64/pool.cc @@ -1,8 +1,8 @@ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory - * FILE: xtoskrnl/mm/amd64/alloc.cc - * DESCRIPTION: Memory manager pool allocation + * FILE: xtoskrnl/mm/amd64/pool.cc + * DESCRIPTION: AMD64 Memory Manager pool manager * DEVELOPERS: Aiken Harris */ @@ -18,7 +18,7 @@ */ XTAPI VOID -MM::Allocator::MapNonPagedPool(VOID) +MM::Pool::MapNonPagedPool(VOID) { PMMMEMORY_LAYOUT MemoryLayout; diff --git a/xtoskrnl/mm/data.cc b/xtoskrnl/mm/data.cc index 0f57f01..fea9782 100644 --- a/xtoskrnl/mm/data.cc +++ b/xtoskrnl/mm/data.cc @@ -9,15 +9,6 @@ #include -/* PFN marking the initial non-paged pool end boundary */ -PFN_NUMBER MM::Allocator::NonPagedPoolFrameEnd; - -/* PFN marking the initial non-paged pool start boundary */ -PFN_NUMBER MM::Allocator::NonPagedPoolFrameStart; - -/* 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]; @@ -106,6 +97,15 @@ MMPFNLIST MM::Pfn::StandbyPagesList = {0, StandbyPageList, MAXULONG_PTR, MAXULON /* List containing free physical pages that have been zeroed out */ MMPFNLIST MM::Pfn::ZeroedPagesList = {0, ZeroedPageList, MAXULONG_PTR, MAXULONG_PTR}; +/* PFN marking the initial non-paged pool end boundary */ +PFN_NUMBER MM::Pool::NonPagedPoolFrameEnd; + +/* PFN marking the initial non-paged pool start boundary */ +PFN_NUMBER MM::Pool::NonPagedPoolFrameStart; + +/* Array of non-paged pool free list heads */ +LIST_ENTRY MM::Pool::NonPagedPoolFreeList[MM_MAX_FREE_PAGE_LIST_HEADS]; + /* Array of lists for available System PTEs, separated by pool type */ MMPTE MM::Pte::FirstSystemFreePte[MaximumPtePoolTypes]; diff --git a/xtoskrnl/mm/i686/alloc.cc b/xtoskrnl/mm/i686/pool.cc similarity index 84% rename from xtoskrnl/mm/i686/alloc.cc rename to xtoskrnl/mm/i686/pool.cc index 79b0abf..f54194e 100644 --- a/xtoskrnl/mm/i686/alloc.cc +++ b/xtoskrnl/mm/i686/pool.cc @@ -1,8 +1,8 @@ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory - * FILE: xtoskrnl/mm/i686/alloc.cc - * DESCRIPTION: Memory manager pool allocation + * FILE: xtoskrnl/mm/i686/pool.cc + * DESCRIPTION: I686 Memory Manager pool manager * DEVELOPERS: Aiken Harris */ @@ -18,7 +18,7 @@ */ XTAPI VOID -MM::Allocator::MapNonPagedPool(VOID) +MM::Pool::MapNonPagedPool(VOID) { PMMMEMORY_LAYOUT MemoryLayout; diff --git a/xtoskrnl/mm/mmgr.cc b/xtoskrnl/mm/mmgr.cc index bff8a7b..c3c54b1 100644 --- a/xtoskrnl/mm/mmgr.cc +++ b/xtoskrnl/mm/mmgr.cc @@ -260,7 +260,7 @@ MM::Manager::InitializeMemoryManager(VOID) MM::Pte::InitializeSystemPteSpace(); /* Initialize non-paged pool */ - MM::Allocator::InitializeNonPagedPool(); + MM::Pool::InitializeNonPagedPool(); /* Initialize PFN database */ MM::Pfn::InitializePfnDatabase(); @@ -269,7 +269,7 @@ MM::Manager::InitializeMemoryManager(VOID) MM::Pfn::InitializePfnBitmap(); /* Initialize paged pool */ - MM::Allocator::InitializePagedPool(); + MM::Pool::InitializePagedPool(); /* Flush TLB */ AR::CpuFunc::FlushTlb(); diff --git a/xtoskrnl/mm/pool.cc b/xtoskrnl/mm/pool.cc new file mode 100644 index 0000000..48f0abc --- /dev/null +++ b/xtoskrnl/mm/pool.cc @@ -0,0 +1,141 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: xtoskrnl/mm/pool.cc + * DESCRIPTION: Memory Manager pool manager + * DEVELOPERS: Aiken Harris + */ + +#include + + +/** + * Initializes the non-paged pool for memory allocator. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::Pool::InitializeNonPagedPool(VOID) +{ + PMMFREE_POOL_ENTRY FreePage, SetupPage; + PMMMEMORY_LAYOUT MemoryLayout; + 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 and set its size */ + FreePage = (PMMFREE_POOL_ENTRY)MemoryLayout->NonPagedPoolStart; + FreePage->Size = MemoryLayout->NonPagedPoolSize; + + /* 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 */ + RTL::LinkedList::InsertHeadList(&NonPagedPoolFreeList[Index], &FreePage->List); + + /* Create a free page for each page in the pool */ + SetupPage = FreePage; + for(Index = 0; Index < MemoryLayout->NonPagedPoolSize; Index++) + { + /* Initialize the owner for each page */ + SetupPage->Owner = FreePage; + SetupPage = (PMMFREE_POOL_ENTRY)((ULONG_PTR)SetupPage + MM_PAGE_SIZE); + } + + /* Store first and last allocated non-paged pool page */ + NonPagedPoolFrameStart = MM::Paging::GetPageFrameNumber(MM::Paging::GetPteAddress(MemoryLayout->NonPagedPoolStart)); + NonPagedPoolFrameEnd = MM::Paging::GetPageFrameNumber(MM::Paging::GetPteAddress(MemoryLayout->NonPagedPoolEnd)); + + /* Initialize system PTE pool for the non-paged expansion pool */ + Pte::InitializeSystemPtePool(Paging::GetNextPte(Paging::GetPteAddress(MemoryLayout->NonPagedExpansionPoolStart)), + MemoryLayout->NonPagedExpansionPoolSize - 2, + NonPagedPoolExpansion); +} + +/** + * Initializes the non-paged pool for memory allocator. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::Pool::InitializePagedPool(VOID) +{ + UNIMPLEMENTED; +} + +/** + * Validates the run level for the specified pool. If the run level is invalid, the kernel panics. + * + * @param PoolType + * Supplies the pool type. + * + * @param Bytes + * Supplies the size of the allocation. + * + * @param Entry + * Supplies a pointer to the allocation entry. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::Pool::VerifyRunLevel(IN MMPOOL_TYPE PoolType, + IN SIZE_T Bytes, + IN PVOID Entry) +{ + KRUNLEVEL RunLevel; + + /* Get current run level */ + RunLevel = KE::RunLevel::GetCurrentRunLevel(); + + /* Validate run level */ + if((PoolType & MM_POOL_TYPE_MASK) == PagedPool) + { + /* Paged pool runs up to APC level */ + if(RunLevel <= APC_LEVEL) + { + /* Run level is valid */ + return; + } + } + else + { + /* Non-paged pool runs up to DISPATCH_LEVEL */ + if(RunLevel <= DISPATCH_LEVEL) + { + /* Run level is valid */ + return; + } + } + + /* Invalid run level for specified pool, kernel panic */ + KE::Crash::Panic(0xC2, + (Entry ? MM_POOL_INVALID_FREE_RUNLEVEL : MM_POOL_INVALID_ALLOC_RUNLEVEL), + RunLevel, + PoolType, + (Entry ? (ULONG_PTR)Entry : Bytes)); +}