2010-02-20 14:40:21 +00:00
|
|
|
/*
|
|
|
|
* PROJECT: ReactOS Kernel
|
|
|
|
* LICENSE: BSD - See COPYING.ARM in the top level directory
|
|
|
|
* FILE: ntoskrnl/mm/ARM3/pfnlist.c
|
|
|
|
* PURPOSE: ARM Memory Manager PFN List Manipulation
|
|
|
|
* PROGRAMMERS: ReactOS Portable Systems Group
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* INCLUDES *******************************************************************/
|
|
|
|
|
|
|
|
#include <ntoskrnl.h>
|
|
|
|
#define NDEBUG
|
|
|
|
#include <debug.h>
|
|
|
|
|
|
|
|
#define MODULE_INVOLVED_IN_ARM3
|
2014-11-10 16:26:55 +00:00
|
|
|
#include <mm/ARM3/miarm.h>
|
2010-02-20 14:40:21 +00:00
|
|
|
|
2010-06-04 22:08:40 +00:00
|
|
|
#if DBG
|
2010-06-01 09:22:10 +00:00
|
|
|
#define ASSERT_LIST_INVARIANT(x) \
|
|
|
|
do { \
|
2011-12-25 18:21:05 +00:00
|
|
|
ASSERT(((x)->Total == 0 && \
|
2010-06-01 09:22:10 +00:00
|
|
|
(x)->Flink == LIST_HEAD && \
|
2011-12-25 18:21:05 +00:00
|
|
|
(x)->Blink == LIST_HEAD) || \
|
|
|
|
((x)->Total != 0 && \
|
|
|
|
(x)->Flink != LIST_HEAD && \
|
|
|
|
(x)->Blink != LIST_HEAD)); \
|
2010-06-01 09:22:10 +00:00
|
|
|
} while (0)
|
2010-06-04 22:08:40 +00:00
|
|
|
#else
|
|
|
|
#define ASSERT_LIST_INVARIANT(x)
|
|
|
|
#endif
|
2010-06-01 09:22:10 +00:00
|
|
|
|
2010-02-20 14:40:21 +00:00
|
|
|
/* GLOBALS ********************************************************************/
|
|
|
|
|
2010-04-20 22:47:51 +00:00
|
|
|
BOOLEAN MmDynamicPfn;
|
|
|
|
BOOLEAN MmMirroring;
|
2010-09-29 01:10:28 +00:00
|
|
|
ULONG MmSystemPageColor;
|
2010-04-20 22:47:51 +00:00
|
|
|
|
2012-03-26 07:26:36 +00:00
|
|
|
ULONG MmTransitionSharedPages;
|
|
|
|
ULONG MmTotalPagesForPagingFile;
|
|
|
|
|
[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
|
|
|
MMPFNLIST MmZeroedPageListHead = {0, ZeroedPageList, LIST_HEAD, LIST_HEAD};
|
|
|
|
MMPFNLIST MmFreePageListHead = {0, FreePageList, LIST_HEAD, LIST_HEAD};
|
|
|
|
MMPFNLIST MmStandbyPageListHead = {0, StandbyPageList, LIST_HEAD, LIST_HEAD};
|
2012-03-26 07:26:36 +00:00
|
|
|
MMPFNLIST MmStandbyPageListByPriority[8];
|
[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
|
|
|
MMPFNLIST MmModifiedPageListHead = {0, ModifiedPageList, LIST_HEAD, LIST_HEAD};
|
2012-03-26 07:26:36 +00:00
|
|
|
MMPFNLIST MmModifiedPageListByColor[1] = {{0, ModifiedPageList, LIST_HEAD, LIST_HEAD}};
|
[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
|
|
|
MMPFNLIST MmModifiedNoWritePageListHead = {0, ModifiedNoWritePageList, LIST_HEAD, LIST_HEAD};
|
|
|
|
MMPFNLIST MmBadPageListHead = {0, BadPageList, LIST_HEAD, LIST_HEAD};
|
|
|
|
MMPFNLIST MmRomPageListHead = {0, StandbyPageList, LIST_HEAD, LIST_HEAD};
|
2010-02-20 14:40:21 +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
|
|
|
PMMPFNLIST MmPageLocationList[] =
|
|
|
|
{
|
|
|
|
&MmZeroedPageListHead,
|
|
|
|
&MmFreePageListHead,
|
|
|
|
&MmStandbyPageListHead,
|
|
|
|
&MmModifiedPageListHead,
|
|
|
|
&MmModifiedNoWritePageListHead,
|
|
|
|
&MmBadPageListHead,
|
|
|
|
NULL,
|
|
|
|
NULL
|
|
|
|
};
|
2010-11-02 15:16:22 +00:00
|
|
|
|
|
|
|
ULONG MI_PFN_CURRENT_USAGE;
|
|
|
|
CHAR MI_PFN_CURRENT_PROCESS_NAME[16] = "None yet";
|
|
|
|
|
2010-02-20 14:40:21 +00:00
|
|
|
/* FUNCTIONS ******************************************************************/
|
2014-10-04 21:17:27 +00:00
|
|
|
static
|
|
|
|
VOID
|
|
|
|
MiIncrementAvailablePages(
|
|
|
|
VOID)
|
|
|
|
{
|
|
|
|
/* Increment available pages */
|
|
|
|
MmAvailablePages++;
|
|
|
|
|
|
|
|
/* Check if we've reached the configured low memory threshold */
|
|
|
|
if (MmAvailablePages == MmLowMemoryThreshold)
|
|
|
|
{
|
|
|
|
/* Clear the event, because now we're ABOVE the threshold */
|
|
|
|
KeClearEvent(MiLowMemoryEvent);
|
|
|
|
}
|
|
|
|
else if (MmAvailablePages == MmHighMemoryThreshold)
|
|
|
|
{
|
|
|
|
/* Otherwise check if we reached the high threshold and signal the event */
|
|
|
|
KeSetEvent(MiHighMemoryEvent, 0, FALSE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static
|
|
|
|
VOID
|
|
|
|
MiDecrementAvailablePages(
|
|
|
|
VOID)
|
|
|
|
{
|
|
|
|
ASSERT(MmAvailablePages > 0);
|
|
|
|
|
|
|
|
/* See if we hit any thresholds */
|
|
|
|
if (MmAvailablePages == MmHighMemoryThreshold)
|
|
|
|
{
|
|
|
|
/* Clear the high memory event */
|
|
|
|
KeClearEvent(MiHighMemoryEvent);
|
|
|
|
}
|
|
|
|
else if (MmAvailablePages == MmLowMemoryThreshold)
|
|
|
|
{
|
|
|
|
/* Signal the low memory event */
|
|
|
|
KeSetEvent(MiLowMemoryEvent, 0, FALSE);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* One less page */
|
|
|
|
MmAvailablePages--;
|
|
|
|
if (MmAvailablePages < MmMinimumFreePages)
|
|
|
|
{
|
|
|
|
/* FIXME: Should wake up the MPW and working set manager, if we had one */
|
|
|
|
|
|
|
|
DPRINT1("Running low on pages: %lu remaining\n", MmAvailablePages);
|
|
|
|
|
|
|
|
/* Call RosMm and see if it can release any pages for us */
|
|
|
|
MmRebalanceMemoryConsumers();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-06-06 14:12:28 +00:00
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
MiZeroPhysicalPage(IN PFN_NUMBER PageFrameIndex)
|
|
|
|
{
|
|
|
|
KIRQL OldIrql;
|
|
|
|
PVOID VirtualAddress;
|
|
|
|
PEPROCESS Process = PsGetCurrentProcess();
|
|
|
|
|
|
|
|
/* Map in hyperspace, then wipe it using XMMI or MEMSET */
|
|
|
|
VirtualAddress = MiMapPageInHyperSpace(Process, PageFrameIndex, &OldIrql);
|
2010-09-27 21:58:54 +00:00
|
|
|
ASSERT(VirtualAddress);
|
2010-06-06 14:12:28 +00:00
|
|
|
KeZeroPages(VirtualAddress, PAGE_SIZE);
|
|
|
|
MiUnmapPageInHyperSpace(Process, VirtualAddress, OldIrql);
|
|
|
|
}
|
|
|
|
|
2010-02-20 14:40:21 +00:00
|
|
|
VOID
|
|
|
|
NTAPI
|
[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
|
|
|
MiUnlinkFreeOrZeroedPage(IN PMMPFN Entry)
|
2010-02-20 14:40:21 +00:00
|
|
|
{
|
|
|
|
PFN_NUMBER OldFlink, OldBlink;
|
|
|
|
PMMPFNLIST ListHead;
|
[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
|
|
|
MMLISTS ListName;
|
2010-09-28 22:41:46 +00:00
|
|
|
ULONG Color;
|
|
|
|
PMMCOLOR_TABLES ColorTable;
|
|
|
|
PMMPFN Pfn1;
|
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
|
|
|
/* Make sure the PFN lock is held */
|
|
|
|
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
|
2010-06-01 09:22:10 +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
|
|
|
/* Make sure the PFN entry isn't in-use */
|
|
|
|
ASSERT(Entry->u3.e1.WriteInProgress == 0);
|
|
|
|
ASSERT(Entry->u3.e1.ReadInProgress == 0);
|
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
|
|
|
/* Find the list for this entry, make sure it's the free or zero list */
|
|
|
|
ListHead = MmPageLocationList[Entry->u3.e1.PageLocation];
|
|
|
|
ListName = ListHead->ListName;
|
|
|
|
ASSERT(ListHead != NULL);
|
|
|
|
ASSERT(ListName <= FreePageList);
|
2010-06-01 15:08:14 +00:00
|
|
|
ASSERT_LIST_INVARIANT(ListHead);
|
|
|
|
|
[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
|
|
|
/* Remove one count */
|
|
|
|
ASSERT(ListHead->Total != 0);
|
|
|
|
ListHead->Total--;
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-02-20 14:40:21 +00:00
|
|
|
/* Get the forward and back pointers */
|
|
|
|
OldFlink = Entry->u1.Flink;
|
|
|
|
OldBlink = Entry->u2.Blink;
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-02-20 14:40:21 +00:00
|
|
|
/* Check if the next entry is the list head */
|
|
|
|
if (OldFlink != LIST_HEAD)
|
|
|
|
{
|
|
|
|
/* It is not, so set the backlink of the actual entry, to our backlink */
|
2010-11-11 13:13:05 +00:00
|
|
|
MI_PFN_ELEMENT(OldFlink)->u2.Blink = OldBlink;
|
2010-02-20 14:40:21 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Set the list head's backlink instead */
|
2010-06-01 09:22:10 +00:00
|
|
|
ListHead->Blink = OldBlink;
|
2010-02-20 14:40:21 +00:00
|
|
|
}
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-02-20 14:40:21 +00:00
|
|
|
/* Check if the back entry is the list head */
|
|
|
|
if (OldBlink != LIST_HEAD)
|
|
|
|
{
|
|
|
|
/* It is not, so set the backlink of the actual entry, to our backlink */
|
2010-11-11 13:13:05 +00:00
|
|
|
MI_PFN_ELEMENT(OldBlink)->u1.Flink = OldFlink;
|
2010-02-20 14:40:21 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Set the list head's backlink instead */
|
|
|
|
ListHead->Flink = OldFlink;
|
|
|
|
}
|
2010-09-29 01:10:28 +00:00
|
|
|
|
2010-09-28 22:41:46 +00:00
|
|
|
/* Get the page color */
|
|
|
|
OldBlink = MiGetPfnEntryIndex(Entry);
|
|
|
|
Color = OldBlink & MmSecondaryColorMask;
|
|
|
|
|
|
|
|
/* Get the first page on the color list */
|
|
|
|
ColorTable = &MmFreePagesByColor[ListName][Color];
|
|
|
|
|
|
|
|
/* Check if this was was actually the head */
|
|
|
|
OldFlink = ColorTable->Flink;
|
|
|
|
if (OldFlink == OldBlink)
|
|
|
|
{
|
|
|
|
/* Make the table point to the next page this page was linking to */
|
|
|
|
ColorTable->Flink = Entry->OriginalPte.u.Long;
|
|
|
|
if (ColorTable->Flink != LIST_HEAD)
|
|
|
|
{
|
|
|
|
/* And make the previous link point to the head now */
|
2010-11-11 13:13:05 +00:00
|
|
|
MI_PFN_ELEMENT(ColorTable->Flink)->u4.PteFrame = COLORED_LIST_HEAD;
|
2010-09-28 22:41:46 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* And if that page was the head, loop the list back around */
|
|
|
|
ColorTable->Blink = (PVOID)LIST_HEAD;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* This page shouldn't be pointing back to the head */
|
2010-09-29 00:13:09 +00:00
|
|
|
ASSERT(Entry->u4.PteFrame != COLORED_LIST_HEAD);
|
2010-09-28 22:41:46 +00:00
|
|
|
|
|
|
|
/* Make the back link point to whoever the next page is */
|
2010-11-11 13:13:05 +00:00
|
|
|
Pfn1 = MI_PFN_ELEMENT(Entry->u4.PteFrame);
|
2010-09-28 22:41:46 +00:00
|
|
|
Pfn1->OriginalPte.u.Long = Entry->OriginalPte.u.Long;
|
|
|
|
|
|
|
|
/* Check if this page was pointing to the head */
|
|
|
|
if (Entry->OriginalPte.u.Long != LIST_HEAD)
|
|
|
|
{
|
|
|
|
/* Make the back link point to the head */
|
2010-11-11 13:13:05 +00:00
|
|
|
Pfn1 = MI_PFN_ELEMENT(Entry->OriginalPte.u.Long);
|
2010-09-29 00:13:09 +00:00
|
|
|
Pfn1->u4.PteFrame = Entry->u4.PteFrame;
|
2010-09-28 22:41:46 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Then the table is directly back pointing to this page now */
|
|
|
|
ColorTable->Blink = Pfn1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* One less colored page */
|
|
|
|
ASSERT(ColorTable->Count >= 1);
|
|
|
|
ColorTable->Count--;
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-09-29 00:13:09 +00:00
|
|
|
/* ReactOS Hack */
|
|
|
|
Entry->OriginalPte.u.Long = 0;
|
2010-09-29 01:10:28 +00:00
|
|
|
|
2010-02-20 14:40:21 +00:00
|
|
|
/* We are not on a list anymore */
|
|
|
|
Entry->u1.Flink = Entry->u2.Blink = 0;
|
2010-06-01 15:08:14 +00:00
|
|
|
ASSERT_LIST_INVARIANT(ListHead);
|
|
|
|
|
2014-10-04 21:17:27 +00:00
|
|
|
/* Decrement number of available pages */
|
|
|
|
MiDecrementAvailablePages();
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-11-02 15:16:22 +00:00
|
|
|
#if MI_TRACE_PFNS
|
|
|
|
ASSERT(MI_PFN_CURRENT_USAGE != MI_USAGE_NOT_SET);
|
|
|
|
Entry->PfnUsage = MI_PFN_CURRENT_USAGE;
|
|
|
|
memcpy(Entry->ProcessName, MI_PFN_CURRENT_PROCESS_NAME, 16);
|
|
|
|
// MI_PFN_CURRENT_USAGE = MI_USAGE_NOT_SET;
|
|
|
|
// memcpy(MI_PFN_CURRENT_PROCESS_NAME, "Not Set", 16);
|
|
|
|
#endif
|
2010-02-20 14:40:21 +00:00
|
|
|
}
|
|
|
|
|
2012-03-26 07:41:47 +00:00
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
MiUnlinkPageFromList(IN PMMPFN Pfn)
|
|
|
|
{
|
|
|
|
PMMPFNLIST ListHead;
|
|
|
|
PFN_NUMBER OldFlink, OldBlink;
|
|
|
|
|
|
|
|
/* Make sure the PFN lock is held */
|
|
|
|
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
|
|
|
|
|
|
|
|
/* ARM3 should only call this for dead pages */
|
|
|
|
ASSERT(Pfn->u3.e2.ReferenceCount == 0);
|
|
|
|
|
|
|
|
/* Transition pages are supposed to be standby/modified/nowrite */
|
|
|
|
ListHead = MmPageLocationList[Pfn->u3.e1.PageLocation];
|
|
|
|
ASSERT(ListHead->ListName >= StandbyPageList);
|
|
|
|
|
|
|
|
/* Check if this was standby, or modified */
|
|
|
|
if (ListHead == &MmStandbyPageListHead)
|
|
|
|
{
|
|
|
|
/* Should not be a ROM page */
|
|
|
|
ASSERT(Pfn->u3.e1.Rom == 0);
|
|
|
|
|
|
|
|
/* Get the exact list */
|
|
|
|
ListHead = &MmStandbyPageListByPriority[Pfn->u4.Priority];
|
|
|
|
|
2014-10-04 21:17:27 +00:00
|
|
|
/* Decrement number of available pages */
|
|
|
|
MiDecrementAvailablePages();
|
2012-03-26 07:41:47 +00:00
|
|
|
|
|
|
|
/* Decrease transition page counter */
|
|
|
|
ASSERT(Pfn->u3.e1.PrototypePte == 1); /* Only supported ARM3 case */
|
|
|
|
MmTransitionSharedPages--;
|
|
|
|
}
|
|
|
|
else if (ListHead == &MmModifiedPageListHead)
|
|
|
|
{
|
|
|
|
/* Only shared memory (page-file backed) modified pages are supported */
|
|
|
|
ASSERT(Pfn->OriginalPte.u.Soft.Prototype == 0);
|
|
|
|
|
|
|
|
/* Decrement the counters */
|
|
|
|
ListHead->Total--;
|
|
|
|
MmTotalPagesForPagingFile--;
|
|
|
|
|
|
|
|
/* Pick the correct colored list */
|
|
|
|
ListHead = &MmModifiedPageListByColor[0];
|
|
|
|
|
|
|
|
/* Decrease transition page counter */
|
|
|
|
MmTransitionSharedPages--;
|
|
|
|
}
|
|
|
|
else if (ListHead == &MmModifiedNoWritePageListHead)
|
|
|
|
{
|
|
|
|
/* List not yet supported */
|
|
|
|
ASSERT(FALSE);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Nothing should be in progress and the list should not be empty */
|
|
|
|
ASSERT(Pfn->u3.e1.WriteInProgress == 0);
|
|
|
|
ASSERT(Pfn->u3.e1.ReadInProgress == 0);
|
|
|
|
ASSERT(ListHead->Total != 0);
|
|
|
|
|
|
|
|
/* Get the forward and back pointers */
|
|
|
|
OldFlink = Pfn->u1.Flink;
|
|
|
|
OldBlink = Pfn->u2.Blink;
|
|
|
|
|
|
|
|
/* Check if the next entry is the list head */
|
|
|
|
if (OldFlink != LIST_HEAD)
|
|
|
|
{
|
|
|
|
/* It is not, so set the backlink of the actual entry, to our backlink */
|
|
|
|
MI_PFN_ELEMENT(OldFlink)->u2.Blink = OldBlink;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Set the list head's backlink instead */
|
|
|
|
ListHead->Blink = OldBlink;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check if the back entry is the list head */
|
|
|
|
if (OldBlink != LIST_HEAD)
|
|
|
|
{
|
|
|
|
/* It is not, so set the backlink of the actual entry, to our backlink */
|
|
|
|
MI_PFN_ELEMENT(OldBlink)->u1.Flink = OldFlink;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Set the list head's backlink instead */
|
|
|
|
ListHead->Flink = OldFlink;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ReactOS Hack */
|
|
|
|
Pfn->OriginalPte.u.Long = 0;
|
|
|
|
|
|
|
|
/* We are not on a list anymore */
|
|
|
|
Pfn->u1.Flink = Pfn->u2.Blink = 0;
|
|
|
|
|
|
|
|
/* Remove one entry from the list */
|
|
|
|
ListHead->Total--;
|
2014-08-06 21:53:57 +00:00
|
|
|
|
|
|
|
ASSERT_LIST_INVARIANT(ListHead);
|
2012-03-26 07:41:47 +00:00
|
|
|
}
|
|
|
|
|
2010-05-09 18:12:50 +00:00
|
|
|
PFN_NUMBER
|
|
|
|
NTAPI
|
|
|
|
MiRemovePageByColor(IN PFN_NUMBER PageIndex,
|
|
|
|
IN ULONG Color)
|
|
|
|
{
|
|
|
|
PMMPFN Pfn1;
|
|
|
|
PMMPFNLIST ListHead;
|
|
|
|
MMLISTS ListName;
|
|
|
|
PFN_NUMBER OldFlink, OldBlink;
|
[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
|
|
|
USHORT OldColor, OldCache;
|
2010-05-09 18:12:50 +00:00
|
|
|
PMMCOLOR_TABLES ColorTable;
|
2010-09-29 01:10:28 +00:00
|
|
|
|
2010-05-09 18:12:50 +00:00
|
|
|
/* Make sure PFN lock is held */
|
|
|
|
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
|
|
|
|
ASSERT(Color < MmSecondaryColors);
|
|
|
|
|
|
|
|
/* Get the PFN entry */
|
2010-11-11 13:13:05 +00:00
|
|
|
Pfn1 = MI_PFN_ELEMENT(PageIndex);
|
2010-05-09 18:12:50 +00:00
|
|
|
ASSERT(Pfn1->u3.e1.RemovalRequested == 0);
|
|
|
|
ASSERT(Pfn1->u3.e1.Rom == 0);
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-05-09 18:12:50 +00:00
|
|
|
/* Capture data for later */
|
|
|
|
OldColor = Pfn1->u3.e1.PageColor;
|
|
|
|
OldCache = Pfn1->u3.e1.CacheAttribute;
|
|
|
|
|
|
|
|
/* Could be either on free or zero list */
|
|
|
|
ListHead = MmPageLocationList[Pfn1->u3.e1.PageLocation];
|
2010-06-01 15:08:14 +00:00
|
|
|
ASSERT_LIST_INVARIANT(ListHead);
|
2010-05-09 18:12:50 +00:00
|
|
|
ListName = ListHead->ListName;
|
|
|
|
ASSERT(ListName <= FreePageList);
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-05-09 18:12:50 +00:00
|
|
|
/* Remove a page */
|
|
|
|
ListHead->Total--;
|
|
|
|
|
|
|
|
/* Get the forward and back pointers */
|
|
|
|
OldFlink = Pfn1->u1.Flink;
|
|
|
|
OldBlink = Pfn1->u2.Blink;
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-05-09 18:12:50 +00:00
|
|
|
/* Check if the next entry is the list head */
|
|
|
|
if (OldFlink != LIST_HEAD)
|
|
|
|
{
|
|
|
|
/* It is not, so set the backlink of the actual entry, to our backlink */
|
2010-11-11 13:13:05 +00:00
|
|
|
MI_PFN_ELEMENT(OldFlink)->u2.Blink = OldBlink;
|
2010-05-09 18:12:50 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Set the list head's backlink instead */
|
2010-11-11 13:08:41 +00:00
|
|
|
ListHead->Blink = OldBlink;
|
2010-05-09 18:12:50 +00:00
|
|
|
}
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-05-09 18:12:50 +00:00
|
|
|
/* Check if the back entry is the list head */
|
|
|
|
if (OldBlink != LIST_HEAD)
|
|
|
|
{
|
|
|
|
/* It is not, so set the backlink of the actual entry, to our backlink */
|
2010-11-11 13:13:05 +00:00
|
|
|
MI_PFN_ELEMENT(OldBlink)->u1.Flink = OldFlink;
|
2010-05-09 18:12:50 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Set the list head's backlink instead */
|
|
|
|
ListHead->Flink = OldFlink;
|
|
|
|
}
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-05-09 18:12:50 +00:00
|
|
|
/* We are not on a list anymore */
|
2011-12-25 18:21:05 +00:00
|
|
|
ASSERT_LIST_INVARIANT(ListHead);
|
2010-05-09 18:12:50 +00:00
|
|
|
Pfn1->u1.Flink = Pfn1->u2.Blink = 0;
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-05-09 18:12:50 +00:00
|
|
|
/* Zero flags but restore color and cache */
|
|
|
|
Pfn1->u3.e2.ShortFlags = 0;
|
|
|
|
Pfn1->u3.e1.PageColor = OldColor;
|
|
|
|
Pfn1->u3.e1.CacheAttribute = OldCache;
|
2010-09-29 01:10:28 +00:00
|
|
|
|
2010-05-09 18:12:50 +00:00
|
|
|
/* Get the first page on the color list */
|
2010-09-28 22:41:46 +00:00
|
|
|
ASSERT(Color < MmSecondaryColors);
|
2010-05-09 18:12:50 +00:00
|
|
|
ColorTable = &MmFreePagesByColor[ListName][Color];
|
|
|
|
ASSERT(ColorTable->Count >= 1);
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-05-09 18:12:50 +00:00
|
|
|
/* Set the forward link to whoever we were pointing to */
|
|
|
|
ColorTable->Flink = Pfn1->OriginalPte.u.Long;
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-09-28 22:41:46 +00:00
|
|
|
/* Get the first page on the color list */
|
2010-05-09 18:12:50 +00:00
|
|
|
if (ColorTable->Flink == LIST_HEAD)
|
|
|
|
{
|
|
|
|
/* This is the beginning of the list, so set the sentinel value */
|
2010-12-26 15:23:03 +00:00
|
|
|
ColorTable->Blink = (PVOID)LIST_HEAD;
|
2010-05-09 18:12:50 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* The list is empty, so we are the first page */
|
2010-11-11 13:13:05 +00:00
|
|
|
MI_PFN_ELEMENT(ColorTable->Flink)->u4.PteFrame = COLORED_LIST_HEAD;
|
2010-05-09 18:12:50 +00:00
|
|
|
}
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-09-28 22:41:46 +00:00
|
|
|
/* One less page */
|
|
|
|
ColorTable->Count--;
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-09-29 00:13:09 +00:00
|
|
|
/* ReactOS Hack */
|
|
|
|
Pfn1->OriginalPte.u.Long = 0;
|
2010-09-29 01:10:28 +00:00
|
|
|
|
2014-10-04 21:17:27 +00:00
|
|
|
/* Decrement number of available pages */
|
|
|
|
MiDecrementAvailablePages();
|
2010-05-09 18:12:50 +00:00
|
|
|
|
2010-11-02 15:16:22 +00:00
|
|
|
#if MI_TRACE_PFNS
|
|
|
|
//ASSERT(MI_PFN_CURRENT_USAGE != MI_USAGE_NOT_SET);
|
|
|
|
Pfn1->PfnUsage = MI_PFN_CURRENT_USAGE;
|
|
|
|
memcpy(Pfn1->ProcessName, MI_PFN_CURRENT_PROCESS_NAME, 16);
|
|
|
|
//MI_PFN_CURRENT_USAGE = MI_USAGE_NOT_SET;
|
|
|
|
//memcpy(MI_PFN_CURRENT_PROCESS_NAME, "Not Set", 16);
|
|
|
|
#endif
|
|
|
|
|
2010-05-09 18:12:50 +00:00
|
|
|
/* Return the page */
|
|
|
|
return PageIndex;
|
|
|
|
}
|
|
|
|
|
|
|
|
PFN_NUMBER
|
|
|
|
NTAPI
|
|
|
|
MiRemoveAnyPage(IN ULONG Color)
|
|
|
|
{
|
|
|
|
PFN_NUMBER PageIndex;
|
|
|
|
PMMPFN Pfn1;
|
|
|
|
|
|
|
|
/* Make sure PFN lock is held and we have pages */
|
|
|
|
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
|
|
|
|
ASSERT(MmAvailablePages != 0);
|
|
|
|
ASSERT(Color < MmSecondaryColors);
|
2010-11-11 13:15:40 +00:00
|
|
|
|
2010-05-09 18:12:50 +00:00
|
|
|
/* Check the colored free list */
|
|
|
|
PageIndex = MmFreePagesByColor[FreePageList][Color].Flink;
|
|
|
|
if (PageIndex == LIST_HEAD)
|
|
|
|
{
|
|
|
|
/* Check the colored zero list */
|
|
|
|
PageIndex = MmFreePagesByColor[ZeroedPageList][Color].Flink;
|
|
|
|
if (PageIndex == LIST_HEAD)
|
|
|
|
{
|
|
|
|
/* Check the free list */
|
2010-06-01 15:08:14 +00:00
|
|
|
ASSERT_LIST_INVARIANT(&MmFreePageListHead);
|
2010-05-09 18:12:50 +00:00
|
|
|
PageIndex = MmFreePageListHead.Flink;
|
|
|
|
Color = PageIndex & MmSecondaryColorMask;
|
|
|
|
if (PageIndex == LIST_HEAD)
|
|
|
|
{
|
|
|
|
/* Check the zero list */
|
2010-06-01 15:08:14 +00:00
|
|
|
ASSERT_LIST_INVARIANT(&MmZeroedPageListHead);
|
2010-05-09 18:12:50 +00:00
|
|
|
PageIndex = MmZeroedPageListHead.Flink;
|
|
|
|
Color = PageIndex & MmSecondaryColorMask;
|
|
|
|
ASSERT(PageIndex != LIST_HEAD);
|
|
|
|
if (PageIndex == LIST_HEAD)
|
|
|
|
{
|
|
|
|
/* FIXME: Should check the standby list */
|
|
|
|
ASSERT(MmZeroedPageListHead.Total == 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2010-11-11 13:15:40 +00:00
|
|
|
|
2010-05-09 18:12:50 +00:00
|
|
|
/* Remove the page from its list */
|
|
|
|
PageIndex = MiRemovePageByColor(PageIndex, Color);
|
|
|
|
|
|
|
|
/* Sanity checks */
|
2010-11-11 13:13:05 +00:00
|
|
|
Pfn1 = MI_PFN_ELEMENT(PageIndex);
|
2010-05-09 18:12:50 +00:00
|
|
|
ASSERT((Pfn1->u3.e1.PageLocation == FreePageList) ||
|
|
|
|
(Pfn1->u3.e1.PageLocation == ZeroedPageList));
|
|
|
|
ASSERT(Pfn1->u3.e2.ReferenceCount == 0);
|
|
|
|
ASSERT(Pfn1->u2.ShareCount == 0);
|
2010-06-01 15:08:14 +00:00
|
|
|
ASSERT_LIST_INVARIANT(&MmFreePageListHead);
|
|
|
|
ASSERT_LIST_INVARIANT(&MmZeroedPageListHead);
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-06-04 22:08:40 +00:00
|
|
|
/* Return the page */
|
2010-05-09 18:12:50 +00:00
|
|
|
return PageIndex;
|
|
|
|
}
|
|
|
|
|
2010-06-06 14:12:28 +00:00
|
|
|
PFN_NUMBER
|
|
|
|
NTAPI
|
|
|
|
MiRemoveZeroPage(IN ULONG Color)
|
|
|
|
{
|
|
|
|
PFN_NUMBER PageIndex;
|
|
|
|
PMMPFN Pfn1;
|
2010-11-18 19:20:38 +00:00
|
|
|
BOOLEAN Zero = FALSE;
|
2010-06-06 14:12:28 +00:00
|
|
|
|
|
|
|
/* Make sure PFN lock is held and we have pages */
|
|
|
|
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
|
|
|
|
ASSERT(MmAvailablePages != 0);
|
|
|
|
ASSERT(Color < MmSecondaryColors);
|
|
|
|
|
|
|
|
/* Check the colored zero list */
|
|
|
|
PageIndex = MmFreePagesByColor[ZeroedPageList][Color].Flink;
|
|
|
|
if (PageIndex == LIST_HEAD)
|
|
|
|
{
|
|
|
|
/* Check the zero list */
|
|
|
|
ASSERT_LIST_INVARIANT(&MmZeroedPageListHead);
|
|
|
|
PageIndex = MmZeroedPageListHead.Flink;
|
|
|
|
if (PageIndex == LIST_HEAD)
|
|
|
|
{
|
2010-09-29 01:10:28 +00:00
|
|
|
/* This means there's no zero pages, we have to look for free ones */
|
2010-06-06 14:12:28 +00:00
|
|
|
ASSERT(MmZeroedPageListHead.Total == 0);
|
|
|
|
Zero = TRUE;
|
2010-11-11 13:15:40 +00:00
|
|
|
|
2010-06-06 14:12:28 +00:00
|
|
|
/* Check the colored free list */
|
2010-09-30 03:17:14 +00:00
|
|
|
PageIndex = MmFreePagesByColor[FreePageList][Color].Flink;
|
2010-06-06 14:12:28 +00:00
|
|
|
if (PageIndex == LIST_HEAD)
|
|
|
|
{
|
|
|
|
/* Check the free list */
|
|
|
|
ASSERT_LIST_INVARIANT(&MmFreePageListHead);
|
|
|
|
PageIndex = MmFreePageListHead.Flink;
|
|
|
|
Color = PageIndex & MmSecondaryColorMask;
|
|
|
|
ASSERT(PageIndex != LIST_HEAD);
|
|
|
|
if (PageIndex == LIST_HEAD)
|
|
|
|
{
|
|
|
|
/* FIXME: Should check the standby list */
|
|
|
|
ASSERT(MmZeroedPageListHead.Total == 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2010-11-18 19:20:38 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
Color = PageIndex & MmSecondaryColorMask;
|
|
|
|
}
|
2010-06-06 14:12:28 +00:00
|
|
|
}
|
2010-09-29 01:10:28 +00:00
|
|
|
|
2010-06-06 14:12:28 +00:00
|
|
|
/* Sanity checks */
|
2010-11-11 13:13:05 +00:00
|
|
|
Pfn1 = MI_PFN_ELEMENT(PageIndex);
|
2010-06-06 14:12:28 +00:00
|
|
|
ASSERT((Pfn1->u3.e1.PageLocation == FreePageList) ||
|
|
|
|
(Pfn1->u3.e1.PageLocation == ZeroedPageList));
|
|
|
|
|
|
|
|
/* Remove the page from its list */
|
|
|
|
PageIndex = MiRemovePageByColor(PageIndex, Color);
|
2010-11-11 13:13:05 +00:00
|
|
|
ASSERT(Pfn1 == MI_PFN_ELEMENT(PageIndex));
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-06-06 14:12:28 +00:00
|
|
|
/* Zero it, if needed */
|
|
|
|
if (Zero) MiZeroPhysicalPage(PageIndex);
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-06-06 14:12:28 +00:00
|
|
|
/* Sanity checks */
|
|
|
|
ASSERT(Pfn1->u3.e2.ReferenceCount == 0);
|
|
|
|
ASSERT(Pfn1->u2.ShareCount == 0);
|
|
|
|
ASSERT_LIST_INVARIANT(&MmFreePageListHead);
|
|
|
|
ASSERT_LIST_INVARIANT(&MmZeroedPageListHead);
|
|
|
|
|
|
|
|
/* Return the page */
|
|
|
|
return PageIndex;
|
|
|
|
}
|
2010-02-20 14:40:21 +00:00
|
|
|
|
2016-10-18 20:19:00 +00:00
|
|
|
/* HACK for keeping legacy Mm alive */
|
|
|
|
extern BOOLEAN MmRosNotifyAvailablePage(PFN_NUMBER PageFrameIndex);
|
|
|
|
|
2010-02-20 14:40:21 +00:00
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
MiInsertPageInFreeList(IN PFN_NUMBER PageFrameIndex)
|
|
|
|
{
|
|
|
|
PMMPFNLIST ListHead;
|
|
|
|
PFN_NUMBER LastPage;
|
2010-05-09 18:12:50 +00:00
|
|
|
PMMPFN Pfn1;
|
2010-02-20 14:40:21 +00:00
|
|
|
ULONG Color;
|
2010-05-09 18:12:50 +00:00
|
|
|
PMMPFN Blink;
|
|
|
|
PMMCOLOR_TABLES ColorTable;
|
2010-09-29 01:10:28 +00:00
|
|
|
|
2010-02-20 14:40:21 +00:00
|
|
|
/* Make sure the page index is valid */
|
2010-06-01 15:08:14 +00:00
|
|
|
ASSERT(KeGetCurrentIrql() >= DISPATCH_LEVEL);
|
2010-02-20 14:40:21 +00:00
|
|
|
ASSERT((PageFrameIndex != 0) &&
|
|
|
|
(PageFrameIndex <= MmHighestPhysicalPage) &&
|
|
|
|
(PageFrameIndex >= MmLowestPhysicalPage));
|
|
|
|
|
|
|
|
/* Get the PFN entry */
|
2010-11-11 13:13:05 +00:00
|
|
|
Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);
|
2010-02-20 14:40:21 +00:00
|
|
|
|
|
|
|
/* Sanity checks that a right kind of page is being inserted here */
|
|
|
|
ASSERT(Pfn1->u4.MustBeCached == 0);
|
|
|
|
ASSERT(Pfn1->u3.e1.Rom != 1);
|
|
|
|
ASSERT(Pfn1->u3.e1.RemovalRequested == 0);
|
|
|
|
ASSERT(Pfn1->u4.VerifierAllocation == 0);
|
|
|
|
ASSERT(Pfn1->u3.e2.ReferenceCount == 0);
|
|
|
|
|
2016-10-18 20:19:00 +00:00
|
|
|
/* HACK HACK HACK : Feed the page to legacy Mm */
|
|
|
|
if (MmRosNotifyAvailablePage(PageFrameIndex))
|
|
|
|
{
|
|
|
|
DPRINT1("Legacy Mm eating ARM3 page!.\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-02-20 14:40:21 +00:00
|
|
|
/* Get the free page list and increment its count */
|
|
|
|
ListHead = &MmFreePageListHead;
|
2010-06-01 15:08:14 +00:00
|
|
|
ASSERT_LIST_INVARIANT(ListHead);
|
2010-02-20 14:40:21 +00:00
|
|
|
ListHead->Total++;
|
|
|
|
|
|
|
|
/* Get the last page on the list */
|
|
|
|
LastPage = ListHead->Blink;
|
2010-02-21 03:52:22 +00:00
|
|
|
if (LastPage != LIST_HEAD)
|
2010-02-20 14:40:21 +00:00
|
|
|
{
|
|
|
|
/* Link us with the previous page, so we're at the end now */
|
2010-11-11 13:13:05 +00:00
|
|
|
MI_PFN_ELEMENT(LastPage)->u1.Flink = PageFrameIndex;
|
2010-02-20 14:40:21 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* The list is empty, so we are the first page */
|
|
|
|
ListHead->Flink = PageFrameIndex;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Now make the list head point back to us (since we go at the end) */
|
|
|
|
ListHead->Blink = PageFrameIndex;
|
2010-06-04 22:08:40 +00:00
|
|
|
ASSERT_LIST_INVARIANT(ListHead);
|
2010-06-01 15:08:14 +00:00
|
|
|
|
2010-02-20 14:40:21 +00:00
|
|
|
/* And initialize our own list pointers */
|
2010-02-21 03:52:22 +00:00
|
|
|
Pfn1->u1.Flink = LIST_HEAD;
|
2010-02-20 14:40:21 +00:00
|
|
|
Pfn1->u2.Blink = LastPage;
|
|
|
|
|
|
|
|
/* Set the list name and default priority */
|
2010-02-21 03:52:22 +00:00
|
|
|
Pfn1->u3.e1.PageLocation = FreePageList;
|
2010-02-20 14:40:21 +00:00
|
|
|
Pfn1->u4.Priority = 3;
|
2010-06-01 15:08:14 +00:00
|
|
|
|
2010-02-20 14:40:21 +00:00
|
|
|
/* Clear some status fields */
|
|
|
|
Pfn1->u4.InPageError = 0;
|
|
|
|
Pfn1->u4.AweAllocation = 0;
|
|
|
|
|
2014-10-04 21:17:27 +00:00
|
|
|
/* Increment number of available pages */
|
|
|
|
MiIncrementAvailablePages();
|
2010-09-29 01:10:28 +00:00
|
|
|
|
2010-02-20 14:40:21 +00:00
|
|
|
/* Get the page color */
|
|
|
|
Color = PageFrameIndex & MmSecondaryColorMask;
|
|
|
|
|
|
|
|
/* Get the first page on the color list */
|
2010-05-09 18:12:50 +00:00
|
|
|
ColorTable = &MmFreePagesByColor[FreePageList][Color];
|
|
|
|
if (ColorTable->Flink == LIST_HEAD)
|
2010-02-20 14:40:21 +00:00
|
|
|
{
|
|
|
|
/* The list is empty, so we are the first page */
|
2010-09-29 00:13:09 +00:00
|
|
|
Pfn1->u4.PteFrame = COLORED_LIST_HEAD;
|
2010-05-09 18:12:50 +00:00
|
|
|
ColorTable->Flink = PageFrameIndex;
|
2010-02-20 14:40:21 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Get the previous page */
|
2010-05-09 18:12:50 +00:00
|
|
|
Blink = (PMMPFN)ColorTable->Blink;
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-11-11 13:13:05 +00:00
|
|
|
/* Make it link to us, and link back to it */
|
2010-02-20 14:40:21 +00:00
|
|
|
Blink->OriginalPte.u.Long = PageFrameIndex;
|
2010-11-11 13:13:05 +00:00
|
|
|
Pfn1->u4.PteFrame = MiGetPfnEntryIndex(Blink);
|
2010-02-20 14:40:21 +00:00
|
|
|
}
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-02-20 14:40:21 +00:00
|
|
|
/* Now initialize our own list pointers */
|
2010-05-09 18:12:50 +00:00
|
|
|
ColorTable->Blink = Pfn1;
|
2010-09-28 22:41:46 +00:00
|
|
|
|
2010-11-11 13:13:05 +00:00
|
|
|
/* This page is now the last */
|
2010-02-21 03:52:22 +00:00
|
|
|
Pfn1->OriginalPte.u.Long = LIST_HEAD;
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-02-20 14:40:21 +00:00
|
|
|
/* And increase the count in the colored list */
|
2010-05-09 18:12:50 +00:00
|
|
|
ColorTable->Count++;
|
2010-09-29 01:10:28 +00:00
|
|
|
|
2010-05-12 19:11:49 +00:00
|
|
|
/* Notify zero page thread if enough pages are on the free list now */
|
2010-09-28 16:47:25 +00:00
|
|
|
if ((ListHead->Total >= 8) && !(MmZeroingPageThreadActive))
|
2010-05-12 19:11:49 +00:00
|
|
|
{
|
2010-09-28 16:47:25 +00:00
|
|
|
/* Set the event */
|
|
|
|
KeSetEvent(&MmZeroingPageEvent, IO_NO_INCREMENT, FALSE);
|
2010-05-12 19:11:49 +00:00
|
|
|
}
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-11-02 15:16:22 +00:00
|
|
|
#if MI_TRACE_PFNS
|
|
|
|
Pfn1->PfnUsage = MI_USAGE_FREE_PAGE;
|
|
|
|
RtlZeroMemory(Pfn1->ProcessName, 16);
|
|
|
|
#endif
|
2010-02-20 14:40:21 +00:00
|
|
|
}
|
|
|
|
|
2010-09-28 14:38:30 +00:00
|
|
|
VOID
|
2012-03-31 20:08:34 +00:00
|
|
|
FASTCALL
|
|
|
|
MiInsertStandbyListAtFront(IN PFN_NUMBER PageFrameIndex)
|
2010-09-28 14:38:30 +00:00
|
|
|
{
|
2012-03-31 20:08:34 +00:00
|
|
|
PMMPFNLIST ListHead;
|
2010-09-28 14:38:30 +00:00
|
|
|
PFN_NUMBER Flink;
|
|
|
|
PMMPFN Pfn1, Pfn2;
|
|
|
|
|
|
|
|
/* Make sure the lock is held */
|
2014-10-07 22:02:12 +00:00
|
|
|
DPRINT("Inserting page: %lx into standby list !\n", PageFrameIndex);
|
2010-09-28 14:38:30 +00:00
|
|
|
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-09-28 14:38:30 +00:00
|
|
|
/* Make sure the PFN is valid */
|
2012-03-31 20:08:34 +00:00
|
|
|
ASSERT((PageFrameIndex != 0) &&
|
2010-09-28 14:38:30 +00:00
|
|
|
(PageFrameIndex <= MmHighestPhysicalPage) &&
|
|
|
|
(PageFrameIndex >= MmLowestPhysicalPage));
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2012-03-31 20:08:34 +00:00
|
|
|
/* Grab the PFN and validate it is the right kind of PFN being inserted */
|
2010-11-11 13:13:05 +00:00
|
|
|
Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);
|
2012-03-31 20:08:34 +00:00
|
|
|
ASSERT(Pfn1->u4.MustBeCached == 0);
|
2010-09-28 14:38:30 +00:00
|
|
|
ASSERT(Pfn1->u3.e2.ReferenceCount == 0);
|
2012-03-31 20:08:34 +00:00
|
|
|
ASSERT(Pfn1->u3.e1.PrototypePte == 1);
|
2010-09-28 14:38:30 +00:00
|
|
|
ASSERT(Pfn1->u3.e1.Rom != 1);
|
|
|
|
|
2012-03-31 20:08:34 +00:00
|
|
|
/* One more transition page on a list */
|
|
|
|
MmTransitionSharedPages++;
|
2010-09-28 14:38:30 +00:00
|
|
|
|
2012-03-31 20:08:34 +00:00
|
|
|
/* Get the standby page list and increment its count */
|
|
|
|
ListHead = &MmStandbyPageListByPriority [Pfn1->u4.Priority];
|
|
|
|
ASSERT_LIST_INVARIANT(ListHead);
|
|
|
|
ListHead->Total++;
|
2010-09-28 14:38:30 +00:00
|
|
|
|
|
|
|
/* Make the head of the list point to this page now */
|
|
|
|
Flink = ListHead->Flink;
|
|
|
|
ListHead->Flink = PageFrameIndex;
|
|
|
|
|
|
|
|
/* Make the page point to the previous head, and back to the list */
|
|
|
|
Pfn1->u1.Flink = Flink;
|
|
|
|
Pfn1->u2.Blink = LIST_HEAD;
|
|
|
|
|
|
|
|
/* Was the list empty? */
|
|
|
|
if (Flink != LIST_HEAD)
|
|
|
|
{
|
|
|
|
/* It wasn't, so update the backlink of the previous head page */
|
2010-11-11 13:13:05 +00:00
|
|
|
Pfn2 = MI_PFN_ELEMENT(Flink);
|
2010-09-28 14:38:30 +00:00
|
|
|
Pfn2->u2.Blink = PageFrameIndex;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* It was empty, so have it loop back around to this new page */
|
|
|
|
ListHead->Blink = PageFrameIndex;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Move the page onto its new location */
|
2012-03-31 20:08:34 +00:00
|
|
|
Pfn1->u3.e1.PageLocation = StandbyPageList;
|
2010-09-28 14:38:30 +00:00
|
|
|
|
2014-10-04 21:17:27 +00:00
|
|
|
/* Increment number of available pages */
|
|
|
|
MiIncrementAvailablePages();
|
2012-03-31 20:08:34 +00:00
|
|
|
}
|
2010-09-28 22:41:46 +00:00
|
|
|
|
2012-03-31 20:08:34 +00:00
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
MiInsertPageInList(IN PMMPFNLIST ListHead,
|
|
|
|
IN PFN_NUMBER PageFrameIndex)
|
|
|
|
{
|
|
|
|
PFN_NUMBER Flink, LastPage;
|
|
|
|
PMMPFN Pfn1, Pfn2;
|
|
|
|
MMLISTS ListName;
|
|
|
|
PMMCOLOR_TABLES ColorHead;
|
|
|
|
ULONG Color;
|
2010-09-28 22:41:46 +00:00
|
|
|
|
2012-03-31 20:08:34 +00:00
|
|
|
/* For free pages, use MiInsertPageInFreeList */
|
|
|
|
ASSERT(ListHead != &MmFreePageListHead);
|
|
|
|
|
|
|
|
/* Make sure the lock is held */
|
|
|
|
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
|
2010-09-28 22:41:46 +00:00
|
|
|
|
2012-03-31 20:08:34 +00:00
|
|
|
/* Make sure the PFN is valid */
|
|
|
|
ASSERT((PageFrameIndex) &&
|
|
|
|
(PageFrameIndex <= MmHighestPhysicalPage) &&
|
|
|
|
(PageFrameIndex >= MmLowestPhysicalPage));
|
2010-09-28 22:41:46 +00:00
|
|
|
|
2012-03-31 20:08:34 +00:00
|
|
|
/* Page should be unused */
|
|
|
|
Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);
|
|
|
|
ASSERT(Pfn1->u3.e2.ReferenceCount == 0);
|
|
|
|
ASSERT(Pfn1->u3.e1.Rom != 1);
|
|
|
|
|
|
|
|
/* Is a standby or modified page being inserted? */
|
|
|
|
ListName = ListHead->ListName;
|
|
|
|
if ((ListName == StandbyPageList) || (ListName == ModifiedPageList))
|
|
|
|
{
|
|
|
|
/* If the page is in transition, it must also be a prototype page */
|
|
|
|
if ((Pfn1->OriginalPte.u.Soft.Prototype == 0) &&
|
|
|
|
(Pfn1->OriginalPte.u.Soft.Transition == 1))
|
|
|
|
{
|
|
|
|
/* Crash the system on inconsistency */
|
|
|
|
KeBugCheckEx(MEMORY_MANAGEMENT, 0x8888, 0, 0, 0);
|
|
|
|
}
|
|
|
|
}
|
2010-09-28 22:41:46 +00:00
|
|
|
|
2012-03-31 20:08:34 +00:00
|
|
|
/* Standby pages are prioritized, so we need to get the real head */
|
|
|
|
if (ListHead == &MmStandbyPageListHead)
|
|
|
|
{
|
|
|
|
/* Obviously the prioritized list should still have the same name */
|
|
|
|
ListHead = &MmStandbyPageListByPriority[Pfn1->u4.Priority];
|
|
|
|
ASSERT(ListHead->ListName == ListName);
|
|
|
|
}
|
2010-09-28 22:41:46 +00:00
|
|
|
|
2012-03-31 20:08:34 +00:00
|
|
|
/* Increment the list count */
|
|
|
|
ListHead->Total++;
|
2010-09-28 22:41:46 +00:00
|
|
|
|
2012-03-31 20:08:34 +00:00
|
|
|
/* Is a modified page being inserted? */
|
|
|
|
if (ListHead == &MmModifiedPageListHead)
|
2010-09-28 22:41:46 +00:00
|
|
|
{
|
2012-03-31 20:08:34 +00:00
|
|
|
/* For now, only single-prototype pages should end up in this path */
|
2012-09-02 18:54:05 +00:00
|
|
|
DPRINT("Modified page being added: %lx\n", PageFrameIndex);
|
2012-03-31 20:08:34 +00:00
|
|
|
ASSERT(Pfn1->OriginalPte.u.Soft.Prototype == 0);
|
|
|
|
|
|
|
|
/* Modified pages are colored when they are selected for page file */
|
|
|
|
ListHead = &MmModifiedPageListByColor[0];
|
|
|
|
ASSERT (ListHead->ListName == ListName);
|
|
|
|
ListHead->Total++;
|
|
|
|
|
|
|
|
/* Increment the number of paging file modified pages */
|
|
|
|
MmTotalPagesForPagingFile++;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Don't handle bad pages yet yet */
|
|
|
|
ASSERT(Pfn1->u3.e1.RemovalRequested == 0);
|
|
|
|
|
|
|
|
/* Zero pages go to the head, all other pages go to the end */
|
|
|
|
if (ListName == ZeroedPageList)
|
|
|
|
{
|
|
|
|
/* Make the head of the list point to this page now */
|
|
|
|
Flink = ListHead->Flink;
|
|
|
|
ListHead->Flink = PageFrameIndex;
|
|
|
|
|
|
|
|
/* Make the page point to the previous head, and back to the list */
|
|
|
|
Pfn1->u1.Flink = Flink;
|
|
|
|
Pfn1->u2.Blink = LIST_HEAD;
|
|
|
|
|
|
|
|
/* Was the list empty? */
|
|
|
|
if (Flink != LIST_HEAD)
|
|
|
|
{
|
|
|
|
/* It wasn't, so update the backlink of the previous head page */
|
|
|
|
Pfn2 = MI_PFN_ELEMENT(Flink);
|
|
|
|
Pfn2->u2.Blink = PageFrameIndex;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* It was empty, so have it loop back around to this new page */
|
|
|
|
ListHead->Blink = PageFrameIndex;
|
|
|
|
}
|
2010-09-28 22:41:46 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-03-31 20:08:34 +00:00
|
|
|
/* Get the last page on the list */
|
|
|
|
LastPage = ListHead->Blink;
|
|
|
|
if (LastPage != LIST_HEAD)
|
|
|
|
{
|
|
|
|
/* Link us with the previous page, so we're at the end now */
|
|
|
|
MI_PFN_ELEMENT(LastPage)->u1.Flink = PageFrameIndex;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* The list is empty, so we are the first page */
|
|
|
|
ListHead->Flink = PageFrameIndex;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Now make the list head point back to us (since we go at the end) */
|
|
|
|
ListHead->Blink = PageFrameIndex;
|
|
|
|
ASSERT_LIST_INVARIANT(ListHead);
|
|
|
|
|
|
|
|
/* And initialize our own list pointers */
|
|
|
|
Pfn1->u1.Flink = LIST_HEAD;
|
|
|
|
Pfn1->u2.Blink = LastPage;
|
2010-09-28 22:41:46 +00:00
|
|
|
}
|
|
|
|
|
2012-03-31 20:08:34 +00:00
|
|
|
/* Move the page onto its new location */
|
|
|
|
Pfn1->u3.e1.PageLocation = ListName;
|
|
|
|
|
|
|
|
/* For zero/free pages, we also have to handle the colored lists */
|
|
|
|
if (ListName <= StandbyPageList)
|
|
|
|
{
|
2014-10-04 21:17:27 +00:00
|
|
|
/* Increment number of available pages */
|
|
|
|
MiIncrementAvailablePages();
|
2012-03-31 20:08:34 +00:00
|
|
|
|
|
|
|
/* Sanity checks */
|
|
|
|
ASSERT(ListName == ZeroedPageList);
|
|
|
|
ASSERT(Pfn1->u4.InPageError == 0);
|
|
|
|
|
|
|
|
/* Get the page color */
|
|
|
|
Color = PageFrameIndex & MmSecondaryColorMask;
|
|
|
|
|
|
|
|
/* Get the list for this color */
|
|
|
|
ColorHead = &MmFreePagesByColor[ZeroedPageList][Color];
|
|
|
|
|
|
|
|
/* Get the old head */
|
|
|
|
Flink = ColorHead->Flink;
|
|
|
|
|
|
|
|
/* Make this page point back to the list, and point forwards to the old head */
|
|
|
|
Pfn1->OriginalPte.u.Long = Flink;
|
|
|
|
Pfn1->u4.PteFrame = COLORED_LIST_HEAD;
|
|
|
|
|
|
|
|
/* Set the new head */
|
|
|
|
ColorHead->Flink = PageFrameIndex;
|
|
|
|
|
|
|
|
/* Was the head empty? */
|
|
|
|
if (Flink != LIST_HEAD)
|
|
|
|
{
|
|
|
|
/* No, so make the old head point to this page */
|
|
|
|
Pfn2 = MI_PFN_ELEMENT(Flink);
|
|
|
|
Pfn2->u4.PteFrame = PageFrameIndex;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Yes, make it loop back to this page */
|
|
|
|
ColorHead->Blink = (PVOID)Pfn1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* One more paged on the colored list */
|
|
|
|
ColorHead->Count++;
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-11-02 15:16:22 +00:00
|
|
|
#if MI_TRACE_PFNS
|
2012-03-31 20:08:34 +00:00
|
|
|
//ASSERT(MI_PFN_CURRENT_USAGE == MI_USAGE_NOT_SET);
|
|
|
|
Pfn1->PfnUsage = MI_USAGE_FREE_PAGE;
|
|
|
|
MI_PFN_CURRENT_USAGE = MI_USAGE_NOT_SET;
|
|
|
|
RtlZeroMemory(Pfn1->ProcessName, 16);
|
2010-11-02 15:16:22 +00:00
|
|
|
#endif
|
2012-03-31 20:08:34 +00:00
|
|
|
}
|
|
|
|
else if (ListName == ModifiedPageList)
|
|
|
|
{
|
|
|
|
/* In ARM3, page must be destined for page file, and not yet written out */
|
|
|
|
ASSERT(Pfn1->OriginalPte.u.Soft.Prototype == 0);
|
|
|
|
ASSERT(Pfn1->OriginalPte.u.Soft.PageFileHigh == 0);
|
|
|
|
|
|
|
|
/* One more transition page */
|
|
|
|
MmTransitionSharedPages++;
|
|
|
|
|
|
|
|
/* Increment the number of per-process modified pages */
|
|
|
|
PsGetCurrentProcess()->ModifiedPageCount++;
|
|
|
|
|
|
|
|
/* FIXME: Wake up modified page writer if there are not enough free pages */
|
|
|
|
}
|
|
|
|
else if (ListName == ModifiedNoWritePageList)
|
|
|
|
{
|
|
|
|
/* This list is not yet implemented */
|
|
|
|
ASSERT(FALSE);
|
|
|
|
}
|
2010-09-28 14:38:30 +00:00
|
|
|
}
|
|
|
|
|
2010-05-29 18:33:50 +00:00
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
MiInitializePfn(IN PFN_NUMBER PageFrameIndex,
|
|
|
|
IN PMMPTE PointerPte,
|
|
|
|
IN BOOLEAN Modified)
|
|
|
|
{
|
|
|
|
PMMPFN Pfn1;
|
|
|
|
NTSTATUS Status;
|
|
|
|
PMMPTE PointerPtePte;
|
|
|
|
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
|
|
|
|
|
|
|
|
/* Setup the PTE */
|
2010-11-11 13:13:05 +00:00
|
|
|
Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);
|
2010-05-29 18:33:50 +00:00
|
|
|
Pfn1->PteAddress = PointerPte;
|
|
|
|
|
|
|
|
/* Check if this PFN is part of a valid address space */
|
|
|
|
if (PointerPte->u.Hard.Valid == 1)
|
|
|
|
{
|
2010-07-24 15:01:05 +00:00
|
|
|
/* Only valid from MmCreateProcessAddressSpace path */
|
|
|
|
ASSERT(PsGetCurrentProcess()->Vm.WorkingSetSize == 0);
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-10-04 18:22:50 +00:00
|
|
|
/* Make this a demand zero PTE */
|
|
|
|
MI_MAKE_SOFTWARE_PTE(&Pfn1->OriginalPte, MM_READWRITE);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Copy the PTE data */
|
|
|
|
Pfn1->OriginalPte = *PointerPte;
|
|
|
|
ASSERT(!((Pfn1->OriginalPte.u.Soft.Prototype == 0) &&
|
|
|
|
(Pfn1->OriginalPte.u.Soft.Transition == 1)));
|
2010-05-29 18:33:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Otherwise this is a fresh page -- set it up */
|
|
|
|
ASSERT(Pfn1->u3.e2.ReferenceCount == 0);
|
|
|
|
Pfn1->u3.e2.ReferenceCount = 1;
|
|
|
|
Pfn1->u2.ShareCount = 1;
|
|
|
|
Pfn1->u3.e1.PageLocation = ActiveAndValid;
|
|
|
|
ASSERT(Pfn1->u3.e1.Rom == 0);
|
|
|
|
Pfn1->u3.e1.Modified = Modified;
|
|
|
|
|
|
|
|
/* Get the page table for the PTE */
|
|
|
|
PointerPtePte = MiAddressToPte(PointerPte);
|
|
|
|
if (PointerPtePte->u.Hard.Valid == 0)
|
|
|
|
{
|
|
|
|
/* Make sure the PDE gets paged in properly */
|
|
|
|
Status = MiCheckPdeForPagedPool(PointerPte);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
/* Crash */
|
|
|
|
KeBugCheckEx(MEMORY_MANAGEMENT,
|
|
|
|
0x61940,
|
|
|
|
(ULONG_PTR)PointerPte,
|
|
|
|
(ULONG_PTR)PointerPtePte->u.Long,
|
|
|
|
(ULONG_PTR)MiPteToAddress(PointerPte));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Get the PFN for the page table */
|
|
|
|
PageFrameIndex = PFN_FROM_PTE(PointerPtePte);
|
|
|
|
ASSERT(PageFrameIndex != 0);
|
|
|
|
Pfn1->u4.PteFrame = PageFrameIndex;
|
|
|
|
|
|
|
|
/* Increase its share count so we don't get rid of it */
|
2010-11-11 13:13:05 +00:00
|
|
|
Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);
|
2010-05-29 18:33:50 +00:00
|
|
|
Pfn1->u2.ShareCount++;
|
|
|
|
}
|
|
|
|
|
2011-09-30 21:45:25 +00:00
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
MiInitializePfnAndMakePteValid(IN PFN_NUMBER PageFrameIndex,
|
|
|
|
IN PMMPTE PointerPte,
|
|
|
|
IN MMPTE TempPte)
|
|
|
|
{
|
|
|
|
PMMPFN Pfn1;
|
|
|
|
NTSTATUS Status;
|
|
|
|
PMMPTE PointerPtePte;
|
|
|
|
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
|
|
|
|
|
|
|
|
/* PTE must be invalid */
|
|
|
|
ASSERT(PointerPte->u.Hard.Valid == 0);
|
|
|
|
|
|
|
|
/* Setup the PTE */
|
|
|
|
Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);
|
|
|
|
Pfn1->PteAddress = PointerPte;
|
|
|
|
Pfn1->OriginalPte = DemandZeroPte;
|
|
|
|
|
|
|
|
/* Otherwise this is a fresh page -- set it up */
|
|
|
|
ASSERT(Pfn1->u3.e2.ReferenceCount == 0);
|
|
|
|
Pfn1->u3.e2.ReferenceCount++;
|
|
|
|
Pfn1->u2.ShareCount++;
|
|
|
|
Pfn1->u3.e1.PageLocation = ActiveAndValid;
|
|
|
|
ASSERT(Pfn1->u3.e1.Rom == 0);
|
|
|
|
Pfn1->u3.e1.Modified = 1;
|
|
|
|
|
|
|
|
/* Get the page table for the PTE */
|
|
|
|
PointerPtePte = MiAddressToPte(PointerPte);
|
|
|
|
if (PointerPtePte->u.Hard.Valid == 0)
|
|
|
|
{
|
|
|
|
/* Make sure the PDE gets paged in properly */
|
|
|
|
Status = MiCheckPdeForPagedPool(PointerPte);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
/* Crash */
|
|
|
|
KeBugCheckEx(MEMORY_MANAGEMENT,
|
|
|
|
0x61940,
|
|
|
|
(ULONG_PTR)PointerPte,
|
|
|
|
(ULONG_PTR)PointerPtePte->u.Long,
|
|
|
|
(ULONG_PTR)MiPteToAddress(PointerPte));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Get the PFN for the page table */
|
|
|
|
PageFrameIndex = PFN_FROM_PTE(PointerPtePte);
|
|
|
|
ASSERT(PageFrameIndex != 0);
|
|
|
|
Pfn1->u4.PteFrame = PageFrameIndex;
|
|
|
|
|
|
|
|
/* Increase its share count so we don't get rid of it */
|
|
|
|
Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);
|
|
|
|
Pfn1->u2.ShareCount++;
|
|
|
|
|
|
|
|
/* Write valid PTE */
|
|
|
|
MI_WRITE_VALID_PTE(PointerPte, TempPte);
|
|
|
|
}
|
|
|
|
|
2012-07-15 23:42:27 +00:00
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
MiInitializeAndChargePfn(OUT PPFN_NUMBER PageFrameIndex,
|
2015-05-10 19:35:00 +00:00
|
|
|
IN PMMPDE PointerPde,
|
2012-07-15 23:42:27 +00:00
|
|
|
IN PFN_NUMBER ContainingPageFrame,
|
|
|
|
IN BOOLEAN SessionAllocation)
|
|
|
|
{
|
2015-05-10 19:35:00 +00:00
|
|
|
MMPDE TempPde;
|
2012-07-15 23:42:27 +00:00
|
|
|
KIRQL OldIrql;
|
|
|
|
|
|
|
|
/* Use either a global or local PDE */
|
2015-05-10 19:35:00 +00:00
|
|
|
TempPde = SessionAllocation ? ValidKernelPdeLocal : ValidKernelPde;
|
2012-07-15 23:42:27 +00:00
|
|
|
|
|
|
|
/* Lock the PFN database */
|
|
|
|
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
|
|
|
|
|
|
|
/* Make sure nobody is racing us */
|
|
|
|
if (PointerPde->u.Hard.Valid == 1)
|
|
|
|
{
|
|
|
|
/* Return special error if that was the case */
|
|
|
|
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
|
|
|
return STATUS_RETRY;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Grab a zero page and set the PFN, then make it valid */
|
|
|
|
*PageFrameIndex = MiRemoveZeroPage(MI_GET_NEXT_COLOR());
|
2015-05-10 19:35:00 +00:00
|
|
|
TempPde.u.Hard.PageFrameNumber = *PageFrameIndex;
|
|
|
|
MI_WRITE_VALID_PDE(PointerPde, TempPde);
|
2012-07-15 23:42:27 +00:00
|
|
|
|
|
|
|
/* Initialize the PFN */
|
|
|
|
MiInitializePfnForOtherProcess(*PageFrameIndex,
|
|
|
|
PointerPde,
|
|
|
|
ContainingPageFrame);
|
|
|
|
ASSERT(MI_PFN_ELEMENT(*PageFrameIndex)->u1.WsIndex == 0);
|
|
|
|
|
|
|
|
/* Release the lock and return success */
|
|
|
|
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
2011-09-30 21:45:25 +00:00
|
|
|
|
2010-05-29 18:33:50 +00:00
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
MiDecrementShareCount(IN PMMPFN Pfn1,
|
|
|
|
IN PFN_NUMBER PageFrameIndex)
|
|
|
|
{
|
2012-03-31 20:08:34 +00:00
|
|
|
PMMPTE PointerPte;
|
|
|
|
MMPTE TempPte;
|
|
|
|
|
2010-05-29 18:33:50 +00:00
|
|
|
ASSERT(PageFrameIndex > 0);
|
2010-11-11 13:13:05 +00:00
|
|
|
ASSERT(MI_PFN_ELEMENT(PageFrameIndex) != NULL);
|
|
|
|
ASSERT(Pfn1 == MI_PFN_ELEMENT(PageFrameIndex));
|
2010-11-02 14:41:51 +00:00
|
|
|
ASSERT(MI_IS_ROS_PFN(Pfn1) == FALSE);
|
2010-05-29 18:33:50 +00:00
|
|
|
|
|
|
|
/* Page must be in-use */
|
|
|
|
if ((Pfn1->u3.e1.PageLocation != ActiveAndValid) &&
|
|
|
|
(Pfn1->u3.e1.PageLocation != StandbyPageList))
|
|
|
|
{
|
|
|
|
/* Otherwise we have PFN corruption */
|
|
|
|
KeBugCheckEx(PFN_LIST_CORRUPT,
|
|
|
|
0x99,
|
|
|
|
PageFrameIndex,
|
|
|
|
Pfn1->u3.e1.PageLocation,
|
|
|
|
0);
|
|
|
|
}
|
|
|
|
|
2014-08-06 21:53:57 +00:00
|
|
|
/* Page should at least have one reference */
|
|
|
|
ASSERT(Pfn1->u3.e2.ReferenceCount != 0);
|
|
|
|
|
2010-05-29 18:33:50 +00:00
|
|
|
/* Check if the share count is now 0 */
|
|
|
|
ASSERT(Pfn1->u2.ShareCount < 0xF000000);
|
|
|
|
if (!--Pfn1->u2.ShareCount)
|
|
|
|
{
|
2012-03-31 20:08:34 +00:00
|
|
|
/* Was this a prototype PTE? */
|
|
|
|
if (Pfn1->u3.e1.PrototypePte)
|
|
|
|
{
|
|
|
|
/* Grab the PTE address and make sure it's in prototype pool */
|
|
|
|
PointerPte = Pfn1->PteAddress;
|
|
|
|
ASSERT((PointerPte >= (PMMPTE)MmPagedPoolStart) && (PointerPte <= (PMMPTE)MmPagedPoolEnd));
|
|
|
|
|
|
|
|
/* The PTE that backs it should also be valdi */
|
|
|
|
PointerPte = MiAddressToPte(PointerPte);
|
|
|
|
ASSERT(PointerPte->u.Hard.Valid == 1);
|
|
|
|
|
|
|
|
/* Get the original prototype PTE and turn it into a transition PTE */
|
|
|
|
PointerPte = Pfn1->PteAddress;
|
|
|
|
TempPte = *PointerPte;
|
|
|
|
TempPte.u.Soft.Transition = 1;
|
|
|
|
TempPte.u.Soft.Valid = 0;
|
|
|
|
TempPte.u.Soft.Prototype = 0;
|
|
|
|
TempPte.u.Soft.Protection = Pfn1->OriginalPte.u.Soft.Protection;
|
|
|
|
MI_WRITE_INVALID_PTE(PointerPte, TempPte);
|
2014-10-07 22:02:12 +00:00
|
|
|
DPRINT("Marking PTE: %p as transition (%p - %lx)\n", PointerPte, Pfn1, MiGetPfnEntryIndex(Pfn1));
|
2012-03-31 20:08:34 +00:00
|
|
|
}
|
2010-05-29 18:33:50 +00:00
|
|
|
|
|
|
|
/* Put the page in transition */
|
|
|
|
Pfn1->u3.e1.PageLocation = TransitionPage;
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-05-29 18:33:50 +00:00
|
|
|
/* PFN lock must be held */
|
|
|
|
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-05-29 18:33:50 +00:00
|
|
|
if (Pfn1->u3.e2.ReferenceCount == 1)
|
|
|
|
{
|
2012-03-31 20:08:34 +00:00
|
|
|
/* Is there still a PFN for this page? */
|
2014-11-15 22:47:51 +00:00
|
|
|
if (MI_IS_PFN_DELETED(Pfn1))
|
2012-03-31 20:08:34 +00:00
|
|
|
{
|
|
|
|
/* Clear the last reference */
|
|
|
|
Pfn1->u3.e2.ReferenceCount = 0;
|
|
|
|
ASSERT(Pfn1->OriginalPte.u.Soft.Prototype == 0);
|
|
|
|
|
|
|
|
/* Mark the page temporarily as valid, we're going to make it free soon */
|
|
|
|
Pfn1->u3.e1.PageLocation = ActiveAndValid;
|
|
|
|
|
|
|
|
/* Bring it back into the free list */
|
|
|
|
MiInsertPageInFreeList(PageFrameIndex);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* PFN not yet deleted, drop a ref count */
|
|
|
|
MiDecrementReferenceCount(Pfn1, PageFrameIndex);
|
|
|
|
}
|
2010-05-29 18:33:50 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Otherwise, just drop the reference count */
|
|
|
|
InterlockedDecrement16((PSHORT)&Pfn1->u3.e2.ReferenceCount);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
[NTOS]: Implement MiDecrementReferenceCount and rewrite large parts of the ProbeAndLock/Unlock MDL API to fully use ARM3 APIs, dropping MmReference/DereferencePage behind.
[NTOS]: Fix many MDL API bugs: correctly check for I/O pages, use LIST_HEAD instead of -1, track system-wide locked pages, use the process working set lock instead of the address space lock, add check for cross-ring MDL mappings, and make some small optimizations.
[NTOS]: Make some more fixes in MmAllocatePagesForMdl, MmFreeMdlPages to make the PFN entries more "correct".
[NTOS]: Had a little breakthrough: instead of complicating our lives and hiding certain ReactOS-Mm fields inside legitimate ARM3/MMPFN fields, differentiate between "legacy" (RosMm) and ARM3 pages. The legacy allocator (MmAllocPage/MmRequestPageMemoryConsumer) will use the non-paged pool to allocate a MMROSPFN add-on (8 bytes), in which the RMAP list head and SWAPENTRY are stored. When a legacy "free" is done, this data is deleted. Additionally, we can now tell apart between ARM3 and RosMm pages, so appropriate ASSERTs have been added to make sure the two never cross paths (which should safely let us use all the PFN fields now and implement working sets, etc...). I don't know why I didn't think of this sooner.
svn path=/trunk/; revision=49201
2010-10-19 04:30:48 +00:00
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
MiDecrementReferenceCount(IN PMMPFN Pfn1,
|
|
|
|
IN PFN_NUMBER PageFrameIndex)
|
|
|
|
{
|
|
|
|
/* PFN lock must be held */
|
|
|
|
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
|
|
|
|
|
|
|
|
/* Sanity checks on the page */
|
2013-11-22 12:10:20 +00:00
|
|
|
if (PageFrameIndex > MmHighestPhysicalPage ||
|
2013-10-01 17:51:38 +00:00
|
|
|
Pfn1 != MI_PFN_ELEMENT(PageFrameIndex) ||
|
|
|
|
Pfn1->u3.e2.ReferenceCount == 0 ||
|
|
|
|
Pfn1->u3.e2.ReferenceCount >= 2500)
|
|
|
|
{
|
|
|
|
DPRINT1("PageFrameIndex=0x%lx, MmHighestPhysicalPage=0x%lx\n", PageFrameIndex, MmHighestPhysicalPage);
|
|
|
|
DPRINT1("Pfn1=%p, Element=%p, RefCount=%u\n", Pfn1, MI_PFN_ELEMENT(PageFrameIndex), Pfn1->u3.e2.ReferenceCount);
|
2013-11-22 12:10:20 +00:00
|
|
|
ASSERT(PageFrameIndex <= MmHighestPhysicalPage);
|
2013-10-01 17:51:38 +00:00
|
|
|
ASSERT(Pfn1 == MI_PFN_ELEMENT(PageFrameIndex));
|
|
|
|
ASSERT(Pfn1->u3.e2.ReferenceCount != 0);
|
|
|
|
ASSERT(Pfn1->u3.e2.ReferenceCount < 2500);
|
|
|
|
}
|
[NTOS]: Implement MiDecrementReferenceCount and rewrite large parts of the ProbeAndLock/Unlock MDL API to fully use ARM3 APIs, dropping MmReference/DereferencePage behind.
[NTOS]: Fix many MDL API bugs: correctly check for I/O pages, use LIST_HEAD instead of -1, track system-wide locked pages, use the process working set lock instead of the address space lock, add check for cross-ring MDL mappings, and make some small optimizations.
[NTOS]: Make some more fixes in MmAllocatePagesForMdl, MmFreeMdlPages to make the PFN entries more "correct".
[NTOS]: Had a little breakthrough: instead of complicating our lives and hiding certain ReactOS-Mm fields inside legitimate ARM3/MMPFN fields, differentiate between "legacy" (RosMm) and ARM3 pages. The legacy allocator (MmAllocPage/MmRequestPageMemoryConsumer) will use the non-paged pool to allocate a MMROSPFN add-on (8 bytes), in which the RMAP list head and SWAPENTRY are stored. When a legacy "free" is done, this data is deleted. Additionally, we can now tell apart between ARM3 and RosMm pages, so appropriate ASSERTs have been added to make sure the two never cross paths (which should safely let us use all the PFN fields now and implement working sets, etc...). I don't know why I didn't think of this sooner.
svn path=/trunk/; revision=49201
2010-10-19 04:30:48 +00:00
|
|
|
|
|
|
|
/* Dereference the page, bail out if it's still alive */
|
|
|
|
InterlockedDecrement16((PSHORT)&Pfn1->u3.e2.ReferenceCount);
|
|
|
|
if (Pfn1->u3.e2.ReferenceCount) return;
|
|
|
|
|
|
|
|
/* Nobody should still have reference to this page */
|
|
|
|
if (Pfn1->u2.ShareCount != 0)
|
|
|
|
{
|
|
|
|
/* Otherwise something's really wrong */
|
|
|
|
KeBugCheckEx(PFN_LIST_CORRUPT, 7, PageFrameIndex, Pfn1->u2.ShareCount, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* And it should be lying on some page list */
|
|
|
|
ASSERT(Pfn1->u3.e1.PageLocation != ActiveAndValid);
|
|
|
|
|
|
|
|
/* Did someone set the delete flag? */
|
|
|
|
if (MI_IS_PFN_DELETED(Pfn1))
|
|
|
|
{
|
|
|
|
/* Insert it into the free list, there's nothing left to do */
|
|
|
|
MiInsertPageInFreeList(PageFrameIndex);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-03-31 20:08:34 +00:00
|
|
|
/* Check to see which list this page should go into */
|
|
|
|
if (Pfn1->u3.e1.Modified == 1)
|
|
|
|
{
|
|
|
|
/* Push it into the modified page list */
|
|
|
|
MiInsertPageInList(&MmModifiedPageListHead, PageFrameIndex);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Otherwise, insert this page into the standby list */
|
|
|
|
ASSERT(Pfn1->u3.e1.RemovalRequested == 0);
|
|
|
|
MiInsertStandbyListAtFront(PageFrameIndex);
|
|
|
|
}
|
[NTOS]: Implement MiDecrementReferenceCount and rewrite large parts of the ProbeAndLock/Unlock MDL API to fully use ARM3 APIs, dropping MmReference/DereferencePage behind.
[NTOS]: Fix many MDL API bugs: correctly check for I/O pages, use LIST_HEAD instead of -1, track system-wide locked pages, use the process working set lock instead of the address space lock, add check for cross-ring MDL mappings, and make some small optimizations.
[NTOS]: Make some more fixes in MmAllocatePagesForMdl, MmFreeMdlPages to make the PFN entries more "correct".
[NTOS]: Had a little breakthrough: instead of complicating our lives and hiding certain ReactOS-Mm fields inside legitimate ARM3/MMPFN fields, differentiate between "legacy" (RosMm) and ARM3 pages. The legacy allocator (MmAllocPage/MmRequestPageMemoryConsumer) will use the non-paged pool to allocate a MMROSPFN add-on (8 bytes), in which the RMAP list head and SWAPENTRY are stored. When a legacy "free" is done, this data is deleted. Additionally, we can now tell apart between ARM3 and RosMm pages, so appropriate ASSERTs have been added to make sure the two never cross paths (which should safely let us use all the PFN fields now and implement working sets, etc...). I don't know why I didn't think of this sooner.
svn path=/trunk/; revision=49201
2010-10-19 04:30:48 +00:00
|
|
|
}
|
|
|
|
|
2010-06-04 22:08:40 +00:00
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
MiInitializePfnForOtherProcess(IN PFN_NUMBER PageFrameIndex,
|
2015-05-10 19:35:00 +00:00
|
|
|
IN PVOID PteAddress,
|
2010-06-04 22:08:40 +00:00
|
|
|
IN PFN_NUMBER PteFrame)
|
|
|
|
{
|
|
|
|
PMMPFN Pfn1;
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-06-04 22:08:40 +00:00
|
|
|
/* Setup the PTE */
|
2010-11-11 13:13:05 +00:00
|
|
|
Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);
|
2015-05-10 19:35:00 +00:00
|
|
|
Pfn1->PteAddress = PteAddress;
|
2010-10-04 18:22:50 +00:00
|
|
|
|
2010-06-04 22:08:40 +00:00
|
|
|
/* Make this a software PTE */
|
|
|
|
MI_MAKE_SOFTWARE_PTE(&Pfn1->OriginalPte, MM_READWRITE);
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-06-04 22:08:40 +00:00
|
|
|
/* Setup the page */
|
|
|
|
ASSERT(Pfn1->u3.e2.ReferenceCount == 0);
|
|
|
|
Pfn1->u3.e2.ReferenceCount = 1;
|
|
|
|
Pfn1->u2.ShareCount = 1;
|
|
|
|
Pfn1->u3.e1.PageLocation = ActiveAndValid;
|
|
|
|
Pfn1->u3.e1.Modified = TRUE;
|
|
|
|
Pfn1->u4.InPageError = FALSE;
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-06-04 22:08:40 +00:00
|
|
|
/* Did we get a PFN for the page table */
|
|
|
|
if (PteFrame)
|
|
|
|
{
|
|
|
|
/* Store it */
|
|
|
|
Pfn1->u4.PteFrame = PteFrame;
|
2010-12-26 15:23:03 +00:00
|
|
|
|
|
|
|
/* Increase its share count so we don't get rid of it */
|
2010-11-11 13:13:05 +00:00
|
|
|
Pfn1 = MI_PFN_ELEMENT(PteFrame);
|
2010-06-04 22:08:40 +00:00
|
|
|
Pfn1->u2.ShareCount++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-02-20 14:40:21 +00:00
|
|
|
/* EOF */
|