ReactOS  r76032
pfnlist.c
Go to the documentation of this file.
1 /*
2  * PROJECT: ReactOS Kernel
3  * LICENSE: BSD - See COPYING.ARM in the top level directory
4  * FILE: ntoskrnl/mm/ARM3/pfnlist.c
5  * PURPOSE: ARM Memory Manager PFN List Manipulation
6  * PROGRAMMERS: ReactOS Portable Systems Group
7  */
8 
9 /* INCLUDES *******************************************************************/
10 
11 #include <ntoskrnl.h>
12 #define NDEBUG
13 #include <debug.h>
14 
15 #define MODULE_INVOLVED_IN_ARM3
16 #include <mm/ARM3/miarm.h>
17 
18 #if DBG
19 #define ASSERT_LIST_INVARIANT(x) \
20 do { \
21  ASSERT(((x)->Total == 0 && \
22  (x)->Flink == LIST_HEAD && \
23  (x)->Blink == LIST_HEAD) || \
24  ((x)->Total != 0 && \
25  (x)->Flink != LIST_HEAD && \
26  (x)->Blink != LIST_HEAD)); \
27 } while (0)
28 #else
29 #define ASSERT_LIST_INVARIANT(x)
30 #endif
31 
32 /* GLOBALS ********************************************************************/
33 
37 
40 
50 
52 {
59  NULL,
60  NULL
61 };
62 
65 
66 /* FUNCTIONS ******************************************************************/
67 static
68 VOID
70  VOID)
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 }
87 
88 static
89 VOID
91  VOID)
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 }
119 
120 VOID
121 NTAPI
123 {
124  KIRQL OldIrql;
127 
128  /* Map in hyperspace, then wipe it using XMMI or MEMSET */
129  VirtualAddress = MiMapPageInHyperSpace(Process, PageFrameIndex, &OldIrql);
130  ASSERT(VirtualAddress);
131  KeZeroPages(VirtualAddress, PAGE_SIZE);
132  MiUnmapPageInHyperSpace(Process, VirtualAddress, OldIrql);
133 }
134 
135 VOID
136 NTAPI
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 // MI_PFN_CURRENT_USAGE = MI_USAGE_NOT_SET;
258 // memcpy(MI_PFN_CURRENT_PROCESS_NAME, "Not Set", 16);
259 #endif
260 }
261 
262 VOID
263 NTAPI
265 {
266  PMMPFNLIST ListHead;
267  PFN_NUMBER OldFlink, OldBlink;
268 
269  /* Make sure the PFN lock is held */
271 
272  /* ARM3 should only call this for dead pages */
273  ASSERT(Pfn->u3.e2.ReferenceCount == 0);
274 
275  /* Transition pages are supposed to be standby/modified/nowrite */
276  ListHead = MmPageLocationList[Pfn->u3.e1.PageLocation];
277  ASSERT(ListHead->ListName >= StandbyPageList);
278 
279  /* Check if this was standby, or modified */
280  if (ListHead == &MmStandbyPageListHead)
281  {
282  /* Should not be a ROM page */
283  ASSERT(Pfn->u3.e1.Rom == 0);
284 
285  /* Get the exact list */
286  ListHead = &MmStandbyPageListByPriority[Pfn->u4.Priority];
287 
288  /* Decrement number of available pages */
290 
291  /* Decrease transition page counter */
292  ASSERT(Pfn->u3.e1.PrototypePte == 1); /* Only supported ARM3 case */
294  }
295  else if (ListHead == &MmModifiedPageListHead)
296  {
297  /* Only shared memory (page-file backed) modified pages are supported */
298  ASSERT(Pfn->OriginalPte.u.Soft.Prototype == 0);
299 
300  /* Decrement the counters */
301  ListHead->Total--;
303 
304  /* Pick the correct colored list */
305  ListHead = &MmModifiedPageListByColor[0];
306 
307  /* Decrease transition page counter */
309  }
310  else if (ListHead == &MmModifiedNoWritePageListHead)
311  {
312  /* List not yet supported */
313  ASSERT(FALSE);
314  }
315 
316  /* Nothing should be in progress and the list should not be empty */
317  ASSERT(Pfn->u3.e1.WriteInProgress == 0);
318  ASSERT(Pfn->u3.e1.ReadInProgress == 0);
319  ASSERT(ListHead->Total != 0);
320 
321  /* Get the forward and back pointers */
322  OldFlink = Pfn->u1.Flink;
323  OldBlink = Pfn->u2.Blink;
324 
325  /* Check if the next entry is the list head */
326  if (OldFlink != LIST_HEAD)
327  {
328  /* It is not, so set the backlink of the actual entry, to our backlink */
329  MI_PFN_ELEMENT(OldFlink)->u2.Blink = OldBlink;
330  }
331  else
332  {
333  /* Set the list head's backlink instead */
334  ListHead->Blink = OldBlink;
335  }
336 
337  /* Check if the back entry is the list head */
338  if (OldBlink != LIST_HEAD)
339  {
340  /* It is not, so set the backlink of the actual entry, to our backlink */
341  MI_PFN_ELEMENT(OldBlink)->u1.Flink = OldFlink;
342  }
343  else
344  {
345  /* Set the list head's backlink instead */
346  ListHead->Flink = OldFlink;
347  }
348 
349  /* ReactOS Hack */
350  Pfn->OriginalPte.u.Long = 0;
351 
352  /* We are not on a list anymore */
353  Pfn->u1.Flink = Pfn->u2.Blink = 0;
354 
355  /* Remove one entry from the list */
356  ListHead->Total--;
357 
358  ASSERT_LIST_INVARIANT(ListHead);
359 }
360 
362 NTAPI
364  IN ULONG Color)
365 {
366  PMMPFN Pfn1;
367  PMMPFNLIST ListHead;
368  MMLISTS ListName;
369  PFN_NUMBER OldFlink, OldBlink;
370  USHORT OldColor, OldCache;
371  PMMCOLOR_TABLES ColorTable;
372 
373  /* Make sure PFN lock is held */
375  ASSERT(Color < MmSecondaryColors);
376 
377  /* Get the PFN entry */
378  Pfn1 = MI_PFN_ELEMENT(PageIndex);
379  ASSERT(Pfn1->u3.e1.RemovalRequested == 0);
380  ASSERT(Pfn1->u3.e1.Rom == 0);
381 
382  /* Capture data for later */
383  OldColor = Pfn1->u3.e1.PageColor;
384  OldCache = Pfn1->u3.e1.CacheAttribute;
385 
386  /* Could be either on free or zero list */
387  ListHead = MmPageLocationList[Pfn1->u3.e1.PageLocation];
388  ASSERT_LIST_INVARIANT(ListHead);
389  ListName = ListHead->ListName;
390  ASSERT(ListName <= FreePageList);
391 
392  /* Remove a page */
393  ListHead->Total--;
394 
395  /* Get the forward and back pointers */
396  OldFlink = Pfn1->u1.Flink;
397  OldBlink = Pfn1->u2.Blink;
398 
399  /* Check if the next entry is the list head */
400  if (OldFlink != LIST_HEAD)
401  {
402  /* It is not, so set the backlink of the actual entry, to our backlink */
403  MI_PFN_ELEMENT(OldFlink)->u2.Blink = OldBlink;
404  }
405  else
406  {
407  /* Set the list head's backlink instead */
408  ListHead->Blink = OldBlink;
409  }
410 
411  /* Check if the back entry is the list head */
412  if (OldBlink != LIST_HEAD)
413  {
414  /* It is not, so set the backlink of the actual entry, to our backlink */
415  MI_PFN_ELEMENT(OldBlink)->u1.Flink = OldFlink;
416  }
417  else
418  {
419  /* Set the list head's backlink instead */
420  ListHead->Flink = OldFlink;
421  }
422 
423  /* We are not on a list anymore */
424  ASSERT_LIST_INVARIANT(ListHead);
425  Pfn1->u1.Flink = Pfn1->u2.Blink = 0;
426 
427  /* Zero flags but restore color and cache */
428  Pfn1->u3.e2.ShortFlags = 0;
429  Pfn1->u3.e1.PageColor = OldColor;
430  Pfn1->u3.e1.CacheAttribute = OldCache;
431 
432  /* Get the first page on the color list */
433  ASSERT(Color < MmSecondaryColors);
434  ColorTable = &MmFreePagesByColor[ListName][Color];
435  ASSERT(ColorTable->Count >= 1);
436 
437  /* Set the forward link to whoever we were pointing to */
438  ColorTable->Flink = Pfn1->OriginalPte.u.Long;
439 
440  /* Get the first page on the color list */
441  if (ColorTable->Flink == LIST_HEAD)
442  {
443  /* This is the beginning of the list, so set the sentinel value */
444  ColorTable->Blink = (PVOID)LIST_HEAD;
445  }
446  else
447  {
448  /* The list is empty, so we are the first page */
449  MI_PFN_ELEMENT(ColorTable->Flink)->u4.PteFrame = COLORED_LIST_HEAD;
450  }
451 
452  /* One less page */
453  ColorTable->Count--;
454 
455  /* ReactOS Hack */
456  Pfn1->OriginalPte.u.Long = 0;
457 
458  /* Decrement number of available pages */
460 
461 #if MI_TRACE_PFNS
462  //ASSERT(MI_PFN_CURRENT_USAGE != MI_USAGE_NOT_SET);
463  Pfn1->PfnUsage = MI_PFN_CURRENT_USAGE;
464  memcpy(Pfn1->ProcessName, MI_PFN_CURRENT_PROCESS_NAME, 16);
465  //MI_PFN_CURRENT_USAGE = MI_USAGE_NOT_SET;
466  //memcpy(MI_PFN_CURRENT_PROCESS_NAME, "Not Set", 16);
467 #endif
468 
469  /* Return the page */
470  return PageIndex;
471 }
472 
474 NTAPI
476 {
477  PFN_NUMBER PageIndex;
478  PMMPFN Pfn1;
479 
480  /* Make sure PFN lock is held and we have pages */
482  ASSERT(MmAvailablePages != 0);
483  ASSERT(Color < MmSecondaryColors);
484 
485  /* Check the colored free list */
487  if (PageIndex == LIST_HEAD)
488  {
489  /* Check the colored zero list */
491  if (PageIndex == LIST_HEAD)
492  {
493  /* Check the free list */
494  ASSERT_LIST_INVARIANT(&MmFreePageListHead);
495  PageIndex = MmFreePageListHead.Flink;
496  Color = PageIndex & MmSecondaryColorMask;
497  if (PageIndex == LIST_HEAD)
498  {
499  /* Check the zero list */
500  ASSERT_LIST_INVARIANT(&MmZeroedPageListHead);
501  PageIndex = MmZeroedPageListHead.Flink;
502  Color = PageIndex & MmSecondaryColorMask;
503  ASSERT(PageIndex != LIST_HEAD);
504  if (PageIndex == LIST_HEAD)
505  {
506  /* FIXME: Should check the standby list */
507  ASSERT(MmZeroedPageListHead.Total == 0);
508  }
509  }
510  }
511  }
512 
513  /* Remove the page from its list */
514  PageIndex = MiRemovePageByColor(PageIndex, Color);
515 
516  /* Sanity checks */
517  Pfn1 = MI_PFN_ELEMENT(PageIndex);
518  ASSERT((Pfn1->u3.e1.PageLocation == FreePageList) ||
519  (Pfn1->u3.e1.PageLocation == ZeroedPageList));
520  ASSERT(Pfn1->u3.e2.ReferenceCount == 0);
521  ASSERT(Pfn1->u2.ShareCount == 0);
522  ASSERT_LIST_INVARIANT(&MmFreePageListHead);
523  ASSERT_LIST_INVARIANT(&MmZeroedPageListHead);
524 
525  /* Return the page */
526  return PageIndex;
527 }
528 
530 NTAPI
532 {
533  PFN_NUMBER PageIndex;
534  PMMPFN Pfn1;
535  BOOLEAN Zero = FALSE;
536 
537  /* Make sure PFN lock is held and we have pages */
539  ASSERT(MmAvailablePages != 0);
540  ASSERT(Color < MmSecondaryColors);
541 
542  /* Check the colored zero list */
544  if (PageIndex == LIST_HEAD)
545  {
546  /* Check the zero list */
547  ASSERT_LIST_INVARIANT(&MmZeroedPageListHead);
548  PageIndex = MmZeroedPageListHead.Flink;
549  if (PageIndex == LIST_HEAD)
550  {
551  /* This means there's no zero pages, we have to look for free ones */
552  ASSERT(MmZeroedPageListHead.Total == 0);
553  Zero = TRUE;
554 
555  /* Check the colored free list */
557  if (PageIndex == LIST_HEAD)
558  {
559  /* Check the free list */
560  ASSERT_LIST_INVARIANT(&MmFreePageListHead);
561  PageIndex = MmFreePageListHead.Flink;
562  Color = PageIndex & MmSecondaryColorMask;
563  ASSERT(PageIndex != LIST_HEAD);
564  if (PageIndex == LIST_HEAD)
565  {
566  /* FIXME: Should check the standby list */
567  ASSERT(MmZeroedPageListHead.Total == 0);
568  }
569  }
570  }
571  else
572  {
573  Color = PageIndex & MmSecondaryColorMask;
574  }
575  }
576 
577  /* Sanity checks */
578  Pfn1 = MI_PFN_ELEMENT(PageIndex);
579  ASSERT((Pfn1->u3.e1.PageLocation == FreePageList) ||
580  (Pfn1->u3.e1.PageLocation == ZeroedPageList));
581 
582  /* Remove the page from its list */
583  PageIndex = MiRemovePageByColor(PageIndex, Color);
584  ASSERT(Pfn1 == MI_PFN_ELEMENT(PageIndex));
585 
586  /* Zero it, if needed */
587  if (Zero) MiZeroPhysicalPage(PageIndex);
588 
589  /* Sanity checks */
590  ASSERT(Pfn1->u3.e2.ReferenceCount == 0);
591  ASSERT(Pfn1->u2.ShareCount == 0);
592  ASSERT_LIST_INVARIANT(&MmFreePageListHead);
593  ASSERT_LIST_INVARIANT(&MmZeroedPageListHead);
594 
595  /* Return the page */
596  return PageIndex;
597 }
598 
599 /* HACK for keeping legacy Mm alive */
600 extern BOOLEAN MmRosNotifyAvailablePage(PFN_NUMBER PageFrameIndex);
601 
602 VOID
603 NTAPI
605 {
606  PMMPFNLIST ListHead;
607  PFN_NUMBER LastPage;
608  PMMPFN Pfn1;
609  ULONG Color;
610  PMMPFN Blink;
611  PMMCOLOR_TABLES ColorTable;
612 
613  /* Make sure the page index is valid */
615  ASSERT((PageFrameIndex != 0) &&
616  (PageFrameIndex <= MmHighestPhysicalPage) &&
617  (PageFrameIndex >= MmLowestPhysicalPage));
618 
619  /* Get the PFN entry */
620  Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);
621 
622  /* Sanity checks that a right kind of page is being inserted here */
623  ASSERT(Pfn1->u4.MustBeCached == 0);
624  ASSERT(Pfn1->u3.e1.Rom != 1);
625  ASSERT(Pfn1->u3.e1.RemovalRequested == 0);
626  ASSERT(Pfn1->u4.VerifierAllocation == 0);
627  ASSERT(Pfn1->u3.e2.ReferenceCount == 0);
628 
629  /* HACK HACK HACK : Feed the page to legacy Mm */
630  if (MmRosNotifyAvailablePage(PageFrameIndex))
631  {
632  DPRINT1("Legacy Mm eating ARM3 page!.\n");
633  return;
634  }
635 
636  /* Get the free page list and increment its count */
637  ListHead = &MmFreePageListHead;
638  ASSERT_LIST_INVARIANT(ListHead);
639  ListHead->Total++;
640 
641  /* Get the last page on the list */
642  LastPage = ListHead->Blink;
643  if (LastPage != LIST_HEAD)
644  {
645  /* Link us with the previous page, so we're at the end now */
646  MI_PFN_ELEMENT(LastPage)->u1.Flink = PageFrameIndex;
647  }
648  else
649  {
650  /* The list is empty, so we are the first page */
651  ListHead->Flink = PageFrameIndex;
652  }
653 
654  /* Now make the list head point back to us (since we go at the end) */
655  ListHead->Blink = PageFrameIndex;
656  ASSERT_LIST_INVARIANT(ListHead);
657 
658  /* And initialize our own list pointers */
659  Pfn1->u1.Flink = LIST_HEAD;
660  Pfn1->u2.Blink = LastPage;
661 
662  /* Set the list name and default priority */
663  Pfn1->u3.e1.PageLocation = FreePageList;
664  Pfn1->u4.Priority = 3;
665 
666  /* Clear some status fields */
667  Pfn1->u4.InPageError = 0;
668  Pfn1->u4.AweAllocation = 0;
669 
670  /* Increment number of available pages */
672 
673  /* Get the page color */
674  Color = PageFrameIndex & MmSecondaryColorMask;
675 
676  /* Get the first page on the color list */
677  ColorTable = &MmFreePagesByColor[FreePageList][Color];
678  if (ColorTable->Flink == LIST_HEAD)
679  {
680  /* The list is empty, so we are the first page */
681  Pfn1->u4.PteFrame = COLORED_LIST_HEAD;
682  ColorTable->Flink = PageFrameIndex;
683  }
684  else
685  {
686  /* Get the previous page */
687  Blink = (PMMPFN)ColorTable->Blink;
688 
689  /* Make it link to us, and link back to it */
690  Blink->OriginalPte.u.Long = PageFrameIndex;
691  Pfn1->u4.PteFrame = MiGetPfnEntryIndex(Blink);
692  }
693 
694  /* Now initialize our own list pointers */
695  ColorTable->Blink = Pfn1;
696 
697  /* This page is now the last */
698  Pfn1->OriginalPte.u.Long = LIST_HEAD;
699 
700  /* And increase the count in the colored list */
701  ColorTable->Count++;
702 
703  /* Notify zero page thread if enough pages are on the free list now */
704  if ((ListHead->Total >= 8) && !(MmZeroingPageThreadActive))
705  {
706  /* Set the event */
708  }
709 
710 #if MI_TRACE_PFNS
711  Pfn1->PfnUsage = MI_USAGE_FREE_PAGE;
712  RtlZeroMemory(Pfn1->ProcessName, 16);
713 #endif
714 }
715 
716 VOID
717 FASTCALL
719 {
720  PMMPFNLIST ListHead;
721  PFN_NUMBER Flink;
722  PMMPFN Pfn1, Pfn2;
723 
724  /* Make sure the lock is held */
725  DPRINT("Inserting page: %lx into standby list !\n", PageFrameIndex);
727 
728  /* Make sure the PFN is valid */
729  ASSERT((PageFrameIndex != 0) &&
730  (PageFrameIndex <= MmHighestPhysicalPage) &&
731  (PageFrameIndex >= MmLowestPhysicalPage));
732 
733  /* Grab the PFN and validate it is the right kind of PFN being inserted */
734  Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);
735  ASSERT(Pfn1->u4.MustBeCached == 0);
736  ASSERT(Pfn1->u3.e2.ReferenceCount == 0);
737  ASSERT(Pfn1->u3.e1.PrototypePte == 1);
738  ASSERT(Pfn1->u3.e1.Rom != 1);
739 
740  /* One more transition page on a list */
742 
743  /* Get the standby page list and increment its count */
744  ListHead = &MmStandbyPageListByPriority [Pfn1->u4.Priority];
745  ASSERT_LIST_INVARIANT(ListHead);
746  ListHead->Total++;
747 
748  /* Make the head of the list point to this page now */
749  Flink = ListHead->Flink;
750  ListHead->Flink = PageFrameIndex;
751 
752  /* Make the page point to the previous head, and back to the list */
753  Pfn1->u1.Flink = Flink;
754  Pfn1->u2.Blink = LIST_HEAD;
755 
756  /* Was the list empty? */
757  if (Flink != LIST_HEAD)
758  {
759  /* It wasn't, so update the backlink of the previous head page */
760  Pfn2 = MI_PFN_ELEMENT(Flink);
761  Pfn2->u2.Blink = PageFrameIndex;
762  }
763  else
764  {
765  /* It was empty, so have it loop back around to this new page */
766  ListHead->Blink = PageFrameIndex;
767  }
768 
769  /* Move the page onto its new location */
771 
772  /* Increment number of available pages */
774 }
775 
776 VOID
777 NTAPI
779  IN PFN_NUMBER PageFrameIndex)
780 {
781  PFN_NUMBER Flink, LastPage;
782  PMMPFN Pfn1, Pfn2;
783  MMLISTS ListName;
784  PMMCOLOR_TABLES ColorHead;
785  ULONG Color;
786 
787  /* For free pages, use MiInsertPageInFreeList */
788  ASSERT(ListHead != &MmFreePageListHead);
789 
790  /* Make sure the lock is held */
792 
793  /* Make sure the PFN is valid */
794  ASSERT((PageFrameIndex) &&
795  (PageFrameIndex <= MmHighestPhysicalPage) &&
796  (PageFrameIndex >= MmLowestPhysicalPage));
797 
798  /* Page should be unused */
799  Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);
800  ASSERT(Pfn1->u3.e2.ReferenceCount == 0);
801  ASSERT(Pfn1->u3.e1.Rom != 1);
802 
803  /* Is a standby or modified page being inserted? */
804  ListName = ListHead->ListName;
805  if ((ListName == StandbyPageList) || (ListName == ModifiedPageList))
806  {
807  /* If the page is in transition, it must also be a prototype page */
808  if ((Pfn1->OriginalPte.u.Soft.Prototype == 0) &&
809  (Pfn1->OriginalPte.u.Soft.Transition == 1))
810  {
811  /* Crash the system on inconsistency */
812  KeBugCheckEx(MEMORY_MANAGEMENT, 0x8888, 0, 0, 0);
813  }
814  }
815 
816  /* Standby pages are prioritized, so we need to get the real head */
817  if (ListHead == &MmStandbyPageListHead)
818  {
819  /* Obviously the prioritized list should still have the same name */
820  ListHead = &MmStandbyPageListByPriority[Pfn1->u4.Priority];
821  ASSERT(ListHead->ListName == ListName);
822  }
823 
824  /* Increment the list count */
825  ListHead->Total++;
826 
827  /* Is a modified page being inserted? */
828  if (ListHead == &MmModifiedPageListHead)
829  {
830  /* For now, only single-prototype pages should end up in this path */
831  DPRINT("Modified page being added: %lx\n", PageFrameIndex);
832  ASSERT(Pfn1->OriginalPte.u.Soft.Prototype == 0);
833 
834  /* Modified pages are colored when they are selected for page file */
835  ListHead = &MmModifiedPageListByColor[0];
836  ASSERT (ListHead->ListName == ListName);
837  ListHead->Total++;
838 
839  /* Increment the number of paging file modified pages */
841  }
842 
843  /* Don't handle bad pages yet yet */
844  ASSERT(Pfn1->u3.e1.RemovalRequested == 0);
845 
846  /* Zero pages go to the head, all other pages go to the end */
847  if (ListName == ZeroedPageList)
848  {
849  /* Make the head of the list point to this page now */
850  Flink = ListHead->Flink;
851  ListHead->Flink = PageFrameIndex;
852 
853  /* Make the page point to the previous head, and back to the list */
854  Pfn1->u1.Flink = Flink;
855  Pfn1->u2.Blink = LIST_HEAD;
856 
857  /* Was the list empty? */
858  if (Flink != LIST_HEAD)
859  {
860  /* It wasn't, so update the backlink of the previous head page */
861  Pfn2 = MI_PFN_ELEMENT(Flink);
862  Pfn2->u2.Blink = PageFrameIndex;
863  }
864  else
865  {
866  /* It was empty, so have it loop back around to this new page */
867  ListHead->Blink = PageFrameIndex;
868  }
869  }
870  else
871  {
872  /* Get the last page on the list */
873  LastPage = ListHead->Blink;
874  if (LastPage != LIST_HEAD)
875  {
876  /* Link us with the previous page, so we're at the end now */
877  MI_PFN_ELEMENT(LastPage)->u1.Flink = PageFrameIndex;
878  }
879  else
880  {
881  /* The list is empty, so we are the first page */
882  ListHead->Flink = PageFrameIndex;
883  }
884 
885  /* Now make the list head point back to us (since we go at the end) */
886  ListHead->Blink = PageFrameIndex;
887  ASSERT_LIST_INVARIANT(ListHead);
888 
889  /* And initialize our own list pointers */
890  Pfn1->u1.Flink = LIST_HEAD;
891  Pfn1->u2.Blink = LastPage;
892  }
893 
894  /* Move the page onto its new location */
895  Pfn1->u3.e1.PageLocation = ListName;
896 
897  /* For zero/free pages, we also have to handle the colored lists */
898  if (ListName <= StandbyPageList)
899  {
900  /* Increment number of available pages */
902 
903  /* Sanity checks */
904  ASSERT(ListName == ZeroedPageList);
905  ASSERT(Pfn1->u4.InPageError == 0);
906 
907  /* Get the page color */
908  Color = PageFrameIndex & MmSecondaryColorMask;
909 
910  /* Get the list for this color */
911  ColorHead = &MmFreePagesByColor[ZeroedPageList][Color];
912 
913  /* Get the old head */
914  Flink = ColorHead->Flink;
915 
916  /* Make this page point back to the list, and point forwards to the old head */
917  Pfn1->OriginalPte.u.Long = Flink;
918  Pfn1->u4.PteFrame = COLORED_LIST_HEAD;
919 
920  /* Set the new head */
921  ColorHead->Flink = PageFrameIndex;
922 
923  /* Was the head empty? */
924  if (Flink != LIST_HEAD)
925  {
926  /* No, so make the old head point to this page */
927  Pfn2 = MI_PFN_ELEMENT(Flink);
928  Pfn2->u4.PteFrame = PageFrameIndex;
929  }
930  else
931  {
932  /* Yes, make it loop back to this page */
933  ColorHead->Blink = (PVOID)Pfn1;
934  }
935 
936  /* One more paged on the colored list */
937  ColorHead->Count++;
938 
939 #if MI_TRACE_PFNS
940  //ASSERT(MI_PFN_CURRENT_USAGE == MI_USAGE_NOT_SET);
941  Pfn1->PfnUsage = MI_USAGE_FREE_PAGE;
943  RtlZeroMemory(Pfn1->ProcessName, 16);
944 #endif
945  }
946  else if (ListName == ModifiedPageList)
947  {
948  /* In ARM3, page must be destined for page file, and not yet written out */
949  ASSERT(Pfn1->OriginalPte.u.Soft.Prototype == 0);
950  ASSERT(Pfn1->OriginalPte.u.Soft.PageFileHigh == 0);
951 
952  /* One more transition page */
954 
955  /* Increment the number of per-process modified pages */
956  PsGetCurrentProcess()->ModifiedPageCount++;
957 
958  /* FIXME: Wake up modified page writer if there are not enough free pages */
959  }
960  else if (ListName == ModifiedNoWritePageList)
961  {
962  /* This list is not yet implemented */
963  ASSERT(FALSE);
964  }
965 }
966 
967 VOID
968 NTAPI
970  IN PMMPTE PointerPte,
971  IN BOOLEAN Modified)
972 {
973  PMMPFN Pfn1;
975  PMMPTE PointerPtePte;
977 
978  /* Setup the PTE */
979  Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);
980  Pfn1->PteAddress = PointerPte;
981 
982  /* Check if this PFN is part of a valid address space */
983  if (PointerPte->u.Hard.Valid == 1)
984  {
985  /* Only valid from MmCreateProcessAddressSpace path */
987 
988  /* Make this a demand zero PTE */
990  }
991  else
992  {
993  /* Copy the PTE data */
994  Pfn1->OriginalPte = *PointerPte;
995  ASSERT(!((Pfn1->OriginalPte.u.Soft.Prototype == 0) &&
996  (Pfn1->OriginalPte.u.Soft.Transition == 1)));
997  }
998 
999  /* Otherwise this is a fresh page -- set it up */
1000  ASSERT(Pfn1->u3.e2.ReferenceCount == 0);
1001  Pfn1->u3.e2.ReferenceCount = 1;
1002  Pfn1->u2.ShareCount = 1;
1003  Pfn1->u3.e1.PageLocation = ActiveAndValid;
1004  ASSERT(Pfn1->u3.e1.Rom == 0);
1005  Pfn1->u3.e1.Modified = Modified;
1006 
1007  /* Get the page table for the PTE */
1008  PointerPtePte = MiAddressToPte(PointerPte);
1009  if (PointerPtePte->u.Hard.Valid == 0)
1010  {
1011  /* Make sure the PDE gets paged in properly */
1012  Status = MiCheckPdeForPagedPool(PointerPte);
1013  if (!NT_SUCCESS(Status))
1014  {
1015  /* Crash */
1016  KeBugCheckEx(MEMORY_MANAGEMENT,
1017  0x61940,
1018  (ULONG_PTR)PointerPte,
1019  (ULONG_PTR)PointerPtePte->u.Long,
1020  (ULONG_PTR)MiPteToAddress(PointerPte));
1021  }
1022  }
1023 
1024  /* Get the PFN for the page table */
1025  PageFrameIndex = PFN_FROM_PTE(PointerPtePte);
1026  ASSERT(PageFrameIndex != 0);
1027  Pfn1->u4.PteFrame = PageFrameIndex;
1028 
1029  /* Increase its share count so we don't get rid of it */
1030  Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);
1031  Pfn1->u2.ShareCount++;
1032 }
1033 
1034 VOID
1035 NTAPI
1037  IN PMMPTE PointerPte,
1038  IN MMPTE TempPte)
1039 {
1040  PMMPFN Pfn1;
1041  NTSTATUS Status;
1042  PMMPTE PointerPtePte;
1044 
1045  /* PTE must be invalid */
1046  ASSERT(PointerPte->u.Hard.Valid == 0);
1047 
1048  /* Setup the PTE */
1049  Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);
1050  Pfn1->PteAddress = PointerPte;
1051  Pfn1->OriginalPte = DemandZeroPte;
1052 
1053  /* Otherwise this is a fresh page -- set it up */
1054  ASSERT(Pfn1->u3.e2.ReferenceCount == 0);
1055  Pfn1->u3.e2.ReferenceCount++;
1056  Pfn1->u2.ShareCount++;
1057  Pfn1->u3.e1.PageLocation = ActiveAndValid;
1058  ASSERT(Pfn1->u3.e1.Rom == 0);
1059  Pfn1->u3.e1.Modified = 1;
1060 
1061  /* Get the page table for the PTE */
1062  PointerPtePte = MiAddressToPte(PointerPte);
1063  if (PointerPtePte->u.Hard.Valid == 0)
1064  {
1065  /* Make sure the PDE gets paged in properly */
1066  Status = MiCheckPdeForPagedPool(PointerPte);
1067  if (!NT_SUCCESS(Status))
1068  {
1069  /* Crash */
1070  KeBugCheckEx(MEMORY_MANAGEMENT,
1071  0x61940,
1072  (ULONG_PTR)PointerPte,
1073  (ULONG_PTR)PointerPtePte->u.Long,
1074  (ULONG_PTR)MiPteToAddress(PointerPte));
1075  }
1076  }
1077 
1078  /* Get the PFN for the page table */
1079  PageFrameIndex = PFN_FROM_PTE(PointerPtePte);
1080  ASSERT(PageFrameIndex != 0);
1081  Pfn1->u4.PteFrame = PageFrameIndex;
1082 
1083  /* Increase its share count so we don't get rid of it */
1084  Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);
1085  Pfn1->u2.ShareCount++;
1086 
1087  /* Write valid PTE */
1088  MI_WRITE_VALID_PTE(PointerPte, TempPte);
1089 }
1090 
1091 NTSTATUS
1092 NTAPI
1094  IN PMMPDE PointerPde,
1095  IN PFN_NUMBER ContainingPageFrame,
1096  IN BOOLEAN SessionAllocation)
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 */
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 */
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 */
1128  return STATUS_SUCCESS;
1129 }
1130 
1131 VOID
1132 NTAPI
1134  IN PFN_NUMBER PageFrameIndex)
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  /* Page must be in-use */
1145  if ((Pfn1->u3.e1.PageLocation != ActiveAndValid) &&
1146  (Pfn1->u3.e1.PageLocation != StandbyPageList))
1147  {
1148  /* Otherwise we have PFN corruption */
1149  KeBugCheckEx(PFN_LIST_CORRUPT,
1150  0x99,
1151  PageFrameIndex,
1152  Pfn1->u3.e1.PageLocation,
1153  0);
1154  }
1155 
1156  /* Page should at least have one reference */
1157  ASSERT(Pfn1->u3.e2.ReferenceCount != 0);
1158 
1159  /* Check if the share count is now 0 */
1160  ASSERT(Pfn1->u2.ShareCount < 0xF000000);
1161  if (!--Pfn1->u2.ShareCount)
1162  {
1163  /* Was this a prototype PTE? */
1164  if (Pfn1->u3.e1.PrototypePte)
1165  {
1166  /* Grab the PTE address and make sure it's in prototype pool */
1167  PointerPte = Pfn1->PteAddress;
1168  ASSERT((PointerPte >= (PMMPTE)MmPagedPoolStart) && (PointerPte <= (PMMPTE)MmPagedPoolEnd));
1169 
1170  /* The PTE that backs it should also be valdi */
1171  PointerPte = MiAddressToPte(PointerPte);
1172  ASSERT(PointerPte->u.Hard.Valid == 1);
1173 
1174  /* Get the original prototype PTE and turn it into a transition PTE */
1175  PointerPte = Pfn1->PteAddress;
1176  TempPte = *PointerPte;
1177  TempPte.u.Soft.Transition = 1;
1178  TempPte.u.Soft.Valid = 0;
1179  TempPte.u.Soft.Prototype = 0;
1180  TempPte.u.Soft.Protection = Pfn1->OriginalPte.u.Soft.Protection;
1181  MI_WRITE_INVALID_PTE(PointerPte, TempPte);
1182  DPRINT("Marking PTE: %p as transition (%p - %lx)\n", PointerPte, Pfn1, MiGetPfnEntryIndex(Pfn1));
1183  }
1184 
1185  /* Put the page in transition */
1186  Pfn1->u3.e1.PageLocation = TransitionPage;
1187 
1188  /* PFN lock must be held */
1190 
1191  if (Pfn1->u3.e2.ReferenceCount == 1)
1192  {
1193  /* Is there still a PFN for this page? */
1194  if (MI_IS_PFN_DELETED(Pfn1))
1195  {
1196  /* Clear the last reference */
1197  Pfn1->u3.e2.ReferenceCount = 0;
1198  ASSERT(Pfn1->OriginalPte.u.Soft.Prototype == 0);
1199 
1200  /* Mark the page temporarily as valid, we're going to make it free soon */
1201  Pfn1->u3.e1.PageLocation = ActiveAndValid;
1202 
1203  /* Bring it back into the free list */
1204  MiInsertPageInFreeList(PageFrameIndex);
1205  }
1206  else
1207  {
1208  /* PFN not yet deleted, drop a ref count */
1209  MiDecrementReferenceCount(Pfn1, PageFrameIndex);
1210  }
1211  }
1212  else
1213  {
1214  /* Otherwise, just drop the reference count */
1215  InterlockedDecrement16((PSHORT)&Pfn1->u3.e2.ReferenceCount);
1216  }
1217  }
1218 }
1219 
1220 VOID
1221 NTAPI
1223  IN PFN_NUMBER PageFrameIndex)
1224 {
1225  /* PFN lock must be held */
1227 
1228  /* Sanity checks on the page */
1229  if (PageFrameIndex > MmHighestPhysicalPage ||
1230  Pfn1 != MI_PFN_ELEMENT(PageFrameIndex) ||
1231  Pfn1->u3.e2.ReferenceCount == 0 ||
1232  Pfn1->u3.e2.ReferenceCount >= 2500)
1233  {
1234  DPRINT1("PageFrameIndex=0x%lx, MmHighestPhysicalPage=0x%lx\n", PageFrameIndex, MmHighestPhysicalPage);
1235  DPRINT1("Pfn1=%p, Element=%p, RefCount=%u\n", Pfn1, MI_PFN_ELEMENT(PageFrameIndex), Pfn1->u3.e2.ReferenceCount);
1236  ASSERT(PageFrameIndex <= MmHighestPhysicalPage);
1237  ASSERT(Pfn1 == MI_PFN_ELEMENT(PageFrameIndex));
1238  ASSERT(Pfn1->u3.e2.ReferenceCount != 0);
1239  ASSERT(Pfn1->u3.e2.ReferenceCount < 2500);
1240  }
1241 
1242  /* Dereference the page, bail out if it's still alive */
1243  InterlockedDecrement16((PSHORT)&Pfn1->u3.e2.ReferenceCount);
1244  if (Pfn1->u3.e2.ReferenceCount) return;
1245 
1246  /* Nobody should still have reference to this page */
1247  if (Pfn1->u2.ShareCount != 0)
1248  {
1249  /* Otherwise something's really wrong */
1250  KeBugCheckEx(PFN_LIST_CORRUPT, 7, PageFrameIndex, Pfn1->u2.ShareCount, 0);
1251  }
1252 
1253  /* And it should be lying on some page list */
1254  ASSERT(Pfn1->u3.e1.PageLocation != ActiveAndValid);
1255 
1256  /* Did someone set the delete flag? */
1257  if (MI_IS_PFN_DELETED(Pfn1))
1258  {
1259  /* Insert it into the free list, there's nothing left to do */
1260  MiInsertPageInFreeList(PageFrameIndex);
1261  return;
1262  }
1263 
1264  /* Check to see which list this page should go into */
1265  if (Pfn1->u3.e1.Modified == 1)
1266  {
1267  /* Push it into the modified page list */
1268  MiInsertPageInList(&MmModifiedPageListHead, PageFrameIndex);
1269  }
1270  else
1271  {
1272  /* Otherwise, insert this page into the standby list */
1273  ASSERT(Pfn1->u3.e1.RemovalRequested == 0);
1274  MiInsertStandbyListAtFront(PageFrameIndex);
1275  }
1276 }
1277 
1278 VOID
1279 NTAPI
1281  IN PVOID PteAddress,
1282  IN PFN_NUMBER PteFrame)
1283 {
1284  PMMPFN Pfn1;
1285 
1286  /* Setup the PTE */
1287  Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);
1288  Pfn1->PteAddress = PteAddress;
1289 
1290  /* Make this a software PTE */
1292 
1293  /* Setup the page */
1294  ASSERT(Pfn1->u3.e2.ReferenceCount == 0);
1295  Pfn1->u3.e2.ReferenceCount = 1;
1296  Pfn1->u2.ShareCount = 1;
1297  Pfn1->u3.e1.PageLocation = ActiveAndValid;
1298  Pfn1->u3.e1.Modified = TRUE;
1299  Pfn1->u4.InPageError = FALSE;
1300 
1301  /* Did we get a PFN for the page table */
1302  if (PteFrame)
1303  {
1304  /* Store it */
1305  Pfn1->u4.PteFrame = PteFrame;
1306 
1307  /* Increase its share count so we don't get rid of it */
1308  Pfn1 = MI_PFN_ELEMENT(PteFrame);
1309  Pfn1->u2.ShareCount++;
1310  }
1311 }
1312 
1313 /* EOF */
DWORD *typedef PVOID
Definition: winlogon.h:52
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
#define MI_MAKE_SOFTWARE_PTE(p, x)
Definition: miarm.h:156
MMSUPPORT Vm
Definition: miarm.h:477
VOID FASTCALL MiInsertStandbyListAtFront(IN PFN_NUMBER PageFrameIndex)
Definition: pfnlist.c:718
#define IN
Definition: typedefs.h:38
VOID NTAPI MiInitializePfn(IN PFN_NUMBER PageFrameIndex, IN PMMPTE PointerPte, IN BOOLEAN Modified)
Definition: pfnlist.c:969
VOID NTAPI MiUnlinkPageFromList(IN PMMPFN Pfn)
Definition: pfnlist.c:264
#define TRUE
Definition: types.h:120
PFN_NUMBER NTAPI MiRemoveZeroPage(IN ULONG Color)
Definition: pfnlist.c:531
VOID NTAPI MiInitializePfnAndMakePteValid(IN PFN_NUMBER PageFrameIndex, IN PMMPTE PointerPte, IN MMPTE TempPte)
Definition: pfnlist.c:1036
PVOID Blink
Definition: miarm.h:409
NTSTATUS NTAPI MiInitializeAndChargePfn(OUT PPFN_NUMBER PageFrameIndex, IN PMMPDE PointerPde, IN PFN_NUMBER ContainingPageFrame, IN BOOLEAN SessionAllocation)
Definition: pfnlist.c:1093
ULONG MI_PFN_CURRENT_USAGE
Definition: pfnlist.c:63
PFN_NUMBER MmMinimumFreePages
Definition: mminit.c:313
signed short * PSHORT
Definition: retypes.h:6
MMPFNLIST MmBadPageListHead
Definition: pfnlist.c:48
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
ULONG_PTR AweAllocation
Definition: mm.h:349
return STATUS_SUCCESS
Definition: btrfs.c:2664
MMPFNLIST MmStandbyPageListHead
Definition: pfnlist.c:43
ULONG MmTotalPagesForPagingFile
Definition: pfnlist.c:39
PFN_NUMBER NTAPI MiRemovePageByColor(IN PFN_NUMBER PageIndex, IN ULONG Color)
Definition: pfnlist.c:363
MMLISTS ListName
Definition: mm.h:368
char CHAR
Definition: xmlstorage.h:175
VOID NTAPI MiInsertPageInList(IN PMMPFNLIST ListHead, IN PFN_NUMBER PageFrameIndex)
Definition: pfnlist.c:778
PFN_NUMBER MmHighMemoryThreshold
Definition: mminit.c:300
PFN_NUMBER Flink
Definition: mm.h:305
#define ASSERT_LIST_INVARIANT(x)
Definition: pfnlist.c:29
#define MM_READWRITE
Definition: miarm.h:49
#define MI_GET_NEXT_COLOR()
Definition: miarm.h:209
HARDWARE_PDE_ARMV6 TempPde
Definition: winldr.c:77
USHORT Modified
Definition: mm.h:288
PVOID MmPagedPoolEnd
Definition: init.c:26
PFN_NUMBER MmLowestPhysicalPage
Definition: meminit.c:30
union _MMPFN::@1569 u4
USHORT RemovalRequested
Definition: mm.h:294
MMPFNLIST MmFreePageListHead
Definition: pfnlist.c:42
union _MMPFN::@1564 u1
NTSTATUS FASTCALL MiCheckPdeForPagedPool(IN PVOID Address)
Definition: pagfault.c:471
PFN_NUMBER MmAvailablePages
Definition: freelist.c:26
LONG NTAPI KeSetEvent(IN PKEVENT Event, IN KPRIORITY Increment, IN BOOLEAN Wait)
Definition: eventobj.c:159
#define FASTCALL
Definition: nt_native.h:50
USHORT PageLocation
Definition: mm.h:293
struct Color Color
PFN_NUMBER Flink
Definition: mm.h:369
enum _MMLISTS MMLISTS
uint32_t ULONG_PTR
Definition: typedefs.h:63
USHORT PrototypePte
Definition: mm.h:291
PMMPFNLIST MmPageLocationList[]
Definition: pfnlist.c:51
UCHAR KIRQL
Definition: env_spec_w32.h:591
MMPFNENTRY e1
Definition: mm.h:325
ULONG * PPFN_NUMBER
Definition: ke.h:8
union _MMPFN::@1566 u3
USHORT CacheAttribute
Definition: mm.h:295
#define MiAddressToPte(x)
Definition: mmx86.c:19
BOOLEAN MmZeroingPageThreadActive
Definition: zeropage.c:20
ULONG PFN_NUMBER
Definition: ke.h:8
ULONG_PTR MustBeCached
Definition: mm.h:351
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
#define FALSE
Definition: types.h:117
FORCEINLINE VOID MI_WRITE_VALID_PTE(IN PMMPTE PointerPte, IN MMPTE TempPte)
Definition: miarm.h:914
ULONG_PTR ShareCount
Definition: mm.h:318
ULONG MmTransitionSharedPages
Definition: pfnlist.c:38
VOID NTAPI MmRebalanceMemoryConsumers(VOID)
Definition: balance.c:218
PFN_NUMBER Blink
Definition: mm.h:370
PFN_NUMBER Flink
Definition: miarm.h:408
VOID NTAPI MiZeroPhysicalPage(IN PFN_NUMBER PageFrameIndex)
Definition: pfnlist.c:122
#define PsGetCurrentProcess
Definition: psfuncs.h:17
PVOID NTAPI MiMapPageInHyperSpace(IN PEPROCESS Process, IN PFN_NUMBER Page, IN PKIRQL OldIrql)
Definition: hypermap.c:30
BOOLEAN MmMirroring
Definition: pfnlist.c:35
smooth NULL
Definition: ftsmooth.c:557
PVOID FORCEINLINE MiPteToAddress(PMMPTE PointerPte)
Definition: mm.h:185
ULONG_PTR VerifierAllocation
Definition: mm.h:348
MMPFNLIST MmRomPageListHead
Definition: pfnlist.c:49
PFN_NUMBER NTAPI MiRemoveAnyPage(IN ULONG Color)
Definition: pfnlist.c:475
KEVENT MmZeroingPageEvent
Definition: zeropage.c:21
ULONG MmSecondaryColorMask
Definition: mminit.c:256
void DPRINT(...)
Definition: polytest.cpp:61
FORCEINLINE VOID MI_WRITE_VALID_PDE(IN PMMPDE PointerPde, IN MMPDE TempPde)
Definition: miarm.h:969
ULONG64 Protection
Definition: mmtypes.h:88
PMMCOLOR_TABLES MmFreePagesByColor[FreePageList+1]
Definition: mminit.c:285
MMPFNLIST MmModifiedPageListHead
Definition: pfnlist.c:45
MMPFNLIST MmModifiedNoWritePageListHead
Definition: pfnlist.c:47
static VOID MiDecrementAvailablePages(VOID)
Definition: pfnlist.c:90
unsigned char BOOLEAN
VOID FASTCALL KeZeroPages(IN PVOID Address, IN ULONG Size)
Definition: stubs.c:82
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:24
ULONG64 Valid
Definition: mmtypes.h:150
#define MI_IS_PFN_DELETED(x)
Definition: miarm.h:162
VOID NTAPI MiUnlinkFreeOrZeroedPage(IN PMMPFN Entry)
Definition: pfnlist.c:137
BOOLEAN MmRosNotifyAvailablePage(PFN_NUMBER PageFrameIndex)
Definition: balance.c:406
VOID FASTCALL KeReleaseQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber, IN KIRQL OldIrql)
Definition: spinlock.c:154
HARDWARE_PTE_ARMV6 TempPte
Definition: winldr.c:75
ULONG MmSystemPageColor
Definition: pfnlist.c:36
VOID NTAPI MiUnmapPageInHyperSpace(IN PEPROCESS Process, IN PVOID Address, IN KIRQL OldIrql)
Definition: hypermap.c:93
FORCEINLINE PMMPFN MI_PFN_ELEMENT(IN PFN_NUMBER Pfn)
Definition: miarm.h:1391
PFN_NUMBER MmLowMemoryThreshold
Definition: mminit.c:299
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:803
ULONG64 PageFileHigh
Definition: mmtypes.h:93
VOID NTAPI MiInsertPageInFreeList(IN PFN_NUMBER PageFrameIndex)
Definition: pfnlist.c:604
Definition: mm.h:301
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
MMPFNLIST MmModifiedPageListByColor[1]
Definition: pfnlist.c:46
ULONG64 Prototype
Definition: mmtypes.h:89
#define PAGE_SIZE
Definition: env_spec_w32.h:49
ULONG64 Valid
Definition: mmtypes.h:86
_In_ ULONG _In_ BOOLEAN _Must_inspect_result_ PVOID * VirtualAddress
Definition: ndis.h:3772
static VOID MiIncrementAvailablePages(VOID)
Definition: pfnlist.c:69
ULONG MmSecondaryColors
Definition: mminit.c:255
LIST_HEAD(acpi_bus_event_list)
KIRQL FASTCALL KeAcquireQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber)
Definition: spinlock.c:108
ULONG_PTR Priority
Definition: mm.h:350
MMPTE ValidKernelPdeLocal
Definition: init.c:34
MMPTE ValidKernelPde
Definition: init.c:30
#define InterlockedDecrement16
Definition: interlocked.h:139
Status
Definition: gdiplustypes.h:24
ULONG_PTR Long
Definition: mmtypes.h:215
PVOID MmPagedPoolStart
Definition: miarm.h:552
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
MMPTE_HARDWARE Hard
Definition: mmtypes.h:217
FORCEINLINE VOID MI_WRITE_INVALID_PTE(IN PMMPTE PointerPte, IN MMPTE InvalidPte)
Definition: miarm.h:943
USHORT PageColor
Definition: mm.h:292
LONG NTSTATUS
Definition: DriverTester.h:11
VOID NTAPI MiInitializePfnForOtherProcess(IN PFN_NUMBER PageFrameIndex, IN PVOID PteAddress, IN PFN_NUMBER PteFrame)
Definition: pfnlist.c:1280
VOID NTAPI MiDecrementReferenceCount(IN PMMPFN Pfn1, IN PFN_NUMBER PageFrameIndex)
Definition: pfnlist.c:1222
unsigned short USHORT
Definition: pedump.c:61
MMPFNLIST MmZeroedPageListHead
Definition: pfnlist.c:41
ULONG_PTR PteFrame
Definition: mm.h:346
ULONG64 Transition
Definition: mmtypes.h:90
PFN_NUMBER Total
Definition: mm.h:367
struct _MMPFN * PMMPFN
#define MI_IS_ROS_PFN(x)
Definition: miarm.h:1041
USHORT Rom
Definition: mm.h:296
PMMPTE PteAddress
Definition: mm.h:314
MMPTE_SOFTWARE Soft
Definition: mmtypes.h:219
MMPTE OriginalPte
Definition: mm.h:335
#define DPRINT1
Definition: precomp.h:8
struct _MMPFN::@1566::@1572 e2
#define STATUS_RETRY
Definition: udferr_usr.h:182
ULONG WsIndex
Definition: mm.h:306
PFN_NUMBER Blink
Definition: mm.h:317
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:219
FORCEINLINE PFN_NUMBER MiGetPfnEntryIndex(IN PMMPFN Pfn1)
Definition: mm.h:893
#define OUT
Definition: typedefs.h:39
unsigned int ULONG
Definition: retypes.h:1
#define IO_NO_INCREMENT
Definition: iotypes.h:565
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
MMPFNLIST MmStandbyPageListByPriority[8]
Definition: pfnlist.c:44
ULONG64 PageFrameNumber
Definition: mmtypes.h:171
MMPTE DemandZeroPte
Definition: init.c:39
PFN_NUMBER Count
Definition: miarm.h:410
PFN_NUMBER MmHighestPhysicalPage
Definition: meminit.c:31
ULONG_PTR InPageError
Definition: mm.h:347
union _MMPTE::@2072 u
PKEVENT MiLowMemoryEvent
Definition: mminit.c:291
VOID NTAPI KeClearEvent(IN PKEVENT Event)
Definition: eventobj.c:22
ULONG WorkingSetSize
Definition: mmtypes.h:931
BOOLEAN MmDynamicPfn
Definition: pfnlist.c:34
PKEVENT MiHighMemoryEvent
Definition: mminit.c:292
union _MMPFN::@1565 u2
#define PFN_FROM_PTE(v)
Definition: mm.h:82
VOID NTAPI MiDecrementShareCount(IN PMMPFN Pfn1, IN PFN_NUMBER PageFrameIndex)
Definition: pfnlist.c:1133
base of all file and directory entries
Definition: entries.h:82
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:90
CHAR MI_PFN_CURRENT_PROCESS_NAME[16]
Definition: pfnlist.c:64
Definition: mm.h:365