/*
* PROJECT: ReactOS Kernel
* LICENSE: BSD - See COPYING.ARM in the top level directory
- * FILE: ntoskrnl/mm/ARM3/init.c
- * PURPOSE: ARM Memory Manager Initialization
+ * FILE: ntoskrnl/mm/ARM3/i386/init.c
+ * PURPOSE: ARM Memory Manager Initialization for x86
* PROGRAMMERS: ReactOS Portable Systems Group
*/
ULONG MxPfnAllocation;
//
-// The ARM³ PFN Database
+// This structure describes the different pieces of RAM-backed address space
//
-PMMPFN MmArmPfnDatabase;
+PPHYSICAL_MEMORY_DESCRIPTOR MmPhysicalMemoryBlock;
//
-// This structure describes the different pieces of RAM-backed address space
+// Before we have a PFN database, memory comes straight from our physical memory
+// blocks, which is nice because it's guaranteed contiguous and also because once
+// we take a page from here, the system doesn't see it anymore.
+// However, once the fun is over, those pages must be re-integrated back into
+// PFN society life, and that requires us keeping a copy of the original layout
+// so that we can parse it later.
//
-PPHYSICAL_MEMORY_DESCRIPTOR MmPhysicalMemoryBlock;
+PMEMORY_ALLOCATION_DESCRIPTOR MxFreeDescriptor;
+MEMORY_ALLOCATION_DESCRIPTOR MxOldFreeDescriptor;
+
+//
+// This is where we keep track of the most basic physical layout markers
+//
+ULONG MmNumberOfPhysicalPages, MmHighestPhysicalPage, MmLowestPhysicalPage;
/* PRIVATE FUNCTIONS **********************************************************/
}
}
+PFN_NUMBER
+NTAPI
+MxGetNextPage(IN PFN_NUMBER PageCount)
+{
+ PFN_NUMBER Pfn;
+
+ //
+ // Make sure we have enough pages
+ //
+ if (PageCount > MxFreeDescriptor->PageCount)
+ {
+ //
+ // Crash the system
+ //
+ KeBugCheckEx(INSTALL_MORE_MEMORY,
+ MmNumberOfPhysicalPages,
+ MxFreeDescriptor->PageCount,
+ MxOldFreeDescriptor.PageCount,
+ PageCount);
+ }
+
+ //
+ // Use our highest usable free pages
+ //
+ Pfn = MxFreeDescriptor->BasePage + MxFreeDescriptor->PageCount - PageCount;
+ MxFreeDescriptor->PageCount -= PageCount;
+ return Pfn;
+}
+
PPHYSICAL_MEMORY_DESCRIPTOR
NTAPI
MmInitializeMemoryLimits(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
MmArmInitSystem(IN ULONG Phase,
IN PLOADER_PARAMETER_BLOCK LoaderBlock)
{
+ PLIST_ENTRY NextEntry;
+ PMEMORY_ALLOCATION_DESCRIPTOR MdBlock;
+ ULONG FreePages = 0;
PMEMORY_AREA MArea;
- PHYSICAL_ADDRESS BoundaryAddressMultiple, Low, High;
+ PHYSICAL_ADDRESS BoundaryAddressMultiple;
PFN_NUMBER PageFrameIndex;
PMMPTE StartPde, EndPde, PointerPte, LastPte;
MMPTE TempPde = HyperTemplatePte, TempPte = HyperTemplatePte;
ULONG OldCount;
BOOLEAN IncludeType[LoaderMaximum];
ULONG i;
- BoundaryAddressMultiple.QuadPart = Low.QuadPart = 0;
- High.QuadPart = -1;
+ BoundaryAddressMultiple.QuadPart = 0;
if (Phase == 0)
{
EndPde = MiAddressToPde(KSEG0_BASE);
RtlZeroMemory(StartPde, (EndPde - StartPde) * sizeof(MMPTE));
+ //
+ // Loop the memory descriptors
+ //
+ NextEntry = LoaderBlock->MemoryDescriptorListHead.Flink;
+ while (NextEntry != &LoaderBlock->MemoryDescriptorListHead)
+ {
+ //
+ // Get the memory block
+ //
+ MdBlock = CONTAINING_RECORD(NextEntry,
+ MEMORY_ALLOCATION_DESCRIPTOR,
+ ListEntry);
+
+ //
+ // Skip invisible memory
+ //
+ if ((MdBlock->MemoryType != LoaderFirmwarePermanent) &&
+ (MdBlock->MemoryType != LoaderSpecialMemory) &&
+ (MdBlock->MemoryType != LoaderHALCachedMemory) &&
+ (MdBlock->MemoryType != LoaderBBTMemory))
+ {
+ //
+ // Check if BURNMEM was used
+ //
+ if (MdBlock->MemoryType != LoaderBad)
+ {
+ //
+ // Count this in the total of pages
+ //
+ MmNumberOfPhysicalPages += MdBlock->PageCount;
+ }
+
+ //
+ // Check if this is the new lowest page
+ //
+ if (MdBlock->BasePage < MmLowestPhysicalPage)
+ {
+ //
+ // Update the lowest page
+ //
+ MmLowestPhysicalPage = MdBlock->BasePage;
+ }
+
+ //
+ // Check if this is the new highest page
+ //
+ PageFrameIndex = MdBlock->BasePage + MdBlock->PageCount;
+ if (PageFrameIndex > MmHighestPhysicalPage)
+ {
+ //
+ // Update the highest page
+ //
+ MmHighestPhysicalPage = PageFrameIndex - 1;
+ }
+
+ //
+ // Check if this is free memory
+ //
+ if ((MdBlock->MemoryType == LoaderFree) ||
+ (MdBlock->MemoryType == LoaderLoadedProgram) ||
+ (MdBlock->MemoryType == LoaderFirmwareTemporary) ||
+ (MdBlock->MemoryType == LoaderOsloaderStack))
+ {
+ //
+ // Check if this is the largest memory descriptor
+ //
+ if (MdBlock->PageCount > FreePages)
+ {
+ //
+ // For now, it is
+ //
+ FreePages = MdBlock->PageCount;
+ MxFreeDescriptor = MdBlock;
+ }
+ }
+ }
+
+ //
+ // Keep going
+ //
+ NextEntry = MdBlock->ListEntry.Flink;
+ }
+
+ //
+ // Save original values of the free descriptor, since it'll be
+ // altered by early allocations
+ //
+ MxOldFreeDescriptor = *MxFreeDescriptor;
+
//
// Check if this is a machine with less than 19MB of RAM
//
MxPfnAllocation = (MmHighestPhysicalPage + 1) * sizeof(MMPFN);
MxPfnAllocation >>= PAGE_SHIFT;
+ //
+ // We have to add one to the count here, because in the process of
+ // shifting down to the page size, we actually ended up getting the
+ // lower aligned size (so say, 0x5FFFF bytes is now 0x5F pages).
+ // Later on, we'll shift this number back into bytes, which would cause
+ // us to end up with only 0x5F000 bytes -- when we actually want to have
+ // 0x60000 bytes.
+ //
+ MxPfnAllocation++;
+
//
// Now calculate the nonpaged pool expansion VA region
//
// with the old memory manager, so we'll create a "Shadow PFN Database"
// instead, and arbitrarly start it at 0xB0000000.
//
- MmArmPfnDatabase = (PVOID)0xB0000000;
- ASSERT(((ULONG_PTR)MmArmPfnDatabase & ((4 * 1024 * 1024) - 1)) == 0);
+ MmPfnDatabase = (PVOID)0xB0000000;
+ ASSERT(((ULONG_PTR)MmPfnDatabase & ((4 * 1024 * 1024) - 1)) == 0);
//
// Non paged pool comes after the PFN database
//
- MmNonPagedPoolStart = (PVOID)((ULONG_PTR)MmArmPfnDatabase +
+ MmNonPagedPoolStart = (PVOID)((ULONG_PTR)MmPfnDatabase +
(MxPfnAllocation << PAGE_SHIFT));
//
// Now we actually need to get these many physical pages. Nonpaged pool
// is actually also physically contiguous (but not the expansion)
//
- PageFrameIndex = MmGetContinuousPages(MmSizeOfNonPagedPoolInBytes +
- (MxPfnAllocation << PAGE_SHIFT),
- Low,
- High,
- BoundaryAddressMultiple,
- FALSE);
+ PageFrameIndex = MxGetNextPage(MxPfnAllocation +
+ (MmSizeOfNonPagedPoolInBytes >> PAGE_SHIFT));
ASSERT(PageFrameIndex != 0);
- DPRINT1(" 0x%p - 0x%p\t%s\n",
- MmArmPfnDatabase,
- (ULONG_PTR)MmArmPfnDatabase + (MxPfnAllocation << PAGE_SHIFT),
- "Shadow PFN Database");
DPRINT("PFN DB PA PFN begins at: %lx\n", PageFrameIndex);
- DPRINT1(" 0x%p - 0x%p\t%s\n",
- MmNonPagedPoolStart,
- (ULONG_PTR)MmNonPagedPoolStart + MmSizeOfNonPagedPoolInBytes,
- "ARM Non Paged Pool");
DPRINT("NP PA PFN begins at: %lx\n", PageFrameIndex + MxPfnAllocation);
//
//
// Get a page
//
- TempPde.u.Hard.PageFrameNumber = MmAllocPage(MC_SYSTEM, 0);
+ TempPde.u.Hard.PageFrameNumber = MxGetNextPage(1);
ASSERT(TempPde.u.Hard.Valid == 1);
*StartPde = TempPde;
//
// Now we need pages for the page tables which will map initial NP
//
- StartPde = MiAddressToPde(MmArmPfnDatabase);
+ StartPde = MiAddressToPde(MmPfnDatabase);
EndPde = MiAddressToPde((PVOID)((ULONG_PTR)MmNonPagedPoolStart +
MmSizeOfNonPagedPoolInBytes - 1));
while (StartPde <= EndPde)
//
// Get a page
//
- TempPde.u.Hard.PageFrameNumber = MmAllocPage(MC_SYSTEM, 0);
+ TempPde.u.Hard.PageFrameNumber = MxGetNextPage(1);
ASSERT(TempPde.u.Hard.Valid == 1);
*StartPde = TempPde;
// Now remember where the expansion starts
//
MmNonPagedPoolExpansionStart = NonPagedPoolExpansionVa;
- 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");
//
// Last step is to actually map the nonpaged pool
// Now go ahead and initialize the ARM pool
//
MiInitializeArmPool();
+ }
+ else if (Phase == 1) // IN BETWEEN, THE PFN DATABASE IS NOW CREATED
+ {
+ //
+ // Initialize the nonpaged pool
+ //
+ InitializePool(NonPagedPool, 0);
//
// We PDE-aligned the nonpaged system start VA, so haul some extra PTEs!
// Sync us up with ReactOS Mm
//
MiSyncARM3WithROS(MmNonPagedSystemStart, (PVOID)((ULONG_PTR)MmNonPagedPoolEnd - 1));
- MiSyncARM3WithROS(MmArmPfnDatabase, (PVOID)((ULONG_PTR)MmNonPagedPoolStart + MmSizeOfNonPagedPoolInBytes - 1));
+ MiSyncARM3WithROS(MmPfnDatabase, (PVOID)((ULONG_PTR)MmNonPagedPoolStart + MmSizeOfNonPagedPoolInBytes - 1));
MiSyncARM3WithROS((PVOID)HYPER_SPACE, (PVOID)(HYPER_SPACE + PAGE_SIZE - 1));
-
- //
- // Initialize the nonpaged pool
- //
- InitializePool(NonPagedPool, 0);
-
+
//
- // Do a little test of the nonpaged pool allocator
+ // Print the memory layout
//
- if (0)
- {
- ULONG i = 0;
- PVOID Buffers[4096];
- while (TRUE)
- {
- Buffers[i] = MiAllocatePoolPages(NonPagedPool, PAGE_SIZE);
- if (!Buffers[i]) break;
- if (i == 4096) break;
- i++;
- }
-
- while (i--)
- {
- MiFreePoolPages(Buffers[i]);
- }
- }
+ 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",
+ MmNonPagedSystemStart, MmNonPagedPoolExpansionStart,
+ "System PTE Space");
+ DPRINT1(" 0x%p - 0x%p\t%s\n",
+ MmNonPagedPoolExpansionStart, MmNonPagedPoolEnd,
+ "Non Paged Pool Expansion PTE Space");
}
- else
+ else // NOW WE HAVE NONPAGED POOL
{
//
// Instantiate memory that we don't consider RAM/usable
PVOID MiNonPagedPoolStart;
ULONG MiNonPagedPoolLength;
ULONG MmBootImageSize;
-ULONG MmNumberOfPhysicalPages, MmHighestPhysicalPage, MmLowestPhysicalPage;
-ULONG_PTR MmPfnDatabaseEnd;
-PMEMORY_ALLOCATION_DESCRIPTOR MiFreeDescriptor;
-MEMORY_ALLOCATION_DESCRIPTOR MiFreeDescriptorOrg;
ULONG MmUserProbeAddress = 0;
PVOID MmHighestUserAddress = NULL;
PBOOLEAN Mm64BitPhysicalAddress = FALSE;
BoundaryAddressMultiple);
}
-VOID
-NTAPI
-MiCountFreePagesInLoaderBlock(PLOADER_PARAMETER_BLOCK LoaderBlock)
-{
- PLIST_ENTRY NextEntry;
- PMEMORY_ALLOCATION_DESCRIPTOR Md;
- ULONG FreePages = 0;
-
- 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;
-}
-
-VOID
-NTAPI
-MiDbgKernelLayout(VOID)
-{
- DPRINT1("%8s%12s\t\t%s\n", "Start", "End", "Type");
- DPRINT1("0x%p - 0x%p\t%s\n",
- MmSystemRangeStart, (ULONG_PTR)MmSystemRangeStart + MmBootImageSize,
- "Boot Image Mapping Region");
- DPRINT1("0x%p - 0x%p\t%s\n",
- MmPfnDatabase, MmPfnDatabaseEnd,
- "PFN Database region");
- 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");
-}
-
VOID
NTAPI
MiDbgDumpMemoryDescriptors(VOID)
INIT_FUNCTION
NTAPI
MmInit1(VOID)
-{
+{
+ /* Initialize the kernel address space */
+ KeInitializeGuardedMutex(&PsGetCurrentProcess()->AddressCreationLock);
+ MmKernelAddressSpace = MmGetCurrentAddressSpace();
+ MmInitGlobalKernelPageDirectory();
+
/* Dump memory descriptors */
if (MiDbgEnableMdDump) MiDbgDumpMemoryDescriptors();
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);
-
- /* Count RAM */
- MiCountFreePagesInLoaderBlock(KeLoaderBlock);
- DbgPrint("Used memory %dKb\n", (MmNumberOfPhysicalPages * PAGE_SIZE) / 1024);
-
- /* Initialize the kernel address space */
- KeInitializeGuardedMutex(&PsGetCurrentProcess()->AddressCreationLock);
- MmKernelAddressSpace = MmGetCurrentAddressSpace();
- MmInitGlobalKernelPageDirectory();
-
- /* We'll put the PFN array right after the loaded modules */
- MmPfnDatabase = (PVOID)((ULONG_PTR)MmSystemRangeStart + MmBootImageSize);
- MmPfnDatabaseEnd = (ULONG_PTR)MmPfnDatabase + (MmHighestPhysicalPage * sizeof(MMPFN));
- MmPfnDatabaseEnd = PAGE_ROUND_UP(MmPfnDatabaseEnd);
- /* Put nonpaged pool after the PFN database */
- 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();
+ //
+ // Initialize ARM³ in phase 0
+ //
+ MmArmInitSystem(0, KeLoaderBlock);
/* Intialize system memory areas */
MiInitSystemMemoryAreas();
-
+
/* Initialize the page list */
MmInitializePageList();
//
- // Initialize ARM³ in phase 0
+ // Initialize ARM³ in phase 1
//
- MmArmInitSystem(0, KeLoaderBlock);
-
- /* Initialize nonpaged pool */
- MiInitializeNonPagedPool();
+ MmArmInitSystem(1, KeLoaderBlock);
+ // DEPRECATED
+ /* Put nonpaged pool after the loaded modules */ // DEPRECATED
+ MiNonPagedPoolStart = (PVOID)((ULONG_PTR)MmSystemRangeStart + // DEPRECATED
+ MmBootImageSize); // DEPRECATED
+ MiNonPagedPoolLength = MM_NONPAGED_POOL_SIZE; // DEPRECATED
+ // DEPRECATED
+ /* Initialize nonpaged pool */ // DEPRECATED
+ MiInitializeNonPagedPool(); // DEPRECATED
+ // DEPRECATED
+ //
+ // Initialize ARM³ in phase 2
+ //
+ MmArmInitSystem(2, KeLoaderBlock);
+
+ /* Put the paged pool after nonpaged pool */
+ MmPagedPoolBase = (PVOID)PAGE_ROUND_UP((ULONG_PTR)MiNonPagedPoolStart +
+ MiNonPagedPoolLength);
+ MmPagedPoolSize = MM_PAGED_POOL_SIZE;
/* Initialize paged pool */
MmInitializePagedPool();
/* Initialize working sets */
MmInitializeMemoryConsumer(MC_USER, MmTrimUserMemory);
-
- //
- // Initialize ARM³ in phase 1
- //
- MmArmInitSystem(1, KeLoaderBlock);
}
BOOLEAN