- Removed the initialisation of the kernel map area.
[reactos.git] / reactos / ntoskrnl / mm / mminit.c
index 3e6fd46..c06a57e 100644 (file)
@@ -1,73 +1,72 @@
-/* $Id: mminit.c,v 1.43 2003/01/11 15:26:59 hbirr Exp $
+/* $Id$
  *
- * COPYRIGHT:   See COPYING in the top directory
- * PROJECT:     ReactOS kernel 
- * FILE:        ntoskrnl/mm/mminit.c
- * PURPOSE:     kernel memory managment initialization functions
- * PROGRAMMER:  David Welch (welch@cwcom.net)
- * UPDATE HISTORY:
- *              Created 9/4/98
+ * COPYRIGHT:       See COPYING in the top directory
+ * PROJECT:         ReactOS kernel
+ * FILE:            ntoskrnl/mm/mminit.c
+ * PURPOSE:         Kernel memory managment initialization functions
+ *
+ * PROGRAMMERS:     David Welch (welch@cwcom.net)
  */
 
 /* INCLUDES *****************************************************************/
 
-#include <ddk/ntddk.h>
-#include <roscfg.h>
-#include <internal/i386/segment.h>
-#include <internal/mm.h>
-#include <internal/ntoskrnl.h>
-#include <internal/io.h>
-#include <internal/ps.h>
-#include <internal/pool.h>
-
+#include <ntoskrnl.h>
 #define NDEBUG
 #include <internal/debug.h>
 
 /* GLOBALS *****************************************************************/
 
-/*
- * Size of extended memory (kb) (fixed for now)
- */
-#define EXTENDED_MEMORY_SIZE  (3*1024*1024)
-
 /*
  * Compiler defined symbols
  */
 extern unsigned int _text_start__;
 extern unsigned int _text_end__;
 
-static BOOLEAN IsThisAnNtAsSystem = FALSE;
-static MM_SYSTEM_SIZE MmSystemSize = MmSmallSystem;
+extern unsigned int _init_start__;
+extern unsigned int _init_end__;
 
 extern unsigned int _bss_end__;
 
-static MEMORY_AREA* kernel_text_desc = NULL;
-static MEMORY_AREA* kernel_data_desc = NULL;
-static MEMORY_AREA* kernel_param_desc = NULL;
-static MEMORY_AREA* kernel_pool_desc = NULL;
-static MEMORY_AREA* kernel_shared_data_desc = NULL;
-static MEMORY_AREA* MiPagedPoolDescriptor = NULL;
+
+static BOOLEAN IsThisAnNtAsSystem = FALSE;
+static MM_SYSTEM_SIZE MmSystemSize = MmSmallSystem;
 
 PHYSICAL_ADDRESS MmSharedDataPagePhysicalAddress;
 
+PVOID MiNonPagedPoolStart;
+ULONG MiNonPagedPoolLength;
+
+extern ULONG init_stack;
+extern ULONG init_stack_top;
+
 /* FUNCTIONS ****************************************************************/
 
+/*
+ * @implemented
+ */
 BOOLEAN STDCALL MmIsThisAnNtAsSystem(VOID)
 {
    return(IsThisAnNtAsSystem);
 }
 
+/*
+ * @implemented
+ */
 MM_SYSTEM_SIZE STDCALL MmQuerySystemSize(VOID)
 {
    return(MmSystemSize);
 }
 
-VOID MiShutdownMemoryManager(VOID)
-{
-}
+VOID
+NTAPI
+MiShutdownMemoryManager(VOID)
+{}
 
-VOID MmInitVirtualMemory(ULONG LastKernelAddress,
-                        ULONG KernelLength)
+VOID
+INIT_FUNCTION
+NTAPI
+MmInitVirtualMemory(ULONG_PTR LastKernelAddress,
+                    ULONG KernelLength)
 /*
  * FUNCTION: Intialize the memory areas list
  * ARGUMENTS:
@@ -79,40 +78,125 @@ VOID MmInitVirtualMemory(ULONG LastKernelAddress,
    ULONG Length;
    ULONG ParamLength = KernelLength;
    NTSTATUS Status;
-   //ULONG i;
-   
+   PHYSICAL_ADDRESS BoundaryAddressMultiple;
+   PFN_TYPE Pfn;
+   PMEMORY_AREA MArea;
+
    DPRINT("MmInitVirtualMemory(%x, %x)\n",LastKernelAddress, KernelLength);
-   
+
+   BoundaryAddressMultiple.QuadPart = 0;
    LastKernelAddress = PAGE_ROUND_UP(LastKernelAddress);
-   
+
    MmInitMemoryAreas();
-   ExInitNonPagedPool(LastKernelAddress + PAGE_SIZE);
+
+   /* Start the paged and nonpaged pool at a 4MB boundary. */ 
+   MiNonPagedPoolStart = (PVOID)ROUND_UP((ULONG_PTR)LastKernelAddress + PAGE_SIZE, 0x400000);
+   MiNonPagedPoolLength = MM_NONPAGED_POOL_SIZE;
+
+   MmPagedPoolBase = (PVOID)ROUND_UP((ULONG_PTR)MiNonPagedPoolStart + MiNonPagedPoolLength + PAGE_SIZE, 0x400000);
+   MmPagedPoolSize = MM_PAGED_POOL_SIZE;
+
+   DPRINT("NonPagedPool %x - %x, PagedPool %x - %x\n", MiNonPagedPoolStart, (ULONG_PTR)MiNonPagedPoolStart + MiNonPagedPoolLength - 1, 
+           MmPagedPoolBase, (ULONG_PTR)MmPagedPoolBase + MmPagedPoolSize - 1);
+
+   MiInitializeNonPagedPool();
 
    /*
     * Setup the system area descriptor list
     */
+   MiInitPageDirectoryMap();
+
+   BaseAddress = (PVOID)KPCR_BASE;
+   MmCreateMemoryArea(NULL,
+                      MmGetKernelAddressSpace(),
+                      MEMORY_AREA_SYSTEM,
+                      &BaseAddress,
+                      PAGE_SIZE * MAXIMUM_PROCESSORS,
+                      0,
+                      &MArea,
+                      TRUE,
+                      FALSE,
+                      BoundaryAddressMultiple);
+
+   /* Local APIC base */
+   BaseAddress = (PVOID)0xFEE00000;
+   MmCreateMemoryArea(NULL,
+                      MmGetKernelAddressSpace(),
+                      MEMORY_AREA_SYSTEM,
+                      &BaseAddress,
+                      PAGE_SIZE,
+                      0,
+                      &MArea,
+                      TRUE,
+                      FALSE,
+                      BoundaryAddressMultiple);
+
+   /* i/o APIC base */
+   BaseAddress = (PVOID)0xFEC00000;
+   MmCreateMemoryArea(NULL,
+                      MmGetKernelAddressSpace(),
+                      MEMORY_AREA_SYSTEM,
+                      &BaseAddress,
+                      PAGE_SIZE,
+                      0,
+                      &MArea,
+                      TRUE,
+                      FALSE,
+                      BoundaryAddressMultiple);
+
+   BaseAddress = (PVOID)0xFF3A0000;
+   MmCreateMemoryArea(NULL,
+                      MmGetKernelAddressSpace(),
+                      MEMORY_AREA_SYSTEM,
+                      &BaseAddress,
+                      0x20000,
+                      0,
+                      &MArea,
+                      TRUE,
+                      FALSE,
+                      BoundaryAddressMultiple);
+
    BaseAddress = (PVOID)KERNEL_BASE;
-   Length = PAGE_ROUND_UP(((ULONG)&_text_end__)) - KERNEL_BASE;
+   Length = PAGE_ROUND_UP(((ULONG_PTR)&_text_end__)) - KERNEL_BASE;
    ParamLength = ParamLength - Length;
-   
+
    /*
     * No need to lock the address space at this point since no
     * other threads are running.
     */
    MmCreateMemoryArea(NULL,
-                     MmGetKernelAddressSpace(),
-                     MEMORY_AREA_SYSTEM,
-                     &BaseAddress,
-                     Length,
-                     0,
-                     &kernel_text_desc,
-                     FALSE);
-
-   Length = PAGE_ROUND_UP(((ULONG)&_bss_end__)) - 
-            PAGE_ROUND_UP(((ULONG)&_text_end__));
+                      MmGetKernelAddressSpace(),
+                      MEMORY_AREA_SYSTEM,
+                      &BaseAddress,
+                      Length,
+                      0,
+                      &MArea,
+                      TRUE,
+                      FALSE,
+                      BoundaryAddressMultiple);
+
+   BaseAddress = (PVOID)PAGE_ROUND_UP(((ULONG_PTR)&_text_end__));
+   ASSERT(BaseAddress == (PVOID)&_init_start__);
+   Length = PAGE_ROUND_UP(((ULONG_PTR)&_init_end__)) -
+            PAGE_ROUND_UP(((ULONG_PTR)&_text_end__));
+   ParamLength = ParamLength - Length;
+
+   MmCreateMemoryArea(NULL,
+                      MmGetKernelAddressSpace(),
+                      MEMORY_AREA_SYSTEM,
+                      &BaseAddress,
+                      Length,
+                      0,
+                      &MArea,
+                      TRUE,
+                      FALSE,
+                      BoundaryAddressMultiple);
+
+   Length = PAGE_ROUND_UP(((ULONG_PTR)&_bss_end__)) -
+            PAGE_ROUND_UP(((ULONG_PTR)&_init_end__));
    ParamLength = ParamLength - Length;
    DPRINT("Length %x\n",Length);
-   BaseAddress = (PVOID)PAGE_ROUND_UP(((ULONG)&_text_end__));
+   BaseAddress = (PVOID)PAGE_ROUND_UP(((ULONG_PTR)&_init_end__));
    DPRINT("BaseAddress %x\n",BaseAddress);
 
    /*
@@ -120,50 +204,53 @@ VOID MmInitVirtualMemory(ULONG LastKernelAddress,
     * the only thread running.
     */
    MmCreateMemoryArea(NULL,
-                     MmGetKernelAddressSpace(),                      
-                     MEMORY_AREA_SYSTEM,
-                     &BaseAddress,
-                     Length,
-                     0,
-                     &kernel_data_desc,
-                     FALSE);
-   
-   BaseAddress = (PVOID)PAGE_ROUND_UP(((ULONG)&_bss_end__));
-//   Length = ParamLength;
-   Length = LastKernelAddress - (ULONG)BaseAddress;
+                      MmGetKernelAddressSpace(),
+                      MEMORY_AREA_SYSTEM,
+                      &BaseAddress,
+                      Length,
+                      0,
+                      &MArea,
+                      TRUE,
+                      FALSE,
+                      BoundaryAddressMultiple);
+
+   BaseAddress = (PVOID)PAGE_ROUND_UP(((ULONG_PTR)&_bss_end__));
+   Length = LastKernelAddress - (ULONG_PTR)BaseAddress;
    MmCreateMemoryArea(NULL,
-                     MmGetKernelAddressSpace(),                      
-                     MEMORY_AREA_SYSTEM,
-                     &BaseAddress,
-                     Length,
-                     0,
-                     &kernel_param_desc,
-                     FALSE);
-
-   BaseAddress = (PVOID)(LastKernelAddress + PAGE_SIZE);
-   Length = NONPAGED_POOL_SIZE;
+                      MmGetKernelAddressSpace(),
+                      MEMORY_AREA_SYSTEM,
+                      &BaseAddress,
+                      Length,
+                      0,
+                      &MArea,
+                      TRUE,
+                      FALSE,
+                      BoundaryAddressMultiple);
+
+   BaseAddress = MiNonPagedPoolStart;
    MmCreateMemoryArea(NULL,
-                     MmGetKernelAddressSpace(),
-                     MEMORY_AREA_SYSTEM,
-                     &BaseAddress,
-                     Length,
-                     0,
-                     &kernel_pool_desc,
-                     FALSE);
+                      MmGetKernelAddressSpace(),
+                      MEMORY_AREA_SYSTEM,
+                      &BaseAddress,
+                      MiNonPagedPoolLength,
+                      0,
+                      &MArea,
+                      TRUE,
+                      FALSE,
+                      BoundaryAddressMultiple);
+
+   BaseAddress = MmPagedPoolBase;
+   Status = MmCreateMemoryArea(NULL,
+                               MmGetKernelAddressSpace(),
+                               MEMORY_AREA_PAGED_POOL,
+                               &BaseAddress,
+                               MmPagedPoolSize,
+                               0,
+                               &MArea,
+                               TRUE,
+                               FALSE,
+                               BoundaryAddressMultiple);
 
-   MmPagedPoolSize = MM_PAGED_POOL_SIZE;
-   BaseAddress = (PVOID)(LastKernelAddress + PAGE_SIZE + NONPAGED_POOL_SIZE +
-                        PAGE_SIZE);
-   MmPagedPoolBase = BaseAddress;
-   Length = MM_PAGED_POOL_SIZE;
-   MmCreateMemoryArea(NULL,
-                     MmGetKernelAddressSpace(),
-                     MEMORY_AREA_PAGED_POOL,
-                     &BaseAddress,
-                     Length,
-                     0,
-                     &MiPagedPoolDescriptor,
-                     FALSE);
    MmInitializePagedPool();
 
    /*
@@ -172,25 +259,27 @@ VOID MmInitVirtualMemory(ULONG LastKernelAddress,
    BaseAddress = (PVOID)KI_USER_SHARED_DATA;
    Length = PAGE_SIZE;
    MmCreateMemoryArea(NULL,
-                     MmGetKernelAddressSpace(),
-                     MEMORY_AREA_SYSTEM,
-                     &BaseAddress,
-                     Length,
-                     0,
-                     &kernel_shared_data_desc,
-                     FALSE);
-   Status = MmRequestPageMemoryConsumer(MC_NPPOOL, TRUE, 
-                                       &MmSharedDataPagePhysicalAddress);
+                      MmGetKernelAddressSpace(),
+                      MEMORY_AREA_SYSTEM,
+                      &BaseAddress,
+                      Length,
+                      0,
+                      &MArea,
+                      TRUE,
+                      FALSE,
+                      BoundaryAddressMultiple);
+   Status = MmRequestPageMemoryConsumer(MC_NPPOOL, TRUE, &Pfn);
+   MmSharedDataPagePhysicalAddress.QuadPart = Pfn << PAGE_SHIFT;
    Status = MmCreateVirtualMapping(NULL,
-                                  (PVOID)KI_USER_SHARED_DATA,
-                                  PAGE_READWRITE,
-                                  MmSharedDataPagePhysicalAddress,
-                                  TRUE);
+                                   (PVOID)KI_USER_SHARED_DATA,
+                                   PAGE_READWRITE,
+                                   &Pfn,
+                                   1);
    if (!NT_SUCCESS(Status))
-     {
-       DbgPrint("Unable to create virtual mapping\n");
-       KeBugCheck(0);
-     }
+   {
+      DbgPrint("Unable to create virtual mapping\n");
+      KEBUGCHECK(0);
+   }
    RtlZeroMemory(BaseAddress, Length);
 
    /*
@@ -199,50 +288,55 @@ VOID MmInitVirtualMemory(ULONG LastKernelAddress,
    MmInitializeMemoryConsumer(MC_USER, MmTrimUserMemory);
 }
 
-VOID MmInit1(ULONG FirstKrnlPhysAddr,
-            ULONG LastKrnlPhysAddr,
-            ULONG LastKernelAddress,
-            PADDRESS_RANGE BIOSMemoryMap,
-            ULONG AddressRangeCount)
+VOID
+INIT_FUNCTION
+NTAPI
+MmInit1(ULONG_PTR FirstKrnlPhysAddr,
+        ULONG_PTR LastKrnlPhysAddr,
+        ULONG_PTR LastKernelAddress,
+        PADDRESS_RANGE BIOSMemoryMap,
+        ULONG AddressRangeCount,
+        ULONG MaxMem)
 /*
  * FUNCTION: Initalize memory managment
  */
 {
    ULONG i;
    ULONG kernel_len;
-#ifndef MP
-   extern unsigned int unmap_me, unmap_me2, unmap_me3;
-#endif
+   ULONG_PTR MappingAddress;
 
-   DPRINT("MmInit1(FirstKrnlPhysAddr, %x, LastKrnlPhysAddr %x, LastKernelAddress %x)\n",
-                 FirstKrnlPhysAddr,
-                 LastKrnlPhysAddr,
-                 LastKernelAddress);
+   DPRINT("MmInit1(FirstKrnlPhysAddr, %p, LastKrnlPhysAddr %p, LastKernelAddress %p)\n",
+          FirstKrnlPhysAddr,
+          LastKrnlPhysAddr,
+          LastKernelAddress);
 
    if ((BIOSMemoryMap != NULL) && (AddressRangeCount > 0))
-     {
-       // If we have a bios memory map, recalulate the the memory size
-       ULONG last = 0;
-       for (i = 0; i < AddressRangeCount; i++)
-         {
-           if (BIOSMemoryMap[i].Type == 1
-               && (BIOSMemoryMap[i].BaseAddrLow + BIOSMemoryMap[i].LengthLow + PAGE_SIZE -1) / PAGE_SIZE > last)
-             {
-                last = (BIOSMemoryMap[i].BaseAddrLow + BIOSMemoryMap[i].LengthLow + PAGE_SIZE -1) / PAGE_SIZE;
-             }
-         }
-       if ((last - 256) * 4 > KeLoaderBlock.MemHigher)
-         {
-            KeLoaderBlock.MemHigher = (last - 256) * 4;
-         }
-     }
+   {
+      // If we have a bios memory map, recalulate the memory size
+      ULONG last = 0;
+      for (i = 0; i < AddressRangeCount; i++)
+      {
+         if (BIOSMemoryMap[i].Type == 1
+               && (BIOSMemoryMap[i].BaseAddrLow + BIOSMemoryMap[i].LengthLow + PAGE_SIZE -1) / PAGE_SIZE > last)
+         {
+            last = (BIOSMemoryMap[i].BaseAddrLow + BIOSMemoryMap[i].LengthLow + PAGE_SIZE -1) / PAGE_SIZE;
+         }
+      }
+      if ((last - 256) * 4 > KeLoaderBlock.MemHigher)
+      {
+         KeLoaderBlock.MemHigher = (last - 256) * 4;
+      }
+   }
+
+   if (KeLoaderBlock.MemHigher >= (MaxMem - 1) * 1024)
+   {
+      KeLoaderBlock.MemHigher = (MaxMem - 1) * 1024;
+   }
+
+   /* Set memory limits */
+   MmUserProbeAddress = (ULONG_PTR)MmSystemRangeStart - 0x10000;
+   MmHighestUserAddress = (PVOID)(MmUserProbeAddress - 1);
 
-   /*
-    * FIXME: Set this based on the system command line
-    */
-   MmUserProbeAddress = (PVOID)0x7fff0000;
-   MmHighestUserAddress = (PVOID)0x7ffeffff;
-   
    /*
     * Initialize memory managment statistics
     */
@@ -256,87 +350,84 @@ VOID MmInit1(ULONG FirstKrnlPhysAddr,
    MmStats.PagingRequestsInLastMinute = 0;
    MmStats.PagingRequestsInLastFiveMinutes = 0;
    MmStats.PagingRequestsInLastFifteenMinutes = 0;
-   
-   /*
-    * Initialize the kernel address space
-    */
-   MmInitializeKernelAddressSpace();
 
-   /*
-    * Unmap low memory
-    */
-#ifndef MP
-   /* In SMP mode we unmap the low memory in MmInit3. 
-      The APIC needs the mapping of the first pages
-      while the processors are starting up. */
-   MmDeletePageTable(NULL, 0);
-#endif
    /*
     * Free all pages not used for kernel memory
     * (we assume the kernel occupies a continuous range of physical
     * memory)
     */
    DPRINT("first krnl %x\nlast krnl %x\n",FirstKrnlPhysAddr,
-         LastKrnlPhysAddr);
-   
+          LastKrnlPhysAddr);
+
    /*
     * Free physical memory not used by the kernel
     */
    MmStats.NrTotalPages = KeLoaderBlock.MemHigher/4;
    if (!MmStats.NrTotalPages)
-     {
-       DbgPrint("Memory not detected, default to 8 MB\n");
-       MmStats.NrTotalPages = 2048;
-     }
+   {
+      DbgPrint("Memory not detected, default to 8 MB\n");
+      MmStats.NrTotalPages = 2048;
+   }
    else
-     {
-       /* add 1MB for standard memory (not extended) */
-       MmStats.NrTotalPages += 256;
-     }
+   {
+      /* add 1MB for standard memory (not extended) */
+      MmStats.NrTotalPages += 256;
+   }
 #ifdef BIOS_MEM_FIX
-  MmStats.NrTotalPages += 16;
+   MmStats.NrTotalPages += 16;
 #endif
-   DbgPrint("Used memory %dKb\n", (MmStats.NrTotalPages * PAGE_SIZE) / 1024);
 
-   LastKernelAddress = (ULONG)MmInitializePageList(
-                                          (PVOID)FirstKrnlPhysAddr,
-                                          (PVOID)LastKrnlPhysAddr,
-                                          MmStats.NrTotalPages,
-                                          PAGE_ROUND_UP(LastKernelAddress),
-             BIOSMemoryMap,
-             AddressRangeCount);
+   /*
+    * Initialize the kernel address space
+    */
+   MmInitializeKernelAddressSpace();
+
+   MmInitGlobalKernelPageDirectory();
+
+   DbgPrint("Used memory %dKb\n", (MmStats.NrTotalPages * PAGE_SIZE) / 1024);
+   DPRINT1("Kernel Stack Limits. InitTop = 0x%x, Init = 0x%x\n", init_stack_top, init_stack);
+
+   LastKernelAddress = (ULONG_PTR)MmInitializePageList(
+                       FirstKrnlPhysAddr,
+                       LastKrnlPhysAddr,
+                       MmStats.NrTotalPages,
+                       PAGE_ROUND_UP(LastKernelAddress),
+                       BIOSMemoryMap,
+                       AddressRangeCount);
    kernel_len = LastKrnlPhysAddr - FirstKrnlPhysAddr;
-   
+
    /*
-    * Create a trap for null pointer references and protect text
-    * segment
+    * Unmap low memory
     */
-   CHECKPOINT;
-   DPRINT("_text_start__ %x _text_end__ %x\n",(int)&_text_start__,(int)&_text_end__);
-   for (i=PAGE_ROUND_UP(((int)&_text_start__));
-       i<PAGE_ROUND_DOWN(((int)&_text_end__));i=i+PAGE_SIZE)
-     {
-       MmSetPageProtect(NULL,
-                        (PVOID)i,
-                        PAGE_EXECUTE_READ);
+#ifdef CONFIG_SMP
+   /* In SMP mode we unmap the low memory pagetable in MmInit3.
+      The APIC needs the mapping of the first pages
+      while the processors are starting up.
+      We unmap all pages except page 2 and 3. */
+   for (MappingAddress = 0;
+        MappingAddress < 1024 * PAGE_SIZE;
+        MappingAddress += PAGE_SIZE)
+   {
+      if (MappingAddress != 2 * PAGE_SIZE &&
+          MappingAddress != 3 * PAGE_SIZE)
+      {
+         MmRawDeleteVirtualMapping((PVOID)MappingAddress);
+      }
    }
+#else
+   MmDeletePageTable(NULL, 0);
+#endif
 
    DPRINT("Invalidating between %x and %x\n",
-         LastKernelAddress,
-         KERNEL_BASE + 2 * PAGE_TABLE_SIZE);
-   for (i=(LastKernelAddress); 
-        i<(KERNEL_BASE + 2 * PAGE_TABLE_SIZE); 
-        i=i+PAGE_SIZE)
-     {
-        MmDeleteVirtualMapping(NULL, (PVOID)(i), FALSE, NULL, NULL);
-     }
+          LastKernelAddress, KERNEL_BASE + 0x00600000);
+   for (MappingAddress = LastKernelAddress;
+        MappingAddress < KERNEL_BASE + 0x00600000;
+        MappingAddress += PAGE_SIZE)
+   {
+      MmRawDeleteVirtualMapping((PVOID)MappingAddress);
+   }
+
    DPRINT("Almost done MmInit()\n");
-#ifndef MP
-   /* FIXME: This is broken in SMP mode */
-   MmDeleteVirtualMapping(NULL, (PVOID)&unmap_me, FALSE, NULL, NULL);
-   MmDeleteVirtualMapping(NULL, (PVOID)&unmap_me2, FALSE, NULL, NULL);
-   MmDeleteVirtualMapping(NULL, (PVOID)&unmap_me3, FALSE, NULL, NULL);
-#endif
    /*
     * Intialize memory areas
     */
@@ -345,26 +436,34 @@ VOID MmInit1(ULONG FirstKrnlPhysAddr,
    MmInitializeMdlImplementation();
 }
 
-VOID MmInit2(VOID)
+VOID
+NTAPI
+INIT_FUNCTION
+MmInit2(VOID)
 {
+   MmInitializeRmapList();
+   MmInitializePageOp();
    MmInitSectionImplementation();
    MmInitPagingFile();
 }
 
-VOID MmInit3(VOID)
+VOID
+INIT_FUNCTION
+NTAPI
+MmInit3(VOID)
 {
    /*
     * Unmap low memory
     */
-#ifdef MP
-   /* In SMP mode we can unmap the low memory  
+#ifdef CONFIG_SMP
+   /* In SMP mode we can unmap the low memory
       if all processors are started. */
    MmDeletePageTable(NULL, 0);
 #endif
-   MmInitPagerThread();
+
+   MmInitZeroPageThread();
    MmCreatePhysicalMemorySection();
-   MmInitializeRmapList();
-   MmInitializePageOp();
+   MiInitBalancerThread();
 
    /*
     * Initialise the modified page writer.
@@ -374,3 +473,26 @@ VOID MmInit3(VOID)
    /* FIXME: Read parameters from memory */
 }
 
+VOID STATIC
+MiFreeInitMemoryPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address,
+                     PFN_TYPE Page, SWAPENTRY SwapEntry,
+                     BOOLEAN Dirty)
+{
+   ASSERT(SwapEntry == 0);
+   if (Page != 0)
+   {
+      MmReleasePageMemoryConsumer(MC_NPPOOL, Page);
+   }
+}
+
+VOID
+NTAPI
+MiFreeInitMemory(VOID)
+{
+   MmLockAddressSpace(MmGetKernelAddressSpace());
+   MmFreeMemoryAreaByPtr(MmGetKernelAddressSpace(),
+                         (PVOID)&_init_start__,
+                         MiFreeInitMemoryPage,
+                         NULL);
+   MmUnlockAddressSpace(MmGetKernelAddressSpace());
+}