Vad->u.VadFlags.Spare = 1;
Vad->u.VadFlags.PrivateMemory = 1;
Vad->u.VadFlags.Protection = MiMakeProtectionMask(marea->Protect);
-
+
/* Insert the VAD */
MiInsertVad(Vad, Process);
marea->Vad = Vad;
MiRemoveNode(IN PMMADDRESS_NODE Node,
IN PMM_AVL_TABLE Table);
+#if DBG
+
+static
+VOID
+MiRosCheckMemoryAreasRecursive(
+ PMEMORY_AREA Node)
+{
+ /* Check if the allocation is ok */
+ ExpCheckPoolAllocation(Node, NonPagedPool, 'ERAM');
+
+ /* Check some fields */
+ ASSERT(Node->Magic == 'erAM');
+ ASSERT(PAGE_ALIGN(Node->StartingAddress) == Node->StartingAddress);
+ ASSERT(Node->EndingAddress != NULL);
+ ASSERT(PAGE_ALIGN(Node->EndingAddress) == Node->EndingAddress);
+ ASSERT((ULONG_PTR)Node->StartingAddress < (ULONG_PTR)Node->EndingAddress);
+ ASSERT((Node->Type == 0) ||
+ (Node->Type == MEMORY_AREA_CACHE) ||
+ // (Node->Type == MEMORY_AREA_CACHE_SEGMENT) ||
+ (Node->Type == MEMORY_AREA_SECTION_VIEW) ||
+ (Node->Type == MEMORY_AREA_OWNED_BY_ARM3) ||
+ (Node->Type == (MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC)));
+
+ /* Recursively check children */
+ if (Node->LeftChild != NULL)
+ MiRosCheckMemoryAreasRecursive(Node->LeftChild);
+ if (Node->RightChild != NULL)
+ MiRosCheckMemoryAreasRecursive(Node->RightChild);
+}
+
+VOID
+NTAPI
+MiRosCheckMemoryAreas(
+ PMMSUPPORT AddressSpace)
+{
+ PMEMORY_AREA RootNode;
+ PEPROCESS AddressSpaceOwner;
+ BOOLEAN NeedReleaseLock;
+
+ NeedReleaseLock = FALSE;
+
+ /* Get the address space owner */
+ AddressSpaceOwner = CONTAINING_RECORD(AddressSpace, EPROCESS, Vm);
+
+ /* Check if we already own the address space lock */
+ if (AddressSpaceOwner->AddressCreationLock.Owner != KeGetCurrentThread())
+ {
+ /* We must own it! */
+ MmLockAddressSpace(AddressSpace);
+ NeedReleaseLock = TRUE;
+ }
+
+ /* Check all memory areas */
+ RootNode = (PMEMORY_AREA)AddressSpace->WorkingSetExpansionLinks.Flink;
+ MiRosCheckMemoryAreasRecursive(RootNode);
+
+ /* Release the lock, if we acquired it */
+ if (NeedReleaseLock)
+ {
+ MmUnlockAddressSpace(AddressSpace);
+ }
+}
+
+extern KGUARDED_MUTEX PspActiveProcessMutex;
+
+VOID
+NTAPI
+MiCheckAllProcessMemoryAreas(VOID)
+{
+ PEPROCESS Process;
+ PLIST_ENTRY Entry;
+
+ /* Acquire the Active Process Lock */
+ KeAcquireGuardedMutex(&PspActiveProcessMutex);
+
+ /* Loop the process list */
+ Entry = PsActiveProcessHead.Flink;
+ while (Entry != &PsActiveProcessHead)
+ {
+ /* Get the process */
+ Process = CONTAINING_RECORD(Entry, EPROCESS, ActiveProcessLinks);
+
+ /* Check memory areas */
+ MiRosCheckMemoryAreas(&Process->Vm);
+
+ Entry = Entry->Flink;
+ }
+
+ /* Release the lock */
+ KeReleaseGuardedMutex(&PspActiveProcessMutex);
+}
+
+#endif
+
/**
* @name MmFreeMemoryArea
*
ULONG_PTR Address;
PVOID EndAddress;
+ /* Make sure we own the address space lock! */
+ ASSERT(CONTAINING_RECORD(AddressSpace, EPROCESS, Vm)->AddressCreationLock.Owner == KeGetCurrentThread());
+
+ /* Check magic */
+ ASSERT(MemoryArea->Magic == 'erAM');
+
if (MemoryArea->Type != MEMORY_AREA_OWNED_BY_ARM3)
{
PEPROCESS CurrentProcess = PsGetCurrentProcess();
Address < (ULONG_PTR)EndAddress;
Address += PAGE_SIZE)
{
- BOOLEAN Dirty = FALSE;
- SWAPENTRY SwapEntry = 0;
- PFN_NUMBER Page = 0;
-
+ BOOLEAN Dirty = FALSE;
+ SWAPENTRY SwapEntry = 0;
+ PFN_NUMBER Page = 0;
+
if (MmIsPageSwapEntry(Process, (PVOID)Address))
{
MmDeletePageFileMapping(Process, (PVOID)Address, &SwapEntry);
#if (_MI_PAGING_LEVELS == 2)
/* Remove page table reference */
ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
- if((SwapEntry || Page) && ((PVOID)Address < MmSystemRangeStart))
+ if ((SwapEntry || Page) && ((PVOID)Address < MmSystemRangeStart))
{
ASSERT(AddressSpace != MmGetKernelAddressSpace());
- if(MmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)] == 0)
+ if (MiQueryPageTableReferences((PVOID)Address) == 0)
{
/* No PTE relies on this PDE. Release it */
KIRQL OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
}
}
- /* There must be no page ops in progress */
- ASSERT(MemoryArea->PageOpCount == 0);
-
/* Remove the tree item. */
{
if (MemoryArea->Parent != NULL)
PMEMORY_AREA *Result,
BOOLEAN FixedAddress,
ULONG AllocationFlags,
- PHYSICAL_ADDRESS BoundaryAddressMultiple)
+ ULONG Granularity)
{
- PVOID EndAddress;
- ULONG Granularity;
ULONG_PTR tmpLength;
PMEMORY_AREA MemoryArea;
Type, BaseAddress, *BaseAddress, Length, AllocationFlags,
FixedAddress, Result);
- Granularity = PAGE_SIZE;
if ((*BaseAddress) == 0 && !FixedAddress)
{
tmpLength = (ULONG_PTR)MM_ROUND_UP(Length, Granularity);
return STATUS_ACCESS_VIOLATION;
}
- if (BoundaryAddressMultiple.QuadPart != 0)
- {
- EndAddress = ((char*)(*BaseAddress)) + tmpLength-1;
- ASSERT(((ULONG_PTR)*BaseAddress/BoundaryAddressMultiple.QuadPart) == ((DWORD_PTR)EndAddress/BoundaryAddressMultiple.QuadPart));
- }
-
if (MmLocateMemoryAreaByRegion(AddressSpace,
*BaseAddress,
tmpLength) != NULL)
TAG_MAREA);
}
- if (!MemoryArea) return STATUS_NO_MEMORY;
+ if (!MemoryArea)
+ {
+ DPRINT1("Not enough memory.\n");
+ return STATUS_NO_MEMORY;
+ }
RtlZeroMemory(MemoryArea, sizeof(MEMORY_AREA));
MemoryArea->Type = Type;
MemoryArea->Protect = Protect;
MemoryArea->Flags = AllocationFlags;
//MemoryArea->LockCount = 0;
- MemoryArea->PageOpCount = 0;
+ MemoryArea->Magic = 'erAM';
MemoryArea->DeleteInProgress = FALSE;
MmInsertMemoryArea(AddressSpace, MemoryArea);
PVOID Address;
PMEMORY_AREA MemoryArea;
- DPRINT("MmDeleteProcessAddressSpace(Process %x (%s))\n", Process,
+ DPRINT("MmDeleteProcessAddressSpace(Process %p (%s))\n", Process,
Process->ImageFileName);
#ifndef _M_AMD64
KeBugCheck(MEMORY_MANAGEMENT);
}
}
-
+
#if (_MI_PAGING_LEVELS == 2)
{
KIRQL OldIrql;
PMMPDE pointerPde;
/* Attach to Process */
KeAttachProcess(&Process->Pcb);
-
+
/* Acquire PFN lock */
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
-
- for(Address = MI_LOWEST_VAD_ADDRESS;
- Address < MM_HIGHEST_VAD_ADDRESS;
- Address =(PVOID)((ULONG_PTR)Address + (PAGE_SIZE * PTE_COUNT)))
+
+ for (Address = MI_LOWEST_VAD_ADDRESS;
+ Address < MM_HIGHEST_VAD_ADDRESS;
+ Address =(PVOID)((ULONG_PTR)Address + (PAGE_SIZE * PTE_COUNT)))
{
/* At this point all references should be dead */
- ASSERT(MmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)] == 0);
+ if (MiQueryPageTableReferences(Address) != 0)
+ {
+ DPRINT1("Process %p, Address %p, UsedPageTableEntries %lu\n",
+ Process,
+ Address,
+ MiQueryPageTableReferences(Address));
+ ASSERT(MiQueryPageTableReferences(Address) == 0);
+ }
pointerPde = MiAddressToPde(Address);
/* Unlike in ARM3, we don't necesarrily free the PDE page as soon as reference reaches 0,
* so we must clean up a bit when process closes */
- if(pointerPde->u.Hard.Valid)
+ if (pointerPde->u.Hard.Valid)
MiDeletePte(pointerPde, MiPdeToPte(pointerPde), Process, NULL);
ASSERT(pointerPde->u.Hard.Valid == 0);
}
/* Release lock */
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
-
+
/* Detach */
KeDetachProcess();
}