ReactOS 0.4.15-dev-7906-g1b85a5f
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
12
13#ifdef _M_IX86
14
15#define IS_PAE() (g_IsPae)
16
17#define PTE_BASE 0xC0000000
18
19#define MiAddressToPteX86(x) \
20 ((PULONG)(((((ULONG)(x)) >> 12) << 2) + PTE_BASE))
21#define MiAddressToPtePAE(x) \
22 ((PULONGLONG)(((((ULONG)(x)) >> 12) << 3) + PTE_BASE))
23
24#define GET_PTE_VALUE_X86(Addr) (*MiAddressToPteX86(Addr))
25#define GET_PTE_VALUE_PAE(Addr) (*MiAddressToPtePAE(Addr))
26#define GET_PTE_VALUE(Addr) (IS_PAE() ? GET_PTE_VALUE_PAE(Addr) : GET_PTE_VALUE_X86(Addr))
27
28#define PTE_IS_VALID(PteValue) ((PteValue) & 1)
29
30#define PTE_GET_PFN_X86(PteValue) (((PteValue) >> PAGE_SHIFT) & 0x0fffffULL)
31#define PTE_GET_PFN_PAE(PteValue) (((PteValue) >> PAGE_SHIFT) & 0xffffffULL)
32#define PTE_GET_PFN(PteValue) (IS_PAE() ? PTE_GET_PFN_PAE(PteValue) : PTE_GET_PFN_X86(PteValue))
33
34#elif defined(_M_AMD64)
35
36#define PTI_SHIFT 12L
37#define PTE_BASE 0xFFFFF68000000000ULL
41{
43 Offset &= 0xFFFFFFFFFULL << 3;
44 return (PULONGLONG)(PTE_BASE + Offset);
45}
46#define MiAddressToPte(x) _MiAddressToPte((PVOID)(x))
47
48#define GET_PTE_VALUE(Addr) (*_MiAddressToPte((PVOID)(Addr)))
49#define PTE_IS_VALID(PteValue) ((PteValue) & 1)
50#define PTE_GET_PFN(PteValue) (((PteValue) >> PAGE_SHIFT) & 0xFffffffffULL)
51
52#endif
53
54static
57PMDL
58(NTAPI
59*pMmAllocatePagesForMdlEx)(
60 _In_ PHYSICAL_ADDRESS LowAddress,
66
67static
69ValidateMapping(
71 _In_ ULONG TotalPtes,
73 _In_ ULONG ValidPtes,
74 _In_ PPFN_NUMBER Pfns)
75{
76 BOOLEAN Valid = TRUE;
77#if defined(_M_IX86) || defined(_M_AMD64)
78 PUCHAR CurrentAddress;
79 ULONGLONG PteValue;
80 ULONG i;
81
82 for (i = 0; i < ValidPtes; i++)
83 {
84 CurrentAddress = (PUCHAR)BaseAddress + i * PAGE_SIZE;
85 PteValue = GET_PTE_VALUE(CurrentAddress);
86 Valid = Valid &&
87 ok(PTE_IS_VALID(PteValue),
88 "[%lu] PTE for %p is not valid (0x%I64x)\n",
89 i, CurrentAddress, PteValue);
90
91 Valid = Valid &&
92 ok(PTE_GET_PFN(PteValue) == Pfns[i],
93 "[%lu] PTE for %p has PFN %Ix, expected %Ix\n",
94 i, CurrentAddress, PTE_GET_PFN(PteValue), Pfns[i]);
95 }
96 for (; i < TotalPtes; i++)
97 {
98 CurrentAddress = (PUCHAR)BaseAddress + i * PAGE_SIZE;
99 PteValue = GET_PTE_VALUE(CurrentAddress);
100 Valid = Valid &&
101 ok(PteValue == 0,
102 "[%lu] PTE for %p is nonzero (0x%I64x)\n",
103 i, CurrentAddress, PteValue);
104 }
105 CurrentAddress = (PUCHAR)BaseAddress - 1 * PAGE_SIZE;
106 PteValue = GET_PTE_VALUE(CurrentAddress);
107 Valid = Valid &&
108 ok(PteValue == (PoolTag & ~1ULL),
109 "PTE for %p contains 0x%I64x, expected %x\n",
110 CurrentAddress, PteValue, PoolTag & ~1);
111 CurrentAddress = (PUCHAR)BaseAddress - 2 * PAGE_SIZE;
112 PteValue = GET_PTE_VALUE(CurrentAddress);
113 Valid = Valid &&
114 ok(PteValue == (TotalPtes + 2) * 2,
115 "PTE for %p contains 0x%I64x, expected %x\n",
116 CurrentAddress, PteValue, (TotalPtes + 2) * 2);
117#endif
118
119 return Valid;
120}
121
122static
123VOID
126 _In_ ULONG TotalPtes,
128{
129 PMDL Mdl;
130 PHYSICAL_ADDRESS ZeroPhysical;
131 PHYSICAL_ADDRESS MaxPhysical;
133 PPFN_NUMBER MdlPages;
134 ULONG i;
135
136 if (skip(pMmAllocatePagesForMdlEx != NULL, "MmAllocatePagesForMdlEx unavailable\n"))
137 {
138 return;
139 }
140
141 ZeroPhysical.QuadPart = 0;
142 MaxPhysical.QuadPart = 0xffffffffffffffffLL;
143
144 /* Create a one-page MDL and map it */
145 Mdl = pMmAllocatePagesForMdlEx(ZeroPhysical,
146 MaxPhysical,
147 ZeroPhysical,
148 PAGE_SIZE,
149 MmCached,
150 0);
151 if (skip(Mdl != NULL, "No MDL\n"))
152 {
153 return;
154 }
155
156 MdlPages = (PVOID)(Mdl + 1);
157
159 PoolTag,
160 Mdl,
161 MmCached);
162 ok(BaseAddress != NULL, "MmMapLockedPagesWithReservedMapping failed\n");
163 if (!skip(BaseAddress != NULL, "Failed to map MDL\n"))
164 {
166
167 ok_bool_true(ValidateMapping(BaseAddress, TotalPtes, PoolTag, 1, MdlPages),
168 "ValidateMapping returned");
169
171 *(volatile ULONG *)BaseAddress = 0x01234567;
173
175 PoolTag,
176 Mdl);
177
178 ok_bool_true(ValidateMapping(Mapping, TotalPtes, PoolTag, 0, NULL),
179 "ValidateMapping returned");
180 }
181
182 /* Try again but at an unaligned address */
184 PoolTag,
185 Mdl,
186 MmCached);
187 ok(BaseAddress != NULL, "MmMapLockedPagesWithReservedMapping failed\n");
188 if (!skip(BaseAddress != NULL, "Failed to map MDL\n"))
189 {
191
192 ok_bool_true(ValidateMapping(BaseAddress, TotalPtes, PoolTag, 1, MdlPages),
193 "ValidateMapping returned");
194
196 *(volatile ULONG *)BaseAddress = 0x01234567;
198
200 PoolTag,
201 Mdl);
202
203 ok_bool_true(ValidateMapping(Mapping, TotalPtes, PoolTag, 0, NULL),
204 "ValidateMapping returned");
205 }
206
208
209 /* Map all pages */
210 Mdl = pMmAllocatePagesForMdlEx(ZeroPhysical,
211 MaxPhysical,
212 ZeroPhysical,
213 TotalPtes * PAGE_SIZE,
214 MmCached,
215 0);
216 if (skip(Mdl != NULL, "No MDL\n"))
217 {
218 return;
219 }
220
221 MdlPages = (PVOID)(Mdl + 1);
222
224 PoolTag,
225 Mdl,
226 MmCached);
227 ok(BaseAddress != NULL, "MmMapLockedPagesWithReservedMapping failed\n");
228 if (!skip(BaseAddress != NULL, "Failed to map MDL\n"))
229 {
231
232 ok_bool_true(ValidateMapping(BaseAddress, TotalPtes, PoolTag, TotalPtes, MdlPages),
233 "ValidateMapping returned");
234
235 for (i = 0; i < TotalPtes; i++)
236 {
238 *((volatile ULONG *)BaseAddress + i * PAGE_SIZE / sizeof(ULONG)) = 0x01234567;
240 }
241
243 PoolTag,
244 Mdl);
245
246 ok_bool_true(ValidateMapping(Mapping, TotalPtes, PoolTag, 0, NULL),
247 "ValidateMapping returned");
248 }
249
251
252 /* Try to map more pages than we reserved */
253 Mdl = pMmAllocatePagesForMdlEx(ZeroPhysical,
254 MaxPhysical,
255 ZeroPhysical,
256 (TotalPtes + 1) * PAGE_SIZE,
257 MmCached,
258 0);
259 if (skip(Mdl != NULL, "No MDL\n"))
260 {
261 return;
262 }
263
265 PoolTag,
266 Mdl,
267 MmCached);
269 if (BaseAddress)
270 {
272 PoolTag,
273 Mdl);
274 }
275
277}
278
279START_TEST(MmReservedMapping)
280{
282
284
285 pMmAllocatePagesForMdlEx = KmtGetSystemRoutineAddress(L"MmAllocatePagesForMdlEx");
286
287 /* one byte - single page */
289 ok(Mapping != NULL, "MmAllocateMappingAddress failed\n");
290 if (!skip(Mapping != NULL, "No mapping\n"))
291 {
292 ok_bool_true(ValidateMapping(Mapping, 1, 'MRmK', 0, NULL),
293 "ValidateMapping returned");
294
296 }
297
298 /* 10 pages */
299 Mapping = MmAllocateMappingAddress(10 * PAGE_SIZE, 'MRmK' & ~1);
300 ok(Mapping != NULL, "MmAllocateMappingAddress failed\n");
301 if (!skip(Mapping != NULL, "No mapping\n"))
302 {
303 ok_bool_true(ValidateMapping(Mapping, 10, 'MRmK', 0, NULL),
304 "ValidateMapping returned");
305
306 /* PAGE_FAULT_IN_NONPAGED_AREA can't be caught with SEH */
307 if (0)
308 {
309 (void)*(volatile UCHAR *)Mapping;
310 }
311
312 TestMap(Mapping, 10, 'MRmK');
313
315 }
316
317 /* PoolTag = 0 */
319 ok(Mapping == NULL, "MmAllocateMappingAddress failed\n");
320 if (Mapping != NULL)
321 {
323 }
324
325 /* PoolTag = 1 */
327 ok(Mapping != NULL, "MmAllocateMappingAddress failed\n");
328 if (Mapping != NULL)
329 {
330 ok_bool_true(ValidateMapping(Mapping, 1, 1, 0, NULL),
331 "ValidateMapping returned");
332
333 TestMap(Mapping, 1, 1);
334
336 }
337
338 /* Free an unaligned address */
340 ok(Mapping != NULL, "MmAllocateMappingAddress failed\n");
341 if (Mapping != NULL)
342 {
343 ok_bool_true(ValidateMapping(Mapping, 1, 'MRmK', 0, NULL),
344 "ValidateMapping returned");
345
346 TestMap(Mapping, 1, 'MRmK');
347
348 MmFreeMappingAddress((PUCHAR)Mapping + sizeof(ULONG), 'MRmK');
349 }
350}
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)
VOID NTAPI MmFreePagesFromMdl(IN PMDL Mdl)
Definition: mdlsup.c:564
VOID NTAPI MmUnmapReservedMapping(IN PVOID BaseAddress, IN ULONG PoolTag, IN PMDL MemoryDescriptorList)
Definition: mdlsup.c:1643
PVOID NTAPI MmMapLockedPagesWithReservedMapping(IN PVOID MappingAddress, IN ULONG PoolTag, IN PMDL MemoryDescriptorList, IN MEMORY_CACHING_TYPE CacheType)
Definition: mdlsup.c:1629
#define PTE_BASE
Definition: mmx86.c:14
unsigned __int64 ULONG64
Definition: imports.h:198
#define _Must_inspect_result_
Definition: ms_sal.h:558
#define _In_
Definition: ms_sal.h:308
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID * BaseAddress
Definition: mmfuncs.h:404
__GNU_EXTENSION typedef unsigned __int64 * PULONGLONG
Definition: ntbasedef.h:383
_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
VOID NTAPI MmFreeMappingAddress(IN PVOID BaseAddress, IN ULONG PoolTag)
Definition: pool.c:1572
PVOID NTAPI MmAllocateMappingAddress(IN SIZE_T NumberOfBytes, IN ULONG PoolTag)
Definition: pool.c:1560
#define L(x)
Definition: ntvdm.h:50
static WCHAR Address[46]
Definition: ping.c:68
#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
#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