Author: tkreuzer Date: Wed Nov 27 00:04:26 2013 New Revision: 61110
URL: http://svn.reactos.org/svn/reactos?rev=61110&view=rev Log: [NTOSKRNL] - 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
Modified: trunk/reactos/ntoskrnl/mm/ARM3/miarm.h trunk/reactos/ntoskrnl/mm/ARM3/pagfault.c trunk/reactos/ntoskrnl/mm/ARM3/section.c trunk/reactos/ntoskrnl/mm/ARM3/virtual.c trunk/reactos/ntoskrnl/mm/balance.c
Modified: trunk/reactos/ntoskrnl/mm/ARM3/miarm.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/miarm.h?re... ============================================================================== --- trunk/reactos/ntoskrnl/mm/ARM3/miarm.h [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/mm/ARM3/miarm.h [iso-8859-1] Wed Nov 27 00:04:26 2013 @@ -107,6 +107,7 @@ #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 @@ #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 @@ LONG ImageLoadingCount; } MM_SESSION_SPACE, *PMM_SESSION_SPACE;
-static const MMPTE MmZeroPte = {{0}}; extern PMM_SESSION_SPACE MmSessionSpace; extern MMPTE HyperTemplatePte; extern MMPDE ValidKernelPde; @@ -1003,6 +1004,21 @@ }
// +// 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 // FORCEINLINE @@ -1012,7 +1028,20 @@ { /* 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; }
// @@ -1039,6 +1068,7 @@ { /* Write the invalid PDE */ ASSERT(InvalidPde.u.Hard.Valid == 0); + ASSERT(InvalidPde.u.Long != 0); *PointerPde = InvalidPde; }
Modified: trunk/reactos/ntoskrnl/mm/ARM3/pagfault.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/pagfault.c... ============================================================================== --- trunk/reactos/ntoskrnl/mm/ARM3/pagfault.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/mm/ARM3/pagfault.c [iso-8859-1] Wed Nov 27 00:04:26 2013 @@ -122,7 +122,7 @@ #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 @@ } };
- /* 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 @@ }
/* 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 @@ /* 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 @@ 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 @@ /* 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) - { - /* PDE (still) not valid, kill the system */ + /* 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)) + { + /* PXE/PPE/PDE (still) not valid, kill the system */ KeBugCheckEx(PAGE_FAULT_IN_NONPAGED_AREA, (ULONG_PTR)Address, StoreInstruction, @@ -1894,7 +1883,7 @@ }
/* 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);
Modified: trunk/reactos/ntoskrnl/mm/ARM3/section.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/section.c?... ============================================================================== --- trunk/reactos/ntoskrnl/mm/ARM3/section.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/mm/ARM3/section.c [iso-8859-1] Wed Nov 27 00:04:26 2013 @@ -198,7 +198,7 @@ }
/* This actually turns on guard page in this scenario! */ - ProtectMask |= MM_GUARDPAGE; + ProtectMask |= MM_DECOMMIT; }
/* Check for nocache option */ @@ -1914,10 +1914,7 @@ // // 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
Modified: trunk/reactos/ntoskrnl/mm/ARM3/virtual.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/virtual.c?... ============================================================================== --- trunk/reactos/ntoskrnl/mm/ARM3/virtual.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/mm/ARM3/virtual.c [iso-8859-1] Wed Nov 27 00:04:26 2013 @@ -350,25 +350,25 @@ 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 */ @@ -486,7 +486,7 @@ }
/* Destroy the PTE and flush the TLB */ - MI_WRITE_INVALID_PTE(PointerPte, MmZeroPte); + MI_ERASE_PTE(PointerPte); KeFlushCurrentTb(); }
@@ -618,7 +618,7 @@ (TempPte.u.Soft.Prototype == 1)) { /* Just nuke it */ - MI_WRITE_INVALID_PTE(PointerPte, MmZeroPte); + MI_ERASE_PTE(PointerPte); } else { @@ -632,7 +632,7 @@ else { /* The PTE was never mapped, just nuke it here */ - MI_WRITE_INVALID_PTE(PointerPte, MmZeroPte); + MI_ERASE_PTE(PointerPte); } }
Modified: trunk/reactos/ntoskrnl/mm/balance.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/balance.c?rev=6... ============================================================================== --- trunk/reactos/ntoskrnl/mm/balance.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/mm/balance.c [iso-8859-1] Wed Nov 27 00:04:26 2013 @@ -394,7 +394,7 @@ 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)