[NTOSKRNL]
authorTimo Kreuzer <timo.kreuzer@reactos.org>
Wed, 27 Nov 2013 00:04:26 +0000 (00:04 +0000)
committerTimo Kreuzer <timo.kreuzer@reactos.org>
Wed, 27 Nov 2013 00:04:26 +0000 (00:04 +0000)
- Get rid of MmZeroPte and instead implement MI_ERASE_PTE. Use this and only this to make a PTE zero. The other functions will not allow to do this.
- Add MI_UPDATE_VALID_PTE to update a valid PTE with another valid PTE
- Add 2 additional protection mask constants: MM_PROTECT_ACCESS for the lower 3 bits and MM_PROTECT_SPECIAL for the higher 2 bits. Make use of the latter when dealing with guard pages and caching.
- Deduplicate some code in MmArmAccessFault
- Move code in MiDeleteSystemPageableVm to where it belongs (it was in the wrong else case!)
- Wse MiQueryPageTableReferences instead of manipulating MmWorkingSetList->UsedPageTableEntries

svn path=/trunk/; revision=61110

reactos/ntoskrnl/mm/ARM3/miarm.h
reactos/ntoskrnl/mm/ARM3/pagfault.c
reactos/ntoskrnl/mm/ARM3/section.c
reactos/ntoskrnl/mm/ARM3/virtual.c
reactos/ntoskrnl/mm/balance.c

index 428e0e3..0ec38ed 100644 (file)
@@ -107,6 +107,7 @@ C_ASSERT(SYSTEM_PD_SIZE == PAGE_SIZE);
 #define MM_WRITECOPY           5
 #define MM_EXECUTE_READWRITE   6
 #define MM_EXECUTE_WRITECOPY   7
+#define MM_PROTECT_ACCESS      7
 
 //
 // These are flags on top of the actual protection mask
@@ -114,6 +115,7 @@ C_ASSERT(SYSTEM_PD_SIZE == PAGE_SIZE);
 #define MM_NOCACHE            0x08
 #define MM_GUARDPAGE          0x10
 #define MM_WRITECOMBINE       0x18
+#define MM_PROTECT_SPECIAL    0x18
 
 //
 // These are special cases
@@ -588,7 +590,6 @@ typedef struct _MM_SESSION_SPACE
     LONG ImageLoadingCount;
 } MM_SESSION_SPACE, *PMM_SESSION_SPACE;
 
-static const MMPTE MmZeroPte = {{0}};
 extern PMM_SESSION_SPACE MmSessionSpace;
 extern MMPTE HyperTemplatePte;
 extern MMPDE ValidKernelPde;
@@ -1002,6 +1003,21 @@ MI_WRITE_VALID_PTE(IN PMMPTE PointerPte,
     *PointerPte = TempPte;
 }
 
+//
+// Updates a valid PTE
+//
+VOID
+FORCEINLINE
+MI_UPDATE_VALID_PTE(IN PMMPTE PointerPte,
+                   IN MMPTE TempPte)
+{
+    /* Write the valid PTE */
+    ASSERT(PointerPte->u.Hard.Valid == 1);
+    ASSERT(TempPte.u.Hard.Valid == 1);
+    ASSERT(PointerPte->u.Hard.PageFrameNumber == TempPte.u.Hard.PageFrameNumber);
+    *PointerPte = TempPte;
+}
+
 //
 // Writes an invalid PTE
 //
@@ -1012,9 +1028,22 @@ MI_WRITE_INVALID_PTE(IN PMMPTE PointerPte,
 {
     /* Write the invalid PTE */
     ASSERT(InvalidPte.u.Hard.Valid == 0);
+    ASSERT(InvalidPte.u.Long != 0);
     *PointerPte = InvalidPte;
 }
 
+//
+// Erase the PTE completely
+//
+VOID
+FORCEINLINE
+MI_ERASE_PTE(IN PMMPTE PointerPte)
+{
+    /* Zero out the PTE */
+    ASSERT(PointerPte->u.Long != 0);
+    PointerPte->u.Long = 0;
+}
+
 //
 // Writes a valid PDE
 //
@@ -1039,6 +1068,7 @@ MI_WRITE_INVALID_PDE(IN PMMPDE PointerPde,
 {
     /* Write the invalid PDE */
     ASSERT(InvalidPde.u.Hard.Valid == 0);
+    ASSERT(InvalidPde.u.Long != 0);
     *PointerPde = InvalidPde;
 }
 
index 5c69317..d8516bf 100644 (file)
@@ -122,7 +122,7 @@ MiIsAccessAllowed(
     #define _BYTE_MASK(Bit0, Bit1, Bit2, Bit3, Bit4, Bit5, Bit6, Bit7) \
         (Bit0) | ((Bit1) << 1) | ((Bit2) << 2) | ((Bit3) << 3) | \
         ((Bit4) << 4) | ((Bit5) << 5) | ((Bit6) << 6) | ((Bit7) << 7)
-    static const UCHAR MiAccessAllowedMask[2][2] =
+    static const UCHAR AccessAllowedMask[2][2] =
     {
         {   // Protect 0  1  2  3  4  5  6  7
             _BYTE_MASK(0, 1, 1, 1, 1, 1, 1, 1), // READ
@@ -134,11 +134,11 @@ MiIsAccessAllowed(
         }
     };
 
-    /* We want only the low 3 bits */
-    ProtectionMask &= 7;
+    /* We want only the lower access bits */
+    ProtectionMask &= MM_PROTECT_ACCESS;
 
     /* Look it up in the table */
-    return (MiAccessAllowedMask[Write != 0][Execute != 0] >> ProtectionMask) & 1;
+    return (AccessAllowedMask[Write != 0][Execute != 0] >> ProtectionMask) & 1;
 }
 
 NTSTATUS
@@ -187,7 +187,7 @@ MiAccessCheck(IN PMMPTE PointerPte,
     }
 
     /* Check if this is a guard page */
-    if (ProtectionMask & MM_GUARDPAGE)
+    if ((ProtectionMask & MM_PROTECT_SPECIAL) == MM_GUARDPAGE)
     {
         NT_ASSERT(ProtectionMask != MM_DECOMMIT);
 
@@ -765,8 +765,8 @@ MiCompleteProtoPteFault(IN BOOLEAN StoreInstruction,
     /* Release the PFN lock */
     KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
 
-    /* Remove caching bits */
-    Protection &= ~(MM_NOCACHE | MM_NOACCESS);
+    /* Remove special/caching bits */
+    Protection &= ~MM_PROTECT_SPECIAL;
 
     /* Setup caching */
     if (Pfn1->u3.e1.CacheAttribute == MiWriteCombined)
@@ -820,7 +820,8 @@ MiResolveTransitionFault(IN PVOID FaultingAddress,
     PMMPFN Pfn1;
     MMPTE TempPte;
     PMMPTE PointerToPteForProtoPage;
-    DPRINT1("Transition fault on 0x%p with PTE 0x%p in process %s\n", FaultingAddress, PointerPte, CurrentProcess->ImageFileName);
+    DPRINT1("Transition fault on 0x%p with PTE 0x%p in process %s\n",
+            FaultingAddress, PointerPte, CurrentProcess->ImageFileName);
 
     /* Windowss does this check */
     ASSERT(*InPageBlock == NULL);
@@ -1453,37 +1454,25 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction,
         /* Bail out, if the fault came from user mode */
         if (Mode == UserMode) return STATUS_ACCESS_VIOLATION;
 
-#if (_MI_PAGING_LEVELS == 4)
-        /* AMD64 system, check if PXE is invalid */
-        if (PointerPxe->u.Hard.Valid == 0)
-        {
-            KeBugCheckEx(PAGE_FAULT_IN_NONPAGED_AREA,
-                         (ULONG_PTR)Address,
-                         StoreInstruction,
-                         (ULONG_PTR)TrapInformation,
-                         7);
-        }
-#endif
-#if (_MI_PAGING_LEVELS == 4)
-        /* PAE/AMD64 system, check if PPE is invalid */
-        if (PointerPpe->u.Hard.Valid == 0)
-        {
-            KeBugCheckEx(PAGE_FAULT_IN_NONPAGED_AREA,
-                         (ULONG_PTR)Address,
-                         StoreInstruction,
-                         (ULONG_PTR)TrapInformation,
-                         5);
-        }
-#endif
 #if (_MI_PAGING_LEVELS == 2)
         if (MI_IS_SYSTEM_PAGE_TABLE_ADDRESS(Address)) MiSynchronizeSystemPde((PMMPDE)PointerPte);
         MiCheckPdeForPagedPool(Address);
 #endif
 
-        /* Check if the PDE is invalid */
-        if (PointerPde->u.Hard.Valid == 0)
+        /* Check if the higher page table entries are invalid */
+        if (
+#if (_MI_PAGING_LEVELS == 4)
+            /* AMD64 system, check if PXE is invalid */
+            (PointerPxe->u.Hard.Valid == 0) ||
+#endif
+#if (_MI_PAGING_LEVELS >= 3)
+            /* PAE/AMD64 system, check if PPE is invalid */
+            (PointerPpe->u.Hard.Valid == 0) ||
+#endif
+            /* Always check if the PDE is valid */
+            (PointerPde->u.Hard.Valid == 0))
         {
-            /* PDE (still) not valid, kill the system */
+            /* PXE/PPE/PDE (still) not valid, kill the system */
             KeBugCheckEx(PAGE_FAULT_IN_NONPAGED_AREA,
                          (ULONG_PTR)Address,
                          StoreInstruction,
@@ -1894,7 +1883,7 @@ UserFault:
         }
 
         /* Is this a guard page? */
-        if (ProtectionCode & MM_GUARDPAGE)
+        if ((ProtectionCode & MM_PROTECT_SPECIAL) == MM_GUARDPAGE)
         {
             /* The VAD protection cannot be MM_DECOMMIT! */
             NT_ASSERT(ProtectionCode != MM_DECOMMIT);
index 403376d..ef79a3c 100644 (file)
@@ -198,7 +198,7 @@ MiMakeProtectionMask(IN ULONG Protect)
         }
 
         /* This actually turns on guard page in this scenario! */
-        ProtectMask |= MM_GUARDPAGE;
+        ProtectMask |= MM_DECOMMIT;
     }
 
     /* Check for nocache option */
@@ -1914,10 +1914,7 @@ MiFlushTbAndCapture(IN PMMVAD FoundVad,
     //
     // Write the new PTE, making sure we are only changing the bits
     //
-    ASSERT(PointerPte->u.Hard.Valid == 1);
-    ASSERT(TempPte.u.Hard.Valid == 1);
-    ASSERT(PointerPte->u.Hard.PageFrameNumber == TempPte.u.Hard.PageFrameNumber);
-    *PointerPte = TempPte;
+    MI_UPDATE_VALID_PTE(PointerPte, TempPte);
 
     //
     // Flush the TLB
index d8d3ead..6afcfc8 100644 (file)
@@ -350,26 +350,26 @@ MiDeleteSystemPageableVm(IN PMMPTE PointerPte,
                 KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
 
                 /* Destroy the PTE */
-                MI_WRITE_INVALID_PTE(PointerPte, MmZeroPte);
+                MI_ERASE_PTE(PointerPte);
+            }
+            else
+            {
+                /*
+                 * The only other ARM3 possibility is a demand zero page, which would
+                 * mean freeing some of the paged pool pages that haven't even been
+                 * touched yet, as part of a larger allocation.
+                 *
+                 * Right now, we shouldn't expect any page file information in the PTE
+                 */
+                ASSERT(PointerPte->u.Soft.PageFileHigh == 0);
+
+                /* Destroy the PTE */
+                MI_ERASE_PTE(PointerPte);
             }
 
             /* Actual legitimate pages */
             ActualPages++;
         }
-        else
-        {
-            /*
-             * The only other ARM3 possibility is a demand zero page, which would
-             * mean freeing some of the paged pool pages that haven't even been
-             * touched yet, as part of a larger allocation.
-             *
-             * Right now, we shouldn't expect any page file information in the PTE
-             */
-            ASSERT(PointerPte->u.Soft.PageFileHigh == 0);
-
-            /* Destroy the PTE */
-            MI_WRITE_INVALID_PTE(PointerPte, MmZeroPte);
-        }
 
         /* Keep going */
         PointerPte++;
@@ -486,7 +486,7 @@ MiDeletePte(IN PMMPTE PointerPte,
     }
 
     /* Destroy the PTE and flush the TLB */
-    MI_WRITE_INVALID_PTE(PointerPte, MmZeroPte);
+    MI_ERASE_PTE(PointerPte);
     KeFlushCurrentTb();
 }
 
@@ -618,7 +618,7 @@ MiDeleteVirtualAddresses(IN ULONG_PTR Va,
                         (TempPte.u.Soft.Prototype == 1))
                     {
                         /* Just nuke it */
-                        MI_WRITE_INVALID_PTE(PointerPte, MmZeroPte);
+                        MI_ERASE_PTE(PointerPte);
                     }
                     else
                     {
@@ -632,7 +632,7 @@ MiDeleteVirtualAddresses(IN ULONG_PTR Va,
                 else
                 {
                     /* The PTE was never mapped, just nuke it here */
-                    MI_WRITE_INVALID_PTE(PointerPte, MmZeroPte);
+                    MI_ERASE_PTE(PointerPte);
                 }
             }
 
index 85fec71..804c674 100644 (file)
@@ -394,7 +394,7 @@ MiBalancerThread(PVOID Unused)
                  Address < (ULONG_PTR)MM_HIGHEST_VAD_ADDRESS;
                  Address += (PAGE_SIZE * PTE_COUNT))
             {
-                if (MmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)] == 0)
+                if (MiQueryPageTableReferences((PVOID)Address) == 0)
                 {
                     pointerPde = MiAddressToPde(Address);
                     if (pointerPde->u.Hard.Valid)