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 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 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 240 START_TEST(MmMdl) 241 { 242 TestMmAllocatePagesForMdl(); 243 TestMmBuildMdlForNonPagedPool(); 244 } 245