ReactOS  0.4.15-dev-2996-gf777e6b
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)
 
BOOLEAN MmRosNotifyAvailablePage (PFN_NUMBER PageFrameIndex)
 
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 }
PFN_NUMBER MmMinimumFreePages
Definition: mminit.c:314
PFN_NUMBER MmHighMemoryThreshold
Definition: mminit.c:301
PFN_NUMBER MmAvailablePages
Definition: freelist.c:26
LONG NTAPI KeSetEvent(IN PKEVENT Event, IN KPRIORITY Increment, IN BOOLEAN Wait)
Definition: eventobj.c:159
#define FALSE
Definition: types.h:117
VOID NTAPI MmRebalanceMemoryConsumers(VOID)
Definition: balance.c:265
#define ASSERT(a)
Definition: mode.c:44
PFN_NUMBER MmLowMemoryThreshold
Definition: mminit.c:300
#define DPRINT1
Definition: precomp.h:8
PKEVENT MiLowMemoryEvent
Definition: mminit.c:292
VOID NTAPI KeClearEvent(IN PKEVENT Event)
Definition: eventobj.c:22
PKEVENT MiHighMemoryEvent
Definition: mminit.c:293

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

◆ MiDecrementReferenceCount()

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

Definition at line 1234 of file pfnlist.c.

1236 {
1237  /* PFN lock must be held */
1239 
1240  /* Sanity checks on the page */
1241  if (PageFrameIndex > MmHighestPhysicalPage ||
1242  Pfn1 != MI_PFN_ELEMENT(PageFrameIndex) ||
1243  Pfn1->u3.e2.ReferenceCount == 0 ||
1244  Pfn1->u3.e2.ReferenceCount >= 2500)
1245  {
1246  DPRINT1("PageFrameIndex=0x%lx, MmHighestPhysicalPage=0x%lx\n", PageFrameIndex, MmHighestPhysicalPage);
1247  DPRINT1("Pfn1=%p, Element=%p, RefCount=%u\n", Pfn1, MI_PFN_ELEMENT(PageFrameIndex), Pfn1->u3.e2.ReferenceCount);
1248  ASSERT(PageFrameIndex <= MmHighestPhysicalPage);
1249  ASSERT(Pfn1 == MI_PFN_ELEMENT(PageFrameIndex));
1250  ASSERT(Pfn1->u3.e2.ReferenceCount != 0);
1251  ASSERT(Pfn1->u3.e2.ReferenceCount < 2500);
1252  }
1253 
1254  /* Dereference the page, bail out if it's still alive */
1255  InterlockedDecrement16((PSHORT)&Pfn1->u3.e2.ReferenceCount);
1256  if (Pfn1->u3.e2.ReferenceCount) return;
1257 
1258  /* Nobody should still have reference to this page */
1259  if (Pfn1->u2.ShareCount != 0)
1260  {
1261  /* Otherwise something's really wrong */
1262  KeBugCheckEx(PFN_LIST_CORRUPT, 7, PageFrameIndex, Pfn1->u2.ShareCount, 0);
1263  }
1264 
1265  /* And it should be lying on some page list */
1266  ASSERT(Pfn1->u3.e1.PageLocation != ActiveAndValid);
1267 
1268  /* Did someone set the delete flag? */
1269  if (MI_IS_PFN_DELETED(Pfn1))
1270  {
1271  /* Insert it into the free list, there's nothing left to do */
1272  MiInsertPageInFreeList(PageFrameIndex);
1273  return;
1274  }
1275 
1276  /* Check to see which list this page should go into */
1277  if (Pfn1->u3.e1.Modified == 1)
1278  {
1279  /* Push it into the modified page list */
1280  MiInsertPageInList(&MmModifiedPageListHead, PageFrameIndex);
1281  }
1282  else
1283  {
1284  /* Otherwise, insert this page into the standby list */
1285  ASSERT(Pfn1->u3.e1.RemovalRequested == 0);
1286  MiInsertStandbyListAtFront(PageFrameIndex);
1287  }
1288 }
VOID FASTCALL MiInsertStandbyListAtFront(IN PFN_NUMBER PageFrameIndex)
Definition: pfnlist.c:721
#define MI_ASSERT_PFN_LOCK_HELD()
Definition: mm.h:996
signed short * PSHORT
Definition: retypes.h:6
VOID NTAPI MiInsertPageInList(IN PMMPFNLIST ListHead, IN PFN_NUMBER PageFrameIndex)
Definition: pfnlist.c:781
union _MMPFN::@1761 u3
MMPFNLIST MmModifiedPageListHead
Definition: pfnlist.c:45
#define ASSERT(a)
Definition: mode.c:44
#define MI_IS_PFN_DELETED(x)
Definition: miarm.h:195
FORCEINLINE PMMPFN MI_PFN_ELEMENT(IN PFN_NUMBER Pfn)
Definition: miarm.h:1579
VOID NTAPI MiInsertPageInFreeList(IN PFN_NUMBER PageFrameIndex)
Definition: pfnlist.c:606
#define InterlockedDecrement16
Definition: interlocked.h:139
struct _MMPFN::@1761::@1767 e2
#define DPRINT1
Definition: precomp.h:8
PFN_NUMBER MmHighestPhysicalPage
Definition: meminit.c:31
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

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

◆ MiDecrementShareCount()

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

Definition at line 1143 of file pfnlist.c.

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

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 }
PFN_NUMBER MmHighMemoryThreshold
Definition: mminit.c:301
PFN_NUMBER MmAvailablePages
Definition: freelist.c:26
LONG NTAPI KeSetEvent(IN PKEVENT Event, IN KPRIORITY Increment, IN BOOLEAN Wait)
Definition: eventobj.c:159
#define FALSE
Definition: types.h:117
PFN_NUMBER MmLowMemoryThreshold
Definition: mminit.c:300
PKEVENT MiLowMemoryEvent
Definition: mminit.c:292
VOID NTAPI KeClearEvent(IN PKEVENT Event)
Definition: eventobj.c:22
PKEVENT MiHighMemoryEvent
Definition: mminit.c:293

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

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

Referenced by MiInitializeSessionPool().

◆ MiInitializePfn()

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

Definition at line 972 of file pfnlist.c.

975 {
976  PMMPFN Pfn1;
978  PMMPTE PointerPtePte;
980 
981  /* Setup the PTE */
982  Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);
983  Pfn1->PteAddress = PointerPte;
984 
985  DPRINT("Called for %p from %p\n", Pfn1, _ReturnAddress());
986 
987  /* Check if this PFN is part of a valid address space */
988  if (PointerPte->u.Hard.Valid == 1)
989  {
990  /* Only valid from MmCreateProcessAddressSpace path */
991  ASSERT(PsGetCurrentProcess()->Vm.WorkingSetSize == 0);
992 
993  /* Make this a demand zero PTE */
995  }
996  else
997  {
998  /* Copy the PTE data */
999  Pfn1->OriginalPte = *PointerPte;
1000  ASSERT(!((Pfn1->OriginalPte.u.Soft.Prototype == 0) &&
1001  (Pfn1->OriginalPte.u.Soft.Transition == 1)));
1002  }
1003 
1004  /* Otherwise this is a fresh page -- set it up */
1005  ASSERT(Pfn1->u3.e2.ReferenceCount == 0);
1006  Pfn1->u3.e2.ReferenceCount = 1;
1007  Pfn1->u2.ShareCount = 1;
1008  Pfn1->u3.e1.PageLocation = ActiveAndValid;
1009  ASSERT(Pfn1->u3.e1.Rom == 0);
1010  Pfn1->u3.e1.Modified = Modified;
1011 
1012  /* Get the page table for the PTE */
1013  PointerPtePte = MiAddressToPte(PointerPte);
1014  if (PointerPtePte->u.Hard.Valid == 0)
1015  {
1016  /* Make sure the PDE gets paged in properly */
1017  Status = MiCheckPdeForPagedPool(PointerPte);
1018  if (!NT_SUCCESS(Status))
1019  {
1020  /* Crash */
1021  KeBugCheckEx(MEMORY_MANAGEMENT,
1022  0x61940,
1023  (ULONG_PTR)PointerPte,
1024  (ULONG_PTR)PointerPtePte->u.Long,
1025  (ULONG_PTR)MiPteToAddress(PointerPte));
1026  }
1027  }
1028 
1029  /* Get the PFN for the page table */
1030  PageFrameIndex = PFN_FROM_PTE(PointerPtePte);
1031  ASSERT(PageFrameIndex != 0);
1032  Pfn1->u4.PteFrame = PageFrameIndex;
1033 
1034  DPRINT("Incrementing share count of %lp from %p\n", PageFrameIndex, _ReturnAddress());
1035 
1036  /* Increase its share count so we don't get rid of it */
1037  Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);
1038  Pfn1->u2.ShareCount++;
1039 }
#define MI_MAKE_SOFTWARE_PTE(p, x)
Definition: miarm.h:189
#define MI_ASSERT_PFN_LOCK_HELD()
Definition: mm.h:996
LONG NTSTATUS
Definition: precomp.h:26
union _MMPFN::@1761 u3
USHORT Modified
Definition: mm.h:349
NTSTATUS FASTCALL MiCheckPdeForPagedPool(IN PVOID Address)
Definition: pagfault.c:475
USHORT PageLocation
Definition: mm.h:354
uint32_t ULONG_PTR
Definition: typedefs.h:65
MMPFNENTRY e1
Definition: mm.h:386
#define MiAddressToPte(x)
Definition: mmx86.c:19
ULONG_PTR ShareCount
Definition: mm.h:379
#define PsGetCurrentProcess
Definition: psfuncs.h:17
union _MMPFN::@1760 u2
Status
Definition: gdiplustypes.h:24
#define ASSERT(a)
Definition: mode.c:44
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
ULONG64 Valid
Definition: mmtypes.h:150
FORCEINLINE PMMPFN MI_PFN_ELEMENT(IN PFN_NUMBER Pfn)
Definition: miarm.h:1579
#define MM_READWRITE
Definition: inbv.c:12
Definition: mm.h:362
ULONG64 Prototype
Definition: mmtypes.h:89
ULONG_PTR Long
Definition: mmtypes.h:215
MMPTE_HARDWARE Hard
Definition: mmtypes.h:217
ULONG_PTR PteFrame
Definition: mm.h:407
ULONG64 Transition
Definition: mmtypes.h:90
struct _MMPFN::@1761::@1767 e2
USHORT Rom
Definition: mm.h:357
PMMPTE PteAddress
Definition: mm.h:375
MMPTE_SOFTWARE Soft
Definition: mmtypes.h:219
MMPTE OriginalPte
Definition: mm.h:396
void * _ReturnAddress(void)
#define DPRINT
Definition: sndvol32.h:71
FORCEINLINE PVOID MiPteToAddress(PMMPTE PointerPte)
Definition: mm.h:201
union _MMPTE::@2287 u
#define PFN_FROM_PTE(v)
Definition: mm.h:92
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::@1764 u4

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

1046 {
1047  PMMPFN Pfn1;
1048  NTSTATUS Status;
1049  PMMPTE PointerPtePte;
1051 
1052  /* PTE must be invalid */
1053  ASSERT(PointerPte->u.Hard.Valid == 0);
1054 
1055  /* Setup the PTE */
1056  Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);
1057  Pfn1->PteAddress = PointerPte;
1058  Pfn1->OriginalPte = DemandZeroPte;
1059 
1060  DPRINT("Incrementing %p from %p\n", Pfn1, _ReturnAddress());
1061 
1062  /* Otherwise this is a fresh page -- set it up */
1063  ASSERT(Pfn1->u3.e2.ReferenceCount == 0);
1064  Pfn1->u3.e2.ReferenceCount++;
1065  Pfn1->u2.ShareCount++;
1066  Pfn1->u3.e1.PageLocation = ActiveAndValid;
1067  ASSERT(Pfn1->u3.e1.Rom == 0);
1068  Pfn1->u3.e1.Modified = 1;
1069 
1070  /* Get the page table for the PTE */
1071  PointerPtePte = MiAddressToPte(PointerPte);
1072  if (PointerPtePte->u.Hard.Valid == 0)
1073  {
1074  /* Make sure the PDE gets paged in properly */
1075  Status = MiCheckPdeForPagedPool(PointerPte);
1076  if (!NT_SUCCESS(Status))
1077  {
1078  /* Crash */
1079  KeBugCheckEx(MEMORY_MANAGEMENT,
1080  0x61940,
1081  (ULONG_PTR)PointerPte,
1082  (ULONG_PTR)PointerPtePte->u.Long,
1083  (ULONG_PTR)MiPteToAddress(PointerPte));
1084  }
1085  }
1086 
1087  /* Get the PFN for the page table */
1088  PageFrameIndex = PFN_FROM_PTE(PointerPtePte);
1089  ASSERT(PageFrameIndex != 0);
1090  Pfn1->u4.PteFrame = PageFrameIndex;
1091 
1092  /* Increase its share count so we don't get rid of it */
1093  Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);
1094  Pfn1->u2.ShareCount++;
1095  DPRINT("Incrementing %p from %p\n", Pfn1, _ReturnAddress());
1096 
1097  /* Write valid PTE */
1098  MI_WRITE_VALID_PTE(PointerPte, TempPte);
1099 }
#define MI_ASSERT_PFN_LOCK_HELD()
Definition: mm.h:996
LONG NTSTATUS
Definition: precomp.h:26
union _MMPFN::@1761 u3
USHORT Modified
Definition: mm.h:349
NTSTATUS FASTCALL MiCheckPdeForPagedPool(IN PVOID Address)
Definition: pagfault.c:475
USHORT PageLocation
Definition: mm.h:354
uint32_t ULONG_PTR
Definition: typedefs.h:65
MMPFNENTRY e1
Definition: mm.h:386
#define MiAddressToPte(x)
Definition: mmx86.c:19
FORCEINLINE VOID MI_WRITE_VALID_PTE(IN PMMPTE PointerPte, IN MMPTE TempPte)
Definition: miarm.h:964
ULONG_PTR ShareCount
Definition: mm.h:379
union _MMPFN::@1760 u2
Status
Definition: gdiplustypes.h:24
#define ASSERT(a)
Definition: mode.c:44
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
ULONG64 Valid
Definition: mmtypes.h:150
HARDWARE_PTE_ARMV6 TempPte
Definition: winldr.c:76
FORCEINLINE PMMPFN MI_PFN_ELEMENT(IN PFN_NUMBER Pfn)
Definition: miarm.h:1579
Definition: mm.h:362
ULONG_PTR Long
Definition: mmtypes.h:215
MMPTE_HARDWARE Hard
Definition: mmtypes.h:217
ULONG_PTR PteFrame
Definition: mm.h:407
struct _MMPFN::@1761::@1767 e2
USHORT Rom
Definition: mm.h:357
PMMPTE PteAddress
Definition: mm.h:375
MMPTE OriginalPte
Definition: mm.h:396
void * _ReturnAddress(void)
MMPTE DemandZeroPte
Definition: init.c:37
#define DPRINT
Definition: sndvol32.h:71
FORCEINLINE PVOID MiPteToAddress(PMMPTE PointerPte)
Definition: mm.h:201
union _MMPTE::@2287 u
#define PFN_FROM_PTE(v)
Definition: mm.h:92
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::@1764 u4

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

1295 {
1296  PMMPFN Pfn1;
1297 
1298  /* Setup the PTE */
1299  Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);
1300  Pfn1->PteAddress = PteAddress;
1301 
1302  /* Make this a software PTE */
1304 
1305  DPRINT("Called for %p from %p\n", Pfn1, _ReturnAddress());
1306 
1307  /* Setup the page */
1308  ASSERT(Pfn1->u3.e2.ReferenceCount == 0);
1309  Pfn1->u3.e2.ReferenceCount = 1;
1310  Pfn1->u2.ShareCount = 1;
1311  Pfn1->u3.e1.PageLocation = ActiveAndValid;
1312  Pfn1->u3.e1.Modified = TRUE;
1313  Pfn1->u4.InPageError = FALSE;
1314 
1315  /* Did we get a PFN for the page table */
1316  if (PteFrame)
1317  {
1318  /* Store it */
1319  Pfn1->u4.PteFrame = PteFrame;
1320 
1321  /* Increase its share count so we don't get rid of it */
1322  Pfn1 = MI_PFN_ELEMENT(PteFrame);
1323 
1324  DPRINT("Incrementing %p from %p\n", Pfn1, _ReturnAddress());
1325  Pfn1->u2.ShareCount++;
1326  }
1327 }
#define MI_MAKE_SOFTWARE_PTE(p, x)
Definition: miarm.h:189
#define TRUE
Definition: types.h:120
union _MMPFN::@1761 u3
USHORT Modified
Definition: mm.h:349
USHORT PageLocation
Definition: mm.h:354
MMPFNENTRY e1
Definition: mm.h:386
#define FALSE
Definition: types.h:117
ULONG_PTR ShareCount
Definition: mm.h:379
union _MMPFN::@1760 u2
#define ASSERT(a)
Definition: mode.c:44
FORCEINLINE PMMPFN MI_PFN_ELEMENT(IN PFN_NUMBER Pfn)
Definition: miarm.h:1579
#define MM_READWRITE
Definition: inbv.c:12
Definition: mm.h:362
ULONG_PTR PteFrame
Definition: mm.h:407
struct _MMPFN::@1761::@1767 e2
PMMPTE PteAddress
Definition: mm.h:375
MMPTE OriginalPte
Definition: mm.h:396
void * _ReturnAddress(void)
ULONG_PTR InPageError
Definition: mm.h:408
#define DPRINT
Definition: sndvol32.h:71
union _MMPFN::@1764 u4

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

◆ MiInsertPageInFreeList()

VOID NTAPI MiInsertPageInFreeList ( IN PFN_NUMBER  PageFrameIndex)

Definition at line 606 of file pfnlist.c.

607 {
608  PMMPFNLIST ListHead;
609  PFN_NUMBER LastPage;
610  PMMPFN Pfn1;
611  ULONG Color;
612  PMMPFN Blink;
613  PMMCOLOR_TABLES ColorTable;
614 
615  /* Make sure the page index is valid */
617  ASSERT((PageFrameIndex != 0) &&
618  (PageFrameIndex <= MmHighestPhysicalPage) &&
619  (PageFrameIndex >= MmLowestPhysicalPage));
620 
621  /* Get the PFN entry */
622  Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);
623 
624  /* Sanity checks that a right kind of page is being inserted here */
625  ASSERT(Pfn1->u4.MustBeCached == 0);
626  ASSERT(Pfn1->u3.e1.Rom != 1);
627  ASSERT(Pfn1->u3.e1.RemovalRequested == 0);
628  ASSERT(Pfn1->u4.VerifierAllocation == 0);
629  ASSERT(Pfn1->u3.e2.ReferenceCount == 0);
630 
631  /* HACK HACK HACK : Feed the page to legacy Mm */
632  if (MmRosNotifyAvailablePage(PageFrameIndex))
633  {
634  DPRINT1("Legacy Mm eating ARM3 page!.\n");
635  return;
636  }
637 
638  /* Get the free page list and increment its count */
639  ListHead = &MmFreePageListHead;
640  ASSERT_LIST_INVARIANT(ListHead);
641  ListHead->Total++;
642 
643  /* Get the last page on the list */
644  LastPage = ListHead->Blink;
645  if (LastPage != LIST_HEAD)
646  {
647  /* Link us with the previous page, so we're at the end now */
648  MI_PFN_ELEMENT(LastPage)->u1.Flink = PageFrameIndex;
649  }
650  else
651  {
652  /* The list is empty, so we are the first page */
653  ListHead->Flink = PageFrameIndex;
654  }
655 
656  /* Now make the list head point back to us (since we go at the end) */
657  ListHead->Blink = PageFrameIndex;
658  ASSERT_LIST_INVARIANT(ListHead);
659 
660  /* And initialize our own list pointers */
661  Pfn1->u1.Flink = LIST_HEAD;
662  Pfn1->u2.Blink = LastPage;
663 
664  /* Set the list name and default priority */
665  Pfn1->u3.e1.PageLocation = FreePageList;
666  Pfn1->u4.Priority = 3;
667 
668  /* Clear some status fields */
669  Pfn1->u4.InPageError = 0;
670  Pfn1->u4.AweAllocation = 0;
671 
672  /* Increment number of available pages */
674 
675  /* Get the page color */
676  Color = PageFrameIndex & MmSecondaryColorMask;
677 
678  /* Get the first page on the color list */
679  ColorTable = &MmFreePagesByColor[FreePageList][Color];
680  if (ColorTable->Flink == LIST_HEAD)
681  {
682  /* The list is empty, so we are the first page */
683  Pfn1->u4.PteFrame = COLORED_LIST_HEAD;
684  ColorTable->Flink = PageFrameIndex;
685  }
686  else
687  {
688  /* Get the previous page */
689  Blink = (PMMPFN)ColorTable->Blink;
690 
691  /* Make it link to us, and link back to it */
692  Blink->OriginalPte.u.Long = PageFrameIndex;
693  Pfn1->u4.PteFrame = MiGetPfnEntryIndex(Blink);
694  }
695 
696  /* Now initialize our own list pointers */
697  ColorTable->Blink = Pfn1;
698 
699  /* This page is now the last */
700  Pfn1->OriginalPte.u.Long = LIST_HEAD;
701 
702  /* And increase the count in the colored list */
703  ColorTable->Count++;
704 
705  /* Notify zero page thread if enough pages are on the free list now */
706  if (ListHead->Total >= 8)
707  {
708  /* Set the event */
710  }
711 
712 #if MI_TRACE_PFNS
713  Pfn1->PfnUsage = MI_USAGE_FREE_PAGE;
714  RtlZeroMemory(Pfn1->ProcessName, 16);
715  Pfn1->CallSite = NULL;
716 #endif
717 }
PVOID Blink
Definition: miarm.h:437
#define MI_ASSERT_PFN_LOCK_HELD()
Definition: mm.h:996
ULONG_PTR AweAllocation
Definition: mm.h:410
PFN_NUMBER Flink
Definition: mm.h:366
union _MMPFN::@1761 u3
#define ASSERT_LIST_INVARIANT(x)
Definition: pfnlist.c:29
PFN_NUMBER MmLowestPhysicalPage
Definition: meminit.c:30
USHORT RemovalRequested
Definition: mm.h:355
MMPFNLIST MmFreePageListHead
Definition: pfnlist.c:42
LONG NTAPI KeSetEvent(IN PKEVENT Event, IN KPRIORITY Increment, IN BOOLEAN Wait)
Definition: eventobj.c:159
USHORT PageLocation
Definition: mm.h:354
struct Color Color
PFN_NUMBER Flink
Definition: mm.h:434
MMPFNENTRY e1
Definition: mm.h:386
ULONG PFN_NUMBER
Definition: ke.h:9
ULONG_PTR MustBeCached
Definition: mm.h:412
#define FALSE
Definition: types.h:117
PFN_NUMBER Blink
Definition: mm.h:435
PFN_NUMBER Flink
Definition: miarm.h:436
ULONG_PTR VerifierAllocation
Definition: mm.h:409
KEVENT MmZeroingPageEvent
Definition: zeropage.c:20
ULONG MmSecondaryColorMask
Definition: mminit.c:257
union _MMPFN::@1760 u2
PMMCOLOR_TABLES MmFreePagesByColor[FreePageList+1]
Definition: mminit.c:286
#define ASSERT(a)
Definition: mode.c:44
BOOLEAN MmRosNotifyAvailablePage(PFN_NUMBER PageFrameIndex)
Definition: balance.c:353
FORCEINLINE PMMPFN MI_PFN_ELEMENT(IN PFN_NUMBER Pfn)
Definition: miarm.h:1579
Definition: mm.h:362
static VOID MiIncrementAvailablePages(VOID)
Definition: pfnlist.c:69
LIST_HEAD(acpi_bus_event_list)
ULONG_PTR Priority
Definition: mm.h:411
ULONG_PTR Long
Definition: mmtypes.h:215
ULONG_PTR PteFrame
Definition: mm.h:407
PFN_NUMBER Total
Definition: mm.h:432
struct _MMPFN * PMMPFN
struct _MMPFN::@1761::@1767 e2
USHORT Rom
Definition: mm.h:357
#define NULL
Definition: types.h:112
MMPTE OriginalPte
Definition: mm.h:396
#define DPRINT1
Definition: precomp.h:8
union _MMPFN::@1759 u1
PFN_NUMBER Blink
Definition: mm.h:378
FORCEINLINE PFN_NUMBER MiGetPfnEntryIndex(IN PMMPFN Pfn1)
Definition: mm.h:1020
unsigned int ULONG
Definition: retypes.h:1
#define IO_NO_INCREMENT
Definition: iotypes.h:598
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
PFN_NUMBER Count
Definition: miarm.h:438
PFN_NUMBER MmHighestPhysicalPage
Definition: meminit.c:31
ULONG_PTR InPageError
Definition: mm.h:408
union _MMPTE::@2287 u
Definition: mm.h:430
union _MMPFN::@1764 u4

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

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

Referenced by MiDecrementReferenceCount(), and MmZeroPageThread().

◆ MiInsertStandbyListAtFront()

VOID FASTCALL MiInsertStandbyListAtFront ( IN PFN_NUMBER  PageFrameIndex)

Definition at line 721 of file pfnlist.c.

722 {
723  PMMPFNLIST ListHead;
724  PFN_NUMBER Flink;
725  PMMPFN Pfn1, Pfn2;
726 
727  /* Make sure the lock is held */
728  DPRINT("Inserting page: %lx into standby list !\n", PageFrameIndex);
730 
731  /* Make sure the PFN is valid */
732  ASSERT((PageFrameIndex != 0) &&
733  (PageFrameIndex <= MmHighestPhysicalPage) &&
734  (PageFrameIndex >= MmLowestPhysicalPage));
735 
736  /* Grab the PFN and validate it is the right kind of PFN being inserted */
737  Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);
738  ASSERT(Pfn1->u4.MustBeCached == 0);
739  ASSERT(Pfn1->u3.e2.ReferenceCount == 0);
740  ASSERT(Pfn1->u3.e1.PrototypePte == 1);
741  ASSERT(Pfn1->u3.e1.Rom != 1);
742 
743  /* One more transition page on a list */
745 
746  /* Get the standby page list and increment its count */
747  ListHead = &MmStandbyPageListByPriority [Pfn1->u4.Priority];
748  ASSERT_LIST_INVARIANT(ListHead);
749  ListHead->Total++;
750 
751  /* Make the head of the list point to this page now */
752  Flink = ListHead->Flink;
753  ListHead->Flink = PageFrameIndex;
754 
755  /* Make the page point to the previous head, and back to the list */
756  Pfn1->u1.Flink = Flink;
757  Pfn1->u2.Blink = LIST_HEAD;
758 
759  /* Was the list empty? */
760  if (Flink != LIST_HEAD)
761  {
762  /* It wasn't, so update the backlink of the previous head page */
763  Pfn2 = MI_PFN_ELEMENT(Flink);
764  Pfn2->u2.Blink = PageFrameIndex;
765  }
766  else
767  {
768  /* It was empty, so have it loop back around to this new page */
769  ListHead->Blink = PageFrameIndex;
770  }
771 
772  /* Move the page onto its new location */
774 
775  /* Increment number of available pages */
777 }
#define MI_ASSERT_PFN_LOCK_HELD()
Definition: mm.h:996
PFN_NUMBER Flink
Definition: mm.h:366
union _MMPFN::@1761 u3
#define ASSERT_LIST_INVARIANT(x)
Definition: pfnlist.c:29
PFN_NUMBER MmLowestPhysicalPage
Definition: meminit.c:30
USHORT PageLocation
Definition: mm.h:354
PFN_NUMBER Flink
Definition: mm.h:434
USHORT PrototypePte
Definition: mm.h:352
MMPFNENTRY e1
Definition: mm.h:386
ULONG PFN_NUMBER
Definition: ke.h:9
ULONG_PTR MustBeCached
Definition: mm.h:412
ULONG MmTransitionSharedPages
Definition: pfnlist.c:38
PFN_NUMBER Blink
Definition: mm.h:435
union _MMPFN::@1760 u2
#define ASSERT(a)
Definition: mode.c:44
FORCEINLINE PMMPFN MI_PFN_ELEMENT(IN PFN_NUMBER Pfn)
Definition: miarm.h:1579
Definition: mm.h:362
static VOID MiIncrementAvailablePages(VOID)
Definition: pfnlist.c:69
LIST_HEAD(acpi_bus_event_list)
ULONG_PTR Priority
Definition: mm.h:411
PFN_NUMBER Total
Definition: mm.h:432
struct _MMPFN::@1761::@1767 e2
USHORT Rom
Definition: mm.h:357
union _MMPFN::@1759 u1
PFN_NUMBER Blink
Definition: mm.h:378
MMPFNLIST MmStandbyPageListByPriority[8]
Definition: pfnlist.c:44
PFN_NUMBER MmHighestPhysicalPage
Definition: meminit.c:31
#define DPRINT
Definition: sndvol32.h:71
Definition: mm.h:430
union _MMPFN::@1764 u4

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 */
484  ASSERT(MmAvailablePages != 0);
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 }
#define MI_ASSERT_PFN_LOCK_HELD()
Definition: mm.h:996
PFN_NUMBER NTAPI MiRemovePageByColor(IN PFN_NUMBER PageIndex, IN ULONG Color)
Definition: pfnlist.c:364
union _MMPFN::@1761 u3
#define ASSERT_LIST_INVARIANT(x)
Definition: pfnlist.c:29
MMPFNLIST MmFreePageListHead
Definition: pfnlist.c:42
PFN_NUMBER MmAvailablePages
Definition: freelist.c:26
USHORT PageLocation
Definition: mm.h:354
struct Color Color
PFN_NUMBER Flink
Definition: mm.h:434
MMPFNENTRY e1
Definition: mm.h:386
ULONG PFN_NUMBER
Definition: ke.h:9
ULONG_PTR ShareCount
Definition: mm.h:379
PFN_NUMBER Flink
Definition: miarm.h:436
ULONG MmSecondaryColorMask
Definition: mminit.c:257
union _MMPFN::@1760 u2
PMMCOLOR_TABLES MmFreePagesByColor[FreePageList+1]
Definition: mminit.c:286
#define ASSERT(a)
Definition: mode.c:44
FORCEINLINE PMMPFN MI_PFN_ELEMENT(IN PFN_NUMBER Pfn)
Definition: miarm.h:1579
Definition: mm.h:362
ULONG MmSecondaryColors
Definition: mminit.c:256
LIST_HEAD(acpi_bus_event_list)
MMPFNLIST MmZeroedPageListHead
Definition: pfnlist.c:41
PFN_NUMBER Total
Definition: mm.h:432
struct _MMPFN::@1761::@1767 e2

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 }
PVOID Blink
Definition: miarm.h:437
ULONG MI_PFN_CURRENT_USAGE
Definition: pfnlist.c:63
#define MI_ASSERT_PFN_LOCK_HELD()
Definition: mm.h:996
MMLISTS ListName
Definition: mm.h:433
PFN_NUMBER Flink
Definition: mm.h:366
union _MMPFN::@1761 u3
#define ASSERT_LIST_INVARIANT(x)
Definition: pfnlist.c:29
USHORT RemovalRequested
Definition: mm.h:355
USHORT PageLocation
Definition: mm.h:354
struct Color Color
PFN_NUMBER Flink
Definition: mm.h:434
enum _MMLISTS MMLISTS
PMMPFNLIST MmPageLocationList[]
Definition: pfnlist.c:51
MMPFNENTRY e1
Definition: mm.h:386
USHORT CacheAttribute
Definition: mm.h:356
ULONG PFN_NUMBER
Definition: ke.h:9
PFN_NUMBER Blink
Definition: mm.h:435
PFN_NUMBER Flink
Definition: miarm.h:436
#define MI_SET_PROCESS2(x)
Definition: mm.h:308
void * PVOID
Definition: retypes.h:9
union _MMPFN::@1760 u2
PMMCOLOR_TABLES MmFreePagesByColor[FreePageList+1]
Definition: mminit.c:286
static VOID MiDecrementAvailablePages(VOID)
Definition: pfnlist.c:90
#define ASSERT(a)
Definition: mode.c:44
FORCEINLINE PMMPFN MI_PFN_ELEMENT(IN PFN_NUMBER Pfn)
Definition: miarm.h:1579
Definition: mm.h:362
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
ULONG MmSecondaryColors
Definition: mminit.c:256
LIST_HEAD(acpi_bus_event_list)
ULONG_PTR Long
Definition: mmtypes.h:215
USHORT PageColor
Definition: mm.h:353
unsigned short USHORT
Definition: pedump.c:61
ULONG_PTR PteFrame
Definition: mm.h:407
PFN_NUMBER Total
Definition: mm.h:432
struct _MMPFN::@1761::@1767 e2
USHORT Rom
Definition: mm.h:357
MMPTE OriginalPte
Definition: mm.h:396
union _MMPFN::@1759 u1
PFN_NUMBER Blink
Definition: mm.h:378
void * _ReturnAddress(void)
PFN_NUMBER Count
Definition: miarm.h:438
union _MMPTE::@2287 u
CHAR MI_PFN_CURRENT_PROCESS_NAME[16]
Definition: pfnlist.c:64
Definition: mm.h:430
union _MMPFN::@1764 u4

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;
537  BOOLEAN Zero = FALSE;
538 
539  /* Make sure PFN lock is held and we have pages */
541  ASSERT(MmAvailablePages != 0);
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 }
#define MI_ASSERT_PFN_LOCK_HELD()
Definition: mm.h:996
#define TRUE
Definition: types.h:120
PFN_NUMBER NTAPI MiRemovePageByColor(IN PFN_NUMBER PageIndex, IN ULONG Color)
Definition: pfnlist.c:364
union _MMPFN::@1761 u3
#define ASSERT_LIST_INVARIANT(x)
Definition: pfnlist.c:29
MMPFNLIST MmFreePageListHead
Definition: pfnlist.c:42
PFN_NUMBER MmAvailablePages
Definition: freelist.c:26
USHORT PageLocation
Definition: mm.h:354
struct Color Color
PFN_NUMBER Flink
Definition: mm.h:434
MMPFNENTRY e1
Definition: mm.h:386
ULONG PFN_NUMBER
Definition: ke.h:9
#define FALSE
Definition: types.h:117
ULONG_PTR ShareCount
Definition: mm.h:379
PFN_NUMBER Flink
Definition: miarm.h:436
VOID NTAPI MiZeroPhysicalPage(IN PFN_NUMBER PageFrameIndex)
Definition: pfnlist.c:122
unsigned char BOOLEAN
ULONG MmSecondaryColorMask
Definition: mminit.c:257
union _MMPFN::@1760 u2
PMMCOLOR_TABLES MmFreePagesByColor[FreePageList+1]
Definition: mminit.c:286
#define ASSERT(a)
Definition: mode.c:44
FORCEINLINE PMMPFN MI_PFN_ELEMENT(IN PFN_NUMBER Pfn)
Definition: miarm.h:1579
Definition: mm.h:362
ULONG MmSecondaryColors
Definition: mminit.c:256
LIST_HEAD(acpi_bus_event_list)
MMPFNLIST MmZeroedPageListHead
Definition: pfnlist.c:41
PFN_NUMBER Total
Definition: mm.h:432
struct _MMPFN::@1761::@1767 e2
IN PVCB IN VBO IN ULONG OUT PBCB OUT PVOID IN BOOLEAN IN BOOLEAN Zero
Definition: fatprocs.h:411

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 }
PVOID Blink
Definition: miarm.h:437
ULONG MI_PFN_CURRENT_USAGE
Definition: pfnlist.c:63
#define MI_ASSERT_PFN_LOCK_HELD()
Definition: mm.h:996
MMLISTS ListName
Definition: mm.h:433
PFN_NUMBER Flink
Definition: mm.h:366
#define ASSERT_LIST_INVARIANT(x)
Definition: pfnlist.c:29
struct Color Color
PFN_NUMBER Flink
Definition: mm.h:434
enum _MMLISTS MMLISTS
PMMPFNLIST MmPageLocationList[]
Definition: pfnlist.c:51
ULONG PFN_NUMBER
Definition: ke.h:9
PFN_NUMBER Blink
Definition: mm.h:435
PFN_NUMBER Flink
Definition: miarm.h:436
#define MI_SET_PROCESS2(x)
Definition: mm.h:308
ULONG MmSecondaryColorMask
Definition: mminit.c:257
void * PVOID
Definition: retypes.h:9
union _MMPFN::@1760 u2
PMMCOLOR_TABLES MmFreePagesByColor[FreePageList+1]
Definition: mminit.c:286
static VOID MiDecrementAvailablePages(VOID)
Definition: pfnlist.c:90
#define ASSERT(a)
Definition: mode.c:44
FORCEINLINE PMMPFN MI_PFN_ELEMENT(IN PFN_NUMBER Pfn)
Definition: miarm.h:1579
Definition: mm.h:362
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
LIST_HEAD(acpi_bus_event_list)
ULONG_PTR Long
Definition: mmtypes.h:215
ULONG_PTR PteFrame
Definition: mm.h:407
PFN_NUMBER Total
Definition: mm.h:432
#define NULL
Definition: types.h:112
MMPTE OriginalPte
Definition: mm.h:396
union _MMPFN::@1759 u1
PFN_NUMBER Blink
Definition: mm.h:378
void * _ReturnAddress(void)
FORCEINLINE PFN_NUMBER MiGetPfnEntryIndex(IN PMMPFN Pfn1)
Definition: mm.h:1020
unsigned int ULONG
Definition: retypes.h:1
PFN_NUMBER Count
Definition: miarm.h:438
union _MMPTE::@2287 u
base of all file and directory entries
Definition: entries.h:82
CHAR MI_PFN_CURRENT_PROCESS_NAME[16]
Definition: pfnlist.c:64
Definition: mm.h:430
union _MMPFN::@1764 u4

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 }
#define MI_ASSERT_PFN_LOCK_HELD()
Definition: mm.h:996
MMPFNLIST MmStandbyPageListHead
Definition: pfnlist.c:43
ULONG MmTotalPagesForPagingFile
Definition: pfnlist.c:39
MMLISTS ListName
Definition: mm.h:433
PFN_NUMBER Flink
Definition: mm.h:366
#define ASSERT_LIST_INVARIANT(x)
Definition: pfnlist.c:29
PFN_NUMBER Flink
Definition: mm.h:434
PMMPFNLIST MmPageLocationList[]
Definition: pfnlist.c:51
ULONG PFN_NUMBER
Definition: ke.h:9
#define FALSE
Definition: types.h:117
ULONG MmTransitionSharedPages
Definition: pfnlist.c:38
PFN_NUMBER Blink
Definition: mm.h:435
union _MMPFN::@1760 u2
MMPFNLIST MmModifiedPageListHead
Definition: pfnlist.c:45
MMPFNLIST MmModifiedNoWritePageListHead
Definition: pfnlist.c:47
static VOID MiDecrementAvailablePages(VOID)
Definition: pfnlist.c:90
#define ASSERT(a)
Definition: mode.c:44
FORCEINLINE PMMPFN MI_PFN_ELEMENT(IN PFN_NUMBER Pfn)
Definition: miarm.h:1579
MMPFNLIST MmModifiedPageListByColor[1]
Definition: pfnlist.c:46
LIST_HEAD(acpi_bus_event_list)
PFN_NUMBER Total
Definition: mm.h:432
union _MMPFN::@1759 u1
PFN_NUMBER Blink
Definition: mm.h:378
MMPFNLIST MmStandbyPageListByPriority[8]
Definition: pfnlist.c:44
Definition: mm.h:430

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

◆ MiZeroPhysicalPage()

VOID NTAPI MiZeroPhysicalPage ( IN PFN_NUMBER  PageFrameIndex)

Definition at line 122 of file pfnlist.c.

123 {
124  KIRQL OldIrql;
127 
128  /* Map in hyperspace, then wipe it using XMMI or MEMSET */
133 }
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define PsGetCurrentProcess
Definition: psfuncs.h:17
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
KIRQL OldIrql
Definition: mm.h:1502
VOID FASTCALL KeZeroPages(IN PVOID Address, IN ULONG Size)
Definition: stubs.c:94
#define ASSERT(a)
Definition: mode.c:44
VOID NTAPI MiUnmapPageInHyperSpace(IN PEPROCESS Process, IN PVOID Address, IN KIRQL OldIrql)
Definition: hypermap.c:91
#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:219

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

◆ MmRosNotifyAvailablePage()

BOOLEAN MmRosNotifyAvailablePage ( PFN_NUMBER  PageFrameIndex)

Definition at line 353 of file balance.c.

354 {
357  PMMPFN Pfn1;
358 
359  /* Make sure the PFN lock is held */
361 
363  {
364  /* Dirty way to know if we were initialized. */
365  return FALSE;
366  }
367 
369  if (!Entry)
370  return FALSE;
371 
374  Request->Page = Page;
375 
376  Pfn1 = MiGetPfnEntry(Page);
377  ASSERT(Pfn1->u3.e2.ReferenceCount == 0);
378  Pfn1->u3.e2.ReferenceCount = 1;
380 
381  /* This marks the PFN as a ReactOS PFN */
382  Pfn1->u4.AweAllocation = TRUE;
383 
384  /* Allocate the extra ReactOS Data and zero it out */
385  Pfn1->u1.SwapEntry = 0;
386  Pfn1->RmapListHead = NULL;
387 
389 
390  return TRUE;
391 }
static LIST_ENTRY AllocationListHead
Definition: balance.c:32
#define MI_ASSERT_PFN_LOCK_HELD()
Definition: mm.h:996
struct _Entry Entry
Definition: kefuncs.h:627
#define TRUE
Definition: types.h:120
ULONG_PTR AweAllocation
Definition: mm.h:410
PMM_RMAP_ENTRY RmapListHead
Definition: mm.h:400
union _MMPFN::@1761 u3
_In_ WDFREQUEST Request
Definition: wdfdevice.h:547
LONG NTAPI KeSetEvent(IN PKEVENT Event, IN KPRIORITY Increment, IN BOOLEAN Wait)
Definition: eventobj.c:159
USHORT PageLocation
Definition: mm.h:354
MMPFNENTRY e1
Definition: mm.h:386
#define FALSE
Definition: types.h:117
PLIST_ENTRY NTAPI ExInterlockedRemoveHeadList(IN OUT PLIST_ENTRY ListHead, IN OUT PKSPIN_LOCK Lock)
Definition: interlocked.c:166
PFN_NUMBER Page
Definition: section.c:4888
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
#define ASSERT(a)
Definition: mode.c:44
static KSPIN_LOCK AllocationListLock
Definition: balance.c:33
Definition: mm.h:362
Definition: typedefs.h:119
FORCEINLINE PMMPFN MiGetPfnEntry(IN PFN_NUMBER Pfn)
Definition: mm.h:1000
struct _MMPFN::@1761::@1767 e2
#define NULL
Definition: types.h:112
SWAPENTRY SwapEntry
Definition: mm.h:373
VOID NTAPI MiZeroPhysicalPage(IN PFN_NUMBER PageFrameIndex)
Definition: pfnlist.c:122
union _MMPFN::@1759 u1
#define IO_NO_INCREMENT
Definition: iotypes.h:598
static ULONG MiMinimumAvailablePages
Definition: balance.c:31
base of all file and directory entries
Definition: entries.h:82
union _MMPFN::@1764 u4

Referenced by MiInsertPageInFreeList().

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

PMMPFNLIST MmPageLocationList[]
Initial value:
=
{
}
MMPFNLIST MmBadPageListHead
Definition: pfnlist.c:48
MMPFNLIST MmStandbyPageListHead
Definition: pfnlist.c:43
MMPFNLIST MmFreePageListHead
Definition: pfnlist.c:42
MMPFNLIST MmModifiedPageListHead
Definition: pfnlist.c:45
MMPFNLIST MmModifiedNoWritePageListHead
Definition: pfnlist.c:47
MMPFNLIST MmZeroedPageListHead
Definition: pfnlist.c:41
#define NULL
Definition: types.h:112

Definition at line 51 of file pfnlist.c.

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

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