Author: ros-arm-bringup Date: Sun Jan 3 06:10:09 2010 New Revision: 44903 URL: http://svn.reactos.org/svn/reactos?rev=44903&view=rev Log: - 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.
Modified: trunk/reactos/ntoskrnl/mm/ARM3/i386/init.c trunk/reactos/ntoskrnl/mm/ARM3/miarm.h trunk/reactos/ntoskrnl/mm/ARM3/pagfault.c Modified: trunk/reactos/ntoskrnl/mm/ARM3/i386/init.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/i386/init.c?rev=44903&r1=44902&r2=44903&view=diff ============================================================================== --- trunk/reactos/ntoskrnl/mm/ARM3/i386/init.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/mm/ARM3/i386/init.c [iso-8859-1] Sun Jan 3 06:10:09 2010 @@ -152,6 +152,14 @@ 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 // aligned up to a PDE boundary (4MB). @@ -222,6 +230,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 **********************************************************/ @@ -276,6 +300,48 @@ MxFreeDescriptor->BasePage += PageCount; MxFreeDescriptor->PageCount -= 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 @@ -606,17 +672,26 @@ 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 @@ // 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 @@ // // For now, it is // - FreePages = MdBlock->PageCount; MxFreeDescriptor = MdBlock; } + + // + // More free pages + // + FreePages += MdBlock->PageCount; } } @@ -803,34 +936,6 @@ 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 // if ((MmNumberOfPhysicalPages <= MI_MIN_PAGES_FOR_NONPAGED_POOL_TUNING) && @@ -841,6 +946,11 @@ // 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 @@ 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 > 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) { // - // Set it to the upper limit - // - MmMaximumNonPagedPoolInBytes = MI_MAX_NONPAGED_POOL_SIZE; - } - - // - // Calculate the number of bytes, and then convert to pages + // 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; @@ -973,6 +1143,19 @@ PAGE_SHIFT; MmNumberOfSystemPtes--; 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"); } // @@ -1295,18 +1478,7 @@ 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 // Modified: trunk/reactos/ntoskrnl/mm/ARM3/miarm.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/miarm.h?rev=44903&r1=44902&r2=44903&view=diff ============================================================================== --- trunk/reactos/ntoskrnl/mm/ARM3/miarm.h [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/mm/ARM3/miarm.h [iso-8859-1] Sun Jan 3 06:10:09 2010 @@ -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 SIZE_T MmAllocatedNonPagedPool; extern ULONG_PTR MmSubsectionBase; extern ULONG MmSpecialPoolTag; +extern PVOID MmHyperSpaceEnd; NTSTATUS NTAPI Modified: trunk/reactos/ntoskrnl/mm/ARM3/pagfault.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/pagfault.c?rev=44903&r1=44902&r2=44903&view=diff ============================================================================== --- trunk/reactos/ntoskrnl/mm/ARM3/pagfault.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/mm/ARM3/pagfault.c [iso-8859-1] Sun Jan 3 06:10:09 2010 @@ -140,8 +140,8 @@ 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 @@ // // 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; }