ReactOS  0.4.10-dev-358-g66981e1
mminit.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/mminit.c
5  * PURPOSE: ARM Memory Manager Initialization
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 "miarm.h"
17 #undef MmSystemRangeStart
18 
19 /* GLOBALS ********************************************************************/
20 
21 //
22 // These are all registry-configurable, but by default, the memory manager will
23 // figure out the most appropriate values.
24 //
28 
29 /* Some of the same values, in pages */
31 
32 //
33 // These numbers describe the discrete equation components of the nonpaged
34 // pool sizing algorithm.
35 //
36 // They are described on http://support.microsoft.com/default.aspx/kb/126402/ja
37 // along with the algorithm that uses them, which is implemented later below.
38 //
43 
44 //
45 // The memory layout (and especially variable names) of the NT kernel mode
46 // components can be a bit hard to twig, especially when it comes to the non
47 // paged area.
48 //
49 // There are really two components to the non-paged pool:
50 //
51 // - The initial nonpaged pool, sized dynamically up to a maximum.
52 // - The expansion nonpaged pool, sized dynamically up to a maximum.
53 //
54 // The initial nonpaged pool is physically continuous for performance, and
55 // immediately follows the PFN database, typically sharing the same PDE. It is
56 // a very small resource (32MB on a 1GB system), and capped at 128MB.
57 //
58 // Right now we call this the "ARM³ Nonpaged Pool" and it begins somewhere after
59 // the PFN database (which starts at 0xB0000000).
60 //
61 // The expansion nonpaged pool, on the other hand, can grow much bigger (400MB
62 // for a 1GB system). On ARM³ however, it is currently capped at 128MB.
63 //
64 // The address where the initial nonpaged pool starts is aptly named
65 // MmNonPagedPoolStart, and it describes a range of MmSizeOfNonPagedPoolInBytes
66 // bytes.
67 //
68 // Expansion nonpaged pool starts at an address described by the variable called
69 // MmNonPagedPoolExpansionStart, and it goes on for MmMaximumNonPagedPoolInBytes
70 // minus MmSizeOfNonPagedPoolInBytes bytes, always reaching MmNonPagedPoolEnd
71 // (because of the way it's calculated) at 0xFFBE0000.
72 //
73 // Initial nonpaged pool is allocated and mapped early-on during boot, but what
74 // about the expansion nonpaged pool? It is instead composed of special pages
75 // which belong to what are called System PTEs. These PTEs are the matter of a
76 // later discussion, but they are also considered part of the "nonpaged" OS, due
77 // to the fact that they are never paged out -- once an address is described by
78 // a System PTE, it is always valid, until the System PTE is torn down.
79 //
80 // System PTEs are actually composed of two "spaces", the system space proper,
81 // and the nonpaged pool expansion space. The latter, as we've already seen,
82 // begins at MmNonPagedPoolExpansionStart. Based on the number of System PTEs
83 // that the system will support, the remaining address space below this address
84 // is used to hold the system space PTEs. This address, in turn, is held in the
85 // variable named MmNonPagedSystemStart, which itself is never allowed to go
86 // below 0xEB000000 (thus creating an upper bound on the number of System PTEs).
87 //
88 // This means that 330MB are reserved for total nonpaged system VA, on top of
89 // whatever the initial nonpaged pool allocation is.
90 //
91 // The following URLs, valid as of April 23rd, 2008, support this evidence:
92 //
93 // http://www.cs.miami.edu/~burt/journal/NT/memory.html
94 // http://www.ditii.com/2007/09/28/windows-memory-management-x86-virtual-address-space/
95 //
100 
101 //
102 // This is where paged pool starts by default
103 //
106 
107 //
108 // And this is its default size
109 //
112 
113 //
114 // Session space starts at 0xBFFFFFFF and grows downwards
115 // By default, it includes an 8MB image area where we map win32k and video card
116 // drivers, followed by a 4MB area containing the session's working set. This is
117 // then followed by a 20MB mapped view area and finally by the session's paged
118 // pool, by default 16MB.
119 //
120 // On a normal system, this results in session space occupying the region from
121 // 0xBD000000 to 0xC0000000
122 //
123 // See miarm.h for the defines that determine the sizing of this region. On an
124 // NT system, some of these can be configured through the registry, but we don't
125 // support that yet.
126 //
127 PVOID MiSessionSpaceEnd; // 0xC0000000
128 PVOID MiSessionImageEnd; // 0xC0000000
131 PVOID MiSessionViewStart; // 0xBE000000
132 PVOID MiSessionPoolEnd; // 0xBE000000
133 PVOID MiSessionPoolStart; // 0xBD000000
134 PVOID MmSessionBase; // 0xBD000000
139 
140 /*
141  * These are the PTE addresses of the boundaries carved out above
142  */
147 
148 //
149 // The system view space, on the other hand, is where sections that are memory
150 // mapped into "system space" end up.
151 //
152 // By default, it is a 16MB region, but we hack it to be 32MB for ReactOS
153 //
156 
157 #if (_MI_PAGING_LEVELS == 2)
158 //
159 // A copy of the system page directory (the page directory associated with the
160 // System process) is kept (double-mapped) by the manager in order to lazily
161 // map paged pool PDEs into external processes when they fault on a paged pool
162 // address.
163 //
166 #endif
167 
168 //
169 // The system cache starts right after hyperspace. The first few pages are for
170 // keeping track of the system working set list.
171 //
172 // This should be 0xC0C00000 -- the cache itself starts at 0xC1000000
173 //
175 
176 //
177 // Windows NT seems to choose between 7000, 11000 and 50000
178 // On systems with more than 32MB, this number is then doubled, and further
179 // aligned up to a PDE boundary (4MB).
180 //
182 
183 //
184 // This is how many pages the PFN database will take up
185 // In Windows, this includes the Quark Color Table, but not in ARM³
186 //
188 
189 //
190 // Unlike the old ReactOS Memory Manager, ARM³ (and Windows) does not keep track
191 // of pages that are not actually valid physical memory, such as ACPI reserved
192 // regions, BIOS address ranges, or holes in physical memory address space which
193 // could indicate device-mapped I/O memory.
194 //
195 // In fact, the lack of a PFN entry for a page usually indicates that this is
196 // I/O space instead.
197 //
198 // A bitmap, called the PFN bitmap, keeps track of all page frames by assigning
199 // a bit to each. If the bit is set, then the page is valid physical RAM.
200 //
202 
203 //
204 // This structure describes the different pieces of RAM-backed address space
205 //
207 
208 //
209 // This is where we keep track of the most basic physical layout markers
210 //
213 
214 //
215 // The total number of pages mapped by the boot loader, which include the kernel
216 // HAL, boot drivers, registry, NLS files and other loader data structures is
217 // kept track of here. This depends on "LoaderPagesSpanned" being correct when
218 // coming from the loader.
219 //
220 // This number is later aligned up to a PDE boundary.
221 //
223 
224 //
225 // These three variables keep track of the core separation of address space that
226 // exists between kernel mode and user mode.
227 //
231 
232 /* And these store the respective highest PTE/PDE address */
235 #if (_MI_PAGING_LEVELS >= 3)
236 PMMPTE MiHighestUserPpe;
237 #if (_MI_PAGING_LEVELS >= 4)
238 PMMPTE MiHighestUserPxe;
239 #endif
240 #endif
241 
242 /* These variables define the system cache address space */
247 
248 //
249 // This is where hyperspace ends (followed by the system cache working set)
250 //
252 
253 //
254 // Page coloring algorithm data
255 //
258 
259 //
260 // Actual (registry-configurable) size of a GUI thread's stack
261 //
263 
264 //
265 // Before we have a PFN database, memory comes straight from our physical memory
266 // blocks, which is nice because it's guaranteed contiguous and also because once
267 // we take a page from here, the system doesn't see it anymore.
268 // However, once the fun is over, those pages must be re-integrated back into
269 // PFN society life, and that requires us keeping a copy of the original layout
270 // so that we can parse it later.
271 //
274 
275 /*
276  * For each page's worth bytes of L2 cache in a given set/way line, the zero and
277  * free lists are organized in what is called a "color".
278  *
279  * This array points to the two lists, so it can be thought of as a multi-dimensional
280  * array of MmFreePagesByColor[2][MmSecondaryColors]. Since the number is dynamic,
281  * we describe the array in pointer form instead.
282  *
283  * On a final note, the color tables themselves are right after the PFN database.
284  */
285 C_ASSERT(FreePageList == 1);
287 
288 /* An event used in Phase 0 before the rest of the system is ready to go */
290 
291 /* All the events used for memory threshold notifications */
298 
299 /* The actual thresholds themselves, in page numbers */
306 
307 /*
308  * This number determines how many free pages must exist, at minimum, until we
309  * start trimming working sets and flushing modified pages to obtain more free
310  * pages.
311  *
312  * This number changes if the system detects that this is a server product
313  */
315 
316 /*
317  * This number indicates how many pages we consider to be a low limit of having
318  * "plenty" of free memory.
319  *
320  * It is doubled on systems that have more than 63MB of memory
321  */
323 
324 /* These values store the type of system this is (small, med, large) and if server */
327 
328 /*
329  * These values store the cache working set minimums and maximums, in pages
330  *
331  * The minimum value is boosted on systems with more than 24MB of RAM, and cut
332  * down to only 32 pages on embedded (<24MB RAM) systems.
333  *
334  * An extra boost of 2MB is given on systems with more than 33MB of RAM.
335  */
338 
339 /* FIXME: Move to cache/working set code later */
341 
342 /*
343  * This value determines in how many fragments/chunks the subsection prototype
344  * PTEs should be allocated when mapping a section object. It is configurable in
345  * the registry through the MapAllocationFragment parameter.
346  *
347  * The default is 64KB on systems with more than 1GB of RAM, 32KB on systems with
348  * more than 256MB of RAM, and 16KB on systems with less than 256MB of RAM.
349  *
350  * The maximum it can be set to is 2MB, and the minimum is 4KB.
351  */
353 
354 /*
355  * These two values track how much virtual memory can be committed, and when
356  * expansion should happen.
357  */
358  // FIXME: They should be moved elsewhere since it's not an "init" setting?
361 
362 /*
363  * These values tune certain user parameters. They have default values set here,
364  * as well as in the code, and can be overwritten by registry settings.
365  */
371 
372 /* Internal setting used for debugging memory descriptors */
374 #ifdef _ARM_
375 TRUE;
376 #else
377 FALSE;
378 #endif
379 
380 /* Number of memory descriptors in the loader block */
382 
383 /* Number of free pages in the loader block */
385 
386 /* Timeout value for critical sections (2.5 minutes) */
387 ULONG MmCritsectTimeoutSeconds = 150; // NT value: 720 * 60 * 60; (30 days)
389 
390 //
391 // Throttling limits for Cc (in pages)
392 // Above top, we don't throttle
393 // Above bottom, we throttle depending on the amount of modified pages
394 // Otherwise, we throttle!
395 //
398 
399 /* PRIVATE FUNCTIONS **********************************************************/
400 
401 VOID
402 NTAPI
404 {
405  PLIST_ENTRY ListEntry;
407  PFN_NUMBER PageFrameIndex, FreePages = 0;
408 
409  /* Loop the memory descriptors */
410  for (ListEntry = LoaderBlock->MemoryDescriptorListHead.Flink;
411  ListEntry != &LoaderBlock->MemoryDescriptorListHead;
412  ListEntry = ListEntry->Flink)
413  {
414  /* Get the descriptor */
415  Descriptor = CONTAINING_RECORD(ListEntry,
417  ListEntry);
418  DPRINT("MD Type: %lx Base: %lx Count: %lx\n",
419  Descriptor->MemoryType, Descriptor->BasePage, Descriptor->PageCount);
420 
421  /* Count this descriptor */
423 
424  /* Check if this is invisible memory */
425  if ((Descriptor->MemoryType == LoaderFirmwarePermanent) ||
426  (Descriptor->MemoryType == LoaderSpecialMemory) ||
427  (Descriptor->MemoryType == LoaderHALCachedMemory) ||
428  (Descriptor->MemoryType == LoaderBBTMemory))
429  {
430  /* Skip this descriptor */
431  continue;
432  }
433 
434  /* Check if this is bad memory */
435  if (Descriptor->MemoryType != LoaderBad)
436  {
437  /* Count this in the total of pages */
439  }
440 
441  /* Check if this is the new lowest page */
442  if (Descriptor->BasePage < MmLowestPhysicalPage)
443  {
444  /* Update the lowest page */
445  MmLowestPhysicalPage = Descriptor->BasePage;
446  }
447 
448  /* Check if this is the new highest page */
449  PageFrameIndex = Descriptor->BasePage + Descriptor->PageCount;
450  if (PageFrameIndex > MmHighestPhysicalPage)
451  {
452  /* Update the highest page */
453  MmHighestPhysicalPage = PageFrameIndex - 1;
454  }
455 
456  /* Check if this is free memory */
457  if ((Descriptor->MemoryType == LoaderFree) ||
458  (Descriptor->MemoryType == LoaderLoadedProgram) ||
459  (Descriptor->MemoryType == LoaderFirmwareTemporary) ||
460  (Descriptor->MemoryType == LoaderOsloaderStack))
461  {
462  /* Count it too free pages */
463  MiNumberOfFreePages += Descriptor->PageCount;
464 
465  /* Check if this is the largest memory descriptor */
466  if (Descriptor->PageCount > FreePages)
467  {
468  /* Remember it */
469  MxFreeDescriptor = Descriptor;
470  FreePages = Descriptor->PageCount;
471  }
472  }
473  }
474 
475  /* Save original values of the free descriptor, since it'll be
476  * altered by early allocations */
477  MxOldFreeDescriptor = *MxFreeDescriptor;
478 }
479 
481 NTAPI
484 {
485  PFN_NUMBER Pfn;
486 
487  /* Make sure we have enough pages */
488  if (PageCount > MxFreeDescriptor->PageCount)
489  {
490  /* Crash the system */
491  KeBugCheckEx(INSTALL_MORE_MEMORY,
493  MxFreeDescriptor->PageCount,
494  MxOldFreeDescriptor.PageCount,
495  PageCount);
496  }
497 
498  /* Use our lowest usable free pages */
499  Pfn = MxFreeDescriptor->BasePage;
500  MxFreeDescriptor->BasePage += PageCount;
501  MxFreeDescriptor->PageCount -= PageCount;
502  return Pfn;
503 }
504 
505 VOID
506 NTAPI
509 {
510  ULONG L2Associativity;
511 
512  /* Check if no setting was provided already */
513  if (!MmSecondaryColors)
514  {
515  /* Get L2 cache information */
516  L2Associativity = KeGetPcr()->SecondLevelCacheAssociativity;
517 
518  /* The number of colors is the number of cache bytes by set/way */
519  MmSecondaryColors = KeGetPcr()->SecondLevelCacheSize;
520  if (L2Associativity) MmSecondaryColors /= L2Associativity;
521  }
522 
523  /* Now convert cache bytes into pages */
525  if (!MmSecondaryColors)
526  {
527  /* If there was no cache data from the KPCR, use the default colors */
529  }
530  else
531  {
532  /* Otherwise, make sure there aren't too many colors */
534  {
535  /* Set the maximum */
537  }
538 
539  /* Make sure there aren't too little colors */
541  {
542  /* Set the default */
544  }
545 
546  /* Finally make sure the colors are a power of two */
548  {
549  /* Set the default */
551  }
552  }
553 
554  /* Compute the mask and store it */
556  KeGetCurrentPrcb()->SecondaryColorMask = MmSecondaryColorMask;
557 }
558 
559 VOID
560 NTAPI
563 {
564  ULONG i;
565  PMMPTE PointerPte, LastPte;
567 
568  /* The color table starts after the ARM3 PFN database */
569  MmFreePagesByColor[0] = (PMMCOLOR_TABLES)&MmPfnDatabase[MmHighestPhysicalPage + 1];
570 
571  /* Loop the PTEs. We have two color tables for each secondary color */
572  PointerPte = MiAddressToPte(&MmFreePagesByColor[0][0]);
573  LastPte = MiAddressToPte((ULONG_PTR)MmFreePagesByColor[0] +
574  (2 * MmSecondaryColors * sizeof(MMCOLOR_TABLES))
575  - 1);
576  while (PointerPte <= LastPte)
577  {
578  /* Check for valid PTE */
579  if (PointerPte->u.Hard.Valid == 0)
580  {
581  /* Get a page and map it */
582  TempPte.u.Hard.PageFrameNumber = MxGetNextPage(1);
583  MI_WRITE_VALID_PTE(PointerPte, TempPte);
584 
585  /* Zero out the page */
586  RtlZeroMemory(MiPteToAddress(PointerPte), PAGE_SIZE);
587  }
588 
589  /* Next */
590  PointerPte++;
591  }
592 
593  /* Now set the address of the next list, right after this one */
594  MmFreePagesByColor[1] = &MmFreePagesByColor[0][MmSecondaryColors];
595 
596  /* Now loop the lists to set them up */
597  for (i = 0; i < MmSecondaryColors; i++)
598  {
599  /* Set both free and zero lists for each color */
600  MmFreePagesByColor[ZeroedPageList][i].Flink = LIST_HEAD;
601  MmFreePagesByColor[ZeroedPageList][i].Blink = (PVOID)LIST_HEAD;
602  MmFreePagesByColor[ZeroedPageList][i].Count = 0;
603  MmFreePagesByColor[FreePageList][i].Flink = LIST_HEAD;
604  MmFreePagesByColor[FreePageList][i].Blink = (PVOID)LIST_HEAD;
605  MmFreePagesByColor[FreePageList][i].Count = 0;
606  }
607 }
608 
609 #ifndef _M_AMD64
610 BOOLEAN
611 NTAPI
614  IN PFN_NUMBER Pfn)
615 {
616  PLIST_ENTRY NextEntry;
618 
619  /* Loop the memory descriptors */
620  NextEntry = LoaderBlock->MemoryDescriptorListHead.Flink;
621  while (NextEntry != &LoaderBlock->MemoryDescriptorListHead)
622  {
623  /* Get the memory descriptor */
624  MdBlock = CONTAINING_RECORD(NextEntry,
626  ListEntry);
627 
628  /* Check if this PFN could be part of the block */
629  if (Pfn >= (MdBlock->BasePage))
630  {
631  /* Check if it really is part of the block */
632  if (Pfn < (MdBlock->BasePage + MdBlock->PageCount))
633  {
634  /* Check if the block is actually memory we don't map */
635  if ((MdBlock->MemoryType == LoaderFirmwarePermanent) ||
636  (MdBlock->MemoryType == LoaderBBTMemory) ||
637  (MdBlock->MemoryType == LoaderSpecialMemory))
638  {
639  /* We don't need PFN database entries for this memory */
640  break;
641  }
642 
643  /* This is memory we want to map */
644  return TRUE;
645  }
646  }
647  else
648  {
649  /* Blocks are ordered, so if it's not here, it doesn't exist */
650  break;
651  }
652 
653  /* Get to the next descriptor */
654  NextEntry = MdBlock->ListEntry.Flink;
655  }
656 
657  /* Check if this PFN is actually from our free memory descriptor */
658  if ((Pfn >= MxOldFreeDescriptor.BasePage) &&
659  (Pfn < MxOldFreeDescriptor.BasePage + MxOldFreeDescriptor.PageCount))
660  {
661  /* We use these pages for initial mappings, so we do want to count them */
662  return TRUE;
663  }
664 
665  /* Otherwise this isn't memory that we describe or care about */
666  return FALSE;
667 }
668 
669 VOID
670 NTAPI
673 {
674  PFN_NUMBER FreePage, FreePageCount, PagesLeft, BasePage, PageCount;
675  PLIST_ENTRY NextEntry;
677  PMMPTE PointerPte, LastPte;
679 
680  /* Get current page data, since we won't be using MxGetNextPage as it would corrupt our state */
681  FreePage = MxFreeDescriptor->BasePage;
682  FreePageCount = MxFreeDescriptor->PageCount;
683  PagesLeft = 0;
684 
685  /* Loop the memory descriptors */
686  NextEntry = LoaderBlock->MemoryDescriptorListHead.Flink;
687  while (NextEntry != &LoaderBlock->MemoryDescriptorListHead)
688  {
689  /* Get the descriptor */
690  MdBlock = CONTAINING_RECORD(NextEntry,
692  ListEntry);
693  if ((MdBlock->MemoryType == LoaderFirmwarePermanent) ||
694  (MdBlock->MemoryType == LoaderBBTMemory) ||
695  (MdBlock->MemoryType == LoaderSpecialMemory))
696  {
697  /* These pages are not part of the PFN database */
698  NextEntry = MdBlock->ListEntry.Flink;
699  continue;
700  }
701 
702  /* Next, check if this is our special free descriptor we've found */
703  if (MdBlock == MxFreeDescriptor)
704  {
705  /* Use the real numbers instead */
706  BasePage = MxOldFreeDescriptor.BasePage;
707  PageCount = MxOldFreeDescriptor.PageCount;
708  }
709  else
710  {
711  /* Use the descriptor's numbers */
712  BasePage = MdBlock->BasePage;
713  PageCount = MdBlock->PageCount;
714  }
715 
716  /* Get the PTEs for this range */
717  PointerPte = MiAddressToPte(&MmPfnDatabase[BasePage]);
718  LastPte = MiAddressToPte(((ULONG_PTR)&MmPfnDatabase[BasePage + PageCount]) - 1);
719  DPRINT("MD Type: %lx Base: %lx Count: %lx\n", MdBlock->MemoryType, BasePage, PageCount);
720 
721  /* Loop them */
722  while (PointerPte <= LastPte)
723  {
724  /* We'll only touch PTEs that aren't already valid */
725  if (PointerPte->u.Hard.Valid == 0)
726  {
727  /* Use the next free page */
728  TempPte.u.Hard.PageFrameNumber = FreePage;
729  ASSERT(FreePageCount != 0);
730 
731  /* Consume free pages */
732  FreePage++;
733  FreePageCount--;
734  if (!FreePageCount)
735  {
736  /* Out of memory */
737  KeBugCheckEx(INSTALL_MORE_MEMORY,
739  FreePageCount,
740  MxOldFreeDescriptor.PageCount,
741  1);
742  }
743 
744  /* Write out this PTE */
745  PagesLeft++;
746  MI_WRITE_VALID_PTE(PointerPte, TempPte);
747 
748  /* Zero this page */
749  RtlZeroMemory(MiPteToAddress(PointerPte), PAGE_SIZE);
750  }
751 
752  /* Next! */
753  PointerPte++;
754  }
755 
756  /* Do the next address range */
757  NextEntry = MdBlock->ListEntry.Flink;
758  }
759 
760  /* Now update the free descriptors to consume the pages we used up during the PFN allocation loop */
761  MxFreeDescriptor->BasePage = FreePage;
762  MxFreeDescriptor->PageCount = FreePageCount;
763 }
764 
765 VOID
766 NTAPI
769 {
770  PMMPDE PointerPde;
771  PMMPTE PointerPte;
772  ULONG i, Count, j;
773  PFN_NUMBER PageFrameIndex, StartupPdIndex, PtePageIndex;
774  PMMPFN Pfn1, Pfn2;
776 
777  /* PFN of the startup page directory */
778  StartupPdIndex = PFN_FROM_PTE(MiAddressToPde(PDE_BASE));
779 
780  /* Start with the first PDE and scan them all */
781  PointerPde = MiAddressToPde(NULL);
782  Count = PD_COUNT * PDE_COUNT;
783  for (i = 0; i < Count; i++)
784  {
785  /* Check for valid PDE */
786  if (PointerPde->u.Hard.Valid == 1)
787  {
788  /* Get the PFN from it */
789  PageFrameIndex = PFN_FROM_PTE(PointerPde);
790 
791  /* Do we want a PFN entry for this page? */
792  if (MiIsRegularMemory(LoaderBlock, PageFrameIndex))
793  {
794  /* Yes we do, set it up */
795  Pfn1 = MiGetPfnEntry(PageFrameIndex);
796  Pfn1->u4.PteFrame = StartupPdIndex;
797  Pfn1->PteAddress = (PMMPTE)PointerPde;
798  Pfn1->u2.ShareCount++;
799  Pfn1->u3.e2.ReferenceCount = 1;
802 #if MI_TRACE_PFNS
803  Pfn1->PfnUsage = MI_USAGE_INIT_MEMORY;
804  memcpy(Pfn1->ProcessName, "Initial PDE", 16);
805 #endif
806  }
807  else
808  {
809  /* No PFN entry */
810  Pfn1 = NULL;
811  }
812 
813  /* Now get the PTE and scan the pages */
814  PointerPte = MiAddressToPte(BaseAddress);
815  for (j = 0; j < PTE_COUNT; j++)
816  {
817  /* Check for a valid PTE */
818  if (PointerPte->u.Hard.Valid == 1)
819  {
820  /* Increase the shared count of the PFN entry for the PDE */
821  ASSERT(Pfn1 != NULL);
822  Pfn1->u2.ShareCount++;
823 
824  /* Now check if the PTE is valid memory too */
825  PtePageIndex = PFN_FROM_PTE(PointerPte);
826  if (MiIsRegularMemory(LoaderBlock, PtePageIndex))
827  {
828  /*
829  * Only add pages above the end of system code or pages
830  * that are part of nonpaged pool
831  */
832  if ((BaseAddress >= 0xA0000000) ||
833  ((BaseAddress >= (ULONG_PTR)MmNonPagedPoolStart) &&
834  (BaseAddress < (ULONG_PTR)MmNonPagedPoolStart +
836  {
837  /* Get the PFN entry and make sure it too is valid */
838  Pfn2 = MiGetPfnEntry(PtePageIndex);
839  if ((MmIsAddressValid(Pfn2)) &&
840  (MmIsAddressValid(Pfn2 + 1)))
841  {
842  /* Setup the PFN entry */
843  Pfn2->u4.PteFrame = PageFrameIndex;
844  Pfn2->PteAddress = PointerPte;
845  Pfn2->u2.ShareCount++;
846  Pfn2->u3.e2.ReferenceCount = 1;
849 #if MI_TRACE_PFNS
850  Pfn2->PfnUsage = MI_USAGE_INIT_MEMORY;
851  memcpy(Pfn1->ProcessName, "Initial PTE", 16);
852 #endif
853  }
854  }
855  }
856  }
857 
858  /* Next PTE */
859  PointerPte++;
860  BaseAddress += PAGE_SIZE;
861  }
862  }
863  else
864  {
865  /* Next PDE mapped address */
866  BaseAddress += PDE_MAPPED_VA;
867  }
868 
869  /* Next PTE */
870  PointerPde++;
871  }
872 }
873 
874 VOID
875 NTAPI
878 {
879  PMMPFN Pfn1;
880  PMMPDE PointerPde;
881 
882  /* Grab the lowest page and check if it has no real references */
884  if (!(MmLowestPhysicalPage) && !(Pfn1->u3.e2.ReferenceCount))
885  {
886  /* Make it a bogus page to catch errors */
887  PointerPde = MiAddressToPde(0xFFFFFFFF);
888  Pfn1->u4.PteFrame = PFN_FROM_PTE(PointerPde);
889  Pfn1->PteAddress = (PMMPTE)PointerPde;
890  Pfn1->u2.ShareCount++;
891  Pfn1->u3.e2.ReferenceCount = 0xFFF0;
894  }
895 }
896 
897 VOID
898 NTAPI
901 {
902  PLIST_ENTRY NextEntry;
903  PFN_NUMBER PageCount = 0;
905  PFN_NUMBER PageFrameIndex;
906  PMMPFN Pfn1;
907  PMMPTE PointerPte;
908  PMMPDE PointerPde;
909  KIRQL OldIrql;
910 
911  /* Now loop through the descriptors */
912  NextEntry = LoaderBlock->MemoryDescriptorListHead.Flink;
913  while (NextEntry != &LoaderBlock->MemoryDescriptorListHead)
914  {
915  /* Get the current descriptor */
916  MdBlock = CONTAINING_RECORD(NextEntry,
918  ListEntry);
919 
920  /* Read its data */
921  PageCount = MdBlock->PageCount;
922  PageFrameIndex = MdBlock->BasePage;
923 
924  /* Don't allow memory above what the PFN database is mapping */
925  if (PageFrameIndex > MmHighestPhysicalPage)
926  {
927  /* Since they are ordered, everything past here will be larger */
928  break;
929  }
930 
931  /* On the other hand, the end page might be higher up... */
932  if ((PageFrameIndex + PageCount) > (MmHighestPhysicalPage + 1))
933  {
934  /* In which case we'll trim the descriptor to go as high as we can */
935  PageCount = MmHighestPhysicalPage + 1 - PageFrameIndex;
936  MdBlock->PageCount = PageCount;
937 
938  /* But if there's nothing left to trim, we got too high, so quit */
939  if (!PageCount) break;
940  }
941 
942  /* Now check the descriptor type */
943  switch (MdBlock->MemoryType)
944  {
945  /* Check for bad RAM */
946  case LoaderBad:
947 
948  DPRINT1("You either have specified /BURNMEMORY or damaged RAM modules.\n");
949  break;
950 
951  /* Check for free RAM */
952  case LoaderFree:
953  case LoaderLoadedProgram:
955  case LoaderOsloaderStack:
956 
957  /* Get the last page of this descriptor. Note we loop backwards */
958  PageFrameIndex += PageCount - 1;
959  Pfn1 = MiGetPfnEntry(PageFrameIndex);
960 
961  /* Lock the PFN Database */
962  OldIrql = MiAcquirePfnLock();
963  while (PageCount--)
964  {
965  /* If the page really has no references, mark it as free */
966  if (!Pfn1->u3.e2.ReferenceCount)
967  {
968  /* Add it to the free list */
970  MiInsertPageInFreeList(PageFrameIndex);
971  }
972 
973  /* Go to the next page */
974  Pfn1--;
975  PageFrameIndex--;
976  }
977 
978  /* Release PFN database */
979  MiReleasePfnLock(OldIrql);
980 
981  /* Done with this block */
982  break;
983 
984  /* Check for pages that are invisible to us */
986  case LoaderSpecialMemory:
987  case LoaderBBTMemory:
988 
989  /* And skip them */
990  break;
991 
992  default:
993 
994  /* Map these pages with the KSEG0 mapping that adds 0x80000000 */
995  PointerPte = MiAddressToPte(KSEG0_BASE + (PageFrameIndex << PAGE_SHIFT));
996  Pfn1 = MiGetPfnEntry(PageFrameIndex);
997  while (PageCount--)
998  {
999  /* Check if the page is really unused */
1000  PointerPde = MiAddressToPde(KSEG0_BASE + (PageFrameIndex << PAGE_SHIFT));
1001  if (!Pfn1->u3.e2.ReferenceCount)
1002  {
1003  /* Mark it as being in-use */
1004  Pfn1->u4.PteFrame = PFN_FROM_PTE(PointerPde);
1005  Pfn1->PteAddress = PointerPte;
1006  Pfn1->u2.ShareCount++;
1007  Pfn1->u3.e2.ReferenceCount = 1;
1008  Pfn1->u3.e1.PageLocation = ActiveAndValid;
1009  Pfn1->u3.e1.CacheAttribute = MiNonCached;
1010 #if MI_TRACE_PFNS
1011  Pfn1->PfnUsage = MI_USAGE_BOOT_DRIVER;
1012 #endif
1013 
1014  /* Check for RAM disk page */
1015  if (MdBlock->MemoryType == LoaderXIPRom)
1016  {
1017  /* Make it a pseudo-I/O ROM mapping */
1018  Pfn1->u1.Flink = 0;
1019  Pfn1->u2.ShareCount = 0;
1020  Pfn1->u3.e2.ReferenceCount = 0;
1021  Pfn1->u3.e1.PageLocation = 0;
1022  Pfn1->u3.e1.Rom = 1;
1023  Pfn1->u4.InPageError = 0;
1024  Pfn1->u3.e1.PrototypePte = 1;
1025  }
1026  }
1027 
1028  /* Advance page structures */
1029  Pfn1++;
1030  PageFrameIndex++;
1031  PointerPte++;
1032  }
1033  break;
1034  }
1035 
1036  /* Next descriptor entry */
1037  NextEntry = MdBlock->ListEntry.Flink;
1038  }
1039 }
1040 
1041 VOID
1042 NTAPI
1045 {
1046  PMMPTE PointerPte, LastPte;
1047  PMMPFN Pfn1;
1048 
1049  /* Loop the PFN database page */
1052  while (PointerPte <= LastPte)
1053  {
1054  /* Make sure the page is valid */
1055  if (PointerPte->u.Hard.Valid == 1)
1056  {
1057  /* Get the PFN entry and just mark it referenced */
1058  Pfn1 = MiGetPfnEntry(PointerPte->u.Hard.PageFrameNumber);
1059  Pfn1->u2.ShareCount = 1;
1060  Pfn1->u3.e2.ReferenceCount = 1;
1061 #if MI_TRACE_PFNS
1062  Pfn1->PfnUsage = MI_USAGE_PFN_DATABASE;
1063 #endif
1064  }
1065 
1066  /* Next */
1067  PointerPte++;
1068  }
1069 }
1070 
1071 VOID
1072 NTAPI
1075 {
1076  /* Scan memory and start setting up PFN entries */
1077  MiBuildPfnDatabaseFromPages(LoaderBlock);
1078 
1079  /* Add the zero page */
1081 
1082  /* Scan the loader block and build the rest of the PFN database */
1083  MiBuildPfnDatabaseFromLoaderBlock(LoaderBlock);
1084 
1085  /* Finally add the pages for the PFN database itself */
1087 }
1088 #endif /* !_M_AMD64 */
1089 
1090 VOID
1091 NTAPI
1094 {
1095  PLIST_ENTRY NextMd;
1097  ULONG_PTR i;
1098  PFN_NUMBER BasePage, LoaderPages;
1099  PMMPFN Pfn1;
1100  KIRQL OldIrql;
1102 
1103  /* Loop the descriptors in order to count them */
1104  i = 0;
1105  NextMd = LoaderBlock->MemoryDescriptorListHead.Flink;
1106  while (NextMd != &LoaderBlock->MemoryDescriptorListHead)
1107  {
1108  MdBlock = CONTAINING_RECORD(NextMd,
1110  ListEntry);
1111  i++;
1112  NextMd = MdBlock->ListEntry.Flink;
1113  }
1114 
1115  /* Allocate a structure to hold the physical runs */
1117  i * sizeof(PHYSICAL_MEMORY_RUN),
1118  'lMmM');
1119  ASSERT(Buffer != NULL);
1120  Entry = Buffer;
1121 
1122  /* Loop the descriptors again */
1123  NextMd = LoaderBlock->MemoryDescriptorListHead.Flink;
1124  while (NextMd != &LoaderBlock->MemoryDescriptorListHead)
1125  {
1126  /* Check what kind this was */
1127  MdBlock = CONTAINING_RECORD(NextMd,
1129  ListEntry);
1130  switch (MdBlock->MemoryType)
1131  {
1132  /* Registry, NLS, and heap data */
1133  case LoaderRegistryData:
1134  case LoaderOsloaderHeap:
1135  case LoaderNlsData:
1136  /* Are all a candidate for deletion */
1137  Entry->BasePage = MdBlock->BasePage;
1138  Entry->PageCount = MdBlock->PageCount;
1139  Entry++;
1140 
1141  /* We keep the rest */
1142  default:
1143  break;
1144  }
1145 
1146  /* Move to the next descriptor */
1147  NextMd = MdBlock->ListEntry.Flink;
1148  }
1149 
1150  /* Acquire the PFN lock */
1151  OldIrql = MiAcquirePfnLock();
1152 
1153  /* Loop the runs */
1154  LoaderPages = 0;
1155  while (--Entry >= Buffer)
1156  {
1157  /* See how many pages are in this run */
1158  i = Entry->PageCount;
1159  BasePage = Entry->BasePage;
1160 
1161  /* Loop each page */
1162  Pfn1 = MiGetPfnEntry(BasePage);
1163  while (i--)
1164  {
1165  /* Check if it has references or is in any kind of list */
1166  if (!(Pfn1->u3.e2.ReferenceCount) && (!Pfn1->u1.Flink))
1167  {
1168  /* Set the new PTE address and put this page into the free list */
1169  Pfn1->PteAddress = (PMMPTE)(BasePage << PAGE_SHIFT);
1170  MiInsertPageInFreeList(BasePage);
1171  LoaderPages++;
1172  }
1173  else if (BasePage)
1174  {
1175  /* It has a reference, so simply drop it */
1177 
1178  /* Drop a dereference on this page, which should delete it */
1179  Pfn1->PteAddress->u.Long = 0;
1180  MI_SET_PFN_DELETED(Pfn1);
1181  MiDecrementShareCount(Pfn1, BasePage);
1182  LoaderPages++;
1183  }
1184 
1185  /* Move to the next page */
1186  Pfn1++;
1187  BasePage++;
1188  }
1189  }
1190 
1191  /* Release the PFN lock and flush the TLB */
1192  DPRINT("Loader pages freed: %lx\n", LoaderPages);
1193  MiReleasePfnLock(OldIrql);
1194  KeFlushCurrentTb();
1195 
1196  /* Free our run structure */
1197  ExFreePoolWithTag(Buffer, 'lMmM');
1198 }
1199 
1200 VOID
1201 NTAPI
1204 {
1205  /* This function needs to do more work, for now, we tune page minimums */
1206 
1207  /* Check for a system with around 64MB RAM or more */
1208  if (MmNumberOfPhysicalPages >= (63 * _1MB) / PAGE_SIZE)
1209  {
1210  /* Double the minimum amount of pages we consider for a "plenty free" scenario */
1211  MmPlentyFreePages *= 2;
1212  }
1213 }
1214 
1215 VOID
1216 NTAPI
1219 {
1220  /* Are we in a low-memory situation? */
1222  {
1223  /* Clear high, set low */
1224  if (KeReadStateEvent(MiHighMemoryEvent)) KeClearEvent(MiHighMemoryEvent);
1225  if (!KeReadStateEvent(MiLowMemoryEvent)) KeSetEvent(MiLowMemoryEvent, 0, FALSE);
1226  }
1228  {
1229  /* We are in between, clear both */
1230  if (KeReadStateEvent(MiHighMemoryEvent)) KeClearEvent(MiHighMemoryEvent);
1231  if (KeReadStateEvent(MiLowMemoryEvent)) KeClearEvent(MiLowMemoryEvent);
1232  }
1233  else
1234  {
1235  /* Clear low, set high */
1236  if (KeReadStateEvent(MiLowMemoryEvent)) KeClearEvent(MiLowMemoryEvent);
1237  if (!KeReadStateEvent(MiHighMemoryEvent)) KeSetEvent(MiHighMemoryEvent, 0, FALSE);
1238  }
1239 }
1240 
1241 NTSTATUS
1242 NTAPI
1245  OUT PKEVENT *Event)
1246 {
1247  PACL Dacl;
1249  ULONG DaclLength;
1250  NTSTATUS Status;
1253 
1254  /* Create the SD */
1255  Status = RtlCreateSecurityDescriptor(&SecurityDescriptor,
1257  if (!NT_SUCCESS(Status)) return Status;
1258 
1259  /* One ACL with 3 ACEs, containing each one SID */
1260  DaclLength = sizeof(ACL) +
1261  3 * sizeof(ACCESS_ALLOWED_ACE) +
1265 
1266  /* Allocate space for the DACL */
1267  Dacl = ExAllocatePoolWithTag(PagedPool, DaclLength, 'lcaD');
1268  if (!Dacl) return STATUS_INSUFFICIENT_RESOURCES;
1269 
1270  /* Setup the ACL inside it */
1271  Status = RtlCreateAcl(Dacl, DaclLength, ACL_REVISION);
1272  if (!NT_SUCCESS(Status)) goto CleanUp;
1273 
1274  /* Add query rights for everyone */
1275  Status = RtlAddAccessAllowedAce(Dacl,
1276  ACL_REVISION,
1278  SeWorldSid);
1279  if (!NT_SUCCESS(Status)) goto CleanUp;
1280 
1281  /* Full rights for the admin */
1282  Status = RtlAddAccessAllowedAce(Dacl,
1283  ACL_REVISION,
1286  if (!NT_SUCCESS(Status)) goto CleanUp;
1287 
1288  /* As well as full rights for the system */
1289  Status = RtlAddAccessAllowedAce(Dacl,
1290  ACL_REVISION,
1293  if (!NT_SUCCESS(Status)) goto CleanUp;
1294 
1295  /* Set this DACL inside the SD */
1296  Status = RtlSetDaclSecurityDescriptor(&SecurityDescriptor,
1297  TRUE,
1298  Dacl,
1299  FALSE);
1300  if (!NT_SUCCESS(Status)) goto CleanUp;
1301 
1302  /* Setup the event attributes, making sure it's a permanent one */
1303  InitializeObjectAttributes(&ObjectAttributes,
1304  Name,
1306  NULL,
1307  &SecurityDescriptor);
1308 
1309  /* Create the event */
1310  Status = ZwCreateEvent(&EventHandle,
1312  &ObjectAttributes,
1314  FALSE);
1315 CleanUp:
1316  /* Free the DACL */
1317  ExFreePoolWithTag(Dacl, 'lcaD');
1318 
1319  /* Check if this is the success path */
1320  if (NT_SUCCESS(Status))
1321  {
1322  /* Add a reference to the object, then close the handle we had */
1323  Status = ObReferenceObjectByHandle(EventHandle,
1326  KernelMode,
1327  (PVOID*)Event,
1328  NULL);
1329  ZwClose (EventHandle);
1330  }
1331 
1332  /* Return status */
1333  return Status;
1334 }
1335 
1336 BOOLEAN
1337 NTAPI
1340 {
1341  UNICODE_STRING LowString = RTL_CONSTANT_STRING(L"\\KernelObjects\\LowMemoryCondition");
1342  UNICODE_STRING HighString = RTL_CONSTANT_STRING(L"\\KernelObjects\\HighMemoryCondition");
1343  UNICODE_STRING LowPagedPoolString = RTL_CONSTANT_STRING(L"\\KernelObjects\\LowPagedPoolCondition");
1344  UNICODE_STRING HighPagedPoolString = RTL_CONSTANT_STRING(L"\\KernelObjects\\HighPagedPoolCondition");
1345  UNICODE_STRING LowNonPagedPoolString = RTL_CONSTANT_STRING(L"\\KernelObjects\\LowNonPagedPoolCondition");
1346  UNICODE_STRING HighNonPagedPoolString = RTL_CONSTANT_STRING(L"\\KernelObjects\\HighNonPagedPoolCondition");
1347  NTSTATUS Status;
1348 
1349  /* Check if we have a registry setting */
1351  {
1352  /* Convert it to pages */
1354  }
1355  else
1356  {
1357  /* The low memory threshold is hit when we don't consider that we have "plenty" of free pages anymore */
1359 
1360  /* More than one GB of memory? */
1361  if (MmNumberOfPhysicalPages > 0x40000)
1362  {
1363  /* Start at 32MB, and add another 16MB for each GB */
1364  MmLowMemoryThreshold = (32 * _1MB) / PAGE_SIZE;
1365  MmLowMemoryThreshold += ((MmNumberOfPhysicalPages - 0x40000) >> 7);
1366  }
1367  else if (MmNumberOfPhysicalPages > 0x8000)
1368  {
1369  /* For systems with > 128MB RAM, add another 4MB for each 128MB */
1370  MmLowMemoryThreshold += ((MmNumberOfPhysicalPages - 0x8000) >> 5);
1371  }
1372 
1373  /* Don't let the minimum threshold go past 64MB */
1375  }
1376 
1377  /* Check if we have a registry setting */
1379  {
1380  /* Convert it into pages */
1382  }
1383  else
1384  {
1385  /* Otherwise, the default is three times the low memory threshold */
1388  }
1389 
1390  /* Make sure high threshold is actually higher than the low */
1392 
1393  /* Create the memory events for all the thresholds */
1394  Status = MiCreateMemoryEvent(&LowString, &MiLowMemoryEvent);
1395  if (!NT_SUCCESS(Status)) return FALSE;
1396  Status = MiCreateMemoryEvent(&HighString, &MiHighMemoryEvent);
1397  if (!NT_SUCCESS(Status)) return FALSE;
1398  Status = MiCreateMemoryEvent(&LowPagedPoolString, &MiLowPagedPoolEvent);
1399  if (!NT_SUCCESS(Status)) return FALSE;
1400  Status = MiCreateMemoryEvent(&HighPagedPoolString, &MiHighPagedPoolEvent);
1401  if (!NT_SUCCESS(Status)) return FALSE;
1402  Status = MiCreateMemoryEvent(&LowNonPagedPoolString, &MiLowNonPagedPoolEvent);
1403  if (!NT_SUCCESS(Status)) return FALSE;
1404  Status = MiCreateMemoryEvent(&HighNonPagedPoolString, &MiHighNonPagedPoolEvent);
1405  if (!NT_SUCCESS(Status)) return FALSE;
1406 
1407  /* Now setup the pool events */
1409 
1410  /* Set the initial event state */
1412  return TRUE;
1413 }
1414 
1415 VOID
1416 NTAPI
1419 {
1421  PMMPDE PointerPde, LastPde;
1422  PMMPTE PointerPte;
1423  ULONG j;
1424  PFN_NUMBER PageFrameIndex;
1425 
1426  /* HAL Heap address -- should be on a PDE boundary */
1427  BaseAddress = (PVOID)MM_HAL_VA_START;
1428  ASSERT(MiAddressToPteOffset(BaseAddress) == 0);
1429 
1430  /* Check how many PDEs the heap has */
1431  PointerPde = MiAddressToPde(BaseAddress);
1432  LastPde = MiAddressToPde((PVOID)MM_HAL_VA_END);
1433 
1434  while (PointerPde <= LastPde)
1435  {
1436  /* Does the HAL own this mapping? */
1437  if ((PointerPde->u.Hard.Valid == 1) &&
1438  (MI_IS_PAGE_LARGE(PointerPde) == FALSE))
1439  {
1440  /* Get the PTE for it and scan each page */
1441  PointerPte = MiAddressToPte(BaseAddress);
1442  for (j = 0 ; j < PTE_COUNT; j++)
1443  {
1444  /* Does the HAL own this page? */
1445  if (PointerPte->u.Hard.Valid == 1)
1446  {
1447  /* Is the HAL using it for device or I/O mapped memory? */
1448  PageFrameIndex = PFN_FROM_PTE(PointerPte);
1449  if (!MiGetPfnEntry(PageFrameIndex))
1450  {
1451  /* FIXME: For PAT, we need to track I/O cache attributes for coherency */
1452  DPRINT1("HAL I/O Mapping at %p is unsafe\n", BaseAddress);
1453  }
1454  }
1455 
1456  /* Move to the next page */
1457  BaseAddress = (PVOID)((ULONG_PTR)BaseAddress + PAGE_SIZE);
1458  PointerPte++;
1459  }
1460  }
1461  else
1462  {
1463  /* Move to the next address */
1464  BaseAddress = (PVOID)((ULONG_PTR)BaseAddress + PDE_MAPPED_VA);
1465  }
1466 
1467  /* Move to the next PDE */
1468  PointerPde++;
1469  }
1470 }
1471 
1472 VOID
1473 NTAPI
1475 {
1476  ULONG i;
1477  PMMPFN Pfn1;
1478  PCHAR Consumer = "Unknown";
1479  KIRQL OldIrql;
1480  ULONG ActivePages = 0, FreePages = 0, OtherPages = 0;
1481 #if MI_TRACE_PFNS
1482  ULONG UsageBucket[MI_USAGE_FREE_PAGE + 1] = {0};
1483  PCHAR MI_USAGE_TEXT[MI_USAGE_FREE_PAGE + 1] =
1484  {
1485  "Not set",
1486  "Paged Pool",
1487  "Nonpaged Pool",
1488  "Nonpaged Pool Ex",
1489  "Kernel Stack",
1490  "Kernel Stack Ex",
1491  "System PTE",
1492  "VAD",
1493  "PEB/TEB",
1494  "Section",
1495  "Page Table",
1496  "Page Directory",
1497  "Old Page Table",
1498  "Driver Page",
1499  "Contiguous Alloc",
1500  "MDL",
1501  "Demand Zero",
1502  "Zero Loop",
1503  "Cache",
1504  "PFN Database",
1505  "Boot Driver",
1506  "Initial Memory",
1507  "Free Page"
1508  };
1509 #endif
1510  //
1511  // Loop the PFN database
1512  //
1513  KeRaiseIrql(HIGH_LEVEL, &OldIrql);
1514  for (i = 0; i <= MmHighestPhysicalPage; i++)
1515  {
1516  Pfn1 = MiGetPfnEntry(i);
1517  if (!Pfn1) continue;
1518 #if MI_TRACE_PFNS
1519  ASSERT(Pfn1->PfnUsage <= MI_USAGE_FREE_PAGE);
1520 #endif
1521  //
1522  // Get the page location
1523  //
1524  switch (Pfn1->u3.e1.PageLocation)
1525  {
1526  case ActiveAndValid:
1527 
1528  Consumer = "Active and Valid";
1529  ActivePages++;
1530  break;
1531 
1532  case ZeroedPageList:
1533 
1534  Consumer = "Zero Page List";
1535  FreePages++;
1536  break;//continue;
1537 
1538  case FreePageList:
1539 
1540  Consumer = "Free Page List";
1541  FreePages++;
1542  break;//continue;
1543 
1544  default:
1545 
1546  Consumer = "Other (ASSERT!)";
1547  OtherPages++;
1548  break;
1549  }
1550 
1551 #if MI_TRACE_PFNS
1552  /* Add into bucket */
1553  UsageBucket[Pfn1->PfnUsage]++;
1554 #endif
1555 
1556  //
1557  // Pretty-print the page
1558  //
1559  if (!StatusOnly)
1560  DbgPrint("0x%08p:\t%20s\t(%04d.%04d)\t[%16s - %16s])\n",
1561  i << PAGE_SHIFT,
1562  Consumer,
1563  Pfn1->u3.e2.ReferenceCount,
1564  Pfn1->u2.ShareCount == LIST_HEAD ? 0xFFFF : Pfn1->u2.ShareCount,
1565 #if MI_TRACE_PFNS
1566  MI_USAGE_TEXT[Pfn1->PfnUsage],
1567  Pfn1->ProcessName);
1568 #else
1569  "Page tracking",
1570  "is disabled");
1571 #endif
1572  }
1573 
1574  DbgPrint("Active: %5d pages\t[%6d KB]\n", ActivePages, (ActivePages << PAGE_SHIFT) / 1024);
1575  DbgPrint("Free: %5d pages\t[%6d KB]\n", FreePages, (FreePages << PAGE_SHIFT) / 1024);
1576  DbgPrint("Other: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024);
1577  DbgPrint("-----------------------------------------\n");
1578 #if MI_TRACE_PFNS
1579  OtherPages = UsageBucket[MI_USAGE_BOOT_DRIVER];
1580  DbgPrint("Boot Images: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024);
1581  OtherPages = UsageBucket[MI_USAGE_DRIVER_PAGE];
1582  DbgPrint("System Drivers: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024);
1583  OtherPages = UsageBucket[MI_USAGE_PFN_DATABASE];
1584  DbgPrint("PFN Database: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024);
1585  OtherPages = UsageBucket[MI_USAGE_PAGE_TABLE] + UsageBucket[MI_USAGE_PAGE_DIRECTORY] + UsageBucket[MI_USAGE_LEGACY_PAGE_DIRECTORY];
1586  DbgPrint("Page Tables: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024);
1587  OtherPages = UsageBucket[MI_USAGE_SYSTEM_PTE];
1588  DbgPrint("System PTEs: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024);
1589  OtherPages = UsageBucket[MI_USAGE_VAD];
1590  DbgPrint("VADs: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024);
1591  OtherPages = UsageBucket[MI_USAGE_CONTINOUS_ALLOCATION];
1592  DbgPrint("Continuous Allocs: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024);
1593  OtherPages = UsageBucket[MI_USAGE_MDL];
1594  DbgPrint("MDLs: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024);
1595  OtherPages = UsageBucket[MI_USAGE_NONPAGED_POOL] + UsageBucket[MI_USAGE_NONPAGED_POOL_EXPANSION];
1596  DbgPrint("NonPaged Pool: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024);
1597  OtherPages = UsageBucket[MI_USAGE_PAGED_POOL];
1598  DbgPrint("Paged Pool: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024);
1599  OtherPages = UsageBucket[MI_USAGE_DEMAND_ZERO];
1600  DbgPrint("Demand Zero: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024);
1601  OtherPages = UsageBucket[MI_USAGE_ZERO_LOOP];
1602  DbgPrint("Zero Loop: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024);
1603  OtherPages = UsageBucket[MI_USAGE_PEB_TEB];
1604  DbgPrint("PEB/TEB: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024);
1605  OtherPages = UsageBucket[MI_USAGE_KERNEL_STACK] + UsageBucket[MI_USAGE_KERNEL_STACK_EXPANSION];
1606  DbgPrint("Kernel Stack: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024);
1607  OtherPages = UsageBucket[MI_USAGE_INIT_MEMORY];
1608  DbgPrint("Init Memory: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024);
1609  OtherPages = UsageBucket[MI_USAGE_SECTION];
1610  DbgPrint("Sections: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024);
1611  OtherPages = UsageBucket[MI_USAGE_CACHE];
1612  DbgPrint("Cache: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024);
1613  OtherPages = UsageBucket[MI_USAGE_FREE_PAGE];
1614  DbgPrint("Free: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024);
1615 #endif
1616  KeLowerIrql(OldIrql);
1617 }
1618 
1620 NTAPI
1623  IN PBOOLEAN IncludeType)
1624 {
1625  PLIST_ENTRY NextEntry;
1626  ULONG Run = 0, InitialRuns;
1627  PFN_NUMBER NextPage = -1, PageCount = 0;
1630 
1631  //
1632  // Start with the maximum we might need
1633  //
1634  InitialRuns = MiNumberDescriptors;
1635 
1636  //
1637  // Allocate the maximum we'll ever need
1638  //
1640  sizeof(PHYSICAL_MEMORY_DESCRIPTOR) +
1641  sizeof(PHYSICAL_MEMORY_RUN) *
1642  (InitialRuns - 1),
1643  'lMmM');
1644  if (!Buffer) return NULL;
1645 
1646  //
1647  // For now that's how many runs we have
1648  //
1649  Buffer->NumberOfRuns = InitialRuns;
1650 
1651  //
1652  // Now loop through the descriptors again
1653  //
1654  NextEntry = LoaderBlock->MemoryDescriptorListHead.Flink;
1655  while (NextEntry != &LoaderBlock->MemoryDescriptorListHead)
1656  {
1657  //
1658  // Grab each one, and check if it's one we should include
1659  //
1660  MdBlock = CONTAINING_RECORD(NextEntry,
1662  ListEntry);
1663  if ((MdBlock->MemoryType < LoaderMaximum) &&
1664  (IncludeType[MdBlock->MemoryType]))
1665  {
1666  //
1667  // Add this to our running total
1668  //
1669  PageCount += MdBlock->PageCount;
1670 
1671  //
1672  // Check if the next page is described by the next descriptor
1673  //
1674  if (MdBlock->BasePage == NextPage)
1675  {
1676  //
1677  // Combine it into the same physical run
1678  //
1679  ASSERT(MdBlock->PageCount != 0);
1680  Buffer->Run[Run - 1].PageCount += MdBlock->PageCount;
1681  NextPage += MdBlock->PageCount;
1682  }
1683  else
1684  {
1685  //
1686  // Otherwise just duplicate the descriptor's contents
1687  //
1688  Buffer->Run[Run].BasePage = MdBlock->BasePage;
1689  Buffer->Run[Run].PageCount = MdBlock->PageCount;
1690  NextPage = Buffer->Run[Run].BasePage + Buffer->Run[Run].PageCount;
1691 
1692  //
1693  // And in this case, increase the number of runs
1694  //
1695  Run++;
1696  }
1697  }
1698 
1699  //
1700  // Try the next descriptor
1701  //
1702  NextEntry = MdBlock->ListEntry.Flink;
1703  }
1704 
1705  //
1706  // We should not have been able to go past our initial estimate
1707  //
1708  ASSERT(Run <= Buffer->NumberOfRuns);
1709 
1710  //
1711  // Our guess was probably exaggerated...
1712  //
1713  if (InitialRuns > Run)
1714  {
1715  //
1716  // Allocate a more accurately sized buffer
1717  //
1718  NewBuffer = ExAllocatePoolWithTag(NonPagedPool,
1719  sizeof(PHYSICAL_MEMORY_DESCRIPTOR) +
1720  sizeof(PHYSICAL_MEMORY_RUN) *
1721  (Run - 1),
1722  'lMmM');
1723  if (NewBuffer)
1724  {
1725  //
1726  // Copy the old buffer into the new, then free it
1727  //
1728  RtlCopyMemory(NewBuffer->Run,
1729  Buffer->Run,
1730  sizeof(PHYSICAL_MEMORY_RUN) * Run);
1731  ExFreePoolWithTag(Buffer, 'lMmM');
1732 
1733  //
1734  // Now use the new buffer
1735  //
1736  Buffer = NewBuffer;
1737  }
1738  }
1739 
1740  //
1741  // Write the final numbers, and return it
1742  //
1743  Buffer->NumberOfRuns = Run;
1744  Buffer->NumberOfPages = PageCount;
1745  return Buffer;
1746 }
1747 
1748 VOID
1749 NTAPI
1752 {
1753  PMMPTE PointerPte;
1754  PMMPDE PointerPde;
1756  PFN_NUMBER PageFrameIndex;
1757  KIRQL OldIrql;
1758  SIZE_T Size;
1759  ULONG BitMapSize;
1760 #if (_MI_PAGING_LEVELS >= 3)
1761  MMPPE TempPpe = ValidKernelPpe;
1762  PMMPPE PointerPpe;
1763 #elif (_MI_PAGING_LEVELS == 2)
1765 
1766  //
1767  // Get the page frame number for the system page directory
1768  //
1769  PointerPte = MiAddressToPte(PDE_BASE);
1770  ASSERT(PD_COUNT == 1);
1771  MmSystemPageDirectory[0] = PFN_FROM_PTE(PointerPte);
1772 
1773  //
1774  // Allocate a system PTE which will hold a copy of the page directory
1775  //
1776  PointerPte = MiReserveSystemPtes(1, SystemPteSpace);
1777  ASSERT(PointerPte);
1778  MmSystemPagePtes = MiPteToAddress(PointerPte);
1779 
1780  //
1781  // Make this system PTE point to the system page directory.
1782  // It is now essentially double-mapped. This will be used later for lazy
1783  // evaluation of PDEs accross process switches, similarly to how the Global
1784  // page directory array in the old ReactOS Mm is used (but in a less hacky
1785  // way).
1786  //
1787  TempPte = ValidKernelPte;
1788  ASSERT(PD_COUNT == 1);
1790  MI_WRITE_VALID_PTE(PointerPte, TempPte);
1791 #endif
1792 
1793 #ifdef _M_IX86
1794  //
1795  // Let's get back to paged pool work: size it up.
1796  // By default, it should be twice as big as nonpaged pool.
1797  //
1801  {
1802  //
1803  // On the other hand, we have limited VA space, so make sure that the VA
1804  // for paged pool doesn't overflow into nonpaged pool VA. Otherwise, set
1805  // whatever maximum is possible.
1806  //
1809  }
1810 #endif // _M_IX86
1811 
1812  //
1813  // Get the size in pages and make sure paged pool is at least 32MB.
1814  //
1815  Size = MmSizeOfPagedPoolInBytes;
1817  Size = BYTES_TO_PAGES(Size);
1818 
1819  //
1820  // Now check how many PTEs will be required for these many pages.
1821  //
1822  Size = (Size + (1024 - 1)) / 1024;
1823 
1824  //
1825  // Recompute the page-aligned size of the paged pool, in bytes and pages.
1826  //
1827  MmSizeOfPagedPoolInBytes = Size * PAGE_SIZE * 1024;
1829 
1830 #ifdef _M_IX86
1831  //
1832  // Let's be really sure this doesn't overflow into nonpaged system VA
1833  //
1834  ASSERT((MmSizeOfPagedPoolInBytes + (ULONG_PTR)MmPagedPoolStart) <=
1836 #endif // _M_IX86
1837 
1838  //
1839  // This is where paged pool ends
1840  //
1841  MmPagedPoolEnd = (PVOID)(((ULONG_PTR)MmPagedPoolStart +
1843 
1844  //
1845  // Lock the PFN database
1846  //
1847  OldIrql = MiAcquirePfnLock();
1848 
1849 #if (_MI_PAGING_LEVELS >= 3)
1850  /* On these systems, there's no double-mapping, so instead, the PPEs
1851  * are setup to span the entire paged pool area, so there's no need for the
1852  * system PD */
1853  for (PointerPpe = MiAddressToPpe(MmPagedPoolStart);
1854  PointerPpe <= MiAddressToPpe(MmPagedPoolEnd);
1855  PointerPpe++)
1856  {
1857  /* Check if the PPE is already valid */
1858  if (!PointerPpe->u.Hard.Valid)
1859  {
1860  /* It is not, so map a fresh zeroed page */
1861  TempPpe.u.Hard.PageFrameNumber = MiRemoveZeroPage(0);
1862  MI_WRITE_VALID_PPE(PointerPpe, TempPpe);
1863  }
1864  }
1865 #endif
1866 
1867  //
1868  // So now get the PDE for paged pool and zero it out
1869  //
1870  PointerPde = MiAddressToPde(MmPagedPoolStart);
1871  RtlZeroMemory(PointerPde,
1872  (1 + MiAddressToPde(MmPagedPoolEnd) - PointerPde) * sizeof(MMPDE));
1873 
1874  //
1875  // Next, get the first and last PTE
1876  //
1877  PointerPte = MiAddressToPte(MmPagedPoolStart);
1880 
1881  /* Allocate a page and map the first paged pool PDE */
1883  MI_SET_PROCESS2("Kernel");
1884  PageFrameIndex = MiRemoveZeroPage(0);
1885  TempPde.u.Hard.PageFrameNumber = PageFrameIndex;
1886  MI_WRITE_VALID_PDE(PointerPde, TempPde);
1887 #if (_MI_PAGING_LEVELS >= 3)
1888  /* Use the PPE of MmPagedPoolStart that was setup above */
1889 // Bla = PFN_FROM_PTE(PpeAddress(MmPagedPool...));
1890 
1891  /* Initialize the PFN entry for it */
1892  MiInitializePfnForOtherProcess(PageFrameIndex,
1893  (PMMPTE)PointerPde,
1894  PFN_FROM_PTE(MiAddressToPpe(MmPagedPoolStart)));
1895 #else
1896  /* Do it this way */
1897 // Bla = MmSystemPageDirectory[(PointerPde - (PMMPTE)PDE_BASE) / PDE_COUNT]
1898 
1899  /* Initialize the PFN entry for it */
1900  MiInitializePfnForOtherProcess(PageFrameIndex,
1901  (PMMPTE)PointerPde,
1902  MmSystemPageDirectory[(PointerPde - (PMMPDE)PDE_BASE) / PDE_COUNT]);
1903 #endif
1904 
1905  //
1906  // Release the PFN database lock
1907  //
1908  MiReleasePfnLock(OldIrql);
1909 
1910  //
1911  // We only have one PDE mapped for now... at fault time, additional PDEs
1912  // will be allocated to handle paged pool growth. This is where they'll have
1913  // to start.
1914  //
1916 
1917  //
1918  // We keep track of each page via a bit, so check how big the bitmap will
1919  // have to be (make sure to align our page count such that it fits nicely
1920  // into a 4-byte aligned bitmap.
1921  //
1922  // We'll also allocate the bitmap header itself part of the same buffer.
1923  //
1924  Size = Size * 1024;
1926  BitMapSize = (ULONG)Size;
1927  Size = sizeof(RTL_BITMAP) + (((Size + 31) / 32) * sizeof(ULONG));
1928 
1929  //
1930  // Allocate the allocation bitmap, which tells us which regions have not yet
1931  // been mapped into memory
1932  //
1934  Size,
1935  TAG_MM);
1937 
1938  //
1939  // Initialize it such that at first, only the first page's worth of PTEs is
1940  // marked as allocated (incidentially, the first PDE we allocated earlier).
1941  //
1944  BitMapSize);
1947 
1948  //
1949  // We have a second bitmap, which keeps track of where allocations end.
1950  // Given the allocation bitmap and a base address, we can therefore figure
1951  // out which page is the last page of that allocation, and thus how big the
1952  // entire allocation is.
1953  //
1955  Size,
1956  TAG_MM);
1960  BitMapSize);
1961 
1962  //
1963  // Since no allocations have been made yet, there are no bits set as the end
1964  //
1966 
1967  //
1968  // Initialize paged pool.
1969  //
1971 
1972  /* Initialize special pool */
1974 
1975  /* Default low threshold of 30MB or one fifth of paged pool */
1976  MiLowPagedPoolThreshold = (30 * _1MB) >> PAGE_SHIFT;
1978 
1979  /* Default high threshold of 60MB or 25% */
1980  MiHighPagedPoolThreshold = (60 * _1MB) >> PAGE_SHIFT;
1983 
1984  /* Setup the global session space */
1986 }
1987 
1988 VOID
1989 NTAPI
1992 {
1993  PLIST_ENTRY NextEntry;
1995  PFN_NUMBER TotalPages = 0;
1996  PCHAR
1997  MemType[] =
1998  {
1999  "ExceptionBlock ",
2000  "SystemBlock ",
2001  "Free ",
2002  "Bad ",
2003  "LoadedProgram ",
2004  "FirmwareTemporary ",
2005  "FirmwarePermanent ",
2006  "OsloaderHeap ",
2007  "OsloaderStack ",
2008  "SystemCode ",
2009  "HalCode ",
2010  "BootDriver ",
2011  "ConsoleInDriver ",
2012  "ConsoleOutDriver ",
2013  "StartupDpcStack ",
2014  "StartupKernelStack",
2015  "StartupPanicStack ",
2016  "StartupPcrPage ",
2017  "StartupPdrPage ",
2018  "RegistryData ",
2019  "MemoryData ",
2020  "NlsData ",
2021  "SpecialMemory ",
2022  "BBTMemory ",
2023  "LoaderReserve ",
2024  "LoaderXIPRom "
2025  };
2026 
2027  DPRINT1("Base\t\tLength\t\tType\n");
2028  for (NextEntry = KeLoaderBlock->MemoryDescriptorListHead.Flink;
2029  NextEntry != &KeLoaderBlock->MemoryDescriptorListHead;
2030  NextEntry = NextEntry->Flink)
2031  {
2032  Md = CONTAINING_RECORD(NextEntry, MEMORY_ALLOCATION_DESCRIPTOR, ListEntry);
2033  DPRINT1("%08lX\t%08lX\t%s\n", Md->BasePage, Md->PageCount, MemType[Md->MemoryType]);
2034  TotalPages += Md->PageCount;
2035  }
2036 
2037  DPRINT1("Total: %08lX (%lu MB)\n", (ULONG)TotalPages, (ULONG)(TotalPages * PAGE_SIZE) / 1024 / 1024);
2038 }
2039 
2040 BOOLEAN
2041 NTAPI
2044  IN PLOADER_PARAMETER_BLOCK LoaderBlock)
2045 {
2046  ULONG i;
2047  BOOLEAN IncludeType[LoaderMaximum];
2048  PVOID Bitmap;
2050  PFN_NUMBER PageCount;
2051 #if DBG
2052  ULONG j;
2053  PMMPTE PointerPte, TestPte;
2054  MMPTE TempPte;
2055 #endif
2056 
2057  /* Dump memory descriptors */
2059 
2060  //
2061  // Instantiate memory that we don't consider RAM/usable
2062  // We use the same exclusions that Windows does, in order to try to be
2063  // compatible with WinLDR-style booting
2064  //
2065  for (i = 0; i < LoaderMaximum; i++) IncludeType[i] = TRUE;
2066  IncludeType[LoaderBad] = FALSE;
2067  IncludeType[LoaderFirmwarePermanent] = FALSE;
2068  IncludeType[LoaderSpecialMemory] = FALSE;
2069  IncludeType[LoaderBBTMemory] = FALSE;
2070  if (Phase == 0)
2071  {
2072  /* Count physical pages on the system */
2073  MiScanMemoryDescriptors(LoaderBlock);
2074 
2075  /* Initialize the phase 0 temporary event */
2076  KeInitializeEvent(&MiTempEvent, NotificationEvent, FALSE);
2077 
2078  /* Set all the events to use the temporary event for now */
2079  MiLowMemoryEvent = &MiTempEvent;
2080  MiHighMemoryEvent = &MiTempEvent;
2081  MiLowPagedPoolEvent = &MiTempEvent;
2082  MiHighPagedPoolEvent = &MiTempEvent;
2083  MiLowNonPagedPoolEvent = &MiTempEvent;
2084  MiHighNonPagedPoolEvent = &MiTempEvent;
2085 
2086  //
2087  // Default throttling limits for Cc
2088  // May be ajusted later on depending on system type
2089  //
2090  MmThrottleTop = 450;
2091  MmThrottleBottom = 127;
2092 
2093  //
2094  // Define the basic user vs. kernel address space separation
2095  //
2099 
2100  /* Highest PTE and PDE based on the addresses above */
2101  MiHighestUserPte = MiAddressToPte(MmHighestUserAddress);
2102  MiHighestUserPde = MiAddressToPde(MmHighestUserAddress);
2103 #if (_MI_PAGING_LEVELS >= 3)
2104  MiHighestUserPpe = MiAddressToPpe(MmHighestUserAddress);
2105 #if (_MI_PAGING_LEVELS >= 4)
2106  MiHighestUserPxe = MiAddressToPxe(MmHighestUserAddress);
2107 #endif
2108 #endif
2109  //
2110  // Get the size of the boot loader's image allocations and then round
2111  // that region up to a PDE size, so that any PDEs we might create for
2112  // whatever follows are separate from the PDEs that boot loader might've
2113  // already created (and later, we can blow all that away if we want to).
2114  //
2119 
2120  /* Initialize session space address layout */
2122 
2123  /* Set the based section highest address */
2125 
2126 #if DBG
2127  /* The subection PTE format depends on things being 8-byte aligned */
2128  ASSERT((sizeof(CONTROL_AREA) % 8) == 0);
2129  ASSERT((sizeof(SUBSECTION) % 8) == 0);
2130 
2131  /* Prototype PTEs are assumed to be in paged pool, so check if the math works */
2132  PointerPte = (PMMPTE)MmPagedPoolStart;
2133  MI_MAKE_PROTOTYPE_PTE(&TempPte, PointerPte);
2134  TestPte = MiProtoPteToPte(&TempPte);
2135  ASSERT(PointerPte == TestPte);
2136 
2137  /* Try the last nonpaged pool address */
2138  PointerPte = (PMMPTE)MI_NONPAGED_POOL_END;
2139  MI_MAKE_PROTOTYPE_PTE(&TempPte, PointerPte);
2140  TestPte = MiProtoPteToPte(&TempPte);
2141  ASSERT(PointerPte == TestPte);
2142 
2143  /* Try a bunch of random addresses near the end of the address space */
2144  PointerPte = (PMMPTE)((ULONG_PTR)MI_HIGHEST_SYSTEM_ADDRESS - 0x37FFF);
2145  for (j = 0; j < 20; j += 1)
2146  {
2147  MI_MAKE_PROTOTYPE_PTE(&TempPte, PointerPte);
2148  TestPte = MiProtoPteToPte(&TempPte);
2149  ASSERT(PointerPte == TestPte);
2150  PointerPte++;
2151  }
2152 
2153  /* Subsection PTEs are always in nonpaged pool, pick a random address to try */
2155  MI_MAKE_SUBSECTION_PTE(&TempPte, PointerPte);
2156  TestPte = MiSubsectionPteToSubsection(&TempPte);
2157  ASSERT(PointerPte == TestPte);
2158 #endif
2159 
2160  /* Loop all 8 standby lists */
2161  for (i = 0; i < 8; i++)
2162  {
2163  /* Initialize them */
2168  }
2169 
2170  /* Initialize the user mode image list */
2172 
2173  /* Initialize critical section timeout value (relative time is negative) */
2174  MmCriticalSectionTimeout.QuadPart = MmCritsectTimeoutSeconds * (-10000000LL);
2175 
2176  /* Initialize the paged pool mutex and the section commit mutex */
2180 
2181  /* Initialize the Loader Lock */
2183 
2184  /* Set the zero page event */
2187 
2188  /* Initialize the dead stack S-LIST */
2190 
2191  //
2192  // Check if this is a machine with less than 19MB of RAM
2193  //
2194  PageCount = MmNumberOfPhysicalPages;
2195  if (PageCount < MI_MIN_PAGES_FOR_SYSPTE_TUNING)
2196  {
2197  //
2198  // Use the very minimum of system PTEs
2199  //
2200  MmNumberOfSystemPtes = 7000;
2201  }
2202  else
2203  {
2204  //
2205  // Use the default
2206  //
2207  MmNumberOfSystemPtes = 11000;
2208  if (PageCount > MI_MIN_PAGES_FOR_SYSPTE_BOOST)
2209  {
2210  //
2211  // Double the amount of system PTEs
2212  //
2213  MmNumberOfSystemPtes <<= 1;
2214  }
2215  if (PageCount > MI_MIN_PAGES_FOR_SYSPTE_BOOST_BOOST)
2216  {
2217  //
2218  // Double the amount of system PTEs
2219  //
2220  MmNumberOfSystemPtes <<= 1;
2221  }
2222  if (MmSpecialPoolTag != 0 && MmSpecialPoolTag != -1)
2223  {
2224  //
2225  // Add some extra PTEs for special pool
2226  //
2227  MmNumberOfSystemPtes += 0x6000;
2228  }
2229  }
2230 
2231  DPRINT("System PTE count has been tuned to %lu (%lu bytes)\n",
2233 
2234  /* Check if no values are set for the heap limits */
2235  if (MmHeapSegmentReserve == 0)
2236  {
2237  MmHeapSegmentReserve = 2 * _1MB;
2238  }
2239 
2240  if (MmHeapSegmentCommit == 0)
2241  {
2243  }
2244 
2246  {
2248  }
2249 
2251  {
2253  }
2254 
2255  /* Initialize the working set lock */
2256  ExInitializePushLock(&MmSystemCacheWs.WorkingSetMutex);
2257 
2258  /* Set commit limit */
2259  MmTotalCommitLimit = 2 * _1GB;
2261 
2262  /* Has the allocation fragment been setup? */
2263  if (!MmAllocationFragment)
2264  {
2265  /* Use the default value */
2267  if (PageCount < ((256 * _1MB) / PAGE_SIZE))
2268  {
2269  /* On memory systems with less than 256MB, divide by 4 */
2271  }
2272  else if (PageCount < (_1GB / PAGE_SIZE))
2273  {
2274  /* On systems with less than 1GB, divide by 2 */
2276  }
2277  }
2278  else
2279  {
2280  /* Convert from 1KB fragments to pages */
2283 
2284  /* Don't let it past the maximum */
2287 
2288  /* Don't let it too small either */
2291  }
2292 
2293  /* Check for kernel stack size that's too big */
2295  {
2296  /* Sanitize to default value */
2298  }
2299  else
2300  {
2301  /* Take the registry setting, and convert it into bytes */
2303 
2304  /* Now align it to a page boundary */
2306 
2307  /* Sanity checks */
2309  ASSERT((MmLargeStackSize & (PAGE_SIZE - 1)) == 0);
2310 
2311  /* Make sure it's not too low */
2313  }
2314 
2315  /* Compute color information (L2 cache-separated paging lists) */
2317 
2318  // Calculate the number of bytes for the PFN database
2319  // then add the color tables and convert to pages
2320  MxPfnAllocation = (MmHighestPhysicalPage + 1) * sizeof(MMPFN);
2323 
2324  // We have to add one to the count here, because in the process of
2325  // shifting down to the page size, we actually ended up getting the
2326  // lower aligned size (so say, 0x5FFFF bytes is now 0x5F pages).
2327  // Later on, we'll shift this number back into bytes, which would cause
2328  // us to end up with only 0x5F000 bytes -- when we actually want to have
2329  // 0x60000 bytes.
2330  MxPfnAllocation++;
2331 
2332  /* Initialize the platform-specific parts */
2333  MiInitMachineDependent(LoaderBlock);
2334 
2335  //
2336  // Build the physical memory block
2337  //
2338  MmPhysicalMemoryBlock = MmInitializeMemoryLimits(LoaderBlock,
2339  IncludeType);
2340 
2341  //
2342  // Allocate enough buffer for the PFN bitmap
2343  // Align it up to a 32-bit boundary
2344  //
2346  (((MmHighestPhysicalPage + 1) + 31) / 32) * 4,
2347  TAG_MM);
2348  if (!Bitmap)
2349  {
2350  //
2351  // This is critical
2352  //
2353  KeBugCheckEx(INSTALL_MORE_MEMORY,
2357  0x101);
2358  }
2359 
2360  //
2361  // Initialize it and clear all the bits to begin with
2362  //
2363  RtlInitializeBitMap(&MiPfnBitMap,
2364  Bitmap,
2366  RtlClearAllBits(&MiPfnBitMap);
2367 
2368  //
2369  // Loop physical memory runs
2370  //
2371  for (i = 0; i < MmPhysicalMemoryBlock->NumberOfRuns; i++)
2372  {
2373  //
2374  // Get the run
2375  //
2376  Run = &MmPhysicalMemoryBlock->Run[i];
2377  DPRINT("PHYSICAL RAM [0x%08p to 0x%08p]\n",
2378  Run->BasePage << PAGE_SHIFT,
2379  (Run->BasePage + Run->PageCount) << PAGE_SHIFT);
2380 
2381  //
2382  // Make sure it has pages inside it
2383  //
2384  if (Run->PageCount)
2385  {
2386  //
2387  // Set the bits in the PFN bitmap
2388  //
2389  RtlSetBits(&MiPfnBitMap, (ULONG)Run->BasePage, (ULONG)Run->PageCount);
2390  }
2391  }
2392 
2393  /* Look for large page cache entries that need caching */
2395 
2396  /* Loop for HAL Heap I/O device mappings that need coherency tracking */
2398 
2399  /* Set the initial resident page count */
2401 
2402  /* Initialize large page structures on PAE/x64, and MmProcessList on x86 */
2404 
2405  /* Check if the registry says any drivers should be loaded with large pages */
2407 
2408  /* Relocate the boot drivers into system PTE space and fixup their PFNs */
2409  MiReloadBootLoadedDrivers(LoaderBlock);
2410 
2411  /* FIXME: Call out into Driver Verifier for initialization */
2412 
2413  /* Check how many pages the system has */
2414  if (MmNumberOfPhysicalPages <= ((13 * _1MB) / PAGE_SIZE))
2415  {
2416  /* Set small system */
2419  }
2420  else if (MmNumberOfPhysicalPages <= ((19 * _1MB) / PAGE_SIZE))
2421  {
2422  /* Set small system and add 100 pages for the cache */
2424  MmSystemCacheWsMinimum += 100;
2426  }
2427  else
2428  {
2429  /* Set medium system and add 400 pages for the cache */
2431  MmSystemCacheWsMinimum += 400;
2433  }
2434 
2435  /* Check for less than 24MB */
2436  if (MmNumberOfPhysicalPages < ((24 * _1MB) / PAGE_SIZE))
2437  {
2438  /* No more than 32 pages */
2440  }
2441 
2442  /* Check for more than 32MB */
2443  if (MmNumberOfPhysicalPages >= ((32 * _1MB) / PAGE_SIZE))
2444  {
2445  /* Check for product type being "Wi" for WinNT */
2446  if (MmProductType == '\0i\0W')
2447  {
2448  /* Then this is a large system */
2450  }
2451  else
2452  {
2453  /* For servers, we need 64MB to consider this as being large */
2454  if (MmNumberOfPhysicalPages >= ((64 * _1MB) / PAGE_SIZE))
2455  {
2456  /* Set it as large */
2458  }
2459  }
2460  }
2461 
2462  /* Check for more than 33 MB */
2463  if (MmNumberOfPhysicalPages > ((33 * _1MB) / PAGE_SIZE))
2464  {
2465  /* Add another 500 pages to the cache */
2466  MmSystemCacheWsMinimum += 500;
2467  }
2468 
2469  /* Now setup the shared user data fields */
2470  ASSERT(SharedUserData->NumberOfPhysicalPages == 0);
2471  SharedUserData->NumberOfPhysicalPages = MmNumberOfPhysicalPages;
2472  SharedUserData->LargePageMinimum = 0;
2473 
2474  /* Check for workstation (Wi for WinNT) */
2475  if (MmProductType == '\0i\0W')
2476  {
2477  /* Set Windows NT Workstation product type */
2478  SharedUserData->NtProductType = NtProductWinNt;
2479  MmProductType = 0;
2480 
2481  /* For this product, we wait till the last moment to throttle */
2482  MmThrottleTop = 250;
2483  MmThrottleBottom = 30;
2484  }
2485  else
2486  {
2487  /* Check for LanMan server (La for LanmanNT) */
2488  if (MmProductType == '\0a\0L')
2489  {
2490  /* This is a domain controller */
2491  SharedUserData->NtProductType = NtProductLanManNt;
2492  }
2493  else
2494  {
2495  /* Otherwise it must be a normal server (Se for ServerNT) */
2496  SharedUserData->NtProductType = NtProductServer;
2497  }
2498 
2499  /* Set the product type, and make the system more aggressive with low memory */
2500  MmProductType = 1;
2501  MmMinimumFreePages = 81;
2502 
2503  /* We will throttle earlier to preserve memory */
2504  MmThrottleTop = 450;
2505  MmThrottleBottom = 80;
2506  }
2507 
2508  /* Update working set tuning parameters */
2510 
2511  /* Finetune the page count by removing working set and NP expansion */
2515  if (MmResidentAvailablePages <= 0)
2516  {
2517  /* This should not happen */
2518  DPRINT1("System cache working set too big\n");
2519  return FALSE;
2520  }
2521 
2522  /* Define limits for system cache */
2523 #ifdef _M_AMD64
2525 #else
2527 #endif
2529 
2530  /* Initialize the system cache */
2531  //MiInitializeSystemCache(MmSystemCacheWsMinimum, MmAvailablePages);
2532 
2533  /* Update the commit limit */
2535  if (MmTotalCommitLimit > 1024) MmTotalCommitLimit -= 1024;
2537 
2538  /* Size up paged pool and build the shadow system page directory */
2539  MiBuildPagedPool();
2540 
2541  /* Debugger physical memory support is now ready to be used */
2543 
2544  /* Initialize the loaded module list */
2545  MiInitializeLoadedModuleList(LoaderBlock);
2546  }
2547 
2548  //
2549  // Always return success for now
2550  //
2551  return TRUE;
2552 }
2553 
2554 /* EOF */
DWORD *typedef PVOID
Definition: winlogon.h:60
PVOID MmPagedPoolEnd
Definition: mminit.c:105
signed char * PCHAR
Definition: retypes.h:7
MMSUPPORT MmSystemCacheWs
Definition: mminit.c:246
PFN_NUMBER MmResidentAvailableAtInit
Definition: freelist.c:28
PRTL_BITMAP PagedPoolAllocationMap
Definition: mm.h:412
PMMPTE MiSessionLastPte
Definition: mminit.c:146
VOID NTAPI INIT_FUNCTION MiMapPfnDatabase(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
Definition: mminit.c:672
ULONG MmMaximumNonPagedPoolPercent
Definition: mminit.c:25
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:35
SIZE_T MmSessionImageSize
Definition: mminit.c:138
Definition: bidi.c:477
PFN_NUMBER MmResidentAvailablePages
Definition: freelist.c:27
#define PAGE_SHIFT
Definition: env_spec_w32.h:45
#define IN
Definition: typedefs.h:38
NTSYSAPI void WINAPI RtlClearBits(PRTL_BITMAP, ULONG, ULONG)
#define max(a, b)
Definition: svc.c:63
GLenum GLclampf GLint GLenum GLuint GLenum GLenum GLsizei GLenum const GLvoid GLfloat GLfloat GLfloat GLfloat GLclampd GLint GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean GLboolean GLboolean GLboolean GLint GLenum GLsizei const GLvoid GLenum GLint GLenum GLint GLint GLsizei GLint GLenum GLint GLint GLint GLint GLsizei GLenum GLsizei const GLuint GLboolean GLenum GLenum GLint GLsizei GLenum GLsizei GLenum const GLvoid GLboolean const GLboolean GLenum const GLdouble const GLfloat const GLdouble const GLfloat GLenum GLint GLint GLint GLint GLint GLint j
Definition: glfuncs.h:98
#define KeRaiseIrql(irql, oldIrql)
Definition: env_spec_w32.h:597
#define MM_HAL_VA_START
Definition: ketypes.h:256
SIZE_T MmHeapDeCommitTotalFreeThreshold
Definition: mminit.c:368
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
Definition: client.c:29
VOID NTAPI INIT_FUNCTION MiSyncCachedRanges(VOID)
Definition: largepag.c:54
MMPFNLIST MmStandbyPageListByPriority[8]
Definition: pfnlist.c:44
#define MI_MIN_PAGES_FOR_SYSPTE_BOOST
Definition: mm.h:52
#define LL
Definition: tui.h:72
#define MI_DEFAULT_SYSTEM_RANGE_START
Definition: mm.h:10
VOID NTAPI INIT_FUNCTION MiBuildPfnDatabaseZeroPage(VOID)
Definition: mminit.c:877
NTSYSAPI void WINAPI RtlInitializeBitMap(PRTL_BITMAP, PULONG, ULONG)
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
PVOID Blink
Definition: miarm.h:411
#define KeLowerIrql(oldIrql)
Definition: env_spec_w32.h:602
NTSTATUS NTAPI INIT_FUNCTION MiInitMachineDependent(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
Definition: init.c:672
struct _RTL_BITMAP RTL_BITMAP
#define MI_MIN_PAGES_FOR_SYSPTE_BOOST_BOOST
Definition: mm.h:53
VOID NTAPI MiInsertPageInFreeList(IN PFN_NUMBER PageFrameIndex)
Definition: pfnlist.c:604
ULONG MmMinAdditionNonPagedPoolPerMb
Definition: mminit.c:40
#define MI_MAX_ALLOCATION_FRAGMENT
Definition: mm.h:68
#define MiAddressToPde(x)
Definition: mmx86.c:20
struct _Entry Entry
Definition: kefuncs.h:640
#define MI_NONPAGED_POOL_END
Definition: mm.h:28
PMMPTE MiSessionImagePteStart
Definition: mminit.c:143
KGUARDED_MUTEX MmSectionBasedMutex
Definition: section.c:110
#define DbgPrint
Definition: loader.c:25
#define MM_HAL_VA_END
Definition: ketypes.h:257
PVOID MmSessionBase
Definition: mminit.c:134
ULONG PFN_COUNT
Definition: mmtypes.h:102
PFN_NUMBER MiLowNonPagedPoolThreshold
Definition: mminit.c:304
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
_In_ USHORT _In_ ULONG _In_ PSOCKADDR _In_ PSOCKADDR _Reserved_ ULONG _In_opt_ PVOID _In_opt_ const WSK_CLIENT_CONNECTION_DISPATCH _In_opt_ PEPROCESS _In_opt_ PETHREAD _In_opt_ PSECURITY_DESCRIPTOR SecurityDescriptor
Definition: wsk.h:182
PMMPTE NTAPI MiReserveSystemPtes(IN ULONG NumberOfPtes, IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType)
Definition: syspte.c:246
struct _MMCOLOR_TABLES MMCOLOR_TABLES
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
BOOLEAN NTAPI MiInitializeLoadedModuleList(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
Definition: sysldr.c:2188
PLOADER_PARAMETER_EXTENSION Extension
Definition: arc.h:512
VOID NTAPI KeInitializeMutant(IN PKMUTANT Mutant, IN BOOLEAN InitialOwner)
Definition: mutex.c:22
MMLISTS ListName
Definition: mm.h:370
PFN_COUNT MmNumberOfPhysicalPages
Definition: mminit.c:212
union _MMPFN::@1663 u2
SIZE_T MmMinimumNonPagedPoolSize
Definition: mminit.c:39
BOOLEAN MiDbgEnableMdDump
Definition: mminit.c:373
PFN_NUMBER PageCount
Definition: miarm.h:398
SIZE_T MmSessionViewSize
Definition: mminit.c:136
FORCEINLINE struct _KPRCB * KeGetCurrentPrcb(VOID)
Definition: ketypes.h:1062
PFN_NUMBER Flink
Definition: mm.h:307
ULONG MmCritsectTimeoutSeconds
Definition: mminit.c:387
VOID NTAPI INIT_FUNCTION MmFreeLoaderBlock(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
Definition: mminit.c:1093
#define MI_MAX_SECONDARY_COLORS
Definition: mm.h:74
#define EVENT_QUERY_STATE
Definition: security.c:53
HARDWARE_PDE_ARMV6 TempPde
Definition: winldr.c:77
PKEVENT MiLowPagedPoolEvent
Definition: mminit.c:294
FORCEINLINE KIRQL MiAcquirePfnLock(VOID)
Definition: mm.h:875
SIZE_T MmTotalCommitLimitMaximum
Definition: mminit.c:360
union _MMPFN::@1662 u1
ULONG MmLargeStackSize
Definition: mminit.c:262
VOID NTAPI MiScanMemoryDescriptors(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
Definition: mminit.c:403
VOID NTAPI INIT_FUNCTION MiInitializeColorTables(VOID)
Definition: mminit.c:562
_Inout_ __drv_aliasesMem PSLIST_ENTRY _Inout_ PSLIST_ENTRY _In_ ULONG Count
Definition: exfuncs.h:1015
union _MMPFN::@1664 u3
#define OBJ_PERMANENT
Definition: winternl.h:226
#define _1KB
Definition: miarm.h:14
#define KERNEL_LARGE_STACK_SIZE
paddr_t NextPage
Definition: mmuobject.c:64
VOID NTAPI MiInitializePfnForOtherProcess(IN PFN_NUMBER PageFrameIndex, IN PVOID PteAddress, IN PFN_NUMBER PteFrame)
Definition: pfnlist.c:1280
PFN_NUMBER NumberOfPages
Definition: miarm.h:404
#define PD_COUNT
Definition: miarm.h:31
PMMPTE FORCEINLINE MiAddressToPpe(PVOID Address)
Definition: mm.h:150
PFN_NUMBER MmSizeOfPagedPoolInPages
Definition: mminit.c:111
NTSYSAPI NTSTATUS NTAPI RtlCreateSecurityDescriptor(_Out_ PSECURITY_DESCRIPTOR SecurityDescriptor, _In_ ULONG Revision)
PFN_COUNT MiExpansionPoolPagesInitialCharge
Definition: pool.c:21
PHYSICAL_MEMORY_RUN Run[1]
Definition: miarm.h:405
PFN_NUMBER NTAPI INIT_FUNCTION MxGetNextPage(IN PFN_NUMBER PageCount)
Definition: mminit.c:483
VOID NTAPI INIT_FUNCTION MiBuildPfnDatabaseSelf(VOID)
Definition: mminit.c:1044
PFN_NUMBER MmAvailablePages
Definition: freelist.c:26
KMUTANT MmSystemLoadLock
Definition: sysldr.c:39
PFN_NUMBER MiHighNonPagedPoolThreshold
Definition: mminit.c:305
LONG NTAPI KeSetEvent(IN PKEVENT Event, IN KPRIORITY Increment, IN BOOLEAN Wait)
Definition: eventobj.c:159
#define MI_WRITE_VALID_PPE
Definition: mm.h:122
PFN_NUMBER MmSystemCacheWsMinimum
Definition: mminit.c:336
SIZE_T MmSizeOfNonPagedPoolInBytes
Definition: mminit.c:26
struct _MMPFN::@1664::@1670 e2
ULONG MmSizeOfSystemCacheInPages
Definition: mminit.c:245
VOID NTAPI INIT_FUNCTION MiBuildPfnDatabaseFromLoaderBlock(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
Definition: mminit.c:900
#define PAGE_ROUND_UP(x)
Definition: scsiport_int.h:13
NTSYSAPI NTSTATUS WINAPI RtlAddAccessAllowedAce(PACL, DWORD, DWORD, PSID)
FORCEINLINE VOID MiReleasePfnLock(_In_ KIRQL OldIrql)
Definition: mm.h:882
POBJECT_TYPE ExEventObjectType
Definition: event.c:22
#define KeGetPcr()
Definition: ke.h:25
USHORT PageLocation
Definition: mm.h:295
PMMPFN MmPfnDatabase
Definition: freelist.c:24
PFN_NUMBER Flink
Definition: mm.h:371
PKEVENT MiHighPagedPoolEvent
Definition: mminit.c:295
VOID NTAPI INIT_FUNCTION MiInitializeLargePageSupport(VOID)
Definition: largepag.c:34
NTSYSAPI NTSTATUS NTAPI RtlCreateAcl(PACL Acl, ULONG AclSize, ULONG AclRevision)
PFN_NUMBER NTAPI MiRemoveZeroPage(IN ULONG Color)
Definition: pfnlist.c:531
uint32_t ULONG_PTR
Definition: typedefs.h:63
PFN_NUMBER MxPfnAllocation
Definition: mminit.c:187
ULONG MiNumberDescriptors
Definition: mminit.c:381
USHORT PrototypePte
Definition: mm.h:293
#define SECURITY_DESCRIPTOR_REVISION
Definition: setypes.h:58
PVOID MiSessionImageStart
Definition: mminit.c:129
#define MI_USER_PROBE_ADDRESS
Definition: mm.h:9
PFN_NUMBER MmLowestPhysicalPage
Definition: mminit.c:211
PFN_NUMBER MmPlentyFreePages
Definition: mminit.c:322
enum _MM_SYSTEM_SIZE MM_SYSTEMSIZE
UCHAR KIRQL
Definition: env_spec_w32.h:591
MMPFNENTRY e1
Definition: mm.h:327
TYPE_OF_MEMORY MemoryType
Definition: arc.h:193
PMMPTE MiSessionBasePte
Definition: mminit.c:145
#define PDE_COUNT
Definition: miarm.h:32
GLenum GLclampf GLint i
Definition: glfuncs.h:14
USHORT CacheAttribute
Definition: mm.h:297
#define MiAddressToPte(x)
Definition: mmx86.c:19
ULONG MmSpecialPoolTag
Definition: pool.c:27
NTSTATUS NTAPI ObReferenceObjectByHandle(IN HANDLE Handle, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, OUT PVOID *Object, OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL)
Definition: obref.c:496
BOOLEAN MmZeroingPageThreadActive
Definition: zeropage.c:20
ULONG PFN_NUMBER
Definition: ke.h:8
#define MI_SECONDARY_COLORS
Definition: mm.h:73
#define TAG_MM
Definition: tag.h:136
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
#define ValidKernelPpe
Definition: mm.h:123
VOID NTAPI INIT_FUNCTION MiInitializePfnDatabase(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
Definition: mminit.c:1074
PMMPTE LastPteForPagedPool
Definition: mm.h:415
PFN_NUMBER MiNumberOfFreePages
Definition: mminit.c:384
#define FALSE
Definition: types.h:117
FORCEINLINE VOID MI_WRITE_VALID_PTE(IN PMMPTE PointerPte, IN MMPTE TempPte)
Definition: miarm.h:916
ULONG_PTR ShareCount
Definition: mm.h:320
PVOID MiSessionSpaceEnd
Definition: mminit.c:127
PFN_NUMBER BasePage
Definition: miarm.h:397
#define KSEG0_BASE
Definition: ketypes.h:273
#define PDE_BASE
Definition: winldr.c:20
Definition: arc.h:130
#define EVENT_ALL_ACCESS
Definition: isotest.c:82
PFN_NUMBER Blink
Definition: mm.h:372
struct _MMCOLOR_TABLES * PMMCOLOR_TABLES
PVOID MiSystemViewStart
Definition: mminit.c:154
PFN_NUMBER Flink
Definition: miarm.h:410
#define MI_SET_PROCESS2(x)
Definition: mm.h:252
SIZE_T MmDefaultMaximumNonPagedPool
Definition: mminit.c:41
VOID NTAPI INIT_FUNCTION MiInitializeSessionSpaceLayout(VOID)
Definition: init.c:65
PVOID MmHighestUserAddress
Definition: mminit.c:229
SIZE_T MmBootImageSize
Definition: mminit.c:222
MM_PAGED_POOL_INFO MmPagedPoolInfo
Definition: pool.c:25
#define MI_SYSTEM_CACHE_WS_START
Definition: mm.h:16
struct _ACL ACL
smooth NULL
Definition: ftsmooth.c:416
PVOID FORCEINLINE MiPteToAddress(PMMPTE PointerPte)
Definition: mm.h:197
NTSYSAPI NTSTATUS WINAPI RtlSetDaclSecurityDescriptor(PSECURITY_DESCRIPTOR, BOOLEAN, PACL, BOOLEAN)
#define MiProtoPteToPte(x)
Definition: mm.h:246
PVOID MmSystemRangeStart
Definition: mminit.c:230
struct tagRun Run
KEVENT MmZeroingPageEvent
Definition: zeropage.c:21
void DPRINT(...)
Definition: polytest.cpp:61
#define ExInitializePushLock
Definition: ex.h:957
VOID NTAPI MiDecrementShareCount(IN PMMPFN Pfn1, IN PFN_NUMBER PageFrameIndex)
Definition: pfnlist.c:1133
FORCEINLINE VOID MI_MAKE_SUBSECTION_PTE(_Out_ PMMPTE NewPte, _In_ PVOID Segment)
Definition: mm.h:257
NTSYSAPI ULONG NTAPI RtlLengthSid(IN PSID Sid)
Definition: sid.c:150
FORCEINLINE VOID MI_WRITE_VALID_PDE(IN PMMPDE PointerPde, IN MMPDE TempPde)
Definition: miarm.h:971
#define MI_SET_USAGE(x)
Definition: mm.h:251
BOOLEAN NTAPI INIT_FUNCTION MiIsRegularMemory(IN PLOADER_PARAMETER_BLOCK LoaderBlock, IN PFN_NUMBER Pfn)
Definition: mminit.c:613
PPHYSICAL_MEMORY_DESCRIPTOR NTAPI INIT_FUNCTION MmInitializeMemoryLimits(IN PLOADER_PARAMETER_BLOCK LoaderBlock, IN PBOOLEAN IncludeType)
Definition: mminit.c:1622
PPHYSICAL_MEMORY_DESCRIPTOR MmPhysicalMemoryBlock
Definition: mminit.c:206
VOID NTAPI INIT_FUNCTION MiBuildPfnDatabaseFromPages(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
Definition: mminit.c:768
PLOADER_PARAMETER_BLOCK KeLoaderBlock
Definition: krnlinit.c:29
ULONG_PTR LoaderPagesSpanned
Definition: arc.h:356
VOID NTAPI INIT_FUNCTION MiBuildPagedPool(VOID)
Definition: mminit.c:1751
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 MM_EMPTY_LIST
Definition: mm.h:84
SIZE_T MmSessionSize
Definition: mminit.c:135
UINTN Size
Definition: acefiex.h:555
PMMPTE MiHighestUserPte
Definition: mminit.c:233
PMMPDE MmSystemPagePtes
Definition: init.c:41
SIZE_T MmMaximumNonPagedPoolInBytes
Definition: mminit.c:27
SIZE_T MmTotalCommitLimit
Definition: mminit.c:359
PMMPTE MmDebugPte
Definition: mmdbg.c:33
NTSYSAPI void WINAPI RtlClearAllBits(PRTL_BITMAP)
VOID NTAPI INIT_FUNCTION MiAdjustWorkingSetManagerParameters(IN BOOLEAN Client)
Definition: mminit.c:1203
PFN_NUMBER MmLowMemoryThreshold
Definition: mminit.c:300
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
#define PDE_MAPPED_VA
Definition: miarm.h:22
BOOLEAN NTAPI INIT_FUNCTION MmArmInitSystem(IN ULONG Phase, IN PLOADER_PARAMETER_BLOCK LoaderBlock)
Definition: mminit.c:2043
unsigned char BOOLEAN
ULONG_PTR MmUserProbeAddress
Definition: mminit.c:228
EX_PUSH_LOCK WorkingSetMutex
Definition: mmtypes.h:935
PFN_COUNT MmNumberOfSystemPtes
Definition: mminit.c:181
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID * BaseAddress
Definition: mmfuncs.h:404
VOID NTAPI MiInitializeSpecialPool(VOID)
Definition: special.c:123
LONG NTSTATUS
Definition: precomp.h:26
PVOID MmSystemCacheEnd
Definition: mminit.c:244
VOID NTAPI INIT_SECTION InitializePool(IN POOL_TYPE PoolType, IN ULONG Threshold)
Definition: expool.c:1015
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:24
SIZE_T MmHeapDeCommitFreeBlockThreshold
Definition: mminit.c:369
#define MI_HIGHEST_USER_ADDRESS
Definition: mmtypes.h:43
BOOLEAN NTAPI MiInitializeSystemSpaceMap(IN PMMSESSION InputSession OPTIONAL)
Definition: section.c:240
PVOID MiDebugMapping
Definition: mmdbg.c:32
PVOID MiSessionSpaceWs
Definition: mminit.c:130
ULONG64 Valid
Definition: mmtypes.h:150
struct _MMPTE * PMMPTE
PMMPDE MiHighestUserPde
Definition: mminit.c:234
PFN_NUMBER MiHighPagedPoolThreshold
Definition: mminit.c:303
PFN_NUMBER MmHighestPhysicalPage
Definition: mminit.c:211
PMMPTE MiSessionImagePteEnd
Definition: mminit.c:144
MEMORY_ALLOCATION_DESCRIPTOR MxOldFreeDescriptor
Definition: mminit.c:273
PKEVENT MiHighNonPagedPoolEvent
Definition: mminit.c:297
PVOID MmHyperSpaceEnd
Definition: mminit.c:251
PMEMORY_ALLOCATION_DESCRIPTOR MxFreeDescriptor
Definition: mminit.c:272
ULONG MmThrottleTop
Definition: mminit.c:396
HARDWARE_PTE_ARMV6 TempPte
Definition: winldr.c:75
#define KERNEL_STACK_SIZE
MMPTE ValidKernelPte
Definition: init.c:31
PVOID MmPagedPoolStart
Definition: mminit.c:104
#define PTE_COUNT
Definition: miarm.h:33
UINTN VOID * Buffer
Definition: acefiex.h:370
BOOLEAN NTAPI INIT_FUNCTION MiInitializeMemoryEvents(VOID)
Definition: mminit.c:1339
PVOID MmHighSectionBase
Definition: section.c:111
SIZE_T MmMinimumStackCommitInBytes
Definition: mminit.c:370
BOOLEAN NTAPI MmIsAddressValid(IN PVOID VirtualAddress)
Definition: mmsup.c:174
#define READ_CONTROL
Definition: nt_native.h:58
LIST_ENTRY MmLoadedUserImageList
Definition: sysldr.c:35
#define MiSubsectionPteToSubsection(x)
Definition: mm.h:252
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
_In_ PUNICODE_STRING Name
Definition: mrx.h:218
#define MI_IS_PAGE_LARGE(x)
Definition: mm.h:100
ULONG MmSecondaryColorMask
Definition: mminit.c:257
#define SharedUserData
#define BYTES_TO_PAGES(Size)
_Out_writes_bytes_to_opt_ AbsoluteSecurityDescriptorSize PSECURITY_DESCRIPTOR _Inout_ PULONG _Out_writes_bytes_to_opt_ DaclSize PACL Dacl
Definition: rtlfuncs.h:1553
PKEVENT MiLowMemoryEvent
Definition: mminit.c:292
KEVENT MiTempEvent
Definition: mminit.c:289
MM_SYSTEMSIZE MmSystemSize
Definition: mminit.c:326
SIZE_T MmHeapSegmentReserve
Definition: mminit.c:366
char * PBOOLEAN
Definition: retypes.h:11
RTL_BITMAP MiPfnBitMap
Definition: mminit.c:201
PSID SeAliasAdminsSid
Definition: sid.c:47
PVOID MmNonPagedSystemStart
Definition: mminit.c:96
static const WCHAR L[]
Definition: oid.c:1087
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:803
LARGE_INTEGER MmCriticalSectionTimeout
Definition: mminit.c:388
#define MI_MIN_INIT_PAGED_POOLSIZE
Definition: mm.h:54
SLIST_HEADER MmDeadStackSListHead
Definition: procsup.c:23
Definition: mm.h:303
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
PMMPTE FORCEINLINE MiAddressToPxe(PVOID Address)
Definition: mm.h:160
#define PAGE_SIZE
Definition: env_spec_w32.h:49
PFN_NUMBER MmSystemPageDirectory[PD_COUNT]
Definition: init.c:40
PVOID MiSessionViewStart
Definition: mminit.c:131
Definition: typedefs.h:117
#define MI_MIN_SECONDARY_COLORS
Definition: mm.h:72
#define _1MB
Definition: miarm.h:15
#define SYNCHRONIZE
Definition: nt_native.h:61
LIST_HEAD(acpi_bus_event_list)
#define MI_MIN_PAGES_FOR_SYSPTE_TUNING
Definition: mm.h:51
PSID SeWorldSid
Definition: sid.c:31
PKEVENT MiLowNonPagedPoolEvent
Definition: mminit.c:296
FORCEINLINE PMMPFN MiGetPfnEntry(IN PFN_NUMBER Pfn)
Definition: mm.h:914
PFN_NUMBER MmMaximumNonPagedPoolInPages
Definition: mminit.c:30
SIZE_T MmSessionPoolSize
Definition: mminit.c:137
MMPTE ValidKernelPde
Definition: init.c:30
Status
Definition: gdiplustypes.h:24
ULONG_PTR Long
Definition: mmtypes.h:215
#define MI_PAGED_POOL_START
Definition: mm.h:20
union _MMPTE::@2170 u
VOID NTAPI INIT_FUNCTION MiNotifyMemoryEvents(VOID)
Definition: mminit.c:1218
C_ASSERT(FreePageList==1)
PVOID MmSystemCacheStart
Definition: mminit.c:243
ULONG_PTR SIZE_T
Definition: typedefs.h:78
MMPTE_HARDWARE Hard
Definition: mmtypes.h:217
#define MI_SET_PFN_DELETED(x)
Definition: miarm.h:163
#define HIGH_LEVEL
Definition: env_spec_w32.h:703
DWORD *typedef HANDLE
Definition: winlogon.h:60
VOID FASTCALL KeInitializeGuardedMutex(OUT PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:31
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
PFN_NUMBER MmSystemCacheWsMaximum
Definition: mminit.c:337
#define ROUND_TO_PAGES(Size)
ULONG_PTR PteFrame
Definition: mm.h:348
#define MI_SYSTEM_CACHE_START
Definition: mm.h:25
ULONG MmMaxAdditionNonPagedPoolPerMb
Definition: mminit.c:42
FORCEINLINE VOID MI_MAKE_PROTOTYPE_PTE(IN PMMPTE NewPte, IN PMMPTE PointerPte)
Definition: mm.h:273
LIST_ENTRY MemoryDescriptorListHead
Definition: arc.h:494
PFN_NUMBER Total
Definition: mm.h:369
PRTL_BITMAP EndOfPagedPoolBitmap
Definition: mm.h:413
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
SIZE_T MmHeapSegmentCommit
Definition: mminit.c:367
PMMWSL MmSystemCacheWorkingSetList
Definition: mminit.c:174
PFN_NUMBER MmHighMemoryThreshold
Definition: mminit.c:301
USHORT Rom
Definition: mm.h:298
PMMPTE PteAddress
Definition: mm.h:316
VOID NTAPI INIT_FUNCTION MiInitializeDriverLargePageList(VOID)
Definition: largepag.c:68
VOID NTAPI INIT_FUNCTION MiAddHalIoMappings(VOID)
Definition: mminit.c:1418
unsigned int * PULONG
Definition: retypes.h:1
#define min(a, b)
Definition: monoChain.cc:55
union _MMPFN::@1667 u4
VOID NTAPI INIT_FUNCTION MiComputeColorInformation(VOID)
Definition: mminit.c:508
VOID NTAPI MiReloadBootLoadedDrivers(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
Definition: sysldr.c:1673
VOID NTAPI MiInitializePoolEvents(VOID)
Definition: pool.c:201
#define DPRINT1
Definition: precomp.h:8
PVOID MmNonPagedPoolEnd
Definition: mminit.c:99
#define ACL_REVISION
Definition: setypes.h:39
PMMCOLOR_TABLES MmFreePagesByColor[FreePageList+1]
Definition: mminit.c:286
PVOID MiSessionPoolStart
Definition: mminit.c:133
NTSYSAPI void WINAPI RtlSetAllBits(PRTL_BITMAP)
PSID SeLocalSystemSid
Definition: sid.c:44
#define OUT
Definition: typedefs.h:39
LONG NTAPI KeReadStateEvent(IN PKEVENT Event)
Definition: eventobj.c:120
PFN_NUMBER MiLowPagedPoolThreshold
Definition: mminit.c:302
ULONG MmMaximumDeadKernelStacks
Definition: procsup.c:22
ULONG MmProductType
Definition: mminit.c:325
unsigned int ULONG
Definition: retypes.h:1
VOID NTAPI INIT_FUNCTION MiDbgDumpMemoryDescriptors(VOID)
Definition: mminit.c:1991
PVOID MiSessionPoolEnd
Definition: mminit.c:132
#define EVENT_MODIFY_STATE
Definition: winbase.h:163
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
SIZE_T MmSizeOfPagedPoolInBytes
Definition: mminit.c:110
#define ULONG_PTR
Definition: config.h:101
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
ULONG64 PageFrameNumber
Definition: mmtypes.h:171
NTSYSAPI void WINAPI RtlSetBits(PRTL_BITMAP, ULONG, ULONG)
KGUARDED_MUTEX MmPagedPoolMutex
Definition: pool.c:24
#define MiAddressToPteOffset(x)
Definition: mmx86.c:21
VOID NTAPI MmDumpArmPfnDatabase(IN BOOLEAN StatusOnly)
Definition: mminit.c:1474
NTSTATUS NTAPI INIT_FUNCTION MiCreateMemoryEvent(IN PUNICODE_STRING Name, OUT PKEVENT *Event)
Definition: mminit.c:1244
PFN_NUMBER Count
Definition: miarm.h:412
ULONG MmThrottleBottom
Definition: mminit.c:397
ULONG_PTR InPageError
Definition: mm.h:349
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
PVOID MmNonPagedPoolExpansionStart
Definition: mminit.c:98
PMMPTE FirstPteForPagedPool
Definition: mm.h:414
PVOID MmNonPagedPoolStart
Definition: mminit.c:97
PVOID MiSessionImageEnd
Definition: mminit.c:128
VOID NTAPI KeClearEvent(IN PKEVENT Event)
Definition: eventobj.c:22
#define MI_ALLOCATION_FRAGMENT
Definition: mm.h:67
KGUARDED_MUTEX MmSectionCommitMutex
Definition: section.c:108
FORCEINLINE BOOLEAN MI_IS_PHYSICAL_ADDRESS(IN PVOID Address)
Definition: miarm.h:902
#define MI_SYSTEM_CACHE_END
Definition: mm.h:26
#define OBJ_KERNEL_HANDLE
Definition: winternl.h:231
SIZE_T MmSystemViewSize
Definition: mminit.c:155
#define MI_MIN_ALLOCATION_FRAGMENT
Definition: mm.h:66
#define PFN_FROM_PTE(v)
Definition: mm.h:88
BOOLEAN MmLargeSystemCache
Definition: mminit.c:340
#define MI_HIGHEST_SYSTEM_ADDRESS
Definition: mm.h:30
PKEVENT MiHighMemoryEvent
Definition: mminit.c:293
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:94
PFN_NUMBER MmMinimumFreePages
Definition: mminit.c:314
VOID NTAPI KeFlushCurrentTb(VOID)
Definition: cpu.c:322
LONGLONG QuadPart
Definition: typedefs.h:112
#define _1GB
Definition: miarm.h:16
PMMPDE NextPdeForPagedPoolExpansion
Definition: mm.h:416
#define INIT_FUNCTION
Definition: ntoskrnl.h:11
WINBASEAPI VOID WINAPI InitializeSListHead(_Out_ PSLIST_HEADER ListHead)
Definition: rtlfuncs.h:3353
ULONG MmSecondaryColors
Definition: mminit.c:256
#define RTL_CONSTANT_STRING(s)
Definition: tunneltest.c:14
_Out_ PHANDLE EventHandle
Definition: iofuncs.h:855
_In_ PSTORAGE_PROPERTY_ID _Outptr_ PSTORAGE_DESCRIPTOR_HEADER * Descriptor
Definition: classpnp.h:966
SIZE_T MmAllocationFragment
Definition: mminit.c:352