fd35a208ce3d77a65fe01132dc866fbc5d1500cb
[reactos.git] / rostests / kmtests / ntos_mm / MmReservedMapping.c
1 /*
2 * PROJECT: ReactOS kernel-mode tests
3 * LICENSE: LGPLv2.1+ - See COPYING.LIB in the top level directory
4 * PURPOSE: Kernel-Mode Test Suite Reserved Mapping test
5 * PROGRAMMER: Thomas Faber <thomas.faber@reactos.org>
6 */
7
8 #include <kmt_test.h>
9
10 #ifdef _M_IX86
11
12 #define PTE_BASE 0xC0000000
13 #define MiAddressToPte(x) \
14 ((PMMPTE)(((((ULONG)(x)) >> 12) << 2) + PTE_BASE))
15 #define MiPteToAddress(_Pte) ((PVOID)((ULONG)(_Pte) << 10))
16
17 #elif defined(_M_AMD64)
18
19 #define PTI_SHIFT 12L
20 #define PTE_BASE 0xFFFFF68000000000ULL
21 PMMPTE
22 FORCEINLINE
23 _MiAddressToPte(PVOID Address)
24 {
25 ULONG64 Offset = (ULONG64)Address >> (PTI_SHIFT - 3);
26 Offset &= 0xFFFFFFFFFULL << 3;
27 return (PMMPTE)(PTE_BASE + Offset);
28 }
29 #define MiAddressToPte(x) _MiAddressToPte((PVOID)(x))
30
31 #endif
32
33 static
34 _Must_inspect_result_
35 _IRQL_requires_max_ (DISPATCH_LEVEL)
36 PMDL
37 (NTAPI
38 *pMmAllocatePagesForMdlEx)(
39 _In_ PHYSICAL_ADDRESS LowAddress,
40 _In_ PHYSICAL_ADDRESS HighAddress,
41 _In_ PHYSICAL_ADDRESS SkipBytes,
42 _In_ SIZE_T TotalBytes,
43 _In_ MEMORY_CACHING_TYPE CacheType,
44 _In_ ULONG Flags);
45
46 static
47 BOOLEAN
48 ValidateMapping(
49 _In_ PVOID BaseAddress,
50 _In_ ULONG TotalPtes,
51 _In_ ULONG PoolTag,
52 _In_ ULONG ValidPtes,
53 _In_ PPFN_NUMBER Pfns)
54 {
55 BOOLEAN Valid = TRUE;
56 #if defined(_M_IX86) || defined(_M_AMD64)
57 PMMPTE PointerPte;
58 ULONG i;
59
60 PointerPte = MiAddressToPte(BaseAddress);
61 for (i = 0; i < ValidPtes; i++)
62 {
63 Valid = Valid &&
64 ok(PointerPte[i].u.Hard.Valid == 1,
65 "[%lu] PTE %p is not valid\n", i, &PointerPte[i]);
66
67 Valid = Valid &&
68 ok(PointerPte[i].u.Hard.PageFrameNumber == Pfns[i],
69 "[%lu] PTE %p has PFN %Ix, expected %Ix\n",
70 i, &PointerPte[i], PointerPte[i].u.Hard.PageFrameNumber, Pfns[i]);
71 }
72 for (; i < TotalPtes; i++)
73 {
74 Valid = Valid &&
75 ok_eq_hex(PointerPte[i].u.Long, 0UL);
76 }
77 Valid = Valid &&
78 ok_eq_tag(PointerPte[-1].u.Long, PoolTag & ~1);
79 Valid = Valid &&
80 ok_eq_ulong(PointerPte[-2].u.Long, (TotalPtes + 2) * 2);
81 #endif
82
83 return Valid;
84 }
85
86 static
87 VOID
88 TestMap(
89 _In_ PVOID Mapping,
90 _In_ ULONG TotalPtes,
91 _In_ ULONG PoolTag)
92 {
93 PMDL Mdl;
94 PHYSICAL_ADDRESS ZeroPhysical;
95 PHYSICAL_ADDRESS MaxPhysical;
96 PVOID BaseAddress;
97 PPFN_NUMBER MdlPages;
98 ULONG i;
99
100 if (skip(pMmAllocatePagesForMdlEx != NULL, "MmAllocatePagesForMdlEx unavailable\n"))
101 {
102 return;
103 }
104
105 ZeroPhysical.QuadPart = 0;
106 MaxPhysical.QuadPart = 0xffffffffffffffffLL;
107
108 /* Create a one-page MDL and map it */
109 Mdl = pMmAllocatePagesForMdlEx(ZeroPhysical,
110 MaxPhysical,
111 ZeroPhysical,
112 PAGE_SIZE,
113 MmCached,
114 0);
115 if (skip(Mdl != NULL, "No MDL\n"))
116 {
117 return;
118 }
119
120 MdlPages = (PVOID)(Mdl + 1);
121
122 BaseAddress = MmMapLockedPagesWithReservedMapping(Mapping,
123 PoolTag,
124 Mdl,
125 MmCached);
126 ok(BaseAddress != NULL, "MmMapLockedPagesWithReservedMapping failed\n");
127 if (!skip(BaseAddress != NULL, "Failed to map MDL\n"))
128 {
129 ok_eq_pointer(BaseAddress, Mapping);
130
131 ok_bool_true(ValidateMapping(BaseAddress, TotalPtes, PoolTag, 1, MdlPages),
132 "ValidateMapping returned");
133
134 KmtStartSeh()
135 *(volatile ULONG *)BaseAddress = 0x01234567;
136 KmtEndSeh(STATUS_SUCCESS);
137
138 MmUnmapReservedMapping(BaseAddress,
139 PoolTag,
140 Mdl);
141
142 ok_bool_true(ValidateMapping(Mapping, TotalPtes, PoolTag, 0, NULL),
143 "ValidateMapping returned");
144 }
145
146 /* Try again but at an unaligned address */
147 BaseAddress = MmMapLockedPagesWithReservedMapping((PUCHAR)Mapping + sizeof(ULONG),
148 PoolTag,
149 Mdl,
150 MmCached);
151 ok(BaseAddress != NULL, "MmMapLockedPagesWithReservedMapping failed\n");
152 if (!skip(BaseAddress != NULL, "Failed to map MDL\n"))
153 {
154 ok_eq_pointer(BaseAddress, (PUCHAR)Mapping + sizeof(ULONG));
155
156 ok_bool_true(ValidateMapping(BaseAddress, TotalPtes, PoolTag, 1, MdlPages),
157 "ValidateMapping returned");
158
159 KmtStartSeh()
160 *(volatile ULONG *)BaseAddress = 0x01234567;
161 KmtEndSeh(STATUS_SUCCESS);
162
163 MmUnmapReservedMapping(BaseAddress,
164 PoolTag,
165 Mdl);
166
167 ok_bool_true(ValidateMapping(Mapping, TotalPtes, PoolTag, 0, NULL),
168 "ValidateMapping returned");
169 }
170
171 MmFreePagesFromMdl(Mdl);
172
173 /* Map all pages */
174 Mdl = pMmAllocatePagesForMdlEx(ZeroPhysical,
175 MaxPhysical,
176 ZeroPhysical,
177 TotalPtes * PAGE_SIZE,
178 MmCached,
179 0);
180 if (skip(Mdl != NULL, "No MDL\n"))
181 {
182 return;
183 }
184
185 MdlPages = (PVOID)(Mdl + 1);
186
187 BaseAddress = MmMapLockedPagesWithReservedMapping(Mapping,
188 PoolTag,
189 Mdl,
190 MmCached);
191 ok(BaseAddress != NULL, "MmMapLockedPagesWithReservedMapping failed\n");
192 if (!skip(BaseAddress != NULL, "Failed to map MDL\n"))
193 {
194 ok_eq_pointer(BaseAddress, Mapping);
195
196 ok_bool_true(ValidateMapping(BaseAddress, TotalPtes, PoolTag, TotalPtes, MdlPages),
197 "ValidateMapping returned");
198
199 for (i = 0; i < TotalPtes; i++)
200 {
201 KmtStartSeh()
202 *((volatile ULONG *)BaseAddress + i * PAGE_SIZE / sizeof(ULONG)) = 0x01234567;
203 KmtEndSeh(STATUS_SUCCESS);
204 }
205
206 MmUnmapReservedMapping(BaseAddress,
207 PoolTag,
208 Mdl);
209
210 ok_bool_true(ValidateMapping(Mapping, TotalPtes, PoolTag, 0, NULL),
211 "ValidateMapping returned");
212 }
213
214 MmFreePagesFromMdl(Mdl);
215
216 /* Try to map more pages than we reserved */
217 Mdl = pMmAllocatePagesForMdlEx(ZeroPhysical,
218 MaxPhysical,
219 ZeroPhysical,
220 (TotalPtes + 1) * PAGE_SIZE,
221 MmCached,
222 0);
223 if (skip(Mdl != NULL, "No MDL\n"))
224 {
225 return;
226 }
227
228 BaseAddress = MmMapLockedPagesWithReservedMapping(Mapping,
229 PoolTag,
230 Mdl,
231 MmCached);
232 ok_eq_pointer(BaseAddress, NULL);
233 if (BaseAddress)
234 {
235 MmUnmapReservedMapping(BaseAddress,
236 PoolTag,
237 Mdl);
238 }
239
240 MmFreePagesFromMdl(Mdl);
241 }
242
243 START_TEST(MmReservedMapping)
244 {
245 PVOID Mapping;
246
247 pMmAllocatePagesForMdlEx = KmtGetSystemRoutineAddress(L"MmAllocatePagesForMdlEx");
248
249 /* one byte - single page */
250 Mapping = MmAllocateMappingAddress(1, 'MRmK');
251 ok(Mapping != NULL, "MmAllocateMappingAddress failed\n");
252 if (!skip(Mapping != NULL, "No mapping\n"))
253 {
254 ok_bool_true(ValidateMapping(Mapping, 1, 'MRmK', 0, NULL),
255 "ValidateMapping returned");
256
257 MmFreeMappingAddress(Mapping, 'MRmK');
258 }
259
260 /* 10 pages */
261 Mapping = MmAllocateMappingAddress(10 * PAGE_SIZE, 'MRmK' & ~1);
262 ok(Mapping != NULL, "MmAllocateMappingAddress failed\n");
263 if (!skip(Mapping != NULL, "No mapping\n"))
264 {
265 ok_bool_true(ValidateMapping(Mapping, 10, 'MRmK', 0, NULL),
266 "ValidateMapping returned");
267
268 /* PAGE_FAULT_IN_NONPAGED_AREA can't be caught with SEH */
269 if (0)
270 {
271 (void)*(volatile UCHAR *)Mapping;
272 }
273
274 TestMap(Mapping, 10, 'MRmK');
275
276 MmFreeMappingAddress(Mapping, 'MRmK');
277 }
278
279 /* PoolTag = 0 */
280 Mapping = MmAllocateMappingAddress(1, 0);
281 ok(Mapping == NULL, "MmAllocateMappingAddress failed\n");
282 if (Mapping != NULL)
283 {
284 MmFreeMappingAddress(Mapping, 0);
285 }
286
287 /* PoolTag = 1 */
288 Mapping = MmAllocateMappingAddress(1, 1);
289 ok(Mapping != NULL, "MmAllocateMappingAddress failed\n");
290 if (Mapping != NULL)
291 {
292 ok_bool_true(ValidateMapping(Mapping, 1, 1, 0, NULL),
293 "ValidateMapping returned");
294
295 TestMap(Mapping, 1, 1);
296
297 MmFreeMappingAddress(Mapping, 1);
298 }
299
300 /* Free an unaligned address */
301 Mapping = MmAllocateMappingAddress(PAGE_SIZE, 'MRmK');
302 ok(Mapping != NULL, "MmAllocateMappingAddress failed\n");
303 if (Mapping != NULL)
304 {
305 ok_bool_true(ValidateMapping(Mapping, 1, 'MRmK', 0, NULL),
306 "ValidateMapping returned");
307
308 TestMap(Mapping, 1, 'MRmK');
309
310 MmFreeMappingAddress((PUCHAR)Mapping + sizeof(ULONG), 'MRmK');
311 }
312 }