From 662fe5030b1cbf2abba956148129d151d40cbb96 Mon Sep 17 00:00:00 2001 From: Sir Richard Date: Sun, 21 Feb 2010 02:13:20 +0000 Subject: [PATCH] [NTOS]: Use system PTEs for drivers, both boot drivers and system-loaded drivers. This removes the last user of the deprecated MmAllocateSection internal API. Another side-effect is that drivers will now have much higher load addresses (in the 0xF0000000 and higher range), as you would expect on Windows, plus increasing coverage and usage of system PTEs (which can still be optimized). [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 | 57 -------------- reactos/ntoskrnl/mm/sysldr.c | 139 +++++++++++++++++++++++----------- 2 files changed, 96 insertions(+), 100 deletions(-) diff --git a/reactos/ntoskrnl/mm/section.c b/reactos/ntoskrnl/mm/section.c index 321a694f0d0..582af62037d 100644 --- a/reactos/ntoskrnl/mm/section.c +++ b/reactos/ntoskrnl/mm/section.c @@ -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 diff --git a/reactos/ntoskrnl/mm/sysldr.c b/reactos/ntoskrnl/mm/sysldr.c index 3c6946d6b1b..281a3966bb2 100644 --- a/reactos/ntoskrnl/mm/sysldr.c +++ b/reactos/ntoskrnl/mm/sysldr.c @@ -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 #define NDEBUG #include +#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; } + + /* 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); - /* Get the driver size */ - DriverSize = Section->ImageSection->ImageSize; - - /* Allocate a virtual section for the module */ - DriverBase = MmAllocateSection(DriverSize, NULL); + /* 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 */ } }