Author: sir_richard Date: Mon Mar 26 07:26:36 2012 New Revision: 56232
URL: http://svn.reactos.org/svn/reactos?rev=56232&view=rev Log: [NTOS]: Perform system space mappings under the SystemSpaceViewLockPointer guarded mutex. [NTOS]: Expand system space view buckets when they are running low. [NTOS]: Support SEC_BASED section creates and mappings, implement based VAD parsing. [NTOS]: Support section mappings at a fixed base address and check for conflicts. [NTOS]: Define 8 prioritized standyby lists and initialize them. Also define the modified page list. [NTOS]: Support mapping with SEC_COMMIT less than the entire size of the section. [NTOS]: Detect and assert if ARM3 sections are attempted to be unmapped, since this isn't supported yet. [NTOS]: Clean up some DPRINTs and clarify ARM3 ASSERTs vs. Windows ASSERTs.
Modified: trunk/reactos/ntoskrnl/mm/ARM3/miarm.h trunk/reactos/ntoskrnl/mm/ARM3/mminit.c trunk/reactos/ntoskrnl/mm/ARM3/pfnlist.c trunk/reactos/ntoskrnl/mm/ARM3/section.c trunk/reactos/ntoskrnl/mm/ARM3/vadnode.c trunk/reactos/ntoskrnl/mm/section.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] Mon Mar 26 07:26:36 2012 @@ -26,7 +26,7 @@ MI_SESSION_IMAGE_SIZE + \ MI_SESSION_WORKING_SET_SIZE)
-#define MI_SYSTEM_VIEW_SIZE (16 * _1MB) +#define MI_SYSTEM_VIEW_SIZE (32 * _1MB)
#define MI_HIGHEST_USER_ADDRESS (PVOID)0x7FFEFFFF #define MI_USER_PROBE_ADDRESS (PVOID)0x7FFF0000 @@ -526,6 +526,7 @@ extern MM_PAGED_POOL_INFO MmPagedPoolInfo; extern RTL_BITMAP MiPfnBitMap; extern KGUARDED_MUTEX MmPagedPoolMutex; +extern KGUARDED_MUTEX MmSectionCommitMutex; extern PVOID MmPagedPoolStart; extern PVOID MmPagedPoolEnd; extern PVOID MmNonPagedSystemStart; @@ -557,6 +558,7 @@ extern ULONG MmMaximumNonPagedPoolPercent; extern ULONG MmLargeStackSize; extern PMMCOLOR_TABLES MmFreePagesByColor[FreePageList + 1]; +extern MMPFNLIST MmStandbyPageListByPriority[8]; extern ULONG MmProductType; extern MM_SYSTEMSIZE MmSystemSize; extern PKEVENT MiLowMemoryEvent; @@ -600,6 +602,9 @@ extern PVOID MiSessionViewStart; // 0xBE000000 extern ULONG MmMaximumDeadKernelStacks; extern SLIST_HEADER MmDeadStackSListHead; +extern MM_AVL_TABLE MmSectionBasedRoot; +extern KGUARDED_MUTEX MmSectionBasedMutex; +extern PVOID MmHighSectionBase;
BOOLEAN FORCEINLINE @@ -1264,6 +1269,12 @@ IN PMMPFN Entry );
+VOID +NTAPI +MiUnlinkPageFromList( + IN PMMPFN Pfn +); + PFN_NUMBER NTAPI MiAllocatePfn( @@ -1405,6 +1416,16 @@
NTSTATUS NTAPI +MiFindEmptyAddressRangeDownBasedTree( + IN SIZE_T Length, + IN ULONG_PTR BoundaryAddress, + IN ULONG_PTR Alignment, + IN PMM_AVL_TABLE Table, + OUT PULONG_PTR Base +); + +NTSTATUS +NTAPI MiFindEmptyAddressRangeInTree( IN SIZE_T Length, IN ULONG_PTR Alignment, @@ -1418,6 +1439,28 @@ MiInsertVad( IN PMMVAD Vad, IN PEPROCESS Process +); + +VOID +NTAPI +MiInsertBasedSection( + IN PSECTION Section +); + +NTSTATUS +NTAPI +MiUnmapViewOfSection( + IN PEPROCESS Process, + IN PVOID BaseAddress, + IN ULONG Flags +); + +NTSTATUS +NTAPI +MiRosUnmapViewOfSection( + IN PEPROCESS Process, + IN PVOID BaseAddress, + IN ULONG Flags );
VOID @@ -1520,10 +1563,24 @@ IN ULONG Protect );
+NTSTATUS +NTAPI +MiRosUnmapViewInSystemSpace( + IN PVOID MappedBase +); + POOL_TYPE NTAPI MmDeterminePoolType( IN PVOID PoolAddress +); + +VOID +NTAPI +MiMakePdeExistAndMakeValid( + IN PMMPTE PointerPde, + IN PEPROCESS TargetProcess, + IN KIRQL OldIrql );
//
Modified: trunk/reactos/ntoskrnl/mm/ARM3/mminit.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/mminit.c?r... ============================================================================== --- trunk/reactos/ntoskrnl/mm/ARM3/mminit.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/mm/ARM3/mminit.c [iso-8859-1] Mon Mar 26 07:26:36 2012 @@ -149,7 +149,7 @@ // The system view space, on the other hand, is where sections that are memory // mapped into "system space" end up. // -// By default, it is a 16MB region. +// By default, it is a 16MB region, but we hack it to be 32MB for ReactOS // PVOID MiSystemViewStart; SIZE_T MmSystemViewSize; @@ -1134,7 +1134,7 @@ /* See how many pages are in this run */ i = Entry->PageCount; BasePage = Entry->BasePage; - + /* Loop each page */ Pfn1 = MiGetPfnEntry(BasePage); while (i--) @@ -2062,12 +2062,27 @@
/* Initialize session space address layout */ MiInitializeSessionSpaceLayout(); + + /* Set the based section highest address */ + MmHighSectionBase = (PVOID)((ULONG_PTR)MmHighestUserAddress - 0x800000); + + /* Loop all 8 standby lists */ + for (i = 0; i < 8; i++) + { + /* Initialize them */ + MmStandbyPageListByPriority[i].Total = 0; + MmStandbyPageListByPriority[i].ListName = StandbyPageList; + MmStandbyPageListByPriority[i].Flink = MM_EMPTY_LIST; + MmStandbyPageListByPriority[i].Blink = MM_EMPTY_LIST; + }
/* Initialize the user mode image list */ InitializeListHead(&MmLoadedUserImageList);
- /* Initialize the paged pool mutex */ + /* Initialize the paged pool mutex and the section commit mutex */ KeInitializeGuardedMutex(&MmPagedPoolMutex); + KeInitializeGuardedMutex(&MmSectionCommitMutex); + KeInitializeGuardedMutex(&MmSectionBasedMutex);
/* Initialize the Loader Lock */ KeInitializeMutant(&MmSystemLoadLock, FALSE);
Modified: trunk/reactos/ntoskrnl/mm/ARM3/pfnlist.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/pfnlist.c?... ============================================================================== --- trunk/reactos/ntoskrnl/mm/ARM3/pfnlist.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/mm/ARM3/pfnlist.c [iso-8859-1] Mon Mar 26 07:26:36 2012 @@ -35,10 +35,15 @@ BOOLEAN MmMirroring; ULONG MmSystemPageColor;
+ULONG MmTransitionSharedPages; +ULONG MmTotalPagesForPagingFile; + MMPFNLIST MmZeroedPageListHead = {0, ZeroedPageList, LIST_HEAD, LIST_HEAD}; MMPFNLIST MmFreePageListHead = {0, FreePageList, LIST_HEAD, LIST_HEAD}; MMPFNLIST MmStandbyPageListHead = {0, StandbyPageList, LIST_HEAD, LIST_HEAD}; +MMPFNLIST MmStandbyPageListByPriority[8]; MMPFNLIST MmModifiedPageListHead = {0, ModifiedPageList, LIST_HEAD, LIST_HEAD}; +MMPFNLIST MmModifiedPageListByColor[1] = {{0, ModifiedPageList, LIST_HEAD, LIST_HEAD}}; MMPFNLIST MmModifiedNoWritePageListHead = {0, ModifiedNoWritePageList, LIST_HEAD, LIST_HEAD}; MMPFNLIST MmBadPageListHead = {0, BadPageList, LIST_HEAD, LIST_HEAD}; MMPFNLIST MmRomPageListHead = {0, StandbyPageList, LIST_HEAD, LIST_HEAD};
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] Mon Mar 26 07:26:36 2012 @@ -82,6 +82,10 @@ };
MMSESSION MmSession; +KGUARDED_MUTEX MmSectionCommitMutex; +MM_AVL_TABLE MmSectionBasedRoot; +KGUARDED_MUTEX MmSectionBasedMutex; +PVOID MmHighSectionBase;
/* PRIVATE FUNCTIONS **********************************************************/
@@ -243,19 +247,87 @@ IN PCONTROL_AREA ControlArea) { PVOID Base; - ULONG Entry, Hash, i; + ULONG Entry, Hash, i, HashSize; + PMMVIEW OldTable; PAGED_CODE();
/* Only global mappings supported for now */ ASSERT(Session == &MmSession);
- /* Stay within 4GB and don't go past the number of hash entries available */ + /* Stay within 4GB */ ASSERT(Buckets < MI_SYSTEM_VIEW_BUCKET_SIZE); - ASSERT(Session->SystemSpaceHashEntries < Session->SystemSpaceHashSize); + + /* Lock system space */ + KeAcquireGuardedMutex(Session->SystemSpaceViewLockPointer); + + /* Check if we're going to exhaust hash entries */ + if ((Session->SystemSpaceHashEntries + 8) > Session->SystemSpaceHashSize) + { + /* Double the hash size */ + HashSize = Session->SystemSpaceHashSize * 2; + + /* Save the old table and allocate a new one */ + OldTable = Session->SystemSpaceViewTable; + Session->SystemSpaceViewTable = ExAllocatePoolWithTag(NonPagedPool, + HashSize * + sizeof(MMVIEW), + ' mM'); + if (!Session->SystemSpaceViewTable) + { + /* Failed to allocate a new table, keep the old one for now */ + Session->SystemSpaceViewTable = OldTable; + } + else + { + /* Clear the new table and set the new ahsh and key */ + RtlZeroMemory(Session->SystemSpaceViewTable, HashSize * sizeof(MMVIEW)); + Session->SystemSpaceHashSize = HashSize; + Session->SystemSpaceHashKey = Session->SystemSpaceHashSize - 1; + + /* Loop the old table */ + for (i = 0; i < Session->SystemSpaceHashSize / 2; i++) + { + /* Check if the entry was valid */ + if (OldTable[i].Entry) + { + /* Re-hash the old entry and search for space in the new table */ + Hash = (OldTable[i].Entry >> 16) % Session->SystemSpaceHashKey; + while (Session->SystemSpaceViewTable[Hash].Entry) + { + /* Loop back at the beginning if we had an overflow */ + if (++Hash >= Session->SystemSpaceHashSize) Hash = 0; + } + + /* Write the old entry in the new table */ + Session->SystemSpaceViewTable[Hash] = OldTable[i]; + } + } + + /* Free the old table */ + ExFreePool(OldTable); + } + } + + /* Check if we ran out */ + if (Session->SystemSpaceHashEntries == Session->SystemSpaceHashSize) + { + DPRINT1("Ran out of system view hash entries\n"); + KeReleaseGuardedMutex(Session->SystemSpaceViewLockPointer); + return NULL; + }
/* Find space where to map this view */ i = RtlFindClearBitsAndSet(Session->SystemSpaceBitMap, Buckets, 0); - ASSERT(i != 0xFFFFFFFF); + if (i == 0xFFFFFFFF) + { + /* Out of space, fail */ + Session->BitmapFailures++; + DPRINT1("Out of system view space\n"); + KeReleaseGuardedMutex(Session->SystemSpaceViewLockPointer); + return NULL; + } + + /* Compute the base address */ Base = (PVOID)((ULONG_PTR)Session->SystemSpaceViewStart + (i * MI_SYSTEM_VIEW_BUCKET_SIZE));
/* Get the hash entry for this allocation */ @@ -275,6 +347,7 @@
/* Hash entry found, increment total and return the base address */ Session->SystemSpaceHashEntries++; + KeReleaseGuardedMutex(Session->SystemSpaceViewLockPointer); return Base; }
@@ -701,30 +774,25 @@ PSEGMENT Segment; PFN_NUMBER PteOffset; NTSTATUS Status; - - /* Get the segment and subection for this section */ + ULONG QuotaCharge = 0, QuotaExcess = 0; + PMMPTE PointerPte, LastPte; + MMPTE TempPte; + + /* Get the segment for this section */ Segment = ControlArea->Segment; - Subsection = (PSUBSECTION)(ControlArea + 1); - - /* Non-pagefile-backed sections not supported */ - ASSERT(ControlArea->u.Flags.GlobalOnlyPerSession == 0); - ASSERT(ControlArea->u.Flags.Rom == 0); - ASSERT(ControlArea->FilePointer == NULL); - ASSERT(Segment->SegmentFlags.TotalNumberOfPtes4132 == 0); - - /* Based sections not supported */ - ASSERT(Section->Address.StartingVpn == 0); - - /* These flags/parameters are not supported */ + + /* One can only reserve a file-based mapping, not shared memory! */ + if ((AllocationType & MEM_RESERVE) && !(ControlArea->FilePointer)) + { + return STATUS_INVALID_PARAMETER_9; + } + + /* This flag determines alignment, but ARM3 does not yet support it */ ASSERT((AllocationType & MEM_DOS_LIM) == 0); - ASSERT((AllocationType & MEM_RESERVE) == 0); - ASSERT(Process->VmTopDown == 0); - ASSERT(Section->u.Flags.CopyOnWrite == FALSE); - ASSERT(ZeroBits == 0);
/* First, increase the map count. No purging is supported yet */ Status = MiCheckPurgeAndUpMapCount(ControlArea, FALSE); - ASSERT(NT_SUCCESS(Status)); + if (!NT_SUCCESS(Status)) return Status;
/* Check if the caller specified the view size */ if (!(*ViewSize)) @@ -742,29 +810,57 @@ SectionOffset->LowPart &= ~((ULONG)_64K - 1); }
- /* We must be dealing with a 64KB aligned offset */ + /* We must be dealing with a 64KB aligned offset. This is a Windows ASSERT */ ASSERT((SectionOffset->LowPart & ((ULONG)_64K - 1)) == 0);
/* It's illegal to try to map more than 2GB */ + /* FIXME: Should dereference the control area */ if (*ViewSize >= 0x80000000) return STATUS_INVALID_VIEW_SIZE; + + /* Windows ASSERTs for this flag */ + ASSERT(ControlArea->u.Flags.GlobalOnlyPerSession == 0); + + /* Get the subsection. We don't support LARGE_CONTROL_AREA in ARM3 */ + ASSERT(ControlArea->u.Flags.Rom == 0); + Subsection = (PSUBSECTION)(ControlArea + 1); + + /* Sections with extended segments are not supported in ARM3 */ + ASSERT(Segment->SegmentFlags.TotalNumberOfPtes4132 == 0);
/* Within this section, figure out which PTEs will describe the view */ PteOffset = (PFN_NUMBER)(SectionOffset->QuadPart >> PAGE_SHIFT);
- /* The offset must be in this segment's PTE chunk and it must be valid */ + /* The offset must be in this segment's PTE chunk and it must be valid. Windows ASSERTs */ ASSERT(PteOffset < Segment->TotalNumberOfPtes); ASSERT(((SectionOffset->QuadPart + *ViewSize + PAGE_SIZE - 1) >> PAGE_SHIFT) >= PteOffset);
/* In ARM3, only one subsection is used for now. It must contain these PTEs */ ASSERT(PteOffset < Subsection->PtesInSubsection); + + /* In ARM3, only page-file backed sections (shared memory) are supported now */ + ASSERT(ControlArea->FilePointer == NULL); + + /* Windows ASSERTs for this too -- there must be a subsection base address */ ASSERT(Subsection->SubsectionBase != NULL);
- /* In ARM3, only MEM_COMMIT is supported for now. The PTEs must've been committed */ - ASSERT(Segment->NumberOfCommittedPages >= Segment->TotalNumberOfPtes); + /* Compute how much commit space the segment will take */ + if ((CommitSize) && (Segment->NumberOfCommittedPages < Segment->TotalNumberOfPtes)) + { + PointerPte = &Subsection->SubsectionBase[PteOffset]; + LastPte = PointerPte + BYTES_TO_PAGES(CommitSize); + QuotaCharge = LastPte - PointerPte; + } + + /* ARM3 does not currently support large pages */ + ASSERT(Segment->SegmentFlags.LargePages == 0);
/* Did the caller specify an address? */ - if (!(*BaseAddress)) - { + if (!(*BaseAddress) && !(Section->Address.StartingVpn)) + { + /* ARM3 does not support these flags yet */ + ASSERT(Process->VmTopDown == 0); + ASSERT(ZeroBits == 0); + /* Which way should we search? */ if (AllocationType & MEM_TOP_DOWN) { @@ -787,21 +883,43 @@ &StartAddress); ASSERT(NT_SUCCESS(Status)); } + + /* Get the ending address, which is the last piece we need for the VAD */ + EndingAddress = (StartAddress + *ViewSize - 1) | (PAGE_SIZE - 1); } else { - /* This (rather easy) code path is not yet implemented */ - UNIMPLEMENTED; - while (TRUE); - } - - /* Get the ending address, which is the last piece we need for the VAD */ - EndingAddress = (StartAddress + *ViewSize - 1) | (PAGE_SIZE - 1); + /* Is it SEC_BASED, or did the caller manually specify an address? */ + if (!(*BaseAddress)) + { + /* It is a SEC_BASED mapping, use the address that was generated */ + StartAddress = Section->Address.StartingVpn + SectionOffset->LowPart; + DPRINT("BASED: 0x%p\n", StartAddress); + } + else + { + /* Just align what the caller gave us */ + StartAddress = ROUND_UP((ULONG_PTR)*BaseAddress, _64K); + } + + /* Get the ending address, which is the last piece we need for the VAD */ + EndingAddress = (StartAddress + *ViewSize - 1) | (PAGE_SIZE - 1); + + /* Make sure it doesn't conflict with an existing allocation */ + if (MiCheckForConflictingNode(StartAddress >> PAGE_SHIFT, + EndingAddress >> PAGE_SHIFT, + &Process->VadRoot)) + { + DPRINT1("Conflict with SEC_BASED or manually based section!\n"); + return STATUS_CONFLICTING_ADDRESSES; // FIXME: CA Leak + } + }
/* A VAD can now be allocated. Do so and zero it out */ /* FIXME: we are allocating a LONG VAD for ReactOS compatibility only */ + ASSERT((AllocationType & MEM_RESERVE) == 0); /* ARM3 does not support this */ Vad = ExAllocatePoolWithTag(NonPagedPool, sizeof(MMVAD_LONG), 'ldaV'); - ASSERT(Vad); + if (!Vad) return STATUS_INSUFFICIENT_RESOURCES; /* FIXME: CA Leak */ RtlZeroMemory(Vad, sizeof(MMVAD_LONG)); Vad->u4.Banked = (PVOID)0xDEADBABE;
@@ -822,10 +940,10 @@ /* Finally, write down the first and last prototype PTE */ Vad->FirstPrototypePte = &Subsection->SubsectionBase[PteOffset]; PteOffset += (Vad->EndingVpn - Vad->StartingVpn); + ASSERT(PteOffset < Subsection->PtesInSubsection); Vad->LastContiguousPte = &Subsection->SubsectionBase[PteOffset];
- /* Make sure the last PTE is valid and still within the subsection */ - ASSERT(PteOffset < Subsection->PtesInSubsection); + /* Make sure the prototype PTE ranges make sense, this is a Windows ASSERT */ ASSERT(Vad->FirstPrototypePte <= Vad->LastContiguousPte);
/* FIXME: Should setup VAD bitmap */ @@ -842,11 +960,49 @@
/* Windows stores this for accounting purposes, do so as well */ if (!Segment->u2.FirstMappedVa) Segment->u2.FirstMappedVa = (PVOID)StartAddress; + + /* Check if anything was committed */ + if (QuotaCharge) + { + /* Set the start and end PTE addresses, and pick the template PTE */ + PointerPte = Vad->FirstPrototypePte; + LastPte = PointerPte + BYTES_TO_PAGES(CommitSize); + TempPte = Segment->SegmentPteTemplate; + + /* Acquire the commit lock and loop all prototype PTEs to be committed */ + KeAcquireGuardedMutexUnsafe(&MmSectionCommitMutex); + while (PointerPte < LastPte) + { + /* Make sure the PTE is already invalid */ + if (PointerPte->u.Long == 0) + { + /* And write the invalid PTE */ + MI_WRITE_INVALID_PTE(PointerPte, TempPte); + } + else + { + /* The PTE is valid, so skip it */ + QuotaExcess++; + } + + /* Move to the next PTE */ + PointerPte++; + } + + /* Now check how many pages exactly we committed, and update accounting */ + ASSERT(QuotaCharge >= QuotaExcess); + QuotaCharge -= QuotaExcess; + Segment->NumberOfCommittedPages += QuotaCharge; + ASSERT(Segment->NumberOfCommittedPages <= Segment->TotalNumberOfPtes); + + /* Now that we're done, release the lock */ + KeReleaseGuardedMutexUnsafe(&MmSectionCommitMutex); + }
/* Finally, let the caller know where, and for what size, the view was mapped */ *ViewSize = (ULONG_PTR)EndingAddress - (ULONG_PTR)StartAddress + 1; *BaseAddress = (PVOID)StartAddress; - DPRINT1("Start and region: 0x%p, 0x%p\n", *BaseAddress, *ViewSize); + DPRINT("Start and region: 0x%p, 0x%p\n", *BaseAddress, *ViewSize); return STATUS_SUCCESS; }
@@ -1226,7 +1382,6 @@ ASSERT(FileHandle == NULL); ASSERT(FileObject == NULL); ASSERT((AllocationAttributes & SEC_LARGE_PAGES) == 0); - ASSERT((AllocationAttributes & SEC_BASED) == 0);
/* Make the same sanity checks that the Nt interface should've validated */ ASSERT((AllocationAttributes & ~(SEC_COMMIT | SEC_RESERVE | SEC_BASED | @@ -1258,10 +1413,10 @@ ProtectionMask, AllocationAttributes); ASSERT(NT_SUCCESS(Status)); + ASSERT(NewSegment != NULL);
/* Set the initial section object data */ Section.InitialPageProtection = SectionPageProtection; - Section.Segment = NULL; Section.SizeOfSection.QuadPart = NewSegment->SizeOfSegment; Section.Segment = NewSegment;
@@ -1296,6 +1451,49 @@ /* Now copy the local section object from the stack into this new object */ RtlCopyMemory(NewSection, &Section, sizeof(SECTION)); NewSection->Address.StartingVpn = 0; + NewSection->u.Flags.UserReference = TRUE; + + /* Migrate the attribute into a flag */ + if (AllocationAttributes & SEC_NO_CHANGE) NewSection->u.Flags.NoChange = TRUE; + + /* If R/W access is not requested, this might eventually become a CoW mapping */ + if (!(SectionPageProtection & (PAGE_READWRITE | PAGE_EXECUTE_READWRITE))) + { + NewSection->u.Flags.CopyOnWrite = TRUE; + } + + /* Is this a "based" allocation, in which all mappings are identical? */ + if (AllocationAttributes & SEC_BASED) + { + /* Convert the flag, and make sure the section isn't too big */ + NewSection->u.Flags.Based = TRUE; + if (NewSection->SizeOfSection.QuadPart > (ULONG_PTR)MmHighSectionBase) + { + DPRINT1("BASED section is too large\n"); + ObDereferenceObject(NewSection); + return STATUS_NO_MEMORY; + } + + /* Lock the VAD tree during the search */ + KeAcquireGuardedMutex(&MmSectionBasedMutex); + + /* Find an address top-down */ + Status = MiFindEmptyAddressRangeDownBasedTree(NewSection->SizeOfSection.LowPart, + (ULONG_PTR)MmHighSectionBase, + _64K, + &MmSectionBasedRoot, + &NewSection->Address.StartingVpn); + ASSERT(NT_SUCCESS(Status)); + + /* Compute the ending address and insert it into the VAD tree */ + NewSection->Address.EndingVpn = NewSection->Address.StartingVpn + + NewSection->SizeOfSection.LowPart - + 1; + MiInsertBasedSection(NewSection); + + /* Finally release the lock */ + KeReleaseGuardedMutex(&MmSectionBasedMutex); + }
/* Return the object and the creation status */ *SectionObject = (PVOID)NewSection; @@ -1421,7 +1619,7 @@ if (!Process->VmDeleted) { /* Do the actual mapping */ - DPRINT1("Mapping ARM3 data section\n"); + DPRINT("Mapping ARM3 data section\n"); Status = MiMapViewOfDataSection(ControlArea, Process, BaseAddress, @@ -1494,6 +1692,30 @@ return STATUS_NOT_IMPLEMENTED; }
+/* + * @implemented + */ +NTSTATUS +NTAPI +MmUnmapViewInSystemSpace(IN PVOID MappedBase) +{ + PMEMORY_AREA MemoryArea; + PAGED_CODE(); + + /* Was this mapped by RosMm? */ + MemoryArea = MmLocateMemoryAreaByAddress(MmGetKernelAddressSpace(), MappedBase); + if ((MemoryArea) && (MemoryArea->Type != MEMORY_AREA_OWNED_BY_ARM3)) + { + return MiRosUnmapViewInSystemSpace(MappedBase); + } + + /* It was not, call the ARM3 routine */ + ASSERT(FALSE); + return STATUS_SUCCESS; +// DPRINT("ARM3 unmapping\n"); +// return MiUnmapViewInSystemSpace(&MmSession, MappedBase); +} + /* SYSTEM CALLS ***************************************************************/
NTSTATUS
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] Mon Mar 26 07:26:36 2012 @@ -163,6 +163,21 @@
VOID NTAPI +MiInsertBasedSection(IN PSECTION Section) +{ + TABLE_SEARCH_RESULT Result; + PMMADDRESS_NODE Parent = NULL; + ASSERT(Section->Address.EndingVpn >= Section->Address.StartingVpn); + + /* Find the parent VAD and where this child should be inserted */ + Result = RtlpFindAvlTableNodeOrParent(&MmSectionBasedRoot, (PVOID)Section->Address.StartingVpn, &Parent); + ASSERT(Result != TableFoundNode); + ASSERT((Parent != NULL) || (Result == TableEmptyTree)); + MiInsertNode(&MmSectionBasedRoot, &Section->Address, Parent, Result); +} + +VOID +NTAPI MiRemoveNode(IN PMMADDRESS_NODE Node, IN PMM_AVL_TABLE Table) { @@ -471,4 +486,101 @@ return TableFoundNode; }
+NTSTATUS +NTAPI +MiFindEmptyAddressRangeDownBasedTree(IN SIZE_T Length, + IN ULONG_PTR BoundaryAddress, + IN ULONG_PTR Alignment, + IN PMM_AVL_TABLE Table, + OUT PULONG_PTR Base) +{ + PMMADDRESS_NODE Node, LowestNode; + ULONG_PTR LowVpn, BestVpn; + + /* Sanity checks */ + ASSERT(Table == &MmSectionBasedRoot); + ASSERT(BoundaryAddress); + ASSERT(BoundaryAddress <= ((ULONG_PTR)MM_HIGHEST_VAD_ADDRESS + 1)); + + /* Compute page length, make sure the boundary address is valid */ + Length = ROUND_TO_PAGES(Length); + if ((BoundaryAddress + 1) < Length) return STATUS_NO_MEMORY; + + /* Check if the table is empty */ + BestVpn = ROUND_UP(BoundaryAddress + 1 - Length, Alignment); + if (Table->NumberGenericTableElements == 0) + { + /* Tree is empty, the candidate address is already the best one */ + *Base = BestVpn; + return STATUS_SUCCESS; + } + + /* Go to the right-most node which should be the biggest address */ + Node = Table->BalancedRoot.RightChild; + 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))) + { + /* Return the address */ + *Base = ROUND_UP(BoundaryAddress - Length, Alignment); + return STATUS_SUCCESS; + } + + /* Now loop the Vad nodes */ + do + { + /* Break out if we've reached the last node */ + LowestNode = MiGetPreviousNode(Node); + if (!LowestNode) break; + + /* Check if this node could contain the requested address */ + LowVpn = ROUND_UP(LowestNode->EndingVpn + 1, Alignment); + if ((LowestNode->EndingVpn < BestVpn) && + (Length <= (Node->StartingVpn - LowVpn))) + { + /* Check if it fits in perfectly */ + if ((BestVpn > LowestNode->EndingVpn) && + (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) + { + /* Return an aligned base address within this node */ + *Base = ROUND_UP(Node->StartingVpn - Length, Alignment); + return STATUS_SUCCESS; + } + } + + /* Move to the next node */ + Node = LowestNode; + } while (TRUE); + + /* 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)) + { + /* Check if it fits in perfectly */ + if (BoundaryAddress < Node->StartingVpn) + { + /* Return the optimal VPN address */ + *Base = BestVpn; + return STATUS_SUCCESS; + } + + /* Return an aligned base address within this node */ + *Base = ROUND_UP(Node->StartingVpn - Length, Alignment); + return STATUS_SUCCESS; + } + + /* No address space left at all */ + return STATUS_NO_MEMORY; +} + /* EOF */
Modified: trunk/reactos/ntoskrnl/mm/section.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/section.c?rev=5... ============================================================================== --- trunk/reactos/ntoskrnl/mm/section.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/mm/section.c [iso-8859-1] Mon Mar 26 07:26:36 2012 @@ -2855,6 +2855,10 @@
DPRINT("Creating Section Object Type\n");
+ /* Initialize the section based root */ + ASSERT(MmSectionBasedRoot.NumberGenericTableElements == 0); + MmSectionBasedRoot.BalancedRoot.u1.Parent = &MmSectionBasedRoot.BalancedRoot; + /* Initialize the Section object type */ RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer)); RtlInitUnicodeString(&Name, L"Section"); @@ -4231,6 +4235,7 @@ MemoryArea->Type != MEMORY_AREA_SECTION_VIEW || MemoryArea->DeleteInProgress) { + ASSERT(MemoryArea->Type != MEMORY_AREA_OWNED_BY_ARM3); MmUnlockAddressSpace(AddressSpace); return STATUS_NOT_MAPPED_VIEW; } @@ -4538,7 +4543,7 @@
if (MiIsRosSectionObject(SectionObject) == FALSE) { - DPRINT1("Mapping ARM3 section into %s\n", Process->ImageFileName); + DPRINT("Mapping ARM3 section into %s\n", Process->ImageFileName); return MmMapViewOfArm3Section(SectionObject, Process, BaseAddress, @@ -4875,7 +4880,6 @@
if (MiIsRosSectionObject(SectionObject) == FALSE) { - DPRINT1("ARM3 System Mapping\n"); return MiMapViewInSystemSpace(SectionObject, &MmSession, MappedBase, @@ -4917,11 +4921,9 @@ return Status; }
-/* - * @implemented - */ -NTSTATUS NTAPI -MmUnmapViewInSystemSpace (IN PVOID MappedBase) +NTSTATUS +NTAPI +MiRosUnmapViewInSystemSpace(IN PVOID MappedBase) { PMMSUPPORT AddressSpace; NTSTATUS Status; @@ -4938,7 +4940,6 @@
return Status; } -
/********************************************************************** * NAME EXPORTED