[NTOS]: Use system PTEs for drivers, both boot drivers and system-loaded drivers...
authorSir Richard <sir_richard@svn.reactos.org>
Sun, 21 Feb 2010 02:13:20 +0000 (02:13 +0000)
committerSir Richard <sir_richard@svn.reactos.org>
Sun, 21 Feb 2010 02:13:20 +0000 (02:13 +0000)
[NTOS]: Do not "copy" boot drivers from one set of pages to another set of pages. Instead, use system PTEs to map the boot drivers to a new VA, and set the PFNs to the original PFNs that the loader had obtained (and don't free that memory). This avoids some overhead.
[NTOS]: Now the only user of MmMapMemoryArea is the caching code, which I won't touch.

svn path=/trunk/; revision=45641

reactos/ntoskrnl/mm/section.c
reactos/ntoskrnl/mm/sysldr.c

index 321a694..582af62 100644 (file)
@@ -4420,63 +4420,6 @@ NtExtendSection(IN HANDLE SectionHandle,
    return STATUS_NOT_IMPLEMENTED;
 }
 
-
-/**********************************************************************
- * NAME       INTERNAL
- *  MmAllocateSection@4
- *
- * DESCRIPTION
- *
- * ARGUMENTS
- *  Length
- *
- * RETURN VALUE
- *
- * NOTE
- *  Code taken from ntoskrnl/mm/special.c.
- *
- * REVISIONS
- */
-PVOID NTAPI
-MmAllocateSection (IN ULONG Length, PVOID BaseAddress)
-{
-   PVOID Result;
-   MEMORY_AREA* marea;
-   NTSTATUS Status;
-   PMMSUPPORT AddressSpace;
-   PHYSICAL_ADDRESS BoundaryAddressMultiple;
-
-   DPRINT("MmAllocateSection(Length %x)\n",Length);
-
-   BoundaryAddressMultiple.QuadPart = 0;
-
-   AddressSpace = MmGetKernelAddressSpace();
-   Result = BaseAddress;
-   MmLockAddressSpace(AddressSpace);
-   Status = MmCreateMemoryArea (AddressSpace,
-                                MEMORY_AREA_SYSTEM,
-                                &Result,
-                                Length,
-                                0,
-                                &marea,
-                                FALSE,
-                                0,
-                                BoundaryAddressMultiple);
-   MmUnlockAddressSpace(AddressSpace);
-
-   if (!NT_SUCCESS(Status))
-   {
-      return (NULL);
-   }
-   DPRINT("Result %p\n",Result);
-
-   /* Create a virtual mapping for this memory area */
-   MmMapMemoryArea(Result, Length, MC_NPPOOL, PAGE_READWRITE);
-
-   return ((PVOID)Result);
-}
-
-
 /**********************************************************************
  * NAME       EXPORTED
  * MmMapViewOfSection
index 3c6946d..281a396 100644 (file)
@@ -4,14 +4,19 @@
 * FILE:            ntoskrnl/mm/sysldr.c
 * PURPOSE:         Contains the Kernel Loader (SYSLDR) for loading PE files.
 * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
+*                  ReactOS Portable Systems Group
 */
 
-/* INCLUDES ******************************************************************/
+/* INCLUDES *******************************************************************/
 
 #include <ntoskrnl.h>
 #define NDEBUG
 #include <debug.h>
 
+#line 16 "ARMĀ³::LOADER"
+#define MODULE_INVOLVED_IN_ARM3
+#include "./ARM3/miarm.h"
+
 /* GCC's incompetence strikes again */
 __inline
 VOID
@@ -25,7 +30,7 @@ sprintf_nt(IN PCHAR Buffer,
     va_end(ap);
 }
 
-/* GLOBALS *******************************************************************/
+/* GLOBALS ********************************************************************/
 
 LIST_ENTRY PsLoadedModuleList;
 LIST_ENTRY MmLoadedUserImageList;
@@ -39,7 +44,7 @@ PVOID MmLastUnloadedDrivers;
 PVOID MmTriageActionTaken;
 PVOID KernelVerifier;
 
-/* FUNCTIONS *****************************************************************/
+/* FUNCTIONS ******************************************************************/
 
 PVOID
 NTAPI
@@ -68,25 +73,6 @@ MiCacheImageSymbols(IN PVOID BaseAddress)
     return DebugDirectory;
 }
 
-VOID
-NTAPI
-MiFreeBootDriverMemory(PVOID BaseAddress,
-                       ULONG Length)
-{
-    ULONG i;
-
-    /* Loop each page */
-    for (i = 0; i < PAGE_ROUND_UP(Length) / PAGE_SIZE; i++)
-    {
-        /* Free the page */
-        MmDeleteVirtualMapping(NULL,
-                               (PVOID)((ULONG_PTR)BaseAddress + i * PAGE_SIZE),
-                               TRUE,
-                               NULL,
-                               NULL);
-    }
-}
-
 NTSTATUS
 NTAPI
 MiLoadImageSection(IN OUT PVOID *SectionPtr,
@@ -103,8 +89,10 @@ MiLoadImageSection(IN OUT PVOID *SectionPtr,
     KAPC_STATE ApcState;
     LARGE_INTEGER SectionOffset = {{0, 0}};
     BOOLEAN LoadSymbols = FALSE;
-    ULONG DriverSize;
+    PFN_NUMBER PteCount;
+    PMMPTE PointerPte, LastPte;
     PVOID DriverBase;
+    MMPTE TempPte;
     PAGED_CODE();
 
     /* Detect session load */
@@ -117,7 +105,7 @@ MiLoadImageSection(IN OUT PVOID *SectionPtr,
 
     /* Not session load, shouldn't have an entry */
     ASSERT(LdrEntry == NULL);
-
+    
     /* Attach to the system process */
     KeStackAttachProcess(&PsInitialSystemProcess->Pcb, &ApcState);
 
@@ -159,16 +147,37 @@ MiLoadImageSection(IN OUT PVOID *SectionPtr,
         KeUnstackDetachProcess(&ApcState);
         return Status;
     }
-
-    /* Get the driver size */
-    DriverSize = Section->ImageSection->ImageSize;
-
-    /*  Allocate a virtual section for the module  */
-    DriverBase = MmAllocateSection(DriverSize, NULL);
+    
+    /* Reserve system PTEs needed */
+    PteCount = ROUND_TO_PAGES(Section->ImageSection->ImageSize) >> PAGE_SHIFT;
+    PointerPte = MiReserveSystemPtes(PteCount, SystemPteSpace);
+    if (!PointerPte) return STATUS_INSUFFICIENT_RESOURCES;
+    
+    /* New driver base */
+    LastPte = PointerPte + PteCount;
+    DriverBase = MiPteToAddress(PointerPte);
+
+    /* The driver is here */
     *ImageBase = DriverBase;
 
+    /* Loop the new driver PTEs */
+    TempPte = ValidKernelPte;
+    while (PointerPte < LastPte)
+    {
+        /* Allocate a page */
+        TempPte.u.Hard.PageFrameNumber = MmAllocPage(MC_NPPOOL);
+        
+        /* Write it */
+        ASSERT(PointerPte->u.Hard.Valid == 0);
+        ASSERT(TempPte.u.Hard.Valid == 1);
+        *PointerPte = TempPte;
+        
+        /* Move on */
+        PointerPte++;
+    }
+        
     /* Copy the image */
-    RtlCopyMemory(DriverBase, Base, DriverSize);
+    RtlCopyMemory(DriverBase, Base, PteCount << PAGE_SHIFT);
 
     /* Now unmap the view */
     Status = MmUnmapViewOfSection(Process, Base);
@@ -1210,6 +1219,10 @@ MiReloadBootLoadedDrivers(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
     PIMAGE_DATA_DIRECTORY DataDirectory;
     PVOID DllBase, NewImageAddress;
     NTSTATUS Status;
+    PMMPTE PointerPte, StartPte, LastPte;
+    PFN_NUMBER PteCount;
+    PMMPFN Pfn1;
+    MMPTE TempPte, OldPte;
 
     /* Loop driver list */
     for (NextEntry = LoaderBlock->LoadOrderListHead.Flink;
@@ -1266,30 +1279,71 @@ MiReloadBootLoadedDrivers(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
 
         /* Remember the original address */
         DllBase = LdrEntry->DllBase;
-
-        /*  Allocate a virtual section for the module  */
-        NewImageAddress = MmAllocateSection(LdrEntry->SizeOfImage, NULL);
-        if (!NewImageAddress)
+        
+        /* Get the first PTE and the number of PTEs we'll need */
+        PointerPte = StartPte = MiAddressToPte(LdrEntry->DllBase);
+        PteCount = ROUND_TO_PAGES(LdrEntry->SizeOfImage) >> PAGE_SHIFT;
+        LastPte = StartPte + PteCount;
+        
+        /* Loop the PTEs */
+        while (PointerPte < LastPte)
+        {
+            /* Mark the page modified in the PFN database */
+            ASSERT(PointerPte->u.Hard.Valid == 1);
+            Pfn1 = MiGetPfnEntry(PFN_FROM_PTE(PointerPte));
+            ASSERT(Pfn1->u3.e1.Rom == 0);
+            Pfn1->u3.e1.Modified = TRUE;
+            
+            /* Next */
+            PointerPte++;
+        }
+        
+        /* Now reserve system PTEs for the image */
+        PointerPte = MiReserveSystemPtes(PteCount, SystemPteSpace);
+        if (!PointerPte)
         {
             /* Shouldn't happen */
             DPRINT1("[Mm0]: Couldn't allocate driver section!\n");
             while (TRUE);
         }
+        
+        /* This is the new virtual address for the module */
+        LastPte = PointerPte + PteCount;
+        NewImageAddress = MiPteToAddress(PointerPte);
 
         /* Sanity check */
         DPRINT("[Mm0]: Copying from: %p to: %p\n", DllBase, NewImageAddress);
         ASSERT(ExpInitializationPhase == 0);
-
-        /* Now copy the entire driver over */
-        RtlCopyMemory(NewImageAddress, DllBase, LdrEntry->SizeOfImage);
+        
+        /* Loop the new driver PTEs */
+        TempPte = ValidKernelPte;
+        while (PointerPte < LastPte)
+        {
+            /* Copy the old data */
+            OldPte = *StartPte;
+            ASSERT(OldPte.u.Hard.Valid == 1);
+            
+            /* Set page number from the loader's memory */
+            TempPte.u.Hard.PageFrameNumber = OldPte.u.Hard.PageFrameNumber;
+            
+            /* Write it */
+            ASSERT(PointerPte->u.Hard.Valid == 0);
+            ASSERT(TempPte.u.Hard.Valid == 1);
+            *PointerPte = TempPte;
+            
+            /* Move on */
+            PointerPte++;
+            StartPte++;
+        }
+        
+        /* Update position */
+        PointerPte -= PteCount;
 
         /* Sanity check */
         ASSERT(*(PULONG)NewImageAddress == *(PULONG)DllBase);
 
         /* Set the image base to the address where the loader put it */
         NtHeader->OptionalHeader.ImageBase = (ULONG_PTR)DllBase;
-        NtHeader = RtlImageNtHeader(NewImageAddress);
-        NtHeader->OptionalHeader.ImageBase = (ULONG_PTR)DllBase;
 
         /* Check if we had relocations */
         if (ValidRelocs)
@@ -1323,10 +1377,9 @@ MiReloadBootLoadedDrivers(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
         LdrEntry->Flags |= LDRP_SYSTEM_MAPPED;
         LdrEntry->EntryPoint = (PVOID)((ULONG_PTR)NewImageAddress +
                                 NtHeader->OptionalHeader.AddressOfEntryPoint);
-        LdrEntry->SizeOfImage = LdrEntry->SizeOfImage;
-
-        /* Free the old copy */
-        MiFreeBootDriverMemory(DllBase, LdrEntry->SizeOfImage);
+        LdrEntry->SizeOfImage = PteCount << PAGE_SHIFT;
+        
+        /* FIXME: We'll need to fixup the PFN linkage when switching to ARM3 */
     }
 }