mirror of
https://github.com/reactos/reactos.git
synced 2025-01-03 21:09:19 +00:00
[NTOSKRNL/MM]
- use ARM3 allocation for PDE pages. There is now one table for system PDEs, and their pages are not leaked anymore. Also fix bug 5857 (aka mshtml bug). Only for x86 now. Timo, I think you should do it for amd64 as well. Thanks for your patience, go back to testing now. A huge congrats to Cameron and Thomas, without them I wouldn't even have dared touching this code. svn path=/trunk/; revision=55631
This commit is contained in:
parent
ebc25c8702
commit
af5540c434
2 changed files with 101 additions and 120 deletions
|
@ -258,8 +258,8 @@ MiDeletePte(IN PMMPTE PointerPte,
|
|||
#if (_MI_PAGING_LEVELS == 2)
|
||||
}
|
||||
#endif
|
||||
/* FIXME: Drop the reference on the page table. For now, leak it until RosMM is gone */
|
||||
//MiDecrementShareCount(MiGetPfnEntry(PFN_FROM_PTE(PointerPde)), PFN_FROM_PTE(PointerPde));
|
||||
/* Drop the reference on the page table. */
|
||||
MiDecrementShareCount(MiGetPfnEntry(PFN_FROM_PTE(PointerPde)), PFN_FROM_PTE(PointerPde));
|
||||
|
||||
/* Drop the share count */
|
||||
MiDecrementShareCount(Pfn1, PageFrameIndex);
|
||||
|
|
|
@ -43,8 +43,6 @@
|
|||
#define HYPERSPACE (0xc0400000)
|
||||
#define IS_HYPERSPACE(v) (((ULONG)(v) >= HYPERSPACE && (ULONG)(v) < HYPERSPACE + 0x400000))
|
||||
|
||||
ULONG MmGlobalKernelPageDirectory[1024];
|
||||
|
||||
#define PTE_TO_PFN(X) ((X) >> PAGE_SHIFT)
|
||||
#define PFN_TO_PTE(X) ((X) << PAGE_SHIFT)
|
||||
|
||||
|
@ -200,72 +198,101 @@ ProtectToPTE(ULONG flProtect)
|
|||
return(Attributes);
|
||||
}
|
||||
|
||||
static
|
||||
VOID
|
||||
MmDeletePageDirectoryEntry(ULONG PdeEntry)
|
||||
FORCEINLINE
|
||||
MmDeletePageDirectoryEntry(PMMPDE PointerPde)
|
||||
{
|
||||
KIRQL OldIrql;
|
||||
PMMPFN Page;
|
||||
|
||||
Page = MiGetPfnEntry(PTE_TO_PFN(PdeEntry));
|
||||
Page = MiGetPfnEntry(PointerPde->u.Hard.PageFrameNumber);
|
||||
|
||||
/* Check if this is a legacy allocation */
|
||||
if (MI_IS_ROS_PFN(Page))
|
||||
{
|
||||
/* Free it using the legacy API */
|
||||
MmReleasePageMemoryConsumer(MC_SYSTEM, PTE_TO_PFN(PdeEntry));
|
||||
}
|
||||
else
|
||||
{
|
||||
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
||||
/* This should not be a legacy allocation*/
|
||||
ASSERT(MI_IS_ROS_PFN(Page) == FALSE);
|
||||
|
||||
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
||||
|
||||
/* Free it using the ARM3 API */
|
||||
MI_SET_PFN_DELETED(Page);
|
||||
MiDecrementShareCount(Page, PTE_TO_PFN(PdeEntry));
|
||||
/* Free it using the ARM3 API */
|
||||
MI_SET_PFN_DELETED(Page);
|
||||
MiDecrementShareCount(Page, PointerPde->u.Hard.PageFrameNumber);
|
||||
|
||||
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
||||
}
|
||||
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
MmDeleteProcessPageDirectory(PEPROCESS Process)
|
||||
{
|
||||
PULONG PageDir;
|
||||
PMMPDE PdeBase, PointerPde;
|
||||
ULONG PdeOffset;
|
||||
KIRQL OldIrql;
|
||||
|
||||
/* Map the page directory in hyperspace */
|
||||
PageDir = MmCreateHyperspaceMapping(PTE_TO_PFN(Process->Pcb.DirectoryTableBase[0]));
|
||||
PdeBase = MiMapPageInHyperSpace(PsGetCurrentProcess(),
|
||||
Process->Pcb.DirectoryTableBase[0] >> PAGE_SHIFT,
|
||||
&OldIrql);
|
||||
|
||||
/* Loop the user land page directory */
|
||||
for (PdeOffset = 0; PdeOffset < ADDR_TO_PDE_OFFSET(MmSystemRangeStart); PdeOffset++)
|
||||
for (PdeOffset = 0; PdeOffset < MiGetPdeOffset(MmSystemRangeStart); PdeOffset++)
|
||||
{
|
||||
PointerPde = PdeBase + PdeOffset;
|
||||
/* Check if a valid PDE exists here */
|
||||
if (PageDir[PdeOffset] != 0)
|
||||
if (PointerPde->u.Hard.Valid)
|
||||
{
|
||||
/* Free the page that backs it */
|
||||
MmDeletePageDirectoryEntry(PageDir[PdeOffset]);
|
||||
MmDeletePageDirectoryEntry(PointerPde);
|
||||
}
|
||||
}
|
||||
|
||||
/* Free the hyperspace mapping page (ARM3) */
|
||||
MmDeletePageDirectoryEntry(PageDir[ADDR_TO_PDE_OFFSET(HYPERSPACE)]);
|
||||
MmDeletePageDirectoryEntry(PdeBase + MiGetPdeOffset(HYPERSPACE));
|
||||
|
||||
/* Delete the hyperspace mapping */
|
||||
MmDeleteHyperspaceMapping(PageDir);
|
||||
MiUnmapPageInHyperSpace(PsGetCurrentProcess(), PdeBase, OldIrql);
|
||||
|
||||
/* Free the PDE page itself (ARM3) */
|
||||
MmDeletePageDirectoryEntry(Process->Pcb.DirectoryTableBase[0]);
|
||||
MmDeletePageDirectoryEntry((PMMPDE)&Process->Pcb.DirectoryTableBase[0]);
|
||||
}
|
||||
|
||||
/* Taken from ARM3/pagfault.c */
|
||||
BOOLEAN
|
||||
FORCEINLINE
|
||||
MiSynchronizeSystemPde(PMMPDE PointerPde)
|
||||
{
|
||||
MMPDE SystemPde;
|
||||
ULONG Index;
|
||||
|
||||
/* Get the Index from the PDE */
|
||||
Index = ((ULONG_PTR)PointerPde & (SYSTEM_PD_SIZE - 1)) / sizeof(MMPTE);
|
||||
|
||||
/* Copy the PDE from the double-mapped system page directory */
|
||||
SystemPde = MmSystemPagePtes[Index];
|
||||
*PointerPde = SystemPde;
|
||||
|
||||
/* Make sure we re-read the PDE and PTE */
|
||||
KeMemoryBarrierWithoutFence();
|
||||
|
||||
/* Return, if we had success */
|
||||
return (BOOLEAN)SystemPde.u.Hard.Valid;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
MiResolveDemandZeroFault(IN PVOID Address,
|
||||
IN ULONG Protection,
|
||||
IN PEPROCESS Process,
|
||||
IN KIRQL OldIrql);
|
||||
VOID
|
||||
NTAPI
|
||||
MiFillSystemPageDirectory(IN PVOID Base,
|
||||
IN SIZE_T NumberOfBytes);
|
||||
|
||||
static PULONG
|
||||
MmGetPageTableForProcess(PEPROCESS Process, PVOID Address, BOOLEAN Create)
|
||||
{
|
||||
ULONG PdeOffset = ADDR_TO_PDE_OFFSET(Address);
|
||||
NTSTATUS Status;
|
||||
PFN_NUMBER Pfn;
|
||||
ULONG Entry;
|
||||
PULONG Pt, PageDir;
|
||||
PULONG Pt;
|
||||
PMMPDE PointerPde;
|
||||
|
||||
if (Address < MmSystemRangeStart)
|
||||
{
|
||||
|
@ -274,39 +301,28 @@ MmGetPageTableForProcess(PEPROCESS Process, PVOID Address, BOOLEAN Create)
|
|||
|
||||
if(Process != PsGetCurrentProcess())
|
||||
{
|
||||
PageDir = MmCreateHyperspaceMapping(PTE_TO_PFN(Process->Pcb.DirectoryTableBase[0]));
|
||||
if (PageDir == NULL)
|
||||
PMMPDE PdeBase;
|
||||
ULONG PdeOffset = MiGetPdeOffset(Address);
|
||||
|
||||
PdeBase = MmCreateHyperspaceMapping(PTE_TO_PFN(Process->Pcb.DirectoryTableBase[0]));
|
||||
if (PdeBase == NULL)
|
||||
{
|
||||
KeBugCheck(MEMORY_MANAGEMENT);
|
||||
}
|
||||
if (0 == InterlockedCompareExchangePte(&PageDir[PdeOffset], 0, 0))
|
||||
PointerPde = PdeBase + PdeOffset;
|
||||
if (PointerPde->u.Hard.Valid == 0)
|
||||
{
|
||||
if (Create == FALSE)
|
||||
{
|
||||
MmDeleteHyperspaceMapping(PageDir);
|
||||
return NULL;
|
||||
}
|
||||
MI_SET_USAGE(MI_USAGE_LEGACY_PAGE_DIRECTORY);
|
||||
|
||||
MI_SET_PROCESS2(Process->ImageFileName);
|
||||
|
||||
Status = MmRequestPageMemoryConsumer(MC_SYSTEM, FALSE, &Pfn);
|
||||
if (!NT_SUCCESS(Status) || Pfn == 0)
|
||||
{
|
||||
KeBugCheck(MEMORY_MANAGEMENT);
|
||||
}
|
||||
Entry = InterlockedCompareExchangePte(&PageDir[PdeOffset], PFN_TO_PTE(Pfn) | PA_PRESENT | PA_READWRITE | PA_USER, 0);
|
||||
if (Entry != 0)
|
||||
{
|
||||
MmReleasePageMemoryConsumer(MC_SYSTEM, Pfn);
|
||||
Pfn = PTE_TO_PFN(Entry);
|
||||
}
|
||||
/* Nobody but page fault should ask for creating the PDE,
|
||||
* Which imples that Process is the current one */
|
||||
ASSERT(Create == FALSE);
|
||||
MmDeleteHyperspaceMapping(PdeBase);
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
Pfn = PTE_TO_PFN(PageDir[PdeOffset]);
|
||||
Pfn = PointerPde->u.Hard.PageFrameNumber;
|
||||
}
|
||||
MmDeleteHyperspaceMapping(PageDir);
|
||||
MmDeleteHyperspaceMapping(PdeBase);
|
||||
Pt = MmCreateHyperspaceMapping(Pfn);
|
||||
if (Pt == NULL)
|
||||
{
|
||||
|
@ -315,59 +331,38 @@ MmGetPageTableForProcess(PEPROCESS Process, PVOID Address, BOOLEAN Create)
|
|||
return Pt + MiAddressToPteOffset(Address);
|
||||
}
|
||||
/* This is for our process */
|
||||
PageDir = (PULONG)MiAddressToPde(Address);
|
||||
if (0 == InterlockedCompareExchangePte(PageDir, 0, 0))
|
||||
PointerPde = MiAddressToPde(Address);
|
||||
Pt = (PULONG)MiAddressToPte(Address);
|
||||
if (PointerPde->u.Hard.Valid == 0)
|
||||
{
|
||||
if (Create == FALSE)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
MI_SET_USAGE(MI_USAGE_LEGACY_PAGE_DIRECTORY);
|
||||
MI_SET_PROCESS2(Process->ImageFileName);
|
||||
|
||||
Status = MmRequestPageMemoryConsumer(MC_SYSTEM, FALSE, &Pfn);
|
||||
if (!NT_SUCCESS(Status) || Pfn == 0)
|
||||
{
|
||||
KeBugCheck(MEMORY_MANAGEMENT);
|
||||
}
|
||||
Entry = InterlockedCompareExchangePte(PageDir, PFN_TO_PTE(Pfn) | PA_PRESENT | PA_READWRITE | PA_USER, 0);
|
||||
if (Entry != 0)
|
||||
{
|
||||
MmReleasePageMemoryConsumer(MC_SYSTEM, Pfn);
|
||||
}
|
||||
MiResolveDemandZeroFault(Pt,
|
||||
MM_READWRITE,
|
||||
Process,
|
||||
MM_NOIRQL);
|
||||
ASSERT(PointerPde->u.Hard.Valid == 1);
|
||||
}
|
||||
return (PULONG)MiAddressToPte(Address);
|
||||
}
|
||||
|
||||
/* This is for kernel land address */
|
||||
PageDir = (PULONG)MiAddressToPde(Address);
|
||||
if (0 == InterlockedCompareExchangePte(PageDir, 0, 0))
|
||||
PointerPde = MiAddressToPde(Address);
|
||||
Pt = (PULONG)MiAddressToPte(Address);
|
||||
if (PointerPde->u.Hard.Valid == 0)
|
||||
{
|
||||
if (0 == InterlockedCompareExchangePte(&MmGlobalKernelPageDirectory[PdeOffset], 0, 0))
|
||||
/* Let ARM3 synchronize the PDE */
|
||||
if(!MiSynchronizeSystemPde(PointerPde))
|
||||
{
|
||||
if (Create == FALSE)
|
||||
{
|
||||
/* PDE (still) not valid, let ARM3 allocate one if asked */
|
||||
if(Create == FALSE)
|
||||
return NULL;
|
||||
}
|
||||
MI_SET_USAGE(MI_USAGE_LEGACY_PAGE_DIRECTORY);
|
||||
if (Process) MI_SET_PROCESS2(Process->ImageFileName);
|
||||
if (!Process) MI_SET_PROCESS2("Kernel Legacy");
|
||||
Status = MmRequestPageMemoryConsumer(MC_SYSTEM, FALSE, &Pfn);
|
||||
if (!NT_SUCCESS(Status) || Pfn == 0)
|
||||
{
|
||||
KeBugCheck(MEMORY_MANAGEMENT);
|
||||
}
|
||||
Entry = PFN_TO_PTE(Pfn) | PA_PRESENT | PA_READWRITE;
|
||||
if(0 != InterlockedCompareExchangePte(&MmGlobalKernelPageDirectory[PdeOffset], Entry, 0))
|
||||
{
|
||||
MmReleasePageMemoryConsumer(MC_SYSTEM, Pfn);
|
||||
}
|
||||
InterlockedExchangePte(PageDir, MmGlobalKernelPageDirectory[PdeOffset]);
|
||||
return (PULONG)MiAddressToPte(Address);
|
||||
MiFillSystemPageDirectory(Address, PAGE_SIZE);
|
||||
}
|
||||
InterlockedExchangePte(PageDir, MmGlobalKernelPageDirectory[PdeOffset]);
|
||||
}
|
||||
return (PULONG)MiAddressToPte(Address);
|
||||
return Pt;
|
||||
}
|
||||
|
||||
BOOLEAN MmUnmapPageTable(PULONG Pt)
|
||||
|
@ -599,19 +594,18 @@ MmDeletePageFileMapping(PEPROCESS Process, PVOID Address,
|
|||
}
|
||||
|
||||
BOOLEAN
|
||||
Mmi386MakeKernelPageTableGlobal(PVOID PAddress)
|
||||
Mmi386MakeKernelPageTableGlobal(PVOID Address)
|
||||
{
|
||||
PULONG Pt, Pde;
|
||||
Pde = (PULONG)MiAddressToPde(PAddress);
|
||||
if (*Pde == 0)
|
||||
PMMPDE PointerPde = MiAddressToPde(Address);
|
||||
PMMPTE PointerPte = MiAddressToPte(Address);
|
||||
|
||||
if (PointerPde->u.Hard.Valid == 0)
|
||||
{
|
||||
Pt = MmGetPageTableForProcess(NULL, PAddress, FALSE);
|
||||
if (Pt != NULL)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
if(!MiSynchronizeSystemPde(PointerPde))
|
||||
return FALSE;
|
||||
return PointerPte->u.Hard.Valid;
|
||||
}
|
||||
return(FALSE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
|
@ -1033,20 +1027,7 @@ INIT_FUNCTION
|
|||
NTAPI
|
||||
MmInitGlobalKernelPageDirectory(VOID)
|
||||
{
|
||||
ULONG i;
|
||||
PULONG CurrentPageDirectory = (PULONG)PAGEDIRECTORY_MAP;
|
||||
|
||||
DPRINT("MmInitGlobalKernelPageDirectory()\n");
|
||||
|
||||
for (i = ADDR_TO_PDE_OFFSET(MmSystemRangeStart); i < 1024; i++)
|
||||
{
|
||||
if (i != ADDR_TO_PDE_OFFSET(PAGETABLE_MAP) &&
|
||||
i != ADDR_TO_PDE_OFFSET(HYPERSPACE) &&
|
||||
0 == MmGlobalKernelPageDirectory[i] && 0 != CurrentPageDirectory[i])
|
||||
{
|
||||
MmGlobalKernelPageDirectory[i] = CurrentPageDirectory[i];
|
||||
}
|
||||
}
|
||||
/* Nothing to do here */
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
|
Loading…
Reference in a new issue