-/* $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:
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);
/*
* 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();
/*
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);
/*
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
*/
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
*/
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.
/* 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());
+}