* Sync up to trunk r55544.
[reactos.git] / ntoskrnl / mm / ARM3 / miarm.h
1 /*
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
7 */
8
9 #ifndef _M_AMD64
10
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_MAX_INIT_NONPAGED_POOL_SIZE (128 * _1MB)
15 #define MI_MAX_NONPAGED_POOL_SIZE (128 * _1MB)
16 #define MI_MAX_FREE_PAGE_LISTS 4
17
18 #define MI_MIN_INIT_PAGED_POOLSIZE (32 * _1MB)
19
20 #define MI_SESSION_VIEW_SIZE (20 * _1MB)
21 #define MI_SESSION_POOL_SIZE (16 * _1MB)
22 #define MI_SESSION_IMAGE_SIZE (8 * _1MB)
23 #define MI_SESSION_WORKING_SET_SIZE (4 * _1MB)
24 #define MI_SESSION_SIZE (MI_SESSION_VIEW_SIZE + \
25 MI_SESSION_POOL_SIZE + \
26 MI_SESSION_IMAGE_SIZE + \
27 MI_SESSION_WORKING_SET_SIZE)
28
29 #define MI_SYSTEM_VIEW_SIZE (16 * _1MB)
30
31 #define MI_HIGHEST_USER_ADDRESS (PVOID)0x7FFEFFFF
32 #define MI_USER_PROBE_ADDRESS (PVOID)0x7FFF0000
33 #define MI_DEFAULT_SYSTEM_RANGE_START (PVOID)0x80000000
34 #define MI_SYSTEM_CACHE_WS_START (PVOID)0xC0C00000
35 #define MI_PAGED_POOL_START (PVOID)0xE1000000
36 #define MI_NONPAGED_POOL_END (PVOID)0xFFBE0000
37 #define MI_DEBUG_MAPPING (PVOID)0xFFBFF000
38
39 #define MI_SYSTEM_PTE_BASE (PVOID)MiAddressToPte(NULL)
40
41 #define MI_MIN_SECONDARY_COLORS 8
42 #define MI_SECONDARY_COLORS 64
43 #define MI_MAX_SECONDARY_COLORS 1024
44
45 #define MI_MIN_ALLOCATION_FRAGMENT (4 * _1KB)
46 #define MI_ALLOCATION_FRAGMENT (64 * _1KB)
47 #define MI_MAX_ALLOCATION_FRAGMENT (2 * _1MB)
48
49 #define MM_HIGHEST_VAD_ADDRESS \
50 (PVOID)((ULONG_PTR)MM_HIGHEST_USER_ADDRESS - (16 * PAGE_SIZE))
51 #define MI_LOWEST_VAD_ADDRESS (PVOID)MM_LOWEST_USER_ADDRESS
52
53 #endif /* !_M_AMD64 */
54
55 /* Make the code cleaner with some definitions for size multiples */
56 #define _1KB (1024u)
57 #define _1MB (1024 * _1KB)
58 #define _1GB (1024 * _1MB)
59
60 /* Everyone loves 64K */
61 #define _64K (64 * _1KB)
62
63 /* Area mapped by a PDE */
64 #define PDE_MAPPED_VA (PTE_COUNT * PAGE_SIZE)
65
66 /* Size of a page table */
67 #define PT_SIZE (PTE_COUNT * sizeof(MMPTE))
68
69 /* Size of a page directory */
70 #define PD_SIZE (PDE_COUNT * sizeof(MMPDE))
71
72 /* Size of all page directories for a process */
73 #define SYSTEM_PD_SIZE (PD_COUNT * PD_SIZE)
74
75 /* Architecture specific count of PDEs in a directory, and count of PTEs in a PT */
76 #ifdef _M_IX86
77 #define PD_COUNT 1
78 #define PDE_COUNT 1024
79 #define PTE_COUNT 1024
80 C_ASSERT(SYSTEM_PD_SIZE == PAGE_SIZE);
81 #define MiIsPteOnPdeBoundary(PointerPte) \
82 ((((ULONG_PTR)PointerPte) & (PAGE_SIZE - 1)) == 0)
83 #elif _M_ARM
84 #define PD_COUNT 1
85 #define PDE_COUNT 4096
86 #define PTE_COUNT 256
87 #else
88 #define PD_COUNT PPE_PER_PAGE
89 #define PDE_COUNT PDE_PER_PAGE
90 #define PTE_COUNT PTE_PER_PAGE
91 #endif
92
93 //
94 // Protection Bits part of the internal memory manager Protection Mask
95 // Taken from http://www.reactos.org/wiki/Techwiki:Memory_management_in_the_Windows_XP_kernel
96 // and public assertions.
97 //
98 #define MM_ZERO_ACCESS 0
99 #define MM_READONLY 1
100 #define MM_EXECUTE 2
101 #define MM_EXECUTE_READ 3
102 #define MM_READWRITE 4
103 #define MM_WRITECOPY 5
104 #define MM_EXECUTE_READWRITE 6
105 #define MM_EXECUTE_WRITECOPY 7
106 #define MM_NOCACHE 8
107 #define MM_DECOMMIT 0x10
108 #define MM_NOACCESS (MM_DECOMMIT | MM_NOCACHE)
109 #define MM_INVALID_PROTECTION 0xFFFFFFFF
110
111 //
112 // Specific PTE Definitions that map to the Memory Manager's Protection Mask Bits
113 // The Memory Manager's definition define the attributes that must be preserved
114 // and these PTE definitions describe the attributes in the hardware sense. This
115 // helps deal with hardware differences between the actual boolean expression of
116 // the argument.
117 //
118 // For example, in the logical attributes, we want to express read-only as a flag
119 // but on x86, it is writability that must be set. On the other hand, on x86, just
120 // like in the kernel, it is disabling the caches that requires a special flag,
121 // while on certain architectures such as ARM, it is enabling the cache which
122 // requires a flag.
123 //
124 #if defined(_M_IX86) || defined(_M_AMD64)
125 //
126 // Access Flags
127 //
128 #define PTE_READONLY 0 // Doesn't exist on x86
129 #define PTE_EXECUTE 0 // Not worrying about NX yet
130 #define PTE_EXECUTE_READ 0 // Not worrying about NX yet
131 #define PTE_READWRITE 0x2
132 #define PTE_WRITECOPY 0x200
133 #define PTE_EXECUTE_READWRITE 0x2 // Not worrying about NX yet
134 #define PTE_EXECUTE_WRITECOPY 0x200
135 #define PTE_PROTOTYPE 0x400
136
137 //
138 // State Flags
139 //
140 #define PTE_VALID 0x1
141 #define PTE_ACCESSED 0x20
142 #define PTE_DIRTY 0x40
143
144 //
145 // Cache flags
146 //
147 #define PTE_ENABLE_CACHE 0
148 #define PTE_DISABLE_CACHE 0x10
149 #define PTE_WRITECOMBINED_CACHE 0x10
150 #elif defined(_M_ARM)
151 #define PTE_READONLY 0x200
152 #define PTE_EXECUTE 0 // Not worrying about NX yet
153 #define PTE_EXECUTE_READ 0 // Not worrying about NX yet
154 #define PTE_READWRITE 0 // Doesn't exist on ARM
155 #define PTE_WRITECOPY 0 // Doesn't exist on ARM
156 #define PTE_EXECUTE_READWRITE 0 // Not worrying about NX yet
157 #define PTE_EXECUTE_WRITECOPY 0 // Not worrying about NX yet
158 #define PTE_PROTOTYPE 0x400 // Using the Shared bit
159 //
160 // Cache flags
161 //
162 #define PTE_ENABLE_CACHE 0
163 #define PTE_DISABLE_CACHE 0x10
164 #define PTE_WRITECOMBINED_CACHE 0x10
165 #else
166 #error Define these please!
167 #endif
168
169 extern const ULONG_PTR MmProtectToPteMask[32];
170 extern const ULONG MmProtectToValue[32];
171
172 //
173 // Assertions for session images, addresses, and PTEs
174 //
175 #define MI_IS_SESSION_IMAGE_ADDRESS(Address) \
176 (((Address) >= MiSessionImageStart) && ((Address) < MiSessionImageEnd))
177
178 #define MI_IS_SESSION_ADDRESS(Address) \
179 (((Address) >= MmSessionBase) && ((Address) < MiSessionSpaceEnd))
180
181 #define MI_IS_SESSION_PTE(Pte) \
182 ((((PMMPTE)Pte) >= MiSessionBasePte) && (((PMMPTE)Pte) < MiSessionLastPte))
183
184 #define MI_IS_PAGE_TABLE_ADDRESS(Address) \
185 (((PVOID)(Address) >= (PVOID)PTE_BASE) && ((PVOID)(Address) <= (PVOID)PTE_TOP))
186
187 #define MI_IS_SYSTEM_PAGE_TABLE_ADDRESS(Address) \
188 (((Address) >= (PVOID)MiAddressToPte(MmSystemRangeStart)) && ((Address) <= (PVOID)PTE_TOP))
189
190 #define MI_IS_PAGE_TABLE_OR_HYPER_ADDRESS(Address) \
191 (((PVOID)(Address) >= (PVOID)PTE_BASE) && ((PVOID)(Address) <= (PVOID)MmHyperSpaceEnd))
192
193 //
194 // Corresponds to MMPTE_SOFTWARE.Protection
195 //
196 #ifdef _M_IX86
197 #define MM_PTE_SOFTWARE_PROTECTION_BITS 5
198 #elif _M_ARM
199 #define MM_PTE_SOFTWARE_PROTECTION_BITS 6
200 #elif _M_AMD64
201 #define MM_PTE_SOFTWARE_PROTECTION_BITS 5
202 #else
203 #error Define these please!
204 #endif
205
206 //
207 // Creates a software PTE with the given protection
208 //
209 #define MI_MAKE_SOFTWARE_PTE(p, x) ((p)->u.Long = (x << MM_PTE_SOFTWARE_PROTECTION_BITS))
210
211 //
212 // Marks a PTE as deleted
213 //
214 #define MI_SET_PFN_DELETED(x) ((x)->PteAddress = (PMMPTE)((ULONG_PTR)(x)->PteAddress | 1))
215 #define MI_IS_PFN_DELETED(x) ((ULONG_PTR)((x)->PteAddress) & 1)
216
217 //
218 // Special values for LoadedImports
219 //
220 #define MM_SYSLDR_NO_IMPORTS (PVOID)0xFFFFFFFE
221 #define MM_SYSLDR_BOOT_LOADED (PVOID)0xFFFFFFFF
222 #define MM_SYSLDR_SINGLE_ENTRY 0x1
223
224 #if defined(_M_IX86) || defined(_M_ARM)
225 //
226 // PFN List Sentinel
227 //
228 #define LIST_HEAD 0xFFFFFFFF
229
230 //
231 // Because GCC cannot automatically downcast 0xFFFFFFFF to lesser-width bits,
232 // we need a manual definition suited to the number of bits in the PteFrame.
233 // This is used as a LIST_HEAD for the colored list
234 //
235 #define COLORED_LIST_HEAD ((1 << 25) - 1) // 0x1FFFFFF
236 #elif defined(_M_AMD64)
237 #define LIST_HEAD 0xFFFFFFFFFFFFFFFFLL
238 #define COLORED_LIST_HEAD ((1ULL << 57) - 1) // 0x1FFFFFFFFFFFFFFLL
239 #else
240 #error Define these please!
241 #endif
242
243 //
244 // Special IRQL value (found in assertions)
245 //
246 #define MM_NOIRQL (KIRQL)0xFFFFFFFF
247
248 //
249 // Returns the color of a page
250 //
251 #define MI_GET_PAGE_COLOR(x) ((x) & MmSecondaryColorMask)
252 #define MI_GET_NEXT_COLOR() (MI_GET_PAGE_COLOR(++MmSystemPageColor))
253 #define MI_GET_NEXT_PROCESS_COLOR(x) (MI_GET_PAGE_COLOR(++(x)->NextPageColor))
254
255 #ifndef _M_AMD64
256 //
257 // Decodes a Prototype PTE into the underlying PTE
258 //
259 #define MiProtoPteToPte(x) \
260 (PMMPTE)((ULONG_PTR)MmPagedPoolStart + \
261 (((x)->u.Proto.ProtoAddressHigh << 7) | (x)->u.Proto.ProtoAddressLow))
262 #endif
263
264 //
265 // Prototype PTEs that don't yet have a pagefile association
266 //
267 #ifdef _M_AMD64
268 #define MI_PTE_LOOKUP_NEEDED 0xffffffffULL
269 #else
270 #define MI_PTE_LOOKUP_NEEDED 0xFFFFF
271 #endif
272
273 //
274 // System views are binned into 64K chunks
275 //
276 #define MI_SYSTEM_VIEW_BUCKET_SIZE _64K
277
278 //
279 // FIXFIX: These should go in ex.h after the pool merge
280 //
281 #ifdef _M_AMD64
282 #define POOL_BLOCK_SIZE 16
283 #else
284 #define POOL_BLOCK_SIZE 8
285 #endif
286 #define POOL_LISTS_PER_PAGE (PAGE_SIZE / POOL_BLOCK_SIZE)
287 #define BASE_POOL_TYPE_MASK 1
288 #define POOL_MAX_ALLOC (PAGE_SIZE - (sizeof(POOL_HEADER) + POOL_BLOCK_SIZE))
289
290 typedef struct _POOL_DESCRIPTOR
291 {
292 POOL_TYPE PoolType;
293 ULONG PoolIndex;
294 ULONG RunningAllocs;
295 ULONG RunningDeAllocs;
296 ULONG TotalPages;
297 ULONG TotalBigPages;
298 ULONG Threshold;
299 PVOID LockAddress;
300 PVOID PendingFrees;
301 LONG PendingFreeDepth;
302 SIZE_T TotalBytes;
303 SIZE_T Spare0;
304 LIST_ENTRY ListHeads[POOL_LISTS_PER_PAGE];
305 } POOL_DESCRIPTOR, *PPOOL_DESCRIPTOR;
306
307 typedef struct _POOL_HEADER
308 {
309 union
310 {
311 struct
312 {
313 #ifdef _M_AMD64
314 USHORT PreviousSize:8;
315 USHORT PoolIndex:8;
316 USHORT BlockSize:8;
317 USHORT PoolType:8;
318 #else
319 USHORT PreviousSize:9;
320 USHORT PoolIndex:7;
321 USHORT BlockSize:9;
322 USHORT PoolType:7;
323 #endif
324 };
325 ULONG Ulong1;
326 };
327 #ifdef _M_AMD64
328 ULONG PoolTag;
329 #endif
330 union
331 {
332 #ifdef _M_AMD64
333 PEPROCESS ProcessBilled;
334 #else
335 ULONG PoolTag;
336 #endif
337 struct
338 {
339 USHORT AllocatorBackTraceIndex;
340 USHORT PoolTagHash;
341 };
342 };
343 } POOL_HEADER, *PPOOL_HEADER;
344
345 C_ASSERT(sizeof(POOL_HEADER) == POOL_BLOCK_SIZE);
346 C_ASSERT(POOL_BLOCK_SIZE == sizeof(LIST_ENTRY));
347
348 extern ULONG ExpNumberOfPagedPools;
349 extern POOL_DESCRIPTOR NonPagedPoolDescriptor;
350 extern PPOOL_DESCRIPTOR ExpPagedPoolDescriptor[16 + 1];
351 extern PVOID PoolTrackTable;
352
353 //
354 // END FIXFIX
355 //
356
357 typedef struct _MI_LARGE_PAGE_DRIVER_ENTRY
358 {
359 LIST_ENTRY Links;
360 UNICODE_STRING BaseName;
361 } MI_LARGE_PAGE_DRIVER_ENTRY, *PMI_LARGE_PAGE_DRIVER_ENTRY;
362
363 typedef enum _MMSYSTEM_PTE_POOL_TYPE
364 {
365 SystemPteSpace,
366 NonPagedPoolExpansion,
367 MaximumPtePoolTypes
368 } MMSYSTEM_PTE_POOL_TYPE;
369
370 typedef enum _MI_PFN_CACHE_ATTRIBUTE
371 {
372 MiNonCached,
373 MiCached,
374 MiWriteCombined,
375 MiNotMapped
376 } MI_PFN_CACHE_ATTRIBUTE, *PMI_PFN_CACHE_ATTRIBUTE;
377
378 typedef struct _PHYSICAL_MEMORY_RUN
379 {
380 PFN_NUMBER BasePage;
381 PFN_NUMBER PageCount;
382 } PHYSICAL_MEMORY_RUN, *PPHYSICAL_MEMORY_RUN;
383
384 typedef struct _PHYSICAL_MEMORY_DESCRIPTOR
385 {
386 ULONG NumberOfRuns;
387 PFN_NUMBER NumberOfPages;
388 PHYSICAL_MEMORY_RUN Run[1];
389 } PHYSICAL_MEMORY_DESCRIPTOR, *PPHYSICAL_MEMORY_DESCRIPTOR;
390
391 typedef struct _MMCOLOR_TABLES
392 {
393 PFN_NUMBER Flink;
394 PVOID Blink;
395 PFN_NUMBER Count;
396 } MMCOLOR_TABLES, *PMMCOLOR_TABLES;
397
398 typedef struct _MI_LARGE_PAGE_RANGES
399 {
400 PFN_NUMBER StartFrame;
401 PFN_NUMBER LastFrame;
402 } MI_LARGE_PAGE_RANGES, *PMI_LARGE_PAGE_RANGES;
403
404 typedef struct _MMVIEW
405 {
406 ULONG_PTR Entry;
407 PCONTROL_AREA ControlArea;
408 } MMVIEW, *PMMVIEW;
409
410 typedef struct _MMSESSION
411 {
412 KGUARDED_MUTEX SystemSpaceViewLock;
413 PKGUARDED_MUTEX SystemSpaceViewLockPointer;
414 PCHAR SystemSpaceViewStart;
415 PMMVIEW SystemSpaceViewTable;
416 ULONG SystemSpaceHashSize;
417 ULONG SystemSpaceHashEntries;
418 ULONG SystemSpaceHashKey;
419 ULONG BitmapFailures;
420 PRTL_BITMAP SystemSpaceBitMap;
421 } MMSESSION, *PMMSESSION;
422
423 extern MMPTE HyperTemplatePte;
424 extern MMPDE ValidKernelPde;
425 extern MMPTE ValidKernelPte;
426 extern MMPDE DemandZeroPde;
427 extern MMPTE DemandZeroPte;
428 extern MMPTE PrototypePte;
429 extern BOOLEAN MmLargeSystemCache;
430 extern BOOLEAN MmZeroPageFile;
431 extern BOOLEAN MmProtectFreedNonPagedPool;
432 extern BOOLEAN MmTrackLockedPages;
433 extern BOOLEAN MmTrackPtes;
434 extern BOOLEAN MmDynamicPfn;
435 extern BOOLEAN MmMirroring;
436 extern BOOLEAN MmMakeLowMemory;
437 extern BOOLEAN MmEnforceWriteProtection;
438 extern SIZE_T MmAllocationFragment;
439 extern ULONG MmConsumedPoolPercentage;
440 extern ULONG MmVerifyDriverBufferType;
441 extern ULONG MmVerifyDriverLevel;
442 extern WCHAR MmVerifyDriverBuffer[512];
443 extern WCHAR MmLargePageDriverBuffer[512];
444 extern LIST_ENTRY MiLargePageDriverList;
445 extern BOOLEAN MiLargePageAllDrivers;
446 extern ULONG MmVerifyDriverBufferLength;
447 extern ULONG MmLargePageDriverBufferLength;
448 extern SIZE_T MmSizeOfNonPagedPoolInBytes;
449 extern SIZE_T MmMaximumNonPagedPoolInBytes;
450 extern PFN_NUMBER MmMaximumNonPagedPoolInPages;
451 extern PFN_NUMBER MmSizeOfPagedPoolInPages;
452 extern PVOID MmNonPagedSystemStart;
453 extern SIZE_T MiNonPagedSystemSize;
454 extern PVOID MmNonPagedPoolStart;
455 extern PVOID MmNonPagedPoolExpansionStart;
456 extern PVOID MmNonPagedPoolEnd;
457 extern SIZE_T MmSizeOfPagedPoolInBytes;
458 extern PVOID MmPagedPoolStart;
459 extern PVOID MmPagedPoolEnd;
460 extern PVOID MmSessionBase;
461 extern SIZE_T MmSessionSize;
462 extern PMMPTE MmFirstReservedMappingPte, MmLastReservedMappingPte;
463 extern PMMPTE MiFirstReservedZeroingPte;
464 extern MI_PFN_CACHE_ATTRIBUTE MiPlatformCacheAttributes[2][MmMaximumCacheType];
465 extern PPHYSICAL_MEMORY_DESCRIPTOR MmPhysicalMemoryBlock;
466 extern SIZE_T MmBootImageSize;
467 extern PMMPTE MmSystemPtesStart[MaximumPtePoolTypes];
468 extern PMMPTE MmSystemPtesEnd[MaximumPtePoolTypes];
469 extern PMEMORY_ALLOCATION_DESCRIPTOR MxFreeDescriptor;
470 extern MEMORY_ALLOCATION_DESCRIPTOR MxOldFreeDescriptor;
471 extern ULONG_PTR MxPfnAllocation;
472 extern MM_PAGED_POOL_INFO MmPagedPoolInfo;
473 extern RTL_BITMAP MiPfnBitMap;
474 extern KGUARDED_MUTEX MmPagedPoolMutex;
475 extern PVOID MmPagedPoolStart;
476 extern PVOID MmPagedPoolEnd;
477 extern PVOID MmNonPagedSystemStart;
478 extern PVOID MiSystemViewStart;
479 extern SIZE_T MmSystemViewSize;
480 extern PVOID MmSessionBase;
481 extern PVOID MiSessionSpaceEnd;
482 extern PMMPTE MiSessionImagePteStart;
483 extern PMMPTE MiSessionImagePteEnd;
484 extern PMMPTE MiSessionBasePte;
485 extern PMMPTE MiSessionLastPte;
486 extern SIZE_T MmSizeOfPagedPoolInBytes;
487 extern PMMPDE MmSystemPagePtes;
488 extern PVOID MmSystemCacheStart;
489 extern PVOID MmSystemCacheEnd;
490 extern MMSUPPORT MmSystemCacheWs;
491 extern SIZE_T MmAllocatedNonPagedPool;
492 extern ULONG_PTR MmSubsectionBase;
493 extern ULONG MmSpecialPoolTag;
494 extern PVOID MmHyperSpaceEnd;
495 extern PMMWSL MmSystemCacheWorkingSetList;
496 extern SIZE_T MmMinimumNonPagedPoolSize;
497 extern ULONG MmMinAdditionNonPagedPoolPerMb;
498 extern SIZE_T MmDefaultMaximumNonPagedPool;
499 extern ULONG MmMaxAdditionNonPagedPoolPerMb;
500 extern ULONG MmSecondaryColors;
501 extern ULONG MmSecondaryColorMask;
502 extern ULONG MmNumberOfSystemPtes;
503 extern ULONG MmMaximumNonPagedPoolPercent;
504 extern ULONG MmLargeStackSize;
505 extern PMMCOLOR_TABLES MmFreePagesByColor[FreePageList + 1];
506 extern ULONG MmProductType;
507 extern MM_SYSTEMSIZE MmSystemSize;
508 extern PKEVENT MiLowMemoryEvent;
509 extern PKEVENT MiHighMemoryEvent;
510 extern PKEVENT MiLowPagedPoolEvent;
511 extern PKEVENT MiHighPagedPoolEvent;
512 extern PKEVENT MiLowNonPagedPoolEvent;
513 extern PKEVENT MiHighNonPagedPoolEvent;
514 extern PFN_NUMBER MmLowMemoryThreshold;
515 extern PFN_NUMBER MmHighMemoryThreshold;
516 extern PFN_NUMBER MiLowPagedPoolThreshold;
517 extern PFN_NUMBER MiHighPagedPoolThreshold;
518 extern PFN_NUMBER MiLowNonPagedPoolThreshold;
519 extern PFN_NUMBER MiHighNonPagedPoolThreshold;
520 extern PFN_NUMBER MmMinimumFreePages;
521 extern PFN_NUMBER MmPlentyFreePages;
522 extern PFN_COUNT MiExpansionPoolPagesInitialCharge;
523 extern PFN_NUMBER MmResidentAvailablePages;
524 extern PFN_NUMBER MmResidentAvailableAtInit;
525 extern ULONG MmTotalFreeSystemPtes[MaximumPtePoolTypes];
526 extern PFN_NUMBER MmTotalSystemDriverPages;
527 extern PVOID MiSessionImageStart;
528 extern PVOID MiSessionImageEnd;
529 extern PMMPTE MiHighestUserPte;
530 extern PMMPDE MiHighestUserPde;
531 extern PFN_NUMBER MmSystemPageDirectory[PD_COUNT];
532 extern PMMPTE MmSharedUserDataPte;
533 extern LIST_ENTRY MmProcessList;
534 extern BOOLEAN MmZeroingPageThreadActive;
535 extern KEVENT MmZeroingPageEvent;
536 extern ULONG MmSystemPageColor;
537 extern ULONG MmProcessColorSeed;
538 extern PMMWSL MmWorkingSetList;
539 extern PFN_NUMBER MiNumberOfFreePages;
540 extern SIZE_T MmSessionViewSize;
541 extern SIZE_T MmSessionPoolSize;
542 extern SIZE_T MmSessionImageSize;
543 extern PVOID MiSystemViewStart;
544 extern PVOID MiSessionPoolEnd; // 0xBE000000
545 extern PVOID MiSessionPoolStart; // 0xBD000000
546 extern PVOID MiSessionViewStart; // 0xBE000000
547
548 BOOLEAN
549 FORCEINLINE
550 MiIsMemoryTypeFree(TYPE_OF_MEMORY MemoryType)
551 {
552 return ((MemoryType == LoaderFree) ||
553 (MemoryType == LoaderLoadedProgram) ||
554 (MemoryType == LoaderFirmwareTemporary) ||
555 (MemoryType == LoaderOsloaderStack));
556 }
557
558 BOOLEAN
559 FORCEINLINE
560 MiIsMemoryTypeInvisible(TYPE_OF_MEMORY MemoryType)
561 {
562 return ((MemoryType == LoaderFirmwarePermanent) ||
563 (MemoryType == LoaderSpecialMemory) ||
564 (MemoryType == LoaderHALCachedMemory) ||
565 (MemoryType == LoaderBBTMemory));
566 }
567
568 #ifdef _M_AMD64
569 BOOLEAN
570 FORCEINLINE
571 MiIsUserPxe(PVOID Address)
572 {
573 return ((ULONG_PTR)Address >> 7) == 0x1FFFFEDF6FB7DA0ULL;
574 }
575
576 BOOLEAN
577 FORCEINLINE
578 MiIsUserPpe(PVOID Address)
579 {
580 return ((ULONG_PTR)Address >> 16) == 0xFFFFF6FB7DA0ULL;
581 }
582
583 BOOLEAN
584 FORCEINLINE
585 MiIsUserPde(PVOID Address)
586 {
587 return ((ULONG_PTR)Address >> 25) == 0x7FFFFB7DA0ULL;
588 }
589
590 BOOLEAN
591 FORCEINLINE
592 MiIsUserPte(PVOID Address)
593 {
594 return ((ULONG_PTR)Address >> 34) == 0x3FFFFDA0ULL;
595 }
596 #else
597 BOOLEAN
598 FORCEINLINE
599 MiIsUserPde(PVOID Address)
600 {
601 return ((Address >= (PVOID)MiAddressToPde(NULL)) &&
602 (Address <= (PVOID)MiHighestUserPde));
603 }
604
605 BOOLEAN
606 FORCEINLINE
607 MiIsUserPte(PVOID Address)
608 {
609 return (Address <= (PVOID)MiHighestUserPte);
610 }
611 #endif
612
613 //
614 // Figures out the hardware bits for a PTE
615 //
616 ULONG_PTR
617 FORCEINLINE
618 MiDetermineUserGlobalPteMask(IN PVOID PointerPte)
619 {
620 MMPTE TempPte;
621
622 /* Start fresh */
623 TempPte.u.Long = 0;
624
625 /* Make it valid and accessed */
626 TempPte.u.Hard.Valid = TRUE;
627 MI_MAKE_ACCESSED_PAGE(&TempPte);
628
629 /* Is this for user-mode? */
630 if (
631 #if (_MI_PAGING_LEVELS == 4)
632 MiIsUserPxe(PointerPte) ||
633 #endif
634 #if (_MI_PAGING_LEVELS >= 3)
635 MiIsUserPpe(PointerPte) ||
636 #endif
637 MiIsUserPde(PointerPte) ||
638 MiIsUserPte(PointerPte))
639 {
640 /* Set the owner bit */
641 MI_MAKE_OWNER_PAGE(&TempPte);
642 }
643
644 /* FIXME: We should also set the global bit */
645
646 /* Return the protection */
647 return TempPte.u.Long;
648 }
649
650 //
651 // Creates a valid kernel PTE with the given protection
652 //
653 FORCEINLINE
654 VOID
655 MI_MAKE_HARDWARE_PTE_KERNEL(IN PMMPTE NewPte,
656 IN PMMPTE MappingPte,
657 IN ULONG_PTR ProtectionMask,
658 IN PFN_NUMBER PageFrameNumber)
659 {
660 /* Only valid for kernel, non-session PTEs */
661 ASSERT(MappingPte > MiHighestUserPte);
662 ASSERT(!MI_IS_SESSION_PTE(MappingPte));
663 ASSERT((MappingPte < (PMMPTE)PDE_BASE) || (MappingPte > (PMMPTE)PDE_TOP));
664
665 /* Start fresh */
666 *NewPte = ValidKernelPte;
667
668 /* Set the protection and page */
669 NewPte->u.Hard.PageFrameNumber = PageFrameNumber;
670 NewPte->u.Long |= MmProtectToPteMask[ProtectionMask];
671 }
672
673 //
674 // Creates a valid PTE with the given protection
675 //
676 FORCEINLINE
677 VOID
678 MI_MAKE_HARDWARE_PTE(IN PMMPTE NewPte,
679 IN PMMPTE MappingPte,
680 IN ULONG_PTR ProtectionMask,
681 IN PFN_NUMBER PageFrameNumber)
682 {
683 /* Set the protection and page */
684 NewPte->u.Long = MiDetermineUserGlobalPteMask(MappingPte);
685 NewPte->u.Long |= MmProtectToPteMask[ProtectionMask];
686 NewPte->u.Hard.PageFrameNumber = PageFrameNumber;
687 }
688
689 //
690 // Creates a valid user PTE with the given protection
691 //
692 FORCEINLINE
693 VOID
694 MI_MAKE_HARDWARE_PTE_USER(IN PMMPTE NewPte,
695 IN PMMPTE MappingPte,
696 IN ULONG_PTR ProtectionMask,
697 IN PFN_NUMBER PageFrameNumber)
698 {
699 /* Only valid for kernel, non-session PTEs */
700 ASSERT(MappingPte <= MiHighestUserPte);
701
702 /* Start fresh */
703 *NewPte = ValidKernelPte;
704
705 /* Set the protection and page */
706 NewPte->u.Hard.Owner = TRUE;
707 NewPte->u.Hard.PageFrameNumber = PageFrameNumber;
708 NewPte->u.Long |= MmProtectToPteMask[ProtectionMask];
709 }
710
711 #ifndef _M_AMD64
712 //
713 // Builds a Prototype PTE for the address of the PTE
714 //
715 FORCEINLINE
716 VOID
717 MI_MAKE_PROTOTYPE_PTE(IN PMMPTE NewPte,
718 IN PMMPTE PointerPte)
719 {
720 ULONG_PTR Offset;
721
722 /* Mark this as a prototype */
723 NewPte->u.Long = 0;
724 NewPte->u.Proto.Prototype = 1;
725
726 /*
727 * Prototype PTEs are only valid in paged pool by design, this little trick
728 * lets us only use 28 bits for the adress of the PTE
729 */
730 Offset = (ULONG_PTR)PointerPte - (ULONG_PTR)MmPagedPoolStart;
731
732 /* 7 bits go in the "low", and the other 21 bits go in the "high" */
733 NewPte->u.Proto.ProtoAddressLow = Offset & 0x7F;
734 NewPte->u.Proto.ProtoAddressHigh = (Offset & 0xFFFFFF80) >> 7;
735 ASSERT(MiProtoPteToPte(NewPte) == PointerPte);
736 }
737 #endif
738
739 //
740 // Returns if the page is physically resident (ie: a large page)
741 // FIXFIX: CISC/x86 only?
742 //
743 FORCEINLINE
744 BOOLEAN
745 MI_IS_PHYSICAL_ADDRESS(IN PVOID Address)
746 {
747 PMMPDE PointerPde;
748
749 /* Large pages are never paged out, always physically resident */
750 PointerPde = MiAddressToPde(Address);
751 return ((PointerPde->u.Hard.LargePage) && (PointerPde->u.Hard.Valid));
752 }
753
754 //
755 // Writes a valid PTE
756 //
757 VOID
758 FORCEINLINE
759 MI_WRITE_VALID_PTE(IN PMMPTE PointerPte,
760 IN MMPTE TempPte)
761 {
762 /* Write the valid PTE */
763 ASSERT(PointerPte->u.Hard.Valid == 0);
764 ASSERT(TempPte.u.Hard.Valid == 1);
765 *PointerPte = TempPte;
766 }
767
768 //
769 // Writes an invalid PTE
770 //
771 VOID
772 FORCEINLINE
773 MI_WRITE_INVALID_PTE(IN PMMPTE PointerPte,
774 IN MMPTE InvalidPte)
775 {
776 /* Write the invalid PTE */
777 ASSERT(InvalidPte.u.Hard.Valid == 0);
778 *PointerPte = InvalidPte;
779 }
780
781 //
782 // Writes a valid PDE
783 //
784 VOID
785 FORCEINLINE
786 MI_WRITE_VALID_PDE(IN PMMPDE PointerPde,
787 IN MMPDE TempPde)
788 {
789 /* Write the valid PDE */
790 ASSERT(PointerPde->u.Hard.Valid == 0);
791 ASSERT(TempPde.u.Hard.Valid == 1);
792 *PointerPde = TempPde;
793 }
794
795 //
796 // Writes an invalid PDE
797 //
798 VOID
799 FORCEINLINE
800 MI_WRITE_INVALID_PDE(IN PMMPDE PointerPde,
801 IN MMPDE InvalidPde)
802 {
803 /* Write the invalid PDE */
804 ASSERT(InvalidPde.u.Hard.Valid == 0);
805 *PointerPde = InvalidPde;
806 }
807
808 //
809 // Checks if the thread already owns a working set
810 //
811 FORCEINLINE
812 BOOLEAN
813 MM_ANY_WS_LOCK_HELD(IN PETHREAD Thread)
814 {
815 /* If any of these are held, return TRUE */
816 return ((Thread->OwnsProcessWorkingSetExclusive) ||
817 (Thread->OwnsProcessWorkingSetShared) ||
818 (Thread->OwnsSystemWorkingSetExclusive) ||
819 (Thread->OwnsSystemWorkingSetShared) ||
820 (Thread->OwnsSessionWorkingSetExclusive) ||
821 (Thread->OwnsSessionWorkingSetShared));
822 }
823
824 //
825 // Checks if the process owns the working set lock
826 //
827 FORCEINLINE
828 BOOLEAN
829 MI_WS_OWNER(IN PEPROCESS Process)
830 {
831 /* Check if this process is the owner, and that the thread owns the WS */
832 return ((KeGetCurrentThread()->ApcState.Process == &Process->Pcb) &&
833 ((PsGetCurrentThread()->OwnsProcessWorkingSetExclusive) ||
834 (PsGetCurrentThread()->OwnsProcessWorkingSetShared)));
835 }
836
837 //
838 // Locks the working set for the given process
839 //
840 FORCEINLINE
841 VOID
842 MiLockProcessWorkingSet(IN PEPROCESS Process,
843 IN PETHREAD Thread)
844 {
845 /* Shouldn't already be owning the process working set */
846 ASSERT(Thread->OwnsProcessWorkingSetShared == FALSE);
847 ASSERT(Thread->OwnsProcessWorkingSetExclusive == FALSE);
848
849 /* Block APCs, make sure that still nothing is already held */
850 KeEnterGuardedRegion();
851 ASSERT(!MM_ANY_WS_LOCK_HELD(Thread));
852
853 /* FIXME: Actually lock it (we can't because Vm is used by MAREAs) */
854
855 /* FIXME: This also can't be checked because Vm is used by MAREAs) */
856 //ASSERT(Process->Vm.Flags.AcquiredUnsafe == 0);
857
858 /* Okay, now we can own it exclusively */
859 ASSERT(Thread->OwnsProcessWorkingSetExclusive == FALSE);
860 Thread->OwnsProcessWorkingSetExclusive = TRUE;
861 }
862
863 //
864 // Unlocks the working set for the given process
865 //
866 FORCEINLINE
867 VOID
868 MiUnlockProcessWorkingSet(IN PEPROCESS Process,
869 IN PETHREAD Thread)
870 {
871 /* Make sure this process really is owner, and it was a safe acquisition */
872 ASSERT(MI_WS_OWNER(Process));
873 /* This can't be checked because Vm is used by MAREAs) */
874 //ASSERT(Process->Vm.Flags.AcquiredUnsafe == 0);
875
876 /* The thread doesn't own it anymore */
877 ASSERT(Thread->OwnsProcessWorkingSetExclusive == TRUE);
878 Thread->OwnsProcessWorkingSetExclusive = FALSE;
879
880 /* FIXME: Actually release it (we can't because Vm is used by MAREAs) */
881
882 /* Unblock APCs */
883 KeLeaveGuardedRegion();
884 }
885
886 //
887 // Locks the working set
888 //
889 FORCEINLINE
890 VOID
891 MiLockWorkingSet(IN PETHREAD Thread,
892 IN PMMSUPPORT WorkingSet)
893 {
894 /* Block APCs */
895 KeEnterGuardedRegion();
896
897 /* Working set should be in global memory */
898 ASSERT(MI_IS_SESSION_ADDRESS((PVOID)WorkingSet) == FALSE);
899
900 /* Thread shouldn't already be owning something */
901 ASSERT(!MM_ANY_WS_LOCK_HELD(Thread));
902
903 /* FIXME: Actually lock it (we can't because Vm is used by MAREAs) */
904
905 /* Which working set is this? */
906 if (WorkingSet == &MmSystemCacheWs)
907 {
908 /* Own the system working set */
909 ASSERT((Thread->OwnsSystemWorkingSetExclusive == FALSE) &&
910 (Thread->OwnsSystemWorkingSetShared == FALSE));
911 Thread->OwnsSystemWorkingSetExclusive = TRUE;
912 }
913 else if (WorkingSet->Flags.SessionSpace)
914 {
915 /* We don't implement this yet */
916 UNIMPLEMENTED;
917 while (TRUE);
918 }
919 else
920 {
921 /* Own the process working set */
922 ASSERT((Thread->OwnsProcessWorkingSetExclusive == FALSE) &&
923 (Thread->OwnsProcessWorkingSetShared == FALSE));
924 Thread->OwnsProcessWorkingSetExclusive = TRUE;
925 }
926 }
927
928 //
929 // Unlocks the working set
930 //
931 FORCEINLINE
932 VOID
933 MiUnlockWorkingSet(IN PETHREAD Thread,
934 IN PMMSUPPORT WorkingSet)
935 {
936 /* Working set should be in global memory */
937 ASSERT(MI_IS_SESSION_ADDRESS((PVOID)WorkingSet) == FALSE);
938
939 /* Which working set is this? */
940 if (WorkingSet == &MmSystemCacheWs)
941 {
942 /* Release the system working set */
943 ASSERT((Thread->OwnsSystemWorkingSetExclusive == TRUE) ||
944 (Thread->OwnsSystemWorkingSetShared == TRUE));
945 Thread->OwnsSystemWorkingSetExclusive = FALSE;
946 }
947 else if (WorkingSet->Flags.SessionSpace)
948 {
949 /* We don't implement this yet */
950 UNIMPLEMENTED;
951 while (TRUE);
952 }
953 else
954 {
955 /* Release the process working set */
956 ASSERT((Thread->OwnsProcessWorkingSetExclusive) ||
957 (Thread->OwnsProcessWorkingSetShared));
958 Thread->OwnsProcessWorkingSetExclusive = FALSE;
959 }
960
961 /* FIXME: Actually release it (we can't because Vm is used by MAREAs) */
962
963 /* Unblock APCs */
964 KeLeaveGuardedRegion();
965 }
966
967 //
968 // Returns the ProtoPTE inside a VAD for the given VPN
969 //
970 FORCEINLINE
971 PMMPTE
972 MI_GET_PROTOTYPE_PTE_FOR_VPN(IN PMMVAD Vad,
973 IN ULONG_PTR Vpn)
974 {
975 PMMPTE ProtoPte;
976
977 /* Find the offset within the VAD's prototype PTEs */
978 ProtoPte = Vad->FirstPrototypePte + (Vpn - Vad->StartingVpn);
979 ASSERT(ProtoPte <= Vad->LastContiguousPte);
980 return ProtoPte;
981 }
982
983 //
984 // Returns the PFN Database entry for the given page number
985 // Warning: This is not necessarily a valid PFN database entry!
986 //
987 FORCEINLINE
988 PMMPFN
989 MI_PFN_ELEMENT(IN PFN_NUMBER Pfn)
990 {
991 /* Get the entry */
992 return &MmPfnDatabase[Pfn];
993 };
994
995 BOOLEAN
996 NTAPI
997 MmArmInitSystem(
998 IN ULONG Phase,
999 IN PLOADER_PARAMETER_BLOCK LoaderBlock
1000 );
1001
1002 VOID
1003 NTAPI
1004 MiInitializeSessionSpaceLayout();
1005
1006 NTSTATUS
1007 NTAPI
1008 MiInitMachineDependent(
1009 IN PLOADER_PARAMETER_BLOCK LoaderBlock
1010 );
1011
1012 VOID
1013 NTAPI
1014 MiComputeColorInformation(
1015 VOID
1016 );
1017
1018 VOID
1019 NTAPI
1020 MiMapPfnDatabase(
1021 IN PLOADER_PARAMETER_BLOCK LoaderBlock
1022 );
1023
1024 VOID
1025 NTAPI
1026 MiInitializeColorTables(
1027 VOID
1028 );
1029
1030 VOID
1031 NTAPI
1032 MiInitializePfnDatabase(
1033 IN PLOADER_PARAMETER_BLOCK LoaderBlock
1034 );
1035
1036 VOID
1037 NTAPI
1038 MiInitializeSessionIds(
1039 VOID
1040 );
1041
1042 BOOLEAN
1043 NTAPI
1044 MiInitializeMemoryEvents(
1045 VOID
1046 );
1047
1048 PFN_NUMBER
1049 NTAPI
1050 MxGetNextPage(
1051 IN PFN_NUMBER PageCount
1052 );
1053
1054 PPHYSICAL_MEMORY_DESCRIPTOR
1055 NTAPI
1056 MmInitializeMemoryLimits(
1057 IN PLOADER_PARAMETER_BLOCK LoaderBlock,
1058 IN PBOOLEAN IncludeType
1059 );
1060
1061 PFN_NUMBER
1062 NTAPI
1063 MiPagesInLoaderBlock(
1064 IN PLOADER_PARAMETER_BLOCK LoaderBlock,
1065 IN PBOOLEAN IncludeType
1066 );
1067
1068 VOID
1069 FASTCALL
1070 MiSyncARM3WithROS(
1071 IN PVOID AddressStart,
1072 IN PVOID AddressEnd
1073 );
1074
1075 NTSTATUS
1076 NTAPI
1077 MmArmAccessFault(
1078 IN BOOLEAN StoreInstruction,
1079 IN PVOID Address,
1080 IN KPROCESSOR_MODE Mode,
1081 IN PVOID TrapInformation
1082 );
1083
1084 NTSTATUS
1085 FASTCALL
1086 MiCheckPdeForPagedPool(
1087 IN PVOID Address
1088 );
1089
1090 VOID
1091 NTAPI
1092 MiInitializeNonPagedPool(
1093 VOID
1094 );
1095
1096 VOID
1097 NTAPI
1098 MiInitializeNonPagedPoolThresholds(
1099 VOID
1100 );
1101
1102 VOID
1103 NTAPI
1104 MiInitializePoolEvents(
1105 VOID
1106 );
1107
1108 VOID //
1109 NTAPI //
1110 InitializePool( //
1111 IN POOL_TYPE PoolType,// FIXFIX: This should go in ex.h after the pool merge
1112 IN ULONG Threshold //
1113 ); //
1114
1115 VOID
1116 NTAPI
1117 MiInitializeSystemPtes(
1118 IN PMMPTE StartingPte,
1119 IN ULONG NumberOfPtes,
1120 IN MMSYSTEM_PTE_POOL_TYPE PoolType
1121 );
1122
1123 PMMPTE
1124 NTAPI
1125 MiReserveSystemPtes(
1126 IN ULONG NumberOfPtes,
1127 IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType
1128 );
1129
1130 VOID
1131 NTAPI
1132 MiReleaseSystemPtes(
1133 IN PMMPTE StartingPte,
1134 IN ULONG NumberOfPtes,
1135 IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType
1136 );
1137
1138
1139 PFN_NUMBER
1140 NTAPI
1141 MiFindContiguousPages(
1142 IN PFN_NUMBER LowestPfn,
1143 IN PFN_NUMBER HighestPfn,
1144 IN PFN_NUMBER BoundaryPfn,
1145 IN PFN_NUMBER SizeInPages,
1146 IN MEMORY_CACHING_TYPE CacheType
1147 );
1148
1149 PVOID
1150 NTAPI
1151 MiCheckForContiguousMemory(
1152 IN PVOID BaseAddress,
1153 IN PFN_NUMBER BaseAddressPages,
1154 IN PFN_NUMBER SizeInPages,
1155 IN PFN_NUMBER LowestPfn,
1156 IN PFN_NUMBER HighestPfn,
1157 IN PFN_NUMBER BoundaryPfn,
1158 IN MI_PFN_CACHE_ATTRIBUTE CacheAttribute
1159 );
1160
1161 PMDL
1162 NTAPI
1163 MiAllocatePagesForMdl(
1164 IN PHYSICAL_ADDRESS LowAddress,
1165 IN PHYSICAL_ADDRESS HighAddress,
1166 IN PHYSICAL_ADDRESS SkipBytes,
1167 IN SIZE_T TotalBytes,
1168 IN MI_PFN_CACHE_ATTRIBUTE CacheAttribute,
1169 IN ULONG Flags
1170 );
1171
1172 PVOID
1173 NTAPI
1174 MiMapLockedPagesInUserSpace(
1175 IN PMDL Mdl,
1176 IN PVOID BaseVa,
1177 IN MEMORY_CACHING_TYPE CacheType,
1178 IN PVOID BaseAddress
1179 );
1180
1181 VOID
1182 NTAPI
1183 MiUnmapLockedPagesInUserSpace(
1184 IN PVOID BaseAddress,
1185 IN PMDL Mdl
1186 );
1187
1188 VOID
1189 NTAPI
1190 MiInsertPageInList(
1191 IN PMMPFNLIST ListHead,
1192 IN PFN_NUMBER PageFrameIndex
1193 );
1194
1195 VOID
1196 NTAPI
1197 MiUnlinkFreeOrZeroedPage(
1198 IN PMMPFN Entry
1199 );
1200
1201 PFN_NUMBER
1202 NTAPI
1203 MiAllocatePfn(
1204 IN PMMPTE PointerPte,
1205 IN ULONG Protection
1206 );
1207
1208 VOID
1209 NTAPI
1210 MiInitializePfn(
1211 IN PFN_NUMBER PageFrameIndex,
1212 IN PMMPTE PointerPte,
1213 IN BOOLEAN Modified
1214 );
1215
1216 VOID
1217 NTAPI
1218 MiInitializePfnAndMakePteValid(
1219 IN PFN_NUMBER PageFrameIndex,
1220 IN PMMPTE PointerPte,
1221 IN MMPTE TempPte
1222 );
1223
1224 VOID
1225 NTAPI
1226 MiInitializePfnForOtherProcess(
1227 IN PFN_NUMBER PageFrameIndex,
1228 IN PMMPTE PointerPte,
1229 IN PFN_NUMBER PteFrame
1230 );
1231
1232 VOID
1233 NTAPI
1234 MiDecrementShareCount(
1235 IN PMMPFN Pfn1,
1236 IN PFN_NUMBER PageFrameIndex
1237 );
1238
1239 VOID
1240 NTAPI
1241 MiDecrementReferenceCount(
1242 IN PMMPFN Pfn1,
1243 IN PFN_NUMBER PageFrameIndex
1244 );
1245
1246 PFN_NUMBER
1247 NTAPI
1248 MiRemoveAnyPage(
1249 IN ULONG Color
1250 );
1251
1252 PFN_NUMBER
1253 NTAPI
1254 MiRemoveZeroPage(
1255 IN ULONG Color
1256 );
1257
1258 VOID
1259 NTAPI
1260 MiZeroPhysicalPage(
1261 IN PFN_NUMBER PageFrameIndex
1262 );
1263
1264 VOID
1265 NTAPI
1266 MiInsertPageInFreeList(
1267 IN PFN_NUMBER PageFrameIndex
1268 );
1269
1270 PFN_COUNT
1271 NTAPI
1272 MiDeleteSystemPageableVm(
1273 IN PMMPTE PointerPte,
1274 IN PFN_NUMBER PageCount,
1275 IN ULONG Flags,
1276 OUT PPFN_NUMBER ValidPages
1277 );
1278
1279 PLDR_DATA_TABLE_ENTRY
1280 NTAPI
1281 MiLookupDataTableEntry(
1282 IN PVOID Address
1283 );
1284
1285 VOID
1286 NTAPI
1287 MiInitializeDriverLargePageList(
1288 VOID
1289 );
1290
1291 VOID
1292 NTAPI
1293 MiInitializeLargePageSupport(
1294 VOID
1295 );
1296
1297 VOID
1298 NTAPI
1299 MiSyncCachedRanges(
1300 VOID
1301 );
1302
1303 BOOLEAN
1304 NTAPI
1305 MiIsPfnInUse(
1306 IN PMMPFN Pfn1
1307 );
1308
1309 PMMVAD
1310 NTAPI
1311 MiLocateAddress(
1312 IN PVOID VirtualAddress
1313 );
1314
1315 PMMADDRESS_NODE
1316 NTAPI
1317 MiCheckForConflictingNode(
1318 IN ULONG_PTR StartVpn,
1319 IN ULONG_PTR EndVpn,
1320 IN PMM_AVL_TABLE Table
1321 );
1322
1323 TABLE_SEARCH_RESULT
1324 NTAPI
1325 MiFindEmptyAddressRangeDownTree(
1326 IN SIZE_T Length,
1327 IN ULONG_PTR BoundaryAddress,
1328 IN ULONG_PTR Alignment,
1329 IN PMM_AVL_TABLE Table,
1330 OUT PULONG_PTR Base,
1331 OUT PMMADDRESS_NODE *Parent
1332 );
1333
1334 NTSTATUS
1335 NTAPI
1336 MiFindEmptyAddressRangeInTree(
1337 IN SIZE_T Length,
1338 IN ULONG_PTR Alignment,
1339 IN PMM_AVL_TABLE Table,
1340 OUT PMMADDRESS_NODE *PreviousVad,
1341 OUT PULONG_PTR Base
1342 );
1343
1344 VOID
1345 NTAPI
1346 MiInsertVad(
1347 IN PMMVAD Vad,
1348 IN PEPROCESS Process
1349 );
1350
1351 VOID
1352 NTAPI
1353 MiInsertNode(
1354 IN PMM_AVL_TABLE Table,
1355 IN PMMADDRESS_NODE NewNode,
1356 PMMADDRESS_NODE Parent,
1357 TABLE_SEARCH_RESULT Result
1358 );
1359
1360 VOID
1361 NTAPI
1362 MiRemoveNode(
1363 IN PMMADDRESS_NODE Node,
1364 IN PMM_AVL_TABLE Table
1365 );
1366
1367 PMMADDRESS_NODE
1368 NTAPI
1369 MiGetPreviousNode(
1370 IN PMMADDRESS_NODE Node
1371 );
1372
1373 PMMADDRESS_NODE
1374 NTAPI
1375 MiGetNextNode(
1376 IN PMMADDRESS_NODE Node
1377 );
1378
1379 BOOLEAN
1380 NTAPI
1381 MiInitializeSystemSpaceMap(
1382 IN PVOID InputSession OPTIONAL
1383 );
1384
1385 ULONG
1386 NTAPI
1387 MiMakeProtectionMask(
1388 IN ULONG Protect
1389 );
1390
1391 VOID
1392 NTAPI
1393 MiDeleteVirtualAddresses(
1394 IN ULONG_PTR Va,
1395 IN ULONG_PTR EndingAddress,
1396 IN PMMVAD Vad
1397 );
1398
1399 ULONG
1400 NTAPI
1401 MiMakeSystemAddressValid(
1402 IN PVOID PageTableVirtualAddress,
1403 IN PEPROCESS CurrentProcess
1404 );
1405
1406 ULONG
1407 NTAPI
1408 MiMakeSystemAddressValidPfn(
1409 IN PVOID VirtualAddress,
1410 IN KIRQL OldIrql
1411 );
1412
1413 VOID
1414 NTAPI
1415 MiRemoveMappedView(
1416 IN PEPROCESS CurrentProcess,
1417 IN PMMVAD Vad
1418 );
1419
1420 PSUBSECTION
1421 NTAPI
1422 MiLocateSubsection(
1423 IN PMMVAD Vad,
1424 IN ULONG_PTR Vpn
1425 );
1426
1427 //
1428 // MiRemoveZeroPage will use inline code to zero out the page manually if only
1429 // free pages are available. In some scenarios, we don't/can't run that piece of
1430 // code and would rather only have a real zero page. If we can't have a zero page,
1431 // then we'd like to have our own code to grab a free page and zero it out, by
1432 // using MiRemoveAnyPage. This macro implements this.
1433 //
1434 PFN_NUMBER
1435 FORCEINLINE
1436 MiRemoveZeroPageSafe(IN ULONG Color)
1437 {
1438 if (MmFreePagesByColor[ZeroedPageList][Color].Flink != LIST_HEAD) return MiRemoveZeroPage(Color);
1439 return 0;
1440 }
1441
1442 //
1443 // New ARM3<->RosMM PAGE Architecture
1444 //
1445 #ifdef _WIN64
1446 // HACK ON TOP OF HACK ALERT!!!
1447 #define MI_GET_ROS_DATA(x) \
1448 (((x)->RosMmData == 0) ? NULL : ((PMMROSPFN)((ULONG64)(ULONG)((x)->RosMmData) | \
1449 ((ULONG64)MmNonPagedPoolStart & 0xffffffff00000000ULL))))
1450 #else
1451 #define MI_GET_ROS_DATA(x) ((PMMROSPFN)(x->RosMmData))
1452 #endif
1453 #define MI_IS_ROS_PFN(x) (((x)->u4.AweAllocation == TRUE) && (MI_GET_ROS_DATA(x) != NULL))
1454 #define ASSERT_IS_ROS_PFN(x) ASSERT(MI_IS_ROS_PFN(x) == TRUE);
1455 typedef struct _MMROSPFN
1456 {
1457 PMM_RMAP_ENTRY RmapListHead;
1458 SWAPENTRY SwapEntry;
1459 } MMROSPFN, *PMMROSPFN;
1460
1461 #define RosMmData AweReferenceCount
1462
1463 /* EOF */