mirror of
https://github.com/reactos/reactos.git
synced 2024-08-16 16:39:08 +00:00
467 lines
15 KiB
C
467 lines
15 KiB
C
/*
|
|
* PROJECT: ReactOS Kernel
|
|
* LICENSE: GPL - See COPYING in the top level directory
|
|
* FILE: ntoskrnl/mm/mminit.c
|
|
* PURPOSE: Memory Manager Initialization
|
|
* PROGRAMMERS:
|
|
*/
|
|
|
|
/* INCLUDES ******************************************************************/
|
|
|
|
#include <ntoskrnl.h>
|
|
#define NDEBUG
|
|
#include <debug.h>
|
|
|
|
#define MODULE_INVOLVED_IN_ARM3
|
|
#include "ARM3/miarm.h"
|
|
|
|
/* GLOBALS *******************************************************************/
|
|
|
|
PCHAR
|
|
MemType[] =
|
|
{
|
|
"ExceptionBlock ",
|
|
"SystemBlock ",
|
|
"Free ",
|
|
"Bad ",
|
|
"LoadedProgram ",
|
|
"FirmwareTemporary ",
|
|
"FirmwarePermanent ",
|
|
"OsloaderHeap ",
|
|
"OsloaderStack ",
|
|
"SystemCode ",
|
|
"HalCode ",
|
|
"BootDriver ",
|
|
"ConsoleInDriver ",
|
|
"ConsoleOutDriver ",
|
|
"StartupDpcStack ",
|
|
"StartupKernelStack",
|
|
"StartupPanicStack ",
|
|
"StartupPcrPage ",
|
|
"StartupPdrPage ",
|
|
"RegistryData ",
|
|
"MemoryData ",
|
|
"NlsData ",
|
|
"SpecialMemory ",
|
|
"BBTMemory ",
|
|
"LoaderReserve ",
|
|
"LoaderXIPRom "
|
|
};
|
|
|
|
PBOOLEAN 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;
|
|
#else
|
|
FALSE;
|
|
#endif
|
|
|
|
/* PRIVATE FUNCTIONS *********************************************************/
|
|
|
|
VOID
|
|
INIT_FUNCTION
|
|
NTAPI
|
|
MiInitSystemMemoryAreas()
|
|
{
|
|
PVOID BaseAddress;
|
|
PHYSICAL_ADDRESS BoundaryAddressMultiple;
|
|
PMEMORY_AREA MArea;
|
|
NTSTATUS Status;
|
|
BoundaryAddressMultiple.QuadPart = 0;
|
|
|
|
//
|
|
// 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[0];
|
|
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
|
|
//
|
|
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;
|
|
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;
|
|
Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
|
|
MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC,
|
|
&BaseAddress,
|
|
PAGE_SIZE,
|
|
PAGE_READWRITE,
|
|
&MArea,
|
|
TRUE,
|
|
0,
|
|
BoundaryAddressMultiple);
|
|
ASSERT(Status == STATUS_SUCCESS);
|
|
|
|
//
|
|
// 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
|
|
MiDbgDumpAddressSpace(VOID)
|
|
{
|
|
//
|
|
// 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[0],
|
|
(ULONG_PTR)MmPfnDatabase[0] + (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
|
|
NTAPI
|
|
MiDbgDumpMemoryDescriptors(VOID)
|
|
{
|
|
PLIST_ENTRY NextEntry;
|
|
PMEMORY_ALLOCATION_DESCRIPTOR Md;
|
|
ULONG TotalPages = 0;
|
|
|
|
DPRINT1("Base\t\tLength\t\tType\n");
|
|
for (NextEntry = KeLoaderBlock->MemoryDescriptorListHead.Flink;
|
|
NextEntry != &KeLoaderBlock->MemoryDescriptorListHead;
|
|
NextEntry = NextEntry->Flink)
|
|
{
|
|
Md = CONTAINING_RECORD(NextEntry, MEMORY_ALLOCATION_DESCRIPTOR, ListEntry);
|
|
DPRINT1("%08lX\t%08lX\t%s\n", Md->BasePage, Md->PageCount, MemType[Md->MemoryType]);
|
|
TotalPages += Md->PageCount;
|
|
}
|
|
|
|
DPRINT1("Total: %08lX (%d MB)\n", TotalPages, (TotalPages * PAGE_SIZE) / 1024 / 1024);
|
|
}
|
|
|
|
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 the kernel address space */
|
|
KeInitializeGuardedMutex(&PsGetCurrentProcess()->AddressCreationLock);
|
|
MmKernelAddressSpace = MmGetCurrentAddressSpace();
|
|
MmInitGlobalKernelPageDirectory();
|
|
|
|
/* Dump memory descriptors */
|
|
if (MiDbgEnableMdDump) MiDbgDumpMemoryDescriptors();
|
|
|
|
//
|
|
// Initialize ARM³ in phase 0
|
|
//
|
|
MmArmInitSystem(0, KeLoaderBlock);
|
|
|
|
#if defined(_WINKD_)
|
|
//
|
|
// Everything required for the debugger to read and write
|
|
// physical memory is now set up
|
|
//
|
|
MiDbgReadyForPhysical = TRUE;
|
|
#endif
|
|
|
|
/* 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();
|
|
|
|
/* Initialize paged pool */
|
|
MmInitializePagedPool();
|
|
|
|
/* Initialize working sets */
|
|
MiInitializeUserPfnBitmap();
|
|
MmInitializeMemoryConsumer(MC_USER, MmTrimUserMemory);
|
|
|
|
/* Reload boot drivers */
|
|
MiReloadBootLoadedDrivers(LoaderBlock);
|
|
|
|
/* Initialize the loaded module list */
|
|
MiInitializeLoadedModuleList(LoaderBlock);
|
|
}
|
|
else if (Phase == 1)
|
|
{
|
|
MmInitializeRmapList();
|
|
MmInitializePageOp();
|
|
MmInitSectionImplementation();
|
|
MmInitPagingFile();
|
|
|
|
//
|
|
// 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
|
|
*/
|
|
MiInitBalancerThread();
|
|
|
|
/*
|
|
* Initialise the modified page writer.
|
|
*/
|
|
MmInitMpwThread();
|
|
|
|
/* Initialize the balance set manager */
|
|
MmInitBsmThread();
|
|
}
|
|
else if (Phase == 2)
|
|
{
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|