[KMTESTS:MM]
[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 BOOLEAN
35 ValidateMapping(
36 _In_ PVOID BaseAddress,
37 _In_ ULONG TotalPtes,
38 _In_ ULONG PoolTag,
39 _In_ ULONG ValidPtes,
40 _In_ PPFN_NUMBER Pfns)
41 {
42 BOOLEAN Valid = TRUE;
43 #if defined(_M_IX86) || defined(_M_AMD64)
44 PMMPTE PointerPte;
45 ULONG i;
46
47 PointerPte = MiAddressToPte(BaseAddress);
48 for (i = 0; i < ValidPtes; i++)
49 {
50 Valid = Valid &&
51 ok(PointerPte[i].u.Hard.Valid == 1,
52 "[%lu] PTE %p is not valid\n", i, &PointerPte[i]);
53
54 Valid = Valid &&
55 ok(PointerPte[i].u.Hard.PageFrameNumber == Pfns[i],
56 "[%lu] PTE %p has PFN %Ix, expected %Ix\n",
57 i, &PointerPte[i], PointerPte[i].u.Hard.PageFrameNumber, Pfns[i]);
58 }
59 for (; i < TotalPtes; i++)
60 {
61 Valid = Valid &&
62 ok_eq_hex(PointerPte[i].u.Long, 0UL);
63 }
64 Valid = Valid &&
65 ok_eq_tag(PointerPte[-1].u.Long, PoolTag & ~1);
66 Valid = Valid &&
67 ok_eq_ulong(PointerPte[-2].u.Long, (TotalPtes + 2) * 2);
68 #endif
69
70 return Valid;
71 }
72
73 static
74 VOID
75 TestMap(
76 _In_ PVOID Mapping,
77 _In_ ULONG TotalPtes,
78 _In_ ULONG PoolTag)
79 {
80 PMDL Mdl;
81 PHYSICAL_ADDRESS ZeroPhysical;
82 PHYSICAL_ADDRESS MaxPhysical;
83 PVOID BaseAddress;
84 PPFN_NUMBER MdlPages;
85 ULONG i;
86
87 ZeroPhysical.QuadPart = 0;
88 MaxPhysical.QuadPart = 0xffffffffffffffffLL;
89
90 /* Create a one-page MDL and map it */
91 Mdl = MmAllocatePagesForMdlEx(ZeroPhysical,
92 MaxPhysical,
93 ZeroPhysical,
94 PAGE_SIZE,
95 MmCached,
96 0);
97 if (skip(Mdl != NULL, "No MDL\n"))
98 {
99 return;
100 }
101
102 MdlPages = (PVOID)(Mdl + 1);
103
104 BaseAddress = MmMapLockedPagesWithReservedMapping(Mapping,
105 PoolTag,
106 Mdl,
107 MmCached);
108 ok(BaseAddress != NULL, "MmMapLockedPagesWithReservedMapping failed\n");
109 if (!skip(BaseAddress != NULL, "Failed to map MDL\n"))
110 {
111 ok_eq_pointer(BaseAddress, Mapping);
112
113 ok_bool_true(ValidateMapping(BaseAddress, TotalPtes, PoolTag, 1, MdlPages),
114 "ValidateMapping returned");
115
116 KmtStartSeh()
117 *(volatile ULONG *)BaseAddress = 0x01234567;
118 KmtEndSeh(STATUS_SUCCESS);
119
120 MmUnmapReservedMapping(BaseAddress,
121 PoolTag,
122 Mdl);
123
124 ok_bool_true(ValidateMapping(Mapping, TotalPtes, PoolTag, 0, NULL),
125 "ValidateMapping returned");
126 }
127
128 /* Try again but at an unaligned address */
129 BaseAddress = MmMapLockedPagesWithReservedMapping((PUCHAR)Mapping + sizeof(ULONG),
130 PoolTag,
131 Mdl,
132 MmCached);
133 ok(BaseAddress != NULL, "MmMapLockedPagesWithReservedMapping failed\n");
134 if (!skip(BaseAddress != NULL, "Failed to map MDL\n"))
135 {
136 ok_eq_pointer(BaseAddress, (PUCHAR)Mapping + sizeof(ULONG));
137
138 ok_bool_true(ValidateMapping(BaseAddress, TotalPtes, PoolTag, 1, MdlPages),
139 "ValidateMapping returned");
140
141 KmtStartSeh()
142 *(volatile ULONG *)BaseAddress = 0x01234567;
143 KmtEndSeh(STATUS_SUCCESS);
144
145 MmUnmapReservedMapping(BaseAddress,
146 PoolTag,
147 Mdl);
148
149 ok_bool_true(ValidateMapping(Mapping, TotalPtes, PoolTag, 0, NULL),
150 "ValidateMapping returned");
151 }
152
153 MmFreePagesFromMdl(Mdl);
154
155 /* Map all pages */
156 Mdl = MmAllocatePagesForMdlEx(ZeroPhysical,
157 MaxPhysical,
158 ZeroPhysical,
159 TotalPtes * PAGE_SIZE,
160 MmCached,
161 0);
162 if (skip(Mdl != NULL, "No MDL\n"))
163 {
164 return;
165 }
166
167 MdlPages = (PVOID)(Mdl + 1);
168
169 BaseAddress = MmMapLockedPagesWithReservedMapping(Mapping,
170 PoolTag,
171 Mdl,
172 MmCached);
173 ok(BaseAddress != NULL, "MmMapLockedPagesWithReservedMapping failed\n");
174 if (!skip(BaseAddress != NULL, "Failed to map MDL\n"))
175 {
176 ok_eq_pointer(BaseAddress, Mapping);
177
178 ok_bool_true(ValidateMapping(BaseAddress, TotalPtes, PoolTag, TotalPtes, MdlPages),
179 "ValidateMapping returned");
180
181 for (i = 0; i < TotalPtes; i++)
182 {
183 KmtStartSeh()
184 *((volatile ULONG *)BaseAddress + i * PAGE_SIZE / sizeof(ULONG)) = 0x01234567;
185 KmtEndSeh(STATUS_SUCCESS);
186 }
187
188 MmUnmapReservedMapping(BaseAddress,
189 PoolTag,
190 Mdl);
191
192 ok_bool_true(ValidateMapping(Mapping, TotalPtes, PoolTag, 0, NULL),
193 "ValidateMapping returned");
194 }
195
196 MmFreePagesFromMdl(Mdl);
197
198 /* Try to map more pages than we reserved */
199 Mdl = MmAllocatePagesForMdlEx(ZeroPhysical,
200 MaxPhysical,
201 ZeroPhysical,
202 (TotalPtes + 1) * PAGE_SIZE,
203 MmCached,
204 0);
205 if (skip(Mdl != NULL, "No MDL\n"))
206 {
207 return;
208 }
209
210 BaseAddress = MmMapLockedPagesWithReservedMapping(Mapping,
211 PoolTag,
212 Mdl,
213 MmCached);
214 ok_eq_pointer(BaseAddress, NULL);
215 if (BaseAddress)
216 {
217 MmUnmapReservedMapping(BaseAddress,
218 PoolTag,
219 Mdl);
220 }
221
222 MmFreePagesFromMdl(Mdl);
223 }
224
225 START_TEST(MmReservedMapping)
226 {
227 PVOID Mapping;
228
229 /* one byte - single page */
230 Mapping = MmAllocateMappingAddress(1, 'MRmK');
231 ok(Mapping != NULL, "MmAllocateMappingAddress failed\n");
232 if (!skip(Mapping != NULL, "No mapping\n"))
233 {
234 ok_bool_true(ValidateMapping(Mapping, 1, 'MRmK', 0, NULL),
235 "ValidateMapping returned");
236
237 MmFreeMappingAddress(Mapping, 'MRmK');
238 }
239
240 /* 10 pages */
241 Mapping = MmAllocateMappingAddress(10 * PAGE_SIZE, 'MRmK' & ~1);
242 ok(Mapping != NULL, "MmAllocateMappingAddress failed\n");
243 if (!skip(Mapping != NULL, "No mapping\n"))
244 {
245 ok_bool_true(ValidateMapping(Mapping, 10, 'MRmK', 0, NULL),
246 "ValidateMapping returned");
247
248 /* PAGE_FAULT_IN_NONPAGED_AREA can't be caught with SEH */
249 if (0)
250 {
251 (void)*(volatile UCHAR *)Mapping;
252 }
253
254 TestMap(Mapping, 10, 'MRmK');
255
256 MmFreeMappingAddress(Mapping, 'MRmK');
257 }
258
259 /* PoolTag = 0 */
260 Mapping = MmAllocateMappingAddress(1, 0);
261 ok(Mapping == NULL, "MmAllocateMappingAddress failed\n");
262 if (Mapping != NULL)
263 {
264 MmFreeMappingAddress(Mapping, 0);
265 }
266
267 /* PoolTag = 1 */
268 Mapping = MmAllocateMappingAddress(1, 1);
269 ok(Mapping != NULL, "MmAllocateMappingAddress failed\n");
270 if (Mapping != NULL)
271 {
272 ok_bool_true(ValidateMapping(Mapping, 1, 1, 0, NULL),
273 "ValidateMapping returned");
274
275 TestMap(Mapping, 1, 1);
276
277 MmFreeMappingAddress(Mapping, 1);
278 }
279
280 /* Free an unaligned address */
281 Mapping = MmAllocateMappingAddress(PAGE_SIZE, 'MRmK');
282 ok(Mapping != NULL, "MmAllocateMappingAddress failed\n");
283 if (Mapping != NULL)
284 {
285 ok_bool_true(ValidateMapping(Mapping, 1, 'MRmK', 0, NULL),
286 "ValidateMapping returned");
287
288 TestMap(Mapping, 1, 'MRmK');
289
290 MmFreeMappingAddress((PUCHAR)Mapping + sizeof(ULONG), 'MRmK');
291 }
292 }