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