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