mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 22:52:54 +00:00
[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
This commit is contained in:
parent
dab0273c89
commit
35673d4a7a
3 changed files with 102 additions and 11 deletions
|
@ -266,7 +266,19 @@ extern const ULONG MmProtectToValue[32];
|
||||||
//
|
//
|
||||||
#define MiProtoPteToPte(x) \
|
#define MiProtoPteToPte(x) \
|
||||||
(PMMPTE)((ULONG_PTR)MmPagedPoolStart + \
|
(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
|
#endif
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -631,7 +643,6 @@ extern PVOID MmSystemCacheStart;
|
||||||
extern PVOID MmSystemCacheEnd;
|
extern PVOID MmSystemCacheEnd;
|
||||||
extern MMSUPPORT MmSystemCacheWs;
|
extern MMSUPPORT MmSystemCacheWs;
|
||||||
extern SIZE_T MmAllocatedNonPagedPool;
|
extern SIZE_T MmAllocatedNonPagedPool;
|
||||||
extern ULONG_PTR MmSubsectionBase;
|
|
||||||
extern ULONG MmSpecialPoolTag;
|
extern ULONG MmSpecialPoolTag;
|
||||||
extern PVOID MmHyperSpaceEnd;
|
extern PVOID MmHyperSpaceEnd;
|
||||||
extern PMMWSL MmSystemCacheWorkingSetList;
|
extern PMMWSL MmSystemCacheWorkingSetList;
|
||||||
|
@ -694,6 +705,7 @@ extern MM_AVL_TABLE MmSectionBasedRoot;
|
||||||
extern KGUARDED_MUTEX MmSectionBasedMutex;
|
extern KGUARDED_MUTEX MmSectionBasedMutex;
|
||||||
extern PVOID MmHighSectionBase;
|
extern PVOID MmHighSectionBase;
|
||||||
extern SIZE_T MmSystemLockPagesCount;
|
extern SIZE_T MmSystemLockPagesCount;
|
||||||
|
extern ULONG_PTR MmSubsectionBase;
|
||||||
|
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
FORCEINLINE
|
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
|
* 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;
|
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;
|
* 7 bits go in the "low" (but we assume the bottom 2 are zero)
|
||||||
NewPte->u.Proto.ProtoAddressHigh = (Offset & 0xFFFFFF80) >> 7;
|
* and the other 21 bits go in the "high"
|
||||||
ASSERT(MiProtoPteToPte(NewPte) == PointerPte);
|
*/
|
||||||
|
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
|
#endif
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
|
@ -2004,6 +2004,11 @@ MmArmInitSystem(IN ULONG Phase,
|
||||||
PVOID Bitmap;
|
PVOID Bitmap;
|
||||||
PPHYSICAL_MEMORY_RUN Run;
|
PPHYSICAL_MEMORY_RUN Run;
|
||||||
PFN_NUMBER PageCount;
|
PFN_NUMBER PageCount;
|
||||||
|
#if DBG
|
||||||
|
ULONG j;
|
||||||
|
PMMPTE PointerPte, TestPte;
|
||||||
|
MMPTE TempPte;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Dump memory descriptors */
|
/* Dump memory descriptors */
|
||||||
if (MiDbgEnableMdDump) MiDbgDumpMemoryDescriptors();
|
if (MiDbgEnableMdDump) MiDbgDumpMemoryDescriptors();
|
||||||
|
@ -2063,10 +2068,44 @@ MmArmInitSystem(IN ULONG Phase,
|
||||||
|
|
||||||
/* Initialize session space address layout */
|
/* Initialize session space address layout */
|
||||||
MiInitializeSessionSpaceLayout();
|
MiInitializeSessionSpaceLayout();
|
||||||
|
|
||||||
/* Set the based section highest address */
|
/* Set the based section highest address */
|
||||||
MmHighSectionBase = (PVOID)((ULONG_PTR)MmHighestUserAddress - 0x800000);
|
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 */
|
/* Loop all 8 standby lists */
|
||||||
for (i = 0; i < 8; i++)
|
for (i = 0; i < 8; i++)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1742,18 +1742,15 @@ UserFault:
|
||||||
{
|
{
|
||||||
/* Get the protection code and check if this is a proto PTE */
|
/* Get the protection code and check if this is a proto PTE */
|
||||||
ProtectionCode = TempPte.u.Soft.Protection;
|
ProtectionCode = TempPte.u.Soft.Protection;
|
||||||
DPRINT1("Code: %lx\n", ProtectionCode);
|
|
||||||
if (TempPte.u.Soft.Prototype)
|
if (TempPte.u.Soft.Prototype)
|
||||||
{
|
{
|
||||||
/* Do we need to go find the real PTE? */
|
/* 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)
|
if (TempPte.u.Soft.PageFileHigh == MI_PTE_LOOKUP_NEEDED)
|
||||||
{
|
{
|
||||||
/* Get the prototype pte and VAD for it */
|
/* Get the prototype pte and VAD for it */
|
||||||
ProtoPte = MiCheckVirtualAddress(Address,
|
ProtoPte = MiCheckVirtualAddress(Address,
|
||||||
&ProtectionCode,
|
&ProtectionCode,
|
||||||
&Vad);
|
&Vad);
|
||||||
DPRINT1("Address: %p ProtoP %p Code: %lx Vad: %p\n", Address, ProtoPte, ProtectionCode, Vad);
|
|
||||||
if (!ProtoPte)
|
if (!ProtoPte)
|
||||||
{
|
{
|
||||||
ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
|
ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue