ReactOS  0.4.15-dev-5137-g826bd41
pool.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/pool.c
5  * PURPOSE: ARM Memory Manager Pool Allocator
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 <mm/ARM3/miarm.h>
17 
18 /* GLOBALS ********************************************************************/
19 
36 
37 /* PRIVATE FUNCTIONS **********************************************************/
38 
39 VOID
40 NTAPI
42  IN ULONG PageCount)
43 {
44  PMMPTE PointerPte, LastPte;
45  MMPTE TempPte;
46 
47  /* If pool is physical, can't protect PTEs */
49 
50  /* Get PTE pointers and loop */
51  PointerPte = MiAddressToPte(VirtualAddress);
52  LastPte = PointerPte + PageCount;
53  do
54  {
55  /* Capture the PTE for safety */
56  TempPte = *PointerPte;
57 
58  /* Mark it as an invalid PTE, set proto bit to recognize it as pool */
59  TempPte.u.Hard.Valid = 0;
60  TempPte.u.Soft.Prototype = 1;
61  MI_WRITE_INVALID_PTE(PointerPte, TempPte);
62  } while (++PointerPte < LastPte);
63 
64  /* Flush the TLB */
66 }
67 
68 BOOLEAN
69 NTAPI
71  IN ULONG PageCount)
72 {
73  PMMPTE PointerPte;
74  MMPTE TempPte;
75  PFN_NUMBER UnprotectedPages = 0;
76 
77  /* If pool is physical, can't protect PTEs */
79 
80  /* Get, and capture the PTE */
81  PointerPte = MiAddressToPte(VirtualAddress);
82  TempPte = *PointerPte;
83 
84  /* Loop protected PTEs */
85  while ((TempPte.u.Hard.Valid == 0) && (TempPte.u.Soft.Prototype == 1))
86  {
87  /* Unprotect the PTE */
88  TempPte.u.Hard.Valid = 1;
89  TempPte.u.Soft.Prototype = 0;
90  MI_WRITE_VALID_PTE(PointerPte, TempPte);
91 
92  /* One more page */
93  if (++UnprotectedPages == PageCount) break;
94 
95  /* Capture next PTE */
96  TempPte = *(++PointerPte);
97  }
98 
99  /* Return if any pages were unprotected */
100  return UnprotectedPages ? TRUE : FALSE;
101 }
102 
104 VOID
106  OUT PVOID* PoolFlink,
107  OUT PVOID* PoolBlink)
108 {
109  BOOLEAN Safe;
110  PVOID PoolVa;
111 
112  /* Initialize variables */
113  *PoolFlink = *PoolBlink = NULL;
114 
115  /* Check if the list has entries */
116  if (IsListEmpty(Links) == FALSE)
117  {
118  /* We are going to need to forward link to do an insert */
119  PoolVa = Links->Flink;
120 
121  /* So make it safe to access */
122  Safe = MiUnProtectFreeNonPagedPool(PoolVa, 1);
123  if (Safe) *PoolFlink = PoolVa;
124  }
125 
126  /* Are we going to need a backward link too? */
127  if (Links != Links->Blink)
128  {
129  /* Get the head's backward link for the insert */
130  PoolVa = Links->Blink;
131 
132  /* Make it safe to access */
133  Safe = MiUnProtectFreeNonPagedPool(PoolVa, 1);
134  if (Safe) *PoolBlink = PoolVa;
135  }
136 }
137 
139 VOID
141  IN PVOID PoolBlink)
142 {
143  /* Reprotect the pages, if they got unprotected earlier */
144  if (PoolFlink) MiProtectFreeNonPagedPool(PoolFlink, 1);
145  if (PoolBlink) MiProtectFreeNonPagedPool(PoolBlink, 1);
146 }
147 
148 VOID
149 NTAPI
152  IN BOOLEAN Critical)
153 {
154  PVOID PoolFlink, PoolBlink;
155 
156  /* Make the list accessible */
157  MiProtectedPoolUnProtectLinks(ListHead, &PoolFlink, &PoolBlink);
158 
159  /* Now insert in the right position */
160  Critical ? InsertHeadList(ListHead, Entry) : InsertTailList(ListHead, Entry);
161 
162  /* And reprotect the pages containing the free links */
163  MiProtectedPoolProtectLinks(PoolFlink, PoolBlink);
164 }
165 
166 VOID
167 NTAPI
169 {
170  PVOID PoolFlink, PoolBlink;
171 
172  /* Make the list accessible */
173  MiProtectedPoolUnProtectLinks(Entry, &PoolFlink, &PoolBlink);
174 
175  /* Now remove */
177 
178  /* And reprotect the pages containing the free links */
179  if (PoolFlink) MiProtectFreeNonPagedPool(PoolFlink, 1);
180  if (PoolBlink) MiProtectFreeNonPagedPool(PoolBlink, 1);
181 }
182 
183 CODE_SEG("INIT")
184 VOID
185 NTAPI
187 {
189 
190  /* Default low threshold of 8MB or one third of nonpaged pool */
193 
194  /* Default high threshold of 20MB or 50% */
198 }
199 
200 CODE_SEG("INIT")
201 VOID
202 NTAPI
204 {
205  KIRQL OldIrql;
206  PFN_NUMBER FreePoolInPages;
207 
208  /* Lock paged pool */
210 
211  /* Total size of the paged pool minus the allocated size, is free */
213 
214  /* Check the initial state high state */
215  if (FreePoolInPages >= MiHighPagedPoolThreshold)
216  {
217  /* We have plenty of pool */
219  }
220  else
221  {
222  /* We don't */
224  }
225 
226  /* Check the initial low state */
227  if (FreePoolInPages <= MiLowPagedPoolThreshold)
228  {
229  /* We're very low in free pool memory */
231  }
232  else
233  {
234  /* We're not */
236  }
237 
238  /* Release the paged pool lock */
240 
241  /* Now it's time for the nonpaged pool lock */
243 
244  /* Free pages are the maximum minus what's been allocated */
246 
247  /* Check if we have plenty */
248  if (FreePoolInPages >= MiHighNonPagedPoolThreshold)
249  {
250  /* We do, set the event */
252  }
253  else
254  {
255  /* We don't, clear the event */
257  }
258 
259  /* Check if we have very little */
260  if (FreePoolInPages <= MiLowNonPagedPoolThreshold)
261  {
262  /* We do, set the event */
264  }
265  else
266  {
267  /* We don't, clear it */
269  }
270 
271  /* We're done, release the nonpaged pool lock */
273 }
274 
275 CODE_SEG("INIT")
276 VOID
277 NTAPI
279 {
280  ULONG i;
281  PFN_COUNT PoolPages;
282  PMMFREE_POOL_ENTRY FreeEntry, FirstEntry;
283  PMMPTE PointerPte;
284  PAGED_CODE();
285 
286  //
287  // Initialize the pool S-LISTs as well as their maximum count. In general,
288  // we'll allow 8 times the default on a 2GB system, and two times the default
289  // on a 1GB system.
290  //
293  if (MmNumberOfPhysicalPages >= ((2 * _1GB) /PAGE_SIZE))
294  {
297  }
298  else if (MmNumberOfPhysicalPages >= (_1GB /PAGE_SIZE))
299  {
302  }
303 
304  //
305  // However if debugging options for the pool are enabled, turn off the S-LIST
306  // to reduce the risk of messing things up even more
307  //
309  {
312  }
313 
314  //
315  // We keep 4 lists of free pages (4 lists help avoid contention)
316  //
317  for (i = 0; i < MI_MAX_FREE_PAGE_LISTS; i++)
318  {
319  //
320  // Initialize each of them
321  //
323  }
324 
325  //
326  // Calculate how many pages the initial nonpaged pool has
327  //
329  MmNumberOfFreeNonPagedPool = PoolPages;
330 
331  //
332  // Initialize the first free entry
333  //
334  FreeEntry = MmNonPagedPoolStart;
335  FirstEntry = FreeEntry;
336  FreeEntry->Size = PoolPages;
337  FreeEntry->Signature = MM_FREE_POOL_SIGNATURE;
338  FreeEntry->Owner = FirstEntry;
339 
340  //
341  // Insert it into the last list
342  //
344  &FreeEntry->List);
345 
346  //
347  // Now create free entries for every single other page
348  //
349  while (PoolPages-- > 1)
350  {
351  //
352  // Link them all back to the original entry
353  //
354  FreeEntry = (PMMFREE_POOL_ENTRY)((ULONG_PTR)FreeEntry + PAGE_SIZE);
355  FreeEntry->Owner = FirstEntry;
356  FreeEntry->Signature = MM_FREE_POOL_SIGNATURE;
357  }
358 
359  //
360  // Validate and remember first allocated pool page
361  //
362  PointerPte = MiAddressToPte(MmNonPagedPoolStart);
363  ASSERT(PointerPte->u.Hard.Valid == 1);
365 
366  //
367  // Keep track of where initial nonpaged pool ends
368  //
371 
372  //
373  // Validate and remember last allocated pool page
374  //
375  PointerPte = MiAddressToPte((PVOID)((ULONG_PTR)MmNonPagedPoolEnd0 - 1));
376  ASSERT(PointerPte->u.Hard.Valid == 1);
378 
379  //
380  // Validate the first nonpaged pool expansion page (which is a guard page)
381  //
383  ASSERT(PointerPte->u.Hard.Valid == 0);
384 
385  //
386  // Calculate the size of the expansion region alone
387  //
390 
391  //
392  // Remove 2 pages, since there's a guard page on top and on the bottom
393  //
395 
396  //
397  // Now initialize the nonpaged pool expansion PTE space. Remember there's a
398  // guard page on top so make sure to skip it. The bottom guard page will be
399  // guaranteed by the fact our size is off by one.
400  //
401  MiInitializeSystemPtes(PointerPte + 1,
404 }
405 
406 POOL_TYPE
407 NTAPI
409 {
410  //
411  // Use a simple bounds check
412  //
413  if (PoolAddress >= MmPagedPoolStart && PoolAddress <= MmPagedPoolEnd)
414  return PagedPool;
415  else if (PoolAddress >= MmNonPagedPoolStart && PoolAddress <= MmNonPagedPoolEnd)
416  return NonPagedPool;
417  KeBugCheckEx(BAD_POOL_CALLER, 0x42, (ULONG_PTR)PoolAddress, 0, 0);
418 }
419 
420 PVOID
421 NTAPI
423  IN SIZE_T SizeInBytes)
424 {
425  PFN_NUMBER PageFrameNumber;
426  PFN_COUNT SizeInPages, PageTableCount;
427  ULONG i;
428  KIRQL OldIrql;
429  PLIST_ENTRY NextEntry, NextHead, LastHead;
430  PMMPTE PointerPte, StartPte;
431  PMMPDE PointerPde;
432  ULONG EndAllocation;
433  MMPTE TempPte;
434  MMPDE TempPde;
435  PMMPFN Pfn1;
436  PVOID BaseVa, BaseVaStart;
437  PMMFREE_POOL_ENTRY FreeEntry;
438 
439  //
440  // Figure out how big the allocation is in pages
441  //
442  SizeInPages = (PFN_COUNT)BYTES_TO_PAGES(SizeInBytes);
443 
444  //
445  // Check for overflow
446  //
447  if (SizeInPages == 0)
448  {
449  //
450  // Fail
451  //
452  return NULL;
453  }
454 
455  //
456  // Handle paged pool
457  //
459  {
460  //
461  // If only one page is being requested, try to grab it from the S-LIST
462  //
463  if ((SizeInPages == 1) && (ExQueryDepthSList(&MiPagedPoolSListHead)))
464  {
466  if (BaseVa) return BaseVa;
467  }
468 
469  //
470  // Lock the paged pool mutex
471  //
473 
474  //
475  // Find some empty allocation space
476  //
478  SizeInPages,
480  if (i == 0xFFFFFFFF)
481  {
482  //
483  // Get the page bit count
484  //
485  i = ((SizeInPages - 1) / PTE_PER_PAGE) + 1;
486  DPRINT("Paged pool expansion: %lu %x\n", i, SizeInPages);
487 
488  //
489  // Check if there is enougn paged pool expansion space left
490  //
493  {
494  //
495  // Out of memory!
496  //
497  DPRINT1("FAILED to allocate %Iu bytes from paged pool\n", SizeInBytes);
499  return NULL;
500  }
501 
502  //
503  // Check if we'll have to expand past the last PTE we have available
504  //
507  {
508  //
509  // We can only support this much then
510  //
512  PageTableCount = (PFN_COUNT)(PointerPde + 1 -
514  ASSERT(PageTableCount < i);
515  i = PageTableCount;
516  }
517  else
518  {
519  //
520  // Otherwise, there is plenty of space left for this expansion
521  //
522  PageTableCount = i;
523  }
524 
525  //
526  // Get the template PDE we'll use to expand
527  //
529 
530  //
531  // Get the first PTE in expansion space
532  //
534  BaseVa = MiPdeToPte(PointerPde);
535  BaseVaStart = BaseVa;
536 
537  //
538  // Lock the PFN database and loop pages
539  //
540  OldIrql = MiAcquirePfnLock();
541  do
542  {
543  //
544  // It should not already be valid
545  //
546  ASSERT(PointerPde->u.Hard.Valid == 0);
547 
548  /* Request a page */
550  MI_SET_PROCESS2("Kernel");
551  PageFrameNumber = MiRemoveAnyPage(MI_GET_NEXT_COLOR());
552  TempPde.u.Hard.PageFrameNumber = PageFrameNumber;
553 #if (_MI_PAGING_LEVELS >= 3)
554  /* On PAE/x64 systems, there's no double-buffering */
555  /* Initialize the PFN entry for it */
556  MiInitializePfnForOtherProcess(PageFrameNumber,
557  (PMMPTE)PointerPde,
558  PFN_FROM_PTE(MiAddressToPte(PointerPde)));
559 
560  /* Write the actual PDE now */
561  MI_WRITE_VALID_PDE(PointerPde, TempPde);
562 #else
563  //
564  // Save it into our double-buffered system page directory
565  //
566  MmSystemPagePtes[((ULONG_PTR)PointerPde & (SYSTEM_PD_SIZE - 1)) / sizeof(MMPTE)] = TempPde;
567 
568  /* Initialize the PFN */
569  MiInitializePfnForOtherProcess(PageFrameNumber,
570  (PMMPTE)PointerPde,
572 #endif
573 
574  //
575  // Move on to the next expansion address
576  //
577  PointerPde++;
578  BaseVa = (PVOID)((ULONG_PTR)BaseVa + PAGE_SIZE);
579  i--;
580  } while (i > 0);
581 
582  //
583  // Release the PFN database lock
584  //
585  MiReleasePfnLock(OldIrql);
586 
587  //
588  // These pages are now available, clear their availablity bits
589  //
592  PTE_PER_PAGE;
594  EndAllocation,
595  PageTableCount * PTE_PER_PAGE);
596 
597  //
598  // Update the next expansion location
599  //
601 
602  //
603  // Zero out the newly available memory
604  //
605  RtlZeroMemory(BaseVaStart, PageTableCount * PAGE_SIZE);
606 
607  //
608  // Now try consuming the pages again
609  //
611  SizeInPages,
612  0);
613  if (i == 0xFFFFFFFF)
614  {
615  //
616  // Out of memory!
617  //
618  DPRINT1("FAILED to allocate %Iu bytes from paged pool\n", SizeInBytes);
620  return NULL;
621  }
622  }
623 
624  //
625  // Update the pool hint if the request was just one page
626  //
627  if (SizeInPages == 1) MmPagedPoolInfo.PagedPoolHint = i + 1;
628 
629  //
630  // Update the end bitmap so we know the bounds of this allocation when
631  // the time comes to free it
632  //
633  EndAllocation = i + SizeInPages - 1;
635 
636  //
637  // Now we can release the lock (it mainly protects the bitmap)
638  //
640 
641  //
642  // Now figure out where this allocation starts
643  //
644  BaseVa = (PVOID)((ULONG_PTR)MmPagedPoolStart + (i << PAGE_SHIFT));
645 
646  //
647  // Flush the TLB
648  //
650 
651  /* Setup a demand-zero writable PTE */
653 
654  //
655  // Find the first and last PTE, then loop them all
656  //
657  PointerPte = MiAddressToPte(BaseVa);
658  StartPte = PointerPte + SizeInPages;
659  do
660  {
661  //
662  // Write the demand zero PTE and keep going
663  //
664  MI_WRITE_INVALID_PTE(PointerPte, TempPte);
665  } while (++PointerPte < StartPte);
666 
667  //
668  // Return the allocation address to the caller
669  //
670  return BaseVa;
671  }
672 
673  //
674  // If only one page is being requested, try to grab it from the S-LIST
675  //
676  if ((SizeInPages == 1) && (ExQueryDepthSList(&MiNonPagedPoolSListHead)))
677  {
679  if (BaseVa) return BaseVa;
680  }
681 
682  //
683  // Allocations of less than 4 pages go into their individual buckets
684  //
685  i = min(SizeInPages, MI_MAX_FREE_PAGE_LISTS) - 1;
686 
687  //
688  // Loop through all the free page lists based on the page index
689  //
690  NextHead = &MmNonPagedPoolFreeListHead[i];
692 
693  //
694  // Acquire the nonpaged pool lock
695  //
697  do
698  {
699  //
700  // Now loop through all the free page entries in this given list
701  //
702  NextEntry = NextHead->Flink;
703  while (NextEntry != NextHead)
704  {
705  /* Is freed non paged pool enabled */
707  {
708  /* We need to be able to touch this page, unprotect it */
709  MiUnProtectFreeNonPagedPool(NextEntry, 0);
710  }
711 
712  //
713  // Grab the entry and see if it can handle our allocation
714  //
715  FreeEntry = CONTAINING_RECORD(NextEntry, MMFREE_POOL_ENTRY, List);
716  ASSERT(FreeEntry->Signature == MM_FREE_POOL_SIGNATURE);
717  if (FreeEntry->Size >= SizeInPages)
718  {
719  //
720  // It does, so consume the pages from here
721  //
722  FreeEntry->Size -= SizeInPages;
723 
724  //
725  // The allocation will begin in this free page area
726  //
727  BaseVa = (PVOID)((ULONG_PTR)FreeEntry +
728  (FreeEntry->Size << PAGE_SHIFT));
729 
730  /* Remove the item from the list, depending if pool is protected */
733  else
734  RemoveEntryList(&FreeEntry->List);
735 
736  //
737  // However, check if its' still got space left
738  //
739  if (FreeEntry->Size != 0)
740  {
741  /* Check which list to insert this entry into */
742  i = min(FreeEntry->Size, MI_MAX_FREE_PAGE_LISTS) - 1;
743 
744  /* Insert the entry into the free list head, check for prot. pool */
747  else
749 
750  /* Is freed non paged pool protected? */
752  {
753  /* Protect the freed pool! */
754  MiProtectFreeNonPagedPool(FreeEntry, FreeEntry->Size);
755  }
756  }
757 
758  //
759  // Grab the PTE for this allocation
760  //
761  PointerPte = MiAddressToPte(BaseVa);
762  ASSERT(PointerPte->u.Hard.Valid == 1);
763 
764  //
765  // Grab the PFN NextEntry and index
766  //
767  Pfn1 = MiGetPfnEntry(PFN_FROM_PTE(PointerPte));
768 
769  //
770  // Now mark it as the beginning of an allocation
771  //
772  ASSERT(Pfn1->u3.e1.StartOfAllocation == 0);
773  Pfn1->u3.e1.StartOfAllocation = 1;
774 
775  /* Mark it as special pool if needed */
776  ASSERT(Pfn1->u4.VerifierAllocation == 0);
778  {
779  Pfn1->u4.VerifierAllocation = 1;
780  }
781 
782  //
783  // Check if the allocation is larger than one page
784  //
785  if (SizeInPages != 1)
786  {
787  //
788  // Navigate to the last PFN entry and PTE
789  //
790  PointerPte += SizeInPages - 1;
791  ASSERT(PointerPte->u.Hard.Valid == 1);
792  Pfn1 = MiGetPfnEntry(PointerPte->u.Hard.PageFrameNumber);
793  }
794 
795  //
796  // Mark this PFN as the last (might be the same as the first)
797  //
798  ASSERT(Pfn1->u3.e1.EndOfAllocation == 0);
799  Pfn1->u3.e1.EndOfAllocation = 1;
800 
801  //
802  // Release the nonpaged pool lock, and return the allocation
803  //
805  return BaseVa;
806  }
807 
808  //
809  // Try the next free page entry
810  //
811  NextEntry = FreeEntry->List.Flink;
812 
813  /* Is freed non paged pool protected? */
815  {
816  /* Protect the freed pool! */
817  MiProtectFreeNonPagedPool(FreeEntry, FreeEntry->Size);
818  }
819  }
820  } while (++NextHead < LastHead);
821 
822  //
823  // If we got here, we're out of space.
824  // Start by releasing the lock
825  //
827 
828  //
829  // Allocate some system PTEs
830  //
831  StartPte = MiReserveSystemPtes(SizeInPages, NonPagedPoolExpansion);
832  PointerPte = StartPte;
833  if (StartPte == NULL)
834  {
835  //
836  // Ran out of memory
837  //
838  DPRINT("Out of NP Expansion Pool\n");
839  return NULL;
840  }
841 
842  //
843  // Acquire the pool lock now
844  //
846 
847  //
848  // Lock the PFN database too
849  //
850  MiAcquirePfnLockAtDpcLevel();
851 
852  /* Check that we have enough available pages for this request */
853  if (MmAvailablePages < SizeInPages)
854  {
855  MiReleasePfnLockFromDpcLevel();
857 
858  MiReleaseSystemPtes(StartPte, SizeInPages, NonPagedPoolExpansion);
859 
860  DPRINT1("OUT OF AVAILABLE PAGES! Required %lu, Available %lu\n", SizeInPages, MmAvailablePages);
861 
862  return NULL;
863  }
864 
865  //
866  // Loop the pages
867  //
869  do
870  {
871  /* Allocate a page */
873  MI_SET_PROCESS2("Kernel");
874  PageFrameNumber = MiRemoveAnyPage(MI_GET_NEXT_COLOR());
875 
876  /* Get the PFN entry for it and fill it out */
877  Pfn1 = MiGetPfnEntry(PageFrameNumber);
878  Pfn1->u3.e2.ReferenceCount = 1;
879  Pfn1->u2.ShareCount = 1;
880  Pfn1->PteAddress = PointerPte;
882  Pfn1->u4.VerifierAllocation = 0;
883 
884  /* Write the PTE for it */
885  TempPte.u.Hard.PageFrameNumber = PageFrameNumber;
886  MI_WRITE_VALID_PTE(PointerPte++, TempPte);
887  } while (--SizeInPages > 0);
888 
889  //
890  // This is the last page
891  //
892  Pfn1->u3.e1.EndOfAllocation = 1;
893 
894  //
895  // Get the first page and mark it as such
896  //
897  Pfn1 = MiGetPfnEntry(StartPte->u.Hard.PageFrameNumber);
898  Pfn1->u3.e1.StartOfAllocation = 1;
899 
900  /* Mark it as a verifier allocation if needed */
901  ASSERT(Pfn1->u4.VerifierAllocation == 0);
903 
904  //
905  // Release the PFN and nonpaged pool lock
906  //
907  MiReleasePfnLockFromDpcLevel();
909 
910  //
911  // Return the address
912  //
913  return MiPteToAddress(StartPte);
914 }
915 
916 ULONG
917 NTAPI
919 {
920  PMMPTE PointerPte, StartPte;
921  PMMPFN Pfn1, StartPfn;
922  PFN_COUNT FreePages, NumberOfPages;
923  KIRQL OldIrql;
924  PMMFREE_POOL_ENTRY FreeEntry, NextEntry, LastEntry;
925  ULONG i, End;
927 
928  //
929  // Handle paged pool
930  //
931  if ((StartingVa >= MmPagedPoolStart) && (StartingVa <= MmPagedPoolEnd))
932  {
933  //
934  // Calculate the offset from the beginning of paged pool, and convert it
935  // into pages
936  //
937  Offset = (ULONG_PTR)StartingVa - (ULONG_PTR)MmPagedPoolStart;
938  i = (ULONG)(Offset >> PAGE_SHIFT);
939  End = i;
940 
941  //
942  // Now use the end bitmap to scan until we find a set bit, meaning that
943  // this allocation finishes here
944  //
945  while (!RtlTestBit(MmPagedPoolInfo.EndOfPagedPoolBitmap, End)) End++;
946 
947  //
948  // Now calculate the total number of pages this allocation spans. If it's
949  // only one page, add it to the S-LIST instead of freeing it
950  //
951  NumberOfPages = End - i + 1;
952  if ((NumberOfPages == 1) &&
954  {
956  return 1;
957  }
958 
959  /* Delete the actual pages */
960  PointerPte = MmPagedPoolInfo.FirstPteForPagedPool + i;
961  FreePages = MiDeleteSystemPageableVm(PointerPte, NumberOfPages, 0, NULL);
962  ASSERT(FreePages == NumberOfPages);
963 
964  //
965  // Acquire the paged pool lock
966  //
968 
969  //
970  // Clear the allocation and free bits
971  //
974 
975  //
976  // Update the hint if we need to
977  //
979 
980  //
981  // Release the lock protecting the bitmaps
982  //
984 
985  //
986  // And finally return the number of pages freed
987  //
988  return NumberOfPages;
989  }
990 
991  //
992  // Get the first PTE and its corresponding PFN entry. If this is also the
993  // last PTE, meaning that this allocation was only for one page, push it into
994  // the S-LIST instead of freeing it
995  //
996  StartPte = PointerPte = MiAddressToPte(StartingVa);
997  StartPfn = Pfn1 = MiGetPfnEntry(PointerPte->u.Hard.PageFrameNumber);
998  if ((Pfn1->u3.e1.EndOfAllocation == 1) &&
1000  {
1002  return 1;
1003  }
1004 
1005  //
1006  // Loop until we find the last PTE
1007  //
1008  while (Pfn1->u3.e1.EndOfAllocation == 0)
1009  {
1010  //
1011  // Keep going
1012  //
1013  PointerPte++;
1014  Pfn1 = MiGetPfnEntry(PointerPte->u.Hard.PageFrameNumber);
1015  }
1016 
1017  //
1018  // Now we know how many pages we have
1019  //
1020  NumberOfPages = (PFN_COUNT)(PointerPte - StartPte + 1);
1021 
1022  //
1023  // Acquire the nonpaged pool lock
1024  //
1026 
1027  //
1028  // Mark the first and last PTEs as not part of an allocation anymore
1029  //
1030  StartPfn->u3.e1.StartOfAllocation = 0;
1031  Pfn1->u3.e1.EndOfAllocation = 0;
1032 
1033  //
1034  // Assume we will free as many pages as the allocation was
1035  //
1036  FreePages = NumberOfPages;
1037 
1038  //
1039  // Peek one page past the end of the allocation
1040  //
1041  PointerPte++;
1042 
1043  //
1044  // Guard against going past initial nonpaged pool
1045  //
1047  {
1048  //
1049  // This page is on the outskirts of initial nonpaged pool, so ignore it
1050  //
1051  Pfn1 = NULL;
1052  }
1053  else
1054  {
1055  /* Sanity check */
1056  ASSERT((ULONG_PTR)StartingVa + NumberOfPages <= (ULONG_PTR)MmNonPagedPoolEnd);
1057 
1058  /* Check if protected pool is enabled */
1060  {
1061  /* The freed block will be merged, it must be made accessible */
1063  }
1064 
1065  //
1066  // Otherwise, our entire allocation must've fit within the initial non
1067  // paged pool, or the expansion nonpaged pool, so get the PFN entry of
1068  // the next allocation
1069  //
1070  if (PointerPte->u.Hard.Valid == 1)
1071  {
1072  //
1073  // It's either expansion or initial: get the PFN entry
1074  //
1075  Pfn1 = MiGetPfnEntry(PointerPte->u.Hard.PageFrameNumber);
1076  }
1077  else
1078  {
1079  //
1080  // This means we've reached the guard page that protects the end of
1081  // the expansion nonpaged pool
1082  //
1083  Pfn1 = NULL;
1084  }
1085 
1086  }
1087 
1088  //
1089  // Check if this allocation actually exists
1090  //
1091  if ((Pfn1) && (Pfn1->u3.e1.StartOfAllocation == 0))
1092  {
1093  //
1094  // It doesn't, so we should actually locate a free entry descriptor
1095  //
1096  FreeEntry = (PMMFREE_POOL_ENTRY)((ULONG_PTR)StartingVa +
1097  (NumberOfPages << PAGE_SHIFT));
1098  ASSERT(FreeEntry->Signature == MM_FREE_POOL_SIGNATURE);
1099  ASSERT(FreeEntry->Owner == FreeEntry);
1100 
1101  /* Consume this entry's pages */
1102  FreePages += FreeEntry->Size;
1103 
1104  /* Remove the item from the list, depending if pool is protected */
1106  MiProtectedPoolRemoveEntryList(&FreeEntry->List);
1107  else
1108  RemoveEntryList(&FreeEntry->List);
1109  }
1110 
1111  //
1112  // Now get the official free entry we'll create for the caller's allocation
1113  //
1114  FreeEntry = StartingVa;
1115 
1116  //
1117  // Check if the our allocation is the very first page
1118  //
1120  {
1121  //
1122  // Then we can't do anything or we'll risk underflowing
1123  //
1124  Pfn1 = NULL;
1125  }
1126  else
1127  {
1128  //
1129  // Otherwise, get the PTE for the page right before our allocation
1130  //
1131  PointerPte -= NumberOfPages + 1;
1132 
1133  /* Check if protected pool is enabled */
1135  {
1136  /* The freed block will be merged, it must be made accessible */
1138  }
1139 
1140  /* Check if this is valid pool, or a guard page */
1141  if (PointerPte->u.Hard.Valid == 1)
1142  {
1143  //
1144  // It's either expansion or initial nonpaged pool, get the PFN entry
1145  //
1146  Pfn1 = MiGetPfnEntry(PointerPte->u.Hard.PageFrameNumber);
1147  }
1148  else
1149  {
1150  //
1151  // We must've reached the guard page, so don't risk touching it
1152  //
1153  Pfn1 = NULL;
1154  }
1155  }
1156 
1157  //
1158  // Check if there is a valid PFN entry for the page before the allocation
1159  // and then check if this page was actually the end of an allocation.
1160  // If it wasn't, then we know for sure it's a free page
1161  //
1162  if ((Pfn1) && (Pfn1->u3.e1.EndOfAllocation == 0))
1163  {
1164  //
1165  // Get the free entry descriptor for that given page range
1166  //
1167  FreeEntry = (PMMFREE_POOL_ENTRY)((ULONG_PTR)StartingVa - PAGE_SIZE);
1168  ASSERT(FreeEntry->Signature == MM_FREE_POOL_SIGNATURE);
1169  FreeEntry = FreeEntry->Owner;
1170 
1171  /* Check if protected pool is enabled */
1173  {
1174  /* The freed block will be merged, it must be made accessible */
1175  MiUnProtectFreeNonPagedPool(FreeEntry, 0);
1176  }
1177 
1178  //
1179  // Check if the entry is small enough (1-3 pages) to be indexed on a free list
1180  // If it is, we'll want to re-insert it, since we're about to
1181  // collapse our pages on top of it, which will change its count
1182  //
1183  if (FreeEntry->Size < MI_MAX_FREE_PAGE_LISTS)
1184  {
1185  /* Remove the item from the list, depending if pool is protected */
1187  MiProtectedPoolRemoveEntryList(&FreeEntry->List);
1188  else
1189  RemoveEntryList(&FreeEntry->List);
1190 
1191  //
1192  // Update its size
1193  //
1194  FreeEntry->Size += FreePages;
1195 
1196  //
1197  // And now find the new appropriate list to place it in
1198  //
1199  i = min(FreeEntry->Size, MI_MAX_FREE_PAGE_LISTS) - 1;
1200 
1201  /* Insert the entry into the free list head, check for prot. pool */
1204  else
1206  }
1207  else
1208  {
1209  //
1210  // Otherwise, just combine our free pages into this entry
1211  //
1212  FreeEntry->Size += FreePages;
1213  }
1214  }
1215 
1216  //
1217  // Check if we were unable to do any compaction, and we'll stick with this
1218  //
1219  if (FreeEntry == StartingVa)
1220  {
1221  //
1222  // Well, now we are a free entry. At worse we just have our newly freed
1223  // pages, at best we have our pages plus whatever entry came after us
1224  //
1225  FreeEntry->Size = FreePages;
1226 
1227  //
1228  // Find the appropriate list we should be on
1229  //
1230  i = min(FreeEntry->Size, MI_MAX_FREE_PAGE_LISTS) - 1;
1231 
1232  /* Insert the entry into the free list head, check for prot. pool */
1235  else
1237  }
1238 
1239  //
1240  // Just a sanity check
1241  //
1242  ASSERT(FreePages != 0);
1243 
1244  //
1245  // Get all the pages between our allocation and its end. These will all now
1246  // become free page chunks.
1247  //
1248  NextEntry = StartingVa;
1249  LastEntry = (PMMFREE_POOL_ENTRY)((ULONG_PTR)NextEntry + (FreePages << PAGE_SHIFT));
1250  do
1251  {
1252  //
1253  // Link back to the parent free entry, and keep going
1254  //
1255  NextEntry->Owner = FreeEntry;
1256  NextEntry->Signature = MM_FREE_POOL_SIGNATURE;
1257  NextEntry = (PMMFREE_POOL_ENTRY)((ULONG_PTR)NextEntry + PAGE_SIZE);
1258  } while (NextEntry != LastEntry);
1259 
1260  /* Is freed non paged pool protected? */
1262  {
1263  /* Protect the freed pool! */
1264  MiProtectFreeNonPagedPool(FreeEntry, FreeEntry->Size);
1265  }
1266 
1267  //
1268  // We're done, release the lock and let the caller know how much we freed
1269  //
1271  return NumberOfPages;
1272 }
1273 
1274 NTSTATUS
1275 NTAPI
1277 {
1278  PMMPTE PointerPte, LastPte;
1279  PMMPDE PointerPde, LastPde;
1280  PFN_NUMBER PageFrameIndex, PdeCount;
1281  PPOOL_DESCRIPTOR PoolDescriptor;
1282  PMM_SESSION_SPACE SessionGlobal;
1283  PMM_PAGED_POOL_INFO PagedPoolInfo;
1284  NTSTATUS Status;
1285  ULONG Index, PoolSize, BitmapSize;
1286  PAGED_CODE();
1287 
1288  /* Lock session pool */
1289  SessionGlobal = MmSessionSpace->GlobalVirtualAddress;
1290  KeInitializeGuardedMutex(&SessionGlobal->PagedPoolMutex);
1291 
1292  /* Setup a valid pool descriptor */
1293  PoolDescriptor = &MmSessionSpace->PagedPool;
1294  ExInitializePoolDescriptor(PoolDescriptor,
1296  0,
1297  0,
1298  &SessionGlobal->PagedPoolMutex);
1299 
1300  /* Setup the pool addresses */
1303  DPRINT1("Session Pool Start: 0x%p End: 0x%p\n",
1305 
1306  /* Reset all the counters */
1307  PagedPoolInfo = &MmSessionSpace->PagedPoolInfo;
1308  PagedPoolInfo->PagedPoolCommit = 0;
1309  PagedPoolInfo->PagedPoolHint = 0;
1310  PagedPoolInfo->AllocatedPagedPool = 0;
1311 
1312  /* Compute PDE and PTE addresses */
1317 
1318  /* Write them down */
1319  MmSessionSpace->PagedPoolBasePde = PointerPde;
1320  PagedPoolInfo->FirstPteForPagedPool = PointerPte;
1321  PagedPoolInfo->LastPteForPagedPool = LastPte;
1322  PagedPoolInfo->NextPdeForPagedPoolExpansion = PointerPde + 1;
1323 
1324  /* Zero the PDEs */
1325  PdeCount = LastPde - PointerPde;
1326  RtlZeroMemory(PointerPde, (PdeCount + 1) * sizeof(MMPTE));
1327 
1328  /* Initialize the PFN for the PDE */
1329  Status = MiInitializeAndChargePfn(&PageFrameIndex,
1330  PointerPde,
1332  TRUE);
1334 
1335  /* Initialize the first page table */
1337  Index >>= 22;
1338 #ifndef _M_AMD64 // FIXME
1340  MmSessionSpace->PageTables[Index] = *PointerPde;
1341 #endif
1342 
1343  /* Bump up counters */
1346 
1347  /* Compute the size of the pool in pages, and of the bitmap for it */
1348  PoolSize = MmSessionPoolSize >> PAGE_SHIFT;
1349  BitmapSize = sizeof(RTL_BITMAP) + ((PoolSize + 31) / 32) * sizeof(ULONG);
1350 
1351  /* Allocate and initialize the bitmap to track allocations */
1353  BitmapSize,
1354  TAG_MM);
1355  ASSERT(PagedPoolInfo->PagedPoolAllocationMap != NULL);
1357  (PULONG)(PagedPoolInfo->PagedPoolAllocationMap + 1),
1358  PoolSize);
1359 
1360  /* Set all bits, but clear the first page table's worth */
1361  RtlSetAllBits(PagedPoolInfo->PagedPoolAllocationMap);
1362  RtlClearBits(PagedPoolInfo->PagedPoolAllocationMap, 0, PTE_PER_PAGE);
1363 
1364  /* Allocate and initialize the bitmap to track free space */
1366  BitmapSize,
1367  TAG_MM);
1368  ASSERT(PagedPoolInfo->EndOfPagedPoolBitmap != NULL);
1370  (PULONG)(PagedPoolInfo->EndOfPagedPoolBitmap + 1),
1371  PoolSize);
1372 
1373  /* Clear all the bits and return success */
1374  RtlClearAllBits(PagedPoolInfo->EndOfPagedPoolBitmap);
1375  return STATUS_SUCCESS;
1376 }
1377 
1405 BOOLEAN
1406 NTAPI
1407 MmRaisePoolQuota(
1411 {
1412  /*
1413  * We must be in dispatch level interrupt here
1414  * as we should be under a spin lock at this point.
1415  */
1417 
1418  switch (PoolType)
1419  {
1420  case NonPagedPool:
1421  {
1422  /*
1423  * When concerning with a raise (charge) of quota
1424  * in a non paged pool scenario, make sure that
1425  * we've got at least 200 pages necessary to provide.
1426  */
1428  {
1429  DPRINT1("MmRaisePoolQuota(): Not enough pages available (current pages -- %lu)\n", MmAvailablePages);
1430  return FALSE;
1431  }
1432 
1433  /*
1434  * Check if there's at least some space available
1435  * in the non paged pool area.
1436  */
1438  {
1439  /* There's too much allocated space, bail out */
1440  DPRINT1("MmRaisePoolQuota(): Failed to increase pool quota, not enough non paged pool space (current size -- %lu || allocated size -- %lu)\n",
1442  return FALSE;
1443  }
1444 
1445  /* Do we have enough resident pages to increase our quota? */
1447  {
1448  DPRINT1("MmRaisePoolQuota(): Failed to increase pool quota, not enough resident pages available (current available pages -- %lu)\n",
1450  return FALSE;
1451  }
1452 
1453  /*
1454  * Raise the non paged pool quota indicator and set
1455  * up new maximum limit of quota for the process.
1456  */
1459  DPRINT("MmRaisePoolQuota(): Non paged pool quota increased (before -- %lu || after -- %lu)\n", CurrentMaxQuota, NewMaxQuota);
1460  return TRUE;
1461  }
1462 
1463  case PagedPool:
1464  {
1465  /*
1466  * Before raising the quota limit of a paged quota
1467  * pool, make sure we've got enough space that is available.
1468  * On Windows it seems it wants to check for at least 1 MB of space
1469  * needed so that it would be possible to raise the paged pool quota.
1470  */
1472  {
1473  /* We haven't gotten enough space, bail out */
1474  DPRINT1("MmRaisePoolQuota(): Failed to increase pool quota, not enough paged pool space (current size -- %lu || allocated size -- %lu)\n",
1476  return FALSE;
1477  }
1478 
1479  /*
1480  * Raise the paged pool quota indicator and set
1481  * up new maximum limit of quota for the process.
1482  */
1485  DPRINT("MmRaisePoolQuota(): Paged pool quota increased (before -- %lu || after -- %lu)\n", CurrentMaxQuota, NewMaxQuota);
1486  return TRUE;
1487  }
1488 
1489  /* Only NonPagedPool and PagedPool are used */
1491  }
1492 }
1493 
1516 VOID
1517 NTAPI
1518 MmReturnPoolQuota(
1521 {
1522  /*
1523  * We must be in dispatch level interrupt here
1524  * as we should be under a spin lock at this point.
1525  */
1527 
1528  switch (PoolType)
1529  {
1530  case NonPagedPool:
1531  {
1532  /* This is a non paged pool type, decrease the non paged quota */
1535  DPRINT("MmReturnPoolQuota(): Non paged pool quota returned (current size -- %lu)\n", MmTotalNonPagedPoolQuota);
1536  break;
1537  }
1538 
1539  case PagedPool:
1540  {
1541  /* This is a paged pool type, decrease the paged quota */
1544  DPRINT("MmReturnPoolQuota(): Paged pool quota returned (current size -- %lu)\n", MmTotalPagedPoolQuota);
1545  break;
1546  }
1547 
1548  /* Only NonPagedPool and PagedPool are used */
1550  }
1551 }
1552 
1553 /* PUBLIC FUNCTIONS ***********************************************************/
1554 
1555 /*
1556  * @unimplemented
1557  */
1558 PVOID
1559 NTAPI
1561  IN ULONG PoolTag)
1562 {
1563  UNIMPLEMENTED;
1564  return NULL;
1565 }
1566 
1567 /*
1568  * @unimplemented
1569  */
1570 VOID
1571 NTAPI
1573  IN ULONG PoolTag)
1574 {
1575  UNIMPLEMENTED;
1576 }
1577 
1578 /* EOF */
VOID NTAPI MiInitializePoolEvents(VOID)
Definition: pool.c:203
#define MI_CHARGE_PAGED_POOL_QUOTA
Definition: mm.h:64
#define MI_MAKE_SOFTWARE_PTE(p, x)
Definition: miarm.h:189
#define DEFAULT_UNREACHABLE
PRTL_BITMAP PagedPoolAllocationMap
Definition: mm.h:486
#define PDE_PER_PAGE
Definition: mm.h:21
SIZE_T MmAllocatedNonPagedPool
Definition: pool.c:26
POOL_TYPE NTAPI MmDeterminePoolType(IN PVOID PoolAddress)
Definition: pool.c:408
PFN_NUMBER MmResidentAvailablePages
Definition: freelist.c:27
#define PAGE_SHIFT
Definition: env_spec_w32.h:45
#define IN
Definition: typedefs.h:39
union _MMPTE::@2285 u
SIZE_T NonPageablePages
Definition: miarm.h:486
BOOLEAN NTAPI MiUnProtectFreeNonPagedPool(IN PVOID VirtualAddress, IN ULONG PageCount)
Definition: pool.c:70
PVOID PagedPoolStart
Definition: miarm.h:488
PFN_NUMBER MiEndOfInitialPoolFrame
Definition: pool.c:23
struct _RTL_BITMAP RTL_BITMAP
PVOID MiSessionPoolStart
Definition: init.c:32
#define MiAddressToPde(x)
Definition: mmx86.c:20
PKEVENT MiHighNonPagedPoolEvent
Definition: mminit.c:297
union _MMPFN::@1753 u2
VOID FASTCALL KeAcquireGuardedMutex(IN PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:42
#define _Out_
Definition: ms_sal.h:345
PMMPDE PageTables
Definition: miarm.h:512
ULONG PFN_COUNT
Definition: mmtypes.h:102
#define TRUE
Definition: types.h:120
PMMPTE NTAPI MiReserveSystemPtes(IN ULONG NumberOfPtes, IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType)
Definition: syspte.c:246
FORCEINLINE VOID InsertHeadList(_Inout_ PLIST_ENTRY ListHead, _Inout_ __drv_aliasesMem PLIST_ENTRY Entry)
Definition: rtlfuncs.h:201
ULONG Signature
Definition: mm.h:476
#define ASSERT_IRQL_EQUAL(x)
Definition: debug.h:43
#define VERIFIER_POOL_MASK
Definition: mm.h:123
NTSTATUS NTAPI MiInitializeAndChargePfn(OUT PPFN_NUMBER PageFrameIndex, IN PMMPDE PointerPde, IN PFN_NUMBER ContainingPageFrame, IN BOOLEAN SessionAllocation)
Definition: pfnlist.c:1093
NTSYSAPI void WINAPI RtlInitializeBitMap(PRTL_BITMAP, PULONG, ULONG)
LONG NTSTATUS
Definition: precomp.h:26
NTSYSAPI VOID NTAPI RtlSetBit(_In_ PRTL_BITMAP BitMapHeader, _In_range_(<, BitMapHeader->SizeOfBitMap) ULONG BitNumber)
Definition: bitmap.c:304
PVOID MmNonPagedPoolExpansionStart
Definition: init.c:25
#define MI_GET_NEXT_COLOR()
Definition: miarm.h:237
#define MM_READWRITE
Definition: bootanim.c:19
HARDWARE_PDE_ARMV6 TempPde
Definition: winldr.c:78
PMM_SESSION_SPACE MmSessionSpace
Definition: session.c:21
PVOID MmPagedPoolEnd
Definition: init.c:26
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:361
VOID NTAPI MiInitializePfnForOtherProcess(IN PFN_NUMBER PageFrameIndex, IN PVOID PteAddress, IN PFN_NUMBER PteFrame)
Definition: pfnlist.c:1282
NTSTATUS NTAPI MiInitializeSessionPool(VOID)
Definition: pool.c:1276
#define InsertTailList(ListHead, Entry)
PFN_NUMBER MmAvailablePages
Definition: freelist.c:26
LONG NTAPI KeSetEvent(IN PKEVENT Event, IN KPRIORITY Increment, IN BOOLEAN Wait)
Definition: eventobj.c:159
FORCEINLINE PMMPDE MiPteToPde(PMMPTE PointerPte)
Definition: mm.h:268
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
USHORT PageLocation
Definition: mm.h:365
SIZE_T MmTotalNonPagedPoolQuota
Definition: pool.c:27
ULONG MmSpecialPoolTag
Definition: pool.c:29
MM_PAGED_POOL_INFO PagedPoolInfo
Definition: miarm.h:504
SLIST_HEADER MiNonPagedPoolSListHead
Definition: pool.c:32
PVOID MmNonPagedPoolEnd
Definition: mminit.c:99
uint32_t ULONG_PTR
Definition: typedefs.h:65
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
PFN_COUNT MmNumberOfFreeNonPagedPool
Definition: pool.c:21
UCHAR KIRQL
Definition: env_spec_w32.h:591
MMPFNENTRY e1
Definition: mm.h:397
PVOID MmSessionBase
Definition: init.c:33
#define MiAddressToPte(x)
Definition: mmx86.c:19
ULONG PFN_NUMBER
Definition: ke.h:9
ULONG_PTR * PSIZE_T
Definition: typedefs.h:80
#define TAG_MM
Definition: tag.h:110
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
PMMPTE LastPteForPagedPool
Definition: mm.h:489
#define FALSE
Definition: types.h:117
FORCEINLINE VOID MI_WRITE_VALID_PTE(IN PMMPTE PointerPte, IN MMPTE TempPte)
Definition: miarm.h:964
ULONG_PTR ShareCount
Definition: mm.h:390
#define InterlockedIncrementSizeT(a)
Definition: interlocked.h:220
VOID NTAPI MiInitializeSystemPtes(IN PMMPTE StartingPte, IN ULONG NumberOfPtes, IN MMSYSTEM_PTE_POOL_TYPE PoolType)
Definition: syspte.c:388
VOID NTAPI MiProtectedPoolRemoveEntryList(IN PLIST_ENTRY Entry)
Definition: pool.c:168
PKEVENT MiLowNonPagedPoolEvent
Definition: mminit.c:296
VOID NTAPI ExInitializePoolDescriptor(IN PPOOL_DESCRIPTOR PoolDescriptor, IN POOL_TYPE PoolType, IN ULONG PoolIndex, IN ULONG Threshold, IN PVOID PoolLock)
Definition: expool.c:966
#define MI_SET_PROCESS2(x)
Definition: mm.h:319
PFN_NUMBER MiStartOfInitialPoolFrame
Definition: pool.c:23
NTSYSAPI void WINAPI RtlSetAllBits(PRTL_BITMAP)
LIST_ENTRY List
Definition: mm.h:474
VOID NTAPI MiInitializeNonPagedPoolThresholds(VOID)
Definition: pool.c:186
PFN_NUMBER MmSystemPageDirectory[PPE_PER_PAGE]
Definition: init.c:40
unsigned char BOOLEAN
POOL_DESCRIPTOR PagedPool
Definition: miarm.h:508
SIZE_T AllocatedPagedPool
Definition: mm.h:493
#define MI_MAX_FREE_PAGE_LISTS
Definition: mm.h:80
FORCEINLINE PMMPTE MiPdeToPte(PMMPDE PointerPde)
Definition: mm.h:244
PVOID MmNonPagedPoolEnd0
Definition: pool.c:22
ULONG_PTR VerifierAllocation
Definition: mm.h:420
PFN_NUMBER MiHighPagedPoolThreshold
Definition: mminit.c:303
#define _In_
Definition: ms_sal.h:308
NTSYSAPI ULONG WINAPI RtlFindClearBitsAndSet(PRTL_BITMAP, ULONG, ULONG)
PFN_COUNT MiExpansionPoolPagesInitialCharge
Definition: pool.c:21
#define BASE_POOL_TYPE_MASK
Definition: ExPools.c:15
FORCEINLINE VOID MI_WRITE_VALID_PDE(IN PMMPDE PointerPde, IN MMPDE TempPde)
Definition: miarm.h:1023
#define MI_SET_USAGE(x)
Definition: mm.h:317
_Must_inspect_result_ _In_ WDFDMATRANSACTION _In_ PFN_WDF_PROGRAM_DMA _In_ WDF_DMA_DIRECTION _In_ PMDL _In_ PVOID VirtualAddress
void * PVOID
Definition: retypes.h:9
VOID NTAPI MiReleaseSystemPtes(IN PMMPTE StartingPte, IN ULONG NumberOfPtes, IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType)
Definition: syspte.c:264
SIZE_T PagedPoolCommit
Definition: mm.h:492
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
VOID NTAPI KeFlushEntireTb(IN BOOLEAN Invalid, IN BOOLEAN AllProcessors)
Definition: cpu.c:438
FORCEINLINE VOID InitializeSListHead(_Out_ PSLIST_HEADER SListHead)
Definition: rtlfuncs.h:3351
ULONG MmConsumedPoolPercentage
Definition: pool.c:30
PMMPDE MmSystemPagePtes
Definition: init.c:41
ULONG NTAPI MiFreePoolPages(IN PVOID StartingVa)
Definition: pool.c:918
KGUARDED_MUTEX MmPagedPoolMutex
Definition: pool.c:24
Status
Definition: gdiplustypes.h:24
PFN_COUNT Size
Definition: mm.h:475
ULONG PageFrameNumber
Definition: mmtypes.h:74
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID * BaseAddress
Definition: mmfuncs.h:404
_Requires_lock_held_(PspQuotaLock)
Raises the quota limit, depending on the given pool type of the quota in question....
Definition: pool.c:1404
struct _MM_SESSION_SPACE * GlobalVirtualAddress
Definition: miarm.h:475
#define MM_FREE_POOL_SIGNATURE
Definition: mm.h:481
#define ASSERT(a)
Definition: mode.c:44
SIZE_T CommittedPages
Definition: miarm.h:487
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
Definition: mm.h:472
INT POOL_TYPE
Definition: typedefs.h:78
_In_ WDFCOLLECTION _In_ ULONG Index
ULONG64 Valid
Definition: mmtypes.h:150
PVOID NTAPI MiAllocatePoolPages(IN POOL_TYPE PoolType, IN SIZE_T SizeInBytes)
Definition: pool.c:422
MM_PAGED_POOL_INFO MmPagedPoolInfo
Definition: pool.c:25
VOID NTAPI RtlClearBit(_In_ PRTL_BITMAP BitMapHeader, _In_ BITMAP_INDEX BitNumber)
Definition: bitmap.c:294
VOID FASTCALL KeReleaseQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber, IN KIRQL OldIrql)
Definition: spinlock.c:154
#define PTE_PER_PAGE
Definition: mm.h:20
HARDWARE_PTE_ARMV6 TempPte
Definition: winldr.c:76
FORCEINLINE USHORT ExQueryDepthSList(_In_ PSLIST_HEADER SListHead)
Definition: exfuncs.h:153
_Must_inspect_result_ NTSYSAPI BOOLEAN NTAPI RtlTestBit(_In_ PRTL_BITMAP BitMapHeader, _In_range_(<, BitMapHeader->SizeOfBitMap) ULONG BitNumber)
Definition: bitmap.c:434
PFN_NUMBER MiHighNonPagedPoolThreshold
Definition: mminit.c:305
MMPTE ValidKernelPte
Definition: init.c:29
ULONG MiNonPagedPoolSListMaximum
Definition: pool.c:33
_Must_inspect_result_ _In_opt_ PWDF_OBJECT_ATTRIBUTES _In_ _Strict_type_match_ POOL_TYPE _In_opt_ ULONG PoolTag
Definition: wdfmemory.h:159
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
VOID NTAPI MiProtectedPoolInsertList(IN PLIST_ENTRY ListHead, IN PLIST_ENTRY Entry, IN BOOLEAN Critical)
Definition: pool.c:150
struct _MMFREE_POOL_ENTRY * Owner
Definition: mm.h:477
#define BYTES_TO_PAGES(Size)
struct _MMPFN::@1754::@1760 e2
ULONG MiPagedPoolSListMaximum
Definition: pool.c:35
_In_ SIZE_T _Out_ PSIZE_T NewMaxQuota
Definition: mm.h:665
PVOID PagedPoolEnd
Definition: miarm.h:489
KGUARDED_MUTEX PagedPoolMutex
Definition: miarm.h:503
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:792
PFN_NUMBER MmMaximumNonPagedPoolInPages
Definition: mminit.c:30
_In_ SIZE_T CurrentMaxQuota
Definition: mm.h:665
_Must_inspect_result_ _In_ WDFCMRESLIST List
Definition: wdfresource.h:550
#define InterlockedPushEntrySList(SListHead, SListEntry)
Definition: rtlfuncs.h:3389
Definition: mm.h:373
union _MMPFN::@1754 u3
#define PAGE_SIZE
Definition: env_spec_w32.h:49
Definition: typedefs.h:119
VOID NTAPI MiInitializeNonPagedPool(VOID)
Definition: pool.c:278
#define _1MB
Definition: miarm.h:19
KIRQL FASTCALL KeAcquireQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber)
Definition: spinlock.c:108
FORCEINLINE PMMPFN MiGetPfnEntry(IN PFN_NUMBER Pfn)
Definition: mm.h:1047
FORCEINLINE VOID MiProtectedPoolUnProtectLinks(IN PLIST_ENTRY Links, OUT PVOID *PoolFlink, OUT PVOID *PoolBlink)
Definition: pool.c:105
MMPTE ValidKernelPde
Definition: init.c:28
ULONG_PTR Long
Definition: mmtypes.h:215
PVOID MmPagedPoolStart
Definition: miarm.h:579
PVOID MmNonPagedPoolStart
Definition: init.c:24
PFN_NUMBER MiLowPagedPoolThreshold
Definition: mminit.c:302
ULONG MmSessionPoolSize
Definition: init.c:36
PFN_COUNT NTAPI MiDeleteSystemPageableVm(IN PMMPTE PointerPte, IN PFN_NUMBER PageCount, IN ULONG Flags, OUT PPFN_NUMBER ValidPages)
Definition: virtual.c:275
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
NTSYSAPI void WINAPI RtlClearBits(PRTL_BITMAP, ULONG, ULONG)
PFN_NUMBER NTAPI MiRemoveAnyPage(IN ULONG Color)
Definition: pfnlist.c:477
ULONG_PTR SIZE_T
Definition: typedefs.h:80
MMPTE_HARDWARE Hard
Definition: mmtypes.h:217
#define SYSTEM_PD_SIZE
Definition: miarm.h:32
union _MMPFN::@1757 u4
FORCEINLINE VOID MI_WRITE_INVALID_PTE(IN PMMPTE PointerPte, IN MMPTE InvalidPte)
Definition: miarm.h:997
PFN_COUNT MmNumberOfPhysicalPages
Definition: init.c:48
BOOLEAN MmProtectFreedNonPagedPool
Definition: pool.c:31
VOID FASTCALL KeInitializeGuardedMutex(OUT PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:31
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
struct _MMFREE_POOL_ENTRY * PMMFREE_POOL_ENTRY
PRTL_BITMAP EndOfPagedPoolBitmap
Definition: mm.h:487
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define FORCEINLINE
Definition: wdftypes.h:67
ULONG MmMaximumNonPagedPoolInBytes
Definition: init.c:22
PMMPTE PteAddress
Definition: mm.h:386
_Must_inspect_result_ typedef _In_ PHYSICAL_ADDRESS _Inout_ PLARGE_INTEGER NumberOfBytes
Definition: iotypes.h:1035
unsigned int * PULONG
Definition: retypes.h:1
#define min(a, b)
Definition: monoChain.cc:55
#define NULL
Definition: types.h:112
_In_ SIZE_T QuotaToReturn
Definition: mm.h:675
NTSYSAPI void WINAPI RtlClearAllBits(PRTL_BITMAP)
VOID FASTCALL KeReleaseGuardedMutex(IN OUT PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:53
PKEVENT MiLowPagedPoolEvent
Definition: mminit.c:294
#define DPRINT1
Definition: precomp.h:8
#define MI_NON_PAGED_QUOTA_MIN_RESIDENT_PAGES
Definition: mm.h:63
SLIST_HEADER MiPagedPoolSListHead
Definition: pool.c:34
FORCEINLINE PFN_NUMBER MiGetPfnEntryIndex(IN PMMPFN Pfn1)
Definition: mm.h:1067
#define OUT
Definition: typedefs.h:40
_Must_inspect_result_ _In_ WDFDEVICE _In_ DEVICE_REGISTRY_PROPERTY _In_ _Strict_type_match_ POOL_TYPE PoolType
Definition: wdfdevice.h:3810
PVOID MiSessionPoolEnd
Definition: init.c:31
PKEVENT MiHighPagedPoolEvent
Definition: mminit.c:295
unsigned int ULONG
Definition: retypes.h:1
#define UNIMPLEMENTED
Definition: debug.h:115
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define ULONG_PTR
Definition: config.h:101
ULONG64 PageFrameNumber
Definition: mmtypes.h:171
VOID NTAPI MiProtectFreeNonPagedPool(IN PVOID VirtualAddress, IN ULONG PageCount)
Definition: pool.c:41
SIZE_T MmTotalPagedPoolQuota
Definition: pool.c:28
PFN_NUMBER MiLowNonPagedPoolThreshold
Definition: mminit.c:304
ULONG PagedPoolHint
Definition: mm.h:491
#define STATUS_SUCCESS
Definition: shellext.h:65
ULONG MmSizeOfNonPagedPoolInBytes
Definition: init.c:21
PFN_NUMBER MmSizeOfPagedPoolInPages
Definition: mminit.c:111
#define InterlockedPopEntrySList(SListHead)
Definition: rtlfuncs.h:3392
#define DPRINT
Definition: sndvol32.h:71
PMMPTE FirstPteForPagedPool
Definition: mm.h:488
FORCEINLINE PVOID MiPteToAddress(PMMPTE PointerPte)
Definition: mm.h:208
LIST_ENTRY MmNonPagedPoolFreeListHead[MI_MAX_FREE_PAGE_LISTS]
Definition: pool.c:20
VOID NTAPI KeClearEvent(IN PKEVENT Event)
Definition: eventobj.c:22
#define MI_CHARGE_NON_PAGED_POOL_QUOTA
Definition: mm.h:65
FORCEINLINE BOOLEAN MI_IS_PHYSICAL_ADDRESS(IN PVOID Address)
Definition: miarm.h:950
PMMPDE PagedPoolBasePde
Definition: miarm.h:490
static CODE_SEG("PAGE")
Definition: isapnp.c:1482
#define PFN_FROM_PTE(v)
Definition: mm.h:92
PVOID NTAPI MmAllocateMappingAddress(IN SIZE_T NumberOfBytes, IN ULONG PoolTag)
Definition: pool.c:1560
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
#define MI_QUOTA_NON_PAGED_NEEDED_PAGES
Definition: mm.h:62
#define _1GB
Definition: miarm.h:20
VOID NTAPI MmFreeMappingAddress(IN PVOID BaseAddress, IN ULONG PoolTag)
Definition: pool.c:1572
ULONG PageFrameNumber
Definition: mmtypes.h:109
PMMPDE NextPdeForPagedPoolExpansion
Definition: mm.h:490
FORCEINLINE VOID MiProtectedPoolProtectLinks(IN PVOID PoolFlink, IN PVOID PoolBlink)
Definition: pool.c:140
PFN_NUMBER SessionPageDirectoryIndex
Definition: miarm.h:485
#define PAGED_CODE()
static KSPIN_LOCK PspQuotaLock
Definition: quota.c:18