mirror of
https://github.com/reactos/reactos.git
synced 2025-04-21 20:50:29 +00:00
[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. svn path=/trunk/; revision=57000
This commit is contained in:
parent
e97a40328f
commit
a2cb9d5ee2
1 changed files with 99 additions and 40 deletions
|
@ -23,7 +23,7 @@ BOOLEAN UserPdeFault = FALSE;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
LONG MmSystemLockPagesCount;
|
LONG MmSystemLockPagesCount;
|
||||||
|
|
||||||
/* PRIVATE FUNCTIONS **********************************************************/
|
/* PRIVATE FUNCTIONS **********************************************************/
|
||||||
|
|
||||||
PMMPTE
|
PMMPTE
|
||||||
|
@ -305,8 +305,18 @@ MiResolveDemandZeroFault(IN PVOID Address,
|
||||||
/* Check if we need a zero page */
|
/* Check if we need a zero page */
|
||||||
NeedZero = (OldIrql != MM_NOIRQL);
|
NeedZero = (OldIrql != MM_NOIRQL);
|
||||||
|
|
||||||
/* Get the next system page color */
|
#if 0
|
||||||
Color = MI_GET_NEXT_COLOR();
|
/* 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 */
|
/* Check if the PFN database should be acquired */
|
||||||
|
@ -332,31 +342,31 @@ MiResolveDemandZeroFault(IN PVOID Address,
|
||||||
if (!Process) MI_SET_PROCESS2("Kernel Demand 0");
|
if (!Process) MI_SET_PROCESS2("Kernel Demand 0");
|
||||||
|
|
||||||
/* Do we need a zero page? */
|
/* 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 */
|
/* Try to get one, if we couldn't grab a free page and zero it */
|
||||||
PageFrameNumber = MiRemoveZeroPageSafe(Color);
|
PageFrameNumber = MiRemoveZeroPageSafe(Color);
|
||||||
if (PageFrameNumber)
|
if (!PageFrameNumber)
|
||||||
{
|
|
||||||
/* We got a genuine zero page, stop worrying about it */
|
|
||||||
NeedZero = FALSE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
/* We'll need a free page and zero it manually */
|
/* We'll need a free page and zero it manually */
|
||||||
PageFrameNumber = MiRemoveAnyPage(Color);
|
PageFrameNumber = MiRemoveAnyPage(Color);
|
||||||
|
NeedZero = TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!NeedZero)
|
|
||||||
{
|
|
||||||
/* Process or system doesn't want a zero page, grab anything */
|
|
||||||
PageFrameNumber = MiRemoveAnyPage(Color);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* System wants a zero page, obtain one */
|
/* Get a color, and see if we should grab a zero or non-zero page */
|
||||||
PageFrameNumber = MiRemoveZeroPage(Color);
|
Color = MI_GET_NEXT_COLOR();
|
||||||
NeedZero = FALSE;
|
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 */
|
/* Initialize it */
|
||||||
|
@ -434,6 +444,7 @@ MiCompleteProtoPteFault(IN BOOLEAN StoreInstruction,
|
||||||
ULONG_PTR Protection;
|
ULONG_PTR Protection;
|
||||||
PFN_NUMBER PageFrameIndex;
|
PFN_NUMBER PageFrameIndex;
|
||||||
PMMPFN Pfn1, Pfn2;
|
PMMPFN Pfn1, Pfn2;
|
||||||
|
BOOLEAN OriginalProtection, DirtyPage;
|
||||||
|
|
||||||
/* Must be called with an valid prototype PTE, with the PFN lock held */
|
/* Must be called with an valid prototype PTE, with the PFN lock held */
|
||||||
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
|
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
|
||||||
|
@ -458,20 +469,61 @@ MiCompleteProtoPteFault(IN BOOLEAN StoreInstruction,
|
||||||
{
|
{
|
||||||
/* Get the protection from the PTE, there's no real Proto PTE data */
|
/* Get the protection from the PTE, there's no real Proto PTE data */
|
||||||
Protection = PointerPte->u.Soft.Protection;
|
Protection = PointerPte->u.Soft.Protection;
|
||||||
|
|
||||||
|
/* Remember that we did not use the proto protection */
|
||||||
|
OriginalProtection = FALSE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Get the protection from the original PTE link */
|
/* Get the protection from the original PTE link */
|
||||||
OriginalPte = &Pfn1->OriginalPte;
|
OriginalPte = &Pfn1->OriginalPte;
|
||||||
Protection = OriginalPte->u.Soft.Protection;
|
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 */
|
/* Release the PFN lock */
|
||||||
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
||||||
|
|
||||||
/* Remove caching bits */
|
/* Remove caching bits */
|
||||||
Protection &= ~(MM_NOCACHE | MM_NOACCESS);
|
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 */
|
/* Check if this is a kernel or user address */
|
||||||
if (Address < MmSystemRangeStart)
|
if (Address < MmSystemRangeStart)
|
||||||
{
|
{
|
||||||
|
@ -484,10 +536,17 @@ MiCompleteProtoPteFault(IN BOOLEAN StoreInstruction,
|
||||||
MI_MAKE_HARDWARE_PTE(&TempPte, PointerPte, Protection, PageFrameIndex);
|
MI_MAKE_HARDWARE_PTE(&TempPte, PointerPte, Protection, PageFrameIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Set the dirty flag if needed */
|
||||||
|
if (DirtyPage) TempPte.u.Hard.Dirty = TRUE;
|
||||||
|
|
||||||
/* Write the PTE */
|
/* Write the PTE */
|
||||||
MI_WRITE_VALID_PTE(PointerPte, TempPte);
|
MI_WRITE_VALID_PTE(PointerPte, TempPte);
|
||||||
|
|
||||||
|
/* Reset the protection if needed */
|
||||||
|
if (OriginalProtection) Protection = MM_ZERO_ACCESS;
|
||||||
|
|
||||||
/* Return success */
|
/* Return success */
|
||||||
|
ASSERT(PointerPte == MiAddressToPte(Address));
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -823,31 +882,31 @@ MiDispatchFault(IN BOOLEAN StoreInstruction,
|
||||||
/* Has the PTE been made valid yet? */
|
/* Has the PTE been made valid yet? */
|
||||||
if (!SuperProtoPte->u.Hard.Valid)
|
if (!SuperProtoPte->u.Hard.Valid)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED;
|
ASSERT(FALSE);
|
||||||
while (TRUE);
|
|
||||||
}
|
}
|
||||||
else
|
else if (PointerPte->u.Hard.Valid == 1)
|
||||||
{
|
{
|
||||||
/* Resolve the fault -- this will release the PFN lock */
|
ASSERT(FALSE);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 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
|
else
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue