From 4e061e178b07a8da4a220a43d80f047448652535 Mon Sep 17 00:00:00 2001 From: Sir Richard Date: Wed, 10 Feb 2010 17:42:07 +0000 Subject: [PATCH] [NTOS]: MxGetNextPage is not platform-specific, so share it. [NTOS]: Factor out computations of NP sizes and limits into MiComputeNonPagedPoolVa. [NTOS]: Fix NP size/limit calculations to use the amount of FREE RAM, not the amount of INSTALLED RAM. [NTOS]: Use Windows 2003's algorithm for NP size on machines with more than 512MB of FREE RAM. [NTOS]: Partly handle the case of machines with NP over 128MB. svn path=/trunk/; revision=45556 --- reactos/ntoskrnl/mm/ARM3/i386/init.c | 280 ++++++++++++--------------- reactos/ntoskrnl/mm/ARM3/miarm.h | 6 + reactos/ntoskrnl/mm/ARM3/mminit.c | 24 +++ 3 files changed, 152 insertions(+), 158 deletions(-) diff --git a/reactos/ntoskrnl/mm/ARM3/i386/init.c b/reactos/ntoskrnl/mm/ARM3/i386/init.c index 47321eaab6e..3fcb081e20f 100644 --- a/reactos/ntoskrnl/mm/ARM3/i386/init.c +++ b/reactos/ntoskrnl/mm/ARM3/i386/init.c @@ -29,39 +29,133 @@ PMEMORY_ALLOCATION_DESCRIPTOR MxFreeDescriptor; MEMORY_ALLOCATION_DESCRIPTOR MxOldFreeDescriptor; +/* Template PTE and PDE for a kernel page */ MMPTE ValidKernelPde = {.u.Hard.Valid = 1, .u.Hard.Write = 1, .u.Hard.Dirty = 1, .u.Hard.Accessed = 1}; MMPTE ValidKernelPte = {.u.Hard.Valid = 1, .u.Hard.Write = 1, .u.Hard.Dirty = 1, .u.Hard.Accessed = 1}; +/* Make the code cleaner with some definitions for size multiples */ +#define _1KB (1024) +#define _1MB (1000 * _1KB) + +/* Architecture specific size of a PDE directory, and size of a page table */ +#define PDE_SIZE (4096 * sizeof(MMPDE)) +#define PT_SIZE (1024 * sizeof(MMPTE)) + /* PRIVATE FUNCTIONS **********************************************************/ -PFN_NUMBER +VOID NTAPI -MxGetNextPage(IN PFN_NUMBER PageCount) +MiComputeNonPagedPoolVa(IN ULONG FreePages) { - PFN_NUMBER Pfn; - - // - // Make sure we have enough pages - // - if (PageCount > MxFreeDescriptor->PageCount) + IN PFN_NUMBER PoolPages; + + /* Check if this is a machine with less than 256MB of RAM, and no overide */ + if ((MmNumberOfPhysicalPages <= MI_MIN_PAGES_FOR_NONPAGED_POOL_TUNING) && + !(MmSizeOfNonPagedPoolInBytes)) { - // - // Crash the system - // - KeBugCheckEx(INSTALL_MORE_MEMORY, - MmNumberOfPhysicalPages, - MxFreeDescriptor->PageCount, - MxOldFreeDescriptor.PageCount, - PageCount); + /* Force the non paged pool to be 2MB so we can reduce RAM usage */ + MmSizeOfNonPagedPoolInBytes = 2 * _1MB; } - // - // Use our lowest usable free pages - // - Pfn = MxFreeDescriptor->BasePage; - MxFreeDescriptor->BasePage += PageCount; - MxFreeDescriptor->PageCount -= PageCount; - return Pfn; + /* Hyperspace ends here */ + MmHyperSpaceEnd = (PVOID)((ULONG_PTR)MmSystemCacheWorkingSetList - 1); + + /* Check if the user gave a ridicuously large nonpaged pool RAM size */ + if ((MmSizeOfNonPagedPoolInBytes >> PAGE_SHIFT) > (FreePages * 7 / 8)) + { + /* More than 7/8ths of RAM was dedicated to nonpaged pool, ignore! */ + MmSizeOfNonPagedPoolInBytes = 0; + } + + /* Check if no registry setting was set, or if the setting was too low */ + if (MmSizeOfNonPagedPoolInBytes < MmMinimumNonPagedPoolSize) + { + /* Start with the minimum (256 KB) and add 32 KB for each MB above 4 */ + MmSizeOfNonPagedPoolInBytes = MmMinimumNonPagedPoolSize; + MmSizeOfNonPagedPoolInBytes += (FreePages - 1024) / 256 * MmMinAdditionNonPagedPoolPerMb; + } + + /* Check if the registy setting or our dynamic calculation was too high */ + if (MmSizeOfNonPagedPoolInBytes > MI_MAX_INIT_NONPAGED_POOL_SIZE) + { + /* Set it to the maximum */ + MmSizeOfNonPagedPoolInBytes = MI_MAX_INIT_NONPAGED_POOL_SIZE; + } + + /* Check if a percentage cap was set through the registry */ + if (MmMaximumNonPagedPoolPercent) UNIMPLEMENTED; + + /* Page-align the nonpaged pool size */ + MmSizeOfNonPagedPoolInBytes &= ~(PAGE_SIZE - 1); + + /* Now, check if there was a registry size for the maximum size */ + if (!MmMaximumNonPagedPoolInBytes) + { + /* Start with the default (1MB) */ + MmMaximumNonPagedPoolInBytes = MmDefaultMaximumNonPagedPool; + + /* Add space for PFN database */ + MmMaximumNonPagedPoolInBytes += (ULONG) + PAGE_ALIGN((MmHighestPhysicalPage + 1) * sizeof(MMPFN)); + + /* Check if the machine has more than 512MB of free RAM */ + if (FreePages >= 0x1F000) + { + /* Add 200KB for each MB above 4 */ + MmMaximumNonPagedPoolInBytes += (FreePages - 1024) / 256 * + (MmMaxAdditionNonPagedPoolPerMb / 2); + if (MmMaximumNonPagedPoolInBytes < MI_MAX_NONPAGED_POOL_SIZE) + { + /* Make it at least 128MB since this machine has a lot of RAM */ + MmMaximumNonPagedPoolInBytes = MI_MAX_NONPAGED_POOL_SIZE; + } + } + else + { + /* Add 400KB for each MB above 4 */ + MmMaximumNonPagedPoolInBytes += (FreePages - 1024) / 256 * + MmMaxAdditionNonPagedPoolPerMb; + } + } + + /* Make sure there's at least 16 pages + the PFN available for expansion */ + PoolPages = MmSizeOfNonPagedPoolInBytes + (PAGE_SIZE * 16) + + ((ULONG)PAGE_ALIGN(MmHighestPhysicalPage + 1) * sizeof(MMPFN)); + if (MmMaximumNonPagedPoolInBytes < PoolPages) + { + /* The maximum should be at least high enough to cover all the above */ + MmMaximumNonPagedPoolInBytes = PoolPages; + } + + /* Systems with 2GB of kernel address space get double the size */ + PoolPages = MI_MAX_NONPAGED_POOL_SIZE * 2; + + /* On the other hand, make sure that PFN + nonpaged pool doesn't get too big */ + if (MmMaximumNonPagedPoolInBytes > PoolPages) + { + /* Trim it down to the maximum architectural limit (256MB) */ + MmMaximumNonPagedPoolInBytes = PoolPages; + } + + /* Check if this is a system with > 128MB of non paged pool */ + if (MmMaximumNonPagedPoolInBytes > MI_MAX_NONPAGED_POOL_SIZE) + { + /* Check if the initial size is less than the extra 128MB boost */ + if (MmSizeOfNonPagedPoolInBytes < (MmMaximumNonPagedPoolInBytes - + MI_MAX_NONPAGED_POOL_SIZE)) + { + /* FIXME: Should check if the initial pool can be expanded */ + + /* Assume no expansion possible, check ift he maximum is too large */ + if (MmMaximumNonPagedPoolInBytes > (MmSizeOfNonPagedPoolInBytes + + MI_MAX_NONPAGED_POOL_SIZE)) + { + /* Set it to the initial value plus the boost */ + MmMaximumNonPagedPoolInBytes = MmSizeOfNonPagedPoolInBytes + + MI_MAX_NONPAGED_POOL_SIZE; + } + } + } } NTSTATUS @@ -71,7 +165,7 @@ MiInitMachineDependent(IN PLOADER_PARAMETER_BLOCK LoaderBlock) PLIST_ENTRY NextEntry; PMEMORY_ALLOCATION_DESCRIPTOR MdBlock; ULONG FreePages = 0; - PFN_NUMBER PageFrameIndex, PoolPages; + PFN_NUMBER PageFrameIndex; PMMPTE StartPde, EndPde, PointerPte, LastPte; MMPTE TempPde, TempPte; PVOID NonPagedPoolExpansionVa; @@ -79,7 +173,7 @@ MiInitMachineDependent(IN PLOADER_PARAMETER_BLOCK LoaderBlock) PFN_NUMBER FreePage, FreePageCount, PagesLeft, BasePage, PageCount; /* Check for kernel stack size that's too big */ - if (MmLargeStackSize > (KERNEL_LARGE_STACK_SIZE / 1024)) + if (MmLargeStackSize > (KERNEL_LARGE_STACK_SIZE / _1KB)) { /* Sanitize to default value */ MmLargeStackSize = KERNEL_LARGE_STACK_SIZE; @@ -87,7 +181,7 @@ MiInitMachineDependent(IN PLOADER_PARAMETER_BLOCK LoaderBlock) else { /* Take the registry setting, and convert it into bytes */ - MmLargeStackSize *= 1024; + MmLargeStackSize *= _1KB; /* Now align it to a page boundary */ MmLargeStackSize = PAGE_ROUND_UP(MmLargeStackSize); @@ -219,138 +313,8 @@ MiInitMachineDependent(IN PLOADER_PARAMETER_BLOCK LoaderBlock) // MxOldFreeDescriptor = *MxFreeDescriptor; - // - // Check if this is a machine with less than 256MB of RAM, and no overide - // - if ((MmNumberOfPhysicalPages <= MI_MIN_PAGES_FOR_NONPAGED_POOL_TUNING) && - !(MmSizeOfNonPagedPoolInBytes)) - { - // - // Force the non paged pool to be 2MB so we can reduce RAM usage - // - MmSizeOfNonPagedPoolInBytes = 2 * 1024 * 1024; - } - - // - // Hyperspace ends here - // - MmHyperSpaceEnd = (PVOID)((ULONG_PTR)MmSystemCacheWorkingSetList - 1); - - // - // Check if the user gave a ridicuously large nonpaged pool RAM size - // - if ((MmSizeOfNonPagedPoolInBytes >> PAGE_SHIFT) > - (MmNumberOfPhysicalPages * 7 / 8)) - { - // - // More than 7/8ths of RAM was dedicated to nonpaged pool, ignore! - // - MmSizeOfNonPagedPoolInBytes = 0; - } - - // - // Check if no registry setting was set, or if the setting was too low - // - if (MmSizeOfNonPagedPoolInBytes < MmMinimumNonPagedPoolSize) - { - // - // Start with the minimum (256 KB) and add 32 KB for each MB above 4 - // - MmSizeOfNonPagedPoolInBytes = MmMinimumNonPagedPoolSize; - MmSizeOfNonPagedPoolInBytes += (MmNumberOfPhysicalPages - 1024) / - 256 * MmMinAdditionNonPagedPoolPerMb; - } - - // - // Check if the registy setting or our dynamic calculation was too high - // - if (MmSizeOfNonPagedPoolInBytes > MI_MAX_INIT_NONPAGED_POOL_SIZE) - { - // - // Set it to the maximum - // - MmSizeOfNonPagedPoolInBytes = MI_MAX_INIT_NONPAGED_POOL_SIZE; - } - - // - // Check if a percentage cap was set through the registry - // - if (MmMaximumNonPagedPoolPercent) - { - // - // Don't feel like supporting this right now - // - UNIMPLEMENTED; - } - - // - // Page-align the nonpaged pool size - // - MmSizeOfNonPagedPoolInBytes &= ~(PAGE_SIZE - 1); - - // - // Now, check if there was a registry size for the maximum size - // - if (!MmMaximumNonPagedPoolInBytes) - { - // - // Start with the default (1MB) - // - MmMaximumNonPagedPoolInBytes = MmDefaultMaximumNonPagedPool; - - // - // Add space for PFN database - // - MmMaximumNonPagedPoolInBytes += (ULONG) - PAGE_ALIGN((MmHighestPhysicalPage + 1) * sizeof(MMPFN)); - - // - // Add 400KB for each MB above 4 - // - MmMaximumNonPagedPoolInBytes += (FreePages - 1024) / 256 * - MmMaxAdditionNonPagedPoolPerMb; - } - - // - // Make sure there's at least 16 pages + the PFN available for expansion - // - PoolPages = MmSizeOfNonPagedPoolInBytes + (PAGE_SIZE * 16) + - ((ULONG)PAGE_ALIGN(MmHighestPhysicalPage + 1) * - sizeof(MMPFN)); - if (MmMaximumNonPagedPoolInBytes < PoolPages) - { - // - // Set it to the minimum value for the maximum (yuck!) - // - MmMaximumNonPagedPoolInBytes = PoolPages; - } - - // - // Systems with 2GB of kernel address space get double the size - // - PoolPages = MI_MAX_NONPAGED_POOL_SIZE * 2; - - // - // Don't let the maximum go too high - // - if (MmMaximumNonPagedPoolInBytes > PoolPages) - { - // - // Set it to the upper limit - // - MmMaximumNonPagedPoolInBytes = PoolPages; - } - - // - // Check if this is a system with > 128MB of non paged pool - // - if (MmMaximumNonPagedPoolInBytes > MI_MAX_NONPAGED_POOL_SIZE) - { - // - // FIXME: Unsure about additional checks needed - // - DPRINT1("Untested path\n"); - } + /* Compute non paged pool limits and size */ + MiComputeNonPagedPoolVa(FreePages); // // Get L2 cache information diff --git a/reactos/ntoskrnl/mm/ARM3/miarm.h b/reactos/ntoskrnl/mm/ARM3/miarm.h index 77e7847a204..05fab8bc2c3 100644 --- a/reactos/ntoskrnl/mm/ARM3/miarm.h +++ b/reactos/ntoskrnl/mm/ARM3/miarm.h @@ -198,6 +198,12 @@ MiInitMachineDependent( IN PLOADER_PARAMETER_BLOCK LoaderBlock ); +PFN_NUMBER +NTAPI +MxGetNextPage( + IN PFN_NUMBER PageCount +); + PPHYSICAL_MEMORY_DESCRIPTOR NTAPI MmInitializeMemoryLimits( diff --git a/reactos/ntoskrnl/mm/ARM3/mminit.c b/reactos/ntoskrnl/mm/ARM3/mminit.c index ea1a60fd040..1d024d3f660 100644 --- a/reactos/ntoskrnl/mm/ARM3/mminit.c +++ b/reactos/ntoskrnl/mm/ARM3/mminit.c @@ -259,6 +259,30 @@ MiSyncARM3WithROS(IN PVOID AddressStart, } } +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 lowest usable free pages */ + Pfn = MxFreeDescriptor->BasePage; + MxFreeDescriptor->BasePage += PageCount; + MxFreeDescriptor->PageCount -= PageCount; + return Pfn; +} + PFN_NUMBER NTAPI MiPagesInLoaderBlock(IN PLOADER_PARAMETER_BLOCK LoaderBlock,