#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 ********************************************************************/
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;
}
}
}
OUT PULONG_PTR Base)
{
PMMADDRESS_NODE Node, PreviousNode;
- ULONG_PTR PageCount, AlignmentVpn, LowVpn, HighVpn;
+ ULONG_PTR PageCount, AlignmentVpn, LowVpn, HighestVpn;
ASSERT(Length != 0);
/* Calculate page numbers for the length, alignment, and starting address */
AlignmentVpn = Alignment >> PAGE_SHIFT;
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 empty */
if (Table->NumberGenericTableElements == 0)
{
}
/* We're up to the highest VAD, will this allocation fit above it? */
- HighVpn = ((ULONG_PTR)MM_HIGHEST_VAD_ADDRESS + 1) / PAGE_SIZE;
- if (HighVpn >= LowVpn + PageCount)
+ 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);
+ }
+
+ if (HighestVpn >= LowVpn + PageCount)
{
/* Yes! Use this VAD to store the allocation */
*PreviousVad = PreviousNode;
OUT PULONG_PTR Base,
OUT PMMADDRESS_NODE *Parent)
{
- PMMADDRESS_NODE Node, OldNode, Child;
+ PMMADDRESS_NODE Node, OldNode = NULL, Child;
ULONG_PTR LowVpn, HighVpn, AlignmentVpn;
PFN_NUMBER PageCount;
PageCount = Length >> PAGE_SHIFT;
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 ((ALIGN_UP_BY((ULONG_PTR)MM_LOWEST_USER_ADDRESS, Alignment) + Length) >
- (BoundaryAddress + 1))
+ if ((LowVpn + Length) > (BoundaryAddress + 1))
{
return TableFoundNode;
}
}
else
{
- /* Node has a right child, the node we had before is the most
- left grandchild of that right child, use it as parent. */
+ /* 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;
}