mirror of
https://github.com/reactos/reactos.git
synced 2025-02-24 09:25:10 +00:00
[NTOS]: Implement MiMapViewInSystemSpace, all it took was another 250 lines and we can now map ARM3 sections into memory. Accessing them causes a fault, which we correctly handle with the prototype PTE fault code.
[NTOS]: Added a bogus allocation flag that can be used with Nt/MmCreateSection and MmMapViewInSystemSpace to take the ARM3 path instead. Only for internal testing at the moment. Now we need to look at how to allow mapping these into user-space as well... svn path=/trunk/; revision=48981
This commit is contained in:
parent
b45cdc574c
commit
7c8612ecb3
3 changed files with 304 additions and 2 deletions
|
@ -245,6 +245,11 @@ extern const ULONG MmProtectToPteMask[32];
|
|||
//
|
||||
#define MI_PTE_LOOKUP_NEEDED 0xFFFFF
|
||||
|
||||
//
|
||||
// System views are binned into 64K chunks
|
||||
//
|
||||
#define MI_SYSTEM_VIEW_BUCKET_SIZE 65536
|
||||
|
||||
//
|
||||
// FIXFIX: These should go in ex.h after the pool merge
|
||||
//
|
||||
|
|
|
@ -175,14 +175,14 @@ MiInitializeSystemSpaceMap(IN PVOID InputSession OPTIONAL)
|
|||
Session->SystemSpaceViewStart = MiSystemViewStart;
|
||||
|
||||
/* Create a bitmap to describe system space */
|
||||
BitmapSize = sizeof(RTL_BITMAP) + ((((MmSystemViewSize / 65536) + 31) / 32) * sizeof(ULONG));
|
||||
BitmapSize = sizeof(RTL_BITMAP) + ((((MmSystemViewSize / MI_SYSTEM_VIEW_BUCKET_SIZE) + 31) / 32) * sizeof(ULONG));
|
||||
Session->SystemSpaceBitMap = ExAllocatePoolWithTag(NonPagedPool,
|
||||
BitmapSize,
|
||||
' mM');
|
||||
ASSERT(Session->SystemSpaceBitMap);
|
||||
RtlInitializeBitMap(Session->SystemSpaceBitMap,
|
||||
(PULONG)(Session->SystemSpaceBitMap + 1),
|
||||
MmSystemViewSize / 65536);
|
||||
MmSystemViewSize / MI_SYSTEM_VIEW_BUCKET_SIZE);
|
||||
|
||||
/* Set system space fully empty to begin with */
|
||||
RtlClearAllBits(Session->SystemSpaceBitMap);
|
||||
|
@ -207,6 +207,262 @@ MiInitializeSystemSpaceMap(IN PVOID InputSession OPTIONAL)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
PVOID
|
||||
NTAPI
|
||||
MiInsertInSystemSpace(IN PMMSESSION Session,
|
||||
IN ULONG Buckets,
|
||||
IN PCONTROL_AREA ControlArea)
|
||||
{
|
||||
PVOID Base;
|
||||
ULONG Entry, Hash, i;
|
||||
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 */
|
||||
ASSERT(Buckets < MI_SYSTEM_VIEW_BUCKET_SIZE);
|
||||
ASSERT(Session->SystemSpaceHashEntries < Session->SystemSpaceHashSize);
|
||||
|
||||
/* Find space where to map this view */
|
||||
i = RtlFindClearBitsAndSet(Session->SystemSpaceBitMap, Buckets, 0);
|
||||
ASSERT(i != 0xFFFFFFFF);
|
||||
Base = (PVOID)((ULONG_PTR)Session->SystemSpaceViewStart + (i * MI_SYSTEM_VIEW_BUCKET_SIZE));
|
||||
|
||||
/* Get the hash entry for this allocation */
|
||||
Entry = ((ULONG_PTR)Base & ~(MI_SYSTEM_VIEW_BUCKET_SIZE - 1)) + Buckets;
|
||||
Hash = (Entry >> 16) % Session->SystemSpaceHashKey;
|
||||
|
||||
/* Loop hash entries until a free one is found */
|
||||
while (Session->SystemSpaceViewTable[Hash].Entry)
|
||||
{
|
||||
/* Unless we overflow, in which case loop back at hash o */
|
||||
if (++Hash >= Session->SystemSpaceHashSize) Hash = 0;
|
||||
}
|
||||
|
||||
/* Add this entry into the hash table */
|
||||
Session->SystemSpaceViewTable[Hash].Entry = Entry;
|
||||
Session->SystemSpaceViewTable[Hash].ControlArea = ControlArea;
|
||||
|
||||
/* Hash entry found, increment total and return the base address */
|
||||
Session->SystemSpaceHashEntries++;
|
||||
return Base;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
MiAddMappedPtes(IN PMMPTE FirstPte,
|
||||
IN PFN_NUMBER PteCount,
|
||||
IN PCONTROL_AREA ControlArea)
|
||||
{
|
||||
MMPTE TempPte;
|
||||
PMMPTE PointerPte, ProtoPte, LastProtoPte, LastPte;
|
||||
PSUBSECTION Subsection;
|
||||
|
||||
/* ARM3 doesn't support this yet */
|
||||
ASSERT(ControlArea->u.Flags.GlobalOnlyPerSession == 0);
|
||||
ASSERT(ControlArea->u.Flags.Rom == 0);
|
||||
ASSERT(ControlArea->FilePointer == NULL);
|
||||
|
||||
/* Sanity checks */
|
||||
ASSERT(PteCount != 0);
|
||||
ASSERT(ControlArea->NumberOfMappedViews >= 1);
|
||||
ASSERT(ControlArea->NumberOfUserReferences >= 1);
|
||||
ASSERT(ControlArea->NumberOfSectionReferences != 0);
|
||||
ASSERT(ControlArea->u.Flags.BeingCreated == 0);
|
||||
ASSERT(ControlArea->u.Flags.BeingDeleted == 0);
|
||||
ASSERT(ControlArea->u.Flags.BeingPurged == 0);
|
||||
|
||||
/* Get the PTEs for the actual mapping */
|
||||
PointerPte = FirstPte;
|
||||
LastPte = FirstPte + PteCount;
|
||||
|
||||
/* Get the prototype PTEs that desribe the section mapping in the subsection */
|
||||
Subsection = (PSUBSECTION)(ControlArea + 1);
|
||||
ProtoPte = Subsection->SubsectionBase;
|
||||
LastProtoPte = &Subsection->SubsectionBase[Subsection->PtesInSubsection];
|
||||
|
||||
/* Loop the PTEs for the mapping */
|
||||
while (PointerPte < LastPte)
|
||||
{
|
||||
/* We may have run out of prototype PTEs in this subsection */
|
||||
if (ProtoPte >= LastProtoPte)
|
||||
{
|
||||
/* But we don't handle this yet */
|
||||
UNIMPLEMENTED;
|
||||
while (TRUE);
|
||||
}
|
||||
|
||||
/* The PTE should be completely clear */
|
||||
ASSERT(PointerPte->u.Long == 0);
|
||||
|
||||
/* Build the prototype PTE and write it */
|
||||
MI_MAKE_PROTOTYPE_PTE(&TempPte, ProtoPte);
|
||||
MI_WRITE_INVALID_PTE(PointerPte, TempPte);
|
||||
|
||||
/* Keep going */
|
||||
PointerPte++;
|
||||
ProtoPte++;
|
||||
}
|
||||
|
||||
/* No failure path */
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
MiFillSystemPageDirectory(IN PVOID Base,
|
||||
IN SIZE_T NumberOfBytes)
|
||||
{
|
||||
PMMPDE PointerPde, LastPde, SystemMapPde;
|
||||
MMPDE TempPde;
|
||||
PFN_NUMBER PageFrameIndex;
|
||||
KIRQL OldIrql;
|
||||
PAGED_CODE();
|
||||
|
||||
/* Find the PDEs needed for this mapping */
|
||||
PointerPde = MiAddressToPde(Base);
|
||||
LastPde = MiAddressToPde((PVOID)((ULONG_PTR)Base + NumberOfBytes - 1));
|
||||
|
||||
/* Find the system double-mapped PDE that describes this mapping */
|
||||
SystemMapPde = &MmSystemPagePtes[((ULONG_PTR)PointerPde & (SYSTEM_PD_SIZE - 1)) / sizeof(MMPTE)];
|
||||
|
||||
/* Use the PDE template and loop the PDEs */
|
||||
TempPde = ValidKernelPde;
|
||||
while (PointerPde <= LastPde)
|
||||
{
|
||||
/* Lock the PFN database */
|
||||
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
||||
|
||||
/* Check if we don't already have this PDE mapped */
|
||||
if (SystemMapPde->u.Hard.Valid == 0)
|
||||
{
|
||||
/* Grab a page for it */
|
||||
PageFrameIndex = MiRemoveZeroPage(MI_GET_NEXT_COLOR());
|
||||
ASSERT(PageFrameIndex);
|
||||
TempPde.u.Hard.PageFrameNumber = PageFrameIndex;
|
||||
|
||||
/* Initialize its PFN entry, with the parent system page directory page table */
|
||||
MiInitializePfnForOtherProcess(PageFrameIndex,
|
||||
PointerPde,
|
||||
MmSystemPageDirectory[(PointerPde - MiAddressToPde(NULL)) / PDE_COUNT]);
|
||||
|
||||
/* Make the system PDE entry valid */
|
||||
MI_WRITE_VALID_PTE(SystemMapPde, TempPde);
|
||||
|
||||
/* The system PDE entry might be the PDE itself, so check for this */
|
||||
if (PointerPde->u.Hard.Valid == 0)
|
||||
{
|
||||
/* It's different, so make the real PDE valid too */
|
||||
MI_WRITE_VALID_PTE(PointerPde, TempPde);
|
||||
}
|
||||
}
|
||||
|
||||
/* Release the lock and keep going with the next PDE */
|
||||
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
||||
SystemMapPde++;
|
||||
PointerPde++;
|
||||
}
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
MiCheckPurgeAndUpMapCount(IN PCONTROL_AREA ControlArea,
|
||||
IN BOOLEAN FailIfSystemViews)
|
||||
{
|
||||
KIRQL OldIrql;
|
||||
|
||||
/* Flag not yet supported */
|
||||
ASSERT(FailIfSystemViews == FALSE);
|
||||
|
||||
/* Lock the PFN database */
|
||||
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
||||
|
||||
/* State not yet supported */
|
||||
ASSERT(ControlArea->u.Flags.BeingPurged == 0);
|
||||
|
||||
/* Increase the reference counts */
|
||||
ControlArea->NumberOfMappedViews++;
|
||||
ControlArea->NumberOfUserReferences++;
|
||||
ASSERT(ControlArea->NumberOfSectionReferences != 0);
|
||||
|
||||
/* Release the PFN lock and return success */
|
||||
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
MiMapViewInSystemSpace(IN PVOID Section,
|
||||
IN PMMSESSION Session,
|
||||
OUT PVOID *MappedBase,
|
||||
IN OUT PSIZE_T ViewSize)
|
||||
{
|
||||
PVOID Base;
|
||||
PCONTROL_AREA ControlArea;
|
||||
ULONG Buckets, SectionSize;
|
||||
NTSTATUS Status;
|
||||
PAGED_CODE();
|
||||
|
||||
/* Only global mappings for now */
|
||||
ASSERT(Session == &MmSession);
|
||||
|
||||
/* Get the control area, check for any flags ARM3 doesn't yet support */
|
||||
ControlArea = ((PSECTION)Section)->Segment->ControlArea;
|
||||
ASSERT(ControlArea->u.Flags.Image == 0);
|
||||
ASSERT(ControlArea->FilePointer == NULL);
|
||||
ASSERT(ControlArea->u.Flags.GlobalOnlyPerSession == 0);
|
||||
ASSERT(ControlArea->u.Flags.Rom == 0);
|
||||
ASSERT(ControlArea->u.Flags.WasPurged == 0);
|
||||
|
||||
/* Increase the reference and map count on the control area, no purges yet */
|
||||
Status = MiCheckPurgeAndUpMapCount(ControlArea, FALSE);
|
||||
ASSERT(NT_SUCCESS(Status));
|
||||
|
||||
/* Get the section size at creation time */
|
||||
SectionSize = ((PSECTION)Section)->SizeOfSection.LowPart;
|
||||
|
||||
/* If the caller didn't specify a view size, assume the whole section */
|
||||
if (!(*ViewSize)) *ViewSize = SectionSize;
|
||||
|
||||
/* Check if the caller wanted a larger section than the view */
|
||||
if (*ViewSize > SectionSize)
|
||||
{
|
||||
/* We should probably fail. FIXME TODO */
|
||||
UNIMPLEMENTED;
|
||||
while (TRUE);
|
||||
}
|
||||
|
||||
/* Get the number of 64K buckets required for this mapping */
|
||||
Buckets = *ViewSize / MI_SYSTEM_VIEW_BUCKET_SIZE;
|
||||
if (*ViewSize & (MI_SYSTEM_VIEW_BUCKET_SIZE - 1)) Buckets++;
|
||||
|
||||
/* Check if the view is more than 4GB large */
|
||||
if (Buckets >= MI_SYSTEM_VIEW_BUCKET_SIZE)
|
||||
{
|
||||
/* We should probably fail */
|
||||
UNIMPLEMENTED;
|
||||
while (TRUE);
|
||||
}
|
||||
|
||||
/* Insert this view into system space and get a base address for it */
|
||||
Base = MiInsertInSystemSpace(Session, Buckets, ControlArea);
|
||||
ASSERT(Base);
|
||||
|
||||
/* Create the PDEs needed for this mapping, and double-map them if needed */
|
||||
MiFillSystemPageDirectory(Base, Buckets * MI_SYSTEM_VIEW_BUCKET_SIZE);
|
||||
|
||||
/* Create the actual prototype PTEs for this mapping */
|
||||
Status = MiAddMappedPtes(MiAddressToPte(Base),
|
||||
BYTES_TO_PAGES(*ViewSize),
|
||||
ControlArea);
|
||||
ASSERT(NT_SUCCESS(Status));
|
||||
|
||||
/* Return the base adress of the mapping and success */
|
||||
*MappedBase = Base;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
MiCreatePagingFileMap(OUT PSEGMENT *Segment,
|
||||
|
|
|
@ -54,6 +54,23 @@
|
|||
#pragma alloc_text(INIT, MmInitSectionImplementation)
|
||||
#endif
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
MiMapViewInSystemSpace(IN PVOID Section,
|
||||
IN PVOID Session,
|
||||
OUT PVOID *MappedBase,
|
||||
IN OUT PSIZE_T ViewSize);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
MmCreateArm3Section(OUT PVOID *SectionObject,
|
||||
IN ACCESS_MASK DesiredAccess,
|
||||
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
|
||||
IN PLARGE_INTEGER InputMaximumSize,
|
||||
IN ULONG SectionPageProtection,
|
||||
IN ULONG AllocationAttributes,
|
||||
IN HANDLE FileHandle OPTIONAL,
|
||||
IN PFILE_OBJECT FileObject OPTIONAL);
|
||||
|
||||
/* TYPES *********************************************************************/
|
||||
|
||||
|
@ -4265,6 +4282,16 @@ MmMapViewInSystemSpace (IN PVOID SectionObject,
|
|||
PMMSUPPORT AddressSpace;
|
||||
NTSTATUS Status;
|
||||
|
||||
if ((ULONG_PTR)SectionObject & 1)
|
||||
{
|
||||
PAGED_CODE();
|
||||
extern PVOID MmSession;
|
||||
return MiMapViewInSystemSpace((PVOID)((ULONG_PTR)SectionObject & ~1),
|
||||
&MmSession,
|
||||
MappedBase,
|
||||
ViewSize);
|
||||
}
|
||||
|
||||
DPRINT("MmMapViewInSystemSpace() called\n");
|
||||
|
||||
Section = (PROS_SECTION_OBJECT)SectionObject;
|
||||
|
@ -4386,6 +4413,20 @@ MmCreateSection (OUT PVOID * Section,
|
|||
{
|
||||
ULONG Protection;
|
||||
PROS_SECTION_OBJECT *SectionObject = (PROS_SECTION_OBJECT *)Section;
|
||||
|
||||
/* Check if an ARM3 section is being created instead */
|
||||
if (AllocationAttributes & 0xC0000000)
|
||||
{
|
||||
DPRINT1("arm 3 path\n");
|
||||
return MmCreateArm3Section(Section,
|
||||
DesiredAccess,
|
||||
ObjectAttributes,
|
||||
MaximumSize,
|
||||
SectionPageProtection,
|
||||
AllocationAttributes &~ 0xC0000000,
|
||||
FileHandle,
|
||||
File);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check the protection
|
||||
|
|
Loading…
Reference in a new issue