Author: jgardou
Date: Wed Sep 24 21:55:37 2014
New Revision: 64262
URL:
http://svn.reactos.org/svn/reactos?rev=64262&view=rev
Log:
[NTOS/MM]
- First try at creating and adding pages to the working set of processes in ARM3. Limited
to 1k pages for now.
CORE-8553
Modified:
branches/TransitionPte/ntoskrnl/mm/ARM3/miarm.h
branches/TransitionPte/ntoskrnl/mm/ARM3/pagfault.c
branches/TransitionPte/ntoskrnl/mm/ARM3/procsup.c
branches/TransitionPte/ntoskrnl/mm/ARM3/virtual.c
Modified: branches/TransitionPte/ntoskrnl/mm/ARM3/miarm.h
URL:
http://svn.reactos.org/svn/reactos/branches/TransitionPte/ntoskrnl/mm/ARM3/…
==============================================================================
--- branches/TransitionPte/ntoskrnl/mm/ARM3/miarm.h [iso-8859-1] (original)
+++ branches/TransitionPte/ntoskrnl/mm/ARM3/miarm.h [iso-8859-1] Wed Sep 24 21:55:37 2014
@@ -2321,6 +2321,19 @@
IN KIRQL OldIrql
);
+VOID
+NTAPI
+MiDeleteFromWorkingSetList(
+ _Inout_ PMMSUPPORT Vm,
+ _In_ PVOID Address);
+
+VOID
+NTAPI
+MiInsertInWorkingSetList(
+ _Inout_ PMMSUPPORT Vm,
+ _In_ PVOID Address,
+ _In_ ULONG Protection);
+
//
// MiRemoveZeroPage will use inline code to zero out the page manually if only
// free pages are available. In some scenarios, we don't/can't run that piece of
Modified: branches/TransitionPte/ntoskrnl/mm/ARM3/pagfault.c
URL:
http://svn.reactos.org/svn/reactos/branches/TransitionPte/ntoskrnl/mm/ARM3/…
==============================================================================
--- branches/TransitionPte/ntoskrnl/mm/ARM3/pagfault.c [iso-8859-1] (original)
+++ branches/TransitionPte/ntoskrnl/mm/ARM3/pagfault.c [iso-8859-1] Wed Sep 24 21:55:37
2014
@@ -2247,6 +2247,9 @@
MiCopyPfn(PageFrameIndex, OldPageFrameIndex);
+ /* Delete the WS entry, we will soon replace it */
+ MiDeleteFromWorkingSetList(&CurrentProcess->Vm, Address);
+
/* Dereference whatever this PTE is referencing */
Pfn1 = MI_PFN_ELEMENT(OldPageFrameIndex);
ASSERT(Pfn1->u3.e1.PrototypePte == 1);
@@ -2262,6 +2265,9 @@
MI_WRITE_VALID_PTE(PointerPte, TempPte);
+ /* Insert into the WS again */
+ MiInsertInWorkingSetList(&CurrentProcess->Vm, Address,
ProtectionCode);
+
KeReleaseQueuedSpinLock(LockQueuePfnLock, LockIrql);
/* Return the status */
@@ -2293,6 +2299,9 @@
PointerPte,
CurrentProcess,
MM_NOIRQL);
+
+ /* Insert into the WS */
+ MiInsertInWorkingSetList(&CurrentProcess->Vm, Address, ProtectionCode);
/* Return the status */
MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
@@ -2528,6 +2537,12 @@
TrapInformation,
Vad);
+ /* Add it to the WS */
+ if (NT_SUCCESS(Status))
+ {
+ MiInsertInWorkingSetList(&CurrentProcess->Vm, Address, ProtectionCode);
+ }
+
/* Return the status */
ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
Modified: branches/TransitionPte/ntoskrnl/mm/ARM3/procsup.c
URL:
http://svn.reactos.org/svn/reactos/branches/TransitionPte/ntoskrnl/mm/ARM3/…
==============================================================================
--- branches/TransitionPte/ntoskrnl/mm/ARM3/procsup.c [iso-8859-1] (original)
+++ branches/TransitionPte/ntoskrnl/mm/ARM3/procsup.c [iso-8859-1] Wed Sep 24 21:55:37
2014
@@ -896,25 +896,155 @@
VOID
NTAPI
+MiDeleteFromWorkingSetList(
+ _Inout_ PMMSUPPORT Vm,
+ _In_ PVOID Address)
+{
+ ULONG i;
+ PMMWSLE Wsle = NULL;
+
+ /* Only the virtual page number is interesting */
+ Address = PAGE_ALIGN(Address);
+
+ /* Check we got the right lock */
+ NT_ASSERT((PsGetCurrentThread()->OwnsSessionWorkingSetExclusive) ||
!MI_IS_SESSION_ADDRESS(Address));
+ NT_ASSERT((PsGetCurrentThread()->OwnsSystemWorkingSetExclusive) || (Address <
MmSystemRangeStart) ||
+ MI_IS_SESSION_ADDRESS(Address));
+ NT_ASSERT((PsGetCurrentThread()->OwnsProcessWorkingSetExclusive) || (Address >
MmSystemRangeStart));
+
+ /* Loop over the entries */
+ for (i = 0; i < Vm->VmWorkingSetList->LastInitializedWsle; i++)
+ {
+ if (!Vm->VmWorkingSetList->Wsle[i].u1.e1.Valid)
+ continue;
+
+ if (PAGE_ALIGN(Vm->VmWorkingSetList->Wsle[i].u1.VirtualAddress) ==
Address)
+ {
+ Wsle = &Vm->VmWorkingSetList->Wsle[i];
+ break;
+ }
+ }
+
+ if (Wsle == NULL)
+ {
+ /* Most likely because we don't expand the thing */
+ DPRINT1("Address %p not found in Vm %p.\n", Address, Vm);
+ return;
+ }
+
+ /* Simply relink it and voilà */
+ Wsle->u1.Long = Vm->VmWorkingSetList->FirstFree << 1;
+ Vm->VmWorkingSetList->FirstFree = i;
+ Vm->WorkingSetSize--;
+}
+
+VOID
+NTAPI
+MiInsertInWorkingSetList(
+ _Inout_ PMMSUPPORT Vm,
+ _In_ PVOID Address,
+ _In_ ULONG Protection)
+{
+ PMMWSLE Wsle = Vm->VmWorkingSetList->Wsle;
+ PMMPFN Pfn1;
+ PMMPTE PointerPte;
+
+ /* Only the virtual page number is interesting */
+ Address = PAGE_ALIGN(Address);
+
+ /* Check we got the right lock */
+ NT_ASSERT((PsGetCurrentThread()->OwnsSessionWorkingSetExclusive) ||
!MI_IS_SESSION_ADDRESS(Address));
+ NT_ASSERT((PsGetCurrentThread()->OwnsSystemWorkingSetExclusive) || (Address <
MmSystemRangeStart) ||
+ MI_IS_SESSION_ADDRESS(Address));
+ NT_ASSERT((PsGetCurrentThread()->OwnsProcessWorkingSetExclusive) || (Address >
MmSystemRangeStart));
+
+ /* Get the entry where we will insert it */
+ if (Vm->VmWorkingSetList->FirstFree ==
Vm->VmWorkingSetList->LastInitializedWsle)
+ {
+ ULONG i;
+
+ if (Vm->VmWorkingSetList->FirstFree ==
Vm->VmWorkingSetList->LastEntry)
+ {
+ DPRINT1("FIXME: Could not add address %p to Vm %p because it is
FULL!\n", Address, Vm);
+ return;
+ }
+
+ /* Double that */
+ Vm->VmWorkingSetList->LastInitializedWsle *= 2;
+ if (Vm->VmWorkingSetList->LastInitializedWsle >
Vm->VmWorkingSetList->LastEntry)
+ Vm->VmWorkingSetList->LastInitializedWsle =
Vm->VmWorkingSetList->LastEntry;
+
+ /* Initialize them */
+ for (i = Vm->VmWorkingSetList->FirstFree; i <
Vm->VmWorkingSetList->LastInitializedWsle; i++)
+ Wsle[i].u1.Long = (i + 1) << 1;
+ }
+
+ /* Get the entry where we will insert it */
+ Wsle = &Vm->VmWorkingSetList->Wsle[Vm->VmWorkingSetList->FirstFree];
+
+ /* See if the PFN deserves to have an entry into the WS */
+ PointerPte = MiAddressToPte(Address);
+ NT_ASSERT(PointerPte->u.Hard.Valid);
+ Pfn1 = MiGetPfnEntry(PFN_FROM_PTE(PointerPte));
+ if ((Address >= MmSystemRangeStart) || (Pfn1->u3.e1.PrototypePte == 0))
+ {
+ Pfn1->u1.WsIndex = Vm->VmWorkingSetList->FirstFree;
+ }
+
+ /* Update the list head */
+ Vm->VmWorkingSetList->FirstFree = Wsle->u1.Long >> 1;
+
+ /* Set the entry address */
+ Wsle->u1.VirtualAddress = Address;
+
+ Wsle->u1.e1.Valid = 1;
+ Wsle->u1.e1.Protection = Protection;
+
+ /* Bump it */
+ Vm->WorkingSetSize++;
+}
+
+VOID
+NTAPI
MiInitializeWorkingSetList(IN PEPROCESS CurrentProcess)
{
PMMPFN Pfn1;
PMMPTE sysPte;
MMPTE tempPte;
-
- /* Setup some bogus list data */
- MmWorkingSetList->LastEntry = CurrentProcess->Vm.MinimumWorkingSetSize;
+ ULONG i;
+ PFN_NUMBER WslePageIndex;
+
+ /* Initialize the WS sizes */
+ // FIXME: hardcoded for now
+ CurrentProcess->Vm.MinimumWorkingSetSize = 50;
+ CurrentProcess->Vm.MaximumWorkingSetSize = 345;
+
+ /* Setup list data */
+ MmWorkingSetList->LastEntry = PAGE_SIZE / sizeof(MMWSLE);
MmWorkingSetList->HashTable = NULL;
MmWorkingSetList->HashTableSize = 0;
MmWorkingSetList->NumberOfImageWaiters = 0;
- MmWorkingSetList->Wsle = (PVOID)0xDEADBABE;
MmWorkingSetList->VadBitMapHint = 1;
- MmWorkingSetList->HashTableStart = (PVOID)0xBADAB00B;
- MmWorkingSetList->HighestPermittedHashAddress = (PVOID)0xCAFEBABE;
+ MmWorkingSetList->HashTableStart = NULL;
+ MmWorkingSetList->HighestPermittedHashAddress = NULL;
MmWorkingSetList->FirstFree = 1;
- MmWorkingSetList->FirstDynamic = 2;
- MmWorkingSetList->NextSlot = 3;
- MmWorkingSetList->LastInitializedWsle = 4;
+ MmWorkingSetList->FirstDynamic = 0;
+ MmWorkingSetList->NextSlot = 0;
+ MmWorkingSetList->LastInitializedWsle =
CurrentProcess->Vm.MaximumWorkingSetSize;
+
+ /* Reserve a page for the entries */
+ WslePageIndex = MiRemoveAnyPage(MI_GET_NEXT_COLOR());
+ sysPte = MiReserveSystemPtes(1, SystemPteSpace);
+ MI_MAKE_HARDWARE_PTE_KERNEL(&tempPte, sysPte, MM_READWRITE, WslePageIndex);
+ MiInitializePfnAndMakePteValid(WslePageIndex, sysPte, tempPte);
+ MmWorkingSetList->Wsle = MiPteToAddress(sysPte);
+
+ /* Initialize the linked-list of free entries */
+ for (i = 0; i < MmWorkingSetList->LastInitializedWsle; i++)
+ {
+ /* Save LSB to keep track of active/non active state */
+ MmWorkingSetList->Wsle[i].u1.Long = (i + 1) << 1;
+ }
/* The rule is that the owner process is always in the FLINK of the PDE's PFN
entry */
Pfn1 = MiGetPfnEntry(CurrentProcess->Pcb.DirectoryTableBase[0] >>
PAGE_SHIFT);
@@ -926,6 +1056,20 @@
MI_MAKE_HARDWARE_PTE_KERNEL(&tempPte, sysPte, MM_READWRITE,
CurrentProcess->WorkingSetPage);
MI_WRITE_VALID_PTE(sysPte, tempPte);
CurrentProcess->Vm.VmWorkingSetList = MiPteToAddress(sysPte);
+}
+
+VOID
+NTAPI
+MiDeleteWorkingSetList(PMMWSL WorkingSetList)
+{
+ PMMPTE SysPte;
+ PMMPFN Pfn1;
+
+ SysPte = MiAddressToPte(WorkingSetList->Wsle);
+ Pfn1 = MiGetPfnEntry(PFN_FROM_PTE(SysPte));
+ MI_SET_PFN_DELETED(Pfn1);
+ MiDecrementShareCount(Pfn1, PFN_FROM_PTE(SysPte));
+ MiReleaseSystemPtes(SysPte, 1, SystemPteSpace);
}
NTSTATUS
@@ -1387,6 +1531,9 @@
/* Check for fully initialized process */
if (Process->AddressSpaceInitialized == 2)
{
+ /* Free the working set list entries */
+ MiDeleteWorkingSetList(Process->Vm.VmWorkingSetList);
+
/* Map the working set page and its page table */
Pfn1 = MiGetPfnEntry(Process->WorkingSetPage);
Pfn2 = MiGetPfnEntry(Pfn1->u4.PteFrame);
Modified: branches/TransitionPte/ntoskrnl/mm/ARM3/virtual.c
URL:
http://svn.reactos.org/svn/reactos/branches/TransitionPte/ntoskrnl/mm/ARM3/…
==============================================================================
--- branches/TransitionPte/ntoskrnl/mm/ARM3/virtual.c [iso-8859-1] (original)
+++ branches/TransitionPte/ntoskrnl/mm/ARM3/virtual.c [iso-8859-1] Wed Sep 24 21:55:37
2014
@@ -721,6 +721,11 @@
}
else
{
+ if (TempPte.u.Hard.Valid == 1)
+ {
+ MiDeleteFromWorkingSetList(&CurrentProcess->Vm,
MiPteToAddress(PointerPte));
+ }
+
/* Delete the PTE proper */
MiDeletePte(PointerPte,
(PVOID)Va,
@@ -2360,9 +2365,12 @@
PteContents.u.Hard.Valid = 0;
PteContents.u.Soft.Transition = 1;
PteContents.u.Trans.Protection = ProtectionMask;
+
+ /* Remove it from the WS */
+ MiDeleteFromWorkingSetList(&Process->Vm,
MiPteToAddress(PointerPte));
+
/* Decrease PFN share count and write the PTE */
MiDecrementShareCount(Pfn1, PFN_FROM_PTE(&PteContents));
- // FIXME: remove the page from the WS
MI_WRITE_INVALID_PTE(PointerPte, PteContents);
#ifdef CONFIG_SMP
// FIXME: Should invalidate entry in every CPU TLB