Author: ion
Date: Fri Aug 3 11:34:35 2012
New Revision: 57033
URL:
http://svn.reactos.org/svn/reactos?rev=57033&view=rev
Log:
[NTOSKRNL]: Support a few more "unsupported" paths that were hitting ASSERTs
before.
[NTOSKRNL]: Massively cleanup triplicated code that is just a series of macros/inlines.
[NTOSKRNL]: Handle more complex prototype PTE faults that are not just demand-zero.
In my private branch, I can now run ReactOS with *all* pagefile-backed sections running
under ARM3 mode.
Modified:
trunk/reactos/ntoskrnl/mm/ARM3/mdlsup.c
trunk/reactos/ntoskrnl/mm/ARM3/miarm.h
trunk/reactos/ntoskrnl/mm/ARM3/pagfault.c
trunk/reactos/ntoskrnl/mm/ARM3/section.c
trunk/reactos/ntoskrnl/mm/ARM3/virtual.c
Modified: trunk/reactos/ntoskrnl/mm/ARM3/mdlsup.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/mdlsup.c?…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/ARM3/mdlsup.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/ARM3/mdlsup.c [iso-8859-1] Fri Aug 3 11:34:35 2012
@@ -602,7 +602,6 @@
PFN_NUMBER PageFrameIndex;
BOOLEAN UsePfnLock;
KIRQL OldIrql;
- USHORT OldRefCount, RefCount;
PMMPFN Pfn1;
DPRINT("Probing MDL: %p\n", Mdl);
@@ -998,45 +997,7 @@
if (CurrentProcess) ASSERT(CurrentProcess->PhysicalVadRoot == NULL);
/* This address should already exist and be fully valid */
- ASSERT(Pfn1->u3.e2.ReferenceCount != 0);
- if (MI_IS_ROS_PFN(Pfn1))
- {
- /* ReactOS Mm doesn't track share count */
- ASSERT(Pfn1->u3.e1.PageLocation == ActiveAndValid);
- }
- else
- {
- /* On ARM3 pages, we should see a valid share count */
- ASSERT((Pfn1->u2.ShareCount != 0) &&
(Pfn1->u3.e1.PageLocation == ActiveAndValid));
-
- /* We don't support mapping a prototype page yet */
- ASSERT((Pfn1->u3.e1.PrototypePte == 0) &&
(Pfn1->OriginalPte.u.Soft.Prototype == 0));
- }
-
- /* More locked pages! */
- InterlockedExchangeAddSizeT(&MmSystemLockPagesCount, 1);
-
- /* Loop trying to update the reference count */
- do
- {
- /* Get the current reference count, make sure it's valid */
- OldRefCount = Pfn1->u3.e2.ReferenceCount;
- ASSERT(OldRefCount != 0);
- ASSERT(OldRefCount < 2500);
-
- /* Bump it up by one */
- RefCount =
InterlockedCompareExchange16((PSHORT)&Pfn1->u3.e2.ReferenceCount,
- OldRefCount + 1,
- OldRefCount);
- ASSERT(RefCount != 0);
- } while (OldRefCount != RefCount);
-
- /* Was this the first lock attempt? */
- if (OldRefCount != 1)
- {
- /* Someone else came through */
- InterlockedExchangeAddSizeT(&MmSystemLockPagesCount, -1);
- }
+ MiReferenceProbedPageAndBumpLockCount(Pfn1);
}
else
{
@@ -1131,7 +1092,6 @@
PVOID Base;
ULONG Flags, PageCount;
KIRQL OldIrql;
- USHORT RefCount, OldRefCount;
PMMPFN Pfn1;
DPRINT("Unlocking MDL: %p\n", Mdl);
@@ -1198,66 +1158,7 @@
// Check if this page is in the PFN database
//
Pfn1 = MiGetPfnEntry(*MdlPages);
- if (Pfn1)
- {
- /* Get the current entry and reference count */
- OldRefCount = Pfn1->u3.e2.ReferenceCount;
- ASSERT(OldRefCount != 0);
-
- /* Is this already the last dereference */
- if (OldRefCount == 1)
- {
- /* It should be on a free list waiting for us */
- ASSERT(Pfn1->u3.e2.ReferenceCount == 1);
- ASSERT(Pfn1->u3.e1.PageLocation != ActiveAndValid);
- ASSERT(Pfn1->u2.ShareCount == 0);
-
- /* Not supported yet */
- ASSERT((Pfn1->u3.e1.PrototypePte == 0) &&
- (Pfn1->OriginalPte.u.Soft.Prototype == 0));
-
- /* One less page */
- InterlockedExchangeAddSizeT(&MmSystemLockPagesCount, -1);
-
- /* Do the last dereference, we're done here */
- MiDecrementReferenceCount(Pfn1, *MdlPages);
- }
- else
- {
- /* Loop decrementing one reference */
- do
- {
- /* Make sure it's still valid */
- OldRefCount = Pfn1->u3.e2.ReferenceCount;
- ASSERT(OldRefCount != 0);
-
- /* Take off one reference */
- RefCount =
InterlockedCompareExchange16((PSHORT)&Pfn1->u3.e2.ReferenceCount,
- OldRefCount - 1,
- OldRefCount);
- ASSERT(RefCount != 0);
- } while (OldRefCount != RefCount);
- ASSERT(RefCount > 1);
-
- /* Are there only lock references left? */
- if (RefCount == 2)
- {
- /* And does the page still have users? */
- if (Pfn1->u2.ShareCount >= 1)
- {
- /* Then it should still be valid */
- ASSERT(Pfn1->u3.e1.PageLocation == ActiveAndValid);
-
- /* Not supported yet */
- ASSERT((Pfn1->u3.e1.PrototypePte == 0) &&
- (Pfn1->OriginalPte.u.Soft.Prototype == 0));
-
- /* But there is one less "locked" page though */
- InterlockedExchangeAddSizeT(&MmSystemLockPagesCount,
-1);
- }
- }
- }
- }
+ if (Pfn1) MiDereferencePfnAndDropLockCount(Pfn1);
} while (++MdlPages < LastPage);
//
@@ -1347,62 +1248,7 @@
{
/* Get the current entry and reference count */
Pfn1 = (PMMPFN)*MdlPages;
- OldRefCount = Pfn1->u3.e2.ReferenceCount;
- ASSERT(OldRefCount != 0);
-
- /* Is this already the last dereference */
- if (OldRefCount == 1)
- {
- /* It should be on a free list waiting for us */
- ASSERT(Pfn1->u3.e2.ReferenceCount == 1);
- ASSERT(Pfn1->u3.e1.PageLocation != ActiveAndValid);
- ASSERT(Pfn1->u2.ShareCount == 0);
-
- /* Not supported yet */
- ASSERT(((Pfn1->u3.e1.PrototypePte == 0) &&
- (Pfn1->OriginalPte.u.Soft.Prototype == 0)));
-
- /* One less page */
- InterlockedExchangeAddSizeT(&MmSystemLockPagesCount, -1);
-
- /* Do the last dereference, we're done here */
- MiDecrementReferenceCount(Pfn1, MiGetPfnEntryIndex(Pfn1));
- }
- else
- {
- /* Loop decrementing one reference */
- do
- {
- /* Make sure it's still valid */
- OldRefCount = Pfn1->u3.e2.ReferenceCount;
- ASSERT(OldRefCount != 0);
-
- /* Take off one reference */
- RefCount =
InterlockedCompareExchange16((PSHORT)&Pfn1->u3.e2.ReferenceCount,
- OldRefCount - 1,
- OldRefCount);
- ASSERT(RefCount != 0);
- } while (OldRefCount != RefCount);
- ASSERT(RefCount > 1);
-
- /* Are there only lock references left? */
- if (RefCount == 2)
- {
- /* And does the page still have users? */
- if (Pfn1->u2.ShareCount >= 1)
- {
- /* Then it should still be valid */
- ASSERT(Pfn1->u3.e1.PageLocation == ActiveAndValid);
-
- /* Not supported yet */
- ASSERT(((Pfn1->u3.e1.PrototypePte == 0) &&
- (Pfn1->OriginalPte.u.Soft.Prototype == 0)));
-
- /* But there is one less "locked" page though */
- InterlockedExchangeAddSizeT(&MmSystemLockPagesCount, -1);
- }
- }
- }
+ MiDereferencePfnAndDropLockCount(Pfn1);
} while (++MdlPages < LastPage);
//
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] Fri Aug 3 11:34:35 2012
@@ -693,6 +693,7 @@
extern MM_AVL_TABLE MmSectionBasedRoot;
extern KGUARDED_MUTEX MmSectionBasedMutex;
extern PVOID MmHighSectionBase;
+extern SIZE_T MmSystemLockPagesCount;
BOOLEAN
FORCEINLINE
@@ -984,6 +985,43 @@
}
//
+// New ARM3<->RosMM PAGE Architecture
+//
+BOOLEAN
+FORCEINLINE
+MiIsRosSectionObject(IN PVOID Section)
+{
+ PROS_SECTION_OBJECT RosSection = Section;
+ if ((RosSection->Type == 'SC') && (RosSection->Size ==
'TN')) return TRUE;
+ return FALSE;
+}
+
+#ifdef _WIN64
+// HACK ON TOP OF HACK ALERT!!!
+#define MI_GET_ROS_DATA(x) \
+ (((x)->RosMmData == 0) ? NULL : ((PMMROSPFN)((ULONG64)(ULONG)((x)->RosMmData) |
\
+ ((ULONG64)MmNonPagedPoolStart &
0xffffffff00000000ULL))))
+#else
+#define MI_GET_ROS_DATA(x) ((PMMROSPFN)(x->RosMmData))
+#endif
+#define MI_IS_ROS_PFN(x) (((x)->u4.AweAllocation == TRUE) &&
(MI_GET_ROS_DATA(x) != NULL))
+#define ASSERT_IS_ROS_PFN(x) ASSERT(MI_IS_ROS_PFN(x) == TRUE);
+typedef struct _MMROSPFN
+{
+ PMM_RMAP_ENTRY RmapListHead;
+ SWAPENTRY SwapEntry;
+} MMROSPFN, *PMMROSPFN;
+
+#define RosMmData AweReferenceCount
+
+VOID
+NTAPI
+MiDecrementReferenceCount(
+ IN PMMPFN Pfn1,
+ IN PFN_NUMBER PageFrameIndex
+);
+
+//
// Locks the working set for the given process
//
FORCEINLINE
@@ -1063,7 +1101,7 @@
/* Own the session working set */
ASSERT((Thread->OwnsSessionWorkingSetExclusive == FALSE) &&
(Thread->OwnsSessionWorkingSetShared == FALSE));
- Thread->OwnsSessionWorkingSetExclusive = TRUE;
+ Thread->OwnsSessionWorkingSetExclusive = TRUE;
}
else
{
@@ -1142,6 +1180,237 @@
return &MmPfnDatabase[Pfn];
};
+//
+// Drops a locked page without dereferencing it
+//
+FORCEINLINE
+VOID
+MiDropLockCount(IN PMMPFN Pfn1)
+{
+ /* This page shouldn't be locked, but it should be valid */
+ ASSERT(Pfn1->u3.e2.ReferenceCount != 0);
+ ASSERT(Pfn1->u2.ShareCount == 0);
+
+ /* Is this the last reference to the page */
+ if (Pfn1->u3.e2.ReferenceCount == 1)
+ {
+ /* It better not be valid */
+ ASSERT(Pfn1->u3.e1.PageLocation != ActiveAndValid);
+
+ /* Is it a prototype PTE? */
+ if ((Pfn1->u3.e1.PrototypePte == 1) &&
+ (Pfn1->OriginalPte.u.Soft.Prototype == 1))
+ {
+ /* We don't handle this */
+ ASSERT(FALSE);
+ }
+
+ /* Update the counter */
+ InterlockedDecrementSizeT(&MmSystemLockPagesCount);
+ }
+}
+
+//
+// Drops a locked page and dereferences it
+//
+FORCEINLINE
+VOID
+MiDereferencePfnAndDropLockCount(IN PMMPFN Pfn1)
+{
+ USHORT RefCount, OldRefCount;
+ PFN_NUMBER PageFrameIndex;
+
+ /* Loop while we decrement the page successfully */
+ do
+ {
+ /* There should be at least one reference */
+ OldRefCount = Pfn1->u3.e2.ReferenceCount;
+ ASSERT(OldRefCount != 0);
+
+ /* Are we the last one */
+ if (OldRefCount == 1)
+ {
+ /* The page shoudln't be shared not active at this point */
+ ASSERT(Pfn1->u3.e2.ReferenceCount == 1);
+ ASSERT(Pfn1->u3.e1.PageLocation != ActiveAndValid);
+ ASSERT(Pfn1->u2.ShareCount == 0);
+
+ /* Is it a prototype PTE? */
+ if ((Pfn1->u3.e1.PrototypePte == 1) &&
+ (Pfn1->OriginalPte.u.Soft.Prototype == 1))
+ {
+ /* We don't handle this */
+ ASSERT(FALSE);
+ }
+
+ /* Update the counter, and drop a reference the long way */
+ InterlockedDecrementSizeT(&MmSystemLockPagesCount);
+ PageFrameIndex = MiGetPfnEntryIndex(Pfn1);
+ MiDecrementReferenceCount(Pfn1, PageFrameIndex);
+ return;
+ }
+
+ /* Drop a reference the short way, and that's it */
+ RefCount =
InterlockedCompareExchange16((PSHORT)&Pfn1->u3.e2.ReferenceCount,
+ OldRefCount - 1,
+ OldRefCount);
+ ASSERT(RefCount != 0);
+ } while (OldRefCount != RefCount);
+
+ /* If we got here, there should be more than one reference */
+ ASSERT(RefCount > 1);
+ if (RefCount == 2)
+ {
+ /* Is it still being shared? */
+ if (Pfn1->u2.ShareCount >= 1)
+ {
+ /* Then it should be valid */
+ ASSERT(Pfn1->u3.e1.PageLocation == ActiveAndValid);
+
+ /* Is it a prototype PTE? */
+ if ((Pfn1->u3.e1.PrototypePte == 1) &&
+ (Pfn1->OriginalPte.u.Soft.Prototype == 1))
+ {
+ /* We don't handle ethis */
+ ASSERT(FALSE);
+ }
+
+ /* Update the counter */
+ InterlockedDecrementSizeT(&MmSystemLockPagesCount);
+ }
+ }
+}
+
+//
+// References a locked page and updates the counter
+// Used in MmProbeAndLockPages to handle different edge cases
+//
+FORCEINLINE
+VOID
+MiReferenceProbedPageAndBumpLockCount(IN PMMPFN Pfn1)
+{
+ USHORT RefCount, OldRefCount;
+
+ /* Sanity check */
+ ASSERT(Pfn1->u3.e2.ReferenceCount != 0);
+
+ /* Does ARM3 own the page? */
+ if (MI_IS_ROS_PFN(Pfn1))
+ {
+ /* ReactOS Mm doesn't track share count */
+ ASSERT(Pfn1->u3.e1.PageLocation == ActiveAndValid);
+ }
+ else
+ {
+ /* On ARM3 pages, we should see a valid share count */
+ ASSERT((Pfn1->u2.ShareCount != 0) && (Pfn1->u3.e1.PageLocation ==
ActiveAndValid));
+
+ /* We don't support mapping a prototype page yet */
+ ASSERT((Pfn1->u3.e1.PrototypePte == 0) &&
(Pfn1->OriginalPte.u.Soft.Prototype == 0));
+ }
+
+ /* More locked pages! */
+ InterlockedIncrementSizeT(&MmSystemLockPagesCount);
+
+ /* Loop trying to update the reference count */
+ do
+ {
+ /* Get the current reference count, make sure it's valid */
+ OldRefCount = Pfn1->u3.e2.ReferenceCount;
+ ASSERT(OldRefCount != 0);
+ ASSERT(OldRefCount < 2500);
+
+ /* Bump it up by one */
+ RefCount =
InterlockedCompareExchange16((PSHORT)&Pfn1->u3.e2.ReferenceCount,
+ OldRefCount + 1,
+ OldRefCount);
+ ASSERT(RefCount != 0);
+ } while (OldRefCount != RefCount);
+
+ /* Was this the first lock attempt? If not, undo our bump */
+ if (OldRefCount != 1) InterlockedDecrementSizeT(&MmSystemLockPagesCount);
+}
+
+//
+// References a locked page and updates the counter
+// Used in all other cases except MmProbeAndLockPages
+//
+FORCEINLINE
+VOID
+MiReferenceUsedPageAndBumpLockCount(IN PMMPFN Pfn1)
+{
+ USHORT NewRefCount;
+
+ /* Is it a prototype PTE? */
+ if ((Pfn1->u3.e1.PrototypePte == 1) &&
+ (Pfn1->OriginalPte.u.Soft.Prototype == 1))
+ {
+ /* We don't handle this */
+ ASSERT(FALSE);
+ }
+
+ /* More locked pages! */
+ InterlockedIncrementSizeT(&MmSystemLockPagesCount);
+
+ /* Update the reference count */
+ NewRefCount = InterlockedIncrement16((PSHORT)&Pfn1->u3.e2.ReferenceCount);
+ if (NewRefCount == 2)
+ {
+ /* Is it locked or shared? */
+ if (Pfn1->u2.ShareCount)
+ {
+ /* It's shared, so make sure it's active */
+ ASSERT(Pfn1->u3.e1.PageLocation == ActiveAndValid);
+ }
+ else
+ {
+ /* It's locked, so we shouldn't lock again */
+ InterlockedDecrementSizeT(&MmSystemLockPagesCount);
+ }
+ }
+ else
+ {
+ /* Someone had already locked the page, so undo our bump */
+ ASSERT(NewRefCount < 2500);
+ InterlockedDecrementSizeT(&MmSystemLockPagesCount);
+ }
+}
+
+//
+// References a locked page and updates the counter
+// Used in all other cases except MmProbeAndLockPages
+//
+FORCEINLINE
+VOID
+MiReferenceUnusedPageAndBumpLockCount(IN PMMPFN Pfn1)
+{
+ USHORT NewRefCount;
+
+ /* Make sure the page isn't used yet */
+ ASSERT(Pfn1->u2.ShareCount == 0);
+ ASSERT(Pfn1->u3.e1.PageLocation != ActiveAndValid);
+
+ /* Is it a prototype PTE? */
+ if ((Pfn1->u3.e1.PrototypePte == 1) &&
+ (Pfn1->OriginalPte.u.Soft.Prototype == 1))
+ {
+ /* We don't handle this */
+ ASSERT(FALSE);
+ }
+
+ /* More locked pages! */
+ InterlockedIncrementSizeT(&MmSystemLockPagesCount);
+
+ /* Update the reference count */
+ NewRefCount = InterlockedIncrement16((PSHORT)&Pfn1->u3.e2.ReferenceCount);
+ if (NewRefCount != 1)
+ {
+ /* Someone had already locked the page, so undo our bump */
+ ASSERT(NewRefCount < 2500);
+ InterlockedDecrementSizeT(&MmSystemLockPagesCount);
+ }
+}
+
BOOLEAN
NTAPI
MmArmInitSystem(
@@ -1425,13 +1694,6 @@
VOID
NTAPI
MiDecrementShareCount(
- IN PMMPFN Pfn1,
- IN PFN_NUMBER PageFrameIndex
-);
-
-VOID
-NTAPI
-MiDecrementReferenceCount(
IN PMMPFN Pfn1,
IN PFN_NUMBER PageFrameIndex
);
@@ -1739,34 +2001,4 @@
return 0;
}
-//
-// New ARM3<->RosMM PAGE Architecture
-//
-BOOLEAN
-FORCEINLINE
-MiIsRosSectionObject(IN PVOID Section)
-{
- PROS_SECTION_OBJECT RosSection = Section;
- if ((RosSection->Type == 'SC') && (RosSection->Size ==
'TN')) return TRUE;
- return FALSE;
-}
-
-#ifdef _WIN64
-// HACK ON TOP OF HACK ALERT!!!
-#define MI_GET_ROS_DATA(x) \
- (((x)->RosMmData == 0) ? NULL : ((PMMROSPFN)((ULONG64)(ULONG)((x)->RosMmData) |
\
- ((ULONG64)MmNonPagedPoolStart &
0xffffffff00000000ULL))))
-#else
-#define MI_GET_ROS_DATA(x) ((PMMROSPFN)(x->RosMmData))
-#endif
-#define MI_IS_ROS_PFN(x) (((x)->u4.AweAllocation == TRUE) &&
(MI_GET_ROS_DATA(x) != NULL))
-#define ASSERT_IS_ROS_PFN(x) ASSERT(MI_IS_ROS_PFN(x) == TRUE);
-typedef struct _MMROSPFN
-{
- PMM_RMAP_ENTRY RmapListHead;
- SWAPENTRY SwapEntry;
-} MMROSPFN, *PMMROSPFN;
-
-#define RosMmData AweReferenceCount
-
/* EOF */
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] Fri Aug 3 11:34:35 2012
@@ -21,8 +21,6 @@
#if MI_TRACE_PFNS
BOOLEAN UserPdeFault = FALSE;
#endif
-
-LONG MmSystemLockPagesCount;
/* PRIVATE FUNCTIONS **********************************************************/
@@ -505,7 +503,7 @@
IN PMMPTE PointerPte,
IN PMMPTE PointerProtoPte,
IN KIRQL OldIrql,
- IN PMMPFN* LockedPfn)
+ IN PMMPFN* LockedProtoPfn)
{
MMPTE TempPte;
PMMPTE OriginalPte, PageTablePte;
@@ -569,8 +567,14 @@
ASSERT(Pfn1->OriginalPte.u.Soft.Prototype != 0);
}
- /* Not yet handled by ReactOS */
- ASSERT(LockedPfn == NULL);
+ /* Did we get a locked incoming PFN? */
+ if (*LockedProtoPfn)
+ {
+ /* Drop a reference */
+ ASSERT((*LockedProtoPfn)->u3.e2.ReferenceCount >= 1);
+ MiDereferencePfnAndDropLockCount(*LockedProtoPfn);
+ *LockedProtoPfn = NULL;
+ }
/* Release the PFN lock */
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
@@ -630,7 +634,6 @@
PMMPFN Pfn1;
MMPTE TempPte;
PMMPTE PointerToPteForProtoPage;
- USHORT NewRefCount;
DPRINT1("Transition fault on 0x%p with PTE 0x%lx in process %s\n",
FaultingAddress, PointerPte, CurrentProcess->ImageFileName);
/* Windowss does this check */
@@ -681,57 +684,14 @@
/* Otherwise, the page is removed from its list */
DPRINT1("Transition page in free/zero list\n");
MiUnlinkPageFromList(Pfn1);
-
- /* Windows does these checks -- perhaps a macro? */
- ASSERT(Pfn1->u2.ShareCount == 0);
- ASSERT(Pfn1->u2.ShareCount == 0);
- ASSERT(Pfn1->u3.e1.PageLocation != ActiveAndValid);
-
- /* Check if this was a prototype PTE */
- if ((Pfn1->u3.e1.PrototypePte == 1) &&
- (Pfn1->OriginalPte.u.Soft.Prototype == 1))
- {
- DPRINT1("Prototype floating page not yet supported\n");
- ASSERT(FALSE);
- }
-
- /* Update counter */
- InterlockedIncrementSizeT(&MmSystemLockPagesCount);
-
- /* We must be the first reference */
- NewRefCount =
InterlockedIncrement16((PSHORT)&Pfn1->u3.e2.ReferenceCount);
- ASSERT(NewRefCount == 1);
+ MiReferenceUnusedPageAndBumpLockCount(Pfn1);
}
/* At this point, there should no longer be any in-page errors */
ASSERT(Pfn1->u4.InPageError == 0);
/* Check if this was a PFN with no more share references */
- if (Pfn1->u2.ShareCount == 0)
- {
- /* Windows checks for these... maybe a macro? */
- ASSERT(Pfn1->u3.e2.ReferenceCount != 0);
- ASSERT(Pfn1->u2.ShareCount == 0);
-
- /* Was this the last active reference to it */
- DPRINT1("Page share count is zero\n");
- if (Pfn1->u3.e2.ReferenceCount == 1)
- {
- /* The page should be leaking somewhere on the free/zero list */
- DPRINT1("Page reference count is one\n");
- ASSERT(Pfn1->u3.e1.PageLocation != ActiveAndValid);
- if ((Pfn1->u3.e1.PrototypePte == 1) &&
- (Pfn1->OriginalPte.u.Soft.Prototype == 1))
- {
- /* Do extra processing if it was a prototype page */
- DPRINT1("Prototype floating page not yet supported\n");
- ASSERT(FALSE);
- }
-
- /* Update counter */
- InterlockedDecrementSizeT(&MmSystemLockPagesCount);
- }
- }
+ if (Pfn1->u2.ShareCount == 0) MiDropLockCount(Pfn1);
/* Bump the share count and make the page valid */
Pfn1->u2.ShareCount++;
@@ -821,7 +781,7 @@
PointerPte,
PointerProtoPte,
OldIrql,
- NULL);
+ OutPfn);
}
/* Make sure there's some protection mask */
@@ -897,7 +857,7 @@
PointerPte,
PointerProtoPte,
OldIrql,
- NULL);
+ OutPfn);
}
NTSTATUS
@@ -915,7 +875,7 @@
KIRQL OldIrql, LockIrql;
NTSTATUS Status;
PMMPTE SuperProtoPte;
- PMMPFN Pfn1;
+ PMMPFN Pfn1, OutPfn = NULL;
PFN_NUMBER PageFrameIndex, PteCount, ProcessedPtes;
DPRINT("ARM3 Page Fault Dispatcher for address: %p in process: %p\n",
Address,
@@ -964,7 +924,7 @@
Address,
PointerPte,
PointerProtoPte,
- NULL,
+ &OutPfn,
NULL,
NULL,
Process,
@@ -1010,14 +970,24 @@
while (TRUE)
{
/* For our current usage, this should be true */
- ASSERT(TempPte.u.Hard.Valid == 1);
- ASSERT(TempPte.u.Soft.Prototype == 0);
- ASSERT(TempPte.u.Soft.Transition == 0);
-
- /* Bump the share count on the PTE */
- PageFrameIndex = PFN_FROM_PTE(&TempPte);
- Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);
- Pfn1->u2.ShareCount++;
+ if (TempPte.u.Hard.Valid == 1)
+ {
+ /* Bump the share count on the PTE */
+ PageFrameIndex = PFN_FROM_PTE(&TempPte);
+ Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);
+ Pfn1->u2.ShareCount++;
+ }
+ else if ((TempPte.u.Soft.Prototype == 0) &&
+ (TempPte.u.Soft.Transition == 1))
+ {
+ /* No standby support yet */
+ ASSERT(FALSE);
+ }
+ else
+ {
+ /* Page is invalid, get out of the loop */
+ break;
+ }
/* One more done, was it the last? */
if (++ProcessedPtes == PteCount)
@@ -1028,7 +998,7 @@
PointerPte,
PointerProtoPte,
LockIrql,
- NULL);
+ &OutPfn);
/* THIS RELEASES THE PFN LOCK! */
break;
@@ -1038,21 +1008,62 @@
ASSERT(FALSE);
}
- /* Only path that we support for now */
- ASSERT(ProcessedPtes != 0);
-
- /* Bump the transition count */
- InterlockedExchangeAdd(&KeGetCurrentPrcb()->MmTransitionCount,
ProcessedPtes);
- ProcessedPtes--;
-
- /* Loop all the processing we did */
- ASSERT(ProcessedPtes == 0);
+ /* Did we resolve the fault? */
+ if (ProcessedPtes)
+ {
+ /* Bump the transition count */
+ InterlockedExchangeAdd(&KeGetCurrentPrcb()->MmTransitionCount,
ProcessedPtes);
+ ProcessedPtes--;
+
+ /* Loop all the processing we did */
+ ASSERT(ProcessedPtes == 0);
+
+ /* Complete this as a transition fault */
+ ASSERT(OldIrql == KeGetCurrentIrql());
+ ASSERT(OldIrql <= APC_LEVEL);
+ ASSERT(KeAreAllApcsDisabled() == TRUE);
+ return STATUS_PAGE_FAULT_TRANSITION;
+ }
+
+ /* We did not -- PFN lock is still held, prepare to resolve prototype PTE
fault */
+ OutPfn = MI_PFN_ELEMENT(SuperProtoPte->u.Hard.PageFrameNumber);
+ MiReferenceUsedPageAndBumpLockCount(OutPfn);
+ ASSERT(OutPfn->u3.e2.ReferenceCount > 1);
+ ASSERT(PointerPte->u.Hard.Valid == 0);
+
+ /* Resolve the fault -- this will release the PFN lock */
+ Status = MiResolveProtoPteFault(StoreInstruction,
+ Address,
+ PointerPte,
+ PointerProtoPte,
+ &OutPfn,
+ NULL,
+ NULL,
+ Process,
+ LockIrql,
+ TrapInformation);
+ ASSERT(Status == STATUS_SUCCESS);
+
+ /* Did the routine clean out the PFN or should we? */
+ if (OutPfn)
+ {
+ /* We had a locked PFN, so acquire the PFN lock to dereference it */
+ ASSERT(PointerProtoPte != NULL);
+ OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
+
+ /* Dereference the locked PFN */
+ MiDereferencePfnAndDropLockCount(OutPfn);
+ ASSERT(OutPfn->u3.e2.ReferenceCount >= 1);
+
+ /* And now release the lock */
+ KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
+ }
/* Complete this as a transition fault */
ASSERT(OldIrql == KeGetCurrentIrql());
ASSERT(OldIrql <= APC_LEVEL);
ASSERT(KeAreAllApcsDisabled() == TRUE);
- return STATUS_PAGE_FAULT_TRANSITION;
+ return Status;
}
}
@@ -1729,8 +1740,46 @@
}
else
{
- /* This path is not yet supported */
- ASSERT(FALSE);
+ /* Get the protection code and check if this is a proto PTE */
+ ProtectionCode = TempPte.u.Soft.Protection;
+ DPRINT1("Code: %lx\n", ProtecitonCode);
+ if (TempPte.u.Soft.Prototype)
+ {
+ /* Do we need to go find the real PTE? */
+ DPRINT1("Soft: %lx\n", TempPte.u.Soft.PageFileHigh);
+ if (TempPte.u.Soft.PageFileHigh == MI_PTE_LOOKUP_NEEDED)
+ {
+ /* Get the prototype pte and VAD for it */
+ ProtoPte = MiCheckVirtualAddress(Address,
+ &ProtectionCode,
+ &Vad);
+ DPRINT1("Address: %p ProtoP %p Code: %lx Vad: %p\n", Address,
ProtoPte, ProtectionCode, Vad);
+ if (!ProtoPte)
+ {
+ ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
+ MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
+ return STATUS_ACCESS_VIOLATION;
+ }
+ }
+ else
+ {
+ /* Get the prototype PTE! */
+ ProtoPte = MiProtoPteToPte(&TempPte);
+
+ /* Is it read-only */
+ if (TempPte.u.Proto.ReadOnly)
+ {
+ /* Set read-only code */
+ ProtectionCode = MM_READONLY;
+ }
+ else
+ {
+ /* Set unknown protection */
+ ProtectionCode = 0x100;
+ ASSERT(CurrentProcess->CloneRoot != NULL);
+ }
+ }
+ }
}
/* FIXME: Run MiAccessCheck */
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] Fri Aug 3 11:34:35 2012
@@ -806,7 +806,6 @@
return Status;
}
-
NTSTATUS
NTAPI
MiSessionCommitPageTables(IN PVOID StartVa,
Modified: trunk/reactos/ntoskrnl/mm/ARM3/virtual.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/virtual.c…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/ARM3/virtual.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/ARM3/virtual.c [iso-8859-1] Fri Aug 3 11:34:35 2012
@@ -1313,9 +1313,9 @@
OUT PVOID *NextVa)
{
- PMMPTE PointerPte;
+ PMMPTE PointerPte, ProtoPte;
PMMPDE PointerPde;
- MMPTE TempPte;
+ MMPTE TempPte, TempProtoPte;
BOOLEAN DemandZeroPte = TRUE, ValidPte = FALSE;
ULONG State = MEM_RESERVE, Protect = 0;
ASSERT((Vad->StartingVpn <= ((ULONG_PTR)Va >> PAGE_SHIFT)) &&
@@ -1353,6 +1353,7 @@
if (ValidPte)
{
/* FIXME: watch out for large pages */
+ ASSERT(PointerPde->u.Hard.LargePage == FALSE);
/* Capture the PTE */
TempPte = *PointerPte;
@@ -1375,6 +1376,11 @@
{
/* This means it's committed */
State = MEM_COMMIT;
+
+ /* We don't support these */
+ ASSERT(Vad->u.VadFlags.VadType != VadDevicePhysicalMemory);
+ ASSERT(Vad->u.VadFlags.VadType != VadRotatePhysical);
+ ASSERT(Vad->u.VadFlags.VadType != VadAwe);
/* Get protection state of this page */
Protect = MiGetPageProtection(PointerPte);
@@ -1395,11 +1401,35 @@
/* Check if this was a demand-zero PTE, since we need to find the state */
if (DemandZeroPte)
{
- /* Check if this is private commited memory, or an image-backed VAD */
+ /* Not yet handled */
+ ASSERT(Vad->u.VadFlags.VadType != VadDevicePhysicalMemory);
+ ASSERT(Vad->u.VadFlags.VadType != VadAwe);
+
+ /* Check if this is private commited memory, or an section-backed VAD */
if ((Vad->u.VadFlags.PrivateMemory == 0) && (Vad->ControlArea))
{
- DPRINT1("Not supported\n");
- ASSERT(FALSE);
+ /* Tell caller about the next range */
+ *NextVa = (PVOID)((ULONG_PTR)Va + PAGE_SIZE);
+
+ /* Get the prototype PTE for this VAD */
+ ProtoPte = MI_GET_PROTOTYPE_PTE_FOR_VPN(Vad,
+ (ULONG_PTR)Va >> PAGE_SHIFT);
+ if (ProtoPte)
+ {
+ /* We should unlock the working set, but it's not being held! */
+
+ /* Is the prototype PTE actually valid (committed)? */
+ TempProtoPte = *ProtoPte;
+ if (TempProtoPte.u.Long)
+ {
+ /* Unless this is a memory-mapped file, handle it like private VAD
*/
+ State = MEM_COMMIT;
+ ASSERT(Vad->u.VadFlags.VadType != VadImageMap);
+ Protect = MmProtectToValue[Vad->u.VadFlags.Protection];
+ }
+
+ /* We should re-lock the working set */
+ }
}
else if (Vad->u.VadFlags.MemCommit)
{