PVOID MiSystemViewStart;
SIZE_T MmSystemViewSize;
+#if (_MI_PAGING_LEVELS == 2)
//
// A copy of the system page directory (the page directory associated with the
// System process) is kept (double-mapped) by the manager in order to lazily
//
PFN_NUMBER MmSystemPageDirectory[PD_COUNT];
PMMPTE MmSystemPagePtes;
+#endif
//
// The system cache starts right after hyperspace. The first few pages are for
/* And these store the respective highest PTE/PDE address */
PMMPTE MiHighestUserPte;
PMMPDE MiHighestUserPde;
+#if (_MI_PAGING_LEVELS >= 3)
+/* We need the highest PPE and PXE addresses */
+#endif
/* These variables define the system cache address space */
PVOID MmSystemCacheStart;
SIZE_T MmTotalCommitLimit;
SIZE_T MmTotalCommitLimitMaximum;
-/* PRIVATE FUNCTIONS **********************************************************/
-
-#ifndef _M_AMD64
-//
-// In Bavaria, this is probably a hate crime
-//
-VOID
-FASTCALL
-MiSyncARM3WithROS(IN PVOID AddressStart,
- IN PVOID AddressEnd)
-{
- //
- // Puerile piece of junk-grade carbonized horseshit puss sold to the lowest bidder
- //
- ULONG Pde = ADDR_TO_PDE_OFFSET(AddressStart);
- while (Pde <= ADDR_TO_PDE_OFFSET(AddressEnd))
- {
- //
- // This both odious and heinous
- //
- extern ULONG MmGlobalKernelPageDirectory[1024];
- MmGlobalKernelPageDirectory[Pde] = ((PULONG)PDE_BASE)[Pde];
- Pde++;
- }
-}
+/* Internal setting used for debugging memory descriptors */
+BOOLEAN MiDbgEnableMdDump =
+#ifdef _ARM_
+TRUE;
+#else
+FALSE;
#endif
+/* PRIVATE FUNCTIONS **********************************************************/
+
PFN_NUMBER
NTAPI
+INIT_FUNCTION
MxGetNextPage(IN PFN_NUMBER PageCount)
{
PFN_NUMBER Pfn;
VOID
NTAPI
+INIT_FUNCTION
MiComputeColorInformation(VOID)
{
ULONG L2Associativity;
VOID
NTAPI
+INIT_FUNCTION
MiInitializeColorTables(VOID)
{
ULONG i;
BOOLEAN
NTAPI
+INIT_FUNCTION
MiIsRegularMemory(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
IN PFN_NUMBER Pfn)
{
VOID
NTAPI
+INIT_FUNCTION
MiMapPfnDatabase(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
{
ULONG FreePage, FreePageCount, PagesLeft, BasePage, PageCount;
VOID
NTAPI
+INIT_FUNCTION
MiBuildPfnDatabaseFromPages(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
{
PMMPDE PointerPde;
Pfn1->u3.e2.ReferenceCount = 1;
Pfn1->u3.e1.PageLocation = ActiveAndValid;
Pfn1->u3.e1.CacheAttribute = MiNonCached;
+#if MI_TRACE_PFNS
+ Pfn1->PfnUsage = MI_USAGE_INIT_MEMORY;
+ memcpy(Pfn1->ProcessName, "Initial PDE", 16);
+#endif
}
else
{
Pfn2->u3.e2.ReferenceCount = 1;
Pfn2->u3.e1.PageLocation = ActiveAndValid;
Pfn2->u3.e1.CacheAttribute = MiNonCached;
+#if MI_TRACE_PFNS
+ Pfn2->PfnUsage = MI_USAGE_INIT_MEMORY;
+ memcpy(Pfn1->ProcessName, "Initial PTE", 16);
+#endif
}
}
}
VOID
NTAPI
+INIT_FUNCTION
MiBuildPfnDatabaseZeroPage(VOID)
{
PMMPFN Pfn1;
VOID
NTAPI
+INIT_FUNCTION
MiBuildPfnDatabaseFromLoaderBlock(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
{
PLIST_ENTRY NextEntry;
/* Check for bad RAM */
case LoaderBad:
- DPRINT1("You have damaged RAM modules. Stopping boot\n");
- while (TRUE);
+ DPRINT1("You either have specified /BURNMEMORY or damaged RAM modules.\n");
break;
/* Check for free RAM */
Pfn1->u3.e2.ReferenceCount = 1;
Pfn1->u3.e1.PageLocation = ActiveAndValid;
Pfn1->u3.e1.CacheAttribute = MiNonCached;
+#if MI_TRACE_PFNS
+ Pfn1->PfnUsage = MI_USAGE_BOOT_DRIVER;
+#endif
/* Check for RAM disk page */
if (MdBlock->MemoryType == LoaderXIPRom)
VOID
NTAPI
+INIT_FUNCTION
MiBuildPfnDatabaseSelf(VOID)
{
PMMPTE PointerPte, LastPte;
Pfn1 = MiGetPfnEntry(PointerPte->u.Hard.PageFrameNumber);
Pfn1->u2.ShareCount = 1;
Pfn1->u3.e2.ReferenceCount = 1;
+#if MI_TRACE_PFNS
+ Pfn1->PfnUsage = MI_USAGE_PFN_DATABASE;
+#endif
}
/* Next */
VOID
NTAPI
+INIT_FUNCTION
MiInitializePfnDatabase(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
{
/* Scan memory and start setting up PFN entries */
VOID
NTAPI
+INIT_FUNCTION
MiAdjustWorkingSetManagerParameters(IN BOOLEAN Client)
{
/* This function needs to do more work, for now, we tune page minimums */
VOID
NTAPI
+INIT_FUNCTION
MiNotifyMemoryEvents(VOID)
{
/* Are we in a low-memory situation? */
NTSTATUS
NTAPI
+INIT_FUNCTION
MiCreateMemoryEvent(IN PUNICODE_STRING Name,
OUT PKEVENT *Event)
{
BOOLEAN
NTAPI
+INIT_FUNCTION
MiInitializeMemoryEvents(VOID)
{
UNICODE_STRING LowString = RTL_CONSTANT_STRING(L"\\KernelObjects\\LowMemoryCondition");
VOID
NTAPI
+INIT_FUNCTION
MiAddHalIoMappings(VOID)
{
PVOID BaseAddress;
VOID
NTAPI
-MmDumpArmPfnDatabase(VOID)
+MmDumpArmPfnDatabase(IN BOOLEAN StatusOnly)
{
ULONG i;
PMMPFN Pfn1;
PCHAR Consumer = "Unknown";
KIRQL OldIrql;
ULONG ActivePages = 0, FreePages = 0, OtherPages = 0;
-
- KeRaiseIrql(HIGH_LEVEL, &OldIrql);
-
+#if MI_TRACE_PFNS
+ ULONG UsageBucket[MI_USAGE_FREE_PAGE + 1] = {0};
+ PCHAR MI_USAGE_TEXT[MI_USAGE_FREE_PAGE + 1] =
+ {
+ "Not set",
+ "Paged Pool",
+ "Nonpaged Pool",
+ "Nonpaged Pool Ex",
+ "Kernel Stack",
+ "Kernel Stack Ex",
+ "System PTE",
+ "VAD",
+ "PEB/TEB",
+ "Section",
+ "Page Table",
+ "Page Directory",
+ "Old Page Table",
+ "Driver Page",
+ "Contiguous Alloc",
+ "MDL",
+ "Demand Zero",
+ "Zero Loop",
+ "Cache",
+ "PFN Database",
+ "Boot Driver",
+ "Initial Memory",
+ "Free Page"
+ };
+#endif
//
// Loop the PFN database
//
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
for (i = 0; i <= MmHighestPhysicalPage; i++)
{
Pfn1 = MiGetPfnEntry(i);
if (!Pfn1) continue;
-
+#if MI_TRACE_PFNS
+ ASSERT(Pfn1->PfnUsage <= MI_USAGE_FREE_PAGE);
+#endif
//
// Get the page location
//
Consumer = "Active and Valid";
ActivePages++;
break;
-
+
+ case ZeroedPageList:
+
+ Consumer = "Zero Page List";
+ FreePages++;
+ break;//continue;
+
case FreePageList:
Consumer = "Free Page List";
FreePages++;
- break;
+ break;//continue;
default:
OtherPages++;
break;
}
-
+
+#if MI_TRACE_PFNS
+ /* Add into bucket */
+ UsageBucket[Pfn1->PfnUsage]++;
+#endif
+
//
// Pretty-print the page
//
- DbgPrint("0x%08p:\t%20s\t(%02d.%02d) [%08p-%08p])\n",
+ if (!StatusOnly)
+ DbgPrint("0x%08p:\t%20s\t(%04d.%04d)\t[%16s - %16s])\n",
i << PAGE_SHIFT,
Consumer,
Pfn1->u3.e2.ReferenceCount,
- Pfn1->u2.ShareCount,
- Pfn1->PteAddress,
- Pfn1->u4.PteFrame);
+ Pfn1->u2.ShareCount == LIST_HEAD ? 0xFFFF : Pfn1->u2.ShareCount,
+#if MI_TRACE_PFNS
+ MI_USAGE_TEXT[Pfn1->PfnUsage],
+ Pfn1->ProcessName);
+#else
+ "Page tracking",
+ "is disabled");
+#endif
}
- DbgPrint("Active: %d pages\t[%d KB]\n", ActivePages, (ActivePages << PAGE_SHIFT) / 1024);
- DbgPrint("Free: %d pages\t[%d KB]\n", FreePages, (FreePages << PAGE_SHIFT) / 1024);
- DbgPrint("Other: %d pages\t[%d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024);
-
+ DbgPrint("Active: %5d pages\t[%6d KB]\n", ActivePages, (ActivePages << PAGE_SHIFT) / 1024);
+ DbgPrint("Free: %5d pages\t[%6d KB]\n", FreePages, (FreePages << PAGE_SHIFT) / 1024);
+ DbgPrint("-----------------------------------------\n");
+#if MI_TRACE_PFNS
+ OtherPages = UsageBucket[MI_USAGE_BOOT_DRIVER];
+ DbgPrint("Boot Images: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024);
+ OtherPages = UsageBucket[MI_USAGE_DRIVER_PAGE];
+ DbgPrint("System Drivers: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024);
+ OtherPages = UsageBucket[MI_USAGE_PFN_DATABASE];
+ DbgPrint("PFN Database: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024);
+ OtherPages = UsageBucket[MI_USAGE_PAGE_TABLE] + UsageBucket[MI_USAGE_LEGACY_PAGE_DIRECTORY];
+ DbgPrint("Page Tables: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024);
+ OtherPages = UsageBucket[MI_USAGE_NONPAGED_POOL] + UsageBucket[MI_USAGE_NONPAGED_POOL_EXPANSION];
+ DbgPrint("NonPaged Pool: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024);
+ OtherPages = UsageBucket[MI_USAGE_PAGED_POOL];
+ DbgPrint("Paged Pool: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024);
+ OtherPages = UsageBucket[MI_USAGE_KERNEL_STACK] + UsageBucket[MI_USAGE_KERNEL_STACK_EXPANSION];
+ DbgPrint("Kernel Stack: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024);
+ OtherPages = UsageBucket[MI_USAGE_INIT_MEMORY];
+ DbgPrint("Init Memory: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024);
+ OtherPages = UsageBucket[MI_USAGE_SECTION];
+ DbgPrint("Sections: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024);
+ OtherPages = UsageBucket[MI_USAGE_CACHE];
+ DbgPrint("Cache: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024);
+#endif
KeLowerIrql(OldIrql);
}
PPHYSICAL_MEMORY_DESCRIPTOR
NTAPI
+INIT_FUNCTION
MmInitializeMemoryLimits(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
IN PBOOLEAN IncludeType)
{
VOID
NTAPI
+INIT_FUNCTION
MiBuildPagedPool(VOID)
{
PMMPTE PointerPte, PointerPde;
PFN_NUMBER PageFrameIndex;
KIRQL OldIrql;
ULONG Size, BitMapSize;
-
+#if (_MI_PAGING_LEVELS == 2)
//
// Get the page frame number for the system page directory
//
ASSERT(PD_COUNT == 1);
TempPte.u.Hard.PageFrameNumber = MmSystemPageDirectory[0];
MI_WRITE_VALID_PTE(PointerPte, TempPte);
-
+#endif
//
// Let's get back to paged pool work: size it up.
// By default, it should be twice as big as nonpaged pool.
// So now get the PDE for paged pool and zero it out
//
PointerPde = MiAddressToPde(MmPagedPoolStart);
+
+#if (_MI_PAGING_LEVELS >= 3)
+ /* On these systems, there's no double-mapping, so instead, the PPE and PXEs
+ * are setup to span the entire paged pool area, so there's no need for the
+ * system PD */
+ ASSERT(FALSE);
+#endif
+
RtlZeroMemory(PointerPde,
(1 + MiAddressToPde(MmPagedPoolEnd) - PointerPde) * sizeof(MMPTE));
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
/* Allocate a page and map the first paged pool PDE */
+ MI_SET_USAGE(MI_USAGE_PAGED_POOL);
+ MI_SET_PROCESS2("Kernel");
PageFrameIndex = MiRemoveZeroPage(0);
TempPte.u.Hard.PageFrameNumber = PageFrameIndex;
MI_WRITE_VALID_PTE(PointerPde, TempPte);
+#if (_MI_PAGING_LEVELS >= 3)
+ /* Use the PPE of MmPagedPoolStart that was setup above */
+// Bla = PFN_FROM_PTE(PpeAddress(MmPagedPool...));
+ ASSERT(FALSE);
+#else
+ /* Do it this way */
+// Bla = MmSystemPageDirectory[(PointerPde - (PMMPTE)PDE_BASE) / PDE_COUNT]
/* Initialize the PFN entry for it */
MiInitializePfnForOtherProcess(PageFrameIndex,
PointerPde,
MmSystemPageDirectory[(PointerPde - (PMMPTE)PDE_BASE) / PDE_COUNT]);
+#endif
//
// Release the PFN database lock
MiHighPagedPoolThreshold = (60 * _1MB) >> PAGE_SHIFT;
MiHighPagedPoolThreshold = min(MiHighPagedPoolThreshold, (Size * 2) / 5);
ASSERT(MiLowPagedPoolThreshold < MiHighPagedPoolThreshold);
+
+ /* Setup the global session space */
+ MiInitializeSystemSpaceMap(NULL);
}
-NTSTATUS
+VOID
NTAPI
+INIT_FUNCTION
+MiDbgDumpMemoryDescriptors(VOID)
+{
+ PLIST_ENTRY NextEntry;
+ PMEMORY_ALLOCATION_DESCRIPTOR Md;
+ ULONG TotalPages = 0;
+ 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 "
+ };
+
+ 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);
+}
+
+BOOLEAN
+NTAPI
+INIT_FUNCTION
MmArmInitSystem(IN ULONG Phase,
IN PLOADER_PARAMETER_BLOCK LoaderBlock)
{
PPHYSICAL_MEMORY_RUN Run;
PFN_NUMBER PageCount;
+ /* Dump memory descriptors */
+ if (MiDbgEnableMdDump) MiDbgDumpMemoryDescriptors();
+
//
// Instantiate memory that we don't consider RAM/usable
// We use the same exclusions that Windows does, in order to try to be
/* Highest PTE and PDE based on the addresses above */
MiHighestUserPte = MiAddressToPte(MmHighestUserAddress);
MiHighestUserPde = MiAddressToPde(MmHighestUserAddress);
-
+#if (_MI_PAGING_LEVELS >= 3)
+ /* We need the highest PPE and PXE addresses */
+ ASSERT(FALSE);
+#endif
//
// Get the size of the boot loader's image allocations and then round
// that region up to a PDE size, so that any PDEs we might create for
/* Initialize the Loader Lock */
KeInitializeMutant(&MmSystemLoadLock, FALSE);
-
+
+ /* Set the zero page event */
+ KeInitializeEvent(&MmZeroingPageEvent, SynchronizationEvent, FALSE);
+ MmZeroingPageThreadActive = FALSE;
+
//
// Count physical pages on the system
//
/* Initialize the platform-specific parts */
MiInitMachineDependent(LoaderBlock);
-
- //
- // Sync us up with ReactOS Mm
- //
- MiSyncARM3WithROS(MmNonPagedSystemStart, (PVOID)((ULONG_PTR)MmNonPagedPoolEnd - 1));
- MiSyncARM3WithROS(MmPfnDatabase, (PVOID)((ULONG_PTR)MmNonPagedPoolStart + MmSizeOfNonPagedPoolInBytes - 1));
- MiSyncARM3WithROS((PVOID)HYPER_SPACE, (PVOID)(HYPER_SPACE + PAGE_SIZE - 1));
-
+
//
// Build the physical memory block
//
//
// Always return success for now
//
- return STATUS_SUCCESS;
+ return TRUE;
}
/* EOF */