/* Capture the PTE */
TempPte = *PointerPte;
- /* We only support valid PTEs for now */
- ASSERT(TempPte.u.Hard.Valid == 1);
+ /* See if the PTE is valid */
if (TempPte.u.Hard.Valid == 0)
{
- /* Invalid PTEs not supported yet */
+ /* Prototype and paged out PTEs not supported yet */
ASSERT(TempPte.u.Soft.Prototype == 0);
- ASSERT(TempPte.u.Soft.Transition == 0);
+ ASSERT(TempPte.u.Soft.PageFileHigh == 0);
+
+ if (TempPte.u.Soft.Transition)
+ {
+ /* Get the PFN entry */
+ PageFrameIndex = PFN_FROM_PTE(&TempPte);
+ Pfn1 = MiGetPfnEntry(PageFrameIndex);
+
+ DPRINT("Pte %p is transitional!\n", PointerPte);
+
+ /* Destroy the PTE */
+ MI_ERASE_PTE(PointerPte);
+
+ /* Drop the reference on the page table. */
+ MiDecrementShareCount(MiGetPfnEntry(Pfn1->u4.PteFrame), Pfn1->u4.PteFrame);
+
+ ASSERT(Pfn1->u3.e1.PrototypePte == 0);
+
+ /* Make the page free. For prototypes, it will be made free when deleting the section object */
+ if (Pfn1->u2.ShareCount == 0)
+ {
+ NT_ASSERT(Pfn1->u3.e2.ReferenceCount == 0);
+
+ /* And it should be in standby or modified list */
+ ASSERT((Pfn1->u3.e1.PageLocation == ModifiedPageList) || (Pfn1->u3.e1.PageLocation == StandbyPageList));
+
+ /* Unlink it and temporarily mark it as active */
+ MiUnlinkPageFromList(Pfn1);
+ Pfn1->u3.e2.ReferenceCount++;
+ Pfn1->u3.e1.PageLocation = ActiveAndValid;
+
+ /* This will put it back in free list and clean properly up */
+ MI_SET_PFN_DELETED(Pfn1);
+ MiDecrementReferenceCount(Pfn1, PageFrameIndex);
+ }
+ return;
+ }
}
/* Get the PFN entry */
#if (_MI_PAGING_LEVELS == 2)
}
#endif
+ /* Drop the share count on the page table */
+ PointerPde = MiPteToPde(PointerPte);
+ MiDecrementShareCount(MiGetPfnEntry(PointerPde->u.Hard.PageFrameNumber),
+ PointerPde->u.Hard.PageFrameNumber);
+
/* Drop the share count */
MiDecrementShareCount(Pfn1, PageFrameIndex);
(ULONG_PTR)Pfn1->PteAddress);
}
}
+
+ /* Erase it */
+ MI_ERASE_PTE(PointerPte);
}
else
{
(ULONG_PTR)Pfn1->PteAddress);
}
+ /* Erase the PTE */
+ MI_ERASE_PTE(PointerPte);
+
/* There should only be 1 shared reference count */
ASSERT(Pfn1->u2.ShareCount == 1);
//CurrentProcess->NumberOfPrivatePages--;
}
- /* Destroy the PTE and flush the TLB */
- MI_ERASE_PTE(PointerPte);
+ /* Flush the TLB */
KeFlushCurrentTb();
}
/* Check for ROS specific memory area */
MemoryArea = MmLocateMemoryAreaByAddress(&Process->Vm, *BaseAddress);
- if ((MemoryArea) && (MemoryArea->Type == MEMORY_AREA_SECTION_VIEW))
+ if ((MemoryArea) && (MemoryArea->Type != MEMORY_AREA_OWNED_BY_ARM3))
{
/* Evil hack */
return MiRosProtectVirtualMemory(Process,
if ((NewAccessProtection & PAGE_NOACCESS) ||
(NewAccessProtection & PAGE_GUARD))
{
- /* The page should be in the WS and we should make it transition now */
- DPRINT1("Making valid page invalid is not yet supported!\n");
- Status = STATUS_NOT_IMPLEMENTED;
- /* Unlock the working set */
- MiUnlockProcessWorkingSetUnsafe(Process, Thread);
- goto FailPath;
- }
+ KIRQL OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
+
+ /* Mark the PTE as transition and change its protection */
+ PteContents.u.Hard.Valid = 0;
+ PteContents.u.Soft.Transition = 1;
+ PteContents.u.Trans.Protection = ProtectionMask;
+ /* Decrease PFN share count and write the PTE */
+ MiDecrementShareCount(Pfn1, PFN_FROM_PTE(&PteContents));
+ // FIXME: remove the page from the WS
+ MI_WRITE_INVALID_PTE(PointerPte, PteContents);
+#ifdef CONFIG_SMP
+ // FIXME: Should invalidate entry in every CPU TLB
+ ASSERT(FALSE);
+#endif
+ KeInvalidateTlbEntry(MiPteToAddress(PointerPte));
- /* Write the protection mask and write it with a TLB flush */
- Pfn1->OriginalPte.u.Soft.Protection = ProtectionMask;
- MiFlushTbAndCapture(Vad,
- PointerPte,
- ProtectionMask,
- Pfn1,
- TRUE);
+ /* We are done for this PTE */
+ KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
+ }
+ else
+ {
+ /* Write the protection mask and write it with a TLB flush */
+ Pfn1->OriginalPte.u.Soft.Protection = ProtectionMask;
+ MiFlushTbAndCapture(Vad,
+ PointerPte,
+ ProtectionMask,
+ Pfn1,
+ TRUE);
+ }
}
else
{
/* We don't support these cases yet */
ASSERT(PteContents.u.Soft.Prototype == 0);
- ASSERT(PteContents.u.Soft.Transition == 0);
+ //ASSERT(PteContents.u.Soft.Transition == 0);
/* The PTE is already demand-zero, just update the protection mask */
PteContents.u.Soft.Protection = ProtectionMask;
}
}
+ DPRINT("NtAllocateVirtualMemory: Process 0x%p, Address 0x%p, Zerobits %lu , RegionSize 0x%x, Allocation type 0x%x, Protect 0x%x.\n",
+ Process, PBaseAddress, ZeroBits, PRegionSize, AllocationType, Protect);
+
//
// Check for large page allocations and make sure that the required privilege
// is being held, before attempting to handle them.
//
}
_SEH2_END;
+ DPRINT("Reserved %x bytes at %p.\n", PRegionSize, StartingAddress);
return STATUS_SUCCESS;
}
}
}
+ DPRINT("NtFreeVirtualMemory: Process 0x%p, Adress 0x%p, size 0x%x, FreeType %x.\n",
+ Process, PBaseAddress, PRegionSize, FreeType);
+
//
// Lock the address space
//
ASSERT(Vad->StartingVpn << PAGE_SHIFT == (ULONG_PTR)MemoryArea->StartingAddress);
ASSERT((Vad->EndingVpn + 1) << PAGE_SHIFT == (ULONG_PTR)MemoryArea->EndingAddress);
Vad->EndingVpn = ((ULONG_PTR)StartingAddress - 1) >> PAGE_SHIFT;
- MemoryArea->EndingAddress = (PVOID)(((Vad->EndingVpn + 1) << PAGE_SHIFT) - 1);
+ MemoryArea->EndingAddress = (PVOID)(StartingAddress);
}
else
{