[NTOSKRNL]
[reactos.git] / reactos / 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
569 //
570 // Figures out the hardware bits for a PTE
571 //
572 ULONG_PTR
573 FORCEINLINE
574 MiDetermineUserGlobalPteMask(IN PVOID PointerPte)
575 {
576 MMPTE TempPte;
577
578 /* Start fresh */
579 TempPte.u.Long = 0;
580
581 /* Make it valid and accessed */
582 TempPte.u.Hard.Valid = TRUE;
583 MI_MAKE_ACCESSED_PAGE(&TempPte);
584
585 /* Is this for user-mode? */
586 if ((PointerPte <= (PVOID)MiHighestUserPte) ||
587 ((PointerPte >= (PVOID)MiAddressToPde(NULL)) &&
588 (PointerPte <= (PVOID)MiHighestUserPde)))
589 {
590 /* Set the owner bit */
591 MI_MAKE_OWNER_PAGE(&TempPte);
592 }
593
594 /* FIXME: We should also set the global bit */
595
596 /* Return the protection */
597 return TempPte.u.Long;
598 }
599
600 //
601 // Creates a valid kernel PTE with the given protection
602 //
603 FORCEINLINE
604 VOID
605 MI_MAKE_HARDWARE_PTE_KERNEL(IN PMMPTE NewPte,
606 IN PMMPTE MappingPte,
607 IN ULONG_PTR ProtectionMask,
608 IN PFN_NUMBER PageFrameNumber)
609 {
610 /* Only valid for kernel, non-session PTEs */
611 ASSERT(MappingPte > MiHighestUserPte);
612 ASSERT(!MI_IS_SESSION_PTE(MappingPte));
613 ASSERT((MappingPte < (PMMPTE)PDE_BASE) || (MappingPte > (PMMPTE)PDE_TOP));
614
615 /* Start fresh */
616 *NewPte = ValidKernelPte;
617
618 /* Set the protection and page */
619 NewPte->u.Hard.PageFrameNumber = PageFrameNumber;
620 NewPte->u.Long |= MmProtectToPteMask[ProtectionMask];
621 }
622
623 //
624 // Creates a valid PTE with the given protection
625 //
626 FORCEINLINE
627 VOID
628 MI_MAKE_HARDWARE_PTE(IN PMMPTE NewPte,
629 IN PMMPTE MappingPte,
630 IN ULONG_PTR ProtectionMask,
631 IN PFN_NUMBER PageFrameNumber)
632 {
633 /* Set the protection and page */
634 NewPte->u.Long = MiDetermineUserGlobalPteMask(MappingPte);
635 NewPte->u.Long |= MmProtectToPteMask[ProtectionMask];
636 NewPte->u.Hard.PageFrameNumber = PageFrameNumber;
637 }
638
639 //
640 // Creates a valid user PTE with the given protection
641 //
642 FORCEINLINE
643 VOID
644 MI_MAKE_HARDWARE_PTE_USER(IN PMMPTE NewPte,
645 IN PMMPTE MappingPte,
646 IN ULONG_PTR ProtectionMask,
647 IN PFN_NUMBER PageFrameNumber)
648 {
649 /* Only valid for kernel, non-session PTEs */
650 ASSERT(MappingPte <= MiHighestUserPte);
651
652 /* Start fresh */
653 *NewPte = ValidKernelPte;
654
655 /* Set the protection and page */
656 NewPte->u.Hard.Owner = TRUE;
657 NewPte->u.Hard.PageFrameNumber = PageFrameNumber;
658 NewPte->u.Long |= MmProtectToPteMask[ProtectionMask];
659 }
660
661 #ifndef _M_AMD64
662 //
663 // Builds a Prototype PTE for the address of the PTE
664 //
665 FORCEINLINE
666 VOID
667 MI_MAKE_PROTOTYPE_PTE(IN PMMPTE NewPte,
668 IN PMMPTE PointerPte)
669 {
670 ULONG_PTR Offset;
671
672 /* Mark this as a prototype */
673 NewPte->u.Long = 0;
674 NewPte->u.Proto.Prototype = 1;
675
676 /*
677 * Prototype PTEs are only valid in paged pool by design, this little trick
678 * lets us only use 28 bits for the adress of the PTE
679 */
680 Offset = (ULONG_PTR)PointerPte - (ULONG_PTR)MmPagedPoolStart;
681
682 /* 7 bits go in the "low", and the other 21 bits go in the "high" */
683 NewPte->u.Proto.ProtoAddressLow = Offset & 0x7F;
684 NewPte->u.Proto.ProtoAddressHigh = (Offset & 0xFFFFFF80) >> 7;
685 ASSERT(MiProtoPteToPte(NewPte) == PointerPte);
686 }
687 #endif
688
689 //
690 // Returns if the page is physically resident (ie: a large page)
691 // FIXFIX: CISC/x86 only?
692 //
693 FORCEINLINE
694 BOOLEAN
695 MI_IS_PHYSICAL_ADDRESS(IN PVOID Address)
696 {
697 PMMPDE PointerPde;
698
699 /* Large pages are never paged out, always physically resident */
700 PointerPde = MiAddressToPde(Address);
701 return ((PointerPde->u.Hard.LargePage) && (PointerPde->u.Hard.Valid));
702 }
703
704 //
705 // Writes a valid PTE
706 //
707 VOID
708 FORCEINLINE
709 MI_WRITE_VALID_PTE(IN PMMPTE PointerPte,
710 IN MMPTE TempPte)
711 {
712 /* Write the valid PTE */
713 ASSERT(PointerPte->u.Hard.Valid == 0);
714 ASSERT(TempPte.u.Hard.Valid == 1);
715 *PointerPte = TempPte;
716 }
717
718 //
719 // Writes an invalid PTE
720 //
721 VOID
722 FORCEINLINE
723 MI_WRITE_INVALID_PTE(IN PMMPTE PointerPte,
724 IN MMPTE InvalidPte)
725 {
726 /* Write the invalid PTE */
727 ASSERT(InvalidPte.u.Hard.Valid == 0);
728 *PointerPte = InvalidPte;
729 }
730
731 //
732 // Writes a valid PDE
733 //
734 VOID
735 FORCEINLINE
736 MI_WRITE_VALID_PDE(IN PMMPDE PointerPde,
737 IN MMPDE TempPde)
738 {
739 /* Write the valid PDE */
740 ASSERT(PointerPde->u.Hard.Valid == 0);
741 ASSERT(TempPde.u.Hard.Valid == 1);
742 *PointerPde = TempPde;
743 }
744
745 //
746 // Writes an invalid PDE
747 //
748 VOID
749 FORCEINLINE
750 MI_WRITE_INVALID_PDE(IN PMMPDE PointerPde,
751 IN MMPDE InvalidPde)
752 {
753 /* Write the invalid PDE */
754 ASSERT(InvalidPde.u.Hard.Valid == 0);
755 *PointerPde = InvalidPde;
756 }
757
758 //
759 // Checks if the thread already owns a working set
760 //
761 FORCEINLINE
762 BOOLEAN
763 MM_ANY_WS_LOCK_HELD(IN PETHREAD Thread)
764 {
765 /* If any of these are held, return TRUE */
766 return ((Thread->OwnsProcessWorkingSetExclusive) ||
767 (Thread->OwnsProcessWorkingSetShared) ||
768 (Thread->OwnsSystemWorkingSetExclusive) ||
769 (Thread->OwnsSystemWorkingSetShared) ||
770 (Thread->OwnsSessionWorkingSetExclusive) ||
771 (Thread->OwnsSessionWorkingSetShared));
772 }
773
774 //
775 // Checks if the process owns the working set lock
776 //
777 FORCEINLINE
778 BOOLEAN
779 MI_WS_OWNER(IN PEPROCESS Process)
780 {
781 /* Check if this process is the owner, and that the thread owns the WS */
782 return ((KeGetCurrentThread()->ApcState.Process == &Process->Pcb) &&
783 ((PsGetCurrentThread()->OwnsProcessWorkingSetExclusive) ||
784 (PsGetCurrentThread()->OwnsProcessWorkingSetShared)));
785 }
786
787 //
788 // Locks the working set for the given process
789 //
790 FORCEINLINE
791 VOID
792 MiLockProcessWorkingSet(IN PEPROCESS Process,
793 IN PETHREAD Thread)
794 {
795 /* Shouldn't already be owning the process working set */
796 ASSERT(Thread->OwnsProcessWorkingSetShared == FALSE);
797 ASSERT(Thread->OwnsProcessWorkingSetExclusive == FALSE);
798
799 /* Block APCs, make sure that still nothing is already held */
800 KeEnterGuardedRegion();
801 ASSERT(!MM_ANY_WS_LOCK_HELD(Thread));
802
803 /* FIXME: Actually lock it (we can't because Vm is used by MAREAs) */
804
805 /* FIXME: This also can't be checked because Vm is used by MAREAs) */
806 //ASSERT(Process->Vm.Flags.AcquiredUnsafe == 0);
807
808 /* Okay, now we can own it exclusively */
809 ASSERT(Thread->OwnsProcessWorkingSetExclusive == FALSE);
810 Thread->OwnsProcessWorkingSetExclusive = TRUE;
811 }
812
813 //
814 // Unlocks the working set for the given process
815 //
816 FORCEINLINE
817 VOID
818 MiUnlockProcessWorkingSet(IN PEPROCESS Process,
819 IN PETHREAD Thread)
820 {
821 /* Make sure this process really is owner, and it was a safe acquisition */
822 ASSERT(MI_WS_OWNER(Process));
823 /* This can't be checked because Vm is used by MAREAs) */
824 //ASSERT(Process->Vm.Flags.AcquiredUnsafe == 0);
825
826 /* The thread doesn't own it anymore */
827 ASSERT(Thread->OwnsProcessWorkingSetExclusive == TRUE);
828 Thread->OwnsProcessWorkingSetExclusive = FALSE;
829
830 /* FIXME: Actually release it (we can't because Vm is used by MAREAs) */
831
832 /* Unblock APCs */
833 KeLeaveGuardedRegion();
834 }
835
836 //
837 // Locks the working set
838 //
839 FORCEINLINE
840 VOID
841 MiLockWorkingSet(IN PETHREAD Thread,
842 IN PMMSUPPORT WorkingSet)
843 {
844 /* Block APCs */
845 KeEnterGuardedRegion();
846
847 /* Working set should be in global memory */
848 ASSERT(MI_IS_SESSION_ADDRESS((PVOID)WorkingSet) == FALSE);
849
850 /* Thread shouldn't already be owning something */
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 /* Which working set is this? */
856 if (WorkingSet == &MmSystemCacheWs)
857 {
858 /* Own the system working set */
859 ASSERT((Thread->OwnsSystemWorkingSetExclusive == FALSE) &&
860 (Thread->OwnsSystemWorkingSetShared == FALSE));
861 Thread->OwnsSystemWorkingSetExclusive = TRUE;
862 }
863 else if (WorkingSet->Flags.SessionSpace)
864 {
865 /* We don't implement this yet */
866 UNIMPLEMENTED;
867 while (TRUE);
868 }
869 else
870 {
871 /* Own the process working set */
872 ASSERT((Thread->OwnsProcessWorkingSetExclusive == FALSE) &&
873 (Thread->OwnsProcessWorkingSetShared == FALSE));
874 Thread->OwnsProcessWorkingSetExclusive = TRUE;
875 }
876 }
877
878 //
879 // Unlocks the working set
880 //
881 FORCEINLINE
882 VOID
883 MiUnlockWorkingSet(IN PETHREAD Thread,
884 IN PMMSUPPORT WorkingSet)
885 {
886 /* Working set should be in global memory */
887 ASSERT(MI_IS_SESSION_ADDRESS((PVOID)WorkingSet) == FALSE);
888
889 /* Which working set is this? */
890 if (WorkingSet == &MmSystemCacheWs)
891 {
892 /* Release the system working set */
893 ASSERT((Thread->OwnsSystemWorkingSetExclusive == TRUE) ||
894 (Thread->OwnsSystemWorkingSetShared == TRUE));
895 Thread->OwnsSystemWorkingSetExclusive = FALSE;
896 }
897 else if (WorkingSet->Flags.SessionSpace)
898 {
899 /* We don't implement this yet */
900 UNIMPLEMENTED;
901 while (TRUE);
902 }
903 else
904 {
905 /* Release the process working set */
906 ASSERT((Thread->OwnsProcessWorkingSetExclusive) ||
907 (Thread->OwnsProcessWorkingSetShared));
908 Thread->OwnsProcessWorkingSetExclusive = FALSE;
909 }
910
911 /* FIXME: Actually release it (we can't because Vm is used by MAREAs) */
912
913 /* Unblock APCs */
914 KeLeaveGuardedRegion();
915 }
916
917 //
918 // Returns the ProtoPTE inside a VAD for the given VPN
919 //
920 FORCEINLINE
921 PMMPTE
922 MI_GET_PROTOTYPE_PTE_FOR_VPN(IN PMMVAD Vad,
923 IN ULONG_PTR Vpn)
924 {
925 PMMPTE ProtoPte;
926
927 /* Find the offset within the VAD's prototype PTEs */
928 ProtoPte = Vad->FirstPrototypePte + (Vpn - Vad->StartingVpn);
929 ASSERT(ProtoPte <= Vad->LastContiguousPte);
930 return ProtoPte;
931 }
932
933 //
934 // Returns the PFN Database entry for the given page number
935 // Warning: This is not necessarily a valid PFN database entry!
936 //
937 FORCEINLINE
938 PMMPFN
939 MI_PFN_ELEMENT(IN PFN_NUMBER Pfn)
940 {
941 /* Get the entry */
942 return &MmPfnDatabase[Pfn];
943 };
944
945 BOOLEAN
946 NTAPI
947 MmArmInitSystem(
948 IN ULONG Phase,
949 IN PLOADER_PARAMETER_BLOCK LoaderBlock
950 );
951
952 VOID
953 NTAPI
954 MiInitializeSessionSpaceLayout();
955
956 NTSTATUS
957 NTAPI
958 MiInitMachineDependent(
959 IN PLOADER_PARAMETER_BLOCK LoaderBlock
960 );
961
962 VOID
963 NTAPI
964 MiComputeColorInformation(
965 VOID
966 );
967
968 VOID
969 NTAPI
970 MiMapPfnDatabase(
971 IN PLOADER_PARAMETER_BLOCK LoaderBlock
972 );
973
974 VOID
975 NTAPI
976 MiInitializeColorTables(
977 VOID
978 );
979
980 VOID
981 NTAPI
982 MiInitializePfnDatabase(
983 IN PLOADER_PARAMETER_BLOCK LoaderBlock
984 );
985
986 BOOLEAN
987 NTAPI
988 MiInitializeMemoryEvents(
989 VOID
990 );
991
992 PFN_NUMBER
993 NTAPI
994 MxGetNextPage(
995 IN PFN_NUMBER PageCount
996 );
997
998 PPHYSICAL_MEMORY_DESCRIPTOR
999 NTAPI
1000 MmInitializeMemoryLimits(
1001 IN PLOADER_PARAMETER_BLOCK LoaderBlock,
1002 IN PBOOLEAN IncludeType
1003 );
1004
1005 PFN_NUMBER
1006 NTAPI
1007 MiPagesInLoaderBlock(
1008 IN PLOADER_PARAMETER_BLOCK LoaderBlock,
1009 IN PBOOLEAN IncludeType
1010 );
1011
1012 VOID
1013 FASTCALL
1014 MiSyncARM3WithROS(
1015 IN PVOID AddressStart,
1016 IN PVOID AddressEnd
1017 );
1018
1019 NTSTATUS
1020 NTAPI
1021 MmArmAccessFault(
1022 IN BOOLEAN StoreInstruction,
1023 IN PVOID Address,
1024 IN KPROCESSOR_MODE Mode,
1025 IN PVOID TrapInformation
1026 );
1027
1028 NTSTATUS
1029 FASTCALL
1030 MiCheckPdeForPagedPool(
1031 IN PVOID Address
1032 );
1033
1034 VOID
1035 NTAPI
1036 MiInitializeNonPagedPool(
1037 VOID
1038 );
1039
1040 VOID
1041 NTAPI
1042 MiInitializeNonPagedPoolThresholds(
1043 VOID
1044 );
1045
1046 VOID
1047 NTAPI
1048 MiInitializePoolEvents(
1049 VOID
1050 );
1051
1052 VOID //
1053 NTAPI //
1054 InitializePool( //
1055 IN POOL_TYPE PoolType,// FIXFIX: This should go in ex.h after the pool merge
1056 IN ULONG Threshold //
1057 ); //
1058
1059 VOID
1060 NTAPI
1061 MiInitializeSystemPtes(
1062 IN PMMPTE StartingPte,
1063 IN ULONG NumberOfPtes,
1064 IN MMSYSTEM_PTE_POOL_TYPE PoolType
1065 );
1066
1067 PMMPTE
1068 NTAPI
1069 MiReserveSystemPtes(
1070 IN ULONG NumberOfPtes,
1071 IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType
1072 );
1073
1074 VOID
1075 NTAPI
1076 MiReleaseSystemPtes(
1077 IN PMMPTE StartingPte,
1078 IN ULONG NumberOfPtes,
1079 IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType
1080 );
1081
1082
1083 PFN_NUMBER
1084 NTAPI
1085 MiFindContiguousPages(
1086 IN PFN_NUMBER LowestPfn,
1087 IN PFN_NUMBER HighestPfn,
1088 IN PFN_NUMBER BoundaryPfn,
1089 IN PFN_NUMBER SizeInPages,
1090 IN MEMORY_CACHING_TYPE CacheType
1091 );
1092
1093 PVOID
1094 NTAPI
1095 MiCheckForContiguousMemory(
1096 IN PVOID BaseAddress,
1097 IN PFN_NUMBER BaseAddressPages,
1098 IN PFN_NUMBER SizeInPages,
1099 IN PFN_NUMBER LowestPfn,
1100 IN PFN_NUMBER HighestPfn,
1101 IN PFN_NUMBER BoundaryPfn,
1102 IN MI_PFN_CACHE_ATTRIBUTE CacheAttribute
1103 );
1104
1105 PMDL
1106 NTAPI
1107 MiAllocatePagesForMdl(
1108 IN PHYSICAL_ADDRESS LowAddress,
1109 IN PHYSICAL_ADDRESS HighAddress,
1110 IN PHYSICAL_ADDRESS SkipBytes,
1111 IN SIZE_T TotalBytes,
1112 IN MI_PFN_CACHE_ATTRIBUTE CacheAttribute,
1113 IN ULONG Flags
1114 );
1115
1116 PVOID
1117 NTAPI
1118 MiMapLockedPagesInUserSpace(
1119 IN PMDL Mdl,
1120 IN PVOID BaseVa,
1121 IN MEMORY_CACHING_TYPE CacheType,
1122 IN PVOID BaseAddress
1123 );
1124
1125 VOID
1126 NTAPI
1127 MiUnmapLockedPagesInUserSpace(
1128 IN PVOID BaseAddress,
1129 IN PMDL Mdl
1130 );
1131
1132 VOID
1133 NTAPI
1134 MiInsertPageInList(
1135 IN PMMPFNLIST ListHead,
1136 IN PFN_NUMBER PageFrameIndex
1137 );
1138
1139 VOID
1140 NTAPI
1141 MiUnlinkFreeOrZeroedPage(
1142 IN PMMPFN Entry
1143 );
1144
1145 PFN_NUMBER
1146 NTAPI
1147 MiAllocatePfn(
1148 IN PMMPTE PointerPte,
1149 IN ULONG Protection
1150 );
1151
1152 VOID
1153 NTAPI
1154 MiInitializePfn(
1155 IN PFN_NUMBER PageFrameIndex,
1156 IN PMMPTE PointerPte,
1157 IN BOOLEAN Modified
1158 );
1159
1160 VOID
1161 NTAPI
1162 MiInitializePfnAndMakePteValid(
1163 IN PFN_NUMBER PageFrameIndex,
1164 IN PMMPTE PointerPte,
1165 IN MMPTE TempPte
1166 );
1167
1168 VOID
1169 NTAPI
1170 MiInitializePfnForOtherProcess(
1171 IN PFN_NUMBER PageFrameIndex,
1172 IN PMMPTE PointerPte,
1173 IN PFN_NUMBER PteFrame
1174 );
1175
1176 VOID
1177 NTAPI
1178 MiDecrementShareCount(
1179 IN PMMPFN Pfn1,
1180 IN PFN_NUMBER PageFrameIndex
1181 );
1182
1183 VOID
1184 NTAPI
1185 MiDecrementReferenceCount(
1186 IN PMMPFN Pfn1,
1187 IN PFN_NUMBER PageFrameIndex
1188 );
1189
1190 PFN_NUMBER
1191 NTAPI
1192 MiRemoveAnyPage(
1193 IN ULONG Color
1194 );
1195
1196 PFN_NUMBER
1197 NTAPI
1198 MiRemoveZeroPage(
1199 IN ULONG Color
1200 );
1201
1202 VOID
1203 NTAPI
1204 MiZeroPhysicalPage(
1205 IN PFN_NUMBER PageFrameIndex
1206 );
1207
1208 VOID
1209 NTAPI
1210 MiInsertPageInFreeList(
1211 IN PFN_NUMBER PageFrameIndex
1212 );
1213
1214 PFN_COUNT
1215 NTAPI
1216 MiDeleteSystemPageableVm(
1217 IN PMMPTE PointerPte,
1218 IN PFN_NUMBER PageCount,
1219 IN ULONG Flags,
1220 OUT PPFN_NUMBER ValidPages
1221 );
1222
1223 PLDR_DATA_TABLE_ENTRY
1224 NTAPI
1225 MiLookupDataTableEntry(
1226 IN PVOID Address
1227 );
1228
1229 VOID
1230 NTAPI
1231 MiInitializeDriverLargePageList(
1232 VOID
1233 );
1234
1235 VOID
1236 NTAPI
1237 MiInitializeLargePageSupport(
1238 VOID
1239 );
1240
1241 VOID
1242 NTAPI
1243 MiSyncCachedRanges(
1244 VOID
1245 );
1246
1247 BOOLEAN
1248 NTAPI
1249 MiIsPfnInUse(
1250 IN PMMPFN Pfn1
1251 );
1252
1253 PMMVAD
1254 NTAPI
1255 MiLocateAddress(
1256 IN PVOID VirtualAddress
1257 );
1258
1259 PMMADDRESS_NODE
1260 NTAPI
1261 MiCheckForConflictingNode(
1262 IN ULONG_PTR StartVpn,
1263 IN ULONG_PTR EndVpn,
1264 IN PMM_AVL_TABLE Table
1265 );
1266
1267 TABLE_SEARCH_RESULT
1268 NTAPI
1269 MiFindEmptyAddressRangeDownTree(
1270 IN SIZE_T Length,
1271 IN ULONG_PTR BoundaryAddress,
1272 IN ULONG_PTR Alignment,
1273 IN PMM_AVL_TABLE Table,
1274 OUT PULONG_PTR Base,
1275 OUT PMMADDRESS_NODE *Parent
1276 );
1277
1278 NTSTATUS
1279 NTAPI
1280 MiFindEmptyAddressRangeInTree(
1281 IN SIZE_T Length,
1282 IN ULONG_PTR Alignment,
1283 IN PMM_AVL_TABLE Table,
1284 OUT PMMADDRESS_NODE *PreviousVad,
1285 OUT PULONG_PTR Base
1286 );
1287
1288 VOID
1289 NTAPI
1290 MiInsertVad(
1291 IN PMMVAD Vad,
1292 IN PEPROCESS Process
1293 );
1294
1295 VOID
1296 NTAPI
1297 MiInsertNode(
1298 IN PMM_AVL_TABLE Table,
1299 IN PMMADDRESS_NODE NewNode,
1300 PMMADDRESS_NODE Parent,
1301 TABLE_SEARCH_RESULT Result
1302 );
1303
1304 VOID
1305 NTAPI
1306 MiRemoveNode(
1307 IN PMMADDRESS_NODE Node,
1308 IN PMM_AVL_TABLE Table
1309 );
1310
1311 PMMADDRESS_NODE
1312 NTAPI
1313 MiGetPreviousNode(
1314 IN PMMADDRESS_NODE Node
1315 );
1316
1317 PMMADDRESS_NODE
1318 NTAPI
1319 MiGetNextNode(
1320 IN PMMADDRESS_NODE Node
1321 );
1322
1323 BOOLEAN
1324 NTAPI
1325 MiInitializeSystemSpaceMap(
1326 IN PVOID InputSession OPTIONAL
1327 );
1328
1329 ULONG
1330 NTAPI
1331 MiMakeProtectionMask(
1332 IN ULONG Protect
1333 );
1334
1335 VOID
1336 NTAPI
1337 MiDeleteVirtualAddresses(
1338 IN ULONG_PTR Va,
1339 IN ULONG_PTR EndingAddress,
1340 IN PMMVAD Vad
1341 );
1342
1343 ULONG
1344 NTAPI
1345 MiMakeSystemAddressValid(
1346 IN PVOID PageTableVirtualAddress,
1347 IN PEPROCESS CurrentProcess
1348 );
1349
1350 ULONG
1351 NTAPI
1352 MiMakeSystemAddressValidPfn(
1353 IN PVOID VirtualAddress,
1354 IN KIRQL OldIrql
1355 );
1356
1357 VOID
1358 NTAPI
1359 MiRemoveMappedView(
1360 IN PEPROCESS CurrentProcess,
1361 IN PMMVAD Vad
1362 );
1363
1364 PSUBSECTION
1365 NTAPI
1366 MiLocateSubsection(
1367 IN PMMVAD Vad,
1368 IN ULONG_PTR Vpn
1369 );
1370
1371 //
1372 // MiRemoveZeroPage will use inline code to zero out the page manually if only
1373 // free pages are available. In some scenarios, we don't/can't run that piece of
1374 // code and would rather only have a real zero page. If we can't have a zero page,
1375 // then we'd like to have our own code to grab a free page and zero it out, by
1376 // using MiRemoveAnyPage. This macro implements this.
1377 //
1378 PFN_NUMBER
1379 FORCEINLINE
1380 MiRemoveZeroPageSafe(IN ULONG Color)
1381 {
1382 if (MmFreePagesByColor[ZeroedPageList][Color].Flink != LIST_HEAD) return MiRemoveZeroPage(Color);
1383 return 0;
1384 }
1385
1386 //
1387 // New ARM3<->RosMM PAGE Architecture
1388 //
1389 #ifdef _WIN64
1390 // HACK ON TOP OF HACK ALERT!!!
1391 #define MI_GET_ROS_DATA(x) \
1392 (((x)->RosMmData == 0) ? NULL : ((PMMROSPFN)((ULONG64)(ULONG)((x)->RosMmData) | \
1393 ((ULONG64)MmNonPagedPoolStart & 0xffffffff00000000ULL))))
1394 #else
1395 #define MI_GET_ROS_DATA(x) ((PMMROSPFN)(x->RosMmData))
1396 #endif
1397 #define MI_IS_ROS_PFN(x) (((x)->u4.AweAllocation == TRUE) && (MI_GET_ROS_DATA(x) != NULL))
1398 #define ASSERT_IS_ROS_PFN(x) ASSERT(MI_IS_ROS_PFN(x) == TRUE);
1399 typedef struct _MMROSPFN
1400 {
1401 PMM_RMAP_ENTRY RmapListHead;
1402 SWAPENTRY SwapEntry;
1403 } MMROSPFN, *PMMROSPFN;
1404
1405 #define RosMmData AweReferenceCount
1406
1407 /* EOF */