ReactOS  r76032
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 */
246 
247 //
248 // This is where hyperspace ends (followed by the system cache working set)
249 //
251 
252 //
253 // Page coloring algorithm data
254 //
257 
258 //
259 // Actual (registry-configurable) size of a GUI thread's stack
260 //
262 
263 //
264 // Before we have a PFN database, memory comes straight from our physical memory
265 // blocks, which is nice because it's guaranteed contiguous and also because once
266 // we take a page from here, the system doesn't see it anymore.
267 // However, once the fun is over, those pages must be re-integrated back into
268 // PFN society life, and that requires us keeping a copy of the original layout
269 // so that we can parse it later.
270 //
273 
274 /*
275  * For each page's worth bytes of L2 cache in a given set/way line, the zero and
276  * free lists are organized in what is called a "color".
277  *
278  * This array points to the two lists, so it can be thought of as a multi-dimensional
279  * array of MmFreePagesByColor[2][MmSecondaryColors]. Since the number is dynamic,
280  * we describe the array in pointer form instead.
281  *
282  * On a final note, the color tables themselves are right after the PFN database.
283  */
284 C_ASSERT(FreePageList == 1);
286 
287 /* An event used in Phase 0 before the rest of the system is ready to go */
289 
290 /* All the events used for memory threshold notifications */
297 
298 /* The actual thresholds themselves, in page numbers */
305 
306 /*
307  * This number determines how many free pages must exist, at minimum, until we
308  * start trimming working sets and flushing modified pages to obtain more free
309  * pages.
310  *
311  * This number changes if the system detects that this is a server product
312  */
314 
315 /*
316  * This number indicates how many pages we consider to be a low limit of having
317  * "plenty" of free memory.
318  *
319  * It is doubled on systems that have more than 63MB of memory
320  */
322 
323 /* These values store the type of system this is (small, med, large) and if server */
326 
327 /*
328  * These values store the cache working set minimums and maximums, in pages
329  *
330  * The minimum value is boosted on systems with more than 24MB of RAM, and cut
331  * down to only 32 pages on embedded (<24MB RAM) systems.
332  *
333  * An extra boost of 2MB is given on systems with more than 33MB of RAM.
334  */
337 
338 /* FIXME: Move to cache/working set code later */
340 
341 /*
342  * This value determines in how many fragments/chunks the subsection prototype
343  * PTEs should be allocated when mapping a section object. It is configurable in
344  * the registry through the MapAllocationFragment parameter.
345  *
346  * The default is 64KB on systems with more than 1GB of RAM, 32KB on systems with
347  * more than 256MB of RAM, and 16KB on systems with less than 256MB of RAM.
348  *
349  * The maximum it can be set to is 2MB, and the minimum is 4KB.
350  */
352 
353 /*
354  * These two values track how much virtual memory can be committed, and when
355  * expansion should happen.
356  */
357  // FIXME: They should be moved elsewhere since it's not an "init" setting?
360 
361 /*
362  * These values tune certain user parameters. They have default values set here,
363  * as well as in the code, and can be overwritten by registry settings.
364  */
370 
371 /* Internal setting used for debugging memory descriptors */
373 #ifdef _ARM_
374 TRUE;
375 #else
376 FALSE;
377 #endif
378 
379 /* Number of memory descriptors in the loader block */
381 
382 /* Number of free pages in the loader block */
384 
385 /* Timeout value for critical sections (2.5 minutes) */
386 ULONG MmCritsectTimeoutSeconds = 150; // NT value: 720 * 60 * 60; (30 days)
388 
389 /* PRIVATE FUNCTIONS **********************************************************/
390 
391 VOID
392 NTAPI
394 {
395  PLIST_ENTRY ListEntry;
397  PFN_NUMBER PageFrameIndex, FreePages = 0;
398 
399  /* Loop the memory descriptors */
400  for (ListEntry = LoaderBlock->MemoryDescriptorListHead.Flink;
401  ListEntry != &LoaderBlock->MemoryDescriptorListHead;
402  ListEntry = ListEntry->Flink)
403  {
404  /* Get the descriptor */
405  Descriptor = CONTAINING_RECORD(ListEntry,
407  ListEntry);
408  DPRINT("MD Type: %lx Base: %lx Count: %lx\n",
409  Descriptor->MemoryType, Descriptor->BasePage, Descriptor->PageCount);
410 
411  /* Count this descriptor */
413 
414  /* Check if this is invisible memory */
415  if ((Descriptor->MemoryType == LoaderFirmwarePermanent) ||
416  (Descriptor->MemoryType == LoaderSpecialMemory) ||
417  (Descriptor->MemoryType == LoaderHALCachedMemory) ||
418  (Descriptor->MemoryType == LoaderBBTMemory))
419  {
420  /* Skip this descriptor */
421  continue;
422  }
423 
424  /* Check if this is bad memory */
425  if (Descriptor->MemoryType != LoaderBad)
426  {
427  /* Count this in the total of pages */
429  }
430 
431  /* Check if this is the new lowest page */
432  if (Descriptor->BasePage < MmLowestPhysicalPage)
433  {
434  /* Update the lowest page */
435  MmLowestPhysicalPage = Descriptor->BasePage;
436  }
437 
438  /* Check if this is the new highest page */
439  PageFrameIndex = Descriptor->BasePage + Descriptor->PageCount;
440  if (PageFrameIndex > MmHighestPhysicalPage)
441  {
442  /* Update the highest page */
443  MmHighestPhysicalPage = PageFrameIndex - 1;
444  }
445 
446  /* Check if this is free memory */
447  if ((Descriptor->MemoryType == LoaderFree) ||
448  (Descriptor->MemoryType == LoaderLoadedProgram) ||
449  (Descriptor->MemoryType == LoaderFirmwareTemporary) ||
450  (Descriptor->MemoryType == LoaderOsloaderStack))
451  {
452  /* Count it too free pages */
453  MiNumberOfFreePages += Descriptor->PageCount;
454 
455  /* Check if this is the largest memory descriptor */
456  if (Descriptor->PageCount > FreePages)
457  {
458  /* Remember it */
459  MxFreeDescriptor = Descriptor;
460  FreePages = Descriptor->PageCount;
461  }
462  }
463  }
464 
465  /* Save original values of the free descriptor, since it'll be
466  * altered by early allocations */
467  MxOldFreeDescriptor = *MxFreeDescriptor;
468 }
469 
471 NTAPI
474 {
475  PFN_NUMBER Pfn;
476 
477  /* Make sure we have enough pages */
478  if (PageCount > MxFreeDescriptor->PageCount)
479  {
480  /* Crash the system */
481  KeBugCheckEx(INSTALL_MORE_MEMORY,
483  MxFreeDescriptor->PageCount,
484  MxOldFreeDescriptor.PageCount,
485  PageCount);
486  }
487 
488  /* Use our lowest usable free pages */
489  Pfn = MxFreeDescriptor->BasePage;
490  MxFreeDescriptor->BasePage += PageCount;
491  MxFreeDescriptor->PageCount -= PageCount;
492  return Pfn;
493 }
494 
495 VOID
496 NTAPI
499 {
500  ULONG L2Associativity;
501 
502  /* Check if no setting was provided already */
503  if (!MmSecondaryColors)
504  {
505  /* Get L2 cache information */
506  L2Associativity = KeGetPcr()->SecondLevelCacheAssociativity;
507 
508  /* The number of colors is the number of cache bytes by set/way */
509  MmSecondaryColors = KeGetPcr()->SecondLevelCacheSize;
510  if (L2Associativity) MmSecondaryColors /= L2Associativity;
511  }
512 
513  /* Now convert cache bytes into pages */
515  if (!MmSecondaryColors)
516  {
517  /* If there was no cache data from the KPCR, use the default colors */
519  }
520  else
521  {
522  /* Otherwise, make sure there aren't too many colors */
524  {
525  /* Set the maximum */
527  }
528 
529  /* Make sure there aren't too little colors */
531  {
532  /* Set the default */
534  }
535 
536  /* Finally make sure the colors are a power of two */
538  {
539  /* Set the default */
541  }
542  }
543 
544  /* Compute the mask and store it */
546  KeGetCurrentPrcb()->SecondaryColorMask = MmSecondaryColorMask;
547 }
548 
549 VOID
550 NTAPI
553 {
554  ULONG i;
555  PMMPTE PointerPte, LastPte;
557 
558  /* The color table starts after the ARM3 PFN database */
559  MmFreePagesByColor[0] = (PMMCOLOR_TABLES)&MmPfnDatabase[MmHighestPhysicalPage + 1];
560 
561  /* Loop the PTEs. We have two color tables for each secondary color */
562  PointerPte = MiAddressToPte(&MmFreePagesByColor[0][0]);
563  LastPte = MiAddressToPte((ULONG_PTR)MmFreePagesByColor[0] +
564  (2 * MmSecondaryColors * sizeof(MMCOLOR_TABLES))
565  - 1);
566  while (PointerPte <= LastPte)
567  {
568  /* Check for valid PTE */
569  if (PointerPte->u.Hard.Valid == 0)
570  {
571  /* Get a page and map it */
572  TempPte.u.Hard.PageFrameNumber = MxGetNextPage(1);
573  MI_WRITE_VALID_PTE(PointerPte, TempPte);
574 
575  /* Zero out the page */
576  RtlZeroMemory(MiPteToAddress(PointerPte), PAGE_SIZE);
577  }
578 
579  /* Next */
580  PointerPte++;
581  }
582 
583  /* Now set the address of the next list, right after this one */
584  MmFreePagesByColor[1] = &MmFreePagesByColor[0][MmSecondaryColors];
585 
586  /* Now loop the lists to set them up */
587  for (i = 0; i < MmSecondaryColors; i++)
588  {
589  /* Set both free and zero lists for each color */
590  MmFreePagesByColor[ZeroedPageList][i].Flink = LIST_HEAD;
591  MmFreePagesByColor[ZeroedPageList][i].Blink = (PVOID)LIST_HEAD;
592  MmFreePagesByColor[ZeroedPageList][i].Count = 0;
593  MmFreePagesByColor[FreePageList][i].Flink = LIST_HEAD;
594  MmFreePagesByColor[FreePageList][i].Blink = (PVOID)LIST_HEAD;
595  MmFreePagesByColor[FreePageList][i].Count = 0;
596  }
597 }
598 
599 #ifndef _M_AMD64
600 BOOLEAN
601 NTAPI
604  IN PFN_NUMBER Pfn)
605 {
606  PLIST_ENTRY NextEntry;
608 
609  /* Loop the memory descriptors */
610  NextEntry = LoaderBlock->MemoryDescriptorListHead.Flink;
611  while (NextEntry != &LoaderBlock->MemoryDescriptorListHead)
612  {
613  /* Get the memory descriptor */
614  MdBlock = CONTAINING_RECORD(NextEntry,
616  ListEntry);
617 
618  /* Check if this PFN could be part of the block */
619  if (Pfn >= (MdBlock->BasePage))
620  {
621  /* Check if it really is part of the block */
622  if (Pfn < (MdBlock->BasePage + MdBlock->PageCount))
623  {
624  /* Check if the block is actually memory we don't map */
625  if ((MdBlock->MemoryType == LoaderFirmwarePermanent) ||
626  (MdBlock->MemoryType == LoaderBBTMemory) ||
627  (MdBlock->MemoryType == LoaderSpecialMemory))
628  {
629  /* We don't need PFN database entries for this memory */
630  break;
631  }
632 
633  /* This is memory we want to map */
634  return TRUE;
635  }
636  }
637  else
638  {
639  /* Blocks are ordered, so if it's not here, it doesn't exist */
640  break;
641  }
642 
643  /* Get to the next descriptor */
644  NextEntry = MdBlock->ListEntry.Flink;
645  }
646 
647  /* Check if this PFN is actually from our free memory descriptor */
648  if ((Pfn >= MxOldFreeDescriptor.BasePage) &&
649  (Pfn < MxOldFreeDescriptor.BasePage + MxOldFreeDescriptor.PageCount))
650  {
651  /* We use these pages for initial mappings, so we do want to count them */
652  return TRUE;
653  }
654 
655  /* Otherwise this isn't memory that we describe or care about */
656  return FALSE;
657 }
658 
659 VOID
660 NTAPI
663 {
664  PFN_NUMBER FreePage, FreePageCount, PagesLeft, BasePage, PageCount;
665  PLIST_ENTRY NextEntry;
667  PMMPTE PointerPte, LastPte;
669 
670  /* Get current page data, since we won't be using MxGetNextPage as it would corrupt our state */
671  FreePage = MxFreeDescriptor->BasePage;
672  FreePageCount = MxFreeDescriptor->PageCount;
673  PagesLeft = 0;
674 
675  /* Loop the memory descriptors */
676  NextEntry = LoaderBlock->MemoryDescriptorListHead.Flink;
677  while (NextEntry != &LoaderBlock->MemoryDescriptorListHead)
678  {
679  /* Get the descriptor */
680  MdBlock = CONTAINING_RECORD(NextEntry,
682  ListEntry);
683  if ((MdBlock->MemoryType == LoaderFirmwarePermanent) ||
684  (MdBlock->MemoryType == LoaderBBTMemory) ||
685  (MdBlock->MemoryType == LoaderSpecialMemory))
686  {
687  /* These pages are not part of the PFN database */
688  NextEntry = MdBlock->ListEntry.Flink;
689  continue;
690  }
691 
692  /* Next, check if this is our special free descriptor we've found */
693  if (MdBlock == MxFreeDescriptor)
694  {
695  /* Use the real numbers instead */
696  BasePage = MxOldFreeDescriptor.BasePage;
697  PageCount = MxOldFreeDescriptor.PageCount;
698  }
699  else
700  {
701  /* Use the descriptor's numbers */
702  BasePage = MdBlock->BasePage;
703  PageCount = MdBlock->PageCount;
704  }
705 
706  /* Get the PTEs for this range */
707  PointerPte = MiAddressToPte(&MmPfnDatabase[BasePage]);
708  LastPte = MiAddressToPte(((ULONG_PTR)&MmPfnDatabase[BasePage + PageCount]) - 1);
709  DPRINT("MD Type: %lx Base: %lx Count: %lx\n", MdBlock->MemoryType, BasePage, PageCount);
710 
711  /* Loop them */
712  while (PointerPte <= LastPte)
713  {
714  /* We'll only touch PTEs that aren't already valid */
715  if (PointerPte->u.Hard.Valid == 0)
716  {
717  /* Use the next free page */
718  TempPte.u.Hard.PageFrameNumber = FreePage;
719  ASSERT(FreePageCount != 0);
720 
721  /* Consume free pages */
722  FreePage++;
723  FreePageCount--;
724  if (!FreePageCount)
725  {
726  /* Out of memory */
727  KeBugCheckEx(INSTALL_MORE_MEMORY,
729  FreePageCount,
730  MxOldFreeDescriptor.PageCount,
731  1);
732  }
733 
734  /* Write out this PTE */
735  PagesLeft++;
736  MI_WRITE_VALID_PTE(PointerPte, TempPte);
737 
738  /* Zero this page */
739  RtlZeroMemory(MiPteToAddress(PointerPte), PAGE_SIZE);
740  }
741 
742  /* Next! */
743  PointerPte++;
744  }
745 
746  /* Do the next address range */
747  NextEntry = MdBlock->ListEntry.Flink;
748  }
749 
750  /* Now update the free descriptors to consume the pages we used up during the PFN allocation loop */
751  MxFreeDescriptor->BasePage = FreePage;
752  MxFreeDescriptor->PageCount = FreePageCount;
753 }
754 
755 VOID
756 NTAPI
759 {
760  PMMPDE PointerPde;
761  PMMPTE PointerPte;
762  ULONG i, Count, j;
763  PFN_NUMBER PageFrameIndex, StartupPdIndex, PtePageIndex;
764  PMMPFN Pfn1, Pfn2;
766 
767  /* PFN of the startup page directory */
768  StartupPdIndex = PFN_FROM_PTE(MiAddressToPde(PDE_BASE));
769 
770  /* Start with the first PDE and scan them all */
771  PointerPde = MiAddressToPde(NULL);
772  Count = PD_COUNT * PDE_COUNT;
773  for (i = 0; i < Count; i++)
774  {
775  /* Check for valid PDE */
776  if (PointerPde->u.Hard.Valid == 1)
777  {
778  /* Get the PFN from it */
779  PageFrameIndex = PFN_FROM_PTE(PointerPde);
780 
781  /* Do we want a PFN entry for this page? */
782  if (MiIsRegularMemory(LoaderBlock, PageFrameIndex))
783  {
784  /* Yes we do, set it up */
785  Pfn1 = MiGetPfnEntry(PageFrameIndex);
786  Pfn1->u4.PteFrame = StartupPdIndex;
787  Pfn1->PteAddress = (PMMPTE)PointerPde;
788  Pfn1->u2.ShareCount++;
789  Pfn1->u3.e2.ReferenceCount = 1;
792 #if MI_TRACE_PFNS
793  Pfn1->PfnUsage = MI_USAGE_INIT_MEMORY;
794  memcpy(Pfn1->ProcessName, "Initial PDE", 16);
795 #endif
796  }
797  else
798  {
799  /* No PFN entry */
800  Pfn1 = NULL;
801  }
802 
803  /* Now get the PTE and scan the pages */
804  PointerPte = MiAddressToPte(BaseAddress);
805  for (j = 0; j < PTE_COUNT; j++)
806  {
807  /* Check for a valid PTE */
808  if (PointerPte->u.Hard.Valid == 1)
809  {
810  /* Increase the shared count of the PFN entry for the PDE */
811  ASSERT(Pfn1 != NULL);
812  Pfn1->u2.ShareCount++;
813 
814  /* Now check if the PTE is valid memory too */
815  PtePageIndex = PFN_FROM_PTE(PointerPte);
816  if (MiIsRegularMemory(LoaderBlock, PtePageIndex))
817  {
818  /*
819  * Only add pages above the end of system code or pages
820  * that are part of nonpaged pool
821  */
822  if ((BaseAddress >= 0xA0000000) ||
823  ((BaseAddress >= (ULONG_PTR)MmNonPagedPoolStart) &&
824  (BaseAddress < (ULONG_PTR)MmNonPagedPoolStart +
826  {
827  /* Get the PFN entry and make sure it too is valid */
828  Pfn2 = MiGetPfnEntry(PtePageIndex);
829  if ((MmIsAddressValid(Pfn2)) &&
830  (MmIsAddressValid(Pfn2 + 1)))
831  {
832  /* Setup the PFN entry */
833  Pfn2->u4.PteFrame = PageFrameIndex;
834  Pfn2->PteAddress = PointerPte;
835  Pfn2->u2.ShareCount++;
836  Pfn2->u3.e2.ReferenceCount = 1;
839 #if MI_TRACE_PFNS
840  Pfn2->PfnUsage = MI_USAGE_INIT_MEMORY;
841  memcpy(Pfn1->ProcessName, "Initial PTE", 16);
842 #endif
843  }
844  }
845  }
846  }
847 
848  /* Next PTE */
849  PointerPte++;
850  BaseAddress += PAGE_SIZE;
851  }
852  }
853  else
854  {
855  /* Next PDE mapped address */
856  BaseAddress += PDE_MAPPED_VA;
857  }
858 
859  /* Next PTE */
860  PointerPde++;
861  }
862 }
863 
864 VOID
865 NTAPI
868 {
869  PMMPFN Pfn1;
870  PMMPDE PointerPde;
871 
872  /* Grab the lowest page and check if it has no real references */
874  if (!(MmLowestPhysicalPage) && !(Pfn1->u3.e2.ReferenceCount))
875  {
876  /* Make it a bogus page to catch errors */
877  PointerPde = MiAddressToPde(0xFFFFFFFF);
878  Pfn1->u4.PteFrame = PFN_FROM_PTE(PointerPde);
879  Pfn1->PteAddress = (PMMPTE)PointerPde;
880  Pfn1->u2.ShareCount++;
881  Pfn1->u3.e2.ReferenceCount = 0xFFF0;
884  }
885 }
886 
887 VOID
888 NTAPI
891 {
892  PLIST_ENTRY NextEntry;
893  PFN_NUMBER PageCount = 0;
895  PFN_NUMBER PageFrameIndex;
896  PMMPFN Pfn1;
897  PMMPTE PointerPte;
898  PMMPDE PointerPde;
899  KIRQL OldIrql;
900 
901  /* Now loop through the descriptors */
902  NextEntry = LoaderBlock->MemoryDescriptorListHead.Flink;
903  while (NextEntry != &LoaderBlock->MemoryDescriptorListHead)
904  {
905  /* Get the current descriptor */
906  MdBlock = CONTAINING_RECORD(NextEntry,
908  ListEntry);
909 
910  /* Read its data */
911  PageCount = MdBlock->PageCount;
912  PageFrameIndex = MdBlock->BasePage;
913 
914  /* Don't allow memory above what the PFN database is mapping */
915  if (PageFrameIndex > MmHighestPhysicalPage)
916  {
917  /* Since they are ordered, everything past here will be larger */
918  break;
919  }
920 
921  /* On the other hand, the end page might be higher up... */
922  if ((PageFrameIndex + PageCount) > (MmHighestPhysicalPage + 1))
923  {
924  /* In which case we'll trim the descriptor to go as high as we can */
925  PageCount = MmHighestPhysicalPage + 1 - PageFrameIndex;
926  MdBlock->PageCount = PageCount;
927 
928  /* But if there's nothing left to trim, we got too high, so quit */
929  if (!PageCount) break;
930  }
931 
932  /* Now check the descriptor type */
933  switch (MdBlock->MemoryType)
934  {
935  /* Check for bad RAM */
936  case LoaderBad:
937 
938  DPRINT1("You either have specified /BURNMEMORY or damaged RAM modules.\n");
939  break;
940 
941  /* Check for free RAM */
942  case LoaderFree:
943  case LoaderLoadedProgram:
945  case LoaderOsloaderStack:
946 
947  /* Get the last page of this descriptor. Note we loop backwards */
948  PageFrameIndex += PageCount - 1;
949  Pfn1 = MiGetPfnEntry(PageFrameIndex);
950 
951  /* Lock the PFN Database */
953  while (PageCount--)
954  {
955  /* If the page really has no references, mark it as free */
956  if (!Pfn1->u3.e2.ReferenceCount)
957  {
958  /* Add it to the free list */
960  MiInsertPageInFreeList(PageFrameIndex);
961  }
962 
963  /* Go to the next page */
964  Pfn1--;
965  PageFrameIndex--;
966  }
967 
968  /* Release PFN database */
970 
971  /* Done with this block */
972  break;
973 
974  /* Check for pages that are invisible to us */
976  case LoaderSpecialMemory:
977  case LoaderBBTMemory:
978 
979  /* And skip them */
980  break;
981 
982  default:
983 
984  /* Map these pages with the KSEG0 mapping that adds 0x80000000 */
985  PointerPte = MiAddressToPte(KSEG0_BASE + (PageFrameIndex << PAGE_SHIFT));
986  Pfn1 = MiGetPfnEntry(PageFrameIndex);
987  while (PageCount--)
988  {
989  /* Check if the page is really unused */
990  PointerPde = MiAddressToPde(KSEG0_BASE + (PageFrameIndex << PAGE_SHIFT));
991  if (!Pfn1->u3.e2.ReferenceCount)
992  {
993  /* Mark it as being in-use */
994  Pfn1->u4.PteFrame = PFN_FROM_PTE(PointerPde);
995  Pfn1->PteAddress = PointerPte;
996  Pfn1->u2.ShareCount++;
997  Pfn1->u3.e2.ReferenceCount = 1;
1000 #if MI_TRACE_PFNS
1001  Pfn1->PfnUsage = MI_USAGE_BOOT_DRIVER;
1002 #endif
1003 
1004  /* Check for RAM disk page */
1005  if (MdBlock->MemoryType == LoaderXIPRom)
1006  {
1007  /* Make it a pseudo-I/O ROM mapping */
1008  Pfn1->u1.Flink = 0;
1009  Pfn1->u2.ShareCount = 0;
1010  Pfn1->u3.e2.ReferenceCount = 0;
1011  Pfn1->u3.e1.PageLocation = 0;
1012  Pfn1->u3.e1.Rom = 1;
1013  Pfn1->u4.InPageError = 0;
1014  Pfn1->u3.e1.PrototypePte = 1;
1015  }
1016  }
1017 
1018  /* Advance page structures */
1019  Pfn1++;
1020  PageFrameIndex++;
1021  PointerPte++;
1022  }
1023  break;
1024  }
1025 
1026  /* Next descriptor entry */
1027  NextEntry = MdBlock->ListEntry.Flink;
1028  }
1029 }
1030 
1031 VOID
1032 NTAPI
1035 {
1036  PMMPTE PointerPte, LastPte;
1037  PMMPFN Pfn1;
1038 
1039  /* Loop the PFN database page */
1042  while (PointerPte <= LastPte)
1043  {
1044  /* Make sure the page is valid */
1045  if (PointerPte->u.Hard.Valid == 1)
1046  {
1047  /* Get the PFN entry and just mark it referenced */
1048  Pfn1 = MiGetPfnEntry(PointerPte->u.Hard.PageFrameNumber);
1049  Pfn1->u2.ShareCount = 1;
1050  Pfn1->u3.e2.ReferenceCount = 1;
1051 #if MI_TRACE_PFNS
1052  Pfn1->PfnUsage = MI_USAGE_PFN_DATABASE;
1053 #endif
1054  }
1055 
1056  /* Next */
1057  PointerPte++;
1058  }
1059 }
1060 
1061 VOID
1062 NTAPI
1065 {
1066  /* Scan memory and start setting up PFN entries */
1067  MiBuildPfnDatabaseFromPages(LoaderBlock);
1068 
1069  /* Add the zero page */
1071 
1072  /* Scan the loader block and build the rest of the PFN database */
1073  MiBuildPfnDatabaseFromLoaderBlock(LoaderBlock);
1074 
1075  /* Finally add the pages for the PFN database itself */
1077 }
1078 #endif /* !_M_AMD64 */
1079 
1080 VOID
1081 NTAPI
1084 {
1085  PLIST_ENTRY NextMd;
1087  ULONG_PTR i;
1088  PFN_NUMBER BasePage, LoaderPages;
1089  PMMPFN Pfn1;
1090  KIRQL OldIrql;
1092 
1093  /* Loop the descriptors in order to count them */
1094  i = 0;
1095  NextMd = LoaderBlock->MemoryDescriptorListHead.Flink;
1096  while (NextMd != &LoaderBlock->MemoryDescriptorListHead)
1097  {
1098  MdBlock = CONTAINING_RECORD(NextMd,
1100  ListEntry);
1101  i++;
1102  NextMd = MdBlock->ListEntry.Flink;
1103  }
1104 
1105  /* Allocate a structure to hold the physical runs */
1107  i * sizeof(PHYSICAL_MEMORY_RUN),
1108  'lMmM');
1109  ASSERT(Buffer != NULL);
1110  Entry = Buffer;
1111 
1112  /* Loop the descriptors again */
1113  NextMd = LoaderBlock->MemoryDescriptorListHead.Flink;
1114  while (NextMd != &LoaderBlock->MemoryDescriptorListHead)
1115  {
1116  /* Check what kind this was */
1117  MdBlock = CONTAINING_RECORD(NextMd,
1119  ListEntry);
1120  switch (MdBlock->MemoryType)
1121  {
1122  /* Registry, NLS, and heap data */
1123  case LoaderRegistryData:
1124  case LoaderOsloaderHeap:
1125  case LoaderNlsData:
1126  /* Are all a candidate for deletion */
1127  Entry->BasePage = MdBlock->BasePage;
1128  Entry->PageCount = MdBlock->PageCount;
1129  Entry++;
1130 
1131  /* We keep the rest */
1132  default:
1133  break;
1134  }
1135 
1136  /* Move to the next descriptor */
1137  NextMd = MdBlock->ListEntry.Flink;
1138  }
1139 
1140  /* Acquire the PFN lock */
1142 
1143  /* Loop the runs */
1144  LoaderPages = 0;
1145  while (--Entry >= Buffer)
1146  {
1147  /* See how many pages are in this run */
1148  i = Entry->PageCount;
1149  BasePage = Entry->BasePage;
1150 
1151  /* Loop each page */
1152  Pfn1 = MiGetPfnEntry(BasePage);
1153  while (i--)
1154  {
1155  /* Check if it has references or is in any kind of list */
1156  if (!(Pfn1->u3.e2.ReferenceCount) && (!Pfn1->u1.Flink))
1157  {
1158  /* Set the new PTE address and put this page into the free list */
1159  Pfn1->PteAddress = (PMMPTE)(BasePage << PAGE_SHIFT);
1160  MiInsertPageInFreeList(BasePage);
1161  LoaderPages++;
1162  }
1163  else if (BasePage)
1164  {
1165  /* It has a reference, so simply drop it */
1167 
1168  /* Drop a dereference on this page, which should delete it */
1169  Pfn1->PteAddress->u.Long = 0;
1170  MI_SET_PFN_DELETED(Pfn1);
1171  MiDecrementShareCount(Pfn1, BasePage);
1172  LoaderPages++;
1173  }
1174 
1175  /* Move to the next page */
1176  Pfn1++;
1177  BasePage++;
1178  }
1179  }
1180 
1181  /* Release the PFN lock and flush the TLB */
1182  DPRINT("Loader pages freed: %lx\n", LoaderPages);
1184  KeFlushCurrentTb();
1185 
1186  /* Free our run structure */
1187  ExFreePoolWithTag(Buffer, 'lMmM');
1188 }
1189 
1190 VOID
1191 NTAPI
1194 {
1195  /* This function needs to do more work, for now, we tune page minimums */
1196 
1197  /* Check for a system with around 64MB RAM or more */
1198  if (MmNumberOfPhysicalPages >= (63 * _1MB) / PAGE_SIZE)
1199  {
1200  /* Double the minimum amount of pages we consider for a "plenty free" scenario */
1201  MmPlentyFreePages *= 2;
1202  }
1203 }
1204 
1205 VOID
1206 NTAPI
1209 {
1210  /* Are we in a low-memory situation? */
1212  {
1213  /* Clear high, set low */
1214  if (KeReadStateEvent(MiHighMemoryEvent)) KeClearEvent(MiHighMemoryEvent);
1215  if (!KeReadStateEvent(MiLowMemoryEvent)) KeSetEvent(MiLowMemoryEvent, 0, FALSE);
1216  }
1218  {
1219  /* We are in between, clear both */
1220  if (KeReadStateEvent(MiHighMemoryEvent)) KeClearEvent(MiHighMemoryEvent);
1221  if (KeReadStateEvent(MiLowMemoryEvent)) KeClearEvent(MiLowMemoryEvent);
1222  }
1223  else
1224  {
1225  /* Clear low, set high */
1226  if (KeReadStateEvent(MiLowMemoryEvent)) KeClearEvent(MiLowMemoryEvent);
1227  if (!KeReadStateEvent(MiHighMemoryEvent)) KeSetEvent(MiHighMemoryEvent, 0, FALSE);
1228  }
1229 }
1230 
1231 NTSTATUS
1232 NTAPI
1235  OUT PKEVENT *Event)
1236 {
1237  PACL Dacl;
1239  ULONG DaclLength;
1240  NTSTATUS Status;
1243 
1244  /* Create the SD */
1245  Status = RtlCreateSecurityDescriptor(&SecurityDescriptor,
1247  if (!NT_SUCCESS(Status)) return Status;
1248 
1249  /* One ACL with 3 ACEs, containing each one SID */
1250  DaclLength = sizeof(ACL) +
1251  3 * sizeof(ACCESS_ALLOWED_ACE) +
1255 
1256  /* Allocate space for the DACL */
1257  Dacl = ExAllocatePoolWithTag(PagedPool, DaclLength, 'lcaD');
1258  if (!Dacl) return STATUS_INSUFFICIENT_RESOURCES;
1259 
1260  /* Setup the ACL inside it */
1261  Status = RtlCreateAcl(Dacl, DaclLength, ACL_REVISION);
1262  if (!NT_SUCCESS(Status)) goto CleanUp;
1263 
1264  /* Add query rights for everyone */
1265  Status = RtlAddAccessAllowedAce(Dacl,
1266  ACL_REVISION,
1268  SeWorldSid);
1269  if (!NT_SUCCESS(Status)) goto CleanUp;
1270 
1271  /* Full rights for the admin */
1272  Status = RtlAddAccessAllowedAce(Dacl,
1273  ACL_REVISION,
1276  if (!NT_SUCCESS(Status)) goto CleanUp;
1277 
1278  /* As well as full rights for the system */
1279  Status = RtlAddAccessAllowedAce(Dacl,
1280  ACL_REVISION,
1283  if (!NT_SUCCESS(Status)) goto CleanUp;
1284 
1285  /* Set this DACL inside the SD */
1286  Status = RtlSetDaclSecurityDescriptor(&SecurityDescriptor,
1287  TRUE,
1288  Dacl,
1289  FALSE);
1290  if (!NT_SUCCESS(Status)) goto CleanUp;
1291 
1292  /* Setup the event attributes, making sure it's a permanent one */
1293  InitializeObjectAttributes(&ObjectAttributes,
1294  Name,
1296  NULL,
1297  &SecurityDescriptor);
1298 
1299  /* Create the event */
1300  Status = ZwCreateEvent(&EventHandle,
1302  &ObjectAttributes,
1304  FALSE);
1305 CleanUp:
1306  /* Free the DACL */
1307  ExFreePoolWithTag(Dacl, 'lcaD');
1308 
1309  /* Check if this is the success path */
1310  if (NT_SUCCESS(Status))
1311  {
1312  /* Add a reference to the object, then close the handle we had */
1313  Status = ObReferenceObjectByHandle(EventHandle,
1316  KernelMode,
1317  (PVOID*)Event,
1318  NULL);
1319  ZwClose (EventHandle);
1320  }
1321 
1322  /* Return status */
1323  return Status;
1324 }
1325 
1326 BOOLEAN
1327 NTAPI
1330 {
1331  UNICODE_STRING LowString = RTL_CONSTANT_STRING(L"\\KernelObjects\\LowMemoryCondition");
1332  UNICODE_STRING HighString = RTL_CONSTANT_STRING(L"\\KernelObjects\\HighMemoryCondition");
1333  UNICODE_STRING LowPagedPoolString = RTL_CONSTANT_STRING(L"\\KernelObjects\\LowPagedPoolCondition");
1334  UNICODE_STRING HighPagedPoolString = RTL_CONSTANT_STRING(L"\\KernelObjects\\HighPagedPoolCondition");
1335  UNICODE_STRING LowNonPagedPoolString = RTL_CONSTANT_STRING(L"\\KernelObjects\\LowNonPagedPoolCondition");
1336  UNICODE_STRING HighNonPagedPoolString = RTL_CONSTANT_STRING(L"\\KernelObjects\\HighNonPagedPoolCondition");
1337  NTSTATUS Status;
1338 
1339  /* Check if we have a registry setting */
1341  {
1342  /* Convert it to pages */
1344  }
1345  else
1346  {
1347  /* The low memory threshold is hit when we don't consider that we have "plenty" of free pages anymore */
1349 
1350  /* More than one GB of memory? */
1351  if (MmNumberOfPhysicalPages > 0x40000)
1352  {
1353  /* Start at 32MB, and add another 16MB for each GB */
1354  MmLowMemoryThreshold = (32 * _1MB) / PAGE_SIZE;
1355  MmLowMemoryThreshold += ((MmNumberOfPhysicalPages - 0x40000) >> 7);
1356  }
1357  else if (MmNumberOfPhysicalPages > 0x8000)
1358  {
1359  /* For systems with > 128MB RAM, add another 4MB for each 128MB */
1360  MmLowMemoryThreshold += ((MmNumberOfPhysicalPages - 0x8000) >> 5);
1361  }
1362 
1363  /* Don't let the minimum threshold go past 64MB */
1365  }
1366 
1367  /* Check if we have a registry setting */
1369  {
1370  /* Convert it into pages */
1372  }
1373  else
1374  {
1375  /* Otherwise, the default is three times the low memory threshold */
1378  }
1379 
1380  /* Make sure high threshold is actually higher than the low */
1382 
1383  /* Create the memory events for all the thresholds */
1384  Status = MiCreateMemoryEvent(&LowString, &MiLowMemoryEvent);
1385  if (!NT_SUCCESS(Status)) return FALSE;
1386  Status = MiCreateMemoryEvent(&HighString, &MiHighMemoryEvent);
1387  if (!NT_SUCCESS(Status)) return FALSE;
1388  Status = MiCreateMemoryEvent(&LowPagedPoolString, &MiLowPagedPoolEvent);
1389  if (!NT_SUCCESS(Status)) return FALSE;
1390  Status = MiCreateMemoryEvent(&HighPagedPoolString, &MiHighPagedPoolEvent);
1391  if (!NT_SUCCESS(Status)) return FALSE;
1392  Status = MiCreateMemoryEvent(&LowNonPagedPoolString, &MiLowNonPagedPoolEvent);
1393  if (!NT_SUCCESS(Status)) return FALSE;
1394  Status = MiCreateMemoryEvent(&HighNonPagedPoolString, &MiHighNonPagedPoolEvent);
1395  if (!NT_SUCCESS(Status)) return FALSE;
1396 
1397  /* Now setup the pool events */
1399 
1400  /* Set the initial event state */
1402  return TRUE;
1403 }
1404 
1405 VOID
1406 NTAPI
1409 {
1411  PMMPDE PointerPde, LastPde;
1412  PMMPTE PointerPte;
1413  ULONG j;
1414  PFN_NUMBER PageFrameIndex;
1415 
1416  /* HAL Heap address -- should be on a PDE boundary */
1417  BaseAddress = (PVOID)MM_HAL_VA_START;
1418  ASSERT(MiAddressToPteOffset(BaseAddress) == 0);
1419 
1420  /* Check how many PDEs the heap has */
1421  PointerPde = MiAddressToPde(BaseAddress);
1422  LastPde = MiAddressToPde((PVOID)MM_HAL_VA_END);
1423 
1424  while (PointerPde <= LastPde)
1425  {
1426  /* Does the HAL own this mapping? */
1427  if ((PointerPde->u.Hard.Valid == 1) &&
1428  (MI_IS_PAGE_LARGE(PointerPde) == FALSE))
1429  {
1430  /* Get the PTE for it and scan each page */
1431  PointerPte = MiAddressToPte(BaseAddress);
1432  for (j = 0 ; j < PTE_COUNT; j++)
1433  {
1434  /* Does the HAL own this page? */
1435  if (PointerPte->u.Hard.Valid == 1)
1436  {
1437  /* Is the HAL using it for device or I/O mapped memory? */
1438  PageFrameIndex = PFN_FROM_PTE(PointerPte);
1439  if (!MiGetPfnEntry(PageFrameIndex))
1440  {
1441  /* FIXME: For PAT, we need to track I/O cache attributes for coherency */
1442  DPRINT1("HAL I/O Mapping at %p is unsafe\n", BaseAddress);
1443  }
1444  }
1445 
1446  /* Move to the next page */
1447  BaseAddress = (PVOID)((ULONG_PTR)BaseAddress + PAGE_SIZE);
1448  PointerPte++;
1449  }
1450  }
1451  else
1452  {
1453  /* Move to the next address */
1454  BaseAddress = (PVOID)((ULONG_PTR)BaseAddress + PDE_MAPPED_VA);
1455  }
1456 
1457  /* Move to the next PDE */
1458  PointerPde++;
1459  }
1460 }
1461 
1462 VOID
1463 NTAPI
1465 {
1466  ULONG i;
1467  PMMPFN Pfn1;
1468  PCHAR Consumer = "Unknown";
1469  KIRQL OldIrql;
1470  ULONG ActivePages = 0, FreePages = 0, OtherPages = 0;
1471 #if MI_TRACE_PFNS
1472  ULONG UsageBucket[MI_USAGE_FREE_PAGE + 1] = {0};
1473  PCHAR MI_USAGE_TEXT[MI_USAGE_FREE_PAGE + 1] =
1474  {
1475  "Not set",
1476  "Paged Pool",
1477  "Nonpaged Pool",
1478  "Nonpaged Pool Ex",
1479  "Kernel Stack",
1480  "Kernel Stack Ex",
1481  "System PTE",
1482  "VAD",
1483  "PEB/TEB",
1484  "Section",
1485  "Page Table",
1486  "Page Directory",
1487  "Old Page Table",
1488  "Driver Page",
1489  "Contiguous Alloc",
1490  "MDL",
1491  "Demand Zero",
1492  "Zero Loop",
1493  "Cache",
1494  "PFN Database",
1495  "Boot Driver",
1496  "Initial Memory",
1497  "Free Page"
1498  };
1499 #endif
1500  //
1501  // Loop the PFN database
1502  //
1503  KeRaiseIrql(HIGH_LEVEL, &OldIrql);
1504  for (i = 0; i <= MmHighestPhysicalPage; i++)
1505  {
1506  Pfn1 = MiGetPfnEntry(i);
1507  if (!Pfn1) continue;
1508 #if MI_TRACE_PFNS
1509  ASSERT(Pfn1->PfnUsage <= MI_USAGE_FREE_PAGE);
1510 #endif
1511  //
1512  // Get the page location
1513  //
1514  switch (Pfn1->u3.e1.PageLocation)
1515  {
1516  case ActiveAndValid:
1517 
1518  Consumer = "Active and Valid";
1519  ActivePages++;
1520  break;
1521 
1522  case ZeroedPageList:
1523 
1524  Consumer = "Zero Page List";
1525  FreePages++;
1526  break;//continue;
1527 
1528  case FreePageList:
1529 
1530  Consumer = "Free Page List";
1531  FreePages++;
1532  break;//continue;
1533 
1534  default:
1535 
1536  Consumer = "Other (ASSERT!)";
1537  OtherPages++;
1538  break;
1539  }
1540 
1541 #if MI_TRACE_PFNS
1542  /* Add into bucket */
1543  UsageBucket[Pfn1->PfnUsage]++;
1544 #endif
1545 
1546  //
1547  // Pretty-print the page
1548  //
1549  if (!StatusOnly)
1550  DbgPrint("0x%08p:\t%20s\t(%04d.%04d)\t[%16s - %16s])\n",
1551  i << PAGE_SHIFT,
1552  Consumer,
1553  Pfn1->u3.e2.ReferenceCount,
1554  Pfn1->u2.ShareCount == LIST_HEAD ? 0xFFFF : Pfn1->u2.ShareCount,
1555 #if MI_TRACE_PFNS
1556  MI_USAGE_TEXT[Pfn1->PfnUsage],
1557  Pfn1->ProcessName);
1558 #else
1559  "Page tracking",
1560  "is disabled");
1561 #endif
1562  }
1563 
1564  DbgPrint("Active: %5d pages\t[%6d KB]\n", ActivePages, (ActivePages << PAGE_SHIFT) / 1024);
1565  DbgPrint("Free: %5d pages\t[%6d KB]\n", FreePages, (FreePages << PAGE_SHIFT) / 1024);
1566  DbgPrint("Other: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024);
1567  DbgPrint("-----------------------------------------\n");
1568 #if MI_TRACE_PFNS
1569  OtherPages = UsageBucket[MI_USAGE_BOOT_DRIVER];
1570  DbgPrint("Boot Images: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024);
1571  OtherPages = UsageBucket[MI_USAGE_DRIVER_PAGE];
1572  DbgPrint("System Drivers: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024);
1573  OtherPages = UsageBucket[MI_USAGE_PFN_DATABASE];
1574  DbgPrint("PFN Database: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024);
1575  OtherPages = UsageBucket[MI_USAGE_PAGE_TABLE] + UsageBucket[MI_USAGE_PAGE_DIRECTORY] + UsageBucket[MI_USAGE_LEGACY_PAGE_DIRECTORY];
1576  DbgPrint("Page Tables: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024);
1577  OtherPages = UsageBucket[MI_USAGE_SYSTEM_PTE];
1578  DbgPrint("System PTEs: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024);
1579  OtherPages = UsageBucket[MI_USAGE_VAD];
1580  DbgPrint("VADs: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024);
1581  OtherPages = UsageBucket[MI_USAGE_CONTINOUS_ALLOCATION];
1582  DbgPrint("Continuous Allocs: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024);
1583  OtherPages = UsageBucket[MI_USAGE_MDL];
1584  DbgPrint("MDLs: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024);
1585  OtherPages = UsageBucket[MI_USAGE_NONPAGED_POOL] + UsageBucket[MI_USAGE_NONPAGED_POOL_EXPANSION];
1586  DbgPrint("NonPaged Pool: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024);
1587  OtherPages = UsageBucket[MI_USAGE_PAGED_POOL];
1588  DbgPrint("Paged Pool: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024);
1589  OtherPages = UsageBucket[MI_USAGE_DEMAND_ZERO];
1590  DbgPrint("Demand Zero: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024);
1591  OtherPages = UsageBucket[MI_USAGE_ZERO_LOOP];
1592  DbgPrint("Zero Loop: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024);
1593  OtherPages = UsageBucket[MI_USAGE_PEB_TEB];
1594  DbgPrint("PEB/TEB: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024);
1595  OtherPages = UsageBucket[MI_USAGE_KERNEL_STACK] + UsageBucket[MI_USAGE_KERNEL_STACK_EXPANSION];
1596  DbgPrint("Kernel Stack: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024);
1597  OtherPages = UsageBucket[MI_USAGE_INIT_MEMORY];
1598  DbgPrint("Init Memory: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024);
1599  OtherPages = UsageBucket[MI_USAGE_SECTION];
1600  DbgPrint("Sections: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024);
1601  OtherPages = UsageBucket[MI_USAGE_CACHE];
1602  DbgPrint("Cache: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024);
1603  OtherPages = UsageBucket[MI_USAGE_FREE_PAGE];
1604  DbgPrint("Free: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024);
1605 #endif
1606  KeLowerIrql(OldIrql);
1607 }
1608 
1610 NTAPI
1613  IN PBOOLEAN IncludeType)
1614 {
1615  PLIST_ENTRY NextEntry;
1616  ULONG Run = 0, InitialRuns;
1617  PFN_NUMBER NextPage = -1, PageCount = 0;
1620 
1621  //
1622  // Start with the maximum we might need
1623  //
1624  InitialRuns = MiNumberDescriptors;
1625 
1626  //
1627  // Allocate the maximum we'll ever need
1628  //
1630  sizeof(PHYSICAL_MEMORY_DESCRIPTOR) +
1631  sizeof(PHYSICAL_MEMORY_RUN) *
1632  (InitialRuns - 1),
1633  'lMmM');
1634  if (!Buffer) return NULL;
1635 
1636  //
1637  // For now that's how many runs we have
1638  //
1639  Buffer->NumberOfRuns = InitialRuns;
1640 
1641  //
1642  // Now loop through the descriptors again
1643  //
1644  NextEntry = LoaderBlock->MemoryDescriptorListHead.Flink;
1645  while (NextEntry != &LoaderBlock->MemoryDescriptorListHead)
1646  {
1647  //
1648  // Grab each one, and check if it's one we should include
1649  //
1650  MdBlock = CONTAINING_RECORD(NextEntry,
1652  ListEntry);
1653  if ((MdBlock->MemoryType < LoaderMaximum) &&
1654  (IncludeType[MdBlock->MemoryType]))
1655  {
1656  //
1657  // Add this to our running total
1658  //
1659  PageCount += MdBlock->PageCount;
1660 
1661  //
1662  // Check if the next page is described by the next descriptor
1663  //
1664  if (MdBlock->BasePage == NextPage)
1665  {
1666  //
1667  // Combine it into the same physical run
1668  //
1669  ASSERT(MdBlock->PageCount != 0);
1670  Buffer->Run[Run - 1].PageCount += MdBlock->PageCount;
1671  NextPage += MdBlock->PageCount;
1672  }
1673  else
1674  {
1675  //
1676  // Otherwise just duplicate the descriptor's contents
1677  //
1678  Buffer->Run[Run].BasePage = MdBlock->BasePage;
1679  Buffer->Run[Run].PageCount = MdBlock->PageCount;
1680  NextPage = Buffer->Run[Run].BasePage + Buffer->Run[Run].PageCount;
1681 
1682  //
1683  // And in this case, increase the number of runs
1684  //
1685  Run++;
1686  }
1687  }
1688 
1689  //
1690  // Try the next descriptor
1691  //
1692  NextEntry = MdBlock->ListEntry.Flink;
1693  }
1694 
1695  //
1696  // We should not have been able to go past our initial estimate
1697  //
1698  ASSERT(Run <= Buffer->NumberOfRuns);
1699 
1700  //
1701  // Our guess was probably exaggerated...
1702  //
1703  if (InitialRuns > Run)
1704  {
1705  //
1706  // Allocate a more accurately sized buffer
1707  //
1708  NewBuffer = ExAllocatePoolWithTag(NonPagedPool,
1709  sizeof(PHYSICAL_MEMORY_DESCRIPTOR) +
1710  sizeof(PHYSICAL_MEMORY_RUN) *
1711  (Run - 1),
1712  'lMmM');
1713  if (NewBuffer)
1714  {
1715  //
1716  // Copy the old buffer into the new, then free it
1717  //
1718  RtlCopyMemory(NewBuffer->Run,
1719  Buffer->Run,
1720  sizeof(PHYSICAL_MEMORY_RUN) * Run);
1721  ExFreePoolWithTag(Buffer, 'lMmM');
1722 
1723  //
1724  // Now use the new buffer
1725  //
1726  Buffer = NewBuffer;
1727  }
1728  }
1729 
1730  //
1731  // Write the final numbers, and return it
1732  //
1733  Buffer->NumberOfRuns = Run;
1734  Buffer->NumberOfPages = PageCount;
1735  return Buffer;
1736 }
1737 
1738 VOID
1739 NTAPI
1742 {
1743  PMMPTE PointerPte;
1744  PMMPDE PointerPde;
1746  PFN_NUMBER PageFrameIndex;
1747  KIRQL OldIrql;
1748  SIZE_T Size;
1749  ULONG BitMapSize;
1750 #if (_MI_PAGING_LEVELS >= 3)
1751  MMPPE TempPpe = ValidKernelPpe;
1752  PMMPPE PointerPpe;
1753 #elif (_MI_PAGING_LEVELS == 2)
1755 
1756  //
1757  // Get the page frame number for the system page directory
1758  //
1759  PointerPte = MiAddressToPte(PDE_BASE);
1760  ASSERT(PD_COUNT == 1);
1761  MmSystemPageDirectory[0] = PFN_FROM_PTE(PointerPte);
1762 
1763  //
1764  // Allocate a system PTE which will hold a copy of the page directory
1765  //
1766  PointerPte = MiReserveSystemPtes(1, SystemPteSpace);
1767  ASSERT(PointerPte);
1768  MmSystemPagePtes = MiPteToAddress(PointerPte);
1769 
1770  //
1771  // Make this system PTE point to the system page directory.
1772  // It is now essentially double-mapped. This will be used later for lazy
1773  // evaluation of PDEs accross process switches, similarly to how the Global
1774  // page directory array in the old ReactOS Mm is used (but in a less hacky
1775  // way).
1776  //
1777  TempPte = ValidKernelPte;
1778  ASSERT(PD_COUNT == 1);
1780  MI_WRITE_VALID_PTE(PointerPte, TempPte);
1781 #endif
1782  //
1783  // Let's get back to paged pool work: size it up.
1784  // By default, it should be twice as big as nonpaged pool.
1785  //
1789  {
1790  //
1791  // On the other hand, we have limited VA space, so make sure that the VA
1792  // for paged pool doesn't overflow into nonpaged pool VA. Otherwise, set
1793  // whatever maximum is possible.
1794  //
1797  }
1798 
1799  //
1800  // Get the size in pages and make sure paged pool is at least 32MB.
1801  //
1802  Size = MmSizeOfPagedPoolInBytes;
1804  Size = BYTES_TO_PAGES(Size);
1805 
1806  //
1807  // Now check how many PTEs will be required for these many pages.
1808  //
1809  Size = (Size + (1024 - 1)) / 1024;
1810 
1811  //
1812  // Recompute the page-aligned size of the paged pool, in bytes and pages.
1813  //
1814  MmSizeOfPagedPoolInBytes = Size * PAGE_SIZE * 1024;
1816 
1817  //
1818  // Let's be really sure this doesn't overflow into nonpaged system VA
1819  //
1820  ASSERT((MmSizeOfPagedPoolInBytes + (ULONG_PTR)MmPagedPoolStart) <=
1822 
1823  //
1824  // This is where paged pool ends
1825  //
1826  MmPagedPoolEnd = (PVOID)(((ULONG_PTR)MmPagedPoolStart +
1828 
1829  //
1830  // Lock the PFN database
1831  //
1833 
1834 #if (_MI_PAGING_LEVELS >= 3)
1835  /* On these systems, there's no double-mapping, so instead, the PPEs
1836  * are setup to span the entire paged pool area, so there's no need for the
1837  * system PD */
1838  for (PointerPpe = MiAddressToPpe(MmPagedPoolStart);
1839  PointerPpe <= MiAddressToPpe(MmPagedPoolEnd);
1840  PointerPpe++)
1841  {
1842  /* Check if the PPE is already valid */
1843  if (!PointerPpe->u.Hard.Valid)
1844  {
1845  /* It is not, so map a fresh zeroed page */
1846  TempPpe.u.Hard.PageFrameNumber = MiRemoveZeroPage(0);
1847  MI_WRITE_VALID_PPE(PointerPpe, TempPpe);
1848  }
1849  }
1850 #endif
1851 
1852  //
1853  // So now get the PDE for paged pool and zero it out
1854  //
1855  PointerPde = MiAddressToPde(MmPagedPoolStart);
1856  RtlZeroMemory(PointerPde,
1857  (1 + MiAddressToPde(MmPagedPoolEnd) - PointerPde) * sizeof(MMPDE));
1858 
1859  //
1860  // Next, get the first and last PTE
1861  //
1862  PointerPte = MiAddressToPte(MmPagedPoolStart);
1865 
1866  /* Allocate a page and map the first paged pool PDE */
1868  MI_SET_PROCESS2("Kernel");
1869  PageFrameIndex = MiRemoveZeroPage(0);
1870  TempPde.u.Hard.PageFrameNumber = PageFrameIndex;
1871  MI_WRITE_VALID_PDE(PointerPde, TempPde);
1872 #if (_MI_PAGING_LEVELS >= 3)
1873  /* Use the PPE of MmPagedPoolStart that was setup above */
1874 // Bla = PFN_FROM_PTE(PpeAddress(MmPagedPool...));
1875 
1876  /* Initialize the PFN entry for it */
1877  MiInitializePfnForOtherProcess(PageFrameIndex,
1878  (PMMPTE)PointerPde,
1879  PFN_FROM_PTE(MiAddressToPpe(MmPagedPoolStart)));
1880 #else
1881  /* Do it this way */
1882 // Bla = MmSystemPageDirectory[(PointerPde - (PMMPTE)PDE_BASE) / PDE_COUNT]
1883 
1884  /* Initialize the PFN entry for it */
1885  MiInitializePfnForOtherProcess(PageFrameIndex,
1886  (PMMPTE)PointerPde,
1887  MmSystemPageDirectory[(PointerPde - (PMMPDE)PDE_BASE) / PDE_COUNT]);
1888 #endif
1889 
1890  //
1891  // Release the PFN database lock
1892  //
1894 
1895  //
1896  // We only have one PDE mapped for now... at fault time, additional PDEs
1897  // will be allocated to handle paged pool growth. This is where they'll have
1898  // to start.
1899  //
1901 
1902  //
1903  // We keep track of each page via a bit, so check how big the bitmap will
1904  // have to be (make sure to align our page count such that it fits nicely
1905  // into a 4-byte aligned bitmap.
1906  //
1907  // We'll also allocate the bitmap header itself part of the same buffer.
1908  //
1909  Size = Size * 1024;
1911  BitMapSize = (ULONG)Size;
1912  Size = sizeof(RTL_BITMAP) + (((Size + 31) / 32) * sizeof(ULONG));
1913 
1914  //
1915  // Allocate the allocation bitmap, which tells us which regions have not yet
1916  // been mapped into memory
1917  //
1919  Size,
1920  TAG_MM);
1922 
1923  //
1924  // Initialize it such that at first, only the first page's worth of PTEs is
1925  // marked as allocated (incidentially, the first PDE we allocated earlier).
1926  //
1929  BitMapSize);
1932 
1933  //
1934  // We have a second bitmap, which keeps track of where allocations end.
1935  // Given the allocation bitmap and a base address, we can therefore figure
1936  // out which page is the last page of that allocation, and thus how big the
1937  // entire allocation is.
1938  //
1940  Size,
1941  TAG_MM);
1945  BitMapSize);
1946 
1947  //
1948  // Since no allocations have been made yet, there are no bits set as the end
1949  //
1951 
1952  //
1953  // Initialize paged pool.
1954  //
1956 
1957  /* Initialize special pool */
1959 
1960  /* Default low threshold of 30MB or one fifth of paged pool */
1961  MiLowPagedPoolThreshold = (30 * _1MB) >> PAGE_SHIFT;
1963 
1964  /* Default high threshold of 60MB or 25% */
1965  MiHighPagedPoolThreshold = (60 * _1MB) >> PAGE_SHIFT;
1968 
1969  /* Setup the global session space */
1971 }
1972 
1973 VOID
1974 NTAPI
1977 {
1978  PLIST_ENTRY NextEntry;
1980  PFN_NUMBER TotalPages = 0;
1981  PCHAR
1982  MemType[] =
1983  {
1984  "ExceptionBlock ",
1985  "SystemBlock ",
1986  "Free ",
1987  "Bad ",
1988  "LoadedProgram ",
1989  "FirmwareTemporary ",
1990  "FirmwarePermanent ",
1991  "OsloaderHeap ",
1992  "OsloaderStack ",
1993  "SystemCode ",
1994  "HalCode ",
1995  "BootDriver ",
1996  "ConsoleInDriver ",
1997  "ConsoleOutDriver ",
1998  "StartupDpcStack ",
1999  "StartupKernelStack",
2000  "StartupPanicStack ",
2001  "StartupPcrPage ",
2002  "StartupPdrPage ",
2003  "RegistryData ",
2004  "MemoryData ",
2005  "NlsData ",
2006  "SpecialMemory ",
2007  "BBTMemory ",
2008  "LoaderReserve ",
2009  "LoaderXIPRom "
2010  };
2011 
2012  DPRINT1("Base\t\tLength\t\tType\n");
2013  for (NextEntry = KeLoaderBlock->MemoryDescriptorListHead.Flink;
2014  NextEntry != &KeLoaderBlock->MemoryDescriptorListHead;
2015  NextEntry = NextEntry->Flink)
2016  {
2017  Md = CONTAINING_RECORD(NextEntry, MEMORY_ALLOCATION_DESCRIPTOR, ListEntry);
2018  DPRINT1("%08lX\t%08lX\t%s\n", Md->BasePage, Md->PageCount, MemType[Md->MemoryType]);
2019  TotalPages += Md->PageCount;
2020  }
2021 
2022  DPRINT1("Total: %08lX (%lu MB)\n", (ULONG)TotalPages, (ULONG)(TotalPages * PAGE_SIZE) / 1024 / 1024);
2023 }
2024 
2025 BOOLEAN
2026 NTAPI
2029  IN PLOADER_PARAMETER_BLOCK LoaderBlock)
2030 {
2031  ULONG i;
2032  BOOLEAN IncludeType[LoaderMaximum];
2033  PVOID Bitmap;
2035  PFN_NUMBER PageCount;
2036 #if DBG
2037  ULONG j;
2038  PMMPTE PointerPte, TestPte;
2039  MMPTE TempPte;
2040 #endif
2041 
2042  /* Dump memory descriptors */
2044 
2045  //
2046  // Instantiate memory that we don't consider RAM/usable
2047  // We use the same exclusions that Windows does, in order to try to be
2048  // compatible with WinLDR-style booting
2049  //
2050  for (i = 0; i < LoaderMaximum; i++) IncludeType[i] = TRUE;
2051  IncludeType[LoaderBad] = FALSE;
2052  IncludeType[LoaderFirmwarePermanent] = FALSE;
2053  IncludeType[LoaderSpecialMemory] = FALSE;
2054  IncludeType[LoaderBBTMemory] = FALSE;
2055  if (Phase == 0)
2056  {
2057  /* Count physical pages on the system */
2058  MiScanMemoryDescriptors(LoaderBlock);
2059 
2060  /* Initialize the phase 0 temporary event */
2061  KeInitializeEvent(&MiTempEvent, NotificationEvent, FALSE);
2062 
2063  /* Set all the events to use the temporary event for now */
2064  MiLowMemoryEvent = &MiTempEvent;
2065  MiHighMemoryEvent = &MiTempEvent;
2066  MiLowPagedPoolEvent = &MiTempEvent;
2067  MiHighPagedPoolEvent = &MiTempEvent;
2068  MiLowNonPagedPoolEvent = &MiTempEvent;
2069  MiHighNonPagedPoolEvent = &MiTempEvent;
2070 
2071  //
2072  // Define the basic user vs. kernel address space separation
2073  //
2077 
2078  /* Highest PTE and PDE based on the addresses above */
2079  MiHighestUserPte = MiAddressToPte(MmHighestUserAddress);
2080  MiHighestUserPde = MiAddressToPde(MmHighestUserAddress);
2081 #if (_MI_PAGING_LEVELS >= 3)
2082  MiHighestUserPpe = MiAddressToPpe(MmHighestUserAddress);
2083 #if (_MI_PAGING_LEVELS >= 4)
2084  MiHighestUserPxe = MiAddressToPxe(MmHighestUserAddress);
2085 #endif
2086 #endif
2087  //
2088  // Get the size of the boot loader's image allocations and then round
2089  // that region up to a PDE size, so that any PDEs we might create for
2090  // whatever follows are separate from the PDEs that boot loader might've
2091  // already created (and later, we can blow all that away if we want to).
2092  //
2097 
2098  /* Initialize session space address layout */
2100 
2101  /* Set the based section highest address */
2103 
2104 #if DBG
2105  /* The subection PTE format depends on things being 8-byte aligned */
2106  ASSERT((sizeof(CONTROL_AREA) % 8) == 0);
2107  ASSERT((sizeof(SUBSECTION) % 8) == 0);
2108 
2109  /* Prototype PTEs are assumed to be in paged pool, so check if the math works */
2110  PointerPte = (PMMPTE)MmPagedPoolStart;
2111  MI_MAKE_PROTOTYPE_PTE(&TempPte, PointerPte);
2112  TestPte = MiProtoPteToPte(&TempPte);
2113  ASSERT(PointerPte == TestPte);
2114 
2115  /* Try the last nonpaged pool address */
2116  PointerPte = (PMMPTE)MI_NONPAGED_POOL_END;
2117  MI_MAKE_PROTOTYPE_PTE(&TempPte, PointerPte);
2118  TestPte = MiProtoPteToPte(&TempPte);
2119  ASSERT(PointerPte == TestPte);
2120 
2121  /* Try a bunch of random addresses near the end of the address space */
2122  PointerPte = (PMMPTE)0xFFFC8000;
2123  for (j = 0; j < 20; j += 1)
2124  {
2125  MI_MAKE_PROTOTYPE_PTE(&TempPte, PointerPte);
2126  TestPte = MiProtoPteToPte(&TempPte);
2127  ASSERT(PointerPte == TestPte);
2128  PointerPte++;
2129  }
2130 
2131  /* Subsection PTEs are always in nonpaged pool, pick a random address to try */
2132  PointerPte = (PMMPTE)0xFFAACBB8;
2133  MI_MAKE_SUBSECTION_PTE(&TempPte, PointerPte);
2134  TestPte = MiSubsectionPteToSubsection(&TempPte);
2135  ASSERT(PointerPte == TestPte);
2136 #endif
2137 
2138  /* Loop all 8 standby lists */
2139  for (i = 0; i < 8; i++)
2140  {
2141  /* Initialize them */
2146  }
2147 
2148  /* Initialize the user mode image list */
2150 
2151  /* Initialize critical section timeout value (relative time is negative) */
2152  MmCriticalSectionTimeout.QuadPart = MmCritsectTimeoutSeconds * (-10000000LL);
2153 
2154  /* Initialize the paged pool mutex and the section commit mutex */
2158 
2159  /* Initialize the Loader Lock */
2161 
2162  /* Set the zero page event */
2165 
2166  /* Initialize the dead stack S-LIST */
2168 
2169  //
2170  // Check if this is a machine with less than 19MB of RAM
2171  //
2172  PageCount = MmNumberOfPhysicalPages;
2173  if (PageCount < MI_MIN_PAGES_FOR_SYSPTE_TUNING)
2174  {
2175  //
2176  // Use the very minimum of system PTEs
2177  //
2178  MmNumberOfSystemPtes = 7000;
2179  }
2180  else
2181  {
2182  //
2183  // Use the default
2184  //
2185  MmNumberOfSystemPtes = 11000;
2186  if (PageCount > MI_MIN_PAGES_FOR_SYSPTE_BOOST)
2187  {
2188  //
2189  // Double the amount of system PTEs
2190  //
2191  MmNumberOfSystemPtes <<= 1;
2192  }
2193  if (PageCount > MI_MIN_PAGES_FOR_SYSPTE_BOOST_BOOST)
2194  {
2195  //
2196  // Double the amount of system PTEs
2197  //
2198  MmNumberOfSystemPtes <<= 1;
2199  }
2200  if (MmSpecialPoolTag != 0 && MmSpecialPoolTag != -1)
2201  {
2202  //
2203  // Add some extra PTEs for special pool
2204  //
2205  MmNumberOfSystemPtes += 0x6000;
2206  }
2207  }
2208 
2209  DPRINT("System PTE count has been tuned to %lu (%lu bytes)\n",
2211 
2212  /* Check if no values are set for the heap limits */
2213  if (MmHeapSegmentReserve == 0)
2214  {
2215  MmHeapSegmentReserve = 2 * _1MB;
2216  }
2217 
2218  if (MmHeapSegmentCommit == 0)
2219  {
2221  }
2222 
2224  {
2226  }
2227 
2229  {
2231  }
2232 
2233  /* Initialize the working set lock */
2234  ExInitializePushLock(&MmSystemCacheWs.WorkingSetMutex);
2235 
2236  /* Set commit limit */
2237  MmTotalCommitLimit = 2 * _1GB;
2239 
2240  /* Has the allocation fragment been setup? */
2241  if (!MmAllocationFragment)
2242  {
2243  /* Use the default value */
2245  if (PageCount < ((256 * _1MB) / PAGE_SIZE))
2246  {
2247  /* On memory systems with less than 256MB, divide by 4 */
2249  }
2250  else if (PageCount < (_1GB / PAGE_SIZE))
2251  {
2252  /* On systems with less than 1GB, divide by 2 */
2254  }
2255  }
2256  else
2257  {
2258  /* Convert from 1KB fragments to pages */
2261 
2262  /* Don't let it past the maximum */
2265 
2266  /* Don't let it too small either */
2269  }
2270 
2271  /* Check for kernel stack size that's too big */
2273  {
2274  /* Sanitize to default value */
2276  }
2277  else
2278  {
2279  /* Take the registry setting, and convert it into bytes */
2281 
2282  /* Now align it to a page boundary */
2284 
2285  /* Sanity checks */
2287  ASSERT((MmLargeStackSize & (PAGE_SIZE - 1)) == 0);
2288 
2289  /* Make sure it's not too low */
2291  }
2292 
2293  /* Compute color information (L2 cache-separated paging lists) */
2295 
2296  // Calculate the number of bytes for the PFN database
2297  // then add the color tables and convert to pages
2298  MxPfnAllocation = (MmHighestPhysicalPage + 1) * sizeof(MMPFN);
2301 
2302  // We have to add one to the count here, because in the process of
2303  // shifting down to the page size, we actually ended up getting the
2304  // lower aligned size (so say, 0x5FFFF bytes is now 0x5F pages).
2305  // Later on, we'll shift this number back into bytes, which would cause
2306  // us to end up with only 0x5F000 bytes -- when we actually want to have
2307  // 0x60000 bytes.
2308  MxPfnAllocation++;
2309 
2310  /* Initialize the platform-specific parts */
2311  MiInitMachineDependent(LoaderBlock);
2312 
2313  //
2314  // Build the physical memory block
2315  //
2316  MmPhysicalMemoryBlock = MmInitializeMemoryLimits(LoaderBlock,
2317  IncludeType);
2318 
2319  //
2320  // Allocate enough buffer for the PFN bitmap
2321  // Align it up to a 32-bit boundary
2322  //
2324  (((MmHighestPhysicalPage + 1) + 31) / 32) * 4,
2325  TAG_MM);
2326  if (!Bitmap)
2327  {
2328  //
2329  // This is critical
2330  //
2331  KeBugCheckEx(INSTALL_MORE_MEMORY,
2335  0x101);
2336  }
2337 
2338  //
2339  // Initialize it and clear all the bits to begin with
2340  //
2341  RtlInitializeBitMap(&MiPfnBitMap,
2342  Bitmap,
2344  RtlClearAllBits(&MiPfnBitMap);
2345 
2346  //
2347  // Loop physical memory runs
2348  //
2349  for (i = 0; i < MmPhysicalMemoryBlock->NumberOfRuns; i++)
2350  {
2351  //
2352  // Get the run
2353  //
2354  Run = &MmPhysicalMemoryBlock->Run[i];
2355  DPRINT("PHYSICAL RAM [0x%08p to 0x%08p]\n",
2356  Run->BasePage << PAGE_SHIFT,
2357  (Run->BasePage + Run->PageCount) << PAGE_SHIFT);
2358 
2359  //
2360  // Make sure it has pages inside it
2361  //
2362  if (Run->PageCount)
2363  {
2364  //
2365  // Set the bits in the PFN bitmap
2366  //
2367  RtlSetBits(&MiPfnBitMap, (ULONG)Run->BasePage, (ULONG)Run->PageCount);
2368  }
2369  }
2370 
2371  /* Look for large page cache entries that need caching */
2373 
2374  /* Loop for HAL Heap I/O device mappings that need coherency tracking */
2376 
2377  /* Set the initial resident page count */
2379 
2380  /* Initialize large page structures on PAE/x64, and MmProcessList on x86 */
2382 
2383  /* Check if the registry says any drivers should be loaded with large pages */
2385 
2386  /* Relocate the boot drivers into system PTE space and fixup their PFNs */
2387  MiReloadBootLoadedDrivers(LoaderBlock);
2388 
2389  /* FIXME: Call out into Driver Verifier for initialization */
2390 
2391  /* Check how many pages the system has */
2392  if (MmNumberOfPhysicalPages <= ((13 * _1MB) / PAGE_SIZE))
2393  {
2394  /* Set small system */
2397  }
2398  else if (MmNumberOfPhysicalPages <= ((19 * _1MB) / PAGE_SIZE))
2399  {
2400  /* Set small system and add 100 pages for the cache */
2402  MmSystemCacheWsMinimum += 100;
2404  }
2405  else
2406  {
2407  /* Set medium system and add 400 pages for the cache */
2409  MmSystemCacheWsMinimum += 400;
2411  }
2412 
2413  /* Check for less than 24MB */
2414  if (MmNumberOfPhysicalPages < ((24 * _1MB) / PAGE_SIZE))
2415  {
2416  /* No more than 32 pages */
2418  }
2419 
2420  /* Check for more than 32MB */
2421  if (MmNumberOfPhysicalPages >= ((32 * _1MB) / PAGE_SIZE))
2422  {
2423  /* Check for product type being "Wi" for WinNT */
2424  if (MmProductType == '\0i\0W')
2425  {
2426  /* Then this is a large system */
2428  }
2429  else
2430  {
2431  /* For servers, we need 64MB to consider this as being large */
2432  if (MmNumberOfPhysicalPages >= ((64 * _1MB) / PAGE_SIZE))
2433  {
2434  /* Set it as large */
2436  }
2437  }
2438  }
2439 
2440  /* Check for more than 33 MB */
2441  if (MmNumberOfPhysicalPages > ((33 * _1MB) / PAGE_SIZE))
2442  {
2443  /* Add another 500 pages to the cache */
2444  MmSystemCacheWsMinimum += 500;
2445  }
2446 
2447  /* Now setup the shared user data fields */
2448  ASSERT(SharedUserData->NumberOfPhysicalPages == 0);
2449  SharedUserData->NumberOfPhysicalPages = MmNumberOfPhysicalPages;
2450  SharedUserData->LargePageMinimum = 0;
2451 
2452  /* Check for workstation (Wi for WinNT) */
2453  if (MmProductType == '\0i\0W')
2454  {
2455  /* Set Windows NT Workstation product type */
2456  SharedUserData->NtProductType = NtProductWinNt;
2457  MmProductType = 0;
2458  }
2459  else
2460  {
2461  /* Check for LanMan server (La for LanmanNT) */
2462  if (MmProductType == '\0a\0L')
2463  {
2464  /* This is a domain controller */
2465  SharedUserData->NtProductType = NtProductLanManNt;
2466  }
2467  else
2468  {
2469  /* Otherwise it must be a normal server (Se for ServerNT) */
2470  SharedUserData->NtProductType = NtProductServer;
2471  }
2472 
2473  /* Set the product type, and make the system more aggressive with low memory */
2474  MmProductType = 1;
2475  MmMinimumFreePages = 81;
2476  }
2477 
2478  /* Update working set tuning parameters */
2480 
2481  /* Finetune the page count by removing working set and NP expansion */
2485  if (MmResidentAvailablePages <= 0)
2486  {
2487  /* This should not happen */
2488  DPRINT1("System cache working set too big\n");
2489  return FALSE;
2490  }
2491 
2492  /* Initialize the system cache */
2493  //MiInitializeSystemCache(MmSystemCacheWsMinimum, MmAvailablePages);
2494 
2495  /* Update the commit limit */
2497  if (MmTotalCommitLimit > 1024) MmTotalCommitLimit -= 1024;
2499 
2500  /* Size up paged pool and build the shadow system page directory */
2501  MiBuildPagedPool();
2502 
2503  /* Debugger physical memory support is now ready to be used */
2505 
2506  /* Initialize the loaded module list */
2507  MiInitializeLoadedModuleList(LoaderBlock);
2508  }
2509 
2510  //
2511  // Always return success for now
2512  //
2513  return TRUE;
2514 }
2515 
2516 /* EOF */
DWORD *typedef PVOID
Definition: winlogon.h:52
PVOID MmPagedPoolEnd
Definition: mminit.c:105
signed char * PCHAR
Definition: retypes.h:7
MMSUPPORT MmSystemCacheWs
Definition: mminit.c:245
PFN_NUMBER MmResidentAvailableAtInit
Definition: freelist.c:28
PRTL_BITMAP PagedPoolAllocationMap
Definition: mm.h:410
PMMPTE MiSessionLastPte
Definition: mminit.c:146
VOID NTAPI INIT_FUNCTION MiMapPfnDatabase(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
Definition: mminit.c:662
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:467
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:367
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
Definition: client.c:21
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:46
#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:867
NTSYSAPI void WINAPI RtlInitializeBitMap(PRTL_BITMAP, PULONG, ULONG)
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
PVOID Blink
Definition: miarm.h:409
#define KeLowerIrql(oldIrql)
Definition: env_spec_w32.h:602
NTSTATUS NTAPI INIT_FUNCTION MiInitMachineDependent(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
Definition: init.c:675
struct _RTL_BITMAP RTL_BITMAP
#define MI_MIN_PAGES_FOR_SYSPTE_BOOST_BOOST
Definition: mm.h:47
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:62
#define MiAddressToPde(x)
Definition: mmx86.c:20
struct _Entry Entry
Definition: kefuncs.h:640
#define MI_NONPAGED_POOL_END
Definition: mm.h:23
PMMPTE MiSessionImagePteStart
Definition: mminit.c:143
KGUARDED_MUTEX MmSectionBasedMutex
Definition: section.c:110
#define DbgPrint
Definition: loader.c:26
#define MM_HAL_VA_END
Definition: ketypes.h:257
Definition: bidi.c:75
PVOID MmSessionBase
Definition: mminit.c:134
ULONG PFN_COUNT
Definition: mmtypes.h:102
PFN_NUMBER MiLowNonPagedPoolThreshold
Definition: mminit.c:303
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:368
PFN_COUNT MmNumberOfPhysicalPages
Definition: mminit.c:212
SIZE_T MmMinimumNonPagedPoolSize
Definition: mminit.c:39
BOOLEAN MiDbgEnableMdDump
Definition: mminit.c:372
PFN_NUMBER PageCount
Definition: miarm.h:396
SIZE_T MmSessionViewSize
Definition: mminit.c:136
FORCEINLINE struct _KPRCB * KeGetCurrentPrcb(VOID)
Definition: ketypes.h:1054
PFN_NUMBER Flink
Definition: mm.h:305
ULONG MmCritsectTimeoutSeconds
Definition: mminit.c:386
VOID NTAPI INIT_FUNCTION MmFreeLoaderBlock(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
Definition: mminit.c:1083
#define MI_MAX_SECONDARY_COLORS
Definition: mm.h:68
#define EVENT_QUERY_STATE
Definition: security.c:56
HARDWARE_PDE_ARMV6 TempPde
Definition: winldr.c:77
PKEVENT MiLowPagedPoolEvent
Definition: mminit.c:293
SIZE_T MmTotalCommitLimitMaximum
Definition: mminit.c:359
ULONG MmLargeStackSize
Definition: mminit.c:261
VOID NTAPI MiScanMemoryDescriptors(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
Definition: mminit.c:393
VOID NTAPI INIT_FUNCTION MiInitializeColorTables(VOID)
Definition: mminit.c:552
_Inout_ __drv_aliasesMem PSLIST_ENTRY _Inout_ PSLIST_ENTRY _In_ ULONG Count
Definition: exfuncs.h:1015
#define OBJ_PERMANENT
Definition: winternl.h:226
#define _1KB
Definition: miarm.h:12
#define KERNEL_LARGE_STACK_SIZE
paddr_t NextPage
Definition: mmuobject.c:64
union _MMPFN::@1569 u4
VOID NTAPI MiInitializePfnForOtherProcess(IN PFN_NUMBER PageFrameIndex, IN PVOID PteAddress, IN PFN_NUMBER PteFrame)
Definition: pfnlist.c:1280
PFN_NUMBER NumberOfPages
Definition: miarm.h:402
#define PD_COUNT
Definition: miarm.h:29
PMMPTE FORCEINLINE MiAddressToPpe(PVOID Address)
Definition: mm.h:138
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:403
PFN_NUMBER NTAPI INIT_FUNCTION MxGetNextPage(IN PFN_NUMBER PageCount)
Definition: mminit.c:473
VOID NTAPI INIT_FUNCTION MiBuildPfnDatabaseSelf(VOID)
Definition: mminit.c:1034
union _MMPFN::@1564 u1
PFN_NUMBER MmAvailablePages
Definition: freelist.c:26
KMUTANT MmSystemLoadLock
Definition: sysldr.c:39
PFN_NUMBER MiHighNonPagedPoolThreshold
Definition: mminit.c:304
LONG NTAPI KeSetEvent(IN PKEVENT Event, IN KPRIORITY Increment, IN BOOLEAN Wait)
Definition: eventobj.c:159
#define MI_WRITE_VALID_PPE
Definition: mm.h:110
PFN_NUMBER MmSystemCacheWsMinimum
Definition: mminit.c:335
SIZE_T MmSizeOfNonPagedPoolInBytes
Definition: mminit.c:26
VOID NTAPI INIT_FUNCTION MiBuildPfnDatabaseFromLoaderBlock(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
Definition: mminit.c:890
#define PAGE_ROUND_UP(x)
Definition: scsiport_int.h:13
NTSYSAPI NTSTATUS WINAPI RtlAddAccessAllowedAce(PACL, DWORD, DWORD, PSID)
POBJECT_TYPE ExEventObjectType
Definition: event.c:22
#define KeGetPcr()
Definition: ke.h:25
USHORT PageLocation
Definition: mm.h:293
PMMPFN MmPfnDatabase
Definition: freelist.c:24
PFN_NUMBER Flink
Definition: mm.h:369
PKEVENT MiHighPagedPoolEvent
Definition: mminit.c:294
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:380
USHORT PrototypePte
Definition: mm.h:291
#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:321
enum _MM_SYSTEM_SIZE MM_SYSTEMSIZE
UCHAR KIRQL
Definition: env_spec_w32.h:591
MMPFNENTRY e1
Definition: mm.h:325
TYPE_OF_MEMORY MemoryType
Definition: arc.h:193
PMMPTE MiSessionBasePte
Definition: mminit.c:145
union _MMPFN::@1566 u3
#define PDE_COUNT
Definition: miarm.h:30
GLenum GLclampf GLint i
Definition: glfuncs.h:14
USHORT CacheAttribute
Definition: mm.h:295
#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:388
BOOLEAN MmZeroingPageThreadActive
Definition: zeropage.c:20
ULONG PFN_NUMBER
Definition: ke.h:8
#define MI_SECONDARY_COLORS
Definition: mm.h:67
#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:111
VOID NTAPI INIT_FUNCTION MiInitializePfnDatabase(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
Definition: mminit.c:1064
PMMPTE LastPteForPagedPool
Definition: mm.h:413
PFN_NUMBER MiNumberOfFreePages
Definition: mminit.c:383
#define FALSE
Definition: types.h:117
FORCEINLINE VOID MI_WRITE_VALID_PTE(IN PMMPTE PointerPte, IN MMPTE TempPte)
Definition: miarm.h:914
ULONG_PTR ShareCount
Definition: mm.h:318
PVOID MiSessionSpaceEnd
Definition: mminit.c:127
PFN_NUMBER BasePage
Definition: miarm.h:395
#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:370
struct _MMCOLOR_TABLES * PMMCOLOR_TABLES
PVOID MiSystemViewStart
Definition: mminit.c:154
PFN_NUMBER Flink
Definition: miarm.h:408
#define MI_SET_PROCESS2(x)
Definition: mm.h:250
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
FORCEINLINE VOID MI_MAKE_SUBSECTION_PTE(IN PMMPTE NewPte, IN PVOID Segment)
Definition: mm.h:245
MM_PAGED_POOL_INFO MmPagedPoolInfo
Definition: pool.c:25
#define MI_SYSTEM_CACHE_WS_START
Definition: mm.h:14
struct _ACL ACL
smooth NULL
Definition: ftsmooth.c:557
PVOID FORCEINLINE MiPteToAddress(PMMPTE PointerPte)
Definition: mm.h:185
NTSYSAPI NTSTATUS WINAPI RtlSetDaclSecurityDescriptor(PSECURITY_DESCRIPTOR, BOOLEAN, PACL, BOOLEAN)
#define MiProtoPteToPte(x)
Definition: mm.h:234
PVOID MmSystemRangeStart
Definition: mminit.c:230
KEVENT MmZeroingPageEvent
Definition: zeropage.c:21
void DPRINT(...)
Definition: polytest.cpp:61
#define ExInitializePushLock
Definition: ex.h:943
VOID NTAPI MiDecrementShareCount(IN PMMPFN Pfn1, IN PFN_NUMBER PageFrameIndex)
Definition: pfnlist.c:1133
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:969
#define MI_SET_USAGE(x)
Definition: mm.h:249
BOOLEAN NTAPI INIT_FUNCTION MiIsRegularMemory(IN PLOADER_PARAMETER_BLOCK LoaderBlock, IN PFN_NUMBER Pfn)
Definition: mminit.c:603
PPHYSICAL_MEMORY_DESCRIPTOR NTAPI INIT_FUNCTION MmInitializeMemoryLimits(IN PLOADER_PARAMETER_BLOCK LoaderBlock, IN PBOOLEAN IncludeType)
Definition: mminit.c:1612
PPHYSICAL_MEMORY_DESCRIPTOR MmPhysicalMemoryBlock
Definition: mminit.c:206
VOID NTAPI INIT_FUNCTION MiBuildPfnDatabaseFromPages(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
Definition: mminit.c:758
PLOADER_PARAMETER_BLOCK KeLoaderBlock
Definition: krnlinit.c:29
ULONG_PTR LoaderPagesSpanned
Definition: arc.h:356
VOID NTAPI INIT_FUNCTION MiBuildPagedPool(VOID)
Definition: mminit.c:1741
#define MM_EMPTY_LIST
Definition: mm.h:78
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:358
PMMPTE MmDebugPte
Definition: mmdbg.c:33
NTSYSAPI void WINAPI RtlClearAllBits(PRTL_BITMAP)
VOID NTAPI INIT_FUNCTION MiAdjustWorkingSetManagerParameters(IN BOOLEAN Client)
Definition: mminit.c:1193
PFN_NUMBER MmLowMemoryThreshold
Definition: mminit.c:299
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
#define PDE_MAPPED_VA
Definition: miarm.h:20
BOOLEAN NTAPI INIT_FUNCTION MmArmInitSystem(IN ULONG Phase, IN PLOADER_PARAMETER_BLOCK LoaderBlock)
Definition: mminit.c:2028
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
PVOID MmSystemCacheEnd
Definition: mminit.c:244
VOID NTAPI INIT_SECTION InitializePool(IN POOL_TYPE PoolType, IN ULONG Threshold)
Definition: expool.c:849
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:24
SIZE_T MmHeapDeCommitFreeBlockThreshold
Definition: mminit.c:368
#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:302
PFN_NUMBER MmHighestPhysicalPage
Definition: mminit.c:211
PMMPTE MiSessionImagePteEnd
Definition: mminit.c:144
MEMORY_ALLOCATION_DESCRIPTOR MxOldFreeDescriptor
Definition: mminit.c:272
PKEVENT MiHighNonPagedPoolEvent
Definition: mminit.c:296
PVOID MmHyperSpaceEnd
Definition: mminit.c:250
PMEMORY_ALLOCATION_DESCRIPTOR MxFreeDescriptor
Definition: mminit.c:271
VOID FASTCALL KeReleaseQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber, IN KIRQL OldIrql)
Definition: spinlock.c:154
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:31
UINTN VOID * Buffer
Definition: acefiex.h:370
BOOLEAN NTAPI INIT_FUNCTION MiInitializeMemoryEvents(VOID)
Definition: mminit.c:1329
PVOID MmHighSectionBase
Definition: section.c:111
SIZE_T MmMinimumStackCommitInBytes
Definition: mminit.c:369
struct tagRun Run
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:240
#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:94
ULONG MmSecondaryColorMask
Definition: mminit.c:256
#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:291
KEVENT MiTempEvent
Definition: mminit.c:288
MM_SYSTEMSIZE MmSystemSize
Definition: mminit.c:325
SIZE_T MmHeapSegmentReserve
Definition: mminit.c:365
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
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:803
LARGE_INTEGER MmCriticalSectionTimeout
Definition: mminit.c:387
#define MI_MIN_INIT_PAGED_POOLSIZE
Definition: mm.h:48
SLIST_HEADER MmDeadStackSListHead
Definition: procsup.c:23
Definition: mm.h:301
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
PMMPTE FORCEINLINE MiAddressToPxe(PVOID Address)
Definition: mm.h:148
#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:66
#define _1MB
Definition: miarm.h:13
#define SYNCHRONIZE
Definition: nt_native.h:61
LIST_HEAD(acpi_bus_event_list)
#define MI_MIN_PAGES_FOR_SYSPTE_TUNING
Definition: mm.h:45
PSID SeWorldSid
Definition: sid.c:31
KIRQL FASTCALL KeAcquireQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber)
Definition: spinlock.c:108
PKEVENT MiLowNonPagedPoolEvent
Definition: mminit.c:295
FORCEINLINE PMMPFN MiGetPfnEntry(IN PFN_NUMBER Pfn)
Definition: mm.h:873
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:15
VOID NTAPI INIT_FUNCTION MiNotifyMemoryEvents(VOID)
Definition: mminit.c:1208
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:161
#define HIGH_LEVEL
Definition: env_spec_w32.h:703
DWORD *typedef HANDLE
Definition: winlogon.h:52
VOID FASTCALL KeInitializeGuardedMutex(OUT PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:31
LONG NTSTATUS
Definition: DriverTester.h:11
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
PFN_NUMBER MmSystemCacheWsMaximum
Definition: mminit.c:336
#define ROUND_TO_PAGES(Size)
ULONG_PTR PteFrame
Definition: mm.h:346
ULONG MmMaxAdditionNonPagedPoolPerMb
Definition: mminit.c:42
FORCEINLINE VOID MI_MAKE_PROTOTYPE_PTE(IN PMMPTE NewPte, IN PMMPTE PointerPte)
Definition: mm.h:253
LIST_ENTRY MemoryDescriptorListHead
Definition: arc.h:494
PFN_NUMBER Total
Definition: mm.h:367
PRTL_BITMAP EndOfPagedPoolBitmap
Definition: mm.h:411
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
SIZE_T MmHeapSegmentCommit
Definition: mminit.c:366
PMMWSL MmSystemCacheWorkingSetList
Definition: mminit.c:174
PFN_NUMBER MmHighMemoryThreshold
Definition: mminit.c:300
USHORT Rom
Definition: mm.h:296
PMMPTE PteAddress
Definition: mm.h:314
VOID NTAPI INIT_FUNCTION MiInitializeDriverLargePageList(VOID)
Definition: largepag.c:68
VOID NTAPI INIT_FUNCTION MiAddHalIoMappings(VOID)
Definition: mminit.c:1408
unsigned int * PULONG
Definition: retypes.h:1
#define min(a, b)
Definition: monoChain.cc:55
VOID NTAPI INIT_FUNCTION MiComputeColorInformation(VOID)
Definition: mminit.c:498
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
struct _MMPFN::@1566::@1572 e2
PVOID MmNonPagedPoolEnd
Definition: mminit.c:99
#define ACL_REVISION
Definition: setypes.h:39
PMMCOLOR_TABLES MmFreePagesByColor[FreePageList+1]
Definition: mminit.c:285
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:301
ULONG MmMaximumDeadKernelStacks
Definition: procsup.c:22
ULONG MmProductType
Definition: mminit.c:324
unsigned int ULONG
Definition: retypes.h:1
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:259
VOID NTAPI INIT_FUNCTION MiDbgDumpMemoryDescriptors(VOID)
Definition: mminit.c:1976
PVOID MiSessionPoolEnd
Definition: mminit.c:132
#define EVENT_MODIFY_STATE
Definition: winbase.h:161
#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:1464
NTSTATUS NTAPI INIT_FUNCTION MiCreateMemoryEvent(IN PUNICODE_STRING Name, OUT PKEVENT *Event)
Definition: mminit.c:1234
PFN_NUMBER Count
Definition: miarm.h:410
ULONG_PTR InPageError
Definition: mm.h:347
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1097
union _MMPTE::@2072 u
PVOID MmNonPagedPoolExpansionStart
Definition: mminit.c:98
PMMPTE FirstPteForPagedPool
Definition: mm.h:412
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:61
KGUARDED_MUTEX MmSectionCommitMutex
Definition: section.c:108
FORCEINLINE BOOLEAN MI_IS_PHYSICAL_ADDRESS(IN PVOID Address)
Definition: miarm.h:900
#define OBJ_KERNEL_HANDLE
Definition: winternl.h:231
SIZE_T MmSystemViewSize
Definition: mminit.c:155
#define MI_MIN_ALLOCATION_FRAGMENT
Definition: mm.h:60
union _MMPFN::@1565 u2
#define PFN_FROM_PTE(v)
Definition: mm.h:82
BOOLEAN MmLargeSystemCache
Definition: mminit.c:339
PKEVENT MiHighMemoryEvent
Definition: mminit.c:292
VOID NTAPI KeBugCheckEx(_In_ ULONG BugCheckCode, _In_ ULONG_PTR BugCheckParameter1, _In_ ULONG_PTR BugCheckParameter2, _In_ ULONG_PTR BugCheckParameter3, _In_ ULONG_PTR BugCheckParameter4)
Definition: rtlcompat.c:90
PFN_NUMBER MmMinimumFreePages
Definition: mminit.c:313
VOID NTAPI KeFlushCurrentTb(VOID)
Definition: cpu.c:332
LONGLONG QuadPart
Definition: typedefs.h:112
#define _1GB
Definition: miarm.h:14
PMMPDE NextPdeForPagedPoolExpansion
Definition: mm.h:414
#define INIT_FUNCTION
Definition: ntoskrnl.h:11
WINBASEAPI VOID WINAPI InitializeSListHead(_Out_ PSLIST_HEADER ListHead)
Definition: rtlfuncs.h:3353
ULONG MmSecondaryColors
Definition: mminit.c:255
#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:351