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?r…
==============================================================================
--- 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?…
==============================================================================
--- 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=…
==============================================================================
--- 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