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