2 * PROJECT: ReactOS Kernel
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * FILE: ntoskrnl/mm/ARM3/miarm.h
5 * PURPOSE: ARM Memory Manager Header
6 * PROGRAMMERS: ReactOS Portable Systems Group
11 #define MI_MIN_PAGES_FOR_NONPAGED_POOL_TUNING ((255 * _1MB) >> PAGE_SHIFT)
12 #define MI_MIN_PAGES_FOR_SYSPTE_TUNING ((19 * _1MB) >> PAGE_SHIFT)
13 #define MI_MIN_PAGES_FOR_SYSPTE_BOOST ((32 * _1MB) >> PAGE_SHIFT)
14 #define MI_MIN_PAGES_FOR_SYSPTE_BOOST_BOOST ((256 * _1MB) >> PAGE_SHIFT)
15 #define MI_MAX_INIT_NONPAGED_POOL_SIZE (128 * _1MB)
16 #define MI_MAX_NONPAGED_POOL_SIZE (128 * _1MB)
17 #define MI_MAX_FREE_PAGE_LISTS 4
19 #define MI_MIN_INIT_PAGED_POOLSIZE (32 * _1MB)
21 #define MI_SESSION_VIEW_SIZE (20 * _1MB)
22 #define MI_SESSION_POOL_SIZE (16 * _1MB)
23 #define MI_SESSION_IMAGE_SIZE (8 * _1MB)
24 #define MI_SESSION_WORKING_SET_SIZE (4 * _1MB)
25 #define MI_SESSION_SIZE (MI_SESSION_VIEW_SIZE + \
26 MI_SESSION_POOL_SIZE + \
27 MI_SESSION_IMAGE_SIZE + \
28 MI_SESSION_WORKING_SET_SIZE)
30 #define MI_SYSTEM_VIEW_SIZE (32 * _1MB)
32 #define MI_HIGHEST_USER_ADDRESS (PVOID)0x7FFEFFFF
33 #define MI_USER_PROBE_ADDRESS (PVOID)0x7FFF0000
34 #define MI_DEFAULT_SYSTEM_RANGE_START (PVOID)0x80000000
35 #define MI_SYSTEM_CACHE_WS_START (PVOID)0xC0C00000
36 #define MI_PAGED_POOL_START (PVOID)0xE1000000
37 #define MI_NONPAGED_POOL_END (PVOID)0xFFBE0000
38 #define MI_DEBUG_MAPPING (PVOID)0xFFBFF000
40 #define MI_SYSTEM_PTE_BASE (PVOID)MiAddressToPte(NULL)
42 #define MI_MIN_SECONDARY_COLORS 8
43 #define MI_SECONDARY_COLORS 64
44 #define MI_MAX_SECONDARY_COLORS 1024
46 #define MI_MIN_ALLOCATION_FRAGMENT (4 * _1KB)
47 #define MI_ALLOCATION_FRAGMENT (64 * _1KB)
48 #define MI_MAX_ALLOCATION_FRAGMENT (2 * _1MB)
50 #define MM_HIGHEST_VAD_ADDRESS \
51 (PVOID)((ULONG_PTR)MM_HIGHEST_USER_ADDRESS - (16 * PAGE_SIZE))
52 #define MI_LOWEST_VAD_ADDRESS (PVOID)MM_LOWEST_USER_ADDRESS
54 #define MI_DEFAULT_SYSTEM_PTE_COUNT 50000
56 #endif /* !_M_AMD64 */
58 /* Make the code cleaner with some definitions for size multiples */
60 #define _1MB (1024 * _1KB)
61 #define _1GB (1024 * _1MB)
63 /* Everyone loves 64K */
64 #define _64K (64 * _1KB)
66 /* Area mapped by a PDE */
67 #define PDE_MAPPED_VA (PTE_COUNT * PAGE_SIZE)
69 /* Size of a page table */
70 #define PT_SIZE (PTE_COUNT * sizeof(MMPTE))
72 /* Size of a page directory */
73 #define PD_SIZE (PDE_COUNT * sizeof(MMPDE))
75 /* Size of all page directories for a process */
76 #define SYSTEM_PD_SIZE (PD_COUNT * PD_SIZE)
78 /* Architecture specific count of PDEs in a directory, and count of PTEs in a PT */
81 #define PDE_COUNT 1024
82 #define PTE_COUNT 1024
83 C_ASSERT(SYSTEM_PD_SIZE
== PAGE_SIZE
);
84 #define MiIsPteOnPdeBoundary(PointerPte) \
85 ((((ULONG_PTR)PointerPte) & (PAGE_SIZE - 1)) == 0)
88 #define PDE_COUNT 4096
91 #define PD_COUNT PPE_PER_PAGE
92 #define PDE_COUNT PDE_PER_PAGE
93 #define PTE_COUNT PTE_PER_PAGE
97 // Protection Bits part of the internal memory manager Protection Mask
98 // Taken from http://www.reactos.org/wiki/Techwiki:Memory_management_in_the_Windows_XP_kernel
99 // and public assertions.
101 #define MM_ZERO_ACCESS 0
102 #define MM_READONLY 1
104 #define MM_EXECUTE_READ 3
105 #define MM_READWRITE 4
106 #define MM_WRITECOPY 5
107 #define MM_EXECUTE_READWRITE 6
108 #define MM_EXECUTE_WRITECOPY 7
110 #define MM_DECOMMIT 0x10
111 #define MM_NOACCESS (MM_DECOMMIT | MM_NOCACHE)
112 #define MM_INVALID_PROTECTION 0xFFFFFFFF
115 // Specific PTE Definitions that map to the Memory Manager's Protection Mask Bits
116 // The Memory Manager's definition define the attributes that must be preserved
117 // and these PTE definitions describe the attributes in the hardware sense. This
118 // helps deal with hardware differences between the actual boolean expression of
121 // For example, in the logical attributes, we want to express read-only as a flag
122 // but on x86, it is writability that must be set. On the other hand, on x86, just
123 // like in the kernel, it is disabling the caches that requires a special flag,
124 // while on certain architectures such as ARM, it is enabling the cache which
127 #if defined(_M_IX86) || defined(_M_AMD64)
131 #define PTE_READONLY 0 // Doesn't exist on x86
132 #define PTE_EXECUTE 0 // Not worrying about NX yet
133 #define PTE_EXECUTE_READ 0 // Not worrying about NX yet
134 #define PTE_READWRITE 0x2
135 #define PTE_WRITECOPY 0x200
136 #define PTE_EXECUTE_READWRITE 0x2 // Not worrying about NX yet
137 #define PTE_EXECUTE_WRITECOPY 0x200
138 #define PTE_PROTOTYPE 0x400
143 #define PTE_VALID 0x1
144 #define PTE_ACCESSED 0x20
145 #define PTE_DIRTY 0x40
150 #define PTE_ENABLE_CACHE 0
151 #define PTE_DISABLE_CACHE 0x10
152 #define PTE_WRITECOMBINED_CACHE 0x10
153 #elif defined(_M_ARM)
154 #define PTE_READONLY 0x200
155 #define PTE_EXECUTE 0 // Not worrying about NX yet
156 #define PTE_EXECUTE_READ 0 // Not worrying about NX yet
157 #define PTE_READWRITE 0 // Doesn't exist on ARM
158 #define PTE_WRITECOPY 0 // Doesn't exist on ARM
159 #define PTE_EXECUTE_READWRITE 0 // Not worrying about NX yet
160 #define PTE_EXECUTE_WRITECOPY 0 // Not worrying about NX yet
161 #define PTE_PROTOTYPE 0x400 // Using the Shared bit
165 #define PTE_ENABLE_CACHE 0
166 #define PTE_DISABLE_CACHE 0x10
167 #define PTE_WRITECOMBINED_CACHE 0x10
169 #error Define these please!
172 extern const ULONG_PTR MmProtectToPteMask
[32];
173 extern const ULONG MmProtectToValue
[32];
176 // Assertions for session images, addresses, and PTEs
178 #define MI_IS_SESSION_IMAGE_ADDRESS(Address) \
179 (((Address) >= MiSessionImageStart) && ((Address) < MiSessionImageEnd))
181 #define MI_IS_SESSION_ADDRESS(Address) \
182 (((Address) >= MmSessionBase) && ((Address) < MiSessionSpaceEnd))
184 #define MI_IS_SESSION_PTE(Pte) \
185 ((((PMMPTE)Pte) >= MiSessionBasePte) && (((PMMPTE)Pte) < MiSessionLastPte))
187 #define MI_IS_PAGE_TABLE_ADDRESS(Address) \
188 (((PVOID)(Address) >= (PVOID)PTE_BASE) && ((PVOID)(Address) <= (PVOID)PTE_TOP))
190 #define MI_IS_SYSTEM_PAGE_TABLE_ADDRESS(Address) \
191 (((Address) >= (PVOID)MiAddressToPte(MmSystemRangeStart)) && ((Address) <= (PVOID)PTE_TOP))
193 #define MI_IS_PAGE_TABLE_OR_HYPER_ADDRESS(Address) \
194 (((PVOID)(Address) >= (PVOID)PTE_BASE) && ((PVOID)(Address) <= (PVOID)MmHyperSpaceEnd))
197 // Corresponds to MMPTE_SOFTWARE.Protection
200 #define MM_PTE_SOFTWARE_PROTECTION_BITS 5
202 #define MM_PTE_SOFTWARE_PROTECTION_BITS 6
204 #define MM_PTE_SOFTWARE_PROTECTION_BITS 5
206 #error Define these please!
210 // Creates a software PTE with the given protection
212 #define MI_MAKE_SOFTWARE_PTE(p, x) ((p)->u.Long = (x << MM_PTE_SOFTWARE_PROTECTION_BITS))
215 // Marks a PTE as deleted
217 #define MI_SET_PFN_DELETED(x) ((x)->PteAddress = (PMMPTE)((ULONG_PTR)(x)->PteAddress | 1))
218 #define MI_IS_PFN_DELETED(x) ((ULONG_PTR)((x)->PteAddress) & 1)
221 // Special values for LoadedImports
223 #define MM_SYSLDR_NO_IMPORTS (PVOID)0xFFFFFFFE
224 #define MM_SYSLDR_BOOT_LOADED (PVOID)0xFFFFFFFF
225 #define MM_SYSLDR_SINGLE_ENTRY 0x1
228 // Number of initial session IDs
230 #define MI_INITIAL_SESSION_IDS 64
232 #if defined(_M_IX86) || defined(_M_ARM)
236 #define LIST_HEAD 0xFFFFFFFF
239 // Because GCC cannot automatically downcast 0xFFFFFFFF to lesser-width bits,
240 // we need a manual definition suited to the number of bits in the PteFrame.
241 // This is used as a LIST_HEAD for the colored list
243 #define COLORED_LIST_HEAD ((1 << 25) - 1) // 0x1FFFFFF
244 #elif defined(_M_AMD64)
245 #define LIST_HEAD 0xFFFFFFFFFFFFFFFFLL
246 #define COLORED_LIST_HEAD ((1ULL << 57) - 1) // 0x1FFFFFFFFFFFFFFLL
248 #error Define these please!
252 // Special IRQL value (found in assertions)
254 #define MM_NOIRQL (KIRQL)0xFFFFFFFF
257 // Returns the color of a page
259 #define MI_GET_PAGE_COLOR(x) ((x) & MmSecondaryColorMask)
260 #define MI_GET_NEXT_COLOR() (MI_GET_PAGE_COLOR(++MmSystemPageColor))
261 #define MI_GET_NEXT_PROCESS_COLOR(x) (MI_GET_PAGE_COLOR(++(x)->NextPageColor))
265 // Decodes a Prototype PTE into the underlying PTE
267 #define MiProtoPteToPte(x) \
268 (PMMPTE)((ULONG_PTR)MmPagedPoolStart + \
269 (((x)->u.Proto.ProtoAddressHigh << 9) | (x)->u.Proto.ProtoAddressLow << 2))
272 // Decodes a Prototype PTE into the underlying PTE
274 #define MiSubsectionPteToSubsection(x) \
275 ((x)->u.Subsect.WhichPool == PagedPool) ? \
276 (PMMPTE)((ULONG_PTR)MmSubsectionBase + \
277 (((x)->u.Subsect.SubsectionAddressHigh << 7) | \
278 (x)->u.Subsect.SubsectionAddressLow << 3)) : \
279 (PMMPTE)((ULONG_PTR)MmNonPagedPoolEnd - \
280 (((x)->u.Subsect.SubsectionAddressHigh << 7) | \
281 (x)->u.Subsect.SubsectionAddressLow << 3))
285 // Prototype PTEs that don't yet have a pagefile association
288 #define MI_PTE_LOOKUP_NEEDED 0xffffffffULL
290 #define MI_PTE_LOOKUP_NEEDED 0xFFFFF
294 // Number of session lists in the MM_SESSIONS_SPACE structure
296 #if defined(_M_AMD64)
297 #define SESSION_POOL_LOOKASIDES 21
298 #elif defined(_M_IX86)
299 #define SESSION_POOL_LOOKASIDES 26
305 // Number of session data and tag pages
307 #define MI_SESSION_DATA_PAGES_MAXIMUM (MM_ALLOCATION_GRANULARITY / PAGE_SIZE)
308 #define MI_SESSION_TAG_PAGES_MAXIMUM (MM_ALLOCATION_GRANULARITY / PAGE_SIZE)
312 // System views are binned into 64K chunks
314 #define MI_SYSTEM_VIEW_BUCKET_SIZE _64K
317 // FIXFIX: These should go in ex.h after the pool merge
320 #define POOL_BLOCK_SIZE 16
322 #define POOL_BLOCK_SIZE 8
324 #define POOL_LISTS_PER_PAGE (PAGE_SIZE / POOL_BLOCK_SIZE)
325 #define BASE_POOL_TYPE_MASK 1
326 #define POOL_MAX_ALLOC (PAGE_SIZE - (sizeof(POOL_HEADER) + POOL_BLOCK_SIZE))
329 // Pool debugging/analysis/tracing flags
331 #define POOL_FLAG_CHECK_TIMERS 0x1
332 #define POOL_FLAG_CHECK_WORKERS 0x2
333 #define POOL_FLAG_CHECK_RESOURCES 0x4
334 #define POOL_FLAG_VERIFIER 0x8
335 #define POOL_FLAG_CHECK_DEADLOCK 0x10
336 #define POOL_FLAG_SPECIAL_POOL 0x20
337 #define POOL_FLAG_DBGPRINT_ON_FAILURE 0x40
338 #define POOL_FLAG_CRASH_ON_FAILURE 0x80
341 // BAD_POOL_HEADER codes during pool bugcheck
343 #define POOL_CORRUPTED_LIST 3
344 #define POOL_SIZE_OR_INDEX_MISMATCH 5
345 #define POOL_ENTRIES_NOT_ALIGNED_PREVIOUS 6
346 #define POOL_HEADER_NOT_ALIGNED 7
347 #define POOL_HEADER_IS_ZERO 8
348 #define POOL_ENTRIES_NOT_ALIGNED_NEXT 9
349 #define POOL_ENTRY_NOT_FOUND 10
352 // BAD_POOL_CALLER codes during pool bugcheck
354 #define POOL_ENTRY_CORRUPTED 1
355 #define POOL_ENTRY_ALREADY_FREE 6
356 #define POOL_ENTRY_NOT_ALLOCATED 7
357 #define POOL_ALLOC_IRQL_INVALID 8
358 #define POOL_FREE_IRQL_INVALID 9
359 #define POOL_BILLED_PROCESS_INVALID 13
360 #define POOL_HEADER_SIZE_INVALID 32
362 typedef struct _POOL_DESCRIPTOR
367 ULONG RunningDeAllocs
;
373 LONG PendingFreeDepth
;
376 LIST_ENTRY ListHeads
[POOL_LISTS_PER_PAGE
];
377 } POOL_DESCRIPTOR
, *PPOOL_DESCRIPTOR
;
379 typedef struct _POOL_HEADER
386 USHORT PreviousSize
:8;
391 USHORT PreviousSize
:9;
405 PEPROCESS ProcessBilled
;
411 USHORT AllocatorBackTraceIndex
;
415 } POOL_HEADER
, *PPOOL_HEADER
;
417 C_ASSERT(sizeof(POOL_HEADER
) == POOL_BLOCK_SIZE
);
418 C_ASSERT(POOL_BLOCK_SIZE
== sizeof(LIST_ENTRY
));
420 typedef struct _POOL_TRACKER_TABLE
425 SIZE_T NonPagedBytes
;
429 } POOL_TRACKER_TABLE
, *PPOOL_TRACKER_TABLE
;
431 typedef struct _POOL_TRACKER_BIG_PAGES
437 } POOL_TRACKER_BIG_PAGES
, *PPOOL_TRACKER_BIG_PAGES
;
439 extern ULONG ExpNumberOfPagedPools
;
440 extern POOL_DESCRIPTOR NonPagedPoolDescriptor
;
441 extern PPOOL_DESCRIPTOR ExpPagedPoolDescriptor
[16 + 1];
442 extern PPOOL_TRACKER_TABLE PoolTrackTable
;
448 typedef struct _MI_LARGE_PAGE_DRIVER_ENTRY
451 UNICODE_STRING BaseName
;
452 } MI_LARGE_PAGE_DRIVER_ENTRY
, *PMI_LARGE_PAGE_DRIVER_ENTRY
;
454 typedef enum _MMSYSTEM_PTE_POOL_TYPE
457 NonPagedPoolExpansion
,
459 } MMSYSTEM_PTE_POOL_TYPE
;
461 typedef enum _MI_PFN_CACHE_ATTRIBUTE
467 } MI_PFN_CACHE_ATTRIBUTE
, *PMI_PFN_CACHE_ATTRIBUTE
;
469 typedef struct _PHYSICAL_MEMORY_RUN
472 PFN_NUMBER PageCount
;
473 } PHYSICAL_MEMORY_RUN
, *PPHYSICAL_MEMORY_RUN
;
475 typedef struct _PHYSICAL_MEMORY_DESCRIPTOR
478 PFN_NUMBER NumberOfPages
;
479 PHYSICAL_MEMORY_RUN Run
[1];
480 } PHYSICAL_MEMORY_DESCRIPTOR
, *PPHYSICAL_MEMORY_DESCRIPTOR
;
482 typedef struct _MMCOLOR_TABLES
487 } MMCOLOR_TABLES
, *PMMCOLOR_TABLES
;
489 typedef struct _MI_LARGE_PAGE_RANGES
491 PFN_NUMBER StartFrame
;
492 PFN_NUMBER LastFrame
;
493 } MI_LARGE_PAGE_RANGES
, *PMI_LARGE_PAGE_RANGES
;
495 typedef struct _MMVIEW
498 PCONTROL_AREA ControlArea
;
501 typedef struct _MMSESSION
503 KGUARDED_MUTEX SystemSpaceViewLock
;
504 PKGUARDED_MUTEX SystemSpaceViewLockPointer
;
505 PCHAR SystemSpaceViewStart
;
506 PMMVIEW SystemSpaceViewTable
;
507 ULONG SystemSpaceHashSize
;
508 ULONG SystemSpaceHashEntries
;
509 ULONG SystemSpaceHashKey
;
510 ULONG BitmapFailures
;
511 PRTL_BITMAP SystemSpaceBitMap
;
512 } MMSESSION
, *PMMSESSION
;
514 typedef struct _MM_SESSION_SPACE_FLAGS
517 ULONG DeletePending
:1;
519 } MM_SESSION_SPACE_FLAGS
;
521 typedef struct _MM_SESSION_SPACE
523 struct _MM_SESSION_SPACE
*GlobalVirtualAddress
;
528 MM_SESSION_SPACE_FLAGS Flags
;
531 LIST_ENTRY ProcessList
;
532 LARGE_INTEGER LastProcessSwappedOutTime
;
533 PFN_NUMBER SessionPageDirectoryIndex
;
534 SIZE_T NonPageablePages
;
535 SIZE_T CommittedPages
;
536 PVOID PagedPoolStart
;
538 PMMPTE PagedPoolBasePde
;
540 LONG ResidentProcessCount
;
541 ULONG SessionPoolAllocationFailures
[4];
542 LIST_ENTRY ImageList
;
546 PEPROCESS LastProcess
;
547 LONG ProcessReferenceToSession
;
548 LIST_ENTRY WsListEntry
;
549 GENERAL_LOOKASIDE Lookaside
[SESSION_POOL_LOOKASIDES
];
551 KGUARDED_MUTEX PagedPoolMutex
;
552 MM_PAGED_POOL_INFO PagedPoolInfo
;
555 PDRIVER_UNLOAD Win32KDriverUnload
;
556 POOL_DESCRIPTOR PagedPool
;
557 #if defined (_M_AMD64)
562 #if defined (_M_AMD64)
563 PMMPTE SpecialPoolFirstPte
;
564 PMMPTE SpecialPoolLastPte
;
565 PMMPTE NextPdeForSpecialPoolExpansion
;
566 PMMPTE LastPdeForSpecialPoolExpansion
;
567 PFN_NUMBER SpecialPagesInUse
;
569 LONG ImageLoadingCount
;
570 } MM_SESSION_SPACE
, *PMM_SESSION_SPACE
;
572 extern PMM_SESSION_SPACE MmSessionSpace
;
573 extern MMPTE HyperTemplatePte
;
574 extern MMPDE ValidKernelPde
;
575 extern MMPTE ValidKernelPte
;
576 extern MMPDE ValidKernelPdeLocal
;
577 extern MMPTE ValidKernelPteLocal
;
578 extern MMPDE DemandZeroPde
;
579 extern MMPTE DemandZeroPte
;
580 extern MMPTE PrototypePte
;
581 extern MMPTE MmDecommittedPte
;
582 extern BOOLEAN MmLargeSystemCache
;
583 extern BOOLEAN MmZeroPageFile
;
584 extern BOOLEAN MmProtectFreedNonPagedPool
;
585 extern BOOLEAN MmTrackLockedPages
;
586 extern BOOLEAN MmTrackPtes
;
587 extern BOOLEAN MmDynamicPfn
;
588 extern BOOLEAN MmMirroring
;
589 extern BOOLEAN MmMakeLowMemory
;
590 extern BOOLEAN MmEnforceWriteProtection
;
591 extern SIZE_T MmAllocationFragment
;
592 extern ULONG MmConsumedPoolPercentage
;
593 extern ULONG MmVerifyDriverBufferType
;
594 extern ULONG MmVerifyDriverLevel
;
595 extern WCHAR MmVerifyDriverBuffer
[512];
596 extern WCHAR MmLargePageDriverBuffer
[512];
597 extern LIST_ENTRY MiLargePageDriverList
;
598 extern BOOLEAN MiLargePageAllDrivers
;
599 extern ULONG MmVerifyDriverBufferLength
;
600 extern ULONG MmLargePageDriverBufferLength
;
601 extern SIZE_T MmSizeOfNonPagedPoolInBytes
;
602 extern SIZE_T MmMaximumNonPagedPoolInBytes
;
603 extern PFN_NUMBER MmMaximumNonPagedPoolInPages
;
604 extern PFN_NUMBER MmSizeOfPagedPoolInPages
;
605 extern PVOID MmNonPagedSystemStart
;
606 extern SIZE_T MiNonPagedSystemSize
;
607 extern PVOID MmNonPagedPoolStart
;
608 extern PVOID MmNonPagedPoolExpansionStart
;
609 extern PVOID MmNonPagedPoolEnd
;
610 extern SIZE_T MmSizeOfPagedPoolInBytes
;
611 extern PVOID MmPagedPoolStart
;
612 extern PVOID MmPagedPoolEnd
;
613 extern PVOID MmSessionBase
;
614 extern SIZE_T MmSessionSize
;
615 extern PMMPTE MmFirstReservedMappingPte
, MmLastReservedMappingPte
;
616 extern PMMPTE MiFirstReservedZeroingPte
;
617 extern MI_PFN_CACHE_ATTRIBUTE MiPlatformCacheAttributes
[2][MmMaximumCacheType
];
618 extern PPHYSICAL_MEMORY_DESCRIPTOR MmPhysicalMemoryBlock
;
619 extern SIZE_T MmBootImageSize
;
620 extern PMMPTE MmSystemPtesStart
[MaximumPtePoolTypes
];
621 extern PMMPTE MmSystemPtesEnd
[MaximumPtePoolTypes
];
622 extern PMEMORY_ALLOCATION_DESCRIPTOR MxFreeDescriptor
;
623 extern MEMORY_ALLOCATION_DESCRIPTOR MxOldFreeDescriptor
;
624 extern ULONG_PTR MxPfnAllocation
;
625 extern MM_PAGED_POOL_INFO MmPagedPoolInfo
;
626 extern RTL_BITMAP MiPfnBitMap
;
627 extern KGUARDED_MUTEX MmPagedPoolMutex
;
628 extern KGUARDED_MUTEX MmSectionCommitMutex
;
629 extern PVOID MmPagedPoolStart
;
630 extern PVOID MmPagedPoolEnd
;
631 extern PVOID MmNonPagedSystemStart
;
632 extern PVOID MiSystemViewStart
;
633 extern SIZE_T MmSystemViewSize
;
634 extern PVOID MmSessionBase
;
635 extern PVOID MiSessionSpaceEnd
;
636 extern PMMPTE MiSessionImagePteStart
;
637 extern PMMPTE MiSessionImagePteEnd
;
638 extern PMMPTE MiSessionBasePte
;
639 extern PMMPTE MiSessionLastPte
;
640 extern SIZE_T MmSizeOfPagedPoolInBytes
;
641 extern PMMPDE MmSystemPagePtes
;
642 extern PVOID MmSystemCacheStart
;
643 extern PVOID MmSystemCacheEnd
;
644 extern MMSUPPORT MmSystemCacheWs
;
645 extern SIZE_T MmAllocatedNonPagedPool
;
646 extern ULONG MmSpecialPoolTag
;
647 extern PVOID MmHyperSpaceEnd
;
648 extern PMMWSL MmSystemCacheWorkingSetList
;
649 extern SIZE_T MmMinimumNonPagedPoolSize
;
650 extern ULONG MmMinAdditionNonPagedPoolPerMb
;
651 extern SIZE_T MmDefaultMaximumNonPagedPool
;
652 extern ULONG MmMaxAdditionNonPagedPoolPerMb
;
653 extern ULONG MmSecondaryColors
;
654 extern ULONG MmSecondaryColorMask
;
655 extern ULONG MmNumberOfSystemPtes
;
656 extern ULONG MmMaximumNonPagedPoolPercent
;
657 extern ULONG MmLargeStackSize
;
658 extern PMMCOLOR_TABLES MmFreePagesByColor
[FreePageList
+ 1];
659 extern MMPFNLIST MmStandbyPageListByPriority
[8];
660 extern ULONG MmProductType
;
661 extern MM_SYSTEMSIZE MmSystemSize
;
662 extern PKEVENT MiLowMemoryEvent
;
663 extern PKEVENT MiHighMemoryEvent
;
664 extern PKEVENT MiLowPagedPoolEvent
;
665 extern PKEVENT MiHighPagedPoolEvent
;
666 extern PKEVENT MiLowNonPagedPoolEvent
;
667 extern PKEVENT MiHighNonPagedPoolEvent
;
668 extern PFN_NUMBER MmLowMemoryThreshold
;
669 extern PFN_NUMBER MmHighMemoryThreshold
;
670 extern PFN_NUMBER MiLowPagedPoolThreshold
;
671 extern PFN_NUMBER MiHighPagedPoolThreshold
;
672 extern PFN_NUMBER MiLowNonPagedPoolThreshold
;
673 extern PFN_NUMBER MiHighNonPagedPoolThreshold
;
674 extern PFN_NUMBER MmMinimumFreePages
;
675 extern PFN_NUMBER MmPlentyFreePages
;
676 extern PFN_COUNT MiExpansionPoolPagesInitialCharge
;
677 extern PFN_NUMBER MmResidentAvailablePages
;
678 extern PFN_NUMBER MmResidentAvailableAtInit
;
679 extern ULONG MmTotalFreeSystemPtes
[MaximumPtePoolTypes
];
680 extern PFN_NUMBER MmTotalSystemDriverPages
;
681 extern PVOID MiSessionImageStart
;
682 extern PVOID MiSessionImageEnd
;
683 extern PMMPTE MiHighestUserPte
;
684 extern PMMPDE MiHighestUserPde
;
685 extern PFN_NUMBER MmSystemPageDirectory
[PD_COUNT
];
686 extern PMMPTE MmSharedUserDataPte
;
687 extern LIST_ENTRY MmProcessList
;
688 extern BOOLEAN MmZeroingPageThreadActive
;
689 extern KEVENT MmZeroingPageEvent
;
690 extern ULONG MmSystemPageColor
;
691 extern ULONG MmProcessColorSeed
;
692 extern PMMWSL MmWorkingSetList
;
693 extern PFN_NUMBER MiNumberOfFreePages
;
694 extern SIZE_T MmSessionViewSize
;
695 extern SIZE_T MmSessionPoolSize
;
696 extern SIZE_T MmSessionImageSize
;
697 extern PVOID MiSystemViewStart
;
698 extern PVOID MiSessionPoolEnd
; // 0xBE000000
699 extern PVOID MiSessionPoolStart
; // 0xBD000000
700 extern PVOID MiSessionViewStart
; // 0xBE000000
701 extern PVOID MiSessionSpaceWs
;
702 extern ULONG MmMaximumDeadKernelStacks
;
703 extern SLIST_HEADER MmDeadStackSListHead
;
704 extern MM_AVL_TABLE MmSectionBasedRoot
;
705 extern KGUARDED_MUTEX MmSectionBasedMutex
;
706 extern PVOID MmHighSectionBase
;
707 extern SIZE_T MmSystemLockPagesCount
;
708 extern ULONG_PTR MmSubsectionBase
;
712 MiIsMemoryTypeFree(TYPE_OF_MEMORY MemoryType
)
714 return ((MemoryType
== LoaderFree
) ||
715 (MemoryType
== LoaderLoadedProgram
) ||
716 (MemoryType
== LoaderFirmwareTemporary
) ||
717 (MemoryType
== LoaderOsloaderStack
));
722 MiIsMemoryTypeInvisible(TYPE_OF_MEMORY MemoryType
)
724 return ((MemoryType
== LoaderFirmwarePermanent
) ||
725 (MemoryType
== LoaderSpecialMemory
) ||
726 (MemoryType
== LoaderHALCachedMemory
) ||
727 (MemoryType
== LoaderBBTMemory
));
733 MiIsUserPxe(PVOID Address
)
735 return ((ULONG_PTR
)Address
>> 7) == 0x1FFFFEDF6FB7DA0ULL
;
740 MiIsUserPpe(PVOID Address
)
742 return ((ULONG_PTR
)Address
>> 16) == 0xFFFFF6FB7DA0ULL
;
747 MiIsUserPde(PVOID Address
)
749 return ((ULONG_PTR
)Address
>> 25) == 0x7FFFFB7DA0ULL
;
754 MiIsUserPte(PVOID Address
)
756 return ((ULONG_PTR
)Address
>> 34) == 0x3FFFFDA0ULL
;
761 MiIsUserPde(PVOID Address
)
763 return ((Address
>= (PVOID
)MiAddressToPde(NULL
)) &&
764 (Address
<= (PVOID
)MiHighestUserPde
));
769 MiIsUserPte(PVOID Address
)
771 return (Address
<= (PVOID
)MiHighestUserPte
);
776 // Figures out the hardware bits for a PTE
780 MiDetermineUserGlobalPteMask(IN PVOID PointerPte
)
787 /* Make it valid and accessed */
788 TempPte
.u
.Hard
.Valid
= TRUE
;
789 MI_MAKE_ACCESSED_PAGE(&TempPte
);
791 /* Is this for user-mode? */
793 #if (_MI_PAGING_LEVELS == 4)
794 MiIsUserPxe(PointerPte
) ||
796 #if (_MI_PAGING_LEVELS >= 3)
797 MiIsUserPpe(PointerPte
) ||
799 MiIsUserPde(PointerPte
) ||
800 MiIsUserPte(PointerPte
))
802 /* Set the owner bit */
803 MI_MAKE_OWNER_PAGE(&TempPte
);
806 /* FIXME: We should also set the global bit */
808 /* Return the protection */
809 return TempPte
.u
.Long
;
813 // Creates a valid kernel PTE with the given protection
817 MI_MAKE_HARDWARE_PTE_KERNEL(IN PMMPTE NewPte
,
818 IN PMMPTE MappingPte
,
819 IN ULONG_PTR ProtectionMask
,
820 IN PFN_NUMBER PageFrameNumber
)
822 /* Only valid for kernel, non-session PTEs */
823 ASSERT(MappingPte
> MiHighestUserPte
);
824 ASSERT(!MI_IS_SESSION_PTE(MappingPte
));
825 ASSERT((MappingPte
< (PMMPTE
)PDE_BASE
) || (MappingPte
> (PMMPTE
)PDE_TOP
));
828 *NewPte
= ValidKernelPte
;
830 /* Set the protection and page */
831 NewPte
->u
.Hard
.PageFrameNumber
= PageFrameNumber
;
832 NewPte
->u
.Long
|= MmProtectToPteMask
[ProtectionMask
];
836 // Creates a valid PTE with the given protection
840 MI_MAKE_HARDWARE_PTE(IN PMMPTE NewPte
,
841 IN PMMPTE MappingPte
,
842 IN ULONG_PTR ProtectionMask
,
843 IN PFN_NUMBER PageFrameNumber
)
845 /* Set the protection and page */
846 NewPte
->u
.Long
= MiDetermineUserGlobalPteMask(MappingPte
);
847 NewPte
->u
.Long
|= MmProtectToPteMask
[ProtectionMask
];
848 NewPte
->u
.Hard
.PageFrameNumber
= PageFrameNumber
;
852 // Creates a valid user PTE with the given protection
856 MI_MAKE_HARDWARE_PTE_USER(IN PMMPTE NewPte
,
857 IN PMMPTE MappingPte
,
858 IN ULONG_PTR ProtectionMask
,
859 IN PFN_NUMBER PageFrameNumber
)
861 /* Only valid for kernel, non-session PTEs */
862 ASSERT(MappingPte
<= MiHighestUserPte
);
865 *NewPte
= ValidKernelPte
;
867 /* Set the protection and page */
868 NewPte
->u
.Hard
.Owner
= TRUE
;
869 NewPte
->u
.Hard
.PageFrameNumber
= PageFrameNumber
;
870 NewPte
->u
.Long
|= MmProtectToPteMask
[ProtectionMask
];
875 // Builds a Prototype PTE for the address of the PTE
879 MI_MAKE_PROTOTYPE_PTE(IN PMMPTE NewPte
,
880 IN PMMPTE PointerPte
)
884 /* Mark this as a prototype */
886 NewPte
->u
.Proto
.Prototype
= 1;
889 * Prototype PTEs are only valid in paged pool by design, this little trick
890 * lets us only use 30 bits for the adress of the PTE, as long as the area
891 * stays 1024MB At most.
893 Offset
= (ULONG_PTR
)PointerPte
- (ULONG_PTR
)MmPagedPoolStart
;
896 * 7 bits go in the "low" (but we assume the bottom 2 are zero)
897 * and the other 21 bits go in the "high"
899 NewPte
->u
.Proto
.ProtoAddressLow
= (Offset
& 0x1FC) >> 2;
900 NewPte
->u
.Proto
.ProtoAddressHigh
= (Offset
& 0x3FFFFE00) >> 9;
904 // Builds a Subsection PTE for the address of the Segment
908 MI_MAKE_SUBSECTION_PTE(IN PMMPTE NewPte
,
913 /* Mark this as a prototype */
915 NewPte
->u
.Subsect
.Prototype
= 1;
918 * Segments are only valid either in nonpaged pool. We store the 20 bit
919 * difference either from the top or bottom of nonpaged pool, giving a
920 * maximum of 128MB to each delta, meaning nonpaged pool cannot exceed
923 if ((ULONG_PTR
)Segment
< ((ULONG_PTR
)MmSubsectionBase
+ (128 * _1MB
)))
925 Offset
= (ULONG_PTR
)Segment
- (ULONG_PTR
)MmSubsectionBase
;
926 NewPte
->u
.Subsect
.WhichPool
= PagedPool
;
930 Offset
= (ULONG_PTR
)MmNonPagedPoolEnd
- (ULONG_PTR
)Segment
;
931 NewPte
->u
.Subsect
.WhichPool
= NonPagedPool
;
935 * 4 bits go in the "low" (but we assume the bottom 3 are zero)
936 * and the other 20 bits go in the "high"
938 NewPte
->u
.Subsect
.SubsectionAddressLow
= (Offset
& 0x78) >> 3;
939 NewPte
->u
.Subsect
.SubsectionAddressHigh
= (Offset
& 0xFFFFF80) >> 7;
945 // Returns if the page is physically resident (ie: a large page)
946 // FIXFIX: CISC/x86 only?
950 MI_IS_PHYSICAL_ADDRESS(IN PVOID Address
)
954 /* Large pages are never paged out, always physically resident */
955 PointerPde
= MiAddressToPde(Address
);
956 return ((PointerPde
->u
.Hard
.LargePage
) && (PointerPde
->u
.Hard
.Valid
));
960 // Writes a valid PTE
964 MI_WRITE_VALID_PTE(IN PMMPTE PointerPte
,
967 /* Write the valid PTE */
968 ASSERT(PointerPte
->u
.Hard
.Valid
== 0);
969 ASSERT(TempPte
.u
.Hard
.Valid
== 1);
970 *PointerPte
= TempPte
;
974 // Writes an invalid PTE
978 MI_WRITE_INVALID_PTE(IN PMMPTE PointerPte
,
981 /* Write the invalid PTE */
982 ASSERT(InvalidPte
.u
.Hard
.Valid
== 0);
983 *PointerPte
= InvalidPte
;
987 // Writes a valid PDE
991 MI_WRITE_VALID_PDE(IN PMMPDE PointerPde
,
994 /* Write the valid PDE */
995 ASSERT(PointerPde
->u
.Hard
.Valid
== 0);
996 ASSERT(TempPde
.u
.Hard
.Valid
== 1);
997 *PointerPde
= TempPde
;
1001 // Writes an invalid PDE
1005 MI_WRITE_INVALID_PDE(IN PMMPDE PointerPde
,
1006 IN MMPDE InvalidPde
)
1008 /* Write the invalid PDE */
1009 ASSERT(InvalidPde
.u
.Hard
.Valid
== 0);
1010 *PointerPde
= InvalidPde
;
1014 // Checks if the thread already owns a working set
1018 MM_ANY_WS_LOCK_HELD(IN PETHREAD Thread
)
1020 /* If any of these are held, return TRUE */
1021 return ((Thread
->OwnsProcessWorkingSetExclusive
) ||
1022 (Thread
->OwnsProcessWorkingSetShared
) ||
1023 (Thread
->OwnsSystemWorkingSetExclusive
) ||
1024 (Thread
->OwnsSystemWorkingSetShared
) ||
1025 (Thread
->OwnsSessionWorkingSetExclusive
) ||
1026 (Thread
->OwnsSessionWorkingSetShared
));
1030 // Checks if the process owns the working set lock
1034 MI_WS_OWNER(IN PEPROCESS Process
)
1036 /* Check if this process is the owner, and that the thread owns the WS */
1037 return ((KeGetCurrentThread()->ApcState
.Process
== &Process
->Pcb
) &&
1038 ((PsGetCurrentThread()->OwnsProcessWorkingSetExclusive
) ||
1039 (PsGetCurrentThread()->OwnsProcessWorkingSetShared
)));
1043 // New ARM3<->RosMM PAGE Architecture
1047 MiIsRosSectionObject(IN PVOID Section
)
1049 PROS_SECTION_OBJECT RosSection
= Section
;
1050 if ((RosSection
->Type
== 'SC') && (RosSection
->Size
== 'TN')) return TRUE
;
1055 // HACK ON TOP OF HACK ALERT!!!
1056 #define MI_GET_ROS_DATA(x) \
1057 (((x)->RosMmData == 0) ? NULL : ((PMMROSPFN)((ULONG64)(ULONG)((x)->RosMmData) | \
1058 ((ULONG64)MmNonPagedPoolStart & 0xffffffff00000000ULL))))
1060 #define MI_GET_ROS_DATA(x) ((PMMROSPFN)(x->RosMmData))
1062 #define MI_IS_ROS_PFN(x) (((x)->u4.AweAllocation == TRUE) && (MI_GET_ROS_DATA(x) != NULL))
1063 #define ASSERT_IS_ROS_PFN(x) ASSERT(MI_IS_ROS_PFN(x) == TRUE);
1064 typedef struct _MMROSPFN
1066 PMM_RMAP_ENTRY RmapListHead
;
1067 SWAPENTRY SwapEntry
;
1068 } MMROSPFN
, *PMMROSPFN
;
1070 #define RosMmData AweReferenceCount
1074 MiDecrementReferenceCount(
1076 IN PFN_NUMBER PageFrameIndex
1080 // Locks the working set for the given process
1084 MiLockProcessWorkingSet(IN PEPROCESS Process
,
1087 /* Shouldn't already be owning the process working set */
1088 ASSERT(Thread
->OwnsProcessWorkingSetShared
== FALSE
);
1089 ASSERT(Thread
->OwnsProcessWorkingSetExclusive
== FALSE
);
1091 /* Block APCs, make sure that still nothing is already held */
1092 KeEnterGuardedRegion();
1093 ASSERT(!MM_ANY_WS_LOCK_HELD(Thread
));
1095 /* FIXME: Actually lock it (we can't because Vm is used by MAREAs) */
1097 /* FIXME: This also can't be checked because Vm is used by MAREAs) */
1098 //ASSERT(Process->Vm.Flags.AcquiredUnsafe == 0);
1100 /* Okay, now we can own it exclusively */
1101 Thread
->OwnsProcessWorkingSetExclusive
= TRUE
;
1105 // Unlocks the working set for the given process
1109 MiUnlockProcessWorkingSet(IN PEPROCESS Process
,
1112 /* Make sure this process really is owner, and it was a safe acquisition */
1113 ASSERT(MI_WS_OWNER(Process
));
1114 /* This can't be checked because Vm is used by MAREAs) */
1115 //ASSERT(Process->Vm.Flags.AcquiredUnsafe == 0);
1117 /* The thread doesn't own it anymore */
1118 ASSERT(Thread
->OwnsProcessWorkingSetExclusive
== TRUE
);
1119 Thread
->OwnsProcessWorkingSetExclusive
= FALSE
;
1121 /* FIXME: Actually release it (we can't because Vm is used by MAREAs) */
1124 KeLeaveGuardedRegion();
1128 // Locks the working set
1132 MiLockWorkingSet(IN PETHREAD Thread
,
1133 IN PMMSUPPORT WorkingSet
)
1136 KeEnterGuardedRegion();
1138 /* Working set should be in global memory */
1139 ASSERT(MI_IS_SESSION_ADDRESS((PVOID
)WorkingSet
) == FALSE
);
1141 /* Thread shouldn't already be owning something */
1142 ASSERT(!MM_ANY_WS_LOCK_HELD(Thread
));
1144 /* FIXME: Actually lock it (we can't because Vm is used by MAREAs) */
1146 /* Which working set is this? */
1147 if (WorkingSet
== &MmSystemCacheWs
)
1149 /* Own the system working set */
1150 ASSERT((Thread
->OwnsSystemWorkingSetExclusive
== FALSE
) &&
1151 (Thread
->OwnsSystemWorkingSetShared
== FALSE
));
1152 Thread
->OwnsSystemWorkingSetExclusive
= TRUE
;
1154 else if (WorkingSet
->Flags
.SessionSpace
)
1156 /* Own the session working set */
1157 ASSERT((Thread
->OwnsSessionWorkingSetExclusive
== FALSE
) &&
1158 (Thread
->OwnsSessionWorkingSetShared
== FALSE
));
1159 Thread
->OwnsSessionWorkingSetExclusive
= TRUE
;
1163 /* Own the process working set */
1164 ASSERT((Thread
->OwnsProcessWorkingSetExclusive
== FALSE
) &&
1165 (Thread
->OwnsProcessWorkingSetShared
== FALSE
));
1166 Thread
->OwnsProcessWorkingSetExclusive
= TRUE
;
1171 // Unlocks the working set
1175 MiUnlockWorkingSet(IN PETHREAD Thread
,
1176 IN PMMSUPPORT WorkingSet
)
1178 /* Working set should be in global memory */
1179 ASSERT(MI_IS_SESSION_ADDRESS((PVOID
)WorkingSet
) == FALSE
);
1181 /* Which working set is this? */
1182 if (WorkingSet
== &MmSystemCacheWs
)
1184 /* Release the system working set */
1185 ASSERT((Thread
->OwnsSystemWorkingSetExclusive
== TRUE
) ||
1186 (Thread
->OwnsSystemWorkingSetShared
== TRUE
));
1187 Thread
->OwnsSystemWorkingSetExclusive
= FALSE
;
1189 else if (WorkingSet
->Flags
.SessionSpace
)
1191 /* Release the session working set */
1192 ASSERT((Thread
->OwnsSessionWorkingSetExclusive
== TRUE
) ||
1193 (Thread
->OwnsSessionWorkingSetShared
== TRUE
));
1194 Thread
->OwnsSessionWorkingSetExclusive
= 0;
1198 /* Release the process working set */
1199 ASSERT((Thread
->OwnsProcessWorkingSetExclusive
) ||
1200 (Thread
->OwnsProcessWorkingSetShared
));
1201 Thread
->OwnsProcessWorkingSetExclusive
= FALSE
;
1204 /* FIXME: Actually release it (we can't because Vm is used by MAREAs) */
1207 KeLeaveGuardedRegion();
1211 // Returns the ProtoPTE inside a VAD for the given VPN
1215 MI_GET_PROTOTYPE_PTE_FOR_VPN(IN PMMVAD Vad
,
1220 /* Find the offset within the VAD's prototype PTEs */
1221 ProtoPte
= Vad
->FirstPrototypePte
+ (Vpn
- Vad
->StartingVpn
);
1222 ASSERT(ProtoPte
<= Vad
->LastContiguousPte
);
1227 // Returns the PFN Database entry for the given page number
1228 // Warning: This is not necessarily a valid PFN database entry!
1232 MI_PFN_ELEMENT(IN PFN_NUMBER Pfn
)
1235 return &MmPfnDatabase
[Pfn
];
1239 // Drops a locked page without dereferencing it
1243 MiDropLockCount(IN PMMPFN Pfn1
)
1245 /* This page shouldn't be locked, but it should be valid */
1246 ASSERT(Pfn1
->u3
.e2
.ReferenceCount
!= 0);
1247 ASSERT(Pfn1
->u2
.ShareCount
== 0);
1249 /* Is this the last reference to the page */
1250 if (Pfn1
->u3
.e2
.ReferenceCount
== 1)
1252 /* It better not be valid */
1253 ASSERT(Pfn1
->u3
.e1
.PageLocation
!= ActiveAndValid
);
1255 /* Is it a prototype PTE? */
1256 if ((Pfn1
->u3
.e1
.PrototypePte
== 1) &&
1257 (Pfn1
->OriginalPte
.u
.Soft
.Prototype
== 1))
1259 /* We don't handle this */
1263 /* Update the counter */
1264 InterlockedDecrementSizeT(&MmSystemLockPagesCount
);
1269 // Drops a locked page and dereferences it
1273 MiDereferencePfnAndDropLockCount(IN PMMPFN Pfn1
)
1275 USHORT RefCount
, OldRefCount
;
1276 PFN_NUMBER PageFrameIndex
;
1278 /* Loop while we decrement the page successfully */
1281 /* There should be at least one reference */
1282 OldRefCount
= Pfn1
->u3
.e2
.ReferenceCount
;
1283 ASSERT(OldRefCount
!= 0);
1285 /* Are we the last one */
1286 if (OldRefCount
== 1)
1288 /* The page shoudln't be shared not active at this point */
1289 ASSERT(Pfn1
->u3
.e2
.ReferenceCount
== 1);
1290 ASSERT(Pfn1
->u3
.e1
.PageLocation
!= ActiveAndValid
);
1291 ASSERT(Pfn1
->u2
.ShareCount
== 0);
1293 /* Is it a prototype PTE? */
1294 if ((Pfn1
->u3
.e1
.PrototypePte
== 1) &&
1295 (Pfn1
->OriginalPte
.u
.Soft
.Prototype
== 1))
1297 /* We don't handle this */
1301 /* Update the counter, and drop a reference the long way */
1302 InterlockedDecrementSizeT(&MmSystemLockPagesCount
);
1303 PageFrameIndex
= MiGetPfnEntryIndex(Pfn1
);
1304 MiDecrementReferenceCount(Pfn1
, PageFrameIndex
);
1308 /* Drop a reference the short way, and that's it */
1309 RefCount
= InterlockedCompareExchange16((PSHORT
)&Pfn1
->u3
.e2
.ReferenceCount
,
1312 ASSERT(RefCount
!= 0);
1313 } while (OldRefCount
!= RefCount
);
1315 /* If we got here, there should be more than one reference */
1316 ASSERT(RefCount
> 1);
1319 /* Is it still being shared? */
1320 if (Pfn1
->u2
.ShareCount
>= 1)
1322 /* Then it should be valid */
1323 ASSERT(Pfn1
->u3
.e1
.PageLocation
== ActiveAndValid
);
1325 /* Is it a prototype PTE? */
1326 if ((Pfn1
->u3
.e1
.PrototypePte
== 1) &&
1327 (Pfn1
->OriginalPte
.u
.Soft
.Prototype
== 1))
1329 /* We don't handle ethis */
1333 /* Update the counter */
1334 InterlockedDecrementSizeT(&MmSystemLockPagesCount
);
1340 // References a locked page and updates the counter
1341 // Used in MmProbeAndLockPages to handle different edge cases
1345 MiReferenceProbedPageAndBumpLockCount(IN PMMPFN Pfn1
)
1347 USHORT RefCount
, OldRefCount
;
1350 ASSERT(Pfn1
->u3
.e2
.ReferenceCount
!= 0);
1352 /* Does ARM3 own the page? */
1353 if (MI_IS_ROS_PFN(Pfn1
))
1355 /* ReactOS Mm doesn't track share count */
1356 ASSERT(Pfn1
->u3
.e1
.PageLocation
== ActiveAndValid
);
1360 /* On ARM3 pages, we should see a valid share count */
1361 ASSERT((Pfn1
->u2
.ShareCount
!= 0) && (Pfn1
->u3
.e1
.PageLocation
== ActiveAndValid
));
1363 /* We don't support mapping a prototype page yet */
1364 ASSERT((Pfn1
->u3
.e1
.PrototypePte
== 0) && (Pfn1
->OriginalPte
.u
.Soft
.Prototype
== 0));
1367 /* More locked pages! */
1368 InterlockedIncrementSizeT(&MmSystemLockPagesCount
);
1370 /* Loop trying to update the reference count */
1373 /* Get the current reference count, make sure it's valid */
1374 OldRefCount
= Pfn1
->u3
.e2
.ReferenceCount
;
1375 ASSERT(OldRefCount
!= 0);
1376 ASSERT(OldRefCount
< 2500);
1378 /* Bump it up by one */
1379 RefCount
= InterlockedCompareExchange16((PSHORT
)&Pfn1
->u3
.e2
.ReferenceCount
,
1382 ASSERT(RefCount
!= 0);
1383 } while (OldRefCount
!= RefCount
);
1385 /* Was this the first lock attempt? If not, undo our bump */
1386 if (OldRefCount
!= 1) InterlockedDecrementSizeT(&MmSystemLockPagesCount
);
1390 // References a locked page and updates the counter
1391 // Used in all other cases except MmProbeAndLockPages
1395 MiReferenceUsedPageAndBumpLockCount(IN PMMPFN Pfn1
)
1399 /* Is it a prototype PTE? */
1400 if ((Pfn1
->u3
.e1
.PrototypePte
== 1) &&
1401 (Pfn1
->OriginalPte
.u
.Soft
.Prototype
== 1))
1403 /* We don't handle this */
1407 /* More locked pages! */
1408 InterlockedIncrementSizeT(&MmSystemLockPagesCount
);
1410 /* Update the reference count */
1411 NewRefCount
= InterlockedIncrement16((PSHORT
)&Pfn1
->u3
.e2
.ReferenceCount
);
1412 if (NewRefCount
== 2)
1414 /* Is it locked or shared? */
1415 if (Pfn1
->u2
.ShareCount
)
1417 /* It's shared, so make sure it's active */
1418 ASSERT(Pfn1
->u3
.e1
.PageLocation
== ActiveAndValid
);
1422 /* It's locked, so we shouldn't lock again */
1423 InterlockedDecrementSizeT(&MmSystemLockPagesCount
);
1428 /* Someone had already locked the page, so undo our bump */
1429 ASSERT(NewRefCount
< 2500);
1430 InterlockedDecrementSizeT(&MmSystemLockPagesCount
);
1435 // References a locked page and updates the counter
1436 // Used in all other cases except MmProbeAndLockPages
1440 MiReferenceUnusedPageAndBumpLockCount(IN PMMPFN Pfn1
)
1444 /* Make sure the page isn't used yet */
1445 ASSERT(Pfn1
->u2
.ShareCount
== 0);
1446 ASSERT(Pfn1
->u3
.e1
.PageLocation
!= ActiveAndValid
);
1448 /* Is it a prototype PTE? */
1449 if ((Pfn1
->u3
.e1
.PrototypePte
== 1) &&
1450 (Pfn1
->OriginalPte
.u
.Soft
.Prototype
== 1))
1452 /* We don't handle this */
1456 /* More locked pages! */
1457 InterlockedIncrementSizeT(&MmSystemLockPagesCount
);
1459 /* Update the reference count */
1460 NewRefCount
= InterlockedIncrement16((PSHORT
)&Pfn1
->u3
.e2
.ReferenceCount
);
1461 if (NewRefCount
!= 1)
1463 /* Someone had already locked the page, so undo our bump */
1464 ASSERT(NewRefCount
< 2500);
1465 InterlockedDecrementSizeT(&MmSystemLockPagesCount
);
1473 IN PLOADER_PARAMETER_BLOCK LoaderBlock
1478 MiInitializeSessionSpaceLayout();
1482 MiInitMachineDependent(
1483 IN PLOADER_PARAMETER_BLOCK LoaderBlock
1488 MiComputeColorInformation(
1495 IN PLOADER_PARAMETER_BLOCK LoaderBlock
1500 MiInitializeColorTables(
1506 MiInitializePfnDatabase(
1507 IN PLOADER_PARAMETER_BLOCK LoaderBlock
1512 MiInitializeSessionIds(
1518 MiInitializeMemoryEvents(
1525 IN PFN_NUMBER PageCount
1528 PPHYSICAL_MEMORY_DESCRIPTOR
1530 MmInitializeMemoryLimits(
1531 IN PLOADER_PARAMETER_BLOCK LoaderBlock
,
1532 IN PBOOLEAN IncludeType
1537 MiPagesInLoaderBlock(
1538 IN PLOADER_PARAMETER_BLOCK LoaderBlock
,
1539 IN PBOOLEAN IncludeType
1545 IN PVOID AddressStart
,
1551 MiRosProtectVirtualMemory(
1552 IN PEPROCESS Process
,
1553 IN OUT PVOID
*BaseAddress
,
1554 IN OUT PSIZE_T NumberOfBytesToProtect
,
1555 IN ULONG NewAccessProtection
,
1556 OUT PULONG OldAccessProtection OPTIONAL
1562 IN BOOLEAN StoreInstruction
,
1564 IN KPROCESSOR_MODE Mode
,
1565 IN PVOID TrapInformation
1570 MiCheckPdeForPagedPool(
1576 MiInitializeNonPagedPool(
1582 MiInitializeNonPagedPoolThresholds(
1588 MiInitializePoolEvents(
1595 IN POOL_TYPE PoolType
,// FIXFIX: This should go in ex.h after the pool merge
1596 IN ULONG Threshold
//
1599 // FIXFIX: THIS ONE TOO
1603 ExInitializePoolDescriptor(
1604 IN PPOOL_DESCRIPTOR PoolDescriptor
,
1605 IN POOL_TYPE PoolType
,
1613 MiInitializeSessionPool(
1619 MiInitializeSystemPtes(
1620 IN PMMPTE StartingPte
,
1621 IN ULONG NumberOfPtes
,
1622 IN MMSYSTEM_PTE_POOL_TYPE PoolType
1627 MiReserveSystemPtes(
1628 IN ULONG NumberOfPtes
,
1629 IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType
1634 MiReleaseSystemPtes(
1635 IN PMMPTE StartingPte
,
1636 IN ULONG NumberOfPtes
,
1637 IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType
1643 MiFindContiguousPages(
1644 IN PFN_NUMBER LowestPfn
,
1645 IN PFN_NUMBER HighestPfn
,
1646 IN PFN_NUMBER BoundaryPfn
,
1647 IN PFN_NUMBER SizeInPages
,
1648 IN MEMORY_CACHING_TYPE CacheType
1653 MiCheckForContiguousMemory(
1654 IN PVOID BaseAddress
,
1655 IN PFN_NUMBER BaseAddressPages
,
1656 IN PFN_NUMBER SizeInPages
,
1657 IN PFN_NUMBER LowestPfn
,
1658 IN PFN_NUMBER HighestPfn
,
1659 IN PFN_NUMBER BoundaryPfn
,
1660 IN MI_PFN_CACHE_ATTRIBUTE CacheAttribute
1665 MiAllocatePagesForMdl(
1666 IN PHYSICAL_ADDRESS LowAddress
,
1667 IN PHYSICAL_ADDRESS HighAddress
,
1668 IN PHYSICAL_ADDRESS SkipBytes
,
1669 IN SIZE_T TotalBytes
,
1670 IN MI_PFN_CACHE_ATTRIBUTE CacheAttribute
,
1676 MiMapLockedPagesInUserSpace(
1679 IN MEMORY_CACHING_TYPE CacheType
,
1680 IN PVOID BaseAddress
1685 MiUnmapLockedPagesInUserSpace(
1686 IN PVOID BaseAddress
,
1693 IN PMMPFNLIST ListHead
,
1694 IN PFN_NUMBER PageFrameIndex
1699 MiUnlinkFreeOrZeroedPage(
1705 MiUnlinkPageFromList(
1712 IN PMMPTE PointerPte
,
1719 IN PFN_NUMBER PageFrameIndex
,
1720 IN PMMPTE PointerPte
,
1726 MiInitializeAndChargePfn(
1727 OUT PPFN_NUMBER PageFrameIndex
,
1728 IN PMMPTE PointerPde
,
1729 IN PFN_NUMBER ContainingPageFrame
,
1730 IN BOOLEAN SessionAllocation
1735 MiInitializePfnAndMakePteValid(
1736 IN PFN_NUMBER PageFrameIndex
,
1737 IN PMMPTE PointerPte
,
1743 MiInitializePfnForOtherProcess(
1744 IN PFN_NUMBER PageFrameIndex
,
1745 IN PMMPTE PointerPte
,
1746 IN PFN_NUMBER PteFrame
1751 MiDecrementShareCount(
1753 IN PFN_NUMBER PageFrameIndex
1771 IN PFN_NUMBER PageFrameIndex
1776 MiInsertPageInFreeList(
1777 IN PFN_NUMBER PageFrameIndex
1782 MiDeleteSystemPageableVm(
1783 IN PMMPTE PointerPte
,
1784 IN PFN_NUMBER PageCount
,
1786 OUT PPFN_NUMBER ValidPages
1791 MiGetPageProtection(
1792 IN PMMPTE PointerPte
1795 PLDR_DATA_TABLE_ENTRY
1797 MiLookupDataTableEntry(
1803 MiInitializeDriverLargePageList(
1809 MiInitializeLargePageSupport(
1828 IN PVOID VirtualAddress
1833 MiCheckForConflictingNode(
1834 IN ULONG_PTR StartVpn
,
1835 IN ULONG_PTR EndVpn
,
1836 IN PMM_AVL_TABLE Table
1841 MiFindEmptyAddressRangeDownTree(
1843 IN ULONG_PTR BoundaryAddress
,
1844 IN ULONG_PTR Alignment
,
1845 IN PMM_AVL_TABLE Table
,
1846 OUT PULONG_PTR Base
,
1847 OUT PMMADDRESS_NODE
*Parent
1852 MiFindEmptyAddressRangeDownBasedTree(
1854 IN ULONG_PTR BoundaryAddress
,
1855 IN ULONG_PTR Alignment
,
1856 IN PMM_AVL_TABLE Table
,
1862 MiFindEmptyAddressRangeInTree(
1864 IN ULONG_PTR Alignment
,
1865 IN PMM_AVL_TABLE Table
,
1866 OUT PMMADDRESS_NODE
*PreviousVad
,
1874 IN PEPROCESS Process
1879 MiInsertBasedSection(
1885 MiUnmapViewOfSection(
1886 IN PEPROCESS Process
,
1887 IN PVOID BaseAddress
,
1893 MiRosUnmapViewOfSection(
1894 IN PEPROCESS Process
,
1895 IN PVOID BaseAddress
,
1902 IN PMM_AVL_TABLE Table
,
1903 IN PMMADDRESS_NODE NewNode
,
1904 PMMADDRESS_NODE Parent
,
1905 TABLE_SEARCH_RESULT Result
1911 IN PMMADDRESS_NODE Node
,
1912 IN PMM_AVL_TABLE Table
1918 IN PMMADDRESS_NODE Node
1924 IN PMMADDRESS_NODE Node
1929 MiInitializeSystemSpaceMap(
1930 IN PMMSESSION InputSession OPTIONAL
1935 MiSessionRemoveProcess(
1941 MiReleaseProcessReferenceToSessionDataPage(
1942 IN PMM_SESSION_SPACE SessionGlobal
1947 MiSessionAddProcess(
1948 IN PEPROCESS NewProcess
1953 MiSessionCommitPageTables(
1960 MiMakeProtectionMask(
1966 MiDeleteVirtualAddresses(
1968 IN ULONG_PTR EndingAddress
,
1974 MiMakeSystemAddressValid(
1975 IN PVOID PageTableVirtualAddress
,
1976 IN PEPROCESS CurrentProcess
1981 MiMakeSystemAddressValidPfn(
1982 IN PVOID VirtualAddress
,
1989 IN PEPROCESS CurrentProcess
,
2002 MiQueryMemorySectionName(
2003 IN HANDLE ProcessHandle
,
2004 IN PVOID BaseAddress
,
2005 OUT PVOID MemoryInformation
,
2006 IN SIZE_T MemoryInformationLength
,
2007 OUT PSIZE_T ReturnLength
2012 MiRosAllocateVirtualMemory(
2013 IN HANDLE ProcessHandle
,
2014 IN PEPROCESS Process
,
2015 IN PMEMORY_AREA MemoryArea
,
2016 IN PMMSUPPORT AddressSpace
,
2017 IN OUT PVOID
* UBaseAddress
,
2018 IN BOOLEAN Attached
,
2019 IN OUT PSIZE_T URegionSize
,
2020 IN ULONG AllocationType
,
2026 MiRosUnmapViewInSystemSpace(
2032 MmDeterminePoolType(
2033 IN PVOID PoolAddress
2038 MiMakePdeExistAndMakeValid(
2039 IN PMMPTE PointerPde
,
2040 IN PEPROCESS TargetProcess
,
2045 // MiRemoveZeroPage will use inline code to zero out the page manually if only
2046 // free pages are available. In some scenarios, we don't/can't run that piece of
2047 // code and would rather only have a real zero page. If we can't have a zero page,
2048 // then we'd like to have our own code to grab a free page and zero it out, by
2049 // using MiRemoveAnyPage. This macro implements this.
2053 MiRemoveZeroPageSafe(IN ULONG Color
)
2055 if (MmFreePagesByColor
[ZeroedPageList
][Color
].Flink
!= LIST_HEAD
) return MiRemoveZeroPage(Color
);