ReactOS  0.4.15-dev-2359-g0dedb9b
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 
34 
35 /* PRIVATE FUNCTIONS **********************************************************/
36 
37 VOID
38 NTAPI
40  IN ULONG PageCount)
41 {
42  PMMPTE PointerPte, LastPte;
43  MMPTE TempPte;
44 
45  /* If pool is physical, can't protect PTEs */
47 
48  /* Get PTE pointers and loop */
49  PointerPte = MiAddressToPte(VirtualAddress);
50  LastPte = PointerPte + PageCount;
51  do
52  {
53  /* Capture the PTE for safety */
54  TempPte = *PointerPte;
55 
56  /* Mark it as an invalid PTE, set proto bit to recognize it as pool */
57  TempPte.u.Hard.Valid = 0;
58  TempPte.u.Soft.Prototype = 1;
59  MI_WRITE_INVALID_PTE(PointerPte, TempPte);
60  } while (++PointerPte < LastPte);
61 
62  /* Flush the TLB */
64 }
65 
66 BOOLEAN
67 NTAPI
69  IN ULONG PageCount)
70 {
71  PMMPTE PointerPte;
72  MMPTE TempPte;
73  PFN_NUMBER UnprotectedPages = 0;
74 
75  /* If pool is physical, can't protect PTEs */
77 
78  /* Get, and capture the PTE */
79  PointerPte = MiAddressToPte(VirtualAddress);
80  TempPte = *PointerPte;
81 
82  /* Loop protected PTEs */
83  while ((TempPte.u.Hard.Valid == 0) && (TempPte.u.Soft.Prototype == 1))
84  {
85  /* Unprotect the PTE */
86  TempPte.u.Hard.Valid = 1;
87  TempPte.u.Soft.Prototype = 0;
88  MI_WRITE_VALID_PTE(PointerPte, TempPte);
89 
90  /* One more page */
91  if (++UnprotectedPages == PageCount) break;
92 
93  /* Capture next PTE */
94  TempPte = *(++PointerPte);
95  }
96 
97  /* Return if any pages were unprotected */
98  return UnprotectedPages ? TRUE : FALSE;
99 }
100 
102 VOID
104  OUT PVOID* PoolFlink,
105  OUT PVOID* PoolBlink)
106 {
107  BOOLEAN Safe;
108  PVOID PoolVa;
109 
110  /* Initialize variables */
111  *PoolFlink = *PoolBlink = NULL;
112 
113  /* Check if the list has entries */
114  if (IsListEmpty(Links) == FALSE)
115  {
116  /* We are going to need to forward link to do an insert */
117  PoolVa = Links->Flink;
118 
119  /* So make it safe to access */
120  Safe = MiUnProtectFreeNonPagedPool(PoolVa, 1);
121  if (Safe) *PoolFlink = PoolVa;
122  }
123 
124  /* Are we going to need a backward link too? */
125  if (Links != Links->Blink)
126  {
127  /* Get the head's backward link for the insert */
128  PoolVa = Links->Blink;
129 
130  /* Make it safe to access */
131  Safe = MiUnProtectFreeNonPagedPool(PoolVa, 1);
132  if (Safe) *PoolBlink = PoolVa;
133  }
134 }
135 
137 VOID
139  IN PVOID PoolBlink)
140 {
141  /* Reprotect the pages, if they got unprotected earlier */
142  if (PoolFlink) MiProtectFreeNonPagedPool(PoolFlink, 1);
143  if (PoolBlink) MiProtectFreeNonPagedPool(PoolBlink, 1);
144 }
145 
146 VOID
147 NTAPI
150  IN BOOLEAN Critical)
151 {
152  PVOID PoolFlink, PoolBlink;
153 
154  /* Make the list accessible */
155  MiProtectedPoolUnProtectLinks(ListHead, &PoolFlink, &PoolBlink);
156 
157  /* Now insert in the right position */
158  Critical ? InsertHeadList(ListHead, Entry) : InsertTailList(ListHead, Entry);
159 
160  /* And reprotect the pages containing the free links */
161  MiProtectedPoolProtectLinks(PoolFlink, PoolBlink);
162 }
163 
164 VOID
165 NTAPI
167 {
168  PVOID PoolFlink, PoolBlink;
169 
170  /* Make the list accessible */
171  MiProtectedPoolUnProtectLinks(Entry, &PoolFlink, &PoolBlink);
172 
173  /* Now remove */
175 
176  /* And reprotect the pages containing the free links */
177  if (PoolFlink) MiProtectFreeNonPagedPool(PoolFlink, 1);
178  if (PoolBlink) MiProtectFreeNonPagedPool(PoolBlink, 1);
179 }
180 
181 CODE_SEG("INIT")
182 VOID
183 NTAPI
185 {
187 
188  /* Default low threshold of 8MB or one third of nonpaged pool */
191 
192  /* Default high threshold of 20MB or 50% */
196 }
197 
198 CODE_SEG("INIT")
199 VOID
200 NTAPI
202 {
203  KIRQL OldIrql;
204  PFN_NUMBER FreePoolInPages;
205 
206  /* Lock paged pool */
208 
209  /* Total size of the paged pool minus the allocated size, is free */
211 
212  /* Check the initial state high state */
213  if (FreePoolInPages >= MiHighPagedPoolThreshold)
214  {
215  /* We have plenty of pool */
217  }
218  else
219  {
220  /* We don't */
222  }
223 
224  /* Check the initial low state */
225  if (FreePoolInPages <= MiLowPagedPoolThreshold)
226  {
227  /* We're very low in free pool memory */
229  }
230  else
231  {
232  /* We're not */
234  }
235 
236  /* Release the paged pool lock */
238 
239  /* Now it's time for the nonpaged pool lock */
241 
242  /* Free pages are the maximum minus what's been allocated */
244 
245  /* Check if we have plenty */
246  if (FreePoolInPages >= MiHighNonPagedPoolThreshold)
247  {
248  /* We do, set the event */
250  }
251  else
252  {
253  /* We don't, clear the event */
255  }
256 
257  /* Check if we have very little */
258  if (FreePoolInPages <= MiLowNonPagedPoolThreshold)
259  {
260  /* We do, set the event */
262  }
263  else
264  {
265  /* We don't, clear it */
267  }
268 
269  /* We're done, release the nonpaged pool lock */
271 }
272 
273 CODE_SEG("INIT")
274 VOID
275 NTAPI
277 {
278  ULONG i;
279  PFN_COUNT PoolPages;
280  PMMFREE_POOL_ENTRY FreeEntry, FirstEntry;
281  PMMPTE PointerPte;
282  PAGED_CODE();
283 
284  //
285  // Initialize the pool S-LISTs as well as their maximum count. In general,
286  // we'll allow 8 times the default on a 2GB system, and two times the default
287  // on a 1GB system.
288  //
291  if (MmNumberOfPhysicalPages >= ((2 * _1GB) /PAGE_SIZE))
292  {
295  }
296  else if (MmNumberOfPhysicalPages >= (_1GB /PAGE_SIZE))
297  {
300  }
301 
302  //
303  // However if debugging options for the pool are enabled, turn off the S-LIST
304  // to reduce the risk of messing things up even more
305  //
307  {
310  }
311 
312  //
313  // We keep 4 lists of free pages (4 lists help avoid contention)
314  //
315  for (i = 0; i < MI_MAX_FREE_PAGE_LISTS; i++)
316  {
317  //
318  // Initialize each of them
319  //
321  }
322 
323  //
324  // Calculate how many pages the initial nonpaged pool has
325  //
327  MmNumberOfFreeNonPagedPool = PoolPages;
328 
329  //
330  // Initialize the first free entry
331  //
332  FreeEntry = MmNonPagedPoolStart;
333  FirstEntry = FreeEntry;
334  FreeEntry->Size = PoolPages;
335  FreeEntry->Signature = MM_FREE_POOL_SIGNATURE;
336  FreeEntry->Owner = FirstEntry;
337 
338  //
339  // Insert it into the last list
340  //
342  &FreeEntry->List);
343 
344  //
345  // Now create free entries for every single other page
346  //
347  while (PoolPages-- > 1)
348  {
349  //
350  // Link them all back to the original entry
351  //
352  FreeEntry = (PMMFREE_POOL_ENTRY)((ULONG_PTR)FreeEntry + PAGE_SIZE);
353  FreeEntry->Owner = FirstEntry;
354  FreeEntry->Signature = MM_FREE_POOL_SIGNATURE;
355  }
356 
357  //
358  // Validate and remember first allocated pool page
359  //
360  PointerPte = MiAddressToPte(MmNonPagedPoolStart);
361  ASSERT(PointerPte->u.Hard.Valid == 1);
363 
364  //
365  // Keep track of where initial nonpaged pool ends
366  //
369 
370  //
371  // Validate and remember last allocated pool page
372  //
373  PointerPte = MiAddressToPte((PVOID)((ULONG_PTR)MmNonPagedPoolEnd0 - 1));
374  ASSERT(PointerPte->u.Hard.Valid == 1);
376 
377  //
378  // Validate the first nonpaged pool expansion page (which is a guard page)
379  //
381  ASSERT(PointerPte->u.Hard.Valid == 0);
382 
383  //
384  // Calculate the size of the expansion region alone
385  //
388 
389  //
390  // Remove 2 pages, since there's a guard page on top and on the bottom
391  //
393 
394  //
395  // Now initialize the nonpaged pool expansion PTE space. Remember there's a
396  // guard page on top so make sure to skip it. The bottom guard page will be
397  // guaranteed by the fact our size is off by one.
398  //
399  MiInitializeSystemPtes(PointerPte + 1,
402 }
403 
404 POOL_TYPE
405 NTAPI
407 {
408  //
409  // Use a simple bounds check
410  //
411  if (PoolAddress >= MmPagedPoolStart && PoolAddress <= MmPagedPoolEnd)
412  return PagedPool;
413  else if (PoolAddress >= MmNonPagedPoolStart && PoolAddress <= MmNonPagedPoolEnd)
414  return NonPagedPool;
415  KeBugCheckEx(BAD_POOL_CALLER, 0x42, (ULONG_PTR)PoolAddress, 0, 0);
416 }
417 
418 PVOID
419 NTAPI
421  IN SIZE_T SizeInBytes)
422 {
423  PFN_NUMBER PageFrameNumber;
424  PFN_COUNT SizeInPages, PageTableCount;
425  ULONG i;
426  KIRQL OldIrql;
427  PLIST_ENTRY NextEntry, NextHead, LastHead;
428  PMMPTE PointerPte, StartPte;
429  PMMPDE PointerPde;
430  ULONG EndAllocation;
431  MMPTE TempPte;
432  MMPDE TempPde;
433  PMMPFN Pfn1;
434  PVOID BaseVa, BaseVaStart;
435  PMMFREE_POOL_ENTRY FreeEntry;
436 
437  //
438  // Figure out how big the allocation is in pages
439  //
440  SizeInPages = (PFN_COUNT)BYTES_TO_PAGES(SizeInBytes);
441 
442  //
443  // Check for overflow
444  //
445  if (SizeInPages == 0)
446  {
447  //
448  // Fail
449  //
450  return NULL;
451  }
452 
453  //
454  // Handle paged pool
455  //
457  {
458  //
459  // If only one page is being requested, try to grab it from the S-LIST
460  //
461  if ((SizeInPages == 1) && (ExQueryDepthSList(&MiPagedPoolSListHead)))
462  {
464  if (BaseVa) return BaseVa;
465  }
466 
467  //
468  // Lock the paged pool mutex
469  //
471 
472  //
473  // Find some empty allocation space
474  //
476  SizeInPages,
478  if (i == 0xFFFFFFFF)
479  {
480  //
481  // Get the page bit count
482  //
483  i = ((SizeInPages - 1) / PTE_PER_PAGE) + 1;
484  DPRINT("Paged pool expansion: %lu %x\n", i, SizeInPages);
485 
486  //
487  // Check if there is enougn paged pool expansion space left
488  //
491  {
492  //
493  // Out of memory!
494  //
495  DPRINT1("FAILED to allocate %Iu bytes from paged pool\n", SizeInBytes);
497  return NULL;
498  }
499 
500  //
501  // Check if we'll have to expand past the last PTE we have available
502  //
505  {
506  //
507  // We can only support this much then
508  //
510  PageTableCount = (PFN_COUNT)(PointerPde + 1 -
512  ASSERT(PageTableCount < i);
513  i = PageTableCount;
514  }
515  else
516  {
517  //
518  // Otherwise, there is plenty of space left for this expansion
519  //
520  PageTableCount = i;
521  }
522 
523  //
524  // Get the template PDE we'll use to expand
525  //
527 
528  //
529  // Get the first PTE in expansion space
530  //
532  BaseVa = MiPdeToPte(PointerPde);
533  BaseVaStart = BaseVa;
534 
535  //
536  // Lock the PFN database and loop pages
537  //
539  do
540  {
541  //
542  // It should not already be valid
543  //
544  ASSERT(PointerPde->u.Hard.Valid == 0);
545 
546  /* Request a page */
548  MI_SET_PROCESS2("Kernel");
549  PageFrameNumber = MiRemoveAnyPage(MI_GET_NEXT_COLOR());
550  TempPde.u.Hard.PageFrameNumber = PageFrameNumber;
551 #if (_MI_PAGING_LEVELS >= 3)
552  /* On PAE/x64 systems, there's no double-buffering */
553  /* Initialize the PFN entry for it */
554  MiInitializePfnForOtherProcess(PageFrameNumber,
555  (PMMPTE)PointerPde,
556  PFN_FROM_PTE(MiAddressToPte(PointerPde)));
557 
558  /* Write the actual PDE now */
559  MI_WRITE_VALID_PDE(PointerPde, TempPde);
560 #else
561  //
562  // Save it into our double-buffered system page directory
563  //
564  MmSystemPagePtes[((ULONG_PTR)PointerPde & (SYSTEM_PD_SIZE - 1)) / sizeof(MMPTE)] = TempPde;
565 
566  /* Initialize the PFN */
567  MiInitializePfnForOtherProcess(PageFrameNumber,
568  (PMMPTE)PointerPde,
570 #endif
571 
572  //
573  // Move on to the next expansion address
574  //
575  PointerPde++;
576  BaseVa = (PVOID)((ULONG_PTR)BaseVa + PAGE_SIZE);
577  i--;
578  } while (i > 0);
579 
580  //
581  // Release the PFN database lock
582  //
584 
585  //
586  // These pages are now available, clear their availablity bits
587  //
590  PTE_PER_PAGE;
592  EndAllocation,
593  PageTableCount * PTE_PER_PAGE);
594 
595  //
596  // Update the next expansion location
597  //
599 
600  //
601  // Zero out the newly available memory
602  //
603  RtlZeroMemory(BaseVaStart, PageTableCount * PAGE_SIZE);
604 
605  //
606  // Now try consuming the pages again
607  //
609  SizeInPages,
610  0);
611  if (i == 0xFFFFFFFF)
612  {
613  //
614  // Out of memory!
615  //
616  DPRINT1("FAILED to allocate %Iu bytes from paged pool\n", SizeInBytes);
618  return NULL;
619  }
620  }
621 
622  //
623  // Update the pool hint if the request was just one page
624  //
625  if (SizeInPages == 1) MmPagedPoolInfo.PagedPoolHint = i + 1;
626 
627  //
628  // Update the end bitmap so we know the bounds of this allocation when
629  // the time comes to free it
630  //
631  EndAllocation = i + SizeInPages - 1;
633 
634  //
635  // Now we can release the lock (it mainly protects the bitmap)
636  //
638 
639  //
640  // Now figure out where this allocation starts
641  //
642  BaseVa = (PVOID)((ULONG_PTR)MmPagedPoolStart + (i << PAGE_SHIFT));
643 
644  //
645  // Flush the TLB
646  //
648 
649  /* Setup a demand-zero writable PTE */
651 
652  //
653  // Find the first and last PTE, then loop them all
654  //
655  PointerPte = MiAddressToPte(BaseVa);
656  StartPte = PointerPte + SizeInPages;
657  do
658  {
659  //
660  // Write the demand zero PTE and keep going
661  //
662  MI_WRITE_INVALID_PTE(PointerPte, TempPte);
663  } while (++PointerPte < StartPte);
664 
665  //
666  // Return the allocation address to the caller
667  //
668  return BaseVa;
669  }
670 
671  //
672  // If only one page is being requested, try to grab it from the S-LIST
673  //
674  if ((SizeInPages == 1) && (ExQueryDepthSList(&MiNonPagedPoolSListHead)))
675  {
677  if (BaseVa) return BaseVa;
678  }
679 
680  //
681  // Allocations of less than 4 pages go into their individual buckets
682  //
683  i = SizeInPages - 1;
685 
686  //
687  // Loop through all the free page lists based on the page index
688  //
689  NextHead = &MmNonPagedPoolFreeListHead[i];
691 
692  //
693  // Acquire the nonpaged pool lock
694  //
696  do
697  {
698  //
699  // Now loop through all the free page entries in this given list
700  //
701  NextEntry = NextHead->Flink;
702  while (NextEntry != NextHead)
703  {
704  /* Is freed non paged pool enabled */
706  {
707  /* We need to be able to touch this page, unprotect it */
708  MiUnProtectFreeNonPagedPool(NextEntry, 0);
709  }
710 
711  //
712  // Grab the entry and see if it can handle our allocation
713  //
714  FreeEntry = CONTAINING_RECORD(NextEntry, MMFREE_POOL_ENTRY, List);
715  ASSERT(FreeEntry->Signature == MM_FREE_POOL_SIGNATURE);
716  if (FreeEntry->Size >= SizeInPages)
717  {
718  //
719  // It does, so consume the pages from here
720  //
721  FreeEntry->Size -= SizeInPages;
722 
723  //
724  // The allocation will begin in this free page area
725  //
726  BaseVa = (PVOID)((ULONG_PTR)FreeEntry +
727  (FreeEntry->Size << PAGE_SHIFT));
728 
729  /* Remove the item from the list, depending if pool is protected */
732  else
733  RemoveEntryList(&FreeEntry->List);
734 
735  //
736  // However, check if its' still got space left
737  //
738  if (FreeEntry->Size != 0)
739  {
740  /* Check which list to insert this entry into */
741  i = FreeEntry->Size - 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  //
851 
852  /* Check that we have enough available pages for this request */
853  if (MmAvailablePages < SizeInPages)
854  {
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  //
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 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 - 1))
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 = (ULONG)(FreeEntry->Size - 1);
1201 
1202  /* Insert the entry into the free list head, check for prot. pool */
1205  else
1207  }
1208  else
1209  {
1210  //
1211  // Otherwise, just combine our free pages into this entry
1212  //
1213  FreeEntry->Size += FreePages;
1214  }
1215  }
1216 
1217  //
1218  // Check if we were unable to do any compaction, and we'll stick with this
1219  //
1220  if (FreeEntry == StartingVa)
1221  {
1222  //
1223  // Well, now we are a free entry. At worse we just have our newly freed
1224  // pages, at best we have our pages plus whatever entry came after us
1225  //
1226  FreeEntry->Size = FreePages;
1227 
1228  //
1229  // Find the appropriate list we should be on
1230  //
1231  i = FreeEntry->Size - 1;
1233 
1234  /* Insert the entry into the free list head, check for prot. pool */
1237  else
1239  }
1240 
1241  //
1242  // Just a sanity check
1243  //
1244  ASSERT(FreePages != 0);
1245 
1246  //
1247  // Get all the pages between our allocation and its end. These will all now
1248  // become free page chunks.
1249  //
1250  NextEntry = StartingVa;
1251  LastEntry = (PMMFREE_POOL_ENTRY)((ULONG_PTR)NextEntry + (FreePages << PAGE_SHIFT));
1252  do
1253  {
1254  //
1255  // Link back to the parent free entry, and keep going
1256  //
1257  NextEntry->Owner = FreeEntry;
1258  NextEntry->Signature = MM_FREE_POOL_SIGNATURE;
1259  NextEntry = (PMMFREE_POOL_ENTRY)((ULONG_PTR)NextEntry + PAGE_SIZE);
1260  } while (NextEntry != LastEntry);
1261 
1262  /* Is freed non paged pool protected? */
1264  {
1265  /* Protect the freed pool! */
1266  MiProtectFreeNonPagedPool(FreeEntry, FreeEntry->Size);
1267  }
1268 
1269  //
1270  // We're done, release the lock and let the caller know how much we freed
1271  //
1273  return NumberOfPages;
1274 }
1275 
1276 
1277 BOOLEAN
1278 NTAPI
1280  IN ULONG CurrentMaxQuota,
1281  OUT PULONG NewMaxQuota)
1282 {
1283  //
1284  // Not implemented
1285  //
1286  UNIMPLEMENTED;
1287  *NewMaxQuota = CurrentMaxQuota + 65536;
1288  return TRUE;
1289 }
1290 
1291 NTSTATUS
1292 NTAPI
1294 {
1295  PMMPTE PointerPte, LastPte;
1296  PMMPDE PointerPde, LastPde;
1297  PFN_NUMBER PageFrameIndex, PdeCount;
1298  PPOOL_DESCRIPTOR PoolDescriptor;
1299  PMM_SESSION_SPACE SessionGlobal;
1300  PMM_PAGED_POOL_INFO PagedPoolInfo;
1301  NTSTATUS Status;
1302  ULONG Index, PoolSize, BitmapSize;
1303  PAGED_CODE();
1304 
1305  /* Lock session pool */
1306  SessionGlobal = MmSessionSpace->GlobalVirtualAddress;
1307  KeInitializeGuardedMutex(&SessionGlobal->PagedPoolMutex);
1308 
1309  /* Setup a valid pool descriptor */
1310  PoolDescriptor = &MmSessionSpace->PagedPool;
1311  ExInitializePoolDescriptor(PoolDescriptor,
1313  0,
1314  0,
1315  &SessionGlobal->PagedPoolMutex);
1316 
1317  /* Setup the pool addresses */
1320  DPRINT1("Session Pool Start: 0x%p End: 0x%p\n",
1322 
1323  /* Reset all the counters */
1324  PagedPoolInfo = &MmSessionSpace->PagedPoolInfo;
1325  PagedPoolInfo->PagedPoolCommit = 0;
1326  PagedPoolInfo->PagedPoolHint = 0;
1327  PagedPoolInfo->AllocatedPagedPool = 0;
1328 
1329  /* Compute PDE and PTE addresses */
1334 
1335  /* Write them down */
1336  MmSessionSpace->PagedPoolBasePde = PointerPde;
1337  PagedPoolInfo->FirstPteForPagedPool = PointerPte;
1338  PagedPoolInfo->LastPteForPagedPool = LastPte;
1339  PagedPoolInfo->NextPdeForPagedPoolExpansion = PointerPde + 1;
1340 
1341  /* Zero the PDEs */
1342  PdeCount = LastPde - PointerPde;
1343  RtlZeroMemory(PointerPde, (PdeCount + 1) * sizeof(MMPTE));
1344 
1345  /* Initialize the PFN for the PDE */
1346  Status = MiInitializeAndChargePfn(&PageFrameIndex,
1347  PointerPde,
1349  TRUE);
1351 
1352  /* Initialize the first page table */
1354  Index >>= 22;
1355 #ifndef _M_AMD64 // FIXME
1357  MmSessionSpace->PageTables[Index] = *PointerPde;
1358 #endif
1359 
1360  /* Bump up counters */
1363 
1364  /* Compute the size of the pool in pages, and of the bitmap for it */
1365  PoolSize = MmSessionPoolSize >> PAGE_SHIFT;
1366  BitmapSize = sizeof(RTL_BITMAP) + ((PoolSize + 31) / 32) * sizeof(ULONG);
1367 
1368  /* Allocate and initialize the bitmap to track allocations */
1370  BitmapSize,
1371  TAG_MM);
1372  ASSERT(PagedPoolInfo->PagedPoolAllocationMap != NULL);
1374  (PULONG)(PagedPoolInfo->PagedPoolAllocationMap + 1),
1375  PoolSize);
1376 
1377  /* Set all bits, but clear the first page table's worth */
1378  RtlSetAllBits(PagedPoolInfo->PagedPoolAllocationMap);
1379  RtlClearBits(PagedPoolInfo->PagedPoolAllocationMap, 0, PTE_PER_PAGE);
1380 
1381  /* Allocate and initialize the bitmap to track free space */
1383  BitmapSize,
1384  TAG_MM);
1385  ASSERT(PagedPoolInfo->EndOfPagedPoolBitmap != NULL);
1387  (PULONG)(PagedPoolInfo->EndOfPagedPoolBitmap + 1),
1388  PoolSize);
1389 
1390  /* Clear all the bits and return success */
1391  RtlClearAllBits(PagedPoolInfo->EndOfPagedPoolBitmap);
1392  return STATUS_SUCCESS;
1393 }
1394 
1395 /* PUBLIC FUNCTIONS ***********************************************************/
1396 
1397 /*
1398  * @unimplemented
1399  */
1400 PVOID
1401 NTAPI
1403  IN ULONG PoolTag)
1404 {
1405  UNIMPLEMENTED;
1406  return NULL;
1407 }
1408 
1409 /*
1410  * @unimplemented
1411  */
1412 VOID
1413 NTAPI
1415  IN ULONG PoolTag)
1416 {
1417  UNIMPLEMENTED;
1418 }
1419 
1420 /* EOF */
VOID NTAPI MiInitializePoolEvents(VOID)
Definition: pool.c:201
#define MI_MAKE_SOFTWARE_PTE(p, x)
Definition: miarm.h:185
PRTL_BITMAP PagedPoolAllocationMap
Definition: mm.h:453
#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:406
#define PAGE_SHIFT
Definition: env_spec_w32.h:45
#define IN
Definition: typedefs.h:39
SIZE_T NonPageablePages
Definition: miarm.h:487
BOOLEAN NTAPI MiUnProtectFreeNonPagedPool(IN PVOID VirtualAddress, IN ULONG PageCount)
Definition: pool.c:68
PVOID PagedPoolStart
Definition: miarm.h:489
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 _MMPTE::@2304 u
VOID FASTCALL KeAcquireGuardedMutex(IN PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:42
PMMPDE PageTables
Definition: miarm.h:513
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:443
struct _MMPFN::@1778::@1784 e2
#define VERIFIER_POOL_MASK
Definition: mm.h:101
NTSTATUS NTAPI MiInitializeAndChargePfn(OUT PPFN_NUMBER PageFrameIndex, IN PMMPDE PointerPde, IN PFN_NUMBER ContainingPageFrame, IN BOOLEAN SessionAllocation)
Definition: pfnlist.c:1092
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:238
HARDWARE_PDE_ARMV6 TempPde
Definition: winldr.c:78
FORCEINLINE KIRQL MiAcquirePfnLock(VOID)
Definition: mm.h:919
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:1279
NTSTATUS NTAPI MiInitializeSessionPool(VOID)
Definition: pool.c:1293
#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
union _MMPFN::@1781 u4
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
FORCEINLINE VOID MiReleasePfnLock(_In_ KIRQL OldIrql)
Definition: mm.h:926
union _MMPFN::@1778 u3
USHORT PageLocation
Definition: mm.h:333
PSLIST_ENTRY WINAPI InterlockedPopEntrySList(PSLIST_HEADER ListHead)
Definition: interlocked.c:55
ULONG MmSpecialPoolTag
Definition: pool.c:27
MM_PAGED_POOL_INFO PagedPoolInfo
Definition: miarm.h:505
FORCEINLINE VOID MiReleasePfnLockFromDpcLevel(VOID)
Definition: mm.h:945
SLIST_HEADER MiNonPagedPoolSListHead
Definition: pool.c:30
PVOID MmNonPagedPoolEnd
Definition: mminit.c:99
uint32_t ULONG_PTR
Definition: typedefs.h:65
FORCEINLINE VOID MiAcquirePfnLockAtDpcLevel(VOID)
Definition: mm.h:934
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
PFN_COUNT MmNumberOfFreeNonPagedPool
Definition: pool.c:21
BOOLEAN NTAPI MiRaisePoolQuota(IN POOL_TYPE PoolType, IN ULONG CurrentMaxQuota, OUT PULONG NewMaxQuota)
Definition: pool.c:1279
UCHAR KIRQL
Definition: env_spec_w32.h:591
MMPFNENTRY e1
Definition: mm.h:365
PVOID MmSessionBase
Definition: init.c:33
#define MiAddressToPte(x)
Definition: mmx86.c:19
ULONG PFN_NUMBER
Definition: ke.h:9
#define TAG_MM
Definition: tag.h:136
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
PMMPTE LastPteForPagedPool
Definition: mm.h:456
#define FALSE
Definition: types.h:117
FORCEINLINE VOID MI_WRITE_VALID_PTE(IN PMMPTE PointerPte, IN MMPTE TempPte)
Definition: miarm.h:942
ULONG_PTR ShareCount
Definition: mm.h:358
#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:166
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:287
PFN_NUMBER MiStartOfInitialPoolFrame
Definition: pool.c:23
NTSYSAPI void WINAPI RtlSetAllBits(PRTL_BITMAP)
LIST_ENTRY List
Definition: mm.h:441
VOID NTAPI MiInitializeNonPagedPoolThresholds(VOID)
Definition: pool.c:184
PFN_NUMBER MmSystemPageDirectory[PPE_PER_PAGE]
Definition: init.c:40
unsigned char BOOLEAN
POOL_DESCRIPTOR PagedPool
Definition: miarm.h:509
SIZE_T AllocatedPagedPool
Definition: mm.h:460
#define MI_MAX_FREE_PAGE_LISTS
Definition: mm.h:80
PVOID MmNonPagedPoolEnd0
Definition: pool.c:22
ULONG_PTR VerifierAllocation
Definition: mm.h:388
PFN_NUMBER MiHighPagedPoolThreshold
Definition: mminit.c:303
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:1001
#define MI_SET_USAGE(x)
Definition: mm.h:285
_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:459
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:416
FORCEINLINE VOID InitializeSListHead(_Out_ PSLIST_HEADER SListHead)
Definition: rtlfuncs.h:3353
ULONG MmConsumedPoolPercentage
Definition: pool.c:28
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:442
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
struct _MM_SESSION_SPACE * GlobalVirtualAddress
Definition: miarm.h:476
#define MM_FREE_POOL_SIGNATURE
Definition: mm.h:448
#define ASSERT(a)
Definition: mode.c:45
SIZE_T CommittedPages
Definition: miarm.h:488
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
Definition: mm.h:439
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:420
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
CODE_SEG("INIT")
Definition: fsrtlpc.c:19
PFN_NUMBER MiHighNonPagedPoolThreshold
Definition: mminit.c:305
MMPTE ValidKernelPte
Definition: init.c:29
ULONG MiNonPagedPoolSListMaximum
Definition: pool.c:31
_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:148
struct _MMFREE_POOL_ENTRY * Owner
Definition: mm.h:444
#define BYTES_TO_PAGES(Size)
ULONG MiPagedPoolSListMaximum
Definition: pool.c:33
PVOID PagedPoolEnd
Definition: miarm.h:490
KGUARDED_MUTEX PagedPoolMutex
Definition: miarm.h:504
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:790
#define MM_READWRITE
Definition: inbv.c:12
PFN_NUMBER MmMaximumNonPagedPoolInPages
Definition: mminit.c:30
_Must_inspect_result_ _In_ WDFCMRESLIST List
Definition: wdfresource.h:550
Definition: mm.h:341
#define PAGE_SIZE
Definition: env_spec_w32.h:49
Definition: typedefs.h:119
VOID NTAPI MiInitializeNonPagedPool(VOID)
Definition: pool.c:276
NTKERNELAPI PSLIST_ENTRY FASTCALL InterlockedPushEntrySList(IN PSLIST_HEADER ListHead, IN PSLIST_ENTRY ListEntry)
Definition: interlocked.c:82
#define _1MB
Definition: miarm.h:15
KIRQL FASTCALL KeAcquireQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber)
Definition: spinlock.c:108
FORCEINLINE PMMPFN MiGetPfnEntry(IN PFN_NUMBER Pfn)
Definition: mm.h:958
FORCEINLINE VOID MiProtectedPoolUnProtectLinks(IN PLIST_ENTRY Links, OUT PVOID *PoolFlink, OUT PVOID *PoolBlink)
Definition: pool.c:103
MMPTE ValidKernelPde
Definition: init.c:28
ULONG_PTR Long
Definition: mmtypes.h:215
PVOID MmPagedPoolStart
Definition: miarm.h:581
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:297
_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:475
ULONG_PTR SIZE_T
Definition: typedefs.h:80
MMPTE_HARDWARE Hard
Definition: mmtypes.h:217
#define SYSTEM_PD_SIZE
Definition: miarm.h:28
#define MiPteToPde(_Pte)
Definition: mm.h:236
FORCEINLINE VOID MI_WRITE_INVALID_PTE(IN PMMPTE PointerPte, IN MMPTE InvalidPte)
Definition: miarm.h:975
PFN_COUNT MmNumberOfPhysicalPages
Definition: init.c:48
BOOLEAN MmProtectFreedNonPagedPool
Definition: pool.c:29
VOID FASTCALL KeInitializeGuardedMutex(OUT PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:31
#define MiPdeToPte(_Pde)
Definition: mm.h:235
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:454
#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:354
_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
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
SLIST_HEADER MiPagedPoolSListHead
Definition: pool.c:32
FORCEINLINE PFN_NUMBER MiGetPfnEntryIndex(IN PMMPFN Pfn1)
Definition: mm.h:978
#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
union _MMPFN::@1777 u2
#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:39
PFN_NUMBER MiLowNonPagedPoolThreshold
Definition: mminit.c:304
ULONG PagedPoolHint
Definition: mm.h:458
#define STATUS_SUCCESS
Definition: shellext.h:65
ULONG MmSizeOfNonPagedPoolInBytes
Definition: init.c:21
PFN_NUMBER MmSizeOfPagedPoolInPages
Definition: mminit.c:111
#define DPRINT
Definition: sndvol32.h:71
PMMPTE FirstPteForPagedPool
Definition: mm.h:455
FORCEINLINE PVOID MiPteToAddress(PMMPTE PointerPte)
Definition: mm.h:201
LIST_ENTRY MmNonPagedPoolFreeListHead[MI_MAX_FREE_PAGE_LISTS]
Definition: pool.c:20
VOID NTAPI KeClearEvent(IN PKEVENT Event)
Definition: eventobj.c:22
FORCEINLINE BOOLEAN MI_IS_PHYSICAL_ADDRESS(IN PVOID Address)
Definition: miarm.h:928
PMMPDE PagedPoolBasePde
Definition: miarm.h:491
#define PFN_FROM_PTE(v)
Definition: mm.h:92
PVOID NTAPI MmAllocateMappingAddress(IN SIZE_T NumberOfBytes, IN ULONG PoolTag)
Definition: pool.c:1402
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 _1GB
Definition: miarm.h:16
VOID NTAPI MmFreeMappingAddress(IN PVOID BaseAddress, IN ULONG PoolTag)
Definition: pool.c:1414
ULONG PageFrameNumber
Definition: mmtypes.h:109
PMMPDE NextPdeForPagedPoolExpansion
Definition: mm.h:457
FORCEINLINE VOID MiProtectedPoolProtectLinks(IN PVOID PoolFlink, IN PVOID PoolBlink)
Definition: pool.c:138
PFN_NUMBER SessionPageDirectoryIndex
Definition: miarm.h:486
#define PAGED_CODE()