ReactOS 0.4.16-dev-336-gb667d82
MmReservedMapping.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS kernel-mode tests
3 * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
4 * PURPOSE: Kernel-Mode Test Suite Reserved Mapping test
5 * COPYRIGHT: Copyright 2015,2023 Thomas Faber (thomas.faber@reactos.org)
6 * COPYRIGHT: Copyright 2015 Pierre Schweitzer (pierre@reactos.org)
7 */
8
9#include <kmt_test.h>
10
14
15#ifdef _M_IX86
16
17#define IS_PAE() (g_IsPae)
18
19#define PTE_BASE 0xC0000000
20
21#define MiAddressToPteX86(x) \
22 ((PULONG)(((((ULONG)(x)) >> 12) << 2) + PTE_BASE))
23#define MiAddressToPtePAE(x) \
24 ((PULONGLONG)(((((ULONG)(x)) >> 12) << 3) + PTE_BASE))
25
26#define GET_PTE_VALUE_X86(Addr) (*MiAddressToPteX86(Addr))
27#define GET_PTE_VALUE_PAE(Addr) (*MiAddressToPtePAE(Addr))
28#define GET_PTE_VALUE(Addr) (IS_PAE() ? GET_PTE_VALUE_PAE(Addr) : GET_PTE_VALUE_X86(Addr))
29
30#define PTE_IS_VALID(PteValue) ((PteValue) & 1)
31
32#define PTE_GET_PFN_X86(PteValue) (((PteValue) >> PAGE_SHIFT) & 0x0fffffULL)
33#define PTE_GET_PFN_PAE(PteValue) (((PteValue) >> PAGE_SHIFT) & 0xffffffULL)
34#define PTE_GET_PFN(PteValue) (IS_PAE() ? PTE_GET_PFN_PAE(PteValue) : PTE_GET_PFN_X86(PteValue))
35
36#elif defined(_M_AMD64)
37
38#define PTI_SHIFT 12L
39#define PTE_BASE 0xFFFFF68000000000ULL
43{
45 Offset &= 0xFFFFFFFFFULL << 3;
46 return (PULONGLONG)(PTE_BASE + Offset);
47}
48#define MiAddressToPte(x) _MiAddressToPte((PVOID)(x))
49
50#define GET_PTE_VALUE(Addr) (*_MiAddressToPte((PVOID)(Addr)))
51#define PTE_IS_VALID(PteValue) ((PteValue) & 1)
52#define PTE_GET_PFN(PteValue) (((PteValue) >> PAGE_SHIFT) & 0xFffffffffULL)
53
54#endif
55
56static
59PMDL
60(NTAPI
61*pMmAllocatePagesForMdlEx)(
62 _In_ PHYSICAL_ADDRESS LowAddress,
68
69static
71ValidateMapping(
73 _In_ ULONG TotalPtes,
75 _In_ ULONG ValidPtes,
76 _In_ PPFN_NUMBER Pfns)
77{
78 BOOLEAN Valid = TRUE;
79#if defined(_M_IX86) || defined(_M_AMD64)
80 PUCHAR CurrentAddress;
81 ULONGLONG PteValue, ExpectedValue;
82 ULONG i;
83
84 for (i = 0; i < ValidPtes; i++)
85 {
86 CurrentAddress = (PUCHAR)BaseAddress + i * PAGE_SIZE;
87 PteValue = GET_PTE_VALUE(CurrentAddress);
88 Valid = Valid &&
89 ok(PTE_IS_VALID(PteValue),
90 "[%lu] PTE for %p is not valid (0x%I64x)\n",
91 i, CurrentAddress, PteValue);
92
93 Valid = Valid &&
94 ok(PTE_GET_PFN(PteValue) == Pfns[i],
95 "[%lu] PTE for %p has PFN %Ix, expected %Ix\n",
96 i, CurrentAddress, PTE_GET_PFN(PteValue), Pfns[i]);
97 }
98 for (; i < TotalPtes; i++)
99 {
100 CurrentAddress = (PUCHAR)BaseAddress + i * PAGE_SIZE;
101 PteValue = GET_PTE_VALUE(CurrentAddress);
102 Valid = Valid &&
103 ok(PteValue == 0,
104 "[%lu] PTE for %p is nonzero (0x%I64x)\n",
105 i, CurrentAddress, PteValue);
106 }
107 CurrentAddress = (PUCHAR)BaseAddress - 1 * PAGE_SIZE;
108 PteValue = GET_PTE_VALUE(CurrentAddress);
109 Valid = Valid &&
110 ok(PteValue == (PoolTag & ~1ULL),
111 "PTE for %p contains 0x%I64x, expected %x\n",
112 CurrentAddress, PteValue, PoolTag & ~1);
113 CurrentAddress = (PUCHAR)BaseAddress - 2 * PAGE_SIZE;
114 PteValue = GET_PTE_VALUE(CurrentAddress);
115
116 if (g_IsReactOS || g_OsVersion >= 0x0600)
117 {
118 /* On ReactOS and on Vista+ the size is stored in
119 * the NextEntry field of a MMPTE_LIST structure */
120#ifdef _M_IX86
121 ExpectedValue = (TotalPtes + 2) << 12;
122#elif defined(_M_AMD64)
123 ExpectedValue = ((ULONG64)TotalPtes + 2) << 32;
124#endif
125 }
126 else
127 {
128 /* On Windows 2003 the size is shifted by 1 bit only */
129 ExpectedValue = (TotalPtes + 2) * 2;
130 }
131 Valid = Valid &&
132 ok(PteValue == ExpectedValue,
133 "PTE for %p contains 0x%I64x, expected %x\n",
134 CurrentAddress, PteValue, ExpectedValue);
135#endif
136
137 return Valid;
138}
139
140static
141VOID
144 _In_ ULONG TotalPtes,
146{
147 PMDL Mdl;
148 PHYSICAL_ADDRESS ZeroPhysical;
149 PHYSICAL_ADDRESS MaxPhysical;
151 PPFN_NUMBER MdlPages;
152 ULONG i;
153
154 if (skip(pMmAllocatePagesForMdlEx != NULL, "MmAllocatePagesForMdlEx unavailable\n"))
155 {
156 return;
157 }
158
159 ZeroPhysical.QuadPart = 0;
160 MaxPhysical.QuadPart = 0xffffffffffffffffLL;
161
162 /* Create a one-page MDL and map it */
163 Mdl = pMmAllocatePagesForMdlEx(ZeroPhysical,
164 MaxPhysical,
165 ZeroPhysical,
166 PAGE_SIZE,
167 MmCached,
168 0);
169 if (skip(Mdl != NULL, "No MDL\n"))
170 {
171 return;
172 }
173
174 MdlPages = (PVOID)(Mdl + 1);
175
177 PoolTag,
178 Mdl,
179 MmCached);
180 ok(BaseAddress != NULL, "MmMapLockedPagesWithReservedMapping failed\n");
181 if (!skip(BaseAddress != NULL, "Failed to map MDL\n"))
182 {
184
185 ok_bool_true(ValidateMapping(BaseAddress, TotalPtes, PoolTag, 1, MdlPages),
186 "ValidateMapping returned");
187
189 *(volatile ULONG *)BaseAddress = 0x01234567;
191
193 PoolTag,
194 Mdl);
195
196 ok_bool_true(ValidateMapping(Mapping, TotalPtes, PoolTag, 0, NULL),
197 "ValidateMapping returned");
198 }
199
200 /* Try again but at an unaligned address */
202 PoolTag,
203 Mdl,
204 MmCached);
205 ok(BaseAddress != NULL, "MmMapLockedPagesWithReservedMapping failed\n");
206 if (!skip(BaseAddress != NULL, "Failed to map MDL\n"))
207 {
209
210 ok_bool_true(ValidateMapping(BaseAddress, TotalPtes, PoolTag, 1, MdlPages),
211 "ValidateMapping returned");
212
214 *(volatile ULONG *)BaseAddress = 0x01234567;
216
218 PoolTag,
219 Mdl);
220
221 ok_bool_true(ValidateMapping(Mapping, TotalPtes, PoolTag, 0, NULL),
222 "ValidateMapping returned");
223 }
224
226
227 /* Map all pages */
228 Mdl = pMmAllocatePagesForMdlEx(ZeroPhysical,
229 MaxPhysical,
230 ZeroPhysical,
231 TotalPtes * PAGE_SIZE,
232 MmCached,
233 0);
234 if (skip(Mdl != NULL, "No MDL\n"))
235 {
236 return;
237 }
238
239 MdlPages = (PVOID)(Mdl + 1);
240
242 PoolTag,
243 Mdl,
244 MmCached);
245 ok(BaseAddress != NULL, "MmMapLockedPagesWithReservedMapping failed\n");
246 if (!skip(BaseAddress != NULL, "Failed to map MDL\n"))
247 {
249
250 ok_bool_true(ValidateMapping(BaseAddress, TotalPtes, PoolTag, TotalPtes, MdlPages),
251 "ValidateMapping returned");
252
253 for (i = 0; i < TotalPtes; i++)
254 {
256 *((volatile ULONG *)BaseAddress + i * PAGE_SIZE / sizeof(ULONG)) = 0x01234567;
258 }
259
261 PoolTag,
262 Mdl);
263
264 ok_bool_true(ValidateMapping(Mapping, TotalPtes, PoolTag, 0, NULL),
265 "ValidateMapping returned");
266 }
267
269
270 /* Try to map more pages than we reserved */
271 Mdl = pMmAllocatePagesForMdlEx(ZeroPhysical,
272 MaxPhysical,
273 ZeroPhysical,
274 (TotalPtes + 1) * PAGE_SIZE,
275 MmCached,
276 0);
277 if (skip(Mdl != NULL, "No MDL\n"))
278 {
279 return;
280 }
281
283 PoolTag,
284 Mdl,
285 MmCached);
287 if (BaseAddress)
288 {
290 PoolTag,
291 Mdl);
292 }
293
295}
296
297START_TEST(MmReservedMapping)
298{
300
302 g_OsVersion = SharedUserData->NtMajorVersion << 8 | SharedUserData->NtMinorVersion;
303 g_IsReactOS = *(PULONG)(KI_USER_SHARED_DATA + PAGE_SIZE - sizeof(ULONG)) == 0x8eac705;
304 ok(g_IsReactOS == 1, "Not reactos\n");
305
306 pMmAllocatePagesForMdlEx = KmtGetSystemRoutineAddress(L"MmAllocatePagesForMdlEx");
307
308 /* one byte - single page */
309 Mapping = MmAllocateMappingAddress(1, 'MRmK');
310 ok(Mapping != NULL, "MmAllocateMappingAddress failed\n");
311 if (!skip(Mapping != NULL, "No mapping\n"))
312 {
313 ok_bool_true(ValidateMapping(Mapping, 1, 'MRmK', 0, NULL),
314 "ValidateMapping returned");
315
316 MmFreeMappingAddress(Mapping, 'MRmK');
317 }
318
319 /* 10 pages */
320 Mapping = MmAllocateMappingAddress(10 * PAGE_SIZE, 'MRmK' & ~1);
321 ok(Mapping != NULL, "MmAllocateMappingAddress failed\n");
322 if (!skip(Mapping != NULL, "No mapping\n"))
323 {
324 ok_bool_true(ValidateMapping(Mapping, 10, 'MRmK', 0, NULL),
325 "ValidateMapping returned");
326
327 /* PAGE_FAULT_IN_NONPAGED_AREA can't be caught with SEH */
328 if (0)
329 {
330 (void)*(volatile UCHAR *)Mapping;
331 }
332
333 TestMap(Mapping, 10, 'MRmK');
334
335 MmFreeMappingAddress(Mapping, 'MRmK');
336 }
337
338 /* PoolTag = 0 */
339 Mapping = MmAllocateMappingAddress(1, 0);
340 ok(Mapping == NULL, "MmAllocateMappingAddress failed\n");
341 if (Mapping != NULL)
342 {
343 MmFreeMappingAddress(Mapping, 0);
344 }
345
346 /* PoolTag = 1 */
347 Mapping = MmAllocateMappingAddress(1, 1);
348 ok(Mapping != NULL, "MmAllocateMappingAddress failed\n");
349 if (Mapping != NULL)
350 {
351 ok_bool_true(ValidateMapping(Mapping, 1, 1, 0, NULL),
352 "ValidateMapping returned");
353
354 TestMap(Mapping, 1, 1);
355
356 MmFreeMappingAddress(Mapping, 1);
357 }
358
359 /* Free an unaligned address */
360 Mapping = MmAllocateMappingAddress(PAGE_SIZE, 'MRmK');
361 ok(Mapping != NULL, "MmAllocateMappingAddress failed\n");
362 if (Mapping != NULL)
363 {
364 ok_bool_true(ValidateMapping(Mapping, 1, 'MRmK', 0, NULL),
365 "ValidateMapping returned");
366
367 TestMap(Mapping, 1, 'MRmK');
368
369 MmFreeMappingAddress((PUCHAR)Mapping + sizeof(ULONG), 'MRmK');
370 }
371}
static ULONG g_OsVersion
static BOOLEAN g_IsReactOS
static BOOLEAN g_IsPae
unsigned char BOOLEAN
#define ok_eq_pointer(value, expected)
Definition: apitest.h:59
#define ok_bool_true(value, desc)
Definition: apitest.h:78
#define ok(value,...)
Definition: atltest.h:57
#define skip(...)
Definition: atltest.h:64
#define START_TEST(x)
Definition: atltest.h:75
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define _IRQL_requires_max_(irql)
Definition: driverspecs.h:230
static PVOID Mapping[EMS_PHYSICAL_PAGES]
Definition: emsdrv.c:41
#define PAGE_SIZE
Definition: env_spec_w32.h:49
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
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 const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define KmtStartSeh()
Definition: kmt_test.h:282
#define KmtEndSeh(ExpectedStatus)
Definition: kmt_test.h:288
PVOID KmtGetSystemRoutineAddress(IN PCWSTR RoutineName)
PVOID NTAPI MmMapLockedPagesWithReservedMapping(_In_ PVOID MappingAddress, _In_ ULONG PoolTag, _In_ PMDL Mdl, _In_ MEMORY_CACHING_TYPE CacheType)
Definition: mdlsup.c:1629
VOID NTAPI MmFreePagesFromMdl(IN PMDL Mdl)
Definition: mdlsup.c:564
VOID NTAPI MmUnmapReservedMapping(_In_ PVOID BaseAddress, _In_ ULONG PoolTag, _In_ PMDL Mdl)
Definition: mdlsup.c:1749
#define PTE_BASE
Definition: mmx86.c:14
unsigned __int64 ULONG64
Definition: imports.h:198
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID * BaseAddress
Definition: mmfuncs.h:404
#define _Must_inspect_result_
Definition: no_sal2.h:62
#define _In_
Definition: no_sal2.h:158
__GNU_EXTENSION typedef unsigned __int64 * PULONGLONG
Definition: ntbasedef.h:391
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
BOOLEAN NTAPI ExIsProcessorFeaturePresent(IN ULONG ProcessorFeature)
Definition: sysinfo.c:363
FORCEINLINE PMMPTE _MiAddressToPte(PVOID Address)
Definition: mm.h:139
#define L(x)
Definition: ntvdm.h:50
static WCHAR Address[46]
Definition: ping.c:68
#define KI_USER_SHARED_DATA
#define SharedUserData
#define PTI_SHIFT
ULONG * PPFN_NUMBER
Definition: ke.h:9
#define STATUS_SUCCESS
Definition: shellext.h:65
EH_STD::__hash_map__< TestClass, TestClass, ThrowHash, ThrowEqual, eh_allocator(TestClass) > TestMap
uint32_t * PULONG
Definition: typedefs.h:59
#define NTAPI
Definition: typedefs.h:36
void * PVOID
Definition: typedefs.h:50
ULONG_PTR SIZE_T
Definition: typedefs.h:80
unsigned char * PUCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
uint64_t ULONGLONG
Definition: typedefs.h:67
LONGLONG QuadPart
Definition: typedefs.h:114
PVOID PMDL
Definition: usb.h:39
_In_ WDFDEVICE _In_ PVOID _In_opt_ PMDL Mdl
_Must_inspect_result_ _In_opt_ PWDF_OBJECT_ATTRIBUTES _In_ _Strict_type_match_ POOL_TYPE _In_opt_ ULONG PoolTag
Definition: wdfmemory.h:164
#define FORCEINLINE
Definition: wdftypes.h:67
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
#define PF_PAE_ENABLED
Definition: ketypes.h:133
_Must_inspect_result_ _In_ PHYSICAL_ADDRESS HighAddress
Definition: mmfuncs.h:226
_Must_inspect_result_ _In_ PHYSICAL_ADDRESS _In_ PHYSICAL_ADDRESS SkipBytes
Definition: mmfuncs.h:227
_Must_inspect_result_ _In_ PHYSICAL_ADDRESS _In_ PHYSICAL_ADDRESS _In_opt_ PHYSICAL_ADDRESS _In_ MEMORY_CACHING_TYPE CacheType
Definition: mmfuncs.h:217
_Must_inspect_result_ _In_ PHYSICAL_ADDRESS _In_ PHYSICAL_ADDRESS _In_ SIZE_T TotalBytes
Definition: mmfuncs.h:228
enum _MEMORY_CACHING_TYPE MEMORY_CACHING_TYPE
@ MmCached
Definition: mmtypes.h:130
unsigned char UCHAR
Definition: xmlstorage.h:181