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>
|
|
|
|
|
|
|
|
#line 15 "ARM³::PFNLIST"
|
|
|
|
#define MODULE_INVOLVED_IN_ARM3
|
|
|
|
#include "../ARM3/miarm.h"
|
|
|
|
|
2010-06-04 22:08:40 +00:00
|
|
|
#if DBG
|
2010-06-01 09:22:10 +00:00
|
|
|
#define ASSERT_LIST_INVARIANT(x) \
|
|
|
|
do { \
|
|
|
|
ASSERT(((x)->Total == 0 && \
|
|
|
|
(x)->Flink == LIST_HEAD && \
|
|
|
|
(x)->Blink == LIST_HEAD) || \
|
|
|
|
((x)->Total != 0 && \
|
|
|
|
(x)->Flink != LIST_HEAD && \
|
|
|
|
(x)->Blink != LIST_HEAD)); \
|
|
|
|
} 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
|
|
|
|
[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};
|
|
|
|
MMPFNLIST MmModifiedPageListHead = {0, ModifiedPageList, LIST_HEAD, LIST_HEAD};
|
|
|
|
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-02-20 14:40:21 +00:00
|
|
|
/* FUNCTIONS ******************************************************************/
|
|
|
|
|
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-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
|
|
|
/* 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);
|
|
|
|
|
|
|
|
/* 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-02-20 14:40:21 +00:00
|
|
|
|
|
|
|
/* Get the forward and back pointers */
|
|
|
|
OldFlink = Entry->u1.Flink;
|
|
|
|
OldBlink = Entry->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 */
|
|
|
|
MiGetPfnEntry(OldFlink)->u2.Blink = OldBlink;
|
|
|
|
}
|
|
|
|
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
|
|
|
}
|
|
|
|
|
|
|
|
/* 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 */
|
|
|
|
MiGetPfnEntry(OldBlink)->u1.Flink = OldFlink;
|
|
|
|
}
|
|
|
|
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-09-29 00:13:09 +00:00
|
|
|
MiGetPfnEntry(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 */
|
|
|
|
Pfn1 = MiGetPfnEntry(Entry->u4.PteFrame);
|
|
|
|
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 */
|
|
|
|
Pfn1 = MiGetPfnEntry(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-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);
|
|
|
|
|
[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
|
|
|
/* 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 */
|
|
|
|
if (--MmAvailablePages < MmMinimumFreePages)
|
|
|
|
{
|
|
|
|
/* FIXME: Should wake up the MPW and working set manager, if we had one */
|
|
|
|
}
|
2010-02-20 14:40:21 +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;
|
|
|
|
ULONG OldColor, OldCache;
|
|
|
|
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 */
|
|
|
|
Pfn1 = MiGetPfnEntry(PageIndex);
|
|
|
|
ASSERT(Pfn1->u3.e1.RemovalRequested == 0);
|
|
|
|
ASSERT(Pfn1->u3.e1.Rom == 0);
|
|
|
|
|
|
|
|
/* 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);
|
|
|
|
|
|
|
|
/* Remove a page */
|
|
|
|
ListHead->Total--;
|
|
|
|
|
|
|
|
/* Get the forward and back pointers */
|
|
|
|
OldFlink = Pfn1->u1.Flink;
|
|
|
|
OldBlink = Pfn1->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 */
|
|
|
|
MiGetPfnEntry(OldFlink)->u2.Blink = OldBlink;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Set the list head's backlink instead */
|
|
|
|
ListHead->Blink = OldFlink;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* 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 */
|
|
|
|
MiGetPfnEntry(OldBlink)->u1.Flink = OldFlink;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Set the list head's backlink instead */
|
|
|
|
ListHead->Flink = OldFlink;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* We are not on a list anymore */
|
2010-06-04 22:08:40 +00:00
|
|
|
ASSERT_LIST_INVARIANT(ListHead);
|
2010-05-09 18:12:50 +00:00
|
|
|
Pfn1->u1.Flink = Pfn1->u2.Blink = 0;
|
|
|
|
|
|
|
|
/* 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);
|
|
|
|
|
|
|
|
/* Set the forward link to whoever we were pointing to */
|
|
|
|
ColorTable->Flink = Pfn1->OriginalPte.u.Long;
|
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-09-28 22:41:46 +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-09-29 00:13:09 +00:00
|
|
|
MiGetPfnEntry(ColorTable->Flink)->u4.PteFrame = COLORED_LIST_HEAD;
|
2010-05-09 18:12:50 +00:00
|
|
|
}
|
|
|
|
|
2010-09-28 22:41:46 +00:00
|
|
|
/* One less page */
|
|
|
|
ColorTable->Count--;
|
2010-09-29 00:13:09 +00:00
|
|
|
|
|
|
|
/* ReactOS Hack */
|
|
|
|
Pfn1->OriginalPte.u.Long = 0;
|
2010-09-29 01:10:28 +00:00
|
|
|
|
2010-05-09 18:12:50 +00:00
|
|
|
/* 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 */
|
|
|
|
if (--MmAvailablePages < MmMinimumFreePages)
|
|
|
|
{
|
|
|
|
/* FIXME: Should wake up the MPW and working set manager, if we had one */
|
|
|
|
}
|
|
|
|
|
|
|
|
/* 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-09-29 01:10:28 +00:00
|
|
|
#if 0
|
2010-05-09 18:12:50 +00:00
|
|
|
/* Check the colored free list */
|
|
|
|
PageIndex = MmFreePagesByColor[FreePageList][Color].Flink;
|
2010-09-30 03:17:14 +00:00
|
|
|
DPRINT1("Found free page: %lx\n", PageIndex);
|
2010-05-09 18:12:50 +00:00
|
|
|
if (PageIndex == LIST_HEAD)
|
|
|
|
{
|
|
|
|
/* Check the colored zero list */
|
|
|
|
PageIndex = MmFreePagesByColor[ZeroedPageList][Color].Flink;
|
2010-09-30 03:17:14 +00:00
|
|
|
DPRINT1("Found zero page: %lx\n", PageIndex);
|
2010-05-09 18:12:50 +00:00
|
|
|
if (PageIndex == LIST_HEAD)
|
|
|
|
{
|
|
|
|
#endif
|
|
|
|
/* 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-09-29 01:10:28 +00:00
|
|
|
#if 0
|
2010-05-09 18:12:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
/* Remove the page from its list */
|
|
|
|
PageIndex = MiRemovePageByColor(PageIndex, Color);
|
|
|
|
|
|
|
|
/* Sanity checks */
|
|
|
|
Pfn1 = MiGetPfnEntry(PageIndex);
|
|
|
|
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-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;
|
|
|
|
BOOLEAN Zero;
|
|
|
|
|
|
|
|
/* 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 */
|
2010-09-29 01:10:28 +00:00
|
|
|
#if 0
|
2010-06-06 14:12:28 +00:00
|
|
|
PageIndex = MmFreePagesByColor[ZeroedPageList][Color].Flink;
|
|
|
|
if (PageIndex == LIST_HEAD)
|
|
|
|
{
|
|
|
|
#endif
|
|
|
|
/* Check the zero list */
|
|
|
|
ASSERT_LIST_INVARIANT(&MmZeroedPageListHead);
|
|
|
|
PageIndex = MmZeroedPageListHead.Flink;
|
|
|
|
Color = PageIndex & MmSecondaryColorMask;
|
|
|
|
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-09-29 01:10:28 +00:00
|
|
|
#if 0
|
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)
|
|
|
|
{
|
|
|
|
#endif
|
|
|
|
/* 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-09-29 01:10:28 +00:00
|
|
|
#if 0
|
2010-06-06 14:12:28 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
2010-09-29 01:10:28 +00:00
|
|
|
#if 0
|
2010-06-06 14:12:28 +00:00
|
|
|
}
|
|
|
|
#endif
|
2010-09-29 01:10:28 +00:00
|
|
|
|
2010-06-06 14:12:28 +00:00
|
|
|
/* Sanity checks */
|
|
|
|
Pfn1 = MiGetPfnEntry(PageIndex);
|
|
|
|
ASSERT((Pfn1->u3.e1.PageLocation == FreePageList) ||
|
|
|
|
(Pfn1->u3.e1.PageLocation == ZeroedPageList));
|
|
|
|
|
|
|
|
/* Remove the page from its list */
|
|
|
|
PageIndex = MiRemovePageByColor(PageIndex, Color);
|
|
|
|
ASSERT(Pfn1 == MiGetPfnEntry(PageIndex));
|
|
|
|
|
|
|
|
/* Zero it, if needed */
|
|
|
|
if (Zero) MiZeroPhysicalPage(PageIndex);
|
|
|
|
|
|
|
|
/* 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
|
|
|
|
|
|
|
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-05-12 19:11:49 +00:00
|
|
|
Pfn1 = MiGetPfnEntry(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);
|
|
|
|
|
|
|
|
/* 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-05-12 19:11:49 +00:00
|
|
|
MiGetPfnEntry(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;
|
|
|
|
|
2010-05-12 19:11:49 +00:00
|
|
|
/* Increase available pages */
|
|
|
|
MmAvailablePages++;
|
2010-02-21 03:52:22 +00:00
|
|
|
|
|
|
|
/* 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);
|
|
|
|
}
|
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-02-20 14:40:21 +00:00
|
|
|
|
|
|
|
/* Make it link to us */
|
2010-09-28 22:41:46 +00:00
|
|
|
Pfn1->u4.PteFrame = MiGetPfnEntryIndex(Blink);
|
|
|
|
|
|
|
|
/* If there is an original pte, it should be an old link, NOT a ReactOS RMAP */
|
[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
|
|
|
ASSERT(Blink->u4.AweAllocation == FALSE);
|
2010-02-20 14:40:21 +00:00
|
|
|
Blink->OriginalPte.u.Long = PageFrameIndex;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* 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
|
|
|
|
|
|
|
/* If there is an original pte, it should be an old link, NOT a ReactOS RMAP */
|
[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
|
|
|
ASSERT(Pfn1->u4.AweAllocation == FALSE);
|
2010-02-21 03:52:22 +00:00
|
|
|
Pfn1->OriginalPte.u.Long = LIST_HEAD;
|
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 */
|
|
|
|
MmZeroingPageThreadActive = TRUE;
|
|
|
|
KeSetEvent(&MmZeroingPageEvent, IO_NO_INCREMENT, FALSE);
|
2010-05-12 19:11:49 +00:00
|
|
|
}
|
2010-02-20 14:40:21 +00:00
|
|
|
}
|
|
|
|
|
2010-09-28 14:38:30 +00:00
|
|
|
/* Note: This function is hardcoded only for the zeroed page list, for now */
|
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
MiInsertPageInList(IN PMMPFNLIST ListHead,
|
|
|
|
IN PFN_NUMBER PageFrameIndex)
|
|
|
|
{
|
|
|
|
PFN_NUMBER Flink;
|
|
|
|
PMMPFN Pfn1, Pfn2;
|
|
|
|
MMLISTS ListName;
|
2010-09-28 22:41:46 +00:00
|
|
|
PMMCOLOR_TABLES ColorHead;
|
|
|
|
ULONG Color;
|
2010-09-29 01:10:28 +00:00
|
|
|
|
2010-09-28 14:38:30 +00:00
|
|
|
/* For free pages, use MiInsertPageInFreeList */
|
|
|
|
ASSERT(ListHead != &MmFreePageListHead);
|
|
|
|
|
|
|
|
/* Make sure the lock is held */
|
|
|
|
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
|
|
|
|
|
|
|
|
/* Make sure the PFN is valid */
|
|
|
|
ASSERT((PageFrameIndex) &&
|
|
|
|
(PageFrameIndex <= MmHighestPhysicalPage) &&
|
|
|
|
(PageFrameIndex >= MmLowestPhysicalPage));
|
|
|
|
|
|
|
|
/* Page should be unused */
|
|
|
|
Pfn1 = MiGetPfnEntry(PageFrameIndex);
|
|
|
|
ASSERT(Pfn1->u3.e2.ReferenceCount == 0);
|
|
|
|
ASSERT(Pfn1->u3.e1.Rom != 1);
|
|
|
|
|
|
|
|
/* Only used for zero pages in ReactOS */
|
|
|
|
ListName = ListHead->ListName;
|
|
|
|
ASSERT(ListName == ZeroedPageList);
|
|
|
|
ListHead->Total++;
|
|
|
|
|
|
|
|
/* Don't handle bad pages yet yet */
|
|
|
|
ASSERT(Pfn1->u3.e1.RemovalRequested == 0);
|
|
|
|
|
|
|
|
/* 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 = MiGetPfnEntry(Flink);
|
|
|
|
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 */
|
|
|
|
Pfn1->u3.e1.PageLocation = ListName;
|
|
|
|
|
|
|
|
/* One more page on the system */
|
|
|
|
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);
|
|
|
|
}
|
2010-09-28 22:41:46 +00:00
|
|
|
|
2010-09-29 01:10:28 +00:00
|
|
|
/* Sanity checks */
|
2010-09-28 22:41:46 +00:00
|
|
|
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;
|
|
|
|
|
|
|
|
/* If there is an original pte, it should be an old link, NOT a ReactOS RMAP */
|
[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
|
|
|
ASSERT(Pfn1->u4.AweAllocation == FALSE);
|
2010-09-28 14:38:30 +00:00
|
|
|
|
2010-09-28 22:41:46 +00:00
|
|
|
/* Make this page point back to the list, and point forwards to the old head */
|
|
|
|
Pfn1->OriginalPte.u.Long = Flink;
|
2010-09-29 00:13:09 +00:00
|
|
|
Pfn1->u4.PteFrame = COLORED_LIST_HEAD;
|
2010-09-28 22:41:46 +00:00
|
|
|
|
|
|
|
/* 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 = MiGetPfnEntry(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-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 */
|
|
|
|
Pfn1 = MiGetPfnEntry(PageFrameIndex);
|
|
|
|
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-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 */
|
|
|
|
Pfn1 = MiGetPfnEntry(PageFrameIndex);
|
|
|
|
Pfn1->u2.ShareCount++;
|
|
|
|
}
|
|
|
|
|
2010-05-30 03:02:39 +00:00
|
|
|
PFN_NUMBER
|
|
|
|
NTAPI
|
|
|
|
MiAllocatePfn(IN PMMPTE PointerPte,
|
|
|
|
IN ULONG Protection)
|
|
|
|
{
|
|
|
|
KIRQL OldIrql;
|
|
|
|
PFN_NUMBER PageFrameIndex;
|
|
|
|
MMPTE TempPte;
|
2010-06-06 18:45:46 +00:00
|
|
|
|
|
|
|
/* Sanity check that we aren't passed a valid PTE */
|
|
|
|
ASSERT(PointerPte->u.Hard.Valid == 0);
|
2010-05-30 03:02:39 +00:00
|
|
|
|
|
|
|
/* Make an empty software PTE */
|
|
|
|
MI_MAKE_SOFTWARE_PTE(&TempPte, MM_READWRITE);
|
|
|
|
|
|
|
|
/* Lock the PFN database */
|
|
|
|
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
|
|
|
|
|
|
|
/* Check if we're running low on pages */
|
|
|
|
if (MmAvailablePages < 128)
|
|
|
|
{
|
|
|
|
DPRINT1("Warning, running low on memory: %d pages left\n", MmAvailablePages);
|
|
|
|
//MiEnsureAvailablePageOrWait(NULL, OldIrql);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Grab a page */
|
2010-06-01 15:08:14 +00:00
|
|
|
ASSERT_LIST_INVARIANT(&MmFreePageListHead);
|
|
|
|
ASSERT_LIST_INVARIANT(&MmZeroedPageListHead);
|
2010-09-29 01:10:28 +00:00
|
|
|
PageFrameIndex = MiRemoveAnyPage(MI_GET_NEXT_COLOR());
|
2010-06-01 15:08:14 +00:00
|
|
|
|
2010-05-30 03:02:39 +00:00
|
|
|
/* Write the software PTE */
|
2010-06-06 18:45:46 +00:00
|
|
|
MI_WRITE_INVALID_PTE(PointerPte, TempPte);
|
2010-05-30 03:02:39 +00:00
|
|
|
PointerPte->u.Soft.Protection |= Protection;
|
|
|
|
|
|
|
|
/* Initialize its PFN entry */
|
|
|
|
MiInitializePfn(PageFrameIndex, PointerPte, TRUE);
|
|
|
|
|
|
|
|
/* Release the PFN lock and return the page */
|
2010-06-01 15:08:14 +00:00
|
|
|
ASSERT_LIST_INVARIANT(&MmFreePageListHead);
|
|
|
|
ASSERT_LIST_INVARIANT(&MmZeroedPageListHead);
|
2010-05-30 03:02:39 +00:00
|
|
|
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
|
|
|
return PageFrameIndex;
|
|
|
|
}
|
|
|
|
|
2010-05-29 18:33:50 +00:00
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
MiDecrementShareCount(IN PMMPFN Pfn1,
|
|
|
|
IN PFN_NUMBER PageFrameIndex)
|
|
|
|
{
|
|
|
|
ASSERT(PageFrameIndex > 0);
|
|
|
|
ASSERT(MiGetPfnEntry(PageFrameIndex) != NULL);
|
|
|
|
ASSERT(Pfn1 == MiGetPfnEntry(PageFrameIndex));
|
|
|
|
|
|
|
|
/* 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);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check if the share count is now 0 */
|
|
|
|
ASSERT(Pfn1->u2.ShareCount < 0xF000000);
|
|
|
|
if (!--Pfn1->u2.ShareCount)
|
|
|
|
{
|
|
|
|
/* ReactOS does not handle these */
|
|
|
|
ASSERT(Pfn1->u3.e1.PrototypePte == 0);
|
|
|
|
|
|
|
|
/* Put the page in transition */
|
|
|
|
Pfn1->u3.e1.PageLocation = TransitionPage;
|
|
|
|
|
|
|
|
/* PFN lock must be held */
|
|
|
|
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
|
|
|
|
|
|
|
|
/* Page should at least have one reference */
|
|
|
|
ASSERT(Pfn1->u3.e2.ReferenceCount != 0);
|
|
|
|
if (Pfn1->u3.e2.ReferenceCount == 1)
|
|
|
|
{
|
|
|
|
/* In ReactOS, this path should always be hit with a deleted PFN */
|
|
|
|
ASSERT(MI_IS_PFN_DELETED(Pfn1) == TRUE);
|
|
|
|
|
|
|
|
/* Clear the last reference */
|
|
|
|
Pfn1->u3.e2.ReferenceCount = 0;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* OriginalPte is used by AweReferenceCount in ReactOS, but either
|
|
|
|
* ways we shouldn't be seeing RMAP entries at this point
|
|
|
|
*/
|
|
|
|
ASSERT(Pfn1->OriginalPte.u.Soft.Prototype == 0);
|
[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
|
|
|
ASSERT(Pfn1->u4.AweAllocation == FALSE);
|
2010-05-29 18:33:50 +00:00
|
|
|
|
|
|
|
/* 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
|
|
|
|
{
|
|
|
|
/* 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 */
|
|
|
|
ASSERT(PageFrameIndex < MmHighestPhysicalPage);
|
|
|
|
ASSERT(Pfn1 == MiGetPfnEntry(PageFrameIndex));
|
|
|
|
ASSERT(Pfn1->u3.e2.ReferenceCount != 0);
|
|
|
|
|
|
|
|
/* 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;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* We don't have a modified list yet */
|
|
|
|
ASSERT(Pfn1->u3.e1.Modified == 0);
|
|
|
|
ASSERT(Pfn1->u3.e1.RemovalRequested == 0);
|
|
|
|
|
|
|
|
/* FIXME: Normally it would go on the standby list, but we're pushing it on the free list */
|
|
|
|
MiInsertPageInFreeList(PageFrameIndex);
|
|
|
|
}
|
|
|
|
|
2010-06-04 22:08:40 +00:00
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
MiInitializePfnForOtherProcess(IN PFN_NUMBER PageFrameIndex,
|
|
|
|
IN PMMPTE PointerPte,
|
|
|
|
IN PFN_NUMBER PteFrame)
|
|
|
|
{
|
|
|
|
PMMPFN Pfn1;
|
|
|
|
|
|
|
|
/* Setup the PTE */
|
|
|
|
Pfn1 = MiGetPfnEntry(PageFrameIndex);
|
|
|
|
Pfn1->PteAddress = PointerPte;
|
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);
|
|
|
|
|
|
|
|
/* 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;
|
|
|
|
|
|
|
|
/* Did we get a PFN for the page table */
|
|
|
|
if (PteFrame)
|
|
|
|
{
|
|
|
|
/* Store it */
|
|
|
|
Pfn1->u4.PteFrame = PteFrame;
|
|
|
|
|
|
|
|
/* Increase its share count so we don't get rid of it */
|
2010-06-05 14:55:17 +00:00
|
|
|
Pfn1 = MiGetPfnEntry(PteFrame);
|
2010-06-04 22:08:40 +00:00
|
|
|
Pfn1->u2.ShareCount++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-02-20 14:40:21 +00:00
|
|
|
/* EOF */
|