d04bf8a498bd45f46bfefe112ea32124253bdb70
[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 #define MI_IS_ROS_PFN(x) ((x)->u4.AweAllocation == TRUE)
1125
1126 VOID
1127 NTAPI
1128 MiDecrementReferenceCount(
1129 IN PMMPFN Pfn1,
1130 IN PFN_NUMBER PageFrameIndex
1131 );
1132
1133 FORCEINLINE
1134 BOOLEAN
1135 MI_IS_WS_UNSAFE(IN PEPROCESS Process)
1136 {
1137 return (Process->Vm.Flags.AcquiredUnsafe == TRUE);
1138 }
1139
1140 //
1141 // Locks the working set for the given process
1142 //
1143 FORCEINLINE
1144 VOID
1145 MiLockProcessWorkingSet(IN PEPROCESS Process,
1146 IN PETHREAD Thread)
1147 {
1148 /* Shouldn't already be owning the process working set */
1149 ASSERT(Thread->OwnsProcessWorkingSetShared == FALSE);
1150 ASSERT(Thread->OwnsProcessWorkingSetExclusive == FALSE);
1151
1152 /* Block APCs, make sure that still nothing is already held */
1153 KeEnterGuardedRegion();
1154 ASSERT(!MM_ANY_WS_LOCK_HELD(Thread));
1155
1156 /* Lock the working set */
1157 ExAcquirePushLockExclusive(&Process->Vm.WorkingSetMutex);
1158
1159 /* Now claim that we own the lock */
1160 ASSERT(!MI_IS_WS_UNSAFE(Process));
1161 ASSERT(Thread->OwnsProcessWorkingSetExclusive == FALSE);
1162 Thread->OwnsProcessWorkingSetExclusive = TRUE;
1163 }
1164
1165 FORCEINLINE
1166 VOID
1167 MiLockProcessWorkingSetShared(IN PEPROCESS Process,
1168 IN PETHREAD Thread)
1169 {
1170 /* Shouldn't already be owning the process working set */
1171 ASSERT(Thread->OwnsProcessWorkingSetShared == FALSE);
1172 ASSERT(Thread->OwnsProcessWorkingSetExclusive == FALSE);
1173
1174 /* Block APCs, make sure that still nothing is already held */
1175 KeEnterGuardedRegion();
1176 ASSERT(!MM_ANY_WS_LOCK_HELD(Thread));
1177
1178 /* Lock the working set */
1179 ExAcquirePushLockShared(&Process->Vm.WorkingSetMutex);
1180
1181 /* Now claim that we own the lock */
1182 ASSERT(!MI_IS_WS_UNSAFE(Process));
1183 ASSERT(Thread->OwnsProcessWorkingSetShared == FALSE);
1184 ASSERT(Thread->OwnsProcessWorkingSetExclusive == FALSE);
1185 Thread->OwnsProcessWorkingSetShared = TRUE;
1186 }
1187
1188 FORCEINLINE
1189 VOID
1190 MiLockProcessWorkingSetUnsafe(IN PEPROCESS Process,
1191 IN PETHREAD Thread)
1192 {
1193 /* Shouldn't already be owning the process working set */
1194 ASSERT(Thread->OwnsProcessWorkingSetExclusive == FALSE);
1195
1196 /* APCs must be blocked, make sure that still nothing is already held */
1197 ASSERT(KeAreAllApcsDisabled() == TRUE);
1198 ASSERT(!MM_ANY_WS_LOCK_HELD(Thread));
1199
1200 /* Lock the working set */
1201 ExAcquirePushLockExclusive(&Process->Vm.WorkingSetMutex);
1202
1203 /* Now claim that we own the lock */
1204 ASSERT(!MI_IS_WS_UNSAFE(Process));
1205 Process->Vm.Flags.AcquiredUnsafe = 1;
1206 ASSERT(Thread->OwnsProcessWorkingSetExclusive == FALSE);
1207 Thread->OwnsProcessWorkingSetExclusive = TRUE;
1208 }
1209
1210 //
1211 // Unlocks the working set for the given process
1212 //
1213 FORCEINLINE
1214 VOID
1215 MiUnlockProcessWorkingSet(IN PEPROCESS Process,
1216 IN PETHREAD Thread)
1217 {
1218 /* Make sure we are the owner of a safe acquisition */
1219 ASSERT(MI_WS_OWNER(Process));
1220 ASSERT(!MI_IS_WS_UNSAFE(Process));
1221
1222 /* The thread doesn't own it anymore */
1223 ASSERT(Thread->OwnsProcessWorkingSetExclusive == TRUE);
1224 Thread->OwnsProcessWorkingSetExclusive = FALSE;
1225
1226 /* Release the lock and re-enable APCs */
1227 ExReleasePushLockExclusive(&Process->Vm.WorkingSetMutex);
1228 KeLeaveGuardedRegion();
1229 }
1230
1231 //
1232 // Unlocks the working set for the given process
1233 //
1234 FORCEINLINE
1235 VOID
1236 MiUnlockProcessWorkingSetShared(IN PEPROCESS Process,
1237 IN PETHREAD Thread)
1238 {
1239 /* Make sure we are the owner of a safe acquisition (because shared) */
1240 ASSERT(MI_WS_OWNER(Process));
1241 ASSERT(!MI_IS_WS_UNSAFE(Process));
1242
1243 /* Ensure we are in a shared acquisition */
1244 ASSERT(Thread->OwnsProcessWorkingSetShared == TRUE);
1245 ASSERT(Thread->OwnsProcessWorkingSetExclusive == FALSE);
1246
1247 /* Don't claim the lock anylonger */
1248 Thread->OwnsProcessWorkingSetShared = FALSE;
1249
1250 /* Release the lock and re-enable APCs */
1251 ExReleasePushLockShared(&Process->Vm.WorkingSetMutex);
1252 KeLeaveGuardedRegion();
1253 }
1254
1255 //
1256 // Unlocks the working set for the given process
1257 //
1258 FORCEINLINE
1259 VOID
1260 MiUnlockProcessWorkingSetUnsafe(IN PEPROCESS Process,
1261 IN PETHREAD Thread)
1262 {
1263 /* Make sure we are the owner of an unsafe acquisition */
1264 ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
1265 ASSERT(KeAreAllApcsDisabled() == TRUE);
1266 ASSERT(MI_WS_OWNER(Process));
1267 ASSERT(MI_IS_WS_UNSAFE(Process));
1268
1269 /* No longer unsafe */
1270 Process->Vm.Flags.AcquiredUnsafe = 0;
1271
1272 /* The thread doesn't own it anymore */
1273 ASSERT(Thread->OwnsProcessWorkingSetExclusive == TRUE);
1274 Thread->OwnsProcessWorkingSetExclusive = FALSE;
1275
1276 /* Release the lock but don't touch APC state */
1277 ExReleasePushLockExclusive(&Process->Vm.WorkingSetMutex);
1278 ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
1279 }
1280
1281 //
1282 // Locks the working set
1283 //
1284 FORCEINLINE
1285 VOID
1286 MiLockWorkingSet(IN PETHREAD Thread,
1287 IN PMMSUPPORT WorkingSet)
1288 {
1289 /* Block APCs */
1290 KeEnterGuardedRegion();
1291
1292 /* Working set should be in global memory */
1293 ASSERT(MI_IS_SESSION_ADDRESS((PVOID)WorkingSet) == FALSE);
1294
1295 /* Thread shouldn't already be owning something */
1296 ASSERT(!MM_ANY_WS_LOCK_HELD(Thread));
1297
1298 /* Lock this working set */
1299 ExAcquirePushLockExclusive(&WorkingSet->WorkingSetMutex);
1300
1301 /* Which working set is this? */
1302 if (WorkingSet == &MmSystemCacheWs)
1303 {
1304 /* Own the system working set */
1305 ASSERT((Thread->OwnsSystemWorkingSetExclusive == FALSE) &&
1306 (Thread->OwnsSystemWorkingSetShared == FALSE));
1307 Thread->OwnsSystemWorkingSetExclusive = TRUE;
1308 }
1309 else if (WorkingSet->Flags.SessionSpace)
1310 {
1311 /* Own the session working set */
1312 ASSERT((Thread->OwnsSessionWorkingSetExclusive == FALSE) &&
1313 (Thread->OwnsSessionWorkingSetShared == FALSE));
1314 Thread->OwnsSessionWorkingSetExclusive = TRUE;
1315 }
1316 else
1317 {
1318 /* Own the process working set */
1319 ASSERT((Thread->OwnsProcessWorkingSetExclusive == FALSE) &&
1320 (Thread->OwnsProcessWorkingSetShared == FALSE));
1321 Thread->OwnsProcessWorkingSetExclusive = TRUE;
1322 }
1323 }
1324
1325 //
1326 // Unlocks the working set
1327 //
1328 FORCEINLINE
1329 VOID
1330 MiUnlockWorkingSet(IN PETHREAD Thread,
1331 IN PMMSUPPORT WorkingSet)
1332 {
1333 /* Working set should be in global memory */
1334 ASSERT(MI_IS_SESSION_ADDRESS((PVOID)WorkingSet) == FALSE);
1335
1336 /* Which working set is this? */
1337 if (WorkingSet == &MmSystemCacheWs)
1338 {
1339 /* Release the system working set */
1340 ASSERT((Thread->OwnsSystemWorkingSetExclusive == TRUE) ||
1341 (Thread->OwnsSystemWorkingSetShared == TRUE));
1342 Thread->OwnsSystemWorkingSetExclusive = FALSE;
1343 }
1344 else if (WorkingSet->Flags.SessionSpace)
1345 {
1346 /* Release the session working set */
1347 ASSERT((Thread->OwnsSessionWorkingSetExclusive == TRUE) ||
1348 (Thread->OwnsSessionWorkingSetShared == TRUE));
1349 Thread->OwnsSessionWorkingSetExclusive = 0;
1350 }
1351 else
1352 {
1353 /* Release the process working set */
1354 ASSERT((Thread->OwnsProcessWorkingSetExclusive) ||
1355 (Thread->OwnsProcessWorkingSetShared));
1356 Thread->OwnsProcessWorkingSetExclusive = FALSE;
1357 }
1358
1359 /* Release the working set lock */
1360 ExReleasePushLockExclusive(&WorkingSet->WorkingSetMutex);
1361
1362 /* Unblock APCs */
1363 KeLeaveGuardedRegion();
1364 }
1365
1366 FORCEINLINE
1367 VOID
1368 MiUnlockProcessWorkingSetForFault(IN PEPROCESS Process,
1369 IN PETHREAD Thread,
1370 OUT PBOOLEAN Safe,
1371 OUT PBOOLEAN Shared)
1372 {
1373 ASSERT(MI_WS_OWNER(Process));
1374
1375 /* Check if the current owner is unsafe */
1376 if (MI_IS_WS_UNSAFE(Process))
1377 {
1378 /* Release unsafely */
1379 MiUnlockProcessWorkingSetUnsafe(Process, Thread);
1380 *Safe = FALSE;
1381 *Shared = FALSE;
1382 }
1383 else if (Thread->OwnsProcessWorkingSetExclusive == 1)
1384 {
1385 /* Owner is safe and exclusive, release normally */
1386 MiUnlockProcessWorkingSet(Process, Thread);
1387 *Safe = TRUE;
1388 *Shared = FALSE;
1389 }
1390 else
1391 {
1392 /* Owner is shared (implies safe), release normally */
1393 MiUnlockProcessWorkingSetShared(Process, Thread);
1394 *Safe = TRUE;
1395 *Shared = TRUE;
1396 }
1397 }
1398
1399 FORCEINLINE
1400 VOID
1401 MiLockProcessWorkingSetForFault(IN PEPROCESS Process,
1402 IN PETHREAD Thread,
1403 IN BOOLEAN Safe,
1404 IN BOOLEAN Shared)
1405 {
1406 /* Check if this was a safe lock or not */
1407 if (Safe)
1408 {
1409 if (Shared)
1410 {
1411 /* Reacquire safely & shared */
1412 MiLockProcessWorkingSetShared(Process, Thread);
1413 }
1414 else
1415 {
1416 /* Reacquire safely */
1417 MiLockProcessWorkingSet(Process, Thread);
1418 }
1419 }
1420 else
1421 {
1422 /* Unsafe lock cannot be shared */
1423 ASSERT(Shared == FALSE);
1424 /* Reacquire unsafely */
1425 MiLockProcessWorkingSetUnsafe(Process, Thread);
1426 }
1427 }
1428
1429 //
1430 // Returns the ProtoPTE inside a VAD for the given VPN
1431 //
1432 FORCEINLINE
1433 PMMPTE
1434 MI_GET_PROTOTYPE_PTE_FOR_VPN(IN PMMVAD Vad,
1435 IN ULONG_PTR Vpn)
1436 {
1437 PMMPTE ProtoPte;
1438
1439 /* Find the offset within the VAD's prototype PTEs */
1440 ProtoPte = Vad->FirstPrototypePte + (Vpn - Vad->StartingVpn);
1441 ASSERT(ProtoPte <= Vad->LastContiguousPte);
1442 return ProtoPte;
1443 }
1444
1445 //
1446 // Returns the PFN Database entry for the given page number
1447 // Warning: This is not necessarily a valid PFN database entry!
1448 //
1449 FORCEINLINE
1450 PMMPFN
1451 MI_PFN_ELEMENT(IN PFN_NUMBER Pfn)
1452 {
1453 /* Get the entry */
1454 return &MmPfnDatabase[Pfn];
1455 };
1456
1457 //
1458 // Drops a locked page without dereferencing it
1459 //
1460 FORCEINLINE
1461 VOID
1462 MiDropLockCount(IN PMMPFN Pfn1)
1463 {
1464 /* This page shouldn't be locked, but it should be valid */
1465 ASSERT(Pfn1->u3.e2.ReferenceCount != 0);
1466 ASSERT(Pfn1->u2.ShareCount == 0);
1467
1468 /* Is this the last reference to the page */
1469 if (Pfn1->u3.e2.ReferenceCount == 1)
1470 {
1471 /* It better not be valid */
1472 ASSERT(Pfn1->u3.e1.PageLocation != ActiveAndValid);
1473
1474 /* Is it a prototype PTE? */
1475 if ((Pfn1->u3.e1.PrototypePte == 1) &&
1476 (Pfn1->OriginalPte.u.Soft.Prototype == 1))
1477 {
1478 /* FIXME: We should return commit */
1479 DPRINT1("Not returning commit for prototype PTE\n");
1480 }
1481
1482 /* Update the counter */
1483 InterlockedDecrementSizeT(&MmSystemLockPagesCount);
1484 }
1485 }
1486
1487 //
1488 // Drops a locked page and dereferences it
1489 //
1490 FORCEINLINE
1491 VOID
1492 MiDereferencePfnAndDropLockCount(IN PMMPFN Pfn1)
1493 {
1494 USHORT RefCount, OldRefCount;
1495 PFN_NUMBER PageFrameIndex;
1496
1497 /* Loop while we decrement the page successfully */
1498 do
1499 {
1500 /* There should be at least one reference */
1501 OldRefCount = Pfn1->u3.e2.ReferenceCount;
1502 ASSERT(OldRefCount != 0);
1503
1504 /* Are we the last one */
1505 if (OldRefCount == 1)
1506 {
1507 /* The page shoudln't be shared not active at this point */
1508 ASSERT(Pfn1->u3.e2.ReferenceCount == 1);
1509 ASSERT(Pfn1->u3.e1.PageLocation != ActiveAndValid);
1510 ASSERT(Pfn1->u2.ShareCount == 0);
1511
1512 /* Is it a prototype PTE? */
1513 if ((Pfn1->u3.e1.PrototypePte == 1) &&
1514 (Pfn1->OriginalPte.u.Soft.Prototype == 1))
1515 {
1516 /* FIXME: We should return commit */
1517 DPRINT1("Not returning commit for prototype PTE\n");
1518 }
1519
1520 /* Update the counter, and drop a reference the long way */
1521 InterlockedDecrementSizeT(&MmSystemLockPagesCount);
1522 PageFrameIndex = MiGetPfnEntryIndex(Pfn1);
1523 MiDecrementReferenceCount(Pfn1, PageFrameIndex);
1524 return;
1525 }
1526
1527 /* Drop a reference the short way, and that's it */
1528 RefCount = InterlockedCompareExchange16((PSHORT)&Pfn1->u3.e2.ReferenceCount,
1529 OldRefCount - 1,
1530 OldRefCount);
1531 ASSERT(RefCount != 0);
1532 } while (OldRefCount != RefCount);
1533
1534 /* If we got here, there should be more than one reference */
1535 ASSERT(RefCount > 1);
1536 if (RefCount == 2)
1537 {
1538 /* Is it still being shared? */
1539 if (Pfn1->u2.ShareCount >= 1)
1540 {
1541 /* Then it should be valid */
1542 ASSERT(Pfn1->u3.e1.PageLocation == ActiveAndValid);
1543
1544 /* Is it a prototype PTE? */
1545 if ((Pfn1->u3.e1.PrototypePte == 1) &&
1546 (Pfn1->OriginalPte.u.Soft.Prototype == 1))
1547 {
1548 /* We don't handle ethis */
1549 ASSERT(FALSE);
1550 }
1551
1552 /* Update the counter */
1553 InterlockedDecrementSizeT(&MmSystemLockPagesCount);
1554 }
1555 }
1556 }
1557
1558 //
1559 // References a locked page and updates the counter
1560 // Used in MmProbeAndLockPages to handle different edge cases
1561 //
1562 FORCEINLINE
1563 VOID
1564 MiReferenceProbedPageAndBumpLockCount(IN PMMPFN Pfn1)
1565 {
1566 USHORT RefCount, OldRefCount;
1567
1568 /* Sanity check */
1569 ASSERT(Pfn1->u3.e2.ReferenceCount != 0);
1570
1571 /* Does ARM3 own the page? */
1572 if (MI_IS_ROS_PFN(Pfn1))
1573 {
1574 /* ReactOS Mm doesn't track share count */
1575 ASSERT(Pfn1->u3.e1.PageLocation == ActiveAndValid);
1576 }
1577 else
1578 {
1579 /* On ARM3 pages, we should see a valid share count */
1580 ASSERT((Pfn1->u2.ShareCount != 0) && (Pfn1->u3.e1.PageLocation == ActiveAndValid));
1581
1582 /* Is it a prototype PTE? */
1583 if ((Pfn1->u3.e1.PrototypePte == 1) &&
1584 (Pfn1->OriginalPte.u.Soft.Prototype == 1))
1585 {
1586 /* FIXME: We should charge commit */
1587 DPRINT1("Not charging commit for prototype PTE\n");
1588 }
1589 }
1590
1591 /* More locked pages! */
1592 InterlockedIncrementSizeT(&MmSystemLockPagesCount);
1593
1594 /* Loop trying to update the reference count */
1595 do
1596 {
1597 /* Get the current reference count, make sure it's valid */
1598 OldRefCount = Pfn1->u3.e2.ReferenceCount;
1599 ASSERT(OldRefCount != 0);
1600 ASSERT(OldRefCount < 2500);
1601
1602 /* Bump it up by one */
1603 RefCount = InterlockedCompareExchange16((PSHORT)&Pfn1->u3.e2.ReferenceCount,
1604 OldRefCount + 1,
1605 OldRefCount);
1606 ASSERT(RefCount != 0);
1607 } while (OldRefCount != RefCount);
1608
1609 /* Was this the first lock attempt? If not, undo our bump */
1610 if (OldRefCount != 1) InterlockedDecrementSizeT(&MmSystemLockPagesCount);
1611 }
1612
1613 //
1614 // References a locked page and updates the counter
1615 // Used in all other cases except MmProbeAndLockPages
1616 //
1617 FORCEINLINE
1618 VOID
1619 MiReferenceUsedPageAndBumpLockCount(IN PMMPFN Pfn1)
1620 {
1621 USHORT NewRefCount;
1622
1623 /* Is it a prototype PTE? */
1624 if ((Pfn1->u3.e1.PrototypePte == 1) &&
1625 (Pfn1->OriginalPte.u.Soft.Prototype == 1))
1626 {
1627 /* FIXME: We should charge commit */
1628 DPRINT1("Not charging commit for prototype PTE\n");
1629 }
1630
1631 /* More locked pages! */
1632 InterlockedIncrementSizeT(&MmSystemLockPagesCount);
1633
1634 /* Update the reference count */
1635 NewRefCount = InterlockedIncrement16((PSHORT)&Pfn1->u3.e2.ReferenceCount);
1636 if (NewRefCount == 2)
1637 {
1638 /* Is it locked or shared? */
1639 if (Pfn1->u2.ShareCount)
1640 {
1641 /* It's shared, so make sure it's active */
1642 ASSERT(Pfn1->u3.e1.PageLocation == ActiveAndValid);
1643 }
1644 else
1645 {
1646 /* It's locked, so we shouldn't lock again */
1647 InterlockedDecrementSizeT(&MmSystemLockPagesCount);
1648 }
1649 }
1650 else
1651 {
1652 /* Someone had already locked the page, so undo our bump */
1653 ASSERT(NewRefCount < 2500);
1654 InterlockedDecrementSizeT(&MmSystemLockPagesCount);
1655 }
1656 }
1657
1658 //
1659 // References a locked page and updates the counter
1660 // Used in all other cases except MmProbeAndLockPages
1661 //
1662 FORCEINLINE
1663 VOID
1664 MiReferenceUnusedPageAndBumpLockCount(IN PMMPFN Pfn1)
1665 {
1666 USHORT NewRefCount;
1667
1668 /* Make sure the page isn't used yet */
1669 ASSERT(Pfn1->u2.ShareCount == 0);
1670 ASSERT(Pfn1->u3.e1.PageLocation != ActiveAndValid);
1671
1672 /* Is it a prototype PTE? */
1673 if ((Pfn1->u3.e1.PrototypePte == 1) &&
1674 (Pfn1->OriginalPte.u.Soft.Prototype == 1))
1675 {
1676 /* FIXME: We should charge commit */
1677 DPRINT1("Not charging commit for prototype PTE\n");
1678 }
1679
1680 /* More locked pages! */
1681 InterlockedIncrementSizeT(&MmSystemLockPagesCount);
1682
1683 /* Update the reference count */
1684 NewRefCount = InterlockedIncrement16((PSHORT)&Pfn1->u3.e2.ReferenceCount);
1685 if (NewRefCount != 1)
1686 {
1687 /* Someone had already locked the page, so undo our bump */
1688 ASSERT(NewRefCount < 2500);
1689 InterlockedDecrementSizeT(&MmSystemLockPagesCount);
1690 }
1691 }
1692
1693 FORCEINLINE
1694 VOID
1695 MiIncrementPageTableReferences(IN PVOID Address)
1696 {
1697 PUSHORT RefCount;
1698
1699 RefCount = &MmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)];
1700
1701 *RefCount += 1;
1702 ASSERT(*RefCount <= PTE_PER_PAGE);
1703 }
1704
1705 FORCEINLINE
1706 VOID
1707 MiDecrementPageTableReferences(IN PVOID Address)
1708 {
1709 PUSHORT RefCount;
1710
1711 RefCount = &MmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)];
1712
1713 *RefCount -= 1;
1714 ASSERT(*RefCount < PTE_PER_PAGE);
1715 }
1716
1717 FORCEINLINE
1718 USHORT
1719 MiQueryPageTableReferences(IN PVOID Address)
1720 {
1721 PUSHORT RefCount;
1722
1723 RefCount = &MmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)];
1724
1725 return *RefCount;
1726 }
1727
1728 BOOLEAN
1729 NTAPI
1730 MmArmInitSystem(
1731 IN ULONG Phase,
1732 IN PLOADER_PARAMETER_BLOCK LoaderBlock
1733 );
1734
1735 VOID
1736 NTAPI
1737 MiInitializeSessionSpaceLayout();
1738
1739 NTSTATUS
1740 NTAPI
1741 MiInitMachineDependent(
1742 IN PLOADER_PARAMETER_BLOCK LoaderBlock
1743 );
1744
1745 VOID
1746 NTAPI
1747 MiComputeColorInformation(
1748 VOID
1749 );
1750
1751 VOID
1752 NTAPI
1753 MiMapPfnDatabase(
1754 IN PLOADER_PARAMETER_BLOCK LoaderBlock
1755 );
1756
1757 VOID
1758 NTAPI
1759 MiInitializeColorTables(
1760 VOID
1761 );
1762
1763 VOID
1764 NTAPI
1765 MiInitializePfnDatabase(
1766 IN PLOADER_PARAMETER_BLOCK LoaderBlock
1767 );
1768
1769 VOID
1770 NTAPI
1771 MiInitializeSessionWsSupport(
1772 VOID
1773 );
1774
1775 VOID
1776 NTAPI
1777 MiInitializeSessionIds(
1778 VOID
1779 );
1780
1781 BOOLEAN
1782 NTAPI
1783 MiInitializeMemoryEvents(
1784 VOID
1785 );
1786
1787 PFN_NUMBER
1788 NTAPI
1789 MxGetNextPage(
1790 IN PFN_NUMBER PageCount
1791 );
1792
1793 PPHYSICAL_MEMORY_DESCRIPTOR
1794 NTAPI
1795 MmInitializeMemoryLimits(
1796 IN PLOADER_PARAMETER_BLOCK LoaderBlock,
1797 IN PBOOLEAN IncludeType
1798 );
1799
1800 PFN_NUMBER
1801 NTAPI
1802 MiPagesInLoaderBlock(
1803 IN PLOADER_PARAMETER_BLOCK LoaderBlock,
1804 IN PBOOLEAN IncludeType
1805 );
1806
1807 VOID
1808 FASTCALL
1809 MiSyncARM3WithROS(
1810 IN PVOID AddressStart,
1811 IN PVOID AddressEnd
1812 );
1813
1814 NTSTATUS
1815 NTAPI
1816 MiRosProtectVirtualMemory(
1817 IN PEPROCESS Process,
1818 IN OUT PVOID *BaseAddress,
1819 IN OUT PSIZE_T NumberOfBytesToProtect,
1820 IN ULONG NewAccessProtection,
1821 OUT PULONG OldAccessProtection OPTIONAL
1822 );
1823
1824 NTSTATUS
1825 NTAPI
1826 MmArmAccessFault(
1827 IN BOOLEAN StoreInstruction,
1828 IN PVOID Address,
1829 IN KPROCESSOR_MODE Mode,
1830 IN PVOID TrapInformation
1831 );
1832
1833 NTSTATUS
1834 FASTCALL
1835 MiCheckPdeForPagedPool(
1836 IN PVOID Address
1837 );
1838
1839 VOID
1840 NTAPI
1841 MiInitializeNonPagedPool(
1842 VOID
1843 );
1844
1845 VOID
1846 NTAPI
1847 MiInitializeNonPagedPoolThresholds(
1848 VOID
1849 );
1850
1851 VOID
1852 NTAPI
1853 MiInitializePoolEvents(
1854 VOID
1855 );
1856
1857 VOID //
1858 NTAPI //
1859 InitializePool( //
1860 IN POOL_TYPE PoolType,// FIXFIX: This should go in ex.h after the pool merge
1861 IN ULONG Threshold //
1862 ); //
1863
1864 // FIXFIX: THIS ONE TOO
1865 VOID
1866 NTAPI
1867 INIT_FUNCTION
1868 ExInitializePoolDescriptor(
1869 IN PPOOL_DESCRIPTOR PoolDescriptor,
1870 IN POOL_TYPE PoolType,
1871 IN ULONG PoolIndex,
1872 IN ULONG Threshold,
1873 IN PVOID PoolLock
1874 );
1875
1876 NTSTATUS
1877 NTAPI
1878 MiInitializeSessionPool(
1879 VOID
1880 );
1881
1882 VOID
1883 NTAPI
1884 MiInitializeSystemPtes(
1885 IN PMMPTE StartingPte,
1886 IN ULONG NumberOfPtes,
1887 IN MMSYSTEM_PTE_POOL_TYPE PoolType
1888 );
1889
1890 PMMPTE
1891 NTAPI
1892 MiReserveSystemPtes(
1893 IN ULONG NumberOfPtes,
1894 IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType
1895 );
1896
1897 VOID
1898 NTAPI
1899 MiReleaseSystemPtes(
1900 IN PMMPTE StartingPte,
1901 IN ULONG NumberOfPtes,
1902 IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType
1903 );
1904
1905
1906 PFN_NUMBER
1907 NTAPI
1908 MiFindContiguousPages(
1909 IN PFN_NUMBER LowestPfn,
1910 IN PFN_NUMBER HighestPfn,
1911 IN PFN_NUMBER BoundaryPfn,
1912 IN PFN_NUMBER SizeInPages,
1913 IN MEMORY_CACHING_TYPE CacheType
1914 );
1915
1916 PVOID
1917 NTAPI
1918 MiCheckForContiguousMemory(
1919 IN PVOID BaseAddress,
1920 IN PFN_NUMBER BaseAddressPages,
1921 IN PFN_NUMBER SizeInPages,
1922 IN PFN_NUMBER LowestPfn,
1923 IN PFN_NUMBER HighestPfn,
1924 IN PFN_NUMBER BoundaryPfn,
1925 IN MI_PFN_CACHE_ATTRIBUTE CacheAttribute
1926 );
1927
1928 PMDL
1929 NTAPI
1930 MiAllocatePagesForMdl(
1931 IN PHYSICAL_ADDRESS LowAddress,
1932 IN PHYSICAL_ADDRESS HighAddress,
1933 IN PHYSICAL_ADDRESS SkipBytes,
1934 IN SIZE_T TotalBytes,
1935 IN MI_PFN_CACHE_ATTRIBUTE CacheAttribute,
1936 IN ULONG Flags
1937 );
1938
1939 PVOID
1940 NTAPI
1941 MiMapLockedPagesInUserSpace(
1942 IN PMDL Mdl,
1943 IN PVOID BaseVa,
1944 IN MEMORY_CACHING_TYPE CacheType,
1945 IN PVOID BaseAddress
1946 );
1947
1948 VOID
1949 NTAPI
1950 MiUnmapLockedPagesInUserSpace(
1951 IN PVOID BaseAddress,
1952 IN PMDL Mdl
1953 );
1954
1955 VOID
1956 NTAPI
1957 MiInsertPageInList(
1958 IN PMMPFNLIST ListHead,
1959 IN PFN_NUMBER PageFrameIndex
1960 );
1961
1962 VOID
1963 NTAPI
1964 MiUnlinkFreeOrZeroedPage(
1965 IN PMMPFN Entry
1966 );
1967
1968 VOID
1969 NTAPI
1970 MiUnlinkPageFromList(
1971 IN PMMPFN Pfn
1972 );
1973
1974 PFN_NUMBER
1975 NTAPI
1976 MiAllocatePfn(
1977 IN PMMPTE PointerPte,
1978 IN ULONG Protection
1979 );
1980
1981 VOID
1982 NTAPI
1983 MiInitializePfn(
1984 IN PFN_NUMBER PageFrameIndex,
1985 IN PMMPTE PointerPte,
1986 IN BOOLEAN Modified
1987 );
1988
1989 NTSTATUS
1990 NTAPI
1991 MiInitializeAndChargePfn(
1992 OUT PPFN_NUMBER PageFrameIndex,
1993 IN PMMPTE PointerPde,
1994 IN PFN_NUMBER ContainingPageFrame,
1995 IN BOOLEAN SessionAllocation
1996 );
1997
1998 VOID
1999 NTAPI
2000 MiInitializePfnAndMakePteValid(
2001 IN PFN_NUMBER PageFrameIndex,
2002 IN PMMPTE PointerPte,
2003 IN MMPTE TempPte
2004 );
2005
2006 VOID
2007 NTAPI
2008 MiInitializePfnForOtherProcess(
2009 IN PFN_NUMBER PageFrameIndex,
2010 IN PMMPTE PointerPte,
2011 IN PFN_NUMBER PteFrame
2012 );
2013
2014 VOID
2015 NTAPI
2016 MiDecrementShareCount(
2017 IN PMMPFN Pfn1,
2018 IN PFN_NUMBER PageFrameIndex
2019 );
2020
2021 PFN_NUMBER
2022 NTAPI
2023 MiRemoveAnyPage(
2024 IN ULONG Color
2025 );
2026
2027 PFN_NUMBER
2028 NTAPI
2029 MiRemoveZeroPage(
2030 IN ULONG Color
2031 );
2032
2033 VOID
2034 NTAPI
2035 MiZeroPhysicalPage(
2036 IN PFN_NUMBER PageFrameIndex
2037 );
2038
2039 VOID
2040 NTAPI
2041 MiInsertPageInFreeList(
2042 IN PFN_NUMBER PageFrameIndex
2043 );
2044
2045 PFN_COUNT
2046 NTAPI
2047 MiDeleteSystemPageableVm(
2048 IN PMMPTE PointerPte,
2049 IN PFN_NUMBER PageCount,
2050 IN ULONG Flags,
2051 OUT PPFN_NUMBER ValidPages
2052 );
2053
2054 ULONG
2055 NTAPI
2056 MiGetPageProtection(
2057 IN PMMPTE PointerPte
2058 );
2059
2060 PLDR_DATA_TABLE_ENTRY
2061 NTAPI
2062 MiLookupDataTableEntry(
2063 IN PVOID Address
2064 );
2065
2066 VOID
2067 NTAPI
2068 MiInitializeDriverLargePageList(
2069 VOID
2070 );
2071
2072 VOID
2073 NTAPI
2074 MiInitializeLargePageSupport(
2075 VOID
2076 );
2077
2078 VOID
2079 NTAPI
2080 MiSyncCachedRanges(
2081 VOID
2082 );
2083
2084 BOOLEAN
2085 NTAPI
2086 MiIsPfnInUse(
2087 IN PMMPFN Pfn1
2088 );
2089
2090 PMMVAD
2091 NTAPI
2092 MiLocateAddress(
2093 IN PVOID VirtualAddress
2094 );
2095
2096 PMMADDRESS_NODE
2097 NTAPI
2098 MiCheckForConflictingNode(
2099 IN ULONG_PTR StartVpn,
2100 IN ULONG_PTR EndVpn,
2101 IN PMM_AVL_TABLE Table
2102 );
2103
2104 TABLE_SEARCH_RESULT
2105 NTAPI
2106 MiFindEmptyAddressRangeDownTree(
2107 IN SIZE_T Length,
2108 IN ULONG_PTR BoundaryAddress,
2109 IN ULONG_PTR Alignment,
2110 IN PMM_AVL_TABLE Table,
2111 OUT PULONG_PTR Base,
2112 OUT PMMADDRESS_NODE *Parent
2113 );
2114
2115 NTSTATUS
2116 NTAPI
2117 MiFindEmptyAddressRangeDownBasedTree(
2118 IN SIZE_T Length,
2119 IN ULONG_PTR BoundaryAddress,
2120 IN ULONG_PTR Alignment,
2121 IN PMM_AVL_TABLE Table,
2122 OUT PULONG_PTR Base
2123 );
2124
2125 NTSTATUS
2126 NTAPI
2127 MiFindEmptyAddressRangeInTree(
2128 IN SIZE_T Length,
2129 IN ULONG_PTR Alignment,
2130 IN PMM_AVL_TABLE Table,
2131 OUT PMMADDRESS_NODE *PreviousVad,
2132 OUT PULONG_PTR Base
2133 );
2134
2135 NTSTATUS
2136 NTAPI
2137 MiCheckSecuredVad(
2138 IN PMMVAD Vad,
2139 IN PVOID Base,
2140 IN SIZE_T Size,
2141 IN ULONG ProtectionMask
2142 );
2143
2144 VOID
2145 NTAPI
2146 MiInsertVad(
2147 IN PMMVAD Vad,
2148 IN PEPROCESS Process
2149 );
2150
2151 VOID
2152 NTAPI
2153 MiInsertBasedSection(
2154 IN PSECTION Section
2155 );
2156
2157 NTSTATUS
2158 NTAPI
2159 MiUnmapViewOfSection(
2160 IN PEPROCESS Process,
2161 IN PVOID BaseAddress,
2162 IN ULONG Flags
2163 );
2164
2165 NTSTATUS
2166 NTAPI
2167 MiRosUnmapViewOfSection(
2168 IN PEPROCESS Process,
2169 IN PVOID BaseAddress,
2170 IN ULONG Flags
2171 );
2172
2173 VOID
2174 NTAPI
2175 MiInsertNode(
2176 IN PMM_AVL_TABLE Table,
2177 IN PMMADDRESS_NODE NewNode,
2178 PMMADDRESS_NODE Parent,
2179 TABLE_SEARCH_RESULT Result
2180 );
2181
2182 VOID
2183 NTAPI
2184 MiRemoveNode(
2185 IN PMMADDRESS_NODE Node,
2186 IN PMM_AVL_TABLE Table
2187 );
2188
2189 PMMADDRESS_NODE
2190 NTAPI
2191 MiGetPreviousNode(
2192 IN PMMADDRESS_NODE Node
2193 );
2194
2195 PMMADDRESS_NODE
2196 NTAPI
2197 MiGetNextNode(
2198 IN PMMADDRESS_NODE Node
2199 );
2200
2201 BOOLEAN
2202 NTAPI
2203 MiInitializeSystemSpaceMap(
2204 IN PMMSESSION InputSession OPTIONAL
2205 );
2206
2207 VOID
2208 NTAPI
2209 MiSessionRemoveProcess(
2210 VOID
2211 );
2212
2213 VOID
2214 NTAPI
2215 MiReleaseProcessReferenceToSessionDataPage(
2216 IN PMM_SESSION_SPACE SessionGlobal
2217 );
2218
2219 VOID
2220 NTAPI
2221 MiSessionAddProcess(
2222 IN PEPROCESS NewProcess
2223 );
2224
2225 NTSTATUS
2226 NTAPI
2227 MiSessionCommitPageTables(
2228 IN PVOID StartVa,
2229 IN PVOID EndVa
2230 );
2231
2232 ULONG
2233 NTAPI
2234 MiMakeProtectionMask(
2235 IN ULONG Protect
2236 );
2237
2238 VOID
2239 NTAPI
2240 MiDeleteVirtualAddresses(
2241 IN ULONG_PTR Va,
2242 IN ULONG_PTR EndingAddress,
2243 IN PMMVAD Vad
2244 );
2245
2246 ULONG
2247 NTAPI
2248 MiMakeSystemAddressValid(
2249 IN PVOID PageTableVirtualAddress,
2250 IN PEPROCESS CurrentProcess
2251 );
2252
2253 ULONG
2254 NTAPI
2255 MiMakeSystemAddressValidPfn(
2256 IN PVOID VirtualAddress,
2257 IN KIRQL OldIrql
2258 );
2259
2260 VOID
2261 NTAPI
2262 MiRemoveMappedView(
2263 IN PEPROCESS CurrentProcess,
2264 IN PMMVAD Vad
2265 );
2266
2267 PSUBSECTION
2268 NTAPI
2269 MiLocateSubsection(
2270 IN PMMVAD Vad,
2271 IN ULONG_PTR Vpn
2272 );
2273
2274 NTSTATUS
2275 NTAPI
2276 MiQueryMemorySectionName(
2277 IN HANDLE ProcessHandle,
2278 IN PVOID BaseAddress,
2279 OUT PVOID MemoryInformation,
2280 IN SIZE_T MemoryInformationLength,
2281 OUT PSIZE_T ReturnLength
2282 );
2283
2284 NTSTATUS
2285 NTAPI
2286 MiRosUnmapViewInSystemSpace(
2287 IN PVOID MappedBase
2288 );
2289
2290 POOL_TYPE
2291 NTAPI
2292 MmDeterminePoolType(
2293 IN PVOID PoolAddress
2294 );
2295
2296 VOID
2297 NTAPI
2298 MiMakePdeExistAndMakeValid(
2299 IN PMMPTE PointerPde,
2300 IN PEPROCESS TargetProcess,
2301 IN KIRQL OldIrql
2302 );
2303
2304 //
2305 // MiRemoveZeroPage will use inline code to zero out the page manually if only
2306 // free pages are available. In some scenarios, we don't/can't run that piece of
2307 // code and would rather only have a real zero page. If we can't have a zero page,
2308 // then we'd like to have our own code to grab a free page and zero it out, by
2309 // using MiRemoveAnyPage. This macro implements this.
2310 //
2311 FORCEINLINE
2312 PFN_NUMBER
2313 MiRemoveZeroPageSafe(IN ULONG Color)
2314 {
2315 if (MmFreePagesByColor[ZeroedPageList][Color].Flink != LIST_HEAD) return MiRemoveZeroPage(Color);
2316 return 0;
2317 }
2318
2319 /* EOF */