MEMORY_AREA MiStaticMemoryAreas[MI_STATIC_MEMORY_AREAS];
ULONG MiStaticMemoryAreaCount;
-/* FUNCTIONS *****************************************************************/
+MM_AVL_TABLE MiRosKernelVadRoot;
+BOOLEAN MiRosKernelVadRootInitialized;
-/**
- * @name MmIterateFirstNode
- *
- * @param Node
- * Head node of the MEMORY_AREA tree.
- *
- * @return The leftmost MEMORY_AREA node (ie. the one with lowest
- * address)
- */
+/* FUNCTIONS *****************************************************************/
-static PMEMORY_AREA MmIterateFirstNode(PMEMORY_AREA Node)
+PMEMORY_AREA NTAPI
+MmLocateMemoryAreaByAddress(
+ PMMSUPPORT AddressSpace,
+ PVOID Address_)
{
- while (Node->LeftChild != NULL)
- Node = Node->LeftChild;
-
- return Node;
-}
+ ULONG_PTR StartVpn = (ULONG_PTR)Address_ / PAGE_SIZE;
+ PEPROCESS Process;
+ PMM_AVL_TABLE Table;
+ PMMADDRESS_NODE Node;
+ PMEMORY_AREA MemoryArea;
+ TABLE_SEARCH_RESULT Result;
+ PMMVAD_LONG Vad;
-/**
- * @name MmIterateNextNode
- *
- * @param Node
- * Current node in the tree.
- *
- * @return Next node in the tree (sorted by address).
- */
+ Process = MmGetAddressSpaceOwner(AddressSpace);
+ Table = (Process != NULL) ? &Process->VadRoot : &MiRosKernelVadRoot;
-static PMEMORY_AREA MmIterateNextNode(PMEMORY_AREA Node)
-{
- if (Node->RightChild != NULL)
- {
- Node = Node->RightChild;
- while (Node->LeftChild != NULL)
- Node = Node->LeftChild;
- }
- else
+ Result = MiCheckForConflictingNode(StartVpn, StartVpn, Table, &Node);
+ if (Result != TableFoundNode)
{
- PMEMORY_AREA TempNode = NULL;
-
- do
- {
- /* Check if we're at the end of tree. */
- if (Node->Parent == NULL)
- return NULL;
-
- TempNode = Node;
- Node = Node->Parent;
- }
- while (TempNode == Node->RightChild);
+ return NULL;
}
- return Node;
-}
-
-/**
- * @name MmIterateLastNode
- *
- * @param Node
- * Head node of the MEMORY_AREA tree.
- *
- * @return The rightmost MEMORY_AREA node (ie. the one with highest
- * address)
- */
-
-static PMEMORY_AREA MmIterateLastNode(PMEMORY_AREA Node)
-{
- while (Node->RightChild != NULL)
- Node = Node->RightChild;
-
- return Node;
-}
-
-/**
- * @name MmIteratePreviousNode
- *
- * @param Node
- * Current node in the tree.
- *
- * @return Previous node in the tree (sorted by address).
- */
-static PMEMORY_AREA MmIteratePrevNode(PMEMORY_AREA Node)
-{
- if (Node->LeftChild != NULL)
- {
- Node = Node->LeftChild;
- while (Node->RightChild != NULL)
- Node = Node->RightChild;
- }
- else
+ Vad = (PMMVAD_LONG)Node;
+ if (Vad->u.VadFlags.Spare == 0)
{
- PMEMORY_AREA TempNode = NULL;
-
- do
+ /* Check if this is VM VAD */
+ if (Vad->ControlArea == NULL)
{
- /* Check if we're at the end of tree. */
- if (Node->Parent == NULL)
- return NULL;
-
- TempNode = Node;
- Node = Node->Parent;
+ /* We store the reactos MEMORY_AREA here */
+ MemoryArea = (PMEMORY_AREA)Vad->FirstPrototypePte;
}
- while (TempNode == Node->LeftChild);
- }
- return Node;
-}
-
-PMEMORY_AREA NTAPI
-MmLocateMemoryAreaByAddress(
- PMMSUPPORT AddressSpace,
- PVOID Address_)
-{
- PMEMORY_AREA Node = (PMEMORY_AREA)AddressSpace->WorkingSetExpansionLinks.Flink;
- ULONG_PTR Address = (ULONG_PTR)Address_;
-
- DPRINT("MmLocateMemoryAreaByAddress(AddressSpace %p, Address %p)\n",
- AddressSpace, Address);
-
- while (Node != NULL)
- {
- if (Address < MA_GetStartingAddress(Node))
- Node = Node->LeftChild;
- else if (Address >= MA_GetEndingAddress(Node))
- Node = Node->RightChild;
else
{
- DPRINT("MmLocateMemoryAreaByAddress(%p): %p [%p - %p]\n",
- Address, Node, MA_GetStartingAddress(Node), MA_GetEndingAddress(Node));
- return Node;
+ /* This is a section VAD. Store the MAREA here for now */
+ MemoryArea = (PMEMORY_AREA)Vad->u4.Banked;
}
}
+ else
+ {
+ MemoryArea = (PMEMORY_AREA)Node;
+ }
- DPRINT("MmLocateMemoryAreaByAddress(%p): 0\n", Address);
- return NULL;
+ return MemoryArea;
}
-PMEMORY_AREA NTAPI
+PMEMORY_AREA
+NTAPI
MmLocateMemoryAreaByRegion(
PMMSUPPORT AddressSpace,
PVOID Address_,
ULONG_PTR Length)
{
- PMEMORY_AREA Node;
- ULONG_PTR Address = (ULONG_PTR)Address_;
- ULONG_PTR Extent = Address + Length;
-
- /* Special case for empty tree. */
- if (AddressSpace->WorkingSetExpansionLinks.Flink == NULL)
- return NULL;
-
- /* Traverse the tree from left to right. */
- for (Node = MmIterateFirstNode((PMEMORY_AREA)AddressSpace->WorkingSetExpansionLinks.Flink);
- Node != NULL;
- Node = MmIterateNextNode(Node))
- {
- if (MA_GetStartingAddress(Node) >= Address &&
- MA_GetStartingAddress(Node) < Extent)
- {
- DPRINT("MmLocateMemoryAreaByRegion(%p - %p): %p - %p\n",
- Address, (ULONG_PTR)Address + Length, MA_GetStartingAddress(Node),
- MA_GetEndingAddress(Node));
- return Node;
- }
- if (MA_GetEndingAddress(Node) > Address &&
- MA_GetEndingAddress(Node) < Extent)
- {
- DPRINT("MmLocateMemoryAreaByRegion(%p - %p): %p - %p\n",
- Address, (ULONG_PTR)Address + Length, MA_GetStartingAddress(Node),
- MA_GetEndingAddress(Node));
- return Node;
- }
- if (MA_GetStartingAddress(Node) <= Address &&
- MA_GetEndingAddress(Node) >= Extent)
- {
- DPRINT("MmLocateMemoryAreaByRegion(%p - %p): %p - %p\n",
- Address, (ULONG_PTR)Address + Length, MA_GetStartingAddress(Node),
- MA_GetEndingAddress(Node));
- return Node;
- }
- if (MA_GetStartingAddress(Node) >= Extent)
- {
- DPRINT("Finished MmLocateMemoryAreaByRegion() = NULL\n");
- return NULL;
- }
- }
-
- return NULL;
-}
-
-/**
- * @name MmCompressHelper
- *
- * This is helper of MmRebalanceTree. Performs a compression transformation
- * count times, starting at root.
- */
+ ULONG_PTR StartVpn = (ULONG_PTR)Address_ / PAGE_SIZE;
+ ULONG_PTR EndVpn = ((ULONG_PTR)Address_ + Length - 1) / PAGE_SIZE;
+ PEPROCESS Process;
+ PMM_AVL_TABLE Table;
+ PMMADDRESS_NODE Node;
+ PMEMORY_AREA MemoryArea;
+ TABLE_SEARCH_RESULT Result;
+ PMMVAD_LONG Vad;
-static VOID
-MmCompressHelper(
- PMMSUPPORT AddressSpace,
- ULONG Count)
-{
- PMEMORY_AREA Root = NULL;
- PMEMORY_AREA Red = (PMEMORY_AREA)AddressSpace->WorkingSetExpansionLinks.Flink;
- PMEMORY_AREA Black = Red->LeftChild;
+ Process = MmGetAddressSpaceOwner(AddressSpace);
+ Table = (Process != NULL) ? &Process->VadRoot : &MiRosKernelVadRoot;
- while (Count--)
+ Result = MiCheckForConflictingNode(StartVpn, EndVpn, Table, &Node);
+ if (Result != TableFoundNode)
{
- if (Root)
- Root->LeftChild = Black;
- else
- AddressSpace->WorkingSetExpansionLinks.Flink = (PVOID)Black;
- Black->Parent = Root;
- Red->LeftChild = Black->RightChild;
- if (Black->RightChild)
- Black->RightChild->Parent = Red;
- Black->RightChild = Red;
- Red->Parent = Black;
- Root = Black;
-
- if (Count)
- {
- Red = Root->LeftChild;
- Black = Red->LeftChild;
- }
+ return NULL;
}
-}
-
-/**
- * @name MmRebalanceTree
- *
- * Rebalance a memory area tree using the Tree->Vine->Balanced Tree
- * method described in libavl documentation in chapter 4.12.
- * (http://www.stanford.edu/~blp/avl/libavl.html/)
- */
-static VOID
-MmRebalanceTree(
- PMMSUPPORT AddressSpace)
-{
- PMEMORY_AREA PreviousNode;
- PMEMORY_AREA CurrentNode;
- PMEMORY_AREA TempNode;
- ULONG NodeCount = 0;
- ULONG Vine; /* Number of nodes in main vine. */
- ULONG Leaves; /* Nodes in incomplete bottom level, if any. */
- INT Height; /* Height of produced balanced tree. */
-
- /* Transform the tree into Vine. */
-
- PreviousNode = NULL;
- CurrentNode = (PMEMORY_AREA)AddressSpace->WorkingSetExpansionLinks.Flink;
- while (CurrentNode != NULL)
+ Vad = (PMMVAD_LONG)Node;
+ if (Vad->u.VadFlags.Spare == 0)
{
- if (CurrentNode->RightChild == NULL)
+ /* Check if this is VM VAD */
+ if (Vad->ControlArea == NULL)
{
- PreviousNode = CurrentNode;
- CurrentNode = CurrentNode->LeftChild;
- NodeCount++;
+ /* We store the reactos MEMORY_AREA here */
+ MemoryArea = (PMEMORY_AREA)Vad->FirstPrototypePte;
}
else
{
- TempNode = CurrentNode->RightChild;
-
- CurrentNode->RightChild = TempNode->LeftChild;
- if (TempNode->LeftChild)
- TempNode->LeftChild->Parent = CurrentNode;
-
- TempNode->LeftChild = CurrentNode;
- CurrentNode->Parent = TempNode;
-
- CurrentNode = TempNode;
-
- if (PreviousNode != NULL)
- PreviousNode->LeftChild = TempNode;
- else
- AddressSpace->WorkingSetExpansionLinks.Flink = (PVOID)TempNode;
- TempNode->Parent = PreviousNode;
+ /* This is a section VAD. Store the MAREA here for now */
+ MemoryArea = (PMEMORY_AREA)Vad->u4.Banked;
}
}
-
- /* Transform Vine back into a balanced tree. */
-
- Leaves = NodeCount + 1;
- for (;;)
+ else
{
- ULONG Next = Leaves & (Leaves - 1);
- if (Next == 0)
- break;
- Leaves = Next;
+ MemoryArea = (PMEMORY_AREA)Node;
}
- Leaves = NodeCount + 1 - Leaves;
-
- MmCompressHelper(AddressSpace, Leaves);
- Vine = NodeCount - Leaves;
- Height = 1 + (Leaves > 0);
- while (Vine > 1)
- {
- MmCompressHelper(AddressSpace, Vine / 2);
- Vine /= 2;
- Height++;
- }
+ ASSERT(MemoryArea != NULL);
+ return MemoryArea;
}
VOID
NTAPI
MiInsertVad(IN PMMVAD Vad,
- IN PEPROCESS Process);
+ IN PMM_AVL_TABLE VadRoot);
ULONG
NTAPI
IN ULONG Protect
);
+
static VOID
MmInsertMemoryArea(
PMMSUPPORT AddressSpace,
PMEMORY_AREA marea)
{
- PMEMORY_AREA Node;
- PMEMORY_AREA PreviousNode;
- ULONG Depth = 0;
PEPROCESS Process = MmGetAddressSpaceOwner(AddressSpace);
+ marea->VadNode.StartingVpn = marea->StartingVpn;
+ marea->VadNode.EndingVpn = marea->EndingVpn;
+ marea->VadNode.u.VadFlags.Spare = 1;
+ marea->VadNode.u.VadFlags.Protection = MiMakeProtectionMask(marea->Protect);
+
/* Build a lame VAD if this is a user-space allocation */
- if ((MA_GetEndingAddress(marea) < (ULONG_PTR)MmSystemRangeStart) &&
- (marea->Type != MEMORY_AREA_OWNED_BY_ARM3))
+ if (MA_GetEndingAddress(marea) < (ULONG_PTR)MmSystemRangeStart)
{
- PMMVAD Vad;
-
- ASSERT(marea->Type == MEMORY_AREA_SECTION_VIEW || marea->Type == MEMORY_AREA_CACHE);
- Vad = &marea->VadNode;
-
- RtlZeroMemory(Vad, sizeof(MMVAD));
- Vad->StartingVpn = PAGE_ROUND_DOWN(MA_GetStartingAddress(marea)) >> PAGE_SHIFT;
- /*
- * For some strange reason, it is perfectly valid to create a MAREA from 0x1000 to... 0x1000.
- * In a normal OS/Memory Manager, this would be retarded, but ReactOS allows this (how it works
- * I don't even want to know).
- */
- if (MA_GetEndingAddress(marea) != MA_GetStartingAddress(marea))
- {
- Vad->EndingVpn = PAGE_ROUND_DOWN((ULONG_PTR)MA_GetEndingAddress(marea) - 1) >> PAGE_SHIFT;
- }
- else
+ ASSERT(Process != NULL);
+ if (marea->Type != MEMORY_AREA_OWNED_BY_ARM3)
{
- Vad->EndingVpn = Vad->StartingVpn;
- }
- Vad->u.VadFlags.Spare = 1;
- Vad->u.VadFlags.Protection = MiMakeProtectionMask(marea->Protect);
-
- /* Insert the VAD */
- MiInsertVad(Vad, Process);
- marea->Vad = Vad;
- }
- else
- {
- marea->Vad = NULL;
- }
-
- if (AddressSpace->WorkingSetExpansionLinks.Flink == NULL)
- {
- AddressSpace->WorkingSetExpansionLinks.Flink = (PVOID)marea;
- marea->LeftChild = marea->RightChild = marea->Parent = NULL;
- return;
- }
+ ASSERT(marea->Type == MEMORY_AREA_SECTION_VIEW || marea->Type == MEMORY_AREA_CACHE);
- Node = (PMEMORY_AREA)AddressSpace->WorkingSetExpansionLinks.Flink;
- do
- {
- DPRINT("MA_GetEndingAddress(marea): %p Node->StartingAddress: %p\n",
- MA_GetEndingAddress(marea), MA_GetStartingAddress(Node));
- DPRINT("marea->StartingAddress: %p MA_GetEndingAddress(Node): %p\n",
- MA_GetStartingAddress(marea), MA_GetEndingAddress(Node));
- ASSERT(MA_GetEndingAddress(marea) <= MA_GetStartingAddress(Node) ||
- MA_GetStartingAddress(marea) >= MA_GetEndingAddress(Node));
- ASSERT(MA_GetStartingAddress(marea) != MA_GetStartingAddress(Node));
-
- PreviousNode = Node;
-
- if (MA_GetStartingAddress(marea) < MA_GetStartingAddress(Node))
- Node = Node->LeftChild;
- else
- Node = Node->RightChild;
-
- if (Node)
- {
- Depth++;
- if (Depth == 22)
- {
- MmRebalanceTree(AddressSpace);
- PreviousNode = Node->Parent;
- }
+ /* Insert the VAD */
+ MiLockProcessWorkingSetUnsafe(PsGetCurrentProcess(), PsGetCurrentThread());
+ MiInsertVad(&marea->VadNode, &Process->VadRoot);
+ MiUnlockProcessWorkingSetUnsafe(PsGetCurrentProcess(), PsGetCurrentThread());
+ marea->Vad = &marea->VadNode;
}
}
- while (Node != NULL);
-
- marea->LeftChild = marea->RightChild = NULL;
- marea->Parent = PreviousNode;
- if (MA_GetStartingAddress(marea) < MA_GetStartingAddress(PreviousNode))
- PreviousNode->LeftChild = marea;
- else
- PreviousNode->RightChild = marea;
-}
-
-static PVOID
-MmFindGapBottomUp(
- PMMSUPPORT AddressSpace,
- ULONG_PTR Length,
- ULONG_PTR Granularity)
-{
- ULONG_PTR LowestAddress, HighestAddress, Candidate;
- PMEMORY_AREA Root, Node;
-
- /* Get the margins of the address space */
- if (MmGetAddressSpaceOwner(AddressSpace) != NULL)
- {
- LowestAddress = (ULONG_PTR)MM_LOWEST_USER_ADDRESS;
- HighestAddress = (ULONG_PTR)MmHighestUserAddress;
- }
else
{
- LowestAddress = (ULONG_PTR)MmSystemRangeStart;
- HighestAddress = MAXULONG_PTR;
- }
-
- /* Start with the lowest address */
- Candidate = LowestAddress;
-
- /* Check for overflow */
- if ((Candidate + Length) < Candidate) return NULL;
-
- /* Get the root of the address space tree */
- Root = (PMEMORY_AREA)AddressSpace->WorkingSetExpansionLinks.Flink;
-
- /* Go to the node with lowest address in the tree. */
- Node = Root ? MmIterateFirstNode(Root) : NULL;
- while (Node && ((ULONG_PTR)MA_GetEndingAddress(Node) < LowestAddress))
- {
- Node = MmIterateNextNode(Node);
- }
+ ASSERT(Process == NULL);
- /* Traverse the tree from low to high addresses */
- while (Node && ((ULONG_PTR)MA_GetEndingAddress(Node) < HighestAddress))
- {
- /* Check if the memory area fits before the current node */
- if (MA_GetStartingAddress(Node) >= (Candidate + Length))
+ if (!MiRosKernelVadRootInitialized)
{
- DPRINT("MmFindGapBottomUp: %p\n", Candidate);
- ASSERT(Candidate >= LowestAddress);
- return (PVOID)Candidate;
+ MiRosKernelVadRoot.BalancedRoot.u1.Parent = &MiRosKernelVadRoot.BalancedRoot;
+ MiRosKernelVadRoot.Unused = 1;
+ MiRosKernelVadRootInitialized = TRUE;
}
- /* Calculate next possible adress above this node */
- Candidate = ALIGN_UP_BY((ULONG_PTR)MA_GetEndingAddress(Node), Granularity);
-
- /* Check for overflow */
- if ((Candidate + Length) < (ULONG_PTR)MA_GetEndingAddress(Node)) return NULL;
-
- /* Go to the next higher node */
- Node = MmIterateNextNode(Node);
- }
-
- /* Check if there is enough space after the last memory area. */
- if ((Candidate + Length) <= HighestAddress)
- {
- DPRINT("MmFindGapBottomUp: %p\n", Candidate);
- ASSERT(Candidate >= LowestAddress);
- return (PVOID)Candidate;
+ /* Insert the VAD */
+ MiLockWorkingSet(PsGetCurrentThread(), &MmSystemCacheWs);
+ MiInsertVad(&marea->VadNode, &MiRosKernelVadRoot);
+ MiUnlockWorkingSet(PsGetCurrentThread(), &MmSystemCacheWs);
+ marea->Vad = NULL;
}
-
- DPRINT("MmFindGapBottomUp: 0\n");
- return NULL;
}
-
-static PVOID
-MmFindGapTopDown(
+PVOID NTAPI
+MmFindGap(
PMMSUPPORT AddressSpace,
ULONG_PTR Length,
- ULONG_PTR Granularity)
+ ULONG_PTR Granularity,
+ BOOLEAN TopDown)
{
- ULONG_PTR LowestAddress, HighestAddress, Candidate;
- PMEMORY_AREA Root, Node;
+ PEPROCESS Process;
+ PMM_AVL_TABLE VadRoot;
+ TABLE_SEARCH_RESULT Result;
+ PMMADDRESS_NODE Parent;
+ ULONG_PTR StartingAddress, HighestAddress;
- /* Get the margins of the address space */
- if (MmGetAddressSpaceOwner(AddressSpace) != NULL)
+ Process = MmGetAddressSpaceOwner(AddressSpace);
+ VadRoot = Process ? &Process->VadRoot : &MiRosKernelVadRoot;
+ if (TopDown)
{
- LowestAddress = (ULONG_PTR)MM_LOWEST_USER_ADDRESS;
- HighestAddress = (ULONG_PTR)MmHighestUserAddress;
+ /* Find an address top-down */
+ HighestAddress = Process ? (ULONG_PTR)MM_HIGHEST_VAD_ADDRESS : (LONG_PTR)-1;
+ Result = MiFindEmptyAddressRangeDownTree(Length,
+ HighestAddress,
+ Granularity,
+ VadRoot,
+ &StartingAddress,
+ &Parent);
}
else
{
- LowestAddress = (ULONG_PTR)MmSystemRangeStart;
- HighestAddress = MAXULONG_PTR;
- }
-
- /* Calculate the highest candidate */
- Candidate = ALIGN_DOWN_BY(HighestAddress + 1 - Length, Granularity);
-
- /* Check for overflow. */
- if (Candidate > HighestAddress) return NULL;
-
- /* Get the root of the address space tree */
- Root = (PMEMORY_AREA)AddressSpace->WorkingSetExpansionLinks.Flink;
-
- /* Go to the node with highest address in the tree. */
- Node = Root ? MmIterateLastNode(Root) : NULL;
- while (Node && (MA_GetStartingAddress(Node) > HighestAddress))
- {
- Node = MmIteratePrevNode(Node);
- }
-
- /* Traverse the tree from high to low addresses */
- while (Node && (MA_GetStartingAddress(Node) > LowestAddress))
- {
- /* Check if the memory area fits after the current node */
- if ((ULONG_PTR)MA_GetEndingAddress(Node) <= Candidate)
- {
- DPRINT("MmFindGapTopDown: %p\n", Candidate);
- return (PVOID)Candidate;
- }
-
- /* Calculate next possible adress below this node */
- Candidate = ALIGN_DOWN_BY(MA_GetStartingAddress(Node) - Length,
- Granularity);
-
- /* Check for overflow. */
- if (Candidate > MA_GetStartingAddress(Node))
- return NULL;
-
- /* Go to the next lower node */
- Node = MmIteratePrevNode(Node);
+ Result = MiFindEmptyAddressRangeInTree(Length,
+ Granularity,
+ VadRoot,
+ &Parent,
+ &StartingAddress);
}
- /* Check if the last candidate is inside the given range */
- if (Candidate >= LowestAddress)
+ if (Result == TableFoundNode)
{
- DPRINT("MmFindGapTopDown: %p\n", Candidate);
- return (PVOID)Candidate;
+ return NULL;
}
- DPRINT("MmFindGapTopDown: 0\n");
- return NULL;
-}
-
-
-PVOID NTAPI
-MmFindGap(
- PMMSUPPORT AddressSpace,
- ULONG_PTR Length,
- ULONG_PTR Granularity,
- BOOLEAN TopDown)
-{
- if (TopDown)
- return MmFindGapTopDown(AddressSpace, Length, Granularity);
-
- return MmFindGapBottomUp(AddressSpace, Length, Granularity);
+ return (PVOID)StartingAddress;
}
VOID
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(MA_GetStartingAddress(Node)) == (PVOID)MA_GetStartingAddress(Node));
- ASSERT(MA_GetEndingAddress(Node) != 0);
- ASSERT(PAGE_ALIGN(MA_GetEndingAddress(Node)) == (PVOID)MA_GetEndingAddress(Node));
- ASSERT(MA_GetStartingAddress(Node) < MA_GetEndingAddress(Node));
- 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
PMM_FREE_PAGE_FUNC FreePage,
PVOID FreePageContext)
{
- PMEMORY_AREA *ParentReplace;
ULONG_PTR Address;
PVOID EndAddress;
KeDetachProcess();
}
+ //if (MemoryArea->VadNode.StartingVpn < (ULONG_PTR)MmSystemRangeStart >> PAGE_SHIFT
if (MemoryArea->Vad)
{
ASSERT(MA_GetEndingAddress(MemoryArea) < (ULONG_PTR)MmSystemRangeStart);
ASSERT(MemoryArea->Type == MEMORY_AREA_SECTION_VIEW || MemoryArea->Type == MEMORY_AREA_CACHE);
/* MmCleanProcessAddressSpace might have removed it (and this would be MmDeleteProcessAdressSpace) */
- ASSERT(((PMMVAD)MemoryArea->Vad)->u.VadFlags.Spare != 0);
+ ASSERT(MemoryArea->VadNode.u.VadFlags.Spare != 0);
if (((PMMVAD)MemoryArea->Vad)->u.VadFlags.Spare == 1)
{
- MiRemoveNode(MemoryArea->Vad, &Process->VadRoot);
+ MiRemoveNode((PMMADDRESS_NODE)&MemoryArea->VadNode, &Process->VadRoot);
}
MemoryArea->Vad = NULL;
}
- }
-
- /* Remove the tree item. */
- {
- if (MemoryArea->Parent != NULL)
- {
- if (MemoryArea->Parent->LeftChild == MemoryArea)
- ParentReplace = &MemoryArea->Parent->LeftChild;
- else
- ParentReplace = &MemoryArea->Parent->RightChild;
- }
else
- ParentReplace = (PMEMORY_AREA*)&AddressSpace->WorkingSetExpansionLinks.Flink;
-
- if (MemoryArea->RightChild == NULL)
{
- *ParentReplace = MemoryArea->LeftChild;
- if (MemoryArea->LeftChild)
- MemoryArea->LeftChild->Parent = MemoryArea->Parent;
- }
- else
- {
- if (MemoryArea->RightChild->LeftChild == NULL)
- {
- MemoryArea->RightChild->LeftChild = MemoryArea->LeftChild;
- if (MemoryArea->LeftChild)
- MemoryArea->LeftChild->Parent = MemoryArea->RightChild;
-
- *ParentReplace = MemoryArea->RightChild;
- MemoryArea->RightChild->Parent = MemoryArea->Parent;
- }
- else
- {
- PMEMORY_AREA LowestNode;
-
- LowestNode = MemoryArea->RightChild->LeftChild;
- while (LowestNode->LeftChild != NULL)
- LowestNode = LowestNode->LeftChild;
-
- LowestNode->Parent->LeftChild = LowestNode->RightChild;
- if (LowestNode->RightChild)
- LowestNode->RightChild->Parent = LowestNode->Parent;
-
- LowestNode->LeftChild = MemoryArea->LeftChild;
- if (MemoryArea->LeftChild)
- MemoryArea->LeftChild->Parent = LowestNode;
-
- LowestNode->RightChild = MemoryArea->RightChild;
- MemoryArea->RightChild->Parent = LowestNode;
-
- *ParentReplace = LowestNode;
- LowestNode->Parent = MemoryArea->Parent;
- }
+ MiRemoveNode((PMMADDRESS_NODE)&MemoryArea->VadNode, &MiRosKernelVadRoot);
}
}
ULONG_PTR Length,
ULONG Protect,
PMEMORY_AREA *Result,
- BOOLEAN FixedAddress,
ULONG AllocationFlags,
ULONG Granularity)
{
DPRINT("MmCreateMemoryArea(Type 0x%lx, BaseAddress %p, "
"*BaseAddress %p, Length %p, AllocationFlags %x, "
- "FixedAddress %x, Result %p)\n",
+ "Result %p)\n",
Type, BaseAddress, *BaseAddress, Length, AllocationFlags,
- FixedAddress, Result);
+ Result);
+
+ /* Is this a static memory area? */
+ if (Type & MEMORY_AREA_STATIC)
+ {
+ /* Use the static array instead of the pool */
+ ASSERT(MiStaticMemoryAreaCount < MI_STATIC_MEMORY_AREAS);
+ MemoryArea = &MiStaticMemoryAreas[MiStaticMemoryAreaCount++];
+ }
+ else
+ {
+ /* Allocate the memory area from nonpaged pool */
+ MemoryArea = ExAllocatePoolWithTag(NonPagedPool,
+ sizeof(MEMORY_AREA),
+ TAG_MAREA);
+ }
+
+ if (!MemoryArea)
+ {
+ DPRINT1("Not enough memory.\n");
+ return STATUS_NO_MEMORY;
+ }
+
+ RtlZeroMemory(MemoryArea, sizeof(MEMORY_AREA));
+ MemoryArea->Type = Type & ~MEMORY_AREA_STATIC;
+ MemoryArea->Protect = Protect;
+ MemoryArea->Flags = AllocationFlags;
+ MemoryArea->Magic = 'erAM';
+ MemoryArea->DeleteInProgress = FALSE;
- if ((*BaseAddress) == 0 && !FixedAddress)
+ if (*BaseAddress == 0)
{
tmpLength = (ULONG_PTR)MM_ROUND_UP(Length, PAGE_SIZE);
*BaseAddress = MmFindGap(AddressSpace,
if ((*BaseAddress) == 0)
{
DPRINT("No suitable gap\n");
+ if (!(Type & MEMORY_AREA_STATIC)) ExFreePoolWithTag(MemoryArea, TAG_MAREA);
return STATUS_NO_MEMORY;
}
+
+ MemoryArea->StartingVpn = (ULONG_PTR)*BaseAddress >> PAGE_SHIFT;
+ MemoryArea->EndingVpn = ((ULONG_PTR)*BaseAddress + tmpLength - 1) >> PAGE_SHIFT;
+ MmInsertMemoryArea(AddressSpace, MemoryArea);
}
else
{
if (!MmGetAddressSpaceOwner(AddressSpace) && *BaseAddress < MmSystemRangeStart)
{
+ ASSERT(FALSE);
+ if (!(Type & MEMORY_AREA_STATIC)) ExFreePoolWithTag(MemoryArea, TAG_MAREA);
return STATUS_ACCESS_VIOLATION;
}
(ULONG_PTR)(*BaseAddress) + tmpLength > (ULONG_PTR)MmSystemRangeStart)
{
DPRINT("Memory area for user mode address space exceeds MmSystemRangeStart\n");
+ if (!(Type & MEMORY_AREA_STATIC)) ExFreePoolWithTag(MemoryArea, TAG_MAREA);
return STATUS_ACCESS_VIOLATION;
}
- if (MmLocateMemoryAreaByRegion(AddressSpace,
- *BaseAddress,
- tmpLength) != NULL)
+ /* No need to check ARM3 owned memory areas, the range MUST be free */
+ if (MemoryArea->Type != MEMORY_AREA_OWNED_BY_ARM3)
{
- DPRINT("Memory area already occupied\n");
- return STATUS_CONFLICTING_ADDRESSES;
+ if (MmLocateMemoryAreaByRegion(AddressSpace,
+ *BaseAddress,
+ tmpLength) != NULL)
+ {
+ DPRINT("Memory area already occupied\n");
+ if (!(Type & MEMORY_AREA_STATIC)) ExFreePoolWithTag(MemoryArea, TAG_MAREA);
+ return STATUS_CONFLICTING_ADDRESSES;
+ }
}
+
+ MemoryArea->StartingVpn = (ULONG_PTR)*BaseAddress >> PAGE_SHIFT;
+ MemoryArea->EndingVpn = ((ULONG_PTR)*BaseAddress + tmpLength - 1) >> PAGE_SHIFT;
+ MmInsertMemoryArea(AddressSpace, MemoryArea);
}
- //
- // Is this a static memory area?
- //
- if (Type & MEMORY_AREA_STATIC)
+ *Result = MemoryArea;
+
+ DPRINT("MmCreateMemoryArea() succeeded (%p)\n", *BaseAddress);
+ return STATUS_SUCCESS;
+}
+
+VOID
+NTAPI
+MiRosCleanupMemoryArea(
+ PEPROCESS Process,
+ PMMVAD Vad)
+{
+ PMEMORY_AREA MemoryArea;
+ PVOID BaseAddress;
+ NTSTATUS Status;
+
+ /* We must be called from MmCleanupAddressSpace and nowhere else!
+ Make sure things are as expected... */
+ ASSERT(Process == PsGetCurrentProcess());
+ ASSERT(Process->VmDeleted == TRUE);
+ ASSERT(((PsGetCurrentThread()->ThreadsProcess == Process) &&
+ (Process->ActiveThreads == 1)) ||
+ (Process->ActiveThreads == 0));
+
+ /* We are in cleanup, we don't need to synchronize */
+ MmUnlockAddressSpace(&Process->Vm);
+
+ MemoryArea = (PMEMORY_AREA)Vad;
+ BaseAddress = (PVOID)MA_GetStartingAddress(MemoryArea);
+
+ if (MemoryArea->Type == MEMORY_AREA_SECTION_VIEW)
{
- //
- // Use the static array instead of the pool
- //
- ASSERT(MiStaticMemoryAreaCount < MI_STATIC_MEMORY_AREAS);
- MemoryArea = &MiStaticMemoryAreas[MiStaticMemoryAreaCount++];
- Type &= ~MEMORY_AREA_STATIC;
+ Status = MiRosUnmapViewOfSection(Process, BaseAddress, 0);
}
- else
+ else if (MemoryArea->Type == MEMORY_AREA_CACHE)
{
- //
- // Allocate the memory area from nonpaged pool
- //
- MemoryArea = ExAllocatePoolWithTag(NonPagedPool,
- sizeof(MEMORY_AREA),
- TAG_MAREA);
+ Status = MmUnmapViewOfCacheSegment(&Process->Vm, BaseAddress);
}
-
- if (!MemoryArea)
+ else
{
- DPRINT1("Not enough memory.\n");
- return STATUS_NO_MEMORY;
+ /* There shouldn't be anything else! */
+ ASSERT(FALSE);
}
- RtlZeroMemory(MemoryArea, sizeof(MEMORY_AREA));
- MemoryArea->Type = Type;
- MemoryArea->StartingVpn = (ULONG_PTR)*BaseAddress >> PAGE_SHIFT;
- MemoryArea->EndingVpn = ((ULONG_PTR)*BaseAddress + tmpLength - 1) >> PAGE_SHIFT;
- MemoryArea->Protect = Protect;
- MemoryArea->Flags = AllocationFlags;
- //MemoryArea->LockCount = 0;
- MemoryArea->Magic = 'erAM';
- MemoryArea->DeleteInProgress = FALSE;
+ /* Make sure this worked! */
+ ASSERT(NT_SUCCESS(Status));
- MmInsertMemoryArea(AddressSpace, MemoryArea);
-
- *Result = MemoryArea;
-
- DPRINT("MmCreateMemoryArea() succeeded (%p)\n", *BaseAddress);
- return STATUS_SUCCESS;
+ /* Lock the address space again */
+ MmLockAddressSpace(&Process->Vm);
}
-
VOID
NTAPI
MmDeleteProcessAddressSpace2(IN PEPROCESS Process);
NTAPI
MmDeleteProcessAddressSpace(PEPROCESS Process)
{
+ KIRQL OldIrql;
PVOID Address;
- PMEMORY_AREA MemoryArea;
DPRINT("MmDeleteProcessAddressSpace(Process %p (%s))\n", Process,
Process->ImageFileName);
#ifndef _M_AMD64
+ OldIrql = MiAcquireExpansionLock();
RemoveEntryList(&Process->MmProcessLinks);
+ MiReleaseExpansionLock(OldIrql);
#endif
MmLockAddressSpace(&Process->Vm);
- while ((MemoryArea = (PMEMORY_AREA)Process->Vm.WorkingSetExpansionLinks.Flink) != NULL)
- {
- switch (MemoryArea->Type)
- {
- case MEMORY_AREA_SECTION_VIEW:
- Address = (PVOID)MA_GetStartingAddress(MemoryArea);
- MmUnlockAddressSpace(&Process->Vm);
- MmUnmapViewOfSection(Process, Address);
- MmLockAddressSpace(&Process->Vm);
- break;
-
- case MEMORY_AREA_CACHE:
- Address = (PVOID)MA_GetStartingAddress(MemoryArea);
- MmUnlockAddressSpace(&Process->Vm);
- MmUnmapViewOfCacheSegment(&Process->Vm, Address);
- MmLockAddressSpace(&Process->Vm);
- break;
-
- case MEMORY_AREA_OWNED_BY_ARM3:
- MmFreeMemoryArea(&Process->Vm,
- MemoryArea,
- NULL,
- NULL);
- break;
-
- default:
- KeBugCheck(MEMORY_MANAGEMENT);
- }
- }
+ /* There should not be any memory areas left! */
+ ASSERT(Process->Vm.WorkingSetExpansionLinks.Flink == NULL);
#if (_MI_PAGING_LEVELS == 2)
{
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 */
MiDeletePte(pointerPde, MiPdeToPte(pointerPde), Process, NULL);
ASSERT(pointerPde->u.Hard.Valid == 0);
}
+
/* Release lock */
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);