mirror of
https://github.com/reactos/reactos.git
synced 2024-11-23 11:33:31 +08:00
[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 :) svn path=/trunk/; revision=57209
This commit is contained in:
parent
5666d93992
commit
cda03c0940
@ -980,8 +980,51 @@ MiDispatchFault(IN BOOLEAN StoreInstruction,
|
||||
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
|
||||
{
|
||||
|
@ -1335,7 +1335,6 @@ MiDecrementReferenceCount(IN PMMPFN Pfn1,
|
||||
}
|
||||
|
||||
/* 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 */
|
||||
|
@ -894,10 +894,10 @@ MiSessionCommitPageTables(IN PVOID StartVa,
|
||||
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 @@ MiMapViewInSystemSpace(IN PVOID Section,
|
||||
{
|
||||
/* 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 @@ MiMapViewOfDataSection(IN PCONTROL_AREA ControlArea,
|
||||
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 @@ MmCreateArm3Section(OUT PVOID *SectionObject,
|
||||
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 @@ MmCreateArm3Section(OUT PVOID *SectionObject,
|
||||
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;
|
||||
/* 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;
|
||||
|
||||
/* 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);
|
||||
/* 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;
|
||||
Section.Segment = NewSegment;
|
||||
|
||||
/* THe mapping created a control area and segment, save the flags */
|
||||
ControlArea = NewSegment->ControlArea;
|
||||
/* The mapping created a control area and segment, save the flags */
|
||||
Section.Segment = NewSegment;
|
||||
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 */
|
||||
@ -2171,6 +2378,13 @@ MmCreateArm3Section(OUT PVOID *SectionObject,
|
||||
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;
|
||||
return Status;
|
||||
|
@ -4860,17 +4860,19 @@ MmCreateSection (OUT PVOID * Section,
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user