Author: tkreuzer Date: Wed Oct 8 00:31:17 2014 New Revision: 64589
URL: http://svn.reactos.org/svn/reactos?rev=64589&view=rev Log: [NTOSKRNL] Implement MiInsertVadEx, replacing duplicated code from NtAllocateVirtualMemory and MiMapViewOfDataSection
Modified: trunk/reactos/ntoskrnl/mm/ARM3/miarm.h trunk/reactos/ntoskrnl/mm/ARM3/section.c trunk/reactos/ntoskrnl/mm/ARM3/vadnode.c trunk/reactos/ntoskrnl/mm/ARM3/virtual.c
Modified: trunk/reactos/ntoskrnl/mm/ARM3/miarm.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/miarm.h?re... ============================================================================== --- trunk/reactos/ntoskrnl/mm/ARM3/miarm.h [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/mm/ARM3/miarm.h [iso-8859-1] Wed Oct 8 00:31:17 2014 @@ -2144,6 +2144,16 @@ IN PEPROCESS Process );
+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); + VOID NTAPI MiInsertBasedSection(
Modified: trunk/reactos/ntoskrnl/mm/ARM3/section.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/section.c?... ============================================================================== --- trunk/reactos/ntoskrnl/mm/ARM3/section.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/mm/ARM3/section.c [iso-8859-1] Wed Oct 8 00:31:17 2014 @@ -1252,9 +1252,7 @@ IN ULONG AllocationType) { PMMVAD_LONG Vad; - PETHREAD Thread = PsGetCurrentThread(); - PMMSUPPORT AddressSpace; - ULONG_PTR StartAddress, EndingAddress; + ULONG_PTR StartAddress; ULONG_PTR ViewSizeInPages; PSUBSECTION Subsection; PSEGMENT Segment; @@ -1263,8 +1261,6 @@ ULONG QuotaCharge = 0, QuotaExcess = 0; PMMPTE PointerPte, LastPte; MMPTE TempPte; - PMMADDRESS_NODE Parent; - TABLE_SEARCH_RESULT Result; DPRINT("Mapping ARM3 data section\n");
/* Get the segment for this section */ @@ -1361,6 +1357,7 @@
/* Write all the data required in the VAD for handling a fault */ Vad->ControlArea = ControlArea; + Vad->u.VadFlags.CommitCharge = 0; Vad->u.VadFlags.Protection = ProtectionMask; Vad->u2.VadFlags2.FileOffset = (ULONG)(SectionOffset->QuadPart >> 16); Vad->u2.VadFlags2.Inherit = (InheritDisposition == ViewShare); @@ -1437,100 +1434,23 @@ StartAddress = 0; }
- /* Lock the address space and make sure the process is alive */ - AddressSpace = MmGetCurrentAddressSpace(); - MmLockAddressSpace(AddressSpace); - if (Process->VmDeleted) - { - MmUnlockAddressSpace(AddressSpace); - ExFreePoolWithTag(Vad, 'ldaV'); - DPRINT1("The process is dying\n"); - return STATUS_PROCESS_IS_TERMINATING; - } - - /* Did the caller specify an address? */ - if (StartAddress == 0) - { - /* ARM3 does not support these flags yet */ - ASSERT(Process->VmTopDown == 0); - ASSERT(ZeroBits == 0); - - /* Which way should we search? */ - if (AllocationType & MEM_TOP_DOWN) - { - /* No, find an address top-down */ - Result = MiFindEmptyAddressRangeDownTree(*ViewSize, - (ULONG_PTR)MM_HIGHEST_VAD_ADDRESS, - _64K, - &Process->VadRoot, - &StartAddress, - &Parent); - } - else - { - /* No, find an address bottom-up */ - Result = MiFindEmptyAddressRangeInTree(*ViewSize, - _64K, - &Process->VadRoot, - &Parent, - &StartAddress); - } - - /* Check if we found a suitable location */ - if (Result == TableFoundNode) - { - DPRINT1("Not enough free space to insert this section!\n"); - MmUnlockAddressSpace(AddressSpace); - MiDereferenceControlArea(ControlArea); - ExFreePoolWithTag(Vad, 'ldaV'); - return STATUS_CONFLICTING_ADDRESSES; - } - - /* Get the ending address, which is the last piece we need for the VAD */ - EndingAddress = StartAddress + (ViewSizeInPages * PAGE_SIZE) - 1; - } - else - { - /* Get the ending address, which is the last piece we need for the VAD */ - EndingAddress = StartAddress + (ViewSizeInPages * PAGE_SIZE) - 1; - - /* Make sure it doesn't conflict with an existing allocation */ - Result = MiCheckForConflictingNode(StartAddress >> PAGE_SHIFT, - EndingAddress >> PAGE_SHIFT, - &Process->VadRoot, - &Parent); - if (Result == TableFoundNode) - { - DPRINT1("Conflict with SEC_BASED or manually based section!\n"); - MmUnlockAddressSpace(AddressSpace); - MiDereferenceControlArea(ControlArea); - ExFreePoolWithTag(Vad, 'ldaV'); - return STATUS_CONFLICTING_ADDRESSES; - } - } - - /* Now set the VAD address */ - Vad->StartingVpn = StartAddress >> PAGE_SHIFT; - Vad->EndingVpn = EndingAddress >> PAGE_SHIFT; - - /* Pretend as if we own the working set */ - MiLockProcessWorkingSetUnsafe(Process, Thread); - /* Insert the VAD */ - Process->VadRoot.NodeHint = Vad; - MiInsertNode(&Process->VadRoot, (PVOID)Vad, Parent, Result); - - /* Release the working set */ - MiUnlockProcessWorkingSetUnsafe(Process, Thread); - - /* Unlock the address space */ - MmUnlockAddressSpace(AddressSpace); + Status = MiInsertVadEx((PMMVAD)Vad, + &StartAddress, + ViewSizeInPages * PAGE_SIZE, + MAXULONG_PTR >> ZeroBits, + MM_VIRTMEM_GRANULARITY, + AllocationType); + if (!NT_SUCCESS(Status)) + { + return Status; + }
/* Windows stores this for accounting purposes, do so as well */ if (!Segment->u2.FirstMappedVa) Segment->u2.FirstMappedVa = (PVOID)StartAddress;
/* Finally, let the caller know where, and for what size, the view was mapped */ - *ViewSize = (ULONG_PTR)EndingAddress - (ULONG_PTR)StartAddress + 1; + *ViewSize = ViewSizeInPages * PAGE_SIZE; *BaseAddress = (PVOID)StartAddress; DPRINT("Start and region: 0x%p, 0x%p\n", *BaseAddress, *ViewSize); return STATUS_SUCCESS;
Modified: trunk/reactos/ntoskrnl/mm/ARM3/vadnode.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/vadnode.c?... ============================================================================== --- trunk/reactos/ntoskrnl/mm/ARM3/vadnode.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/mm/ARM3/vadnode.c [iso-8859-1] Wed Oct 8 00:31:17 2014 @@ -193,6 +193,138 @@ MiInsertNode(&Process->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_CONFLICTING_ADDRESSES; + } + + 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) + { + DPRINT1("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 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 NTAPI MiInsertBasedSection(IN PSECTION Section)
Modified: trunk/reactos/ntoskrnl/mm/ARM3/virtual.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/virtual.c?... ============================================================================== --- trunk/reactos/ntoskrnl/mm/ARM3/virtual.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/mm/ARM3/virtual.c [iso-8859-1] Wed Oct 8 00:31:17 2014 @@ -4304,12 +4304,12 @@ { PEPROCESS Process; PMEMORY_AREA MemoryArea; - PFN_NUMBER PageCount; PMMVAD Vad = NULL, FoundVad; NTSTATUS Status; PMMSUPPORT AddressSpace; PVOID PBaseAddress; - ULONG_PTR PRegionSize, StartingAddress, EndingAddress, HighestAddress; + ULONG_PTR PRegionSize, StartingAddress, EndingAddress; + ULONG_PTR HighestAddress = (ULONG_PTR)MM_HIGHEST_VAD_ADDRESS; PEPROCESS CurrentProcess = PsGetCurrentProcess(); KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); PETHREAD CurrentThread = PsGetCurrentThread(); @@ -4319,7 +4319,6 @@ MMPTE TempPte; PMMPTE PointerPte, PointerPde, LastPte; TABLE_SEARCH_RESULT Result; - PMMADDRESS_NODE Parent; PAGED_CODE();
/* Check for valid Zero bits */ @@ -4544,7 +4543,6 @@ // This is a blind commit, all we need is the region size // PRegionSize = ROUND_TO_PAGES(PRegionSize); - PageCount = BYTES_TO_PAGES(PRegionSize); EndingAddress = 0; StartingAddress = 0;
@@ -4563,13 +4561,6 @@ goto FailPathNoLock; } } - else - { - // - // Use the highest VAD address as maximum - // - HighestAddress = (ULONG_PTR)MM_HIGHEST_VAD_ADDRESS; - } } else { @@ -4579,8 +4570,8 @@ // fall based on the aligned address and the passed in region size // EndingAddress = ((ULONG_PTR)PBaseAddress + PRegionSize - 1) | (PAGE_SIZE - 1); - StartingAddress = ROUND_DOWN((ULONG_PTR)PBaseAddress, _64K); - PageCount = BYTES_TO_PAGES(EndingAddress - StartingAddress); + PRegionSize = EndingAddress + 1 - ROUND_DOWN((ULONG_PTR)PBaseAddress, _64K); + StartingAddress = (ULONG_PTR)PBaseAddress; }
// @@ -4594,7 +4585,7 @@ goto FailPathNoLock; }
- Vad->u.LongFlags = 0; + RtlZeroMemory(Vad, sizeof(MMVAD_LONG)); if (AllocationType & MEM_COMMIT) Vad->u.VadFlags.MemCommit = 1; Vad->u.VadFlags.Protection = ProtectionMask; Vad->u.VadFlags.PrivateMemory = 1; @@ -4602,124 +4593,24 @@ Vad->ControlArea = NULL; // For Memory-Area hack
// - // Lock the address space and make sure the process isn't already dead - // - AddressSpace = MmGetCurrentAddressSpace(); - MmLockAddressSpace(AddressSpace); - if (Process->VmDeleted) - { - Status = STATUS_PROCESS_IS_TERMINATING; - goto FailPath; - } - - // - // Did we have a base address? If no, find a valid address that is 64KB - // aligned in the VAD tree. Otherwise, make sure that the address range - // which was passed in isn't already conflicting with an existing address - // range. - // - if (!PBaseAddress) - { - /* Which way should we search? */ - if ((AllocationType & MEM_TOP_DOWN) || Process->VmTopDown) - { - /* Find an address top-down */ - Result = MiFindEmptyAddressRangeDownTree(PRegionSize, - HighestAddress, - _64K, - &Process->VadRoot, - &StartingAddress, - &Parent); - } - else - { - /* Find an address bottom-up */ - Result = MiFindEmptyAddressRangeInTree(PRegionSize, - _64K, - &Process->VadRoot, - &Parent, - &StartingAddress); - } - - if (Result == TableFoundNode) - { - Status = STATUS_NO_MEMORY; - goto FailPath; - } - - // - // Now we know where the allocation ends. Make sure it doesn't end up - // somewhere in kernel mode. - // - ASSERT(StartingAddress != 0); - ASSERT(StartingAddress < (ULONG_PTR)MM_HIGHEST_USER_ADDRESS); - EndingAddress = (StartingAddress + PRegionSize - 1) | (PAGE_SIZE - 1); - ASSERT(EndingAddress > StartingAddress); - if (EndingAddress > HighestAddress) - { - Status = STATUS_NO_MEMORY; - goto FailPath; - } - } - else - { - /* Make sure it doesn't conflict with an existing allocation */ - Result = MiCheckForConflictingNode(StartingAddress >> PAGE_SHIFT, - EndingAddress >> PAGE_SHIFT, - &Process->VadRoot, - &Parent); - if (Result == TableFoundNode) - { - // - // The address specified is in conflict! - // - Status = STATUS_CONFLICTING_ADDRESSES; - goto FailPath; - } - } - - // - // Write out the VAD fields for this allocation - // - Vad->StartingVpn = StartingAddress >> PAGE_SHIFT; - Vad->EndingVpn = EndingAddress >> PAGE_SHIFT; - - // - // FIXME: Should setup VAD bitmap - // - Status = STATUS_SUCCESS; - - // - // Lock the working set and insert the VAD into the process VAD tree - // - MiLockProcessWorkingSetUnsafe(Process, CurrentThread); - Process->VadRoot.NodeHint = Vad; - MiInsertNode(&Process->VadRoot, (PVOID)Vad, Parent, Result); - MiUnlockProcessWorkingSetUnsafe(Process, CurrentThread); - - // - // Make sure the actual region size is at least as big as the - // requested region size and update the value - // - ASSERT(PRegionSize <= (EndingAddress + 1 - StartingAddress)); - PRegionSize = (EndingAddress + 1 - StartingAddress); - - // - // Update the virtual size of the process, and if this is now the highest - // virtual size we have ever seen, update the peak virtual size to reflect - // this. - // - Process->VirtualSize += PRegionSize; - if (Process->VirtualSize > Process->PeakVirtualSize) - { - Process->PeakVirtualSize = Process->VirtualSize; - } - - // - // Release address space and detach and dereference the target process if + // Insert the VAD + // + Status = MiInsertVadEx(Vad, + &StartingAddress, + PRegionSize, + HighestAddress, + MM_VIRTMEM_GRANULARITY, + AllocationType); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Failed to insert the VAD!\n"); + goto FailPathNoLock; + } + + // + // Detach and dereference the target process if // it was different from the current process // - MmUnlockAddressSpace(AddressSpace); if (Attached) KeUnstackDetachProcess(&ApcState); if (ProcessHandle != NtCurrentProcess()) ObDereferenceObject(Process);