[ros-diffs] [sir_richard] 49525: [NTOS]: Assign a working set to the system process and correctly initialize its address space. [NTOS]: Assign the working set list address, system-wide, but per-process (in hyp...

sir_richard at svn.reactos.org sir_richard at svn.reactos.org
Mon Nov 8 12:35:51 UTC 2010


Author: sir_richard
Date: Mon Nov  8 12:35:50 2010
New Revision: 49525

URL: http://svn.reactos.org/svn/reactos?rev=49525&view=rev
Log:
[NTOS]: Assign a working set to the system process and correctly initialize its address space.
[NTOS]: Assign the working set list address, system-wide, but per-process (in hyperspace).
[NTOS]: Give every process its working set page, and store it. Build a bogus working set list (MMWSL).
[NTOS]: Use the process working set list (MMWSL) to track page table references during faults, just as Windows does.
[NTOS]: Correctly initialize the colored page list heads and assert their validity.

Modified:
    trunk/reactos/ntoskrnl/include/internal/i386/mm.h
    trunk/reactos/ntoskrnl/mm/ARM3/i386/init.c
    trunk/reactos/ntoskrnl/mm/ARM3/miarm.h
    trunk/reactos/ntoskrnl/mm/ARM3/pagfault.c
    trunk/reactos/ntoskrnl/mm/ARM3/procsup.c

Modified: trunk/reactos/ntoskrnl/include/internal/i386/mm.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/i386/mm.h?rev=49525&r1=49524&r2=49525&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/include/internal/i386/mm.h [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/include/internal/i386/mm.h [iso-8859-1] Mon Nov  8 12:35:50 2010
@@ -84,7 +84,11 @@
 #define MI_MAPPING_RANGE_START              (ULONG)HYPER_SPACE
 #define MI_MAPPING_RANGE_END                (MI_MAPPING_RANGE_START + \
                                              MI_HYPERSPACE_PTES * PAGE_SIZE)
-#define MI_ZERO_PTE                         (PMMPTE)(MI_MAPPING_RANGE_END + \
+#define MI_DUMMY_PTE                        (PMMPTE)(MI_MAPPING_RANGE_END + \
+                                             PAGE_SIZE)
+#define MI_VAD_BITMAP                       (PMMPTE)(MI_DUMMY_PTE + \
+                                             PAGE_SIZE)
+#define MI_WORKING_SET_LIST                 (PMMPTE)(MI_VAD_BITMAP + \
                                              PAGE_SIZE)
 
 /* On x86, these two are the same */

Modified: trunk/reactos/ntoskrnl/mm/ARM3/i386/init.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/i386/init.c?rev=49525&r1=49524&r2=49525&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/mm/ARM3/i386/init.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/ARM3/i386/init.c [iso-8859-1] Mon Nov  8 12:35:50 2010
@@ -160,7 +160,9 @@
     MMPTE TempPde, TempPte;
     PVOID NonPagedPoolExpansionVa;
     KIRQL OldIrql;
-
+    PMMPFN Pfn1;
+    ULONG Flags;
+    
     /* Check for kernel stack size that's too big */
     if (MmLargeStackSize > (KERNEL_LARGE_STACK_SIZE / _1KB))
     {
@@ -558,6 +560,9 @@
     MmFirstReservedMappingPte = MiAddressToPte(MI_MAPPING_RANGE_START);
     MmLastReservedMappingPte = MiAddressToPte(MI_MAPPING_RANGE_END);
     MmFirstReservedMappingPte->u.Hard.PageFrameNumber = MI_HYPERSPACE_PTES;
+    
+    /* Set the working set address */
+    MmWorkingSetList = (PVOID)MI_WORKING_SET_LIST;
 
     //
     // Reserve system PTEs for zeroing PTEs and clear them
@@ -571,6 +576,28 @@
     //
     MiFirstReservedZeroingPte->u.Hard.PageFrameNumber = MI_ZERO_PTES - 1;
     
+    /* Lock PFN database */
+    OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
+    
+    /* Reset the ref/share count so that MmInitializeProcessAddressSpace works */
+    Pfn1 = MiGetPfnEntry(PFN_FROM_PTE(MiAddressToPde(PDE_BASE)));
+    Pfn1->u2.ShareCount = 0;
+    Pfn1->u3.e2.ReferenceCount = 0;
+    
+    /* Get a page for the working set list */
+    MI_SET_USAGE(MI_USAGE_PAGE_TABLE);
+    MI_SET_PROCESS2("Kernel WS List");
+    PageFrameIndex = MiRemoveAnyPage(0);
+    TempPte.u.Hard.PageFrameNumber = PageFrameIndex;
+    
+    /* Map the working set list */
+    PointerPte = MiAddressToPte(MmWorkingSetList);
+    MI_WRITE_VALID_PTE(PointerPte, TempPte);
+        
+    /* Zero it out, and save the frame index */
+    RtlZeroMemory(MiPteToAddress(PointerPte), PAGE_SIZE);
+    PsGetCurrentProcess()->WorkingSetPage = PageFrameIndex;
+        
     /* Check for Pentium LOCK errata */
     if (KiI386PentiumLockErrataPresent)
     {
@@ -581,6 +608,43 @@
         PointerPte->u.Hard.WriteThrough = 1;
     }
 
+    /* Release the lock */
+    KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
+
+    /* Initialize the bogus address space */
+    Flags = 0;
+    MmInitializeProcessAddressSpace(PsGetCurrentProcess(), NULL, NULL, &Flags, NULL);
+    
+    /* Make sure the color lists are valid */
+    ASSERT(MmFreePagesByColor[0] < (PMMCOLOR_TABLES)PTE_BASE);
+    StartPde = MiAddressToPde(MmFreePagesByColor[0]);
+    ASSERT(StartPde->u.Hard.Valid == 1);
+    PointerPte = MiAddressToPte(MmFreePagesByColor[0]);
+    ASSERT(PointerPte->u.Hard.Valid == 1);
+    LastPte = MiAddressToPte((ULONG_PTR)&MmFreePagesByColor[1][MmSecondaryColors] - 1);
+    ASSERT(LastPte->u.Hard.Valid == 1);
+
+    /* Loop the color list PTEs */
+    while (PointerPte <= LastPte)
+    {
+        /* Get the PFN entry */
+        Pfn1 = MiGetPfnEntry(PFN_FROM_PTE(PointerPte));
+        if (!Pfn1->u3.e2.ReferenceCount)
+        {
+            /* Fill it out */
+            Pfn1->u4.PteFrame = PFN_FROM_PTE(StartPde);
+            Pfn1->PteAddress = PointerPte;
+            Pfn1->u2.ShareCount++;
+            Pfn1->u3.e2.ReferenceCount = 1;
+            Pfn1->u3.e1.PageLocation = ActiveAndValid;
+            Pfn1->u3.e1.CacheAttribute = MiCached;
+        }
+        
+        /* Keep going */
+        PointerPte++;
+    }
+    
+    /* All done */
     return STATUS_SUCCESS;
 }
 

Modified: trunk/reactos/ntoskrnl/mm/ARM3/miarm.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/miarm.h?rev=49525&r1=49524&r2=49525&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/mm/ARM3/miarm.h [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/ARM3/miarm.h [iso-8859-1] Mon Nov  8 12:35:50 2010
@@ -513,6 +513,7 @@
 extern KEVENT MmZeroingPageEvent;
 extern ULONG MmSystemPageColor;
 extern ULONG MmProcessColorSeed;
+extern PMMWSL MmWorkingSetList;
 
 //
 // Figures out the hardware bits for a PTE

Modified: trunk/reactos/ntoskrnl/mm/ARM3/pagfault.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/pagfault.c?rev=49525&r1=49524&r2=49525&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/mm/ARM3/pagfault.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/ARM3/pagfault.c [iso-8859-1] Mon Nov  8 12:35:50 2010
@@ -991,6 +991,14 @@
         MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
         return Status;
     }
+
+    /* Is this a user address? */
+    if (Address <= MM_HIGHEST_USER_ADDRESS)
+    {
+        /* Add an additional page table reference */
+        MmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)]++;
+        ASSERT(MmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)] <= PTE_COUNT);
+    }
     
     /* Did we get a prototype PTE back? */
     if (!ProtoPte)

Modified: trunk/reactos/ntoskrnl/mm/ARM3/procsup.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/procsup.c?rev=49525&r1=49524&r2=49525&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/mm/ARM3/procsup.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/ARM3/procsup.c [iso-8859-1] Mon Nov  8 12:35:50 2010
@@ -19,6 +19,7 @@
 /* GLOBALS ********************************************************************/
 
 ULONG MmProcessColorSeed = 0x12345678;
+PMMWSL MmWorkingSetList;
 
 /* PRIVATE FUNCTIONS **********************************************************/
 
@@ -892,6 +893,32 @@
     return Status;
 }
 
+VOID
+NTAPI
+MiInitializeWorkingSetList(IN PEPROCESS CurrentProcess)
+{
+    PMMPFN Pfn1;
+
+    /* Setup some bogus list data */
+    MmWorkingSetList->LastEntry = CurrentProcess->Vm.MinimumWorkingSetSize;
+    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->FirstFree = 1;
+    MmWorkingSetList->FirstDynamic = 2;
+    MmWorkingSetList->NextSlot = 3;
+    MmWorkingSetList->LastInitializedWsle = 4;
+    
+    /* The rule is that the owner process is always in the FLINK of the PDE's PFN entry */
+    Pfn1 = MiGetPfnEntry(MiAddressToPte(PDE_BASE)->u.Hard.PageFrameNumber);
+    ASSERT(Pfn1->u4.PteFrame == MiGetPfnEntryIndex(Pfn1));
+    Pfn1->u1.Event = (PKEVENT)CurrentProcess;
+}
+
 NTSTATUS
 NTAPI
 MmInitializeProcessAddressSpace(IN PEPROCESS Process,
@@ -912,6 +939,7 @@
     PWCHAR Source;
     PCHAR Destination;
     USHORT Length = 0;
+    MMPTE TempPte;
     
     /* We should have a PDE */
     ASSERT(Process->Pcb.DirectoryTableBase[0] != 0);
@@ -944,6 +972,22 @@
     PointerPde = MiAddressToPde(HYPER_SPACE);
     PageFrameNumber = PFN_FROM_PTE(PointerPde);
     MiInitializePfn(PageFrameNumber, PointerPde, TRUE);
+    
+    /* Setup the PFN for the PTE for the working set */
+    PointerPte = MiAddressToPte(MI_WORKING_SET_LIST);
+    MI_MAKE_HARDWARE_PTE(&TempPte, PointerPte, MM_READWRITE, 0);
+    ASSERT(PointerPte->u.Long != 0);
+    PageFrameNumber = PFN_FROM_PTE(PointerPte);
+    MI_WRITE_INVALID_PTE(PointerPte, DemandZeroPte);
+    MiInitializePfn(PageFrameNumber, PointerPte, TRUE);
+    TempPte.u.Hard.PageFrameNumber = PageFrameNumber;
+    MI_WRITE_VALID_PTE(PointerPte, TempPte);
+
+    /* Now initialize the working set list */
+    MiInitializeWorkingSetList(Process);
+
+    /* Sanity check */
+    ASSERT(Process->PhysicalVadRoot == NULL);
 
     /* Release PFN lock */
     KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
@@ -1062,12 +1106,13 @@
                             OUT PULONG_PTR DirectoryTableBase)
 {
     KIRQL OldIrql;
-    PFN_NUMBER PdeIndex, HyperIndex;
+    PFN_NUMBER PdeIndex, HyperIndex, WsListIndex;
     PMMPTE PointerPte;
     MMPTE TempPte, PdePte;
     ULONG PdeOffset;
-    PMMPTE SystemTable;
+    PMMPTE SystemTable, HyperTable;
     ULONG Color;
+    PMMPFN Pfn1;
 
     /* Choose a process color */
     Process->NextPageColor = RtlRandom(&MmProcessColorSeed);
@@ -1105,6 +1150,21 @@
         /* Zero it outside the PFN lock */
         KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
         MiZeroPhysicalPage(HyperIndex);
+        OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
+    }
+
+    /* Get a zero page for the woring set list, if possible */
+    MI_SET_USAGE(MI_USAGE_PAGE_TABLE);
+    Color = MI_GET_NEXT_PROCESS_COLOR(Process);
+    WsListIndex = MiRemoveZeroPageSafe(Color);
+    if (!WsListIndex)
+    {
+        /* No zero pages, grab a free one */
+        WsListIndex = MiRemoveAnyPage(Color);
+        
+        /* Zero it outside the PFN lock */
+        KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
+        MiZeroPhysicalPage(WsListIndex);
     }
     else
     {
@@ -1117,11 +1177,42 @@
     Process->AddressSpaceInitialized = 1;
 
     /* Set the base directory pointers */
+    Process->WorkingSetPage = WsListIndex;
     DirectoryTableBase[0] = PdeIndex << PAGE_SHIFT;
     DirectoryTableBase[1] = HyperIndex << PAGE_SHIFT;
 
     /* Make sure we don't already have a page directory setup */
     ASSERT(Process->Pcb.DirectoryTableBase[0] == 0);
+    
+    /* Get a PTE to map hyperspace */
+    PointerPte = MiReserveSystemPtes(1, SystemPteSpace);
+    ASSERT(PointerPte != NULL);
+
+    /* Build it */
+    MI_MAKE_HARDWARE_PTE_KERNEL(&PdePte,
+                                PointerPte,
+                                MM_READWRITE,
+                                HyperIndex);
+
+    /* Set it dirty and map it */
+    PdePte.u.Hard.Dirty = TRUE;
+    MI_WRITE_VALID_PTE(PointerPte, PdePte);
+
+    /* Now get hyperspace's page table */
+    HyperTable = MiPteToAddress(PointerPte);
+
+    /* Now write the PTE/PDE entry for the working set list index itself */
+    TempPte = ValidKernelPte;
+    TempPte.u.Hard.PageFrameNumber = WsListIndex;
+    PdeOffset = MiAddressToPteOffset(MmWorkingSetList);
+    HyperTable[PdeOffset] = TempPte;
+
+    /* Let go of the system PTE */
+    MiReleaseSystemPtes(PointerPte, 1, SystemPteSpace);
+
+    /* Save the PTE address of the page directory itself */
+    Pfn1 = MiGetPfnEntry(PdeIndex);
+    Pfn1->PteAddress = (PMMPTE)PDE_BASE;
 
     /* Insert us into the Mm process list */
     InsertTailList(&MmProcessList, &Process->MmProcessLinks);




More information about the Ros-diffs mailing list