[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
This commit is contained in:
Sir Richard 2010-02-10 17:42:07 +00:00
parent b7b948cff5
commit 4e061e178b
3 changed files with 152 additions and 158 deletions

View file

@ -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

View file

@ -198,6 +198,12 @@ MiInitMachineDependent(
IN PLOADER_PARAMETER_BLOCK LoaderBlock
);
PFN_NUMBER
NTAPI
MxGetNextPage(
IN PFN_NUMBER PageCount
);
PPHYSICAL_MEMORY_DESCRIPTOR
NTAPI
MmInitializeMemoryLimits(

View file

@ -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,