Author: sir_richard
Date: Sun Feb 21 03:13:20 2010
New Revision: 45641
URL:
http://svn.reactos.org/svn/reactos?rev=45641&view=rev
Log:
[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.
Modified:
trunk/reactos/ntoskrnl/mm/section.c
trunk/reactos/ntoskrnl/mm/sysldr.c
Modified: trunk/reactos/ntoskrnl/mm/section.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/section.c?rev=…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/section.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/section.c [iso-8859-1] Sun Feb 21 03:13:20 2010
@@ -4420,63 +4420,6 @@
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
Modified: trunk/reactos/ntoskrnl/mm/sysldr.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/sysldr.c?rev=4…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/sysldr.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/sysldr.c [iso-8859-1] Sun Feb 21 03:13:20 2010
@@ -4,13 +4,18 @@
* FILE: ntoskrnl/mm/sysldr.c
* PURPOSE: Contains the Kernel Loader (SYSLDR) for loading PE files.
* PROGRAMMERS: Alex Ionescu (alex.ionescu(a)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
@@ -25,7 +30,7 @@
va_end(ap);
}
-/* GLOBALS *******************************************************************/
+/* GLOBALS ********************************************************************/
LIST_ENTRY PsLoadedModuleList;
LIST_ENTRY MmLoadedUserImageList;
@@ -39,7 +44,7 @@
PVOID MmTriageActionTaken;
PVOID KernelVerifier;
-/* FUNCTIONS *****************************************************************/
+/* FUNCTIONS ******************************************************************/
PVOID
NTAPI
@@ -66,25 +71,6 @@
/* Return the directory */
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
@@ -103,8 +89,10 @@
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 @@
/* Not session load, shouldn't have an entry */
ASSERT(LdrEntry == NULL);
-
+
/* Attach to the system process */
KeStackAttachProcess(&PsInitialSystemProcess->Pcb, &ApcState);
@@ -159,16 +147,37 @@
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 @@
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,29 +1279,70 @@
/* 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 */
@@ -1323,10 +1377,9 @@
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 */
}
}