//
// ReactOS to NT Physical Page Descriptor Entry Legacy Mapping Definitions
//
-typedef union
-{
- MMPFN;// Pfn;
-
- struct
- {
- LIST_ENTRY ListEntry; // 0x000
- ULONG_PTR RmapListHead; // 0x008
- USHORT ReferenceCount; // 0x00C
- struct // 0x00$
- {
- USHORT _unused1:1;
- USHORT StartOfAllocation:1;
- USHORT EndOfAllocation:1;
- USHORT Zero:1;
- USHORT LockCount:4;
- USHORT Consumer:3;
- USHORT _unused2:1;
- USHORT Type:2;
- USHORT _unused3:1;
- USHORT _unused4:1;
- } Flags;
- LONG MapCount; // 0x10
- ULONG_PTR SavedSwapEntry; // 0x018
- };
-} PHYSICAL_PAGE, *PPHYSICAL_PAGE;
-
-C_ASSERT(sizeof(PHYSICAL_PAGE) == sizeof(MMPFN));
-
-#define MiInsertInListTail(x, y) MiInsertInListTail(x, (PMMPFN)y)
-//#define MiGetPfnEntry(Pfn) ((PPHYSICAL_PAGE)MiGetPfnEntry(Pfn))
-#define MiGetPfnEntryIndex(x) MiGetPfnEntryIndex((struct _MMPFN*)x)
-#define LockCount Flags.LockCount
-
-/* The first array contains ReactOS PFNs, the second contains ARM3 PFNs */
-PMMPFN MmPfnDatabase[2];
-#define MmPfnDatabase ((PPHYSICAL_PAGE*)MmPfnDatabase)
-
-//#define MMPFN PHYSICAL_PAGE
-//#define PMMPFN PPHYSICAL_PAGE
+// REACTOS NT
+//
+#define RmapListHead AweReferenceCount
+#define PHYSICAL_PAGE MMPFN
+#define PPHYSICAL_PAGE PMMPFN
/* The first array contains ReactOS PFNs, the second contains ARM3 PFNs */
-//PPHYSICAL_PAGE MmPfnDatabase[2];
+PPHYSICAL_PAGE MmPfnDatabase[2];
PFN_NUMBER MmAvailablePages;
PFN_NUMBER MmResidentAvailablePages;
+PFN_NUMBER MmResidentAvailableAtInit;
SIZE_T MmTotalCommitLimit;
SIZE_T MmTotalCommittedPages;
SIZE_T MmPeakCommitment;
SIZE_T MmtotalCommitLimitMaximum;
-static KEVENT ZeroPageThreadEvent;
+KEVENT ZeroPageThreadEvent;
static BOOLEAN ZeroPageThreadShouldTerminate = FALSE;
static RTL_BITMAP MiUserPfnBitMap;
RtlClearAllBits(&MiUserPfnBitMap);
}
-PFN_NUMBER
+PFN_TYPE
NTAPI
MmGetLRUFirstUserPage(VOID)
{
VOID
NTAPI
-MmInsertLRULastUserPage(PFN_NUMBER Pfn)
+MmInsertLRULastUserPage(PFN_TYPE Pfn)
{
KIRQL OldIrql;
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
}
-PFN_NUMBER
+PFN_TYPE
NTAPI
-MmGetLRUNextUserPage(PFN_NUMBER PreviousPfn)
+MmGetLRUNextUserPage(PFN_TYPE PreviousPfn)
{
ULONG Position;
KIRQL OldIrql;
VOID
NTAPI
-MmRemoveLRUUserPage(PFN_NUMBER Page)
+MmRemoveLRUUserPage(PFN_TYPE Page)
{
/* Unset the page as a user page */
RtlClearBit(&MiUserPfnBitMap, Page);
BOOLEAN
NTAPI
-MiIsPfnInUse(IN PMMPFN Pfn1)
+MiIsPfnFree(IN PMMPFN Pfn1)
{
- return ((Pfn1->u3.e1.PageLocation != FreePageList) &&
- (Pfn1->u3.e1.PageLocation != ZeroedPageList));
+ /* Must be a free or zero page, with no references, linked */
+ return ((Pfn1->u3.e1.PageLocation <= StandbyPageList) &&
+ (Pfn1->u1.Flink) &&
+ (Pfn1->u2.Blink) &&
+ !(Pfn1->u3.e2.ReferenceCount));
}
-PFN_NUMBER
+BOOLEAN
NTAPI
-MiFindContiguousPages(IN PFN_NUMBER LowestPfn,
- IN PFN_NUMBER HighestPfn,
- IN PFN_NUMBER BoundaryPfn,
- IN PFN_NUMBER SizeInPages,
- IN MEMORY_CACHING_TYPE CacheType)
+MiIsPfnInUse(IN PMMPFN Pfn1)
{
- PFN_NUMBER Page, PageCount, LastPage, Length, BoundaryMask;
- ULONG i = 0;
- PMMPFN Pfn1, EndPfn;
- KIRQL OldIrql;
- PAGED_CODE ();
- ASSERT(SizeInPages != 0);
-
- //
- // Convert the boundary PFN into an alignment mask
- //
- BoundaryMask = ~(BoundaryPfn - 1);
-
- //
- // Loop all the physical memory blocks
- //
- do
- {
- //
- // Capture the base page and length of this memory block
- //
- Page = MmPhysicalMemoryBlock->Run[i].BasePage;
- PageCount = MmPhysicalMemoryBlock->Run[i].PageCount;
-
- //
- // Check how far this memory block will go
- //
- LastPage = Page + PageCount;
-
- //
- // Trim it down to only the PFNs we're actually interested in
- //
- if ((LastPage - 1) > HighestPfn) LastPage = HighestPfn + 1;
- if (Page < LowestPfn) Page = LowestPfn;
-
- //
- // Skip this run if it's empty or fails to contain all the pages we need
- //
- if (!(PageCount) || ((Page + SizeInPages) > LastPage)) continue;
-
- //
- // Now scan all the relevant PFNs in this run
- //
- Length = 0;
- for (Pfn1 = MiGetPfnEntry(Page); Page < LastPage; Page++, Pfn1++)
- {
- //
- // If this PFN is in use, ignore it
- //
- if (MiIsPfnInUse(Pfn1)) continue;
-
- //
- // If we haven't chosen a start PFN yet and the caller specified an
- // alignment, make sure the page matches the alignment restriction
- //
- if ((!(Length) && (BoundaryPfn)) &&
- (((Page ^ (Page + SizeInPages - 1)) & BoundaryMask)))
- {
- //
- // It does not, so bail out
- //
- continue;
- }
-
- //
- // Increase the number of valid pages, and check if we have enough
- //
- if (++Length == SizeInPages)
- {
- //
- // It appears we've amassed enough legitimate pages, rollback
- //
- Pfn1 -= (Length - 1);
- Page -= (Length - 1);
-
- //
- // Acquire the PFN lock
- //
- OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
- do
- {
- //
- // Things might've changed for us. Is the page still free?
- //
- if (MiIsPfnInUse(Pfn1)) break;
-
- //
- // So far so good. Is this the last confirmed valid page?
- //
- if (!--Length)
- {
- //
- // Sanity check that we didn't go out of bounds
- //
- ASSERT(i != MmPhysicalMemoryBlock->NumberOfRuns);
-
- //
- // Loop until all PFN entries have been processed
- //
- EndPfn = Pfn1 - SizeInPages + 1;
- do
- {
- //
- // This PFN is now a used page, set it up
- //
- MiUnlinkFreeOrZeroedPage(Pfn1);
- Pfn1->u3.e2.ReferenceCount = 1;
-
- //
- // Check if it was already zeroed
- //
- if (Pfn1->u3.e1.PageLocation != ZeroedPageList)
- {
- //
- // It wasn't, so zero it
- //
- MiZeroPage(MiGetPfnEntryIndex(Pfn1));
- }
-
- //
- // Mark it in use
- //
- Pfn1->u3.e1.PageLocation = ActiveAndValid;
-
- //
- // Check if this is the last PFN, otherwise go on
- //
- if (Pfn1 == EndPfn) break;
- Pfn1--;
- } while (TRUE);
-
- //
- // Mark the first and last PFN so we can find them later
- //
- Pfn1->u3.e1.StartOfAllocation = 1;
- (Pfn1 + SizeInPages - 1)->u3.e1.EndOfAllocation = 1;
-
- //
- // Now it's safe to let go of the PFN lock
- //
- KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
-
- //
- // Quick sanity check that the last PFN is consistent
- //
- EndPfn = Pfn1 + SizeInPages;
- ASSERT(EndPfn == MiGetPfnEntry(Page + 1));
-
- //
- // Compute the first page, and make sure it's consistent
- //
- Page -= SizeInPages - 1;
- ASSERT(Pfn1 == MiGetPfnEntry(Page));
- ASSERT(Page != 0);
- return Page;
- }
-
- //
- // Keep going. The purpose of this loop is to reconfirm that
- // after acquiring the PFN lock these pages are still usable
- //
- Pfn1++;
- Page++;
- } while (TRUE);
-
- //
- // If we got here, something changed while we hadn't acquired
- // the PFN lock yet, so we'll have to restart
- //
- KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
- Length = 0;
- }
- }
- } while (++i != MmPhysicalMemoryBlock->NumberOfRuns);
-
- //
- // And if we get here, it means no suitable physical memory runs were found
- //
- return 0;
+ /* Standby list or higher, unlinked, and with references */
+ return !MiIsPfnFree(Pfn1);
}
PMDL
PFN_NUMBER PageCount, LowPage, HighPage, SkipPages, PagesFound = 0, Page;
PPFN_NUMBER MdlPage, LastMdlPage;
KIRQL OldIrql;
- PMMPFN Pfn1;
+ PPHYSICAL_PAGE Pfn1;
INT LookForZeroedPages;
ASSERT (KeGetCurrentIrql() <= APC_LEVEL);
MmDumpPfnDatabase(VOID)
{
ULONG i;
- PMMPFN Pfn1;
+ PPHYSICAL_PAGE Pfn1;
PCHAR State = "????", Type = "Unknown";
KIRQL OldIrql;
ULONG Totals[5] = {0}, FreePages = 0;
State,
Type,
Pfn1->u3.e2.ReferenceCount,
- ((PPHYSICAL_PAGE)Pfn1)->RmapListHead);
+ Pfn1->RmapListHead);
}
DbgPrint("Nonpaged Pool: %d pages\t[%d KB]\n", Totals[MC_NPPOOL], (Totals[MC_NPPOOL] << PAGE_SHIFT) / 1024);
PMEMORY_ALLOCATION_DESCRIPTOR Md;
PLIST_ENTRY NextEntry;
ULONG NrSystemPages = 0;
+ KIRQL OldIrql;
/* This is what a used page looks like */
RtlZeroMemory(&UsedPage, sizeof(UsedPage));
UsedPage.u3.e1.PageLocation = ActiveAndValid;
UsedPage.u3.e2.ReferenceCount = 1;
+ /* Lock PFN database */
+ OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
+
/* Loop the memory descriptors */
for (NextEntry = KeLoaderBlock->MemoryDescriptorListHead.Flink;
NextEntry != &KeLoaderBlock->MemoryDescriptorListHead;
MmPfnDatabase[0][i] = UsedPage;
NrSystemPages++;
}
+
+ /* Release the PFN database lock */
+ KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
KeInitializeEvent(&ZeroPageThreadEvent, NotificationEvent, TRUE);
DPRINT("Pages: %x %x\n", MmAvailablePages, NrSystemPages);
VOID
NTAPI
-MmSetRmapListHeadPage(PFN_NUMBER Pfn, struct _MM_RMAP_ENTRY* ListHead)
+MmSetRmapListHeadPage(PFN_TYPE Pfn, struct _MM_RMAP_ENTRY* ListHead)
{
KIRQL oldIrql;
oldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
- ((PPHYSICAL_PAGE)MiGetPfnEntry(Pfn))->RmapListHead = (LONG_PTR)ListHead;
+ MiGetPfnEntry(Pfn)->RmapListHead = (LONG)ListHead;
KeReleaseQueuedSpinLock(LockQueuePfnLock, oldIrql);
}
struct _MM_RMAP_ENTRY*
NTAPI
-MmGetRmapListHeadPage(PFN_NUMBER Pfn)
+MmGetRmapListHeadPage(PFN_TYPE Pfn)
{
KIRQL oldIrql;
struct _MM_RMAP_ENTRY* ListHead;
oldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
- ListHead = (struct _MM_RMAP_ENTRY*)((PPHYSICAL_PAGE)MiGetPfnEntry(Pfn))->RmapListHead;
+ ListHead = (struct _MM_RMAP_ENTRY*)MiGetPfnEntry(Pfn)->RmapListHead;
KeReleaseQueuedSpinLock(LockQueuePfnLock, oldIrql);
return(ListHead);
VOID
NTAPI
-MmSetSavedSwapEntryPage(PFN_NUMBER Pfn, SWAPENTRY SwapEntry)
+MmSetSavedSwapEntryPage(PFN_TYPE Pfn, SWAPENTRY SwapEntry)
{
KIRQL oldIrql;
SWAPENTRY
NTAPI
-MmGetSavedSwapEntryPage(PFN_NUMBER Pfn)
+MmGetSavedSwapEntryPage(PFN_TYPE Pfn)
{
SWAPENTRY SwapEntry;
KIRQL oldIrql;
VOID
NTAPI
-MmReferencePage(PFN_NUMBER Pfn)
+MmReferencePage(PFN_TYPE Pfn)
{
PPHYSICAL_PAGE Page;
return;
}
- Page = (PVOID)MiGetPfnEntry(Pfn);
+ Page = MiGetPfnEntry(Pfn);
ASSERT(Page);
Page->u3.e2.ReferenceCount++;
ULONG
NTAPI
-MmGetReferenceCountPage(PFN_NUMBER Pfn)
+MmGetReferenceCountPage(PFN_TYPE Pfn)
{
KIRQL oldIrql;
ULONG RCount;
DPRINT("MmGetReferenceCountPage(PhysicalAddress %x)\n", Pfn << PAGE_SHIFT);
oldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
- Page = (PVOID)MiGetPfnEntry(Pfn);
+ Page = MiGetPfnEntry(Pfn);
ASSERT(Page);
RCount = Page->u3.e2.ReferenceCount;
BOOLEAN
NTAPI
-MmIsPageInUse(PFN_NUMBER Pfn)
+MmIsPageInUse(PFN_TYPE Pfn)
{
return MiIsPfnInUse(MiGetPfnEntry(Pfn));
}
VOID
NTAPI
-MiSetConsumer(IN PFN_NUMBER Pfn,
+MiSetConsumer(IN PFN_TYPE Pfn,
IN ULONG Type)
{
MiGetPfnEntry(Pfn)->u3.e1.PageLocation = ActiveAndValid;
VOID
NTAPI
-MmDereferencePage(PFN_NUMBER Pfn)
+MmDereferencePage(PFN_TYPE Pfn)
{
PPHYSICAL_PAGE Page;
DPRINT("MmDereferencePage(PhysicalAddress %x)\n", Pfn << PAGE_SHIFT);
- Page = (PVOID)MiGetPfnEntry(Pfn);
+ Page = MiGetPfnEntry(Pfn);
ASSERT(Page);
Page->u3.e2.ReferenceCount--;
}
}
-PFN_NUMBER
+PFN_TYPE
NTAPI
MmAllocPage(ULONG Type)
{
- PFN_NUMBER PfnOffset;
+ PFN_TYPE PfnOffset;
PPHYSICAL_PAGE PageDescriptor;
BOOLEAN NeedClear = FALSE;
DPRINT1("MmAllocPage(): Out of memory\n");
return 0;
}
- PageDescriptor = (PVOID)MiRemoveHeadList(&MmFreePageListHead);
+ PageDescriptor = MiRemoveHeadList(&MmFreePageListHead);
NeedClear = TRUE;
}
else
{
- PageDescriptor = (PVOID)MiRemoveHeadList(&MmZeroedPageListHead);
+ PageDescriptor = MiRemoveHeadList(&MmZeroedPageListHead);
}
PageDescriptor->u3.e2.ReferenceCount = 1;
NTSTATUS
NTAPI
-MiZeroPage(PFN_NUMBER Page)
+MiZeroPage(PFN_TYPE Page)
{
KIRQL Irql;
PVOID TempAddress;
NTSTATUS Status;
KIRQL oldIrql;
PPHYSICAL_PAGE PageDescriptor;
- PFN_NUMBER Pfn;
+ PFN_TYPE Pfn;
ULONG Count;
/* Free initial kernel memory */
oldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
while (MmFreePageListHead.Total)
{
- PageDescriptor = (PVOID)MiRemoveHeadList(&MmFreePageListHead);
+ PageDescriptor = MiRemoveHeadList(&MmFreePageListHead);
/* We set the page to used, because MmCreateVirtualMapping failed with unused pages */
KeReleaseQueuedSpinLock(LockQueuePfnLock, oldIrql);
Pfn = PageDescriptor - MmPfnDatabase[0];