ReactOS 0.4.15-dev-6049-ge54b32b
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 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:271
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 1224 of file pfnlist.c.

1226{
1227 /* PFN lock must be held */
1229
1230 /* Sanity checks on the page */
1231 if (PageFrameIndex > MmHighestPhysicalPage ||
1232 Pfn1 != MI_PFN_ELEMENT(PageFrameIndex) ||
1233 Pfn1->u3.e2.ReferenceCount == 0 ||
1234 Pfn1->u3.e2.ReferenceCount >= 2500)
1235 {
1236 DPRINT1("PageFrameIndex=0x%lx, MmHighestPhysicalPage=0x%lx\n", PageFrameIndex, MmHighestPhysicalPage);
1237 DPRINT1("Pfn1=%p, Element=%p, RefCount=%u\n", Pfn1, MI_PFN_ELEMENT(PageFrameIndex), Pfn1->u3.e2.ReferenceCount);
1238 ASSERT(PageFrameIndex <= MmHighestPhysicalPage);
1239 ASSERT(Pfn1 == MI_PFN_ELEMENT(PageFrameIndex));
1240 ASSERT(Pfn1->u3.e2.ReferenceCount != 0);
1241 ASSERT(Pfn1->u3.e2.ReferenceCount < 2500);
1242 }
1243
1244 /* Dereference the page, bail out if it's still alive */
1245 InterlockedDecrement16((PSHORT)&Pfn1->u3.e2.ReferenceCount);
1246 if (Pfn1->u3.e2.ReferenceCount) return;
1247
1248 /* Nobody should still have reference to this page */
1249 if (Pfn1->u2.ShareCount != 0)
1250 {
1251 /* Otherwise something's really wrong */
1252 KeBugCheckEx(PFN_LIST_CORRUPT, 7, PageFrameIndex, Pfn1->u2.ShareCount, 0);
1253 }
1254
1255 /* And it should be lying on some page list */
1256 ASSERT(Pfn1->u3.e1.PageLocation != ActiveAndValid);
1257
1258 /* Did someone set the delete flag? */
1259 if (MI_IS_PFN_DELETED(Pfn1))
1260 {
1261 /* Insert it into the free list, there's nothing left to do */
1262 MiInsertPageInFreeList(PageFrameIndex);
1263 return;
1264 }
1265
1266 /* Check to see which list this page should go into */
1267 if (Pfn1->u3.e1.Modified == 1)
1268 {
1269 /* Push it into the modified page list */
1271 }
1272 else
1273 {
1274 /* Otherwise, insert this page into the standby list */
1275 ASSERT(Pfn1->u3.e1.RemovalRequested == 0);
1276 MiInsertStandbyListAtFront(PageFrameIndex);
1277 }
1278}
#define InterlockedDecrement16
Definition: interlocked.h:139
PFN_NUMBER MmHighestPhysicalPage
Definition: meminit.c:31
#define MI_IS_PFN_DELETED(x)
Definition: miarm.h:195
FORCEINLINE PMMPFN MI_PFN_ELEMENT(IN PFN_NUMBER Pfn)
Definition: miarm.h:1574
@ ActiveAndValid
Definition: mmtypes.h:155
#define MI_ASSERT_PFN_LOCK_HELD()
Definition: mm.h:1043
VOID NTAPI MiInsertPageInFreeList(IN PFN_NUMBER PageFrameIndex)
Definition: pfnlist.c:603
MMPFNLIST MmModifiedPageListHead
Definition: pfnlist.c:45
VOID NTAPI MiInsertPageInList(IN PMMPFNLIST ListHead, IN PFN_NUMBER PageFrameIndex)
Definition: pfnlist.c:771
VOID FASTCALL MiInsertStandbyListAtFront(IN PFN_NUMBER PageFrameIndex)
Definition: pfnlist.c:711
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
union _MMPFN::@1772 u3
struct _MMPFN::@1772::@1778 e2
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 1133 of file pfnlist.c.

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

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 1093 of file pfnlist.c.

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

Referenced by MiInitializeSessionPool().

◆ MiInitializePfn()

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

Definition at line 962 of file pfnlist.c.

965{
966 PMMPFN Pfn1;
968 PMMPTE PointerPtePte;
970
971 /* Setup the PTE */
972 Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);
973 Pfn1->PteAddress = PointerPte;
974
975 DPRINT("Called for %p from %p\n", Pfn1, _ReturnAddress());
976
977 /* Check if this PFN is part of a valid address space */
978 if (PointerPte->u.Hard.Valid == 1)
979 {
980 /* Only valid from MmCreateProcessAddressSpace path */
981 ASSERT(PsGetCurrentProcess()->Vm.WorkingSetSize == 0);
982
983 /* Make this a demand zero PTE */
985 }
986 else
987 {
988 /* Copy the PTE data */
989 Pfn1->OriginalPte = *PointerPte;
990 ASSERT(!((Pfn1->OriginalPte.u.Soft.Prototype == 0) &&
991 (Pfn1->OriginalPte.u.Soft.Transition == 1)));
992 }
993
994 /* Otherwise this is a fresh page -- set it up */
995 ASSERT(Pfn1->u3.e2.ReferenceCount == 0);
996 Pfn1->u3.e2.ReferenceCount = 1;
997 Pfn1->u2.ShareCount = 1;
999 ASSERT(Pfn1->u3.e1.Rom == 0);
1000 Pfn1->u3.e1.Modified = Modified;
1001
1002 /* Get the page table for the PTE */
1003 PointerPtePte = MiAddressToPte(PointerPte);
1004 if (PointerPtePte->u.Hard.Valid == 0)
1005 {
1006 /* Make sure the PDE gets paged in properly */
1007 Status = MiCheckPdeForPagedPool(PointerPte);
1008 if (!NT_SUCCESS(Status))
1009 {
1010 /* Crash */
1011 KeBugCheckEx(MEMORY_MANAGEMENT,
1012 0x61940,
1013 (ULONG_PTR)PointerPte,
1014 (ULONG_PTR)PointerPtePte->u.Long,
1015 (ULONG_PTR)MiPteToAddress(PointerPte));
1016 }
1017 }
1018
1019 /* Get the PFN for the page table */
1020 PageFrameIndex = PFN_FROM_PTE(PointerPtePte);
1021 ASSERT(PageFrameIndex != 0);
1022 Pfn1->u4.PteFrame = PageFrameIndex;
1023
1024 DPRINT("Incrementing share count of %lp from %p\n", PageFrameIndex, _ReturnAddress());
1025
1026 /* Increase its share count so we don't get rid of it */
1027 Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);
1028 Pfn1->u2.ShareCount++;
1029}
LONG NTSTATUS
Definition: precomp.h:26
#define MM_READWRITE
Definition: bootanim.c:19
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
Status
Definition: gdiplustypes.h:25
#define MI_MAKE_SOFTWARE_PTE(p, x)
Definition: miarm.h:189
NTSTATUS FASTCALL MiCheckPdeForPagedPool(IN PVOID Address)
Definition: pagfault.c:475
#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
union _MMPFN::@1775 u4
PMMPTE PteAddress
Definition: mm.h:386
MMPFNENTRY e1
Definition: mm.h:397
ULONG_PTR ShareCount
Definition: mm.h:390
union _MMPFN::@1771 u2
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 1033 of file pfnlist.c.

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

1285{
1286 PMMPFN Pfn1;
1287
1288 /* Setup the PTE */
1289 Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);
1290 Pfn1->PteAddress = PteAddress;
1291
1292 /* Make this a software PTE */
1294
1295 DPRINT("Called for %p from %p\n", Pfn1, _ReturnAddress());
1296
1297 /* Setup the page */
1298 ASSERT(Pfn1->u3.e2.ReferenceCount == 0);
1299 Pfn1->u3.e2.ReferenceCount = 1;
1300 Pfn1->u2.ShareCount = 1;
1302 Pfn1->u3.e1.Modified = TRUE;
1303 Pfn1->u4.InPageError = FALSE;
1304
1305 /* Did we get a PFN for the page table */
1306 if (PteFrame)
1307 {
1308 /* Store it */
1309 Pfn1->u4.PteFrame = PteFrame;
1310
1311 /* Increase its share count so we don't get rid of it */
1312 Pfn1 = MI_PFN_ELEMENT(PteFrame);
1313
1314 DPRINT("Incrementing %p from %p\n", Pfn1, _ReturnAddress());
1315 Pfn1->u2.ShareCount++;
1316 }
1317}
#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 603 of file pfnlist.c.

604{
605 PMMPFNLIST ListHead;
606 PFN_NUMBER LastPage;
607 PMMPFN Pfn1;
608 ULONG Color;
609 PMMPFN Blink;
610 PMMCOLOR_TABLES ColorTable;
611
612 /* Make sure the page index is valid */
614 ASSERT((PageFrameIndex != 0) &&
615 (PageFrameIndex <= MmHighestPhysicalPage) &&
616 (PageFrameIndex >= MmLowestPhysicalPage));
617
618 /* Get the PFN entry */
619 Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);
620
621 /* Sanity checks that a right kind of page is being inserted here */
622 ASSERT(Pfn1->u4.MustBeCached == 0);
623 ASSERT(Pfn1->u3.e1.Rom != 1);
624 ASSERT(Pfn1->u3.e1.RemovalRequested == 0);
625 ASSERT(Pfn1->u4.VerifierAllocation == 0);
626 ASSERT(Pfn1->u3.e2.ReferenceCount == 0);
627
628 /* Get the free page list and increment its count */
629 ListHead = &MmFreePageListHead;
630 ASSERT_LIST_INVARIANT(ListHead);
631 ListHead->Total++;
632
633 /* Get the last page on the list */
634 LastPage = ListHead->Blink;
635 if (LastPage != LIST_HEAD)
636 {
637 /* Link us with the previous page, so we're at the end now */
638 MI_PFN_ELEMENT(LastPage)->u1.Flink = PageFrameIndex;
639 }
640 else
641 {
642 /* The list is empty, so we are the first page */
643 ListHead->Flink = PageFrameIndex;
644 }
645
646 /* Now make the list head point back to us (since we go at the end) */
647 ListHead->Blink = PageFrameIndex;
648 ASSERT_LIST_INVARIANT(ListHead);
649
650 /* And initialize our own list pointers */
651 Pfn1->u1.Flink = LIST_HEAD;
652 Pfn1->u2.Blink = LastPage;
653
654 /* Set the list name and default priority */
656 Pfn1->u4.Priority = 3;
657
658 /* Clear some status fields */
659 Pfn1->u4.InPageError = 0;
660 Pfn1->u4.AweAllocation = 0;
661
662 /* Increment number of available pages */
664
665 /* Get the page color */
666 Color = PageFrameIndex & MmSecondaryColorMask;
667
668 /* Get the first page on the color list */
669 ColorTable = &MmFreePagesByColor[FreePageList][Color];
670 if (ColorTable->Flink == LIST_HEAD)
671 {
672 /* The list is empty, so we are the first page */
673 Pfn1->u4.PteFrame = COLORED_LIST_HEAD;
674 ColorTable->Flink = PageFrameIndex;
675 }
676 else
677 {
678 /* Get the previous page */
679 Blink = (PMMPFN)ColorTable->Blink;
680
681 /* Make it link to us, and link back to it */
682 Blink->OriginalPte.u.Long = PageFrameIndex;
683 Pfn1->u4.PteFrame = MiGetPfnEntryIndex(Blink);
684 }
685
686 /* Now initialize our own list pointers */
687 ColorTable->Blink = Pfn1;
688
689 /* This page is now the last */
690 Pfn1->OriginalPte.u.Long = LIST_HEAD;
691
692 /* And increase the count in the colored list */
693 ColorTable->Count++;
694
695 /* Notify zero page thread if enough pages are on the free list now */
696 if (ListHead->Total >= 8)
697 {
698 /* Set the event */
700 }
701
702#if MI_TRACE_PFNS
703 Pfn1->PfnUsage = MI_USAGE_FREE_PAGE;
704 RtlZeroMemory(Pfn1->ProcessName, 16);
705 Pfn1->CallSite = NULL;
706#endif
707}
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:150
@ 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:433
PVOID Blink
Definition: miarm.h:432
PFN_NUMBER Flink
Definition: miarm.h:431
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 771 of file pfnlist.c.

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

712{
713 PMMPFNLIST ListHead;
714 PFN_NUMBER Flink;
715 PMMPFN Pfn1, Pfn2;
716
717 /* Make sure the lock is held */
718 DPRINT("Inserting page: %lx into standby list !\n", PageFrameIndex);
720
721 /* Make sure the PFN is valid */
722 ASSERT((PageFrameIndex != 0) &&
723 (PageFrameIndex <= MmHighestPhysicalPage) &&
724 (PageFrameIndex >= MmLowestPhysicalPage));
725
726 /* Grab the PFN and validate it is the right kind of PFN being inserted */
727 Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);
728 ASSERT(Pfn1->u4.MustBeCached == 0);
729 ASSERT(Pfn1->u3.e2.ReferenceCount == 0);
730 ASSERT(Pfn1->u3.e1.PrototypePte == 1);
731 ASSERT(Pfn1->u3.e1.Rom != 1);
732
733 /* One more transition page on a list */
735
736 /* Get the standby page list and increment its count */
737 ListHead = &MmStandbyPageListByPriority [Pfn1->u4.Priority];
738 ASSERT_LIST_INVARIANT(ListHead);
739 ListHead->Total++;
740
741 /* Make the head of the list point to this page now */
742 Flink = ListHead->Flink;
743 ListHead->Flink = PageFrameIndex;
744
745 /* Make the page point to the previous head, and back to the list */
746 Pfn1->u1.Flink = Flink;
747 Pfn1->u2.Blink = LIST_HEAD;
748
749 /* Was the list empty? */
750 if (Flink != LIST_HEAD)
751 {
752 /* It wasn't, so update the backlink of the previous head page */
753 Pfn2 = MI_PFN_ELEMENT(Flink);
754 Pfn2->u2.Blink = PageFrameIndex;
755 }
756 else
757 {
758 /* It was empty, so have it loop back around to this new page */
759 ListHead->Blink = PageFrameIndex;
760 }
761
762 /* Move the page onto its new location */
764
765 /* Increment number of available pages */
767}
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 */
486
487 /* Check the colored free list */
489 if (PageIndex == LIST_HEAD)
490 {
491 /* Check the colored zero list */
493 if (PageIndex == LIST_HEAD)
494 {
495 /* Check the free list */
497 PageIndex = MmFreePageListHead.Flink;
498 Color = PageIndex & MmSecondaryColorMask;
499 if (PageIndex == LIST_HEAD)
500 {
501 /* Check the zero list */
503 PageIndex = MmZeroedPageListHead.Flink;
504 Color = PageIndex & MmSecondaryColorMask;
505 ASSERT(PageIndex != LIST_HEAD);
506 if (PageIndex == LIST_HEAD)
507 {
508 /* FIXME: Should check the standby list */
510 }
511 }
512 }
513 }
514
515 /* Remove the page from its list */
516 PageIndex = MiRemovePageByColor(PageIndex, Color);
517
518 /* Sanity checks */
519 Pfn1 = MI_PFN_ELEMENT(PageIndex);
520 ASSERT((Pfn1->u3.e1.PageLocation == FreePageList) ||
521 (Pfn1->u3.e1.PageLocation == ZeroedPageList));
522 ASSERT(Pfn1->u3.e2.ReferenceCount == 0);
523 ASSERT(Pfn1->u2.ShareCount == 0);
526
527 /* Return the page */
528 return PageIndex;
529}
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 533 of file pfnlist.c.

534{
535 PFN_NUMBER PageIndex;
536 PMMPFN Pfn1;
538
539 /* Make sure PFN lock is held and we have pages */
543
544 /* Check the colored zero list */
546 if (PageIndex == LIST_HEAD)
547 {
548 /* Check the zero list */
550 PageIndex = MmZeroedPageListHead.Flink;
551 if (PageIndex == LIST_HEAD)
552 {
553 /* This means there's no zero pages, we have to look for free ones */
555 Zero = TRUE;
556
557 /* Check the colored free list */
559 if (PageIndex == LIST_HEAD)
560 {
561 /* Check the free list */
563 PageIndex = MmFreePageListHead.Flink;
564 Color = PageIndex & MmSecondaryColorMask;
565 ASSERT(PageIndex != LIST_HEAD);
566 if (PageIndex == LIST_HEAD)
567 {
568 /* FIXME: Should check the standby list */
570 }
571 }
572 }
573 else
574 {
575 Color = PageIndex & MmSecondaryColorMask;
576 }
577 }
578
579 /* Sanity checks */
580 Pfn1 = MI_PFN_ELEMENT(PageIndex);
581 ASSERT((Pfn1->u3.e1.PageLocation == FreePageList) ||
582 (Pfn1->u3.e1.PageLocation == ZeroedPageList));
583
584 /* Remove the page from its list */
585 PageIndex = MiRemovePageByColor(PageIndex, Color);
586 ASSERT(Pfn1 == MI_PFN_ELEMENT(PageIndex));
587
588 /* Zero it, if needed */
589 if (Zero) MiZeroPhysicalPage(PageIndex);
590
591 /* Sanity checks */
592 ASSERT(Pfn1->u3.e2.ReferenceCount == 0);
593 ASSERT(Pfn1->u2.ShareCount == 0);
596
597 /* Return the page */
598 return PageIndex;
599}
unsigned char BOOLEAN
IN PVCB IN VBO IN ULONG OUT PBCB OUT PVOID IN BOOLEAN IN BOOLEAN Zero
Definition: fatprocs.h:418
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().

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().