- Fix some pool calculations.

- Check for some untested pool calculations.
- Handle paging-in the page tables when needed.
- Setup paging colors based on L2 cache size/associativity.
- Setup system PTE size earlier. 


svn path=/trunk/; revision=44903
This commit is contained in:
ReactOS Portable Systems Group 2010-01-03 05:10:09 +00:00
parent 1f8e0c8569
commit 342f38623c
3 changed files with 241 additions and 54 deletions

View file

@ -151,6 +151,14 @@ ULONG MmSystemViewSize;
PFN_NUMBER MmSystemPageDirectory;
PMMPTE MmSystemPagePtes;
//
// The system cache starts right after hyperspace. The first few pages are for
// keeping track of the system working set list.
//
// This should be 0xC0C00000 -- the cache itself starts at 0xC1000000
//
PMMWSL MmSystemCacheWorkingSetList = MI_SYSTEM_CACHE_WS_START;
//
// Windows NT seems to choose between 7000, 11000 and 50000
// On systems with more than 32MB, this number is then doubled, and further
@ -223,6 +231,22 @@ PVOID MmSystemCacheStart;
PVOID MmSystemCacheEnd;
MMSUPPORT MmSystemCacheWs;
//
// This is where hyperspace ends (followed by the system cache working set)
//
PVOID MmHyperSpaceEnd;
//
// Page coloring algorithm data
//
ULONG MmSecondaryColors;
ULONG MmSecondaryColorMask;
//
// Actual (registry-configurable) size of a GUI thread's stack
//
ULONG MmLargeStackSize;
/* PRIVATE FUNCTIONS **********************************************************/
//
@ -278,6 +302,48 @@ MxGetNextPage(IN PFN_NUMBER PageCount)
return Pfn;
}
PFN_NUMBER
NTAPI
MiPagesInLoaderBlock(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
IN PBOOLEAN IncludeType)
{
PLIST_ENTRY NextEntry;
PFN_NUMBER PageCount = 0;
PMEMORY_ALLOCATION_DESCRIPTOR MdBlock;
//
// Now loop through the descriptors
//
NextEntry = LoaderBlock->MemoryDescriptorListHead.Flink;
while (NextEntry != &LoaderBlock->MemoryDescriptorListHead)
{
//
// Grab each one, and check if it's one we should include
//
MdBlock = CONTAINING_RECORD(NextEntry,
MEMORY_ALLOCATION_DESCRIPTOR,
ListEntry);
if ((MdBlock->MemoryType < LoaderMaximum) &&
(IncludeType[MdBlock->MemoryType]))
{
//
// Add this to our running total
//
PageCount += MdBlock->PageCount;
}
//
// Try the next descriptor
//
NextEntry = MdBlock->ListEntry.Flink;
}
//
// Return the total
//
return PageCount;
}
PPHYSICAL_MEMORY_DESCRIPTOR
NTAPI
MmInitializeMemoryLimits(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
@ -606,17 +672,26 @@ MmArmInitSystem(IN ULONG Phase,
PLIST_ENTRY NextEntry;
PMEMORY_ALLOCATION_DESCRIPTOR MdBlock;
ULONG FreePages = 0;
PFN_NUMBER PageFrameIndex;
PFN_NUMBER PageFrameIndex, PoolPages;
PMMPTE StartPde, EndPde, PointerPte, LastPte;
MMPTE TempPde = HyperTemplatePte, TempPte = HyperTemplatePte;
PVOID NonPagedPoolExpansionVa;
ULONG OldCount;
ULONG OldCount, i, L2Associativity;
BOOLEAN IncludeType[LoaderMaximum];
ULONG i;
PVOID Bitmap;
PPHYSICAL_MEMORY_RUN Run;
PFN_NUMBER FreePage, FreePageCount, PagesLeft, BasePage, PageCount;
//
// Instantiate memory that we don't consider RAM/usable
// We use the same exclusions that Windows does, in order to try to be
// compatible with WinLDR-style booting
//
for (i = 0; i < LoaderMaximum; i++) IncludeType[i] = TRUE;
IncludeType[LoaderBad] = FALSE;
IncludeType[LoaderFirmwarePermanent] = FALSE;
IncludeType[LoaderSpecialMemory] = FALSE;
IncludeType[LoaderBBTMemory] = FALSE;
if (Phase == 0)
{
//
@ -698,7 +773,61 @@ MmArmInitSystem(IN ULONG Phase,
//
MiSystemViewStart = (PVOID)((ULONG_PTR)MmSessionBase -
MmSystemViewSize);
//
// Count physical pages on the system
//
PageCount = MiPagesInLoaderBlock(LoaderBlock, IncludeType);
//
// Check if this is a machine with less than 19MB of RAM
//
if (PageCount < MI_MIN_PAGES_FOR_SYSPTE_TUNING)
{
//
// Use the very minimum of system PTEs
//
MmNumberOfSystemPtes = 7000;
}
else
{
//
// Use the default, but check if we have more than 32MB of RAM
//
MmNumberOfSystemPtes = 11000;
if (PageCount > MI_MIN_PAGES_FOR_SYSPTE_BOOST)
{
//
// Double the amount of system PTEs
//
MmNumberOfSystemPtes <<= 1;
}
}
DPRINT("System PTE count has been tuned to %d (%d bytes)\n",
MmNumberOfSystemPtes, MmNumberOfSystemPtes * PAGE_SIZE);
//
//
// Start of Architecture Specific Initialization Code
//
//
//
// The large kernel stack is cutomizable, but use default value for now
//
MmLargeStackSize = KERNEL_LARGE_STACK_SIZE;
//
// Setup template
//
HyperTemplatePte.u.Long = 0;
HyperTemplatePte.u.Hard.Valid = 1;
HyperTemplatePte.u.Hard.Write = 1;
HyperTemplatePte.u.Hard.Dirty = 1;
HyperTemplatePte.u.Hard.Accessed = 1;
if (Ke386GlobalPagesEnabled) HyperTemplatePte.u.Hard.Global = 1;
//
// Set CR3 for the system process
//
@ -784,9 +913,13 @@ MmArmInitSystem(IN ULONG Phase,
//
// For now, it is
//
FreePages = MdBlock->PageCount;
MxFreeDescriptor = MdBlock;
}
//
// More free pages
//
FreePages += MdBlock->PageCount;
}
}
@ -802,34 +935,6 @@ MmArmInitSystem(IN ULONG Phase,
//
MxOldFreeDescriptor = *MxFreeDescriptor;
//
// Check if this is a machine with less than 19MB of RAM
//
if (MmNumberOfPhysicalPages < MI_MIN_PAGES_FOR_SYSPTE_TUNING)
{
//
// Use the very minimum of system PTEs
//
MmNumberOfSystemPtes = 7000;
}
else
{
//
// Use the default, but check if we have more than 32MB of RAM
//
MmNumberOfSystemPtes = 11000;
if (MmNumberOfPhysicalPages > MI_MIN_PAGES_FOR_SYSPTE_BOOST)
{
//
// Double the amount of system PTEs
//
MmNumberOfSystemPtes <<= 1;
}
}
DPRINT("System PTE count has been tuned to %d (%d bytes)\n",
MmNumberOfSystemPtes, MmNumberOfSystemPtes * PAGE_SIZE);
//
// Check if this is a machine with less than 256MB of RAM, and no overide
//
@ -842,6 +947,11 @@ MmArmInitSystem(IN ULONG Phase,
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
//
@ -900,26 +1010,86 @@ MmArmInitSystem(IN ULONG Phase,
if (!MmMaximumNonPagedPoolInBytes)
{
//
// Start with the default (1MB) and add 400 KB for each MB above 4
// Start with the default (1MB)
//
MmMaximumNonPagedPoolInBytes = MmDefaultMaximumNonPagedPool;
MmMaximumNonPagedPoolInBytes += (MmNumberOfPhysicalPages - 1024) /
256 * MmMaxAdditionNonPagedPoolPerMb;
//
// 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 > MI_MAX_NONPAGED_POOL_SIZE)
if (MmMaximumNonPagedPoolInBytes > PoolPages)
{
//
// Set it to the upper limit
//
MmMaximumNonPagedPoolInBytes = MI_MAX_NONPAGED_POOL_SIZE;
MmMaximumNonPagedPoolInBytes = PoolPages;
}
//
// Calculate the number of bytes, and then convert to pages
// 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
//
L2Associativity = KeGetPcr()->SecondLevelCacheAssociativity;
MmSecondaryColors = KeGetPcr()->SecondLevelCacheSize;
if (L2Associativity) MmSecondaryColors /= L2Associativity;
//
// Compute final color mask and count
//
MmSecondaryColors >>= PAGE_SHIFT;
if (!MmSecondaryColors) MmSecondaryColors = 1;
MmSecondaryColorMask = MmSecondaryColors - 1;
//
// Store it
//
KeGetCurrentPrcb()->SecondaryColorMask = MmSecondaryColorMask;
//
// Calculate the number of bytes for the PFN database
// and then convert to pages
//
MxPfnAllocation = (MmHighestPhysicalPage + 1) * sizeof(MMPFN);
MxPfnAllocation >>= PAGE_SHIFT;
@ -975,6 +1145,19 @@ MmArmInitSystem(IN ULONG Phase,
ASSERT(MmNumberOfSystemPtes > 1000);
}
//
// Check if we are in a situation where the size of the paged pool
// is so large that it overflows into nonpaged pool
//
if (MmSizeOfPagedPoolInBytes >
((ULONG_PTR)MmNonPagedSystemStart - (ULONG_PTR)MmPagedPoolStart))
{
//
// We need some recalculations here
//
DPRINT1("Paged pool is too big!\n");
}
//
// Normally, the PFN database should start after the loader images.
// This is already the case in ReactOS, but for now we want to co-exist
@ -1295,18 +1478,7 @@ MmArmInitSystem(IN ULONG Phase,
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));
//
// Instantiate memory that we don't consider RAM/usable
// We use the same exclusions that Windows does, in order to try to be
// compatible with WinLDR-style booting
//
for (i = 0; i < LoaderMaximum; i++) IncludeType[i] = TRUE;
IncludeType[LoaderBad] = FALSE;
IncludeType[LoaderFirmwarePermanent] = FALSE;
IncludeType[LoaderSpecialMemory] = FALSE;
IncludeType[LoaderBBTMemory] = FALSE;
//
// Build the physical memory block
//

View file

@ -26,6 +26,7 @@
#define MI_SYSTEM_VIEW_SIZE (16 * 1024 * 1024)
#define MI_SYSTEM_CACHE_WS_START (PVOID)0xC0C00000
#define MI_PAGED_POOL_START (PVOID)0xE1000000
#define MI_NONPAGED_POOL_END (PVOID)0xFFBE0000
#define MI_DEBUG_MAPPING (PVOID)0xFFBFF000
@ -166,6 +167,7 @@ extern MMSUPPORT MmSystemCacheWs;
extern SIZE_T MmAllocatedNonPagedPool;
extern ULONG_PTR MmSubsectionBase;
extern ULONG MmSpecialPoolTag;
extern PVOID MmHyperSpaceEnd;
NTSTATUS
NTAPI

View file

@ -140,8 +140,8 @@ MiDispatchFault(IN BOOLEAN StoreInstruction,
KIRQL OldIrql;
NTSTATUS Status;
DPRINT("ARM3 Page Fault Dispatcher for address: %p in process: %p\n",
Address,
Process);
Address,
Process);
//
// Make sure APCs are off and we're not at dispatch
@ -297,14 +297,27 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction,
//
// Check for a fault on the page table or hyperspace itself
// FIXME: Use MmHyperSpaceEnd
//
if ((Address >= (PVOID)PTE_BASE) && (Address <= (PVOID)0xC0800000))
if ((Address >= (PVOID)PTE_BASE) && (Address <= MmHyperSpaceEnd))
{
//
// This might happen...not sure yet
//
DPRINT1("FAULT ON PAGE TABLES!\n");
//
// Map in the page table
//
if (MiCheckPdeForPagedPool(Address) == STATUS_WAIT_1)
{
DPRINT1("PAGE TABLES FAULTED IN!\n");
return STATUS_SUCCESS;
}
//
// Otherwise the page table doesn't actually exist
//
DPRINT1("FAILING\n");
return STATUS_ACCESS_VIOLATION;
}