Author: sir_richard
Date: Thu Jul 22 02:20:27 2010
New Revision: 48175
URL:
http://svn.reactos.org/svn/reactos?rev=48175&view=rev
Log:
[NTOS]: Learn to build User PTEs as well, with MI_MAKE_HARDWARE_PTE_USER.
[NTOS]: MI_MAKE_HARDWARE_PTE becomes MI_MAKE_HARDWARE_PTE_KERNEL, since it assumed this.
MI_MAKE_HARDWARE_PTE is now a "generic" you can use when you don't know what
the PTE should be. It uses MiDetermineUserGlobalMask to set the right bits.
[NTOS]: Add two more helpers: MI_IS_PAGE_TABLE_ADDRESS and
MI_IS_SYSTEM_PAGE_TABLE_ADDDRESS. One is in the symbols, the other I made up to make
things clearer.
[NTOS]: MiResolveDemandZeroFault now knnows how to resolve user-demand-zero-faults.
[NTOS]: Implement MiZeroPfn to do the actual zeroing during user-demand-zero-faults (also
later for VAD faults).
Modified:
trunk/reactos/ntoskrnl/mm/ARM3/miarm.h
trunk/reactos/ntoskrnl/mm/ARM3/pagfault.c
trunk/reactos/ntoskrnl/mm/ARM3/procsup.c
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] Thu Jul 22 02:20:27 2010
@@ -192,6 +192,12 @@
#define MI_IS_SESSION_PTE(Pte) \
((((PMMPTE)Pte) >= MiSessionBasePte) && (((PMMPTE)Pte) <
MiSessionLastPte))
+
+#define MI_IS_PAGE_TABLE_ADDRESS(Address) \
+ (((PVOID)(Address) >= (PVOID)PTE_BASE) && ((PVOID)(Address) <=
(PVOID)PTE_TOP))
+
+#define MI_IS_SYSTEM_PAGE_TABLE_ADDRESS(Address) \
+ (((Address) >= (PVOID)MiAddressToPte(MmSystemRangeStart)) && ((Address)
<= (PVOID)PTE_TOP))
//
// Corresponds to MMPTE_SOFTWARE.Protection
@@ -470,7 +476,60 @@
#define MI_PFNENTRY_TO_PFN(x) (x - MmPfnDatabase[1])
//
+// Figures out the hardware bits for a PTE
+//
+ULONG
+FORCEINLINE
+MiDetermineUserGlobalPteMask(IN PMMPTE PointerPte)
+{
+ MMPTE TempPte;
+
+ /* Start fresh */
+ TempPte.u.Long = 0;
+
+ /* Make it valid and accessed */
+ TempPte.u.Hard.Valid = TRUE;
+ TempPte.u.Hard.Accessed = TRUE;
+
+ /* Is this for user-mode? */
+ if ((PointerPte <= MiHighestUserPte) ||
+ ((PointerPte >= MiAddressToPde(NULL)) && (PointerPte <=
MiHighestUserPde)))
+ {
+ /* Set the owner bit */
+ TempPte.u.Hard.Owner = TRUE;
+ }
+
+ /* FIXME: We should also set the global bit */
+
+ /* Return the protection */
+ return TempPte.u.Long;
+}
+
+//
// Creates a valid kernel PTE with the given protection
+//
+FORCEINLINE
+VOID
+MI_MAKE_HARDWARE_PTE_KERNEL(IN PMMPTE NewPte,
+ IN PMMPTE MappingPte,
+ IN ULONG ProtectionMask,
+ IN PFN_NUMBER PageFrameNumber)
+{
+ /* Only valid for kernel, non-session PTEs */
+ ASSERT(MappingPte > MiHighestUserPte);
+ ASSERT(!MI_IS_SESSION_PTE(MappingPte));
+ ASSERT((MappingPte < (PMMPTE)PDE_BASE) || (MappingPte > (PMMPTE)PDE_TOP));
+
+ /* Start fresh */
+ *NewPte = ValidKernelPte;
+
+ /* Set the protection and page */
+ NewPte->u.Hard.PageFrameNumber = PageFrameNumber;
+ NewPte->u.Long |= MmProtectToPteMask[ProtectionMask];
+}
+
+//
+// Creates a valid PTE with the given protection
//
FORCEINLINE
VOID
@@ -479,15 +538,30 @@
IN ULONG ProtectionMask,
IN PFN_NUMBER PageFrameNumber)
{
+ /* Set the protection and page */
+ NewPte->u.Long = MiDetermineUserGlobalPteMask(MappingPte);
+ NewPte->u.Long |= MmProtectToPteMask[ProtectionMask];
+ NewPte->u.Hard.PageFrameNumber = PageFrameNumber;
+}
+
+//
+// Creates a valid user PTE with the given protection
+//
+FORCEINLINE
+VOID
+MI_MAKE_HARDWARE_PTE_USER(IN PMMPTE NewPte,
+ IN PMMPTE MappingPte,
+ IN ULONG ProtectionMask,
+ IN PFN_NUMBER PageFrameNumber)
+{
/* Only valid for kernel, non-session PTEs */
- ASSERT(MappingPte > MiHighestUserPte);
- ASSERT(!MI_IS_SESSION_PTE(MappingPte));
- ASSERT((MappingPte < (PMMPTE)PDE_BASE) || (MappingPte > (PMMPTE)PDE_TOP));
+ ASSERT(MappingPte <= MiHighestUserPte);
/* Start fresh */
*NewPte = ValidKernelPte;
/* Set the protection and page */
+ NewPte->u.Hard.Owner = TRUE;
NewPte->u.Hard.PageFrameNumber = PageFrameNumber;
NewPte->u.Long |= MmProtectToPteMask[ProtectionMask];
}
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] Thu Jul 22 02:20:27 2010
@@ -34,8 +34,7 @@
//
// Check if this is a fault while trying to access the page table itself
//
- if ((Address >= (PVOID)MiAddressToPte(MmSystemRangeStart)) &&
- (Address < (PVOID)PTE_TOP))
+ if (MI_IS_SYSTEM_PAGE_TABLE_ADDRESS(Address))
{
//
// Send a hint to the page fault handler that this is only a valid fault
@@ -82,6 +81,52 @@
// Return status
//
return Status;
+}
+
+VOID
+NTAPI
+MiZeroPfn(IN PFN_NUMBER PageFrameNumber)
+{
+ PMMPTE ZeroPte;
+ MMPTE TempPte;
+ PMMPFN Pfn1;
+ PVOID ZeroAddress;
+
+ /* Get the PFN for this page */
+ Pfn1 = MiGetPfnEntry(PageFrameNumber);
+ ASSERT(Pfn1);
+
+ /* Grab a system PTE we can use to zero the page */
+ ZeroPte = MiReserveSystemPtes(1, SystemPteSpace);
+ ASSERT(ZeroPte);
+
+ /* Initialize the PTE for it */
+ TempPte = ValidKernelPte;
+ TempPte.u.Hard.PageFrameNumber = PageFrameNumber;
+
+ /* 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);
+ }
+
+ /* Make the system PTE valid with our PFN */
+ MI_WRITE_VALID_PTE(ZeroPte, TempPte);
+
+ /* Get the address it maps to, and zero it out */
+ ZeroAddress = MiPteToAddress(ZeroPte);
+ KeZeroPages(ZeroAddress, PAGE_SIZE);
+
+ /* Now get rid of it */
+ MiReleaseSystemPtes(ZeroPte, 1, SystemPteSpace);
}
NTSTATUS
@@ -93,13 +138,24 @@
{
PFN_NUMBER PageFrameNumber;
MMPTE TempPte;
+ BOOLEAN NeedZero = FALSE;
DPRINT("ARM3 Demand Zero Page Fault Handler for address: %p in process:
%p\n",
Address,
Process);
- /* Must currently only be called by paging path, for system addresses only */
+ /* Must currently only be called by paging path */
ASSERT(OldIrql == MM_NOIRQL);
- ASSERT(Process == NULL);
+ if (Process)
+ {
+ /* Sanity check */
+ ASSERT(MI_IS_PAGE_TABLE_ADDRESS(PointerPte));
+
+ /* No forking yet */
+ ASSERT(Process->ForkInProgress == NULL);
+
+ /* We'll need a zero page */
+ NeedZero = TRUE;
+ }
//
// Lock the PFN database
@@ -124,11 +180,31 @@
//
InterlockedIncrement(&KeGetCurrentPrcb()->MmDemandZeroCount);
- /* Shouldn't see faults for user PTEs yet */
- ASSERT(PointerPte > MiHighestUserPte);
+ /* Zero the page if need be */
+ if (NeedZero) MiZeroPfn(PageFrameNumber);
/* Build the PTE */
- MI_MAKE_HARDWARE_PTE(&TempPte, PointerPte, PointerPte->u.Soft.Protection,
PageFrameNumber);
+ if (PointerPte <= MiHighestUserPte)
+ {
+ /* For user mode */
+ MI_MAKE_HARDWARE_PTE_USER(&TempPte,
+ PointerPte,
+ PointerPte->u.Soft.Protection,
+ PageFrameNumber);
+ }
+ else
+ {
+ /* For kernel mode */
+ MI_MAKE_HARDWARE_PTE(&TempPte,
+ PointerPte,
+ PointerPte->u.Soft.Protection,
+ PageFrameNumber);
+ }
+
+ /* Set it dirty if it's a writable page */
+ if (TempPte.u.Hard.Write) TempPte.u.Hard.Dirty = TRUE;
+
+ /* Write it */
MI_WRITE_VALID_PTE(PointerPte, TempPte);
//
Modified: trunk/reactos/ntoskrnl/mm/ARM3/procsup.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/procsup.c…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/ARM3/procsup.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/ARM3/procsup.c [iso-8859-1] Thu Jul 22 02:20:27 2010
@@ -156,7 +156,7 @@
MI_MAKE_SOFTWARE_PTE(&InvalidPte, MM_NOACCESS);
/* Setup the template stack PTE */
- MI_MAKE_HARDWARE_PTE(&TempPte, PointerPte + 1, MM_READWRITE, 0);
+ MI_MAKE_HARDWARE_PTE_KERNEL(&TempPte, PointerPte + 1, MM_READWRITE, 0);
//
// Acquire the PFN DB lock
@@ -270,7 +270,7 @@
MiInitializePfn(PageFrameIndex, LimitPte, 1);
/* Setup the template stack PTE */
- MI_MAKE_HARDWARE_PTE(&TempPte, LimitPte, MM_READWRITE, PageFrameIndex);
+ MI_MAKE_HARDWARE_PTE_KERNEL(&TempPte, LimitPte, MM_READWRITE,
PageFrameIndex);
/* Write the valid PTE */
MI_WRITE_VALID_PTE(LimitPte--, TempPte);