From 35673d4a7a1ce76ac2cc7e75111ebc8434f44008 Mon Sep 17 00:00:00 2001 From: Alex Ionescu Date: Fri, 24 Aug 2012 06:08:20 +0000 Subject: [PATCH] [NTOSKRNL]: Fix broken way we were creating prototype PTEs, which was only supporting 256MB worth of prototype PTE area instead of 1GB. [NTOSKRNL]: Add support (macros) for subsection PTEs. svn path=/trunk/; revision=57148 --- reactos/ntoskrnl/mm/ARM3/miarm.h | 69 ++++++++++++++++++++++++++--- reactos/ntoskrnl/mm/ARM3/mminit.c | 41 ++++++++++++++++- reactos/ntoskrnl/mm/ARM3/pagfault.c | 3 -- 3 files changed, 102 insertions(+), 11 deletions(-) diff --git a/reactos/ntoskrnl/mm/ARM3/miarm.h b/reactos/ntoskrnl/mm/ARM3/miarm.h index c99b0a63e59..344f5c689e0 100644 --- a/reactos/ntoskrnl/mm/ARM3/miarm.h +++ b/reactos/ntoskrnl/mm/ARM3/miarm.h @@ -266,7 +266,19 @@ extern const ULONG MmProtectToValue[32]; // #define MiProtoPteToPte(x) \ (PMMPTE)((ULONG_PTR)MmPagedPoolStart + \ - (((x)->u.Proto.ProtoAddressHigh << 7) | (x)->u.Proto.ProtoAddressLow)) + (((x)->u.Proto.ProtoAddressHigh << 9) | (x)->u.Proto.ProtoAddressLow << 2)) + +// +// Decodes a Prototype PTE into the underlying PTE +// +#define MiSubsectionPteToSubsection(x) \ + ((x)->u.Subsect.WhichPool == PagedPool) ? \ + (PMMPTE)((ULONG_PTR)MmSubsectionBase + \ + (((x)->u.Subsect.SubsectionAddressHigh << 7) | \ + (x)->u.Subsect.SubsectionAddressLow << 3)) : \ + (PMMPTE)((ULONG_PTR)MmNonPagedPoolEnd - \ + (((x)->u.Subsect.SubsectionAddressHigh << 7) | \ + (x)->u.Subsect.SubsectionAddressLow << 3)) #endif // @@ -631,7 +643,6 @@ extern PVOID MmSystemCacheStart; extern PVOID MmSystemCacheEnd; extern MMSUPPORT MmSystemCacheWs; extern SIZE_T MmAllocatedNonPagedPool; -extern ULONG_PTR MmSubsectionBase; extern ULONG MmSpecialPoolTag; extern PVOID MmHyperSpaceEnd; extern PMMWSL MmSystemCacheWorkingSetList; @@ -694,6 +705,7 @@ extern MM_AVL_TABLE MmSectionBasedRoot; extern KGUARDED_MUTEX MmSectionBasedMutex; extern PVOID MmHighSectionBase; extern SIZE_T MmSystemLockPagesCount; +extern ULONG_PTR MmSubsectionBase; BOOLEAN FORCEINLINE @@ -875,15 +887,58 @@ MI_MAKE_PROTOTYPE_PTE(IN PMMPTE NewPte, /* * Prototype PTEs are only valid in paged pool by design, this little trick - * lets us only use 28 bits for the adress of the PTE + * lets us only use 30 bits for the adress of the PTE, as long as the area + * stays 1024MB At most. */ Offset = (ULONG_PTR)PointerPte - (ULONG_PTR)MmPagedPoolStart; - /* 7 bits go in the "low", and the other 21 bits go in the "high" */ - NewPte->u.Proto.ProtoAddressLow = Offset & 0x7F; - NewPte->u.Proto.ProtoAddressHigh = (Offset & 0xFFFFFF80) >> 7; - ASSERT(MiProtoPteToPte(NewPte) == PointerPte); + /* + * 7 bits go in the "low" (but we assume the bottom 2 are zero) + * and the other 21 bits go in the "high" + */ + NewPte->u.Proto.ProtoAddressLow = (Offset & 0x1FC) >> 2; + NewPte->u.Proto.ProtoAddressHigh = (Offset & 0x3FFFFE00) >> 9; } + +// +// Builds a Subsection PTE for the address of the Segment +// +FORCEINLINE +VOID +MI_MAKE_SUBSECTION_PTE(IN PMMPTE NewPte, + IN PVOID Segment) +{ + ULONG_PTR Offset; + + /* Mark this as a prototype */ + NewPte->u.Long = 0; + NewPte->u.Subsect.Prototype = 1; + + /* + * Segments are only valid either in nonpaged pool. We store the 20 bit + * difference either from the top or bottom of nonpaged pool, giving a + * maximum of 128MB to each delta, meaning nonpaged pool cannot exceed + * 256MB. + */ + if ((ULONG_PTR)Segment < ((ULONG_PTR)MmSubsectionBase + (128 * _1MB))) + { + Offset = (ULONG_PTR)Segment - (ULONG_PTR)MmSubsectionBase; + NewPte->u.Subsect.WhichPool = PagedPool; + } + else + { + Offset = (ULONG_PTR)MmNonPagedPoolEnd - (ULONG_PTR)Segment; + NewPte->u.Subsect.WhichPool = NonPagedPool; + } + + /* + * 4 bits go in the "low" (but we assume the bottom 3 are zero) + * and the other 20 bits go in the "high" + */ + NewPte->u.Subsect.SubsectionAddressLow = (Offset & 0x78) >> 3; + NewPte->u.Subsect.SubsectionAddressHigh = (Offset & 0xFFFFF80) >> 7; +} + #endif // diff --git a/reactos/ntoskrnl/mm/ARM3/mminit.c b/reactos/ntoskrnl/mm/ARM3/mminit.c index 3d4e1b0f4ac..8b7e87ecefb 100644 --- a/reactos/ntoskrnl/mm/ARM3/mminit.c +++ b/reactos/ntoskrnl/mm/ARM3/mminit.c @@ -2004,6 +2004,11 @@ MmArmInitSystem(IN ULONG Phase, PVOID Bitmap; PPHYSICAL_MEMORY_RUN Run; PFN_NUMBER PageCount; +#if DBG + ULONG j; + PMMPTE PointerPte, TestPte; + MMPTE TempPte; +#endif /* Dump memory descriptors */ if (MiDbgEnableMdDump) MiDbgDumpMemoryDescriptors(); @@ -2063,10 +2068,44 @@ MmArmInitSystem(IN ULONG Phase, /* Initialize session space address layout */ MiInitializeSessionSpaceLayout(); - + /* Set the based section highest address */ MmHighSectionBase = (PVOID)((ULONG_PTR)MmHighestUserAddress - 0x800000); +#if DBG + /* The subection PTE format depends on things being 8-byte aligned */ + ASSERT((sizeof(CONTROL_AREA) % 8) == 0); + ASSERT((sizeof(SUBSECTION) % 8) == 0); + + /* Prototype PTEs are assumed to be in paged pool, so check if the math works */ + PointerPte = (PMMPTE)MmPagedPoolStart; + MI_MAKE_PROTOTYPE_PTE(&TempPte, PointerPte); + TestPte = MiProtoPteToPte(&TempPte); + ASSERT(PointerPte == TestPte); + + /* Try the last nonpaged pool address */ + PointerPte = (PMMPTE)MI_NONPAGED_POOL_END; + MI_MAKE_PROTOTYPE_PTE(&TempPte, PointerPte); + TestPte = MiProtoPteToPte(&TempPte); + ASSERT(PointerPte == TestPte); + + /* Try a bunch of random addresses near the end of the address space */ + PointerPte = (PMMPTE)0xFFFC8000; + for (j = 0; j < 20; j += 1) + { + MI_MAKE_PROTOTYPE_PTE(&TempPte, PointerPte); + TestPte = MiProtoPteToPte(&TempPte); + ASSERT(PointerPte == TestPte); + PointerPte++; + } + + /* Subsection PTEs are always in nonpaged pool, pick a random address to try */ + PointerPte = (PMMPTE)0xFFAACBB8; + MI_MAKE_SUBSECTION_PTE(&TempPte, PointerPte); + TestPte = MiSubsectionPteToSubsection(&TempPte); + ASSERT(PointerPte == TestPte); +#endif + /* Loop all 8 standby lists */ for (i = 0; i < 8; i++) { diff --git a/reactos/ntoskrnl/mm/ARM3/pagfault.c b/reactos/ntoskrnl/mm/ARM3/pagfault.c index 96e884e2336..b8995cfd5f3 100644 --- a/reactos/ntoskrnl/mm/ARM3/pagfault.c +++ b/reactos/ntoskrnl/mm/ARM3/pagfault.c @@ -1742,18 +1742,15 @@ UserFault: { /* Get the protection code and check if this is a proto PTE */ ProtectionCode = TempPte.u.Soft.Protection; - DPRINT1("Code: %lx\n", ProtectionCode); if (TempPte.u.Soft.Prototype) { /* Do we need to go find the real PTE? */ - DPRINT1("Soft: %lx\n", TempPte.u.Soft.PageFileHigh); if (TempPte.u.Soft.PageFileHigh == MI_PTE_LOOKUP_NEEDED) { /* Get the prototype pte and VAD for it */ ProtoPte = MiCheckVirtualAddress(Address, &ProtectionCode, &Vad); - DPRINT1("Address: %p ProtoP %p Code: %lx Vad: %p\n", Address, ProtoPte, ProtectionCode, Vad); if (!ProtoPte) { ASSERT(KeGetCurrentIrql() <= APC_LEVEL);