mirror of
https://github.com/reactos/reactos.git
synced 2025-02-24 01:15:09 +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) \
|
||||
((((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
|
||||
//
|
||||
|
@ -469,15 +475,45 @@ extern PFN_NUMBER MmSystemPageDirectory[PD_COUNT];
|
|||
#define MI_PFN_TO_PFNENTRY(x) (&MmPfnDatabase[1][x])
|
||||
#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(IN PMMPTE NewPte,
|
||||
IN PMMPTE MappingPte,
|
||||
IN ULONG ProtectionMask,
|
||||
IN PFN_NUMBER PageFrameNumber)
|
||||
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);
|
||||
|
@ -492,6 +528,44 @@ MI_MAKE_HARDWARE_PTE(IN PMMPTE NewPte,
|
|||
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)
|
||||
// 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
|
||||
//
|
||||
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
|
||||
|
@ -84,6 +83,52 @@ MiCheckPdeForPagedPool(IN PVOID Address)
|
|||
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
|
||||
NTAPI
|
||||
MiResolveDemandZeroFault(IN PVOID Address,
|
||||
|
@ -93,13 +138,24 @@ MiResolveDemandZeroFault(IN PVOID Address,
|
|||
{
|
||||
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 @@ MiResolveDemandZeroFault(IN PVOID Address,
|
|||
//
|
||||
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);
|
||||
|
||||
//
|
||||
|
|
|
@ -156,7 +156,7 @@ MmCreateKernelStack(IN BOOLEAN GuiStack,
|
|||
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 @@ MmGrowKernelStackEx(IN PVOID StackPointer,
|
|||
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);
|
||||
|
|
Loading…
Reference in a new issue