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