#include <debug.h>
#define MODULE_INVOLVED_IN_ARM3
-#include "../ARM3/miarm.h"
+#include <mm/ARM3/miarm.h>
/* Include Mm version of AVL support */
-#include "../ARM3/miavl.h"
-#include "../../../lib/rtl/avlsupp.c"
+#include "miavl.h"
+#include <sdk/lib/rtl/avlsupp.c>
/* GLOBALS ********************************************************************/
return FoundVad;
}
-PMMADDRESS_NODE
+TABLE_SEARCH_RESULT
NTAPI
MiCheckForConflictingNode(IN ULONG_PTR StartVpn,
IN ULONG_PTR EndVpn,
- IN PMM_AVL_TABLE Table)
+ IN PMM_AVL_TABLE Table,
+ OUT PMMADDRESS_NODE *NodeOrParent)
{
- PMMADDRESS_NODE CurrentNode;
+ PMMADDRESS_NODE ParentNode, CurrentNode;
/* If the tree is empty, there is no conflict */
- if (!Table->NumberGenericTableElements) return NULL;
+ if (Table->NumberGenericTableElements == 0) return TableEmptyTree;
- /* Start looping from the right */
+ /* Start looping from the root node */
CurrentNode = RtlRightChildAvl(&Table->BalancedRoot);
ASSERT(CurrentNode != NULL);
while (CurrentNode)
{
+ ParentNode = CurrentNode;
+
/* This address comes after */
if (StartVpn > CurrentNode->EndingVpn)
{
else
{
/* This address is part of this node, return it */
- break;
+ *NodeOrParent = ParentNode;
+ return TableFoundNode;
}
}
- /* Return either the conflicting node, or no node at all */
- return CurrentNode;
+ /* There is no more child, save the current node as parent */
+ *NodeOrParent = ParentNode;
+ if (StartVpn > ParentNode->EndingVpn)
+ {
+ return TableInsertAsRight;
+ }
+ else
+ {
+ return TableInsertAsLeft;
+ }
}
VOID
PVOID AllocatedBase = (PVOID)(Vad->StartingVpn << PAGE_SHIFT);
Size = ((Vad->EndingVpn + 1) - Vad->StartingVpn) << PAGE_SHIFT;
+
+ if (AllocatedBase == NULL)
+ {
+ AllocatedBase = (PVOID)(ULONG_PTR)1;
+ Size -= 1;
+ }
+
Status = MmCreateMemoryArea(&Process->Vm,
MEMORY_AREA_OWNED_BY_ARM3,
&AllocatedBase,
Size,
PAGE_READWRITE,
&MemoryArea,
- TRUE,
0,
PAGE_SIZE);
ASSERT(NT_SUCCESS(Status));
else
{
/* This is a section VAD. Store the MAREA here for now */
- ASSERT(Vad->u4.Banked == (PVOID)0xDEADBABE);
+ ASSERT(Vad->u4.Banked == (PVOID)(ULONG_PTR)0xDEADBABEDEADBABEULL);
Vad->u4.Banked = (PVOID)MemoryArea;
}
}
VOID
NTAPI
MiInsertVad(IN PMMVAD Vad,
- IN PEPROCESS Process)
+ IN PMM_AVL_TABLE VadRoot)
{
TABLE_SEARCH_RESULT Result;
PMMADDRESS_NODE Parent = NULL;
/* Validate the VAD and set it as the current hint */
ASSERT(Vad->EndingVpn >= Vad->StartingVpn);
- Process->VadRoot.NodeHint = Vad;
+ VadRoot->NodeHint = Vad;
/* Find the parent VAD and where this child should be inserted */
- Result = RtlpFindAvlTableNodeOrParent(&Process->VadRoot, (PVOID)Vad->StartingVpn, &Parent);
+ Result = RtlpFindAvlTableNodeOrParent(VadRoot, (PVOID)Vad->StartingVpn, &Parent);
ASSERT(Result != TableFoundNode);
ASSERT((Parent != NULL) || (Result == TableEmptyTree));
/* Do the actual insert operation */
- MiInsertNode(&Process->VadRoot, (PVOID)Vad, Parent, Result);
+ MiInsertNode(VadRoot, (PVOID)Vad, Parent, Result);
+}
+
+NTSTATUS
+NTAPI
+MiInsertVadEx(
+ _Inout_ PMMVAD Vad,
+ _In_ ULONG_PTR *BaseAddress,
+ _In_ SIZE_T ViewSize,
+ _In_ ULONG_PTR HighestAddress,
+ _In_ ULONG_PTR Alignment,
+ _In_ ULONG AllocationType)
+{
+ ULONG_PTR StartingAddress, EndingAddress;
+ PEPROCESS CurrentProcess;
+ PETHREAD CurrentThread;
+ TABLE_SEARCH_RESULT Result;
+ PMMADDRESS_NODE Parent;
+
+ /* Align the view size to pages */
+ ViewSize = ALIGN_UP_BY(ViewSize, PAGE_SIZE);
+
+ /* Get the current process */
+ CurrentProcess = PsGetCurrentProcess();
+
+ /* Acquire the address creation lock and make sure the process is alive */
+ KeAcquireGuardedMutex(&CurrentProcess->AddressCreationLock);
+ if (CurrentProcess->VmDeleted)
+ {
+ KeReleaseGuardedMutex(&CurrentProcess->AddressCreationLock);
+ DPRINT1("The process is dying\n");
+ return STATUS_PROCESS_IS_TERMINATING;
+ }
+
+ /* Did the caller specify an address? */
+ if (*BaseAddress == 0)
+ {
+ /* Make sure HighestAddress is not too large */
+ HighestAddress = min(HighestAddress, (ULONG_PTR)MM_HIGHEST_VAD_ADDRESS);
+
+ /* Which way should we search? */
+ if ((AllocationType & MEM_TOP_DOWN) || CurrentProcess->VmTopDown)
+ {
+ /* Find an address top-down */
+ Result = MiFindEmptyAddressRangeDownTree(ViewSize,
+ HighestAddress,
+ Alignment,
+ &CurrentProcess->VadRoot,
+ &StartingAddress,
+ &Parent);
+ }
+ else
+ {
+ /* Find an address bottom-up */
+ Result = MiFindEmptyAddressRangeInTree(ViewSize,
+ Alignment,
+ &CurrentProcess->VadRoot,
+ &Parent,
+ &StartingAddress);
+ }
+
+ /* Get the ending address, which is the last piece we need for the VAD */
+ EndingAddress = StartingAddress + ViewSize - 1;
+
+ /* Check if we found a suitable location */
+ if ((Result == TableFoundNode) || (EndingAddress > HighestAddress))
+ {
+ DPRINT1("Not enough free space to insert this VAD node!\n");
+ KeReleaseGuardedMutex(&CurrentProcess->AddressCreationLock);
+ return STATUS_NO_MEMORY;
+ }
+
+ ASSERT(StartingAddress != 0);
+ ASSERT(StartingAddress < (ULONG_PTR)HighestAddress);
+ ASSERT(EndingAddress > StartingAddress);
+ }
+ else
+ {
+ /* Calculate the starting and ending address */
+ StartingAddress = ALIGN_DOWN_BY(*BaseAddress, Alignment);
+ EndingAddress = StartingAddress + ViewSize - 1;
+
+ /* Make sure it doesn't conflict with an existing allocation */
+ Result = MiCheckForConflictingNode(StartingAddress >> PAGE_SHIFT,
+ EndingAddress >> PAGE_SHIFT,
+ &CurrentProcess->VadRoot,
+ &Parent);
+ if (Result == TableFoundNode)
+ {
+ DPRINT("Given address conflicts with existing node\n");
+ KeReleaseGuardedMutex(&CurrentProcess->AddressCreationLock);
+ return STATUS_CONFLICTING_ADDRESSES;
+ }
+ }
+
+ /* Now set the VAD address */
+ Vad->StartingVpn = StartingAddress >> PAGE_SHIFT;
+ Vad->EndingVpn = EndingAddress >> PAGE_SHIFT;
+
+ /* Check if we already need to charge for the pages */
+ if ((Vad->u.VadFlags.PrivateMemory && Vad->u.VadFlags.MemCommit) ||
+ (!Vad->u.VadFlags.PrivateMemory &&
+ (Vad->u.VadFlags.Protection & PAGE_WRITECOPY)))
+ {
+ /* Set the commit charge */
+ Vad->u.VadFlags.CommitCharge = ViewSize / PAGE_SIZE;
+ }
+
+ /* Check if the VAD is to be secured */
+ if (Vad->u2.VadFlags2.OneSecured)
+ {
+ /* This *must* be a long VAD! */
+ ASSERT(Vad->u2.VadFlags2.LongVad);
+
+ /* Yeah this is retarded, I didn't invent it! */
+ ((PMMVAD_LONG)Vad)->u3.Secured.StartVpn = StartingAddress;
+ ((PMMVAD_LONG)Vad)->u3.Secured.EndVpn = EndingAddress;
+ }
+
+ /* Lock the working set */
+ CurrentThread = PsGetCurrentThread();
+ MiLockProcessWorkingSetUnsafe(CurrentProcess, CurrentThread);
+
+ /* Insert the VAD */
+ CurrentProcess->VadRoot.NodeHint = Vad;
+ MiInsertNode(&CurrentProcess->VadRoot, (PVOID)Vad, Parent, Result);
+
+ /* Release the working set */
+ MiUnlockProcessWorkingSetUnsafe(CurrentProcess, CurrentThread);
+
+ /* Update the process' virtual size, and peak virtual size */
+ CurrentProcess->VirtualSize += ViewSize;
+ if (CurrentProcess->VirtualSize > CurrentProcess->PeakVirtualSize)
+ {
+ CurrentProcess->PeakVirtualSize = CurrentProcess->VirtualSize;
+ }
+
+ /* Unlock the address space */
+ KeReleaseGuardedMutex(&CurrentProcess->AddressCreationLock);
+
+ *BaseAddress = StartingAddress;
+ return STATUS_SUCCESS;
}
VOID
/* Free the node from ReactOS view as well */
Vad = (PMMVAD_LONG)Node;
- if (Vad->u.VadFlags.Spare == 0)
+ if ((Table != &MmSectionBasedRoot) && (Vad->u.VadFlags.Spare == 0))
{
PMEMORY_AREA MemoryArea;
PEPROCESS Process;
if (MemoryArea)
{
/* Make sure we have not already freed it */
- ASSERT(MemoryArea != (PVOID)0xDEADBAB1);
+ ASSERT(MemoryArea != (PVOID)(ULONG_PTR)0xDEADBAB1DEADBAB1ULL);
/* Get the process */
Process = CONTAINING_RECORD(Table, EPROCESS, VadRoot);
if (Vad->ControlArea == NULL)
{
/* Delete the pointer to it */
- Vad->FirstPrototypePte = (PVOID)0xDEADBAB1;
+ Vad->FirstPrototypePte = (PVOID)(ULONG_PTR)0xDEADBAB1DEADBAB1ULL;
}
else
{
/* Delete the pointer to it */
- Vad->u4.Banked = (PVOID)0xDEADBAB1;
+ Vad->u4.Banked = (PVOID)(ULONG_PTR)0xDEADBAB1DEADBAB1ULL;
}
}
}
return NULL;
}
-NTSTATUS
+TABLE_SEARCH_RESULT
NTAPI
MiFindEmptyAddressRangeInTree(IN SIZE_T Length,
IN ULONG_PTR Alignment,
OUT PMMADDRESS_NODE *PreviousVad,
OUT PULONG_PTR Base)
{
- PMMADDRESS_NODE Node;
- PMMADDRESS_NODE NextNode;
- ULONG_PTR StartingVpn, HighestVpn, AlignmentVpn, LengthVpn, LowVpn;
+ PMMADDRESS_NODE Node, PreviousNode;
+ ULONG_PTR PageCount, AlignmentVpn, LowVpn, HighestVpn;
ASSERT(Length != 0);
- /* Precompute page numbers for the length, alignment, and starting address */
- LengthVpn = (Length + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
+ /* Calculate page numbers for the length, alignment, and starting address */
+ PageCount = BYTES_TO_PAGES(Length);
AlignmentVpn = Alignment >> PAGE_SHIFT;
- StartingVpn = ROUND_UP((ULONG_PTR)MM_LOWEST_USER_ADDRESS >> PAGE_SHIFT,
- AlignmentVpn);
+ LowVpn = ALIGN_UP_BY((ULONG_PTR)MM_LOWEST_USER_ADDRESS >> PAGE_SHIFT, AlignmentVpn);
+
+ /* Check for kernel mode table (memory areas) */
+ if (Table->Unused == 1)
+ {
+ LowVpn = ALIGN_UP_BY((ULONG_PTR)MmSystemRangeStart >> PAGE_SHIFT, AlignmentVpn);
+ }
- /* Check if the table is free, so the lowest possible address is available */
- if (!Table->NumberGenericTableElements) goto FoundAtBottom;
+ /* Check if the table is empty */
+ if (Table->NumberGenericTableElements == 0)
+ {
+ /* Tree is empty, the candidate address is already the best one */
+ *Base = LowVpn << PAGE_SHIFT;
+ return TableEmptyTree;
+ }
/* Otherwise, follow the leftmost child of the right root node's child */
Node = RtlRightChildAvl(&Table->BalancedRoot);
while (RtlLeftChildAvl(Node)) Node = RtlLeftChildAvl(Node);
- /* This is the node for the remaining gap at the bottom, can it be used? */
- if ((Node->StartingVpn > StartingVpn) &&
- (LengthVpn < Node->StartingVpn - StartingVpn))
+ /* Start a search to find a gap */
+ PreviousNode = NULL;
+ while (Node != NULL)
{
-FoundAtBottom:
- /* Use this VAD to store the allocation */
- *PreviousVad = NULL;
- *Base = StartingVpn << PAGE_SHIFT;
- return STATUS_SUCCESS;
- }
+ /* Check if the gap below the current node is suitable */
+ if (Node->StartingVpn >= LowVpn + PageCount)
+ {
+ /* There is enough space to add our node */
+ *Base = LowVpn << PAGE_SHIFT;
- /* Otherwise, we start a search to find a gap */
- while (TRUE)
- {
- /* The last aligned page number in this entry */
- LowVpn = ROUND_UP(Node->EndingVpn + 1, AlignmentVpn);
+ /* Can we use the current node as parent? */
+ if (RtlLeftChildAvl(Node) == NULL)
+ {
+ /* Node has no left child, so use it as parent */
+ *PreviousVad = Node;
+ return TableInsertAsLeft;
+ }
+ else
+ {
+ /* Node has a left child, this means that the previous node is
+ the right-most child of it's left child and can be used as
+ the parent. In case we use the space before the left-most
+ node, it's left child must be NULL. */
+ ASSERT(PreviousNode != NULL);
+ ASSERT(RtlRightChildAvl(PreviousNode) == NULL);
+ *PreviousVad = PreviousNode;
+ return TableInsertAsRight;
+ }
+ }
- /* Keep going as long as there's still a next node */
- NextNode = MiGetNextNode(Node);
- if (!NextNode) break;
+ /* The next candidate is above the current node */
+ if (Node->EndingVpn >= LowVpn)
+ LowVpn = ALIGN_UP_BY(Node->EndingVpn + 1, AlignmentVpn);
- /* Can this allocation fit in this node? */
- if ((LengthVpn <= (NextNode->StartingVpn - LowVpn)) &&
- (NextNode->StartingVpn > LowVpn))
- {
-Found:
- /* Yes! Use this VAD to store the allocation */
- *PreviousVad = Node;
- *Base = ROUND_UP((Node->EndingVpn << PAGE_SHIFT) | (PAGE_SIZE - 1),
- Alignment);
- return STATUS_SUCCESS;
- }
+ /* Remember the current node and go to the next node */
+ PreviousNode = Node;
+ Node = MiGetNextNode(Node);
+ }
- /* Try the next node */
- Node = NextNode;
+ /* We're up to the highest VAD, will this allocation fit above it? */
+ HighestVpn = ((ULONG_PTR)MM_HIGHEST_VAD_ADDRESS + 1) / PAGE_SIZE;
+
+ /* Check for kernel mode table (memory areas) */
+ if (Table->Unused == 1)
+ {
+ HighestVpn = ALIGN_UP_BY((ULONG_PTR)(LONG_PTR)-1 >> PAGE_SHIFT, AlignmentVpn);
}
- /* We're down to the last (top) VAD, will this allocation fit inside it? */
- HighestVpn = ((ULONG_PTR)MM_HIGHEST_VAD_ADDRESS + 1) >> PAGE_SHIFT;
- if ((HighestVpn > LowVpn) && (LengthVpn <= HighestVpn - LowVpn)) goto Found;
+ if (HighestVpn >= LowVpn + PageCount)
+ {
+ /* Yes! Use this VAD to store the allocation */
+ *PreviousVad = PreviousNode;
+ *Base = LowVpn << PAGE_SHIFT;
+ return TableInsertAsRight;
+ }
/* Nyet, there's no free address space for this allocation, so we'll fail */
- return STATUS_NO_MEMORY;
+ return TableFoundNode;
}
TABLE_SEARCH_RESULT
OUT PULONG_PTR Base,
OUT PMMADDRESS_NODE *Parent)
{
- PMMADDRESS_NODE Node, LowestNode, Child;
- ULONG_PTR LowVpn, HighVpn;
+ PMMADDRESS_NODE Node, OldNode = NULL, Child;
+ ULONG_PTR LowVpn, HighVpn, AlignmentVpn;
PFN_NUMBER PageCount;
/* Sanity checks */
ASSERT(BoundaryAddress);
- ASSERT(BoundaryAddress <= ((ULONG_PTR)MM_HIGHEST_VAD_ADDRESS + 1));
+ ASSERT(BoundaryAddress <= ((ULONG_PTR)MM_HIGHEST_VAD_ADDRESS));
+ ASSERT((Alignment & (PAGE_SIZE - 1)) == 0);
- /* Compute page length, make sure the boundary address is valid */
+ /* Calculate page numbers for the length and alignment */
Length = ROUND_TO_PAGES(Length);
PageCount = Length >> PAGE_SHIFT;
- if ((BoundaryAddress + 1) < Length) return TableFoundNode;
+ AlignmentVpn = Alignment / PAGE_SIZE;
+
+ /* Check for kernel mode table (memory areas) */
+ if (Table->Unused == 1)
+ {
+ LowVpn = ALIGN_UP_BY((ULONG_PTR)MmSystemRangeStart >> PAGE_SHIFT, AlignmentVpn);
+ }
+ else
+ {
+ LowVpn = ALIGN_UP_BY((ULONG_PTR)MM_LOWEST_USER_ADDRESS, Alignment);
+ }
+
+ /* Check if there is enough space below the boundary */
+ if ((LowVpn + Length) > (BoundaryAddress + 1))
+ {
+ return TableFoundNode;
+ }
/* Check if the table is empty */
if (Table->NumberGenericTableElements == 0)
{
/* Tree is empty, the candidate address is already the best one */
- *Base = ROUND_UP(BoundaryAddress + 1 - Length, Alignment);
+ *Base = ALIGN_DOWN_BY(BoundaryAddress + 1 - Length, Alignment);
return TableEmptyTree;
}
/* Calculate the initial upper margin */
- HighVpn = BoundaryAddress >> PAGE_SHIFT;
+ HighVpn = (BoundaryAddress + 1) >> PAGE_SHIFT;
- /* Starting from the root, go down until the right-most child
- * which is just behind the boundary*/
- LowestNode = Node = RtlRightChildAvl(&Table->BalancedRoot);
- while (((Child = RtlRightChildAvl(Node)) != 0 )
- && (Node->EndingVpn < HighVpn )) Node = Child;
+ /* Starting from the root, follow the right children until we found a node
+ that ends above the boundary */
+ Node = RtlRightChildAvl(&Table->BalancedRoot);
+ while ((Node->EndingVpn < HighVpn) &&
+ ((Child = RtlRightChildAvl(Node)) != NULL)) Node = Child;
/* Now loop the Vad nodes */
while (Node)
{
- /* Keep track of the lowest node */
- LowestNode = Node;
-
/* Calculate the lower margin */
- LowVpn = ROUND_UP(Node->EndingVpn + 1, Alignment >> PAGE_SHIFT);
+ LowVpn = ALIGN_UP_BY(Node->EndingVpn + 1, AlignmentVpn);
/* Check if the current bounds are suitable */
if ((HighVpn > LowVpn) && ((HighVpn - LowVpn) >= PageCount))
{
/* There is enough space to add our node */
- LowVpn = HighVpn - PageCount;
+ LowVpn = ALIGN_DOWN_BY(HighVpn - PageCount, AlignmentVpn);
*Base = LowVpn << PAGE_SHIFT;
/* Can we use the current node as parent? */
- Child = RtlRightChildAvl(Node);
- if (!Child)
+ if (!RtlRightChildAvl(Node))
{
/* Node has no right child, so use it as parent */
*Parent = Node;
}
else
{
- /* Node has a right child, find most left grand child */
- Node = Child;
- while ((Child = RtlLeftChildAvl(Node))) Node = Child;
- *Parent = Node;
+ /* Node has a right child. This means we must have already
+ moved one node left from the right-most node we started
+ with, thus we already have an OldNode! */
+ ASSERT(OldNode != NULL);
+
+ /* The node we had before is the most left grandchild of
+ that right child, use it as parent. */
+ ASSERT(RtlLeftChildAvl(OldNode) == NULL);
+ *Parent = OldNode;
return TableInsertAsLeft;
}
}
- /* Update the upper margin if neccessary */
+ /* Update the upper margin if necessary */
if (Node->StartingVpn < HighVpn) HighVpn = Node->StartingVpn;
- /* Go to the next lower node */
+ /* Remember the current node and go to the previous node */
+ OldNode = Node;
Node = MiGetPreviousNode(Node);
}
/* Check if there's enough space before the lowest Vad */
- LowVpn = ROUND_UP((ULONG_PTR)MI_LOWEST_VAD_ADDRESS, Alignment) >> PAGE_SHIFT;
+ LowVpn = ALIGN_UP_BY((ULONG_PTR)MI_LOWEST_VAD_ADDRESS, Alignment) / PAGE_SIZE;
if ((HighVpn > LowVpn) && ((HighVpn - LowVpn) >= PageCount))
{
/* There is enough space to add our address */
- LowVpn = HighVpn - PageCount;
+ LowVpn = ALIGN_DOWN_BY(HighVpn - PageCount, Alignment >> PAGE_SHIFT);
*Base = LowVpn << PAGE_SHIFT;
- *Parent = LowestNode;
+ *Parent = OldNode;
return TableInsertAsLeft;
}
if ((BoundaryAddress + 1) < Length) return STATUS_NO_MEMORY;
/* Check if the table is empty */
- BestVpn = ROUND_UP(BoundaryAddress + 1 - Length, Alignment);
+ BestVpn = ROUND_DOWN(BoundaryAddress + 1 - Length, Alignment);
if (Table->NumberGenericTableElements == 0)
{
/* Tree is empty, the candidate address is already the best one */
while (RtlRightChildAvl(Node)) Node = RtlRightChildAvl(Node);
/* Check if we can fit in here */
- LowVpn = ROUND_UP(Node->EndingVpn, Alignment);
- if ((LowVpn < BoundaryAddress) && (Length < (BoundaryAddress - LowVpn)))
+ LowVpn = ROUND_UP(Node->EndingVpn + 1, Alignment);
+ if ((LowVpn < BoundaryAddress) && (Length <= (BoundaryAddress - LowVpn)))
{
- /* Return the address */
- *Base = ROUND_UP(BoundaryAddress - Length, Alignment);
+#if (NTDDI_VERSION >= NTDDI_VISTA)
+ /* Return the address. */
+ *Base = BestVpn;
+#else
+ /* Note: this is a compatibility hack that mimics a bug in the 2k3
+ kernel. It will can waste up to Alignment bytes of memory above
+ the allocation. This bug was fixed in Windows Vista */
+ *Base = ROUND_DOWN(BoundaryAddress - Length, Alignment);
+#endif
return STATUS_SUCCESS;
}
/* Check if this node could contain the requested address */
LowVpn = ROUND_UP(LowestNode->EndingVpn + 1, Alignment);
if ((LowestNode->EndingVpn < BestVpn) &&
+ (LowVpn < Node->StartingVpn) &&
(Length <= (Node->StartingVpn - LowVpn)))
{
- /* Check if it fits in perfectly */
- if ((BestVpn > LowestNode->EndingVpn) &&
- (BoundaryAddress < Node->StartingVpn))
+ /* Check if we need to take BoundaryAddress into account */
+ if (BoundaryAddress < Node->StartingVpn)
{
/* Return the optimal VPN address */
*Base = BestVpn;
return STATUS_SUCCESS;
}
-
- /* It doesn't, check if it can partly fit */
- if (Node->StartingVpn > LowVpn)
+ else
{
- /* Return an aligned base address within this node */
- *Base = ROUND_UP(Node->StartingVpn - Length, Alignment);
+ /* The upper margin is given by the Node's starting address */
+ *Base = ROUND_DOWN(Node->StartingVpn - Length, Alignment);
return STATUS_SUCCESS;
}
}
/* Check if there's enough space before the lowest Vad */
if ((Node->StartingVpn > (ULONG_PTR)MI_LOWEST_VAD_ADDRESS) &&
- ((Node->StartingVpn - (ULONG_PTR)MI_LOWEST_VAD_ADDRESS) > Length))
+ ((Node->StartingVpn - (ULONG_PTR)MI_LOWEST_VAD_ADDRESS) >= Length))
{
/* Check if it fits in perfectly */
if (BoundaryAddress < Node->StartingVpn)
}
/* Return an aligned base address within this node */
- *Base = ROUND_UP(Node->StartingVpn - Length, Alignment);
+ *Base = ROUND_DOWN(Node->StartingVpn - Length, Alignment);
return STATUS_SUCCESS;
}
}
/* EOF */
+