[NTOS]: Enable usage of ARM3 paged pool, up until Mm Phase 2.
[reactos.git] / reactos / ntoskrnl / mm / mminit.c
index 7f6219a..83c45f1 100644 (file)
@@ -12,6 +12,9 @@
 #define NDEBUG
 #include <debug.h>
 
+#define MODULE_INVOLVED_IN_ARM3
+#include "ARM3/miarm.h"
+
 /* GLOBALS *******************************************************************/
 
 PCHAR
@@ -45,20 +48,14 @@ MemType[] =
     "LoaderXIPRom      "
 };
 
-BOOLEAN IsThisAnNtAsSystem = FALSE;
-MM_SYSTEMSIZE MmSystemSize = MmSmallSystem;
-PVOID MiNonPagedPoolStart;
-ULONG MiNonPagedPoolLength;
-ULONG MmBootImageSize;
-ULONG MmNumberOfPhysicalPages, MmHighestPhysicalPage, MmLowestPhysicalPage;
-ULONG_PTR MiKSeg0Start, MiKSeg0End;
-ULONG_PTR MmPfnDatabaseEnd;
-PMEMORY_ALLOCATION_DESCRIPTOR MiFreeDescriptor;
-MEMORY_ALLOCATION_DESCRIPTOR MiFreeDescriptorOrg;
-extern KMUTANT MmSystemLoadLock;
-extern HANDLE MpwThreadHandle;
-extern BOOLEAN MpwThreadShouldTerminate;
-extern KEVENT MpwThreadEvent;
+BOOLEAN Mm64BitPhysicalAddress = FALSE;
+ULONG MmReadClusterSize;
+//
+// 0 | 1 is on/off paging, 2 is undocumented
+//
+UCHAR MmDisablePagingExecutive = 1; // Forced to off
+PMMPTE MmSharedUserDataPte;
+PMMSUPPORT MmKernelAddressSpace;
 BOOLEAN MiDbgEnableMdDump =
 #ifdef _ARM_
 TRUE;
@@ -68,41 +65,6 @@ FALSE;
 
 /* PRIVATE FUNCTIONS *********************************************************/
 
-VOID
-NTAPI
-MiShutdownMemoryManager(VOID)
-{
-#if 0
-    ULONG PagesWritten;
-    PETHREAD Thread;
-
-    /* Ask MPW thread to shutdown */
-    MpwThreadShouldTerminate = TRUE;
-    KeSetEvent(&MpwThreadEvent, IO_NO_INCREMENT, FALSE);
-
-    /* Wait for it */
-    ObReferenceObjectByHandle(MpwThreadHandle,
-                              THREAD_ALL_ACCESS,
-                              PsThreadType,
-                              KernelMode,
-                              (PVOID*)&Thread,
-                              NULL);
-
-    KeWaitForSingleObject(Thread,
-                          Executive,
-                          KernelMode,
-                          FALSE,
-                          NULL);
-
-    ObDereferenceObject(Thread);
-
-    /* Check if there are any dirty pages, and flush them.
-       There will be no other chance to do this later, since filesystems
-       are going to be shut down. */
-    CcRosFlushDirtyPages(128, &PagesWritten);
-#endif
-}
-
 VOID
 INIT_FUNCTION
 NTAPI
@@ -111,129 +73,259 @@ MiInitSystemMemoryAreas()
     PVOID BaseAddress;
     PHYSICAL_ADDRESS BoundaryAddressMultiple;
     PMEMORY_AREA MArea;
+    NTSTATUS Status;
     BoundaryAddressMultiple.QuadPart = 0;
     
     //
-    // First initialize the page table and hyperspace memory areas
+    // Create the memory area to define the PTE base
+    //
+    BaseAddress = (PVOID)PTE_BASE;
+    Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
+                                MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC,
+                                &BaseAddress,
+                                4 * 1024 * 1024,
+                                PAGE_READWRITE,
+                                &MArea,
+                                TRUE,
+                                0,
+                                BoundaryAddressMultiple);
+    ASSERT(Status == STATUS_SUCCESS);
+    
+    //
+    // Create the memory area to define Hyperspace
+    //
+    BaseAddress = (PVOID)HYPER_SPACE;
+    Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
+                                MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC,
+                                &BaseAddress,
+                                4 * 1024 * 1024,
+                                PAGE_READWRITE,
+                                &MArea,
+                                TRUE,
+                                0,
+                                BoundaryAddressMultiple);
+    ASSERT(Status == STATUS_SUCCESS);
+    
+    //
+    // Protect the PFN database
+    //
+    BaseAddress = MmPfnDatabase;
+    Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
+                                MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC,
+                                &BaseAddress,
+                                (MxPfnAllocation << PAGE_SHIFT),
+                                PAGE_READWRITE,
+                                &MArea,
+                                TRUE,
+                                0,
+                                BoundaryAddressMultiple);
+    ASSERT(Status == STATUS_SUCCESS);
+    
+    //
+    // ReactOS requires a memory area to keep the initial NP area off-bounds
+    //
+    BaseAddress = MmNonPagedPoolStart;
+    Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
+                                MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC,
+                                &BaseAddress,
+                                MmSizeOfNonPagedPoolInBytes,
+                                PAGE_READWRITE,
+                                &MArea,
+                                TRUE,
+                                0,
+                                BoundaryAddressMultiple);
+    ASSERT(Status == STATUS_SUCCESS);
+    
+    //
+    // And we need one more for the system NP
+    //
+    BaseAddress = MmNonPagedSystemStart;
+    Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
+                                MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC,
+                                &BaseAddress,
+                                (ULONG_PTR)MmNonPagedPoolEnd -
+                                (ULONG_PTR)MmNonPagedSystemStart,
+                                PAGE_READWRITE,
+                                &MArea,
+                                TRUE,
+                                0,
+                                BoundaryAddressMultiple);
+    ASSERT(Status == STATUS_SUCCESS);
+    
+    //
+    // We also need one for system view space
+    //
+    BaseAddress = MiSystemViewStart;
+    Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
+                                MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC,
+                                &BaseAddress,
+                                MmSystemViewSize,
+                                PAGE_READWRITE,
+                                &MArea,
+                                TRUE,
+                                0,
+                                BoundaryAddressMultiple);
+    ASSERT(Status == STATUS_SUCCESS);
+    
+    //
+    // And another for session space
+    //
+    BaseAddress = MmSessionBase;
+    Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
+                                MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC,
+                                &BaseAddress,
+                                (ULONG_PTR)MiSessionSpaceEnd -
+                                (ULONG_PTR)MmSessionBase,
+                                PAGE_READWRITE,
+                                &MArea,
+                                TRUE,
+                                0,
+                                BoundaryAddressMultiple);
+    ASSERT(Status == STATUS_SUCCESS);
+    
+    //
+    // One more for ARM paged pool
+    //
+    BaseAddress = MmPagedPoolStart;
+    Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
+                                MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC,
+                                &BaseAddress,
+                                MmSizeOfPagedPoolInBytes,
+                                PAGE_READWRITE,
+                                &MArea,
+                                TRUE,
+                                0,
+                                BoundaryAddressMultiple);
+    ASSERT(Status == STATUS_SUCCESS);
+    
+    //
+    // And now, ReactOS paged pool
     //
-    MiInitPageDirectoryMap();
+    BaseAddress = MmPagedPoolBase;
+    Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
+                                MEMORY_AREA_PAGED_POOL | MEMORY_AREA_STATIC,
+                                &BaseAddress,
+                                MmPagedPoolSize,
+                                PAGE_READWRITE,
+                                &MArea,
+                                TRUE,
+                                0,
+                                BoundaryAddressMultiple);
+    ASSERT(Status == STATUS_SUCCESS);
     
     //
     // Next, the KPCR
     //
     BaseAddress = (PVOID)PCR;
-    MmCreateMemoryArea(MmGetKernelAddressSpace(),
-                       MEMORY_AREA_SYSTEM | MEMORY_AREA_STATIC,
-                       &BaseAddress,
-                       PAGE_SIZE * KeNumberProcessors,
-                       PAGE_READWRITE,
-                       &MArea,
-                       TRUE,
-                       0,
-                       BoundaryAddressMultiple);
-
+    Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
+                                MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC,
+                                &BaseAddress,
+                                PAGE_SIZE * KeNumberProcessors,
+                                PAGE_READWRITE,
+                                &MArea,
+                                TRUE,
+                                0,
+                                BoundaryAddressMultiple);
+    ASSERT(Status == STATUS_SUCCESS);
+    
     //
     // Now the KUSER_SHARED_DATA
     //
     BaseAddress = (PVOID)KI_USER_SHARED_DATA;
-    MmCreateMemoryArea(MmGetKernelAddressSpace(),
-                       MEMORY_AREA_SYSTEM | MEMORY_AREA_STATIC,
-                       &BaseAddress,
-                       PAGE_SIZE,
-                       PAGE_READWRITE,
-                       &MArea,
-                       TRUE,
-                       0,
-                       BoundaryAddressMultiple);
-}
-
-VOID
-NTAPI
-MiCountFreePagesInLoaderBlock(PLOADER_PARAMETER_BLOCK LoaderBlock)
-{
-    PLIST_ENTRY NextEntry;
-    PMEMORY_ALLOCATION_DESCRIPTOR Md;
-    ULONG FreePages = 0;
+    Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
+                                MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC,
+                                &BaseAddress,
+                                PAGE_SIZE,
+                                PAGE_READWRITE,
+                                &MArea,
+                                TRUE,
+                                0,
+                                BoundaryAddressMultiple);
+    ASSERT(Status == STATUS_SUCCESS);
 
-    for (NextEntry = KeLoaderBlock->MemoryDescriptorListHead.Flink;
-        NextEntry != &KeLoaderBlock->MemoryDescriptorListHead;
-        NextEntry = NextEntry->Flink)
-    {
-        Md = CONTAINING_RECORD(NextEntry, MEMORY_ALLOCATION_DESCRIPTOR, ListEntry);
-
-        /* Skip invisible memory */
-        if ((Md->MemoryType != LoaderFirmwarePermanent) &&
-            (Md->MemoryType != LoaderSpecialMemory) &&
-            (Md->MemoryType != LoaderHALCachedMemory) &&
-            (Md->MemoryType != LoaderBBTMemory))
-        {
-            /* Check if BURNMEM was used */
-            if (Md->MemoryType != LoaderBad)
-            {
-                /* Count this in the total of pages */
-                MmNumberOfPhysicalPages += Md->PageCount;
-            }
-            
-            /* Check if this is the new lowest page */
-            if (Md->BasePage < MmLowestPhysicalPage)
-            {
-                /* Update the lowest page */
-                MmLowestPhysicalPage = Md->BasePage;
-            }
-            
-            /* Check if this is the new highest page */
-            if ((Md->BasePage + Md->PageCount) > MmHighestPhysicalPage)
-            {
-                /* Update the highest page */
-                MmHighestPhysicalPage = Md->BasePage + Md->PageCount - 1;
-            }
-
-            /* Check if this is free memory */
-            if ((Md->MemoryType == LoaderFree) ||
-                (Md->MemoryType == LoaderLoadedProgram) ||
-                (Md->MemoryType == LoaderFirmwareTemporary) ||
-                (Md->MemoryType == LoaderOsloaderStack))
-            {
-                /* Check if this is the largest memory descriptor */
-                if (Md->PageCount > FreePages)
-                {
-                    /* For now, it is */
-                    FreePages = Md->PageCount;
-                    MiFreeDescriptor = Md;
-                }
-            }
-        }
-    }
-
-    /* Save original values of the free descriptor, since it'll be
-       altered by early allocations */
-    MiFreeDescriptorOrg = *MiFreeDescriptor;
+    //
+    // And the debugger mapping
+    //
+    BaseAddress = MI_DEBUG_MAPPING;
+    Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
+                                MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC,
+                                &BaseAddress,
+                                PAGE_SIZE,
+                                PAGE_READWRITE,
+                                &MArea,
+                                TRUE,
+                                0,
+                                BoundaryAddressMultiple);
+    ASSERT(Status == STATUS_SUCCESS);
+
+#if defined(_X86_)
+    //
+    // Finally, reserve the 2  pages we currently make use of for HAL mappings
+    //
+    BaseAddress = (PVOID)0xFFC00000;
+    Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
+                                MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC,
+                                &BaseAddress,
+                                PAGE_SIZE * 2,
+                                PAGE_READWRITE,
+                                &MArea,
+                                TRUE,
+                                0,
+                                BoundaryAddressMultiple);
+    ASSERT(Status == STATUS_SUCCESS);
+#endif
 }
 
 VOID
 NTAPI
-MiDbgKernelLayout(VOID)
+MiDbgDumpAddressSpace(VOID)
 {
-    DPRINT1("%8s%12s\t\t%s\n", "Start", "End", "Type");
-    DPRINT1("0x%p - 0x%p\t%s\n",
-            KSEG0_BASE, MiKSeg0Start,
-            "Undefined region");
-    DPRINT1("0x%p - 0x%p\t%s\n",
-            MiKSeg0Start, MiKSeg0End,
-            "FreeLDR Kernel mapping region");
-    DPRINT1("0x%p - 0x%p\t%s\n",
-            MmPfnDatabase, MmPfnDatabaseEnd,
-            "PFN Database region");
-    if (MmPfnDatabaseEnd != (ULONG_PTR)MiNonPagedPoolStart)
-    DPRINT1("0x%p - 0x%p\t%s\n",
-            MmPfnDatabaseEnd, MiNonPagedPoolStart,
-            "Remaining FreeLDR mapping");
-    DPRINT1("0x%p - 0x%p\t%s\n",
-             MiNonPagedPoolStart, (ULONG_PTR)MiNonPagedPoolStart + MiNonPagedPoolLength,
-            "Non paged pool region");
-    DPRINT1("0x%p - 0x%p\t%s\n",
-            MmPagedPoolBase, (ULONG_PTR)MmPagedPoolBase + MmPagedPoolSize,
-            "Paged pool region");
+    //
+    // Print the memory layout
+    //
+    DPRINT1("          0x%p - 0x%p\t%s\n",
+            MmSystemRangeStart,
+            (ULONG_PTR)MmSystemRangeStart + MmBootImageSize,
+            "Boot Loaded Image");
+    DPRINT1("          0x%p - 0x%p\t%s\n",
+            MmPagedPoolBase,
+            (ULONG_PTR)MmPagedPoolBase + MmPagedPoolSize,
+            "Paged Pool");
+    DPRINT1("          0x%p - 0x%p\t%s\n",
+            MmPfnDatabase,
+            (ULONG_PTR)MmPfnDatabase + (MxPfnAllocation << PAGE_SHIFT),
+            "PFN Database");
+    DPRINT1("          0x%p - 0x%p\t%s\n",
+            MmNonPagedPoolStart,
+            (ULONG_PTR)MmNonPagedPoolStart + MmSizeOfNonPagedPoolInBytes,
+            "ARM³ Non Paged Pool");
+    DPRINT1("          0x%p - 0x%p\t%s\n",
+            MiSystemViewStart,
+            (ULONG_PTR)MiSystemViewStart + MmSystemViewSize,
+            "System View Space");        
+    DPRINT1("          0x%p - 0x%p\t%s\n",
+            MmSessionBase,
+            MiSessionSpaceEnd,
+            "Session Space");
+    DPRINT1("          0x%p - 0x%p\t%s\n",
+            PTE_BASE, PDE_BASE,
+            "Page Tables");
+    DPRINT1("          0x%p - 0x%p\t%s\n",
+            PDE_BASE, HYPER_SPACE,
+            "Page Directories");
+    DPRINT1("          0x%p - 0x%p\t%s\n",
+            HYPER_SPACE, HYPER_SPACE + (4 * 1024 * 1024),
+            "Hyperspace");
+    DPRINT1("          0x%p - 0x%p\t%s\n",
+            MmPagedPoolStart,
+            (ULONG_PTR)MmPagedPoolStart + MmSizeOfPagedPoolInBytes,
+            "ARM³ Paged Pool");
+    DPRINT1("          0x%p - 0x%p\t%s\n",
+            MmNonPagedSystemStart, MmNonPagedPoolExpansionStart,
+            "System PTE Space");
+    DPRINT1("          0x%p - 0x%p\t%s\n",
+            MmNonPagedPoolExpansionStart, MmNonPagedPoolEnd,
+            "Non Paged Pool Expansion PTE Space");
 }
 
 VOID
@@ -257,229 +349,100 @@ MiDbgDumpMemoryDescriptors(VOID)
     DPRINT1("Total: %08lX (%d MB)\n", TotalPages, (TotalPages * PAGE_SIZE) / 1024 / 1024);
 }
 
-ULONG_PTR
-NTAPI
-MiGetLastKernelAddress(VOID)
-{
-    PLIST_ENTRY NextEntry;
-    PMEMORY_ALLOCATION_DESCRIPTOR Md;
-    ULONG_PTR LastKrnlPhysAddr = 0;
-
-    for (NextEntry = KeLoaderBlock->MemoryDescriptorListHead.Flink;
-         NextEntry != &KeLoaderBlock->MemoryDescriptorListHead;
-         NextEntry = NextEntry->Flink)
-    {
-        Md = CONTAINING_RECORD(NextEntry, MEMORY_ALLOCATION_DESCRIPTOR, ListEntry);
-
-        if (Md->MemoryType != LoaderFree &&
-            Md->MemoryType != LoaderFirmwareTemporary &&
-            Md->MemoryType != LoaderSpecialMemory)
-        {
-            if (Md->BasePage+Md->PageCount > LastKrnlPhysAddr)
-                LastKrnlPhysAddr = Md->BasePage+Md->PageCount;
-        }
-    }
-
-    /* Convert to a physical address */
-    return LastKrnlPhysAddr << PAGE_SHIFT;
-}
-
-
-VOID
-NTAPI
-MiInitHyperSpace(VOID);
-
-NTSTATUS
-NTAPI
-MmArmInitSystem(IN ULONG Phase,
-                IN PLOADER_PARAMETER_BLOCK LoaderBlock);
-
-VOID
-INIT_FUNCTION
-NTAPI
-MmInit1(VOID)
-{
-    PLDR_DATA_TABLE_ENTRY LdrEntry;
-    ULONG Dummy[2];
-    
-    /* Dump memory descriptors */
-    if (MiDbgEnableMdDump) MiDbgDumpMemoryDescriptors();
-
-    /* Set the page directory */
-    PsGetCurrentProcess()->Pcb.DirectoryTableBase[0] = (ULONG)MmGetPageDirectory();
-
-    /* Get the size of FreeLDR's image allocations */
-    MmBootImageSize = KeLoaderBlock->Extension->LoaderPagesSpanned;
-    MmBootImageSize *= PAGE_SIZE;
-
-    /* Set memory limits */
-    MmSystemRangeStart = (PVOID)KSEG0_BASE;
-    MmUserProbeAddress = (ULONG_PTR)MmSystemRangeStart - 0x10000;
-    MmHighestUserAddress = (PVOID)(MmUserProbeAddress - 1);
-    DPRINT("MmSystemRangeStart:  %08x\n", MmSystemRangeStart);
-    DPRINT("MmUserProbeAddress:  %08x\n", MmUserProbeAddress);
-    DPRINT("MmHighestUserAddress:%08x\n", MmHighestUserAddress);
-
-    /* Initialize memory managment statistics */
-    RtlZeroMemory(&MmStats, sizeof(MmStats));
-    
-    /* Count RAM */
-    MiCountFreePagesInLoaderBlock(KeLoaderBlock);
-    DbgPrint("Used memory %dKb\n", (MmNumberOfPhysicalPages * PAGE_SIZE) / 1024);
-    
-    /* Initialize the kernel address space */
-    MmInitializeHandBuiltProcess(PsGetCurrentProcess(), Dummy);
-    MmKernelAddressSpace = MmGetCurrentAddressSpace();
-    MmInitGlobalKernelPageDirectory();
-    
-    /* Get kernel address boundaries */
-    LdrEntry = CONTAINING_RECORD(KeLoaderBlock->LoadOrderListHead.Flink,
-                                 LDR_DATA_TABLE_ENTRY,
-                                 InLoadOrderLinks);
-    MiKSeg0Start = (ULONG_PTR)LdrEntry->DllBase | KSEG0_BASE;
-    MiKSeg0End = PAGE_ROUND_UP(MiGetLastKernelAddress()  | KSEG0_BASE);
-
-    /* We'll put the PFN array right after the loaded modules */
-    MmPfnDatabase = (PVOID)MiKSeg0End;
-    MmPfnDatabaseEnd = (ULONG_PTR)MmPfnDatabase + (MmHighestPhysicalPage * sizeof(MMPFN));
-    MmPfnDatabaseEnd = PAGE_ROUND_UP(MmPfnDatabaseEnd);
-    
-    /*
-     * FreeLDR maps 6MB starting at the kernel base address, followed by the
-     * PFN database. If the PFN database doesn't go over the FreeLDR allocation
-     * then choose the end of the FreeLDR block. If it does go past the FreeLDR
-     * allocation, then choose the next PAGE_SIZE boundary.
-     */
-    if ((ULONG_PTR)MmPfnDatabaseEnd < (MiKSeg0Start + 0x600000))
-    {
-        /* Use the first memory following FreeLDR's 6MB mapping */
-        MiNonPagedPoolStart = (PVOID)((ULONG_PTR)MiKSeg0Start + 0x600000);
-    }
-    else
-    {
-        /* Use the next free available page */
-        MiNonPagedPoolStart = (PVOID)MmPfnDatabaseEnd;
-    }
-    
-    /* Length of non-paged pool */
-    MiNonPagedPoolLength = MM_NONPAGED_POOL_SIZE;
-
-    /* Put the paged pool after the non-paged pool */
-    MmPagedPoolBase = (PVOID)PAGE_ROUND_UP((ULONG_PTR)MiNonPagedPoolStart +
-                                           MiNonPagedPoolLength);
-    MmPagedPoolSize = MM_PAGED_POOL_SIZE;
-    
-    /* Dump kernel memory layout */
-    MiDbgKernelLayout();
-    
-    /* Intialize system memory areas */
-    MiInitSystemMemoryAreas();
-
-    /* Initialize hyperspace */
-    MiInitHyperSpace();
-
-    /* Initialize the page list */
-    MmInitializePageList();
-
-    /* Unmap low memory */
-    MmDeletePageTable(NULL, 0);
-    
-#ifdef _ARM_
-    /* Initialize ARM³ */
-    MmArmInitSystem(0, KeLoaderBlock);
-#endif
-
-    /* Initialize nonpaged pool */
-    MiInitializeNonPagedPool();
-    
-    /* Initialize paged pool */
-    MmInitializePagedPool();
-
-    /* Initialize MDLs */
-    MmInitializeMdlImplementation();
-    
-    /* Initialize working sets */
-    MmInitializeMemoryConsumer(MC_USER, MmTrimUserMemory);
-}
+VOID NTAPI MiInitializeUserPfnBitmap(VOID);
 
 BOOLEAN
 NTAPI
 MmInitSystem(IN ULONG Phase,
              IN PLOADER_PARAMETER_BLOCK LoaderBlock)
 {
+    extern MMPTE ValidKernelPte;
+    PMMPTE PointerPte;
+    MMPTE TempPte = ValidKernelPte;
+    PFN_NUMBER PageFrameNumber;
+    
     if (Phase == 0)
     {
-        /* Initialize Mm bootstrap */
-        MmInit1();
-
-        /* Initialize the Loader Lock */
-        KeInitializeMutant(&MmSystemLoadLock, FALSE);
-
-        /* Reload boot drivers */
-        MiReloadBootLoadedDrivers(LoaderBlock);
-
-        /* Initialize the loaded module list */
-        MiInitializeLoadedModuleList(LoaderBlock);
-
-        /* We're done, for now */
-        DPRINT("Mm0: COMPLETE\n");
+        /* Initialize the kernel address space */
+        KeInitializeGuardedMutex(&PsGetCurrentProcess()->AddressCreationLock);
+        MmKernelAddressSpace = MmGetCurrentAddressSpace();
+        MmInitGlobalKernelPageDirectory();
+        
+        /* Dump memory descriptors */
+        if (MiDbgEnableMdDump) MiDbgDumpMemoryDescriptors();
+        
+        /* Initialize ARM³ in phase 0 */
+        MmArmInitSystem(0, KeLoaderBlock);    
+        
+        /* Put the paged pool after the loaded modules */
+        MmPagedPoolBase = (PVOID)PAGE_ROUND_UP((ULONG_PTR)MmSystemRangeStart +
+                                               MmBootImageSize);
+        MmPagedPoolSize = MM_PAGED_POOL_SIZE;
+        
+        /* Intialize system memory areas */
+        MiInitSystemMemoryAreas();
+
+        /* Dump the address space */
+        MiDbgDumpAddressSpace();
     }
     else if (Phase == 1)
     {
+        MmInitializePagedPool();
+        MiInitializeUserPfnBitmap();
+        MmInitializeMemoryConsumer(MC_USER, MmTrimUserMemory);
         MmInitializeRmapList();
         MmInitializePageOp();
         MmInitSectionImplementation();
         MmInitPagingFile();
-        MmCreatePhysicalMemorySection();
-
-        /* Setup shared user data settings that NT does as well */
-        ASSERT(SharedUserData->NumberOfPhysicalPages == 0);
-        SharedUserData->NumberOfPhysicalPages = MmStats.NrTotalPages;
-        SharedUserData->LargePageMinimum = 0;
-
-        /* For now, we assume that we're always Workstation */
-        SharedUserData->NtProductType = NtProductWinNt;
-    }
-    else if (Phase == 2)
-    {
+        
+        //
+        // Create a PTE to double-map the shared data section. We allocate it
+        // from paged pool so that we can't fault when trying to touch the PTE
+        // itself (to map it), since paged pool addresses will already be mapped
+        // by the fault handler.
+        //
+        MmSharedUserDataPte = ExAllocatePoolWithTag(PagedPool,
+                                                    sizeof(MMPTE),
+                                                    '  mM');
+        if (!MmSharedUserDataPte) return FALSE;
+        
+        //
+        // Now get the PTE for shared data, and read the PFN that holds it
+        //
+        PointerPte = MiAddressToPte(KI_USER_SHARED_DATA);
+        ASSERT(PointerPte->u.Hard.Valid == 1);
+        PageFrameNumber = PFN_FROM_PTE(PointerPte);
+        
+        //
+        // Now write a copy of it
+        //
+        MI_MAKE_OWNER_PAGE(&TempPte);
+        TempPte.u.Hard.PageFrameNumber = PageFrameNumber;
+        *MmSharedUserDataPte = TempPte;
+        
+        /* Setup the memory threshold events */
+        if (!MiInitializeMemoryEvents()) return FALSE;
+        
         /*
-        * Unmap low memory
-        */
+         * Unmap low memory
+         */
         MiInitBalancerThread();
-
+        
         /*
-        * Initialise the modified page writer.
-        */
+         * Initialise the modified page writer.
+         */
         MmInitMpwThread();
-
+        
         /* Initialize the balance set manager */
         MmInitBsmThread();
-
-        /* FIXME: Read parameters from memory */
+    }
+    else if (Phase == 2)
+    {
+        /* Enough fun for now */
+        extern BOOLEAN AllowPagedPool;
+        AllowPagedPool = FALSE;
     }
 
     return TRUE;
 }
 
-
-/* PUBLIC FUNCTIONS **********************************************************/
-
-/*
- * @implemented
- */
-BOOLEAN
-NTAPI
-MmIsThisAnNtAsSystem(VOID)
-{
-   return IsThisAnNtAsSystem;
-}
-
-/*
- * @implemented
- */
-MM_SYSTEMSIZE
-NTAPI
-MmQuerySystemSize(VOID)
-{
-   return MmSystemSize;
-}