- Begin the implementation of the ARM Pool Manager, a replacement for the ReactOS nonpaged pool.

- Define the nonpaged system address space as done on Windows (see init.c for a brief introduction and source reading materials on this).
  - Size up the ARM pool as done on Windows (again, see init.c for documentation on this).
  - Create the PDEs for the expansion pool and the initial pool.
  - Allocate the pages for the initial pool, and map them.
    - Unlike ReactOS, ARM³ does the right thing and uses physically continuous pages.
  - Define two new static MEMORY_AREAs for the expansion and initial ARM pool.
  - No actual pool code/implementation is available yet, we are just slicing up the address space for now (mhmm... cake!)*.

* There is no cake.


svn path=/trunk/; revision=41525
This commit is contained in:
ReactOS Portable Systems Group 2009-06-22 06:16:57 +00:00
parent 47122e35e8
commit f2ce1cf66f
5 changed files with 402 additions and 1 deletions

View file

@ -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)

View file

@ -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 <ntoskrnl.h>
#define NDEBUG
#include <debug.h>
#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 */

View file

@ -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 */

View file

@ -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();

View file

@ -359,6 +359,9 @@
<file>page.c</file>
</directory>
</if>
<directory name="ARM3">
<file>init.c</file>
</directory>
<file>anonmem.c</file>
<file>balance.c</file>
<file>cont.c</file>