ReactOS 0.4.17-dev-1343-g8fe3cee
mm.h
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4 * PURPOSE: ARM64 memory management definitions
5 * COPYRIGHT: Copyright 2026 Justin Miller <justin.miller@reactos.org>
6 */
7
8#pragma once
9
10#define _MI_PAGING_LEVELS 4
11#define _MI_HAS_NO_EXECUTE 1
12
13/* Same layout as amd64, the loader shares the root table between TTBR0 and TTBR1 */
14#define MI_USER_PROBE_ADDRESS (PVOID)0x000007FFFFFF0000ULL
15#define MI_DEFAULT_SYSTEM_RANGE_START (PVOID)0xFFFF080000000000ULL
16#define MI_REAL_SYSTEM_RANGE_START 0xFFFF800000000000ULL
17#define HYPER_SPACE 0xFFFFF70000000000ULL
18#define HYPER_SPACE_END 0xFFFFF77FFFFFFFFFULL
19#define MI_SYSTEM_CACHE_WS_START 0xFFFFF78000001000ULL
20#define MM_SYSTEM_SPACE_START 0xFFFFF88000000000ULL
21#define MI_DEBUG_MAPPING (PVOID)0xFFFFF89FFFFFF000ULL
22#define MI_PAGED_POOL_START (PVOID)0xFFFFF8A000000000ULL
23#define MI_SESSION_SPACE_END 0xFFFFF98000000000ULL
24#define MI_SYSTEM_CACHE_START 0xFFFFF98000000000ULL
25#define MI_SYSTEM_CACHE_END 0xFFFFFA7FFFFFFFFFULL
26#define MI_PFN_DATABASE 0xFFFFFA8000000000ULL
27#define MI_NONPAGED_POOL_END (PVOID)0xFFFFFFFFFFBFFFFFULL
28#define MI_HIGHEST_SYSTEM_ADDRESS (PVOID)0xFFFFFFFFFFFFFFFFULL
29#define MmSystemRangeStart ((PVOID)MI_REAL_SYSTEM_RANGE_START)
30
31/* WOW64 address definitions */
32#define MM_HIGHEST_USER_ADDRESS_WOW64 0x7FFEFFFF
33#define MM_SYSTEM_RANGE_START_WOW64 0x80000000
34
35/* The size of the virtual memory area that is mapped using a single PDE */
36#define PDE_MAPPED_VA (PTE_PER_PAGE * PAGE_SIZE)
37
38/* Misc address definitions */
39#define MI_SYSTEM_PTE_BASE (PVOID)MiAddressToPte(KSEG0_BASE)
40#define MM_HIGHEST_VAD_ADDRESS (PVOID)((ULONG_PTR)MM_HIGHEST_USER_ADDRESS - (16 * PAGE_SIZE))
41#define MI_MAPPING_RANGE_START HYPER_SPACE
42#define MI_MAPPING_RANGE_END (MI_MAPPING_RANGE_START + MI_HYPERSPACE_PTES * PAGE_SIZE)
43#define MI_DUMMY_PTE (MI_MAPPING_RANGE_END + PAGE_SIZE)
44#define MI_VAD_BITMAP (MI_DUMMY_PTE + PAGE_SIZE)
45#define MI_WORKING_SET_LIST (MI_VAD_BITMAP + PAGE_SIZE)
46
47/* Memory sizes */
48#define MI_MIN_PAGES_FOR_NONPAGED_POOL_TUNING ((255 * _1MB) >> PAGE_SHIFT)
49#define MI_MIN_PAGES_FOR_SYSPTE_TUNING ((19 * _1MB) >> PAGE_SHIFT)
50#define MI_MIN_PAGES_FOR_SYSPTE_BOOST ((32 * _1MB) >> PAGE_SHIFT)
51#define MI_MIN_PAGES_FOR_SYSPTE_BOOST_BOOST ((256 * _1MB) >> PAGE_SHIFT)
52#define MI_MIN_INIT_PAGED_POOLSIZE (32 * _1MB)
53#define MI_MAX_INIT_NONPAGED_POOL_SIZE (128ULL * 1024 * 1024 * 1024)
54#define MI_MAX_NONPAGED_POOL_SIZE (128ULL * 1024 * 1024 * 1024)
55#define MI_SYSTEM_VIEW_SIZE (512 * _1MB)
56#define MI_SESSION_VIEW_SIZE (512 * _1MB)
57#define MI_SESSION_POOL_SIZE (64 * _1MB)
58#define MI_SESSION_IMAGE_SIZE (16 * _1MB)
59#define MI_SESSION_WORKING_SET_SIZE (16 * _1MB)
60#define MI_SESSION_SIZE (MI_SESSION_VIEW_SIZE + \
61 MI_SESSION_POOL_SIZE + \
62 MI_SESSION_IMAGE_SIZE + \
63 MI_SESSION_WORKING_SET_SIZE)
64#define MI_MIN_ALLOCATION_FRAGMENT (4 * _1KB)
65#define MI_ALLOCATION_FRAGMENT (64 * _1KB)
66#define MI_MAX_ALLOCATION_FRAGMENT (2 * _1MB)
67
68/* Misc constants */
69#define MM_PTE_SOFTWARE_PROTECTION_BITS 5
70#define MI_MIN_SECONDARY_COLORS 8
71#define MI_SECONDARY_COLORS 64
72#define MI_MAX_SECONDARY_COLORS 1024
73#define MI_NUMBER_SYSTEM_PTES (22000 * 22)
74#define MI_MAX_FREE_PAGE_LISTS 4
75#define MI_HYPERSPACE_PTES (256 - 1)
76#define MI_ZERO_PTES (32)
77#define MI_MAX_ZERO_BITS 53
78#define SESSION_POOL_LOOKASIDES 21
79
80/* MMPTE related defines */
81#define MM_EMPTY_PTE_LIST ((ULONG64)0xFFFFFFFF)
82#define MM_EMPTY_LIST ((ULONG_PTR)-1)
83
84/* MAIR_EL1 slots the loader programs */
85#define MI_CACHE_TYPE_CACHED 0
86#define MI_CACHE_TYPE_WRITE_COMBINED 1
87#define MI_CACHE_TYPE_DEVICE 3
88
89/* Easy accessing PFN in PTE */
90#define PFN_FROM_PTE(v) ((v)->u.Hard.PageFrameNumber)
91#define PFN_FROM_PDE(v) ((v)->u.Hard.PageFrameNumber)
92#define PFN_FROM_PPE(v) ((v)->u.Hard.PageFrameNumber)
93#define PFN_FROM_PXE(v) ((v)->u.Hard.PageFrameNumber)
94
95/*
96 * Writable is a software bit, the hardware only sees AP[2] (NotDirty).
97 * A writable page stays read only until the first write marks it dirty.
98 */
99#define MI_MAKE_DIRTY_PAGE(x) ((x)->u.Hard.NotDirty = ((x)->u.Hard.Writable == 0))
100#define MI_MAKE_CLEAN_PAGE(x) ((x)->u.Hard.NotDirty = 1)
101#define MI_MAKE_ACCESSED_PAGE(x) ((x)->u.Hard.Accessed = 1)
102#define MI_IS_PAGE_LARGE(x) ((x)->u.Hard.NotLargePage == 0)
103#define MI_IS_PAGE_WRITEABLE(x) ((x)->u.Hard.Writable == 1)
104#define MI_IS_PAGE_COPY_ON_WRITE(x)((x)->u.Hard.CopyOnWrite == 1)
105#define MI_IS_PAGE_EXECUTABLE(x) \
106 (((x)->u.Hard.Owner ? (x)->u.Hard.UserNoExecute : (x)->u.Hard.PrivilegedNoExecute) == 0)
107#define MI_IS_PAGE_DIRTY(x) ((x)->u.Hard.NotDirty == 0)
108#define MI_MAKE_WRITE_PAGE(x) ((x)->u.Hard.Writable = 1)
109#define MI_MAKE_READ_ONLY_PAGE(x) ((x)->u.Hard.Writable = 0, (x)->u.Hard.NotDirty = 1)
110#define MI_MAKE_EXECUTABLE_PAGE(x) ((x)->u.Hard.PrivilegedNoExecute = 0, (x)->u.Hard.UserNoExecute = 0)
111#define MI_MAKE_NO_EXECUTE_PAGE(x) ((x)->u.Hard.PrivilegedNoExecute = 1, (x)->u.Hard.UserNoExecute = 1)
112#define MI_IS_PAGE_GLOBAL(x) ((x)->u.Hard.NonGlobal == 0)
113
114/* User pages are tagged with the ASID and never run at EL1 */
115#define MI_MAKE_OWNER_PAGE(x) \
116 ((x)->u.Hard.Owner = 1, \
117 (x)->u.Hard.NonGlobal = 1, \
118 (x)->u.Hard.PrivilegedNoExecute = 1)
119
120#define MI_MAKE_PTE_CACHED(Pte) ((Pte)->u.Hard.CacheType = MI_CACHE_TYPE_CACHED)
121#define MI_MAKE_PTE_NON_CACHED(Pte) ((Pte)->u.Hard.CacheType = MI_CACHE_TYPE_DEVICE)
122#define MI_MAKE_PTE_WRITE_COMBINE(Pte) ((Pte)->u.Hard.CacheType = MI_CACHE_TYPE_WRITE_COMBINED)
123
124/* Fault status from ESR_EL1, passed to MmAccessFault as the fault code */
125#define MI_IS_NOT_PRESENT_FAULT(FaultCode) !BooleanFlagOn(FaultCode, 0x00000001)
126#define MI_IS_WRITE_ACCESS(FaultCode) BooleanFlagOn(FaultCode, 0x00000002)
127#define MI_IS_INSTRUCTION_FETCH(FaultCode) BooleanFlagOn(FaultCode, 0x00000010)
128
129/* On ARM64, these are the same */
130#define MI_WRITE_VALID_PPE MI_WRITE_VALID_PTE
131#define ValidKernelPpe ValidKernelPde
132
133/* Each level indexes 9 bits of the address, the self map repeats the walk */
134#define MI_VA_LEVEL_SHIFT(Level) (PTI_SHIFT + 9 * (Level))
135#define MI_VA_SIGNIFICANT_BITS 48
136
138PMMPTE
142 _In_ ULONG_PTR TableBase)
143{
145
147 return (PMMPTE)TableBase + Index;
148}
149
150#define MiAddressToPte(x) MiArm64AddressToEntry((PVOID)(x), 0, PTE_BASE)
151#define MiAddressToPde(x) MiArm64AddressToEntry((PVOID)(x), 1, PDE_BASE)
152#define MiAddressToPpe(x) MiArm64AddressToEntry((PVOID)(x), 2, PPE_BASE)
153#define MiAddressToPxe(x) MiArm64AddressToEntry((PVOID)(x), 3, PXE_BASE)
154
155/* Convert an address to the index of its entry inside the table */
157ULONG
160{
161 return (ULONG)(((ULONG64)Address >> PTI_SHIFT) & PTI_MASK_ARM64);
162}
163#define MiAddressToPteOffset(x) MiAddressToPti(x)
164
166ULONG
169{
170 return (ULONG)(((ULONG64)Address >> PDI_SHIFT) & PDI_MASK_ARM64);
171}
172#define MiAddressToPdeOffset(x) MiAddressToPdi(x)
173#define MiGetPdeOffset(x) MiAddressToPdi(x)
174
176ULONG
179{
180 return (ULONG)(((ULONG64)Address >> PXI_SHIFT) & PXI_MASK);
181}
182
183/* An entry address maps back by dropping one level and sign extending bit 47 */
185PVOID
189{
191
193 Value <<= (64 - MI_VA_SIGNIFICANT_BITS);
194 return (PVOID)(Value >> (64 - MI_VA_SIGNIFICANT_BITS));
195}
196
197#define MiPteToAddress(x) MiArm64EntryToAddress((x), 0)
198#define MiPdeToAddress(x) MiArm64EntryToAddress((x), 1)
199#define MiPpeToAddress(x) MiArm64EntryToAddress((x), 2)
200#define MiPxeToAddress(x) MiArm64EntryToAddress((x), 3)
201
202/* Walking up one level is the same as translating the entry address again */
203#define MiPdeToPte(x) ((PMMPTE)MiPteToAddress(x))
204#define MiPpeToPte(x) ((PMMPTE)MiPdeToAddress(x))
205#define MiPxeToPte(x) ((PMMPTE)MiPpeToAddress(x))
206#define MiPteToPde(x) ((PMMPDE)MiAddressToPte(x))
207#define MiPteToPpe(x) ((PMMPPE)MiAddressToPde(x))
208#define MiPteToPxe(x) ((PMMPXE)MiAddressToPpe(x))
209#define MiPdeToPpe(x) ((PMMPPE)MiAddressToPte(x))
210#define MiPdeToPxe(x) ((PMMPXE)MiAddressToPde(x))
211
212/* Check P*E boundaries */
213#define MiIsPteOnPdeBoundary(PointerPte) \
214 ((((ULONG_PTR)(PointerPte)) & (PAGE_SIZE - 1)) == 0)
215#define MiIsPteOnPpeBoundary(PointerPte) \
216 ((((ULONG_PTR)(PointerPte)) & (PDE_PER_PAGE * PAGE_SIZE - 1)) == 0)
217#define MiIsPteOnPxeBoundary(PointerPte) \
218 ((((ULONG_PTR)(PointerPte)) & (PPE_PER_PAGE * PDE_PER_PAGE * PAGE_SIZE - 1)) == 0)
219
220/* Prototype and subsection PTEs keep a sign extended 48 bit address in bits 16 to 63 */
221#define MiProtoPteToPte(x) \
222 (PMMPTE)(((LONG64)(x)->u.Long) >> 16)
223
224#define MiSubsectionPteToSubsection(x) \
225 (PMMPTE)((LONG64)(x)->u.Subsect.SubsectionAddress)
226
228VOID
230 _Out_ PMMPTE NewPte,
232{
233 NewPte->u.Long = 0;
234 NewPte->u.Subsect.Prototype = 1;
235 NewPte->u.Subsect.SubsectionAddress = ((ULONG_PTR)Segment & 0x0000FFFFFFFFFFFFULL);
236}
237
239VOID
241 _Out_ PMMPTE NewPte,
242 _In_ PMMPTE PointerPte)
243{
244 NewPte->u.Long = (ULONG64)PointerPte << 16;
245 NewPte->u.Proto.Prototype = 1;
246 ASSERT(MiProtoPteToPte(NewPte) == PointerPte);
247}
248
252 _In_ PMMPTE PointerPte)
253{
254 return ((PointerPte->u.Hard.Valid != 0) ||
255 (PointerPte->u.Proto.Prototype != 0) ||
256 (PointerPte->u.Trans.Transition != 0) ||
257 (PointerPte->u.Hard.PageFrameNumber != 0));
258}
259
264{
265 return ((MiAddressToPxe(Address)->u.Hard.Valid) &&
266 (MiAddressToPpe(Address)->u.Hard.Valid) &&
267 (MiAddressToPde(Address)->u.Hard.Valid));
268}
unsigned char BOOLEAN
Definition: actypes.h:127
PLIST_ENTRY Entry
Definition: devhcd.cpp:1262
_In_ ULONG _In_ UCHAR Level
Definition: dispmprt.h:1329
#define ULONG_PTR
Definition: config.h:101
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble * u
Definition: glfuncs.h:240
#define ASSERT(a)
Definition: mode.c:44
unsigned __int64 ULONG64
Definition: imports.h:198
#define _Out_
Definition: no_sal2.h:160
#define _In_
Definition: no_sal2.h:158
FORCEINLINE ULONG MiAddressToPxi(PVOID Address)
Definition: mm.h:199
FORCEINLINE ULONG MiAddressToPdi(PVOID Address)
Definition: mm.h:189
FORCEINLINE VOID MI_MAKE_PROTOTYPE_PTE(IN PMMPTE NewPte, IN PMMPTE PointerPte)
Definition: mm.h:341
FORCEINLINE BOOLEAN MiIsPdeForAddressValid(PVOID Address)
Definition: mm.h:365
#define MiProtoPteToPte(x)
Definition: mm.h:315
FORCEINLINE ULONG MiAddressToPti(PVOID Address)
Definition: mm.h:180
FORCEINLINE BOOLEAN MI_IS_MAPPED_PTE(PMMPTE PointerPte)
Definition: mm.h:355
#define MiAddressToPde(x)
Definition: mm.h:155
FORCEINLINE VOID MI_MAKE_SUBSECTION_PTE(_Out_ PMMPTE NewPte, _In_ PVOID Segment)
Definition: mm.h:327
#define MiAddressToPxe(x)
Definition: mm.h:153
FORCEINLINE PMMPTE MiArm64AddressToEntry(_In_ PVOID Address, _In_ ULONG Level, _In_ ULONG_PTR TableBase)
Definition: mm.h:139
#define MiAddressToPpe(x)
Definition: mm.h:152
#define MI_VA_LEVEL_SHIFT(Level)
Definition: mm.h:134
FORCEINLINE PVOID MiArm64EntryToAddress(_In_ PVOID Entry, _In_ ULONG Level)
Definition: mm.h:186
#define MI_VA_SIGNIFICANT_BITS
Definition: mm.h:135
static WCHAR Address[46]
Definition: ping.c:68
#define PDI_SHIFT
#define PXI_SHIFT
#define PXI_MASK
#define PTI_SHIFT
#define PTI_MASK_ARM64
#define PDI_MASK_ARM64
int64_t LONG64
Definition: typedefs.h:68
uint32_t ULONG_PTR
Definition: typedefs.h:65
uint32_t ULONG
Definition: typedefs.h:59
_In_ WDFCOLLECTION _In_ ULONG Index
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
Definition: wdfregistry.h:413
#define FORCEINLINE
Definition: wdftypes.h:67
_Inout_ PVOID Segment
Definition: exfuncs.h:1101