ReactOS 0.4.16-dev-340-g0540c21
pfnlist.c File Reference
#include <ntoskrnl.h>
#include <debug.h>
#include <mm/ARM3/miarm.h>
Include dependency graph for pfnlist.c:

Go to the source code of this file.

Macros

#define NDEBUG
 
#define MODULE_INVOLVED_IN_ARM3
 
#define ASSERT_LIST_INVARIANT(x)
 

Functions

static VOID MiIncrementAvailablePages (VOID)
 
static VOID MiDecrementAvailablePages (VOID)
 
VOID NTAPI MiZeroPhysicalPage (IN PFN_NUMBER PageFrameIndex)
 
VOID NTAPI MiUnlinkFreeOrZeroedPage (IN PMMPFN Entry)
 
VOID NTAPI MiUnlinkPageFromList (IN PMMPFN Pfn)
 
PFN_NUMBER NTAPI MiRemovePageByColor (IN PFN_NUMBER PageIndex, IN ULONG Color)
 
PFN_NUMBER NTAPI MiRemoveAnyPage (IN ULONG Color)
 
PFN_NUMBER NTAPI MiRemoveZeroPage (IN ULONG Color)
 
VOID NTAPI MiInsertPageInFreeList (IN PFN_NUMBER PageFrameIndex)
 
VOID FASTCALL MiInsertStandbyListAtFront (IN PFN_NUMBER PageFrameIndex)
 
VOID NTAPI MiInsertPageInList (IN PMMPFNLIST ListHead, IN PFN_NUMBER PageFrameIndex)
 
VOID NTAPI MiInitializePfn (IN PFN_NUMBER PageFrameIndex, IN PMMPTE PointerPte, IN BOOLEAN Modified)
 
VOID NTAPI MiInitializePfnAndMakePteValid (IN PFN_NUMBER PageFrameIndex, IN PMMPTE PointerPte, IN MMPTE TempPte)
 
NTSTATUS NTAPI MiInitializeAndChargePfn (OUT PPFN_NUMBER PageFrameIndex, IN PMMPDE PointerPde, IN PFN_NUMBER ContainingPageFrame, IN BOOLEAN SessionAllocation)
 
VOID NTAPI MiDecrementShareCount (IN PMMPFN Pfn1, IN PFN_NUMBER PageFrameIndex)
 
VOID NTAPI MmDereferencePage (PFN_NUMBER Pfn)
 
VOID NTAPI MiDecrementReferenceCount (IN PMMPFN Pfn1, IN PFN_NUMBER PageFrameIndex)
 
VOID NTAPI MiInitializePfnForOtherProcess (IN PFN_NUMBER PageFrameIndex, IN PVOID PteAddress, IN PFN_NUMBER PteFrame)
 

Variables

BOOLEAN MmDynamicPfn
 
BOOLEAN MmMirroring
 
ULONG MmSystemPageColor
 
ULONG MmTransitionSharedPages
 
ULONG MmTotalPagesForPagingFile
 
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 MmStandbyPageListByPriority [8]
 
MMPFNLIST MmModifiedPageListHead = {0, ModifiedPageList, LIST_HEAD, LIST_HEAD}
 
MMPFNLIST MmModifiedPageListByColor [1] = {{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}
 
PMMPFNLIST MmPageLocationList []
 
ULONG MI_PFN_CURRENT_USAGE
 
CHAR MI_PFN_CURRENT_PROCESS_NAME [16] = "None yet"
 

Macro Definition Documentation

◆ ASSERT_LIST_INVARIANT

#define ASSERT_LIST_INVARIANT (   x)

Definition at line 29 of file pfnlist.c.

◆ MODULE_INVOLVED_IN_ARM3

#define MODULE_INVOLVED_IN_ARM3

Definition at line 15 of file pfnlist.c.

◆ NDEBUG

#define NDEBUG

Definition at line 12 of file pfnlist.c.

Function Documentation

◆ MiDecrementAvailablePages()

static VOID MiDecrementAvailablePages ( VOID  )
static

Definition at line 90 of file pfnlist.c.

92{
94
95 /* See if we hit any thresholds */
97 {
98 /* Clear the high memory event */
100 }
102 {
103 /* Signal the low memory event */
105 }
106
107 /* One less page */
110 {
111 /* FIXME: Should wake up the MPW and working set manager, if we had one */
112
113 DPRINT1("Running low on pages: %lu remaining\n", MmAvailablePages);
114
115 /* Call RosMm and see if it can release any pages for us */
117 }
118}
#define DPRINT1
Definition: precomp.h:8
#define FALSE
Definition: types.h:117
#define KeSetEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:476
VOID NTAPI KeClearEvent(IN PKEVENT Event)
Definition: eventobj.c:22
PFN_NUMBER MmLowMemoryThreshold
Definition: mminit.c:300
PFN_NUMBER MmMinimumFreePages
Definition: mminit.c:314
PKEVENT MiHighMemoryEvent
Definition: mminit.c:293
PKEVENT MiLowMemoryEvent
Definition: mminit.c:292
PFN_NUMBER MmHighMemoryThreshold
Definition: mminit.c:301
#define ASSERT(a)
Definition: mode.c:44
VOID NTAPI MmRebalanceMemoryConsumers(VOID)
Definition: balance.c:290
PFN_NUMBER MmAvailablePages
Definition: freelist.c:26

Referenced by MiRemovePageByColor(), MiUnlinkFreeOrZeroedPage(), and MiUnlinkPageFromList().

◆ MiDecrementReferenceCount()

VOID NTAPI MiDecrementReferenceCount ( IN PMMPFN  Pfn1,
IN PFN_NUMBER  PageFrameIndex 
)

Definition at line 1236 of file pfnlist.c.

1238{
1239 /* PFN lock must be held */
1241
1242 /* Handle RosMm PFNs here, too (in case they got locked/unlocked by ARM3) */
1243 if (MI_IS_ROS_PFN(Pfn1))
1244 {
1245 MmDereferencePage(PageFrameIndex);
1246 return;
1247 }
1248
1249 /* Sanity checks on the page */
1250 if (PageFrameIndex > MmHighestPhysicalPage ||
1251 Pfn1 != MI_PFN_ELEMENT(PageFrameIndex) ||
1252 Pfn1->u3.e2.ReferenceCount == 0 ||
1253 Pfn1->u3.e2.ReferenceCount >= 2500)
1254 {
1255 DPRINT1("PageFrameIndex=0x%lx, MmHighestPhysicalPage=0x%lx\n", PageFrameIndex, MmHighestPhysicalPage);
1256 DPRINT1("Pfn1=%p, Element=%p, RefCount=%u\n", Pfn1, MI_PFN_ELEMENT(PageFrameIndex), Pfn1->u3.e2.ReferenceCount);
1257 ASSERT(PageFrameIndex <= MmHighestPhysicalPage);
1258 ASSERT(Pfn1 == MI_PFN_ELEMENT(PageFrameIndex));
1259 ASSERT(Pfn1->u3.e2.ReferenceCount != 0);
1260 ASSERT(Pfn1->u3.e2.ReferenceCount < 2500);
1261 }
1262
1263 /* Dereference the page, bail out if it's still alive */
1264 InterlockedDecrement16((PSHORT)&Pfn1->u3.e2.ReferenceCount);
1265 if (Pfn1->u3.e2.ReferenceCount) return;
1266
1267 /* Nobody should still have reference to this page */
1268 if (Pfn1->u2.ShareCount != 0)
1269 {
1270 /* Otherwise something's really wrong */
1271 KeBugCheckEx(PFN_LIST_CORRUPT, 7, PageFrameIndex, Pfn1->u2.ShareCount, 0);
1272 }
1273
1274 /* And it should be lying on some page list */
1275 ASSERT(Pfn1->u3.e1.PageLocation != ActiveAndValid);
1276
1277 /* Did someone set the delete flag? */
1278 if (MI_IS_PFN_DELETED(Pfn1))
1279 {
1280 /* Insert it into the free list, there's nothing left to do */
1281 MiInsertPageInFreeList(PageFrameIndex);
1282 return;
1283 }
1284
1285 /* Check to see which list this page should go into */
1286 if (Pfn1->u3.e1.Modified == 1)
1287 {
1288 /* Push it into the modified page list */
1290 }
1291 else
1292 {
1293 /* Otherwise, insert this page into the standby list */
1294 ASSERT(Pfn1->u3.e1.RemovalRequested == 0);
1295 MiInsertStandbyListAtFront(PageFrameIndex);
1296 }
1297}
#define InterlockedDecrement16
Definition: interlocked.h:139
PFN_NUMBER MmHighestPhysicalPage
Definition: meminit.c:31
#define MI_IS_ROS_PFN(x)
Definition: miarm.h:1116
#define MI_IS_PFN_DELETED(x)
Definition: miarm.h:209
FORCEINLINE PMMPFN MI_PFN_ELEMENT(IN PFN_NUMBER Pfn)
Definition: miarm.h:1587
@ ActiveAndValid
Definition: mmtypes.h:159
#define MI_ASSERT_PFN_LOCK_HELD()
Definition: mm.h:1043
VOID NTAPI MiInsertPageInFreeList(IN PFN_NUMBER PageFrameIndex)
Definition: pfnlist.c:611
VOID NTAPI MmDereferencePage(PFN_NUMBER Pfn)
Definition: freelist.c:566
MMPFNLIST MmModifiedPageListHead
Definition: pfnlist.c:45
VOID NTAPI MiInsertPageInList(IN PMMPFNLIST ListHead, IN PFN_NUMBER PageFrameIndex)
Definition: pfnlist.c:779
VOID FASTCALL MiInsertStandbyListAtFront(IN PFN_NUMBER PageFrameIndex)
Definition: pfnlist.c:719
VOID NTAPI KeBugCheckEx(_In_ ULONG BugCheckCode, _In_ ULONG_PTR BugCheckParameter1, _In_ ULONG_PTR BugCheckParameter2, _In_ ULONG_PTR BugCheckParameter3, _In_ ULONG_PTR BugCheckParameter4)
Definition: rtlcompat.c:108
struct _MMPFN::@1805::@1811 e2
union _MMPFN::@1805 u3
int16_t * PSHORT
Definition: typedefs.h:55

Referenced by MiDecrementShareCount(), MiDeletePte(), MiDereferencePfnAndDropLockCount(), and MmFreePagesFromMdl().

◆ MiDecrementShareCount()

VOID NTAPI MiDecrementShareCount ( IN PMMPFN  Pfn1,
IN PFN_NUMBER  PageFrameIndex 
)

Definition at line 1141 of file pfnlist.c.

1143{
1144 PMMPTE PointerPte;
1145 MMPTE TempPte;
1146
1147 ASSERT(PageFrameIndex > 0);
1148 ASSERT(MI_PFN_ELEMENT(PageFrameIndex) != NULL);
1149 ASSERT(Pfn1 == MI_PFN_ELEMENT(PageFrameIndex));
1150 ASSERT(MI_IS_ROS_PFN(Pfn1) == FALSE);
1151
1152 DPRINT("Decrementing %p from %p\n", Pfn1, _ReturnAddress());
1153
1154 /* Page must be in-use */
1155 if ((Pfn1->u3.e1.PageLocation != ActiveAndValid) &&
1156 (Pfn1->u3.e1.PageLocation != StandbyPageList))
1157 {
1158 /* Otherwise we have PFN corruption */
1159 KeBugCheckEx(PFN_LIST_CORRUPT,
1160 0x99,
1161 PageFrameIndex,
1162 Pfn1->u3.e1.PageLocation,
1163 0);
1164 }
1165
1166 /* Page should at least have one reference */
1167 ASSERT(Pfn1->u3.e2.ReferenceCount != 0);
1168
1169 /* Check if the share count is now 0 */
1170 ASSERT(Pfn1->u2.ShareCount < 0xF000000);
1171 if (!--Pfn1->u2.ShareCount)
1172 {
1173 /* Was this a prototype PTE? */
1174 if (Pfn1->u3.e1.PrototypePte)
1175 {
1176 /* Grab the PTE address and make sure it's in prototype pool */
1177 PointerPte = Pfn1->PteAddress;
1178 ASSERT((PointerPte >= (PMMPTE)MmPagedPoolStart) && (PointerPte <= (PMMPTE)MmPagedPoolEnd));
1179
1180 /* The PTE that backs it should also be valdi */
1181 PointerPte = MiAddressToPte(PointerPte);
1182 ASSERT(PointerPte->u.Hard.Valid == 1);
1183
1184 /* Get the original prototype PTE and turn it into a transition PTE */
1185 PointerPte = Pfn1->PteAddress;
1186 TempPte = *PointerPte;
1187 TempPte.u.Soft.Transition = 1;
1188 TempPte.u.Soft.Valid = 0;
1189 TempPte.u.Soft.Prototype = 0;
1190 TempPte.u.Soft.Protection = Pfn1->OriginalPte.u.Soft.Protection;
1191 MI_WRITE_INVALID_PTE(PointerPte, TempPte);
1192 DPRINT("Marking PTE: %p as transition (%p - %lx)\n", PointerPte, Pfn1, MiGetPfnEntryIndex(Pfn1));
1193 }
1194
1195 /* Put the page in transition */
1196 Pfn1->u3.e1.PageLocation = TransitionPage;
1197
1198 /* PFN lock must be held */
1200
1201 if (Pfn1->u3.e2.ReferenceCount == 1)
1202 {
1203 /* Is there still a PFN for this page? */
1204 if (MI_IS_PFN_DELETED(Pfn1))
1205 {
1206 /* Clear the last reference */
1207 Pfn1->u3.e2.ReferenceCount = 0;
1208 ASSERT(Pfn1->OriginalPte.u.Soft.Prototype == 0);
1209
1210 /* Mark the page temporarily as valid, we're going to make it free soon */
1211 Pfn1->u3.e1.PageLocation = ActiveAndValid;
1212
1213 /* Bring it back into the free list */
1214 MiInsertPageInFreeList(PageFrameIndex);
1215 }
1216 else
1217 {
1218 /* PFN not yet deleted, drop a ref count */
1219 MiDecrementReferenceCount(Pfn1, PageFrameIndex);
1220 }
1221 }
1222 else
1223 {
1224 /* Otherwise, just drop the reference count */
1225 InterlockedDecrement16((PSHORT)&Pfn1->u3.e2.ReferenceCount);
1226 }
1227 }
1228}
HARDWARE_PTE_ARMV6 TempPte
Definition: winldr.c:76
#define NULL
Definition: types.h:112
#define _ReturnAddress()
Definition: intrin_arm.h:35
PVOID MmPagedPoolStart
Definition: miarm.h:588
FORCEINLINE VOID MI_WRITE_INVALID_PTE(IN PMMPTE PointerPte, IN MMPTE InvalidPte)
Definition: miarm.h:1006
#define MiAddressToPte(x)
Definition: mmx86.c:19
@ TransitionPage
Definition: mmtypes.h:160
@ StandbyPageList
Definition: mmtypes.h:155
FORCEINLINE PFN_NUMBER MiGetPfnEntryIndex(IN PMMPFN Pfn1)
Definition: mm.h:1067
PVOID MmPagedPoolEnd
Definition: init.c:26
VOID NTAPI MiDecrementReferenceCount(IN PMMPFN Pfn1, IN PFN_NUMBER PageFrameIndex)
Definition: pfnlist.c:1236
#define DPRINT
Definition: sndvol32.h:73
ULONG64 Valid
Definition: mmtypes.h:150
union _MMPTE::@2339 u
MMPTE_HARDWARE Hard
Definition: mmtypes.h:217

Referenced by FreeWsleIndex(), MiDeletePte(), MiDeleteSystemPageableVm(), MiFreeContiguousMemory(), MiProcessValidPteList(), MiProtectVirtualMemory(), MiReleaseProcessReferenceToSessionDataPage(), MiRemoveMappedPtes(), MiUnmapLockedPagesInUserSpace(), MmDeleteKernelStack(), MmDeleteProcessAddressSpace(), MmFreeLoaderBlock(), MmFreeSpecialPool(), and TrimWsList().

◆ MiIncrementAvailablePages()

static VOID MiIncrementAvailablePages ( VOID  )
static

Definition at line 69 of file pfnlist.c.

71{
72 /* Increment available pages */
74
75 /* Check if we've reached the configured low memory threshold */
77 {
78 /* Clear the event, because now we're ABOVE the threshold */
80 }
82 {
83 /* Otherwise check if we reached the high threshold and signal the event */
85 }
86}

Referenced by MiInsertPageInFreeList(), MiInsertPageInList(), and MiInsertStandbyListAtFront().

◆ MiInitializeAndChargePfn()

NTSTATUS NTAPI MiInitializeAndChargePfn ( OUT PPFN_NUMBER  PageFrameIndex,
IN PMMPDE  PointerPde,
IN PFN_NUMBER  ContainingPageFrame,
IN BOOLEAN  SessionAllocation 
)

Definition at line 1101 of file pfnlist.c.

1105{
1106 MMPDE TempPde;
1107 KIRQL OldIrql;
1108
1109 /* Use either a global or local PDE */
1110 TempPde = SessionAllocation ? ValidKernelPdeLocal : ValidKernelPde;
1111
1112 /* Lock the PFN database */
1113 OldIrql = MiAcquirePfnLock();
1114
1115 /* Make sure nobody is racing us */
1116 if (PointerPde->u.Hard.Valid == 1)
1117 {
1118 /* Return special error if that was the case */
1119 MiReleasePfnLock(OldIrql);
1120 return STATUS_RETRY;
1121 }
1122
1123 /* Grab a zero page and set the PFN, then make it valid */
1124 *PageFrameIndex = MiRemoveZeroPage(MI_GET_NEXT_COLOR());
1125 TempPde.u.Hard.PageFrameNumber = *PageFrameIndex;
1126 MI_WRITE_VALID_PDE(PointerPde, TempPde);
1127
1128 /* Initialize the PFN */
1129 MiInitializePfnForOtherProcess(*PageFrameIndex,
1130 PointerPde,
1131 ContainingPageFrame);
1132 ASSERT(MI_PFN_ELEMENT(*PageFrameIndex)->u1.WsIndex == 0);
1133
1134 /* Release the lock and return success */
1135 MiReleasePfnLock(OldIrql);
1136 return STATUS_SUCCESS;
1137}
HARDWARE_PDE_ARMV6 TempPde
Definition: winldr.c:78
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define MI_GET_NEXT_COLOR()
Definition: miarm.h:246
FORCEINLINE VOID MI_WRITE_VALID_PDE(IN PMMPDE PointerPde, IN MMPDE TempPde)
Definition: miarm.h:1031
MMPTE ValidKernelPdeLocal
Definition: init.c:32
MMPTE ValidKernelPde
Definition: init.c:28
PFN_NUMBER NTAPI MiRemoveZeroPage(IN ULONG Color)
Definition: pfnlist.c:537
VOID NTAPI MiInitializePfnForOtherProcess(IN PFN_NUMBER PageFrameIndex, IN PVOID PteAddress, IN PFN_NUMBER PteFrame)
Definition: pfnlist.c:1301
#define STATUS_SUCCESS
Definition: shellext.h:65
ULONG PageFrameNumber
Definition: mmtypes.h:74
union _MMPFN::@1803 u1
ULONG WsIndex
Definition: mm.h:378
#define STATUS_RETRY
Definition: udferr_usr.h:182
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:778

Referenced by MiInitializeSessionPool().

◆ MiInitializePfn()

VOID NTAPI MiInitializePfn ( IN PFN_NUMBER  PageFrameIndex,
IN PMMPTE  PointerPte,
IN BOOLEAN  Modified 
)

Definition at line 970 of file pfnlist.c.

973{
974 PMMPFN Pfn1;
976 PMMPTE PointerPtePte;
978
979 /* Setup the PTE */
980 Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);
981 Pfn1->PteAddress = PointerPte;
982
983 DPRINT("Called for %p from %p\n", Pfn1, _ReturnAddress());
984
985 /* Check if this PFN is part of a valid address space */
986 if (PointerPte->u.Hard.Valid == 1)
987 {
988 /* Only valid from MmCreateProcessAddressSpace path */
989 ASSERT(PsGetCurrentProcess()->Vm.WorkingSetSize == 0);
990
991 /* Make this a demand zero PTE */
993 }
994 else
995 {
996 /* Copy the PTE data */
997 Pfn1->OriginalPte = *PointerPte;
998 ASSERT(!((Pfn1->OriginalPte.u.Soft.Prototype == 0) &&
999 (Pfn1->OriginalPte.u.Soft.Transition == 1)));
1000 }
1001
1002 /* Otherwise this is a fresh page -- set it up */
1003 ASSERT(Pfn1->u3.e2.ReferenceCount == 0);
1004 Pfn1->u3.e2.ReferenceCount = 1;
1005 Pfn1->u2.ShareCount = 1;
1007 ASSERT(Pfn1->u3.e1.Rom == 0);
1008 Pfn1->u3.e1.Modified = Modified;
1009
1010 /* Get the page table for the PTE */
1011 PointerPtePte = MiAddressToPte(PointerPte);
1012 if (PointerPtePte->u.Hard.Valid == 0)
1013 {
1014 /* Make sure the PDE gets paged in properly */
1015 Status = MiCheckPdeForPagedPool(PointerPte);
1016 if (!NT_SUCCESS(Status))
1017 {
1018 /* Crash */
1019 KeBugCheckEx(MEMORY_MANAGEMENT,
1020 0x61940,
1021 (ULONG_PTR)PointerPte,
1022 (ULONG_PTR)PointerPtePte->u.Long,
1023 (ULONG_PTR)MiPteToAddress(PointerPte));
1024 }
1025 }
1026
1027 /* Get the PFN for the page table */
1028 PageFrameIndex = PFN_FROM_PTE(PointerPtePte);
1029 ASSERT(PageFrameIndex != 0);
1030 Pfn1->u4.PteFrame = PageFrameIndex;
1031
1032 DPRINT("Incrementing share count of %lp from %p\n", PageFrameIndex, _ReturnAddress());
1033
1034 /* Increase its share count so we don't get rid of it */
1035 Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);
1036 Pfn1->u2.ShareCount++;
1037}
LONG NTSTATUS
Definition: precomp.h:26
#define MM_READWRITE
Definition: bootanim.c:19
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
Status
Definition: gdiplustypes.h:25
#define MI_MAKE_SOFTWARE_PTE(p, x)
Definition: miarm.h:203
NTSTATUS FASTCALL MiCheckPdeForPagedPool(IN PVOID Address)
Definition: pagfault.c:479
#define PFN_FROM_PTE(v)
Definition: mm.h:92
#define MiPteToAddress(_Pte)
Definition: mm.h:116
USHORT Modified
Definition: mm.h:360
USHORT PageLocation
Definition: mm.h:365
USHORT Rom
Definition: mm.h:368
Definition: mm.h:374
MMPTE OriginalPte
Definition: mm.h:407
PMMPTE PteAddress
Definition: mm.h:386
union _MMPFN::@1804 u2
union _MMPFN::@1808 u4
MMPFNENTRY e1
Definition: mm.h:397
ULONG_PTR ShareCount
Definition: mm.h:390
ULONG_PTR PteFrame
Definition: mm.h:418
ULONG64 Transition
Definition: mmtypes.h:90
ULONG64 Prototype
Definition: mmtypes.h:89
MMPTE_SOFTWARE Soft
Definition: mmtypes.h:219
ULONG_PTR Long
Definition: mmtypes.h:215
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define PsGetCurrentProcess
Definition: psfuncs.h:17

Referenced by MiLoadImageSection(), MiResolveDemandZeroFault(), MiResolvePageFileFault(), MiResolveProtoPteFault(), MmArmAccessFault(), MmCreateKernelStack(), MmGrowKernelStackEx(), and MmInitializeProcessAddressSpace().

◆ MiInitializePfnAndMakePteValid()

VOID NTAPI MiInitializePfnAndMakePteValid ( IN PFN_NUMBER  PageFrameIndex,
IN PMMPTE  PointerPte,
IN MMPTE  TempPte 
)

Definition at line 1041 of file pfnlist.c.

1044{
1045 PMMPFN Pfn1;
1047 PMMPTE PointerPtePte;
1049
1050 /* PTE must be invalid */
1051 ASSERT(PointerPte->u.Hard.Valid == 0);
1052
1053 /* Setup the PTE */
1054 Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);
1055 Pfn1->PteAddress = PointerPte;
1056 Pfn1->OriginalPte = DemandZeroPte;
1057
1058 DPRINT("Incrementing %p from %p\n", Pfn1, _ReturnAddress());
1059
1060 /* Otherwise this is a fresh page -- set it up */
1061 ASSERT(Pfn1->u3.e2.ReferenceCount == 0);
1062 Pfn1->u3.e2.ReferenceCount++;
1063 Pfn1->u2.ShareCount++;
1065 ASSERT(Pfn1->u3.e1.Rom == 0);
1066 Pfn1->u3.e1.Modified = 1;
1067
1068 /* Get the page table for the PTE */
1069 PointerPtePte = MiAddressToPte(PointerPte);
1070 if (PointerPtePte->u.Hard.Valid == 0)
1071 {
1072 /* Make sure the PDE gets paged in properly */
1073 Status = MiCheckPdeForPagedPool(PointerPte);
1074 if (!NT_SUCCESS(Status))
1075 {
1076 /* Crash */
1077 KeBugCheckEx(MEMORY_MANAGEMENT,
1078 0x61940,
1079 (ULONG_PTR)PointerPte,
1080 (ULONG_PTR)PointerPtePte->u.Long,
1081 (ULONG_PTR)MiPteToAddress(PointerPte));
1082 }
1083 }
1084
1085 /* Get the PFN for the page table */
1086 PageFrameIndex = PFN_FROM_PTE(PointerPtePte);
1087 ASSERT(PageFrameIndex != 0);
1088 Pfn1->u4.PteFrame = PageFrameIndex;
1089
1090 /* Increase its share count so we don't get rid of it */
1091 Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);
1092 Pfn1->u2.ShareCount++;
1093 DPRINT("Incrementing %p from %p\n", Pfn1, _ReturnAddress());
1094
1095 /* Write valid PTE */
1096 MI_WRITE_VALID_PTE(PointerPte, TempPte);
1097}
FORCEINLINE VOID MI_WRITE_VALID_PTE(IN PMMPTE PointerPte, IN MMPTE TempPte)
Definition: miarm.h:973
MMPTE DemandZeroPte
Definition: init.c:37

Referenced by GetFreeWsleIndex(), MiSessionCreateInternal(), MiSessionInitializeWorkingSetList(), and MmAllocateSpecialPool().

◆ MiInitializePfnForOtherProcess()

VOID NTAPI MiInitializePfnForOtherProcess ( IN PFN_NUMBER  PageFrameIndex,
IN PVOID  PteAddress,
IN PFN_NUMBER  PteFrame 
)

Definition at line 1301 of file pfnlist.c.

1304{
1305 PMMPFN Pfn1;
1306
1307 /* Setup the PTE */
1308 Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);
1309 Pfn1->PteAddress = PteAddress;
1310
1311 /* Make this a software PTE */
1313
1314 DPRINT("Called for %p from %p\n", Pfn1, _ReturnAddress());
1315
1316 /* Setup the page */
1317 ASSERT(Pfn1->u3.e2.ReferenceCount == 0);
1318 Pfn1->u3.e2.ReferenceCount = 1;
1319 Pfn1->u2.ShareCount = 1;
1321 Pfn1->u3.e1.Modified = TRUE;
1322 Pfn1->u4.InPageError = FALSE;
1323
1324 /* Did we get a PFN for the page table */
1325 if (PteFrame)
1326 {
1327 /* Store it */
1328 Pfn1->u4.PteFrame = PteFrame;
1329
1330 /* Increase its share count so we don't get rid of it */
1331 Pfn1 = MI_PFN_ELEMENT(PteFrame);
1332
1333 DPRINT("Incrementing %p from %p\n", Pfn1, _ReturnAddress());
1334 Pfn1->u2.ShareCount++;
1335 }
1336}
#define TRUE
Definition: types.h:120
ULONG_PTR InPageError
Definition: mm.h:419

Referenced by MiAllocatePoolPages(), MiBuildPagedPool(), MiFillSystemPageDirectory(), MiInitializeAndChargePfn(), MiSessionCommitPageTables(), MiSessionCreateInternal(), and MiSessionInitializeWorkingSetList().

◆ MiInsertPageInFreeList()

VOID NTAPI MiInsertPageInFreeList ( IN PFN_NUMBER  PageFrameIndex)

Definition at line 611 of file pfnlist.c.

612{
613 PMMPFNLIST ListHead;
614 PFN_NUMBER LastPage;
615 PMMPFN Pfn1;
616 ULONG Color;
617 PMMPFN Blink;
618 PMMCOLOR_TABLES ColorTable;
619
620 /* Make sure the page index is valid */
622 ASSERT((PageFrameIndex != 0) &&
623 (PageFrameIndex <= MmHighestPhysicalPage) &&
624 (PageFrameIndex >= MmLowestPhysicalPage));
625
626 /* Get the PFN entry */
627 Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);
628
629 /* Sanity checks that a right kind of page is being inserted here */
630 ASSERT(Pfn1->u4.MustBeCached == 0);
631 ASSERT(Pfn1->u3.e1.Rom != 1);
632 ASSERT(Pfn1->u3.e1.RemovalRequested == 0);
633 ASSERT(Pfn1->u4.VerifierAllocation == 0);
634 ASSERT(Pfn1->u3.e2.ReferenceCount == 0);
635
636 /* Get the free page list and increment its count */
637 ListHead = &MmFreePageListHead;
638 ASSERT_LIST_INVARIANT(ListHead);
639 ListHead->Total++;
640
641 /* Get the last page on the list */
642 LastPage = ListHead->Blink;
643 if (LastPage != LIST_HEAD)
644 {
645 /* Link us with the previous page, so we're at the end now */
646 MI_PFN_ELEMENT(LastPage)->u1.Flink = PageFrameIndex;
647 }
648 else
649 {
650 /* The list is empty, so we are the first page */
651 ListHead->Flink = PageFrameIndex;
652 }
653
654 /* Now make the list head point back to us (since we go at the end) */
655 ListHead->Blink = PageFrameIndex;
656 ASSERT_LIST_INVARIANT(ListHead);
657
658 /* And initialize our own list pointers */
659 Pfn1->u1.Flink = LIST_HEAD;
660 Pfn1->u2.Blink = LastPage;
661
662 /* Set the list name and default priority */
664 Pfn1->u4.Priority = 3;
665
666 /* Clear some status fields */
667 Pfn1->u4.InPageError = 0;
668 Pfn1->u4.AweAllocation = 0;
669
670 /* Increment number of available pages */
672
673 /* Get the page color */
674 Color = PageFrameIndex & MmSecondaryColorMask;
675
676 /* Get the first page on the color list */
677 ColorTable = &MmFreePagesByColor[FreePageList][Color];
678 if (ColorTable->Flink == LIST_HEAD)
679 {
680 /* The list is empty, so we are the first page */
681 Pfn1->u4.PteFrame = COLORED_LIST_HEAD;
682 ColorTable->Flink = PageFrameIndex;
683 }
684 else
685 {
686 /* Get the previous page */
687 Blink = (PMMPFN)ColorTable->Blink;
688
689 /* Make it link to us, and link back to it */
690 Blink->OriginalPte.u.Long = PageFrameIndex;
691 Pfn1->u4.PteFrame = MiGetPfnEntryIndex(Blink);
692 }
693
694 /* Now initialize our own list pointers */
695 ColorTable->Blink = Pfn1;
696
697 /* This page is now the last */
698 Pfn1->OriginalPte.u.Long = LIST_HEAD;
699
700 /* And increase the count in the colored list */
701 ColorTable->Count++;
702
703 /* Notify zero page thread if enough pages are on the free list now */
704 if (ListHead->Total >= 8)
705 {
706 /* Set the event */
708 }
709
710#if MI_TRACE_PFNS
711 Pfn1->PfnUsage = MI_USAGE_FREE_PAGE;
712 RtlZeroMemory(Pfn1->ProcessName, 16);
713 Pfn1->CallSite = NULL;
714#endif
715}
PFN_NUMBER MmLowestPhysicalPage
Definition: meminit.c:30
ULONG MmSecondaryColorMask
Definition: mminit.c:257
KEVENT MmZeroingPageEvent
Definition: zeropage.c:20
PMMCOLOR_TABLES MmFreePagesByColor[FreePageList+1]
Definition: mminit.c:286
@ FreePageList
Definition: mmtypes.h:154
@ MI_USAGE_FREE_PAGE
Definition: mm.h:349
struct _MMPFN * PMMPFN
#define ASSERT_LIST_INVARIANT(x)
Definition: pfnlist.c:29
static VOID MiIncrementAvailablePages(VOID)
Definition: pfnlist.c:69
MMPFNLIST MmFreePageListHead
Definition: pfnlist.c:42
ULONG PFN_NUMBER
Definition: ke.h:9
PFN_NUMBER Count
Definition: miarm.h:447
PVOID Blink
Definition: miarm.h:446
PFN_NUMBER Flink
Definition: miarm.h:445
USHORT RemovalRequested
Definition: mm.h:366
Definition: mm.h:442
PFN_NUMBER Total
Definition: mm.h:443
PFN_NUMBER Blink
Definition: mm.h:446
PFN_NUMBER Flink
Definition: mm.h:445
ULONG_PTR MustBeCached
Definition: mm.h:423
PFN_NUMBER Blink
Definition: mm.h:389
PFN_NUMBER Flink
Definition: mm.h:377
ULONG_PTR VerifierAllocation
Definition: mm.h:420
ULONG_PTR Priority
Definition: mm.h:422
ULONG_PTR AweAllocation
Definition: mm.h:421
#define LIST_HEAD(name, type)
Definition: queue.h:167
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG
Definition: typedefs.h:59
#define IO_NO_INCREMENT
Definition: iotypes.h:598

Referenced by MiAddDescriptorToDatabase(), MiBuildPfnDatabaseFromLoaderBlock(), MiDecrementReferenceCount(), MiDecrementShareCount(), MiSegmentDelete(), MmCreateProcessAddressSpace(), MmDereferencePage(), and MmFreeLoaderBlock().

◆ MiInsertPageInList()

VOID NTAPI MiInsertPageInList ( IN PMMPFNLIST  ListHead,
IN PFN_NUMBER  PageFrameIndex 
)

Definition at line 779 of file pfnlist.c.

781{
782 PFN_NUMBER Flink, LastPage;
783 PMMPFN Pfn1, Pfn2;
784 MMLISTS ListName;
785 PMMCOLOR_TABLES ColorHead;
786 ULONG Color;
787
788 /* For free pages, use MiInsertPageInFreeList */
789 ASSERT(ListHead != &MmFreePageListHead);
790
791 /* Make sure the lock is held */
793
794 /* Make sure the PFN is valid */
795 ASSERT((PageFrameIndex) &&
796 (PageFrameIndex <= MmHighestPhysicalPage) &&
797 (PageFrameIndex >= MmLowestPhysicalPage));
798
799 /* Page should be unused */
800 Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);
801 ASSERT(Pfn1->u3.e2.ReferenceCount == 0);
802 ASSERT(Pfn1->u3.e1.Rom != 1);
803
804 /* Is a standby or modified page being inserted? */
805 ListName = ListHead->ListName;
806 if ((ListName == StandbyPageList) || (ListName == ModifiedPageList))
807 {
808 /* If the page is in transition, it must also be a prototype page */
809 if ((Pfn1->OriginalPte.u.Soft.Prototype == 0) &&
810 (Pfn1->OriginalPte.u.Soft.Transition == 1))
811 {
812 /* Crash the system on inconsistency */
813 KeBugCheckEx(MEMORY_MANAGEMENT, 0x8888, 0, 0, 0);
814 }
815 }
816
817 /* Standby pages are prioritized, so we need to get the real head */
818 if (ListHead == &MmStandbyPageListHead)
819 {
820 /* Obviously the prioritized list should still have the same name */
821 ListHead = &MmStandbyPageListByPriority[Pfn1->u4.Priority];
822 ASSERT(ListHead->ListName == ListName);
823 }
824
825 /* Increment the list count */
826 ListHead->Total++;
827
828 /* Is a modified page being inserted? */
829 if (ListHead == &MmModifiedPageListHead)
830 {
831 /* For now, only single-prototype pages should end up in this path */
832 DPRINT("Modified page being added: %lx\n", PageFrameIndex);
833 ASSERT(Pfn1->OriginalPte.u.Soft.Prototype == 0);
834
835 /* Modified pages are colored when they are selected for page file */
836 ListHead = &MmModifiedPageListByColor[0];
837 ASSERT (ListHead->ListName == ListName);
838 ListHead->Total++;
839
840 /* Increment the number of paging file modified pages */
842 }
843
844 /* Don't handle bad pages yet yet */
845 ASSERT(Pfn1->u3.e1.RemovalRequested == 0);
846
847 /* Zero pages go to the head, all other pages go to the end */
848 if (ListName == ZeroedPageList)
849 {
850 /* Make the head of the list point to this page now */
851 Flink = ListHead->Flink;
852 ListHead->Flink = PageFrameIndex;
853
854 /* Make the page point to the previous head, and back to the list */
855 Pfn1->u1.Flink = Flink;
856 Pfn1->u2.Blink = LIST_HEAD;
857
858 /* Was the list empty? */
859 if (Flink != LIST_HEAD)
860 {
861 /* It wasn't, so update the backlink of the previous head page */
862 Pfn2 = MI_PFN_ELEMENT(Flink);
863 Pfn2->u2.Blink = PageFrameIndex;
864 }
865 else
866 {
867 /* It was empty, so have it loop back around to this new page */
868 ListHead->Blink = PageFrameIndex;
869 }
870 }
871 else
872 {
873 /* Get the last page on the list */
874 LastPage = ListHead->Blink;
875 if (LastPage != LIST_HEAD)
876 {
877 /* Link us with the previous page, so we're at the end now */
878 MI_PFN_ELEMENT(LastPage)->u1.Flink = PageFrameIndex;
879 }
880 else
881 {
882 /* The list is empty, so we are the first page */
883 ListHead->Flink = PageFrameIndex;
884 }
885
886 /* Now make the list head point back to us (since we go at the end) */
887 ListHead->Blink = PageFrameIndex;
888 ASSERT_LIST_INVARIANT(ListHead);
889
890 /* And initialize our own list pointers */
891 Pfn1->u1.Flink = LIST_HEAD;
892 Pfn1->u2.Blink = LastPage;
893 }
894
895 /* Move the page onto its new location */
896 Pfn1->u3.e1.PageLocation = ListName;
897
898 /* For zero/free pages, we also have to handle the colored lists */
899 if (ListName <= StandbyPageList)
900 {
901 /* Increment number of available pages */
903
904 /* Sanity checks */
905 ASSERT(ListName == ZeroedPageList);
906 ASSERT(Pfn1->u4.InPageError == 0);
907
908 /* Get the page color */
909 Color = PageFrameIndex & MmSecondaryColorMask;
910
911 /* Get the list for this color */
913
914 /* Get the old head */
915 Flink = ColorHead->Flink;
916
917 /* Make this page point back to the list, and point forwards to the old head */
918 Pfn1->OriginalPte.u.Long = Flink;
919 Pfn1->u4.PteFrame = COLORED_LIST_HEAD;
920
921 /* Set the new head */
922 ColorHead->Flink = PageFrameIndex;
923
924 /* Was the head empty? */
925 if (Flink != LIST_HEAD)
926 {
927 /* No, so make the old head point to this page */
928 Pfn2 = MI_PFN_ELEMENT(Flink);
929 Pfn2->u4.PteFrame = PageFrameIndex;
930 }
931 else
932 {
933 /* Yes, make it loop back to this page */
934 ColorHead->Blink = (PVOID)Pfn1;
935 }
936
937 /* One more paged on the colored list */
938 ColorHead->Count++;
939
940#if MI_TRACE_PFNS
942 Pfn1->PfnUsage = MI_USAGE_FREE_PAGE;
943 RtlZeroMemory(Pfn1->ProcessName, 16);
944 Pfn1->CallSite = NULL;
945#endif
946 }
947 else if (ListName == ModifiedPageList)
948 {
949 /* In ARM3, page must be destined for page file, and not yet written out */
950 ASSERT(Pfn1->OriginalPte.u.Soft.Prototype == 0);
952
953 /* One more transition page */
955
956 /* Increment the number of per-process modified pages */
957 PsGetCurrentProcess()->ModifiedPageCount++;
958
959 /* FIXME: Wake up modified page writer if there are not enough free pages */
960 }
961 else if (ListName == ModifiedNoWritePageList)
962 {
963 /* This list is not yet implemented */
964 ASSERT(FALSE);
965 }
966}
enum _MMLISTS MMLISTS
@ ZeroedPageList
Definition: mmtypes.h:153
@ ModifiedPageList
Definition: mmtypes.h:156
@ ModifiedNoWritePageList
Definition: mmtypes.h:157
@ MI_USAGE_NOT_SET
Definition: mm.h:324
MMPFNLIST MmStandbyPageListHead
Definition: pfnlist.c:43
MMPFNLIST MmModifiedPageListByColor[1]
Definition: pfnlist.c:46
ULONG MmTransitionSharedPages
Definition: pfnlist.c:38
ULONG MI_PFN_CURRENT_USAGE
Definition: pfnlist.c:63
MMPFNLIST MmStandbyPageListByPriority[8]
Definition: pfnlist.c:44
ULONG MmTotalPagesForPagingFile
Definition: pfnlist.c:39
ULONG64 PageFileHigh
Definition: mmtypes.h:93
void * PVOID
Definition: typedefs.h:50

Referenced by MiDecrementReferenceCount(), and MmZeroPageThread().

◆ MiInsertStandbyListAtFront()

VOID FASTCALL MiInsertStandbyListAtFront ( IN PFN_NUMBER  PageFrameIndex)

Definition at line 719 of file pfnlist.c.

720{
721 PMMPFNLIST ListHead;
722 PFN_NUMBER Flink;
723 PMMPFN Pfn1, Pfn2;
724
725 /* Make sure the lock is held */
726 DPRINT("Inserting page: %lx into standby list !\n", PageFrameIndex);
728
729 /* Make sure the PFN is valid */
730 ASSERT((PageFrameIndex != 0) &&
731 (PageFrameIndex <= MmHighestPhysicalPage) &&
732 (PageFrameIndex >= MmLowestPhysicalPage));
733
734 /* Grab the PFN and validate it is the right kind of PFN being inserted */
735 Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);
736 ASSERT(Pfn1->u4.MustBeCached == 0);
737 ASSERT(Pfn1->u3.e2.ReferenceCount == 0);
738 ASSERT(Pfn1->u3.e1.PrototypePte == 1);
739 ASSERT(Pfn1->u3.e1.Rom != 1);
740
741 /* One more transition page on a list */
743
744 /* Get the standby page list and increment its count */
745 ListHead = &MmStandbyPageListByPriority [Pfn1->u4.Priority];
746 ASSERT_LIST_INVARIANT(ListHead);
747 ListHead->Total++;
748
749 /* Make the head of the list point to this page now */
750 Flink = ListHead->Flink;
751 ListHead->Flink = PageFrameIndex;
752
753 /* Make the page point to the previous head, and back to the list */
754 Pfn1->u1.Flink = Flink;
755 Pfn1->u2.Blink = LIST_HEAD;
756
757 /* Was the list empty? */
758 if (Flink != LIST_HEAD)
759 {
760 /* It wasn't, so update the backlink of the previous head page */
761 Pfn2 = MI_PFN_ELEMENT(Flink);
762 Pfn2->u2.Blink = PageFrameIndex;
763 }
764 else
765 {
766 /* It was empty, so have it loop back around to this new page */
767 ListHead->Blink = PageFrameIndex;
768 }
769
770 /* Move the page onto its new location */
772
773 /* Increment number of available pages */
775}
USHORT PrototypePte
Definition: mm.h:363

Referenced by MiDecrementReferenceCount().

◆ MiRemoveAnyPage()

PFN_NUMBER NTAPI MiRemoveAnyPage ( IN ULONG  Color)

Definition at line 477 of file pfnlist.c.

478{
479 PFN_NUMBER PageIndex;
480 PMMPFN Pfn1;
481
482 /* Make sure PFN lock is held and we have pages */
485 if (MmAvailablePages == 0)
486 {
487 return 0;
488 }
489
490 /* Check the colored free list */
492 if (PageIndex == LIST_HEAD)
493 {
494 /* Check the colored zero list */
496 if (PageIndex == LIST_HEAD)
497 {
498 /* Check the free list */
500 PageIndex = MmFreePageListHead.Flink;
501 Color = PageIndex & MmSecondaryColorMask;
502 if (PageIndex == LIST_HEAD)
503 {
504 /* Check the zero list */
506 PageIndex = MmZeroedPageListHead.Flink;
507 Color = PageIndex & MmSecondaryColorMask;
508 ASSERT(PageIndex != LIST_HEAD);
509 if (PageIndex == LIST_HEAD)
510 {
511 /* FIXME: Should check the standby list */
513 }
514 }
515 }
516 }
517
518 /* Remove the page from its list */
519 PageIndex = MiRemovePageByColor(PageIndex, Color);
520 ASSERT(PageIndex != 0);
521
522 /* Sanity checks */
523 Pfn1 = MI_PFN_ELEMENT(PageIndex);
524 ASSERT((Pfn1->u3.e1.PageLocation == FreePageList) ||
525 (Pfn1->u3.e1.PageLocation == ZeroedPageList));
526 ASSERT(Pfn1->u3.e2.ReferenceCount == 0);
527 ASSERT(Pfn1->u2.ShareCount == 0);
530
531 /* Return the page */
532 return PageIndex;
533}
ULONG MmSecondaryColors
Definition: mminit.c:256
PFN_NUMBER NTAPI MiRemovePageByColor(IN PFN_NUMBER PageIndex, IN ULONG Color)
Definition: pfnlist.c:364
MMPFNLIST MmZeroedPageListHead
Definition: pfnlist.c:41

Referenced by GetFreeWsleIndex(), MiAllocatePagesForMdl(), MiAllocatePoolPages(), MiArchCreateProcessAddressSpace(), MiInitMachineDependent(), MiLoadImageSection(), MiResolveDemandZeroFault(), MiResolvePageFileFault(), MiResolveProtoPteFault(), MiSessionCreateInternal(), MiSessionInitializeWorkingSetList(), MmAllocateSpecialPool(), MmArmAccessFault(), MmCreateKernelStack(), MmCreateProcessAddressSpace(), MmGrowKernelStackEx(), and MmZeroPageThread().

◆ MiRemovePageByColor()

PFN_NUMBER NTAPI MiRemovePageByColor ( IN PFN_NUMBER  PageIndex,
IN ULONG  Color 
)

Definition at line 364 of file pfnlist.c.

366{
367 PMMPFN Pfn1;
368 PMMPFNLIST ListHead;
369 MMLISTS ListName;
370 PFN_NUMBER OldFlink, OldBlink;
371 USHORT OldColor, OldCache;
372 PMMCOLOR_TABLES ColorTable;
373
374 /* Make sure PFN lock is held */
377
378 /* Get the PFN entry */
379 Pfn1 = MI_PFN_ELEMENT(PageIndex);
380 ASSERT(Pfn1->u3.e1.RemovalRequested == 0);
381 ASSERT(Pfn1->u3.e1.Rom == 0);
382
383 /* Capture data for later */
384 OldColor = Pfn1->u3.e1.PageColor;
385 OldCache = Pfn1->u3.e1.CacheAttribute;
386
387 /* Could be either on free or zero list */
388 ListHead = MmPageLocationList[Pfn1->u3.e1.PageLocation];
389 ASSERT_LIST_INVARIANT(ListHead);
390 ListName = ListHead->ListName;
391 ASSERT(ListName <= FreePageList);
392
393 /* Remove a page */
394 ListHead->Total--;
395
396 /* Get the forward and back pointers */
397 OldFlink = Pfn1->u1.Flink;
398 OldBlink = Pfn1->u2.Blink;
399
400 /* Check if the next entry is the list head */
401 if (OldFlink != LIST_HEAD)
402 {
403 /* It is not, so set the backlink of the actual entry, to our backlink */
404 MI_PFN_ELEMENT(OldFlink)->u2.Blink = OldBlink;
405 }
406 else
407 {
408 /* Set the list head's backlink instead */
409 ListHead->Blink = OldBlink;
410 }
411
412 /* Check if the back entry is the list head */
413 if (OldBlink != LIST_HEAD)
414 {
415 /* It is not, so set the backlink of the actual entry, to our backlink */
416 MI_PFN_ELEMENT(OldBlink)->u1.Flink = OldFlink;
417 }
418 else
419 {
420 /* Set the list head's backlink instead */
421 ListHead->Flink = OldFlink;
422 }
423
424 /* We are not on a list anymore */
425 ASSERT_LIST_INVARIANT(ListHead);
426 Pfn1->u1.Flink = Pfn1->u2.Blink = 0;
427
428 /* Zero flags but restore color and cache */
429 Pfn1->u3.e2.ShortFlags = 0;
430 Pfn1->u3.e1.PageColor = OldColor;
431 Pfn1->u3.e1.CacheAttribute = OldCache;
432
433 /* Get the first page on the color list */
435 ColorTable = &MmFreePagesByColor[ListName][Color];
436 ASSERT(ColorTable->Count >= 1);
437
438 /* Set the forward link to whoever we were pointing to */
439 ColorTable->Flink = Pfn1->OriginalPte.u.Long;
440
441 /* Get the first page on the color list */
442 if (ColorTable->Flink == LIST_HEAD)
443 {
444 /* This is the beginning of the list, so set the sentinel value */
445 ColorTable->Blink = (PVOID)LIST_HEAD;
446 }
447 else
448 {
449 /* The list is empty, so we are the first page */
450 MI_PFN_ELEMENT(ColorTable->Flink)->u4.PteFrame = COLORED_LIST_HEAD;
451 }
452
453 /* One less page */
454 ColorTable->Count--;
455
456 /* ReactOS Hack */
457 Pfn1->OriginalPte.u.Long = 0;
458
459 /* Decrement number of available pages */
461
462#if MI_TRACE_PFNS
464 Pfn1->PfnUsage = MI_PFN_CURRENT_USAGE;
465 memcpy(Pfn1->ProcessName, MI_PFN_CURRENT_PROCESS_NAME, 16);
466 Pfn1->CallSite = _ReturnAddress();
468 MI_SET_PROCESS2("Not Set");
469#endif
470
471 /* Return the page */
472 return PageIndex;
473}
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define MI_SET_PROCESS2(x)
Definition: mm.h:319
unsigned short USHORT
Definition: pedump.c:61
static VOID MiDecrementAvailablePages(VOID)
Definition: pfnlist.c:90
CHAR MI_PFN_CURRENT_PROCESS_NAME[16]
Definition: pfnlist.c:64
PMMPFNLIST MmPageLocationList[]
Definition: pfnlist.c:51
USHORT CacheAttribute
Definition: mm.h:367
USHORT PageColor
Definition: mm.h:364
MMLISTS ListName
Definition: mm.h:444

Referenced by MiRemoveAnyPage(), and MiRemoveZeroPage().

◆ MiRemoveZeroPage()

PFN_NUMBER NTAPI MiRemoveZeroPage ( IN ULONG  Color)

Definition at line 537 of file pfnlist.c.

538{
539 PFN_NUMBER PageIndex;
540 PMMPFN Pfn1;
542
543 /* Make sure PFN lock is held and we have pages */
546 if (MmAvailablePages == 0)
547 {
548 return 0;
549 }
550
551 /* Check the colored zero list */
553 if (PageIndex == LIST_HEAD)
554 {
555 /* Check the zero list */
557 PageIndex = MmZeroedPageListHead.Flink;
558 if (PageIndex == LIST_HEAD)
559 {
560 /* This means there's no zero pages, we have to look for free ones */
562 Zero = TRUE;
563
564 /* Check the colored free list */
566 if (PageIndex == LIST_HEAD)
567 {
568 /* Check the free list */
570 PageIndex = MmFreePageListHead.Flink;
571 Color = PageIndex & MmSecondaryColorMask;
572 ASSERT(PageIndex != LIST_HEAD);
573 if (PageIndex == LIST_HEAD)
574 {
575 /* FIXME: Should check the standby list */
577 }
578 }
579 }
580 else
581 {
582 Color = PageIndex & MmSecondaryColorMask;
583 }
584 }
585
586 /* Sanity checks */
587 Pfn1 = MI_PFN_ELEMENT(PageIndex);
588 ASSERT((Pfn1->u3.e1.PageLocation == FreePageList) ||
589 (Pfn1->u3.e1.PageLocation == ZeroedPageList));
590
591 /* Remove the page from its list */
592 PageIndex = MiRemovePageByColor(PageIndex, Color);
593 ASSERT(PageIndex != 0);
594 ASSERT(Pfn1 == MI_PFN_ELEMENT(PageIndex));
595
596 /* Zero it, if needed */
597 if (Zero) MiZeroPhysicalPage(PageIndex);
598
599 /* Sanity checks */
600 ASSERT(Pfn1->u3.e2.ReferenceCount == 0);
601 ASSERT(Pfn1->u2.ShareCount == 0);
604
605 /* Return the page */
606 return PageIndex;
607}
unsigned char BOOLEAN
IN PVCB IN VBO IN ULONG OUT PBCB OUT PVOID IN BOOLEAN IN BOOLEAN Zero
Definition: fatprocs.h:419
VOID NTAPI MiZeroPhysicalPage(IN PFN_NUMBER PageFrameIndex)
Definition: pfnlist.c:122

Referenced by MiBuildPagedPool(), MiFillSystemPageDirectory(), MiInitializeAndChargePfn(), MiRemoveZeroPageSafe(), MiResolveDemandZeroFault(), MiSessionCommitPageTables(), and MmAllocPage().

◆ MiUnlinkFreeOrZeroedPage()

VOID NTAPI MiUnlinkFreeOrZeroedPage ( IN PMMPFN  Entry)

Definition at line 137 of file pfnlist.c.

138{
139 PFN_NUMBER OldFlink, OldBlink;
140 PMMPFNLIST ListHead;
141 MMLISTS ListName;
142 ULONG Color;
143 PMMCOLOR_TABLES ColorTable;
144 PMMPFN Pfn1;
145
146 /* Make sure the PFN lock is held */
148
149 /* Make sure the PFN entry isn't in-use */
150 ASSERT(Entry->u3.e1.WriteInProgress == 0);
151 ASSERT(Entry->u3.e1.ReadInProgress == 0);
152
153 /* Find the list for this entry, make sure it's the free or zero list */
154 ListHead = MmPageLocationList[Entry->u3.e1.PageLocation];
155 ListName = ListHead->ListName;
156 ASSERT(ListHead != NULL);
157 ASSERT(ListName <= FreePageList);
158 ASSERT_LIST_INVARIANT(ListHead);
159
160 /* Remove one count */
161 ASSERT(ListHead->Total != 0);
162 ListHead->Total--;
163
164 /* Get the forward and back pointers */
165 OldFlink = Entry->u1.Flink;
166 OldBlink = Entry->u2.Blink;
167
168 /* Check if the next entry is the list head */
169 if (OldFlink != LIST_HEAD)
170 {
171 /* It is not, so set the backlink of the actual entry, to our backlink */
172 MI_PFN_ELEMENT(OldFlink)->u2.Blink = OldBlink;
173 }
174 else
175 {
176 /* Set the list head's backlink instead */
177 ListHead->Blink = OldBlink;
178 }
179
180 /* Check if the back entry is the list head */
181 if (OldBlink != LIST_HEAD)
182 {
183 /* It is not, so set the backlink of the actual entry, to our backlink */
184 MI_PFN_ELEMENT(OldBlink)->u1.Flink = OldFlink;
185 }
186 else
187 {
188 /* Set the list head's backlink instead */
189 ListHead->Flink = OldFlink;
190 }
191
192 /* Get the page color */
193 OldBlink = MiGetPfnEntryIndex(Entry);
194 Color = OldBlink & MmSecondaryColorMask;
195
196 /* Get the first page on the color list */
197 ColorTable = &MmFreePagesByColor[ListName][Color];
198
199 /* Check if this was was actually the head */
200 OldFlink = ColorTable->Flink;
201 if (OldFlink == OldBlink)
202 {
203 /* Make the table point to the next page this page was linking to */
204 ColorTable->Flink = Entry->OriginalPte.u.Long;
205 if (ColorTable->Flink != LIST_HEAD)
206 {
207 /* And make the previous link point to the head now */
208 MI_PFN_ELEMENT(ColorTable->Flink)->u4.PteFrame = COLORED_LIST_HEAD;
209 }
210 else
211 {
212 /* And if that page was the head, loop the list back around */
213 ColorTable->Blink = (PVOID)LIST_HEAD;
214 }
215 }
216 else
217 {
218 /* This page shouldn't be pointing back to the head */
219 ASSERT(Entry->u4.PteFrame != COLORED_LIST_HEAD);
220
221 /* Make the back link point to whoever the next page is */
222 Pfn1 = MI_PFN_ELEMENT(Entry->u4.PteFrame);
223 Pfn1->OriginalPte.u.Long = Entry->OriginalPte.u.Long;
224
225 /* Check if this page was pointing to the head */
226 if (Entry->OriginalPte.u.Long != LIST_HEAD)
227 {
228 /* Make the back link point to the head */
229 Pfn1 = MI_PFN_ELEMENT(Entry->OriginalPte.u.Long);
230 Pfn1->u4.PteFrame = Entry->u4.PteFrame;
231 }
232 else
233 {
234 /* Then the table is directly back pointing to this page now */
235 ColorTable->Blink = Pfn1;
236 }
237 }
238
239 /* One less colored page */
240 ASSERT(ColorTable->Count >= 1);
241 ColorTable->Count--;
242
243 /* ReactOS Hack */
244 Entry->OriginalPte.u.Long = 0;
245
246 /* We are not on a list anymore */
247 Entry->u1.Flink = Entry->u2.Blink = 0;
248 ASSERT_LIST_INVARIANT(ListHead);
249
250 /* Decrement number of available pages */
252
253#if MI_TRACE_PFNS
255 Entry->PfnUsage = MI_PFN_CURRENT_USAGE;
256 memcpy(Entry->ProcessName, MI_PFN_CURRENT_PROCESS_NAME, 16);
257 Entry->CallSite = _ReturnAddress();
259 MI_SET_PROCESS2("Not Set");
260#endif
261}
base of all file and directory entries
Definition: entries.h:83

Referenced by MiAllocatePagesForMdl(), and MiFindContiguousPages().

◆ MiUnlinkPageFromList()

VOID NTAPI MiUnlinkPageFromList ( IN PMMPFN  Pfn)

Definition at line 265 of file pfnlist.c.

266{
267 PMMPFNLIST ListHead;
268 PFN_NUMBER OldFlink, OldBlink;
269
270 /* Make sure the PFN lock is held */
272
273 /* ARM3 should only call this for dead pages */
274 ASSERT(Pfn->u3.e2.ReferenceCount == 0);
275
276 /* Transition pages are supposed to be standby/modified/nowrite */
277 ListHead = MmPageLocationList[Pfn->u3.e1.PageLocation];
278 ASSERT(ListHead->ListName >= StandbyPageList);
279
280 /* Check if this was standby, or modified */
281 if (ListHead == &MmStandbyPageListHead)
282 {
283 /* Should not be a ROM page */
284 ASSERT(Pfn->u3.e1.Rom == 0);
285
286 /* Get the exact list */
287 ListHead = &MmStandbyPageListByPriority[Pfn->u4.Priority];
288
289 /* Decrement number of available pages */
291
292 /* Decrease transition page counter */
293 ASSERT(Pfn->u3.e1.PrototypePte == 1); /* Only supported ARM3 case */
295 }
296 else if (ListHead == &MmModifiedPageListHead)
297 {
298 /* Only shared memory (page-file backed) modified pages are supported */
299 ASSERT(Pfn->OriginalPte.u.Soft.Prototype == 0);
300
301 /* Decrement the counters */
302 ListHead->Total--;
304
305 /* Pick the correct colored list */
306 ListHead = &MmModifiedPageListByColor[0];
307
308 /* Decrease transition page counter */
310 }
311 else if (ListHead == &MmModifiedNoWritePageListHead)
312 {
313 /* List not yet supported */
314 ASSERT(FALSE);
315 }
316
317 /* Nothing should be in progress and the list should not be empty */
318 ASSERT(Pfn->u3.e1.WriteInProgress == 0);
319 ASSERT(Pfn->u3.e1.ReadInProgress == 0);
320 ASSERT(ListHead->Total != 0);
321
322 /* Get the forward and back pointers */
323 OldFlink = Pfn->u1.Flink;
324 OldBlink = Pfn->u2.Blink;
325
326 /* Check if the next entry is the list head */
327 if (OldFlink != LIST_HEAD)
328 {
329 /* It is not, so set the backlink of the actual entry, to our backlink */
330 MI_PFN_ELEMENT(OldFlink)->u2.Blink = OldBlink;
331 }
332 else
333 {
334 /* Set the list head's backlink instead */
335 ListHead->Blink = OldBlink;
336 }
337
338 /* Check if the back entry is the list head */
339 if (OldBlink != LIST_HEAD)
340 {
341 /* It is not, so set the backlink of the actual entry, to our backlink */
342 MI_PFN_ELEMENT(OldBlink)->u1.Flink = OldFlink;
343 }
344 else
345 {
346 /* Set the list head's backlink instead */
347 ListHead->Flink = OldFlink;
348 }
349
350 /* ReactOS Hack */
351 Pfn->OriginalPte.u.Long = 0;
352
353 /* We are not on a list anymore */
354 Pfn->u1.Flink = Pfn->u2.Blink = 0;
355
356 /* Remove one entry from the list */
357 ListHead->Total--;
358
359 ASSERT_LIST_INVARIANT(ListHead);
360}
MMPFNLIST MmModifiedNoWritePageListHead
Definition: pfnlist.c:47

Referenced by MiDeletePte(), MiDispatchFault(), MiResolveTransitionFault(), and MiSegmentDelete().

◆ MiZeroPhysicalPage()

VOID NTAPI MiZeroPhysicalPage ( IN PFN_NUMBER  PageFrameIndex)

Definition at line 122 of file pfnlist.c.

123{
127
128 /* Map in hyperspace, then wipe it using XMMI or MEMSET */
133}
#define PAGE_SIZE
Definition: env_spec_w32.h:49
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:223
VOID FASTCALL KeZeroPages(IN PVOID Address, IN ULONG Size)
Definition: cpu.c:56
VOID NTAPI MiUnmapPageInHyperSpace(IN PEPROCESS Process, IN PVOID Address, IN KIRQL OldIrql)
Definition: hypermap.c:91
PVOID NTAPI MiMapPageInHyperSpace(IN PEPROCESS Process, IN PFN_NUMBER Page, IN PKIRQL OldIrql)
Definition: hypermap.c:28
_Must_inspect_result_ _In_ WDFDMATRANSACTION _In_ PFN_WDF_PROGRAM_DMA _In_ WDF_DMA_DIRECTION _In_ PMDL _In_ PVOID VirtualAddress

Referenced by CcInitCacheZeroPage(), MiAllocatePagesForMdl(), MiArchCreateProcessAddressSpace(), MiRemoveZeroPage(), MiSessionCreateInternal(), MiSessionInitializeWorkingSetList(), and MmCreateProcessAddressSpace().

◆ MmDereferencePage()

VOID NTAPI MmDereferencePage ( PFN_NUMBER  Pfn)

Definition at line 566 of file freelist.c.

567{
568 PMMPFN Pfn1;
569 DPRINT("MmDereferencePage(PhysicalAddress %x)\n", Pfn << PAGE_SHIFT);
570
572
573 Pfn1 = MiGetPfnEntry(Pfn);
574 ASSERT(Pfn1);
575 ASSERT_IS_ROS_PFN(Pfn1);
576
577 ASSERT(Pfn1->u3.e2.ReferenceCount != 0);
578 Pfn1->u3.e2.ReferenceCount--;
579 if (Pfn1->u3.e2.ReferenceCount == 0)
580 {
581 /* Apply LRU hack */
582 if (Pfn1->u4.MustBeCached)
583 {
585 Pfn1->u4.MustBeCached = 0;
586 }
587
588 /* Mark the page temporarily as valid, we're going to make it free soon */
590
591 /* It's not a ROS PFN anymore */
592 Pfn1->u4.AweAllocation = FALSE;
593
594 /* Bring it back into the free list */
595 DPRINT("Legacy free: %lx\n", Pfn);
597 }
598}
#define PAGE_SHIFT
Definition: env_spec_w32.h:45
#define ASSERT_IS_ROS_PFN(x)
Definition: freelist.c:20
static VOID MmRemoveLRUUserPage(PFN_NUMBER Page)
Definition: freelist.c:87
VOID NTAPI MiInsertPageInFreeList(IN PFN_NUMBER PageFrameIndex)
Definition: pfnlist.c:611
FORCEINLINE PMMPFN MiGetPfnEntry(IN PFN_NUMBER Pfn)
Definition: mm.h:1047

Referenced by MiDecrementReferenceCount(), and MmGetLRUNextUserPage().

Variable Documentation

◆ MI_PFN_CURRENT_PROCESS_NAME

CHAR MI_PFN_CURRENT_PROCESS_NAME[16] = "None yet"

Definition at line 64 of file pfnlist.c.

Referenced by MiRemovePageByColor(), and MiUnlinkFreeOrZeroedPage().

◆ MI_PFN_CURRENT_USAGE

ULONG MI_PFN_CURRENT_USAGE

Definition at line 63 of file pfnlist.c.

Referenced by MiInsertPageInList(), MiRemovePageByColor(), and MiUnlinkFreeOrZeroedPage().

◆ MmBadPageListHead

MMPFNLIST MmBadPageListHead = {0, BadPageList, LIST_HEAD, LIST_HEAD}

Definition at line 48 of file pfnlist.c.

◆ MmDynamicPfn

BOOLEAN MmDynamicPfn

Definition at line 34 of file pfnlist.c.

◆ MmFreePageListHead

◆ MmMirroring

BOOLEAN MmMirroring

Definition at line 35 of file pfnlist.c.

◆ MmModifiedNoWritePageListHead

MMPFNLIST MmModifiedNoWritePageListHead = {0, ModifiedNoWritePageList, LIST_HEAD, LIST_HEAD}

Definition at line 47 of file pfnlist.c.

Referenced by MiUnlinkPageFromList().

◆ MmModifiedPageListByColor

MMPFNLIST MmModifiedPageListByColor[1] = {{0, ModifiedPageList, LIST_HEAD, LIST_HEAD}}

Definition at line 46 of file pfnlist.c.

Referenced by MiInsertPageInList(), and MiUnlinkPageFromList().

◆ MmModifiedPageListHead

◆ MmPageLocationList

◆ MmRomPageListHead

MMPFNLIST MmRomPageListHead = {0, StandbyPageList, LIST_HEAD, LIST_HEAD}

Definition at line 49 of file pfnlist.c.

◆ MmStandbyPageListByPriority

MMPFNLIST MmStandbyPageListByPriority[8]

◆ MmStandbyPageListHead

MMPFNLIST MmStandbyPageListHead = {0, StandbyPageList, LIST_HEAD, LIST_HEAD}

Definition at line 43 of file pfnlist.c.

Referenced by MiInsertPageInList(), and MiUnlinkPageFromList().

◆ MmSystemPageColor

ULONG MmSystemPageColor

Definition at line 36 of file pfnlist.c.

◆ MmTotalPagesForPagingFile

ULONG MmTotalPagesForPagingFile

Definition at line 39 of file pfnlist.c.

Referenced by MiInsertPageInList(), and MiUnlinkPageFromList().

◆ MmTransitionSharedPages

ULONG MmTransitionSharedPages

Definition at line 38 of file pfnlist.c.

Referenced by MiInsertPageInList(), MiInsertStandbyListAtFront(), and MiUnlinkPageFromList().

◆ MmZeroedPageListHead

MMPFNLIST MmZeroedPageListHead = {0, ZeroedPageList, LIST_HEAD, LIST_HEAD}

Definition at line 41 of file pfnlist.c.

Referenced by MiRemoveAnyPage(), MiRemoveZeroPage(), and MmZeroPageThread().