[NTOS]: To Timo, with Love (make System PTEs work on x64).
[reactos.git] / reactos / ntoskrnl / mm / ARM3 / miarm.h
1 /*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * FILE: ntoskrnl/mm/ARM3/miarm.h
5 * PURPOSE: ARM Memory Manager Header
6 * PROGRAMMERS: ReactOS Portable Systems Group
7 */
8
9 #ifndef _M_AMD64
10
11 #define MI_MIN_PAGES_FOR_NONPAGED_POOL_TUNING ((255 * _1MB) >> PAGE_SHIFT)
12 #define MI_MIN_PAGES_FOR_SYSPTE_TUNING ((19 * _1MB) >> PAGE_SHIFT)
13 #define MI_MIN_PAGES_FOR_SYSPTE_BOOST ((32 * _1MB) >> PAGE_SHIFT)
14 #define MI_MAX_INIT_NONPAGED_POOL_SIZE (128 * _1MB)
15 #define MI_MAX_NONPAGED_POOL_SIZE (128 * _1MB)
16 #define MI_MAX_FREE_PAGE_LISTS 4
17
18 #define MI_MIN_INIT_PAGED_POOLSIZE (32 * _1MB)
19
20 #define MI_SESSION_VIEW_SIZE (20 * _1MB)
21 #define MI_SESSION_POOL_SIZE (16 * _1MB)
22 #define MI_SESSION_IMAGE_SIZE (8 * _1MB)
23 #define MI_SESSION_WORKING_SET_SIZE (4 * _1MB)
24 #define MI_SESSION_SIZE (MI_SESSION_VIEW_SIZE + \
25 MI_SESSION_POOL_SIZE + \
26 MI_SESSION_IMAGE_SIZE + \
27 MI_SESSION_WORKING_SET_SIZE)
28
29 #define MI_SYSTEM_VIEW_SIZE (16 * _1MB)
30
31 #define MI_SYSTEM_CACHE_WS_START (PVOID)0xC0C00000
32 #define MI_PAGED_POOL_START (PVOID)0xE1000000
33 #define MI_NONPAGED_POOL_END (PVOID)0xFFBE0000
34 #define MI_DEBUG_MAPPING (PVOID)0xFFBFF000
35
36 // on AMD64 this would be MiAddressToPte(MM_KSEG0_BASE)
37 #define MI_SYSTEM_PTE_BASE (PVOID)MiAddressToPte(NULL)
38
39 #define MI_MIN_SECONDARY_COLORS 8
40 #define MI_SECONDARY_COLORS 64
41 #define MI_MAX_SECONDARY_COLORS 1024
42
43 #define MI_MIN_ALLOCATION_FRAGMENT (4 * _1KB)
44 #define MI_ALLOCATION_FRAGMENT (64 * _1KB)
45 #define MI_MAX_ALLOCATION_FRAGMENT (2 * _1MB)
46
47 #define MM_HIGHEST_VAD_ADDRESS \
48 (PVOID)((ULONG_PTR)MM_HIGHEST_USER_ADDRESS - (16 * PAGE_SIZE))
49
50 /* The range 0x10000->0x7FEFFFFF is reserved for the ROSMM MAREA Allocator */
51 #define MI_LOWEST_VAD_ADDRESS (PVOID)0x7FF00000
52
53 #endif /* !_M_AMD64 */
54
55 /* Make the code cleaner with some definitions for size multiples */
56 #define _1KB (1024u)
57 #define _1MB (1024 * _1KB)
58 #define _1GB (1024 * _1MB)
59
60 /* Area mapped by a PDE */
61 #define PDE_MAPPED_VA (PTE_COUNT * PAGE_SIZE)
62
63 /* Size of a page table */
64 #define PT_SIZE (PTE_COUNT * sizeof(MMPTE))
65
66 /* Architecture specific count of PDEs in a directory, and count of PTEs in a PT */
67 #ifdef _M_IX86
68 #define PD_COUNT 1
69 #define PDE_COUNT 1024
70 #define PTE_COUNT 1024
71 #elif _M_ARM
72 #define PD_COUNT 1
73 #define PDE_COUNT 4096
74 #define PTE_COUNT 256
75 #else
76 #define PD_COUNT PPE_PER_PAGE
77 #define PDE_COUNT PDE_PER_PAGE
78 #define PTE_COUNT PTE_PER_PAGE
79 #endif
80
81 #ifdef _M_IX86
82 #define IMAGE_FILE_MACHINE_NATIVE IMAGE_FILE_MACHINE_I386
83 #elif _M_ARM
84 #define IMAGE_FILE_MACHINE_NATIVE IMAGE_FILE_MACHINE_ARM
85 #elif _M_AMD64
86 #define IMAGE_FILE_MACHINE_NATIVE IMAGE_FILE_MACHINE_AMD64
87 #else
88 #error Define these please!
89 #endif
90
91 //
92 // Protection Bits part of the internal memory manager Protection Mask
93 // Taken from http://www.reactos.org/wiki/Techwiki:Memory_management_in_the_Windows_XP_kernel
94 // and public assertions.
95 //
96 #define MM_ZERO_ACCESS 0
97 #define MM_READONLY 1
98 #define MM_EXECUTE 2
99 #define MM_EXECUTE_READ 3
100 #define MM_READWRITE 4
101 #define MM_WRITECOPY 5
102 #define MM_EXECUTE_READWRITE 6
103 #define MM_EXECUTE_WRITECOPY 7
104 #define MM_NOCACHE 8
105 #define MM_DECOMMIT 0x10
106 #define MM_NOACCESS (MM_DECOMMIT | MM_NOCACHE)
107
108 //
109 // Specific PTE Definitions that map to the Memory Manager's Protection Mask Bits
110 // The Memory Manager's definition define the attributes that must be preserved
111 // and these PTE definitions describe the attributes in the hardware sense. This
112 // helps deal with hardware differences between the actual boolean expression of
113 // the argument.
114 //
115 // For example, in the logical attributes, we want to express read-only as a flag
116 // but on x86, it is writability that must be set. On the other hand, on x86, just
117 // like in the kernel, it is disabling the caches that requires a special flag,
118 // while on certain architectures such as ARM, it is enabling the cache which
119 // requires a flag.
120 //
121 #if defined(_M_IX86) || defined(_M_AMD64)
122 //
123 // Access Flags
124 //
125 #define PTE_READONLY 0
126 #define PTE_EXECUTE 0 // Not worrying about NX yet
127 #define PTE_EXECUTE_READ 0 // Not worrying about NX yet
128 #define PTE_READWRITE 0x2
129 #define PTE_WRITECOPY 0x200
130 #define PTE_EXECUTE_READWRITE 0x0
131 #define PTE_EXECUTE_WRITECOPY 0x200
132 //
133 // Cache flags
134 //
135 #define PTE_ENABLE_CACHE 0
136 #define PTE_DISABLE_CACHE 0x10
137 #define PTE_WRITECOMBINED_CACHE 0x10
138 #elif defined(_M_ARM)
139 #else
140 #error Define these please!
141 #endif
142 static const
143 ULONG
144 MmProtectToPteMask[32] =
145 {
146 //
147 // These are the base MM_ protection flags
148 //
149 0,
150 PTE_READONLY | PTE_ENABLE_CACHE,
151 PTE_EXECUTE | PTE_ENABLE_CACHE,
152 PTE_EXECUTE_READ | PTE_ENABLE_CACHE,
153 PTE_READWRITE | PTE_ENABLE_CACHE,
154 PTE_WRITECOPY | PTE_ENABLE_CACHE,
155 PTE_EXECUTE_READWRITE | PTE_ENABLE_CACHE,
156 PTE_EXECUTE_WRITECOPY | PTE_ENABLE_CACHE,
157 //
158 // These OR in the MM_NOCACHE flag
159 //
160 0,
161 PTE_READONLY | PTE_DISABLE_CACHE,
162 PTE_EXECUTE | PTE_DISABLE_CACHE,
163 PTE_EXECUTE_READ | PTE_DISABLE_CACHE,
164 PTE_READWRITE | PTE_DISABLE_CACHE,
165 PTE_WRITECOPY | PTE_DISABLE_CACHE,
166 PTE_EXECUTE_READWRITE | PTE_DISABLE_CACHE,
167 PTE_EXECUTE_WRITECOPY | PTE_DISABLE_CACHE,
168 //
169 // These OR in the MM_DECOMMIT flag, which doesn't seem supported on x86/64/ARM
170 //
171 0,
172 PTE_READONLY | PTE_ENABLE_CACHE,
173 PTE_EXECUTE | PTE_ENABLE_CACHE,
174 PTE_EXECUTE_READ | PTE_ENABLE_CACHE,
175 PTE_READWRITE | PTE_ENABLE_CACHE,
176 PTE_WRITECOPY | PTE_ENABLE_CACHE,
177 PTE_EXECUTE_READWRITE | PTE_ENABLE_CACHE,
178 PTE_EXECUTE_WRITECOPY | PTE_ENABLE_CACHE,
179 //
180 // These OR in the MM_NOACCESS flag, which seems to enable WriteCombining?
181 //
182 0,
183 PTE_READONLY | PTE_WRITECOMBINED_CACHE,
184 PTE_EXECUTE | PTE_WRITECOMBINED_CACHE,
185 PTE_EXECUTE_READ | PTE_WRITECOMBINED_CACHE,
186 PTE_READWRITE | PTE_WRITECOMBINED_CACHE,
187 PTE_WRITECOPY | PTE_WRITECOMBINED_CACHE,
188 PTE_EXECUTE_READWRITE | PTE_WRITECOMBINED_CACHE,
189 PTE_EXECUTE_WRITECOPY | PTE_WRITECOMBINED_CACHE,
190 };
191
192 //
193 // Assertions for session images, addresses, and PTEs
194 //
195 #define MI_IS_SESSION_IMAGE_ADDRESS(Address) \
196 (((Address) >= MiSessionImageStart) && ((Address) < MiSessionImageEnd))
197
198 #define MI_IS_SESSION_ADDRESS(Address) \
199 (((Address) >= MmSessionBase) && ((Address) < MiSessionSpaceEnd))
200
201 #define MI_IS_SESSION_PTE(Pte) \
202 ((((PMMPTE)Pte) >= MiSessionBasePte) && (((PMMPTE)Pte) < MiSessionLastPte))
203
204 #define MI_IS_PAGE_TABLE_ADDRESS(Address) \
205 (((PVOID)(Address) >= (PVOID)PTE_BASE) && ((PVOID)(Address) <= (PVOID)PTE_TOP))
206
207 #define MI_IS_SYSTEM_PAGE_TABLE_ADDRESS(Address) \
208 (((Address) >= (PVOID)MiAddressToPte(MmSystemRangeStart)) && ((Address) <= (PVOID)PTE_TOP))
209
210 #define MI_IS_PAGE_TABLE_OR_HYPER_ADDRESS(Address) \
211 (((PVOID)(Address) >= (PVOID)PTE_BASE) && ((PVOID)(Address) <= (PVOID)MmHyperSpaceEnd))
212
213 //
214 // Corresponds to MMPTE_SOFTWARE.Protection
215 //
216 #ifdef _M_IX86
217 #define MM_PTE_SOFTWARE_PROTECTION_BITS 5
218 #elif _M_ARM
219 #define MM_PTE_SOFTWARE_PROTECTION_BITS 5
220 #elif _M_AMD64
221 #define MM_PTE_SOFTWARE_PROTECTION_BITS 5
222 #else
223 #error Define these please!
224 #endif
225
226 //
227 // Creates a software PTE with the given protection
228 //
229 #define MI_MAKE_SOFTWARE_PTE(p, x) ((p)->u.Long = (x << MM_PTE_SOFTWARE_PROTECTION_BITS))
230
231 //
232 // Marks a PTE as deleted
233 //
234 #define MI_SET_PFN_DELETED(x) ((x)->PteAddress = (PMMPTE)((ULONG_PTR)(x)->PteAddress | 1))
235 #define MI_IS_PFN_DELETED(x) ((ULONG_PTR)((x)->PteAddress) & 1)
236
237 //
238 // Special values for LoadedImports
239 //
240 #define MM_SYSLDR_NO_IMPORTS (PVOID)0xFFFFFFFE
241 #define MM_SYSLDR_BOOT_LOADED (PVOID)0xFFFFFFFF
242 #define MM_SYSLDR_SINGLE_ENTRY 0x1
243
244 //
245 // PFN List Sentinel
246 //
247 #define LIST_HEAD 0xFFFFFFFF
248
249 //
250 // Special IRQL value (found in assertions)
251 //
252 #define MM_NOIRQL (KIRQL)0xFFFFFFFF
253
254 //
255 // FIXFIX: These should go in ex.h after the pool merge
256 //
257 #ifdef _M_AMD64
258 #define POOL_BLOCK_SIZE 16
259 #else
260 #define POOL_BLOCK_SIZE 8
261 #endif
262 #define POOL_LISTS_PER_PAGE (PAGE_SIZE / POOL_BLOCK_SIZE)
263 #define BASE_POOL_TYPE_MASK 1
264 #define POOL_MAX_ALLOC (PAGE_SIZE - (sizeof(POOL_HEADER) + POOL_BLOCK_SIZE))
265
266 typedef struct _POOL_DESCRIPTOR
267 {
268 POOL_TYPE PoolType;
269 ULONG PoolIndex;
270 ULONG RunningAllocs;
271 ULONG RunningDeAllocs;
272 ULONG TotalPages;
273 ULONG TotalBigPages;
274 ULONG Threshold;
275 PVOID LockAddress;
276 PVOID PendingFrees;
277 LONG PendingFreeDepth;
278 SIZE_T TotalBytes;
279 SIZE_T Spare0;
280 LIST_ENTRY ListHeads[POOL_LISTS_PER_PAGE];
281 } POOL_DESCRIPTOR, *PPOOL_DESCRIPTOR;
282
283 typedef struct _POOL_HEADER
284 {
285 union
286 {
287 struct
288 {
289 #ifdef _M_AMD64
290 ULONG PreviousSize:8;
291 ULONG PoolIndex:8;
292 ULONG BlockSize:8;
293 ULONG PoolType:8;
294 #else
295 USHORT PreviousSize:9;
296 USHORT PoolIndex:7;
297 USHORT BlockSize:9;
298 USHORT PoolType:7;
299 #endif
300 };
301 ULONG Ulong1;
302 };
303 #ifdef _M_AMD64
304 ULONG PoolTag;
305 #endif
306 union
307 {
308 #ifdef _M_AMD64
309 PEPROCESS ProcessBilled;
310 #else
311 ULONG PoolTag;
312 #endif
313 struct
314 {
315 USHORT AllocatorBackTraceIndex;
316 USHORT PoolTagHash;
317 };
318 };
319 } POOL_HEADER, *PPOOL_HEADER;
320
321 C_ASSERT(sizeof(POOL_HEADER) == POOL_BLOCK_SIZE);
322 C_ASSERT(POOL_BLOCK_SIZE == sizeof(LIST_ENTRY));
323
324 extern ULONG ExpNumberOfPagedPools;
325 extern POOL_DESCRIPTOR NonPagedPoolDescriptor;
326 extern PPOOL_DESCRIPTOR ExpPagedPoolDescriptor[16 + 1];
327 extern PVOID PoolTrackTable;
328
329 //
330 // END FIXFIX
331 //
332
333 typedef struct _MI_LARGE_PAGE_DRIVER_ENTRY
334 {
335 LIST_ENTRY Links;
336 UNICODE_STRING BaseName;
337 } MI_LARGE_PAGE_DRIVER_ENTRY, *PMI_LARGE_PAGE_DRIVER_ENTRY;
338
339 typedef enum _MMSYSTEM_PTE_POOL_TYPE
340 {
341 SystemPteSpace,
342 NonPagedPoolExpansion,
343 MaximumPtePoolTypes
344 } MMSYSTEM_PTE_POOL_TYPE;
345
346 typedef enum _MI_PFN_CACHE_ATTRIBUTE
347 {
348 MiNonCached,
349 MiCached,
350 MiWriteCombined,
351 MiNotMapped
352 } MI_PFN_CACHE_ATTRIBUTE, *PMI_PFN_CACHE_ATTRIBUTE;
353
354 typedef struct _PHYSICAL_MEMORY_RUN
355 {
356 ULONG BasePage;
357 ULONG PageCount;
358 } PHYSICAL_MEMORY_RUN, *PPHYSICAL_MEMORY_RUN;
359
360 typedef struct _PHYSICAL_MEMORY_DESCRIPTOR
361 {
362 ULONG NumberOfRuns;
363 ULONG NumberOfPages;
364 PHYSICAL_MEMORY_RUN Run[1];
365 } PHYSICAL_MEMORY_DESCRIPTOR, *PPHYSICAL_MEMORY_DESCRIPTOR;
366
367 typedef struct _MMCOLOR_TABLES
368 {
369 PFN_NUMBER Flink;
370 PVOID Blink;
371 PFN_NUMBER Count;
372 } MMCOLOR_TABLES, *PMMCOLOR_TABLES;
373
374 typedef struct _MI_LARGE_PAGE_RANGES
375 {
376 PFN_NUMBER StartFrame;
377 PFN_NUMBER LastFrame;
378 } MI_LARGE_PAGE_RANGES, *PMI_LARGE_PAGE_RANGES;
379
380 extern MMPTE HyperTemplatePte;
381 extern MMPDE ValidKernelPde;
382 extern MMPTE ValidKernelPte;
383 extern MMPDE DemandZeroPde;
384 extern BOOLEAN MmLargeSystemCache;
385 extern BOOLEAN MmZeroPageFile;
386 extern BOOLEAN MmProtectFreedNonPagedPool;
387 extern BOOLEAN MmTrackLockedPages;
388 extern BOOLEAN MmTrackPtes;
389 extern BOOLEAN MmDynamicPfn;
390 extern BOOLEAN MmMirroring;
391 extern BOOLEAN MmMakeLowMemory;
392 extern BOOLEAN MmEnforceWriteProtection;
393 extern ULONG MmAllocationFragment;
394 extern ULONG MmConsumedPoolPercentage;
395 extern ULONG MmVerifyDriverBufferType;
396 extern ULONG MmVerifyDriverLevel;
397 extern WCHAR MmVerifyDriverBuffer[512];
398 extern WCHAR MmLargePageDriverBuffer[512];
399 extern LIST_ENTRY MiLargePageDriverList;
400 extern BOOLEAN MiLargePageAllDrivers;
401 extern ULONG MmVerifyDriverBufferLength;
402 extern ULONG MmLargePageDriverBufferLength;
403 extern SIZE_T MmSizeOfNonPagedPoolInBytes;
404 extern SIZE_T MmMaximumNonPagedPoolInBytes;
405 extern PFN_NUMBER MmMaximumNonPagedPoolInPages;
406 extern PFN_NUMBER MmSizeOfPagedPoolInPages;
407 extern PVOID MmNonPagedSystemStart;
408 extern PVOID MmNonPagedPoolStart;
409 extern PVOID MmNonPagedPoolExpansionStart;
410 extern PVOID MmNonPagedPoolEnd;
411 extern SIZE_T MmSizeOfPagedPoolInBytes;
412 extern PVOID MmPagedPoolStart;
413 extern PVOID MmPagedPoolEnd;
414 extern PVOID MmSessionBase;
415 extern SIZE_T MmSessionSize;
416 extern PMMPTE MmFirstReservedMappingPte, MmLastReservedMappingPte;
417 extern PMMPTE MiFirstReservedZeroingPte;
418 extern MI_PFN_CACHE_ATTRIBUTE MiPlatformCacheAttributes[2][MmMaximumCacheType];
419 extern PPHYSICAL_MEMORY_DESCRIPTOR MmPhysicalMemoryBlock;
420 extern SIZE_T MmBootImageSize;
421 extern PMMPTE MmSystemPtesStart[MaximumPtePoolTypes];
422 extern PMMPTE MmSystemPtesEnd[MaximumPtePoolTypes];
423 extern PMEMORY_ALLOCATION_DESCRIPTOR MxFreeDescriptor;
424 extern MEMORY_ALLOCATION_DESCRIPTOR MxOldFreeDescriptor;
425 extern ULONG_PTR MxPfnAllocation;
426 extern MM_PAGED_POOL_INFO MmPagedPoolInfo;
427 extern RTL_BITMAP MiPfnBitMap;
428 extern KGUARDED_MUTEX MmPagedPoolMutex;
429 extern PVOID MmPagedPoolStart;
430 extern PVOID MmPagedPoolEnd;
431 extern PVOID MmNonPagedSystemStart;
432 extern PVOID MiSystemViewStart;
433 extern SIZE_T MmSystemViewSize;
434 extern PVOID MmSessionBase;
435 extern PVOID MiSessionSpaceEnd;
436 extern PMMPTE MiSessionImagePteStart;
437 extern PMMPTE MiSessionImagePteEnd;
438 extern PMMPTE MiSessionBasePte;
439 extern PMMPTE MiSessionLastPte;
440 extern SIZE_T MmSizeOfPagedPoolInBytes;
441 extern PMMPTE MmSystemPagePtes;
442 extern PVOID MmSystemCacheStart;
443 extern PVOID MmSystemCacheEnd;
444 extern MMSUPPORT MmSystemCacheWs;
445 extern SIZE_T MmAllocatedNonPagedPool;
446 extern ULONG_PTR MmSubsectionBase;
447 extern ULONG MmSpecialPoolTag;
448 extern PVOID MmHyperSpaceEnd;
449 extern PMMWSL MmSystemCacheWorkingSetList;
450 extern SIZE_T MmMinimumNonPagedPoolSize;
451 extern ULONG MmMinAdditionNonPagedPoolPerMb;
452 extern SIZE_T MmDefaultMaximumNonPagedPool;
453 extern ULONG MmMaxAdditionNonPagedPoolPerMb;
454 extern ULONG MmSecondaryColors;
455 extern ULONG MmSecondaryColorMask;
456 extern ULONG_PTR MmNumberOfSystemPtes;
457 extern ULONG MmMaximumNonPagedPoolPercent;
458 extern ULONG MmLargeStackSize;
459 extern PMMCOLOR_TABLES MmFreePagesByColor[FreePageList + 1];
460 extern ULONG MmProductType;
461 extern MM_SYSTEMSIZE MmSystemSize;
462 extern PKEVENT MiLowMemoryEvent;
463 extern PKEVENT MiHighMemoryEvent;
464 extern PKEVENT MiLowPagedPoolEvent;
465 extern PKEVENT MiHighPagedPoolEvent;
466 extern PKEVENT MiLowNonPagedPoolEvent;
467 extern PKEVENT MiHighNonPagedPoolEvent;
468 extern PFN_NUMBER MmLowMemoryThreshold;
469 extern PFN_NUMBER MmHighMemoryThreshold;
470 extern PFN_NUMBER MiLowPagedPoolThreshold;
471 extern PFN_NUMBER MiHighPagedPoolThreshold;
472 extern PFN_NUMBER MiLowNonPagedPoolThreshold;
473 extern PFN_NUMBER MiHighNonPagedPoolThreshold;
474 extern PFN_NUMBER MmMinimumFreePages;
475 extern PFN_NUMBER MmPlentyFreePages;
476 extern PFN_NUMBER MiExpansionPoolPagesInitialCharge;
477 extern PFN_NUMBER MmResidentAvailablePages;
478 extern PFN_NUMBER MmResidentAvailableAtInit;
479 extern ULONG MmTotalFreeSystemPtes[MaximumPtePoolTypes];
480 extern PFN_NUMBER MmTotalSystemDriverPages;
481 extern PVOID MiSessionImageStart;
482 extern PVOID MiSessionImageEnd;
483 extern PMMPTE MiHighestUserPte;
484 extern PMMPDE MiHighestUserPde;
485 extern PFN_NUMBER MmSystemPageDirectory[PD_COUNT];
486
487 #define MI_PFN_TO_PFNENTRY(x) (&MmPfnDatabase[1][x])
488 #define MI_PFNENTRY_TO_PFN(x) (x - MmPfnDatabase[1])
489
490 //
491 // Figures out the hardware bits for a PTE
492 //
493 ULONG
494 FORCEINLINE
495 MiDetermineUserGlobalPteMask(IN PMMPTE PointerPte)
496 {
497 MMPTE TempPte;
498
499 /* Start fresh */
500 TempPte.u.Long = 0;
501
502 /* Make it valid and accessed */
503 TempPte.u.Hard.Valid = TRUE;
504 TempPte.u.Hard.Accessed = TRUE;
505
506 /* Is this for user-mode? */
507 if ((PointerPte <= MiHighestUserPte) ||
508 ((PointerPte >= MiAddressToPde(NULL)) && (PointerPte <= MiHighestUserPde)))
509 {
510 /* Set the owner bit */
511 TempPte.u.Hard.Owner = TRUE;
512 }
513
514 /* FIXME: We should also set the global bit */
515
516 /* Return the protection */
517 return TempPte.u.Long;
518 }
519
520 //
521 // Creates a valid kernel PTE with the given protection
522 //
523 FORCEINLINE
524 VOID
525 MI_MAKE_HARDWARE_PTE_KERNEL(IN PMMPTE NewPte,
526 IN PMMPTE MappingPte,
527 IN ULONG ProtectionMask,
528 IN PFN_NUMBER PageFrameNumber)
529 {
530 /* Only valid for kernel, non-session PTEs */
531 ASSERT(MappingPte > MiHighestUserPte);
532 ASSERT(!MI_IS_SESSION_PTE(MappingPte));
533 ASSERT((MappingPte < (PMMPTE)PDE_BASE) || (MappingPte > (PMMPTE)PDE_TOP));
534
535 /* Start fresh */
536 *NewPte = ValidKernelPte;
537
538 /* Set the protection and page */
539 NewPte->u.Hard.PageFrameNumber = PageFrameNumber;
540 NewPte->u.Long |= MmProtectToPteMask[ProtectionMask];
541 }
542
543 //
544 // Creates a valid PTE with the given protection
545 //
546 FORCEINLINE
547 VOID
548 MI_MAKE_HARDWARE_PTE(IN PMMPTE NewPte,
549 IN PMMPTE MappingPte,
550 IN ULONG ProtectionMask,
551 IN PFN_NUMBER PageFrameNumber)
552 {
553 /* Set the protection and page */
554 NewPte->u.Long = MiDetermineUserGlobalPteMask(MappingPte);
555 NewPte->u.Long |= MmProtectToPteMask[ProtectionMask];
556 NewPte->u.Hard.PageFrameNumber = PageFrameNumber;
557 }
558
559 //
560 // Creates a valid user PTE with the given protection
561 //
562 FORCEINLINE
563 VOID
564 MI_MAKE_HARDWARE_PTE_USER(IN PMMPTE NewPte,
565 IN PMMPTE MappingPte,
566 IN ULONG ProtectionMask,
567 IN PFN_NUMBER PageFrameNumber)
568 {
569 /* Only valid for kernel, non-session PTEs */
570 ASSERT(MappingPte <= MiHighestUserPte);
571
572 /* Start fresh */
573 *NewPte = ValidKernelPte;
574
575 /* Set the protection and page */
576 NewPte->u.Hard.Owner = TRUE;
577 NewPte->u.Hard.PageFrameNumber = PageFrameNumber;
578 NewPte->u.Long |= MmProtectToPteMask[ProtectionMask];
579 }
580
581 //
582 // Returns if the page is physically resident (ie: a large page)
583 // FIXFIX: CISC/x86 only?
584 //
585 FORCEINLINE
586 BOOLEAN
587 MI_IS_PHYSICAL_ADDRESS(IN PVOID Address)
588 {
589 PMMPDE PointerPde;
590
591 /* Large pages are never paged out, always physically resident */
592 PointerPde = MiAddressToPde(Address);
593 return ((PointerPde->u.Hard.LargePage) && (PointerPde->u.Hard.Valid));
594 }
595
596 //
597 // Writes a valid PTE
598 //
599 VOID
600 FORCEINLINE
601 MI_WRITE_VALID_PTE(IN PMMPTE PointerPte,
602 IN MMPTE TempPte)
603 {
604 /* Write the valid PTE */
605 ASSERT(PointerPte->u.Hard.Valid == 0);
606 ASSERT(TempPte.u.Hard.Valid == 1);
607 *PointerPte = TempPte;
608 }
609
610 //
611 // Writes an invalid PTE
612 //
613 VOID
614 FORCEINLINE
615 MI_WRITE_INVALID_PTE(IN PMMPTE PointerPte,
616 IN MMPTE InvalidPte)
617 {
618 /* Write the invalid PTE */
619 ASSERT(InvalidPte.u.Hard.Valid == 0);
620 *PointerPte = InvalidPte;
621 }
622
623 //
624 // Checks if the thread already owns a working set
625 //
626 FORCEINLINE
627 BOOLEAN
628 MM_ANY_WS_LOCK_HELD(IN PETHREAD Thread)
629 {
630 /* If any of these are held, return TRUE */
631 return ((Thread->OwnsProcessWorkingSetExclusive) ||
632 (Thread->OwnsProcessWorkingSetShared) ||
633 (Thread->OwnsSystemWorkingSetExclusive) ||
634 (Thread->OwnsSystemWorkingSetShared) ||
635 (Thread->OwnsSessionWorkingSetExclusive) ||
636 (Thread->OwnsSessionWorkingSetShared));
637 }
638
639 //
640 // Checks if the process owns the working set lock
641 //
642 FORCEINLINE
643 BOOLEAN
644 MI_WS_OWNER(IN PEPROCESS Process)
645 {
646 /* Check if this process is the owner, and that the thread owns the WS */
647 return ((KeGetCurrentThread()->ApcState.Process == &Process->Pcb) &&
648 ((PsGetCurrentThread()->OwnsProcessWorkingSetExclusive) ||
649 (PsGetCurrentThread()->OwnsProcessWorkingSetShared)));
650 }
651
652 //
653 // Locks the working set for the given process
654 //
655 FORCEINLINE
656 VOID
657 MiLockProcessWorkingSet(IN PEPROCESS Process,
658 IN PETHREAD Thread)
659 {
660 /* Shouldn't already be owning the process working set */
661 ASSERT(Thread->OwnsProcessWorkingSetShared == FALSE);
662 ASSERT(Thread->OwnsProcessWorkingSetExclusive == FALSE);
663
664 /* Block APCs, make sure that still nothing is already held */
665 KeEnterGuardedRegion();
666 ASSERT(!MM_ANY_WS_LOCK_HELD(Thread));
667
668 /* FIXME: Actually lock it (we can't because Vm is used by MAREAs) */
669
670 /* FIXME: This also can't be checked because Vm is used by MAREAs) */
671 //ASSERT(Process->Vm.Flags.AcquiredUnsafe == 0);
672
673 /* Okay, now we can own it exclusively */
674 ASSERT(Thread->OwnsProcessWorkingSetExclusive == FALSE);
675 Thread->OwnsProcessWorkingSetExclusive = TRUE;
676 }
677
678 //
679 // Unlocks the working set for the given process
680 //
681 FORCEINLINE
682 VOID
683 MiUnlockProcessWorkingSet(IN PEPROCESS Process,
684 IN PETHREAD Thread)
685 {
686 /* Make sure this process really is owner, and it was a safe acquisition */
687 ASSERT(MI_WS_OWNER(Process));
688 /* This can't be checked because Vm is used by MAREAs) */
689 //ASSERT(Process->Vm.Flags.AcquiredUnsafe == 0);
690
691 /* The thread doesn't own it anymore */
692 ASSERT(Thread->OwnsProcessWorkingSetExclusive == TRUE);
693 Thread->OwnsProcessWorkingSetExclusive = FALSE;
694
695 /* FIXME: Actually release it (we can't because Vm is used by MAREAs) */
696
697 /* Unblock APCs */
698 KeLeaveGuardedRegion();
699 }
700
701 //
702 // Locks the working set
703 //
704 FORCEINLINE
705 VOID
706 MiLockWorkingSet(IN PETHREAD Thread,
707 IN PMMSUPPORT WorkingSet)
708 {
709 /* Block APCs */
710 KeEnterGuardedRegion();
711
712 /* Working set should be in global memory */
713 ASSERT(MI_IS_SESSION_ADDRESS((PVOID)WorkingSet) == FALSE);
714
715 /* Thread shouldn't already be owning something */
716 ASSERT(!MM_ANY_WS_LOCK_HELD(Thread));
717
718 /* FIXME: Actually lock it (we can't because Vm is used by MAREAs) */
719
720 /* Which working set is this? */
721 if (WorkingSet == &MmSystemCacheWs)
722 {
723 /* Own the system working set */
724 ASSERT((Thread->OwnsSystemWorkingSetExclusive == FALSE) &&
725 (Thread->OwnsSystemWorkingSetShared == FALSE));
726 Thread->OwnsSystemWorkingSetExclusive = TRUE;
727 }
728 else if (WorkingSet->Flags.SessionSpace)
729 {
730 /* We don't implement this yet */
731 UNIMPLEMENTED;
732 while (TRUE);
733 }
734 else
735 {
736 /* Own the process working set */
737 ASSERT((Thread->OwnsProcessWorkingSetExclusive == FALSE) &&
738 (Thread->OwnsProcessWorkingSetShared == FALSE));
739 Thread->OwnsProcessWorkingSetExclusive = TRUE;
740 }
741 }
742
743 //
744 // Unlocks the working set
745 //
746 FORCEINLINE
747 VOID
748 MiUnlockWorkingSet(IN PETHREAD Thread,
749 IN PMMSUPPORT WorkingSet)
750 {
751 /* Working set should be in global memory */
752 ASSERT(MI_IS_SESSION_ADDRESS((PVOID)WorkingSet) == FALSE);
753
754 /* Which working set is this? */
755 if (WorkingSet == &MmSystemCacheWs)
756 {
757 /* Release the system working set */
758 ASSERT((Thread->OwnsSystemWorkingSetExclusive == TRUE) ||
759 (Thread->OwnsSystemWorkingSetShared == TRUE));
760 Thread->OwnsSystemWorkingSetExclusive = FALSE;
761 }
762 else if (WorkingSet->Flags.SessionSpace)
763 {
764 /* We don't implement this yet */
765 UNIMPLEMENTED;
766 while (TRUE);
767 }
768 else
769 {
770 /* Release the process working set */
771 ASSERT((Thread->OwnsProcessWorkingSetExclusive) ||
772 (Thread->OwnsProcessWorkingSetShared));
773 Thread->OwnsProcessWorkingSetExclusive = FALSE;
774 }
775
776 /* FIXME: Actually release it (we can't because Vm is used by MAREAs) */
777
778 /* Unblock APCs */
779 KeLeaveGuardedRegion();
780 }
781
782 NTSTATUS
783 NTAPI
784 MmArmInitSystem(
785 IN ULONG Phase,
786 IN PLOADER_PARAMETER_BLOCK LoaderBlock
787 );
788
789 NTSTATUS
790 NTAPI
791 MiInitMachineDependent(
792 IN PLOADER_PARAMETER_BLOCK LoaderBlock
793 );
794
795 VOID
796 NTAPI
797 MiComputeColorInformation(
798 VOID
799 );
800
801 VOID
802 NTAPI
803 MiMapPfnDatabase(
804 IN PLOADER_PARAMETER_BLOCK LoaderBlock
805 );
806
807 VOID
808 NTAPI
809 MiInitializeColorTables(
810 VOID
811 );
812
813 VOID
814 NTAPI
815 MiInitializePfnDatabase(
816 IN PLOADER_PARAMETER_BLOCK LoaderBlock
817 );
818
819 BOOLEAN
820 NTAPI
821 MiInitializeMemoryEvents(
822 VOID
823 );
824
825 PFN_NUMBER
826 NTAPI
827 MxGetNextPage(
828 IN PFN_NUMBER PageCount
829 );
830
831 PPHYSICAL_MEMORY_DESCRIPTOR
832 NTAPI
833 MmInitializeMemoryLimits(
834 IN PLOADER_PARAMETER_BLOCK LoaderBlock,
835 IN PBOOLEAN IncludeType
836 );
837
838 PFN_NUMBER
839 NTAPI
840 MiPagesInLoaderBlock(
841 IN PLOADER_PARAMETER_BLOCK LoaderBlock,
842 IN PBOOLEAN IncludeType
843 );
844
845 VOID
846 FASTCALL
847 MiSyncARM3WithROS(
848 IN PVOID AddressStart,
849 IN PVOID AddressEnd
850 );
851
852 NTSTATUS
853 NTAPI
854 MmArmAccessFault(
855 IN BOOLEAN StoreInstruction,
856 IN PVOID Address,
857 IN KPROCESSOR_MODE Mode,
858 IN PVOID TrapInformation
859 );
860
861 NTSTATUS
862 FASTCALL
863 MiCheckPdeForPagedPool(
864 IN PVOID Address
865 );
866
867 VOID
868 NTAPI
869 MiInitializeNonPagedPool(
870 VOID
871 );
872
873 VOID
874 NTAPI
875 MiInitializeNonPagedPoolThresholds(
876 VOID
877 );
878
879 VOID
880 NTAPI
881 MiInitializePoolEvents(
882 VOID
883 );
884
885 VOID //
886 NTAPI //
887 InitializePool( //
888 IN POOL_TYPE PoolType,// FIXFIX: This should go in ex.h after the pool merge
889 IN ULONG Threshold //
890 ); //
891
892 VOID
893 NTAPI
894 MiInitializeSystemPtes(
895 IN PMMPTE StartingPte,
896 IN ULONG NumberOfPtes,
897 IN MMSYSTEM_PTE_POOL_TYPE PoolType
898 );
899
900 PMMPTE
901 NTAPI
902 MiReserveSystemPtes(
903 IN ULONG NumberOfPtes,
904 IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType
905 );
906
907 VOID
908 NTAPI
909 MiReleaseSystemPtes(
910 IN PMMPTE StartingPte,
911 IN ULONG NumberOfPtes,
912 IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType
913 );
914
915
916 PFN_NUMBER
917 NTAPI
918 MiFindContiguousPages(
919 IN PFN_NUMBER LowestPfn,
920 IN PFN_NUMBER HighestPfn,
921 IN PFN_NUMBER BoundaryPfn,
922 IN PFN_NUMBER SizeInPages,
923 IN MEMORY_CACHING_TYPE CacheType
924 );
925
926 PVOID
927 NTAPI
928 MiCheckForContiguousMemory(
929 IN PVOID BaseAddress,
930 IN PFN_NUMBER BaseAddressPages,
931 IN PFN_NUMBER SizeInPages,
932 IN PFN_NUMBER LowestPfn,
933 IN PFN_NUMBER HighestPfn,
934 IN PFN_NUMBER BoundaryPfn,
935 IN MI_PFN_CACHE_ATTRIBUTE CacheAttribute
936 );
937
938 PMDL
939 NTAPI
940 MiAllocatePagesForMdl(
941 IN PHYSICAL_ADDRESS LowAddress,
942 IN PHYSICAL_ADDRESS HighAddress,
943 IN PHYSICAL_ADDRESS SkipBytes,
944 IN SIZE_T TotalBytes,
945 IN MI_PFN_CACHE_ATTRIBUTE CacheAttribute,
946 IN ULONG Flags
947 );
948
949 PVOID
950 NTAPI
951 MiMapLockedPagesInUserSpace(
952 IN PMDL Mdl,
953 IN PVOID BaseVa,
954 IN MEMORY_CACHING_TYPE CacheType,
955 IN PVOID BaseAddress
956 );
957
958 VOID
959 NTAPI
960 MiUnmapLockedPagesInUserSpace(
961 IN PVOID BaseAddress,
962 IN PMDL Mdl
963 );
964
965 VOID
966 NTAPI
967 MiInsertInListTail(
968 IN PMMPFNLIST ListHead,
969 IN PMMPFN Entry
970 );
971
972 VOID
973 NTAPI
974 MiInsertZeroListAtBack(
975 IN PFN_NUMBER PageIndex
976 );
977
978 VOID
979 NTAPI
980 MiUnlinkFreeOrZeroedPage(
981 IN PMMPFN Entry
982 );
983
984 PMMPFN
985 NTAPI
986 MiRemoveHeadList(
987 IN PMMPFNLIST ListHead
988 );
989
990 PFN_NUMBER
991 NTAPI
992 MiAllocatePfn(
993 IN PMMPTE PointerPte,
994 IN ULONG Protection
995 );
996
997 VOID
998 NTAPI
999 MiInitializePfn(
1000 IN PFN_NUMBER PageFrameIndex,
1001 IN PMMPTE PointerPte,
1002 IN BOOLEAN Modified
1003 );
1004
1005 VOID
1006 NTAPI
1007 MiInitializePfnForOtherProcess(
1008 IN PFN_NUMBER PageFrameIndex,
1009 IN PMMPTE PointerPte,
1010 IN PFN_NUMBER PteFrame
1011 );
1012
1013 VOID
1014 NTAPI
1015 MiDecrementShareCount(
1016 IN PMMPFN Pfn1,
1017 IN PFN_NUMBER PageFrameIndex
1018 );
1019
1020 PFN_NUMBER
1021 NTAPI
1022 MiRemoveAnyPage(
1023 IN ULONG Color
1024 );
1025
1026 PFN_NUMBER
1027 NTAPI
1028 MiRemoveZeroPage(
1029 IN ULONG Color
1030 );
1031
1032 VOID
1033 NTAPI
1034 MiInsertPageInFreeList(
1035 IN PFN_NUMBER PageFrameIndex
1036 );
1037
1038 PFN_NUMBER
1039 NTAPI
1040 MiDeleteSystemPageableVm(
1041 IN PMMPTE PointerPte,
1042 IN PFN_NUMBER PageCount,
1043 IN ULONG Flags,
1044 OUT PPFN_NUMBER ValidPages
1045 );
1046
1047 PLDR_DATA_TABLE_ENTRY
1048 NTAPI
1049 MiLookupDataTableEntry(
1050 IN PVOID Address
1051 );
1052
1053 VOID
1054 NTAPI
1055 MiInitializeDriverLargePageList(
1056 VOID
1057 );
1058
1059 VOID
1060 NTAPI
1061 MiInitializeLargePageSupport(
1062 VOID
1063 );
1064
1065 VOID
1066 NTAPI
1067 MiSyncCachedRanges(
1068 VOID
1069 );
1070
1071 BOOLEAN
1072 NTAPI
1073 MiIsPfnInUse(
1074 IN PMMPFN Pfn1
1075 );
1076
1077 PMMVAD
1078 NTAPI
1079 MiLocateAddress(
1080 IN PVOID VirtualAddress
1081 );
1082
1083 PMMADDRESS_NODE
1084 NTAPI
1085 MiCheckForConflictingNode(
1086 IN ULONG_PTR StartVpn,
1087 IN ULONG_PTR EndVpn,
1088 IN PMM_AVL_TABLE Table
1089 );
1090
1091 NTSTATUS
1092 NTAPI
1093 MiFindEmptyAddressRangeDownTree(
1094 IN SIZE_T Length,
1095 IN ULONG_PTR BoundaryAddress,
1096 IN ULONG_PTR Alignment,
1097 IN PMM_AVL_TABLE Table,
1098 OUT PULONG_PTR Base
1099 );
1100
1101 VOID
1102 NTAPI
1103 MiInsertNode(
1104 IN PMMADDRESS_NODE NewNode,
1105 IN PMM_AVL_TABLE Table
1106 );
1107
1108 /* EOF */