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