From f2ce1cf66ff480615629c78baaacb32af597fc45 Mon Sep 17 00:00:00 2001 From: ReactOS Portable Systems Group Date: Mon, 22 Jun 2009 06:16:57 +0000 Subject: [PATCH] =?UTF-8?q?-=20Begin=20the=20implementation=20of=20the=20A?= =?UTF-8?q?RM=20Pool=20Manager,=20a=20replacement=20for=20the=20ReactOS=20?= =?UTF-8?q?nonpaged=20pool.=20=20=20-=20Define=20the=20nonpaged=20system?= =?UTF-8?q?=20address=20space=20as=20done=20on=20Windows=20(see=20init.c?= =?UTF-8?q?=20for=20a=20brief=20introduction=20and=20source=20reading=20ma?= =?UTF-8?q?terials=20on=20this).=20=20=20-=20Size=20up=20the=20ARM=20pool?= =?UTF-8?q?=20as=20done=20on=20Windows=20(again,=20see=20init.c=20for=20do?= =?UTF-8?q?cumentation=20on=20this).=20=20=20-=20Create=20the=20PDEs=20for?= =?UTF-8?q?=20the=20expansion=20pool=20and=20the=20initial=20pool.=20=20?= =?UTF-8?q?=20-=20Allocate=20the=20pages=20for=20the=20initial=20pool,=20a?= =?UTF-8?q?nd=20map=20them.=20=20=20=20=20-=20Unlike=20ReactOS,=20ARM?= =?UTF-8?q?=C2=B3=20does=20the=20right=20thing=20and=20uses=20physically?= =?UTF-8?q?=20continuous=20pages.=20=20=20-=20Define=20two=20new=20static?= =?UTF-8?q?=20MEMORY=5FAREAs=20for=20the=20expansion=20and=20initial=20ARM?= =?UTF-8?q?=20pool.=20=20=20-=20No=20actual=20pool=20code/implementation?= =?UTF-8?q?=20is=20available=20yet,=20we=20are=20just=20slicing=20up=20the?= =?UTF-8?q?=20address=20space=20for=20now=20(mhmm...=20cake!)*.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * There is no cake. svn path=/trunk/; revision=41525 --- reactos/ntoskrnl/include/internal/mm.h | 2 +- reactos/ntoskrnl/mm/ARM3/init.c | 373 +++++++++++++++++++++++ reactos/ntoskrnl/mm/ARM3/miarm.h | 15 + reactos/ntoskrnl/mm/mminit.c | 10 + reactos/ntoskrnl/ntoskrnl-generic.rbuild | 3 + 5 files changed, 402 insertions(+), 1 deletion(-) create mode 100644 reactos/ntoskrnl/mm/ARM3/init.c create mode 100644 reactos/ntoskrnl/mm/ARM3/miarm.h diff --git a/reactos/ntoskrnl/include/internal/mm.h b/reactos/ntoskrnl/include/internal/mm.h index 91552e71030..04d2aaa33b9 100644 --- a/reactos/ntoskrnl/include/internal/mm.h +++ b/reactos/ntoskrnl/include/internal/mm.h @@ -29,7 +29,7 @@ struct _MM_PAGEOP; typedef ULONG SWAPENTRY; typedef ULONG PFN_TYPE, *PPFN_TYPE; -#define MI_STATIC_MEMORY_AREAS (6) +#define MI_STATIC_MEMORY_AREAS (8) #define MEMORY_AREA_INVALID (0) #define MEMORY_AREA_SECTION_VIEW (1) diff --git a/reactos/ntoskrnl/mm/ARM3/init.c b/reactos/ntoskrnl/mm/ARM3/init.c new file mode 100644 index 00000000000..b113b5d7e7d --- /dev/null +++ b/reactos/ntoskrnl/mm/ARM3/init.c @@ -0,0 +1,373 @@ +/* + * PROJECT: ReactOS Kernel + * LICENSE: BSD - See COPYING.ARM in the top level directory + * FILE: ntoskrnl/mm/ARM3/init.c + * PURPOSE: ARM Memory Manager Initialization + * PROGRAMMERS: ReactOS Portable Systems Group + */ + +/* INCLUDES *******************************************************************/ + +#include +#define NDEBUG +#include + +#line 15 "ARM³::INIT" +#define MODULE_INVOLVED_IN_ARM3 +#include "../ARM3/miarm.h" + +/* GLOBALS ********************************************************************/ + +// +// These are all registry-configurable, but by default, the memory manager will +// figure out the most appropriate values. +// +ULONG MmMaximumNonPagedPoolPercent; +ULONG MmSizeOfNonPagedPoolInBytes; +ULONG MmMaximumNonPagedPoolInBytes; + +// +// These numbers describe the discrete equation components of the nonpaged +// pool sizing algorithm. +// +// They are described on http://support.microsoft.com/default.aspx/kb/126402/ja +// along with the algorithm that uses them, which is implemented later below. +// +ULONG MmMinimumNonPagedPoolSize = 256 * 1024; +ULONG MmMinAdditionNonPagedPoolPerMb = 32 * 1024; +ULONG MmDefaultMaximumNonPagedPool = 1024 * 1024; +ULONG MmMaxAdditionNonPagedPoolPerMb = 400 * 1024; + +// +// The memory layout (and especially variable names) of the NT kernel mode +// components can be a bit hard to twig, especially when it comes to the non +// paged area. +// +// There are really two components to the non-paged pool: +// +// - The initial nonpaged pool, sized dynamically up to a maximum. +// - The expansion nonpaged pool, sized dynamically up to a maximum. +// +// The initial nonpaged pool is physically continuous for performance, and +// immediately follows the PFN database, typically sharing the same PDE. It is +// a very small resource (32MB on a 1GB system), and capped at 128MB. +// +// Right now, we call this the "ARM Pool" and it begins at 0xA0000000 since we +// don't want to interefere with the ReactOS memory manager PFN database (yet). +// +// The expansion nonpaged pool, on the other hand, can grow much bigger (400MB +// for a 1GB system). On ARM³ however, it is currently capped at 128MB. +// +// The address where the initial nonpaged pool starts is aptly named +// MmNonPagedPoolStart, and it describes a range of MmSizeOfNonPagedPoolInBytes +// bytes. +// +// Expansion nonpaged pool starts at an address described by the variable called +// MmNonPagedPoolExpansionStart, and it goes on for MmMaximumNonPagedPoolInBytes +// minus MmSizeOfNonPagedPoolInBytes bytes, always reaching MmNonPagedPoolEnd +// (because of the way it's calculated) at 0xFFBE0000. +// +// Initial nonpaged pool is allocated and mapped early-on during boot, but what +// about the expansion nonpaged pool? It is instead composed of special pages +// which belong to what are called System PTEs. These PTEs are the matter of a +// later discussion, but they are also considered part of the "nonpaged" OS, due +// to the fact that they are never paged out -- once an address is described by +// a System PTE, it is always valid, until the System PTE is torn down. +// +// System PTEs are actually composed of two "spaces", the system space proper, +// and the nonpaged pool expansion space. The latter, as we've already seen, +// begins at MmNonPagedPoolExpansionStart. Based on the number of System PTEs +// that the system will support, the remaining address space below this address +// is used to hold the system space PTEs. This address, in turn, is held in the +// variable named MmNonPagedSystemStart, which itself is never allowed to go +// below 0xEB000000 (thus creating an upper bound on the number of System PTEs). +// +// This means that 330MB are reserved for total nonpaged system VA, on top of +// whatever the initial nonpaged pool allocation is. +// +// The following URLs, valid as of April 23rd, 2008, support this evidence: +// +// http://www.cs.miami.edu/~burt/journal/NT/memory.html +// http://www.ditii.com/2007/09/28/windows-memory-management-x86-virtual-address-space/ +// +PVOID MmNonPagedSystemStart; +PVOID MmNonPagedPoolStart; +PVOID MmNonPagedPoolExpansionStart; +PVOID MmNonPagedPoolEnd = (PVOID)0xFFBE0000; + +/* PRIVATE FUNCTIONS **********************************************************/ + +NTSTATUS +NTAPI +MmArmInitSystem(IN ULONG Phase, + IN PLOADER_PARAMETER_BLOCK LoaderBlock) +{ + PMEMORY_AREA MArea; + PHYSICAL_ADDRESS BoundaryAddressMultiple, Low, High; + PFN_NUMBER PageFrameIndex; + PMMPTE StartPde, EndPde, PointerPte, LastPte; + MMPTE TempPde = HyperTemplatePte, TempPte = HyperTemplatePte; + PVOID NonPagedPoolExpansionVa, BaseAddress; + NTSTATUS Status; + BoundaryAddressMultiple.QuadPart = Low.QuadPart = 0; + High.QuadPart = -1; + + if (Phase == 0) + { + // + // 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; + } + + // + // 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) and add 400 KB for each MB above 4 + // + MmMaximumNonPagedPoolInBytes = MmDefaultMaximumNonPagedPool; + MmMaximumNonPagedPoolInBytes += (MmNumberOfPhysicalPages - 1024) / + 256 * MmMaxAdditionNonPagedPoolPerMb; + } + + // + // Don't let the maximum go too high + // + if (MmMaximumNonPagedPoolInBytes > MI_MAX_NONPAGED_POOL_SIZE) + { + // + // Set it to the upper limit + // + MmMaximumNonPagedPoolInBytes = MI_MAX_NONPAGED_POOL_SIZE; + } + + // + // Now calculate the nonpaged pool expansion VA region + // + MmNonPagedPoolStart = (PVOID)((ULONG_PTR)MmNonPagedPoolEnd - + MmMaximumNonPagedPoolInBytes + + MmSizeOfNonPagedPoolInBytes); + MmNonPagedPoolStart = (PVOID)PAGE_ALIGN(MmNonPagedPoolStart); + NonPagedPoolExpansionVa = MmNonPagedPoolStart; + DPRINT1("NP Pool has been tuned to: %d bytes and %d bytes\n", + MmSizeOfNonPagedPoolInBytes, MmMaximumNonPagedPoolInBytes); + DPRINT1("NP Expansion VA begins at: %p and ends at: %p\n", + MmNonPagedPoolStart, MmNonPagedPoolEnd); + + // + // Now calculate the nonpaged system VA region + // This includes nonpaged pool expansion (above) and the system PTEs + // Since there are no system PTEs yet, this is (for now) the same + // + MmNonPagedSystemStart = MmNonPagedPoolStart; + DPRINT1("NP System VA (later will be System PTEs) start at: %p\n", + MmNonPagedSystemStart); + + // + // Non paged pool should come after the PFN database, but since we are + // co-existing with the ReactOS NP pool, our "ARM Pool" will instead + // start at this arbitrarly chosen base address. + // When ARM pool becomes non paged pool, this needs to be changed. + // + MmNonPagedPoolStart = (PVOID)0xA0000000; + DPRINT1("NP VA begins at: %p and ends at: %p\n", + MmNonPagedPoolStart, + (ULONG_PTR)MmNonPagedPoolStart + MmSizeOfNonPagedPoolInBytes); + + // + // Now we actually need to get these many physical pages. Nonpaged pool + // is actually also physically contiguous (but not the expansion) + // + PageFrameIndex = MmGetContinuousPages(MmSizeOfNonPagedPoolInBytes, + Low, + High, + BoundaryAddressMultiple); + ASSERT(PageFrameIndex != 0); + DPRINT1("NP PA PFN begins at: %lx\n", PageFrameIndex); + + // + // Now we need some pages to create the page tables for the NP system VA + // which would normally include system PTEs and expansion NP + // + StartPde = MiAddressToPde(MmNonPagedSystemStart); + EndPde = MiAddressToPde((PVOID)((ULONG_PTR)MmNonPagedPoolEnd - 1)); + while (StartPde <= EndPde) + { + // + // Sanity check + // + ASSERT(StartPde->u.Hard.Valid == 0); + + // + // Get a page + // + TempPde.u.Hard.PageFrameNumber = MmAllocPage(MC_SYSTEM, 0); + ASSERT(TempPde.u.Hard.Valid == 1); + *StartPde = TempPde; + + // + // Zero out the page table + // + PointerPte = MiPteToAddress(StartPde); + RtlZeroMemory(PointerPte, PAGE_SIZE); + + // + // Next + // + StartPde++; + } + + // + // Now we need pages for the page tables which will map initial NP + // + StartPde = MiAddressToPde(MmNonPagedPoolStart); + EndPde = MiAddressToPde((PVOID)((ULONG_PTR)MmNonPagedPoolStart + + MmSizeOfNonPagedPoolInBytes - 1)); + while (StartPde <= EndPde) + { + // + // Sanity check + // + ASSERT(StartPde->u.Hard.Valid == 0); + + // + // Get a page + // + TempPde.u.Hard.PageFrameNumber = MmAllocPage(MC_SYSTEM, 0); + ASSERT(TempPde.u.Hard.Valid == 1); + *StartPde = TempPde; + + // + // Zero out the page table + // + PointerPte = MiPteToAddress(StartPde); + RtlZeroMemory(PointerPte, PAGE_SIZE); + + // + // Next + // + StartPde++; + } + + // + // Now rememeber where the expansion starts + // + MmNonPagedPoolExpansionStart = NonPagedPoolExpansionVa; + + // + // Last step is to actually map the nonpaged pool + // + PointerPte = MiAddressToPte(MmNonPagedPoolStart); + LastPte = MiAddressToPte((PVOID)((ULONG_PTR)MmNonPagedPoolStart + + MmSizeOfNonPagedPoolInBytes - 1)); + while (PointerPte <= LastPte) + { + // + // Use one of our contigous pages + // + TempPte.u.Hard.PageFrameNumber = PageFrameIndex++; + ASSERT(PointerPte->u.Hard.Valid == 0); + ASSERT(TempPte.u.Hard.Valid == 1); + *PointerPte++ = TempPte; + } + + // + // ReactOS requires a memory area to keep the initial NP area off-bounds + // + BaseAddress = MmNonPagedPoolStart; + Status = MmCreateMemoryArea(MmGetKernelAddressSpace(), + MEMORY_AREA_SYSTEM | MEMORY_AREA_STATIC, + &BaseAddress, + MmSizeOfNonPagedPoolInBytes, + PAGE_READWRITE, + &MArea, + TRUE, + 0, + BoundaryAddressMultiple); + ASSERT(Status == STATUS_SUCCESS); + + // + // And we need one more for the system NP (expansion NP only for now) + // + BaseAddress = MmNonPagedSystemStart; + Status = MmCreateMemoryArea(MmGetKernelAddressSpace(), + MEMORY_AREA_SYSTEM | MEMORY_AREA_STATIC, + &BaseAddress, + (ULONG_PTR)MmNonPagedPoolEnd - + (ULONG_PTR)MmNonPagedSystemStart, + PAGE_READWRITE, + &MArea, + TRUE, + 0, + BoundaryAddressMultiple); + ASSERT(Status == STATUS_SUCCESS); + } + + // + // Always return success for now + // + return STATUS_SUCCESS; +} + +/* EOF */ diff --git a/reactos/ntoskrnl/mm/ARM3/miarm.h b/reactos/ntoskrnl/mm/ARM3/miarm.h new file mode 100644 index 00000000000..7011adfee2e --- /dev/null +++ b/reactos/ntoskrnl/mm/ARM3/miarm.h @@ -0,0 +1,15 @@ +/* + * PROJECT: ReactOS Kernel + * LICENSE: BSD - See COPYING.ARM in the top level directory + * FILE: ntoskrnl/mm/ARM3/miarm.h + * PURPOSE: ARM Memory Manager Header + * PROGRAMMERS: ReactOS Portable Systems Group + */ + +#define MI_MIN_PAGES_FOR_NONPAGED_POOL_TUNING ((255*1024*1024) >> PAGE_SHIFT) +#define MI_MAX_INIT_NONPAGED_POOL_SIZE (128 * 1024 * 1024) +#define MI_MAX_NONPAGED_POOL_SIZE (128 * 1024 * 1024) + +extern MMPTE HyperTemplatePte; + +/* EOF */ diff --git a/reactos/ntoskrnl/mm/mminit.c b/reactos/ntoskrnl/mm/mminit.c index 67fc1c25c15..960e056637e 100644 --- a/reactos/ntoskrnl/mm/mminit.c +++ b/reactos/ntoskrnl/mm/mminit.c @@ -289,6 +289,11 @@ VOID NTAPI MiInitHyperSpace(VOID); +NTSTATUS +NTAPI +MmArmInitSystem(IN ULONG Phase, + IN PLOADER_PARAMETER_BLOCK LoaderBlock); + VOID INIT_FUNCTION NTAPI @@ -379,6 +384,11 @@ MmInit1(VOID) /* Unmap low memory */ MmDeletePageTable(NULL, 0); + // + // Initialize ARM³ + // + MmArmInitSystem(0, KeLoaderBlock); + /* Initialize nonpaged pool */ MiInitializeNonPagedPool(); diff --git a/reactos/ntoskrnl/ntoskrnl-generic.rbuild b/reactos/ntoskrnl/ntoskrnl-generic.rbuild index c1cbe6887ab..78d6e5dd15b 100644 --- a/reactos/ntoskrnl/ntoskrnl-generic.rbuild +++ b/reactos/ntoskrnl/ntoskrnl-generic.rbuild @@ -359,6 +359,9 @@ page.c + + init.c + anonmem.c balance.c cont.c