mirror of
https://github.com/reactos/reactos.git
synced 2025-08-03 22:46:17 +00:00
[NTOSKRNL]: Fix a stupid bug in MiProtectVirtualMemory which was causing empty PTEs whose protection was being set to remain zero PTEs, instead of demand-zero PTEs, but still acquire a page table reference. When they were later touched in the page fault code, and made into demand-zero PTEs, they'd get referenced again, thus Aleksey hacked away all the referencing code to work around this (causing PDEs to disappear...)
[NTOSKRNL]: Restore the page table reference counting mechanism, and put it in a macro to be cleaner. Also use macros for testing PD boundaries, instead of math-by-hand. svn path=/trunk/; revision=57229
This commit is contained in:
parent
5547667b67
commit
706b25f988
4 changed files with 54 additions and 34 deletions
|
@ -1619,6 +1619,41 @@ MiReferenceUnusedPageAndBumpLockCount(IN PMMPFN Pfn1)
|
|||
}
|
||||
}
|
||||
|
||||
FORCEINLINE
|
||||
VOID
|
||||
MiIncrementPageTableReferences(IN PVOID Address)
|
||||
{
|
||||
PUSHORT RefCount;
|
||||
|
||||
RefCount = &MmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)];
|
||||
|
||||
*RefCount += 1;
|
||||
ASSERT(*RefCount <= PTE_PER_PAGE);
|
||||
}
|
||||
|
||||
FORCEINLINE
|
||||
VOID
|
||||
MiDecrementPageTableReferences(IN PVOID Address)
|
||||
{
|
||||
PUSHORT RefCount;
|
||||
|
||||
RefCount = &MmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)];
|
||||
|
||||
*RefCount -= 1;
|
||||
ASSERT(*RefCount < PTE_PER_PAGE);
|
||||
}
|
||||
|
||||
FORCEINLINE
|
||||
USHORT
|
||||
MiQueryPageTableReferences(IN PVOID Address)
|
||||
{
|
||||
PUSHORT RefCount;
|
||||
|
||||
RefCount = &MmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)];
|
||||
|
||||
return *RefCount;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
MmArmInitSystem(
|
||||
|
|
|
@ -1684,8 +1684,7 @@ UserFault:
|
|||
if (Address <= MM_HIGHEST_USER_ADDRESS)
|
||||
{
|
||||
/* Add an additional page table reference */
|
||||
MmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)]++;
|
||||
ASSERT(MmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)] <= PTE_COUNT);
|
||||
MiIncrementPageTableReferences(Address);
|
||||
}
|
||||
|
||||
/* Did we get a prototype PTE back? */
|
||||
|
|
|
@ -1821,7 +1821,6 @@ MiSetProtectionOnSection(IN PEPROCESS Process,
|
|||
PMMPDE PointerPde;
|
||||
PMMPFN Pfn1;
|
||||
ULONG ProtectionMask, QuotaCharge = 0;
|
||||
PUSHORT UsedPageTableEntries;
|
||||
PETHREAD Thread = PsGetCurrentThread();
|
||||
PAGED_CODE();
|
||||
|
||||
|
@ -1914,9 +1913,7 @@ MiSetProtectionOnSection(IN PEPROCESS Process,
|
|||
// This used to be a zero PTE and it no longer is, so we must add a
|
||||
// reference to the pagetable.
|
||||
//
|
||||
UsedPageTableEntries = &MmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(MiPteToAddress(PointerPte))];
|
||||
(*UsedPageTableEntries)++;
|
||||
ASSERT((*UsedPageTableEntries) <= PTE_COUNT);
|
||||
MiIncrementPageTableReferences(MiPteToAddress(PointerPte));
|
||||
|
||||
//
|
||||
// Create the demand-zero prototype PTE
|
||||
|
|
|
@ -589,10 +589,8 @@ MiDeleteVirtualAddresses(IN ULONG_PTR Va,
|
|||
TempPte = *PointerPte;
|
||||
if (TempPte.u.Long)
|
||||
{
|
||||
DPRINT("Decrement used PTEs by address: %lx\n", Va);
|
||||
(*UsedPageTableEntries)--;
|
||||
*UsedPageTableEntries -= 1;
|
||||
ASSERT((*UsedPageTableEntries) < PTE_COUNT);
|
||||
DPRINT("Refs: %lx\n", (*UsedPageTableEntries));
|
||||
|
||||
/* Check if the PTE is actually mapped in */
|
||||
if (TempPte.u.Long & 0xFFFFFC01)
|
||||
|
@ -653,14 +651,10 @@ MiDeleteVirtualAddresses(IN ULONG_PTR Va,
|
|||
/* The PDE should still be valid at this point */
|
||||
ASSERT(PointerPde->u.Hard.Valid == 1);
|
||||
|
||||
DPRINT("Should check if handles for: %p are zero (PDE: %lx)\n", Va, PointerPde->u.Hard.PageFrameNumber);
|
||||
if (!(*UsedPageTableEntries))
|
||||
if (*UsedPageTableEntries == 0)
|
||||
{
|
||||
DPRINT("They are!\n");
|
||||
if (PointerPde->u.Long != 0)
|
||||
{
|
||||
DPRINT("PDE active: %lx in %16s\n", PointerPde->u.Hard.PageFrameNumber, CurrentProcess->ImageFileName);
|
||||
|
||||
/* Delete the PTE proper */
|
||||
MiDeletePte(PointerPde,
|
||||
MiPteToAddress(PointerPde),
|
||||
|
@ -1880,7 +1874,6 @@ MiProtectVirtualMemory(IN PEPROCESS Process,
|
|||
ULONG_PTR StartingAddress, EndingAddress;
|
||||
PMMPTE PointerPde, PointerPte, LastPte;
|
||||
MMPTE PteContents;
|
||||
//PUSHORT UsedPageTableEntries;
|
||||
PMMPFN Pfn1;
|
||||
ULONG ProtectionMask, OldProtect;
|
||||
BOOLEAN Committed;
|
||||
|
@ -2050,24 +2043,23 @@ MiProtectVirtualMemory(IN PEPROCESS Process,
|
|||
while (PointerPte <= LastPte)
|
||||
{
|
||||
/* Check if we've crossed a PDE boundary and make the new PDE valid too */
|
||||
if ((((ULONG_PTR)PointerPte) & (SYSTEM_PD_SIZE - 1)) == 0)
|
||||
if (MiIsPteOnPdeBoundary(PointerPte))
|
||||
{
|
||||
PointerPde = MiAddressToPte(PointerPte);
|
||||
MiMakePdeExistAndMakeValid(PointerPde, Process, MM_NOIRQL);
|
||||
}
|
||||
|
||||
/* Capture the PTE and see what we're dealing with */
|
||||
/* Capture the PTE and check if it was empty */
|
||||
PteContents = *PointerPte;
|
||||
if (PteContents.u.Long == 0)
|
||||
{
|
||||
/* This used to be a zero PTE and it no longer is, so we must add a
|
||||
reference to the pagetable. */
|
||||
//UsedPageTableEntries = &MmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(MiPteToAddress(PointerPte))];
|
||||
//(*UsedPageTableEntries)++;
|
||||
//ASSERT((*UsedPageTableEntries) <= PTE_COUNT);
|
||||
DPRINT1("HACK: Not increasing UsedPageTableEntries count!\n");
|
||||
MiIncrementPageTableReferences(MiPteToAddress(PointerPte));
|
||||
}
|
||||
else if (PteContents.u.Hard.Valid == 1)
|
||||
|
||||
/* Check what kind of PTE we are dealing with */
|
||||
if (PteContents.u.Hard.Valid == 1)
|
||||
{
|
||||
/* Get the PFN entry */
|
||||
Pfn1 = MiGetPfnEntry(PFN_FROM_PTE(&PteContents));
|
||||
|
@ -2080,8 +2072,11 @@ MiProtectVirtualMemory(IN PEPROCESS Process,
|
|||
(NewAccessProtection & PAGE_GUARD))
|
||||
{
|
||||
/* The page should be in the WS and we should make it transition now */
|
||||
UNIMPLEMENTED;
|
||||
//continue;
|
||||
DPRINT1("Making valid page invalid is not yet supported!\n");
|
||||
Status = STATUS_NOT_IMPLEMENTED;
|
||||
/* Unlock the working set */
|
||||
MiUnlockProcessWorkingSetUnsafe(Process, Thread);
|
||||
goto FailPath;
|
||||
}
|
||||
|
||||
/* Write the protection mask and write it with a TLB flush */
|
||||
|
@ -2270,7 +2265,6 @@ MiDecommitPages(IN PVOID StartingAddress,
|
|||
ULONG PteCount = 0;
|
||||
PMMPFN Pfn1;
|
||||
MMPTE PteContents;
|
||||
PUSHORT UsedPageTableEntries;
|
||||
PETHREAD CurrentThread = PsGetCurrentThread();
|
||||
|
||||
//
|
||||
|
@ -2292,7 +2286,7 @@ MiDecommitPages(IN PVOID StartingAddress,
|
|||
//
|
||||
// Check if we've crossed a PDE boundary
|
||||
//
|
||||
if ((((ULONG_PTR)PointerPte) & (SYSTEM_PD_SIZE - 1)) == 0)
|
||||
if (MiIsPteOnPdeBoundary(PointerPte))
|
||||
{
|
||||
//
|
||||
// Get the new PDE and flush the valid PTEs we had built up until
|
||||
|
@ -2383,9 +2377,7 @@ MiDecommitPages(IN PVOID StartingAddress,
|
|||
// This used to be a zero PTE and it no longer is, so we must add a
|
||||
// reference to the pagetable.
|
||||
//
|
||||
UsedPageTableEntries = &MmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(StartingAddress)];
|
||||
(*UsedPageTableEntries)++;
|
||||
ASSERT((*UsedPageTableEntries) <= PTE_COUNT);
|
||||
MiIncrementPageTableReferences(StartingAddress);
|
||||
|
||||
//
|
||||
// Next, we account for decommitted PTEs and make the PTE as such
|
||||
|
@ -3648,7 +3640,6 @@ NtAllocateVirtualMemory(IN HANDLE ProcessHandle,
|
|||
PMEMORY_AREA MemoryArea;
|
||||
PFN_NUMBER PageCount;
|
||||
PMMVAD Vad, FoundVad;
|
||||
PUSHORT UsedPageTableEntries;
|
||||
NTSTATUS Status;
|
||||
PMMSUPPORT AddressSpace;
|
||||
PVOID PBaseAddress;
|
||||
|
@ -4268,7 +4259,7 @@ NtAllocateVirtualMemory(IN HANDLE ProcessHandle,
|
|||
//
|
||||
// Have we crossed into a new page table?
|
||||
//
|
||||
if (!(((ULONG_PTR)PointerPte) & (SYSTEM_PD_SIZE - 1)))
|
||||
if (MiIsPteOnPdeBoundary(PointerPte))
|
||||
{
|
||||
//
|
||||
// Get the PDE and now make it valid too
|
||||
|
@ -4286,9 +4277,7 @@ NtAllocateVirtualMemory(IN HANDLE ProcessHandle,
|
|||
// First increment the count of pages in the page table for this
|
||||
// process
|
||||
//
|
||||
UsedPageTableEntries = &MmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(MiPteToAddress(PointerPte))];
|
||||
(*UsedPageTableEntries)++;
|
||||
ASSERT((*UsedPageTableEntries) <= PTE_COUNT);
|
||||
MiIncrementPageTableReferences(MiPteToAddress(PointerPte));
|
||||
|
||||
//
|
||||
// And now write the invalid demand-zero PTE as requested
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue