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