fbdfeabaa56254535775b69f30425c9db9640035
[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_MIN_PAGES_FOR_SYSPTE_BOOST_BOOST ((256 * _1MB) >> PAGE_SHIFT)
15 #define MI_MAX_INIT_NONPAGED_POOL_SIZE (128 * _1MB)
16 #define MI_MAX_NONPAGED_POOL_SIZE (128 * _1MB)
17 #define MI_MAX_FREE_PAGE_LISTS 4
18
19 #define MI_MIN_INIT_PAGED_POOLSIZE (32 * _1MB)
20
21 #define MI_SESSION_VIEW_SIZE (48 * _1MB)
22 #define MI_SESSION_POOL_SIZE (16 * _1MB)
23 #define MI_SESSION_IMAGE_SIZE (8 * _1MB)
24 #define MI_SESSION_WORKING_SET_SIZE (4 * _1MB)
25 #define MI_SESSION_SIZE (MI_SESSION_VIEW_SIZE + \
26 MI_SESSION_POOL_SIZE + \
27 MI_SESSION_IMAGE_SIZE + \
28 MI_SESSION_WORKING_SET_SIZE)
29
30 #define MI_SYSTEM_VIEW_SIZE (32 * _1MB)
31
32 #define MI_HIGHEST_USER_ADDRESS (PVOID)0x7FFEFFFF
33 #define MI_USER_PROBE_ADDRESS (PVOID)0x7FFF0000
34 #define MI_DEFAULT_SYSTEM_RANGE_START (PVOID)0x80000000
35 #define MI_SYSTEM_CACHE_WS_START (PVOID)0xC0C00000
36 #define MI_PAGED_POOL_START (PVOID)0xE1000000
37 #define MI_NONPAGED_POOL_END (PVOID)0xFFBE0000
38 #define MI_DEBUG_MAPPING (PVOID)0xFFBFF000
39
40 #define MI_SYSTEM_PTE_BASE (PVOID)MiAddressToPte(NULL)
41
42 #define MI_MIN_SECONDARY_COLORS 8
43 #define MI_SECONDARY_COLORS 64
44 #define MI_MAX_SECONDARY_COLORS 1024
45
46 #define MI_MIN_ALLOCATION_FRAGMENT (4 * _1KB)
47 #define MI_ALLOCATION_FRAGMENT (64 * _1KB)
48 #define MI_MAX_ALLOCATION_FRAGMENT (2 * _1MB)
49
50 #define MM_HIGHEST_VAD_ADDRESS \
51 (PVOID)((ULONG_PTR)MM_HIGHEST_USER_ADDRESS - (16 * PAGE_SIZE))
52 #define MI_LOWEST_VAD_ADDRESS (PVOID)MM_LOWEST_USER_ADDRESS
53
54 #define MI_DEFAULT_SYSTEM_PTE_COUNT 50000
55
56 #endif /* !_M_AMD64 */
57
58 /* Make the code cleaner with some definitions for size multiples */
59 #define _1KB (1024u)
60 #define _1MB (1024 * _1KB)
61 #define _1GB (1024 * _1MB)
62
63 /* Everyone loves 64K */
64 #define _64K (64 * _1KB)
65
66 /* Area mapped by a PDE */
67 #define PDE_MAPPED_VA (PTE_COUNT * PAGE_SIZE)
68
69 /* Size of a page table */
70 #define PT_SIZE (PTE_COUNT * sizeof(MMPTE))
71
72 /* Size of a page directory */
73 #define PD_SIZE (PDE_COUNT * sizeof(MMPDE))
74
75 /* Size of all page directories for a process */
76 #define SYSTEM_PD_SIZE (PD_COUNT * PD_SIZE)
77
78 /* Architecture specific count of PDEs in a directory, and count of PTEs in a PT */
79 #ifdef _M_IX86
80 #define PD_COUNT 1
81 #define PDE_COUNT 1024
82 #define PTE_COUNT 1024
83 C_ASSERT(SYSTEM_PD_SIZE == PAGE_SIZE);
84 #define MiIsPteOnPdeBoundary(PointerPte) \
85 ((((ULONG_PTR)PointerPte) & (PAGE_SIZE - 1)) == 0)
86 #elif _M_ARM
87 #define PD_COUNT 1
88 #define PDE_COUNT 4096
89 #define PTE_COUNT 256
90 #else
91 #define PD_COUNT PPE_PER_PAGE
92 #define PDE_COUNT PDE_PER_PAGE
93 #define PTE_COUNT PTE_PER_PAGE
94 #endif
95
96 //
97 // Protection Bits part of the internal memory manager Protection Mask, from:
98 // http://reactos.org/wiki/Techwiki:Memory_management_in_the_Windows_XP_kernel
99 // https://www.reactos.org/wiki/Techwiki:Memory_Protection_constants
100 // and public assertions.
101 //
102 #define MM_ZERO_ACCESS 0
103 #define MM_READONLY 1
104 #define MM_EXECUTE 2
105 #define MM_EXECUTE_READ 3
106 #define MM_READWRITE 4
107 #define MM_WRITECOPY 5
108 #define MM_EXECUTE_READWRITE 6
109 #define MM_EXECUTE_WRITECOPY 7
110 #define MM_PROTECT_ACCESS 7
111
112 //
113 // These are flags on top of the actual protection mask
114 //
115 #define MM_NOCACHE 0x08
116 #define MM_GUARDPAGE 0x10
117 #define MM_WRITECOMBINE 0x18
118 #define MM_PROTECT_SPECIAL 0x18
119
120 //
121 // These are special cases
122 //
123 #define MM_DECOMMIT (MM_ZERO_ACCESS | MM_GUARDPAGE)
124 #define MM_NOACCESS (MM_ZERO_ACCESS | MM_WRITECOMBINE)
125 #define MM_OUTSWAPPED_KSTACK (MM_EXECUTE_WRITECOPY | MM_WRITECOMBINE)
126 #define MM_INVALID_PROTECTION 0xFFFFFFFF
127
128 //
129 // Specific PTE Definitions that map to the Memory Manager's Protection Mask Bits
130 // The Memory Manager's definition define the attributes that must be preserved
131 // and these PTE definitions describe the attributes in the hardware sense. This
132 // helps deal with hardware differences between the actual boolean expression of
133 // the argument.
134 //
135 // For example, in the logical attributes, we want to express read-only as a flag
136 // but on x86, it is writability that must be set. On the other hand, on x86, just
137 // like in the kernel, it is disabling the caches that requires a special flag,
138 // while on certain architectures such as ARM, it is enabling the cache which
139 // requires a flag.
140 //
141 #if defined(_M_IX86) || defined(_M_AMD64)
142 //
143 // Access Flags
144 //
145 #define PTE_READONLY 0 // Doesn't exist on x86
146 #define PTE_EXECUTE 0 // Not worrying about NX yet
147 #define PTE_EXECUTE_READ 0 // Not worrying about NX yet
148 #define PTE_READWRITE 0x2
149 #define PTE_WRITECOPY 0x200
150 #define PTE_EXECUTE_READWRITE 0x2 // Not worrying about NX yet
151 #define PTE_EXECUTE_WRITECOPY 0x200
152 #define PTE_PROTOTYPE 0x400
153
154 //
155 // State Flags
156 //
157 #define PTE_VALID 0x1
158 #define PTE_ACCESSED 0x20
159 #define PTE_DIRTY 0x40
160
161 //
162 // Cache flags
163 //
164 #define PTE_ENABLE_CACHE 0
165 #define PTE_DISABLE_CACHE 0x10
166 #define PTE_WRITECOMBINED_CACHE 0x10
167 #elif defined(_M_ARM)
168 #define PTE_READONLY 0x200
169 #define PTE_EXECUTE 0 // Not worrying about NX yet
170 #define PTE_EXECUTE_READ 0 // Not worrying about NX yet
171 #define PTE_READWRITE 0 // Doesn't exist on ARM
172 #define PTE_WRITECOPY 0 // Doesn't exist on ARM
173 #define PTE_EXECUTE_READWRITE 0 // Not worrying about NX yet
174 #define PTE_EXECUTE_WRITECOPY 0 // Not worrying about NX yet
175 #define PTE_PROTOTYPE 0x400 // Using the Shared bit
176 //
177 // Cache flags
178 //
179 #define PTE_ENABLE_CACHE 0
180 #define PTE_DISABLE_CACHE 0x10
181 #define PTE_WRITECOMBINED_CACHE 0x10
182 #else
183 #error Define these please!
184 #endif
185
186 extern const ULONG_PTR MmProtectToPteMask[32];
187 extern const ULONG MmProtectToValue[32];
188
189 //
190 // Assertions for session images, addresses, and PTEs
191 //
192 #define MI_IS_SESSION_IMAGE_ADDRESS(Address) \
193 (((Address) >= MiSessionImageStart) && ((Address) < MiSessionImageEnd))
194
195 #define MI_IS_SESSION_ADDRESS(Address) \
196 (((Address) >= MmSessionBase) && ((Address) < MiSessionSpaceEnd))
197
198 #define MI_IS_SESSION_PTE(Pte) \
199 ((((PMMPTE)Pte) >= MiSessionBasePte) && (((PMMPTE)Pte) < MiSessionLastPte))
200
201 #define MI_IS_PAGE_TABLE_ADDRESS(Address) \
202 (((PVOID)(Address) >= (PVOID)PTE_BASE) && ((PVOID)(Address) <= (PVOID)PTE_TOP))
203
204 #define MI_IS_SYSTEM_PAGE_TABLE_ADDRESS(Address) \
205 (((Address) >= (PVOID)MiAddressToPte(MmSystemRangeStart)) && ((Address) <= (PVOID)PTE_TOP))
206
207 #define MI_IS_PAGE_TABLE_OR_HYPER_ADDRESS(Address) \
208 (((PVOID)(Address) >= (PVOID)PTE_BASE) && ((PVOID)(Address) <= (PVOID)MmHyperSpaceEnd))
209
210 //
211 // Corresponds to MMPTE_SOFTWARE.Protection
212 //
213 #ifdef _M_IX86
214 #define MM_PTE_SOFTWARE_PROTECTION_BITS 5
215 #elif _M_ARM
216 #define MM_PTE_SOFTWARE_PROTECTION_BITS 6
217 #elif _M_AMD64
218 #define MM_PTE_SOFTWARE_PROTECTION_BITS 5
219 #else
220 #error Define these please!
221 #endif
222
223 //
224 // Creates a software PTE with the given protection
225 //
226 #define MI_MAKE_SOFTWARE_PTE(p, x) ((p)->u.Long = (x << MM_PTE_SOFTWARE_PROTECTION_BITS))
227
228 //
229 // Marks a PTE as deleted
230 //
231 #define MI_SET_PFN_DELETED(x) ((x)->PteAddress = (PMMPTE)((ULONG_PTR)(x)->PteAddress | 1))
232 #define MI_IS_PFN_DELETED(x) ((ULONG_PTR)((x)->PteAddress) & 1)
233
234 //
235 // Special values for LoadedImports
236 //
237 #define MM_SYSLDR_NO_IMPORTS (PVOID)0xFFFFFFFE
238 #define MM_SYSLDR_BOOT_LOADED (PVOID)0xFFFFFFFF
239 #define MM_SYSLDR_SINGLE_ENTRY 0x1
240
241 //
242 // Number of initial session IDs
243 //
244 #define MI_INITIAL_SESSION_IDS 64
245
246 #if defined(_M_IX86) || defined(_M_ARM)
247 //
248 // PFN List Sentinel
249 //
250 #define LIST_HEAD 0xFFFFFFFF
251
252 //
253 // Because GCC cannot automatically downcast 0xFFFFFFFF to lesser-width bits,
254 // we need a manual definition suited to the number of bits in the PteFrame.
255 // This is used as a LIST_HEAD for the colored list
256 //
257 #define COLORED_LIST_HEAD ((1 << 25) - 1) // 0x1FFFFFF
258 #elif defined(_M_AMD64)
259 #define LIST_HEAD 0xFFFFFFFFFFFFFFFFLL
260 #define COLORED_LIST_HEAD ((1ULL << 57) - 1) // 0x1FFFFFFFFFFFFFFLL
261 #else
262 #error Define these please!
263 #endif
264
265 //
266 // Special IRQL value (found in assertions)
267 //
268 #define MM_NOIRQL (KIRQL)0xFFFFFFFF
269
270 //
271 // Returns the color of a page
272 //
273 #define MI_GET_PAGE_COLOR(x) ((x) & MmSecondaryColorMask)
274 #define MI_GET_NEXT_COLOR() (MI_GET_PAGE_COLOR(++MmSystemPageColor))
275 #define MI_GET_NEXT_PROCESS_COLOR(x) (MI_GET_PAGE_COLOR(++(x)->NextPageColor))
276
277 #ifndef _M_AMD64
278 //
279 // Decodes a Prototype PTE into the underlying PTE
280 //
281 #define MiProtoPteToPte(x) \
282 (PMMPTE)((ULONG_PTR)MmPagedPoolStart + \
283 (((x)->u.Proto.ProtoAddressHigh << 9) | (x)->u.Proto.ProtoAddressLow << 2))
284
285 //
286 // Decodes a Prototype PTE into the underlying PTE
287 //
288 #define MiSubsectionPteToSubsection(x) \
289 ((x)->u.Subsect.WhichPool == PagedPool) ? \
290 (PMMPTE)((ULONG_PTR)MmSubsectionBase + \
291 (((x)->u.Subsect.SubsectionAddressHigh << 7) | \
292 (x)->u.Subsect.SubsectionAddressLow << 3)) : \
293 (PMMPTE)((ULONG_PTR)MmNonPagedPoolEnd - \
294 (((x)->u.Subsect.SubsectionAddressHigh << 7) | \
295 (x)->u.Subsect.SubsectionAddressLow << 3))
296 #endif
297
298 //
299 // Prototype PTEs that don't yet have a pagefile association
300 //
301 #ifdef _M_AMD64
302 #define MI_PTE_LOOKUP_NEEDED 0xffffffffULL
303 #else
304 #define MI_PTE_LOOKUP_NEEDED 0xFFFFF
305 #endif
306
307 //
308 // Number of session lists in the MM_SESSIONS_SPACE structure
309 //
310 #if defined(_M_AMD64)
311 #define SESSION_POOL_LOOKASIDES 21
312 #elif defined(_M_IX86)
313 #define SESSION_POOL_LOOKASIDES 26
314 #else
315 #error Not Defined!
316 #endif
317
318 //
319 // Number of session data and tag pages
320 //
321 #define MI_SESSION_DATA_PAGES_MAXIMUM (MM_ALLOCATION_GRANULARITY / PAGE_SIZE)
322 #define MI_SESSION_TAG_PAGES_MAXIMUM (MM_ALLOCATION_GRANULARITY / PAGE_SIZE)
323
324 //
325 // Used by MiCheckSecuredVad
326 //
327 #define MM_READ_WRITE_ALLOWED 11
328 #define MM_READ_ONLY_ALLOWED 10
329 #define MM_NO_ACCESS_ALLOWED 01
330 #define MM_DELETE_CHECK 85
331
332 //
333 // System views are binned into 64K chunks
334 //
335 #define MI_SYSTEM_VIEW_BUCKET_SIZE _64K
336
337 //
338 // FIXFIX: These should go in ex.h after the pool merge
339 //
340 #ifdef _M_AMD64
341 #define POOL_BLOCK_SIZE 16
342 #else
343 #define POOL_BLOCK_SIZE 8
344 #endif
345 #define POOL_LISTS_PER_PAGE (PAGE_SIZE / POOL_BLOCK_SIZE)
346 #define BASE_POOL_TYPE_MASK 1
347 #define POOL_MAX_ALLOC (PAGE_SIZE - (sizeof(POOL_HEADER) + POOL_BLOCK_SIZE))
348
349 //
350 // Pool debugging/analysis/tracing flags
351 //
352 #define POOL_FLAG_CHECK_TIMERS 0x1
353 #define POOL_FLAG_CHECK_WORKERS 0x2
354 #define POOL_FLAG_CHECK_RESOURCES 0x4
355 #define POOL_FLAG_VERIFIER 0x8
356 #define POOL_FLAG_CHECK_DEADLOCK 0x10
357 #define POOL_FLAG_SPECIAL_POOL 0x20
358 #define POOL_FLAG_DBGPRINT_ON_FAILURE 0x40
359 #define POOL_FLAG_CRASH_ON_FAILURE 0x80
360
361 //
362 // BAD_POOL_HEADER codes during pool bugcheck
363 //
364 #define POOL_CORRUPTED_LIST 3
365 #define POOL_SIZE_OR_INDEX_MISMATCH 5
366 #define POOL_ENTRIES_NOT_ALIGNED_PREVIOUS 6
367 #define POOL_HEADER_NOT_ALIGNED 7
368 #define POOL_HEADER_IS_ZERO 8
369 #define POOL_ENTRIES_NOT_ALIGNED_NEXT 9
370 #define POOL_ENTRY_NOT_FOUND 10
371
372 //
373 // BAD_POOL_CALLER codes during pool bugcheck
374 //
375 #define POOL_ENTRY_CORRUPTED 1
376 #define POOL_ENTRY_ALREADY_FREE 6
377 #define POOL_ENTRY_NOT_ALLOCATED 7
378 #define POOL_ALLOC_IRQL_INVALID 8
379 #define POOL_FREE_IRQL_INVALID 9
380 #define POOL_BILLED_PROCESS_INVALID 13
381 #define POOL_HEADER_SIZE_INVALID 32
382
383 typedef struct _POOL_DESCRIPTOR
384 {
385 POOL_TYPE PoolType;
386 ULONG PoolIndex;
387 ULONG RunningAllocs;
388 ULONG RunningDeAllocs;
389 ULONG TotalPages;
390 ULONG TotalBigPages;
391 ULONG Threshold;
392 PVOID LockAddress;
393 PVOID PendingFrees;
394 LONG PendingFreeDepth;
395 SIZE_T TotalBytes;
396 SIZE_T Spare0;
397 LIST_ENTRY ListHeads[POOL_LISTS_PER_PAGE];
398 } POOL_DESCRIPTOR, *PPOOL_DESCRIPTOR;
399
400 typedef struct _POOL_HEADER
401 {
402 union
403 {
404 struct
405 {
406 #ifdef _M_AMD64
407 USHORT PreviousSize:8;
408 USHORT PoolIndex:8;
409 USHORT BlockSize:8;
410 USHORT PoolType:8;
411 #else
412 USHORT PreviousSize:9;
413 USHORT PoolIndex:7;
414 USHORT BlockSize:9;
415 USHORT PoolType:7;
416 #endif
417 };
418 ULONG Ulong1;
419 };
420 #ifdef _M_AMD64
421 ULONG PoolTag;
422 #endif
423 union
424 {
425 #ifdef _M_AMD64
426 PEPROCESS ProcessBilled;
427 #else
428 ULONG PoolTag;
429 #endif
430 struct
431 {
432 USHORT AllocatorBackTraceIndex;
433 USHORT PoolTagHash;
434 };
435 };
436 } POOL_HEADER, *PPOOL_HEADER;
437
438 C_ASSERT(sizeof(POOL_HEADER) == POOL_BLOCK_SIZE);
439 C_ASSERT(POOL_BLOCK_SIZE == sizeof(LIST_ENTRY));
440
441 typedef struct _POOL_TRACKER_TABLE
442 {
443 ULONG Key;
444 LONG NonPagedAllocs;
445 LONG NonPagedFrees;
446 SIZE_T NonPagedBytes;
447 LONG PagedAllocs;
448 LONG PagedFrees;
449 SIZE_T PagedBytes;
450 } POOL_TRACKER_TABLE, *PPOOL_TRACKER_TABLE;
451
452 typedef struct _POOL_TRACKER_BIG_PAGES
453 {
454 PVOID Va;
455 ULONG Key;
456 ULONG NumberOfPages;
457 PVOID QuotaObject;
458 } POOL_TRACKER_BIG_PAGES, *PPOOL_TRACKER_BIG_PAGES;
459
460 extern ULONG ExpNumberOfPagedPools;
461 extern POOL_DESCRIPTOR NonPagedPoolDescriptor;
462 extern PPOOL_DESCRIPTOR ExpPagedPoolDescriptor[16 + 1];
463 extern PPOOL_TRACKER_TABLE PoolTrackTable;
464
465 //
466 // END FIXFIX
467 //
468
469 typedef struct _MI_LARGE_PAGE_DRIVER_ENTRY
470 {
471 LIST_ENTRY Links;
472 UNICODE_STRING BaseName;
473 } MI_LARGE_PAGE_DRIVER_ENTRY, *PMI_LARGE_PAGE_DRIVER_ENTRY;
474
475 typedef enum _MMSYSTEM_PTE_POOL_TYPE
476 {
477 SystemPteSpace,
478 NonPagedPoolExpansion,
479 MaximumPtePoolTypes
480 } MMSYSTEM_PTE_POOL_TYPE;
481
482 typedef enum _MI_PFN_CACHE_ATTRIBUTE
483 {
484 MiNonCached,
485 MiCached,
486 MiWriteCombined,
487 MiNotMapped
488 } MI_PFN_CACHE_ATTRIBUTE, *PMI_PFN_CACHE_ATTRIBUTE;
489
490 typedef struct _PHYSICAL_MEMORY_RUN
491 {
492 PFN_NUMBER BasePage;
493 PFN_NUMBER PageCount;
494 } PHYSICAL_MEMORY_RUN, *PPHYSICAL_MEMORY_RUN;
495
496 typedef struct _PHYSICAL_MEMORY_DESCRIPTOR
497 {
498 ULONG NumberOfRuns;
499 PFN_NUMBER NumberOfPages;
500 PHYSICAL_MEMORY_RUN Run[1];
501 } PHYSICAL_MEMORY_DESCRIPTOR, *PPHYSICAL_MEMORY_DESCRIPTOR;
502
503 typedef struct _MMCOLOR_TABLES
504 {
505 PFN_NUMBER Flink;
506 PVOID Blink;
507 PFN_NUMBER Count;
508 } MMCOLOR_TABLES, *PMMCOLOR_TABLES;
509
510 typedef struct _MI_LARGE_PAGE_RANGES
511 {
512 PFN_NUMBER StartFrame;
513 PFN_NUMBER LastFrame;
514 } MI_LARGE_PAGE_RANGES, *PMI_LARGE_PAGE_RANGES;
515
516 typedef struct _MMVIEW
517 {
518 ULONG_PTR Entry;
519 PCONTROL_AREA ControlArea;
520 } MMVIEW, *PMMVIEW;
521
522 typedef struct _MMSESSION
523 {
524 KGUARDED_MUTEX SystemSpaceViewLock;
525 PKGUARDED_MUTEX SystemSpaceViewLockPointer;
526 PCHAR SystemSpaceViewStart;
527 PMMVIEW SystemSpaceViewTable;
528 ULONG SystemSpaceHashSize;
529 ULONG SystemSpaceHashEntries;
530 ULONG SystemSpaceHashKey;
531 ULONG BitmapFailures;
532 PRTL_BITMAP SystemSpaceBitMap;
533 } MMSESSION, *PMMSESSION;
534
535 typedef struct _MM_SESSION_SPACE_FLAGS
536 {
537 ULONG Initialized:1;
538 ULONG DeletePending:1;
539 ULONG Filler:30;
540 } MM_SESSION_SPACE_FLAGS;
541
542 typedef struct _MM_SESSION_SPACE
543 {
544 struct _MM_SESSION_SPACE *GlobalVirtualAddress;
545 LONG ReferenceCount;
546 union
547 {
548 ULONG LongFlags;
549 MM_SESSION_SPACE_FLAGS Flags;
550 } u;
551 ULONG SessionId;
552 LIST_ENTRY ProcessList;
553 LARGE_INTEGER LastProcessSwappedOutTime;
554 PFN_NUMBER SessionPageDirectoryIndex;
555 SIZE_T NonPageablePages;
556 SIZE_T CommittedPages;
557 PVOID PagedPoolStart;
558 PVOID PagedPoolEnd;
559 PMMPTE PagedPoolBasePde;
560 ULONG Color;
561 LONG ResidentProcessCount;
562 ULONG SessionPoolAllocationFailures[4];
563 LIST_ENTRY ImageList;
564 LCID LocaleId;
565 ULONG AttachCount;
566 KEVENT AttachEvent;
567 PEPROCESS LastProcess;
568 LONG ProcessReferenceToSession;
569 LIST_ENTRY WsListEntry;
570 GENERAL_LOOKASIDE Lookaside[SESSION_POOL_LOOKASIDES];
571 MMSESSION Session;
572 KGUARDED_MUTEX PagedPoolMutex;
573 MM_PAGED_POOL_INFO PagedPoolInfo;
574 MMSUPPORT Vm;
575 PMMWSLE Wsle;
576 PDRIVER_UNLOAD Win32KDriverUnload;
577 POOL_DESCRIPTOR PagedPool;
578 #if defined (_M_AMD64)
579 MMPTE PageDirectory;
580 #else
581 PMMPTE PageTables;
582 #endif
583 #if defined (_M_AMD64)
584 PMMPTE SpecialPoolFirstPte;
585 PMMPTE SpecialPoolLastPte;
586 PMMPTE NextPdeForSpecialPoolExpansion;
587 PMMPTE LastPdeForSpecialPoolExpansion;
588 PFN_NUMBER SpecialPagesInUse;
589 #endif
590 LONG ImageLoadingCount;
591 } MM_SESSION_SPACE, *PMM_SESSION_SPACE;
592
593 extern PMM_SESSION_SPACE MmSessionSpace;
594 extern MMPTE HyperTemplatePte;
595 extern MMPDE ValidKernelPde;
596 extern MMPTE ValidKernelPte;
597 extern MMPDE ValidKernelPdeLocal;
598 extern MMPTE ValidKernelPteLocal;
599 extern MMPDE DemandZeroPde;
600 extern MMPTE DemandZeroPte;
601 extern MMPTE PrototypePte;
602 extern MMPTE MmDecommittedPte;
603 extern BOOLEAN MmLargeSystemCache;
604 extern BOOLEAN MmZeroPageFile;
605 extern BOOLEAN MmProtectFreedNonPagedPool;
606 extern BOOLEAN MmTrackLockedPages;
607 extern BOOLEAN MmTrackPtes;
608 extern BOOLEAN MmDynamicPfn;
609 extern BOOLEAN MmMirroring;
610 extern BOOLEAN MmMakeLowMemory;
611 extern BOOLEAN MmEnforceWriteProtection;
612 extern SIZE_T MmAllocationFragment;
613 extern ULONG MmConsumedPoolPercentage;
614 extern ULONG MmVerifyDriverBufferType;
615 extern ULONG MmVerifyDriverLevel;
616 extern WCHAR MmVerifyDriverBuffer[512];
617 extern WCHAR MmLargePageDriverBuffer[512];
618 extern LIST_ENTRY MiLargePageDriverList;
619 extern BOOLEAN MiLargePageAllDrivers;
620 extern ULONG MmVerifyDriverBufferLength;
621 extern ULONG MmLargePageDriverBufferLength;
622 extern SIZE_T MmSizeOfNonPagedPoolInBytes;
623 extern SIZE_T MmMaximumNonPagedPoolInBytes;
624 extern PFN_NUMBER MmMaximumNonPagedPoolInPages;
625 extern PFN_NUMBER MmSizeOfPagedPoolInPages;
626 extern PVOID MmNonPagedSystemStart;
627 extern SIZE_T MiNonPagedSystemSize;
628 extern PVOID MmNonPagedPoolStart;
629 extern PVOID MmNonPagedPoolExpansionStart;
630 extern PVOID MmNonPagedPoolEnd;
631 extern SIZE_T MmSizeOfPagedPoolInBytes;
632 extern PVOID MmPagedPoolStart;
633 extern PVOID MmPagedPoolEnd;
634 extern PVOID MmSessionBase;
635 extern SIZE_T MmSessionSize;
636 extern PMMPTE MmFirstReservedMappingPte, MmLastReservedMappingPte;
637 extern PMMPTE MiFirstReservedZeroingPte;
638 extern MI_PFN_CACHE_ATTRIBUTE MiPlatformCacheAttributes[2][MmMaximumCacheType];
639 extern PPHYSICAL_MEMORY_DESCRIPTOR MmPhysicalMemoryBlock;
640 extern SIZE_T MmBootImageSize;
641 extern PMMPTE MmSystemPtesStart[MaximumPtePoolTypes];
642 extern PMMPTE MmSystemPtesEnd[MaximumPtePoolTypes];
643 extern PMEMORY_ALLOCATION_DESCRIPTOR MxFreeDescriptor;
644 extern MEMORY_ALLOCATION_DESCRIPTOR MxOldFreeDescriptor;
645 extern ULONG_PTR MxPfnAllocation;
646 extern MM_PAGED_POOL_INFO MmPagedPoolInfo;
647 extern RTL_BITMAP MiPfnBitMap;
648 extern KGUARDED_MUTEX MmPagedPoolMutex;
649 extern KGUARDED_MUTEX MmSectionCommitMutex;
650 extern PVOID MmPagedPoolStart;
651 extern PVOID MmPagedPoolEnd;
652 extern PVOID MmNonPagedSystemStart;
653 extern PVOID MiSystemViewStart;
654 extern SIZE_T MmSystemViewSize;
655 extern PVOID MmSessionBase;
656 extern PVOID MiSessionSpaceEnd;
657 extern PMMPTE MiSessionImagePteStart;
658 extern PMMPTE MiSessionImagePteEnd;
659 extern PMMPTE MiSessionBasePte;
660 extern PMMPTE MiSessionLastPte;
661 extern SIZE_T MmSizeOfPagedPoolInBytes;
662 extern PMMPDE MmSystemPagePtes;
663 extern PVOID MmSystemCacheStart;
664 extern PVOID MmSystemCacheEnd;
665 extern MMSUPPORT MmSystemCacheWs;
666 extern SIZE_T MmAllocatedNonPagedPool;
667 extern ULONG MmSpecialPoolTag;
668 extern PVOID MmHyperSpaceEnd;
669 extern PMMWSL MmSystemCacheWorkingSetList;
670 extern SIZE_T MmMinimumNonPagedPoolSize;
671 extern ULONG MmMinAdditionNonPagedPoolPerMb;
672 extern SIZE_T MmDefaultMaximumNonPagedPool;
673 extern ULONG MmMaxAdditionNonPagedPoolPerMb;
674 extern ULONG MmSecondaryColors;
675 extern ULONG MmSecondaryColorMask;
676 extern ULONG MmNumberOfSystemPtes;
677 extern ULONG MmMaximumNonPagedPoolPercent;
678 extern ULONG MmLargeStackSize;
679 extern PMMCOLOR_TABLES MmFreePagesByColor[FreePageList + 1];
680 extern MMPFNLIST MmStandbyPageListByPriority[8];
681 extern ULONG MmProductType;
682 extern MM_SYSTEMSIZE MmSystemSize;
683 extern PKEVENT MiLowMemoryEvent;
684 extern PKEVENT MiHighMemoryEvent;
685 extern PKEVENT MiLowPagedPoolEvent;
686 extern PKEVENT MiHighPagedPoolEvent;
687 extern PKEVENT MiLowNonPagedPoolEvent;
688 extern PKEVENT MiHighNonPagedPoolEvent;
689 extern PFN_NUMBER MmLowMemoryThreshold;
690 extern PFN_NUMBER MmHighMemoryThreshold;
691 extern PFN_NUMBER MiLowPagedPoolThreshold;
692 extern PFN_NUMBER MiHighPagedPoolThreshold;
693 extern PFN_NUMBER MiLowNonPagedPoolThreshold;
694 extern PFN_NUMBER MiHighNonPagedPoolThreshold;
695 extern PFN_NUMBER MmMinimumFreePages;
696 extern PFN_NUMBER MmPlentyFreePages;
697 extern SIZE_T MmMinimumStackCommitInBytes;
698 extern PFN_COUNT MiExpansionPoolPagesInitialCharge;
699 extern PFN_NUMBER MmResidentAvailablePages;
700 extern PFN_NUMBER MmResidentAvailableAtInit;
701 extern ULONG MmTotalFreeSystemPtes[MaximumPtePoolTypes];
702 extern PFN_NUMBER MmTotalSystemDriverPages;
703 extern ULONG MmCritsectTimeoutSeconds;
704 extern PVOID MiSessionImageStart;
705 extern PVOID MiSessionImageEnd;
706 extern PMMPTE MiHighestUserPte;
707 extern PMMPDE MiHighestUserPde;
708 extern PFN_NUMBER MmSystemPageDirectory[PD_COUNT];
709 extern PMMPTE MmSharedUserDataPte;
710 extern LIST_ENTRY MmProcessList;
711 extern BOOLEAN MmZeroingPageThreadActive;
712 extern KEVENT MmZeroingPageEvent;
713 extern ULONG MmSystemPageColor;
714 extern ULONG MmProcessColorSeed;
715 extern PMMWSL MmWorkingSetList;
716 extern PFN_NUMBER MiNumberOfFreePages;
717 extern SIZE_T MmSessionViewSize;
718 extern SIZE_T MmSessionPoolSize;
719 extern SIZE_T MmSessionImageSize;
720 extern PVOID MiSystemViewStart;
721 extern PVOID MiSessionPoolEnd; // 0xBE000000
722 extern PVOID MiSessionPoolStart; // 0xBD000000
723 extern PVOID MiSessionViewStart; // 0xBE000000
724 extern PVOID MiSessionSpaceWs;
725 extern ULONG MmMaximumDeadKernelStacks;
726 extern SLIST_HEADER MmDeadStackSListHead;
727 extern MM_AVL_TABLE MmSectionBasedRoot;
728 extern KGUARDED_MUTEX MmSectionBasedMutex;
729 extern PVOID MmHighSectionBase;
730 extern SIZE_T MmSystemLockPagesCount;
731 extern ULONG_PTR MmSubsectionBase;
732 extern LARGE_INTEGER MmCriticalSectionTimeout;
733 extern LIST_ENTRY MmWorkingSetExpansionHead;
734
735 FORCEINLINE
736 BOOLEAN
737 MiIsMemoryTypeFree(TYPE_OF_MEMORY MemoryType)
738 {
739 return ((MemoryType == LoaderFree) ||
740 (MemoryType == LoaderLoadedProgram) ||
741 (MemoryType == LoaderFirmwareTemporary) ||
742 (MemoryType == LoaderOsloaderStack));
743 }
744
745 FORCEINLINE
746 BOOLEAN
747 MiIsMemoryTypeInvisible(TYPE_OF_MEMORY MemoryType)
748 {
749 return ((MemoryType == LoaderFirmwarePermanent) ||
750 (MemoryType == LoaderSpecialMemory) ||
751 (MemoryType == LoaderHALCachedMemory) ||
752 (MemoryType == LoaderBBTMemory));
753 }
754
755 #ifdef _M_AMD64
756 FORCEINLINE
757 BOOLEAN
758 MiIsUserPxe(PVOID Address)
759 {
760 return ((ULONG_PTR)Address >> 7) == 0x1FFFFEDF6FB7DA0ULL;
761 }
762
763 FORCEINLINE
764 BOOLEAN
765 MiIsUserPpe(PVOID Address)
766 {
767 return ((ULONG_PTR)Address >> 16) == 0xFFFFF6FB7DA0ULL;
768 }
769
770 FORCEINLINE
771 BOOLEAN
772 MiIsUserPde(PVOID Address)
773 {
774 return ((ULONG_PTR)Address >> 25) == 0x7FFFFB7DA0ULL;
775 }
776
777 FORCEINLINE
778 BOOLEAN
779 MiIsUserPte(PVOID Address)
780 {
781 return ((ULONG_PTR)Address >> 34) == 0x3FFFFDA0ULL;
782 }
783 #else
784 FORCEINLINE
785 BOOLEAN
786 MiIsUserPde(PVOID Address)
787 {
788 return ((Address >= (PVOID)MiAddressToPde(NULL)) &&
789 (Address <= (PVOID)MiHighestUserPde));
790 }
791
792 FORCEINLINE
793 BOOLEAN
794 MiIsUserPte(PVOID Address)
795 {
796 return (Address <= (PVOID)MiHighestUserPte);
797 }
798 #endif
799
800 //
801 // Figures out the hardware bits for a PTE
802 //
803 FORCEINLINE
804 ULONG_PTR
805 MiDetermineUserGlobalPteMask(IN PVOID PointerPte)
806 {
807 MMPTE TempPte;
808
809 /* Start fresh */
810 TempPte.u.Long = 0;
811
812 /* Make it valid and accessed */
813 TempPte.u.Hard.Valid = TRUE;
814 MI_MAKE_ACCESSED_PAGE(&TempPte);
815
816 /* Is this for user-mode? */
817 if (
818 #if (_MI_PAGING_LEVELS == 4)
819 MiIsUserPxe(PointerPte) ||
820 #endif
821 #if (_MI_PAGING_LEVELS >= 3)
822 MiIsUserPpe(PointerPte) ||
823 #endif
824 MiIsUserPde(PointerPte) ||
825 MiIsUserPte(PointerPte))
826 {
827 /* Set the owner bit */
828 MI_MAKE_OWNER_PAGE(&TempPte);
829 }
830
831 /* FIXME: We should also set the global bit */
832
833 /* Return the protection */
834 return TempPte.u.Long;
835 }
836
837 //
838 // Creates a valid kernel PTE with the given protection
839 //
840 FORCEINLINE
841 VOID
842 MI_MAKE_HARDWARE_PTE_KERNEL(IN PMMPTE NewPte,
843 IN PMMPTE MappingPte,
844 IN ULONG_PTR ProtectionMask,
845 IN PFN_NUMBER PageFrameNumber)
846 {
847 /* Only valid for kernel, non-session PTEs */
848 ASSERT(MappingPte > MiHighestUserPte);
849 ASSERT(!MI_IS_SESSION_PTE(MappingPte));
850 ASSERT((MappingPte < (PMMPTE)PDE_BASE) || (MappingPte > (PMMPTE)PDE_TOP));
851
852 /* Start fresh */
853 *NewPte = ValidKernelPte;
854
855 /* Set the protection and page */
856 NewPte->u.Hard.PageFrameNumber = PageFrameNumber;
857 NewPte->u.Long |= MmProtectToPteMask[ProtectionMask];
858 }
859
860 //
861 // Creates a valid PTE with the given protection
862 //
863 FORCEINLINE
864 VOID
865 MI_MAKE_HARDWARE_PTE(IN PMMPTE NewPte,
866 IN PMMPTE MappingPte,
867 IN ULONG_PTR ProtectionMask,
868 IN PFN_NUMBER PageFrameNumber)
869 {
870 /* Set the protection and page */
871 NewPte->u.Long = MiDetermineUserGlobalPteMask(MappingPte);
872 NewPte->u.Long |= MmProtectToPteMask[ProtectionMask];
873 NewPte->u.Hard.PageFrameNumber = PageFrameNumber;
874 }
875
876 //
877 // Creates a valid user PTE with the given protection
878 //
879 FORCEINLINE
880 VOID
881 MI_MAKE_HARDWARE_PTE_USER(IN PMMPTE NewPte,
882 IN PMMPTE MappingPte,
883 IN ULONG_PTR ProtectionMask,
884 IN PFN_NUMBER PageFrameNumber)
885 {
886 /* Only valid for kernel, non-session PTEs */
887 ASSERT(MappingPte <= MiHighestUserPte);
888
889 /* Start fresh */
890 *NewPte = ValidKernelPte;
891
892 /* Set the protection and page */
893 NewPte->u.Hard.Owner = TRUE;
894 NewPte->u.Hard.PageFrameNumber = PageFrameNumber;
895 NewPte->u.Long |= MmProtectToPteMask[ProtectionMask];
896 }
897
898 #ifndef _M_AMD64
899 //
900 // Builds a Prototype PTE for the address of the PTE
901 //
902 FORCEINLINE
903 VOID
904 MI_MAKE_PROTOTYPE_PTE(IN PMMPTE NewPte,
905 IN PMMPTE PointerPte)
906 {
907 ULONG_PTR Offset;
908
909 /* Mark this as a prototype */
910 NewPte->u.Long = 0;
911 NewPte->u.Proto.Prototype = 1;
912
913 /*
914 * Prototype PTEs are only valid in paged pool by design, this little trick
915 * lets us only use 30 bits for the adress of the PTE, as long as the area
916 * stays 1024MB At most.
917 */
918 Offset = (ULONG_PTR)PointerPte - (ULONG_PTR)MmPagedPoolStart;
919
920 /*
921 * 7 bits go in the "low" (but we assume the bottom 2 are zero)
922 * and the other 21 bits go in the "high"
923 */
924 NewPte->u.Proto.ProtoAddressLow = (Offset & 0x1FC) >> 2;
925 NewPte->u.Proto.ProtoAddressHigh = (Offset & 0x3FFFFE00) >> 9;
926 }
927
928 //
929 // Builds a Subsection PTE for the address of the Segment
930 //
931 FORCEINLINE
932 VOID
933 MI_MAKE_SUBSECTION_PTE(IN PMMPTE NewPte,
934 IN PVOID Segment)
935 {
936 ULONG_PTR Offset;
937
938 /* Mark this as a prototype */
939 NewPte->u.Long = 0;
940 NewPte->u.Subsect.Prototype = 1;
941
942 /*
943 * Segments are only valid either in nonpaged pool. We store the 20 bit
944 * difference either from the top or bottom of nonpaged pool, giving a
945 * maximum of 128MB to each delta, meaning nonpaged pool cannot exceed
946 * 256MB.
947 */
948 if ((ULONG_PTR)Segment < ((ULONG_PTR)MmSubsectionBase + (128 * _1MB)))
949 {
950 Offset = (ULONG_PTR)Segment - (ULONG_PTR)MmSubsectionBase;
951 NewPte->u.Subsect.WhichPool = PagedPool;
952 }
953 else
954 {
955 Offset = (ULONG_PTR)MmNonPagedPoolEnd - (ULONG_PTR)Segment;
956 NewPte->u.Subsect.WhichPool = NonPagedPool;
957 }
958
959 /*
960 * 4 bits go in the "low" (but we assume the bottom 3 are zero)
961 * and the other 20 bits go in the "high"
962 */
963 NewPte->u.Subsect.SubsectionAddressLow = (Offset & 0x78) >> 3;
964 NewPte->u.Subsect.SubsectionAddressHigh = (Offset & 0xFFFFF80) >> 7;
965 }
966
967 FORCEINLINE
968 BOOLEAN
969 MI_IS_MAPPED_PTE(PMMPTE PointerPte)
970 {
971 /// \todo Make this reasonable code, this is UGLY!
972 return ((PointerPte->u.Long & 0xFFFFFC01) != 0);
973 }
974
975 #endif
976
977 //
978 // Returns if the page is physically resident (ie: a large page)
979 // FIXFIX: CISC/x86 only?
980 //
981 FORCEINLINE
982 BOOLEAN
983 MI_IS_PHYSICAL_ADDRESS(IN PVOID Address)
984 {
985 PMMPDE PointerPde;
986
987 /* Large pages are never paged out, always physically resident */
988 PointerPde = MiAddressToPde(Address);
989 return ((PointerPde->u.Hard.LargePage) && (PointerPde->u.Hard.Valid));
990 }
991
992 //
993 // Writes a valid PTE
994 //
995 FORCEINLINE
996 VOID
997 MI_WRITE_VALID_PTE(IN PMMPTE PointerPte,
998 IN MMPTE TempPte)
999 {
1000 /* Write the valid PTE */
1001 ASSERT(PointerPte->u.Hard.Valid == 0);
1002 ASSERT(TempPte.u.Hard.Valid == 1);
1003 *PointerPte = TempPte;
1004 }
1005
1006 //
1007 // Updates a valid PTE
1008 //
1009 FORCEINLINE
1010 VOID
1011 MI_UPDATE_VALID_PTE(IN PMMPTE PointerPte,
1012 IN MMPTE TempPte)
1013 {
1014 /* Write the valid PTE */
1015 ASSERT(PointerPte->u.Hard.Valid == 1);
1016 ASSERT(TempPte.u.Hard.Valid == 1);
1017 ASSERT(PointerPte->u.Hard.PageFrameNumber == TempPte.u.Hard.PageFrameNumber);
1018 *PointerPte = TempPte;
1019 }
1020
1021 //
1022 // Writes an invalid PTE
1023 //
1024 FORCEINLINE
1025 VOID
1026 MI_WRITE_INVALID_PTE(IN PMMPTE PointerPte,
1027 IN MMPTE InvalidPte)
1028 {
1029 /* Write the invalid PTE */
1030 ASSERT(InvalidPte.u.Hard.Valid == 0);
1031 ASSERT(InvalidPte.u.Long != 0);
1032 *PointerPte = InvalidPte;
1033 }
1034
1035 //
1036 // Erase the PTE completely
1037 //
1038 FORCEINLINE
1039 VOID
1040 MI_ERASE_PTE(IN PMMPTE PointerPte)
1041 {
1042 /* Zero out the PTE */
1043 ASSERT(PointerPte->u.Long != 0);
1044 PointerPte->u.Long = 0;
1045 }
1046
1047 //
1048 // Writes a valid PDE
1049 //
1050 FORCEINLINE
1051 VOID
1052 MI_WRITE_VALID_PDE(IN PMMPDE PointerPde,
1053 IN MMPDE TempPde)
1054 {
1055 /* Write the valid PDE */
1056 ASSERT(PointerPde->u.Hard.Valid == 0);
1057 ASSERT(TempPde.u.Hard.Valid == 1);
1058 *PointerPde = TempPde;
1059 }
1060
1061 //
1062 // Writes an invalid PDE
1063 //
1064 FORCEINLINE
1065 VOID
1066 MI_WRITE_INVALID_PDE(IN PMMPDE PointerPde,
1067 IN MMPDE InvalidPde)
1068 {
1069 /* Write the invalid PDE */
1070 ASSERT(InvalidPde.u.Hard.Valid == 0);
1071 ASSERT(InvalidPde.u.Long != 0);
1072 *PointerPde = InvalidPde;
1073 }
1074
1075 //
1076 // Checks if the thread already owns a working set
1077 //
1078 FORCEINLINE
1079 BOOLEAN
1080 MM_ANY_WS_LOCK_HELD(IN PETHREAD Thread)
1081 {
1082 /* If any of these are held, return TRUE */
1083 return ((Thread->OwnsProcessWorkingSetExclusive) ||
1084 (Thread->OwnsProcessWorkingSetShared) ||
1085 (Thread->OwnsSystemWorkingSetExclusive) ||
1086 (Thread->OwnsSystemWorkingSetShared) ||
1087 (Thread->OwnsSessionWorkingSetExclusive) ||
1088 (Thread->OwnsSessionWorkingSetShared));
1089 }
1090
1091 //
1092 // Checks if the process owns the working set lock
1093 //
1094 FORCEINLINE
1095 BOOLEAN
1096 MI_WS_OWNER(IN PEPROCESS Process)
1097 {
1098 /* Check if this process is the owner, and that the thread owns the WS */
1099 if (PsGetCurrentThread()->OwnsProcessWorkingSetExclusive == 0)
1100 {
1101 DPRINT1("Thread: %p is not an owner\n", PsGetCurrentThread());
1102 }
1103 if (KeGetCurrentThread()->ApcState.Process != &Process->Pcb)
1104 {
1105 DPRINT1("Current thread %p is attached to another process %p\n", PsGetCurrentThread(), Process);
1106 }
1107 return ((KeGetCurrentThread()->ApcState.Process == &Process->Pcb) &&
1108 ((PsGetCurrentThread()->OwnsProcessWorkingSetExclusive) ||
1109 (PsGetCurrentThread()->OwnsProcessWorkingSetShared)));
1110 }
1111
1112 //
1113 // New ARM3<->RosMM PAGE Architecture
1114 //
1115 FORCEINLINE
1116 BOOLEAN
1117 MiIsRosSectionObject(IN PVOID Section)
1118 {
1119 PROS_SECTION_OBJECT RosSection = Section;
1120 if ((RosSection->Type == 'SC') && (RosSection->Size == 'TN')) return TRUE;
1121 return FALSE;
1122 }
1123
1124 #ifdef _WIN64
1125 // HACK ON TOP OF HACK ALERT!!!
1126 #define MI_GET_ROS_DATA(x) \
1127 (((x)->RosMmData == 0) ? NULL : ((PMMROSPFN)((ULONG64)(ULONG)((x)->RosMmData) | \
1128 ((ULONG64)MmNonPagedPoolStart & 0xffffffff00000000ULL))))
1129 #else
1130 #define MI_GET_ROS_DATA(x) ((PMMROSPFN)(x->RosMmData))
1131 #endif
1132 #define MI_IS_ROS_PFN(x) (((x)->u4.AweAllocation == TRUE) && (MI_GET_ROS_DATA(x) != NULL))
1133 #define ASSERT_IS_ROS_PFN(x) ASSERT(MI_IS_ROS_PFN(x) == TRUE);
1134 typedef struct _MMROSPFN
1135 {
1136 PMM_RMAP_ENTRY RmapListHead;
1137 SWAPENTRY SwapEntry;
1138 } MMROSPFN, *PMMROSPFN;
1139
1140 #define RosMmData AweReferenceCount
1141
1142 VOID
1143 NTAPI
1144 MiDecrementReferenceCount(
1145 IN PMMPFN Pfn1,
1146 IN PFN_NUMBER PageFrameIndex
1147 );
1148
1149 FORCEINLINE
1150 BOOLEAN
1151 MI_IS_WS_UNSAFE(IN PEPROCESS Process)
1152 {
1153 return (Process->Vm.Flags.AcquiredUnsafe == TRUE);
1154 }
1155
1156 //
1157 // Locks the working set for the given process
1158 //
1159 FORCEINLINE
1160 VOID
1161 MiLockProcessWorkingSet(IN PEPROCESS Process,
1162 IN PETHREAD Thread)
1163 {
1164 /* Shouldn't already be owning the process working set */
1165 ASSERT(Thread->OwnsProcessWorkingSetShared == FALSE);
1166 ASSERT(Thread->OwnsProcessWorkingSetExclusive == FALSE);
1167
1168 /* Block APCs, make sure that still nothing is already held */
1169 KeEnterGuardedRegion();
1170 ASSERT(!MM_ANY_WS_LOCK_HELD(Thread));
1171
1172 /* Lock the working set */
1173 ExAcquirePushLockExclusive(&Process->Vm.WorkingSetMutex);
1174
1175 /* Now claim that we own the lock */
1176 ASSERT(!MI_IS_WS_UNSAFE(Process));
1177 ASSERT(Thread->OwnsProcessWorkingSetExclusive == FALSE);
1178 Thread->OwnsProcessWorkingSetExclusive = TRUE;
1179 }
1180
1181 FORCEINLINE
1182 VOID
1183 MiLockProcessWorkingSetShared(IN PEPROCESS Process,
1184 IN PETHREAD Thread)
1185 {
1186 /* Shouldn't already be owning the process working set */
1187 ASSERT(Thread->OwnsProcessWorkingSetShared == FALSE);
1188 ASSERT(Thread->OwnsProcessWorkingSetExclusive == FALSE);
1189
1190 /* Block APCs, make sure that still nothing is already held */
1191 KeEnterGuardedRegion();
1192 ASSERT(!MM_ANY_WS_LOCK_HELD(Thread));
1193
1194 /* Lock the working set */
1195 ExAcquirePushLockShared(&Process->Vm.WorkingSetMutex);
1196
1197 /* Now claim that we own the lock */
1198 ASSERT(!MI_IS_WS_UNSAFE(Process));
1199 ASSERT(Thread->OwnsProcessWorkingSetShared == FALSE);
1200 ASSERT(Thread->OwnsProcessWorkingSetExclusive == FALSE);
1201 Thread->OwnsProcessWorkingSetShared = TRUE;
1202 }
1203
1204 FORCEINLINE
1205 VOID
1206 MiLockProcessWorkingSetUnsafe(IN PEPROCESS Process,
1207 IN PETHREAD Thread)
1208 {
1209 /* Shouldn't already be owning the process working set */
1210 ASSERT(Thread->OwnsProcessWorkingSetExclusive == FALSE);
1211
1212 /* APCs must be blocked, make sure that still nothing is already held */
1213 ASSERT(KeAreAllApcsDisabled() == TRUE);
1214 ASSERT(!MM_ANY_WS_LOCK_HELD(Thread));
1215
1216 /* Lock the working set */
1217 ExAcquirePushLockExclusive(&Process->Vm.WorkingSetMutex);
1218
1219 /* Now claim that we own the lock */
1220 ASSERT(!MI_IS_WS_UNSAFE(Process));
1221 Process->Vm.Flags.AcquiredUnsafe = 1;
1222 ASSERT(Thread->OwnsProcessWorkingSetExclusive == FALSE);
1223 Thread->OwnsProcessWorkingSetExclusive = TRUE;
1224 }
1225
1226 //
1227 // Unlocks the working set for the given process
1228 //
1229 FORCEINLINE
1230 VOID
1231 MiUnlockProcessWorkingSet(IN PEPROCESS Process,
1232 IN PETHREAD Thread)
1233 {
1234 /* Make sure we are the owner of a safe acquisition */
1235 ASSERT(MI_WS_OWNER(Process));
1236 ASSERT(!MI_IS_WS_UNSAFE(Process));
1237
1238 /* The thread doesn't own it anymore */
1239 ASSERT(Thread->OwnsProcessWorkingSetExclusive == TRUE);
1240 Thread->OwnsProcessWorkingSetExclusive = FALSE;
1241
1242 /* Release the lock and re-enable APCs */
1243 ExReleasePushLockExclusive(&Process->Vm.WorkingSetMutex);
1244 KeLeaveGuardedRegion();
1245 }
1246
1247 //
1248 // Unlocks the working set for the given process
1249 //
1250 FORCEINLINE
1251 VOID
1252 MiUnlockProcessWorkingSetShared(IN PEPROCESS Process,
1253 IN PETHREAD Thread)
1254 {
1255 /* Make sure we are the owner of a safe acquisition (because shared) */
1256 ASSERT(MI_WS_OWNER(Process));
1257 ASSERT(!MI_IS_WS_UNSAFE(Process));
1258
1259 /* Ensure we are in a shared acquisition */
1260 ASSERT(Thread->OwnsProcessWorkingSetShared == TRUE);
1261 ASSERT(Thread->OwnsProcessWorkingSetExclusive == FALSE);
1262
1263 /* Don't claim the lock anylonger */
1264 Thread->OwnsProcessWorkingSetShared = FALSE;
1265
1266 /* Release the lock and re-enable APCs */
1267 ExReleasePushLockShared(&Process->Vm.WorkingSetMutex);
1268 KeLeaveGuardedRegion();
1269 }
1270
1271 //
1272 // Unlocks the working set for the given process
1273 //
1274 FORCEINLINE
1275 VOID
1276 MiUnlockProcessWorkingSetUnsafe(IN PEPROCESS Process,
1277 IN PETHREAD Thread)
1278 {
1279 /* Make sure we are the owner of an unsafe acquisition */
1280 ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
1281 ASSERT(KeAreAllApcsDisabled() == TRUE);
1282 ASSERT(MI_WS_OWNER(Process));
1283 ASSERT(MI_IS_WS_UNSAFE(Process));
1284
1285 /* No longer unsafe */
1286 Process->Vm.Flags.AcquiredUnsafe = 0;
1287
1288 /* The thread doesn't own it anymore */
1289 ASSERT(Thread->OwnsProcessWorkingSetExclusive == TRUE);
1290 Thread->OwnsProcessWorkingSetExclusive = FALSE;
1291
1292 /* Release the lock but don't touch APC state */
1293 ExReleasePushLockExclusive(&Process->Vm.WorkingSetMutex);
1294 ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
1295 }
1296
1297 //
1298 // Locks the working set
1299 //
1300 FORCEINLINE
1301 VOID
1302 MiLockWorkingSet(IN PETHREAD Thread,
1303 IN PMMSUPPORT WorkingSet)
1304 {
1305 /* Block APCs */
1306 KeEnterGuardedRegion();
1307
1308 /* Working set should be in global memory */
1309 ASSERT(MI_IS_SESSION_ADDRESS((PVOID)WorkingSet) == FALSE);
1310
1311 /* Thread shouldn't already be owning something */
1312 ASSERT(!MM_ANY_WS_LOCK_HELD(Thread));
1313
1314 /* Lock this working set */
1315 ExAcquirePushLockExclusive(&WorkingSet->WorkingSetMutex);
1316
1317 /* Which working set is this? */
1318 if (WorkingSet == &MmSystemCacheWs)
1319 {
1320 /* Own the system working set */
1321 ASSERT((Thread->OwnsSystemWorkingSetExclusive == FALSE) &&
1322 (Thread->OwnsSystemWorkingSetShared == FALSE));
1323 Thread->OwnsSystemWorkingSetExclusive = TRUE;
1324 }
1325 else if (WorkingSet->Flags.SessionSpace)
1326 {
1327 /* Own the session working set */
1328 ASSERT((Thread->OwnsSessionWorkingSetExclusive == FALSE) &&
1329 (Thread->OwnsSessionWorkingSetShared == FALSE));
1330 Thread->OwnsSessionWorkingSetExclusive = TRUE;
1331 }
1332 else
1333 {
1334 /* Own the process working set */
1335 ASSERT((Thread->OwnsProcessWorkingSetExclusive == FALSE) &&
1336 (Thread->OwnsProcessWorkingSetShared == FALSE));
1337 Thread->OwnsProcessWorkingSetExclusive = TRUE;
1338 }
1339 }
1340
1341 //
1342 // Unlocks the working set
1343 //
1344 FORCEINLINE
1345 VOID
1346 MiUnlockWorkingSet(IN PETHREAD Thread,
1347 IN PMMSUPPORT WorkingSet)
1348 {
1349 /* Working set should be in global memory */
1350 ASSERT(MI_IS_SESSION_ADDRESS((PVOID)WorkingSet) == FALSE);
1351
1352 /* Which working set is this? */
1353 if (WorkingSet == &MmSystemCacheWs)
1354 {
1355 /* Release the system working set */
1356 ASSERT((Thread->OwnsSystemWorkingSetExclusive == TRUE) ||
1357 (Thread->OwnsSystemWorkingSetShared == TRUE));
1358 Thread->OwnsSystemWorkingSetExclusive = FALSE;
1359 }
1360 else if (WorkingSet->Flags.SessionSpace)
1361 {
1362 /* Release the session working set */
1363 ASSERT((Thread->OwnsSessionWorkingSetExclusive == TRUE) ||
1364 (Thread->OwnsSessionWorkingSetShared == TRUE));
1365 Thread->OwnsSessionWorkingSetExclusive = 0;
1366 }
1367 else
1368 {
1369 /* Release the process working set */
1370 ASSERT((Thread->OwnsProcessWorkingSetExclusive) ||
1371 (Thread->OwnsProcessWorkingSetShared));
1372 Thread->OwnsProcessWorkingSetExclusive = FALSE;
1373 }
1374
1375 /* Release the working set lock */
1376 ExReleasePushLockExclusive(&WorkingSet->WorkingSetMutex);
1377
1378 /* Unblock APCs */
1379 KeLeaveGuardedRegion();
1380 }
1381
1382 FORCEINLINE
1383 VOID
1384 MiUnlockProcessWorkingSetForFault(IN PEPROCESS Process,
1385 IN PETHREAD Thread,
1386 OUT PBOOLEAN Safe,
1387 OUT PBOOLEAN Shared)
1388 {
1389 ASSERT(MI_WS_OWNER(Process));
1390
1391 /* Check if the current owner is unsafe */
1392 if (MI_IS_WS_UNSAFE(Process))
1393 {
1394 /* Release unsafely */
1395 MiUnlockProcessWorkingSetUnsafe(Process, Thread);
1396 *Safe = FALSE;
1397 *Shared = FALSE;
1398 }
1399 else if (Thread->OwnsProcessWorkingSetExclusive == 1)
1400 {
1401 /* Owner is safe and exclusive, release normally */
1402 MiUnlockProcessWorkingSet(Process, Thread);
1403 *Safe = TRUE;
1404 *Shared = FALSE;
1405 }
1406 else
1407 {
1408 /* Owner is shared (implies safe), release normally */
1409 MiUnlockProcessWorkingSetShared(Process, Thread);
1410 *Safe = TRUE;
1411 *Shared = TRUE;
1412 }
1413 }
1414
1415 FORCEINLINE
1416 VOID
1417 MiLockProcessWorkingSetForFault(IN PEPROCESS Process,
1418 IN PETHREAD Thread,
1419 IN BOOLEAN Safe,
1420 IN BOOLEAN Shared)
1421 {
1422 /* Check if this was a safe lock or not */
1423 if (Safe)
1424 {
1425 if (Shared)
1426 {
1427 /* Reacquire safely & shared */
1428 MiLockProcessWorkingSetShared(Process, Thread);
1429 }
1430 else
1431 {
1432 /* Reacquire safely */
1433 MiLockProcessWorkingSet(Process, Thread);
1434 }
1435 }
1436 else
1437 {
1438 /* Unsafe lock cannot be shared */
1439 ASSERT(Shared == FALSE);
1440 /* Reacquire unsafely */
1441 MiLockProcessWorkingSetUnsafe(Process, Thread);
1442 }
1443 }
1444
1445 //
1446 // Returns the ProtoPTE inside a VAD for the given VPN
1447 //
1448 FORCEINLINE
1449 PMMPTE
1450 MI_GET_PROTOTYPE_PTE_FOR_VPN(IN PMMVAD Vad,
1451 IN ULONG_PTR Vpn)
1452 {
1453 PMMPTE ProtoPte;
1454
1455 /* Find the offset within the VAD's prototype PTEs */
1456 ProtoPte = Vad->FirstPrototypePte + (Vpn - Vad->StartingVpn);
1457 ASSERT(ProtoPte <= Vad->LastContiguousPte);
1458 return ProtoPte;
1459 }
1460
1461 //
1462 // Returns the PFN Database entry for the given page number
1463 // Warning: This is not necessarily a valid PFN database entry!
1464 //
1465 FORCEINLINE
1466 PMMPFN
1467 MI_PFN_ELEMENT(IN PFN_NUMBER Pfn)
1468 {
1469 /* Get the entry */
1470 return &MmPfnDatabase[Pfn];
1471 };
1472
1473 //
1474 // Drops a locked page without dereferencing it
1475 //
1476 FORCEINLINE
1477 VOID
1478 MiDropLockCount(IN PMMPFN Pfn1)
1479 {
1480 /* This page shouldn't be locked, but it should be valid */
1481 ASSERT(Pfn1->u3.e2.ReferenceCount != 0);
1482 ASSERT(Pfn1->u2.ShareCount == 0);
1483
1484 /* Is this the last reference to the page */
1485 if (Pfn1->u3.e2.ReferenceCount == 1)
1486 {
1487 /* It better not be valid */
1488 ASSERT(Pfn1->u3.e1.PageLocation != ActiveAndValid);
1489
1490 /* Is it a prototype PTE? */
1491 if ((Pfn1->u3.e1.PrototypePte == 1) &&
1492 (Pfn1->OriginalPte.u.Soft.Prototype == 1))
1493 {
1494 /* FIXME: We should return commit */
1495 DPRINT1("Not returning commit for prototype PTE\n");
1496 }
1497
1498 /* Update the counter */
1499 InterlockedDecrementSizeT(&MmSystemLockPagesCount);
1500 }
1501 }
1502
1503 //
1504 // Drops a locked page and dereferences it
1505 //
1506 FORCEINLINE
1507 VOID
1508 MiDereferencePfnAndDropLockCount(IN PMMPFN Pfn1)
1509 {
1510 USHORT RefCount, OldRefCount;
1511 PFN_NUMBER PageFrameIndex;
1512
1513 /* Loop while we decrement the page successfully */
1514 do
1515 {
1516 /* There should be at least one reference */
1517 OldRefCount = Pfn1->u3.e2.ReferenceCount;
1518 ASSERT(OldRefCount != 0);
1519
1520 /* Are we the last one */
1521 if (OldRefCount == 1)
1522 {
1523 /* The page shoudln't be shared not active at this point */
1524 ASSERT(Pfn1->u3.e2.ReferenceCount == 1);
1525 ASSERT(Pfn1->u3.e1.PageLocation != ActiveAndValid);
1526 ASSERT(Pfn1->u2.ShareCount == 0);
1527
1528 /* Is it a prototype PTE? */
1529 if ((Pfn1->u3.e1.PrototypePte == 1) &&
1530 (Pfn1->OriginalPte.u.Soft.Prototype == 1))
1531 {
1532 /* FIXME: We should return commit */
1533 DPRINT1("Not returning commit for prototype PTE\n");
1534 }
1535
1536 /* Update the counter, and drop a reference the long way */
1537 InterlockedDecrementSizeT(&MmSystemLockPagesCount);
1538 PageFrameIndex = MiGetPfnEntryIndex(Pfn1);
1539 MiDecrementReferenceCount(Pfn1, PageFrameIndex);
1540 return;
1541 }
1542
1543 /* Drop a reference the short way, and that's it */
1544 RefCount = InterlockedCompareExchange16((PSHORT)&Pfn1->u3.e2.ReferenceCount,
1545 OldRefCount - 1,
1546 OldRefCount);
1547 ASSERT(RefCount != 0);
1548 } while (OldRefCount != RefCount);
1549
1550 /* If we got here, there should be more than one reference */
1551 ASSERT(RefCount > 1);
1552 if (RefCount == 2)
1553 {
1554 /* Is it still being shared? */
1555 if (Pfn1->u2.ShareCount >= 1)
1556 {
1557 /* Then it should be valid */
1558 ASSERT(Pfn1->u3.e1.PageLocation == ActiveAndValid);
1559
1560 /* Is it a prototype PTE? */
1561 if ((Pfn1->u3.e1.PrototypePte == 1) &&
1562 (Pfn1->OriginalPte.u.Soft.Prototype == 1))
1563 {
1564 /* We don't handle ethis */
1565 ASSERT(FALSE);
1566 }
1567
1568 /* Update the counter */
1569 InterlockedDecrementSizeT(&MmSystemLockPagesCount);
1570 }
1571 }
1572 }
1573
1574 //
1575 // References a locked page and updates the counter
1576 // Used in MmProbeAndLockPages to handle different edge cases
1577 //
1578 FORCEINLINE
1579 VOID
1580 MiReferenceProbedPageAndBumpLockCount(IN PMMPFN Pfn1)
1581 {
1582 USHORT RefCount, OldRefCount;
1583
1584 /* Sanity check */
1585 ASSERT(Pfn1->u3.e2.ReferenceCount != 0);
1586
1587 /* Does ARM3 own the page? */
1588 if (MI_IS_ROS_PFN(Pfn1))
1589 {
1590 /* ReactOS Mm doesn't track share count */
1591 ASSERT(Pfn1->u3.e1.PageLocation == ActiveAndValid);
1592 }
1593 else
1594 {
1595 /* On ARM3 pages, we should see a valid share count */
1596 ASSERT((Pfn1->u2.ShareCount != 0) && (Pfn1->u3.e1.PageLocation == ActiveAndValid));
1597
1598 /* Is it a prototype PTE? */
1599 if ((Pfn1->u3.e1.PrototypePte == 1) &&
1600 (Pfn1->OriginalPte.u.Soft.Prototype == 1))
1601 {
1602 /* FIXME: We should charge commit */
1603 DPRINT1("Not charging commit for prototype PTE\n");
1604 }
1605 }
1606
1607 /* More locked pages! */
1608 InterlockedIncrementSizeT(&MmSystemLockPagesCount);
1609
1610 /* Loop trying to update the reference count */
1611 do
1612 {
1613 /* Get the current reference count, make sure it's valid */
1614 OldRefCount = Pfn1->u3.e2.ReferenceCount;
1615 ASSERT(OldRefCount != 0);
1616 ASSERT(OldRefCount < 2500);
1617
1618 /* Bump it up by one */
1619 RefCount = InterlockedCompareExchange16((PSHORT)&Pfn1->u3.e2.ReferenceCount,
1620 OldRefCount + 1,
1621 OldRefCount);
1622 ASSERT(RefCount != 0);
1623 } while (OldRefCount != RefCount);
1624
1625 /* Was this the first lock attempt? If not, undo our bump */
1626 if (OldRefCount != 1) InterlockedDecrementSizeT(&MmSystemLockPagesCount);
1627 }
1628
1629 //
1630 // References a locked page and updates the counter
1631 // Used in all other cases except MmProbeAndLockPages
1632 //
1633 FORCEINLINE
1634 VOID
1635 MiReferenceUsedPageAndBumpLockCount(IN PMMPFN Pfn1)
1636 {
1637 USHORT NewRefCount;
1638
1639 /* Is it a prototype PTE? */
1640 if ((Pfn1->u3.e1.PrototypePte == 1) &&
1641 (Pfn1->OriginalPte.u.Soft.Prototype == 1))
1642 {
1643 /* FIXME: We should charge commit */
1644 DPRINT1("Not charging commit for prototype PTE\n");
1645 }
1646
1647 /* More locked pages! */
1648 InterlockedIncrementSizeT(&MmSystemLockPagesCount);
1649
1650 /* Update the reference count */
1651 NewRefCount = InterlockedIncrement16((PSHORT)&Pfn1->u3.e2.ReferenceCount);
1652 if (NewRefCount == 2)
1653 {
1654 /* Is it locked or shared? */
1655 if (Pfn1->u2.ShareCount)
1656 {
1657 /* It's shared, so make sure it's active */
1658 ASSERT(Pfn1->u3.e1.PageLocation == ActiveAndValid);
1659 }
1660 else
1661 {
1662 /* It's locked, so we shouldn't lock again */
1663 InterlockedDecrementSizeT(&MmSystemLockPagesCount);
1664 }
1665 }
1666 else
1667 {
1668 /* Someone had already locked the page, so undo our bump */
1669 ASSERT(NewRefCount < 2500);
1670 InterlockedDecrementSizeT(&MmSystemLockPagesCount);
1671 }
1672 }
1673
1674 //
1675 // References a locked page and updates the counter
1676 // Used in all other cases except MmProbeAndLockPages
1677 //
1678 FORCEINLINE
1679 VOID
1680 MiReferenceUnusedPageAndBumpLockCount(IN PMMPFN Pfn1)
1681 {
1682 USHORT NewRefCount;
1683
1684 /* Make sure the page isn't used yet */
1685 ASSERT(Pfn1->u2.ShareCount == 0);
1686 ASSERT(Pfn1->u3.e1.PageLocation != ActiveAndValid);
1687
1688 /* Is it a prototype PTE? */
1689 if ((Pfn1->u3.e1.PrototypePte == 1) &&
1690 (Pfn1->OriginalPte.u.Soft.Prototype == 1))
1691 {
1692 /* FIXME: We should charge commit */
1693 DPRINT1("Not charging commit for prototype PTE\n");
1694 }
1695
1696 /* More locked pages! */
1697 InterlockedIncrementSizeT(&MmSystemLockPagesCount);
1698
1699 /* Update the reference count */
1700 NewRefCount = InterlockedIncrement16((PSHORT)&Pfn1->u3.e2.ReferenceCount);
1701 if (NewRefCount != 1)
1702 {
1703 /* Someone had already locked the page, so undo our bump */
1704 ASSERT(NewRefCount < 2500);
1705 InterlockedDecrementSizeT(&MmSystemLockPagesCount);
1706 }
1707 }
1708
1709 FORCEINLINE
1710 VOID
1711 MiIncrementPageTableReferences(IN PVOID Address)
1712 {
1713 PUSHORT RefCount;
1714
1715 RefCount = &MmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)];
1716
1717 *RefCount += 1;
1718 ASSERT(*RefCount <= PTE_PER_PAGE);
1719 }
1720
1721 FORCEINLINE
1722 VOID
1723 MiDecrementPageTableReferences(IN PVOID Address)
1724 {
1725 PUSHORT RefCount;
1726
1727 RefCount = &MmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)];
1728
1729 *RefCount -= 1;
1730 ASSERT(*RefCount < PTE_PER_PAGE);
1731 }
1732
1733 FORCEINLINE
1734 USHORT
1735 MiQueryPageTableReferences(IN PVOID Address)
1736 {
1737 PUSHORT RefCount;
1738
1739 RefCount = &MmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)];
1740
1741 return *RefCount;
1742 }
1743
1744 BOOLEAN
1745 NTAPI
1746 MmArmInitSystem(
1747 IN ULONG Phase,
1748 IN PLOADER_PARAMETER_BLOCK LoaderBlock
1749 );
1750
1751 VOID
1752 NTAPI
1753 MiInitializeSessionSpaceLayout();
1754
1755 NTSTATUS
1756 NTAPI
1757 MiInitMachineDependent(
1758 IN PLOADER_PARAMETER_BLOCK LoaderBlock
1759 );
1760
1761 VOID
1762 NTAPI
1763 MiComputeColorInformation(
1764 VOID
1765 );
1766
1767 VOID
1768 NTAPI
1769 MiMapPfnDatabase(
1770 IN PLOADER_PARAMETER_BLOCK LoaderBlock
1771 );
1772
1773 VOID
1774 NTAPI
1775 MiInitializeColorTables(
1776 VOID
1777 );
1778
1779 VOID
1780 NTAPI
1781 MiInitializePfnDatabase(
1782 IN PLOADER_PARAMETER_BLOCK LoaderBlock
1783 );
1784
1785 VOID
1786 NTAPI
1787 MiInitializeSessionWsSupport(
1788 VOID
1789 );
1790
1791 VOID
1792 NTAPI
1793 MiInitializeSessionIds(
1794 VOID
1795 );
1796
1797 BOOLEAN
1798 NTAPI
1799 MiInitializeMemoryEvents(
1800 VOID
1801 );
1802
1803 PFN_NUMBER
1804 NTAPI
1805 MxGetNextPage(
1806 IN PFN_NUMBER PageCount
1807 );
1808
1809 PPHYSICAL_MEMORY_DESCRIPTOR
1810 NTAPI
1811 MmInitializeMemoryLimits(
1812 IN PLOADER_PARAMETER_BLOCK LoaderBlock,
1813 IN PBOOLEAN IncludeType
1814 );
1815
1816 PFN_NUMBER
1817 NTAPI
1818 MiPagesInLoaderBlock(
1819 IN PLOADER_PARAMETER_BLOCK LoaderBlock,
1820 IN PBOOLEAN IncludeType
1821 );
1822
1823 VOID
1824 FASTCALL
1825 MiSyncARM3WithROS(
1826 IN PVOID AddressStart,
1827 IN PVOID AddressEnd
1828 );
1829
1830 NTSTATUS
1831 NTAPI
1832 MiRosProtectVirtualMemory(
1833 IN PEPROCESS Process,
1834 IN OUT PVOID *BaseAddress,
1835 IN OUT PSIZE_T NumberOfBytesToProtect,
1836 IN ULONG NewAccessProtection,
1837 OUT PULONG OldAccessProtection OPTIONAL
1838 );
1839
1840 NTSTATUS
1841 NTAPI
1842 MmArmAccessFault(
1843 IN BOOLEAN StoreInstruction,
1844 IN PVOID Address,
1845 IN KPROCESSOR_MODE Mode,
1846 IN PVOID TrapInformation
1847 );
1848
1849 NTSTATUS
1850 FASTCALL
1851 MiCheckPdeForPagedPool(
1852 IN PVOID Address
1853 );
1854
1855 VOID
1856 NTAPI
1857 MiInitializeNonPagedPool(
1858 VOID
1859 );
1860
1861 VOID
1862 NTAPI
1863 MiInitializeNonPagedPoolThresholds(
1864 VOID
1865 );
1866
1867 VOID
1868 NTAPI
1869 MiInitializePoolEvents(
1870 VOID
1871 );
1872
1873 VOID //
1874 NTAPI //
1875 InitializePool( //
1876 IN POOL_TYPE PoolType,// FIXFIX: This should go in ex.h after the pool merge
1877 IN ULONG Threshold //
1878 ); //
1879
1880 // FIXFIX: THIS ONE TOO
1881 VOID
1882 NTAPI
1883 INIT_FUNCTION
1884 ExInitializePoolDescriptor(
1885 IN PPOOL_DESCRIPTOR PoolDescriptor,
1886 IN POOL_TYPE PoolType,
1887 IN ULONG PoolIndex,
1888 IN ULONG Threshold,
1889 IN PVOID PoolLock
1890 );
1891
1892 NTSTATUS
1893 NTAPI
1894 MiInitializeSessionPool(
1895 VOID
1896 );
1897
1898 VOID
1899 NTAPI
1900 MiInitializeSystemPtes(
1901 IN PMMPTE StartingPte,
1902 IN ULONG NumberOfPtes,
1903 IN MMSYSTEM_PTE_POOL_TYPE PoolType
1904 );
1905
1906 PMMPTE
1907 NTAPI
1908 MiReserveSystemPtes(
1909 IN ULONG NumberOfPtes,
1910 IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType
1911 );
1912
1913 VOID
1914 NTAPI
1915 MiReleaseSystemPtes(
1916 IN PMMPTE StartingPte,
1917 IN ULONG NumberOfPtes,
1918 IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType
1919 );
1920
1921
1922 PFN_NUMBER
1923 NTAPI
1924 MiFindContiguousPages(
1925 IN PFN_NUMBER LowestPfn,
1926 IN PFN_NUMBER HighestPfn,
1927 IN PFN_NUMBER BoundaryPfn,
1928 IN PFN_NUMBER SizeInPages,
1929 IN MEMORY_CACHING_TYPE CacheType
1930 );
1931
1932 PVOID
1933 NTAPI
1934 MiCheckForContiguousMemory(
1935 IN PVOID BaseAddress,
1936 IN PFN_NUMBER BaseAddressPages,
1937 IN PFN_NUMBER SizeInPages,
1938 IN PFN_NUMBER LowestPfn,
1939 IN PFN_NUMBER HighestPfn,
1940 IN PFN_NUMBER BoundaryPfn,
1941 IN MI_PFN_CACHE_ATTRIBUTE CacheAttribute
1942 );
1943
1944 PMDL
1945 NTAPI
1946 MiAllocatePagesForMdl(
1947 IN PHYSICAL_ADDRESS LowAddress,
1948 IN PHYSICAL_ADDRESS HighAddress,
1949 IN PHYSICAL_ADDRESS SkipBytes,
1950 IN SIZE_T TotalBytes,
1951 IN MI_PFN_CACHE_ATTRIBUTE CacheAttribute,
1952 IN ULONG Flags
1953 );
1954
1955 PVOID
1956 NTAPI
1957 MiMapLockedPagesInUserSpace(
1958 IN PMDL Mdl,
1959 IN PVOID BaseVa,
1960 IN MEMORY_CACHING_TYPE CacheType,
1961 IN PVOID BaseAddress
1962 );
1963
1964 VOID
1965 NTAPI
1966 MiUnmapLockedPagesInUserSpace(
1967 IN PVOID BaseAddress,
1968 IN PMDL Mdl
1969 );
1970
1971 VOID
1972 NTAPI
1973 MiInsertPageInList(
1974 IN PMMPFNLIST ListHead,
1975 IN PFN_NUMBER PageFrameIndex
1976 );
1977
1978 VOID
1979 NTAPI
1980 MiUnlinkFreeOrZeroedPage(
1981 IN PMMPFN Entry
1982 );
1983
1984 VOID
1985 NTAPI
1986 MiUnlinkPageFromList(
1987 IN PMMPFN Pfn
1988 );
1989
1990 PFN_NUMBER
1991 NTAPI
1992 MiAllocatePfn(
1993 IN PMMPTE PointerPte,
1994 IN ULONG Protection
1995 );
1996
1997 VOID
1998 NTAPI
1999 MiInitializePfn(
2000 IN PFN_NUMBER PageFrameIndex,
2001 IN PMMPTE PointerPte,
2002 IN BOOLEAN Modified
2003 );
2004
2005 NTSTATUS
2006 NTAPI
2007 MiInitializeAndChargePfn(
2008 OUT PPFN_NUMBER PageFrameIndex,
2009 IN PMMPTE PointerPde,
2010 IN PFN_NUMBER ContainingPageFrame,
2011 IN BOOLEAN SessionAllocation
2012 );
2013
2014 VOID
2015 NTAPI
2016 MiInitializePfnAndMakePteValid(
2017 IN PFN_NUMBER PageFrameIndex,
2018 IN PMMPTE PointerPte,
2019 IN MMPTE TempPte
2020 );
2021
2022 VOID
2023 NTAPI
2024 MiInitializePfnForOtherProcess(
2025 IN PFN_NUMBER PageFrameIndex,
2026 IN PMMPTE PointerPte,
2027 IN PFN_NUMBER PteFrame
2028 );
2029
2030 VOID
2031 NTAPI
2032 MiDecrementShareCount(
2033 IN PMMPFN Pfn1,
2034 IN PFN_NUMBER PageFrameIndex
2035 );
2036
2037 PFN_NUMBER
2038 NTAPI
2039 MiRemoveAnyPage(
2040 IN ULONG Color
2041 );
2042
2043 PFN_NUMBER
2044 NTAPI
2045 MiRemoveZeroPage(
2046 IN ULONG Color
2047 );
2048
2049 VOID
2050 NTAPI
2051 MiZeroPhysicalPage(
2052 IN PFN_NUMBER PageFrameIndex
2053 );
2054
2055 VOID
2056 NTAPI
2057 MiInsertPageInFreeList(
2058 IN PFN_NUMBER PageFrameIndex
2059 );
2060
2061 PFN_COUNT
2062 NTAPI
2063 MiDeleteSystemPageableVm(
2064 IN PMMPTE PointerPte,
2065 IN PFN_NUMBER PageCount,
2066 IN ULONG Flags,
2067 OUT PPFN_NUMBER ValidPages
2068 );
2069
2070 ULONG
2071 NTAPI
2072 MiGetPageProtection(
2073 IN PMMPTE PointerPte
2074 );
2075
2076 PLDR_DATA_TABLE_ENTRY
2077 NTAPI
2078 MiLookupDataTableEntry(
2079 IN PVOID Address
2080 );
2081
2082 VOID
2083 NTAPI
2084 MiInitializeDriverLargePageList(
2085 VOID
2086 );
2087
2088 VOID
2089 NTAPI
2090 MiInitializeLargePageSupport(
2091 VOID
2092 );
2093
2094 VOID
2095 NTAPI
2096 MiSyncCachedRanges(
2097 VOID
2098 );
2099
2100 BOOLEAN
2101 NTAPI
2102 MiIsPfnInUse(
2103 IN PMMPFN Pfn1
2104 );
2105
2106 PMMVAD
2107 NTAPI
2108 MiLocateAddress(
2109 IN PVOID VirtualAddress
2110 );
2111
2112 PMMADDRESS_NODE
2113 NTAPI
2114 MiCheckForConflictingNode(
2115 IN ULONG_PTR StartVpn,
2116 IN ULONG_PTR EndVpn,
2117 IN PMM_AVL_TABLE Table
2118 );
2119
2120 TABLE_SEARCH_RESULT
2121 NTAPI
2122 MiFindEmptyAddressRangeDownTree(
2123 IN SIZE_T Length,
2124 IN ULONG_PTR BoundaryAddress,
2125 IN ULONG_PTR Alignment,
2126 IN PMM_AVL_TABLE Table,
2127 OUT PULONG_PTR Base,
2128 OUT PMMADDRESS_NODE *Parent
2129 );
2130
2131 NTSTATUS
2132 NTAPI
2133 MiFindEmptyAddressRangeDownBasedTree(
2134 IN SIZE_T Length,
2135 IN ULONG_PTR BoundaryAddress,
2136 IN ULONG_PTR Alignment,
2137 IN PMM_AVL_TABLE Table,
2138 OUT PULONG_PTR Base
2139 );
2140
2141 NTSTATUS
2142 NTAPI
2143 MiFindEmptyAddressRangeInTree(
2144 IN SIZE_T Length,
2145 IN ULONG_PTR Alignment,
2146 IN PMM_AVL_TABLE Table,
2147 OUT PMMADDRESS_NODE *PreviousVad,
2148 OUT PULONG_PTR Base
2149 );
2150
2151 NTSTATUS
2152 NTAPI
2153 MiCheckSecuredVad(
2154 IN PMMVAD Vad,
2155 IN PVOID Base,
2156 IN SIZE_T Size,
2157 IN ULONG ProtectionMask
2158 );
2159
2160 VOID
2161 NTAPI
2162 MiInsertVad(
2163 IN PMMVAD Vad,
2164 IN PEPROCESS Process
2165 );
2166
2167 VOID
2168 NTAPI
2169 MiInsertBasedSection(
2170 IN PSECTION Section
2171 );
2172
2173 NTSTATUS
2174 NTAPI
2175 MiUnmapViewOfSection(
2176 IN PEPROCESS Process,
2177 IN PVOID BaseAddress,
2178 IN ULONG Flags
2179 );
2180
2181 NTSTATUS
2182 NTAPI
2183 MiRosUnmapViewOfSection(
2184 IN PEPROCESS Process,
2185 IN PVOID BaseAddress,
2186 IN ULONG Flags
2187 );
2188
2189 VOID
2190 NTAPI
2191 MiInsertNode(
2192 IN PMM_AVL_TABLE Table,
2193 IN PMMADDRESS_NODE NewNode,
2194 PMMADDRESS_NODE Parent,
2195 TABLE_SEARCH_RESULT Result
2196 );
2197
2198 VOID
2199 NTAPI
2200 MiRemoveNode(
2201 IN PMMADDRESS_NODE Node,
2202 IN PMM_AVL_TABLE Table
2203 );
2204
2205 PMMADDRESS_NODE
2206 NTAPI
2207 MiGetPreviousNode(
2208 IN PMMADDRESS_NODE Node
2209 );
2210
2211 PMMADDRESS_NODE
2212 NTAPI
2213 MiGetNextNode(
2214 IN PMMADDRESS_NODE Node
2215 );
2216
2217 BOOLEAN
2218 NTAPI
2219 MiInitializeSystemSpaceMap(
2220 IN PMMSESSION InputSession OPTIONAL
2221 );
2222
2223 VOID
2224 NTAPI
2225 MiSessionRemoveProcess(
2226 VOID
2227 );
2228
2229 VOID
2230 NTAPI
2231 MiReleaseProcessReferenceToSessionDataPage(
2232 IN PMM_SESSION_SPACE SessionGlobal
2233 );
2234
2235 VOID
2236 NTAPI
2237 MiSessionAddProcess(
2238 IN PEPROCESS NewProcess
2239 );
2240
2241 NTSTATUS
2242 NTAPI
2243 MiSessionCommitPageTables(
2244 IN PVOID StartVa,
2245 IN PVOID EndVa
2246 );
2247
2248 ULONG
2249 NTAPI
2250 MiMakeProtectionMask(
2251 IN ULONG Protect
2252 );
2253
2254 VOID
2255 NTAPI
2256 MiDeleteVirtualAddresses(
2257 IN ULONG_PTR Va,
2258 IN ULONG_PTR EndingAddress,
2259 IN PMMVAD Vad
2260 );
2261
2262 ULONG
2263 NTAPI
2264 MiMakeSystemAddressValid(
2265 IN PVOID PageTableVirtualAddress,
2266 IN PEPROCESS CurrentProcess
2267 );
2268
2269 ULONG
2270 NTAPI
2271 MiMakeSystemAddressValidPfn(
2272 IN PVOID VirtualAddress,
2273 IN KIRQL OldIrql
2274 );
2275
2276 VOID
2277 NTAPI
2278 MiRemoveMappedView(
2279 IN PEPROCESS CurrentProcess,
2280 IN PMMVAD Vad
2281 );
2282
2283 PSUBSECTION
2284 NTAPI
2285 MiLocateSubsection(
2286 IN PMMVAD Vad,
2287 IN ULONG_PTR Vpn
2288 );
2289
2290 NTSTATUS
2291 NTAPI
2292 MiQueryMemorySectionName(
2293 IN HANDLE ProcessHandle,
2294 IN PVOID BaseAddress,
2295 OUT PVOID MemoryInformation,
2296 IN SIZE_T MemoryInformationLength,
2297 OUT PSIZE_T ReturnLength
2298 );
2299
2300 NTSTATUS
2301 NTAPI
2302 MiRosUnmapViewInSystemSpace(
2303 IN PVOID MappedBase
2304 );
2305
2306 POOL_TYPE
2307 NTAPI
2308 MmDeterminePoolType(
2309 IN PVOID PoolAddress
2310 );
2311
2312 VOID
2313 NTAPI
2314 MiMakePdeExistAndMakeValid(
2315 IN PMMPTE PointerPde,
2316 IN PEPROCESS TargetProcess,
2317 IN KIRQL OldIrql
2318 );
2319
2320 //
2321 // MiRemoveZeroPage will use inline code to zero out the page manually if only
2322 // free pages are available. In some scenarios, we don't/can't run that piece of
2323 // code and would rather only have a real zero page. If we can't have a zero page,
2324 // then we'd like to have our own code to grab a free page and zero it out, by
2325 // using MiRemoveAnyPage. This macro implements this.
2326 //
2327 FORCEINLINE
2328 PFN_NUMBER
2329 MiRemoveZeroPageSafe(IN ULONG Color)
2330 {
2331 if (MmFreePagesByColor[ZeroedPageList][Color].Flink != LIST_HEAD) return MiRemoveZeroPage(Color);
2332 return 0;
2333 }
2334
2335 /* EOF */