Author: ion
Date: Sat Sep 1 02:32:25 2012
New Revision: 57209
URL:
http://svn.reactos.org/svn/reactos?rev=57209&view=rev
Log:
[NTOSKRNL]: Cleanup MmCreateArm3Section a little bit to handle file-backed sections in the
future.
[NTOSKRNL]: Remove an ASSERT(FALSE) that was only there for testing.
[NTOSKRNL]: Support transition pages during prototype PTE faults, which is our first try
at soft faults! Should fix ASSERTs that were seen in the previous attempts in ole32,
corrupting the registry.
[NTOSKRNL]: It's fine for MiCreatePagingFileMap to fail in MmCreateSection --
don't assert and simply return failure. Should fix the ASSERTs taht were seen in
KmTest.
[NTOSKRNL]: Enable richard's ARM3 section code unconditionally for all non-file backed
sections. Works4me. Let's see what Testbot says.
Nobody has showed me how to use/where is PatchBot, and google founds 0 relevant results,
so this is going into main again. However I'm actually home this week to revert if
something goes wrong :)
Modified:
trunk/reactos/ntoskrnl/mm/ARM3/pagfault.c
trunk/reactos/ntoskrnl/mm/ARM3/pfnlist.c
trunk/reactos/ntoskrnl/mm/ARM3/section.c
trunk/reactos/ntoskrnl/mm/section.c
Modified: trunk/reactos/ntoskrnl/mm/ARM3/pagfault.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/pagfault.…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/ARM3/pagfault.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/ARM3/pagfault.c [iso-8859-1] Sat Sep 1 02:32:25 2012
@@ -980,8 +980,51 @@
else if ((TempPte.u.Soft.Prototype == 0) &&
(TempPte.u.Soft.Transition == 1))
{
- /* No standby support yet */
- ASSERT(FALSE);
+ /* This is a standby page, bring it back from the cache */
+ PageFrameIndex = TempPte.u.Trans.PageFrameNumber;
+ DPRINT1("oooh, shiny, a soft fault! 0x%lx\n",
PageFrameIndex);
+ Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);
+ ASSERT(Pfn1->u3.e1.PageLocation != ActiveAndValid);
+
+ /* Should not yet happen in ReactOS */
+ ASSERT(Pfn1->u3.e1.ReadInProgress == 0);
+ ASSERT(Pfn1->u4.InPageError == 0);
+
+ /* Get the page */
+ MiUnlinkPageFromList(Pfn1);
+
+ /* Bump its reference count */
+ ASSERT(Pfn1->u2.ShareCount == 0);
+ InterlockedIncrement16((PSHORT)&Pfn1->u3.e2.ReferenceCount);
+ Pfn1->u2.ShareCount++;
+
+ /* Make it valid again */
+ /* This looks like another macro.... */
+ Pfn1->u3.e1.PageLocation = ActiveAndValid;
+ ASSERT(PointerProtoPte->u.Hard.Valid == 0);
+ ASSERT(PointerProtoPte->u.Trans.Prototype == 0);
+ ASSERT(PointerProtoPte->u.Trans.Transition == 1);
+ TempPte.u.Long = (PointerProtoPte->u.Long & ~0xFFF) |
+
MmProtectToPteMask[PointerProtoPte->u.Trans.Protection];
+ TempPte.u.Hard.Valid = 1;
+ TempPte.u.Hard.Accessed = 1;
+
+ /* Is the PTE writeable? */
+ if (((Pfn1->u3.e1.Modified) && (TempPte.u.Hard.Write))
&&
+ (TempPte.u.Hard.CopyOnWrite == 0))
+ {
+ /* Make it dirty */
+ TempPte.u.Hard.Dirty = TRUE;
+ }
+ else
+ {
+ /* Make it clean */
+ TempPte.u.Hard.Dirty = FALSE;
+ }
+
+ /* Write the valid PTE */
+ MI_WRITE_VALID_PTE(PointerProtoPte, TempPte);
+ ASSERT(PointerPte->u.Hard.Valid == 0);
}
else
{
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] Sat Sep 1 02:32:25 2012
@@ -1335,7 +1335,6 @@
}
/* Check to see which list this page should go into */
- ASSERT(FALSE);
if (Pfn1->u3.e1.Modified == 1)
{
/* Push it into the modified page list */
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] Sat Sep 1 02:32:25 2012
@@ -894,10 +894,10 @@
ASSERT(ActualPages <= PageCount);
/* Release the working set lock */
-// MiUnlockWorkingSet(PsGetCurrentThread(),
+// MiUnlockWorkingSet(PsGetCurrentThread(),
// &MmSessionSpace->GlobalVirtualAddress->Vm);
-
+
/* If we did at least one page... */
if (ActualPages)
{
@@ -974,7 +974,7 @@
{
/* Create the PDEs needed for this mapping */
Status = MiSessionCommitPageTables(Base,
- (PVOID)((ULONG_PTR)Base +
+ (PVOID)((ULONG_PTR)Base +
Buckets * MI_SYSTEM_VIEW_BUCKET_SIZE));
NT_ASSERT(NT_SUCCESS(Status));
}
@@ -1243,6 +1243,37 @@
return STATUS_SUCCESS;
}
+VOID
+NTAPI
+MiSubsectionConsistent(IN PSUBSECTION Subsection)
+{
+ /* ReactOS only supports systems with 4K pages and 4K sectors */
+ ASSERT(Subsection->u.SubsectionFlags.SectorEndOffset == 0);
+
+ /* Therefore, then number of PTEs should be equal to the number of sectors */
+ if (Subsection->NumberOfFullSectors != Subsection->PtesInSubsection)
+ {
+ /* Break and warn if this is inconsistent */
+ DPRINT1("Mm: Subsection inconsistent (%x vs %x)\n",
+ Subsection->NumberOfFullSectors, Subsection->PtesInSubsection);
+ DbgBreakPoint();
+ }
+}
+
+NTSTATUS
+NTAPI
+MiCreateDataFileMap(IN PFILE_OBJECT File,
+ OUT PSEGMENT *Segment,
+ IN PSIZE_T MaximumSize,
+ IN ULONG SectionPageProtection,
+ IN ULONG AllocationAttributes,
+ IN ULONG IgnoreFileSizing)
+{
+ /* Not yet implemented */
+ ASSERT(FALSE);
+ return STATUS_NOT_IMPLEMENTED;
+}
+
NTSTATUS
NTAPI
MiCreatePagingFileMap(OUT PSEGMENT *Segment,
@@ -2048,15 +2079,15 @@
SECTION Section;
PSECTION NewSection;
PSUBSECTION Subsection;
- PSEGMENT NewSegment;
+ PSEGMENT NewSegment, Segment;
NTSTATUS Status;
PCONTROL_AREA ControlArea;
- ULONG ProtectionMask;
-
- /* ARM3 does not yet support this */
- ASSERT(FileHandle == NULL);
- ASSERT(FileObject == NULL);
- ASSERT((AllocationAttributes & SEC_LARGE_PAGES) == 0);
+ ULONG ProtectionMask, ControlAreaSize, Size, NonPagedCharge, PagedCharge;
+ KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
+ BOOLEAN FileLock = FALSE, KernelCall = FALSE;
+ KIRQL OldIrql;
+ PFILE_OBJECT File;
+ PVOID PreviousSectionPointer;
/* Make the same sanity checks that the Nt interface should've validated */
ASSERT((AllocationAttributes & ~(SEC_COMMIT | SEC_RESERVE | SEC_BASED |
@@ -2079,53 +2110,229 @@
ProtectionMask = MiMakeProtectionMask(SectionPageProtection);
if (ProtectionMask == MM_INVALID_PROTECTION) return STATUS_INVALID_PAGE_PROTECTION;
- /* A handle must be supplied with SEC_IMAGE, and this is the no-handle path */
- if (AllocationAttributes & SEC_IMAGE) return STATUS_INVALID_FILE_FOR_SECTION;
-
- /* So this must be a pagefile-backed section, create the mappings needed */
- Status = MiCreatePagingFileMap(&NewSegment,
- (PSIZE_T)InputMaximumSize,
- ProtectionMask,
- AllocationAttributes);
- ASSERT(NT_SUCCESS(Status));
- ASSERT(NewSegment != NULL);
+ /* Check if this is going to be a data or image backed file section */
+ if ((FileHandle) || (FileObject))
+ {
+ /* These cannot be mapped with large pages */
+ if (AllocationAttributes & SEC_LARGE_PAGES) return
STATUS_INVALID_PARAMETER_6;
+
+ /* For now, only support the mechanism through a file handle */
+ ASSERT(FileObject == NULL);
+
+ /* Reference the file handle to get the object */
+ Status = ObReferenceObjectByHandle(FileHandle,
+ MmMakeFileAccess[ProtectionMask],
+ IoFileObjectType,
+ PreviousMode,
+ (PVOID*)&File,
+ NULL);
+ if (!NT_SUCCESS(Status)) return Status;
+
+ /* Make sure Cc has been doing its job */
+ if (!File->SectionObjectPointer)
+ {
+ /* This is not a valid file system-based file, fail */
+ ObDereferenceObject(File);
+ return STATUS_INVALID_FILE_FOR_SECTION;
+ }
+
+ /* Image-file backed sections are not yet supported */
+ ASSERT((AllocationAttributes & SEC_IMAGE) == 0);
+
+ /* Compute the size of the control area, and allocate it */
+ ControlAreaSize = sizeof(CONTROL_AREA) + sizeof(MSUBSECTION);
+ ControlArea = ExAllocatePoolWithTag(NonPagedPool, ControlAreaSize,
'aCmM');
+ if (!ControlArea)
+ {
+ ObDereferenceObject(File);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ /* Zero it out */
+ RtlZeroMemory(ControlArea, ControlAreaSize);
+
+ /* Did we get a handle, or an object? */
+ if (FileHandle)
+ {
+ /* We got a file handle so we have to lock down the file */
+#if 0
+ Status = FsRtlAcquireToCreateMappedSection(File, SectionPageProtection);
+ if (!NT_SUCCESS(Status))
+ {
+ ExFreePool(ControlArea);
+ ObDereferenceObject(File);
+ return Status;
+ }
+#else
+ /* ReactOS doesn't support this API yet, so do nothing */
+ Status = STATUS_SUCCESS;
+#endif
+ /* Update the top-level IRP so that drivers know what's happening */
+ IoSetTopLevelIrp((PIRP)FSRTL_FSP_TOP_LEVEL_IRP);
+ FileLock = TRUE;
+ }
+
+ /* Lock the PFN database while we play with the section pointers */
+ OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
+
+ /* Image-file backed sections are not yet supported */
+ ASSERT((AllocationAttributes & SEC_IMAGE) == 0);
+
+ /* There should not already be a control area for this file */
+ ASSERT(File->SectionObjectPointer->DataSectionObject == NULL);
+ NewSegment = NULL;
+
+ /* Write down that this CA is being created, and set it */
+ ControlArea->u.Flags.BeingCreated = TRUE;
+ PreviousSectionPointer = File->SectionObjectPointer;
+ File->SectionObjectPointer->DataSectionObject = ControlArea;
+
+ /* We can release the PFN lock now */
+ KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
+
+ /* We don't support previously-mapped file */
+ ASSERT(NewSegment == NULL);
+
+ /* Image-file backed sections are not yet supported */
+ ASSERT((AllocationAttributes & SEC_IMAGE) == 0);
+
+ /* So we always create a data file map */
+ Status = MiCreateDataFileMap(File,
+ &Segment,
+ (PSIZE_T)InputMaximumSize,
+ SectionPageProtection,
+ AllocationAttributes,
+ KernelCall);
+ ASSERT(PreviousSectionPointer == File->SectionObjectPointer);
+ ASSERT(NT_SUCCESS(Status));
+
+ /* Check if a maximum size was specified */
+ if (!InputMaximumSize->QuadPart)
+ {
+ /* Nope, use the segment size */
+ Section.SizeOfSection.QuadPart = (LONGLONG)Segment->SizeOfSegment;
+ }
+ else
+ {
+ /* Yep, use the entered size */
+ Section.SizeOfSection.QuadPart = InputMaximumSize->QuadPart;
+ }
+
+ }
+ else
+ {
+ /* A handle must be supplied with SEC_IMAGE, as this is the no-handle path */
+ if (AllocationAttributes & SEC_IMAGE) return
STATUS_INVALID_FILE_FOR_SECTION;
+
+ /* Not yet supported */
+ ASSERT((AllocationAttributes & SEC_LARGE_PAGES) == 0);
+
+ /* So this must be a pagefile-backed section, create the mappings needed */
+ Status = MiCreatePagingFileMap(&NewSegment,
+ (PSIZE_T)InputMaximumSize,
+ ProtectionMask,
+ AllocationAttributes);
+ if (!NT_SUCCESS(Status)) return Status;
+
+ /* Set the size here, and read the control area */
+ Section.SizeOfSection.QuadPart = NewSegment->SizeOfSegment;
+ ControlArea = NewSegment->ControlArea;
+ }
+
+ /* Did we already have a segment? */
+ if (!NewSegment)
+ {
+ /* This must be the file path and we created a segment */
+ NewSegment = Segment;
+ ASSERT(File != NULL);
+
+ /* Acquire the PFN lock while we set control area flags */
+ OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
+
+ /* We don't support this race condition yet, so assume no waiters */
+ ASSERT(ControlArea->WaitingForDeletion == NULL);
+ ControlArea->WaitingForDeletion = NULL;
+
+ /* Image-file backed sections are not yet supported, nor ROM images */
+ ASSERT((AllocationAttributes & SEC_IMAGE) == 0);
+ ASSERT(Segment->ControlArea->u.Flags.Rom == 0);
+
+ /* Take off the being created flag, and then release the lock */
+ ControlArea->u.Flags.BeingCreated = FALSE;
+ KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
+ }
+
+ /* Check if we locked the file earlier */
+ if (FileLock)
+ {
+ /* Reset the top-level IRP and release the lock */
+ IoSetTopLevelIrp(NULL);
+ //FsRtlReleaseFile(File);
+ FileLock = FALSE;
+ }
/* Set the initial section object data */
Section.InitialPageProtection = SectionPageProtection;
- Section.SizeOfSection.QuadPart = NewSegment->SizeOfSegment;
+
+ /* The mapping created a control area and segment, save the flags */
Section.Segment = NewSegment;
-
- /* THe mapping created a control area and segment, save the flags */
- ControlArea = NewSegment->ControlArea;
Section.u.LongFlags = ControlArea->u.LongFlags;
- /* ARM3 cannot support these right now, make sure they're not being set */
- ASSERT(ControlArea->u.Flags.Image == 0);
- ASSERT(ControlArea->FilePointer == NULL);
+ /* Check if this is a user-mode read-write non-image file mapping */
+ if (!(FileObject) &&
+ (SectionPageProtection & (PAGE_READWRITE | PAGE_EXECUTE_READWRITE))
&&
+ (ControlArea->u.Flags.Image == 0) &&
+ (ControlArea->FilePointer != NULL))
+ {
+ /* Add a reference and set the flag */
+ Section.u.Flags.UserWritable = 1;
+ InterlockedIncrement((PLONG)&ControlArea->WritableUserReferences);
+ }
+
+ /* Check for image mappings or page file mappings */
+ if ((ControlArea->u.Flags.Image == 1) || !(ControlArea->FilePointer))
+ {
+ /* Charge the segment size, and allocate a subsection */
+ PagedCharge = sizeof(SECTION) + NewSegment->TotalNumberOfPtes *
sizeof(MMPTE);
+ Size = sizeof(SUBSECTION);
+ }
+ else
+ {
+ /* Charge nothing, and allocate a mapped subsection */
+ PagedCharge = 0;
+ Size = sizeof(MSUBSECTION);
+ }
+
+ /* Check if this is a normal CA */
ASSERT(ControlArea->u.Flags.GlobalOnlyPerSession == 0);
ASSERT(ControlArea->u.Flags.Rom == 0);
- ASSERT(ControlArea->u.Flags.WasPurged == 0);
-
- /* A pagefile-backed mapping only has one subsection, and this is all ARM3 supports
*/
+
+ /* Charge only a CA, and the subsection is right after */
+ NonPagedCharge = sizeof(CONTROL_AREA);
Subsection = (PSUBSECTION)(ControlArea + 1);
+
+ /* We only support single-subsection mappings */
+ NonPagedCharge += Size;
ASSERT(Subsection->NextSubsection == NULL);
/* Create the actual section object, with enough space for the prototype PTEs */
- Status = ObCreateObject(ExGetPreviousMode(),
+ Status = ObCreateObject(PreviousMode,
MmSectionObjectType,
ObjectAttributes,
- ExGetPreviousMode(),
+ PreviousMode,
NULL,
sizeof(SECTION),
- sizeof(SECTION) +
- NewSegment->TotalNumberOfPtes * sizeof(MMPTE),
- sizeof(CONTROL_AREA) + sizeof(SUBSECTION),
+ PagedCharge,
+ NonPagedCharge,
(PVOID*)&NewSection);
ASSERT(NT_SUCCESS(Status));
/* Now copy the local section object from the stack into this new object */
RtlCopyMemory(NewSection, &Section, sizeof(SECTION));
NewSection->Address.StartingVpn = 0;
+
+ /* For now, only user calls are supported */
+ ASSERT(KernelCall == FALSE);
NewSection->u.Flags.UserReference = TRUE;
/* Migrate the attribute into a flag */
@@ -2170,6 +2377,13 @@
/* Finally release the lock */
KeReleaseGuardedMutex(&MmSectionBasedMutex);
}
+
+ /* Write down if this was a kernel call */
+ ControlArea->u.Flags.WasPurged |= KernelCall;
+ ASSERT(ControlArea->u.Flags.WasPurged == FALSE);
+
+ /* Make sure the segment and the section are the same size, or the section is smaller
*/
+ ASSERT(NewSection->SizeOfSection.QuadPart <=
NewSection->Segment->SizeOfSegment);
/* Return the object and the creation status */
*SectionObject = (PVOID)NewSection;
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] Sat Sep 1 02:32:25 2012
@@ -4860,17 +4860,19 @@
PROS_SECTION_OBJECT *SectionObject = (PROS_SECTION_OBJECT *)Section;
/* Check if an ARM3 section is being created instead */
- if (AllocationAttributes & 1)
+ if (!(AllocationAttributes & SEC_IMAGE) && (AllocationAttributes))
{
- DPRINT1("Creating ARM3 section\n");
- return MmCreateArm3Section(Section,
- DesiredAccess,
- ObjectAttributes,
- MaximumSize,
- SectionPageProtection,
- AllocationAttributes &~ 1,
- FileHandle,
- FileObject);
+ if (!(FileObject) && !(FileHandle))
+ {
+ return MmCreateArm3Section(Section,
+ DesiredAccess,
+ ObjectAttributes,
+ MaximumSize,
+ SectionPageProtection,
+ AllocationAttributes &~ 1,
+ FileHandle,
+ FileObject);
+ }
}
/*