Author: ion
Date: Tue Jul 31 07:11:52 2012
New Revision: 57000
URL:
http://svn.reactos.org/svn/reactos?rev=57000&view=rev
Log:
[NTOSKRNL]: Additional support for session space. A few more ASSERTs and paranoia.
[NTOSKRNL]: Don't assume all prototype PTEs are cached, in fact none are in ReactOS at
the moment! This resulted in the wrong hardware caching bits for the PEB/TEB and NLS Data
which are using ARM3 section code.
[NTOSKRNL]: Also implement dirty page bit for prototype PTEs.
Modified:
trunk/reactos/ntoskrnl/mm/ARM3/pagfault.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] Tue Jul 31 07:11:52 2012
@@ -23,7 +23,7 @@
#endif
LONG MmSystemLockPagesCount;
-
+
/* PRIVATE FUNCTIONS **********************************************************/
PMMPTE
@@ -305,8 +305,18 @@
/* Check if we need a zero page */
NeedZero = (OldIrql != MM_NOIRQL);
- /* Get the next system page color */
- Color = MI_GET_NEXT_COLOR();
+#if 0
+ /* Session-backed image views must be zeroed */
+ if ((Process == HYDRA_PROCESS) &&
+ ((MI_IS_SESSION_IMAGE_ADDRESS(Address)) ||
+ ((Address >= (PVOID)MiSessionViewStart) &&
+ (Address < (PVOID)MiSessionSpaceWs))))
+ {
+ NeedZero = TRUE;
+ }
+#endif
+ /* Hardcode unknown color */
+ Color = 0xFFFFFFFF;
}
/* Check if the PFN database should be acquired */
@@ -332,31 +342,31 @@
if (!Process) MI_SET_PROCESS2("Kernel Demand 0");
/* Do we need a zero page? */
- if ((NeedZero) && (Process))
+ if (Color != 0xFFFFFFFF)
{
/* Try to get one, if we couldn't grab a free page and zero it */
PageFrameNumber = MiRemoveZeroPageSafe(Color);
- if (PageFrameNumber)
- {
- /* We got a genuine zero page, stop worrying about it */
- NeedZero = FALSE;
- }
- else
+ if (!PageFrameNumber)
{
/* We'll need a free page and zero it manually */
PageFrameNumber = MiRemoveAnyPage(Color);
- }
- }
- else if (!NeedZero)
- {
- /* Process or system doesn't want a zero page, grab anything */
- PageFrameNumber = MiRemoveAnyPage(Color);
+ NeedZero = TRUE;
+ }
}
else
{
- /* System wants a zero page, obtain one */
- PageFrameNumber = MiRemoveZeroPage(Color);
- NeedZero = FALSE;
+ /* Get a color, and see if we should grab a zero or non-zero page */
+ Color = MI_GET_NEXT_COLOR();
+ if (!NeedZero)
+ {
+ /* Process or system doesn't want a zero page, grab anything */
+ PageFrameNumber = MiRemoveAnyPage(Color);
+ }
+ else
+ {
+ /* System wants a zero page, obtain one */
+ PageFrameNumber = MiRemoveZeroPage(Color);
+ }
}
/* Initialize it */
@@ -434,6 +444,7 @@
ULONG_PTR Protection;
PFN_NUMBER PageFrameIndex;
PMMPFN Pfn1, Pfn2;
+ BOOLEAN OriginalProtection, DirtyPage;
/* Must be called with an valid prototype PTE, with the PFN lock held */
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
@@ -458,13 +469,40 @@
{
/* Get the protection from the PTE, there's no real Proto PTE data */
Protection = PointerPte->u.Soft.Protection;
+
+ /* Remember that we did not use the proto protection */
+ OriginalProtection = FALSE;
}
else
{
/* Get the protection from the original PTE link */
OriginalPte = &Pfn1->OriginalPte;
Protection = OriginalPte->u.Soft.Protection;
- }
+
+ /* Remember that we used the original protection */
+ OriginalProtection = TRUE;
+
+ /* Check if this was a write on a read only proto */
+ if ((StoreInstruction) && !(Protection & MM_READWRITE))
+ {
+ /* Clear the flag */
+ StoreInstruction = 0;
+ }
+ }
+
+ /* Check if this was a write on a non-COW page */
+ DirtyPage = FALSE;
+ if ((StoreInstruction) && ((Protection & MM_WRITECOPY) != MM_WRITECOPY))
+ {
+ /* Then the page should be marked dirty */
+ DirtyPage = TRUE;
+
+ /* ReactOS check */
+ ASSERT(Pfn1->OriginalPte.u.Soft.Prototype != 0);
+ }
+
+ /* Not yet handled by ReactOS */
+ ASSERT(LockedPfn == NULL);
/* Release the PFN lock */
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
@@ -472,6 +510,20 @@
/* Remove caching bits */
Protection &= ~(MM_NOCACHE | MM_NOACCESS);
+ /* Setup caching */
+ if (Pfn1->u3.e1.CacheAttribute == MiWriteCombined)
+ {
+ /* Write combining, no caching */
+ MI_PAGE_DISABLE_CACHE(&TempPte);
+ MI_PAGE_WRITE_COMBINED(&TempPte);
+ }
+ else if (Pfn1->u3.e1.CacheAttribute == MiNonCached)
+ {
+ /* Write through, no caching */
+ MI_PAGE_DISABLE_CACHE(&TempPte);
+ MI_PAGE_WRITE_THROUGH(&TempPte);
+ }
+
/* Check if this is a kernel or user address */
if (Address < MmSystemRangeStart)
{
@@ -484,10 +536,17 @@
MI_MAKE_HARDWARE_PTE(&TempPte, PointerPte, Protection, PageFrameIndex);
}
+ /* Set the dirty flag if needed */
+ if (DirtyPage) TempPte.u.Hard.Dirty = TRUE;
+
/* Write the PTE */
MI_WRITE_VALID_PTE(PointerPte, TempPte);
+ /* Reset the protection if needed */
+ if (OriginalProtection) Protection = MM_ZERO_ACCESS;
+
/* Return success */
+ ASSERT(PointerPte == MiAddressToPte(Address));
return STATUS_SUCCESS;
}
@@ -823,31 +882,31 @@
/* Has the PTE been made valid yet? */
if (!SuperProtoPte->u.Hard.Valid)
{
- UNIMPLEMENTED;
- while (TRUE);
- }
- else
- {
- /* Resolve the fault -- this will release the PFN lock */
- ASSERT(PointerPte->u.Hard.Valid == 0);
- Status = MiResolveProtoPteFault(StoreInstruction,
- Address,
- PointerPte,
- PointerProtoPte,
- NULL,
- NULL,
- NULL,
- Process,
- LockIrql,
- TrapInformation);
- ASSERT(Status == STATUS_SUCCESS);
-
- /* Complete this as a transition fault */
- ASSERT(OldIrql == KeGetCurrentIrql());
- ASSERT(OldIrql <= APC_LEVEL);
- ASSERT(KeAreAllApcsDisabled() == TRUE);
- return Status;
- }
+ ASSERT(FALSE);
+ }
+ else if (PointerPte->u.Hard.Valid == 1)
+ {
+ ASSERT(FALSE);
+ }
+
+ /* Resolve the fault -- this will release the PFN lock */
+ Status = MiResolveProtoPteFault(StoreInstruction,
+ Address,
+ PointerPte,
+ PointerProtoPte,
+ NULL,
+ NULL,
+ NULL,
+ Process,
+ LockIrql,
+ TrapInformation);
+ ASSERT(Status == STATUS_SUCCESS);
+
+ /* Complete this as a transition fault */
+ ASSERT(OldIrql == KeGetCurrentIrql());
+ ASSERT(OldIrql <= APC_LEVEL);
+ ASSERT(KeAreAllApcsDisabled() == TRUE);
+ return Status;
}
else
{