mirror of
https://github.com/reactos/reactos.git
synced 2025-02-24 09:25:10 +00:00
[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). svn path=/trunk/; revision=48175
This commit is contained in:
parent
7c3bc09fa1
commit
d403f0ffd4
3 changed files with 163 additions and 13 deletions
|
@ -193,6 +193,12 @@ MmProtectToPteMask[32] =
|
||||||
#define MI_IS_SESSION_PTE(Pte) \
|
#define MI_IS_SESSION_PTE(Pte) \
|
||||||
((((PMMPTE)Pte) >= MiSessionBasePte) && (((PMMPTE)Pte) < MiSessionLastPte))
|
((((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
|
// Corresponds to MMPTE_SOFTWARE.Protection
|
||||||
//
|
//
|
||||||
|
@ -469,15 +475,45 @@ extern PFN_NUMBER MmSystemPageDirectory[PD_COUNT];
|
||||||
#define MI_PFN_TO_PFNENTRY(x) (&MmPfnDatabase[1][x])
|
#define MI_PFN_TO_PFNENTRY(x) (&MmPfnDatabase[1][x])
|
||||||
#define MI_PFNENTRY_TO_PFN(x) (x - MmPfnDatabase[1])
|
#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
|
// Creates a valid kernel PTE with the given protection
|
||||||
//
|
//
|
||||||
FORCEINLINE
|
FORCEINLINE
|
||||||
VOID
|
VOID
|
||||||
MI_MAKE_HARDWARE_PTE(IN PMMPTE NewPte,
|
MI_MAKE_HARDWARE_PTE_KERNEL(IN PMMPTE NewPte,
|
||||||
IN PMMPTE MappingPte,
|
IN PMMPTE MappingPte,
|
||||||
IN ULONG ProtectionMask,
|
IN ULONG ProtectionMask,
|
||||||
IN PFN_NUMBER PageFrameNumber)
|
IN PFN_NUMBER PageFrameNumber)
|
||||||
{
|
{
|
||||||
/* Only valid for kernel, non-session PTEs */
|
/* Only valid for kernel, non-session PTEs */
|
||||||
ASSERT(MappingPte > MiHighestUserPte);
|
ASSERT(MappingPte > MiHighestUserPte);
|
||||||
|
@ -492,6 +528,44 @@ MI_MAKE_HARDWARE_PTE(IN PMMPTE NewPte,
|
||||||
NewPte->u.Long |= MmProtectToPteMask[ProtectionMask];
|
NewPte->u.Long |= MmProtectToPteMask[ProtectionMask];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Creates a valid PTE with the given protection
|
||||||
|
//
|
||||||
|
FORCEINLINE
|
||||||
|
VOID
|
||||||
|
MI_MAKE_HARDWARE_PTE(IN PMMPTE NewPte,
|
||||||
|
IN PMMPTE MappingPte,
|
||||||
|
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);
|
||||||
|
|
||||||
|
/* Start fresh */
|
||||||
|
*NewPte = ValidKernelPte;
|
||||||
|
|
||||||
|
/* Set the protection and page */
|
||||||
|
NewPte->u.Hard.Owner = TRUE;
|
||||||
|
NewPte->u.Hard.PageFrameNumber = PageFrameNumber;
|
||||||
|
NewPte->u.Long |= MmProtectToPteMask[ProtectionMask];
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Returns if the page is physically resident (ie: a large page)
|
// Returns if the page is physically resident (ie: a large page)
|
||||||
// FIXFIX: CISC/x86 only?
|
// FIXFIX: CISC/x86 only?
|
||||||
|
|
|
@ -34,8 +34,7 @@ MiCheckPdeForPagedPool(IN PVOID Address)
|
||||||
//
|
//
|
||||||
// Check if this is a fault while trying to access the page table itself
|
// Check if this is a fault while trying to access the page table itself
|
||||||
//
|
//
|
||||||
if ((Address >= (PVOID)MiAddressToPte(MmSystemRangeStart)) &&
|
if (MI_IS_SYSTEM_PAGE_TABLE_ADDRESS(Address))
|
||||||
(Address < (PVOID)PTE_TOP))
|
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
// Send a hint to the page fault handler that this is only a valid fault
|
// Send a hint to the page fault handler that this is only a valid fault
|
||||||
|
@ -84,6 +83,52 @@ MiCheckPdeForPagedPool(IN PVOID Address)
|
||||||
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
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
MiResolveDemandZeroFault(IN PVOID Address,
|
MiResolveDemandZeroFault(IN PVOID Address,
|
||||||
|
@ -93,13 +138,24 @@ MiResolveDemandZeroFault(IN PVOID Address,
|
||||||
{
|
{
|
||||||
PFN_NUMBER PageFrameNumber;
|
PFN_NUMBER PageFrameNumber;
|
||||||
MMPTE TempPte;
|
MMPTE TempPte;
|
||||||
|
BOOLEAN NeedZero = FALSE;
|
||||||
DPRINT("ARM3 Demand Zero Page Fault Handler for address: %p in process: %p\n",
|
DPRINT("ARM3 Demand Zero Page Fault Handler for address: %p in process: %p\n",
|
||||||
Address,
|
Address,
|
||||||
Process);
|
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(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
|
// Lock the PFN database
|
||||||
|
@ -124,11 +180,31 @@ MiResolveDemandZeroFault(IN PVOID Address,
|
||||||
//
|
//
|
||||||
InterlockedIncrement(&KeGetCurrentPrcb()->MmDemandZeroCount);
|
InterlockedIncrement(&KeGetCurrentPrcb()->MmDemandZeroCount);
|
||||||
|
|
||||||
/* Shouldn't see faults for user PTEs yet */
|
/* Zero the page if need be */
|
||||||
ASSERT(PointerPte > MiHighestUserPte);
|
if (NeedZero) MiZeroPfn(PageFrameNumber);
|
||||||
|
|
||||||
/* Build the PTE */
|
/* 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);
|
MI_WRITE_VALID_PTE(PointerPte, TempPte);
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
|
@ -156,7 +156,7 @@ MmCreateKernelStack(IN BOOLEAN GuiStack,
|
||||||
MI_MAKE_SOFTWARE_PTE(&InvalidPte, MM_NOACCESS);
|
MI_MAKE_SOFTWARE_PTE(&InvalidPte, MM_NOACCESS);
|
||||||
|
|
||||||
/* Setup the template stack PTE */
|
/* 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
|
// Acquire the PFN DB lock
|
||||||
|
@ -270,7 +270,7 @@ MmGrowKernelStackEx(IN PVOID StackPointer,
|
||||||
MiInitializePfn(PageFrameIndex, LimitPte, 1);
|
MiInitializePfn(PageFrameIndex, LimitPte, 1);
|
||||||
|
|
||||||
/* Setup the template stack PTE */
|
/* 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 */
|
/* Write the valid PTE */
|
||||||
MI_WRITE_VALID_PTE(LimitPte--, TempPte);
|
MI_WRITE_VALID_PTE(LimitPte--, TempPte);
|
||||||
|
|
Loading…
Reference in a new issue