[NTOS]: Enable usage of ARM3 paged pool, up until Mm Phase 2.
[reactos.git] / reactos / ntoskrnl / mm / freelist.c
index 894fb23..c3156ec 100644 (file)
 #define MODULE_INVOLVED_IN_ARM3
 #include "ARM3/miarm.h"
 
-/* TYPES *******************************************************************/
-
-#define MM_PHYSICAL_PAGE_FREE    (0x1)
-#define MM_PHYSICAL_PAGE_USED    (0x2)
-
 /* GLOBALS ****************************************************************/
 
 //
 //
 // ReactOS to NT Physical Page Descriptor Entry Legacy Mapping Definitions
 //
+//        REACTOS                 NT
+//
+#define RmapListHead         AweReferenceCount
+#define PHYSICAL_PAGE        MMPFN
+#define PPHYSICAL_PAGE       PMMPFN
 
-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 MiGetPfnEntry(Pfn) ((PPHYSICAL_PAGE)MiGetPfnEntry(Pfn))
-#define MiGetPfnEntryIndex(x) MiGetPfnEntryIndex((struct _MMPFN*)x)
-#define LockCount            Flags.LockCount
-
-PMMPFN MmPfnDatabase;
-#define MmPfnDatabase ((PPHYSICAL_PAGE)MmPfnDatabase)
-
-#define MMPFN PHYSICAL_PAGE
-#define PMMPFN PPHYSICAL_PAGE
+PPHYSICAL_PAGE MmPfnDatabase;
 
-ULONG MmAvailablePages;
-ULONG MmResidentAvailablePages;
+PFN_NUMBER MmAvailablePages;
+PFN_NUMBER MmResidentAvailablePages;
+PFN_NUMBER MmResidentAvailableAtInit;
 
 SIZE_T MmTotalCommitLimit;
 SIZE_T MmTotalCommittedPages;
@@ -81,294 +45,105 @@ SIZE_T MmSharedCommit;
 SIZE_T MmDriverCommit;
 SIZE_T MmProcessCommit;
 SIZE_T MmPagedPoolCommit;
-SIZE_T MmPeakCommitment;
+SIZE_T MmPeakCommitment; 
 SIZE_T MmtotalCommitLimitMaximum;
 
-MMPFNLIST MmZeroedPageListHead;
-MMPFNLIST MmFreePageListHead;
-MMPFNLIST MmStandbyPageListHead;
-MMPFNLIST MmModifiedPageListHead;
-MMPFNLIST MmModifiedNoWritePageListHead;
-
-/* List of pages allocated to the MC_USER Consumer */
-static LIST_ENTRY UserPageListHead;
-/* List of pages zeroed by the ZPW (MmZeroPageThreadMain) */
-static LIST_ENTRY FreeZeroedPageListHead;
-/* List of free pages, filled by MmGetReferenceCountPage and
- * and MmInitializePageList */
-static LIST_ENTRY FreeUnzeroedPageListHead;
-
-static KEVENT ZeroPageThreadEvent;
+KEVENT ZeroPageThreadEvent;
 static BOOLEAN ZeroPageThreadShouldTerminate = FALSE;
-
-static ULONG UnzeroedPageCount = 0;
+static RTL_BITMAP MiUserPfnBitMap;
 
 /* FUNCTIONS *************************************************************/
 
-PFN_NUMBER
+VOID
 NTAPI
-MmGetLRUFirstUserPage(VOID)
+MiInitializeUserPfnBitmap(VOID)
 {
-   PLIST_ENTRY NextListEntry;
-   PHYSICAL_PAGE* PageDescriptor;
-   KIRQL oldIrql;
+    PVOID Bitmap;
+    
+    /* Allocate enough buffer for the PFN bitmap and align it on 32-bits */
+    Bitmap = ExAllocatePoolWithTag(NonPagedPool,
+                                   (((MmHighestPhysicalPage + 1) + 31) / 32) * 4,
+                                   '  mM');
+    ASSERT(Bitmap);
+
+    /* Initialize it and clear all the bits to begin with */
+    RtlInitializeBitMap(&MiUserPfnBitMap,
+                        Bitmap,
+                        MmHighestPhysicalPage + 1);
+    RtlClearAllBits(&MiUserPfnBitMap);
+}
 
-   oldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
-   NextListEntry = UserPageListHead.Flink;
-   if (NextListEntry == &UserPageListHead)
-   {
-         KeReleaseQueuedSpinLock(LockQueuePfnLock, oldIrql);
-      return 0;
-   }
-   PageDescriptor = CONTAINING_RECORD(NextListEntry, PHYSICAL_PAGE, ListEntry);
-   ASSERT_PFN(&PageDescriptor->Pfn);
-   KeReleaseQueuedSpinLock(LockQueuePfnLock, oldIrql);
-   return PageDescriptor - MmPfnDatabase;
+PFN_TYPE
+NTAPI
+MmGetLRUFirstUserPage(VOID)
+{
+    ULONG Position;
+    KIRQL OldIrql;
+    
+    /* Find the first user page */
+    OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
+    Position = RtlFindSetBits(&MiUserPfnBitMap, 1, 0);
+    KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
+    if (Position == 0xFFFFFFFF) return 0;
+    
+    /* Return it */
+    return Position;
 }
 
 VOID
 NTAPI
-MmInsertLRULastUserPage(PFN_NUMBER Pfn)
+MmInsertLRULastUserPage(PFN_TYPE Pfn)
 {
-   KIRQL oldIrql;
-   PPHYSICAL_PAGE Page;
+    KIRQL OldIrql;
 
-   oldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
-   Page = MiGetPfnEntry(Pfn);
-   ASSERT(Page);
-   ASSERT(Page->Flags.Type == MM_PHYSICAL_PAGE_USED);
-   ASSERT(Page->Flags.Consumer == MC_USER);
-   InsertTailList(&UserPageListHead, &Page->ListEntry);
-   KeReleaseQueuedSpinLock(LockQueuePfnLock, oldIrql);
+    /* Set the page as a user page */
+    OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
+    RtlSetBit(&MiUserPfnBitMap, Pfn);
+    KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
 }
 
-PFN_NUMBER
+PFN_TYPE
 NTAPI
-MmGetLRUNextUserPage(PFN_NUMBER PreviousPfn)
+MmGetLRUNextUserPage(PFN_TYPE PreviousPfn)
 {
-   PLIST_ENTRY NextListEntry;
-   PHYSICAL_PAGE* PageDescriptor;
-   KIRQL oldIrql;
-   PPHYSICAL_PAGE Page;
-
-   oldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
-   Page = MiGetPfnEntry(PreviousPfn);
-   ASSERT(Page);
-   ASSERT(Page->Flags.Type == MM_PHYSICAL_PAGE_USED);
-   ASSERT(Page->Flags.Consumer == MC_USER);
-   NextListEntry = (PLIST_ENTRY)Page->ListEntry.Flink;
-   if (NextListEntry == &UserPageListHead)
-   {
-         KeReleaseQueuedSpinLock(LockQueuePfnLock, oldIrql);
-      return 0;
-   }
-   PageDescriptor = CONTAINING_RECORD(NextListEntry, PHYSICAL_PAGE, ListEntry);
-   KeReleaseQueuedSpinLock(LockQueuePfnLock, oldIrql);
-   return PageDescriptor - MmPfnDatabase;
+    ULONG Position;
+    KIRQL OldIrql;
+    
+    /* Find the next user page */
+    OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
+    Position = RtlFindSetBits(&MiUserPfnBitMap, 1, PreviousPfn + 1);
+    KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
+    if (Position == 0xFFFFFFFF) return 0;
+    
+    /* Return it */
+    return Position;
 }
 
 VOID
 NTAPI
-MmRemoveLRUUserPage(PFN_NUMBER Page)
+MmRemoveLRUUserPage(PFN_TYPE Page)
 {
-   RemoveEntryList(&MiGetPfnEntry(Page)->ListEntry);
+    /* Unset the page as a user page */
+    RtlClearBit(&MiUserPfnBitMap, Page);
 }
 
-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)
+MiIsPfnFree(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 (Pfn1->Flags.Type != MM_PHYSICAL_PAGE_FREE) 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 (Pfn1->Flags.Type != MM_PHYSICAL_PAGE_FREE) 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
-                        {
-                            //
-                            // If this was an unzeroed page, there are now less
-                            //
-                            if (Pfn1->Flags.Zero == 0) UnzeroedPageCount--;
-                            
-                            //
-                            // One less free page
-                            //
-                            MmAvailablePages--;
-                            
-                            //
-                            // This PFN is now a used page, set it up
-                            //
-                            RemoveEntryList(&Pfn1->ListEntry);
-                            Pfn1->Flags.Type = MM_PHYSICAL_PAGE_USED;
-                            Pfn1->Flags.Consumer = MC_NPPOOL;
-                            Pfn1->ReferenceCount = 1;
-                            Pfn1->LockCount = 0;
-                            Pfn1->SavedSwapEntry = 0;
-                            
-                            //
-                            // Check if it was already zeroed
-                            //
-                            if (Pfn1->Flags.Zero == 0)
-                            {
-                                //
-                                // It wasn't, so zero it
-                                //
-                                MiZeroPage(MiGetPfnEntryIndex(Pfn1));
-                            }
+    /* 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));
+}
 
-                            //
-                            // 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->Flags.StartOfAllocation = 1;
-                        (Pfn1 + SizeInPages - 1)->Flags.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;    
+BOOLEAN
+NTAPI
+MiIsPfnInUse(IN PMMPFN Pfn1)
+{
+    /* Standby list or higher, unlinked, and with references */
+    return !MiIsPfnFree(Pfn1);
 }
 
 PMDL
@@ -384,7 +159,6 @@ MiAllocatePagesForMdl(IN PHYSICAL_ADDRESS LowAddress,
     PFN_NUMBER PageCount, LowPage, HighPage, SkipPages, PagesFound = 0, Page;
     PPFN_NUMBER MdlPage, LastMdlPage;
     KIRQL OldIrql;
-    PLIST_ENTRY ListEntry;
     PPHYSICAL_PAGE Pfn1;
     INT LookForZeroedPages;
     ASSERT (KeGetCurrentIrql() <= APC_LEVEL);
@@ -455,20 +229,19 @@ MiAllocatePagesForMdl(IN PHYSICAL_ADDRESS LowAddress,
             //
             // Do we have zeroed pages?
             //
-            if (!IsListEmpty(&FreeZeroedPageListHead))
+            if (MmZeroedPageListHead.Total)
             {
                 //
                 // Grab a zero page
                 //
-                ListEntry = RemoveTailList(&FreeZeroedPageListHead);
+                Pfn1 = MiRemoveHeadList(&MmZeroedPageListHead);
             }
-            else if (!IsListEmpty(&FreeUnzeroedPageListHead))
+            else if (MmFreePageListHead.Total)
             {
                 //
                 // Nope, grab an unzeroed page
                 //
-                ListEntry = RemoveTailList(&FreeUnzeroedPageListHead);
-                UnzeroedPageCount--;
+                Pfn1 = MiRemoveHeadList(&MmFreePageListHead);
             }
             else
             {
@@ -479,27 +252,18 @@ MiAllocatePagesForMdl(IN PHYSICAL_ADDRESS LowAddress,
                 break;
             }
             
-            //
-            // Get the PFN entry for this page
-            //
-            Pfn1 = CONTAINING_RECORD(ListEntry, PHYSICAL_PAGE, ListEntry);
-            
             //
             // Make sure it's really free
             //
-            ASSERT(Pfn1->Flags.Type == MM_PHYSICAL_PAGE_FREE);
-            ASSERT(Pfn1->ReferenceCount == 0);
+            ASSERT(MiIsPfnInUse(Pfn1) == FALSE);
+            ASSERT(Pfn1->u3.e2.ReferenceCount == 0);
             
             //
             // Allocate it and mark it
             //
-            Pfn1->Flags.Type = MM_PHYSICAL_PAGE_USED;
-            Pfn1->Flags.Consumer = MC_NPPOOL;
-            Pfn1->Flags.StartOfAllocation = 1;
-            Pfn1->Flags.EndOfAllocation = 1;
-            Pfn1->ReferenceCount = 1;
-            Pfn1->LockCount = 0;
-            Pfn1->SavedSwapEntry = 0;
+            Pfn1->u3.e1.StartOfAllocation = 1;
+            Pfn1->u3.e1.EndOfAllocation = 1;
+            Pfn1->u3.e2.ReferenceCount = 1;
             
             //
             // Decrease available pages
@@ -534,30 +298,21 @@ MiAllocatePagesForMdl(IN PHYSICAL_ADDRESS LowAddress,
                 //
                 // Make sure it's free and if this is our first pass, zeroed
                 //
-                if (Pfn1->Flags.Type != MM_PHYSICAL_PAGE_FREE) continue;
-                if (Pfn1->Flags.Zero != LookForZeroedPages) continue;
+                if (MiIsPfnInUse(Pfn1)) continue;
+                if ((Pfn1->u3.e1.PageLocation == ZeroedPageList) != LookForZeroedPages) continue;
                 
                 //
                 // Sanity checks
                 //
-                ASSERT(Pfn1->ReferenceCount == 0);
+                ASSERT(Pfn1->u3.e2.ReferenceCount == 0);
                 
                 //
                 // Now setup the page and mark it
                 //
-                Pfn1->Flags.Type = MM_PHYSICAL_PAGE_USED;
-                Pfn1->Flags.Consumer = MC_NPPOOL;
-                Pfn1->ReferenceCount = 1;
-                Pfn1->Flags.StartOfAllocation = 1;
-                Pfn1->Flags.EndOfAllocation = 1;
-                Pfn1->LockCount = 0;
-                Pfn1->SavedSwapEntry = 0;
-                
-                //
-                // If this page was unzeroed, we've consumed such a page
-                //
-                if (!Pfn1->Flags.Zero) UnzeroedPageCount--;
-                
+                Pfn1->u3.e2.ReferenceCount = 1;
+                Pfn1->u3.e1.StartOfAllocation = 1;
+                Pfn1->u3.e1.EndOfAllocation = 1;
+                                
                 //
                 // Decrease available pages
                 //
@@ -624,7 +379,8 @@ MiAllocatePagesForMdl(IN PHYSICAL_ADDRESS LowAddress,
         //
         Pfn1 = MiGetPfnEntry(Page);
         ASSERT(Pfn1);
-        if (Pfn1->Flags.Zero == 0) MiZeroPage(Page);
+        if (Pfn1->u3.e1.PageLocation != ZeroedPageList) MiZeroPage(Page);
+        Pfn1->u3.e1.PageLocation = ActiveAndValid;
     }
     
     //
@@ -641,7 +397,7 @@ MmDumpPfnDatabase(VOID)
 {
     ULONG i;
     PPHYSICAL_PAGE Pfn1;
-    PCHAR State = "????", Consumer = "Unknown";
+    PCHAR State = "????", Type = "Unknown";
     KIRQL OldIrql;
     ULONG Totals[5] = {0}, FreePages = 0;
     
@@ -656,69 +412,33 @@ MmDumpPfnDatabase(VOID)
         if (!Pfn1) continue;
         
         //
-        // Get the consumer
+        // Get the type
         //
-        switch (Pfn1->Flags.Consumer)
+        if (MiIsPfnInUse(Pfn1))
         {
-            case MC_NPPOOL:
-                
-                Consumer = "Nonpaged Pool";
-                break;
-                
-            case MC_PPOOL:
-                
-                Consumer = "Paged Pool";
-                break;
-                
-            case MC_CACHE:
-                
-                Consumer = "File System Cache";
-                break;
-                
-            case MC_USER:
-                
-                Consumer = "Process Working Set";
-                break;
-                
-            case MC_SYSTEM:
-                
-                Consumer = "System";
-                break;
+            State = "Used";
         }
-        
-        //
-        // Get the type
-        //
-        switch (Pfn1->Flags.Type)
+        else
         {
-            case MM_PHYSICAL_PAGE_USED:
-                
-                State = "Used";
-                Totals[Pfn1->Flags.Consumer]++;
-                break;
-                
-            case MM_PHYSICAL_PAGE_FREE:
-                
-                State = "Free";
-                Consumer = "Free";
-                FreePages++;
-                break;
+            State = "Free";
+            Type = "Free";
+            FreePages++;
+            break;
         }
-
+        
         //
         // Pretty-print the page
         //
-        DbgPrint("0x%08p:\t%04s\t%20s\t(%02d.%02d) [%08p])\n",
+        DbgPrint("0x%08p:\t%04s\t%20s\t(%02d) [%08p])\n",
                  i << PAGE_SHIFT,
                  State,
-                 Consumer,
-                 Pfn1->ReferenceCount,
-                 Pfn1->LockCount,
+                 Type,
+                 Pfn1->u3.e2.ReferenceCount,
                  Pfn1->RmapListHead);
     }
     
     DbgPrint("Nonpaged Pool:       %d pages\t[%d KB]\n", Totals[MC_NPPOOL], (Totals[MC_NPPOOL] << PAGE_SHIFT) / 1024);
-    DbgPrint("Paged Pool:          %d pages\t[%d KB]\n", Totals[MC_PPOOL],  (Totals[MC_PPOOL] << PAGE_SHIFT) / 1024);
+    DbgPrint("Paged Pool:          %d pages\t[%d KB]\n", Totals[MC_PPOOL],  (Totals[MC_PPOOL]  << PAGE_SHIFT) / 1024);
     DbgPrint("File System Cache:   %d pages\t[%d KB]\n", Totals[MC_CACHE],  (Totals[MC_CACHE]  << PAGE_SHIFT) / 1024);
     DbgPrint("Process Working Set: %d pages\t[%d KB]\n", Totals[MC_USER],   (Totals[MC_USER]   << PAGE_SHIFT) / 1024);
     DbgPrint("System:              %d pages\t[%d KB]\n", Totals[MC_SYSTEM], (Totals[MC_SYSTEM] << PAGE_SHIFT) / 1024);
@@ -729,104 +449,18 @@ MmDumpPfnDatabase(VOID)
 
 VOID
 NTAPI
-MmInitializePageList(VOID)
-{
-    ULONG i;
-    PHYSICAL_PAGE UsedPage;
-    PMEMORY_ALLOCATION_DESCRIPTOR Md;
-    PLIST_ENTRY NextEntry;
-    ULONG NrSystemPages = 0;
-
-    /* Initialize the page lists */
-    InitializeListHead(&UserPageListHead);
-    InitializeListHead(&FreeUnzeroedPageListHead);
-    InitializeListHead(&FreeZeroedPageListHead);
-
-    /* This is what a used page looks like */
-    RtlZeroMemory(&UsedPage, sizeof(UsedPage));
-    UsedPage.Flags.Type = MM_PHYSICAL_PAGE_USED;
-    UsedPage.Flags.Consumer = MC_NPPOOL;
-    UsedPage.ReferenceCount = 1;
-
-    /* Loop the memory descriptors */
-    for (NextEntry = KeLoaderBlock->MemoryDescriptorListHead.Flink;
-         NextEntry != &KeLoaderBlock->MemoryDescriptorListHead;
-         NextEntry = NextEntry->Flink)
-    {
-        /* Get the descriptor */
-        Md = CONTAINING_RECORD(NextEntry,
-                               MEMORY_ALLOCATION_DESCRIPTOR,
-                               ListEntry);
-
-        /* Skip bad memory */
-        if ((Md->MemoryType == LoaderFirmwarePermanent) ||
-            (Md->MemoryType == LoaderBBTMemory) ||
-            (Md->MemoryType == LoaderSpecialMemory) ||
-            (Md->MemoryType == LoaderBad))
-        {
-            //
-            // We do not build PFN entries for this
-            //
-            continue;
-        }
-        else if ((Md->MemoryType == LoaderFree) ||
-                 (Md->MemoryType == LoaderLoadedProgram) ||
-                 (Md->MemoryType == LoaderFirmwareTemporary) ||
-                 (Md->MemoryType == LoaderOsloaderStack))
-        {
-            /* Loop every page part of the block */
-            for (i = 0; i < Md->PageCount; i++)
-            {
-                /* Mark it as a free page */
-                MmPfnDatabase[Md->BasePage + i].Flags.Type = MM_PHYSICAL_PAGE_FREE;
-                InsertTailList(&FreeUnzeroedPageListHead,
-                               &MmPfnDatabase[Md->BasePage + i].ListEntry);
-                UnzeroedPageCount++;
-                MmAvailablePages++;
-            }
-        }
-        else
-        {
-            /* Loop every page part of the block */
-            for (i = 0; i < Md->PageCount; i++)
-            {
-                /* Everything else is used memory */
-                MmPfnDatabase[Md->BasePage + i] = UsedPage;
-                NrSystemPages++;
-            }
-        }
-    }
-    
-    /* Finally handle the pages describing the PFN database themselves */
-    for (i = MxOldFreeDescriptor.BasePage; i < MxFreeDescriptor->BasePage; i++)
-    {
-        /* Ensure this page was not added previously */
-        ASSERT(MmPfnDatabase[i].Flags.Type == 0);
-
-        /* Mark it as used kernel memory */
-        MmPfnDatabase[i] = UsedPage;
-        NrSystemPages++;
-    }
-    
-    KeInitializeEvent(&ZeroPageThreadEvent, NotificationEvent, TRUE);
-    DPRINT("Pages: %x %x\n", MmAvailablePages, NrSystemPages);
-    MmInitializeBalancer(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);
-   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;
@@ -840,24 +474,24 @@ MmGetRmapListHeadPage(PFN_NUMBER Pfn)
 
 VOID
 NTAPI
-MmSetSavedSwapEntryPage(PFN_NUMBER Pfn,  SWAPENTRY SwapEntry)
+MmSetSavedSwapEntryPage(PFN_TYPE Pfn,  SWAPENTRY SwapEntry)
 {
    KIRQL oldIrql;
 
    oldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
-   MiGetPfnEntry(Pfn)->SavedSwapEntry = SwapEntry;
+   MiGetPfnEntry(Pfn)->u1.WsIndex = SwapEntry;
    KeReleaseQueuedSpinLock(LockQueuePfnLock, oldIrql);
 }
 
 SWAPENTRY
 NTAPI
-MmGetSavedSwapEntryPage(PFN_NUMBER Pfn)
+MmGetSavedSwapEntryPage(PFN_TYPE Pfn)
 {
    SWAPENTRY SwapEntry;
    KIRQL oldIrql;
 
    oldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
-   SwapEntry = MiGetPfnEntry(Pfn)->SavedSwapEntry;
+   SwapEntry = MiGetPfnEntry(Pfn)->u1.WsIndex;
    KeReleaseQueuedSpinLock(LockQueuePfnLock, oldIrql);
 
    return(SwapEntry);
@@ -865,7 +499,7 @@ MmGetSavedSwapEntryPage(PFN_NUMBER Pfn)
 
 VOID
 NTAPI
-MmReferencePage(PFN_NUMBER Pfn)
+MmReferencePage(PFN_TYPE Pfn)
 {
    PPHYSICAL_PAGE Page;
 
@@ -878,18 +512,13 @@ MmReferencePage(PFN_NUMBER Pfn)
 
    Page = MiGetPfnEntry(Pfn);
    ASSERT(Page);
-   if (Page->Flags.Type != MM_PHYSICAL_PAGE_USED)
-   {
-      DPRINT1("Referencing non-used page\n");
-      KeBugCheck(MEMORY_MANAGEMENT);
-   }
 
-   Page->ReferenceCount++;
+   Page->u3.e2.ReferenceCount++;
 }
 
 ULONG
 NTAPI
-MmGetReferenceCountPage(PFN_NUMBER Pfn)
+MmGetReferenceCountPage(PFN_TYPE Pfn)
 {
    KIRQL oldIrql;
    ULONG RCount;
@@ -900,13 +529,8 @@ MmGetReferenceCountPage(PFN_NUMBER Pfn)
    oldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
    Page = MiGetPfnEntry(Pfn);
    ASSERT(Page);
-   if (Page->Flags.Type != MM_PHYSICAL_PAGE_USED)
-   {
-      DPRINT1("Getting reference count for free page\n");
-      KeBugCheck(MEMORY_MANAGEMENT);
-   }
 
-   RCount = Page->ReferenceCount;
+   RCount = Page->u3.e2.ReferenceCount;
 
    KeReleaseQueuedSpinLock(LockQueuePfnLock, oldIrql);
    return(RCount);
@@ -914,17 +538,22 @@ MmGetReferenceCountPage(PFN_NUMBER Pfn)
 
 BOOLEAN
 NTAPI
-MmIsPageInUse(PFN_NUMBER Pfn)
+MmIsPageInUse(PFN_TYPE Pfn)
 {
+    return MiIsPfnInUse(MiGetPfnEntry(Pfn));
+}
 
-   DPRINT("MmIsPageInUse(PhysicalAddress %x)\n", Pfn << PAGE_SHIFT);
-
-   return (MiGetPfnEntry(Pfn)->Flags.Type == MM_PHYSICAL_PAGE_USED);
+VOID
+NTAPI
+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;
 
@@ -933,134 +562,33 @@ MmDereferencePage(PFN_NUMBER Pfn)
    Page = MiGetPfnEntry(Pfn);
    ASSERT(Page);
 
-   if (Page->Flags.Type != MM_PHYSICAL_PAGE_USED)
-   {
-      DPRINT1("Dereferencing free page\n");
-      KeBugCheck(MEMORY_MANAGEMENT);
-   }
-   if (Page->ReferenceCount == 0)
-   {
-      DPRINT1("Derefrencing page with reference count 0\n");
-      KeBugCheck(MEMORY_MANAGEMENT);
-   }
-
-   Page->ReferenceCount--;
-   if (Page->ReferenceCount == 0)
+   Page->u3.e2.ReferenceCount--;
+   if (Page->u3.e2.ReferenceCount == 0)
    {
       MmAvailablePages++;
-      if (Page->Flags.Consumer == MC_USER) RemoveEntryList(&Page->ListEntry);
-      if (Page->RmapListHead != (LONG_PTR)NULL)
-      {
-         DPRINT1("Freeing page with rmap entries.\n");
-         KeBugCheck(MEMORY_MANAGEMENT);
-      }
-      if (Page->LockCount > 0)
-      {
-         DPRINT1("Freeing locked page\n");
-         KeBugCheck(MEMORY_MANAGEMENT);
-      }
-      if (Page->SavedSwapEntry != 0)
-      {
-         DPRINT1("Freeing page with swap entry.\n");
-         KeBugCheck(MEMORY_MANAGEMENT);
-      }
-      if (Page->Flags.Type != MM_PHYSICAL_PAGE_USED)
-      {
-         DPRINT1("Freeing page with flags %x\n",
-                  Page->Flags.Type);
-         KeBugCheck(MEMORY_MANAGEMENT);
-      }
-      Page->Flags.Type = MM_PHYSICAL_PAGE_FREE;
-      Page->Flags.Consumer = MC_MAXIMUM;
-      InsertTailList(&FreeUnzeroedPageListHead,
-                     &Page->ListEntry);
-      UnzeroedPageCount++;
-      if (UnzeroedPageCount > 8 && 0 == KeReadStateEvent(&ZeroPageThreadEvent))
+      Page->u3.e1.PageLocation = FreePageList;
+      MiInsertInListTail(&MmFreePageListHead, Page);
+      if (MmFreePageListHead.Total > 8 && 0 == KeReadStateEvent(&ZeroPageThreadEvent))
       {
          KeSetEvent(&ZeroPageThreadEvent, IO_NO_INCREMENT, FALSE);
       }
    }
 }
 
-ULONG
+PFN_TYPE
 NTAPI
-MmGetLockCountPage(PFN_NUMBER Pfn)
+MmAllocPage(ULONG Type)
 {
-   KIRQL oldIrql;
-   ULONG CurrentLockCount;
-   PPHYSICAL_PAGE Page;
-
-   DPRINT("MmGetLockCountPage(PhysicalAddress %x)\n", Pfn << PAGE_SHIFT);
-
-   oldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
-
-   Page = MiGetPfnEntry(Pfn);
-   ASSERT(Page);
-   if (Page->Flags.Type != MM_PHYSICAL_PAGE_USED)
-   {
-      DPRINT1("Getting lock count for free page\n");
-      KeBugCheck(MEMORY_MANAGEMENT);
-   }
-
-   CurrentLockCount = Page->LockCount;
-   KeReleaseQueuedSpinLock(LockQueuePfnLock, oldIrql);
-
-   return(CurrentLockCount);
-}
-
-VOID
-NTAPI
-MmLockPage(PFN_NUMBER Pfn)
-{
-   PPHYSICAL_PAGE Page;
-
-   DPRINT("MmLockPage(PhysicalAddress %x)\n", Pfn << PAGE_SHIFT);
-
-   Page = MiGetPfnEntry(Pfn);
-   ASSERT(Page);
-   if (Page->Flags.Type != MM_PHYSICAL_PAGE_USED)
-   {
-      DPRINT1("Locking free page\n");
-      KeBugCheck(MEMORY_MANAGEMENT);
-   }
-
-   Page->LockCount++;
-}
-
-VOID
-NTAPI
-MmUnlockPage(PFN_NUMBER Pfn)
-{
-   PPHYSICAL_PAGE Page;
-
-   DPRINT("MmUnlockPage(PhysicalAddress %x)\n", Pfn << PAGE_SHIFT);
-
-   Page = MiGetPfnEntry(Pfn);
-   ASSERT(Page);
-   if (Page->Flags.Type != MM_PHYSICAL_PAGE_USED)
-   {
-      DPRINT1("Unlocking free page\n");
-      KeBugCheck(MEMORY_MANAGEMENT);
-   }
-
-   Page->LockCount--;
-}
-
-PFN_NUMBER
-NTAPI
-MmAllocPage(ULONG Consumer, SWAPENTRY SwapEntry)
-{
-   PFN_NUMBER PfnOffset;
-   PLIST_ENTRY ListEntry;
+   PFN_TYPE PfnOffset;
    PPHYSICAL_PAGE PageDescriptor;
    BOOLEAN NeedClear = FALSE;
 
    DPRINT("MmAllocPage()\n");
 
-   if (IsListEmpty(&FreeZeroedPageListHead))
+   if (MmZeroedPageListHead.Total == 0)
    {
-      if (IsListEmpty(&FreeUnzeroedPageListHead))
-      {
+       if (MmFreePageListHead.Total == 0)
+       {
          /* Check if this allocation is for the PFN DB itself */
          if (MmNumberOfPhysicalPages == 0) 
          {
@@ -1070,49 +598,32 @@ MmAllocPage(ULONG Consumer, SWAPENTRY SwapEntry)
          DPRINT1("MmAllocPage(): Out of memory\n");
          return 0;
       }
-      ListEntry = RemoveTailList(&FreeUnzeroedPageListHead);
-      UnzeroedPageCount--;
-
-      PageDescriptor = CONTAINING_RECORD(ListEntry, PHYSICAL_PAGE, ListEntry);
+      PageDescriptor = MiRemoveHeadList(&MmFreePageListHead);
 
       NeedClear = TRUE;
    }
    else
    {
-      ListEntry = RemoveTailList(&FreeZeroedPageListHead);
-
-      PageDescriptor = CONTAINING_RECORD(ListEntry, PHYSICAL_PAGE, ListEntry);
+      PageDescriptor = MiRemoveHeadList(&MmZeroedPageListHead);
    }
 
-   if (PageDescriptor->Flags.Type != MM_PHYSICAL_PAGE_FREE)
-   {
-      DPRINT1("Got non-free page from freelist\n");
-      KeBugCheck(MEMORY_MANAGEMENT);
-   }
-   if (PageDescriptor->ReferenceCount != 0)
-   {
-      DPRINT1("%d\n", PageDescriptor->ReferenceCount);
-      KeBugCheck(MEMORY_MANAGEMENT);
-   }
-   PageDescriptor->Flags.Type = MM_PHYSICAL_PAGE_USED;
-   PageDescriptor->Flags.Consumer = Consumer;
-   PageDescriptor->ReferenceCount = 1;
-   PageDescriptor->LockCount = 0;
-   PageDescriptor->SavedSwapEntry = SwapEntry;
+   PageDescriptor->u3.e2.ReferenceCount = 1;
 
    MmAvailablePages--;
 
-   PfnOffset = PageDescriptor - MmPfnDatabase;
-   if ((NeedClear) && (Consumer != MC_SYSTEM))
+   PfnOffset = MiGetPfnEntryIndex(PageDescriptor);
+   if ((NeedClear) && (Type != MC_SYSTEM))
    {
       MiZeroPage(PfnOffset);
    }
+     
+   PageDescriptor->u3.e1.PageLocation = ActiveAndValid;
    return PfnOffset;
 }
 
 NTSTATUS
 NTAPI
-MiZeroPage(PFN_NUMBER Page)
+MiZeroPage(PFN_TYPE Page)
 {
     KIRQL Irql;
     PVOID TempAddress;
@@ -1135,9 +646,8 @@ MmZeroPageThreadMain(PVOID Ignored)
 {
    NTSTATUS Status;
    KIRQL oldIrql;
-   PLIST_ENTRY ListEntry;
    PPHYSICAL_PAGE PageDescriptor;
-   PFN_NUMBER Pfn;
+   PFN_TYPE Pfn;
    ULONG Count;
 
    /* Free initial kernel memory */
@@ -1154,11 +664,6 @@ MmZeroPageThreadMain(PVOID Ignored)
                                      KernelMode,
                                      FALSE,
                                      NULL);
-      if (!NT_SUCCESS(Status))
-      {
-         DPRINT1("ZeroPageThread: Wait failed\n");
-         KeBugCheck(MEMORY_MANAGEMENT);
-      }
 
       if (ZeroPageThreadShouldTerminate)
       {
@@ -1167,29 +672,24 @@ MmZeroPageThreadMain(PVOID Ignored)
       }
       Count = 0;
       oldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
-      while (!IsListEmpty(&FreeUnzeroedPageListHead))
+      while (MmFreePageListHead.Total)
       {
-         ListEntry = RemoveTailList(&FreeUnzeroedPageListHead);
-         UnzeroedPageCount--;
-         PageDescriptor = CONTAINING_RECORD(ListEntry, PHYSICAL_PAGE, ListEntry);
+         PageDescriptor = MiRemoveHeadList(&MmFreePageListHead);
          /* We set the page to used, because MmCreateVirtualMapping failed with unused pages */
-         PageDescriptor->Flags.Type = MM_PHYSICAL_PAGE_USED;
          KeReleaseQueuedSpinLock(LockQueuePfnLock, oldIrql);
-         Pfn = PageDescriptor - MmPfnDatabase;
+         Pfn = MiGetPfnEntryIndex(PageDescriptor);
          Status = MiZeroPage(Pfn);
 
          oldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
-         PageDescriptor->Flags.Zero = 1;
-         PageDescriptor->Flags.Type = MM_PHYSICAL_PAGE_FREE;
          if (NT_SUCCESS(Status))
          {
-            InsertHeadList(&FreeZeroedPageListHead, ListEntry);
+            MiInsertZeroListAtBack(Pfn);
             Count++;
          }
          else
          {
-            InsertHeadList(&FreeUnzeroedPageListHead, ListEntry);
-            UnzeroedPageCount++;
+            MiInsertInListTail(&MmFreePageListHead, PageDescriptor);
+            PageDescriptor->u3.e1.PageLocation = FreePageList;
          }
 
       }