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