ReactOS 0.4.16-dev-117-g38f21f9
pool.c File Reference
#include <ntoskrnl.h>
#include <debug.h>
#include <mm/ARM3/miarm.h>
Include dependency graph for pool.c:

Go to the source code of this file.

Macros

#define NDEBUG
 
#define MODULE_INVOLVED_IN_ARM3
 

Functions

VOID NTAPI MiProtectFreeNonPagedPool (IN PVOID VirtualAddress, IN ULONG PageCount)
 
BOOLEAN NTAPI MiUnProtectFreeNonPagedPool (IN PVOID VirtualAddress, IN ULONG PageCount)
 
FORCEINLINE VOID MiProtectedPoolUnProtectLinks (IN PLIST_ENTRY Links, OUT PVOID *PoolFlink, OUT PVOID *PoolBlink)
 
FORCEINLINE VOID MiProtectedPoolProtectLinks (IN PVOID PoolFlink, IN PVOID PoolBlink)
 
VOID NTAPI MiProtectedPoolInsertList (IN PLIST_ENTRY ListHead, IN PLIST_ENTRY Entry, IN BOOLEAN Critical)
 
VOID NTAPI MiProtectedPoolRemoveEntryList (IN PLIST_ENTRY Entry)
 
VOID NTAPI MiInitializeNonPagedPoolThresholds (VOID)
 
VOID NTAPI MiInitializePoolEvents (VOID)
 
VOID NTAPI MiInitializeNonPagedPool (VOID)
 
POOL_TYPE NTAPI MmDeterminePoolType (IN PVOID PoolAddress)
 
PVOID NTAPI MiAllocatePoolPages (IN POOL_TYPE PoolType, IN SIZE_T SizeInBytes)
 
ULONG NTAPI MiFreePoolPages (IN PVOID StartingVa)
 
NTSTATUS NTAPI MiInitializeSessionPool (VOID)
 
 _Requires_lock_held_ (PspQuotaLock)
 Raises the quota limit, depending on the given pool type of the quota in question. The routine is used exclusively by Process Manager for quota handling.
 
PVOID NTAPI MmAllocateMappingAddress (IN SIZE_T NumberOfBytes, IN ULONG PoolTag)
 
VOID NTAPI MmFreeMappingAddress (IN PVOID BaseAddress, IN ULONG PoolTag)
 

Variables

LIST_ENTRY MmNonPagedPoolFreeListHead [MI_MAX_FREE_PAGE_LISTS]
 
PFN_COUNT MmNumberOfFreeNonPagedPool
 
PFN_COUNT MiExpansionPoolPagesInitialCharge
 
PVOID MmNonPagedPoolEnd0
 
PFN_NUMBER MiStartOfInitialPoolFrame
 
PFN_NUMBER MiEndOfInitialPoolFrame
 
KGUARDED_MUTEX MmPagedPoolMutex
 
MM_PAGED_POOL_INFO MmPagedPoolInfo
 
SIZE_T MmAllocatedNonPagedPool
 
SIZE_T MmTotalNonPagedPoolQuota
 
SIZE_T MmTotalPagedPoolQuota
 
ULONG MmSpecialPoolTag
 
ULONG MmConsumedPoolPercentage
 
BOOLEAN MmProtectFreedNonPagedPool
 
SLIST_HEADER MiNonPagedPoolSListHead
 
ULONG MiNonPagedPoolSListMaximum = 4
 
SLIST_HEADER MiPagedPoolSListHead
 
ULONG MiPagedPoolSListMaximum = 8
 

Macro Definition Documentation

◆ MODULE_INVOLVED_IN_ARM3

#define MODULE_INVOLVED_IN_ARM3

Definition at line 15 of file pool.c.

◆ NDEBUG

#define NDEBUG

Definition at line 12 of file pool.c.

Function Documentation

◆ _Requires_lock_held_()

_Requires_lock_held_ ( PspQuotaLock  )

Raises the quota limit, depending on the given pool type of the quota in question. The routine is used exclusively by Process Manager for quota handling.

Returns the quota, depending on the given pool type of the quota in question. The routine is used exclusively by Process Manager for quota handling.

Parameters
[in]PoolTypeThe type of quota pool which the quota in question has to be raised.
[in]CurrentMaxQuotaThe current maximum limit of quota threshold.
[out]NewMaxQuotaThe newly raised maximum limit of quota threshold, returned to the caller.
Returns
Returns TRUE if quota raising procedure has succeeded without problems, FALSE otherwise.
Remarks
A spin lock must be held when raising the pool quota limit to avoid race occurences.
Parameters
[in]PoolTypeThe type of quota pool which the quota in question has to be raised.
[in]CurrentMaxQuotaThe current maximum limit of quota threshold.
Returns
Nothing.
Remarks
A spin lock must be held when raising the pool quota limit to avoid race occurences.

Definition at line 1404 of file pool.c.

1411{
1412 /*
1413 * We must be in dispatch level interrupt here
1414 * as we should be under a spin lock at this point.
1415 */
1417
1418 switch (PoolType)
1419 {
1420 case NonPagedPool:
1421 {
1422 /*
1423 * When concerning with a raise (charge) of quota
1424 * in a non paged pool scenario, make sure that
1425 * we've got at least 200 pages necessary to provide.
1426 */
1428 {
1429 DPRINT1("MmRaisePoolQuota(): Not enough pages available (current pages -- %lu)\n", MmAvailablePages);
1430 return FALSE;
1431 }
1432
1433 /*
1434 * Check if there's at least some space available
1435 * in the non paged pool area.
1436 */
1438 {
1439 /* There's too much allocated space, bail out */
1440 DPRINT1("MmRaisePoolQuota(): Failed to increase pool quota, not enough non paged pool space (current size -- %lu || allocated size -- %lu)\n",
1442 return FALSE;
1443 }
1444
1445 /* Do we have enough resident pages to increase our quota? */
1447 {
1448 DPRINT1("MmRaisePoolQuota(): Failed to increase pool quota, not enough resident pages available (current available pages -- %lu)\n",
1450 return FALSE;
1451 }
1452
1453 /*
1454 * Raise the non paged pool quota indicator and set
1455 * up new maximum limit of quota for the process.
1456 */
1459 DPRINT("MmRaisePoolQuota(): Non paged pool quota increased (before -- %lu || after -- %lu)\n", CurrentMaxQuota, NewMaxQuota);
1460 return TRUE;
1461 }
1462
1463 case PagedPool:
1464 {
1465 /*
1466 * Before raising the quota limit of a paged quota
1467 * pool, make sure we've got enough space that is available.
1468 * On Windows it seems it wants to check for at least 1 MB of space
1469 * needed so that it would be possible to raise the paged pool quota.
1470 */
1472 {
1473 /* We haven't gotten enough space, bail out */
1474 DPRINT1("MmRaisePoolQuota(): Failed to increase pool quota, not enough paged pool space (current size -- %lu || allocated size -- %lu)\n",
1476 return FALSE;
1477 }
1478
1479 /*
1480 * Raise the paged pool quota indicator and set
1481 * up new maximum limit of quota for the process.
1482 */
1485 DPRINT("MmRaisePoolQuota(): Paged pool quota increased (before -- %lu || after -- %lu)\n", CurrentMaxQuota, NewMaxQuota);
1486 return TRUE;
1487 }
1488
1489 /* Only NonPagedPool and PagedPool are used */
1491 }
1492}
#define DPRINT1
Definition: precomp.h:8
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define ASSERT_IRQL_EQUAL(x)
Definition: debug.h:43
#define PAGE_SHIFT
Definition: env_spec_w32.h:45
#define NonPagedPool
Definition: env_spec_w32.h:307
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
#define PagedPool
Definition: env_spec_w32.h:308
PFN_NUMBER MmMaximumNonPagedPoolInPages
Definition: mminit.c:30
PFN_NUMBER MmSizeOfPagedPoolInPages
Definition: mminit.c:111
#define DEFAULT_UNREACHABLE
PFN_NUMBER MmResidentAvailablePages
Definition: freelist.c:27
_In_ SIZE_T _Out_ PSIZE_T NewMaxQuota
Definition: mm.h:667
#define MI_QUOTA_NON_PAGED_NEEDED_PAGES
Definition: mm.h:62
#define MI_CHARGE_PAGED_POOL_QUOTA
Definition: mm.h:64
_In_ SIZE_T CurrentMaxQuota
Definition: mm.h:665
#define MI_NON_PAGED_QUOTA_MIN_RESIDENT_PAGES
Definition: mm.h:63
PFN_NUMBER MmAvailablePages
Definition: freelist.c:26
#define MI_CHARGE_NON_PAGED_POOL_QUOTA
Definition: mm.h:65
SIZE_T MmTotalPagedPoolQuota
Definition: pool.c:28
SIZE_T MmTotalNonPagedPoolQuota
Definition: pool.c:27
MM_PAGED_POOL_INFO MmPagedPoolInfo
Definition: pool.c:25
SIZE_T MmAllocatedNonPagedPool
Definition: pool.c:26
#define DPRINT
Definition: sndvol32.h:73
SIZE_T AllocatedPagedPool
Definition: mm.h:493
_Must_inspect_result_ _In_ WDFDEVICE _In_ DEVICE_REGISTRY_PROPERTY _In_ _Strict_type_match_ POOL_TYPE PoolType
Definition: wdfdevice.h:3815

◆ MiAllocatePoolPages()

PVOID NTAPI MiAllocatePoolPages ( IN POOL_TYPE  PoolType,
IN SIZE_T  SizeInBytes 
)

Definition at line 422 of file pool.c.

424{
425 PFN_NUMBER PageFrameNumber;
426 PFN_COUNT SizeInPages, PageTableCount;
427 ULONG i;
429 PLIST_ENTRY NextEntry, NextHead, LastHead;
430 PMMPTE PointerPte, StartPte;
431 PMMPDE PointerPde;
432 ULONG EndAllocation;
435 PMMPFN Pfn1;
436 PVOID BaseVa, BaseVaStart;
437 PMMFREE_POOL_ENTRY FreeEntry;
438
439 //
440 // Figure out how big the allocation is in pages
441 //
442 SizeInPages = (PFN_COUNT)BYTES_TO_PAGES(SizeInBytes);
443
444 //
445 // Check for overflow
446 //
447 if (SizeInPages == 0)
448 {
449 //
450 // Fail
451 //
452 return NULL;
453 }
454
455 //
456 // Handle paged pool
457 //
459 {
460 //
461 // If only one page is being requested, try to grab it from the S-LIST
462 //
463 if ((SizeInPages == 1) && (ExQueryDepthSList(&MiPagedPoolSListHead)))
464 {
466 if (BaseVa) return BaseVa;
467 }
468
469 //
470 // Lock the paged pool mutex
471 //
473
474 //
475 // Find some empty allocation space
476 //
478 SizeInPages,
480 if (i == 0xFFFFFFFF)
481 {
482 //
483 // Get the page bit count
484 //
485 i = ((SizeInPages - 1) / PTE_PER_PAGE) + 1;
486 DPRINT("Paged pool expansion: %lu %x\n", i, SizeInPages);
487
488 //
489 // Check if there is enougn paged pool expansion space left
490 //
493 {
494 //
495 // Out of memory!
496 //
497 DPRINT1("FAILED to allocate %Iu bytes from paged pool\n", SizeInBytes);
499 return NULL;
500 }
501
502 //
503 // Check if we'll have to expand past the last PTE we have available
504 //
507 {
508 //
509 // We can only support this much then
510 //
512 PageTableCount = (PFN_COUNT)(PointerPde + 1 -
514 ASSERT(PageTableCount < i);
515 i = PageTableCount;
516 }
517 else
518 {
519 //
520 // Otherwise, there is plenty of space left for this expansion
521 //
522 PageTableCount = i;
523 }
524
525 //
526 // Get the template PDE we'll use to expand
527 //
529
530 //
531 // Get the first PTE in expansion space
532 //
534 BaseVa = MiPdeToPte(PointerPde);
535 BaseVaStart = BaseVa;
536
537 //
538 // Lock the PFN database and loop pages
539 //
540 OldIrql = MiAcquirePfnLock();
541 do
542 {
543 //
544 // It should not already be valid
545 //
546 ASSERT(PointerPde->u.Hard.Valid == 0);
547
548 /* Request a page */
550 MI_SET_PROCESS2("Kernel");
551 PageFrameNumber = MiRemoveAnyPage(MI_GET_NEXT_COLOR());
552 TempPde.u.Hard.PageFrameNumber = PageFrameNumber;
553#if (_MI_PAGING_LEVELS >= 3)
554 /* On PAE/x64 systems, there's no double-buffering */
555 /* Initialize the PFN entry for it */
556 MiInitializePfnForOtherProcess(PageFrameNumber,
557 (PMMPTE)PointerPde,
558 PFN_FROM_PTE(MiAddressToPte(PointerPde)));
559
560 /* Write the actual PDE now */
561 MI_WRITE_VALID_PDE(PointerPde, TempPde);
562#else
563 //
564 // Save it into our double-buffered system page directory
565 //
566 MmSystemPagePtes[((ULONG_PTR)PointerPde & (SYSTEM_PD_SIZE - 1)) / sizeof(MMPTE)] = TempPde;
567
568 /* Initialize the PFN */
569 MiInitializePfnForOtherProcess(PageFrameNumber,
570 (PMMPTE)PointerPde,
572#endif
573
574 //
575 // Move on to the next expansion address
576 //
577 PointerPde++;
578 BaseVa = (PVOID)((ULONG_PTR)BaseVa + PAGE_SIZE);
579 i--;
580 } while (i > 0);
581
582 //
583 // Release the PFN database lock
584 //
585 MiReleasePfnLock(OldIrql);
586
587 //
588 // These pages are now available, clear their availablity bits
589 //
594 EndAllocation,
595 PageTableCount * PTE_PER_PAGE);
596
597 //
598 // Update the next expansion location
599 //
601
602 //
603 // Zero out the newly available memory
604 //
605 RtlZeroMemory(BaseVaStart, PageTableCount * PAGE_SIZE);
606
607 //
608 // Now try consuming the pages again
609 //
611 SizeInPages,
612 0);
613 if (i == 0xFFFFFFFF)
614 {
615 //
616 // Out of memory!
617 //
618 DPRINT1("FAILED to allocate %Iu bytes from paged pool\n", SizeInBytes);
620 return NULL;
621 }
622 }
623
624 //
625 // Update the pool hint if the request was just one page
626 //
627 if (SizeInPages == 1) MmPagedPoolInfo.PagedPoolHint = i + 1;
628
629 //
630 // Update the end bitmap so we know the bounds of this allocation when
631 // the time comes to free it
632 //
633 EndAllocation = i + SizeInPages - 1;
635
636 //
637 // Now we can release the lock (it mainly protects the bitmap)
638 //
640
641 //
642 // Now figure out where this allocation starts
643 //
644 BaseVa = (PVOID)((ULONG_PTR)MmPagedPoolStart + (i << PAGE_SHIFT));
645
646 //
647 // Flush the TLB
648 //
650
651 /* Setup a demand-zero writable PTE */
653
654 //
655 // Find the first and last PTE, then loop them all
656 //
657 PointerPte = MiAddressToPte(BaseVa);
658 StartPte = PointerPte + SizeInPages;
659 do
660 {
661 //
662 // Write the demand zero PTE and keep going
663 //
664 MI_WRITE_INVALID_PTE(PointerPte, TempPte);
665 } while (++PointerPte < StartPte);
666
667 //
668 // Return the allocation address to the caller
669 //
670 return BaseVa;
671 }
672
673 //
674 // If only one page is being requested, try to grab it from the S-LIST
675 //
676 if ((SizeInPages == 1) && (ExQueryDepthSList(&MiNonPagedPoolSListHead)))
677 {
679 if (BaseVa) return BaseVa;
680 }
681
682 //
683 // Allocations of less than 4 pages go into their individual buckets
684 //
685 i = min(SizeInPages, MI_MAX_FREE_PAGE_LISTS) - 1;
686
687 //
688 // Loop through all the free page lists based on the page index
689 //
690 NextHead = &MmNonPagedPoolFreeListHead[i];
692
693 //
694 // Acquire the nonpaged pool lock
695 //
697 do
698 {
699 //
700 // Now loop through all the free page entries in this given list
701 //
702 NextEntry = NextHead->Flink;
703 while (NextEntry != NextHead)
704 {
705 /* Is freed non paged pool enabled */
707 {
708 /* We need to be able to touch this page, unprotect it */
709 MiUnProtectFreeNonPagedPool(NextEntry, 0);
710 }
711
712 //
713 // Grab the entry and see if it can handle our allocation
714 //
715 FreeEntry = CONTAINING_RECORD(NextEntry, MMFREE_POOL_ENTRY, List);
717 if (FreeEntry->Size >= SizeInPages)
718 {
719 //
720 // It does, so consume the pages from here
721 //
722 FreeEntry->Size -= SizeInPages;
723
724 //
725 // The allocation will begin in this free page area
726 //
727 BaseVa = (PVOID)((ULONG_PTR)FreeEntry +
728 (FreeEntry->Size << PAGE_SHIFT));
729
730 /* Remove the item from the list, depending if pool is protected */
733 else
734 RemoveEntryList(&FreeEntry->List);
735
736 //
737 // However, check if its' still got space left
738 //
739 if (FreeEntry->Size != 0)
740 {
741 /* Check which list to insert this entry into */
742 i = min(FreeEntry->Size, MI_MAX_FREE_PAGE_LISTS) - 1;
743
744 /* Insert the entry into the free list head, check for prot. pool */
747 else
749
750 /* Is freed non paged pool protected? */
752 {
753 /* Protect the freed pool! */
754 MiProtectFreeNonPagedPool(FreeEntry, FreeEntry->Size);
755 }
756 }
757
758 //
759 // Grab the PTE for this allocation
760 //
761 PointerPte = MiAddressToPte(BaseVa);
762 ASSERT(PointerPte->u.Hard.Valid == 1);
763
764 //
765 // Grab the PFN NextEntry and index
766 //
767 Pfn1 = MiGetPfnEntry(PFN_FROM_PTE(PointerPte));
768
769 //
770 // Now mark it as the beginning of an allocation
771 //
772 ASSERT(Pfn1->u3.e1.StartOfAllocation == 0);
773 Pfn1->u3.e1.StartOfAllocation = 1;
774
775 /* Mark it as special pool if needed */
776 ASSERT(Pfn1->u4.VerifierAllocation == 0);
778 {
779 Pfn1->u4.VerifierAllocation = 1;
780 }
781
782 //
783 // Check if the allocation is larger than one page
784 //
785 if (SizeInPages != 1)
786 {
787 //
788 // Navigate to the last PFN entry and PTE
789 //
790 PointerPte += SizeInPages - 1;
791 ASSERT(PointerPte->u.Hard.Valid == 1);
792 Pfn1 = MiGetPfnEntry(PointerPte->u.Hard.PageFrameNumber);
793 }
794
795 //
796 // Mark this PFN as the last (might be the same as the first)
797 //
798 ASSERT(Pfn1->u3.e1.EndOfAllocation == 0);
799 Pfn1->u3.e1.EndOfAllocation = 1;
800
801 //
802 // Release the nonpaged pool lock, and return the allocation
803 //
805 return BaseVa;
806 }
807
808 //
809 // Try the next free page entry
810 //
811 NextEntry = FreeEntry->List.Flink;
812
813 /* Is freed non paged pool protected? */
815 {
816 /* Protect the freed pool! */
817 MiProtectFreeNonPagedPool(FreeEntry, FreeEntry->Size);
818 }
819 }
820 } while (++NextHead < LastHead);
821
822 //
823 // If we got here, we're out of space.
824 // Start by releasing the lock
825 //
827
828 //
829 // Allocate some system PTEs
830 //
831 StartPte = MiReserveSystemPtes(SizeInPages, NonPagedPoolExpansion);
832 PointerPte = StartPte;
833 if (StartPte == NULL)
834 {
835 //
836 // Ran out of memory
837 //
838 DPRINT("Out of NP Expansion Pool\n");
839 return NULL;
840 }
841
842 //
843 // Acquire the pool lock now
844 //
846
847 //
848 // Lock the PFN database too
849 //
850 MiAcquirePfnLockAtDpcLevel();
851
852 /* Check that we have enough available pages for this request */
853 if (MmAvailablePages < SizeInPages)
854 {
855 MiReleasePfnLockFromDpcLevel();
857
858 MiReleaseSystemPtes(StartPte, SizeInPages, NonPagedPoolExpansion);
859
860 DPRINT1("OUT OF AVAILABLE PAGES! Required %lu, Available %lu\n", SizeInPages, MmAvailablePages);
861
862 return NULL;
863 }
864
865 //
866 // Loop the pages
867 //
869 do
870 {
871 /* Allocate a page */
873 MI_SET_PROCESS2("Kernel");
874 PageFrameNumber = MiRemoveAnyPage(MI_GET_NEXT_COLOR());
875
876 /* Get the PFN entry for it and fill it out */
877 Pfn1 = MiGetPfnEntry(PageFrameNumber);
878 Pfn1->u3.e2.ReferenceCount = 1;
879 Pfn1->u2.ShareCount = 1;
880 Pfn1->PteAddress = PointerPte;
882 Pfn1->u4.VerifierAllocation = 0;
883
884 /* Write the PTE for it */
885 TempPte.u.Hard.PageFrameNumber = PageFrameNumber;
886 MI_WRITE_VALID_PTE(PointerPte++, TempPte);
887 } while (--SizeInPages > 0);
888
889 //
890 // This is the last page
891 //
892 Pfn1->u3.e1.EndOfAllocation = 1;
893
894 //
895 // Get the first page and mark it as such
896 //
897 Pfn1 = MiGetPfnEntry(StartPte->u.Hard.PageFrameNumber);
898 Pfn1->u3.e1.StartOfAllocation = 1;
899
900 /* Mark it as a verifier allocation if needed */
901 ASSERT(Pfn1->u4.VerifierAllocation == 0);
903
904 //
905 // Release the PFN and nonpaged pool lock
906 //
907 MiReleasePfnLockFromDpcLevel();
909
910 //
911 // Return the address
912 //
913 return MiPteToAddress(StartPte);
914}
#define BASE_POOL_TYPE_MASK
Definition: ExPools.c:15
HARDWARE_PTE_ARMV6 TempPte
Definition: winldr.c:76
HARDWARE_PDE_ARMV6 TempPde
Definition: winldr.c:78
#define MM_READWRITE
Definition: bootanim.c:19
#define RtlClearBits
Definition: dbgbitmap.h:331
#define RtlFindClearBitsAndSet
Definition: dbgbitmap.h:333
#define RtlSetBit
Definition: dbgbitmap.h:344
#define NULL
Definition: types.h:112
#define ULONG_PTR
Definition: config.h:101
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define InsertTailList(ListHead, Entry)
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define PAGE_SIZE
Definition: env_spec_w32.h:49
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
VOID FASTCALL KeReleaseGuardedMutex(IN OUT PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:53
VOID FASTCALL KeAcquireGuardedMutex(IN PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:42
VOID FASTCALL KeReleaseQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber, IN KIRQL OldIrql)
Definition: spinlock.c:154
KIRQL FASTCALL KeAcquireQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber)
Definition: spinlock.c:108
@ NonPagedPoolExpansion
Definition: miarm.h:404
PVOID MmPagedPoolStart
Definition: miarm.h:574
#define MI_GET_NEXT_COLOR()
Definition: miarm.h:232
PFN_NUMBER NTAPI MiRemoveAnyPage(IN ULONG Color)
Definition: pfnlist.c:477
VOID NTAPI MiReleaseSystemPtes(IN PMMPTE StartingPte, IN ULONG NumberOfPtes, IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType)
Definition: syspte.c:264
#define MI_MAKE_SOFTWARE_PTE(p, x)
Definition: miarm.h:189
VOID NTAPI MiInitializePfnForOtherProcess(IN PFN_NUMBER PageFrameIndex, IN PVOID PteAddress, IN PFN_NUMBER PteFrame)
Definition: pfnlist.c:1301
FORCEINLINE VOID MI_WRITE_VALID_PDE(IN PMMPDE PointerPde, IN MMPDE TempPde)
Definition: miarm.h:1018
FORCEINLINE VOID MI_WRITE_INVALID_PTE(IN PMMPTE PointerPte, IN MMPTE InvalidPte)
Definition: miarm.h:992
PMMPTE NTAPI MiReserveSystemPtes(IN ULONG NumberOfPtes, IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType)
Definition: syspte.c:246
#define SYSTEM_PD_SIZE
Definition: miarm.h:32
FORCEINLINE VOID MI_WRITE_VALID_PTE(IN PMMPTE PointerPte, IN MMPTE TempPte)
Definition: miarm.h:959
#define MiAddressToPte(x)
Definition: mmx86.c:19
#define MiAddressToPde(x)
Definition: mmx86.c:20
#define ASSERT(a)
Definition: mode.c:44
#define min(a, b)
Definition: monoChain.cc:55
@ ActiveAndValid
Definition: mmtypes.h:159
#define MI_MAX_FREE_PAGE_LISTS
Definition: mm.h:80
#define PFN_FROM_PTE(v)
Definition: mm.h:92
#define MiPteToPde(_Pte)
Definition: mm.h:121
#define PTE_PER_PAGE
Definition: mm.h:20
#define MiPteToAddress(_Pte)
Definition: mm.h:116
#define PDE_PER_PAGE
Definition: mm.h:21
#define MiPdeToPte(_Pde)
Definition: mm.h:120
#define VERIFIER_POOL_MASK
Definition: mm.h:123
FORCEINLINE PMMPFN MiGetPfnEntry(IN PFN_NUMBER Pfn)
Definition: mm.h:1047
#define MI_SET_PROCESS2(x)
Definition: mm.h:319
@ MI_USAGE_PAGED_POOL
Definition: mm.h:325
#define MI_SET_USAGE(x)
Definition: mm.h:317
#define MM_FREE_POOL_SIGNATURE
Definition: mm.h:481
VOID NTAPI KeFlushEntireTb(IN BOOLEAN Invalid, IN BOOLEAN AllProcessors)
Definition: cpu.c:652
PMMPDE MmSystemPagePtes
Definition: init.c:41
PFN_NUMBER MmSystemPageDirectory[PPE_PER_PAGE]
Definition: init.c:40
VOID NTAPI MiProtectedPoolRemoveEntryList(IN PLIST_ENTRY Entry)
Definition: pool.c:168
BOOLEAN MmProtectFreedNonPagedPool
Definition: pool.c:31
KGUARDED_MUTEX MmPagedPoolMutex
Definition: pool.c:24
SLIST_HEADER MiNonPagedPoolSListHead
Definition: pool.c:32
VOID NTAPI MiProtectFreeNonPagedPool(IN PVOID VirtualAddress, IN ULONG PageCount)
Definition: pool.c:41
LIST_ENTRY MmNonPagedPoolFreeListHead[MI_MAX_FREE_PAGE_LISTS]
Definition: pool.c:20
SLIST_HEADER MiPagedPoolSListHead
Definition: pool.c:34
BOOLEAN NTAPI MiUnProtectFreeNonPagedPool(IN PVOID VirtualAddress, IN ULONG PageCount)
Definition: pool.c:70
VOID NTAPI MiProtectedPoolInsertList(IN PLIST_ENTRY ListHead, IN PLIST_ENTRY Entry, IN BOOLEAN Critical)
Definition: pool.c:150
MMPTE ValidKernelPte
Definition: init.c:29
MMPTE ValidKernelPde
Definition: init.c:28
ULONG PFN_NUMBER
Definition: ke.h:9
ULONG PageFrameNumber
Definition: mmtypes.h:74
ULONG PageFrameNumber
Definition: mmtypes.h:109
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
Definition: mm.h:473
ULONG Signature
Definition: mm.h:476
PFN_COUNT Size
Definition: mm.h:475
LIST_ENTRY List
Definition: mm.h:474
USHORT PageLocation
Definition: mm.h:365
Definition: mm.h:374
PMMPTE PteAddress
Definition: mm.h:386
union _MMPFN::@1798 u2
union _MMPFN::@1802 u4
MMPFNENTRY e1
Definition: mm.h:397
ULONG_PTR VerifierAllocation
Definition: mm.h:420
ULONG_PTR ShareCount
Definition: mm.h:390
union _MMPFN::@1799 u3
struct _MMPFN::@1799::@1805 e2
ULONG64 Valid
Definition: mmtypes.h:150
ULONG64 PageFrameNumber
Definition: mmtypes.h:171
union _MMPTE::@2334 u
MMPTE_HARDWARE Hard
Definition: mmtypes.h:217
PMMPTE LastPteForPagedPool
Definition: mm.h:489
PRTL_BITMAP EndOfPagedPoolBitmap
Definition: mm.h:487
PRTL_BITMAP PagedPoolAllocationMap
Definition: mm.h:486
PMMPDE NextPdeForPagedPoolExpansion
Definition: mm.h:490
PMMPTE FirstPteForPagedPool
Definition: mm.h:488
ULONG PagedPoolHint
Definition: mm.h:491
void * PVOID
Definition: typedefs.h:50
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
_Must_inspect_result_ _In_ WDFCMRESLIST List
Definition: wdfresource.h:550
FORCEINLINE USHORT ExQueryDepthSList(_In_ PSLIST_HEADER SListHead)
Definition: exfuncs.h:153
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:778
@ LockQueueMmNonPagedPoolLock
Definition: ketypes.h:673
#define BYTES_TO_PAGES(Size)
ULONG PFN_COUNT
Definition: mmtypes.h:102
#define InterlockedPopEntrySList(SListHead)
Definition: rtlfuncs.h:3406

Referenced by _IRQL_requires_(), ExAllocatePoolWithTag(), and InitializePool().

◆ MiFreePoolPages()

ULONG NTAPI MiFreePoolPages ( IN PVOID  StartingVa)

Definition at line 918 of file pool.c.

919{
920 PMMPTE PointerPte, StartPte;
921 PMMPFN Pfn1, StartPfn;
922 PFN_COUNT FreePages, NumberOfPages;
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 //
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 //
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 */
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));
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 */
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);
1169 FreeEntry = FreeEntry->Owner;
1170
1171 /* Check if protected pool is enabled */
1173 {
1174 /* The freed block will be merged, it must be made accessible */
1175 MiUnProtectFreeNonPagedPool(FreeEntry, 0);
1176 }
1177
1178 //
1179 // Check if the entry is small enough (1-3 pages) to be indexed on a free list
1180 // If it is, we'll want to re-insert it, since we're about to
1181 // collapse our pages on top of it, which will change its count
1182 //
1183 if (FreeEntry->Size < MI_MAX_FREE_PAGE_LISTS)
1184 {
1185 /* Remove the item from the list, depending if pool is protected */
1188 else
1189 RemoveEntryList(&FreeEntry->List);
1190
1191 //
1192 // Update its size
1193 //
1194 FreeEntry->Size += FreePages;
1195
1196 //
1197 // And now find the new appropriate list to place it in
1198 //
1199 i = min(FreeEntry->Size, MI_MAX_FREE_PAGE_LISTS) - 1;
1200
1201 /* Insert the entry into the free list head, check for prot. pool */
1204 else
1206 }
1207 else
1208 {
1209 //
1210 // Otherwise, just combine our free pages into this entry
1211 //
1212 FreeEntry->Size += FreePages;
1213 }
1214 }
1215
1216 //
1217 // Check if we were unable to do any compaction, and we'll stick with this
1218 //
1219 if (FreeEntry == StartingVa)
1220 {
1221 //
1222 // Well, now we are a free entry. At worse we just have our newly freed
1223 // pages, at best we have our pages plus whatever entry came after us
1224 //
1225 FreeEntry->Size = FreePages;
1226
1227 //
1228 // Find the appropriate list we should be on
1229 //
1230 i = min(FreeEntry->Size, MI_MAX_FREE_PAGE_LISTS) - 1;
1231
1232 /* Insert the entry into the free list head, check for prot. pool */
1235 else
1237 }
1238
1239 //
1240 // Just a sanity check
1241 //
1242 ASSERT(FreePages != 0);
1243
1244 //
1245 // Get all the pages between our allocation and its end. These will all now
1246 // become free page chunks.
1247 //
1248 NextEntry = StartingVa;
1249 LastEntry = (PMMFREE_POOL_ENTRY)((ULONG_PTR)NextEntry + (FreePages << PAGE_SHIFT));
1250 do
1251 {
1252 //
1253 // Link back to the parent free entry, and keep going
1254 //
1255 NextEntry->Owner = FreeEntry;
1256 NextEntry->Signature = MM_FREE_POOL_SIGNATURE;
1257 NextEntry = (PMMFREE_POOL_ENTRY)((ULONG_PTR)NextEntry + PAGE_SIZE);
1258 } while (NextEntry != LastEntry);
1259
1260 /* Is freed non paged pool protected? */
1262 {
1263 /* Protect the freed pool! */
1264 MiProtectFreeNonPagedPool(FreeEntry, FreeEntry->Size);
1265 }
1266
1267 //
1268 // We're done, release the lock and let the caller know how much we freed
1269 //
1271 return NumberOfPages;
1272}
#define RtlClearBit
Definition: dbgbitmap.h:330
#define RtlTestBit
Definition: dbgbitmap.h:347
PVOID MmNonPagedPoolEnd
Definition: mminit.c:99
PFN_COUNT NTAPI MiDeleteSystemPageableVm(IN PMMPTE PointerPte, IN PFN_NUMBER PageCount, IN ULONG Flags, OUT PPFN_NUMBER ValidPages)
Definition: virtual.c:275
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
struct _MMFREE_POOL_ENTRY * PMMFREE_POOL_ENTRY
FORCEINLINE PFN_NUMBER MiGetPfnEntryIndex(IN PMMPFN Pfn1)
Definition: mm.h:1067
PVOID MmPagedPoolEnd
Definition: init.c:26
ULONG MiNonPagedPoolSListMaximum
Definition: pool.c:33
PFN_NUMBER MiStartOfInitialPoolFrame
Definition: pool.c:23
ULONG MiPagedPoolSListMaximum
Definition: pool.c:35
PFN_NUMBER MiEndOfInitialPoolFrame
Definition: pool.c:23
struct _MMFREE_POOL_ENTRY * Owner
Definition: mm.h:477
#define InterlockedPushEntrySList(SListHead, SListEntry)
Definition: rtlfuncs.h:3403

Referenced by _IRQL_requires_(), and ExFreePoolWithTag().

◆ MiInitializeNonPagedPool()

VOID NTAPI MiInitializeNonPagedPool ( VOID  )

Definition at line 278 of file pool.c.

279{
280 ULONG i;
281 PFN_COUNT PoolPages;
282 PMMFREE_POOL_ENTRY FreeEntry, FirstEntry;
283 PMMPTE PointerPte;
284 PAGED_CODE();
285
286 //
287 // Initialize the pool S-LISTs as well as their maximum count. In general,
288 // we'll allow 8 times the default on a 2GB system, and two times the default
289 // on a 1GB system.
290 //
293 if (MmNumberOfPhysicalPages >= ((2 * _1GB) /PAGE_SIZE))
294 {
297 }
299 {
302 }
303
304 //
305 // However if debugging options for the pool are enabled, turn off the S-LIST
306 // to reduce the risk of messing things up even more
307 //
309 {
312 }
313
314 //
315 // We keep 4 lists of free pages (4 lists help avoid contention)
316 //
317 for (i = 0; i < MI_MAX_FREE_PAGE_LISTS; i++)
318 {
319 //
320 // Initialize each of them
321 //
323 }
324
325 //
326 // Calculate how many pages the initial nonpaged pool has
327 //
329 MmNumberOfFreeNonPagedPool = PoolPages;
330
331 //
332 // Initialize the first free entry
333 //
334 FreeEntry = MmNonPagedPoolStart;
335 FirstEntry = FreeEntry;
336 FreeEntry->Size = PoolPages;
338 FreeEntry->Owner = FirstEntry;
339
340 //
341 // Insert it into the last list
342 //
344 &FreeEntry->List);
345
346 //
347 // Now create free entries for every single other page
348 //
349 while (PoolPages-- > 1)
350 {
351 //
352 // Link them all back to the original entry
353 //
354 FreeEntry = (PMMFREE_POOL_ENTRY)((ULONG_PTR)FreeEntry + PAGE_SIZE);
355 FreeEntry->Owner = FirstEntry;
357 }
358
359 //
360 // Validate and remember first allocated pool page
361 //
363 ASSERT(PointerPte->u.Hard.Valid == 1);
365
366 //
367 // Keep track of where initial nonpaged pool ends
368 //
371
372 //
373 // Validate and remember last allocated pool page
374 //
375 PointerPte = MiAddressToPte((PVOID)((ULONG_PTR)MmNonPagedPoolEnd0 - 1));
376 ASSERT(PointerPte->u.Hard.Valid == 1);
378
379 //
380 // Validate the first nonpaged pool expansion page (which is a guard page)
381 //
383 ASSERT(PointerPte->u.Hard.Valid == 0);
384
385 //
386 // Calculate the size of the expansion region alone
387 //
390
391 //
392 // Remove 2 pages, since there's a guard page on top and on the bottom
393 //
395
396 //
397 // Now initialize the nonpaged pool expansion PTE space. Remember there's a
398 // guard page on top so make sure to skip it. The bottom guard page will be
399 // guaranteed by the fact our size is off by one.
400 //
401 MiInitializeSystemPtes(PointerPte + 1,
404}
#define PAGED_CODE()
#define InsertHeadList(ListHead, Entry)
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
VOID NTAPI MiInitializeSystemPtes(IN PMMPTE StartingPte, IN ULONG NumberOfPtes, IN MMSYSTEM_PTE_POOL_TYPE PoolType)
Definition: syspte.c:388
#define _1GB
Definition: miarm.h:20
PFN_COUNT MmNumberOfPhysicalPages
Definition: init.c:48
ULONG MmMaximumNonPagedPoolInBytes
Definition: init.c:22
ULONG MmSizeOfNonPagedPoolInBytes
Definition: init.c:21
PVOID MmNonPagedPoolExpansionStart
Definition: init.c:25
PVOID MmNonPagedPoolStart
Definition: init.c:24
PFN_COUNT MmNumberOfFreeNonPagedPool
Definition: pool.c:21
PFN_COUNT MiExpansionPoolPagesInitialCharge
Definition: pool.c:21
PVOID MmNonPagedPoolEnd0
Definition: pool.c:22
FORCEINLINE VOID InitializeSListHead(_Out_ PSLIST_HEADER SListHead)
Definition: rtlfuncs.h:3365

Referenced by MiBuildNonPagedPool(), and MiInitMachineDependent().

◆ MiInitializeNonPagedPoolThresholds()

VOID NTAPI MiInitializeNonPagedPoolThresholds ( VOID  )

Definition at line 186 of file pool.c.

187{
189
190 /* Default low threshold of 8MB or one third of nonpaged pool */
193
194 /* Default high threshold of 20MB or 50% */
198}
#define _1MB
Definition: miarm.h:19
PFN_NUMBER MiLowNonPagedPoolThreshold
Definition: mminit.c:304
PFN_NUMBER MiHighNonPagedPoolThreshold
Definition: mminit.c:305
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
Definition: wdfdevice.h:4533

Referenced by MiBuildNonPagedPool(), and MiInitMachineDependent().

◆ MiInitializePoolEvents()

VOID NTAPI MiInitializePoolEvents ( VOID  )

Definition at line 203 of file pool.c.

204{
206 PFN_NUMBER FreePoolInPages;
207
208 /* Lock paged pool */
210
211 /* Total size of the paged pool minus the allocated size, is free */
213
214 /* Check the initial state high state */
215 if (FreePoolInPages >= MiHighPagedPoolThreshold)
216 {
217 /* We have plenty of pool */
219 }
220 else
221 {
222 /* We don't */
224 }
225
226 /* Check the initial low state */
227 if (FreePoolInPages <= MiLowPagedPoolThreshold)
228 {
229 /* We're very low in free pool memory */
231 }
232 else
233 {
234 /* We're not */
236 }
237
238 /* Release the paged pool lock */
240
241 /* Now it's time for the nonpaged pool lock */
243
244 /* Free pages are the maximum minus what's been allocated */
246
247 /* Check if we have plenty */
248 if (FreePoolInPages >= MiHighNonPagedPoolThreshold)
249 {
250 /* We do, set the event */
252 }
253 else
254 {
255 /* We don't, clear the event */
257 }
258
259 /* Check if we have very little */
260 if (FreePoolInPages <= MiLowNonPagedPoolThreshold)
261 {
262 /* We do, set the event */
264 }
265 else
266 {
267 /* We don't, clear it */
269 }
270
271 /* We're done, release the nonpaged pool lock */
273}
#define KeSetEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:476
VOID NTAPI KeClearEvent(IN PKEVENT Event)
Definition: eventobj.c:22
PFN_NUMBER MiLowPagedPoolThreshold
Definition: mminit.c:302
PFN_NUMBER MiHighPagedPoolThreshold
Definition: mminit.c:303
PKEVENT MiLowNonPagedPoolEvent
Definition: mminit.c:296
PKEVENT MiHighPagedPoolEvent
Definition: mminit.c:295
PKEVENT MiLowPagedPoolEvent
Definition: mminit.c:294
PKEVENT MiHighNonPagedPoolEvent
Definition: mminit.c:297

Referenced by MiInitializeMemoryEvents().

◆ MiInitializeSessionPool()

NTSTATUS NTAPI MiInitializeSessionPool ( VOID  )

Definition at line 1276 of file pool.c.

1277{
1278 PMMPTE PointerPte, LastPte;
1279 PMMPDE PointerPde, LastPde;
1280 PFN_NUMBER PageFrameIndex, PdeCount;
1281 PPOOL_DESCRIPTOR PoolDescriptor;
1282 PMM_SESSION_SPACE SessionGlobal;
1283 PMM_PAGED_POOL_INFO PagedPoolInfo;
1285 ULONG Index, PoolSize, BitmapSize;
1286 PAGED_CODE();
1287
1288 /* Lock session pool */
1289 SessionGlobal = MmSessionSpace->GlobalVirtualAddress;
1291
1292 /* Setup a valid pool descriptor */
1293 PoolDescriptor = &MmSessionSpace->PagedPool;
1294 ExInitializePoolDescriptor(PoolDescriptor,
1296 0,
1297 0,
1298 &SessionGlobal->PagedPoolMutex);
1299
1300 /* Setup the pool addresses */
1303 DPRINT1("Session Pool Start: 0x%p End: 0x%p\n",
1305
1306 /* Reset all the counters */
1307 PagedPoolInfo = &MmSessionSpace->PagedPoolInfo;
1308 PagedPoolInfo->PagedPoolCommit = 0;
1309 PagedPoolInfo->PagedPoolHint = 0;
1310 PagedPoolInfo->AllocatedPagedPool = 0;
1311
1312 /* Compute PDE and PTE addresses */
1317
1318 /* Write them down */
1319 MmSessionSpace->PagedPoolBasePde = PointerPde;
1320 PagedPoolInfo->FirstPteForPagedPool = PointerPte;
1321 PagedPoolInfo->LastPteForPagedPool = LastPte;
1322 PagedPoolInfo->NextPdeForPagedPoolExpansion = PointerPde + 1;
1323
1324 /* Zero the PDEs */
1325 PdeCount = LastPde - PointerPde;
1326 RtlZeroMemory(PointerPde, (PdeCount + 1) * sizeof(MMPTE));
1327
1328 /* Initialize the PFN for the PDE */
1329 Status = MiInitializeAndChargePfn(&PageFrameIndex,
1330 PointerPde,
1332 TRUE);
1334
1335 /* Initialize the first page table */
1337 Index >>= 22;
1338#ifndef _M_AMD64 // FIXME
1340 MmSessionSpace->PageTables[Index] = *PointerPde;
1341#endif
1342
1343 /* Bump up counters */
1346
1347 /* Compute the size of the pool in pages, and of the bitmap for it */
1348 PoolSize = MmSessionPoolSize >> PAGE_SHIFT;
1349 BitmapSize = sizeof(RTL_BITMAP) + ((PoolSize + 31) / 32) * sizeof(ULONG);
1350
1351 /* Allocate and initialize the bitmap to track allocations */
1353 BitmapSize,
1354 TAG_MM);
1355 ASSERT(PagedPoolInfo->PagedPoolAllocationMap != NULL);
1357 (PULONG)(PagedPoolInfo->PagedPoolAllocationMap + 1),
1358 PoolSize);
1359
1360 /* Set all bits, but clear the first page table's worth */
1361 RtlSetAllBits(PagedPoolInfo->PagedPoolAllocationMap);
1363
1364 /* Allocate and initialize the bitmap to track free space */
1366 BitmapSize,
1367 TAG_MM);
1368 ASSERT(PagedPoolInfo->EndOfPagedPoolBitmap != NULL);
1370 (PULONG)(PagedPoolInfo->EndOfPagedPoolBitmap + 1),
1371 PoolSize);
1372
1373 /* Clear all the bits and return success */
1374 RtlClearAllBits(PagedPoolInfo->EndOfPagedPoolBitmap);
1375 return STATUS_SUCCESS;
1376}
LONG NTSTATUS
Definition: precomp.h:26
#define RtlInitializeBitMap
Definition: dbgbitmap.h:326
#define RtlClearAllBits
Definition: dbgbitmap.h:329
#define RtlSetAllBits
Definition: dbgbitmap.h:346
#define RTL_BITMAP
Definition: dbgbitmap.h:323
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
VOID NTAPI ExInitializePoolDescriptor(IN PPOOL_DESCRIPTOR PoolDescriptor, IN POOL_TYPE PoolType, IN ULONG PoolIndex, IN ULONG Threshold, IN PVOID PoolLock)
Definition: expool.c:969
Status
Definition: gdiplustypes.h:25
VOID FASTCALL KeInitializeGuardedMutex(OUT PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:31
#define InterlockedIncrementSizeT(a)
Definition: interlocked.h:220
PMM_SESSION_SPACE MmSessionSpace
Definition: session.c:21
NTSTATUS NTAPI MiInitializeAndChargePfn(OUT PPFN_NUMBER PageFrameIndex, IN PMMPDE PointerPde, IN PFN_NUMBER ContainingPageFrame, IN BOOLEAN SessionAllocation)
Definition: pfnlist.c:1101
PVOID MiSessionPoolStart
Definition: init.c:32
ULONG MmSessionPoolSize
Definition: init.c:36
PVOID MmSessionBase
Definition: init.c:33
PVOID MiSessionPoolEnd
Definition: init.c:31
#define STATUS_SUCCESS
Definition: shellext.h:65
ULONG_PTR Long
Definition: mmtypes.h:215
SIZE_T PagedPoolCommit
Definition: mm.h:492
PFN_NUMBER SessionPageDirectoryIndex
Definition: miarm.h:480
PMMPDE PageTables
Definition: miarm.h:507
KGUARDED_MUTEX PagedPoolMutex
Definition: miarm.h:498
PVOID PagedPoolStart
Definition: miarm.h:483
MM_PAGED_POOL_INFO PagedPoolInfo
Definition: miarm.h:499
struct _MM_SESSION_SPACE * GlobalVirtualAddress
Definition: miarm.h:470
PVOID PagedPoolEnd
Definition: miarm.h:484
SIZE_T CommittedPages
Definition: miarm.h:482
SIZE_T NonPageablePages
Definition: miarm.h:481
POOL_DESCRIPTOR PagedPool
Definition: miarm.h:503
PMMPDE PagedPoolBasePde
Definition: miarm.h:485
#define TAG_MM
Definition: tag.h:113
uint32_t * PULONG
Definition: typedefs.h:59
_In_ WDFCOLLECTION _In_ ULONG Index
@ PagedPoolSession
Definition: ketypes.h:893

◆ MiProtectedPoolInsertList()

VOID NTAPI MiProtectedPoolInsertList ( IN PLIST_ENTRY  ListHead,
IN PLIST_ENTRY  Entry,
IN BOOLEAN  Critical 
)

Definition at line 150 of file pool.c.

153{
154 PVOID PoolFlink, PoolBlink;
155
156 /* Make the list accessible */
157 MiProtectedPoolUnProtectLinks(ListHead, &PoolFlink, &PoolBlink);
158
159 /* Now insert in the right position */
160 Critical ? InsertHeadList(ListHead, Entry) : InsertTailList(ListHead, Entry);
161
162 /* And reprotect the pages containing the free links */
163 MiProtectedPoolProtectLinks(PoolFlink, PoolBlink);
164}
FORCEINLINE VOID MiProtectedPoolUnProtectLinks(IN PLIST_ENTRY Links, OUT PVOID *PoolFlink, OUT PVOID *PoolBlink)
Definition: pool.c:105
FORCEINLINE VOID MiProtectedPoolProtectLinks(IN PVOID PoolFlink, IN PVOID PoolBlink)
Definition: pool.c:140
base of all file and directory entries
Definition: entries.h:83

Referenced by MiAllocatePoolPages(), and MiFreePoolPages().

◆ MiProtectedPoolProtectLinks()

FORCEINLINE VOID MiProtectedPoolProtectLinks ( IN PVOID  PoolFlink,
IN PVOID  PoolBlink 
)

Definition at line 140 of file pool.c.

142{
143 /* Reprotect the pages, if they got unprotected earlier */
144 if (PoolFlink) MiProtectFreeNonPagedPool(PoolFlink, 1);
145 if (PoolBlink) MiProtectFreeNonPagedPool(PoolBlink, 1);
146}

Referenced by MiProtectedPoolInsertList().

◆ MiProtectedPoolRemoveEntryList()

VOID NTAPI MiProtectedPoolRemoveEntryList ( IN PLIST_ENTRY  Entry)

Definition at line 168 of file pool.c.

169{
170 PVOID PoolFlink, PoolBlink;
171
172 /* Make the list accessible */
173 MiProtectedPoolUnProtectLinks(Entry, &PoolFlink, &PoolBlink);
174
175 /* Now remove */
177
178 /* And reprotect the pages containing the free links */
179 if (PoolFlink) MiProtectFreeNonPagedPool(PoolFlink, 1);
180 if (PoolBlink) MiProtectFreeNonPagedPool(PoolBlink, 1);
181}

Referenced by MiAllocatePoolPages(), and MiFreePoolPages().

◆ MiProtectedPoolUnProtectLinks()

FORCEINLINE VOID MiProtectedPoolUnProtectLinks ( IN PLIST_ENTRY  Links,
OUT PVOID PoolFlink,
OUT PVOID PoolBlink 
)

Definition at line 105 of file pool.c.

108{
109 BOOLEAN Safe;
110 PVOID PoolVa;
111
112 /* Initialize variables */
113 *PoolFlink = *PoolBlink = NULL;
114
115 /* Check if the list has entries */
116 if (IsListEmpty(Links) == FALSE)
117 {
118 /* We are going to need to forward link to do an insert */
119 PoolVa = Links->Flink;
120
121 /* So make it safe to access */
122 Safe = MiUnProtectFreeNonPagedPool(PoolVa, 1);
123 if (Safe) *PoolFlink = PoolVa;
124 }
125
126 /* Are we going to need a backward link too? */
127 if (Links != Links->Blink)
128 {
129 /* Get the head's backward link for the insert */
130 PoolVa = Links->Blink;
131
132 /* Make it safe to access */
133 Safe = MiUnProtectFreeNonPagedPool(PoolVa, 1);
134 if (Safe) *PoolBlink = PoolVa;
135 }
136}
unsigned char BOOLEAN
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954

Referenced by MiProtectedPoolInsertList(), and MiProtectedPoolRemoveEntryList().

◆ MiProtectFreeNonPagedPool()

VOID NTAPI MiProtectFreeNonPagedPool ( IN PVOID  VirtualAddress,
IN ULONG  PageCount 
)

Definition at line 41 of file pool.c.

43{
44 PMMPTE PointerPte, LastPte;
46
47 /* If pool is physical, can't protect PTEs */
49
50 /* Get PTE pointers and loop */
51 PointerPte = MiAddressToPte(VirtualAddress);
52 LastPte = PointerPte + PageCount;
53 do
54 {
55 /* Capture the PTE for safety */
56 TempPte = *PointerPte;
57
58 /* Mark it as an invalid PTE, set proto bit to recognize it as pool */
59 TempPte.u.Hard.Valid = 0;
60 TempPte.u.Soft.Prototype = 1;
61 MI_WRITE_INVALID_PTE(PointerPte, TempPte);
62 } while (++PointerPte < LastPte);
63
64 /* Flush the TLB */
66}
FORCEINLINE BOOLEAN MI_IS_PHYSICAL_ADDRESS(IN PVOID Address)
Definition: miarm.h:945
_Must_inspect_result_ _In_ WDFDMATRANSACTION _In_ PFN_WDF_PROGRAM_DMA _In_ WDF_DMA_DIRECTION _In_ PMDL _In_ PVOID VirtualAddress

Referenced by MiAllocatePoolPages(), MiFreePoolPages(), MiProtectedPoolProtectLinks(), and MiProtectedPoolRemoveEntryList().

◆ MiUnProtectFreeNonPagedPool()

BOOLEAN NTAPI MiUnProtectFreeNonPagedPool ( IN PVOID  VirtualAddress,
IN ULONG  PageCount 
)

Definition at line 70 of file pool.c.

72{
73 PMMPTE PointerPte;
75 PFN_NUMBER UnprotectedPages = 0;
76
77 /* If pool is physical, can't protect PTEs */
79
80 /* Get, and capture the PTE */
81 PointerPte = MiAddressToPte(VirtualAddress);
82 TempPte = *PointerPte;
83
84 /* Loop protected PTEs */
85 while ((TempPte.u.Hard.Valid == 0) && (TempPte.u.Soft.Prototype == 1))
86 {
87 /* Unprotect the PTE */
88 TempPte.u.Hard.Valid = 1;
89 TempPte.u.Soft.Prototype = 0;
90 MI_WRITE_VALID_PTE(PointerPte, TempPte);
91
92 /* One more page */
93 if (++UnprotectedPages == PageCount) break;
94
95 /* Capture next PTE */
96 TempPte = *(++PointerPte);
97 }
98
99 /* Return if any pages were unprotected */
100 return UnprotectedPages ? TRUE : FALSE;
101}

Referenced by MiAllocatePoolPages(), MiFreePoolPages(), and MiProtectedPoolUnProtectLinks().

◆ MmAllocateMappingAddress()

PVOID NTAPI MmAllocateMappingAddress ( IN SIZE_T  NumberOfBytes,
IN ULONG  PoolTag 
)

Definition at line 1560 of file pool.c.

1562{
1564 return NULL;
1565}
#define UNIMPLEMENTED
Definition: debug.h:118

Referenced by START_TEST().

◆ MmDeterminePoolType()

POOL_TYPE NTAPI MmDeterminePoolType ( IN PVOID  PoolAddress)

Definition at line 408 of file pool.c.

409{
410 //
411 // Use a simple bounds check
412 //
413 if (PoolAddress >= MmPagedPoolStart && PoolAddress <= MmPagedPoolEnd)
414 return PagedPool;
415 else if (PoolAddress >= MmNonPagedPoolStart && PoolAddress <= MmNonPagedPoolEnd)
416 return NonPagedPool;
417 KeBugCheckEx(BAD_POOL_CALLER, 0x42, (ULONG_PTR)PoolAddress, 0, 0);
418}
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

Referenced by ExFreePoolWithTag(), and ExpCheckPoolAllocation().

◆ MmFreeMappingAddress()

VOID NTAPI MmFreeMappingAddress ( IN PVOID  BaseAddress,
IN ULONG  PoolTag 
)

Definition at line 1572 of file pool.c.

1574{
1576}

Referenced by START_TEST().

Variable Documentation

◆ MiEndOfInitialPoolFrame

PFN_NUMBER MiEndOfInitialPoolFrame

Definition at line 23 of file pool.c.

Referenced by MiFreePoolPages(), and MiInitializeNonPagedPool().

◆ MiExpansionPoolPagesInitialCharge

PFN_COUNT MiExpansionPoolPagesInitialCharge

Definition at line 21 of file pool.c.

Referenced by MiInitializeNonPagedPool(), and MmArmInitSystem().

◆ MiNonPagedPoolSListHead

SLIST_HEADER MiNonPagedPoolSListHead

Definition at line 32 of file pool.c.

Referenced by MiAllocatePoolPages(), MiFreePoolPages(), and MiInitializeNonPagedPool().

◆ MiNonPagedPoolSListMaximum

ULONG MiNonPagedPoolSListMaximum = 4

Definition at line 33 of file pool.c.

Referenced by MiFreePoolPages(), and MiInitializeNonPagedPool().

◆ MiPagedPoolSListHead

SLIST_HEADER MiPagedPoolSListHead

Definition at line 34 of file pool.c.

Referenced by MiAllocatePoolPages(), MiFreePoolPages(), and MiInitializeNonPagedPool().

◆ MiPagedPoolSListMaximum

ULONG MiPagedPoolSListMaximum = 8

Definition at line 35 of file pool.c.

Referenced by MiFreePoolPages(), and MiInitializeNonPagedPool().

◆ MiStartOfInitialPoolFrame

PFN_NUMBER MiStartOfInitialPoolFrame

Definition at line 23 of file pool.c.

Referenced by MiFreePoolPages(), and MiInitializeNonPagedPool().

◆ MmAllocatedNonPagedPool

SIZE_T MmAllocatedNonPagedPool

Definition at line 26 of file pool.c.

Referenced by _Requires_lock_held_(), and MiInitializePoolEvents().

◆ MmConsumedPoolPercentage

ULONG MmConsumedPoolPercentage

Definition at line 30 of file pool.c.

◆ MmNonPagedPoolEnd0

PVOID MmNonPagedPoolEnd0

Definition at line 22 of file pool.c.

Referenced by MiInitializeNonPagedPool().

◆ MmNonPagedPoolFreeListHead

LIST_ENTRY MmNonPagedPoolFreeListHead[MI_MAX_FREE_PAGE_LISTS]

Definition at line 20 of file pool.c.

Referenced by MiAllocatePoolPages(), MiFreePoolPages(), and MiInitializeNonPagedPool().

◆ MmNumberOfFreeNonPagedPool

PFN_COUNT MmNumberOfFreeNonPagedPool

Definition at line 21 of file pool.c.

Referenced by MiInitializeNonPagedPool().

◆ MmPagedPoolInfo

◆ MmPagedPoolMutex

KGUARDED_MUTEX MmPagedPoolMutex

◆ MmProtectFreedNonPagedPool

BOOLEAN MmProtectFreedNonPagedPool

◆ MmSpecialPoolTag

ULONG MmSpecialPoolTag

Definition at line 29 of file pool.c.

Referenced by MiInitializeSpecialPool(), MmArmInitSystem(), and MmUseSpecialPool().

◆ MmTotalNonPagedPoolQuota

SIZE_T MmTotalNonPagedPoolQuota

Definition at line 27 of file pool.c.

Referenced by _Requires_lock_held_().

◆ MmTotalPagedPoolQuota

SIZE_T MmTotalPagedPoolQuota

Definition at line 28 of file pool.c.

Referenced by _Requires_lock_held_().