[KMTESTS:MM]
authorThomas Faber <thomas.faber@reactos.org>
Thu, 10 Sep 2015 09:58:02 +0000 (09:58 +0000)
committerThomas Faber <thomas.faber@reactos.org>
Thu, 10 Sep 2015 09:58:02 +0000 (09:58 +0000)
- Add a test for MmAllocateMappingAddress/MmMapLockedPagesWithReservedMapping
CORE-10147

svn path=/trunk/; revision=69168

rostests/kmtests/CMakeLists.txt
rostests/kmtests/kmtest_drv/testlist.c
rostests/kmtests/ntos_mm/MmReservedMapping.c [new file with mode: 0644]

index 128933e..b423908 100644 (file)
@@ -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
index 23fc3fb..415df0e 100644 (file)
@@ -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 (file)
index 0000000..2e437f2
--- /dev/null
@@ -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 <thomas.faber@reactos.org>
+ */
+
+#include <kmt_test.h>
+
+#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');
+    }
+}