[NTOS:MM] Use inline functions to acquire/release the PFN lock.
[reactos.git] / ntoskrnl / mm / marea.c
index 759be7a..1dc4d61 100644 (file)
@@ -43,7 +43,7 @@
 
 #include <ntoskrnl.h>
 #define NDEBUG
-#include "../cache/section/newmm.h"
+#include <cache/section/newmm.h>
 #include <debug.h>
 
 #include "ARM3/miarm.h"
 MEMORY_AREA MiStaticMemoryAreas[MI_STATIC_MEMORY_AREAS];
 ULONG MiStaticMemoryAreaCount;
 
-/* FUNCTIONS *****************************************************************/
-
-/**
- * @name MmIterateFirstNode
- *
- * @param Node
- *        Head node of the MEMORY_AREA tree.
- *
- * @return The leftmost MEMORY_AREA node (ie. the one with lowest
- *         address)
- */
-
-static PMEMORY_AREA MmIterateFirstNode(PMEMORY_AREA Node)
-{
-   while (Node->LeftChild != NULL)
-      Node = Node->LeftChild;
-
-   return Node;
-}
-
-/**
- * @name MmIterateNextNode
- *
- * @param Node
- *        Current node in the tree.
- *
- * @return Next node in the tree (sorted by address).
- */
-
-static PMEMORY_AREA MmIterateNextNode(PMEMORY_AREA Node)
-{
-   if (Node->RightChild != NULL)
-   {
-      Node = Node->RightChild;
-      while (Node->LeftChild != NULL)
-         Node = Node->LeftChild;
-   }
-   else
-   {
-      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 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).
- */
+MM_AVL_TABLE MiRosKernelVadRoot;
+BOOLEAN MiRosKernelVadRootInitialized;
 
-static PMEMORY_AREA MmIteratePrevNode(PMEMORY_AREA Node)
-{
-   if (Node->LeftChild != NULL)
-   {
-      Node = Node->LeftChild;
-      while (Node->RightChild != NULL)
-         Node = Node->RightChild;
-   }
-   else
-   {
-      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->LeftChild);
-   }
-   return Node;
-}
+/* FUNCTIONS *****************************************************************/
 
 PMEMORY_AREA NTAPI
 MmLocateMemoryAreaByAddress(
-   PMMSUPPORT AddressSpace,
-   PVOID Address)
-{
-   PMEMORY_AREA Node = (PMEMORY_AREA)AddressSpace->WorkingSetExpansionLinks.Flink;
-
-   DPRINT("MmLocateMemoryAreaByAddress(AddressSpace %p, Address %p)\n",
-           AddressSpace, Address);
-
-   while (Node != NULL)
-   {
-      if (Address < Node->StartingAddress)
-         Node = Node->LeftChild;
-      else if (Address >= Node->EndingAddress)
-         Node = Node->RightChild;
-      else
-      {
-         DPRINT("MmLocateMemoryAreaByAddress(%p): %p [%p - %p]\n",
-                Address, Node, Node->StartingAddress, Node->EndingAddress);
-         return Node;
-      }
-   }
-
-   DPRINT("MmLocateMemoryAreaByAddress(%p): 0\n", Address);
-   return NULL;
-}
-
-PMEMORY_AREA NTAPI
-MmLocateMemoryAreaByRegion(
-   PMMSUPPORT AddressSpace,
-   PVOID Address,
-   ULONG_PTR Length)
-{
-   PMEMORY_AREA Node;
-   PVOID Extent = (PVOID)((ULONG_PTR)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 (Node->StartingAddress >= Address &&
-          Node->StartingAddress < Extent)
-      {
-         DPRINT("MmLocateMemoryAreaByRegion(%p - %p): %p - %p\n",
-                Address, (ULONG_PTR)Address + Length, Node->StartingAddress,
-                Node->EndingAddress);
-         return Node;
-      }
-      if (Node->EndingAddress > Address &&
-          Node->EndingAddress < Extent)
-      {
-         DPRINT("MmLocateMemoryAreaByRegion(%p - %p): %p - %p\n",
-                Address, (ULONG_PTR)Address + Length, Node->StartingAddress,
-                Node->EndingAddress);
-         return Node;
-      }
-      if (Node->StartingAddress <= Address &&
-          Node->EndingAddress >= Extent)
-      {
-         DPRINT("MmLocateMemoryAreaByRegion(%p - %p): %p - %p\n",
-                Address, (ULONG_PTR)Address + Length, Node->StartingAddress,
-                Node->EndingAddress);
-         return Node;
-      }
-      if (Node->StartingAddress >= 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.
- */
-
-static VOID
-MmCompressHelper(
-   PMMSUPPORT AddressSpace,
-   ULONG Count)
+    PMMSUPPORT AddressSpace,
+    PVOID Address_)
 {
-   PMEMORY_AREA Root = NULL;
-   PMEMORY_AREA Red = (PMEMORY_AREA)AddressSpace->WorkingSetExpansionLinks.Flink;
-   PMEMORY_AREA Black = Red->LeftChild;
-
-   while (Count--)
-   {
-      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;
-      }
-   }
-}
-
-/**
- * @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/)
- */
+    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;
 
-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)
-   {
-      if (CurrentNode->RightChild == NULL)
-      {
-         PreviousNode = CurrentNode;
-         CurrentNode = CurrentNode->LeftChild;
-         NodeCount++;
-      }
-      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;
-      }
-   }
-
-   /* Transform Vine back into a balanced tree. */
-
-   Leaves = NodeCount + 1;
-   for (;;)
-   {
-      ULONG Next = Leaves & (Leaves - 1);
-      if (Next == 0)
-         break;
-      Leaves = Next;
-   }
-   Leaves = NodeCount + 1 - Leaves;
-
-   MmCompressHelper(AddressSpace, Leaves);
-
-   Vine = NodeCount - Leaves;
-   Height = 1 + (Leaves > 0);
-   while (Vine > 1)
-   {
-      MmCompressHelper(AddressSpace, Vine / 2);
-      Vine /= 2;
-      Height++;
-   }
-}
+    Process = MmGetAddressSpaceOwner(AddressSpace);
+    Table = (Process != NULL) ? &Process->VadRoot : &MiRosKernelVadRoot;
 
-VOID
-NTAPI
-MiInsertVad(IN PMMVAD Vad,
-IN PEPROCESS Process);
-
-ULONG
-NTAPI
-MiMakeProtectionMask(
-    IN ULONG Protect
-);
+    Result = MiCheckForConflictingNode(StartVpn, StartVpn, Table, &Node);
+    if (Result != TableFoundNode)
+    {
+        return NULL;
+    }
 
-static VOID
-MmInsertMemoryArea(
-   PMMSUPPORT AddressSpace,
-   PMEMORY_AREA marea)
-{
-   PMEMORY_AREA Node;
-   PMEMORY_AREA PreviousNode;
-   ULONG Depth = 0;
-   PEPROCESS Process = MmGetAddressSpaceOwner(AddressSpace);
-
-   /* Build a lame VAD if this is a user-space allocation */
-   if ((marea->EndingAddress < MmSystemRangeStart) && (marea->Type != MEMORY_AREA_OWNED_BY_ARM3))
-   {
-       PMMVAD Vad;
-
-       ASSERT(marea->Type == MEMORY_AREA_SECTION_VIEW || marea->Type == MEMORY_AREA_CACHE);
-       Vad = ExAllocatePoolWithTag(NonPagedPool, sizeof(MMVAD), TAG_MVAD);
-       ASSERT(Vad);
-       RtlZeroMemory(Vad, sizeof(MMVAD));
-       Vad->StartingVpn = PAGE_ROUND_DOWN(marea->StartingAddress) >> 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 (marea->EndingAddress != marea->StartingAddress)
+    Vad = (PMMVAD_LONG)Node;
+    if (Vad->u.VadFlags.Spare == 0)
+    {
+        /* Check if this is VM VAD */
+        if (Vad->ControlArea == NULL)
         {
-            Vad->EndingVpn = PAGE_ROUND_DOWN((ULONG_PTR)marea->EndingAddress - 1) >> PAGE_SHIFT;
+            /* We store the reactos MEMORY_AREA here */
+            MemoryArea = (PMEMORY_AREA)Vad->FirstPrototypePte;
         }
         else
         {
-            Vad->EndingVpn = Vad->StartingVpn;
+            /* This is a section VAD. Store the MAREA here for now */
+            MemoryArea = (PMEMORY_AREA)Vad->u4.Banked;
         }
-       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;
-   }
-   else
-   {
-       marea->Vad = NULL;
-   }
-
-   if (AddressSpace->WorkingSetExpansionLinks.Flink == NULL)
-   {
-      AddressSpace->WorkingSetExpansionLinks.Flink = (PVOID)marea;
-      marea->LeftChild = marea->RightChild = marea->Parent = NULL;
-      return;
-   }
-
-   Node = (PMEMORY_AREA)AddressSpace->WorkingSetExpansionLinks.Flink;
-   do
-   {
-      DPRINT("marea->EndingAddress: %p Node->StartingAddress: %p\n",
-             marea->EndingAddress, Node->StartingAddress);
-      DPRINT("marea->StartingAddress: %p Node->EndingAddress: %p\n",
-             marea->StartingAddress, Node->EndingAddress);
-      ASSERT(marea->EndingAddress <= Node->StartingAddress ||
-             marea->StartingAddress >= Node->EndingAddress);
-      ASSERT(marea->StartingAddress != Node->StartingAddress);
-
-      PreviousNode = Node;
-
-      if (marea->StartingAddress < Node->StartingAddress)
-         Node = Node->LeftChild;
-      else
-         Node = Node->RightChild;
-
-      if (Node)
-      {
-         Depth++;
-         if (Depth == 22)
-         {
-            MmRebalanceTree(AddressSpace);
-            PreviousNode = Node->Parent;
-         }
-      }
-   }
-   while (Node != NULL);
-
-   marea->LeftChild = marea->RightChild = NULL;
-   marea->Parent = PreviousNode;
-   if (marea->StartingAddress < PreviousNode->StartingAddress)
-      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;
+        MemoryArea = (PMEMORY_AREA)Node;
     }
 
-    /* Start with the lowest address */
-    Candidate = LowestAddress;
+    return MemoryArea;
+}
 
-    /* Check for overflow */
-    if ((Candidate + Length) < Candidate) return NULL;
+PMEMORY_AREA
+NTAPI
+MmLocateMemoryAreaByRegion(
+    PMMSUPPORT AddressSpace,
+    PVOID Address_,
+    ULONG_PTR Length)
+{
+    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;
 
-    /* Get the root of the address space tree */
-    Root = (PMEMORY_AREA)AddressSpace->WorkingSetExpansionLinks.Flink;
+    Process = MmGetAddressSpaceOwner(AddressSpace);
+    Table = (Process != NULL) ? &Process->VadRoot : &MiRosKernelVadRoot;
 
-    /* Go to the node with lowest address in the tree. */
-    Node = Root ? MmIterateFirstNode(Root) : NULL;
-    while (Node && ((ULONG_PTR)Node->EndingAddress < LowestAddress))
+    Result = MiCheckForConflictingNode(StartVpn, EndVpn, Table, &Node);
+    if (Result != TableFoundNode)
     {
-        Node = MmIterateNextNode(Node);
+        return NULL;
     }
 
-    /* Traverse the tree from low to high addresses */
-    while (Node && ((ULONG_PTR)Node->EndingAddress < HighestAddress))
+    Vad = (PMMVAD_LONG)Node;
+    if (Vad->u.VadFlags.Spare == 0)
     {
-        /* Check if the memory area fits before the current node */
-        if ((ULONG_PTR)Node->StartingAddress >= (Candidate + Length))
+        /* Check if this is VM VAD */
+        if (Vad->ControlArea == NULL)
         {
-            DPRINT("MmFindGapBottomUp: %p\n", Candidate);
-            ASSERT(Candidate >= LowestAddress);
-            return (PVOID)Candidate;
+            /* We store the reactos MEMORY_AREA here */
+            MemoryArea = (PMEMORY_AREA)Vad->FirstPrototypePte;
+        }
+        else
+        {
+            /* This is a section VAD. Store the MAREA here for now */
+            MemoryArea = (PMEMORY_AREA)Vad->u4.Banked;
         }
-
-        /* Calculate next possible adress above this node */
-        Candidate = ALIGN_UP_BY((ULONG_PTR)Node->EndingAddress, Granularity);
-
-        /* Check for overflow */
-        if ((Candidate + Length) < (ULONG_PTR)Node->EndingAddress) 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)
+    else
     {
-        DPRINT("MmFindGapBottomUp: %p\n", Candidate);
-        ASSERT(Candidate >= LowestAddress);
-        return (PVOID)Candidate;
+        MemoryArea = (PMEMORY_AREA)Node;
     }
 
-    DPRINT("MmFindGapBottomUp: 0\n");
-    return NULL;
+    ASSERT(MemoryArea != NULL);
+    return MemoryArea;
 }
 
+VOID
+NTAPI
+MiInsertVad(IN PMMVAD Vad,
+            IN PMM_AVL_TABLE VadRoot);
 
-static PVOID
-MmFindGapTopDown(
-   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;
-    }
+ULONG
+NTAPI
+MiMakeProtectionMask(
+    IN ULONG Protect
+);
 
-    /* Calculate the highest candidate */
-    Candidate = ALIGN_DOWN_BY(HighestAddress + 1 - Length, Granularity);
 
-    /* Check for overflow. */
-    if (Candidate > HighestAddress) return NULL;
+static VOID
+MmInsertMemoryArea(
+    PMMSUPPORT AddressSpace,
+    PMEMORY_AREA marea)
+{
+    PEPROCESS Process = MmGetAddressSpaceOwner(AddressSpace);
 
-    /* Get the root of the address space tree */
-    Root = (PMEMORY_AREA)AddressSpace->WorkingSetExpansionLinks.Flink;
+    marea->VadNode.u.VadFlags.Spare = 1;
+    marea->VadNode.u.VadFlags.Protection = MiMakeProtectionMask(marea->Protect);
 
-    /* Go to the node with highest address in the tree. */
-    Node = Root ? MmIterateLastNode(Root) : NULL;
-    while (Node && ((ULONG_PTR)Node->StartingAddress > HighestAddress))
+    /* Build a lame VAD if this is a user-space allocation */
+    if (marea->VadNode.EndingVpn + 1 < (ULONG_PTR)MmSystemRangeStart >> PAGE_SHIFT)
     {
-        Node = MmIteratePrevNode(Node);
-    }
+        ASSERT(Process != NULL);
+        if (marea->Type != MEMORY_AREA_OWNED_BY_ARM3)
+        {
+            ASSERT(marea->Type == MEMORY_AREA_SECTION_VIEW || marea->Type == MEMORY_AREA_CACHE);
 
-    /* Traverse the tree from high to low addresses */
-    while (Node && ((ULONG_PTR)Node->StartingAddress > LowestAddress))
+            /* Insert the VAD */
+            MiLockProcessWorkingSetUnsafe(PsGetCurrentProcess(), PsGetCurrentThread());
+            MiInsertVad(&marea->VadNode, &Process->VadRoot);
+            MiUnlockProcessWorkingSetUnsafe(PsGetCurrentProcess(), PsGetCurrentThread());
+            marea->Vad = &marea->VadNode;
+        }
+    }
+    else
     {
-        /* Check if the memory area fits after the current node */
-        if ((ULONG_PTR)Node->EndingAddress <= Candidate)
+        ASSERT(Process == NULL);
+
+        if (!MiRosKernelVadRootInitialized)
         {
-            DPRINT("MmFindGapTopDown: %p\n", Candidate);
-            return (PVOID)Candidate;
+            MiRosKernelVadRoot.BalancedRoot.u1.Parent = &MiRosKernelVadRoot.BalancedRoot;
+            MiRosKernelVadRoot.Unused = 1;
+            MiRosKernelVadRootInitialized = TRUE;
         }
 
-        /* Calculate next possible adress below this node */
-        Candidate = ALIGN_DOWN_BY((ULONG_PTR)Node->StartingAddress - Length,
-                                  Granularity);
-
-        /* Check for overflow. */
-        if (Candidate > (ULONG_PTR)Node->StartingAddress)
-            return NULL;
-
-        /* Go to the next lower node */
-        Node = MmIteratePrevNode(Node);
-    }
-
-    /* Check if the last candidate is inside the given range */
-    if (Candidate >= LowestAddress)
-    {
-        DPRINT("MmFindGapTopDown: %p\n", Candidate);
-        return (PVOID)Candidate;
+        /* Insert the VAD */
+        MiLockWorkingSet(PsGetCurrentThread(), &MmSystemCacheWs);
+        MiInsertVad(&marea->VadNode, &MiRosKernelVadRoot);
+        MiUnlockWorkingSet(PsGetCurrentThread(), &MmSystemCacheWs);
+        marea->Vad = 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);
-}
-
-ULONG_PTR NTAPI
-MmFindGapAtAddress(
-   PMMSUPPORT AddressSpace,
-   PVOID Address)
-{
-   PMEMORY_AREA Node = (PMEMORY_AREA)AddressSpace->WorkingSetExpansionLinks.Flink;
-   PMEMORY_AREA RightNeighbour = NULL;
-   PVOID LowestAddress  = MmGetAddressSpaceOwner(AddressSpace) ? MM_LOWEST_USER_ADDRESS : MmSystemRangeStart;
-   PVOID HighestAddress = MmGetAddressSpaceOwner(AddressSpace) ?
-                          (PVOID)((ULONG_PTR)MmSystemRangeStart - 1) : (PVOID)MAXULONG_PTR;
-
-   Address = MM_ROUND_DOWN(Address, PAGE_SIZE);
-
-   if (LowestAddress < MmSystemRangeStart)
-   {
-      if (Address >= MmSystemRangeStart)
-      {
-         return 0;
-      }
-   }
-   else
-   {
-      if (Address < LowestAddress)
-      {
-         return 0;
-      }
-   }
-
-   while (Node != NULL)
-   {
-      if (Address < Node->StartingAddress)
-      {
-         RightNeighbour = Node;
-         Node = Node->LeftChild;
-      }
-      else if (Address >= Node->EndingAddress)
-      {
-         Node = Node->RightChild;
-      }
-      else
-      {
-         DPRINT("MmFindGapAtAddress: 0\n");
-         return 0;
-      }
-   }
-
-   if (RightNeighbour)
-   {
-      DPRINT("MmFindGapAtAddress: %p [%p]\n", Address,
-             (ULONG_PTR)RightNeighbour->StartingAddress - (ULONG_PTR)Address);
-      return (ULONG_PTR)RightNeighbour->StartingAddress - (ULONG_PTR)Address;
-   }
-   else
-   {
-      DPRINT("MmFindGapAtAddress: %p [%p]\n", Address,
-             (ULONG_PTR)HighestAddress - (ULONG_PTR)Address);
-      return (ULONG_PTR)HighestAddress - (ULONG_PTR)Address;
-   }
-}
-
-VOID
-NTAPI
-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)
+    PMMSUPPORT AddressSpace,
+    ULONG_PTR Length,
+    ULONG_PTR Granularity,
+    BOOLEAN TopDown)
 {
-    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())
+    PEPROCESS Process;
+    PMM_AVL_TABLE VadRoot;
+    TABLE_SEARCH_RESULT Result;
+    PMMADDRESS_NODE Parent;
+    ULONG_PTR StartingAddress, HighestAddress;
+
+    Process = MmGetAddressSpaceOwner(AddressSpace);
+    VadRoot = Process ? &Process->VadRoot : &MiRosKernelVadRoot;
+    if (TopDown)
     {
-        /* We must own it! */
-        MmLockAddressSpace(AddressSpace);
-        NeedReleaseLock = TRUE;
+        /* Find an address top-down */
+        HighestAddress = Process ? (ULONG_PTR)MM_HIGHEST_VAD_ADDRESS : (LONG_PTR)-1;
+        Result = MiFindEmptyAddressRangeDownTree(Length,
+                                                 HighestAddress,
+                                                 Granularity,
+                                                 VadRoot,
+                                                 &StartingAddress,
+                                                 &Parent);
     }
-
-    /* Check all memory areas */
-    RootNode = (PMEMORY_AREA)AddressSpace->WorkingSetExpansionLinks.Flink;
-    MiRosCheckMemoryAreasRecursive(RootNode);
-
-    /* Release the lock, if we acquired it */
-    if (NeedReleaseLock)
+    else
     {
-        MmUnlockAddressSpace(AddressSpace);
+        Result = MiFindEmptyAddressRangeInTree(Length,
+                                               Granularity,
+                                               VadRoot,
+                                               &Parent,
+                                               &StartingAddress);
     }
-}
-
-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)
+    if (Result == TableFoundNode)
     {
-        /* Get the process */
-        Process = CONTAINING_RECORD(Entry, EPROCESS, ActiveProcessLinks);
-
-        /* Check memory areas */
-        MiRosCheckMemoryAreas(&Process->Vm);
-
-        Entry = Entry->Flink;
+        return NULL;
     }
 
-    /* Release the lock */
-    KeReleaseGuardedMutex(&PspActiveProcessMutex);
+    return (PVOID)StartingAddress;
 }
 
-#endif
+VOID
+NTAPI
+MiRemoveNode(IN PMMADDRESS_NODE Node,
+             IN PMM_AVL_TABLE Table);
+
 
 /**
  * @name MmFreeMemoryArea
@@ -788,63 +273,56 @@ MiCheckAllProcessMemoryAreas(VOID)
  *
  * @remarks Lock the address space before calling this function.
  */
-VOID
-NTAPI
-MiDeletePte(IN PMMPTE PointerPte,
-            IN PVOID VirtualAddress,
-            IN PEPROCESS CurrentProcess,
-            IN PMMPTE PrototypePte);
 
 NTSTATUS NTAPI
 MmFreeMemoryArea(
-   PMMSUPPORT AddressSpace,
-   PMEMORY_AREA MemoryArea,
-   PMM_FREE_PAGE_FUNC FreePage,
-   PVOID FreePageContext)
+    PMMSUPPORT AddressSpace,
+    PMEMORY_AREA MemoryArea,
+    PMM_FREE_PAGE_FUNC FreePage,
+    PVOID FreePageContext)
 {
-   PMEMORY_AREA *ParentReplace;
-   ULONG_PTR Address;
-   PVOID EndAddress;
+    ULONG_PTR Address;
+    PVOID EndAddress;
 
-   /* Make sure we own the address space lock! */
-   ASSERT(CONTAINING_RECORD(AddressSpace, EPROCESS, Vm)->AddressCreationLock.Owner == KeGetCurrentThread());
+    /* 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();
-       PEPROCESS Process = MmGetAddressSpaceOwner(AddressSpace);
-
-       if (Process != NULL &&
-           Process != CurrentProcess)
-       {
-          KeAttachProcess(&Process->Pcb);
-       }
-
-       EndAddress = MM_ROUND_UP(MemoryArea->EndingAddress, PAGE_SIZE);
-       for (Address = (ULONG_PTR)MemoryArea->StartingAddress;
-            Address < (ULONG_PTR)EndAddress;
-            Address += PAGE_SIZE)
-       {
-             BOOLEAN Dirty = FALSE;
-             SWAPENTRY SwapEntry = 0;
-             PFN_NUMBER Page = 0;
-
-             if (MmIsPageSwapEntry(Process, (PVOID)Address))
-             {
+    if (MemoryArea->Type != MEMORY_AREA_OWNED_BY_ARM3)
+    {
+        PEPROCESS CurrentProcess = PsGetCurrentProcess();
+        PEPROCESS Process = MmGetAddressSpaceOwner(AddressSpace);
+
+        if (Process != NULL &&
+                Process != CurrentProcess)
+        {
+            KeAttachProcess(&Process->Pcb);
+        }
+
+        EndAddress = MM_ROUND_UP(MA_GetEndingAddress(MemoryArea), PAGE_SIZE);
+        for (Address = MA_GetStartingAddress(MemoryArea);
+                Address < (ULONG_PTR)EndAddress;
+                Address += PAGE_SIZE)
+        {
+            BOOLEAN Dirty = FALSE;
+            SWAPENTRY SwapEntry = 0;
+            PFN_NUMBER Page = 0;
+
+            if (MmIsPageSwapEntry(Process, (PVOID)Address))
+            {
                 MmDeletePageFileMapping(Process, (PVOID)Address, &SwapEntry);
-             }
-             else
-             {
-                MmDeleteVirtualMapping(Process, (PVOID)Address, FALSE, &Dirty, &Page);
-             }
-             if (FreePage != NULL)
-             {
+            }
+            else
+            {
+                MmDeleteVirtualMapping(Process, (PVOID)Address, &Dirty, &Page);
+            }
+            if (FreePage != NULL)
+            {
                 FreePage(FreePageContext, MemoryArea, (PVOID)Address,
                          Page, SwapEntry, (BOOLEAN)Dirty);
-             }
+            }
 #if (_MI_PAGING_LEVELS == 2)
             /* Remove page table reference */
             ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
@@ -854,99 +332,52 @@ MmFreeMemoryArea(
                 if (MiQueryPageTableReferences((PVOID)Address) == 0)
                 {
                     /* No PTE relies on this PDE. Release it */
-                    KIRQL OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
+                    KIRQL OldIrql = MiAcquirePfnLock();
                     PMMPDE PointerPde = MiAddressToPde(Address);
                     ASSERT(PointerPde->u.Hard.Valid == 1);
                     MiDeletePte(PointerPde, MiPdeToPte(PointerPde), Process, NULL);
                     ASSERT(PointerPde->u.Hard.Valid == 0);
-                    KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
+                    MiReleasePfnLock(OldIrql);
                 }
             }
 #endif
-       }
-
-       if (Process != NULL &&
-           Process != CurrentProcess)
-       {
-          KeDetachProcess();
-       }
-
-       if (MemoryArea->Vad)
-       {
-           ASSERT(MemoryArea->EndingAddress < 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);
-           if (((PMMVAD)MemoryArea->Vad)->u.VadFlags.Spare == 1)
-           {
-               MiRemoveNode(MemoryArea->Vad, &Process->VadRoot);
-           }
-
-           ExFreePoolWithTag(MemoryArea->Vad, TAG_MVAD);
-           MemoryArea->Vad = NULL;
-       }
+        }
+
+        if (Process != NULL &&
+                Process != CurrentProcess)
+        {
+            KeDetachProcess();
+        }
+
+        //if (MemoryArea->VadNode.StartingVpn < (ULONG_PTR)MmSystemRangeStart >> PAGE_SHIFT
+        if (MemoryArea->Vad)
+        {
+            ASSERT(MemoryArea->VadNode.EndingVpn + 1 < (ULONG_PTR)MmSystemRangeStart >> PAGE_SHIFT);
+            ASSERT(MemoryArea->Type == MEMORY_AREA_SECTION_VIEW || MemoryArea->Type == MEMORY_AREA_CACHE);
+
+            /* MmCleanProcessAddressSpace might have removed it (and this would be MmDeleteProcessAdressSpace) */
+            ASSERT(MemoryArea->VadNode.u.VadFlags.Spare != 0);
+            if (((PMMVAD)MemoryArea->Vad)->u.VadFlags.Spare == 1)
+            {
+                MiRemoveNode((PMMADDRESS_NODE)&MemoryArea->VadNode, &Process->VadRoot);
+            }
+
+            MemoryArea->Vad = NULL;
+        }
+        else
+        {
+            MiRemoveNode((PMMADDRESS_NODE)&MemoryArea->VadNode, &MiRosKernelVadRoot);
+        }
     }
 
-   /* 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;
-         }
-      }
-   }
-
-   ExFreePoolWithTag(MemoryArea, TAG_MAREA);
-
-   DPRINT("MmFreeMemoryAreaByNode() succeeded\n");
-
-   return STATUS_SUCCESS;
+#if DBG
+    MemoryArea->Magic = 'daeD';
+#endif
+    ExFreePoolWithTag(MemoryArea, TAG_MAREA);
+
+    DPRINT("MmFreeMemoryAreaByNode() succeeded\n");
+
+    return STATUS_SUCCESS;
 }
 
 /**
@@ -982,138 +413,153 @@ MmCreateMemoryArea(PMMSUPPORT AddressSpace,
                    ULONG_PTR Length,
                    ULONG Protect,
                    PMEMORY_AREA *Result,
-                   BOOLEAN FixedAddress,
                    ULONG AllocationFlags,
                    ULONG Granularity)
 {
-   ULONG_PTR tmpLength;
-   PMEMORY_AREA MemoryArea;
-
-   DPRINT("MmCreateMemoryArea(Type 0x%lx, BaseAddress %p, "
-          "*BaseAddress %p, Length %p, AllocationFlags %x, "
-          "FixedAddress %x, Result %p)\n",
-          Type, BaseAddress, *BaseAddress, Length, AllocationFlags,
-          FixedAddress, Result);
-
-   if ((*BaseAddress) == 0 && !FixedAddress)
-   {
-      tmpLength = (ULONG_PTR)MM_ROUND_UP(Length, Granularity);
-      *BaseAddress = MmFindGap(AddressSpace,
-                               tmpLength,
-                               Granularity,
-                               (AllocationFlags & MEM_TOP_DOWN) == MEM_TOP_DOWN);
-      if ((*BaseAddress) == 0)
-      {
-         DPRINT("No suitable gap\n");
-         return STATUS_NO_MEMORY;
-      }
-   }
-   else
-   {
-      tmpLength = Length + ((ULONG_PTR) *BaseAddress
-                         - (ULONG_PTR) MM_ROUND_DOWN(*BaseAddress, Granularity));
-      tmpLength = (ULONG_PTR)MM_ROUND_UP(tmpLength, Granularity);
-      *BaseAddress = MM_ROUND_DOWN(*BaseAddress, Granularity);
-
-      if (!MmGetAddressSpaceOwner(AddressSpace) && *BaseAddress < MmSystemRangeStart)
-      {
-         return STATUS_ACCESS_VIOLATION;
-      }
-
-      if (MmGetAddressSpaceOwner(AddressSpace) &&
-          (ULONG_PTR)(*BaseAddress) + tmpLength > (ULONG_PTR)MmSystemRangeStart)
-      {
-         DPRINT("Memory area for user mode address space exceeds MmSystemRangeStart\n");
-         return STATUS_ACCESS_VIOLATION;
-      }
-
-      if (MmLocateMemoryAreaByRegion(AddressSpace,
-                                     *BaseAddress,
-                                     tmpLength) != NULL)
-      {
-         DPRINT("Memory area already occupied\n");
-         return STATUS_CONFLICTING_ADDRESSES;
-      }
-   }
-
-    //
-    // Is this a static memory area?
-    //
+    ULONG_PTR tmpLength;
+    PMEMORY_AREA MemoryArea;
+    ULONG_PTR EndingAddress;
+
+    DPRINT("MmCreateMemoryArea(Type 0x%lx, BaseAddress %p, "
+           "*BaseAddress %p, Length %p, AllocationFlags %x, "
+           "Result %p)\n",
+           Type, BaseAddress, *BaseAddress, Length, AllocationFlags,
+           Result);
+
+    /* Is this a static memory area? */
     if (Type & MEMORY_AREA_STATIC)
     {
-        //
-        // Use the static array instead of the pool
-        //
+        /* Use the static array instead of the pool */
         ASSERT(MiStaticMemoryAreaCount < MI_STATIC_MEMORY_AREAS);
         MemoryArea = &MiStaticMemoryAreas[MiStaticMemoryAreaCount++];
-        Type &= ~MEMORY_AREA_STATIC;
     }
     else
     {
-        //
-        // Allocate the memory area from nonpaged pool
-        //
+        /* 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;
-   }
+    if (!MemoryArea)
+    {
+        DPRINT1("Not enough memory.\n");
+        return STATUS_NO_MEMORY;
+    }
 
-   RtlZeroMemory(MemoryArea, sizeof(MEMORY_AREA));
-   MemoryArea->Type = Type;
-   MemoryArea->StartingAddress = *BaseAddress;
-   MemoryArea->EndingAddress = (PVOID)((ULONG_PTR)*BaseAddress + tmpLength);
-   MemoryArea->Protect = Protect;
-   MemoryArea->Flags = AllocationFlags;
-   //MemoryArea->LockCount = 0;
-   MemoryArea->Magic = 'erAM';
-   MemoryArea->DeleteInProgress = FALSE;
+    RtlZeroMemory(MemoryArea, sizeof(MEMORY_AREA));
+    MemoryArea->Type = Type & ~MEMORY_AREA_STATIC;
+    MemoryArea->Protect = Protect;
+    MemoryArea->Flags = AllocationFlags;
+    MemoryArea->Magic = 'erAM';
+    MemoryArea->DeleteInProgress = FALSE;
 
-   MmInsertMemoryArea(AddressSpace, MemoryArea);
+    if (*BaseAddress == 0)
+    {
+        tmpLength = (ULONG_PTR)MM_ROUND_UP(Length, PAGE_SIZE);
+        *BaseAddress = MmFindGap(AddressSpace,
+                                 tmpLength,
+                                 Granularity,
+                                 (AllocationFlags & MEM_TOP_DOWN) == MEM_TOP_DOWN);
+        if ((*BaseAddress) == 0)
+        {
+            DPRINT("No suitable gap\n");
+            if (!(Type & MEMORY_AREA_STATIC)) ExFreePoolWithTag(MemoryArea, TAG_MAREA);
+            return STATUS_NO_MEMORY;
+        }
 
-   *Result = MemoryArea;
+        MemoryArea->VadNode.StartingVpn = (ULONG_PTR)*BaseAddress >> PAGE_SHIFT;
+        MemoryArea->VadNode.EndingVpn = ((ULONG_PTR)*BaseAddress + tmpLength - 1) >> PAGE_SHIFT;
+        MmInsertMemoryArea(AddressSpace, MemoryArea);
+    }
+    else
+    {
+        EndingAddress = ((ULONG_PTR)*BaseAddress + Length - 1) | (PAGE_SIZE - 1);
+        *BaseAddress = ALIGN_DOWN_POINTER_BY(*BaseAddress, Granularity);
+        tmpLength = EndingAddress + 1 - (ULONG_PTR)*BaseAddress;
+
+        if (!MmGetAddressSpaceOwner(AddressSpace) && *BaseAddress < MmSystemRangeStart)
+        {
+            ASSERT(FALSE);
+            if (!(Type & MEMORY_AREA_STATIC)) ExFreePoolWithTag(MemoryArea, TAG_MAREA);
+            return STATUS_ACCESS_VIOLATION;
+        }
 
-   DPRINT("MmCreateMemoryArea() succeeded (%p)\n", *BaseAddress);
-   return STATUS_SUCCESS;
+        if (MmGetAddressSpaceOwner(AddressSpace) &&
+                (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;
+        }
+
+        /* No need to check ARM3 owned memory areas, the range MUST be free */
+        if (MemoryArea->Type != MEMORY_AREA_OWNED_BY_ARM3)
+        {
+            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->VadNode.StartingVpn = (ULONG_PTR)*BaseAddress >> PAGE_SHIFT;
+        MemoryArea->VadNode.EndingVpn = ((ULONG_PTR)*BaseAddress + tmpLength - 1) >> PAGE_SHIFT;
+        MmInsertMemoryArea(AddressSpace, MemoryArea);
+    }
+
+    *Result = MemoryArea;
+
+    DPRINT("MmCreateMemoryArea() succeeded (%p)\n", *BaseAddress);
+    return STATUS_SUCCESS;
 }
 
-VOID NTAPI
-MmMapMemoryArea(PVOID BaseAddress,
-                SIZE_T Length,
-                ULONG Consumer,
-                ULONG Protection)
+VOID
+NTAPI
+MiRosCleanupMemoryArea(
+    PEPROCESS Process,
+    PMMVAD Vad)
 {
-   ULONG i;
-   NTSTATUS Status;
-
-   ASSERT(((ULONG_PTR)BaseAddress % PAGE_SIZE) == 0);
-
-   for (i = 0; i < PAGE_ROUND_UP(Length) / PAGE_SIZE; i++)
-   {
-      PFN_NUMBER Page;
-
-      Status = MmRequestPageMemoryConsumer(Consumer, TRUE, &Page);
-      if (!NT_SUCCESS(Status))
-      {
-         DPRINT1("Unable to allocate page\n");
-         KeBugCheck(MEMORY_MANAGEMENT);
-      }
-      Status = MmCreateVirtualMapping (NULL,
-                                       (PVOID)((ULONG_PTR)BaseAddress + (i * PAGE_SIZE)),
-                                       Protection,
-                                       &Page,
-                                       1);
-      if (!NT_SUCCESS(Status))
-      {
-         DPRINT1("Unable to create virtual mapping\n");
-         KeBugCheck(MEMORY_MANAGEMENT);
-      }
-   }
+    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)
+    {
+        Status = MiRosUnmapViewOfSection(Process, BaseAddress, Process->ProcessExiting);
+    }
+    else if (MemoryArea->Type == MEMORY_AREA_CACHE)
+    {
+        Status = MmUnmapViewOfCacheSegment(&Process->Vm, BaseAddress);
+    }
+    else
+    {
+        /* There shouldn't be anything else! */
+        ASSERT(FALSE);
+    }
+
+    /* Make sure this worked! */
+    ASSERT(NT_SUCCESS(Status));
+
+    /* Lock the address space again */
+    MmLockAddressSpace(&Process->Vm);
 }
 
 VOID
@@ -1124,46 +570,21 @@ NTSTATUS
 NTAPI
 MmDeleteProcessAddressSpace(PEPROCESS Process)
 {
-   PVOID Address;
-   PMEMORY_AREA MemoryArea;
+    KIRQL OldIrql;
+    PVOID Address;
 
-   DPRINT("MmDeleteProcessAddressSpace(Process %p (%s))\n", Process,
-          Process->ImageFileName);
+    DPRINT("MmDeleteProcessAddressSpace(Process %p (%s))\n", Process,
+           Process->ImageFileName);
 
 #ifndef _M_AMD64
-   RemoveEntryList(&Process->MmProcessLinks);
+    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)MemoryArea->StartingAddress;
-             MmUnlockAddressSpace(&Process->Vm);
-             MmUnmapViewOfSection(Process, Address);
-             MmLockAddressSpace(&Process->Vm);
-             break;
-
-         case MEMORY_AREA_CACHE:
-             Address = (PVOID)MemoryArea->StartingAddress;
-             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);
-      }
-   }
+    MmLockAddressSpace(&Process->Vm);
+
+    /* There should not be any memory areas left! */
+    ASSERT(Process->Vm.WorkingSetExpansionLinks.Flink == NULL);
 
 #if (_MI_PAGING_LEVELS == 2)
     {
@@ -1173,11 +594,11 @@ MmDeleteProcessAddressSpace(PEPROCESS Process)
         KeAttachProcess(&Process->Pcb);
 
         /* Acquire PFN lock */
-        OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
+        OldIrql = MiAcquirePfnLock();
 
         for (Address = MI_LOWEST_VAD_ADDRESS;
-             Address < MM_HIGHEST_VAD_ADDRESS;
-             Address =(PVOID)((ULONG_PTR)Address + (PAGE_SIZE * PTE_COUNT)))
+                Address < MM_HIGHEST_VAD_ADDRESS;
+                Address =(PVOID)((ULONG_PTR)Address + (PAGE_SIZE * PTE_COUNT)))
         {
             /* At this point all references should be dead */
             if (MiQueryPageTableReferences(Address) != 0)
@@ -1188,6 +609,7 @@ MmDeleteProcessAddressSpace(PEPROCESS Process)
                         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 */
@@ -1195,19 +617,20 @@ MmDeleteProcessAddressSpace(PEPROCESS Process)
                 MiDeletePte(pointerPde, MiPdeToPte(pointerPde), Process, NULL);
             ASSERT(pointerPde->u.Hard.Valid == 0);
         }
+
         /* Release lock */
-        KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
+        MiReleasePfnLock(OldIrql);
 
         /* Detach */
         KeDetachProcess();
     }
 #endif
 
-   MmUnlockAddressSpace(&Process->Vm);
+    MmUnlockAddressSpace(&Process->Vm);
 
-   DPRINT("Finished MmReleaseMmInfo()\n");
-   MmDeleteProcessAddressSpace2(Process);
-   return(STATUS_SUCCESS);
+    DPRINT("Finished MmDeleteProcessAddressSpace()\n");
+    MmDeleteProcessAddressSpace2(Process);
+    return(STATUS_SUCCESS);
 }
 
 /* EOF */