ReactOS 0.4.16-dev-1494-gd054f63
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
13
14#ifdef _M_IX86
15
16#define IS_PAE() (g_IsPae)
17
18#define PTE_BASE 0xC0000000
19
20#define MiAddressToPteX86(x) \
21 ((PULONG)(((((ULONG)(x)) >> 12) << 2) + PTE_BASE))
22#define MiAddressToPtePAE(x) \
23 ((PULONGLONG)(((((ULONG)(x)) >> 12) << 3) + PTE_BASE))
24
25#define GET_PTE_VALUE_X86(Addr) (*MiAddressToPteX86(Addr))
26#define GET_PTE_VALUE_PAE(Addr) (*MiAddressToPtePAE(Addr))
27#define GET_PTE_VALUE(Addr) (IS_PAE() ? GET_PTE_VALUE_PAE(Addr) : GET_PTE_VALUE_X86(Addr))
28
29#define PTE_IS_VALID(PteValue) ((PteValue) & 1)
30
31#define PTE_GET_PFN_X86(PteValue) (((PteValue) >> PAGE_SHIFT) & 0x0fffffULL)
32#define PTE_GET_PFN_PAE(PteValue) (((PteValue) >> PAGE_SHIFT) & 0xffffffULL)
33#define PTE_GET_PFN(PteValue) (IS_PAE() ? PTE_GET_PFN_PAE(PteValue) : PTE_GET_PFN_X86(PteValue))
34
35#elif defined(_M_AMD64)
36
37#define PTI_SHIFT 12L
38#define PTE_BASE 0xFFFFF68000000000ULL
42{
44 Offset &= 0xFFFFFFFFFULL << 3;
45 return (PULONGLONG)(PTE_BASE + Offset);
46}
47#define MiAddressToPte(x) _MiAddressToPte((PVOID)(x))
48
49#define GET_PTE_VALUE(Addr) (*_MiAddressToPte((PVOID)(Addr)))
50#define PTE_IS_VALID(PteValue) ((PteValue) & 1)
51#define PTE_GET_PFN(PteValue) (((PteValue) >> PAGE_SHIFT) & 0xFffffffffULL)
52
53#endif
54
55static
58PMDL
59(NTAPI
60*pMmAllocatePagesForMdlEx)(
61 _In_ PHYSICAL_ADDRESS LowAddress,
67
68static
70ValidateMapping(
72 _In_ ULONG TotalPtes,
74 _In_ ULONG ValidPtes,
75 _In_ PPFN_NUMBER Pfns)
76{
77 BOOLEAN Valid = TRUE;
78#if defined(_M_IX86) || defined(_M_AMD64)
79 PUCHAR CurrentAddress;
80 ULONGLONG PteValue, ExpectedValue;
81 ULONG i;
82
83#ifdef _M_AMD64
85 "Win10 1607+ breaks these next tests.\n"))
86 return Valid;
87#endif
88
89 for (i = 0; i < ValidPtes; i++)
90 {
91 CurrentAddress = (PUCHAR)BaseAddress + i * PAGE_SIZE;
92 PteValue = GET_PTE_VALUE(CurrentAddress);
93 Valid = Valid &&
94 ok(PTE_IS_VALID(PteValue),
95 "[%lu] PTE for %p is not valid (0x%I64x)\n",
96 i, CurrentAddress, PteValue);
97
98 Valid = Valid &&
99 ok(PTE_GET_PFN(PteValue) == Pfns[i],
100 "[%lu] PTE for %p has PFN %Ix, expected %Ix\n",
101 i, CurrentAddress, PTE_GET_PFN(PteValue), Pfns[i]);
102 }
103 for (; i < TotalPtes; i++)
104 {
105 CurrentAddress = (PUCHAR)BaseAddress + i * PAGE_SIZE;
106 PteValue = GET_PTE_VALUE(CurrentAddress);
107 Valid = Valid &&
108 ok(PteValue == 0,
109 "[%lu] PTE for %p is nonzero (0x%I64x)\n",
110 i, CurrentAddress, PteValue);
111 }
112 CurrentAddress = (PUCHAR)BaseAddress - 1 * PAGE_SIZE;
113 PteValue = GET_PTE_VALUE(CurrentAddress);
114
116 "DVRT (Win10 1607+) breaks these next tests.\n"))
117 return Valid;
118
119#ifdef _M_AMD64
121 ExpectedValue = ((PoolTag & ~1ULL) + 1) << 28;
122 else if (GetNTVersion() >= _WIN32_WINNT_VISTA)
123#else
125#endif
126 ExpectedValue = ((PoolTag & ~1ULL) + 1) << 32;
127 else
128 ExpectedValue = PoolTag & ~1ULL;
129
130 Valid = Valid &&
131 ok(PteValue == ExpectedValue,
132 "PTE for %p contains 0x%I64x, expected 0x%I64x\n",
133 CurrentAddress, PteValue, ExpectedValue);
134 CurrentAddress = (PUCHAR)BaseAddress - 2 * PAGE_SIZE;
135 PteValue = GET_PTE_VALUE(CurrentAddress);
136
137#ifdef _M_AMD64
139 {
140 ExpectedValue = (TotalPtes + 2) << 28;
141 }
143#else
145#endif
146 {
147 /* On ReactOS and on Vista+ the size is stored in
148 * the NextEntry field of a MMPTE_LIST structure */
149 ExpectedValue = ((ULONG64)TotalPtes + 2) << 32;
150 }
151 else
152 {
153 /* On Windows 2003 the size is shifted by 1 bit only */
154 ExpectedValue = (TotalPtes + 2) * 2;
155 }
156 Valid = Valid &&
157 ok(PteValue == ExpectedValue,
158 "PTE for %p contains 0x%I64x, expected 0x%I64x\n",
159 CurrentAddress, PteValue, ExpectedValue);
160#endif
161
162 return Valid;
163}
164
165static
166VOID
169 _In_ ULONG TotalPtes,
171{
172 PMDL Mdl;
173 PHYSICAL_ADDRESS ZeroPhysical;
174 PHYSICAL_ADDRESS MaxPhysical;
176 PPFN_NUMBER MdlPages;
177 ULONG i;
178
179 if (skip(pMmAllocatePagesForMdlEx != NULL, "MmAllocatePagesForMdlEx unavailable\n"))
180 {
181 return;
182 }
183
184 ZeroPhysical.QuadPart = 0;
185 MaxPhysical.QuadPart = 0xffffffffffffffffLL;
186
187 /* Create a one-page MDL and map it */
188 Mdl = pMmAllocatePagesForMdlEx(ZeroPhysical,
189 MaxPhysical,
190 ZeroPhysical,
191 PAGE_SIZE,
192 MmCached,
193 0);
194 if (skip(Mdl != NULL, "No MDL\n"))
195 {
196 return;
197 }
198
199 MdlPages = (PVOID)(Mdl + 1);
200
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;
215 ok_eq_ulong(*(volatile ULONG *)BaseAddress, 0x01234567);
217
219 PoolTag,
220 Mdl);
221
222 ok_bool_true(ValidateMapping(Mapping, TotalPtes, PoolTag, 0, NULL),
223 "ValidateMapping returned");
224 }
225
226 /* Try again but at an unaligned address */
228 PoolTag,
229 Mdl,
230 MmCached);
231 ok(BaseAddress != NULL, "MmMapLockedPagesWithReservedMapping failed\n");
232 if (!skip(BaseAddress != NULL, "Failed to map MDL\n"))
233 {
236 else
238
239 ok_bool_true(ValidateMapping(BaseAddress, TotalPtes, PoolTag, 1, MdlPages),
240 "ValidateMapping returned");
241
243 *(volatile ULONG *)BaseAddress = 0x01234567;
244 ok_eq_ulong(*(volatile ULONG *)BaseAddress, 0x01234567);
246
248 PoolTag,
249 Mdl);
250
251 ok_bool_true(ValidateMapping(Mapping, TotalPtes, PoolTag, 0, NULL),
252 "ValidateMapping returned");
253 }
254
257
258 /* Map all pages */
259 Mdl = pMmAllocatePagesForMdlEx(ZeroPhysical,
260 MaxPhysical,
261 ZeroPhysical,
262 TotalPtes * PAGE_SIZE,
263 MmCached,
264 0);
265 if (skip(Mdl != NULL, "No MDL\n"))
266 {
267 return;
268 }
269
270 MdlPages = (PVOID)(Mdl + 1);
271
273 PoolTag,
274 Mdl,
275 MmCached);
276 ok(BaseAddress != NULL, "MmMapLockedPagesWithReservedMapping failed\n");
277 if (!skip(BaseAddress != NULL, "Failed to map MDL\n"))
278 {
280
281 ok_bool_true(ValidateMapping(BaseAddress, TotalPtes, PoolTag, TotalPtes, MdlPages),
282 "ValidateMapping returned");
283
284 for (i = 0; i < TotalPtes; i++)
285 {
287 *((volatile ULONG *)((PUCHAR)BaseAddress + i * PAGE_SIZE)) = 0x01234567 + i;
288 ok_eq_ulong(*((volatile ULONG *)((PUCHAR)BaseAddress + i * PAGE_SIZE)), 0x01234567 + i);
290 }
291
293 PoolTag,
294 Mdl);
295
296 ok_bool_true(ValidateMapping(Mapping, TotalPtes, PoolTag, 0, NULL),
297 "ValidateMapping returned");
298 }
299
302
303 /* Try to map more pages than we reserved */
304 Mdl = pMmAllocatePagesForMdlEx(ZeroPhysical,
305 MaxPhysical,
306 ZeroPhysical,
307 (TotalPtes + 1) * PAGE_SIZE,
308 MmCached,
309 0);
310 if (skip(Mdl != NULL, "No MDL\n"))
311 {
312 return;
313 }
314
316 PoolTag,
317 Mdl,
318 MmCached);
320 if (BaseAddress)
321 {
323 PoolTag,
324 Mdl);
325 }
326
329}
330
331START_TEST(MmReservedMapping)
332{
334
336 g_IsReactOS = *(PULONG)(KI_USER_SHARED_DATA + PAGE_SIZE - sizeof(ULONG)) == 0x8eac705;
337 if (!g_IsReactOS)
338 trace("Not ReactOS\n");
339
340 pMmAllocatePagesForMdlEx = KmtGetSystemRoutineAddress(L"MmAllocatePagesForMdlEx");
341
342 /* one byte - single page */
343 Mapping = MmAllocateMappingAddress(1, 'MRmK');
344 ok(Mapping != NULL, "MmAllocateMappingAddress failed\n");
345 if (!skip(Mapping != NULL, "No mapping\n"))
346 {
347 ok_bool_true(ValidateMapping(Mapping, 1, 'MRmK', 0, NULL),
348 "ValidateMapping returned");
349
350 MmFreeMappingAddress(Mapping, 'MRmK');
351 }
352
353 /* 10 pages */
354 Mapping = MmAllocateMappingAddress(10 * PAGE_SIZE, 'MRmK');
355 ok(Mapping != NULL, "MmAllocateMappingAddress failed\n");
356 if (!skip(Mapping != NULL, "No mapping\n"))
357 {
358 ok_bool_true(ValidateMapping(Mapping, 10, 'MRmK', 0, NULL),
359 "ValidateMapping returned");
360
361 /* PAGE_FAULT_IN_NONPAGED_AREA can't be caught with SEH */
362 if (0)
363 {
364 (void)*(volatile UCHAR *)Mapping;
365 }
366
367 TestMap(Mapping, 10, 'MRmK');
368
369 MmFreeMappingAddress(Mapping, 'MRmK');
370 }
371
372 /* PoolTag = 0 */
373 Mapping = MmAllocateMappingAddress(1, 0);
374 ok(Mapping == NULL, "MmAllocateMappingAddress failed\n");
375 if (Mapping != NULL)
376 {
377 MmFreeMappingAddress(Mapping, 0);
378 }
379
380 /* PoolTag = 1 */
381 Mapping = MmAllocateMappingAddress(1, 1);
382 ok(Mapping != NULL, "MmAllocateMappingAddress failed\n");
383 if (Mapping != NULL)
384 {
385 ok_bool_true(ValidateMapping(Mapping, 1, 1, 0, NULL),
386 "ValidateMapping returned");
387
388 TestMap(Mapping, 1, 1);
389
390 MmFreeMappingAddress(Mapping, 1);
391 }
392
393 /* Free an unaligned address */
394 Mapping = MmAllocateMappingAddress(PAGE_SIZE, 'MRmK');
395 ok(Mapping != NULL, "MmAllocateMappingAddress failed\n");
396 if (Mapping != NULL)
397 {
398 ok_bool_true(ValidateMapping(Mapping, 1, 'MRmK', 0, NULL),
399 "ValidateMapping returned");
400
401 TestMap(Mapping, 1, 'MRmK');
402
403 MmFreeMappingAddress((PUCHAR)Mapping + sizeof(ULONG), 'MRmK');
404 }
405}
#define ALIGN_DOWN_BY(size, align)
static BOOLEAN g_IsReactOS
static BOOLEAN g_IsPae
unsigned char BOOLEAN
#define ok_eq_pointer(value, expected)
Definition: apitest.h:44
#define ok_eq_ulong(value, expected)
Definition: apitest.h:48
#define GetNTVersion()
Definition: apitest.h:17
#define ok_bool_true(value, desc)
Definition: apitest.h:63
#define trace
Definition: atltest.h:70
#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 L(x)
Definition: resources.c:13
#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 ExFreePool(addr)
Definition: env_spec_w32.h:352
#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:285
#define KmtEndSeh(ExpectedStatus)
Definition: kmt_test.h:291
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:395
_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
static WCHAR Address[46]
Definition: ping.c:68
#define KI_USER_SHARED_DATA
#define PTI_SHIFT
ULONG * PPFN_NUMBER
Definition: ke.h:9
#define _WIN32_WINNT_WIN10
Definition: sdkddkver.h:32
#define _WIN32_WINNT_WIN8
Definition: sdkddkver.h:29
#define _WIN32_WINNT_VISTA
Definition: sdkddkver.h:25
#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