ReactOS  0.4.13-dev-247-g0f29b3f
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 INIT_FUNCTION
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 INIT_FUNCTION
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 INIT_FUNCTION
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_COUNT) + 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_COUNT;
592  EndAllocation,
593  PageTableCount * PTE_COUNT);
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  DPRINT1("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  //
853  // Loop the pages
854  //
856  do
857  {
858  /* Allocate a page */
860  MI_SET_PROCESS2("Kernel");
861  PageFrameNumber = MiRemoveAnyPage(MI_GET_NEXT_COLOR());
862 
863  /* Get the PFN entry for it and fill it out */
864  Pfn1 = MiGetPfnEntry(PageFrameNumber);
865  Pfn1->u3.e2.ReferenceCount = 1;
866  Pfn1->u2.ShareCount = 1;
867  Pfn1->PteAddress = PointerPte;
869  Pfn1->u4.VerifierAllocation = 0;
870 
871  /* Write the PTE for it */
872  TempPte.u.Hard.PageFrameNumber = PageFrameNumber;
873  MI_WRITE_VALID_PTE(PointerPte++, TempPte);
874  } while (--SizeInPages > 0);
875 
876  //
877  // This is the last page
878  //
879  Pfn1->u3.e1.EndOfAllocation = 1;
880 
881  //
882  // Get the first page and mark it as such
883  //
884  Pfn1 = MiGetPfnEntry(StartPte->u.Hard.PageFrameNumber);
885  Pfn1->u3.e1.StartOfAllocation = 1;
886 
887  /* Mark it as a verifier allocation if needed */
888  ASSERT(Pfn1->u4.VerifierAllocation == 0);
890 
891  //
892  // Release the PFN and nonpaged pool lock
893  //
896 
897  //
898  // Return the address
899  //
900  return MiPteToAddress(StartPte);
901 }
902 
903 ULONG
904 NTAPI
906 {
907  PMMPTE PointerPte, StartPte;
908  PMMPFN Pfn1, StartPfn;
909  PFN_COUNT FreePages, NumberOfPages;
910  KIRQL OldIrql;
911  PMMFREE_POOL_ENTRY FreeEntry, NextEntry, LastEntry;
912  ULONG i, End;
914 
915  //
916  // Handle paged pool
917  //
918  if ((StartingVa >= MmPagedPoolStart) && (StartingVa <= MmPagedPoolEnd))
919  {
920  //
921  // Calculate the offset from the beginning of paged pool, and convert it
922  // into pages
923  //
924  Offset = (ULONG_PTR)StartingVa - (ULONG_PTR)MmPagedPoolStart;
925  i = (ULONG)(Offset >> PAGE_SHIFT);
926  End = i;
927 
928  //
929  // Now use the end bitmap to scan until we find a set bit, meaning that
930  // this allocation finishes here
931  //
932  while (!RtlTestBit(MmPagedPoolInfo.EndOfPagedPoolBitmap, End)) End++;
933 
934  //
935  // Now calculate the total number of pages this allocation spans. If it's
936  // only one page, add it to the S-LIST instead of freeing it
937  //
938  NumberOfPages = End - i + 1;
939  if ((NumberOfPages == 1) &&
941  {
943  return 1;
944  }
945 
946  /* Delete the actual pages */
947  PointerPte = MmPagedPoolInfo.FirstPteForPagedPool + i;
948  FreePages = MiDeleteSystemPageableVm(PointerPte, NumberOfPages, 0, NULL);
949  ASSERT(FreePages == NumberOfPages);
950 
951  //
952  // Acquire the paged pool lock
953  //
955 
956  //
957  // Clear the allocation and free bits
958  //
961 
962  //
963  // Update the hint if we need to
964  //
966 
967  //
968  // Release the lock protecting the bitmaps
969  //
971 
972  //
973  // And finally return the number of pages freed
974  //
975  return NumberOfPages;
976  }
977 
978  //
979  // Get the first PTE and its corresponding PFN entry. If this is also the
980  // last PTE, meaning that this allocation was only for one page, push it into
981  // the S-LIST instead of freeing it
982  //
983  StartPte = PointerPte = MiAddressToPte(StartingVa);
984  StartPfn = Pfn1 = MiGetPfnEntry(PointerPte->u.Hard.PageFrameNumber);
985  if ((Pfn1->u3.e1.EndOfAllocation == 1) &&
987  {
989  return 1;
990  }
991 
992  //
993  // Loop until we find the last PTE
994  //
995  while (Pfn1->u3.e1.EndOfAllocation == 0)
996  {
997  //
998  // Keep going
999  //
1000  PointerPte++;
1001  Pfn1 = MiGetPfnEntry(PointerPte->u.Hard.PageFrameNumber);
1002  }
1003 
1004  //
1005  // Now we know how many pages we have
1006  //
1007  NumberOfPages = (PFN_COUNT)(PointerPte - StartPte + 1);
1008 
1009  //
1010  // Acquire the nonpaged pool lock
1011  //
1013 
1014  //
1015  // Mark the first and last PTEs as not part of an allocation anymore
1016  //
1017  StartPfn->u3.e1.StartOfAllocation = 0;
1018  Pfn1->u3.e1.EndOfAllocation = 0;
1019 
1020  //
1021  // Assume we will free as many pages as the allocation was
1022  //
1023  FreePages = NumberOfPages;
1024 
1025  //
1026  // Peek one page past the end of the allocation
1027  //
1028  PointerPte++;
1029 
1030  //
1031  // Guard against going past initial nonpaged pool
1032  //
1034  {
1035  //
1036  // This page is on the outskirts of initial nonpaged pool, so ignore it
1037  //
1038  Pfn1 = NULL;
1039  }
1040  else
1041  {
1042  /* Sanity check */
1043  ASSERT((ULONG_PTR)StartingVa + NumberOfPages <= (ULONG_PTR)MmNonPagedPoolEnd);
1044 
1045  /* Check if protected pool is enabled */
1047  {
1048  /* The freed block will be merged, it must be made accessible */
1050  }
1051 
1052  //
1053  // Otherwise, our entire allocation must've fit within the initial non
1054  // paged pool, or the expansion nonpaged pool, so get the PFN entry of
1055  // the next allocation
1056  //
1057  if (PointerPte->u.Hard.Valid == 1)
1058  {
1059  //
1060  // It's either expansion or initial: get the PFN entry
1061  //
1062  Pfn1 = MiGetPfnEntry(PointerPte->u.Hard.PageFrameNumber);
1063  }
1064  else
1065  {
1066  //
1067  // This means we've reached the guard page that protects the end of
1068  // the expansion nonpaged pool
1069  //
1070  Pfn1 = NULL;
1071  }
1072 
1073  }
1074 
1075  //
1076  // Check if this allocation actually exists
1077  //
1078  if ((Pfn1) && (Pfn1->u3.e1.StartOfAllocation == 0))
1079  {
1080  //
1081  // It doesn't, so we should actually locate a free entry descriptor
1082  //
1083  FreeEntry = (PMMFREE_POOL_ENTRY)((ULONG_PTR)StartingVa +
1084  (NumberOfPages << PAGE_SHIFT));
1085  ASSERT(FreeEntry->Signature == MM_FREE_POOL_SIGNATURE);
1086  ASSERT(FreeEntry->Owner == FreeEntry);
1087 
1088  /* Consume this entry's pages */
1089  FreePages += FreeEntry->Size;
1090 
1091  /* Remove the item from the list, depending if pool is protected */
1093  MiProtectedPoolRemoveEntryList(&FreeEntry->List);
1094  else
1095  RemoveEntryList(&FreeEntry->List);
1096  }
1097 
1098  //
1099  // Now get the official free entry we'll create for the caller's allocation
1100  //
1101  FreeEntry = StartingVa;
1102 
1103  //
1104  // Check if the our allocation is the very first page
1105  //
1107  {
1108  //
1109  // Then we can't do anything or we'll risk underflowing
1110  //
1111  Pfn1 = NULL;
1112  }
1113  else
1114  {
1115  //
1116  // Otherwise, get the PTE for the page right before our allocation
1117  //
1118  PointerPte -= NumberOfPages + 1;
1119 
1120  /* Check if protected pool is enabled */
1122  {
1123  /* The freed block will be merged, it must be made accessible */
1125  }
1126 
1127  /* Check if this is valid pool, or a guard page */
1128  if (PointerPte->u.Hard.Valid == 1)
1129  {
1130  //
1131  // It's either expansion or initial nonpaged pool, get the PFN entry
1132  //
1133  Pfn1 = MiGetPfnEntry(PointerPte->u.Hard.PageFrameNumber);
1134  }
1135  else
1136  {
1137  //
1138  // We must've reached the guard page, so don't risk touching it
1139  //
1140  Pfn1 = NULL;
1141  }
1142  }
1143 
1144  //
1145  // Check if there is a valid PFN entry for the page before the allocation
1146  // and then check if this page was actually the end of an allocation.
1147  // If it wasn't, then we know for sure it's a free page
1148  //
1149  if ((Pfn1) && (Pfn1->u3.e1.EndOfAllocation == 0))
1150  {
1151  //
1152  // Get the free entry descriptor for that given page range
1153  //
1154  FreeEntry = (PMMFREE_POOL_ENTRY)((ULONG_PTR)StartingVa - PAGE_SIZE);
1155  ASSERT(FreeEntry->Signature == MM_FREE_POOL_SIGNATURE);
1156  FreeEntry = FreeEntry->Owner;
1157 
1158  /* Check if protected pool is enabled */
1160  {
1161  /* The freed block will be merged, it must be made accessible */
1162  MiUnProtectFreeNonPagedPool(FreeEntry, 0);
1163  }
1164 
1165  //
1166  // Check if the entry is small enough to be indexed on a free list
1167  // If it is, we'll want to re-insert it, since we're about to
1168  // collapse our pages on top of it, which will change its count
1169  //
1170  if (FreeEntry->Size < (MI_MAX_FREE_PAGE_LISTS - 1))
1171  {
1172  /* Remove the item from the list, depending if pool is protected */
1174  MiProtectedPoolRemoveEntryList(&FreeEntry->List);
1175  else
1176  RemoveEntryList(&FreeEntry->List);
1177 
1178  //
1179  // Update its size
1180  //
1181  FreeEntry->Size += FreePages;
1182 
1183  //
1184  // And now find the new appropriate list to place it in
1185  //
1186  i = (ULONG)(FreeEntry->Size - 1);
1188 
1189  /* Insert the entry into the free list head, check for prot. pool */
1192  else
1194  }
1195  else
1196  {
1197  //
1198  // Otherwise, just combine our free pages into this entry
1199  //
1200  FreeEntry->Size += FreePages;
1201  }
1202  }
1203 
1204  //
1205  // Check if we were unable to do any compaction, and we'll stick with this
1206  //
1207  if (FreeEntry == StartingVa)
1208  {
1209  //
1210  // Well, now we are a free entry. At worse we just have our newly freed
1211  // pages, at best we have our pages plus whatever entry came after us
1212  //
1213  FreeEntry->Size = FreePages;
1214 
1215  //
1216  // Find the appropriate list we should be on
1217  //
1218  i = FreeEntry->Size - 1;
1220 
1221  /* Insert the entry into the free list head, check for prot. pool */
1224  else
1226  }
1227 
1228  //
1229  // Just a sanity check
1230  //
1231  ASSERT(FreePages != 0);
1232 
1233  //
1234  // Get all the pages between our allocation and its end. These will all now
1235  // become free page chunks.
1236  //
1237  NextEntry = StartingVa;
1238  LastEntry = (PMMFREE_POOL_ENTRY)((ULONG_PTR)NextEntry + (FreePages << PAGE_SHIFT));
1239  do
1240  {
1241  //
1242  // Link back to the parent free entry, and keep going
1243  //
1244  NextEntry->Owner = FreeEntry;
1245  NextEntry->Signature = MM_FREE_POOL_SIGNATURE;
1246  NextEntry = (PMMFREE_POOL_ENTRY)((ULONG_PTR)NextEntry + PAGE_SIZE);
1247  } while (NextEntry != LastEntry);
1248 
1249  /* Is freed non paged pool protected? */
1251  {
1252  /* Protect the freed pool! */
1253  MiProtectFreeNonPagedPool(FreeEntry, FreeEntry->Size);
1254  }
1255 
1256  //
1257  // We're done, release the lock and let the caller know how much we freed
1258  //
1260  return NumberOfPages;
1261 }
1262 
1263 
1264 BOOLEAN
1265 NTAPI
1267  IN ULONG CurrentMaxQuota,
1268  OUT PULONG NewMaxQuota)
1269 {
1270  //
1271  // Not implemented
1272  //
1273  UNIMPLEMENTED;
1274  *NewMaxQuota = CurrentMaxQuota + 65536;
1275  return TRUE;
1276 }
1277 
1278 NTSTATUS
1279 NTAPI
1281 {
1282  PMMPTE PointerPte, LastPte;
1283  PMMPDE PointerPde, LastPde;
1284  PFN_NUMBER PageFrameIndex, PdeCount;
1285  PPOOL_DESCRIPTOR PoolDescriptor;
1286  PMM_SESSION_SPACE SessionGlobal;
1287  PMM_PAGED_POOL_INFO PagedPoolInfo;
1288  NTSTATUS Status;
1289  ULONG Index, PoolSize, BitmapSize;
1290  PAGED_CODE();
1291 
1292  /* Lock session pool */
1293  SessionGlobal = MmSessionSpace->GlobalVirtualAddress;
1294  KeInitializeGuardedMutex(&SessionGlobal->PagedPoolMutex);
1295 
1296  /* Setup a valid pool descriptor */
1297  PoolDescriptor = &MmSessionSpace->PagedPool;
1298  ExInitializePoolDescriptor(PoolDescriptor,
1300  0,
1301  0,
1302  &SessionGlobal->PagedPoolMutex);
1303 
1304  /* Setup the pool addresses */
1307  DPRINT1("Session Pool Start: 0x%p End: 0x%p\n",
1309 
1310  /* Reset all the counters */
1311  PagedPoolInfo = &MmSessionSpace->PagedPoolInfo;
1312  PagedPoolInfo->PagedPoolCommit = 0;
1313  PagedPoolInfo->PagedPoolHint = 0;
1314  PagedPoolInfo->AllocatedPagedPool = 0;
1315 
1316  /* Compute PDE and PTE addresses */
1321 
1322  /* Write them down */
1323  MmSessionSpace->PagedPoolBasePde = PointerPde;
1324  PagedPoolInfo->FirstPteForPagedPool = PointerPte;
1325  PagedPoolInfo->LastPteForPagedPool = LastPte;
1326  PagedPoolInfo->NextPdeForPagedPoolExpansion = PointerPde + 1;
1327 
1328  /* Zero the PDEs */
1329  PdeCount = LastPde - PointerPde;
1330  RtlZeroMemory(PointerPde, (PdeCount + 1) * sizeof(MMPTE));
1331 
1332  /* Initialize the PFN for the PDE */
1333  Status = MiInitializeAndChargePfn(&PageFrameIndex,
1334  PointerPde,
1336  TRUE);
1338 
1339  /* Initialize the first page table */
1341  Index >>= 22;
1342 #ifndef _M_AMD64 // FIXME
1344  MmSessionSpace->PageTables[Index] = *PointerPde;
1345 #endif
1346 
1347  /* Bump up counters */
1350 
1351  /* Compute the size of the pool in pages, and of the bitmap for it */
1352  PoolSize = MmSessionPoolSize >> PAGE_SHIFT;
1353  BitmapSize = sizeof(RTL_BITMAP) + ((PoolSize + 31) / 32) * sizeof(ULONG);
1354 
1355  /* Allocate and initialize the bitmap to track allocations */
1357  BitmapSize,
1358  TAG_MM);
1359  ASSERT(PagedPoolInfo->PagedPoolAllocationMap != NULL);
1361  (PULONG)(PagedPoolInfo->PagedPoolAllocationMap + 1),
1362  PoolSize);
1363 
1364  /* Set all bits, but clear the first page table's worth */
1365  RtlSetAllBits(PagedPoolInfo->PagedPoolAllocationMap);
1366  RtlClearBits(PagedPoolInfo->PagedPoolAllocationMap, 0, PTE_PER_PAGE);
1367 
1368  /* Allocate and initialize the bitmap to track free space */
1370  BitmapSize,
1371  TAG_MM);
1372  ASSERT(PagedPoolInfo->EndOfPagedPoolBitmap != NULL);
1374  (PULONG)(PagedPoolInfo->EndOfPagedPoolBitmap + 1),
1375  PoolSize);
1376 
1377  /* Clear all the bits and return success */
1378  RtlClearAllBits(PagedPoolInfo->EndOfPagedPoolBitmap);
1379  return STATUS_SUCCESS;
1380 }
1381 
1382 /* PUBLIC FUNCTIONS ***********************************************************/
1383 
1384 /*
1385  * @unimplemented
1386  */
1387 PVOID
1388 NTAPI
1390  IN ULONG PoolTag)
1391 {
1392  UNIMPLEMENTED;
1393  return NULL;
1394 }
1395 
1396 /*
1397  * @unimplemented
1398  */
1399 VOID
1400 NTAPI
1402  IN ULONG PoolTag)
1403 {
1404  UNIMPLEMENTED;
1405 }
1406 
1407 /* EOF */
#define MI_MAKE_SOFTWARE_PTE(p, x)
Definition: miarm.h:193
PRTL_BITMAP PagedPoolAllocationMap
Definition: mm.h:414
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:38
NTSYSAPI void WINAPI RtlClearBits(PRTL_BITMAP, ULONG, ULONG)
#define TRUE
Definition: types.h:120
SIZE_T NonPageablePages
Definition: miarm.h:495
BOOLEAN NTAPI MiUnProtectFreeNonPagedPool(IN PVOID VirtualAddress, IN ULONG PageCount)
Definition: pool.c:68
NTSYSAPI void WINAPI RtlInitializeBitMap(PRTL_BITMAP, PULONG, ULONG)
PVOID PagedPoolStart
Definition: miarm.h:497
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
VOID FASTCALL KeAcquireGuardedMutex(IN PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:42
PMMPDE PageTables
Definition: miarm.h:521
union _MMPTE::@2227 u
ULONG PFN_COUNT
Definition: mmtypes.h:102
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:404
#define VERIFIER_POOL_MASK
Definition: mm.h:103
NTSTATUS NTAPI MiInitializeAndChargePfn(OUT PPFN_NUMBER PageFrameIndex, IN PMMPDE PointerPde, IN PFN_NUMBER ContainingPageFrame, IN BOOLEAN SessionAllocation)
Definition: pfnlist.c:1093
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 MM_READWRITE
Definition: miarm.h:51
#define MI_GET_NEXT_COLOR()
Definition: miarm.h:246
HARDWARE_PDE_ARMV6 TempPde
Definition: winldr.c:77
FORCEINLINE KIRQL MiAcquirePfnLock(VOID)
Definition: mm.h:901
PMM_SESSION_SPACE MmSessionSpace
Definition: session.c:21
PVOID MmPagedPoolEnd
Definition: init.c:26
union _MMPFN::@1721 u3
VOID NTAPI MiInitializePfnForOtherProcess(IN PFN_NUMBER PageFrameIndex, IN PVOID PteAddress, IN PFN_NUMBER PteFrame)
Definition: pfnlist.c:1280
NTSTATUS NTAPI MiInitializeSessionPool(VOID)
Definition: pool.c:1280
#define InsertTailList(ListHead, Entry)
LONG NTAPI KeSetEvent(IN PKEVENT Event, IN KPRIORITY Increment, IN BOOLEAN Wait)
Definition: eventobj.c:159
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
FORCEINLINE VOID MiReleasePfnLock(_In_ KIRQL OldIrql)
Definition: mm.h:908
USHORT PageLocation
Definition: mm.h:297
#define PAGED_CODE()
Definition: video.h:57
PSLIST_ENTRY WINAPI InterlockedPopEntrySList(PSLIST_HEADER ListHead)
Definition: interlocked.c:55
ULONG MmSpecialPoolTag
Definition: pool.c:27
union _MMPFN::@1720 u2
MM_PAGED_POOL_INFO PagedPoolInfo
Definition: miarm.h:513
FORCEINLINE VOID MiReleasePfnLockFromDpcLevel(VOID)
Definition: mm.h:927
SLIST_HEADER MiNonPagedPoolSListHead
Definition: pool.c:30
PVOID MmNonPagedPoolEnd
Definition: mminit.c:99
uint32_t ULONG_PTR
Definition: typedefs.h:63
FORCEINLINE VOID MiAcquirePfnLockAtDpcLevel(VOID)
Definition: mm.h:916
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
struct _MMPFN::@1721::@1727 e2
PFN_COUNT MmNumberOfFreeNonPagedPool
Definition: pool.c:21
BOOLEAN NTAPI MiRaisePoolQuota(IN POOL_TYPE PoolType, IN ULONG CurrentMaxQuota, OUT PULONG NewMaxQuota)
Definition: pool.c:1266
UCHAR KIRQL
Definition: env_spec_w32.h:591
MMPFNENTRY e1
Definition: mm.h:329
PVOID MmSessionBase
Definition: init.c:33
#define PDE_COUNT
Definition: miarm.h:32
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
#define MiAddressToPte(x)
Definition: mmx86.c:19
ULONG PFN_NUMBER
Definition: ke.h:8
#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
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
PMMPTE LastPteForPagedPool
Definition: mm.h:417
FORCEINLINE VOID MI_WRITE_VALID_PTE(IN PMMPTE PointerPte, IN MMPTE TempPte)
Definition: miarm.h:951
ULONG_PTR ShareCount
Definition: mm.h:322
#define InterlockedIncrementSizeT(a)
Definition: interlocked.h:220
VOID NTAPI MiProtectedPoolRemoveEntryList(IN PLIST_ENTRY Entry)
Definition: pool.c:166
PKEVENT MiLowNonPagedPoolEvent
Definition: mminit.c:296
#define MI_SET_PROCESS2(x)
Definition: mm.h:254
PFN_NUMBER MiStartOfInitialPoolFrame
Definition: pool.c:23
LIST_ENTRY List
Definition: mm.h:402
_Must_inspect_result_ _In_ LPCGUID ULONG _In_ FSRTL_ALLOCATE_ECP_FLAGS _In_opt_ PFSRTL_EXTRA_CREATE_PARAMETER_CLEANUP_CALLBACK _In_ ULONG PoolTag
Definition: fltkernel.h:2520
unsigned char BOOLEAN
POOL_DESCRIPTOR PagedPool
Definition: miarm.h:517
SIZE_T AllocatedPagedPool
Definition: mm.h:421
#define MI_MAX_FREE_PAGE_LISTS
Definition: mm.h:77
smooth NULL
Definition: ftsmooth.c:416
PVOID FORCEINLINE MiPteToAddress(PMMPTE PointerPte)
Definition: mm.h:198
PVOID MmNonPagedPoolEnd0
Definition: pool.c:22
ULONG_PTR VerifierAllocation
Definition: mm.h:352
PFN_NUMBER MiHighPagedPoolThreshold
Definition: mminit.c:303
#define FORCEINLINE
Definition: ntbasedef.h:221
void DPRINT(...)
Definition: polytest.cpp:61
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:1006
#define MI_SET_USAGE(x)
Definition: mm.h:253
void * PVOID
Definition: retypes.h:9
SIZE_T PagedPoolCommit
Definition: mm.h:420
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:413
FORCEINLINE VOID InitializeSListHead(_Out_ PSLIST_HEADER SListHead)
Definition: rtlfuncs.h:3353
INIT_FUNCTION VOID NTAPI MiInitializeNonPagedPoolThresholds(VOID)
Definition: pool.c:184
ULONG MmConsumedPoolPercentage
Definition: pool.c:28
PMMPDE MmSystemPagePtes
Definition: init.c:41
ULONG NTAPI MiFreePoolPages(IN PVOID StartingVa)
Definition: pool.c:905
KGUARDED_MUTEX MmPagedPoolMutex
Definition: pool.c:24
INIT_FUNCTION VOID NTAPI MiInitializeNonPagedPool(VOID)
Definition: pool.c:276
PFN_COUNT Size
Definition: mm.h:403
NTSYSAPI void WINAPI RtlClearAllBits(PRTL_BITMAP)
ULONG PageFrameNumber
Definition: mmtypes.h:74
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID * BaseAddress
Definition: mmfuncs.h:404
struct _MM_SESSION_SPACE * GlobalVirtualAddress
Definition: miarm.h:484
#define MM_FREE_POOL_SIGNATURE
Definition: mm.h:409
LIST_ENTRY List
Definition: psmgr.c:57
SIZE_T CommittedPages
Definition: miarm.h:496
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
Definition: mm.h:400
INT POOL_TYPE
Definition: typedefs.h:76
ULONG64 Valid
Definition: mmtypes.h:150
PVOID NTAPI MiAllocatePoolPages(IN POOL_TYPE PoolType, IN SIZE_T SizeInBytes)
Definition: pool.c:420
static const UCHAR Index[8]
Definition: usbohci.c:18
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:75
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:31
#define PTE_COUNT
Definition: miarm.h:33
ULONG MiNonPagedPoolSListMaximum
Definition: pool.c:31
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#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:405
#define BYTES_TO_PAGES(Size)
ULONG MiPagedPoolSListMaximum
Definition: pool.c:33
PVOID PagedPoolEnd
Definition: miarm.h:498
KGUARDED_MUTEX PagedPoolMutex
Definition: miarm.h:512
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:803
PFN_NUMBER MmMaximumNonPagedPoolInPages
Definition: mminit.c:30
Definition: mm.h:305
#define PAGE_SIZE
Definition: env_spec_w32.h:49
PFN_NUMBER MmSystemPageDirectory[PD_COUNT]
Definition: init.c:40
Definition: typedefs.h:117
_In_ ULONG _In_ BOOLEAN _Must_inspect_result_ PVOID * VirtualAddress
Definition: ndis.h:3791
NTKERNELAPI PSLIST_ENTRY FASTCALL InterlockedPushEntrySList(IN PSLIST_HEADER ListHead, IN PSLIST_ENTRY ListEntry)
Definition: interlocked.c:82
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:359
#define _1MB
Definition: miarm.h:15
union _MMPFN::@1724 u4
NTSYSAPI ULONG WINAPI RtlFindClearBitsAndSet(PRTL_BITMAP, ULONG, ULONG)
INIT_FUNCTION VOID NTAPI MiInitializeSystemPtes(IN PMMPTE StartingPte, IN ULONG NumberOfPtes, IN MMSYSTEM_PTE_POOL_TYPE PoolType)
Definition: syspte.c:399
KIRQL FASTCALL KeAcquireQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber)
Definition: spinlock.c:108
FORCEINLINE PMMPFN MiGetPfnEntry(IN PFN_NUMBER Pfn)
Definition: mm.h:940
FORCEINLINE VOID MiProtectedPoolUnProtectLinks(IN PLIST_ENTRY Links, OUT PVOID *PoolFlink, OUT PVOID *PoolBlink)
Definition: pool.c:103
MMPTE ValidKernelPde
Definition: init.c:30
Status
Definition: gdiplustypes.h:24
ULONG_PTR Long
Definition: mmtypes.h:215
PVOID MmPagedPoolStart
Definition: miarm.h:589
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
PFN_NUMBER NTAPI MiRemoveAnyPage(IN ULONG Color)
Definition: pfnlist.c:475
ULONG_PTR SIZE_T
Definition: typedefs.h:78
MMPTE_HARDWARE Hard
Definition: mmtypes.h:217
#define SYSTEM_PD_SIZE
Definition: miarm.h:36
#define MiPteToPde(_Pte)
Definition: mm.h:233
FORCEINLINE VOID MI_WRITE_INVALID_PTE(IN PMMPTE PointerPte, IN MMPTE InvalidPte)
Definition: miarm.h:980
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:232
struct _MMFREE_POOL_ENTRY * PMMFREE_POOL_ENTRY
PRTL_BITMAP EndOfPagedPoolBitmap
Definition: mm.h:415
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
ULONG MmMaximumNonPagedPoolInBytes
Definition: init.c:22
PMMPTE PteAddress
Definition: mm.h:318
unsigned int * PULONG
Definition: retypes.h:1
#define min(a, b)
Definition: monoChain.cc:55
INIT_FUNCTION VOID NTAPI ExInitializePoolDescriptor(IN PPOOL_DESCRIPTOR PoolDescriptor, IN POOL_TYPE PoolType, IN ULONG PoolIndex, IN ULONG Threshold, IN PVOID PoolLock)
Definition: expool.c:966
VOID FASTCALL KeReleaseGuardedMutex(IN OUT PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:53
PKEVENT MiLowPagedPoolEvent
Definition: mminit.c:294
#define DPRINT1
Definition: precomp.h:8
NTSYSAPI void WINAPI RtlSetAllBits(PRTL_BITMAP)
SLIST_HEADER MiPagedPoolSListHead
Definition: pool.c:32
FORCEINLINE PFN_NUMBER MiGetPfnEntryIndex(IN PMMPFN Pfn1)
Definition: mm.h:960
#define OUT
Definition: typedefs.h:39
PVOID MiSessionPoolEnd
Definition: init.c:31
_Must_inspect_result_ typedef _In_ PHYSICAL_ADDRESS _Inout_ PLARGE_INTEGER NumberOfBytes
Definition: iotypes.h:997
PKEVENT MiHighPagedPoolEvent
Definition: mminit.c:295
unsigned int ULONG
Definition: retypes.h:1
#define UNIMPLEMENTED
Definition: debug.h:114
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
#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:419
INIT_FUNCTION VOID NTAPI MiInitializePoolEvents(VOID)
Definition: pool.c:201
ULONG MmSizeOfNonPagedPoolInBytes
Definition: init.c:21
PFN_NUMBER MmSizeOfPagedPoolInPages
Definition: mminit.c:111
PMMPTE FirstPteForPagedPool
Definition: mm.h:416
LIST_ENTRY MmNonPagedPoolFreeListHead[MI_MAX_FREE_PAGE_LISTS]
Definition: pool.c:20
VOID NTAPI KeClearEvent(IN PKEVENT Event)
Definition: eventobj.c:22
return STATUS_SUCCESS
Definition: btrfs.c:2745
FORCEINLINE BOOLEAN MI_IS_PHYSICAL_ADDRESS(IN PVOID Address)
Definition: miarm.h:937
_Must_inspect_result_ _In_ FLT_CONTEXT_TYPE _In_ SIZE_T _In_ POOL_TYPE PoolType
Definition: fltkernel.h:1444
PMMPDE PagedPoolBasePde
Definition: miarm.h:499
#define PFN_FROM_PTE(v)
Definition: mm.h:89
PVOID NTAPI MmAllocateMappingAddress(IN SIZE_T NumberOfBytes, IN ULONG PoolTag)
Definition: pool.c:1389
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:107
#define _1GB
Definition: miarm.h:16
VOID NTAPI MmFreeMappingAddress(IN PVOID BaseAddress, IN ULONG PoolTag)
Definition: pool.c:1401
ULONG PageFrameNumber
Definition: mmtypes.h:109
PMMPDE NextPdeForPagedPoolExpansion
Definition: mm.h:418
FORCEINLINE VOID MiProtectedPoolProtectLinks(IN PVOID PoolFlink, IN PVOID PoolBlink)
Definition: pool.c:138
PFN_NUMBER SessionPageDirectoryIndex
Definition: miarm.h:494