[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
This commit is contained in:
Sir Richard 2010-02-21 02:13:20 +00:00
parent 2445098aef
commit 662fe5030b
2 changed files with 96 additions and 100 deletions

View file

@ -4420,63 +4420,6 @@ NtExtendSection(IN HANDLE SectionHandle,
return STATUS_NOT_IMPLEMENTED; 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 * NAME EXPORTED
* MmMapViewOfSection * MmMapViewOfSection

View file

@ -4,14 +4,19 @@
* FILE: ntoskrnl/mm/sysldr.c * FILE: ntoskrnl/mm/sysldr.c
* PURPOSE: Contains the Kernel Loader (SYSLDR) for loading PE files. * PURPOSE: Contains the Kernel Loader (SYSLDR) for loading PE files.
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
* ReactOS Portable Systems Group
*/ */
/* INCLUDES ******************************************************************/ /* INCLUDES *******************************************************************/
#include <ntoskrnl.h> #include <ntoskrnl.h>
#define NDEBUG #define NDEBUG
#include <debug.h> #include <debug.h>
#line 16 "ARM³::LOADER"
#define MODULE_INVOLVED_IN_ARM3
#include "./ARM3/miarm.h"
/* GCC's incompetence strikes again */ /* GCC's incompetence strikes again */
__inline __inline
VOID VOID
@ -25,7 +30,7 @@ sprintf_nt(IN PCHAR Buffer,
va_end(ap); va_end(ap);
} }
/* GLOBALS *******************************************************************/ /* GLOBALS ********************************************************************/
LIST_ENTRY PsLoadedModuleList; LIST_ENTRY PsLoadedModuleList;
LIST_ENTRY MmLoadedUserImageList; LIST_ENTRY MmLoadedUserImageList;
@ -39,7 +44,7 @@ PVOID MmLastUnloadedDrivers;
PVOID MmTriageActionTaken; PVOID MmTriageActionTaken;
PVOID KernelVerifier; PVOID KernelVerifier;
/* FUNCTIONS *****************************************************************/ /* FUNCTIONS ******************************************************************/
PVOID PVOID
NTAPI NTAPI
@ -68,25 +73,6 @@ MiCacheImageSymbols(IN PVOID BaseAddress)
return DebugDirectory; 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 NTSTATUS
NTAPI NTAPI
MiLoadImageSection(IN OUT PVOID *SectionPtr, MiLoadImageSection(IN OUT PVOID *SectionPtr,
@ -103,8 +89,10 @@ MiLoadImageSection(IN OUT PVOID *SectionPtr,
KAPC_STATE ApcState; KAPC_STATE ApcState;
LARGE_INTEGER SectionOffset = {{0, 0}}; LARGE_INTEGER SectionOffset = {{0, 0}};
BOOLEAN LoadSymbols = FALSE; BOOLEAN LoadSymbols = FALSE;
ULONG DriverSize; PFN_NUMBER PteCount;
PMMPTE PointerPte, LastPte;
PVOID DriverBase; PVOID DriverBase;
MMPTE TempPte;
PAGED_CODE(); PAGED_CODE();
/* Detect session load */ /* Detect session load */
@ -117,7 +105,7 @@ MiLoadImageSection(IN OUT PVOID *SectionPtr,
/* Not session load, shouldn't have an entry */ /* Not session load, shouldn't have an entry */
ASSERT(LdrEntry == NULL); ASSERT(LdrEntry == NULL);
/* Attach to the system process */ /* Attach to the system process */
KeStackAttachProcess(&PsInitialSystemProcess->Pcb, &ApcState); KeStackAttachProcess(&PsInitialSystemProcess->Pcb, &ApcState);
@ -159,16 +147,37 @@ MiLoadImageSection(IN OUT PVOID *SectionPtr,
KeUnstackDetachProcess(&ApcState); KeUnstackDetachProcess(&ApcState);
return Status; 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 */ /* The driver is here */
DriverSize = Section->ImageSection->ImageSize;
/* Allocate a virtual section for the module */
DriverBase = MmAllocateSection(DriverSize, NULL);
*ImageBase = DriverBase; *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 */ /* Copy the image */
RtlCopyMemory(DriverBase, Base, DriverSize); RtlCopyMemory(DriverBase, Base, PteCount << PAGE_SHIFT);
/* Now unmap the view */ /* Now unmap the view */
Status = MmUnmapViewOfSection(Process, Base); Status = MmUnmapViewOfSection(Process, Base);
@ -1210,6 +1219,10 @@ MiReloadBootLoadedDrivers(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
PIMAGE_DATA_DIRECTORY DataDirectory; PIMAGE_DATA_DIRECTORY DataDirectory;
PVOID DllBase, NewImageAddress; PVOID DllBase, NewImageAddress;
NTSTATUS Status; NTSTATUS Status;
PMMPTE PointerPte, StartPte, LastPte;
PFN_NUMBER PteCount;
PMMPFN Pfn1;
MMPTE TempPte, OldPte;
/* Loop driver list */ /* Loop driver list */
for (NextEntry = LoaderBlock->LoadOrderListHead.Flink; for (NextEntry = LoaderBlock->LoadOrderListHead.Flink;
@ -1266,30 +1279,71 @@ MiReloadBootLoadedDrivers(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
/* Remember the original address */ /* Remember the original address */
DllBase = LdrEntry->DllBase; DllBase = LdrEntry->DllBase;
/* Allocate a virtual section for the module */ /* Get the first PTE and the number of PTEs we'll need */
NewImageAddress = MmAllocateSection(LdrEntry->SizeOfImage, NULL); PointerPte = StartPte = MiAddressToPte(LdrEntry->DllBase);
if (!NewImageAddress) 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 */ /* Shouldn't happen */
DPRINT1("[Mm0]: Couldn't allocate driver section!\n"); DPRINT1("[Mm0]: Couldn't allocate driver section!\n");
while (TRUE); while (TRUE);
} }
/* This is the new virtual address for the module */
LastPte = PointerPte + PteCount;
NewImageAddress = MiPteToAddress(PointerPte);
/* Sanity check */ /* Sanity check */
DPRINT("[Mm0]: Copying from: %p to: %p\n", DllBase, NewImageAddress); DPRINT("[Mm0]: Copying from: %p to: %p\n", DllBase, NewImageAddress);
ASSERT(ExpInitializationPhase == 0); ASSERT(ExpInitializationPhase == 0);
/* Now copy the entire driver over */ /* Loop the new driver PTEs */
RtlCopyMemory(NewImageAddress, DllBase, LdrEntry->SizeOfImage); 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 */ /* Sanity check */
ASSERT(*(PULONG)NewImageAddress == *(PULONG)DllBase); ASSERT(*(PULONG)NewImageAddress == *(PULONG)DllBase);
/* Set the image base to the address where the loader put it */ /* Set the image base to the address where the loader put it */
NtHeader->OptionalHeader.ImageBase = (ULONG_PTR)DllBase; NtHeader->OptionalHeader.ImageBase = (ULONG_PTR)DllBase;
NtHeader = RtlImageNtHeader(NewImageAddress);
NtHeader->OptionalHeader.ImageBase = (ULONG_PTR)DllBase;
/* Check if we had relocations */ /* Check if we had relocations */
if (ValidRelocs) if (ValidRelocs)
@ -1323,10 +1377,9 @@ MiReloadBootLoadedDrivers(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
LdrEntry->Flags |= LDRP_SYSTEM_MAPPED; LdrEntry->Flags |= LDRP_SYSTEM_MAPPED;
LdrEntry->EntryPoint = (PVOID)((ULONG_PTR)NewImageAddress + LdrEntry->EntryPoint = (PVOID)((ULONG_PTR)NewImageAddress +
NtHeader->OptionalHeader.AddressOfEntryPoint); NtHeader->OptionalHeader.AddressOfEntryPoint);
LdrEntry->SizeOfImage = LdrEntry->SizeOfImage; LdrEntry->SizeOfImage = PteCount << PAGE_SHIFT;
/* Free the old copy */ /* FIXME: We'll need to fixup the PFN linkage when switching to ARM3 */
MiFreeBootDriverMemory(DllBase, LdrEntry->SizeOfImage);
} }
} }