mirror of
https://github.com/reactos/reactos.git
synced 2025-07-31 10:01:43 +00:00
- 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:
parent
1f8e0c8569
commit
342f38623c
3 changed files with 241 additions and 54 deletions
|
@ -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
|
||||
//
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue