https://git.reactos.org/?p=reactos.git;a=commitdiff;h=e4047d1521cd75ffded656aef221d7eb8285a04e

commit e4047d1521cd75ffded656aef221d7eb8285a04e
Author:     Jérôme Gardou <[email protected]>
AuthorDate: Tue Oct 27 17:37:38 2020 +0100
Commit:     Jérôme Gardou <[email protected]>
CommitDate: Wed Feb 3 09:41:22 2021 +0100

    [NTOS/MM] Introduce MmArePagesResident and MmMakePagesResident
---
 ntoskrnl/include/internal/mm.h |  14 +++++
 ntoskrnl/mm/section.c          | 140 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 154 insertions(+)

diff --git a/ntoskrnl/include/internal/mm.h b/ntoskrnl/include/internal/mm.h
index 662f49c9bd7..be8b0acc4b0 100644
--- a/ntoskrnl/include/internal/mm.h
+++ b/ntoskrnl/include/internal/mm.h
@@ -1323,6 +1323,20 @@ MmMapViewInSystemSpaceEx (
     _Inout_ PLARGE_INTEGER SectionOffset
     );
 
+BOOLEAN
+NTAPI
+MmArePagesResident(
+    _In_ PEPROCESS Process,
+    _In_ PVOID BaseAddress,
+    _In_ ULONG Length);
+
+NTSTATUS
+NTAPI
+MmMakePagesResident(
+    _In_ PEPROCESS Process,
+    _In_ PVOID Address,
+    _In_ ULONG Length);
+
 /* sysldr.c ******************************************************************/
 
 VOID
diff --git a/ntoskrnl/mm/section.c b/ntoskrnl/mm/section.c
index fc2c1a3e904..4d29f5a9ff4 100644
--- a/ntoskrnl/mm/section.c
+++ b/ntoskrnl/mm/section.c
@@ -5076,4 +5076,144 @@ MmCreateSection (OUT PVOID  * Section,
     return Status;
 }
 
+BOOLEAN
+NTAPI
+MmArePagesResident(
+    _In_ PEPROCESS Process,
+    _In_ PVOID Address,
+    _In_ ULONG Length)
+{
+    PMEMORY_AREA MemoryArea;
+    BOOLEAN Ret = TRUE;
+    PMM_SECTION_SEGMENT Segment;
+    LARGE_INTEGER SegmentOffset, RangeEnd;
+
+    MmLockAddressSpace(&Process->Vm);
+
+    MemoryArea = MmLocateMemoryAreaByAddress(&Process->Vm, Address);
+    if (MemoryArea == NULL)
+    {
+        MmUnlockAddressSpace(&Process->Vm);
+        return FALSE;
+    }
+
+    /* Only supported in old Mm for now */
+    ASSERT(MemoryArea->Type == MEMORY_AREA_SECTION_VIEW);
+    /* For file mappings */
+    ASSERT(MemoryArea->VadNode.u.VadFlags.VadType != VadImageMap);
+
+    Segment = MemoryArea->SectionData.Segment;
+    MmLockSectionSegment(Segment);
+
+    SegmentOffset.QuadPart = PAGE_ROUND_DOWN(Address) - 
MA_GetStartingAddress(MemoryArea)
+            + MemoryArea->SectionData.ViewOffset.QuadPart;
+    RangeEnd.QuadPart = PAGE_ROUND_UP((ULONG_PTR)Address + Length) - 
MA_GetStartingAddress(MemoryArea)
+            + MemoryArea->SectionData.ViewOffset.QuadPart;
+
+    while (SegmentOffset.QuadPart < RangeEnd.QuadPart)
+    {
+        ULONG_PTR Entry = MmGetPageEntrySectionSegment(Segment, 
&SegmentOffset);
+        if ((Entry == 0) || IS_SWAP_FROM_SSE(Entry))
+        {
+            Ret = FALSE;
+            break;
+        }
+        SegmentOffset.QuadPart += PAGE_SIZE;
+    }
+
+    MmUnlockSectionSegment(Segment);
+
+    MmUnlockAddressSpace(&Process->Vm);
+    return Ret;
+}
+
+NTSTATUS
+NTAPI
+MmMakePagesResident(
+    _In_ PEPROCESS Process,
+    _In_ PVOID Address,
+    _In_ ULONG Length)
+{
+    PMEMORY_AREA MemoryArea;
+    PMM_SECTION_SEGMENT Segment;
+    LARGE_INTEGER SegmentOffset, RangeEnd;
+
+    MmLockAddressSpace(&Process->Vm);
+
+    MemoryArea = MmLocateMemoryAreaByAddress(&Process->Vm, Address);
+    if (MemoryArea == NULL)
+    {
+        MmUnlockAddressSpace(&Process->Vm);
+        return FALSE;
+    }
+
+    /* Only supported in old Mm for now */
+    ASSERT(MemoryArea->Type == MEMORY_AREA_SECTION_VIEW);
+    /* For file mappings */
+    ASSERT(MemoryArea->VadNode.u.VadFlags.VadType != VadImageMap);
+
+    Segment = MemoryArea->SectionData.Segment;
+    MmLockSectionSegment(Segment);
+
+    SegmentOffset.QuadPart = PAGE_ROUND_DOWN(Address) - 
MA_GetStartingAddress(MemoryArea)
+            + MemoryArea->SectionData.ViewOffset.QuadPart;
+    RangeEnd.QuadPart = PAGE_ROUND_UP((ULONG_PTR)Address + Length) - 
MA_GetStartingAddress(MemoryArea)
+            + MemoryArea->SectionData.ViewOffset.QuadPart;
+
+    while (SegmentOffset.QuadPart < RangeEnd.QuadPart)
+    {
+        ULONG_PTR Entry = MmGetPageEntrySectionSegment(Segment, 
&SegmentOffset);
+
+        /* Let any pending read proceed */
+        while (MM_IS_WAIT_PTE(Entry))
+        {
+            MmUnlockSectionSegment(Segment);
+            MmUnlockAddressSpace(&Process->Vm);
+            MiWaitForPageEvent(NULL, NULL);
+            MmLockAddressSpace(&Process->Vm);
+            MmLockSectionSegment(Segment);
+            Entry = MmGetPageEntrySectionSegment(Segment, &SegmentOffset);
+        }
+
+        /* We are called from Cc, this can't be backed by the page files */
+        ASSERT(!IS_SWAP_FROM_SSE(Entry));
+
+        /* At this point, there may be a valid page there */
+        if (Entry == 0)
+        {
+            PFN_NUMBER Page;
+            NTSTATUS Status;
+
+            /*
+             * Release all our locks and read in the page from disk
+             */
+            MmSetPageEntrySectionSegment(Segment, &SegmentOffset, 
MAKE_SWAP_SSE(MM_WAIT_ENTRY));
+            MmUnlockSectionSegment(Segment);
+            MmUnlockAddressSpace(&Process->Vm);
+
+            /* FIXME: Read the whole range at once instead of one page at a 
time */
+            Status = MiReadPage(MemoryArea, SegmentOffset.QuadPart, &Page);
+            if (!NT_SUCCESS(Status))
+            {
+                /* Reset the Segment entry and fail */
+                MmLockSectionSegment(Segment);
+                MmSetPageEntrySectionSegment(Segment, &SegmentOffset, 0);
+                MmUnlockSectionSegment(Segment);
+                MiSetPageEvent(Process, Address);
+                return Status;
+            }
+
+            MmLockAddressSpace(&Process->Vm);
+            MmLockSectionSegment(Segment);
+            MmSetPageEntrySectionSegment(Segment, &SegmentOffset, 
MAKE_SSE(Page << PAGE_SHIFT, 1));
+        }
+        SegmentOffset.QuadPart += PAGE_SIZE;
+    }
+
+    MmUnlockSectionSegment(Segment);
+
+    MmUnlockAddressSpace(&Process->Vm);
+    return STATUS_SUCCESS;
+}
+
 /* EOF */

Reply via email to