mirror of
https://github.com/reactos/reactos.git
synced 2025-05-18 16:51:18 +00:00
[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 svn path=/trunk/; revision=61110
This commit is contained in:
parent
5ab8592b44
commit
4019985115
5 changed files with 75 additions and 59 deletions
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue