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 } 313