From 62d6fa7706bd5b00b1aec2a99a10065a0558e84b Mon Sep 17 00:00:00 2001 From: Thomas Faber Date: Thu, 10 Sep 2015 09:58:02 +0000 Subject: [PATCH] [KMTESTS:MM] - Add a test for MmAllocateMappingAddress/MmMapLockedPagesWithReservedMapping CORE-10147 svn path=/trunk/; revision=69168 --- rostests/kmtests/CMakeLists.txt | 1 + rostests/kmtests/kmtest_drv/testlist.c | 2 + rostests/kmtests/ntos_mm/MmReservedMapping.c | 228 +++++++++++++++++++ 3 files changed, 231 insertions(+) create mode 100644 rostests/kmtests/ntos_mm/MmReservedMapping.c diff --git a/rostests/kmtests/CMakeLists.txt b/rostests/kmtests/CMakeLists.txt index 128933e8d08..b42390828a5 100644 --- a/rostests/kmtests/CMakeLists.txt +++ b/rostests/kmtests/CMakeLists.txt @@ -65,6 +65,7 @@ list(APPEND KMTEST_DRV_SOURCE ntos_ke/KeSpinLock.c ntos_ke/KeTimer.c ntos_mm/MmMdl.c + ntos_mm/MmReservedMapping.c ntos_mm/MmSection.c ntos_mm/ZwAllocateVirtualMemory.c ntos_mm/ZwCreateSection.c diff --git a/rostests/kmtests/kmtest_drv/testlist.c b/rostests/kmtests/kmtest_drv/testlist.c index 23fc3fb9a25..415df0e7185 100644 --- a/rostests/kmtests/kmtest_drv/testlist.c +++ b/rostests/kmtests/kmtest_drv/testlist.c @@ -41,6 +41,7 @@ KMT_TESTFUNC Test_KeTimer; KMT_TESTFUNC Test_KernelType; KMT_TESTFUNC Test_MmMdl; KMT_TESTFUNC Test_MmSection; +KMT_TESTFUNC Test_MmReservedMapping; KMT_TESTFUNC Test_NpfsConnect; KMT_TESTFUNC Test_NpfsCreate; KMT_TESTFUNC Test_NpfsFileInfo; @@ -101,6 +102,7 @@ const KMT_TEST TestList[] = { "-KernelType", Test_KernelType }, { "MmMdl", Test_MmMdl }, { "MmSection", Test_MmSection }, + { "MmReservedMapping", Test_MmReservedMapping }, { "NpfsConnect", Test_NpfsConnect }, { "NpfsCreate", Test_NpfsCreate }, { "NpfsFileInfo", Test_NpfsFileInfo }, diff --git a/rostests/kmtests/ntos_mm/MmReservedMapping.c b/rostests/kmtests/ntos_mm/MmReservedMapping.c new file mode 100644 index 00000000000..2e437f23930 --- /dev/null +++ b/rostests/kmtests/ntos_mm/MmReservedMapping.c @@ -0,0 +1,228 @@ +/* + * PROJECT: ReactOS kernel-mode tests + * LICENSE: LGPLv2.1+ - See COPYING.LIB in the top level directory + * PURPOSE: Kernel-Mode Test Suite Reserved Mapping test + * PROGRAMMER: Thomas Faber + */ + +#include + +#ifdef _M_IX86 + +#define PTE_BASE 0xC0000000 +#define MiAddressToPte(x) \ + ((PMMPTE)(((((ULONG)(x)) >> 12) << 2) + PTE_BASE)) +#define MiPteToAddress(_Pte) ((PVOID)((ULONG)(_Pte) << 10)) + +#elif defined(_M_AMD64) + +#define PTI_SHIFT 12L +#define PTE_BASE 0xFFFFF68000000000ULL +PMMPTE +FORCEINLINE +_MiAddressToPte(PVOID Address) +{ + ULONG64 Offset = (ULONG64)Address >> (PTI_SHIFT - 3); + Offset &= 0xFFFFFFFFFULL << 3; + return (PMMPTE)(PTE_BASE + Offset); +} +#define MiAddressToPte(x) _MiAddressToPte((PVOID)(x)) + +#endif + +static +BOOLEAN +ValidateMapping( + _In_ PVOID BaseAddress, + _In_ ULONG TotalPtes, + _In_ ULONG ValidPtes, + _In_ PPFN_NUMBER Pfns) +{ + BOOLEAN Valid = TRUE; +#if defined(_M_IX86) || defined(_M_AMD64) + PMMPTE PointerPte; + ULONG i; + + PointerPte = MiAddressToPte(BaseAddress); + for (i = 0; i < ValidPtes; i++) + { + Valid = Valid && + ok(PointerPte[i].u.Hard.Valid == 1, + "[%lu] PTE %p is not valid\n", i, &PointerPte[i]); + + Valid = Valid && + ok(PointerPte[i].u.Hard.PageFrameNumber == Pfns[i], + "[%lu] PTE %p has PFN %Ix, expected %Ix\n", + i, &PointerPte[i], PointerPte[i].u.Hard.PageFrameNumber, Pfns[i]); + } + for (; i < TotalPtes; i++) + { + Valid = Valid && + ok_eq_hex(PointerPte[i].u.Long, 0UL); + } + Valid = Valid && + ok_eq_tag(PointerPte[-1].u.Long, 'MRmK' & ~1); + Valid = Valid && + ok_eq_ulong(PointerPte[-2].u.Long, (TotalPtes + 2) * 2); +#endif + + return Valid; +} + +static +VOID +TestMap( + _In_ PVOID Mapping) +{ + PMDL Mdl; + PHYSICAL_ADDRESS ZeroPhysical; + PHYSICAL_ADDRESS MaxPhysical; + PVOID BaseAddress; + PPFN_NUMBER MdlPages; + ULONG i; + + ZeroPhysical.QuadPart = 0; + MaxPhysical.QuadPart = 0xffffffffffffffffLL; + + /* Create a one-page MDL and map it */ + Mdl = MmAllocatePagesForMdlEx(ZeroPhysical, + MaxPhysical, + ZeroPhysical, + PAGE_SIZE, + MmCached, + 0); + if (skip(Mdl != NULL, "No MDL\n")) + { + return; + } + + MdlPages = (PVOID)(Mdl + 1); + + BaseAddress = MmMapLockedPagesWithReservedMapping(Mapping, + 'MRmK', + Mdl, + MmCached); + if (BaseAddress) + { + ok_eq_pointer(BaseAddress, Mapping); + + ok_bool_true(ValidateMapping(BaseAddress, 10, 1, MdlPages), + "ValidateMapping returned"); + + KmtStartSeh() + *(volatile ULONG *)BaseAddress = 0x01234567; + KmtEndSeh(STATUS_SUCCESS); + + MmUnmapReservedMapping(BaseAddress, + 'MRmK', + Mdl); + + ok_bool_true(ValidateMapping(Mapping, 10, 0, NULL), + "ValidateMapping returned"); + } + + MmFreePagesFromMdl(Mdl); + + /* Map all pages */ + Mdl = MmAllocatePagesForMdlEx(ZeroPhysical, + MaxPhysical, + ZeroPhysical, + 10 * PAGE_SIZE, + MmCached, + 0); + if (skip(Mdl != NULL, "No MDL\n")) + { + return; + } + + MdlPages = (PVOID)(Mdl + 1); + + BaseAddress = MmMapLockedPagesWithReservedMapping(Mapping, + 'MRmK', + Mdl, + MmCached); + if (BaseAddress) + { + ok_eq_pointer(BaseAddress, Mapping); + + ok_bool_true(ValidateMapping(BaseAddress, 10, 10, MdlPages), + "ValidateMapping returned"); + + for (i = 0; i < 10; i++) + { + KmtStartSeh() + *((volatile ULONG *)BaseAddress + i * PAGE_SIZE / sizeof(ULONG)) = 0x01234567; + KmtEndSeh(STATUS_SUCCESS); + } + + MmUnmapReservedMapping(BaseAddress, + 'MRmK', + Mdl); + + ok_bool_true(ValidateMapping(Mapping, 10, 0, NULL), + "ValidateMapping returned"); + } + + MmFreePagesFromMdl(Mdl); + + /* Try to map more pages than we reserved */ + Mdl = MmAllocatePagesForMdlEx(ZeroPhysical, + MaxPhysical, + ZeroPhysical, + 11 * PAGE_SIZE, + MmCached, + 0); + if (skip(Mdl != NULL, "No MDL\n")) + { + return; + } + + BaseAddress = MmMapLockedPagesWithReservedMapping(Mapping, + 'MRmK', + Mdl, + MmCached); + ok_eq_pointer(BaseAddress, NULL); + if (BaseAddress) + { + MmUnmapReservedMapping(BaseAddress, + 'MRmK', + Mdl); + } + + MmFreePagesFromMdl(Mdl); +} + +START_TEST(MmReservedMapping) +{ + PVOID Mapping; + + /* one byte - single page */ + Mapping = MmAllocateMappingAddress(1, 'MRmK'); + ok(Mapping != NULL, "MmAllocateMappingAddress failed\n"); + if (!skip(Mapping != NULL, "No mapping\n")) + { + ok_bool_true(ValidateMapping(Mapping, 1, 0, NULL), + "ValidateMapping returned"); + + MmFreeMappingAddress(Mapping, 'MRmK'); + } + + /* 10 pages */ + Mapping = MmAllocateMappingAddress(10 * PAGE_SIZE, 'MRmK' & ~1); + ok(Mapping != NULL, "MmAllocateMappingAddress failed\n"); + if (!skip(Mapping != NULL, "No mapping\n")) + { + ok_bool_true(ValidateMapping(Mapping, 10, 0, NULL), + "ValidateMapping returned"); + + /* PAGE_FAULT_IN_NONPAGED_AREA can't be caught with SEH */ + if (0) + { + (void)*(volatile UCHAR *)Mapping; + } + + TestMap(Mapping); + + MmFreeMappingAddress(Mapping, 'MRmK'); + } +}