mirror of
https://github.com/reactos/reactos.git
synced 2025-06-25 17:19:44 +00:00
[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:
parent
b7b948cff5
commit
4e061e178b
3 changed files with 152 additions and 158 deletions
|
@ -29,39 +29,133 @@
|
||||||
PMEMORY_ALLOCATION_DESCRIPTOR MxFreeDescriptor;
|
PMEMORY_ALLOCATION_DESCRIPTOR MxFreeDescriptor;
|
||||||
MEMORY_ALLOCATION_DESCRIPTOR MxOldFreeDescriptor;
|
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 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};
|
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 **********************************************************/
|
/* PRIVATE FUNCTIONS **********************************************************/
|
||||||
|
|
||||||
PFN_NUMBER
|
VOID
|
||||||
NTAPI
|
NTAPI
|
||||||
MxGetNextPage(IN PFN_NUMBER PageCount)
|
MiComputeNonPagedPoolVa(IN ULONG FreePages)
|
||||||
{
|
{
|
||||||
PFN_NUMBER Pfn;
|
IN PFN_NUMBER PoolPages;
|
||||||
|
|
||||||
//
|
/* Check if this is a machine with less than 256MB of RAM, and no overide */
|
||||||
// Make sure we have enough pages
|
if ((MmNumberOfPhysicalPages <= MI_MIN_PAGES_FOR_NONPAGED_POOL_TUNING) &&
|
||||||
//
|
!(MmSizeOfNonPagedPoolInBytes))
|
||||||
if (PageCount > MxFreeDescriptor->PageCount)
|
|
||||||
{
|
{
|
||||||
//
|
/* Force the non paged pool to be 2MB so we can reduce RAM usage */
|
||||||
// Crash the system
|
MmSizeOfNonPagedPoolInBytes = 2 * _1MB;
|
||||||
//
|
|
||||||
KeBugCheckEx(INSTALL_MORE_MEMORY,
|
|
||||||
MmNumberOfPhysicalPages,
|
|
||||||
MxFreeDescriptor->PageCount,
|
|
||||||
MxOldFreeDescriptor.PageCount,
|
|
||||||
PageCount);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
/* Hyperspace ends here */
|
||||||
// Use our lowest usable free pages
|
MmHyperSpaceEnd = (PVOID)((ULONG_PTR)MmSystemCacheWorkingSetList - 1);
|
||||||
//
|
|
||||||
Pfn = MxFreeDescriptor->BasePage;
|
/* Check if the user gave a ridicuously large nonpaged pool RAM size */
|
||||||
MxFreeDescriptor->BasePage += PageCount;
|
if ((MmSizeOfNonPagedPoolInBytes >> PAGE_SHIFT) > (FreePages * 7 / 8))
|
||||||
MxFreeDescriptor->PageCount -= PageCount;
|
{
|
||||||
return Pfn;
|
/* 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
|
NTSTATUS
|
||||||
|
@ -71,7 +165,7 @@ MiInitMachineDependent(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
||||||
PLIST_ENTRY NextEntry;
|
PLIST_ENTRY NextEntry;
|
||||||
PMEMORY_ALLOCATION_DESCRIPTOR MdBlock;
|
PMEMORY_ALLOCATION_DESCRIPTOR MdBlock;
|
||||||
ULONG FreePages = 0;
|
ULONG FreePages = 0;
|
||||||
PFN_NUMBER PageFrameIndex, PoolPages;
|
PFN_NUMBER PageFrameIndex;
|
||||||
PMMPTE StartPde, EndPde, PointerPte, LastPte;
|
PMMPTE StartPde, EndPde, PointerPte, LastPte;
|
||||||
MMPTE TempPde, TempPte;
|
MMPTE TempPde, TempPte;
|
||||||
PVOID NonPagedPoolExpansionVa;
|
PVOID NonPagedPoolExpansionVa;
|
||||||
|
@ -79,7 +173,7 @@ MiInitMachineDependent(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
||||||
PFN_NUMBER FreePage, FreePageCount, PagesLeft, BasePage, PageCount;
|
PFN_NUMBER FreePage, FreePageCount, PagesLeft, BasePage, PageCount;
|
||||||
|
|
||||||
/* Check for kernel stack size that's too big */
|
/* 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 */
|
/* Sanitize to default value */
|
||||||
MmLargeStackSize = KERNEL_LARGE_STACK_SIZE;
|
MmLargeStackSize = KERNEL_LARGE_STACK_SIZE;
|
||||||
|
@ -87,7 +181,7 @@ MiInitMachineDependent(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Take the registry setting, and convert it into bytes */
|
/* Take the registry setting, and convert it into bytes */
|
||||||
MmLargeStackSize *= 1024;
|
MmLargeStackSize *= _1KB;
|
||||||
|
|
||||||
/* Now align it to a page boundary */
|
/* Now align it to a page boundary */
|
||||||
MmLargeStackSize = PAGE_ROUND_UP(MmLargeStackSize);
|
MmLargeStackSize = PAGE_ROUND_UP(MmLargeStackSize);
|
||||||
|
@ -219,138 +313,8 @@ MiInitMachineDependent(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
||||||
//
|
//
|
||||||
MxOldFreeDescriptor = *MxFreeDescriptor;
|
MxOldFreeDescriptor = *MxFreeDescriptor;
|
||||||
|
|
||||||
//
|
/* Compute non paged pool limits and size */
|
||||||
// Check if this is a machine with less than 256MB of RAM, and no overide
|
MiComputeNonPagedPoolVa(FreePages);
|
||||||
//
|
|
||||||
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");
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get L2 cache information
|
// Get L2 cache information
|
||||||
|
|
|
@ -198,6 +198,12 @@ MiInitMachineDependent(
|
||||||
IN PLOADER_PARAMETER_BLOCK LoaderBlock
|
IN PLOADER_PARAMETER_BLOCK LoaderBlock
|
||||||
);
|
);
|
||||||
|
|
||||||
|
PFN_NUMBER
|
||||||
|
NTAPI
|
||||||
|
MxGetNextPage(
|
||||||
|
IN PFN_NUMBER PageCount
|
||||||
|
);
|
||||||
|
|
||||||
PPHYSICAL_MEMORY_DESCRIPTOR
|
PPHYSICAL_MEMORY_DESCRIPTOR
|
||||||
NTAPI
|
NTAPI
|
||||||
MmInitializeMemoryLimits(
|
MmInitializeMemoryLimits(
|
||||||
|
|
|
@ -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
|
PFN_NUMBER
|
||||||
NTAPI
|
NTAPI
|
||||||
MiPagesInLoaderBlock(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
|
MiPagesInLoaderBlock(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue