2010-02-10 02:00:56 +00:00
|
|
|
/*
|
|
|
|
* PROJECT: ReactOS Kernel
|
|
|
|
* LICENSE: BSD - See COPYING.ARM in the top level directory
|
|
|
|
* FILE: ntoskrnl/mm/ARM3/mminit.c
|
|
|
|
* PURPOSE: ARM Memory Manager Initialization
|
|
|
|
* PROGRAMMERS: ReactOS Portable Systems Group
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* INCLUDES *******************************************************************/
|
|
|
|
|
|
|
|
#include <ntoskrnl.h>
|
|
|
|
#define NDEBUG
|
|
|
|
#include <debug.h>
|
|
|
|
|
|
|
|
#define MODULE_INVOLVED_IN_ARM3
|
|
|
|
#include "miarm.h"
|
2012-02-08 22:23:10 +00:00
|
|
|
#undef MmSystemRangeStart
|
2010-02-10 02:00:56 +00:00
|
|
|
|
|
|
|
/* GLOBALS ********************************************************************/
|
|
|
|
|
|
|
|
//
|
|
|
|
// These are all registry-configurable, but by default, the memory manager will
|
|
|
|
// figure out the most appropriate values.
|
|
|
|
//
|
|
|
|
ULONG MmMaximumNonPagedPoolPercent;
|
2010-07-16 00:34:26 +00:00
|
|
|
SIZE_T MmSizeOfNonPagedPoolInBytes;
|
|
|
|
SIZE_T MmMaximumNonPagedPoolInBytes;
|
2010-02-10 02:00:56 +00:00
|
|
|
|
[NTOS]: Make MM init read MmProductType to determine what SKU of ReactOS this is, instead of assuming Server. If you want to go back to the old behavior, you need to change "WinNT" to "ServerNT" in the hivesys under Product Type.
[NTOS]: Configure the MmSystemSize variable properly based on SKU and RAM. Previously, ReactOS told all drivers and applications you were running on a system with < 13MB RAM.
[NTOS]: Initialize thresholds for low and high memory (in pages), low and high paged pool memory, and low and high nonpaged pool memory. These are described in the source.
[NTOS]: Initialize events for each of those thresholds, and populate the \KernelObject\xxxCondition events that are documented in MSDN for driver and app developers.
[NTOS]: Define some internal thresholds to use later, representing the minimum number of free pages under we go berserk, and the minimum number of free pages that we consider "plenty".
[NTOS]: Rename MiRemoveFromList to MiUnlinkFreeOrZeroedPage (Windows name). Make the function handle MmAvailablePages decrement, instead of having the caller do it.
[NTOS]: Remove run-time initialization of the PFN lists, just initialize them statically (also fixes the fact we forgot to initialize their names).
[NTOS]: Move some more initialization code to ARM3 instead of mm.
[NTOS]: Read ProductType from registry into MmProductType instead of dummy value. Remove duplicate "Mirroring" variable read.
svn path=/trunk/; revision=45638
2010-02-20 21:48:36 +00:00
|
|
|
/* Some of the same values, in pages */
|
|
|
|
PFN_NUMBER MmMaximumNonPagedPoolInPages;
|
|
|
|
|
2010-02-10 02:00:56 +00:00
|
|
|
//
|
|
|
|
// 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.
|
|
|
|
//
|
2010-07-16 00:34:26 +00:00
|
|
|
SIZE_T MmMinimumNonPagedPoolSize = 256 * 1024;
|
2010-02-10 02:00:56 +00:00
|
|
|
ULONG MmMinAdditionNonPagedPoolPerMb = 32 * 1024;
|
2010-12-26 15:23:03 +00:00
|
|
|
SIZE_T MmDefaultMaximumNonPagedPool = 1024 * 1024;
|
2010-02-10 02:00:56 +00:00
|
|
|
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³ Nonpaged Pool" and it begins somewhere after
|
|
|
|
// the PFN database (which starts at 0xB0000000).
|
|
|
|
//
|
2010-12-26 15:23:03 +00:00
|
|
|
// The expansion nonpaged pool, on the other hand, can grow much bigger (400MB
|
2010-02-10 02:00:56 +00:00
|
|
|
// 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,
|
2010-12-26 15:23:03 +00:00
|
|
|
// and the nonpaged pool expansion space. The latter, as we've already seen,
|
2010-02-10 02:00:56 +00:00
|
|
|
// 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 = MI_NONPAGED_POOL_END;
|
|
|
|
|
|
|
|
//
|
|
|
|
// This is where paged pool starts by default
|
|
|
|
//
|
|
|
|
PVOID MmPagedPoolStart = MI_PAGED_POOL_START;
|
|
|
|
PVOID MmPagedPoolEnd;
|
|
|
|
|
|
|
|
//
|
|
|
|
// And this is its default size
|
|
|
|
//
|
2010-07-16 00:34:26 +00:00
|
|
|
SIZE_T MmSizeOfPagedPoolInBytes = MI_MIN_INIT_PAGED_POOLSIZE;
|
2010-02-10 02:00:56 +00:00
|
|
|
PFN_NUMBER MmSizeOfPagedPoolInPages = MI_MIN_INIT_PAGED_POOLSIZE / PAGE_SIZE;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Session space starts at 0xBFFFFFFF and grows downwards
|
|
|
|
// By default, it includes an 8MB image area where we map win32k and video card
|
|
|
|
// drivers, followed by a 4MB area containing the session's working set. This is
|
|
|
|
// then followed by a 20MB mapped view area and finally by the session's paged
|
|
|
|
// pool, by default 16MB.
|
2010-12-26 15:23:03 +00:00
|
|
|
//
|
2010-02-10 02:00:56 +00:00
|
|
|
// On a normal system, this results in session space occupying the region from
|
|
|
|
// 0xBD000000 to 0xC0000000
|
|
|
|
//
|
|
|
|
// See miarm.h for the defines that determine the sizing of this region. On an
|
|
|
|
// NT system, some of these can be configured through the registry, but we don't
|
|
|
|
// support that yet.
|
|
|
|
//
|
|
|
|
PVOID MiSessionSpaceEnd; // 0xC0000000
|
|
|
|
PVOID MiSessionImageEnd; // 0xC0000000
|
|
|
|
PVOID MiSessionImageStart; // 0xBF800000
|
2012-08-01 07:54:37 +00:00
|
|
|
PVOID MiSessionSpaceWs;
|
2010-02-10 02:00:56 +00:00
|
|
|
PVOID MiSessionViewStart; // 0xBE000000
|
|
|
|
PVOID MiSessionPoolEnd; // 0xBE000000
|
|
|
|
PVOID MiSessionPoolStart; // 0xBD000000
|
|
|
|
PVOID MmSessionBase; // 0xBD000000
|
2010-07-16 00:34:26 +00:00
|
|
|
SIZE_T MmSessionSize;
|
|
|
|
SIZE_T MmSessionViewSize;
|
|
|
|
SIZE_T MmSessionPoolSize;
|
|
|
|
SIZE_T MmSessionImageSize;
|
2010-02-10 02:00:56 +00:00
|
|
|
|
2010-05-12 18:36:15 +00:00
|
|
|
/*
|
|
|
|
* These are the PTE addresses of the boundaries carved out above
|
|
|
|
*/
|
|
|
|
PMMPTE MiSessionImagePteStart;
|
|
|
|
PMMPTE MiSessionImagePteEnd;
|
|
|
|
PMMPTE MiSessionBasePte;
|
|
|
|
PMMPTE MiSessionLastPte;
|
|
|
|
|
2010-02-10 02:00:56 +00:00
|
|
|
//
|
|
|
|
// The system view space, on the other hand, is where sections that are memory
|
|
|
|
// mapped into "system space" end up.
|
|
|
|
//
|
2012-03-26 07:26:36 +00:00
|
|
|
// By default, it is a 16MB region, but we hack it to be 32MB for ReactOS
|
2010-02-10 02:00:56 +00:00
|
|
|
//
|
|
|
|
PVOID MiSystemViewStart;
|
2010-07-16 00:34:26 +00:00
|
|
|
SIZE_T MmSystemViewSize;
|
2010-02-10 02:00:56 +00:00
|
|
|
|
2010-07-26 21:45:42 +00:00
|
|
|
#if (_MI_PAGING_LEVELS == 2)
|
2010-02-10 02:00:56 +00:00
|
|
|
//
|
|
|
|
// A copy of the system page directory (the page directory associated with the
|
|
|
|
// System process) is kept (double-mapped) by the manager in order to lazily
|
|
|
|
// map paged pool PDEs into external processes when they fault on a paged pool
|
|
|
|
// address.
|
|
|
|
//
|
2020-02-05 22:48:26 +00:00
|
|
|
PFN_NUMBER MmSystemPageDirectory[PPE_PER_PAGE];
|
2010-11-24 15:21:45 +00:00
|
|
|
PMMPDE MmSystemPagePtes;
|
2010-07-26 21:45:42 +00:00
|
|
|
#endif
|
2010-02-10 02:00:56 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// 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
|
|
|
|
//
|
2012-02-08 22:23:10 +00:00
|
|
|
PMMWSL MmSystemCacheWorkingSetList = (PVOID)MI_SYSTEM_CACHE_WS_START;
|
2010-02-10 02:00:56 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// 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).
|
|
|
|
//
|
[HAL/NDK]
- Make Vector parameter in HalEnableSystemInterrupt, HalDisableSystemInterrupt and HalBeginSystemInterrupt an ULONG, not an UCHAR
[NDK]
- 64bit fixes for HANDLE_TABLE, KPROCESS, SECTION_IMAGE_INFORMATION, MMADDRESS_LIST, MMVAD_FLAGS, MMVAD, MMVAD_LONG, MMVAD_SHORT, MEMORY_DESCRIPTOR, MEMORY_ALLOCATION_DESCRIPTOR, LdrVerifyMappedImageMatchesChecksum
- KDPC_DATA::DpcQueueDepth is signed on amd64, unsigned on x86
[NTOSKRNL]
- Fix hundreds of MSVC and amd64 warnings
- add a pragma message to FstubFixupEfiPartition, since it looks broken
- Move portable Ke constants from <arch>/cpu.c to krnlinit.c
- Fixed a bug in amd64 KiGeneralProtectionFaultHandler
svn path=/trunk/; revision=53734
2011-09-18 13:11:45 +00:00
|
|
|
PFN_COUNT MmNumberOfSystemPtes;
|
2010-02-10 02:00:56 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// This is how many pages the PFN database will take up
|
|
|
|
// In Windows, this includes the Quark Color Table, but not in ARM³
|
|
|
|
//
|
2010-07-16 00:34:26 +00:00
|
|
|
PFN_NUMBER MxPfnAllocation;
|
2010-02-10 02:00:56 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// Unlike the old ReactOS Memory Manager, ARM³ (and Windows) does not keep track
|
|
|
|
// of pages that are not actually valid physical memory, such as ACPI reserved
|
|
|
|
// regions, BIOS address ranges, or holes in physical memory address space which
|
|
|
|
// could indicate device-mapped I/O memory.
|
|
|
|
//
|
|
|
|
// In fact, the lack of a PFN entry for a page usually indicates that this is
|
|
|
|
// I/O space instead.
|
|
|
|
//
|
|
|
|
// A bitmap, called the PFN bitmap, keeps track of all page frames by assigning
|
|
|
|
// a bit to each. If the bit is set, then the page is valid physical RAM.
|
|
|
|
//
|
|
|
|
RTL_BITMAP MiPfnBitMap;
|
|
|
|
|
|
|
|
//
|
|
|
|
// This structure describes the different pieces of RAM-backed address space
|
|
|
|
//
|
|
|
|
PPHYSICAL_MEMORY_DESCRIPTOR MmPhysicalMemoryBlock;
|
|
|
|
|
|
|
|
//
|
|
|
|
// This is where we keep track of the most basic physical layout markers
|
|
|
|
//
|
[HAL/NDK]
- Make Vector parameter in HalEnableSystemInterrupt, HalDisableSystemInterrupt and HalBeginSystemInterrupt an ULONG, not an UCHAR
[NDK]
- 64bit fixes for HANDLE_TABLE, KPROCESS, SECTION_IMAGE_INFORMATION, MMADDRESS_LIST, MMVAD_FLAGS, MMVAD, MMVAD_LONG, MMVAD_SHORT, MEMORY_DESCRIPTOR, MEMORY_ALLOCATION_DESCRIPTOR, LdrVerifyMappedImageMatchesChecksum
- KDPC_DATA::DpcQueueDepth is signed on amd64, unsigned on x86
[NTOSKRNL]
- Fix hundreds of MSVC and amd64 warnings
- add a pragma message to FstubFixupEfiPartition, since it looks broken
- Move portable Ke constants from <arch>/cpu.c to krnlinit.c
- Fixed a bug in amd64 KiGeneralProtectionFaultHandler
svn path=/trunk/; revision=53734
2011-09-18 13:11:45 +00:00
|
|
|
PFN_NUMBER MmHighestPhysicalPage, MmLowestPhysicalPage = -1;
|
|
|
|
PFN_COUNT MmNumberOfPhysicalPages;
|
2010-02-10 02:00:56 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// The total number of pages mapped by the boot loader, which include the kernel
|
|
|
|
// HAL, boot drivers, registry, NLS files and other loader data structures is
|
|
|
|
// kept track of here. This depends on "LoaderPagesSpanned" being correct when
|
|
|
|
// coming from the loader.
|
|
|
|
//
|
|
|
|
// This number is later aligned up to a PDE boundary.
|
|
|
|
//
|
2010-07-16 00:34:26 +00:00
|
|
|
SIZE_T MmBootImageSize;
|
2010-02-10 02:00:56 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// These three variables keep track of the core separation of address space that
|
|
|
|
// exists between kernel mode and user mode.
|
|
|
|
//
|
2010-07-16 00:34:26 +00:00
|
|
|
ULONG_PTR MmUserProbeAddress;
|
2010-02-10 02:00:56 +00:00
|
|
|
PVOID MmHighestUserAddress;
|
|
|
|
PVOID MmSystemRangeStart;
|
|
|
|
|
2010-05-12 18:36:15 +00:00
|
|
|
/* And these store the respective highest PTE/PDE address */
|
|
|
|
PMMPTE MiHighestUserPte;
|
|
|
|
PMMPDE MiHighestUserPde;
|
2010-07-26 21:45:42 +00:00
|
|
|
#if (_MI_PAGING_LEVELS >= 3)
|
[HAL/NDK]
- Make Vector parameter in HalEnableSystemInterrupt, HalDisableSystemInterrupt and HalBeginSystemInterrupt an ULONG, not an UCHAR
[NDK]
- 64bit fixes for HANDLE_TABLE, KPROCESS, SECTION_IMAGE_INFORMATION, MMADDRESS_LIST, MMVAD_FLAGS, MMVAD, MMVAD_LONG, MMVAD_SHORT, MEMORY_DESCRIPTOR, MEMORY_ALLOCATION_DESCRIPTOR, LdrVerifyMappedImageMatchesChecksum
- KDPC_DATA::DpcQueueDepth is signed on amd64, unsigned on x86
[NTOSKRNL]
- Fix hundreds of MSVC and amd64 warnings
- add a pragma message to FstubFixupEfiPartition, since it looks broken
- Move portable Ke constants from <arch>/cpu.c to krnlinit.c
- Fixed a bug in amd64 KiGeneralProtectionFaultHandler
svn path=/trunk/; revision=53734
2011-09-18 13:11:45 +00:00
|
|
|
PMMPTE MiHighestUserPpe;
|
|
|
|
#if (_MI_PAGING_LEVELS >= 4)
|
|
|
|
PMMPTE MiHighestUserPxe;
|
|
|
|
#endif
|
2010-07-26 21:45:42 +00:00
|
|
|
#endif
|
2010-05-12 18:36:15 +00:00
|
|
|
|
|
|
|
/* These variables define the system cache address space */
|
2018-04-03 21:13:17 +00:00
|
|
|
PVOID MmSystemCacheStart = (PVOID)MI_SYSTEM_CACHE_START;
|
2010-02-10 02:00:56 +00:00
|
|
|
PVOID MmSystemCacheEnd;
|
2019-07-27 07:32:29 +00:00
|
|
|
ULONG_PTR MmSizeOfSystemCacheInPages;
|
2010-02-10 02:00:56 +00:00
|
|
|
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
|
|
|
|
//
|
2010-02-10 03:59:17 +00:00
|
|
|
ULONG MmLargeStackSize = KERNEL_LARGE_STACK_SIZE;
|
2010-02-10 02:00:56 +00:00
|
|
|
|
2010-02-11 00:01:32 +00:00
|
|
|
//
|
|
|
|
// Before we have a PFN database, memory comes straight from our physical memory
|
|
|
|
// blocks, which is nice because it's guaranteed contiguous and also because once
|
|
|
|
// we take a page from here, the system doesn't see it anymore.
|
|
|
|
// However, once the fun is over, those pages must be re-integrated back into
|
|
|
|
// PFN society life, and that requires us keeping a copy of the original layout
|
|
|
|
// so that we can parse it later.
|
|
|
|
//
|
|
|
|
PMEMORY_ALLOCATION_DESCRIPTOR MxFreeDescriptor;
|
|
|
|
MEMORY_ALLOCATION_DESCRIPTOR MxOldFreeDescriptor;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* For each page's worth bytes of L2 cache in a given set/way line, the zero and
|
|
|
|
* free lists are organized in what is called a "color".
|
|
|
|
*
|
|
|
|
* This array points to the two lists, so it can be thought of as a multi-dimensional
|
|
|
|
* array of MmFreePagesByColor[2][MmSecondaryColors]. Since the number is dynamic,
|
|
|
|
* we describe the array in pointer form instead.
|
|
|
|
*
|
|
|
|
* On a final note, the color tables themselves are right after the PFN database.
|
|
|
|
*/
|
|
|
|
C_ASSERT(FreePageList == 1);
|
|
|
|
PMMCOLOR_TABLES MmFreePagesByColor[FreePageList + 1];
|
|
|
|
|
[NTOS]: Make MM init read MmProductType to determine what SKU of ReactOS this is, instead of assuming Server. If you want to go back to the old behavior, you need to change "WinNT" to "ServerNT" in the hivesys under Product Type.
[NTOS]: Configure the MmSystemSize variable properly based on SKU and RAM. Previously, ReactOS told all drivers and applications you were running on a system with < 13MB RAM.
[NTOS]: Initialize thresholds for low and high memory (in pages), low and high paged pool memory, and low and high nonpaged pool memory. These are described in the source.
[NTOS]: Initialize events for each of those thresholds, and populate the \KernelObject\xxxCondition events that are documented in MSDN for driver and app developers.
[NTOS]: Define some internal thresholds to use later, representing the minimum number of free pages under we go berserk, and the minimum number of free pages that we consider "plenty".
[NTOS]: Rename MiRemoveFromList to MiUnlinkFreeOrZeroedPage (Windows name). Make the function handle MmAvailablePages decrement, instead of having the caller do it.
[NTOS]: Remove run-time initialization of the PFN lists, just initialize them statically (also fixes the fact we forgot to initialize their names).
[NTOS]: Move some more initialization code to ARM3 instead of mm.
[NTOS]: Read ProductType from registry into MmProductType instead of dummy value. Remove duplicate "Mirroring" variable read.
svn path=/trunk/; revision=45638
2010-02-20 21:48:36 +00:00
|
|
|
/* An event used in Phase 0 before the rest of the system is ready to go */
|
|
|
|
KEVENT MiTempEvent;
|
|
|
|
|
|
|
|
/* All the events used for memory threshold notifications */
|
|
|
|
PKEVENT MiLowMemoryEvent;
|
|
|
|
PKEVENT MiHighMemoryEvent;
|
|
|
|
PKEVENT MiLowPagedPoolEvent;
|
|
|
|
PKEVENT MiHighPagedPoolEvent;
|
|
|
|
PKEVENT MiLowNonPagedPoolEvent;
|
|
|
|
PKEVENT MiHighNonPagedPoolEvent;
|
|
|
|
|
|
|
|
/* The actual thresholds themselves, in page numbers */
|
|
|
|
PFN_NUMBER MmLowMemoryThreshold;
|
|
|
|
PFN_NUMBER MmHighMemoryThreshold;
|
|
|
|
PFN_NUMBER MiLowPagedPoolThreshold;
|
|
|
|
PFN_NUMBER MiHighPagedPoolThreshold;
|
|
|
|
PFN_NUMBER MiLowNonPagedPoolThreshold;
|
|
|
|
PFN_NUMBER MiHighNonPagedPoolThreshold;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This number determines how many free pages must exist, at minimum, until we
|
|
|
|
* start trimming working sets and flushing modified pages to obtain more free
|
|
|
|
* pages.
|
|
|
|
*
|
|
|
|
* This number changes if the system detects that this is a server product
|
|
|
|
*/
|
|
|
|
PFN_NUMBER MmMinimumFreePages = 26;
|
|
|
|
|
2010-12-26 15:23:03 +00:00
|
|
|
/*
|
[NTOS]: Make MM init read MmProductType to determine what SKU of ReactOS this is, instead of assuming Server. If you want to go back to the old behavior, you need to change "WinNT" to "ServerNT" in the hivesys under Product Type.
[NTOS]: Configure the MmSystemSize variable properly based on SKU and RAM. Previously, ReactOS told all drivers and applications you were running on a system with < 13MB RAM.
[NTOS]: Initialize thresholds for low and high memory (in pages), low and high paged pool memory, and low and high nonpaged pool memory. These are described in the source.
[NTOS]: Initialize events for each of those thresholds, and populate the \KernelObject\xxxCondition events that are documented in MSDN for driver and app developers.
[NTOS]: Define some internal thresholds to use later, representing the minimum number of free pages under we go berserk, and the minimum number of free pages that we consider "plenty".
[NTOS]: Rename MiRemoveFromList to MiUnlinkFreeOrZeroedPage (Windows name). Make the function handle MmAvailablePages decrement, instead of having the caller do it.
[NTOS]: Remove run-time initialization of the PFN lists, just initialize them statically (also fixes the fact we forgot to initialize their names).
[NTOS]: Move some more initialization code to ARM3 instead of mm.
[NTOS]: Read ProductType from registry into MmProductType instead of dummy value. Remove duplicate "Mirroring" variable read.
svn path=/trunk/; revision=45638
2010-02-20 21:48:36 +00:00
|
|
|
* This number indicates how many pages we consider to be a low limit of having
|
|
|
|
* "plenty" of free memory.
|
|
|
|
*
|
|
|
|
* It is doubled on systems that have more than 63MB of memory
|
|
|
|
*/
|
|
|
|
PFN_NUMBER MmPlentyFreePages = 400;
|
|
|
|
|
|
|
|
/* These values store the type of system this is (small, med, large) and if server */
|
|
|
|
ULONG MmProductType;
|
|
|
|
MM_SYSTEMSIZE MmSystemSize;
|
|
|
|
|
2010-04-20 22:47:51 +00:00
|
|
|
/*
|
|
|
|
* These values store the cache working set minimums and maximums, in pages
|
|
|
|
*
|
|
|
|
* The minimum value is boosted on systems with more than 24MB of RAM, and cut
|
|
|
|
* down to only 32 pages on embedded (<24MB RAM) systems.
|
|
|
|
*
|
|
|
|
* An extra boost of 2MB is given on systems with more than 33MB of RAM.
|
|
|
|
*/
|
|
|
|
PFN_NUMBER MmSystemCacheWsMinimum = 288;
|
|
|
|
PFN_NUMBER MmSystemCacheWsMaximum = 350;
|
|
|
|
|
|
|
|
/* FIXME: Move to cache/working set code later */
|
|
|
|
BOOLEAN MmLargeSystemCache;
|
|
|
|
|
2010-07-22 18:26:04 +00:00
|
|
|
/*
|
|
|
|
* This value determines in how many fragments/chunks the subsection prototype
|
|
|
|
* PTEs should be allocated when mapping a section object. It is configurable in
|
|
|
|
* the registry through the MapAllocationFragment parameter.
|
|
|
|
*
|
|
|
|
* The default is 64KB on systems with more than 1GB of RAM, 32KB on systems with
|
|
|
|
* more than 256MB of RAM, and 16KB on systems with less than 256MB of RAM.
|
|
|
|
*
|
|
|
|
* The maximum it can be set to is 2MB, and the minimum is 4KB.
|
|
|
|
*/
|
|
|
|
SIZE_T MmAllocationFragment;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* These two values track how much virtual memory can be committed, and when
|
|
|
|
* expansion should happen.
|
|
|
|
*/
|
|
|
|
// FIXME: They should be moved elsewhere since it's not an "init" setting?
|
|
|
|
SIZE_T MmTotalCommitLimit;
|
|
|
|
SIZE_T MmTotalCommitLimitMaximum;
|
|
|
|
|
2013-08-28 18:57:29 +00:00
|
|
|
/*
|
2013-08-28 20:12:35 +00:00
|
|
|
* These values tune certain user parameters. They have default values set here,
|
2013-08-28 18:57:29 +00:00
|
|
|
* as well as in the code, and can be overwritten by registry settings.
|
|
|
|
*/
|
|
|
|
SIZE_T MmHeapSegmentReserve = 1 * _1MB;
|
|
|
|
SIZE_T MmHeapSegmentCommit = 2 * PAGE_SIZE;
|
|
|
|
SIZE_T MmHeapDeCommitTotalFreeThreshold = 64 * _1KB;
|
|
|
|
SIZE_T MmHeapDeCommitFreeBlockThreshold = PAGE_SIZE;
|
|
|
|
SIZE_T MmMinimumStackCommitInBytes = 0;
|
|
|
|
|
2010-10-18 23:07:09 +00:00
|
|
|
/* Internal setting used for debugging memory descriptors */
|
|
|
|
BOOLEAN MiDbgEnableMdDump =
|
|
|
|
#ifdef _ARM_
|
|
|
|
TRUE;
|
|
|
|
#else
|
|
|
|
FALSE;
|
|
|
|
#endif
|
|
|
|
|
2011-09-24 00:12:58 +00:00
|
|
|
/* Number of memory descriptors in the loader block */
|
|
|
|
ULONG MiNumberDescriptors = 0;
|
|
|
|
|
|
|
|
/* Number of free pages in the loader block */
|
|
|
|
PFN_NUMBER MiNumberOfFreePages = 0;
|
|
|
|
|
2013-01-14 13:55:12 +00:00
|
|
|
/* Timeout value for critical sections (2.5 minutes) */
|
|
|
|
ULONG MmCritsectTimeoutSeconds = 150; // NT value: 720 * 60 * 60; (30 days)
|
|
|
|
LARGE_INTEGER MmCriticalSectionTimeout;
|
2011-09-24 00:12:58 +00:00
|
|
|
|
2018-02-09 13:21:14 +00:00
|
|
|
//
|
|
|
|
// Throttling limits for Cc (in pages)
|
|
|
|
// Above top, we don't throttle
|
|
|
|
// Above bottom, we throttle depending on the amount of modified pages
|
|
|
|
// Otherwise, we throttle!
|
|
|
|
//
|
|
|
|
ULONG MmThrottleTop;
|
|
|
|
ULONG MmThrottleBottom;
|
|
|
|
|
2010-02-10 02:00:56 +00:00
|
|
|
/* PRIVATE FUNCTIONS **********************************************************/
|
|
|
|
|
2011-09-24 00:12:58 +00:00
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
MiScanMemoryDescriptors(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
|
|
|
{
|
|
|
|
PLIST_ENTRY ListEntry;
|
|
|
|
PMEMORY_ALLOCATION_DESCRIPTOR Descriptor;
|
|
|
|
PFN_NUMBER PageFrameIndex, FreePages = 0;
|
|
|
|
|
|
|
|
/* Loop the memory descriptors */
|
|
|
|
for (ListEntry = LoaderBlock->MemoryDescriptorListHead.Flink;
|
|
|
|
ListEntry != &LoaderBlock->MemoryDescriptorListHead;
|
|
|
|
ListEntry = ListEntry->Flink)
|
|
|
|
{
|
|
|
|
/* Get the descriptor */
|
|
|
|
Descriptor = CONTAINING_RECORD(ListEntry,
|
|
|
|
MEMORY_ALLOCATION_DESCRIPTOR,
|
|
|
|
ListEntry);
|
|
|
|
DPRINT("MD Type: %lx Base: %lx Count: %lx\n",
|
|
|
|
Descriptor->MemoryType, Descriptor->BasePage, Descriptor->PageCount);
|
|
|
|
|
|
|
|
/* Count this descriptor */
|
|
|
|
MiNumberDescriptors++;
|
|
|
|
|
|
|
|
/* Check if this is invisible memory */
|
2012-01-07 17:05:41 +00:00
|
|
|
if ((Descriptor->MemoryType == LoaderFirmwarePermanent) ||
|
|
|
|
(Descriptor->MemoryType == LoaderSpecialMemory) ||
|
|
|
|
(Descriptor->MemoryType == LoaderHALCachedMemory) ||
|
2011-09-24 00:12:58 +00:00
|
|
|
(Descriptor->MemoryType == LoaderBBTMemory))
|
|
|
|
{
|
|
|
|
/* Skip this descriptor */
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check if this is bad memory */
|
|
|
|
if (Descriptor->MemoryType != LoaderBad)
|
|
|
|
{
|
|
|
|
/* Count this in the total of pages */
|
2011-09-24 08:52:26 +00:00
|
|
|
MmNumberOfPhysicalPages += (PFN_COUNT)Descriptor->PageCount;
|
2011-09-24 00:12:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Check if this is the new lowest page */
|
|
|
|
if (Descriptor->BasePage < MmLowestPhysicalPage)
|
|
|
|
{
|
|
|
|
/* Update the lowest page */
|
|
|
|
MmLowestPhysicalPage = Descriptor->BasePage;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check if this is the new highest page */
|
|
|
|
PageFrameIndex = Descriptor->BasePage + Descriptor->PageCount;
|
|
|
|
if (PageFrameIndex > MmHighestPhysicalPage)
|
|
|
|
{
|
|
|
|
/* Update the highest page */
|
|
|
|
MmHighestPhysicalPage = PageFrameIndex - 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check if this is free memory */
|
|
|
|
if ((Descriptor->MemoryType == LoaderFree) ||
|
|
|
|
(Descriptor->MemoryType == LoaderLoadedProgram) ||
|
|
|
|
(Descriptor->MemoryType == LoaderFirmwareTemporary) ||
|
|
|
|
(Descriptor->MemoryType == LoaderOsloaderStack))
|
|
|
|
{
|
|
|
|
/* Count it too free pages */
|
|
|
|
MiNumberOfFreePages += Descriptor->PageCount;
|
|
|
|
|
|
|
|
/* Check if this is the largest memory descriptor */
|
|
|
|
if (Descriptor->PageCount > FreePages)
|
|
|
|
{
|
|
|
|
/* Remember it */
|
|
|
|
MxFreeDescriptor = Descriptor;
|
|
|
|
FreePages = Descriptor->PageCount;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Save original values of the free descriptor, since it'll be
|
|
|
|
* altered by early allocations */
|
|
|
|
MxOldFreeDescriptor = *MxFreeDescriptor;
|
|
|
|
}
|
|
|
|
|
2020-10-06 19:44:01 +00:00
|
|
|
CODE_SEG("INIT")
|
2010-02-10 17:42:07 +00:00
|
|
|
PFN_NUMBER
|
|
|
|
NTAPI
|
|
|
|
MxGetNextPage(IN PFN_NUMBER PageCount)
|
|
|
|
{
|
|
|
|
PFN_NUMBER Pfn;
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-02-10 17:42:07 +00:00
|
|
|
/* Make sure we have enough pages */
|
|
|
|
if (PageCount > MxFreeDescriptor->PageCount)
|
|
|
|
{
|
|
|
|
/* Crash the system */
|
|
|
|
KeBugCheckEx(INSTALL_MORE_MEMORY,
|
|
|
|
MmNumberOfPhysicalPages,
|
|
|
|
MxFreeDescriptor->PageCount,
|
|
|
|
MxOldFreeDescriptor.PageCount,
|
|
|
|
PageCount);
|
|
|
|
}
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-02-10 17:42:07 +00:00
|
|
|
/* Use our lowest usable free pages */
|
|
|
|
Pfn = MxFreeDescriptor->BasePage;
|
|
|
|
MxFreeDescriptor->BasePage += PageCount;
|
|
|
|
MxFreeDescriptor->PageCount -= PageCount;
|
|
|
|
return Pfn;
|
|
|
|
}
|
|
|
|
|
2020-10-06 19:44:01 +00:00
|
|
|
CODE_SEG("INIT")
|
2010-02-11 00:01:32 +00:00
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
MiComputeColorInformation(VOID)
|
|
|
|
{
|
|
|
|
ULONG L2Associativity;
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-02-11 00:01:32 +00:00
|
|
|
/* Check if no setting was provided already */
|
|
|
|
if (!MmSecondaryColors)
|
|
|
|
{
|
|
|
|
/* Get L2 cache information */
|
|
|
|
L2Associativity = KeGetPcr()->SecondLevelCacheAssociativity;
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-02-11 00:01:32 +00:00
|
|
|
/* The number of colors is the number of cache bytes by set/way */
|
|
|
|
MmSecondaryColors = KeGetPcr()->SecondLevelCacheSize;
|
|
|
|
if (L2Associativity) MmSecondaryColors /= L2Associativity;
|
|
|
|
}
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-02-11 00:01:32 +00:00
|
|
|
/* Now convert cache bytes into pages */
|
|
|
|
MmSecondaryColors >>= PAGE_SHIFT;
|
|
|
|
if (!MmSecondaryColors)
|
|
|
|
{
|
|
|
|
/* If there was no cache data from the KPCR, use the default colors */
|
|
|
|
MmSecondaryColors = MI_SECONDARY_COLORS;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Otherwise, make sure there aren't too many colors */
|
|
|
|
if (MmSecondaryColors > MI_MAX_SECONDARY_COLORS)
|
|
|
|
{
|
|
|
|
/* Set the maximum */
|
|
|
|
MmSecondaryColors = MI_MAX_SECONDARY_COLORS;
|
|
|
|
}
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-02-11 00:01:32 +00:00
|
|
|
/* Make sure there aren't too little colors */
|
|
|
|
if (MmSecondaryColors < MI_MIN_SECONDARY_COLORS)
|
|
|
|
{
|
|
|
|
/* Set the default */
|
|
|
|
MmSecondaryColors = MI_SECONDARY_COLORS;
|
|
|
|
}
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-02-11 00:01:32 +00:00
|
|
|
/* Finally make sure the colors are a power of two */
|
|
|
|
if (MmSecondaryColors & (MmSecondaryColors - 1))
|
|
|
|
{
|
|
|
|
/* Set the default */
|
|
|
|
MmSecondaryColors = MI_SECONDARY_COLORS;
|
|
|
|
}
|
|
|
|
}
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-02-11 00:01:32 +00:00
|
|
|
/* Compute the mask and store it */
|
|
|
|
MmSecondaryColorMask = MmSecondaryColors - 1;
|
2010-12-26 15:23:03 +00:00
|
|
|
KeGetCurrentPrcb()->SecondaryColorMask = MmSecondaryColorMask;
|
2010-02-11 00:01:32 +00:00
|
|
|
}
|
|
|
|
|
2020-10-06 19:44:01 +00:00
|
|
|
CODE_SEG("INIT")
|
2010-02-11 00:01:32 +00:00
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
MiInitializeColorTables(VOID)
|
|
|
|
{
|
|
|
|
ULONG i;
|
|
|
|
PMMPTE PointerPte, LastPte;
|
|
|
|
MMPTE TempPte = ValidKernelPte;
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-02-11 00:01:32 +00:00
|
|
|
/* The color table starts after the ARM3 PFN database */
|
2010-06-06 15:59:42 +00:00
|
|
|
MmFreePagesByColor[0] = (PMMCOLOR_TABLES)&MmPfnDatabase[MmHighestPhysicalPage + 1];
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-02-11 00:01:32 +00:00
|
|
|
/* Loop the PTEs. We have two color tables for each secondary color */
|
|
|
|
PointerPte = MiAddressToPte(&MmFreePagesByColor[0][0]);
|
|
|
|
LastPte = MiAddressToPte((ULONG_PTR)MmFreePagesByColor[0] +
|
|
|
|
(2 * MmSecondaryColors * sizeof(MMCOLOR_TABLES))
|
|
|
|
- 1);
|
|
|
|
while (PointerPte <= LastPte)
|
|
|
|
{
|
|
|
|
/* Check for valid PTE */
|
|
|
|
if (PointerPte->u.Hard.Valid == 0)
|
|
|
|
{
|
|
|
|
/* Get a page and map it */
|
|
|
|
TempPte.u.Hard.PageFrameNumber = MxGetNextPage(1);
|
2010-06-06 18:45:46 +00:00
|
|
|
MI_WRITE_VALID_PTE(PointerPte, TempPte);
|
|
|
|
|
2010-02-11 00:01:32 +00:00
|
|
|
/* Zero out the page */
|
|
|
|
RtlZeroMemory(MiPteToAddress(PointerPte), PAGE_SIZE);
|
|
|
|
}
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-02-11 00:01:32 +00:00
|
|
|
/* Next */
|
|
|
|
PointerPte++;
|
|
|
|
}
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-02-11 00:01:32 +00:00
|
|
|
/* Now set the address of the next list, right after this one */
|
|
|
|
MmFreePagesByColor[1] = &MmFreePagesByColor[0][MmSecondaryColors];
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-02-11 00:01:32 +00:00
|
|
|
/* Now loop the lists to set them up */
|
|
|
|
for (i = 0; i < MmSecondaryColors; i++)
|
|
|
|
{
|
|
|
|
/* Set both free and zero lists for each color */
|
2011-09-30 09:30:52 +00:00
|
|
|
MmFreePagesByColor[ZeroedPageList][i].Flink = LIST_HEAD;
|
|
|
|
MmFreePagesByColor[ZeroedPageList][i].Blink = (PVOID)LIST_HEAD;
|
2010-02-11 00:01:32 +00:00
|
|
|
MmFreePagesByColor[ZeroedPageList][i].Count = 0;
|
2011-09-30 09:30:52 +00:00
|
|
|
MmFreePagesByColor[FreePageList][i].Flink = LIST_HEAD;
|
|
|
|
MmFreePagesByColor[FreePageList][i].Blink = (PVOID)LIST_HEAD;
|
2010-02-11 00:01:32 +00:00
|
|
|
MmFreePagesByColor[FreePageList][i].Count = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-09-30 09:30:52 +00:00
|
|
|
#ifndef _M_AMD64
|
2020-10-06 19:44:01 +00:00
|
|
|
CODE_SEG("INIT")
|
2010-02-11 00:01:32 +00:00
|
|
|
BOOLEAN
|
|
|
|
NTAPI
|
|
|
|
MiIsRegularMemory(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
|
|
|
|
IN PFN_NUMBER Pfn)
|
|
|
|
{
|
|
|
|
PLIST_ENTRY NextEntry;
|
|
|
|
PMEMORY_ALLOCATION_DESCRIPTOR MdBlock;
|
|
|
|
|
|
|
|
/* Loop the memory descriptors */
|
|
|
|
NextEntry = LoaderBlock->MemoryDescriptorListHead.Flink;
|
|
|
|
while (NextEntry != &LoaderBlock->MemoryDescriptorListHead)
|
|
|
|
{
|
|
|
|
/* Get the memory descriptor */
|
|
|
|
MdBlock = CONTAINING_RECORD(NextEntry,
|
|
|
|
MEMORY_ALLOCATION_DESCRIPTOR,
|
|
|
|
ListEntry);
|
|
|
|
|
|
|
|
/* Check if this PFN could be part of the block */
|
|
|
|
if (Pfn >= (MdBlock->BasePage))
|
|
|
|
{
|
|
|
|
/* Check if it really is part of the block */
|
|
|
|
if (Pfn < (MdBlock->BasePage + MdBlock->PageCount))
|
|
|
|
{
|
|
|
|
/* Check if the block is actually memory we don't map */
|
|
|
|
if ((MdBlock->MemoryType == LoaderFirmwarePermanent) ||
|
|
|
|
(MdBlock->MemoryType == LoaderBBTMemory) ||
|
|
|
|
(MdBlock->MemoryType == LoaderSpecialMemory))
|
|
|
|
{
|
|
|
|
/* We don't need PFN database entries for this memory */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* This is memory we want to map */
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Blocks are ordered, so if it's not here, it doesn't exist */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Get to the next descriptor */
|
|
|
|
NextEntry = MdBlock->ListEntry.Flink;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check if this PFN is actually from our free memory descriptor */
|
|
|
|
if ((Pfn >= MxOldFreeDescriptor.BasePage) &&
|
|
|
|
(Pfn < MxOldFreeDescriptor.BasePage + MxOldFreeDescriptor.PageCount))
|
|
|
|
{
|
|
|
|
/* We use these pages for initial mappings, so we do want to count them */
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Otherwise this isn't memory that we describe or care about */
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2020-10-06 19:44:01 +00:00
|
|
|
CODE_SEG("INIT")
|
2010-02-11 00:01:32 +00:00
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
MiMapPfnDatabase(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
|
|
|
{
|
[HAL/NDK]
- Make Vector parameter in HalEnableSystemInterrupt, HalDisableSystemInterrupt and HalBeginSystemInterrupt an ULONG, not an UCHAR
[NDK]
- 64bit fixes for HANDLE_TABLE, KPROCESS, SECTION_IMAGE_INFORMATION, MMADDRESS_LIST, MMVAD_FLAGS, MMVAD, MMVAD_LONG, MMVAD_SHORT, MEMORY_DESCRIPTOR, MEMORY_ALLOCATION_DESCRIPTOR, LdrVerifyMappedImageMatchesChecksum
- KDPC_DATA::DpcQueueDepth is signed on amd64, unsigned on x86
[NTOSKRNL]
- Fix hundreds of MSVC and amd64 warnings
- add a pragma message to FstubFixupEfiPartition, since it looks broken
- Move portable Ke constants from <arch>/cpu.c to krnlinit.c
- Fixed a bug in amd64 KiGeneralProtectionFaultHandler
svn path=/trunk/; revision=53734
2011-09-18 13:11:45 +00:00
|
|
|
PFN_NUMBER FreePage, FreePageCount, PagesLeft, BasePage, PageCount;
|
2010-02-11 00:01:32 +00:00
|
|
|
PLIST_ENTRY NextEntry;
|
|
|
|
PMEMORY_ALLOCATION_DESCRIPTOR MdBlock;
|
|
|
|
PMMPTE PointerPte, LastPte;
|
|
|
|
MMPTE TempPte = ValidKernelPte;
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-02-11 00:01:32 +00:00
|
|
|
/* Get current page data, since we won't be using MxGetNextPage as it would corrupt our state */
|
|
|
|
FreePage = MxFreeDescriptor->BasePage;
|
|
|
|
FreePageCount = MxFreeDescriptor->PageCount;
|
|
|
|
PagesLeft = 0;
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-02-11 00:01:32 +00:00
|
|
|
/* Loop the memory descriptors */
|
|
|
|
NextEntry = LoaderBlock->MemoryDescriptorListHead.Flink;
|
|
|
|
while (NextEntry != &LoaderBlock->MemoryDescriptorListHead)
|
|
|
|
{
|
|
|
|
/* Get the descriptor */
|
|
|
|
MdBlock = CONTAINING_RECORD(NextEntry,
|
|
|
|
MEMORY_ALLOCATION_DESCRIPTOR,
|
|
|
|
ListEntry);
|
|
|
|
if ((MdBlock->MemoryType == LoaderFirmwarePermanent) ||
|
|
|
|
(MdBlock->MemoryType == LoaderBBTMemory) ||
|
|
|
|
(MdBlock->MemoryType == LoaderSpecialMemory))
|
|
|
|
{
|
|
|
|
/* These pages are not part of the PFN database */
|
|
|
|
NextEntry = MdBlock->ListEntry.Flink;
|
|
|
|
continue;
|
|
|
|
}
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-02-11 00:01:32 +00:00
|
|
|
/* Next, check if this is our special free descriptor we've found */
|
|
|
|
if (MdBlock == MxFreeDescriptor)
|
|
|
|
{
|
|
|
|
/* Use the real numbers instead */
|
|
|
|
BasePage = MxOldFreeDescriptor.BasePage;
|
|
|
|
PageCount = MxOldFreeDescriptor.PageCount;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Use the descriptor's numbers */
|
|
|
|
BasePage = MdBlock->BasePage;
|
|
|
|
PageCount = MdBlock->PageCount;
|
|
|
|
}
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-02-11 00:01:32 +00:00
|
|
|
/* Get the PTEs for this range */
|
2010-06-06 15:59:42 +00:00
|
|
|
PointerPte = MiAddressToPte(&MmPfnDatabase[BasePage]);
|
|
|
|
LastPte = MiAddressToPte(((ULONG_PTR)&MmPfnDatabase[BasePage + PageCount]) - 1);
|
2010-02-11 00:01:32 +00:00
|
|
|
DPRINT("MD Type: %lx Base: %lx Count: %lx\n", MdBlock->MemoryType, BasePage, PageCount);
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-02-11 00:01:32 +00:00
|
|
|
/* Loop them */
|
|
|
|
while (PointerPte <= LastPte)
|
|
|
|
{
|
|
|
|
/* We'll only touch PTEs that aren't already valid */
|
|
|
|
if (PointerPte->u.Hard.Valid == 0)
|
|
|
|
{
|
|
|
|
/* Use the next free page */
|
|
|
|
TempPte.u.Hard.PageFrameNumber = FreePage;
|
|
|
|
ASSERT(FreePageCount != 0);
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-02-11 00:01:32 +00:00
|
|
|
/* Consume free pages */
|
|
|
|
FreePage++;
|
|
|
|
FreePageCount--;
|
|
|
|
if (!FreePageCount)
|
|
|
|
{
|
|
|
|
/* Out of memory */
|
|
|
|
KeBugCheckEx(INSTALL_MORE_MEMORY,
|
|
|
|
MmNumberOfPhysicalPages,
|
|
|
|
FreePageCount,
|
|
|
|
MxOldFreeDescriptor.PageCount,
|
|
|
|
1);
|
|
|
|
}
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-02-11 00:01:32 +00:00
|
|
|
/* Write out this PTE */
|
|
|
|
PagesLeft++;
|
2010-06-06 18:45:46 +00:00
|
|
|
MI_WRITE_VALID_PTE(PointerPte, TempPte);
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-02-11 00:01:32 +00:00
|
|
|
/* Zero this page */
|
|
|
|
RtlZeroMemory(MiPteToAddress(PointerPte), PAGE_SIZE);
|
|
|
|
}
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-02-11 00:01:32 +00:00
|
|
|
/* Next! */
|
|
|
|
PointerPte++;
|
|
|
|
}
|
2010-06-06 15:59:42 +00:00
|
|
|
|
2010-02-11 00:01:32 +00:00
|
|
|
/* Do the next address range */
|
|
|
|
NextEntry = MdBlock->ListEntry.Flink;
|
|
|
|
}
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-02-11 00:01:32 +00:00
|
|
|
/* Now update the free descriptors to consume the pages we used up during the PFN allocation loop */
|
|
|
|
MxFreeDescriptor->BasePage = FreePage;
|
|
|
|
MxFreeDescriptor->PageCount = FreePageCount;
|
|
|
|
}
|
|
|
|
|
2020-10-06 19:44:01 +00:00
|
|
|
CODE_SEG("INIT")
|
2010-02-11 09:15:50 +00:00
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
MiBuildPfnDatabaseFromPages(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
|
|
|
{
|
|
|
|
PMMPDE PointerPde;
|
|
|
|
PMMPTE PointerPte;
|
|
|
|
ULONG i, Count, j;
|
|
|
|
PFN_NUMBER PageFrameIndex, StartupPdIndex, PtePageIndex;
|
|
|
|
PMMPFN Pfn1, Pfn2;
|
|
|
|
ULONG_PTR BaseAddress = 0;
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-02-11 09:15:50 +00:00
|
|
|
/* PFN of the startup page directory */
|
|
|
|
StartupPdIndex = PFN_FROM_PTE(MiAddressToPde(PDE_BASE));
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-02-11 09:15:50 +00:00
|
|
|
/* Start with the first PDE and scan them all */
|
|
|
|
PointerPde = MiAddressToPde(NULL);
|
2020-02-05 22:48:26 +00:00
|
|
|
Count = PPE_PER_PAGE * PDE_PER_PAGE;
|
2010-02-11 09:15:50 +00:00
|
|
|
for (i = 0; i < Count; i++)
|
|
|
|
{
|
|
|
|
/* Check for valid PDE */
|
|
|
|
if (PointerPde->u.Hard.Valid == 1)
|
|
|
|
{
|
|
|
|
/* Get the PFN from it */
|
|
|
|
PageFrameIndex = PFN_FROM_PTE(PointerPde);
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-02-11 09:15:50 +00:00
|
|
|
/* Do we want a PFN entry for this page? */
|
|
|
|
if (MiIsRegularMemory(LoaderBlock, PageFrameIndex))
|
|
|
|
{
|
|
|
|
/* Yes we do, set it up */
|
2010-06-06 15:59:42 +00:00
|
|
|
Pfn1 = MiGetPfnEntry(PageFrameIndex);
|
2010-02-11 09:15:50 +00:00
|
|
|
Pfn1->u4.PteFrame = StartupPdIndex;
|
2010-11-24 15:21:45 +00:00
|
|
|
Pfn1->PteAddress = (PMMPTE)PointerPde;
|
2010-02-11 09:15:50 +00:00
|
|
|
Pfn1->u2.ShareCount++;
|
|
|
|
Pfn1->u3.e2.ReferenceCount = 1;
|
|
|
|
Pfn1->u3.e1.PageLocation = ActiveAndValid;
|
2010-02-18 16:56:54 +00:00
|
|
|
Pfn1->u3.e1.CacheAttribute = MiNonCached;
|
2010-11-02 15:16:22 +00:00
|
|
|
#if MI_TRACE_PFNS
|
|
|
|
Pfn1->PfnUsage = MI_USAGE_INIT_MEMORY;
|
2021-03-30 14:20:25 +00:00
|
|
|
MI_SET_PFN_PROCESS_NAME(Pfn1, "Initial PDE");
|
2010-11-02 15:16:22 +00:00
|
|
|
#endif
|
2010-02-11 09:15:50 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* No PFN entry */
|
|
|
|
Pfn1 = NULL;
|
|
|
|
}
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-02-11 09:15:50 +00:00
|
|
|
/* Now get the PTE and scan the pages */
|
|
|
|
PointerPte = MiAddressToPte(BaseAddress);
|
2020-02-05 22:48:26 +00:00
|
|
|
for (j = 0; j < PTE_PER_PAGE; j++)
|
2010-02-11 09:15:50 +00:00
|
|
|
{
|
|
|
|
/* Check for a valid PTE */
|
|
|
|
if (PointerPte->u.Hard.Valid == 1)
|
|
|
|
{
|
|
|
|
/* Increase the shared count of the PFN entry for the PDE */
|
|
|
|
ASSERT(Pfn1 != NULL);
|
|
|
|
Pfn1->u2.ShareCount++;
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-02-11 09:15:50 +00:00
|
|
|
/* Now check if the PTE is valid memory too */
|
|
|
|
PtePageIndex = PFN_FROM_PTE(PointerPte);
|
|
|
|
if (MiIsRegularMemory(LoaderBlock, PtePageIndex))
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Only add pages above the end of system code or pages
|
|
|
|
* that are part of nonpaged pool
|
|
|
|
*/
|
|
|
|
if ((BaseAddress >= 0xA0000000) ||
|
|
|
|
((BaseAddress >= (ULONG_PTR)MmNonPagedPoolStart) &&
|
|
|
|
(BaseAddress < (ULONG_PTR)MmNonPagedPoolStart +
|
|
|
|
MmSizeOfNonPagedPoolInBytes)))
|
|
|
|
{
|
|
|
|
/* Get the PFN entry and make sure it too is valid */
|
2010-06-06 15:59:42 +00:00
|
|
|
Pfn2 = MiGetPfnEntry(PtePageIndex);
|
2010-02-11 09:15:50 +00:00
|
|
|
if ((MmIsAddressValid(Pfn2)) &&
|
|
|
|
(MmIsAddressValid(Pfn2 + 1)))
|
|
|
|
{
|
|
|
|
/* Setup the PFN entry */
|
|
|
|
Pfn2->u4.PteFrame = PageFrameIndex;
|
|
|
|
Pfn2->PteAddress = PointerPte;
|
|
|
|
Pfn2->u2.ShareCount++;
|
|
|
|
Pfn2->u3.e2.ReferenceCount = 1;
|
|
|
|
Pfn2->u3.e1.PageLocation = ActiveAndValid;
|
2010-02-18 16:56:54 +00:00
|
|
|
Pfn2->u3.e1.CacheAttribute = MiNonCached;
|
2010-11-02 15:16:22 +00:00
|
|
|
#if MI_TRACE_PFNS
|
|
|
|
Pfn2->PfnUsage = MI_USAGE_INIT_MEMORY;
|
2021-03-30 14:20:25 +00:00
|
|
|
MI_SET_PFN_PROCESS_NAME(Pfn2, "Initial PTE");
|
2010-11-02 15:16:22 +00:00
|
|
|
#endif
|
2010-02-11 09:15:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-02-11 09:15:50 +00:00
|
|
|
/* Next PTE */
|
|
|
|
PointerPte++;
|
|
|
|
BaseAddress += PAGE_SIZE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Next PDE mapped address */
|
2010-04-20 22:47:51 +00:00
|
|
|
BaseAddress += PDE_MAPPED_VA;
|
2010-02-11 09:15:50 +00:00
|
|
|
}
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-02-11 09:15:50 +00:00
|
|
|
/* Next PTE */
|
|
|
|
PointerPde++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-06 19:44:01 +00:00
|
|
|
CODE_SEG("INIT")
|
2010-02-11 09:15:50 +00:00
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
MiBuildPfnDatabaseZeroPage(VOID)
|
|
|
|
{
|
2010-02-18 16:56:54 +00:00
|
|
|
PMMPFN Pfn1;
|
|
|
|
PMMPDE PointerPde;
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-02-18 16:56:54 +00:00
|
|
|
/* Grab the lowest page and check if it has no real references */
|
2010-06-06 15:59:42 +00:00
|
|
|
Pfn1 = MiGetPfnEntry(MmLowestPhysicalPage);
|
2010-02-18 16:56:54 +00:00
|
|
|
if (!(MmLowestPhysicalPage) && !(Pfn1->u3.e2.ReferenceCount))
|
|
|
|
{
|
|
|
|
/* Make it a bogus page to catch errors */
|
|
|
|
PointerPde = MiAddressToPde(0xFFFFFFFF);
|
|
|
|
Pfn1->u4.PteFrame = PFN_FROM_PTE(PointerPde);
|
2010-11-24 15:21:45 +00:00
|
|
|
Pfn1->PteAddress = (PMMPTE)PointerPde;
|
2010-02-18 16:56:54 +00:00
|
|
|
Pfn1->u2.ShareCount++;
|
|
|
|
Pfn1->u3.e2.ReferenceCount = 0xFFF0;
|
|
|
|
Pfn1->u3.e1.PageLocation = ActiveAndValid;
|
|
|
|
Pfn1->u3.e1.CacheAttribute = MiNonCached;
|
2010-12-26 15:23:03 +00:00
|
|
|
}
|
2010-02-11 09:15:50 +00:00
|
|
|
}
|
|
|
|
|
2020-10-06 19:44:01 +00:00
|
|
|
CODE_SEG("INIT")
|
2010-02-11 09:15:50 +00:00
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
MiBuildPfnDatabaseFromLoaderBlock(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
|
|
|
{
|
2010-02-18 16:56:54 +00:00
|
|
|
PLIST_ENTRY NextEntry;
|
|
|
|
PFN_NUMBER PageCount = 0;
|
|
|
|
PMEMORY_ALLOCATION_DESCRIPTOR MdBlock;
|
|
|
|
PFN_NUMBER PageFrameIndex;
|
|
|
|
PMMPFN Pfn1;
|
|
|
|
PMMPTE PointerPte;
|
|
|
|
PMMPDE PointerPde;
|
2010-06-06 15:59:42 +00:00
|
|
|
KIRQL OldIrql;
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-02-18 16:56:54 +00:00
|
|
|
/* Now loop through the descriptors */
|
|
|
|
NextEntry = LoaderBlock->MemoryDescriptorListHead.Flink;
|
|
|
|
while (NextEntry != &LoaderBlock->MemoryDescriptorListHead)
|
|
|
|
{
|
|
|
|
/* Get the current descriptor */
|
|
|
|
MdBlock = CONTAINING_RECORD(NextEntry,
|
|
|
|
MEMORY_ALLOCATION_DESCRIPTOR,
|
|
|
|
ListEntry);
|
|
|
|
|
|
|
|
/* Read its data */
|
|
|
|
PageCount = MdBlock->PageCount;
|
|
|
|
PageFrameIndex = MdBlock->BasePage;
|
|
|
|
|
|
|
|
/* Don't allow memory above what the PFN database is mapping */
|
|
|
|
if (PageFrameIndex > MmHighestPhysicalPage)
|
|
|
|
{
|
|
|
|
/* Since they are ordered, everything past here will be larger */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* On the other hand, the end page might be higher up... */
|
|
|
|
if ((PageFrameIndex + PageCount) > (MmHighestPhysicalPage + 1))
|
|
|
|
{
|
|
|
|
/* In which case we'll trim the descriptor to go as high as we can */
|
|
|
|
PageCount = MmHighestPhysicalPage + 1 - PageFrameIndex;
|
|
|
|
MdBlock->PageCount = PageCount;
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-02-18 16:56:54 +00:00
|
|
|
/* But if there's nothing left to trim, we got too high, so quit */
|
|
|
|
if (!PageCount) break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Now check the descriptor type */
|
|
|
|
switch (MdBlock->MemoryType)
|
|
|
|
{
|
|
|
|
/* Check for bad RAM */
|
|
|
|
case LoaderBad:
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-08-19 08:50:23 +00:00
|
|
|
DPRINT1("You either have specified /BURNMEMORY or damaged RAM modules.\n");
|
2010-02-18 16:56:54 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
/* Check for free RAM */
|
|
|
|
case LoaderFree:
|
|
|
|
case LoaderLoadedProgram:
|
|
|
|
case LoaderFirmwareTemporary:
|
|
|
|
case LoaderOsloaderStack:
|
|
|
|
|
|
|
|
/* Get the last page of this descriptor. Note we loop backwards */
|
|
|
|
PageFrameIndex += PageCount - 1;
|
2010-06-06 15:59:42 +00:00
|
|
|
Pfn1 = MiGetPfnEntry(PageFrameIndex);
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-06-06 15:59:42 +00:00
|
|
|
/* Lock the PFN Database */
|
2017-11-21 22:33:42 +00:00
|
|
|
OldIrql = MiAcquirePfnLock();
|
2010-02-18 16:56:54 +00:00
|
|
|
while (PageCount--)
|
|
|
|
{
|
|
|
|
/* If the page really has no references, mark it as free */
|
|
|
|
if (!Pfn1->u3.e2.ReferenceCount)
|
|
|
|
{
|
2010-06-06 15:59:42 +00:00
|
|
|
/* Add it to the free list */
|
2010-02-18 16:56:54 +00:00
|
|
|
Pfn1->u3.e1.CacheAttribute = MiNonCached;
|
2010-06-06 15:59:42 +00:00
|
|
|
MiInsertPageInFreeList(PageFrameIndex);
|
2010-02-18 16:56:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Go to the next page */
|
|
|
|
Pfn1--;
|
|
|
|
PageFrameIndex--;
|
|
|
|
}
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-06-06 15:59:42 +00:00
|
|
|
/* Release PFN database */
|
2017-11-21 22:33:42 +00:00
|
|
|
MiReleasePfnLock(OldIrql);
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-02-18 16:56:54 +00:00
|
|
|
/* Done with this block */
|
|
|
|
break;
|
|
|
|
|
|
|
|
/* Check for pages that are invisible to us */
|
|
|
|
case LoaderFirmwarePermanent:
|
|
|
|
case LoaderSpecialMemory:
|
|
|
|
case LoaderBBTMemory:
|
|
|
|
|
|
|
|
/* And skip them */
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
|
|
|
/* Map these pages with the KSEG0 mapping that adds 0x80000000 */
|
|
|
|
PointerPte = MiAddressToPte(KSEG0_BASE + (PageFrameIndex << PAGE_SHIFT));
|
2010-06-06 15:59:42 +00:00
|
|
|
Pfn1 = MiGetPfnEntry(PageFrameIndex);
|
2010-02-18 16:56:54 +00:00
|
|
|
while (PageCount--)
|
|
|
|
{
|
|
|
|
/* Check if the page is really unused */
|
|
|
|
PointerPde = MiAddressToPde(KSEG0_BASE + (PageFrameIndex << PAGE_SHIFT));
|
|
|
|
if (!Pfn1->u3.e2.ReferenceCount)
|
|
|
|
{
|
|
|
|
/* Mark it as being in-use */
|
|
|
|
Pfn1->u4.PteFrame = PFN_FROM_PTE(PointerPde);
|
|
|
|
Pfn1->PteAddress = PointerPte;
|
|
|
|
Pfn1->u2.ShareCount++;
|
|
|
|
Pfn1->u3.e2.ReferenceCount = 1;
|
|
|
|
Pfn1->u3.e1.PageLocation = ActiveAndValid;
|
|
|
|
Pfn1->u3.e1.CacheAttribute = MiNonCached;
|
2010-11-02 15:16:22 +00:00
|
|
|
#if MI_TRACE_PFNS
|
|
|
|
Pfn1->PfnUsage = MI_USAGE_BOOT_DRIVER;
|
|
|
|
#endif
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-02-18 16:56:54 +00:00
|
|
|
/* Check for RAM disk page */
|
|
|
|
if (MdBlock->MemoryType == LoaderXIPRom)
|
|
|
|
{
|
|
|
|
/* Make it a pseudo-I/O ROM mapping */
|
|
|
|
Pfn1->u1.Flink = 0;
|
|
|
|
Pfn1->u2.ShareCount = 0;
|
|
|
|
Pfn1->u3.e2.ReferenceCount = 0;
|
|
|
|
Pfn1->u3.e1.PageLocation = 0;
|
|
|
|
Pfn1->u3.e1.Rom = 1;
|
|
|
|
Pfn1->u4.InPageError = 0;
|
|
|
|
Pfn1->u3.e1.PrototypePte = 1;
|
|
|
|
}
|
|
|
|
}
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-02-18 16:56:54 +00:00
|
|
|
/* Advance page structures */
|
|
|
|
Pfn1++;
|
|
|
|
PageFrameIndex++;
|
|
|
|
PointerPte++;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Next descriptor entry */
|
|
|
|
NextEntry = MdBlock->ListEntry.Flink;
|
|
|
|
}
|
2010-02-11 09:15:50 +00:00
|
|
|
}
|
|
|
|
|
2020-10-06 19:44:01 +00:00
|
|
|
CODE_SEG("INIT")
|
2010-02-11 09:15:50 +00:00
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
MiBuildPfnDatabaseSelf(VOID)
|
|
|
|
{
|
2010-02-18 16:56:54 +00:00
|
|
|
PMMPTE PointerPte, LastPte;
|
|
|
|
PMMPFN Pfn1;
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-02-18 16:56:54 +00:00
|
|
|
/* Loop the PFN database page */
|
2010-06-06 15:59:42 +00:00
|
|
|
PointerPte = MiAddressToPte(MiGetPfnEntry(MmLowestPhysicalPage));
|
|
|
|
LastPte = MiAddressToPte(MiGetPfnEntry(MmHighestPhysicalPage));
|
2010-02-18 16:56:54 +00:00
|
|
|
while (PointerPte <= LastPte)
|
|
|
|
{
|
|
|
|
/* Make sure the page is valid */
|
|
|
|
if (PointerPte->u.Hard.Valid == 1)
|
|
|
|
{
|
|
|
|
/* Get the PFN entry and just mark it referenced */
|
2010-06-06 15:59:42 +00:00
|
|
|
Pfn1 = MiGetPfnEntry(PointerPte->u.Hard.PageFrameNumber);
|
2010-02-18 16:56:54 +00:00
|
|
|
Pfn1->u2.ShareCount = 1;
|
|
|
|
Pfn1->u3.e2.ReferenceCount = 1;
|
2010-11-02 15:16:22 +00:00
|
|
|
#if MI_TRACE_PFNS
|
|
|
|
Pfn1->PfnUsage = MI_USAGE_PFN_DATABASE;
|
|
|
|
#endif
|
2010-02-18 16:56:54 +00:00
|
|
|
}
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-02-18 16:56:54 +00:00
|
|
|
/* Next */
|
|
|
|
PointerPte++;
|
|
|
|
}
|
2010-02-11 09:15:50 +00:00
|
|
|
}
|
|
|
|
|
2020-10-06 19:44:01 +00:00
|
|
|
CODE_SEG("INIT")
|
2010-02-11 09:15:50 +00:00
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
MiInitializePfnDatabase(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
|
|
|
{
|
|
|
|
/* Scan memory and start setting up PFN entries */
|
|
|
|
MiBuildPfnDatabaseFromPages(LoaderBlock);
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-02-11 09:15:50 +00:00
|
|
|
/* Add the zero page */
|
|
|
|
MiBuildPfnDatabaseZeroPage();
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-02-11 09:15:50 +00:00
|
|
|
/* Scan the loader block and build the rest of the PFN database */
|
|
|
|
MiBuildPfnDatabaseFromLoaderBlock(LoaderBlock);
|
2010-12-26 15:23:03 +00:00
|
|
|
|
|
|
|
/* Finally add the pages for the PFN database itself */
|
2010-02-11 09:15:50 +00:00
|
|
|
MiBuildPfnDatabaseSelf();
|
|
|
|
}
|
2011-09-30 09:30:52 +00:00
|
|
|
#endif /* !_M_AMD64 */
|
2010-02-11 09:15:50 +00:00
|
|
|
|
2020-10-06 19:44:01 +00:00
|
|
|
CODE_SEG("INIT")
|
2012-02-17 07:23:27 +00:00
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
MmFreeLoaderBlock(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
|
|
|
{
|
|
|
|
PLIST_ENTRY NextMd;
|
|
|
|
PMEMORY_ALLOCATION_DESCRIPTOR MdBlock;
|
2012-03-28 19:41:40 +00:00
|
|
|
ULONG_PTR i;
|
2012-02-17 07:23:27 +00:00
|
|
|
PFN_NUMBER BasePage, LoaderPages;
|
|
|
|
PMMPFN Pfn1;
|
|
|
|
KIRQL OldIrql;
|
|
|
|
PPHYSICAL_MEMORY_RUN Buffer, Entry;
|
|
|
|
|
|
|
|
/* Loop the descriptors in order to count them */
|
|
|
|
i = 0;
|
|
|
|
NextMd = LoaderBlock->MemoryDescriptorListHead.Flink;
|
|
|
|
while (NextMd != &LoaderBlock->MemoryDescriptorListHead)
|
|
|
|
{
|
|
|
|
MdBlock = CONTAINING_RECORD(NextMd,
|
|
|
|
MEMORY_ALLOCATION_DESCRIPTOR,
|
|
|
|
ListEntry);
|
|
|
|
i++;
|
|
|
|
NextMd = MdBlock->ListEntry.Flink;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Allocate a structure to hold the physical runs */
|
|
|
|
Buffer = ExAllocatePoolWithTag(NonPagedPool,
|
|
|
|
i * sizeof(PHYSICAL_MEMORY_RUN),
|
|
|
|
'lMmM');
|
|
|
|
ASSERT(Buffer != NULL);
|
|
|
|
Entry = Buffer;
|
|
|
|
|
|
|
|
/* Loop the descriptors again */
|
|
|
|
NextMd = LoaderBlock->MemoryDescriptorListHead.Flink;
|
|
|
|
while (NextMd != &LoaderBlock->MemoryDescriptorListHead)
|
|
|
|
{
|
|
|
|
/* Check what kind this was */
|
|
|
|
MdBlock = CONTAINING_RECORD(NextMd,
|
|
|
|
MEMORY_ALLOCATION_DESCRIPTOR,
|
|
|
|
ListEntry);
|
|
|
|
switch (MdBlock->MemoryType)
|
|
|
|
{
|
|
|
|
/* Registry, NLS, and heap data */
|
|
|
|
case LoaderRegistryData:
|
|
|
|
case LoaderOsloaderHeap:
|
|
|
|
case LoaderNlsData:
|
|
|
|
/* Are all a candidate for deletion */
|
|
|
|
Entry->BasePage = MdBlock->BasePage;
|
|
|
|
Entry->PageCount = MdBlock->PageCount;
|
|
|
|
Entry++;
|
|
|
|
|
|
|
|
/* We keep the rest */
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Move to the next descriptor */
|
|
|
|
NextMd = MdBlock->ListEntry.Flink;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Acquire the PFN lock */
|
2017-11-21 22:33:42 +00:00
|
|
|
OldIrql = MiAcquirePfnLock();
|
2012-02-17 07:23:27 +00:00
|
|
|
|
|
|
|
/* Loop the runs */
|
|
|
|
LoaderPages = 0;
|
|
|
|
while (--Entry >= Buffer)
|
|
|
|
{
|
|
|
|
/* See how many pages are in this run */
|
|
|
|
i = Entry->PageCount;
|
|
|
|
BasePage = Entry->BasePage;
|
2012-03-26 07:26:36 +00:00
|
|
|
|
2012-02-17 07:23:27 +00:00
|
|
|
/* Loop each page */
|
|
|
|
Pfn1 = MiGetPfnEntry(BasePage);
|
|
|
|
while (i--)
|
|
|
|
{
|
|
|
|
/* Check if it has references or is in any kind of list */
|
|
|
|
if (!(Pfn1->u3.e2.ReferenceCount) && (!Pfn1->u1.Flink))
|
|
|
|
{
|
|
|
|
/* Set the new PTE address and put this page into the free list */
|
|
|
|
Pfn1->PteAddress = (PMMPTE)(BasePage << PAGE_SHIFT);
|
|
|
|
MiInsertPageInFreeList(BasePage);
|
|
|
|
LoaderPages++;
|
|
|
|
}
|
|
|
|
else if (BasePage)
|
|
|
|
{
|
|
|
|
/* It has a reference, so simply drop it */
|
|
|
|
ASSERT(MI_IS_PHYSICAL_ADDRESS(MiPteToAddress(Pfn1->PteAddress)) == FALSE);
|
|
|
|
|
|
|
|
/* Drop a dereference on this page, which should delete it */
|
|
|
|
Pfn1->PteAddress->u.Long = 0;
|
|
|
|
MI_SET_PFN_DELETED(Pfn1);
|
|
|
|
MiDecrementShareCount(Pfn1, BasePage);
|
|
|
|
LoaderPages++;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Move to the next page */
|
|
|
|
Pfn1++;
|
|
|
|
BasePage++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Release the PFN lock and flush the TLB */
|
2013-09-11 19:59:59 +00:00
|
|
|
DPRINT("Loader pages freed: %lx\n", LoaderPages);
|
2017-11-21 22:33:42 +00:00
|
|
|
MiReleasePfnLock(OldIrql);
|
2012-02-17 07:23:27 +00:00
|
|
|
KeFlushCurrentTb();
|
|
|
|
|
|
|
|
/* Free our run structure */
|
2012-09-28 12:17:23 +00:00
|
|
|
ExFreePoolWithTag(Buffer, 'lMmM');
|
2012-02-17 07:23:27 +00:00
|
|
|
}
|
|
|
|
|
2020-10-06 19:44:01 +00:00
|
|
|
CODE_SEG("INIT")
|
[NTOS]: Make MM init read MmProductType to determine what SKU of ReactOS this is, instead of assuming Server. If you want to go back to the old behavior, you need to change "WinNT" to "ServerNT" in the hivesys under Product Type.
[NTOS]: Configure the MmSystemSize variable properly based on SKU and RAM. Previously, ReactOS told all drivers and applications you were running on a system with < 13MB RAM.
[NTOS]: Initialize thresholds for low and high memory (in pages), low and high paged pool memory, and low and high nonpaged pool memory. These are described in the source.
[NTOS]: Initialize events for each of those thresholds, and populate the \KernelObject\xxxCondition events that are documented in MSDN for driver and app developers.
[NTOS]: Define some internal thresholds to use later, representing the minimum number of free pages under we go berserk, and the minimum number of free pages that we consider "plenty".
[NTOS]: Rename MiRemoveFromList to MiUnlinkFreeOrZeroedPage (Windows name). Make the function handle MmAvailablePages decrement, instead of having the caller do it.
[NTOS]: Remove run-time initialization of the PFN lists, just initialize them statically (also fixes the fact we forgot to initialize their names).
[NTOS]: Move some more initialization code to ARM3 instead of mm.
[NTOS]: Read ProductType from registry into MmProductType instead of dummy value. Remove duplicate "Mirroring" variable read.
svn path=/trunk/; revision=45638
2010-02-20 21:48:36 +00:00
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
MiAdjustWorkingSetManagerParameters(IN BOOLEAN Client)
|
|
|
|
{
|
|
|
|
/* This function needs to do more work, for now, we tune page minimums */
|
2010-12-26 15:23:03 +00:00
|
|
|
|
[NTOS]: Make MM init read MmProductType to determine what SKU of ReactOS this is, instead of assuming Server. If you want to go back to the old behavior, you need to change "WinNT" to "ServerNT" in the hivesys under Product Type.
[NTOS]: Configure the MmSystemSize variable properly based on SKU and RAM. Previously, ReactOS told all drivers and applications you were running on a system with < 13MB RAM.
[NTOS]: Initialize thresholds for low and high memory (in pages), low and high paged pool memory, and low and high nonpaged pool memory. These are described in the source.
[NTOS]: Initialize events for each of those thresholds, and populate the \KernelObject\xxxCondition events that are documented in MSDN for driver and app developers.
[NTOS]: Define some internal thresholds to use later, representing the minimum number of free pages under we go berserk, and the minimum number of free pages that we consider "plenty".
[NTOS]: Rename MiRemoveFromList to MiUnlinkFreeOrZeroedPage (Windows name). Make the function handle MmAvailablePages decrement, instead of having the caller do it.
[NTOS]: Remove run-time initialization of the PFN lists, just initialize them statically (also fixes the fact we forgot to initialize their names).
[NTOS]: Move some more initialization code to ARM3 instead of mm.
[NTOS]: Read ProductType from registry into MmProductType instead of dummy value. Remove duplicate "Mirroring" variable read.
svn path=/trunk/; revision=45638
2010-02-20 21:48:36 +00:00
|
|
|
/* Check for a system with around 64MB RAM or more */
|
|
|
|
if (MmNumberOfPhysicalPages >= (63 * _1MB) / PAGE_SIZE)
|
|
|
|
{
|
|
|
|
/* Double the minimum amount of pages we consider for a "plenty free" scenario */
|
|
|
|
MmPlentyFreePages *= 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-06 19:44:01 +00:00
|
|
|
CODE_SEG("INIT")
|
[NTOS]: Make MM init read MmProductType to determine what SKU of ReactOS this is, instead of assuming Server. If you want to go back to the old behavior, you need to change "WinNT" to "ServerNT" in the hivesys under Product Type.
[NTOS]: Configure the MmSystemSize variable properly based on SKU and RAM. Previously, ReactOS told all drivers and applications you were running on a system with < 13MB RAM.
[NTOS]: Initialize thresholds for low and high memory (in pages), low and high paged pool memory, and low and high nonpaged pool memory. These are described in the source.
[NTOS]: Initialize events for each of those thresholds, and populate the \KernelObject\xxxCondition events that are documented in MSDN for driver and app developers.
[NTOS]: Define some internal thresholds to use later, representing the minimum number of free pages under we go berserk, and the minimum number of free pages that we consider "plenty".
[NTOS]: Rename MiRemoveFromList to MiUnlinkFreeOrZeroedPage (Windows name). Make the function handle MmAvailablePages decrement, instead of having the caller do it.
[NTOS]: Remove run-time initialization of the PFN lists, just initialize them statically (also fixes the fact we forgot to initialize their names).
[NTOS]: Move some more initialization code to ARM3 instead of mm.
[NTOS]: Read ProductType from registry into MmProductType instead of dummy value. Remove duplicate "Mirroring" variable read.
svn path=/trunk/; revision=45638
2010-02-20 21:48:36 +00:00
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
MiNotifyMemoryEvents(VOID)
|
|
|
|
{
|
|
|
|
/* Are we in a low-memory situation? */
|
|
|
|
if (MmAvailablePages < MmLowMemoryThreshold)
|
|
|
|
{
|
|
|
|
/* Clear high, set low */
|
|
|
|
if (KeReadStateEvent(MiHighMemoryEvent)) KeClearEvent(MiHighMemoryEvent);
|
|
|
|
if (!KeReadStateEvent(MiLowMemoryEvent)) KeSetEvent(MiLowMemoryEvent, 0, FALSE);
|
|
|
|
}
|
|
|
|
else if (MmAvailablePages < MmHighMemoryThreshold)
|
|
|
|
{
|
|
|
|
/* We are in between, clear both */
|
|
|
|
if (KeReadStateEvent(MiHighMemoryEvent)) KeClearEvent(MiHighMemoryEvent);
|
|
|
|
if (KeReadStateEvent(MiLowMemoryEvent)) KeClearEvent(MiLowMemoryEvent);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Clear low, set high */
|
|
|
|
if (KeReadStateEvent(MiLowMemoryEvent)) KeClearEvent(MiLowMemoryEvent);
|
|
|
|
if (!KeReadStateEvent(MiHighMemoryEvent)) KeSetEvent(MiHighMemoryEvent, 0, FALSE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-06 19:44:01 +00:00
|
|
|
CODE_SEG("INIT")
|
[NTOS]: Make MM init read MmProductType to determine what SKU of ReactOS this is, instead of assuming Server. If you want to go back to the old behavior, you need to change "WinNT" to "ServerNT" in the hivesys under Product Type.
[NTOS]: Configure the MmSystemSize variable properly based on SKU and RAM. Previously, ReactOS told all drivers and applications you were running on a system with < 13MB RAM.
[NTOS]: Initialize thresholds for low and high memory (in pages), low and high paged pool memory, and low and high nonpaged pool memory. These are described in the source.
[NTOS]: Initialize events for each of those thresholds, and populate the \KernelObject\xxxCondition events that are documented in MSDN for driver and app developers.
[NTOS]: Define some internal thresholds to use later, representing the minimum number of free pages under we go berserk, and the minimum number of free pages that we consider "plenty".
[NTOS]: Rename MiRemoveFromList to MiUnlinkFreeOrZeroedPage (Windows name). Make the function handle MmAvailablePages decrement, instead of having the caller do it.
[NTOS]: Remove run-time initialization of the PFN lists, just initialize them statically (also fixes the fact we forgot to initialize their names).
[NTOS]: Move some more initialization code to ARM3 instead of mm.
[NTOS]: Read ProductType from registry into MmProductType instead of dummy value. Remove duplicate "Mirroring" variable read.
svn path=/trunk/; revision=45638
2010-02-20 21:48:36 +00:00
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
MiCreateMemoryEvent(IN PUNICODE_STRING Name,
|
|
|
|
OUT PKEVENT *Event)
|
|
|
|
{
|
|
|
|
PACL Dacl;
|
|
|
|
HANDLE EventHandle;
|
|
|
|
ULONG DaclLength;
|
|
|
|
NTSTATUS Status;
|
|
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
|
|
SECURITY_DESCRIPTOR SecurityDescriptor;
|
|
|
|
|
|
|
|
/* Create the SD */
|
|
|
|
Status = RtlCreateSecurityDescriptor(&SecurityDescriptor,
|
|
|
|
SECURITY_DESCRIPTOR_REVISION);
|
|
|
|
if (!NT_SUCCESS(Status)) return Status;
|
|
|
|
|
|
|
|
/* One ACL with 3 ACEs, containing each one SID */
|
|
|
|
DaclLength = sizeof(ACL) +
|
|
|
|
3 * sizeof(ACCESS_ALLOWED_ACE) +
|
|
|
|
RtlLengthSid(SeLocalSystemSid) +
|
|
|
|
RtlLengthSid(SeAliasAdminsSid) +
|
|
|
|
RtlLengthSid(SeWorldSid);
|
|
|
|
|
|
|
|
/* Allocate space for the DACL */
|
2022-11-01 21:06:12 +00:00
|
|
|
Dacl = ExAllocatePoolWithTag(PagedPool, DaclLength, TAG_DACL);
|
[NTOS]: Make MM init read MmProductType to determine what SKU of ReactOS this is, instead of assuming Server. If you want to go back to the old behavior, you need to change "WinNT" to "ServerNT" in the hivesys under Product Type.
[NTOS]: Configure the MmSystemSize variable properly based on SKU and RAM. Previously, ReactOS told all drivers and applications you were running on a system with < 13MB RAM.
[NTOS]: Initialize thresholds for low and high memory (in pages), low and high paged pool memory, and low and high nonpaged pool memory. These are described in the source.
[NTOS]: Initialize events for each of those thresholds, and populate the \KernelObject\xxxCondition events that are documented in MSDN for driver and app developers.
[NTOS]: Define some internal thresholds to use later, representing the minimum number of free pages under we go berserk, and the minimum number of free pages that we consider "plenty".
[NTOS]: Rename MiRemoveFromList to MiUnlinkFreeOrZeroedPage (Windows name). Make the function handle MmAvailablePages decrement, instead of having the caller do it.
[NTOS]: Remove run-time initialization of the PFN lists, just initialize them statically (also fixes the fact we forgot to initialize their names).
[NTOS]: Move some more initialization code to ARM3 instead of mm.
[NTOS]: Read ProductType from registry into MmProductType instead of dummy value. Remove duplicate "Mirroring" variable read.
svn path=/trunk/; revision=45638
2010-02-20 21:48:36 +00:00
|
|
|
if (!Dacl) return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
|
|
|
|
/* Setup the ACL inside it */
|
|
|
|
Status = RtlCreateAcl(Dacl, DaclLength, ACL_REVISION);
|
|
|
|
if (!NT_SUCCESS(Status)) goto CleanUp;
|
2010-12-26 15:23:03 +00:00
|
|
|
|
[NTOS]: Make MM init read MmProductType to determine what SKU of ReactOS this is, instead of assuming Server. If you want to go back to the old behavior, you need to change "WinNT" to "ServerNT" in the hivesys under Product Type.
[NTOS]: Configure the MmSystemSize variable properly based on SKU and RAM. Previously, ReactOS told all drivers and applications you were running on a system with < 13MB RAM.
[NTOS]: Initialize thresholds for low and high memory (in pages), low and high paged pool memory, and low and high nonpaged pool memory. These are described in the source.
[NTOS]: Initialize events for each of those thresholds, and populate the \KernelObject\xxxCondition events that are documented in MSDN for driver and app developers.
[NTOS]: Define some internal thresholds to use later, representing the minimum number of free pages under we go berserk, and the minimum number of free pages that we consider "plenty".
[NTOS]: Rename MiRemoveFromList to MiUnlinkFreeOrZeroedPage (Windows name). Make the function handle MmAvailablePages decrement, instead of having the caller do it.
[NTOS]: Remove run-time initialization of the PFN lists, just initialize them statically (also fixes the fact we forgot to initialize their names).
[NTOS]: Move some more initialization code to ARM3 instead of mm.
[NTOS]: Read ProductType from registry into MmProductType instead of dummy value. Remove duplicate "Mirroring" variable read.
svn path=/trunk/; revision=45638
2010-02-20 21:48:36 +00:00
|
|
|
/* Add query rights for everyone */
|
|
|
|
Status = RtlAddAccessAllowedAce(Dacl,
|
|
|
|
ACL_REVISION,
|
|
|
|
SYNCHRONIZE | EVENT_QUERY_STATE | READ_CONTROL,
|
|
|
|
SeWorldSid);
|
|
|
|
if (!NT_SUCCESS(Status)) goto CleanUp;
|
2010-12-26 15:23:03 +00:00
|
|
|
|
[NTOS]: Make MM init read MmProductType to determine what SKU of ReactOS this is, instead of assuming Server. If you want to go back to the old behavior, you need to change "WinNT" to "ServerNT" in the hivesys under Product Type.
[NTOS]: Configure the MmSystemSize variable properly based on SKU and RAM. Previously, ReactOS told all drivers and applications you were running on a system with < 13MB RAM.
[NTOS]: Initialize thresholds for low and high memory (in pages), low and high paged pool memory, and low and high nonpaged pool memory. These are described in the source.
[NTOS]: Initialize events for each of those thresholds, and populate the \KernelObject\xxxCondition events that are documented in MSDN for driver and app developers.
[NTOS]: Define some internal thresholds to use later, representing the minimum number of free pages under we go berserk, and the minimum number of free pages that we consider "plenty".
[NTOS]: Rename MiRemoveFromList to MiUnlinkFreeOrZeroedPage (Windows name). Make the function handle MmAvailablePages decrement, instead of having the caller do it.
[NTOS]: Remove run-time initialization of the PFN lists, just initialize them statically (also fixes the fact we forgot to initialize their names).
[NTOS]: Move some more initialization code to ARM3 instead of mm.
[NTOS]: Read ProductType from registry into MmProductType instead of dummy value. Remove duplicate "Mirroring" variable read.
svn path=/trunk/; revision=45638
2010-02-20 21:48:36 +00:00
|
|
|
/* Full rights for the admin */
|
|
|
|
Status = RtlAddAccessAllowedAce(Dacl,
|
|
|
|
ACL_REVISION,
|
|
|
|
EVENT_ALL_ACCESS,
|
|
|
|
SeAliasAdminsSid);
|
|
|
|
if (!NT_SUCCESS(Status)) goto CleanUp;
|
2010-12-26 15:23:03 +00:00
|
|
|
|
[NTOS]: Make MM init read MmProductType to determine what SKU of ReactOS this is, instead of assuming Server. If you want to go back to the old behavior, you need to change "WinNT" to "ServerNT" in the hivesys under Product Type.
[NTOS]: Configure the MmSystemSize variable properly based on SKU and RAM. Previously, ReactOS told all drivers and applications you were running on a system with < 13MB RAM.
[NTOS]: Initialize thresholds for low and high memory (in pages), low and high paged pool memory, and low and high nonpaged pool memory. These are described in the source.
[NTOS]: Initialize events for each of those thresholds, and populate the \KernelObject\xxxCondition events that are documented in MSDN for driver and app developers.
[NTOS]: Define some internal thresholds to use later, representing the minimum number of free pages under we go berserk, and the minimum number of free pages that we consider "plenty".
[NTOS]: Rename MiRemoveFromList to MiUnlinkFreeOrZeroedPage (Windows name). Make the function handle MmAvailablePages decrement, instead of having the caller do it.
[NTOS]: Remove run-time initialization of the PFN lists, just initialize them statically (also fixes the fact we forgot to initialize their names).
[NTOS]: Move some more initialization code to ARM3 instead of mm.
[NTOS]: Read ProductType from registry into MmProductType instead of dummy value. Remove duplicate "Mirroring" variable read.
svn path=/trunk/; revision=45638
2010-02-20 21:48:36 +00:00
|
|
|
/* As well as full rights for the system */
|
|
|
|
Status = RtlAddAccessAllowedAce(Dacl,
|
|
|
|
ACL_REVISION,
|
|
|
|
EVENT_ALL_ACCESS,
|
|
|
|
SeLocalSystemSid);
|
|
|
|
if (!NT_SUCCESS(Status)) goto CleanUp;
|
2010-12-26 15:23:03 +00:00
|
|
|
|
[NTOS]: Make MM init read MmProductType to determine what SKU of ReactOS this is, instead of assuming Server. If you want to go back to the old behavior, you need to change "WinNT" to "ServerNT" in the hivesys under Product Type.
[NTOS]: Configure the MmSystemSize variable properly based on SKU and RAM. Previously, ReactOS told all drivers and applications you were running on a system with < 13MB RAM.
[NTOS]: Initialize thresholds for low and high memory (in pages), low and high paged pool memory, and low and high nonpaged pool memory. These are described in the source.
[NTOS]: Initialize events for each of those thresholds, and populate the \KernelObject\xxxCondition events that are documented in MSDN for driver and app developers.
[NTOS]: Define some internal thresholds to use later, representing the minimum number of free pages under we go berserk, and the minimum number of free pages that we consider "plenty".
[NTOS]: Rename MiRemoveFromList to MiUnlinkFreeOrZeroedPage (Windows name). Make the function handle MmAvailablePages decrement, instead of having the caller do it.
[NTOS]: Remove run-time initialization of the PFN lists, just initialize them statically (also fixes the fact we forgot to initialize their names).
[NTOS]: Move some more initialization code to ARM3 instead of mm.
[NTOS]: Read ProductType from registry into MmProductType instead of dummy value. Remove duplicate "Mirroring" variable read.
svn path=/trunk/; revision=45638
2010-02-20 21:48:36 +00:00
|
|
|
/* Set this DACL inside the SD */
|
|
|
|
Status = RtlSetDaclSecurityDescriptor(&SecurityDescriptor,
|
|
|
|
TRUE,
|
|
|
|
Dacl,
|
|
|
|
FALSE);
|
|
|
|
if (!NT_SUCCESS(Status)) goto CleanUp;
|
2010-12-26 15:23:03 +00:00
|
|
|
|
[NTOS]: Make MM init read MmProductType to determine what SKU of ReactOS this is, instead of assuming Server. If you want to go back to the old behavior, you need to change "WinNT" to "ServerNT" in the hivesys under Product Type.
[NTOS]: Configure the MmSystemSize variable properly based on SKU and RAM. Previously, ReactOS told all drivers and applications you were running on a system with < 13MB RAM.
[NTOS]: Initialize thresholds for low and high memory (in pages), low and high paged pool memory, and low and high nonpaged pool memory. These are described in the source.
[NTOS]: Initialize events for each of those thresholds, and populate the \KernelObject\xxxCondition events that are documented in MSDN for driver and app developers.
[NTOS]: Define some internal thresholds to use later, representing the minimum number of free pages under we go berserk, and the minimum number of free pages that we consider "plenty".
[NTOS]: Rename MiRemoveFromList to MiUnlinkFreeOrZeroedPage (Windows name). Make the function handle MmAvailablePages decrement, instead of having the caller do it.
[NTOS]: Remove run-time initialization of the PFN lists, just initialize them statically (also fixes the fact we forgot to initialize their names).
[NTOS]: Move some more initialization code to ARM3 instead of mm.
[NTOS]: Read ProductType from registry into MmProductType instead of dummy value. Remove duplicate "Mirroring" variable read.
svn path=/trunk/; revision=45638
2010-02-20 21:48:36 +00:00
|
|
|
/* Setup the event attributes, making sure it's a permanent one */
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
|
|
Name,
|
|
|
|
OBJ_KERNEL_HANDLE | OBJ_PERMANENT,
|
|
|
|
NULL,
|
|
|
|
&SecurityDescriptor);
|
|
|
|
|
|
|
|
/* Create the event */
|
|
|
|
Status = ZwCreateEvent(&EventHandle,
|
|
|
|
EVENT_ALL_ACCESS,
|
|
|
|
&ObjectAttributes,
|
|
|
|
NotificationEvent,
|
|
|
|
FALSE);
|
|
|
|
CleanUp:
|
|
|
|
/* Free the DACL */
|
2022-11-01 21:06:12 +00:00
|
|
|
ExFreePoolWithTag(Dacl, TAG_DACL);
|
[NTOS]: Make MM init read MmProductType to determine what SKU of ReactOS this is, instead of assuming Server. If you want to go back to the old behavior, you need to change "WinNT" to "ServerNT" in the hivesys under Product Type.
[NTOS]: Configure the MmSystemSize variable properly based on SKU and RAM. Previously, ReactOS told all drivers and applications you were running on a system with < 13MB RAM.
[NTOS]: Initialize thresholds for low and high memory (in pages), low and high paged pool memory, and low and high nonpaged pool memory. These are described in the source.
[NTOS]: Initialize events for each of those thresholds, and populate the \KernelObject\xxxCondition events that are documented in MSDN for driver and app developers.
[NTOS]: Define some internal thresholds to use later, representing the minimum number of free pages under we go berserk, and the minimum number of free pages that we consider "plenty".
[NTOS]: Rename MiRemoveFromList to MiUnlinkFreeOrZeroedPage (Windows name). Make the function handle MmAvailablePages decrement, instead of having the caller do it.
[NTOS]: Remove run-time initialization of the PFN lists, just initialize them statically (also fixes the fact we forgot to initialize their names).
[NTOS]: Move some more initialization code to ARM3 instead of mm.
[NTOS]: Read ProductType from registry into MmProductType instead of dummy value. Remove duplicate "Mirroring" variable read.
svn path=/trunk/; revision=45638
2010-02-20 21:48:36 +00:00
|
|
|
|
|
|
|
/* Check if this is the success path */
|
|
|
|
if (NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
/* Add a reference to the object, then close the handle we had */
|
|
|
|
Status = ObReferenceObjectByHandle(EventHandle,
|
|
|
|
EVENT_MODIFY_STATE,
|
|
|
|
ExEventObjectType,
|
|
|
|
KernelMode,
|
|
|
|
(PVOID*)Event,
|
|
|
|
NULL);
|
2010-12-26 15:23:03 +00:00
|
|
|
ZwClose (EventHandle);
|
[NTOS]: Make MM init read MmProductType to determine what SKU of ReactOS this is, instead of assuming Server. If you want to go back to the old behavior, you need to change "WinNT" to "ServerNT" in the hivesys under Product Type.
[NTOS]: Configure the MmSystemSize variable properly based on SKU and RAM. Previously, ReactOS told all drivers and applications you were running on a system with < 13MB RAM.
[NTOS]: Initialize thresholds for low and high memory (in pages), low and high paged pool memory, and low and high nonpaged pool memory. These are described in the source.
[NTOS]: Initialize events for each of those thresholds, and populate the \KernelObject\xxxCondition events that are documented in MSDN for driver and app developers.
[NTOS]: Define some internal thresholds to use later, representing the minimum number of free pages under we go berserk, and the minimum number of free pages that we consider "plenty".
[NTOS]: Rename MiRemoveFromList to MiUnlinkFreeOrZeroedPage (Windows name). Make the function handle MmAvailablePages decrement, instead of having the caller do it.
[NTOS]: Remove run-time initialization of the PFN lists, just initialize them statically (also fixes the fact we forgot to initialize their names).
[NTOS]: Move some more initialization code to ARM3 instead of mm.
[NTOS]: Read ProductType from registry into MmProductType instead of dummy value. Remove duplicate "Mirroring" variable read.
svn path=/trunk/; revision=45638
2010-02-20 21:48:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Return status */
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
2020-10-06 19:44:01 +00:00
|
|
|
CODE_SEG("INIT")
|
[NTOS]: Make MM init read MmProductType to determine what SKU of ReactOS this is, instead of assuming Server. If you want to go back to the old behavior, you need to change "WinNT" to "ServerNT" in the hivesys under Product Type.
[NTOS]: Configure the MmSystemSize variable properly based on SKU and RAM. Previously, ReactOS told all drivers and applications you were running on a system with < 13MB RAM.
[NTOS]: Initialize thresholds for low and high memory (in pages), low and high paged pool memory, and low and high nonpaged pool memory. These are described in the source.
[NTOS]: Initialize events for each of those thresholds, and populate the \KernelObject\xxxCondition events that are documented in MSDN for driver and app developers.
[NTOS]: Define some internal thresholds to use later, representing the minimum number of free pages under we go berserk, and the minimum number of free pages that we consider "plenty".
[NTOS]: Rename MiRemoveFromList to MiUnlinkFreeOrZeroedPage (Windows name). Make the function handle MmAvailablePages decrement, instead of having the caller do it.
[NTOS]: Remove run-time initialization of the PFN lists, just initialize them statically (also fixes the fact we forgot to initialize their names).
[NTOS]: Move some more initialization code to ARM3 instead of mm.
[NTOS]: Read ProductType from registry into MmProductType instead of dummy value. Remove duplicate "Mirroring" variable read.
svn path=/trunk/; revision=45638
2010-02-20 21:48:36 +00:00
|
|
|
BOOLEAN
|
|
|
|
NTAPI
|
|
|
|
MiInitializeMemoryEvents(VOID)
|
|
|
|
{
|
|
|
|
UNICODE_STRING LowString = RTL_CONSTANT_STRING(L"\\KernelObjects\\LowMemoryCondition");
|
|
|
|
UNICODE_STRING HighString = RTL_CONSTANT_STRING(L"\\KernelObjects\\HighMemoryCondition");
|
|
|
|
UNICODE_STRING LowPagedPoolString = RTL_CONSTANT_STRING(L"\\KernelObjects\\LowPagedPoolCondition");
|
|
|
|
UNICODE_STRING HighPagedPoolString = RTL_CONSTANT_STRING(L"\\KernelObjects\\HighPagedPoolCondition");
|
|
|
|
UNICODE_STRING LowNonPagedPoolString = RTL_CONSTANT_STRING(L"\\KernelObjects\\LowNonPagedPoolCondition");
|
|
|
|
UNICODE_STRING HighNonPagedPoolString = RTL_CONSTANT_STRING(L"\\KernelObjects\\HighNonPagedPoolCondition");
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
|
|
|
/* Check if we have a registry setting */
|
|
|
|
if (MmLowMemoryThreshold)
|
|
|
|
{
|
|
|
|
/* Convert it to pages */
|
|
|
|
MmLowMemoryThreshold *= (_1MB / PAGE_SIZE);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* The low memory threshold is hit when we don't consider that we have "plenty" of free pages anymore */
|
|
|
|
MmLowMemoryThreshold = MmPlentyFreePages;
|
|
|
|
|
|
|
|
/* More than one GB of memory? */
|
|
|
|
if (MmNumberOfPhysicalPages > 0x40000)
|
|
|
|
{
|
|
|
|
/* Start at 32MB, and add another 16MB for each GB */
|
|
|
|
MmLowMemoryThreshold = (32 * _1MB) / PAGE_SIZE;
|
|
|
|
MmLowMemoryThreshold += ((MmNumberOfPhysicalPages - 0x40000) >> 7);
|
|
|
|
}
|
|
|
|
else if (MmNumberOfPhysicalPages > 0x8000)
|
|
|
|
{
|
|
|
|
/* For systems with > 128MB RAM, add another 4MB for each 128MB */
|
|
|
|
MmLowMemoryThreshold += ((MmNumberOfPhysicalPages - 0x8000) >> 5);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Don't let the minimum threshold go past 64MB */
|
|
|
|
MmLowMemoryThreshold = min(MmLowMemoryThreshold, (64 * _1MB) / PAGE_SIZE);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check if we have a registry setting */
|
|
|
|
if (MmHighMemoryThreshold)
|
|
|
|
{
|
|
|
|
/* Convert it into pages */
|
|
|
|
MmHighMemoryThreshold *= (_1MB / PAGE_SIZE);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Otherwise, the default is three times the low memory threshold */
|
|
|
|
MmHighMemoryThreshold = 3 * MmLowMemoryThreshold;
|
|
|
|
ASSERT(MmHighMemoryThreshold > MmLowMemoryThreshold);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Make sure high threshold is actually higher than the low */
|
|
|
|
MmHighMemoryThreshold = max(MmHighMemoryThreshold, MmLowMemoryThreshold);
|
|
|
|
|
|
|
|
/* Create the memory events for all the thresholds */
|
|
|
|
Status = MiCreateMemoryEvent(&LowString, &MiLowMemoryEvent);
|
|
|
|
if (!NT_SUCCESS(Status)) return FALSE;
|
|
|
|
Status = MiCreateMemoryEvent(&HighString, &MiHighMemoryEvent);
|
|
|
|
if (!NT_SUCCESS(Status)) return FALSE;
|
|
|
|
Status = MiCreateMemoryEvent(&LowPagedPoolString, &MiLowPagedPoolEvent);
|
|
|
|
if (!NT_SUCCESS(Status)) return FALSE;
|
|
|
|
Status = MiCreateMemoryEvent(&HighPagedPoolString, &MiHighPagedPoolEvent);
|
|
|
|
if (!NT_SUCCESS(Status)) return FALSE;
|
|
|
|
Status = MiCreateMemoryEvent(&LowNonPagedPoolString, &MiLowNonPagedPoolEvent);
|
|
|
|
if (!NT_SUCCESS(Status)) return FALSE;
|
|
|
|
Status = MiCreateMemoryEvent(&HighNonPagedPoolString, &MiHighNonPagedPoolEvent);
|
|
|
|
if (!NT_SUCCESS(Status)) return FALSE;
|
|
|
|
|
|
|
|
/* Now setup the pool events */
|
|
|
|
MiInitializePoolEvents();
|
|
|
|
|
|
|
|
/* Set the initial event state */
|
|
|
|
MiNotifyMemoryEvents();
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2020-10-06 19:44:01 +00:00
|
|
|
CODE_SEG("INIT")
|
2010-04-20 22:47:51 +00:00
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
MiAddHalIoMappings(VOID)
|
|
|
|
{
|
|
|
|
PVOID BaseAddress;
|
2012-02-06 00:24:31 +00:00
|
|
|
PMMPDE PointerPde, LastPde;
|
2010-04-20 22:47:51 +00:00
|
|
|
PMMPTE PointerPte;
|
2012-02-06 00:24:31 +00:00
|
|
|
ULONG j;
|
2010-04-20 22:47:51 +00:00
|
|
|
PFN_NUMBER PageFrameIndex;
|
|
|
|
|
|
|
|
/* HAL Heap address -- should be on a PDE boundary */
|
2011-09-30 09:30:52 +00:00
|
|
|
BaseAddress = (PVOID)MM_HAL_VA_START;
|
2010-04-20 22:47:51 +00:00
|
|
|
ASSERT(MiAddressToPteOffset(BaseAddress) == 0);
|
|
|
|
|
|
|
|
/* Check how many PDEs the heap has */
|
|
|
|
PointerPde = MiAddressToPde(BaseAddress);
|
2012-02-06 00:24:31 +00:00
|
|
|
LastPde = MiAddressToPde((PVOID)MM_HAL_VA_END);
|
|
|
|
|
|
|
|
while (PointerPde <= LastPde)
|
2010-04-20 22:47:51 +00:00
|
|
|
{
|
|
|
|
/* Does the HAL own this mapping? */
|
|
|
|
if ((PointerPde->u.Hard.Valid == 1) &&
|
2010-11-24 15:21:45 +00:00
|
|
|
(MI_IS_PAGE_LARGE(PointerPde) == FALSE))
|
2010-04-20 22:47:51 +00:00
|
|
|
{
|
|
|
|
/* Get the PTE for it and scan each page */
|
|
|
|
PointerPte = MiAddressToPte(BaseAddress);
|
2020-02-05 22:48:26 +00:00
|
|
|
for (j = 0; j < PTE_PER_PAGE; j++)
|
2010-04-20 22:47:51 +00:00
|
|
|
{
|
|
|
|
/* Does the HAL own this page? */
|
|
|
|
if (PointerPte->u.Hard.Valid == 1)
|
|
|
|
{
|
|
|
|
/* Is the HAL using it for device or I/O mapped memory? */
|
|
|
|
PageFrameIndex = PFN_FROM_PTE(PointerPte);
|
|
|
|
if (!MiGetPfnEntry(PageFrameIndex))
|
|
|
|
{
|
|
|
|
/* FIXME: For PAT, we need to track I/O cache attributes for coherency */
|
|
|
|
DPRINT1("HAL I/O Mapping at %p is unsafe\n", BaseAddress);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Move to the next page */
|
|
|
|
BaseAddress = (PVOID)((ULONG_PTR)BaseAddress + PAGE_SIZE);
|
|
|
|
PointerPte++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Move to the next address */
|
|
|
|
BaseAddress = (PVOID)((ULONG_PTR)BaseAddress + PDE_MAPPED_VA);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Move to the next PDE */
|
|
|
|
PointerPde++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-02-18 16:56:54 +00:00
|
|
|
VOID
|
|
|
|
NTAPI
|
2010-11-02 14:58:39 +00:00
|
|
|
MmDumpArmPfnDatabase(IN BOOLEAN StatusOnly)
|
2010-02-18 16:56:54 +00:00
|
|
|
{
|
|
|
|
ULONG i;
|
|
|
|
PMMPFN Pfn1;
|
|
|
|
PCHAR Consumer = "Unknown";
|
|
|
|
KIRQL OldIrql;
|
|
|
|
ULONG ActivePages = 0, FreePages = 0, OtherPages = 0;
|
2010-11-02 15:16:22 +00:00
|
|
|
#if MI_TRACE_PFNS
|
|
|
|
ULONG UsageBucket[MI_USAGE_FREE_PAGE + 1] = {0};
|
|
|
|
PCHAR MI_USAGE_TEXT[MI_USAGE_FREE_PAGE + 1] =
|
|
|
|
{
|
|
|
|
"Not set",
|
|
|
|
"Paged Pool",
|
|
|
|
"Nonpaged Pool",
|
|
|
|
"Nonpaged Pool Ex",
|
|
|
|
"Kernel Stack",
|
|
|
|
"Kernel Stack Ex",
|
|
|
|
"System PTE",
|
|
|
|
"VAD",
|
|
|
|
"PEB/TEB",
|
|
|
|
"Section",
|
|
|
|
"Page Table",
|
|
|
|
"Page Directory",
|
|
|
|
"Old Page Table",
|
|
|
|
"Driver Page",
|
|
|
|
"Contiguous Alloc",
|
|
|
|
"MDL",
|
|
|
|
"Demand Zero",
|
|
|
|
"Zero Loop",
|
|
|
|
"Cache",
|
|
|
|
"PFN Database",
|
|
|
|
"Boot Driver",
|
|
|
|
"Initial Memory",
|
|
|
|
"Free Page"
|
|
|
|
};
|
|
|
|
#endif
|
2010-02-18 16:56:54 +00:00
|
|
|
//
|
|
|
|
// Loop the PFN database
|
|
|
|
//
|
2010-11-02 15:16:22 +00:00
|
|
|
KeRaiseIrql(HIGH_LEVEL, &OldIrql);
|
2010-02-18 16:56:54 +00:00
|
|
|
for (i = 0; i <= MmHighestPhysicalPage; i++)
|
|
|
|
{
|
2010-06-06 15:59:42 +00:00
|
|
|
Pfn1 = MiGetPfnEntry(i);
|
2010-02-18 16:56:54 +00:00
|
|
|
if (!Pfn1) continue;
|
2010-11-02 15:16:22 +00:00
|
|
|
#if MI_TRACE_PFNS
|
|
|
|
ASSERT(Pfn1->PfnUsage <= MI_USAGE_FREE_PAGE);
|
|
|
|
#endif
|
2010-02-18 16:56:54 +00:00
|
|
|
//
|
|
|
|
// Get the page location
|
|
|
|
//
|
|
|
|
switch (Pfn1->u3.e1.PageLocation)
|
|
|
|
{
|
|
|
|
case ActiveAndValid:
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-02-18 16:56:54 +00:00
|
|
|
Consumer = "Active and Valid";
|
|
|
|
ActivePages++;
|
|
|
|
break;
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-11-02 15:16:22 +00:00
|
|
|
case ZeroedPageList:
|
|
|
|
|
|
|
|
Consumer = "Zero Page List";
|
|
|
|
FreePages++;
|
|
|
|
break;//continue;
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-02-18 16:56:54 +00:00
|
|
|
case FreePageList:
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-02-18 16:56:54 +00:00
|
|
|
Consumer = "Free Page List";
|
|
|
|
FreePages++;
|
2010-11-02 15:16:22 +00:00
|
|
|
break;//continue;
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-02-18 16:56:54 +00:00
|
|
|
default:
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-02-18 16:56:54 +00:00
|
|
|
Consumer = "Other (ASSERT!)";
|
|
|
|
OtherPages++;
|
|
|
|
break;
|
|
|
|
}
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-11-02 15:16:22 +00:00
|
|
|
#if MI_TRACE_PFNS
|
|
|
|
/* Add into bucket */
|
|
|
|
UsageBucket[Pfn1->PfnUsage]++;
|
|
|
|
#endif
|
|
|
|
|
2010-02-18 16:56:54 +00:00
|
|
|
//
|
|
|
|
// Pretty-print the page
|
|
|
|
//
|
2010-11-02 15:16:22 +00:00
|
|
|
if (!StatusOnly)
|
2019-11-17 22:01:18 +00:00
|
|
|
DbgPrint("0x%08p:\t%20s\t(%04d.%04d)\t[%16s - %16s]\n",
|
2010-02-18 16:56:54 +00:00
|
|
|
i << PAGE_SHIFT,
|
|
|
|
Consumer,
|
|
|
|
Pfn1->u3.e2.ReferenceCount,
|
2010-11-02 15:16:22 +00:00
|
|
|
Pfn1->u2.ShareCount == LIST_HEAD ? 0xFFFF : Pfn1->u2.ShareCount,
|
|
|
|
#if MI_TRACE_PFNS
|
|
|
|
MI_USAGE_TEXT[Pfn1->PfnUsage],
|
|
|
|
Pfn1->ProcessName);
|
|
|
|
#else
|
|
|
|
"Page tracking",
|
|
|
|
"is disabled");
|
|
|
|
#endif
|
2010-02-18 16:56:54 +00:00
|
|
|
}
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-11-02 15:16:22 +00:00
|
|
|
DbgPrint("Active: %5d pages\t[%6d KB]\n", ActivePages, (ActivePages << PAGE_SHIFT) / 1024);
|
|
|
|
DbgPrint("Free: %5d pages\t[%6d KB]\n", FreePages, (FreePages << PAGE_SHIFT) / 1024);
|
2017-05-22 13:37:44 +00:00
|
|
|
DbgPrint("Other: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024);
|
2010-11-02 15:16:22 +00:00
|
|
|
DbgPrint("-----------------------------------------\n");
|
|
|
|
#if MI_TRACE_PFNS
|
|
|
|
OtherPages = UsageBucket[MI_USAGE_BOOT_DRIVER];
|
|
|
|
DbgPrint("Boot Images: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024);
|
|
|
|
OtherPages = UsageBucket[MI_USAGE_DRIVER_PAGE];
|
|
|
|
DbgPrint("System Drivers: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024);
|
|
|
|
OtherPages = UsageBucket[MI_USAGE_PFN_DATABASE];
|
|
|
|
DbgPrint("PFN Database: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024);
|
2017-05-22 13:37:44 +00:00
|
|
|
OtherPages = UsageBucket[MI_USAGE_PAGE_TABLE] + UsageBucket[MI_USAGE_PAGE_DIRECTORY] + UsageBucket[MI_USAGE_LEGACY_PAGE_DIRECTORY];
|
2010-11-02 15:16:22 +00:00
|
|
|
DbgPrint("Page Tables: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024);
|
2017-05-22 13:37:44 +00:00
|
|
|
OtherPages = UsageBucket[MI_USAGE_SYSTEM_PTE];
|
|
|
|
DbgPrint("System PTEs: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024);
|
|
|
|
OtherPages = UsageBucket[MI_USAGE_VAD];
|
|
|
|
DbgPrint("VADs: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024);
|
|
|
|
OtherPages = UsageBucket[MI_USAGE_CONTINOUS_ALLOCATION];
|
|
|
|
DbgPrint("Continuous Allocs: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024);
|
|
|
|
OtherPages = UsageBucket[MI_USAGE_MDL];
|
|
|
|
DbgPrint("MDLs: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024);
|
2010-11-02 15:16:22 +00:00
|
|
|
OtherPages = UsageBucket[MI_USAGE_NONPAGED_POOL] + UsageBucket[MI_USAGE_NONPAGED_POOL_EXPANSION];
|
|
|
|
DbgPrint("NonPaged Pool: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024);
|
|
|
|
OtherPages = UsageBucket[MI_USAGE_PAGED_POOL];
|
|
|
|
DbgPrint("Paged Pool: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024);
|
2017-05-22 13:37:44 +00:00
|
|
|
OtherPages = UsageBucket[MI_USAGE_DEMAND_ZERO];
|
|
|
|
DbgPrint("Demand Zero: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024);
|
|
|
|
OtherPages = UsageBucket[MI_USAGE_ZERO_LOOP];
|
|
|
|
DbgPrint("Zero Loop: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024);
|
|
|
|
OtherPages = UsageBucket[MI_USAGE_PEB_TEB];
|
|
|
|
DbgPrint("PEB/TEB: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024);
|
2010-11-02 15:16:22 +00:00
|
|
|
OtherPages = UsageBucket[MI_USAGE_KERNEL_STACK] + UsageBucket[MI_USAGE_KERNEL_STACK_EXPANSION];
|
|
|
|
DbgPrint("Kernel Stack: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024);
|
|
|
|
OtherPages = UsageBucket[MI_USAGE_INIT_MEMORY];
|
|
|
|
DbgPrint("Init Memory: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024);
|
|
|
|
OtherPages = UsageBucket[MI_USAGE_SECTION];
|
|
|
|
DbgPrint("Sections: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024);
|
|
|
|
OtherPages = UsageBucket[MI_USAGE_CACHE];
|
|
|
|
DbgPrint("Cache: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024);
|
2017-05-22 13:37:44 +00:00
|
|
|
OtherPages = UsageBucket[MI_USAGE_FREE_PAGE];
|
|
|
|
DbgPrint("Free: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024);
|
2010-11-02 15:16:22 +00:00
|
|
|
#endif
|
2010-02-18 16:56:54 +00:00
|
|
|
KeLowerIrql(OldIrql);
|
|
|
|
}
|
|
|
|
|
2020-10-06 19:44:01 +00:00
|
|
|
CODE_SEG("INIT")
|
2010-02-10 02:00:56 +00:00
|
|
|
PPHYSICAL_MEMORY_DESCRIPTOR
|
|
|
|
NTAPI
|
|
|
|
MmInitializeMemoryLimits(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
|
|
|
|
IN PBOOLEAN IncludeType)
|
|
|
|
{
|
|
|
|
PLIST_ENTRY NextEntry;
|
2011-09-24 00:12:58 +00:00
|
|
|
ULONG Run = 0, InitialRuns;
|
2010-02-10 02:00:56 +00:00
|
|
|
PFN_NUMBER NextPage = -1, PageCount = 0;
|
|
|
|
PPHYSICAL_MEMORY_DESCRIPTOR Buffer, NewBuffer;
|
|
|
|
PMEMORY_ALLOCATION_DESCRIPTOR MdBlock;
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-02-10 02:00:56 +00:00
|
|
|
//
|
2011-09-24 00:12:58 +00:00
|
|
|
// Start with the maximum we might need
|
2010-02-10 02:00:56 +00:00
|
|
|
//
|
2011-09-24 00:12:58 +00:00
|
|
|
InitialRuns = MiNumberDescriptors;
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-02-10 02:00:56 +00:00
|
|
|
//
|
|
|
|
// Allocate the maximum we'll ever need
|
|
|
|
//
|
|
|
|
Buffer = ExAllocatePoolWithTag(NonPagedPool,
|
|
|
|
sizeof(PHYSICAL_MEMORY_DESCRIPTOR) +
|
|
|
|
sizeof(PHYSICAL_MEMORY_RUN) *
|
|
|
|
(InitialRuns - 1),
|
|
|
|
'lMmM');
|
|
|
|
if (!Buffer) return NULL;
|
|
|
|
|
|
|
|
//
|
|
|
|
// For now that's how many runs we have
|
|
|
|
//
|
|
|
|
Buffer->NumberOfRuns = InitialRuns;
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-02-10 02:00:56 +00:00
|
|
|
//
|
|
|
|
// Now loop through the descriptors again
|
|
|
|
//
|
|
|
|
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;
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-02-10 02:00:56 +00:00
|
|
|
//
|
|
|
|
// Check if the next page is described by the next descriptor
|
2010-12-26 15:23:03 +00:00
|
|
|
//
|
2010-02-10 02:00:56 +00:00
|
|
|
if (MdBlock->BasePage == NextPage)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Combine it into the same physical run
|
|
|
|
//
|
|
|
|
ASSERT(MdBlock->PageCount != 0);
|
|
|
|
Buffer->Run[Run - 1].PageCount += MdBlock->PageCount;
|
|
|
|
NextPage += MdBlock->PageCount;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Otherwise just duplicate the descriptor's contents
|
|
|
|
//
|
|
|
|
Buffer->Run[Run].BasePage = MdBlock->BasePage;
|
|
|
|
Buffer->Run[Run].PageCount = MdBlock->PageCount;
|
|
|
|
NextPage = Buffer->Run[Run].BasePage + Buffer->Run[Run].PageCount;
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-02-10 02:00:56 +00:00
|
|
|
//
|
|
|
|
// And in this case, increase the number of runs
|
|
|
|
//
|
|
|
|
Run++;
|
|
|
|
}
|
|
|
|
}
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-02-10 02:00:56 +00:00
|
|
|
//
|
|
|
|
// Try the next descriptor
|
|
|
|
//
|
|
|
|
NextEntry = MdBlock->ListEntry.Flink;
|
|
|
|
}
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-02-10 02:00:56 +00:00
|
|
|
//
|
|
|
|
// We should not have been able to go past our initial estimate
|
|
|
|
//
|
|
|
|
ASSERT(Run <= Buffer->NumberOfRuns);
|
|
|
|
|
|
|
|
//
|
|
|
|
// Our guess was probably exaggerated...
|
|
|
|
//
|
|
|
|
if (InitialRuns > Run)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Allocate a more accurately sized buffer
|
|
|
|
//
|
|
|
|
NewBuffer = ExAllocatePoolWithTag(NonPagedPool,
|
|
|
|
sizeof(PHYSICAL_MEMORY_DESCRIPTOR) +
|
|
|
|
sizeof(PHYSICAL_MEMORY_RUN) *
|
|
|
|
(Run - 1),
|
|
|
|
'lMmM');
|
|
|
|
if (NewBuffer)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Copy the old buffer into the new, then free it
|
|
|
|
//
|
|
|
|
RtlCopyMemory(NewBuffer->Run,
|
|
|
|
Buffer->Run,
|
|
|
|
sizeof(PHYSICAL_MEMORY_RUN) * Run);
|
2011-06-01 13:39:36 +00:00
|
|
|
ExFreePoolWithTag(Buffer, 'lMmM');
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-02-10 02:00:56 +00:00
|
|
|
//
|
|
|
|
// Now use the new buffer
|
|
|
|
//
|
|
|
|
Buffer = NewBuffer;
|
|
|
|
}
|
|
|
|
}
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-02-10 02:00:56 +00:00
|
|
|
//
|
|
|
|
// Write the final numbers, and return it
|
|
|
|
//
|
|
|
|
Buffer->NumberOfRuns = Run;
|
|
|
|
Buffer->NumberOfPages = PageCount;
|
|
|
|
return Buffer;
|
|
|
|
}
|
|
|
|
|
2020-10-06 19:44:01 +00:00
|
|
|
CODE_SEG("INIT")
|
2010-02-10 02:00:56 +00:00
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
MiBuildPagedPool(VOID)
|
|
|
|
{
|
2010-11-24 15:21:45 +00:00
|
|
|
PMMPTE PointerPte;
|
|
|
|
PMMPDE PointerPde;
|
|
|
|
MMPDE TempPde = ValidKernelPde;
|
2010-02-10 02:00:56 +00:00
|
|
|
PFN_NUMBER PageFrameIndex;
|
|
|
|
KIRQL OldIrql;
|
2018-02-04 18:20:20 +00:00
|
|
|
SIZE_T Size, NumberOfPages, NumberOfPdes;
|
[HAL/NDK]
- Make Vector parameter in HalEnableSystemInterrupt, HalDisableSystemInterrupt and HalBeginSystemInterrupt an ULONG, not an UCHAR
[NDK]
- 64bit fixes for HANDLE_TABLE, KPROCESS, SECTION_IMAGE_INFORMATION, MMADDRESS_LIST, MMVAD_FLAGS, MMVAD, MMVAD_LONG, MMVAD_SHORT, MEMORY_DESCRIPTOR, MEMORY_ALLOCATION_DESCRIPTOR, LdrVerifyMappedImageMatchesChecksum
- KDPC_DATA::DpcQueueDepth is signed on amd64, unsigned on x86
[NTOSKRNL]
- Fix hundreds of MSVC and amd64 warnings
- add a pragma message to FstubFixupEfiPartition, since it looks broken
- Move portable Ke constants from <arch>/cpu.c to krnlinit.c
- Fixed a bug in amd64 KiGeneralProtectionFaultHandler
svn path=/trunk/; revision=53734
2011-09-18 13:11:45 +00:00
|
|
|
ULONG BitMapSize;
|
2012-02-05 17:19:58 +00:00
|
|
|
#if (_MI_PAGING_LEVELS >= 3)
|
|
|
|
MMPPE TempPpe = ValidKernelPpe;
|
|
|
|
PMMPPE PointerPpe;
|
|
|
|
#elif (_MI_PAGING_LEVELS == 2)
|
[HAL/NDK]
- Make Vector parameter in HalEnableSystemInterrupt, HalDisableSystemInterrupt and HalBeginSystemInterrupt an ULONG, not an UCHAR
[NDK]
- 64bit fixes for HANDLE_TABLE, KPROCESS, SECTION_IMAGE_INFORMATION, MMADDRESS_LIST, MMVAD_FLAGS, MMVAD, MMVAD_LONG, MMVAD_SHORT, MEMORY_DESCRIPTOR, MEMORY_ALLOCATION_DESCRIPTOR, LdrVerifyMappedImageMatchesChecksum
- KDPC_DATA::DpcQueueDepth is signed on amd64, unsigned on x86
[NTOSKRNL]
- Fix hundreds of MSVC and amd64 warnings
- add a pragma message to FstubFixupEfiPartition, since it looks broken
- Move portable Ke constants from <arch>/cpu.c to krnlinit.c
- Fixed a bug in amd64 KiGeneralProtectionFaultHandler
svn path=/trunk/; revision=53734
2011-09-18 13:11:45 +00:00
|
|
|
MMPTE TempPte = ValidKernelPte;
|
|
|
|
|
2010-02-10 02:00:56 +00:00
|
|
|
//
|
|
|
|
// Get the page frame number for the system page directory
|
|
|
|
//
|
|
|
|
PointerPte = MiAddressToPte(PDE_BASE);
|
2020-02-05 22:48:26 +00:00
|
|
|
ASSERT(PPE_PER_PAGE == 1);
|
2010-05-12 18:33:18 +00:00
|
|
|
MmSystemPageDirectory[0] = PFN_FROM_PTE(PointerPte);
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-02-10 02:00:56 +00:00
|
|
|
//
|
|
|
|
// Allocate a system PTE which will hold a copy of the page directory
|
|
|
|
//
|
|
|
|
PointerPte = MiReserveSystemPtes(1, SystemPteSpace);
|
|
|
|
ASSERT(PointerPte);
|
|
|
|
MmSystemPagePtes = MiPteToAddress(PointerPte);
|
|
|
|
|
|
|
|
//
|
|
|
|
// Make this system PTE point to the system page directory.
|
|
|
|
// It is now essentially double-mapped. This will be used later for lazy
|
|
|
|
// evaluation of PDEs accross process switches, similarly to how the Global
|
|
|
|
// page directory array in the old ReactOS Mm is used (but in a less hacky
|
|
|
|
// way).
|
|
|
|
//
|
2010-02-10 13:56:54 +00:00
|
|
|
TempPte = ValidKernelPte;
|
2020-02-05 22:48:26 +00:00
|
|
|
ASSERT(PPE_PER_PAGE == 1);
|
2010-05-12 18:33:18 +00:00
|
|
|
TempPte.u.Hard.PageFrameNumber = MmSystemPageDirectory[0];
|
2010-06-06 18:45:46 +00:00
|
|
|
MI_WRITE_VALID_PTE(PointerPte, TempPte);
|
2010-07-26 21:45:42 +00:00
|
|
|
#endif
|
2018-01-28 16:45:41 +00:00
|
|
|
|
|
|
|
#ifdef _M_IX86
|
2010-02-10 02:00:56 +00:00
|
|
|
//
|
|
|
|
// Let's get back to paged pool work: size it up.
|
|
|
|
// By default, it should be twice as big as nonpaged pool.
|
|
|
|
//
|
|
|
|
MmSizeOfPagedPoolInBytes = 2 * MmMaximumNonPagedPoolInBytes;
|
|
|
|
if (MmSizeOfPagedPoolInBytes > ((ULONG_PTR)MmNonPagedSystemStart -
|
|
|
|
(ULONG_PTR)MmPagedPoolStart))
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// On the other hand, we have limited VA space, so make sure that the VA
|
|
|
|
// for paged pool doesn't overflow into nonpaged pool VA. Otherwise, set
|
|
|
|
// whatever maximum is possible.
|
|
|
|
//
|
|
|
|
MmSizeOfPagedPoolInBytes = (ULONG_PTR)MmNonPagedSystemStart -
|
|
|
|
(ULONG_PTR)MmPagedPoolStart;
|
|
|
|
}
|
2018-01-28 16:45:41 +00:00
|
|
|
#endif // _M_IX86
|
2010-02-10 02:00:56 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// Get the size in pages and make sure paged pool is at least 32MB.
|
|
|
|
//
|
|
|
|
Size = MmSizeOfPagedPoolInBytes;
|
|
|
|
if (Size < MI_MIN_INIT_PAGED_POOLSIZE) Size = MI_MIN_INIT_PAGED_POOLSIZE;
|
2018-02-04 18:20:20 +00:00
|
|
|
NumberOfPages = BYTES_TO_PAGES(Size);
|
2010-02-10 02:00:56 +00:00
|
|
|
|
|
|
|
//
|
2018-02-04 18:20:20 +00:00
|
|
|
// Now check how many PDEs will be required for these many pages.
|
2010-02-10 02:00:56 +00:00
|
|
|
//
|
2018-02-04 18:20:20 +00:00
|
|
|
NumberOfPdes = (NumberOfPages + (PTE_PER_PAGE - 1)) / PTE_PER_PAGE;
|
2010-02-10 02:00:56 +00:00
|
|
|
|
|
|
|
//
|
2018-02-04 18:20:20 +00:00
|
|
|
// Recompute the PDE-aligned size of the paged pool, in bytes and pages.
|
2010-02-10 02:00:56 +00:00
|
|
|
//
|
2018-02-04 18:20:20 +00:00
|
|
|
MmSizeOfPagedPoolInBytes = NumberOfPdes * PTE_PER_PAGE * PAGE_SIZE;
|
2010-02-10 02:00:56 +00:00
|
|
|
MmSizeOfPagedPoolInPages = MmSizeOfPagedPoolInBytes >> PAGE_SHIFT;
|
|
|
|
|
2018-01-28 16:45:41 +00:00
|
|
|
#ifdef _M_IX86
|
2010-02-10 02:00:56 +00:00
|
|
|
//
|
|
|
|
// Let's be really sure this doesn't overflow into nonpaged system VA
|
|
|
|
//
|
2010-12-26 15:23:03 +00:00
|
|
|
ASSERT((MmSizeOfPagedPoolInBytes + (ULONG_PTR)MmPagedPoolStart) <=
|
2010-02-10 02:00:56 +00:00
|
|
|
(ULONG_PTR)MmNonPagedSystemStart);
|
2018-01-28 16:45:41 +00:00
|
|
|
#endif // _M_IX86
|
2010-02-10 02:00:56 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// This is where paged pool ends
|
|
|
|
//
|
|
|
|
MmPagedPoolEnd = (PVOID)(((ULONG_PTR)MmPagedPoolStart +
|
|
|
|
MmSizeOfPagedPoolInBytes) - 1);
|
|
|
|
|
|
|
|
//
|
2012-02-05 17:19:58 +00:00
|
|
|
// Lock the PFN database
|
2010-02-10 02:00:56 +00:00
|
|
|
//
|
2017-11-21 22:33:42 +00:00
|
|
|
OldIrql = MiAcquirePfnLock();
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-07-26 21:45:42 +00:00
|
|
|
#if (_MI_PAGING_LEVELS >= 3)
|
2012-02-05 17:19:58 +00:00
|
|
|
/* On these systems, there's no double-mapping, so instead, the PPEs
|
2010-07-26 21:45:42 +00:00
|
|
|
* are setup to span the entire paged pool area, so there's no need for the
|
|
|
|
* system PD */
|
2012-02-05 17:19:58 +00:00
|
|
|
for (PointerPpe = MiAddressToPpe(MmPagedPoolStart);
|
|
|
|
PointerPpe <= MiAddressToPpe(MmPagedPoolEnd);
|
|
|
|
PointerPpe++)
|
|
|
|
{
|
|
|
|
/* Check if the PPE is already valid */
|
|
|
|
if (!PointerPpe->u.Hard.Valid)
|
|
|
|
{
|
|
|
|
/* It is not, so map a fresh zeroed page */
|
|
|
|
TempPpe.u.Hard.PageFrameNumber = MiRemoveZeroPage(0);
|
|
|
|
MI_WRITE_VALID_PPE(PointerPpe, TempPpe);
|
2018-02-04 18:20:20 +00:00
|
|
|
MiInitializePfnForOtherProcess(TempPpe.u.Hard.PageFrameNumber,
|
|
|
|
(PMMPTE)PointerPpe,
|
|
|
|
PFN_FROM_PTE(MiAddressToPte(PointerPpe)));
|
2012-02-05 17:19:58 +00:00
|
|
|
}
|
|
|
|
}
|
2010-07-26 21:45:42 +00:00
|
|
|
#endif
|
|
|
|
|
2012-02-05 17:19:58 +00:00
|
|
|
//
|
|
|
|
// So now get the PDE for paged pool and zero it out
|
|
|
|
//
|
|
|
|
PointerPde = MiAddressToPde(MmPagedPoolStart);
|
2010-02-10 02:00:56 +00:00
|
|
|
RtlZeroMemory(PointerPde,
|
2010-11-24 15:21:45 +00:00
|
|
|
(1 + MiAddressToPde(MmPagedPoolEnd) - PointerPde) * sizeof(MMPDE));
|
2010-02-10 02:00:56 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// Next, get the first and last PTE
|
|
|
|
//
|
|
|
|
PointerPte = MiAddressToPte(MmPagedPoolStart);
|
|
|
|
MmPagedPoolInfo.FirstPteForPagedPool = PointerPte;
|
|
|
|
MmPagedPoolInfo.LastPteForPagedPool = MiAddressToPte(MmPagedPoolEnd);
|
|
|
|
|
2010-06-06 14:13:35 +00:00
|
|
|
/* Allocate a page and map the first paged pool PDE */
|
2010-11-02 15:16:22 +00:00
|
|
|
MI_SET_USAGE(MI_USAGE_PAGED_POOL);
|
|
|
|
MI_SET_PROCESS2("Kernel");
|
2010-06-06 14:13:35 +00:00
|
|
|
PageFrameIndex = MiRemoveZeroPage(0);
|
2010-11-24 15:21:45 +00:00
|
|
|
TempPde.u.Hard.PageFrameNumber = PageFrameIndex;
|
|
|
|
MI_WRITE_VALID_PDE(PointerPde, TempPde);
|
2010-07-26 21:45:42 +00:00
|
|
|
#if (_MI_PAGING_LEVELS >= 3)
|
|
|
|
/* Use the PPE of MmPagedPoolStart that was setup above */
|
|
|
|
// Bla = PFN_FROM_PTE(PpeAddress(MmPagedPool...));
|
2012-02-05 17:19:58 +00:00
|
|
|
|
|
|
|
/* Initialize the PFN entry for it */
|
|
|
|
MiInitializePfnForOtherProcess(PageFrameIndex,
|
|
|
|
(PMMPTE)PointerPde,
|
|
|
|
PFN_FROM_PTE(MiAddressToPpe(MmPagedPoolStart)));
|
2010-07-26 21:45:42 +00:00
|
|
|
#else
|
|
|
|
/* Do it this way */
|
2020-02-05 22:48:26 +00:00
|
|
|
// Bla = MmSystemPageDirectory[(PointerPde - (PMMPTE)PDE_BASE) / PDE_PER_PAGE]
|
2010-07-26 23:09:17 +00:00
|
|
|
|
2010-06-06 14:13:35 +00:00
|
|
|
/* Initialize the PFN entry for it */
|
|
|
|
MiInitializePfnForOtherProcess(PageFrameIndex,
|
2010-11-24 15:21:45 +00:00
|
|
|
(PMMPTE)PointerPde,
|
2020-02-05 22:48:26 +00:00
|
|
|
MmSystemPageDirectory[(PointerPde - (PMMPDE)PDE_BASE) / PDE_PER_PAGE]);
|
2010-07-26 23:09:17 +00:00
|
|
|
#endif
|
2010-06-06 14:13:35 +00:00
|
|
|
|
2010-02-10 02:00:56 +00:00
|
|
|
//
|
|
|
|
// Release the PFN database lock
|
|
|
|
//
|
2017-11-21 22:33:42 +00:00
|
|
|
MiReleasePfnLock(OldIrql);
|
2010-02-10 02:00:56 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// We only have one PDE mapped for now... at fault time, additional PDEs
|
|
|
|
// will be allocated to handle paged pool growth. This is where they'll have
|
|
|
|
// to start.
|
|
|
|
//
|
|
|
|
MmPagedPoolInfo.NextPdeForPagedPoolExpansion = PointerPde + 1;
|
|
|
|
|
|
|
|
//
|
|
|
|
// We keep track of each page via a bit, so check how big the bitmap will
|
|
|
|
// have to be (make sure to align our page count such that it fits nicely
|
|
|
|
// into a 4-byte aligned bitmap.
|
|
|
|
//
|
|
|
|
// We'll also allocate the bitmap header itself part of the same buffer.
|
|
|
|
//
|
2018-02-04 18:20:20 +00:00
|
|
|
NumberOfPages = NumberOfPdes * PTE_PER_PAGE;
|
|
|
|
ASSERT(NumberOfPages == MmSizeOfPagedPoolInPages);
|
|
|
|
BitMapSize = (ULONG)NumberOfPages;
|
|
|
|
Size = sizeof(RTL_BITMAP) + (((BitMapSize + 31) / 32) * sizeof(ULONG));
|
2010-02-10 02:00:56 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// Allocate the allocation bitmap, which tells us which regions have not yet
|
|
|
|
// been mapped into memory
|
|
|
|
//
|
|
|
|
MmPagedPoolInfo.PagedPoolAllocationMap = ExAllocatePoolWithTag(NonPagedPool,
|
|
|
|
Size,
|
2016-01-05 19:53:07 +00:00
|
|
|
TAG_MM);
|
2010-02-10 02:00:56 +00:00
|
|
|
ASSERT(MmPagedPoolInfo.PagedPoolAllocationMap);
|
|
|
|
|
|
|
|
//
|
|
|
|
// Initialize it such that at first, only the first page's worth of PTEs is
|
|
|
|
// marked as allocated (incidentially, the first PDE we allocated earlier).
|
|
|
|
//
|
|
|
|
RtlInitializeBitMap(MmPagedPoolInfo.PagedPoolAllocationMap,
|
|
|
|
(PULONG)(MmPagedPoolInfo.PagedPoolAllocationMap + 1),
|
|
|
|
BitMapSize);
|
|
|
|
RtlSetAllBits(MmPagedPoolInfo.PagedPoolAllocationMap);
|
2018-02-04 18:20:20 +00:00
|
|
|
RtlClearBits(MmPagedPoolInfo.PagedPoolAllocationMap, 0, PTE_PER_PAGE);
|
2010-02-10 02:00:56 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// We have a second bitmap, which keeps track of where allocations end.
|
|
|
|
// Given the allocation bitmap and a base address, we can therefore figure
|
|
|
|
// out which page is the last page of that allocation, and thus how big the
|
|
|
|
// entire allocation is.
|
|
|
|
//
|
|
|
|
MmPagedPoolInfo.EndOfPagedPoolBitmap = ExAllocatePoolWithTag(NonPagedPool,
|
|
|
|
Size,
|
2016-01-05 19:53:07 +00:00
|
|
|
TAG_MM);
|
2010-02-10 02:00:56 +00:00
|
|
|
ASSERT(MmPagedPoolInfo.EndOfPagedPoolBitmap);
|
|
|
|
RtlInitializeBitMap(MmPagedPoolInfo.EndOfPagedPoolBitmap,
|
|
|
|
(PULONG)(MmPagedPoolInfo.EndOfPagedPoolBitmap + 1),
|
|
|
|
BitMapSize);
|
|
|
|
|
|
|
|
//
|
|
|
|
// Since no allocations have been made yet, there are no bits set as the end
|
|
|
|
//
|
|
|
|
RtlClearAllBits(MmPagedPoolInfo.EndOfPagedPoolBitmap);
|
|
|
|
|
|
|
|
//
|
|
|
|
// Initialize paged pool.
|
|
|
|
//
|
|
|
|
InitializePool(PagedPool, 0);
|
|
|
|
|
2011-09-26 21:57:40 +00:00
|
|
|
/* Initialize special pool */
|
|
|
|
MiInitializeSpecialPool();
|
|
|
|
|
[NTOS]: Make MM init read MmProductType to determine what SKU of ReactOS this is, instead of assuming Server. If you want to go back to the old behavior, you need to change "WinNT" to "ServerNT" in the hivesys under Product Type.
[NTOS]: Configure the MmSystemSize variable properly based on SKU and RAM. Previously, ReactOS told all drivers and applications you were running on a system with < 13MB RAM.
[NTOS]: Initialize thresholds for low and high memory (in pages), low and high paged pool memory, and low and high nonpaged pool memory. These are described in the source.
[NTOS]: Initialize events for each of those thresholds, and populate the \KernelObject\xxxCondition events that are documented in MSDN for driver and app developers.
[NTOS]: Define some internal thresholds to use later, representing the minimum number of free pages under we go berserk, and the minimum number of free pages that we consider "plenty".
[NTOS]: Rename MiRemoveFromList to MiUnlinkFreeOrZeroedPage (Windows name). Make the function handle MmAvailablePages decrement, instead of having the caller do it.
[NTOS]: Remove run-time initialization of the PFN lists, just initialize them statically (also fixes the fact we forgot to initialize their names).
[NTOS]: Move some more initialization code to ARM3 instead of mm.
[NTOS]: Read ProductType from registry into MmProductType instead of dummy value. Remove duplicate "Mirroring" variable read.
svn path=/trunk/; revision=45638
2010-02-20 21:48:36 +00:00
|
|
|
/* Default low threshold of 30MB or one fifth of paged pool */
|
|
|
|
MiLowPagedPoolThreshold = (30 * _1MB) >> PAGE_SHIFT;
|
|
|
|
MiLowPagedPoolThreshold = min(MiLowPagedPoolThreshold, Size / 5);
|
|
|
|
|
|
|
|
/* Default high threshold of 60MB or 25% */
|
|
|
|
MiHighPagedPoolThreshold = (60 * _1MB) >> PAGE_SHIFT;
|
|
|
|
MiHighPagedPoolThreshold = min(MiHighPagedPoolThreshold, (Size * 2) / 5);
|
|
|
|
ASSERT(MiLowPagedPoolThreshold < MiHighPagedPoolThreshold);
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-10-04 18:36:37 +00:00
|
|
|
/* Setup the global session space */
|
|
|
|
MiInitializeSystemSpaceMap(NULL);
|
2010-02-10 02:00:56 +00:00
|
|
|
}
|
|
|
|
|
2020-10-06 19:44:01 +00:00
|
|
|
CODE_SEG("INIT")
|
2010-10-18 23:07:09 +00:00
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
MiDbgDumpMemoryDescriptors(VOID)
|
|
|
|
{
|
|
|
|
PLIST_ENTRY NextEntry;
|
|
|
|
PMEMORY_ALLOCATION_DESCRIPTOR Md;
|
[HAL/NDK]
- Make Vector parameter in HalEnableSystemInterrupt, HalDisableSystemInterrupt and HalBeginSystemInterrupt an ULONG, not an UCHAR
[NDK]
- 64bit fixes for HANDLE_TABLE, KPROCESS, SECTION_IMAGE_INFORMATION, MMADDRESS_LIST, MMVAD_FLAGS, MMVAD, MMVAD_LONG, MMVAD_SHORT, MEMORY_DESCRIPTOR, MEMORY_ALLOCATION_DESCRIPTOR, LdrVerifyMappedImageMatchesChecksum
- KDPC_DATA::DpcQueueDepth is signed on amd64, unsigned on x86
[NTOSKRNL]
- Fix hundreds of MSVC and amd64 warnings
- add a pragma message to FstubFixupEfiPartition, since it looks broken
- Move portable Ke constants from <arch>/cpu.c to krnlinit.c
- Fixed a bug in amd64 KiGeneralProtectionFaultHandler
svn path=/trunk/; revision=53734
2011-09-18 13:11:45 +00:00
|
|
|
PFN_NUMBER TotalPages = 0;
|
2010-10-18 23:07:09 +00:00
|
|
|
PCHAR
|
|
|
|
MemType[] =
|
|
|
|
{
|
|
|
|
"ExceptionBlock ",
|
|
|
|
"SystemBlock ",
|
|
|
|
"Free ",
|
|
|
|
"Bad ",
|
|
|
|
"LoadedProgram ",
|
|
|
|
"FirmwareTemporary ",
|
|
|
|
"FirmwarePermanent ",
|
|
|
|
"OsloaderHeap ",
|
|
|
|
"OsloaderStack ",
|
|
|
|
"SystemCode ",
|
|
|
|
"HalCode ",
|
|
|
|
"BootDriver ",
|
|
|
|
"ConsoleInDriver ",
|
|
|
|
"ConsoleOutDriver ",
|
|
|
|
"StartupDpcStack ",
|
|
|
|
"StartupKernelStack",
|
|
|
|
"StartupPanicStack ",
|
|
|
|
"StartupPcrPage ",
|
|
|
|
"StartupPdrPage ",
|
|
|
|
"RegistryData ",
|
|
|
|
"MemoryData ",
|
|
|
|
"NlsData ",
|
|
|
|
"SpecialMemory ",
|
|
|
|
"BBTMemory ",
|
|
|
|
"LoaderReserve ",
|
|
|
|
"LoaderXIPRom "
|
|
|
|
};
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-10-18 23:07:09 +00:00
|
|
|
DPRINT1("Base\t\tLength\t\tType\n");
|
|
|
|
for (NextEntry = KeLoaderBlock->MemoryDescriptorListHead.Flink;
|
|
|
|
NextEntry != &KeLoaderBlock->MemoryDescriptorListHead;
|
|
|
|
NextEntry = NextEntry->Flink)
|
|
|
|
{
|
|
|
|
Md = CONTAINING_RECORD(NextEntry, MEMORY_ALLOCATION_DESCRIPTOR, ListEntry);
|
|
|
|
DPRINT1("%08lX\t%08lX\t%s\n", Md->BasePage, Md->PageCount, MemType[Md->MemoryType]);
|
|
|
|
TotalPages += Md->PageCount;
|
|
|
|
}
|
|
|
|
|
2013-08-31 16:02:13 +00:00
|
|
|
DPRINT1("Total: %08lX (%lu MB)\n", (ULONG)TotalPages, (ULONG)(TotalPages * PAGE_SIZE) / 1024 / 1024);
|
2010-10-18 23:07:09 +00:00
|
|
|
}
|
|
|
|
|
2020-10-06 19:44:01 +00:00
|
|
|
CODE_SEG("INIT")
|
2010-10-18 23:07:09 +00:00
|
|
|
BOOLEAN
|
2010-02-10 02:00:56 +00:00
|
|
|
NTAPI
|
|
|
|
MmArmInitSystem(IN ULONG Phase,
|
|
|
|
IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
|
|
|
{
|
|
|
|
ULONG i;
|
|
|
|
BOOLEAN IncludeType[LoaderMaximum];
|
|
|
|
PVOID Bitmap;
|
|
|
|
PPHYSICAL_MEMORY_RUN Run;
|
|
|
|
PFN_NUMBER PageCount;
|
2012-08-24 06:08:20 +00:00
|
|
|
#if DBG
|
|
|
|
ULONG j;
|
|
|
|
PMMPTE PointerPte, TestPte;
|
|
|
|
MMPTE TempPte;
|
|
|
|
#endif
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-10-18 23:07:09 +00:00
|
|
|
/* Dump memory descriptors */
|
|
|
|
if (MiDbgEnableMdDump) MiDbgDumpMemoryDescriptors();
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-02-10 02:00:56 +00:00
|
|
|
//
|
|
|
|
// 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)
|
|
|
|
{
|
2011-09-24 14:22:13 +00:00
|
|
|
/* Count physical pages on the system */
|
|
|
|
MiScanMemoryDescriptors(LoaderBlock);
|
|
|
|
|
[NTOS]: Make MM init read MmProductType to determine what SKU of ReactOS this is, instead of assuming Server. If you want to go back to the old behavior, you need to change "WinNT" to "ServerNT" in the hivesys under Product Type.
[NTOS]: Configure the MmSystemSize variable properly based on SKU and RAM. Previously, ReactOS told all drivers and applications you were running on a system with < 13MB RAM.
[NTOS]: Initialize thresholds for low and high memory (in pages), low and high paged pool memory, and low and high nonpaged pool memory. These are described in the source.
[NTOS]: Initialize events for each of those thresholds, and populate the \KernelObject\xxxCondition events that are documented in MSDN for driver and app developers.
[NTOS]: Define some internal thresholds to use later, representing the minimum number of free pages under we go berserk, and the minimum number of free pages that we consider "plenty".
[NTOS]: Rename MiRemoveFromList to MiUnlinkFreeOrZeroedPage (Windows name). Make the function handle MmAvailablePages decrement, instead of having the caller do it.
[NTOS]: Remove run-time initialization of the PFN lists, just initialize them statically (also fixes the fact we forgot to initialize their names).
[NTOS]: Move some more initialization code to ARM3 instead of mm.
[NTOS]: Read ProductType from registry into MmProductType instead of dummy value. Remove duplicate "Mirroring" variable read.
svn path=/trunk/; revision=45638
2010-02-20 21:48:36 +00:00
|
|
|
/* Initialize the phase 0 temporary event */
|
|
|
|
KeInitializeEvent(&MiTempEvent, NotificationEvent, FALSE);
|
|
|
|
|
|
|
|
/* Set all the events to use the temporary event for now */
|
|
|
|
MiLowMemoryEvent = &MiTempEvent;
|
|
|
|
MiHighMemoryEvent = &MiTempEvent;
|
|
|
|
MiLowPagedPoolEvent = &MiTempEvent;
|
|
|
|
MiHighPagedPoolEvent = &MiTempEvent;
|
|
|
|
MiLowNonPagedPoolEvent = &MiTempEvent;
|
|
|
|
MiHighNonPagedPoolEvent = &MiTempEvent;
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2018-02-09 13:21:14 +00:00
|
|
|
//
|
|
|
|
// Default throttling limits for Cc
|
|
|
|
// May be ajusted later on depending on system type
|
|
|
|
//
|
|
|
|
MmThrottleTop = 450;
|
|
|
|
MmThrottleBottom = 127;
|
|
|
|
|
2010-02-10 02:00:56 +00:00
|
|
|
//
|
|
|
|
// Define the basic user vs. kernel address space separation
|
|
|
|
//
|
2011-09-24 08:52:26 +00:00
|
|
|
MmSystemRangeStart = (PVOID)MI_DEFAULT_SYSTEM_RANGE_START;
|
2012-12-30 11:52:05 +00:00
|
|
|
MmUserProbeAddress = (ULONG_PTR)MI_USER_PROBE_ADDRESS;
|
2011-09-24 08:52:26 +00:00
|
|
|
MmHighestUserAddress = (PVOID)MI_HIGHEST_USER_ADDRESS;
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-05-12 18:36:15 +00:00
|
|
|
/* Highest PTE and PDE based on the addresses above */
|
|
|
|
MiHighestUserPte = MiAddressToPte(MmHighestUserAddress);
|
|
|
|
MiHighestUserPde = MiAddressToPde(MmHighestUserAddress);
|
2010-07-26 21:45:42 +00:00
|
|
|
#if (_MI_PAGING_LEVELS >= 3)
|
[HAL/NDK]
- Make Vector parameter in HalEnableSystemInterrupt, HalDisableSystemInterrupt and HalBeginSystemInterrupt an ULONG, not an UCHAR
[NDK]
- 64bit fixes for HANDLE_TABLE, KPROCESS, SECTION_IMAGE_INFORMATION, MMADDRESS_LIST, MMVAD_FLAGS, MMVAD, MMVAD_LONG, MMVAD_SHORT, MEMORY_DESCRIPTOR, MEMORY_ALLOCATION_DESCRIPTOR, LdrVerifyMappedImageMatchesChecksum
- KDPC_DATA::DpcQueueDepth is signed on amd64, unsigned on x86
[NTOSKRNL]
- Fix hundreds of MSVC and amd64 warnings
- add a pragma message to FstubFixupEfiPartition, since it looks broken
- Move portable Ke constants from <arch>/cpu.c to krnlinit.c
- Fixed a bug in amd64 KiGeneralProtectionFaultHandler
svn path=/trunk/; revision=53734
2011-09-18 13:11:45 +00:00
|
|
|
MiHighestUserPpe = MiAddressToPpe(MmHighestUserAddress);
|
|
|
|
#if (_MI_PAGING_LEVELS >= 4)
|
|
|
|
MiHighestUserPxe = MiAddressToPxe(MmHighestUserAddress);
|
|
|
|
#endif
|
2010-07-26 21:45:42 +00:00
|
|
|
#endif
|
2010-02-10 02:00:56 +00:00
|
|
|
//
|
|
|
|
// Get the size of the boot loader's image allocations and then round
|
|
|
|
// that region up to a PDE size, so that any PDEs we might create for
|
|
|
|
// whatever follows are separate from the PDEs that boot loader might've
|
|
|
|
// already created (and later, we can blow all that away if we want to).
|
|
|
|
//
|
|
|
|
MmBootImageSize = KeLoaderBlock->Extension->LoaderPagesSpanned;
|
|
|
|
MmBootImageSize *= PAGE_SIZE;
|
2010-05-12 18:42:05 +00:00
|
|
|
MmBootImageSize = (MmBootImageSize + PDE_MAPPED_VA - 1) & ~(PDE_MAPPED_VA - 1);
|
|
|
|
ASSERT((MmBootImageSize % PDE_MAPPED_VA) == 0);
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2011-09-24 08:52:26 +00:00
|
|
|
/* Initialize session space address layout */
|
|
|
|
MiInitializeSessionSpaceLayout();
|
2012-08-24 06:08:20 +00:00
|
|
|
|
2012-03-26 07:26:36 +00:00
|
|
|
/* Set the based section highest address */
|
|
|
|
MmHighSectionBase = (PVOID)((ULONG_PTR)MmHighestUserAddress - 0x800000);
|
|
|
|
|
|
|
|
/* Loop all 8 standby lists */
|
|
|
|
for (i = 0; i < 8; i++)
|
|
|
|
{
|
|
|
|
/* Initialize them */
|
|
|
|
MmStandbyPageListByPriority[i].Total = 0;
|
|
|
|
MmStandbyPageListByPriority[i].ListName = StandbyPageList;
|
|
|
|
MmStandbyPageListByPriority[i].Flink = MM_EMPTY_LIST;
|
|
|
|
MmStandbyPageListByPriority[i].Blink = MM_EMPTY_LIST;
|
|
|
|
}
|
2010-12-26 15:23:03 +00:00
|
|
|
|
[NTOS]: Make MM init read MmProductType to determine what SKU of ReactOS this is, instead of assuming Server. If you want to go back to the old behavior, you need to change "WinNT" to "ServerNT" in the hivesys under Product Type.
[NTOS]: Configure the MmSystemSize variable properly based on SKU and RAM. Previously, ReactOS told all drivers and applications you were running on a system with < 13MB RAM.
[NTOS]: Initialize thresholds for low and high memory (in pages), low and high paged pool memory, and low and high nonpaged pool memory. These are described in the source.
[NTOS]: Initialize events for each of those thresholds, and populate the \KernelObject\xxxCondition events that are documented in MSDN for driver and app developers.
[NTOS]: Define some internal thresholds to use later, representing the minimum number of free pages under we go berserk, and the minimum number of free pages that we consider "plenty".
[NTOS]: Rename MiRemoveFromList to MiUnlinkFreeOrZeroedPage (Windows name). Make the function handle MmAvailablePages decrement, instead of having the caller do it.
[NTOS]: Remove run-time initialization of the PFN lists, just initialize them statically (also fixes the fact we forgot to initialize their names).
[NTOS]: Move some more initialization code to ARM3 instead of mm.
[NTOS]: Read ProductType from registry into MmProductType instead of dummy value. Remove duplicate "Mirroring" variable read.
svn path=/trunk/; revision=45638
2010-02-20 21:48:36 +00:00
|
|
|
/* Initialize the user mode image list */
|
|
|
|
InitializeListHead(&MmLoadedUserImageList);
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2021-04-12 09:36:19 +00:00
|
|
|
/* Initalize the Working set list */
|
|
|
|
InitializeListHead(&MmWorkingSetExpansionHead);
|
|
|
|
|
2013-01-14 13:55:12 +00:00
|
|
|
/* Initialize critical section timeout value (relative time is negative) */
|
|
|
|
MmCriticalSectionTimeout.QuadPart = MmCritsectTimeoutSeconds * (-10000000LL);
|
|
|
|
|
2012-03-26 07:26:36 +00:00
|
|
|
/* Initialize the paged pool mutex and the section commit mutex */
|
[NTOS]: Make MM init read MmProductType to determine what SKU of ReactOS this is, instead of assuming Server. If you want to go back to the old behavior, you need to change "WinNT" to "ServerNT" in the hivesys under Product Type.
[NTOS]: Configure the MmSystemSize variable properly based on SKU and RAM. Previously, ReactOS told all drivers and applications you were running on a system with < 13MB RAM.
[NTOS]: Initialize thresholds for low and high memory (in pages), low and high paged pool memory, and low and high nonpaged pool memory. These are described in the source.
[NTOS]: Initialize events for each of those thresholds, and populate the \KernelObject\xxxCondition events that are documented in MSDN for driver and app developers.
[NTOS]: Define some internal thresholds to use later, representing the minimum number of free pages under we go berserk, and the minimum number of free pages that we consider "plenty".
[NTOS]: Rename MiRemoveFromList to MiUnlinkFreeOrZeroedPage (Windows name). Make the function handle MmAvailablePages decrement, instead of having the caller do it.
[NTOS]: Remove run-time initialization of the PFN lists, just initialize them statically (also fixes the fact we forgot to initialize their names).
[NTOS]: Move some more initialization code to ARM3 instead of mm.
[NTOS]: Read ProductType from registry into MmProductType instead of dummy value. Remove duplicate "Mirroring" variable read.
svn path=/trunk/; revision=45638
2010-02-20 21:48:36 +00:00
|
|
|
KeInitializeGuardedMutex(&MmPagedPoolMutex);
|
2012-03-26 07:26:36 +00:00
|
|
|
KeInitializeGuardedMutex(&MmSectionCommitMutex);
|
|
|
|
KeInitializeGuardedMutex(&MmSectionBasedMutex);
|
2010-12-26 15:23:03 +00:00
|
|
|
|
[NTOS]: Make MM init read MmProductType to determine what SKU of ReactOS this is, instead of assuming Server. If you want to go back to the old behavior, you need to change "WinNT" to "ServerNT" in the hivesys under Product Type.
[NTOS]: Configure the MmSystemSize variable properly based on SKU and RAM. Previously, ReactOS told all drivers and applications you were running on a system with < 13MB RAM.
[NTOS]: Initialize thresholds for low and high memory (in pages), low and high paged pool memory, and low and high nonpaged pool memory. These are described in the source.
[NTOS]: Initialize events for each of those thresholds, and populate the \KernelObject\xxxCondition events that are documented in MSDN for driver and app developers.
[NTOS]: Define some internal thresholds to use later, representing the minimum number of free pages under we go berserk, and the minimum number of free pages that we consider "plenty".
[NTOS]: Rename MiRemoveFromList to MiUnlinkFreeOrZeroedPage (Windows name). Make the function handle MmAvailablePages decrement, instead of having the caller do it.
[NTOS]: Remove run-time initialization of the PFN lists, just initialize them statically (also fixes the fact we forgot to initialize their names).
[NTOS]: Move some more initialization code to ARM3 instead of mm.
[NTOS]: Read ProductType from registry into MmProductType instead of dummy value. Remove duplicate "Mirroring" variable read.
svn path=/trunk/; revision=45638
2010-02-20 21:48:36 +00:00
|
|
|
/* Initialize the Loader Lock */
|
2010-12-26 15:23:03 +00:00
|
|
|
KeInitializeMutant(&MmSystemLoadLock, FALSE);
|
2010-09-28 16:47:25 +00:00
|
|
|
|
2020-02-22 11:31:54 +00:00
|
|
|
/* Set up the zero page event */
|
|
|
|
KeInitializeEvent(&MmZeroingPageEvent, NotificationEvent, FALSE);
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2012-03-04 17:56:00 +00:00
|
|
|
/* Initialize the dead stack S-LIST */
|
|
|
|
InitializeSListHead(&MmDeadStackSListHead);
|
|
|
|
|
2010-02-10 02:00:56 +00:00
|
|
|
//
|
|
|
|
// Check if this is a machine with less than 19MB of RAM
|
|
|
|
//
|
2011-09-24 14:22:13 +00:00
|
|
|
PageCount = MmNumberOfPhysicalPages;
|
2010-02-10 02:00:56 +00:00
|
|
|
if (PageCount < MI_MIN_PAGES_FOR_SYSPTE_TUNING)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Use the very minimum of system PTEs
|
|
|
|
//
|
|
|
|
MmNumberOfSystemPtes = 7000;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
//
|
2012-07-23 00:52:01 +00:00
|
|
|
// Use the default
|
2010-02-10 02:00:56 +00:00
|
|
|
//
|
|
|
|
MmNumberOfSystemPtes = 11000;
|
|
|
|
if (PageCount > MI_MIN_PAGES_FOR_SYSPTE_BOOST)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Double the amount of system PTEs
|
|
|
|
//
|
|
|
|
MmNumberOfSystemPtes <<= 1;
|
|
|
|
}
|
2012-07-23 00:52:01 +00:00
|
|
|
if (PageCount > MI_MIN_PAGES_FOR_SYSPTE_BOOST_BOOST)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Double the amount of system PTEs
|
|
|
|
//
|
|
|
|
MmNumberOfSystemPtes <<= 1;
|
|
|
|
}
|
2015-02-12 09:14:52 +00:00
|
|
|
if (MmSpecialPoolTag != 0 && MmSpecialPoolTag != -1)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Add some extra PTEs for special pool
|
|
|
|
//
|
|
|
|
MmNumberOfSystemPtes += 0x6000;
|
|
|
|
}
|
2010-02-10 02:00:56 +00:00
|
|
|
}
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2013-08-31 16:02:13 +00:00
|
|
|
DPRINT("System PTE count has been tuned to %lu (%lu bytes)\n",
|
2010-02-10 02:00:56 +00:00
|
|
|
MmNumberOfSystemPtes, MmNumberOfSystemPtes * PAGE_SIZE);
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2013-08-28 18:57:29 +00:00
|
|
|
/* Check if no values are set for the heap limits */
|
|
|
|
if (MmHeapSegmentReserve == 0)
|
|
|
|
{
|
|
|
|
MmHeapSegmentReserve = 2 * _1MB;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (MmHeapSegmentCommit == 0)
|
|
|
|
{
|
|
|
|
MmHeapSegmentCommit = 2 * PAGE_SIZE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (MmHeapDeCommitTotalFreeThreshold == 0)
|
|
|
|
{
|
|
|
|
MmHeapDeCommitTotalFreeThreshold = 64 * _1KB;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (MmHeapDeCommitFreeBlockThreshold == 0)
|
|
|
|
{
|
|
|
|
MmHeapDeCommitFreeBlockThreshold = PAGE_SIZE;
|
|
|
|
}
|
|
|
|
|
2010-07-22 18:26:04 +00:00
|
|
|
/* Initialize the working set lock */
|
2011-04-08 12:30:33 +00:00
|
|
|
ExInitializePushLock(&MmSystemCacheWs.WorkingSetMutex);
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-07-22 18:26:04 +00:00
|
|
|
/* Set commit limit */
|
2018-08-16 16:40:23 +00:00
|
|
|
MmTotalCommitLimit = (2 * _1GB) >> PAGE_SHIFT;
|
2010-07-22 18:26:04 +00:00
|
|
|
MmTotalCommitLimitMaximum = MmTotalCommitLimit;
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-07-22 18:26:04 +00:00
|
|
|
/* Has the allocation fragment been setup? */
|
|
|
|
if (!MmAllocationFragment)
|
|
|
|
{
|
|
|
|
/* Use the default value */
|
|
|
|
MmAllocationFragment = MI_ALLOCATION_FRAGMENT;
|
|
|
|
if (PageCount < ((256 * _1MB) / PAGE_SIZE))
|
|
|
|
{
|
|
|
|
/* On memory systems with less than 256MB, divide by 4 */
|
|
|
|
MmAllocationFragment = MI_ALLOCATION_FRAGMENT / 4;
|
|
|
|
}
|
|
|
|
else if (PageCount < (_1GB / PAGE_SIZE))
|
|
|
|
{
|
|
|
|
/* On systems with less than 1GB, divide by 2 */
|
|
|
|
MmAllocationFragment = MI_ALLOCATION_FRAGMENT / 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Convert from 1KB fragments to pages */
|
|
|
|
MmAllocationFragment *= _1KB;
|
|
|
|
MmAllocationFragment = ROUND_TO_PAGES(MmAllocationFragment);
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-07-22 18:26:04 +00:00
|
|
|
/* Don't let it past the maximum */
|
|
|
|
MmAllocationFragment = min(MmAllocationFragment,
|
|
|
|
MI_MAX_ALLOCATION_FRAGMENT);
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-07-22 18:26:04 +00:00
|
|
|
/* Don't let it too small either */
|
|
|
|
MmAllocationFragment = max(MmAllocationFragment,
|
|
|
|
MI_MIN_ALLOCATION_FRAGMENT);
|
|
|
|
}
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2011-09-23 22:24:11 +00:00
|
|
|
/* Check for kernel stack size that's too big */
|
|
|
|
if (MmLargeStackSize > (KERNEL_LARGE_STACK_SIZE / _1KB))
|
|
|
|
{
|
|
|
|
/* Sanitize to default value */
|
|
|
|
MmLargeStackSize = KERNEL_LARGE_STACK_SIZE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Take the registry setting, and convert it into bytes */
|
|
|
|
MmLargeStackSize *= _1KB;
|
|
|
|
|
|
|
|
/* Now align it to a page boundary */
|
|
|
|
MmLargeStackSize = PAGE_ROUND_UP(MmLargeStackSize);
|
|
|
|
|
|
|
|
/* Sanity checks */
|
|
|
|
ASSERT(MmLargeStackSize <= KERNEL_LARGE_STACK_SIZE);
|
|
|
|
ASSERT((MmLargeStackSize & (PAGE_SIZE - 1)) == 0);
|
|
|
|
|
|
|
|
/* Make sure it's not too low */
|
|
|
|
if (MmLargeStackSize < KERNEL_STACK_SIZE) MmLargeStackSize = KERNEL_STACK_SIZE;
|
|
|
|
}
|
|
|
|
|
2011-09-24 14:22:13 +00:00
|
|
|
/* Compute color information (L2 cache-separated paging lists) */
|
|
|
|
MiComputeColorInformation();
|
|
|
|
|
|
|
|
// Calculate the number of bytes for the PFN database
|
|
|
|
// then add the color tables and convert to pages
|
|
|
|
MxPfnAllocation = (MmHighestPhysicalPage + 1) * sizeof(MMPFN);
|
|
|
|
MxPfnAllocation += (MmSecondaryColors * sizeof(MMCOLOR_TABLES) * 2);
|
|
|
|
MxPfnAllocation >>= PAGE_SHIFT;
|
|
|
|
|
|
|
|
// We have to add one to the count here, because in the process of
|
|
|
|
// shifting down to the page size, we actually ended up getting the
|
|
|
|
// lower aligned size (so say, 0x5FFFF bytes is now 0x5F pages).
|
|
|
|
// Later on, we'll shift this number back into bytes, which would cause
|
|
|
|
// us to end up with only 0x5F000 bytes -- when we actually want to have
|
|
|
|
// 0x60000 bytes.
|
|
|
|
MxPfnAllocation++;
|
|
|
|
|
2010-12-26 15:23:03 +00:00
|
|
|
/* Initialize the platform-specific parts */
|
2010-02-10 02:00:56 +00:00
|
|
|
MiInitMachineDependent(LoaderBlock);
|
2010-10-18 14:29:05 +00:00
|
|
|
|
2020-03-08 19:05:02 +00:00
|
|
|
#if DBG
|
|
|
|
/* Prototype PTEs are assumed to be in paged pool, so check if the math works */
|
|
|
|
PointerPte = (PMMPTE)MmPagedPoolStart;
|
|
|
|
MI_MAKE_PROTOTYPE_PTE(&TempPte, PointerPte);
|
|
|
|
TestPte = MiProtoPteToPte(&TempPte);
|
|
|
|
ASSERT(PointerPte == TestPte);
|
|
|
|
|
|
|
|
/* Try the last nonpaged pool address */
|
|
|
|
PointerPte = (PMMPTE)MI_NONPAGED_POOL_END;
|
|
|
|
MI_MAKE_PROTOTYPE_PTE(&TempPte, PointerPte);
|
|
|
|
TestPte = MiProtoPteToPte(&TempPte);
|
|
|
|
ASSERT(PointerPte == TestPte);
|
|
|
|
|
|
|
|
/* Try a bunch of random addresses near the end of the address space */
|
|
|
|
PointerPte = (PMMPTE)((ULONG_PTR)MI_HIGHEST_SYSTEM_ADDRESS - 0x37FFF);
|
|
|
|
for (j = 0; j < 20; j += 1)
|
|
|
|
{
|
|
|
|
MI_MAKE_PROTOTYPE_PTE(&TempPte, PointerPte);
|
|
|
|
TestPte = MiProtoPteToPte(&TempPte);
|
|
|
|
ASSERT(PointerPte == TestPte);
|
|
|
|
PointerPte++;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Subsection PTEs are always in nonpaged pool, pick a random address to try */
|
|
|
|
PointerPte = (PMMPTE)((ULONG_PTR)MmNonPagedPoolStart + (MmSizeOfNonPagedPoolInBytes / 2));
|
|
|
|
MI_MAKE_SUBSECTION_PTE(&TempPte, PointerPte);
|
|
|
|
TestPte = MiSubsectionPteToSubsection(&TempPte);
|
|
|
|
ASSERT(PointerPte == TestPte);
|
|
|
|
#endif
|
|
|
|
|
2010-02-10 02:00:56 +00:00
|
|
|
//
|
|
|
|
// Build the physical memory block
|
|
|
|
//
|
|
|
|
MmPhysicalMemoryBlock = MmInitializeMemoryLimits(LoaderBlock,
|
|
|
|
IncludeType);
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-02-10 02:00:56 +00:00
|
|
|
//
|
|
|
|
// Allocate enough buffer for the PFN bitmap
|
|
|
|
// Align it up to a 32-bit boundary
|
|
|
|
//
|
|
|
|
Bitmap = ExAllocatePoolWithTag(NonPagedPool,
|
|
|
|
(((MmHighestPhysicalPage + 1) + 31) / 32) * 4,
|
2016-01-05 19:53:07 +00:00
|
|
|
TAG_MM);
|
2010-02-10 02:00:56 +00:00
|
|
|
if (!Bitmap)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// This is critical
|
|
|
|
//
|
|
|
|
KeBugCheckEx(INSTALL_MORE_MEMORY,
|
|
|
|
MmNumberOfPhysicalPages,
|
|
|
|
MmLowestPhysicalPage,
|
|
|
|
MmHighestPhysicalPage,
|
|
|
|
0x101);
|
|
|
|
}
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-02-10 02:00:56 +00:00
|
|
|
//
|
|
|
|
// Initialize it and clear all the bits to begin with
|
|
|
|
//
|
|
|
|
RtlInitializeBitMap(&MiPfnBitMap,
|
|
|
|
Bitmap,
|
[HAL/NDK]
- Make Vector parameter in HalEnableSystemInterrupt, HalDisableSystemInterrupt and HalBeginSystemInterrupt an ULONG, not an UCHAR
[NDK]
- 64bit fixes for HANDLE_TABLE, KPROCESS, SECTION_IMAGE_INFORMATION, MMADDRESS_LIST, MMVAD_FLAGS, MMVAD, MMVAD_LONG, MMVAD_SHORT, MEMORY_DESCRIPTOR, MEMORY_ALLOCATION_DESCRIPTOR, LdrVerifyMappedImageMatchesChecksum
- KDPC_DATA::DpcQueueDepth is signed on amd64, unsigned on x86
[NTOSKRNL]
- Fix hundreds of MSVC and amd64 warnings
- add a pragma message to FstubFixupEfiPartition, since it looks broken
- Move portable Ke constants from <arch>/cpu.c to krnlinit.c
- Fixed a bug in amd64 KiGeneralProtectionFaultHandler
svn path=/trunk/; revision=53734
2011-09-18 13:11:45 +00:00
|
|
|
(ULONG)MmHighestPhysicalPage + 1);
|
2010-02-10 02:00:56 +00:00
|
|
|
RtlClearAllBits(&MiPfnBitMap);
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-02-10 02:00:56 +00:00
|
|
|
//
|
|
|
|
// Loop physical memory runs
|
|
|
|
//
|
|
|
|
for (i = 0; i < MmPhysicalMemoryBlock->NumberOfRuns; i++)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Get the run
|
|
|
|
//
|
|
|
|
Run = &MmPhysicalMemoryBlock->Run[i];
|
|
|
|
DPRINT("PHYSICAL RAM [0x%08p to 0x%08p]\n",
|
|
|
|
Run->BasePage << PAGE_SHIFT,
|
|
|
|
(Run->BasePage + Run->PageCount) << PAGE_SHIFT);
|
|
|
|
|
|
|
|
//
|
|
|
|
// Make sure it has pages inside it
|
|
|
|
//
|
|
|
|
if (Run->PageCount)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Set the bits in the PFN bitmap
|
|
|
|
//
|
[HAL/NDK]
- Make Vector parameter in HalEnableSystemInterrupt, HalDisableSystemInterrupt and HalBeginSystemInterrupt an ULONG, not an UCHAR
[NDK]
- 64bit fixes for HANDLE_TABLE, KPROCESS, SECTION_IMAGE_INFORMATION, MMADDRESS_LIST, MMVAD_FLAGS, MMVAD, MMVAD_LONG, MMVAD_SHORT, MEMORY_DESCRIPTOR, MEMORY_ALLOCATION_DESCRIPTOR, LdrVerifyMappedImageMatchesChecksum
- KDPC_DATA::DpcQueueDepth is signed on amd64, unsigned on x86
[NTOSKRNL]
- Fix hundreds of MSVC and amd64 warnings
- add a pragma message to FstubFixupEfiPartition, since it looks broken
- Move portable Ke constants from <arch>/cpu.c to krnlinit.c
- Fixed a bug in amd64 KiGeneralProtectionFaultHandler
svn path=/trunk/; revision=53734
2011-09-18 13:11:45 +00:00
|
|
|
RtlSetBits(&MiPfnBitMap, (ULONG)Run->BasePage, (ULONG)Run->PageCount);
|
2010-02-10 02:00:56 +00:00
|
|
|
}
|
|
|
|
}
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-04-20 22:47:51 +00:00
|
|
|
/* Look for large page cache entries that need caching */
|
|
|
|
MiSyncCachedRanges();
|
|
|
|
|
|
|
|
/* Loop for HAL Heap I/O device mappings that need coherency tracking */
|
|
|
|
MiAddHalIoMappings();
|
|
|
|
|
|
|
|
/* Set the initial resident page count */
|
|
|
|
MmResidentAvailablePages = MmAvailablePages - 32;
|
|
|
|
|
|
|
|
/* Initialize large page structures on PAE/x64, and MmProcessList on x86 */
|
|
|
|
MiInitializeLargePageSupport();
|
|
|
|
|
|
|
|
/* Check if the registry says any drivers should be loaded with large pages */
|
|
|
|
MiInitializeDriverLargePageList();
|
|
|
|
|
|
|
|
/* Relocate the boot drivers into system PTE space and fixup their PFNs */
|
|
|
|
MiReloadBootLoadedDrivers(LoaderBlock);
|
|
|
|
|
|
|
|
/* FIXME: Call out into Driver Verifier for initialization */
|
|
|
|
|
[NTOS]: Make MM init read MmProductType to determine what SKU of ReactOS this is, instead of assuming Server. If you want to go back to the old behavior, you need to change "WinNT" to "ServerNT" in the hivesys under Product Type.
[NTOS]: Configure the MmSystemSize variable properly based on SKU and RAM. Previously, ReactOS told all drivers and applications you were running on a system with < 13MB RAM.
[NTOS]: Initialize thresholds for low and high memory (in pages), low and high paged pool memory, and low and high nonpaged pool memory. These are described in the source.
[NTOS]: Initialize events for each of those thresholds, and populate the \KernelObject\xxxCondition events that are documented in MSDN for driver and app developers.
[NTOS]: Define some internal thresholds to use later, representing the minimum number of free pages under we go berserk, and the minimum number of free pages that we consider "plenty".
[NTOS]: Rename MiRemoveFromList to MiUnlinkFreeOrZeroedPage (Windows name). Make the function handle MmAvailablePages decrement, instead of having the caller do it.
[NTOS]: Remove run-time initialization of the PFN lists, just initialize them statically (also fixes the fact we forgot to initialize their names).
[NTOS]: Move some more initialization code to ARM3 instead of mm.
[NTOS]: Read ProductType from registry into MmProductType instead of dummy value. Remove duplicate "Mirroring" variable read.
svn path=/trunk/; revision=45638
2010-02-20 21:48:36 +00:00
|
|
|
/* Check how many pages the system has */
|
2010-07-22 18:26:04 +00:00
|
|
|
if (MmNumberOfPhysicalPages <= ((13 * _1MB) / PAGE_SIZE))
|
[NTOS]: Make MM init read MmProductType to determine what SKU of ReactOS this is, instead of assuming Server. If you want to go back to the old behavior, you need to change "WinNT" to "ServerNT" in the hivesys under Product Type.
[NTOS]: Configure the MmSystemSize variable properly based on SKU and RAM. Previously, ReactOS told all drivers and applications you were running on a system with < 13MB RAM.
[NTOS]: Initialize thresholds for low and high memory (in pages), low and high paged pool memory, and low and high nonpaged pool memory. These are described in the source.
[NTOS]: Initialize events for each of those thresholds, and populate the \KernelObject\xxxCondition events that are documented in MSDN for driver and app developers.
[NTOS]: Define some internal thresholds to use later, representing the minimum number of free pages under we go berserk, and the minimum number of free pages that we consider "plenty".
[NTOS]: Rename MiRemoveFromList to MiUnlinkFreeOrZeroedPage (Windows name). Make the function handle MmAvailablePages decrement, instead of having the caller do it.
[NTOS]: Remove run-time initialization of the PFN lists, just initialize them statically (also fixes the fact we forgot to initialize their names).
[NTOS]: Move some more initialization code to ARM3 instead of mm.
[NTOS]: Read ProductType from registry into MmProductType instead of dummy value. Remove duplicate "Mirroring" variable read.
svn path=/trunk/; revision=45638
2010-02-20 21:48:36 +00:00
|
|
|
{
|
|
|
|
/* Set small system */
|
|
|
|
MmSystemSize = MmSmallSystem;
|
2012-03-04 17:56:00 +00:00
|
|
|
MmMaximumDeadKernelStacks = 0;
|
[NTOS]: Make MM init read MmProductType to determine what SKU of ReactOS this is, instead of assuming Server. If you want to go back to the old behavior, you need to change "WinNT" to "ServerNT" in the hivesys under Product Type.
[NTOS]: Configure the MmSystemSize variable properly based on SKU and RAM. Previously, ReactOS told all drivers and applications you were running on a system with < 13MB RAM.
[NTOS]: Initialize thresholds for low and high memory (in pages), low and high paged pool memory, and low and high nonpaged pool memory. These are described in the source.
[NTOS]: Initialize events for each of those thresholds, and populate the \KernelObject\xxxCondition events that are documented in MSDN for driver and app developers.
[NTOS]: Define some internal thresholds to use later, representing the minimum number of free pages under we go berserk, and the minimum number of free pages that we consider "plenty".
[NTOS]: Rename MiRemoveFromList to MiUnlinkFreeOrZeroedPage (Windows name). Make the function handle MmAvailablePages decrement, instead of having the caller do it.
[NTOS]: Remove run-time initialization of the PFN lists, just initialize them statically (also fixes the fact we forgot to initialize their names).
[NTOS]: Move some more initialization code to ARM3 instead of mm.
[NTOS]: Read ProductType from registry into MmProductType instead of dummy value. Remove duplicate "Mirroring" variable read.
svn path=/trunk/; revision=45638
2010-02-20 21:48:36 +00:00
|
|
|
}
|
2010-07-22 18:26:04 +00:00
|
|
|
else if (MmNumberOfPhysicalPages <= ((19 * _1MB) / PAGE_SIZE))
|
[NTOS]: Make MM init read MmProductType to determine what SKU of ReactOS this is, instead of assuming Server. If you want to go back to the old behavior, you need to change "WinNT" to "ServerNT" in the hivesys under Product Type.
[NTOS]: Configure the MmSystemSize variable properly based on SKU and RAM. Previously, ReactOS told all drivers and applications you were running on a system with < 13MB RAM.
[NTOS]: Initialize thresholds for low and high memory (in pages), low and high paged pool memory, and low and high nonpaged pool memory. These are described in the source.
[NTOS]: Initialize events for each of those thresholds, and populate the \KernelObject\xxxCondition events that are documented in MSDN for driver and app developers.
[NTOS]: Define some internal thresholds to use later, representing the minimum number of free pages under we go berserk, and the minimum number of free pages that we consider "plenty".
[NTOS]: Rename MiRemoveFromList to MiUnlinkFreeOrZeroedPage (Windows name). Make the function handle MmAvailablePages decrement, instead of having the caller do it.
[NTOS]: Remove run-time initialization of the PFN lists, just initialize them statically (also fixes the fact we forgot to initialize their names).
[NTOS]: Move some more initialization code to ARM3 instead of mm.
[NTOS]: Read ProductType from registry into MmProductType instead of dummy value. Remove duplicate "Mirroring" variable read.
svn path=/trunk/; revision=45638
2010-02-20 21:48:36 +00:00
|
|
|
{
|
2010-04-20 22:47:51 +00:00
|
|
|
/* Set small system and add 100 pages for the cache */
|
[NTOS]: Make MM init read MmProductType to determine what SKU of ReactOS this is, instead of assuming Server. If you want to go back to the old behavior, you need to change "WinNT" to "ServerNT" in the hivesys under Product Type.
[NTOS]: Configure the MmSystemSize variable properly based on SKU and RAM. Previously, ReactOS told all drivers and applications you were running on a system with < 13MB RAM.
[NTOS]: Initialize thresholds for low and high memory (in pages), low and high paged pool memory, and low and high nonpaged pool memory. These are described in the source.
[NTOS]: Initialize events for each of those thresholds, and populate the \KernelObject\xxxCondition events that are documented in MSDN for driver and app developers.
[NTOS]: Define some internal thresholds to use later, representing the minimum number of free pages under we go berserk, and the minimum number of free pages that we consider "plenty".
[NTOS]: Rename MiRemoveFromList to MiUnlinkFreeOrZeroedPage (Windows name). Make the function handle MmAvailablePages decrement, instead of having the caller do it.
[NTOS]: Remove run-time initialization of the PFN lists, just initialize them statically (also fixes the fact we forgot to initialize their names).
[NTOS]: Move some more initialization code to ARM3 instead of mm.
[NTOS]: Read ProductType from registry into MmProductType instead of dummy value. Remove duplicate "Mirroring" variable read.
svn path=/trunk/; revision=45638
2010-02-20 21:48:36 +00:00
|
|
|
MmSystemSize = MmSmallSystem;
|
2010-04-20 22:47:51 +00:00
|
|
|
MmSystemCacheWsMinimum += 100;
|
2012-03-04 17:56:00 +00:00
|
|
|
MmMaximumDeadKernelStacks = 2;
|
[NTOS]: Make MM init read MmProductType to determine what SKU of ReactOS this is, instead of assuming Server. If you want to go back to the old behavior, you need to change "WinNT" to "ServerNT" in the hivesys under Product Type.
[NTOS]: Configure the MmSystemSize variable properly based on SKU and RAM. Previously, ReactOS told all drivers and applications you were running on a system with < 13MB RAM.
[NTOS]: Initialize thresholds for low and high memory (in pages), low and high paged pool memory, and low and high nonpaged pool memory. These are described in the source.
[NTOS]: Initialize events for each of those thresholds, and populate the \KernelObject\xxxCondition events that are documented in MSDN for driver and app developers.
[NTOS]: Define some internal thresholds to use later, representing the minimum number of free pages under we go berserk, and the minimum number of free pages that we consider "plenty".
[NTOS]: Rename MiRemoveFromList to MiUnlinkFreeOrZeroedPage (Windows name). Make the function handle MmAvailablePages decrement, instead of having the caller do it.
[NTOS]: Remove run-time initialization of the PFN lists, just initialize them statically (also fixes the fact we forgot to initialize their names).
[NTOS]: Move some more initialization code to ARM3 instead of mm.
[NTOS]: Read ProductType from registry into MmProductType instead of dummy value. Remove duplicate "Mirroring" variable read.
svn path=/trunk/; revision=45638
2010-02-20 21:48:36 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-04-20 22:47:51 +00:00
|
|
|
/* Set medium system and add 400 pages for the cache */
|
[NTOS]: Make MM init read MmProductType to determine what SKU of ReactOS this is, instead of assuming Server. If you want to go back to the old behavior, you need to change "WinNT" to "ServerNT" in the hivesys under Product Type.
[NTOS]: Configure the MmSystemSize variable properly based on SKU and RAM. Previously, ReactOS told all drivers and applications you were running on a system with < 13MB RAM.
[NTOS]: Initialize thresholds for low and high memory (in pages), low and high paged pool memory, and low and high nonpaged pool memory. These are described in the source.
[NTOS]: Initialize events for each of those thresholds, and populate the \KernelObject\xxxCondition events that are documented in MSDN for driver and app developers.
[NTOS]: Define some internal thresholds to use later, representing the minimum number of free pages under we go berserk, and the minimum number of free pages that we consider "plenty".
[NTOS]: Rename MiRemoveFromList to MiUnlinkFreeOrZeroedPage (Windows name). Make the function handle MmAvailablePages decrement, instead of having the caller do it.
[NTOS]: Remove run-time initialization of the PFN lists, just initialize them statically (also fixes the fact we forgot to initialize their names).
[NTOS]: Move some more initialization code to ARM3 instead of mm.
[NTOS]: Read ProductType from registry into MmProductType instead of dummy value. Remove duplicate "Mirroring" variable read.
svn path=/trunk/; revision=45638
2010-02-20 21:48:36 +00:00
|
|
|
MmSystemSize = MmMediumSystem;
|
2010-04-20 22:47:51 +00:00
|
|
|
MmSystemCacheWsMinimum += 400;
|
2012-03-04 17:56:00 +00:00
|
|
|
MmMaximumDeadKernelStacks = 5;
|
2010-04-20 22:47:51 +00:00
|
|
|
}
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-04-20 22:47:51 +00:00
|
|
|
/* Check for less than 24MB */
|
|
|
|
if (MmNumberOfPhysicalPages < ((24 * _1MB) / PAGE_SIZE))
|
|
|
|
{
|
|
|
|
/* No more than 32 pages */
|
|
|
|
MmSystemCacheWsMinimum = 32;
|
[NTOS]: Make MM init read MmProductType to determine what SKU of ReactOS this is, instead of assuming Server. If you want to go back to the old behavior, you need to change "WinNT" to "ServerNT" in the hivesys under Product Type.
[NTOS]: Configure the MmSystemSize variable properly based on SKU and RAM. Previously, ReactOS told all drivers and applications you were running on a system with < 13MB RAM.
[NTOS]: Initialize thresholds for low and high memory (in pages), low and high paged pool memory, and low and high nonpaged pool memory. These are described in the source.
[NTOS]: Initialize events for each of those thresholds, and populate the \KernelObject\xxxCondition events that are documented in MSDN for driver and app developers.
[NTOS]: Define some internal thresholds to use later, representing the minimum number of free pages under we go berserk, and the minimum number of free pages that we consider "plenty".
[NTOS]: Rename MiRemoveFromList to MiUnlinkFreeOrZeroedPage (Windows name). Make the function handle MmAvailablePages decrement, instead of having the caller do it.
[NTOS]: Remove run-time initialization of the PFN lists, just initialize them statically (also fixes the fact we forgot to initialize their names).
[NTOS]: Move some more initialization code to ARM3 instead of mm.
[NTOS]: Read ProductType from registry into MmProductType instead of dummy value. Remove duplicate "Mirroring" variable read.
svn path=/trunk/; revision=45638
2010-02-20 21:48:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Check for more than 32MB */
|
|
|
|
if (MmNumberOfPhysicalPages >= ((32 * _1MB) / PAGE_SIZE))
|
|
|
|
{
|
|
|
|
/* Check for product type being "Wi" for WinNT */
|
|
|
|
if (MmProductType == '\0i\0W')
|
|
|
|
{
|
|
|
|
/* Then this is a large system */
|
|
|
|
MmSystemSize = MmLargeSystem;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* For servers, we need 64MB to consider this as being large */
|
|
|
|
if (MmNumberOfPhysicalPages >= ((64 * _1MB) / PAGE_SIZE))
|
|
|
|
{
|
|
|
|
/* Set it as large */
|
|
|
|
MmSystemSize = MmLargeSystem;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-04-20 22:47:51 +00:00
|
|
|
/* Check for more than 33 MB */
|
|
|
|
if (MmNumberOfPhysicalPages > ((33 * _1MB) / PAGE_SIZE))
|
|
|
|
{
|
|
|
|
/* Add another 500 pages to the cache */
|
|
|
|
MmSystemCacheWsMinimum += 500;
|
|
|
|
}
|
2010-12-26 15:23:03 +00:00
|
|
|
|
[NTOS]: Make MM init read MmProductType to determine what SKU of ReactOS this is, instead of assuming Server. If you want to go back to the old behavior, you need to change "WinNT" to "ServerNT" in the hivesys under Product Type.
[NTOS]: Configure the MmSystemSize variable properly based on SKU and RAM. Previously, ReactOS told all drivers and applications you were running on a system with < 13MB RAM.
[NTOS]: Initialize thresholds for low and high memory (in pages), low and high paged pool memory, and low and high nonpaged pool memory. These are described in the source.
[NTOS]: Initialize events for each of those thresholds, and populate the \KernelObject\xxxCondition events that are documented in MSDN for driver and app developers.
[NTOS]: Define some internal thresholds to use later, representing the minimum number of free pages under we go berserk, and the minimum number of free pages that we consider "plenty".
[NTOS]: Rename MiRemoveFromList to MiUnlinkFreeOrZeroedPage (Windows name). Make the function handle MmAvailablePages decrement, instead of having the caller do it.
[NTOS]: Remove run-time initialization of the PFN lists, just initialize them statically (also fixes the fact we forgot to initialize their names).
[NTOS]: Move some more initialization code to ARM3 instead of mm.
[NTOS]: Read ProductType from registry into MmProductType instead of dummy value. Remove duplicate "Mirroring" variable read.
svn path=/trunk/; revision=45638
2010-02-20 21:48:36 +00:00
|
|
|
/* Now setup the shared user data fields */
|
|
|
|
ASSERT(SharedUserData->NumberOfPhysicalPages == 0);
|
|
|
|
SharedUserData->NumberOfPhysicalPages = MmNumberOfPhysicalPages;
|
|
|
|
SharedUserData->LargePageMinimum = 0;
|
|
|
|
|
|
|
|
/* Check for workstation (Wi for WinNT) */
|
|
|
|
if (MmProductType == '\0i\0W')
|
|
|
|
{
|
|
|
|
/* Set Windows NT Workstation product type */
|
|
|
|
SharedUserData->NtProductType = NtProductWinNt;
|
|
|
|
MmProductType = 0;
|
2018-02-09 13:21:14 +00:00
|
|
|
|
|
|
|
/* For this product, we wait till the last moment to throttle */
|
|
|
|
MmThrottleTop = 250;
|
|
|
|
MmThrottleBottom = 30;
|
[NTOS]: Make MM init read MmProductType to determine what SKU of ReactOS this is, instead of assuming Server. If you want to go back to the old behavior, you need to change "WinNT" to "ServerNT" in the hivesys under Product Type.
[NTOS]: Configure the MmSystemSize variable properly based on SKU and RAM. Previously, ReactOS told all drivers and applications you were running on a system with < 13MB RAM.
[NTOS]: Initialize thresholds for low and high memory (in pages), low and high paged pool memory, and low and high nonpaged pool memory. These are described in the source.
[NTOS]: Initialize events for each of those thresholds, and populate the \KernelObject\xxxCondition events that are documented in MSDN for driver and app developers.
[NTOS]: Define some internal thresholds to use later, representing the minimum number of free pages under we go berserk, and the minimum number of free pages that we consider "plenty".
[NTOS]: Rename MiRemoveFromList to MiUnlinkFreeOrZeroedPage (Windows name). Make the function handle MmAvailablePages decrement, instead of having the caller do it.
[NTOS]: Remove run-time initialization of the PFN lists, just initialize them statically (also fixes the fact we forgot to initialize their names).
[NTOS]: Move some more initialization code to ARM3 instead of mm.
[NTOS]: Read ProductType from registry into MmProductType instead of dummy value. Remove duplicate "Mirroring" variable read.
svn path=/trunk/; revision=45638
2010-02-20 21:48:36 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-09-20 19:53:14 +00:00
|
|
|
/* Check for LanMan server (La for LanmanNT) */
|
[NTOS]: Make MM init read MmProductType to determine what SKU of ReactOS this is, instead of assuming Server. If you want to go back to the old behavior, you need to change "WinNT" to "ServerNT" in the hivesys under Product Type.
[NTOS]: Configure the MmSystemSize variable properly based on SKU and RAM. Previously, ReactOS told all drivers and applications you were running on a system with < 13MB RAM.
[NTOS]: Initialize thresholds for low and high memory (in pages), low and high paged pool memory, and low and high nonpaged pool memory. These are described in the source.
[NTOS]: Initialize events for each of those thresholds, and populate the \KernelObject\xxxCondition events that are documented in MSDN for driver and app developers.
[NTOS]: Define some internal thresholds to use later, representing the minimum number of free pages under we go berserk, and the minimum number of free pages that we consider "plenty".
[NTOS]: Rename MiRemoveFromList to MiUnlinkFreeOrZeroedPage (Windows name). Make the function handle MmAvailablePages decrement, instead of having the caller do it.
[NTOS]: Remove run-time initialization of the PFN lists, just initialize them statically (also fixes the fact we forgot to initialize their names).
[NTOS]: Move some more initialization code to ARM3 instead of mm.
[NTOS]: Read ProductType from registry into MmProductType instead of dummy value. Remove duplicate "Mirroring" variable read.
svn path=/trunk/; revision=45638
2010-02-20 21:48:36 +00:00
|
|
|
if (MmProductType == '\0a\0L')
|
|
|
|
{
|
|
|
|
/* This is a domain controller */
|
|
|
|
SharedUserData->NtProductType = NtProductLanManNt;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-09-20 19:53:14 +00:00
|
|
|
/* Otherwise it must be a normal server (Se for ServerNT) */
|
[NTOS]: Make MM init read MmProductType to determine what SKU of ReactOS this is, instead of assuming Server. If you want to go back to the old behavior, you need to change "WinNT" to "ServerNT" in the hivesys under Product Type.
[NTOS]: Configure the MmSystemSize variable properly based on SKU and RAM. Previously, ReactOS told all drivers and applications you were running on a system with < 13MB RAM.
[NTOS]: Initialize thresholds for low and high memory (in pages), low and high paged pool memory, and low and high nonpaged pool memory. These are described in the source.
[NTOS]: Initialize events for each of those thresholds, and populate the \KernelObject\xxxCondition events that are documented in MSDN for driver and app developers.
[NTOS]: Define some internal thresholds to use later, representing the minimum number of free pages under we go berserk, and the minimum number of free pages that we consider "plenty".
[NTOS]: Rename MiRemoveFromList to MiUnlinkFreeOrZeroedPage (Windows name). Make the function handle MmAvailablePages decrement, instead of having the caller do it.
[NTOS]: Remove run-time initialization of the PFN lists, just initialize them statically (also fixes the fact we forgot to initialize their names).
[NTOS]: Move some more initialization code to ARM3 instead of mm.
[NTOS]: Read ProductType from registry into MmProductType instead of dummy value. Remove duplicate "Mirroring" variable read.
svn path=/trunk/; revision=45638
2010-02-20 21:48:36 +00:00
|
|
|
SharedUserData->NtProductType = NtProductServer;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Set the product type, and make the system more aggressive with low memory */
|
|
|
|
MmProductType = 1;
|
|
|
|
MmMinimumFreePages = 81;
|
2018-02-09 13:21:14 +00:00
|
|
|
|
|
|
|
/* We will throttle earlier to preserve memory */
|
|
|
|
MmThrottleTop = 450;
|
|
|
|
MmThrottleBottom = 80;
|
[NTOS]: Make MM init read MmProductType to determine what SKU of ReactOS this is, instead of assuming Server. If you want to go back to the old behavior, you need to change "WinNT" to "ServerNT" in the hivesys under Product Type.
[NTOS]: Configure the MmSystemSize variable properly based on SKU and RAM. Previously, ReactOS told all drivers and applications you were running on a system with < 13MB RAM.
[NTOS]: Initialize thresholds for low and high memory (in pages), low and high paged pool memory, and low and high nonpaged pool memory. These are described in the source.
[NTOS]: Initialize events for each of those thresholds, and populate the \KernelObject\xxxCondition events that are documented in MSDN for driver and app developers.
[NTOS]: Define some internal thresholds to use later, representing the minimum number of free pages under we go berserk, and the minimum number of free pages that we consider "plenty".
[NTOS]: Rename MiRemoveFromList to MiUnlinkFreeOrZeroedPage (Windows name). Make the function handle MmAvailablePages decrement, instead of having the caller do it.
[NTOS]: Remove run-time initialization of the PFN lists, just initialize them statically (also fixes the fact we forgot to initialize their names).
[NTOS]: Move some more initialization code to ARM3 instead of mm.
[NTOS]: Read ProductType from registry into MmProductType instead of dummy value. Remove duplicate "Mirroring" variable read.
svn path=/trunk/; revision=45638
2010-02-20 21:48:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Update working set tuning parameters */
|
|
|
|
MiAdjustWorkingSetManagerParameters(!MmProductType);
|
2010-04-20 22:47:51 +00:00
|
|
|
|
|
|
|
/* Finetune the page count by removing working set and NP expansion */
|
|
|
|
MmResidentAvailablePages -= MiExpansionPoolPagesInitialCharge;
|
|
|
|
MmResidentAvailablePages -= MmSystemCacheWsMinimum;
|
|
|
|
MmResidentAvailableAtInit = MmResidentAvailablePages;
|
|
|
|
if (MmResidentAvailablePages <= 0)
|
|
|
|
{
|
|
|
|
/* This should not happen */
|
|
|
|
DPRINT1("System cache working set too big\n");
|
|
|
|
return FALSE;
|
|
|
|
}
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2018-02-06 12:38:55 +00:00
|
|
|
/* Define limits for system cache */
|
|
|
|
#ifdef _M_AMD64
|
2019-06-21 12:04:01 +00:00
|
|
|
MmSizeOfSystemCacheInPages = ((MI_SYSTEM_CACHE_END + 1) - MI_SYSTEM_CACHE_START) / PAGE_SIZE;
|
2018-02-06 12:38:55 +00:00
|
|
|
#else
|
|
|
|
MmSizeOfSystemCacheInPages = ((ULONG_PTR)MI_PAGED_POOL_START - (ULONG_PTR)MI_SYSTEM_CACHE_START) / PAGE_SIZE;
|
|
|
|
#endif
|
|
|
|
MmSystemCacheEnd = (PVOID)((ULONG_PTR)MmSystemCacheStart + (MmSizeOfSystemCacheInPages * PAGE_SIZE) - 1);
|
2019-06-21 12:04:01 +00:00
|
|
|
#ifdef _M_AMD64
|
|
|
|
ASSERT(MmSystemCacheEnd == (PVOID)MI_SYSTEM_CACHE_END);
|
|
|
|
#else
|
|
|
|
ASSERT(MmSystemCacheEnd == (PVOID)((ULONG_PTR)MI_PAGED_POOL_START - 1));
|
|
|
|
#endif
|
2018-02-06 12:38:55 +00:00
|
|
|
|
2010-07-22 18:26:04 +00:00
|
|
|
/* Initialize the system cache */
|
|
|
|
//MiInitializeSystemCache(MmSystemCacheWsMinimum, MmAvailablePages);
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-07-22 18:26:04 +00:00
|
|
|
/* Update the commit limit */
|
|
|
|
MmTotalCommitLimit = MmAvailablePages;
|
|
|
|
if (MmTotalCommitLimit > 1024) MmTotalCommitLimit -= 1024;
|
|
|
|
MmTotalCommitLimitMaximum = MmTotalCommitLimit;
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-04-20 22:47:51 +00:00
|
|
|
/* Size up paged pool and build the shadow system page directory */
|
|
|
|
MiBuildPagedPool();
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-06-06 15:59:42 +00:00
|
|
|
/* Debugger physical memory support is now ready to be used */
|
2010-07-16 13:23:43 +00:00
|
|
|
MmDebugPte = MiAddressToPte(MiDebugMapping);
|
2010-06-06 15:59:42 +00:00
|
|
|
|
|
|
|
/* Initialize the loaded module list */
|
|
|
|
MiInitializeLoadedModuleList(LoaderBlock);
|
2010-02-10 02:00:56 +00:00
|
|
|
}
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-02-10 02:00:56 +00:00
|
|
|
//
|
|
|
|
// Always return success for now
|
|
|
|
//
|
2010-10-18 23:07:09 +00:00
|
|
|
return TRUE;
|
2010-02-10 02:00:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* EOF */
|