Implement PFN database initialization and memory descriptor processing
All checks were successful
Builds / ExectOS (amd64, debug) (push) Successful in 32s
Builds / ExectOS (i686, debug) (push) Successful in 31s
Builds / ExectOS (amd64, release) (push) Successful in 33s
Builds / ExectOS (i686, release) (push) Successful in 34s

This commit is contained in:
2025-12-28 23:25:07 +01:00
parent 4593a89a9b
commit 0880a0f344
12 changed files with 841 additions and 0 deletions

View File

@@ -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.
*