[NTOS:MM] Make x64 address space layout more like Vista+
[reactos.git] / ntoskrnl / mm / ARM3 / mminit.c
index 06db17a..76d4a4b 100644 (file)
@@ -94,7 +94,6 @@ ULONG MmMaxAdditionNonPagedPoolPerMb = 400 * 1024;
 // http://www.ditii.com/2007/09/28/windows-memory-management-x86-virtual-address-space/
 //
 PVOID MmNonPagedSystemStart;
-SIZE_T MiNonPagedSystemSize;
 PVOID MmNonPagedPoolStart;
 PVOID MmNonPagedPoolExpansionStart;
 PVOID MmNonPagedPoolEnd = MI_NONPAGED_POOL_END;
@@ -359,6 +358,16 @@ SIZE_T MmAllocationFragment;
 SIZE_T MmTotalCommitLimit;
 SIZE_T MmTotalCommitLimitMaximum;
 
+/*
+ * These values tune certain user parameters. They have default values set here,
+ * as well as in the code, and can be overwritten by registry settings.
+ */
+SIZE_T MmHeapSegmentReserve = 1 * _1MB;
+SIZE_T MmHeapSegmentCommit = 2 * PAGE_SIZE;
+SIZE_T MmHeapDeCommitTotalFreeThreshold = 64 * _1KB;
+SIZE_T MmHeapDeCommitFreeBlockThreshold = PAGE_SIZE;
+SIZE_T MmMinimumStackCommitInBytes = 0;
+
 /* Internal setting used for debugging memory descriptors */
 BOOLEAN MiDbgEnableMdDump =
 #ifdef _ARM_
@@ -373,6 +382,9 @@ ULONG MiNumberDescriptors = 0;
 /* Number of free pages in the loader block */
 PFN_NUMBER MiNumberOfFreePages = 0;
 
+/* Timeout value for critical sections (2.5 minutes) */
+ULONG MmCritsectTimeoutSeconds = 150; // NT value: 720 * 60 * 60; (30 days)
+LARGE_INTEGER MmCriticalSectionTimeout;
 
 /* PRIVATE FUNCTIONS **********************************************************/
 
@@ -937,7 +949,7 @@ MiBuildPfnDatabaseFromLoaderBlock(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
                 Pfn1 = MiGetPfnEntry(PageFrameIndex);
 
                 /* Lock the PFN Database */
-                OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
+                OldIrql = MiAcquirePfnLock();
                 while (PageCount--)
                 {
                     /* If the page really has no references, mark it as free */
@@ -954,7 +966,7 @@ MiBuildPfnDatabaseFromLoaderBlock(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
                 }
 
                 /* Release PFN database */
-                KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
+                MiReleasePfnLock(OldIrql);
 
                 /* Done with this block */
                 break;
@@ -1126,7 +1138,7 @@ MmFreeLoaderBlock(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
     }
 
     /* Acquire the PFN lock */
-    OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
+    OldIrql = MiAcquirePfnLock();
 
     /* Loop the runs */
     LoaderPages = 0;
@@ -1167,8 +1179,8 @@ MmFreeLoaderBlock(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
     }
 
     /* Release the PFN lock and flush the TLB */
-    DPRINT1("Loader pages freed: %lx\n", LoaderPages);
-    KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
+    DPRINT("Loader pages freed: %lx\n", LoaderPages);
+    MiReleasePfnLock(OldIrql);
     KeFlushCurrentTb();
 
     /* Free our run structure */
@@ -1551,6 +1563,7 @@ MmDumpArmPfnDatabase(IN BOOLEAN StatusOnly)
 
     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("Other:                %5d pages\t[%6d KB]\n", OtherPages,   (OtherPages     << PAGE_SHIFT) / 1024);
     DbgPrint("-----------------------------------------\n");
 #if MI_TRACE_PFNS
     OtherPages = UsageBucket[MI_USAGE_BOOT_DRIVER];
@@ -1559,12 +1572,26 @@ MmDumpArmPfnDatabase(IN BOOLEAN StatusOnly)
     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];
+    OtherPages = UsageBucket[MI_USAGE_PAGE_TABLE] + UsageBucket[MI_USAGE_PAGE_DIRECTORY] + UsageBucket[MI_USAGE_LEGACY_PAGE_DIRECTORY];
     DbgPrint("Page Tables:          %5d pages\t[%6d KB]\n", OtherPages,   (OtherPages     << PAGE_SHIFT) / 1024);
+    OtherPages = UsageBucket[MI_USAGE_SYSTEM_PTE];
+    DbgPrint("System PTEs:          %5d pages\t[%6d KB]\n", OtherPages,   (OtherPages     << PAGE_SHIFT) / 1024);
+    OtherPages = UsageBucket[MI_USAGE_VAD];
+    DbgPrint("VADs:                 %5d pages\t[%6d KB]\n", OtherPages,   (OtherPages     << PAGE_SHIFT) / 1024);
+    OtherPages = UsageBucket[MI_USAGE_CONTINOUS_ALLOCATION];
+    DbgPrint("Continuous Allocs:    %5d pages\t[%6d KB]\n", OtherPages,   (OtherPages     << PAGE_SHIFT) / 1024);
+    OtherPages = UsageBucket[MI_USAGE_MDL];
+    DbgPrint("MDLs:                 %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_DEMAND_ZERO];
+    DbgPrint("Demand Zero:          %5d pages\t[%6d KB]\n", OtherPages,   (OtherPages     << PAGE_SHIFT) / 1024);
+    OtherPages = UsageBucket[MI_USAGE_ZERO_LOOP];
+    DbgPrint("Zero Loop:            %5d pages\t[%6d KB]\n", OtherPages,   (OtherPages     << PAGE_SHIFT) / 1024);
+    OtherPages = UsageBucket[MI_USAGE_PEB_TEB];
+    DbgPrint("PEB/TEB:              %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];
@@ -1573,6 +1600,8 @@ MmDumpArmPfnDatabase(IN BOOLEAN StatusOnly)
     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);
+    OtherPages = UsageBucket[MI_USAGE_FREE_PAGE];
+    DbgPrint("Free:                 %5d pages\t[%6d KB]\n", OtherPages,   (OtherPages     << PAGE_SHIFT) / 1024);
 #endif
     KeLowerIrql(OldIrql);
 }
@@ -1750,6 +1779,8 @@ MiBuildPagedPool(VOID)
     TempPte.u.Hard.PageFrameNumber = MmSystemPageDirectory[0];
     MI_WRITE_VALID_PTE(PointerPte, TempPte);
 #endif
+
+#ifdef _M_IX86
     //
     // Let's get back to paged pool work: size it up.
     // By default, it should be twice as big as nonpaged pool.
@@ -1766,6 +1797,7 @@ MiBuildPagedPool(VOID)
         MmSizeOfPagedPoolInBytes = (ULONG_PTR)MmNonPagedSystemStart -
                                    (ULONG_PTR)MmPagedPoolStart;
     }
+#endif // _M_IX86
 
     //
     // Get the size in pages and make sure paged pool is at least 32MB.
@@ -1785,11 +1817,13 @@ MiBuildPagedPool(VOID)
     MmSizeOfPagedPoolInBytes = Size * PAGE_SIZE * 1024;
     MmSizeOfPagedPoolInPages = MmSizeOfPagedPoolInBytes >> PAGE_SHIFT;
 
+#ifdef _M_IX86
     //
     // Let's be really sure this doesn't overflow into nonpaged system VA
     //
     ASSERT((MmSizeOfPagedPoolInBytes + (ULONG_PTR)MmPagedPoolStart) <=
            (ULONG_PTR)MmNonPagedSystemStart);
+#endif // _M_IX86
 
     //
     // This is where paged pool ends
@@ -1800,7 +1834,7 @@ MiBuildPagedPool(VOID)
     //
     // Lock the PFN database
     //
-    OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
+    OldIrql = MiAcquirePfnLock();
 
 #if (_MI_PAGING_LEVELS >= 3)
     /* On these systems, there's no double-mapping, so instead, the PPEs
@@ -1861,7 +1895,7 @@ MiBuildPagedPool(VOID)
     //
     // Release the PFN database lock
     //
-    KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
+    MiReleasePfnLock(OldIrql);
 
     //
     // We only have one PDE mapped for now... at fault time, additional PDEs
@@ -1888,7 +1922,7 @@ MiBuildPagedPool(VOID)
     //
     MmPagedPoolInfo.PagedPoolAllocationMap = ExAllocatePoolWithTag(NonPagedPool,
                                                                    Size,
-                                                                   '  mM');
+                                                                   TAG_MM);
     ASSERT(MmPagedPoolInfo.PagedPoolAllocationMap);
 
     //
@@ -1909,7 +1943,7 @@ MiBuildPagedPool(VOID)
     //
     MmPagedPoolInfo.EndOfPagedPoolBitmap = ExAllocatePoolWithTag(NonPagedPool,
                                                                  Size,
-                                                                 '  mM');
+                                                                 TAG_MM);
     ASSERT(MmPagedPoolInfo.EndOfPagedPoolBitmap);
     RtlInitializeBitMap(MmPagedPoolInfo.EndOfPagedPoolBitmap,
                         (PULONG)(MmPagedPoolInfo.EndOfPagedPoolBitmap + 1),
@@ -1990,7 +2024,7 @@ MiDbgDumpMemoryDescriptors(VOID)
         TotalPages += Md->PageCount;
     }
 
-    DPRINT1("Total: %08lX (%d MB)\n", (ULONG)TotalPages, (ULONG)(TotalPages * PAGE_SIZE) / 1024 / 1024);
+    DPRINT1("Total: %08lX (%lu MB)\n", (ULONG)TotalPages, (ULONG)(TotalPages * PAGE_SIZE) / 1024 / 1024);
 }
 
 BOOLEAN
@@ -2043,7 +2077,7 @@ MmArmInitSystem(IN ULONG Phase,
         // Define the basic user vs. kernel address space separation
         //
         MmSystemRangeStart = (PVOID)MI_DEFAULT_SYSTEM_RANGE_START;
-        MmUserProbeAddress = (ULONG_PTR)MI_HIGHEST_USER_ADDRESS;
+        MmUserProbeAddress = (ULONG_PTR)MI_USER_PROBE_ADDRESS;
         MmHighestUserAddress = (PVOID)MI_HIGHEST_USER_ADDRESS;
 
         /* Highest PTE and PDE based on the addresses above */
@@ -2090,7 +2124,7 @@ MmArmInitSystem(IN ULONG Phase,
         ASSERT(PointerPte == TestPte);
 
         /* Try a bunch of random addresses near the end of the address space */
-        PointerPte = (PMMPTE)0xFFFC8000;
+        PointerPte = (PMMPTE)((ULONG_PTR)MI_HIGHEST_SYSTEM_ADDRESS - 0x37FFF);
         for (j = 0; j < 20; j += 1)
         {
             MI_MAKE_PROTOTYPE_PTE(&TempPte, PointerPte);
@@ -2100,7 +2134,7 @@ MmArmInitSystem(IN ULONG Phase,
         }
 
         /* Subsection PTEs are always in nonpaged pool, pick a random address to try */
-        PointerPte = (PMMPTE)0xFFAACBB8;
+        PointerPte = (PMMPTE)((ULONG_PTR)MmNonPagedPoolStart + (MmSizeOfNonPagedPoolInBytes / 2));
         MI_MAKE_SUBSECTION_PTE(&TempPte, PointerPte);
         TestPte = MiSubsectionPteToSubsection(&TempPte);
         ASSERT(PointerPte == TestPte);
@@ -2119,6 +2153,9 @@ MmArmInitSystem(IN ULONG Phase,
         /* Initialize the user mode image list */
         InitializeListHead(&MmLoadedUserImageList);
 
+        /* Initialize critical section timeout value (relative time is negative) */
+        MmCriticalSectionTimeout.QuadPart = MmCritsectTimeoutSeconds * (-10000000LL);
+
         /* Initialize the paged pool mutex and the section commit mutex */
         KeInitializeGuardedMutex(&MmPagedPoolMutex);
         KeInitializeGuardedMutex(&MmSectionCommitMutex);
@@ -2165,11 +2202,39 @@ MmArmInitSystem(IN ULONG Phase,
                 //
                 MmNumberOfSystemPtes <<= 1;
             }
+            if (MmSpecialPoolTag != 0 && MmSpecialPoolTag != -1)
+            {
+                //
+                // Add some extra PTEs for special pool
+                //
+                MmNumberOfSystemPtes += 0x6000;
+            }
         }
 
-        DPRINT("System PTE count has been tuned to %d (%d bytes)\n",
+        DPRINT("System PTE count has been tuned to %lu (%lu bytes)\n",
                MmNumberOfSystemPtes, MmNumberOfSystemPtes * PAGE_SIZE);
 
+        /* Check if no values are set for the heap limits */
+        if (MmHeapSegmentReserve == 0)
+        {
+            MmHeapSegmentReserve = 2 * _1MB;
+        }
+
+        if (MmHeapSegmentCommit == 0)
+        {
+            MmHeapSegmentCommit = 2 * PAGE_SIZE;
+        }
+
+        if (MmHeapDeCommitTotalFreeThreshold == 0)
+        {
+            MmHeapDeCommitTotalFreeThreshold = 64 * _1KB;
+        }
+
+        if (MmHeapDeCommitFreeBlockThreshold == 0)
+        {
+            MmHeapDeCommitFreeBlockThreshold = PAGE_SIZE;
+        }
+
         /* Initialize the working set lock */
         ExInitializePushLock(&MmSystemCacheWs.WorkingSetMutex);
 
@@ -2262,7 +2327,7 @@ MmArmInitSystem(IN ULONG Phase,
         //
         Bitmap = ExAllocatePoolWithTag(NonPagedPool,
                                        (((MmHighestPhysicalPage + 1) + 31) / 32) * 4,
-                                       '  mM');
+                                       TAG_MM);
         if (!Bitmap)
         {
             //