Implement basic non-paged pool allocator
Some checks failed
Builds / ExectOS (i686, debug) (push) Failing after 22s
Builds / ExectOS (amd64, debug) (push) Failing after 23s
Builds / ExectOS (i686, release) (push) Failing after 30s
Builds / ExectOS (amd64, release) (push) Failing after 32s

This commit is contained in:
2026-02-26 20:10:03 +01:00
parent 5778a761b5
commit 7bdd0dfe2c
3 changed files with 182 additions and 4 deletions

View File

@@ -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;
}
/**

View File

@@ -9,6 +9,9 @@
#include <xtos.hh>
/* 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];