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 MDL test
5 * COPYRIGHT: Copyright 2015,2023 Thomas Faber (thomas.faber@reactos.org)
6 * COPYRIGHT: Copyright 2017 Pierre Schweitzer (pierre@reactos.org)
7 */
8
9 #include <kmt_test.h>
10
11 static
12 VOID
TestMmAllocatePagesForMdl(VOID)13 TestMmAllocatePagesForMdl(VOID)
14 {
15 PMDL Mdl;
16 PHYSICAL_ADDRESS LowAddress;
17 PHYSICAL_ADDRESS HighAddress;
18 PHYSICAL_ADDRESS SkipBytes;
19 PVOID SystemVa;
20 PMDL Mdls[32];
21 PVOID SystemVas[32];
22 ULONG i;
23 PPFN_NUMBER MdlPages;
24 ULONG MdlPageCount;
25
26 LowAddress.QuadPart = 0;
27 HighAddress.QuadPart = -1;
28 SkipBytes.QuadPart = 0;
29 /* simple allocate/free */
30 Mdl = MmAllocatePagesForMdl(LowAddress,
31 HighAddress,
32 SkipBytes,
33 2 * 1024 * 1024);
34 ok(Mdl != NULL, "MmAllocatePagesForMdl failed\n");
35 if (skip(Mdl != NULL, "No Mdl\n"))
36 return;
37 ok(MmGetMdlByteCount(Mdl) == 2 * 1024 * 1024, "Byte count: %lu\n", MmGetMdlByteCount(Mdl));
38 ok(MmGetMdlVirtualAddress(Mdl) == NULL, "Virtual address: %p\n", MmGetMdlVirtualAddress(Mdl));
39 ok(!(Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA), "MdlFlags: %lx\n", Mdl->MdlFlags);
40 MdlPages = MmGetMdlPfnArray(Mdl);
41 MdlPageCount = ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(Mdl), MmGetMdlByteCount(Mdl));
42 ok(MdlPageCount == 2 * 1024 * 1024 / PAGE_SIZE, "MdlPageCount = %lu\n", MdlPageCount);
43 for (i = 0; i < MdlPageCount; i++)
44 {
45 ok(MdlPages[i] != 0 && MdlPages[i] != (PFN_NUMBER)-1,
46 "MdlPages[%lu] = 0x%I64x\n", i, (ULONGLONG)MdlPages[i]);
47 }
48 MmFreePagesFromMdl(Mdl);
49 ExFreePoolWithTag(Mdl, 0);
50
51 /* Now map/unmap it */
52 Mdl = MmAllocatePagesForMdl(LowAddress,
53 HighAddress,
54 SkipBytes,
55 2 * 1024 * 1024);
56 ok(Mdl != NULL, "MmAllocatePagesForMdl failed\n");
57 if (skip(Mdl != NULL, "No Mdl\n"))
58 return;
59 ok(MmGetMdlByteCount(Mdl) == 2 * 1024 * 1024, "Byte count: %lu\n", MmGetMdlByteCount(Mdl));
60 ok(MmGetMdlVirtualAddress(Mdl) == NULL, "Virtual address: %p\n", MmGetMdlVirtualAddress(Mdl));
61 ok(!(Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA), "MdlFlags: %lx\n", Mdl->MdlFlags);
62 SystemVa = MmMapLockedPagesSpecifyCache(Mdl,
63 KernelMode,
64 MmCached,
65 NULL,
66 FALSE,
67 NormalPagePriority);
68 ok(SystemVa != NULL, "MmMapLockedPagesSpecifyCache failed\n");
69 if (!skip(SystemVa != NULL, "No system VA\n"))
70 {
71 ok(MmGetMdlByteCount(Mdl) == 2 * 1024 * 1024, "Byte count: %lu\n", MmGetMdlByteCount(Mdl));
72 ok(MmGetMdlVirtualAddress(Mdl) == NULL, "Virtual address: %p, System VA: %p\n", MmGetMdlVirtualAddress(Mdl), SystemVa);
73 ok(Mdl->MappedSystemVa == SystemVa, "MappedSystemVa: %p, System VA: %p\n", Mdl->MappedSystemVa, SystemVa);
74 ok((Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA), "MdlFlags: %lx\n", Mdl->MdlFlags);
75 MmUnmapLockedPages(SystemVa, Mdl);
76 }
77 ok(MmGetMdlByteCount(Mdl) == 2 * 1024 * 1024, "Byte count: %lu\n", MmGetMdlByteCount(Mdl));
78 ok(MmGetMdlVirtualAddress(Mdl) == NULL, "Virtual address: %p\n", MmGetMdlVirtualAddress(Mdl));
79 ok(!(Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA), "MdlFlags: %lx\n", Mdl->MdlFlags);
80 MmFreePagesFromMdl(Mdl);
81 ExFreePoolWithTag(Mdl, 0);
82
83 /* Now map it, and free without unmapping */
84 Mdl = MmAllocatePagesForMdl(LowAddress,
85 HighAddress,
86 SkipBytes,
87 2 * 1024 * 1024);
88 ok(Mdl != NULL, "MmAllocatePagesForMdl failed\n");
89 if (skip(Mdl != NULL, "No Mdl\n"))
90 return;
91 ok(MmGetMdlByteCount(Mdl) == 2 * 1024 * 1024, "Byte count: %lu\n", MmGetMdlByteCount(Mdl));
92 ok(MmGetMdlVirtualAddress(Mdl) == NULL, "Virtual address: %p\n", MmGetMdlVirtualAddress(Mdl));
93 ok(!(Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA), "MdlFlags: %lx\n", Mdl->MdlFlags);
94 SystemVa = MmMapLockedPagesSpecifyCache(Mdl,
95 KernelMode,
96 MmCached,
97 NULL,
98 FALSE,
99 NormalPagePriority);
100 ok(SystemVa != NULL, "MmMapLockedPagesSpecifyCache failed\n");
101 ok(MmGetMdlByteCount(Mdl) == 2 * 1024 * 1024, "Byte count: %lu\n", MmGetMdlByteCount(Mdl));
102 ok(MmGetMdlVirtualAddress(Mdl) == NULL, "Virtual address: %p, System VA: %p\n", MmGetMdlVirtualAddress(Mdl), SystemVa);
103 ok(Mdl->MappedSystemVa == SystemVa, "MappedSystemVa: %p, System VA: %p\n", Mdl->MappedSystemVa, SystemVa);
104 ok((Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA), "MdlFlags: %lx\n", Mdl->MdlFlags);
105 MmFreePagesFromMdl(Mdl);
106 ExFreePoolWithTag(Mdl, 0);
107
108 /* try to allocate 2 GB -- should succeed (possibly with fewer pages) but not map */
109 Mdl = MmAllocatePagesForMdl(LowAddress,
110 HighAddress,
111 SkipBytes,
112 2UL * 1024 * 1024 * 1024);
113 ok(Mdl != NULL, "MmAllocatePagesForMdl failed for 2 GB\n");
114 if (Mdl != NULL)
115 {
116 ok(MmGetMdlByteCount(Mdl) <= 2UL * 1024 * 1024 * 1024, "Byte count: %lu\n", MmGetMdlByteCount(Mdl));
117 ok(MmGetMdlVirtualAddress(Mdl) == NULL, "Virtual address: %p\n", MmGetMdlVirtualAddress(Mdl));
118 ok(!(Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA), "MdlFlags: %lx\n", Mdl->MdlFlags);
119 MdlPages = MmGetMdlPfnArray(Mdl);
120 MdlPageCount = ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(Mdl), MmGetMdlByteCount(Mdl));
121 ok(MdlPageCount <= 2UL * 1024 * 1024 * 1024 / PAGE_SIZE, "MdlPageCount = %lu\n", MdlPageCount);
122 for (i = 0; i < MdlPageCount; i++)
123 {
124 if (MdlPages[i] == 0 ||
125 MdlPages[i] == (PFN_NUMBER)-1)
126 {
127 ok(0, "MdlPages[%lu] = 0x%I64x\n", i, (ULONGLONG)MdlPages[i]);
128 }
129 }
130 SystemVa = MmMapLockedPagesSpecifyCache(Mdl,
131 KernelMode,
132 MmCached,
133 NULL,
134 FALSE,
135 NormalPagePriority);
136 ok(SystemVa == NULL, "MmMapLockedPagesSpecifyCache succeeded for 2 GB\n");
137 if (SystemVa != NULL)
138 MmUnmapLockedPages(SystemVa, Mdl);
139 ok(MmGetMdlByteCount(Mdl) <= 2UL * 1024 * 1024 * 1024, "Byte count: %lu\n", MmGetMdlByteCount(Mdl));
140 ok(MmGetMdlVirtualAddress(Mdl) == NULL, "Virtual address: %p\n", MmGetMdlVirtualAddress(Mdl));
141 ok(!(Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA), "MdlFlags: %lx\n", Mdl->MdlFlags);
142 MmFreePagesFromMdl(Mdl);
143 ExFreePoolWithTag(Mdl, 0);
144 }
145
146 /* now allocate and map 32 MB Mdls until we fail */
147 for (i = 0; i < sizeof(Mdls) / sizeof(Mdls[0]); i++)
148 {
149 Mdls[i] = MmAllocatePagesForMdl(LowAddress,
150 HighAddress,
151 SkipBytes,
152 32 * 1024 * 1024);
153 if (Mdls[i] == NULL)
154 {
155 trace("MmAllocatePagesForMdl failed with i = %lu\n", i);
156 break;
157 }
158 ok(MmGetMdlVirtualAddress(Mdls[i]) == NULL, "Virtual address: %p\n", MmGetMdlVirtualAddress(Mdls[i]));
159 ok(!(Mdls[i]->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA), "MdlFlags: %lx\n", Mdls[i]->MdlFlags);
160 SystemVas[i] = MmMapLockedPagesSpecifyCache(Mdls[i],
161 KernelMode,
162 MmCached,
163 NULL,
164 FALSE,
165 NormalPagePriority);
166 if (SystemVas[i] == NULL)
167 {
168 ok(MmGetMdlByteCount(Mdls[i]) <= 32 * 1024 * 1024, "Byte count: %lu\n", MmGetMdlByteCount(Mdls[i]));
169 ok(MmGetMdlVirtualAddress(Mdls[i]) == NULL, "Virtual address: %p\n", MmGetMdlVirtualAddress(Mdls[i]));
170 ok(!(Mdls[i]->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA), "MdlFlags: %lx\n", Mdls[i]->MdlFlags);
171 trace("MmMapLockedPagesSpecifyCache failed with i = %lu\n", i);
172 break;
173 }
174 ok(MmGetMdlByteCount(Mdls[i]) == 32 * 1024 * 1024, "Byte count: %lu\n", MmGetMdlByteCount(Mdls[i]));
175 ok(MmGetMdlVirtualAddress(Mdls[i]) == NULL, "Virtual address: %p, System VA: %p\n", MmGetMdlVirtualAddress(Mdls[i]), SystemVas[i]);
176 ok(Mdls[i]->MappedSystemVa == SystemVas[i], "MappedSystemVa: %p\n", Mdls[i]->MappedSystemVa, SystemVas[i]);
177 ok((Mdls[i]->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA), "MdlFlags: %lx\n", Mdls[i]->MdlFlags);
178 }
179 for (i = 0; i < sizeof(Mdls) / sizeof(Mdls[0]); i++)
180 {
181 if (Mdls[i] == NULL)
182 break;
183 if (SystemVas[i] != NULL)
184 MmUnmapLockedPages(SystemVas[i], Mdls[i]);
185 MmFreePagesFromMdl(Mdls[i]);
186 ExFreePoolWithTag(Mdls[i], 0);
187 if (SystemVas[i] == NULL)
188 break;
189 }
190 }
191
192 static
193 VOID
TestMmBuildMdlForNonPagedPool(VOID)194 TestMmBuildMdlForNonPagedPool(VOID)
195 {
196 PVOID Page;
197 PMDL Mdl;
198
199 Page = ExAllocatePoolWithTag(PagedPool, PAGE_SIZE, 'Test');
200 ok(Page != NULL, "ExAllocatePoolWithTag failed\n");
201 if (skip(Page != NULL, "No buffer\n"))
202 return;
203
204 Mdl = IoAllocateMdl(Page, PAGE_SIZE, FALSE, FALSE, NULL);
205 ok(Mdl != NULL, "IoAllocateMdl failed\n");
206 if (skip(Mdl != NULL, "No MDL\n"))
207 return;
208
209 ok((Mdl->MdlFlags & MDL_PAGES_LOCKED) == 0, "MDL locked\n");
210 ok((Mdl->MdlFlags & MDL_SOURCE_IS_NONPAGED_POOL) == 0, "MDL from non paged\n");
211
212 MmBuildMdlForNonPagedPool(Mdl);
213 ok((Mdl->MdlFlags & MDL_PAGES_LOCKED) == 0, "MDL locked\n");
214 ok((Mdl->MdlFlags & MDL_SOURCE_IS_NONPAGED_POOL) != 0, "MDL from paged\n");
215
216 IoFreeMdl(Mdl);
217 ExFreePoolWithTag(Page, 'Test');
218
219 Page = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, 'Test');
220 ok(Page != NULL, "ExAllocatePoolWithTag failed\n");
221 if (skip(Page != NULL, "No buffer\n"))
222 return;
223
224 Mdl = IoAllocateMdl(Page, PAGE_SIZE, FALSE, FALSE, NULL);
225 ok(Mdl != NULL, "IoAllocateMdl failed\n");
226 if (skip(Mdl != NULL, "No MDL\n"))
227 return;
228
229 ok((Mdl->MdlFlags & MDL_PAGES_LOCKED) == 0, "MDL locked\n");
230 ok((Mdl->MdlFlags & MDL_SOURCE_IS_NONPAGED_POOL) == 0, "MDL from non paged\n");
231
232 MmBuildMdlForNonPagedPool(Mdl);
233 ok((Mdl->MdlFlags & MDL_PAGES_LOCKED) == 0, "MDL locked\n");
234 ok((Mdl->MdlFlags & MDL_SOURCE_IS_NONPAGED_POOL) != 0, "MDL from paged\n");
235
236 IoFreeMdl(Mdl);
237 ExFreePoolWithTag(Page, 'Test');
238 }
239
START_TEST(MmMdl)240 START_TEST(MmMdl)
241 {
242 TestMmAllocatePagesForMdl();
243 TestMmBuildMdlForNonPagedPool();
244 }
245