[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;
}
/**********************************************************************
* 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

View 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;
}
/* 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 */
}
}