ReactOS  r73918
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("-----------------------------------------\n");
1567 #if MI_TRACE_PFNS
1568  OtherPages = UsageBucket[MI_USAGE_BOOT_DRIVER];
1569  DbgPrint("Boot Images: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024);
1570  OtherPages = UsageBucket[MI_USAGE_DRIVER_PAGE];
1571  DbgPrint("System Drivers: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024);
1572  OtherPages = UsageBucket[MI_USAGE_PFN_DATABASE];
1573  DbgPrint("PFN Database: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024);
1574  OtherPages = UsageBucket[MI_USAGE_PAGE_TABLE] + UsageBucket[MI_USAGE_LEGACY_PAGE_DIRECTORY];
1575  DbgPrint("Page Tables: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024);
1576  OtherPages = UsageBucket[MI_USAGE_NONPAGED_POOL] + UsageBucket[MI_USAGE_NONPAGED_POOL_EXPANSION];
1577  DbgPrint("NonPaged Pool: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024);
1578  OtherPages = UsageBucket[MI_USAGE_PAGED_POOL];
1579  DbgPrint("Paged Pool: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024);
1580  OtherPages = UsageBucket[MI_USAGE_KERNEL_STACK] + UsageBucket[MI_USAGE_KERNEL_STACK_EXPANSION];
1581  DbgPrint("Kernel Stack: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024);
1582  OtherPages = UsageBucket[MI_USAGE_INIT_MEMORY];
1583  DbgPrint("Init Memory: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024);
1584  OtherPages = UsageBucket[MI_USAGE_SECTION];
1585  DbgPrint("Sections: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024);
1586  OtherPages = UsageBucket[MI_USAGE_CACHE];
1587  DbgPrint("Cache: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024);
1588 #endif
1589  KeLowerIrql(OldIrql);
1590 }
1591 
1593 NTAPI
1596  IN PBOOLEAN IncludeType)
1597 {
1598  PLIST_ENTRY NextEntry;
1599  ULONG Run = 0, InitialRuns;
1600  PFN_NUMBER NextPage = -1, PageCount = 0;
1603 
1604  //
1605  // Start with the maximum we might need
1606  //
1607  InitialRuns = MiNumberDescriptors;
1608 
1609  //
1610  // Allocate the maximum we'll ever need
1611  //
1613  sizeof(PHYSICAL_MEMORY_DESCRIPTOR) +
1614  sizeof(PHYSICAL_MEMORY_RUN) *
1615  (InitialRuns - 1),
1616  'lMmM');
1617  if (!Buffer) return NULL;
1618 
1619  //
1620  // For now that's how many runs we have
1621  //
1622  Buffer->NumberOfRuns = InitialRuns;
1623 
1624  //
1625  // Now loop through the descriptors again
1626  //
1627  NextEntry = LoaderBlock->MemoryDescriptorListHead.Flink;
1628  while (NextEntry != &LoaderBlock->MemoryDescriptorListHead)
1629  {
1630  //
1631  // Grab each one, and check if it's one we should include
1632  //
1633  MdBlock = CONTAINING_RECORD(NextEntry,
1635  ListEntry);
1636  if ((MdBlock->MemoryType < LoaderMaximum) &&
1637  (IncludeType[MdBlock->MemoryType]))
1638  {
1639  //
1640  // Add this to our running total
1641  //
1642  PageCount += MdBlock->PageCount;
1643 
1644  //
1645  // Check if the next page is described by the next descriptor
1646  //
1647  if (MdBlock->BasePage == NextPage)
1648  {
1649  //
1650  // Combine it into the same physical run
1651  //
1652  ASSERT(MdBlock->PageCount != 0);
1653  Buffer->Run[Run - 1].PageCount += MdBlock->PageCount;
1654  NextPage += MdBlock->PageCount;
1655  }
1656  else
1657  {
1658  //
1659  // Otherwise just duplicate the descriptor's contents
1660  //
1661  Buffer->Run[Run].BasePage = MdBlock->BasePage;
1662  Buffer->Run[Run].PageCount = MdBlock->PageCount;
1663  NextPage = Buffer->Run[Run].BasePage + Buffer->Run[Run].PageCount;
1664 
1665  //
1666  // And in this case, increase the number of runs
1667  //
1668  Run++;
1669  }
1670  }
1671 
1672  //
1673  // Try the next descriptor
1674  //
1675  NextEntry = MdBlock->ListEntry.Flink;
1676  }
1677 
1678  //
1679  // We should not have been able to go past our initial estimate
1680  //
1681  ASSERT(Run <= Buffer->NumberOfRuns);
1682 
1683  //
1684  // Our guess was probably exaggerated...
1685  //
1686  if (InitialRuns > Run)
1687  {
1688  //
1689  // Allocate a more accurately sized buffer
1690  //
1691  NewBuffer = ExAllocatePoolWithTag(NonPagedPool,
1692  sizeof(PHYSICAL_MEMORY_DESCRIPTOR) +
1693  sizeof(PHYSICAL_MEMORY_RUN) *
1694  (Run - 1),
1695  'lMmM');
1696  if (NewBuffer)
1697  {
1698  //
1699  // Copy the old buffer into the new, then free it
1700  //
1701  RtlCopyMemory(NewBuffer->Run,
1702  Buffer->Run,
1703  sizeof(PHYSICAL_MEMORY_RUN) * Run);
1704  ExFreePoolWithTag(Buffer, 'lMmM');
1705 
1706  //
1707  // Now use the new buffer
1708  //
1709  Buffer = NewBuffer;
1710  }
1711  }
1712 
1713  //
1714  // Write the final numbers, and return it
1715  //
1716  Buffer->NumberOfRuns = Run;
1717  Buffer->NumberOfPages = PageCount;
1718  return Buffer;
1719 }
1720 
1721 VOID
1722 NTAPI
1725 {
1726  PMMPTE PointerPte;
1727  PMMPDE PointerPde;
1729  PFN_NUMBER PageFrameIndex;
1730  KIRQL OldIrql;
1731  SIZE_T Size;
1732  ULONG BitMapSize;
1733 #if (_MI_PAGING_LEVELS >= 3)
1734  MMPPE TempPpe = ValidKernelPpe;
1735  PMMPPE PointerPpe;
1736 #elif (_MI_PAGING_LEVELS == 2)
1738 
1739  //
1740  // Get the page frame number for the system page directory
1741  //
1742  PointerPte = MiAddressToPte(PDE_BASE);
1743  ASSERT(PD_COUNT == 1);
1744  MmSystemPageDirectory[0] = PFN_FROM_PTE(PointerPte);
1745 
1746  //
1747  // Allocate a system PTE which will hold a copy of the page directory
1748  //
1749  PointerPte = MiReserveSystemPtes(1, SystemPteSpace);
1750  ASSERT(PointerPte);
1751  MmSystemPagePtes = MiPteToAddress(PointerPte);
1752 
1753  //
1754  // Make this system PTE point to the system page directory.
1755  // It is now essentially double-mapped. This will be used later for lazy
1756  // evaluation of PDEs accross process switches, similarly to how the Global
1757  // page directory array in the old ReactOS Mm is used (but in a less hacky
1758  // way).
1759  //
1760  TempPte = ValidKernelPte;
1761  ASSERT(PD_COUNT == 1);
1763  MI_WRITE_VALID_PTE(PointerPte, TempPte);
1764 #endif
1765  //
1766  // Let's get back to paged pool work: size it up.
1767  // By default, it should be twice as big as nonpaged pool.
1768  //
1772  {
1773  //
1774  // On the other hand, we have limited VA space, so make sure that the VA
1775  // for paged pool doesn't overflow into nonpaged pool VA. Otherwise, set
1776  // whatever maximum is possible.
1777  //
1780  }
1781 
1782  //
1783  // Get the size in pages and make sure paged pool is at least 32MB.
1784  //
1785  Size = MmSizeOfPagedPoolInBytes;
1787  Size = BYTES_TO_PAGES(Size);
1788 
1789  //
1790  // Now check how many PTEs will be required for these many pages.
1791  //
1792  Size = (Size + (1024 - 1)) / 1024;
1793 
1794  //
1795  // Recompute the page-aligned size of the paged pool, in bytes and pages.
1796  //
1797  MmSizeOfPagedPoolInBytes = Size * PAGE_SIZE * 1024;
1799 
1800  //
1801  // Let's be really sure this doesn't overflow into nonpaged system VA
1802  //
1803  ASSERT((MmSizeOfPagedPoolInBytes + (ULONG_PTR)MmPagedPoolStart) <=
1805 
1806  //
1807  // This is where paged pool ends
1808  //
1809  MmPagedPoolEnd = (PVOID)(((ULONG_PTR)MmPagedPoolStart +
1811 
1812  //
1813  // Lock the PFN database
1814  //
1816 
1817 #if (_MI_PAGING_LEVELS >= 3)
1818  /* On these systems, there's no double-mapping, so instead, the PPEs
1819  * are setup to span the entire paged pool area, so there's no need for the
1820  * system PD */
1821  for (PointerPpe = MiAddressToPpe(MmPagedPoolStart);
1822  PointerPpe <= MiAddressToPpe(MmPagedPoolEnd);
1823  PointerPpe++)
1824  {
1825  /* Check if the PPE is already valid */
1826  if (!PointerPpe->u.Hard.Valid)
1827  {
1828  /* It is not, so map a fresh zeroed page */
1829  TempPpe.u.Hard.PageFrameNumber = MiRemoveZeroPage(0);
1830  MI_WRITE_VALID_PPE(PointerPpe, TempPpe);
1831  }
1832  }
1833 #endif
1834 
1835  //
1836  // So now get the PDE for paged pool and zero it out
1837  //
1838  PointerPde = MiAddressToPde(MmPagedPoolStart);
1839  RtlZeroMemory(PointerPde,
1840  (1 + MiAddressToPde(MmPagedPoolEnd) - PointerPde) * sizeof(MMPDE));
1841 
1842  //
1843  // Next, get the first and last PTE
1844  //
1845  PointerPte = MiAddressToPte(MmPagedPoolStart);
1848 
1849  /* Allocate a page and map the first paged pool PDE */
1851  MI_SET_PROCESS2("Kernel");
1852  PageFrameIndex = MiRemoveZeroPage(0);
1853  TempPde.u.Hard.PageFrameNumber = PageFrameIndex;
1854  MI_WRITE_VALID_PDE(PointerPde, TempPde);
1855 #if (_MI_PAGING_LEVELS >= 3)
1856  /* Use the PPE of MmPagedPoolStart that was setup above */
1857 // Bla = PFN_FROM_PTE(PpeAddress(MmPagedPool...));
1858 
1859  /* Initialize the PFN entry for it */
1860  MiInitializePfnForOtherProcess(PageFrameIndex,
1861  (PMMPTE)PointerPde,
1862  PFN_FROM_PTE(MiAddressToPpe(MmPagedPoolStart)));
1863 #else
1864  /* Do it this way */
1865 // Bla = MmSystemPageDirectory[(PointerPde - (PMMPTE)PDE_BASE) / PDE_COUNT]
1866 
1867  /* Initialize the PFN entry for it */
1868  MiInitializePfnForOtherProcess(PageFrameIndex,
1869  (PMMPTE)PointerPde,
1870  MmSystemPageDirectory[(PointerPde - (PMMPDE)PDE_BASE) / PDE_COUNT]);
1871 #endif
1872 
1873  //
1874  // Release the PFN database lock
1875  //
1877 
1878  //
1879  // We only have one PDE mapped for now... at fault time, additional PDEs
1880  // will be allocated to handle paged pool growth. This is where they'll have
1881  // to start.
1882  //
1884 
1885  //
1886  // We keep track of each page via a bit, so check how big the bitmap will
1887  // have to be (make sure to align our page count such that it fits nicely
1888  // into a 4-byte aligned bitmap.
1889  //
1890  // We'll also allocate the bitmap header itself part of the same buffer.
1891  //
1892  Size = Size * 1024;
1894  BitMapSize = (ULONG)Size;
1895  Size = sizeof(RTL_BITMAP) + (((Size + 31) / 32) * sizeof(ULONG));
1896 
1897  //
1898  // Allocate the allocation bitmap, which tells us which regions have not yet
1899  // been mapped into memory
1900  //
1902  Size,
1903  TAG_MM);
1905 
1906  //
1907  // Initialize it such that at first, only the first page's worth of PTEs is
1908  // marked as allocated (incidentially, the first PDE we allocated earlier).
1909  //
1912  BitMapSize);
1915 
1916  //
1917  // We have a second bitmap, which keeps track of where allocations end.
1918  // Given the allocation bitmap and a base address, we can therefore figure
1919  // out which page is the last page of that allocation, and thus how big the
1920  // entire allocation is.
1921  //
1923  Size,
1924  TAG_MM);
1928  BitMapSize);
1929 
1930  //
1931  // Since no allocations have been made yet, there are no bits set as the end
1932  //
1934 
1935  //
1936  // Initialize paged pool.
1937  //
1939 
1940  /* Initialize special pool */
1942 
1943  /* Default low threshold of 30MB or one fifth of paged pool */
1944  MiLowPagedPoolThreshold = (30 * _1MB) >> PAGE_SHIFT;
1946 
1947  /* Default high threshold of 60MB or 25% */
1948  MiHighPagedPoolThreshold = (60 * _1MB) >> PAGE_SHIFT;
1951 
1952  /* Setup the global session space */
1954 }
1955 
1956 VOID
1957 NTAPI
1960 {
1961  PLIST_ENTRY NextEntry;
1963  PFN_NUMBER TotalPages = 0;
1964  PCHAR
1965  MemType[] =
1966  {
1967  "ExceptionBlock ",
1968  "SystemBlock ",
1969  "Free ",
1970  "Bad ",
1971  "LoadedProgram ",
1972  "FirmwareTemporary ",
1973  "FirmwarePermanent ",
1974  "OsloaderHeap ",
1975  "OsloaderStack ",
1976  "SystemCode ",
1977  "HalCode ",
1978  "BootDriver ",
1979  "ConsoleInDriver ",
1980  "ConsoleOutDriver ",
1981  "StartupDpcStack ",
1982  "StartupKernelStack",
1983  "StartupPanicStack ",
1984  "StartupPcrPage ",
1985  "StartupPdrPage ",
1986  "RegistryData ",
1987  "MemoryData ",
1988  "NlsData ",
1989  "SpecialMemory ",
1990  "BBTMemory ",
1991  "LoaderReserve ",
1992  "LoaderXIPRom "
1993  };
1994 
1995  DPRINT1("Base\t\tLength\t\tType\n");
1996  for (NextEntry = KeLoaderBlock->MemoryDescriptorListHead.Flink;
1997  NextEntry != &KeLoaderBlock->MemoryDescriptorListHead;
1998  NextEntry = NextEntry->Flink)
1999  {
2000  Md = CONTAINING_RECORD(NextEntry, MEMORY_ALLOCATION_DESCRIPTOR, ListEntry);
2001  DPRINT1("%08lX\t%08lX\t%s\n", Md->BasePage, Md->PageCount, MemType[Md->MemoryType]);
2002  TotalPages += Md->PageCount;
2003  }
2004 
2005  DPRINT1("Total: %08lX (%lu MB)\n", (ULONG)TotalPages, (ULONG)(TotalPages * PAGE_SIZE) / 1024 / 1024);
2006 }
2007 
2008 BOOLEAN
2009 NTAPI
2012  IN PLOADER_PARAMETER_BLOCK LoaderBlock)
2013 {
2014  ULONG i;
2015  BOOLEAN IncludeType[LoaderMaximum];
2016  PVOID Bitmap;
2018  PFN_NUMBER PageCount;
2019 #if DBG
2020  ULONG j;
2021  PMMPTE PointerPte, TestPte;
2022  MMPTE TempPte;
2023 #endif
2024 
2025  /* Dump memory descriptors */
2027 
2028  //
2029  // Instantiate memory that we don't consider RAM/usable
2030  // We use the same exclusions that Windows does, in order to try to be
2031  // compatible with WinLDR-style booting
2032  //
2033  for (i = 0; i < LoaderMaximum; i++) IncludeType[i] = TRUE;
2034  IncludeType[LoaderBad] = FALSE;
2035  IncludeType[LoaderFirmwarePermanent] = FALSE;
2036  IncludeType[LoaderSpecialMemory] = FALSE;
2037  IncludeType[LoaderBBTMemory] = FALSE;
2038  if (Phase == 0)
2039  {
2040  /* Count physical pages on the system */
2041  MiScanMemoryDescriptors(LoaderBlock);
2042 
2043  /* Initialize the phase 0 temporary event */
2044  KeInitializeEvent(&MiTempEvent, NotificationEvent, FALSE);
2045 
2046  /* Set all the events to use the temporary event for now */
2047  MiLowMemoryEvent = &MiTempEvent;
2048  MiHighMemoryEvent = &MiTempEvent;
2049  MiLowPagedPoolEvent = &MiTempEvent;
2050  MiHighPagedPoolEvent = &MiTempEvent;
2051  MiLowNonPagedPoolEvent = &MiTempEvent;
2052  MiHighNonPagedPoolEvent = &MiTempEvent;
2053 
2054  //
2055  // Define the basic user vs. kernel address space separation
2056  //
2060 
2061  /* Highest PTE and PDE based on the addresses above */
2062  MiHighestUserPte = MiAddressToPte(MmHighestUserAddress);
2063  MiHighestUserPde = MiAddressToPde(MmHighestUserAddress);
2064 #if (_MI_PAGING_LEVELS >= 3)
2065  MiHighestUserPpe = MiAddressToPpe(MmHighestUserAddress);
2066 #if (_MI_PAGING_LEVELS >= 4)
2067  MiHighestUserPxe = MiAddressToPxe(MmHighestUserAddress);
2068 #endif
2069 #endif
2070  //
2071  // Get the size of the boot loader's image allocations and then round
2072  // that region up to a PDE size, so that any PDEs we might create for
2073  // whatever follows are separate from the PDEs that boot loader might've
2074  // already created (and later, we can blow all that away if we want to).
2075  //
2080 
2081  /* Initialize session space address layout */
2083 
2084  /* Set the based section highest address */
2086 
2087 #if DBG
2088  /* The subection PTE format depends on things being 8-byte aligned */
2089  ASSERT((sizeof(CONTROL_AREA) % 8) == 0);
2090  ASSERT((sizeof(SUBSECTION) % 8) == 0);
2091 
2092  /* Prototype PTEs are assumed to be in paged pool, so check if the math works */
2093  PointerPte = (PMMPTE)MmPagedPoolStart;
2094  MI_MAKE_PROTOTYPE_PTE(&TempPte, PointerPte);
2095  TestPte = MiProtoPteToPte(&TempPte);
2096  ASSERT(PointerPte == TestPte);
2097 
2098  /* Try the last nonpaged pool address */
2099  PointerPte = (PMMPTE)MI_NONPAGED_POOL_END;
2100  MI_MAKE_PROTOTYPE_PTE(&TempPte, PointerPte);
2101  TestPte = MiProtoPteToPte(&TempPte);
2102  ASSERT(PointerPte == TestPte);
2103 
2104  /* Try a bunch of random addresses near the end of the address space */
2105  PointerPte = (PMMPTE)0xFFFC8000;
2106  for (j = 0; j < 20; j += 1)
2107  {
2108  MI_MAKE_PROTOTYPE_PTE(&TempPte, PointerPte);
2109  TestPte = MiProtoPteToPte(&TempPte);
2110  ASSERT(PointerPte == TestPte);
2111  PointerPte++;
2112  }
2113 
2114  /* Subsection PTEs are always in nonpaged pool, pick a random address to try */
2115  PointerPte = (PMMPTE)0xFFAACBB8;
2116  MI_MAKE_SUBSECTION_PTE(&TempPte, PointerPte);
2117  TestPte = MiSubsectionPteToSubsection(&TempPte);
2118  ASSERT(PointerPte == TestPte);
2119 #endif
2120 
2121  /* Loop all 8 standby lists */
2122  for (i = 0; i < 8; i++)
2123  {
2124  /* Initialize them */
2129  }
2130 
2131  /* Initialize the user mode image list */
2133 
2134  /* Initialize critical section timeout value (relative time is negative) */
2135  MmCriticalSectionTimeout.QuadPart = MmCritsectTimeoutSeconds * (-10000000LL);
2136 
2137  /* Initialize the paged pool mutex and the section commit mutex */
2141 
2142  /* Initialize the Loader Lock */
2144 
2145  /* Set the zero page event */
2148 
2149  /* Initialize the dead stack S-LIST */
2151 
2152  //
2153  // Check if this is a machine with less than 19MB of RAM
2154  //
2155  PageCount = MmNumberOfPhysicalPages;
2156  if (PageCount < MI_MIN_PAGES_FOR_SYSPTE_TUNING)
2157  {
2158  //
2159  // Use the very minimum of system PTEs
2160  //
2161  MmNumberOfSystemPtes = 7000;
2162  }
2163  else
2164  {
2165  //
2166  // Use the default
2167  //
2168  MmNumberOfSystemPtes = 11000;
2169  if (PageCount > MI_MIN_PAGES_FOR_SYSPTE_BOOST)
2170  {
2171  //
2172  // Double the amount of system PTEs
2173  //
2174  MmNumberOfSystemPtes <<= 1;
2175  }
2176  if (PageCount > MI_MIN_PAGES_FOR_SYSPTE_BOOST_BOOST)
2177  {
2178  //
2179  // Double the amount of system PTEs
2180  //
2181  MmNumberOfSystemPtes <<= 1;
2182  }
2183  if (MmSpecialPoolTag != 0 && MmSpecialPoolTag != -1)
2184  {
2185  //
2186  // Add some extra PTEs for special pool
2187  //
2188  MmNumberOfSystemPtes += 0x6000;
2189  }
2190  }
2191 
2192  DPRINT("System PTE count has been tuned to %lu (%lu bytes)\n",
2194 
2195  /* Check if no values are set for the heap limits */
2196  if (MmHeapSegmentReserve == 0)
2197  {
2198  MmHeapSegmentReserve = 2 * _1MB;
2199  }
2200 
2201  if (MmHeapSegmentCommit == 0)
2202  {
2204  }
2205 
2207  {
2209  }
2210 
2212  {
2214  }
2215 
2216  /* Initialize the working set lock */
2217  ExInitializePushLock(&MmSystemCacheWs.WorkingSetMutex);
2218 
2219  /* Set commit limit */
2220  MmTotalCommitLimit = 2 * _1GB;
2222 
2223  /* Has the allocation fragment been setup? */
2224  if (!MmAllocationFragment)
2225  {
2226  /* Use the default value */
2228  if (PageCount < ((256 * _1MB) / PAGE_SIZE))
2229  {
2230  /* On memory systems with less than 256MB, divide by 4 */
2232  }
2233  else if (PageCount < (_1GB / PAGE_SIZE))
2234  {
2235  /* On systems with less than 1GB, divide by 2 */
2237  }
2238  }
2239  else
2240  {
2241  /* Convert from 1KB fragments to pages */
2244 
2245  /* Don't let it past the maximum */
2248 
2249  /* Don't let it too small either */
2252  }
2253 
2254  /* Check for kernel stack size that's too big */
2256  {
2257  /* Sanitize to default value */
2259  }
2260  else
2261  {
2262  /* Take the registry setting, and convert it into bytes */
2264 
2265  /* Now align it to a page boundary */
2267 
2268  /* Sanity checks */
2270  ASSERT((MmLargeStackSize & (PAGE_SIZE - 1)) == 0);
2271 
2272  /* Make sure it's not too low */
2274  }
2275 
2276  /* Compute color information (L2 cache-separated paging lists) */
2278 
2279  // Calculate the number of bytes for the PFN database
2280  // then add the color tables and convert to pages
2281  MxPfnAllocation = (MmHighestPhysicalPage + 1) * sizeof(MMPFN);
2284 
2285  // We have to add one to the count here, because in the process of
2286  // shifting down to the page size, we actually ended up getting the
2287  // lower aligned size (so say, 0x5FFFF bytes is now 0x5F pages).
2288  // Later on, we'll shift this number back into bytes, which would cause
2289  // us to end up with only 0x5F000 bytes -- when we actually want to have
2290  // 0x60000 bytes.
2291  MxPfnAllocation++;
2292 
2293  /* Initialize the platform-specific parts */
2294  MiInitMachineDependent(LoaderBlock);
2295 
2296  //
2297  // Build the physical memory block
2298  //
2299  MmPhysicalMemoryBlock = MmInitializeMemoryLimits(LoaderBlock,
2300  IncludeType);
2301 
2302  //
2303  // Allocate enough buffer for the PFN bitmap
2304  // Align it up to a 32-bit boundary
2305  //
2307  (((MmHighestPhysicalPage + 1) + 31) / 32) * 4,
2308  TAG_MM);
2309  if (!Bitmap)
2310  {
2311  //
2312  // This is critical
2313  //
2314  KeBugCheckEx(INSTALL_MORE_MEMORY,
2318  0x101);
2319  }
2320 
2321  //
2322  // Initialize it and clear all the bits to begin with
2323  //
2324  RtlInitializeBitMap(&MiPfnBitMap,
2325  Bitmap,
2327  RtlClearAllBits(&MiPfnBitMap);
2328 
2329  //
2330  // Loop physical memory runs
2331  //
2332  for (i = 0; i < MmPhysicalMemoryBlock->NumberOfRuns; i++)
2333  {
2334  //
2335  // Get the run
2336  //
2337  Run = &MmPhysicalMemoryBlock->Run[i];
2338  DPRINT("PHYSICAL RAM [0x%08p to 0x%08p]\n",
2339  Run->BasePage << PAGE_SHIFT,
2340  (Run->BasePage + Run->PageCount) << PAGE_SHIFT);
2341 
2342  //
2343  // Make sure it has pages inside it
2344  //
2345  if (Run->PageCount)
2346  {
2347  //
2348  // Set the bits in the PFN bitmap
2349  //
2350  RtlSetBits(&MiPfnBitMap, (ULONG)Run->BasePage, (ULONG)Run->PageCount);
2351  }
2352  }
2353 
2354  /* Look for large page cache entries that need caching */
2356 
2357  /* Loop for HAL Heap I/O device mappings that need coherency tracking */
2359 
2360  /* Set the initial resident page count */
2362 
2363  /* Initialize large page structures on PAE/x64, and MmProcessList on x86 */
2365 
2366  /* Check if the registry says any drivers should be loaded with large pages */
2368 
2369  /* Relocate the boot drivers into system PTE space and fixup their PFNs */
2370  MiReloadBootLoadedDrivers(LoaderBlock);
2371 
2372  /* FIXME: Call out into Driver Verifier for initialization */
2373 
2374  /* Check how many pages the system has */
2375  if (MmNumberOfPhysicalPages <= ((13 * _1MB) / PAGE_SIZE))
2376  {
2377  /* Set small system */
2380  }
2381  else if (MmNumberOfPhysicalPages <= ((19 * _1MB) / PAGE_SIZE))
2382  {
2383  /* Set small system and add 100 pages for the cache */
2385  MmSystemCacheWsMinimum += 100;
2387  }
2388  else
2389  {
2390  /* Set medium system and add 400 pages for the cache */
2392  MmSystemCacheWsMinimum += 400;
2394  }
2395 
2396  /* Check for less than 24MB */
2397  if (MmNumberOfPhysicalPages < ((24 * _1MB) / PAGE_SIZE))
2398  {
2399  /* No more than 32 pages */
2401  }
2402 
2403  /* Check for more than 32MB */
2404  if (MmNumberOfPhysicalPages >= ((32 * _1MB) / PAGE_SIZE))
2405  {
2406  /* Check for product type being "Wi" for WinNT */
2407  if (MmProductType == '\0i\0W')
2408  {
2409  /* Then this is a large system */
2411  }
2412  else
2413  {
2414  /* For servers, we need 64MB to consider this as being large */
2415  if (MmNumberOfPhysicalPages >= ((64 * _1MB) / PAGE_SIZE))
2416  {
2417  /* Set it as large */
2419  }
2420  }
2421  }
2422 
2423  /* Check for more than 33 MB */
2424  if (MmNumberOfPhysicalPages > ((33 * _1MB) / PAGE_SIZE))
2425  {
2426  /* Add another 500 pages to the cache */
2427  MmSystemCacheWsMinimum += 500;
2428  }
2429 
2430  /* Now setup the shared user data fields */
2431  ASSERT(SharedUserData->NumberOfPhysicalPages == 0);
2432  SharedUserData->NumberOfPhysicalPages = MmNumberOfPhysicalPages;
2433  SharedUserData->LargePageMinimum = 0;
2434 
2435  /* Check for workstation (Wi for WinNT) */
2436  if (MmProductType == '\0i\0W')
2437  {
2438  /* Set Windows NT Workstation product type */
2439  SharedUserData->NtProductType = NtProductWinNt;
2440  MmProductType = 0;
2441  }
2442  else
2443  {
2444  /* Check for LanMan server (La for LanmanNT) */
2445  if (MmProductType == '\0a\0L')
2446  {
2447  /* This is a domain controller */
2448  SharedUserData->NtProductType = NtProductLanManNt;
2449  }
2450  else
2451  {
2452  /* Otherwise it must be a normal server (Se for ServerNT) */
2453  SharedUserData->NtProductType = NtProductServer;
2454  }
2455 
2456  /* Set the product type, and make the system more aggressive with low memory */
2457  MmProductType = 1;
2458  MmMinimumFreePages = 81;
2459  }
2460 
2461  /* Update working set tuning parameters */
2463 
2464  /* Finetune the page count by removing working set and NP expansion */
2468  if (MmResidentAvailablePages <= 0)
2469  {
2470  /* This should not happen */
2471  DPRINT1("System cache working set too big\n");
2472  return FALSE;
2473  }
2474 
2475  /* Initialize the system cache */
2476  //MiInitializeSystemCache(MmSystemCacheWsMinimum, MmAvailablePages);
2477 
2478  /* Update the commit limit */
2480  if (MmTotalCommitLimit > 1024) MmTotalCommitLimit -= 1024;
2482 
2483  /* Size up paged pool and build the shadow system page directory */
2484  MiBuildPagedPool();
2485 
2486  /* Debugger physical memory support is now ready to be used */
2488 
2489  /* Initialize the loaded module list */
2490  MiInitializeLoadedModuleList(LoaderBlock);
2491  }
2492 
2493  //
2494  // Always return success for now
2495  //
2496  return TRUE;
2497 }
2498 
2499 /* EOF */
DWORD *typedef PVOID
Definition: winlogon.h:52
PVOID MmPagedPoolEnd
Definition: mminit.c:105
MMSUPPORT MmSystemCacheWs
Definition: mminit.c:245
PFN_NUMBER MmResidentAvailableAtInit
Definition: freelist.c:28
PRTL_BITMAP PagedPoolAllocationMap
Definition: mm.h:414
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
struct _MMPFN::@1488::@1494 e2
#define PAGE_SHIFT
Definition: env_spec_w32.h:45
#define IN
Definition: typedefs.h:39
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
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
#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
union _MMPFN::@1491 u4
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)
NTSYSAPI VOID NTAPI RtlSetAllBits(_In_ PRTL_BITMAP BitMapHeader)
Definition: bitmap.c:283
_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:502
VOID NTAPI KeInitializeMutant(IN PKMUTANT Mutant, IN BOOLEAN InitialOwner)
Definition: mutex.c:22
MMLISTS ListName
Definition: mm.h:372
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:309
ULONG MmCritsectTimeoutSeconds
Definition: mminit.c:386
VOID NTAPI INIT_FUNCTION MmFreeLoaderBlock(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
Definition: mminit.c:1083
#define TRUE
Definition: numbers.c:17
#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
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::@1487 u2
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:297
PMMPFN MmPfnDatabase
Definition: freelist.c:24
PFN_NUMBER Flink
Definition: mm.h:373
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:64
PFN_NUMBER MxPfnAllocation
Definition: mminit.c:187
ULONG MiNumberDescriptors
Definition: mminit.c:380
USHORT PrototypePte
Definition: mm.h:295
#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
NTSYSAPI VOID NTAPI RtlInitializeBitMap(_Out_ PRTL_BITMAP BitMapHeader, _In_opt_ __drv_aliasesMem PULONG BitMapBuffer, _In_opt_ ULONG SizeOfBitMap)
UCHAR KIRQL
Definition: env_spec_w32.h:591
MMPFNENTRY e1
Definition: mm.h:329
TYPE_OF_MEMORY MemoryType
Definition: arc.h:193
PMMPTE MiSessionBasePte
Definition: mminit.c:145
#define PDE_COUNT
Definition: miarm.h:30
GLenum GLclampf GLint i
Definition: glfuncs.h:14
USHORT CacheAttribute
Definition: mm.h:299
#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:417
PFN_NUMBER MiNumberOfFreePages
Definition: mminit.c:383
FORCEINLINE VOID MI_WRITE_VALID_PTE(IN PMMPTE PointerPte, IN MMPTE TempPte)
Definition: miarm.h:914
ULONG_PTR ShareCount
Definition: mm.h:322
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:374
struct _MMCOLOR_TABLES * PMMCOLOR_TABLES
PVOID MiSystemViewStart
Definition: mminit.c:154
#define NULL
Definition: mystdio.h:57
PFN_NUMBER Flink
Definition: miarm.h:408
#define MI_SET_PROCESS2(x)
Definition: mm.h:254
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
NTSYSAPI VOID NTAPI RtlClearAllBits(_In_ PRTL_BITMAP BitMapHeader)
Definition: bitmap.c:272
struct _ACL ACL
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:253
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:1595
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
VOID NTAPI INIT_FUNCTION MiBuildPagedPool(VOID)
Definition: mminit.c:1724
#define MM_EMPTY_LIST
Definition: mm.h:78
union _MMPFN::@1488 u3
SIZE_T MmSessionSize
Definition: mminit.c:135
UINTN Size
Definition: acefiex.h:550
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
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:120
#define PDE_MAPPED_VA
Definition: miarm.h:20
BOOLEAN NTAPI INIT_FUNCTION MmArmInitSystem(IN ULONG Phase, IN PLOADER_PARAMETER_BLOCK LoaderBlock)
Definition: mminit.c:2011
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
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
NTSYSAPI VOID NTAPI RtlSetBits(_In_ PRTL_BITMAP BitMapHeader, _In_range_(0, BitMapHeader->SizeOfBitMap-NumberToSet) ULONG StartingIndex, _In_range_(0, BitMapHeader->SizeOfBitMap-StartingIndex) ULONG NumberToSet)
Definition: bitmap.c:374
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
#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:1529
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:305
union _MMPFN::@1486 u1
#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:118
#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:877
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:79
MMPTE_HARDWARE Hard
Definition: mmtypes.h:217
union _MMPTE::@1885 u
#define MI_SET_PFN_DELETED(x)
Definition: miarm.h:161
#define HIGH_LEVEL
Definition: env_spec_w32.h:703
#define NT_SUCCESS(StatCode)
Definition: cmd.c:149
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:350
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:484
PFN_NUMBER Total
Definition: mm.h:371
PRTL_BITMAP EndOfPagedPoolBitmap
Definition: mm.h:415
#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:300
PMMPTE PteAddress
Definition: mm.h:318
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
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
PSID SeLocalSystemSid
Definition: sid.c:44
signed char * PCHAR
Definition: retypes.h:7
#define OUT
Definition: typedefs.h:40
LONG NTAPI KeReadStateEvent(IN PKEVENT Event)
Definition: eventobj.c:120
#define FALSE
Definition: numbers.c:16
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:260
NTSYSAPI VOID NTAPI RtlClearBits(_In_ PRTL_BITMAP BitMapHeader, _In_range_(0, BitMapHeader->SizeOfBitMap-NumberToClear) ULONG StartingIndex, _In_range_(0, BitMapHeader->SizeOfBitMap-StartingIndex) ULONG NumberToClear)
Definition: bitmap.c:314
VOID NTAPI INIT_FUNCTION MiDbgDumpMemoryDescriptors(VOID)
Definition: mminit.c:1959
PVOID MiSessionPoolEnd
Definition: mminit.c:132
#define EVENT_MODIFY_STATE
Definition: winbase.h:161
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
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
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:351
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1097
#define max(a, b)
Definition: slicer.cc:81
PVOID MmNonPagedPoolExpansionStart
Definition: mminit.c:98
PMMPTE FirstPteForPagedPool
Definition: mm.h:416
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
#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:113
#define _1GB
Definition: miarm.h:14
PMMPDE NextPdeForPagedPoolExpansion
Definition: mm.h:418
#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