Author: arty
Date: Fri Jun  1 09:01:41 2012
New Revision: 56682

URL: http://svn.reactos.org/svn/reactos?rev=56682&view=rev
Log:
[NTOSKRNL]
- Allow placement of a wait entry in virgin address space prior to mapping a 
page.
- Add a wait entry in the address space when paging in section view.
- Correct a problem that previously prevented us from evicting or querying 
pages that
  had been protected into PAGE_NOACCESS protection by adding a query for 
disabled
  mappings and handling disabled mappings in a few places (this may be 
controversial).

Modified:
    trunk/reactos/ntoskrnl/cache/section/newmm.h
    trunk/reactos/ntoskrnl/include/internal/mm.h
    trunk/reactos/ntoskrnl/mm/i386/page.c
    trunk/reactos/ntoskrnl/mm/section.c

Modified: trunk/reactos/ntoskrnl/cache/section/newmm.h
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/cache/section/newmm.h?rev=56682&r1=56681&r2=56682&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/cache/section/newmm.h [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/cache/section/newmm.h [iso-8859-1] Fri Jun  1 
09:01:41 2012
@@ -4,7 +4,6 @@
 
 /* TYPES *********************************************************************/
 
-#define MM_WAIT_ENTRY            0x7ffffc00
 #define PFN_FROM_SSE(E)          ((PFN_NUMBER)((E) >> PAGE_SHIFT))
 #define IS_SWAP_FROM_SSE(E)      ((E) & 0x00000001)
 #define MM_IS_WAIT_PTE(E)        \

Modified: trunk/reactos/ntoskrnl/include/internal/mm.h
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/mm.h?rev=56682&r1=56681&r2=56682&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/include/internal/mm.h [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/include/internal/mm.h [iso-8859-1] Fri Jun  1 
09:01:41 2012
@@ -179,6 +179,10 @@
     (PAGE_WRITECOPY | \
     PAGE_EXECUTE_WRITECOPY)
 
+//
+// Wait entry for marking pages that are being serviced
+//
+#define MM_WAIT_ENTRY            0x7ffffc00
 
 #define InterlockedCompareExchangePte(PointerPte, Exchange, Comperand) \
     InterlockedCompareExchange((PLONG)(PointerPte), Exchange, Comperand)
@@ -1263,6 +1267,13 @@
     PVOID Address
 );
 
+BOOLEAN
+NTAPI
+MmIsDisabledPage(
+    struct _EPROCESS* Process,
+    PVOID Address
+);
+
 VOID
 NTAPI
 MmInitGlobalKernelPageDirectory(VOID);

Modified: trunk/reactos/ntoskrnl/mm/i386/page.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/i386/page.c?rev=56682&r1=56681&r2=56682&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/mm/i386/page.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/i386/page.c [iso-8859-1] Fri Jun  1 09:01:41 2012
@@ -467,7 +467,9 @@
      */
     Pte = InterlockedExchangePte(Pt, 0);
 
-    WasValid = (Pte & PA_PRESENT);
+    /* We count a mapping as valid if it's a present page, or it's a nonzero 
pfn with
+     * the swap bit unset, indicating a valid page protected to PAGE_NOACCESS. 
*/
+    WasValid = (Pte & PA_PRESENT) || ((Pte >> PAGE_SHIFT) && !(Pte & 0x800));
     if (WasValid)
     {
         /* Flush the TLB since we transitioned this PTE
@@ -702,6 +704,14 @@
 
 BOOLEAN
 NTAPI
+MmIsDisabledPage(PEPROCESS Process, PVOID Address)
+{
+    ULONG_PTR Entry = MmGetPageEntryForProcess(Process, Address);
+    return !(Entry & PA_PRESENT) && !(Entry & 0x800) && (Entry >> PAGE_SHIFT);
+}
+
+BOOLEAN
+NTAPI
 MmIsPageSwapEntry(PEPROCESS Process, PVOID Address)
 {
     ULONG Entry;
@@ -738,12 +748,17 @@
     if (Pt == NULL)
     {
         /* Nobody should page out an address that hasn't even been mapped */
-        KeBugCheck(MEMORY_MANAGEMENT);
+        /* But we might place a wait entry first, requiring the page table */
+        if (SwapEntry != MM_WAIT_ENTRY)
+        {
+            KeBugCheck(MEMORY_MANAGEMENT);
+        }
+        Pt = MmGetPageTableForProcess(Process, Address, TRUE);
     }
     Pte = InterlockedExchangePte(Pt, SwapEntry << 1);
     if (Pte != 0)
     {
-        KeBugCheck(MEMORY_MANAGEMENT);
+        KeBugCheckEx(MEMORY_MANAGEMENT, SwapEntry, (ULONG_PTR)Process, 
(ULONG_PTR)Address, 0);
     }
 
        if (Address < MmSystemRangeStart)
@@ -975,7 +990,8 @@
     }
     Pte = InterlockedExchangePte(Pt, PAGE_MASK(*Pt) | Attributes | (*Pt & 
(PA_ACCESSED|PA_DIRTY)));
 
-    if (!(Pte & PA_PRESENT))
+    // We should be able to bring a page back from PAGE_NOACCESS
+    if ((Pte & 0x800) || !(Pte >> PAGE_SHIFT))
     {
         DPRINT1("Invalid Pte %lx\n", Pte);
         KeBugCheck(MEMORY_MANAGEMENT);

Modified: trunk/reactos/ntoskrnl/mm/section.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/section.c?rev=56682&r1=56681&r2=56682&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/mm/section.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/section.c [iso-8859-1] Fri Jun  1 09:01:41 2012
@@ -1223,6 +1223,11 @@
       return(STATUS_SUCCESS);
    }
 
+   if (MmIsDisabledPage(Process, Address))
+   {
+       return(STATUS_ACCESS_VIOLATION);
+   }
+
    /*
     * Check for the virtual memory area being deleted.
     */
@@ -1438,6 +1443,8 @@
 
    if (Entry == 0)
    {
+      SWAPENTRY FakeSwapEntry;
+
       /*
        * If the entry is zero (and it can't change because we have
        * locked the segment) then we need to load the page.
@@ -1448,6 +1455,7 @@
        */
       MmSetPageEntrySectionSegment(Segment, &Offset, 
MAKE_SWAP_SSE(MM_WAIT_ENTRY));
       MmUnlockSectionSegment(Segment);
+      MmCreatePageFileMapping(Process, PAddress, MM_WAIT_ENTRY);
       MmUnlockAddressSpace(AddressSpace);
 
       if ((Segment->Flags & MM_PAGEFILE_SEGMENT) ||
@@ -1496,6 +1504,9 @@
       MmSetPageEntrySectionSegment(Segment, &Offset, Entry);
       MmUnlockSectionSegment(Segment);
 
+      MmDeletePageFileMapping(Process, PAddress, &FakeSwapEntry);
+      DPRINT("CreateVirtualMapping Page %x Process %p PAddress %p Attributes 
%x\n", 
+              Page, Process, PAddress, Attributes);
       Status = MmCreateVirtualMapping(Process,
                                       PAddress,
                                       Attributes,
@@ -1506,6 +1517,7 @@
          DPRINT1("Unable to create virtual mapping\n");
           KeBugCheck(MEMORY_MANAGEMENT);
       }
+      ASSERT(MmIsPagePresent(Process, PAddress));
       MmInsertRmap(Page, Process, Address);
 
       MiSetPageEvent(Process, Address);
@@ -2441,7 +2453,7 @@
             }
          }
 
-         if (MmIsPagePresent(Process, Address))
+         if (MmIsPagePresent(Process, Address) || MmIsDisabledPage(Process, 
Address))
          {
             MmSetPageProtect(Process, Address,
                              Protect);


Reply via email to