Author: tkreuzer
Date: Fri Dec 4 14:06:00 2009
New Revision: 44402
URL:
http://svn.reactos.org/svn/reactos?rev=44402&view=rev
Log:
[MM]
Rewrite MmAllocateSection to use system PTEs. Store the MDL pointer in the first PFN, to
avoid allocating an additional PTE. Implement MmFreeSection. Now the bootdrivers go where
they should go, freeing up lower system memory, and unloaded drivers actually get their
memory freed (saving us 188 KB each boot).
Modified:
branches/ros-amd64-bringup/reactos/ntoskrnl/include/internal/mm.h
branches/ros-amd64-bringup/reactos/ntoskrnl/mm/section.c
branches/ros-amd64-bringup/reactos/ntoskrnl/mm/sysldr.c
Modified: branches/ros-amd64-bringup/reactos/ntoskrnl/include/internal/mm.h
URL:
http://svn.reactos.org/svn/reactos/branches/ros-amd64-bringup/reactos/ntosk…
==============================================================================
--- branches/ros-amd64-bringup/reactos/ntoskrnl/include/internal/mm.h [iso-8859-1]
(original)
+++ branches/ros-amd64-bringup/reactos/ntoskrnl/include/internal/mm.h [iso-8859-1] Fri Dec
4 14:06:00 2009
@@ -233,6 +233,7 @@
(PAGE_WRITECOPY | \
PAGE_EXECUTE_WRITECOPY)
+#define MI_PFN_ELEMENT(Pfn) (&MmPfnDatabase[Pfn])
#define InterlockedCompareExchangePte(PointerPte, Exchange, Comperand) \
InterlockedCompareExchange((PLONG)(PointerPte), Exchange, Comperand)
Modified: branches/ros-amd64-bringup/reactos/ntoskrnl/mm/section.c
URL:
http://svn.reactos.org/svn/reactos/branches/ros-amd64-bringup/reactos/ntosk…
==============================================================================
--- branches/ros-amd64-bringup/reactos/ntoskrnl/mm/section.c [iso-8859-1] (original)
+++ branches/ros-amd64-bringup/reactos/ntoskrnl/mm/section.c [iso-8859-1] Fri Dec 4
14:06:00 2009
@@ -48,6 +48,7 @@
#define NDEBUG
#include <debug.h>
#include <reactos/exeformat.h>
+#include "ARM3/miarm.h"
#if defined (ALLOC_PRAGMA)
#pragma alloc_text(INIT, MmCreatePhysicalMemorySection)
@@ -4501,42 +4502,117 @@
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,
+ PHYSICAL_ADDRESS LowAddress, HighAddress, SkipBytes;
+ PMDL Mdl;
+ PFN_COUNT PageCount;
+ PPFN_NUMBER MdlPages;
+ MMPTE TempPte, *PointerPte;
+ PMMPFN Pfn;
+
+ /* Allocate an MDL */
+ LowAddress.QuadPart = 0;
+ HighAddress.QuadPart = -1;
+ SkipBytes.QuadPart = 0;
+ Mdl = MiAllocatePagesForMdl(LowAddress,
+ HighAddress,
+ SkipBytes,
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);
-}
-
+ MiPlatformCacheAttributes[0][MmCached],
+ 0); // use MM_ALLOCATE_FULLY_REQUIRED
+ if (!Mdl)
+ {
+ /* Fail */
+ return NULL;
+ }
+
+ /* Check if we got all we need */
+ if (Mdl->ByteCount < Length)
+ {
+ /* We didn't get enough */
+ MmFreePagesFromMdl(Mdl);
+ ExFreePool(Mdl);
+ return NULL;
+ }
+
+ /* Calculate how many pages we should have */
+ PageCount = BYTES_TO_PAGES(Length);
+
+ /* Reserve system PTEs */
+ PointerPte = MiReserveSystemPtes(PageCount, SystemPteSpace);
+ if (!PointerPte)
+ {
+ /* Free the MDL and fail */
+ MmFreePagesFromMdl(Mdl);
+ ExFreePool(Mdl);
+ return NULL;
+ }
+
+ /* Safe the base address */
+ BaseAddress = MiPteToAddress(PointerPte);
+
+ /* Get a pointer to the page array */
+ MdlPages = (PPFN_NUMBER)(Mdl + 1);
+
+ /* Get the first page's PFN entry */
+ Pfn = MI_PFN_ELEMENT(*MdlPages);
+
+ /* Save the pointer to the MDL in the PFN entry */
+ *(PMDL*)&Pfn->OriginalPte = Mdl;
+
+ /* Setup template PTE */
+ TempPte = HyperTemplatePte;
+
+ /* Map the PTEs */
+ do
+ {
+ /* Sanity checks */
+ ASSERT(PointerPte->u.Hard.Valid == 0);
+ ASSERT(PointerPte->u.Soft.Transition == 0);
+
+ /* Get the PFN */
+ TempPte.u.Hard.PageFrameNumber = *MdlPages++;
+
+ /* Write the PTE */
+ *PointerPte++ = TempPte;
+ } while (--PageCount);
+
+ /* Return the base address */
+ return BaseAddress;
+}
+
+VOID
+NTAPI
+MmFreeSection(PVOID BaseAddress)
+{
+ PMMPTE PointerPte;
+ PFN_NUMBER *MdlPages, PageFrameNumber, PageCount;
+ PMMPFN Pfn;
+ PMDL Mdl;
+
+ /* Get a pointer to the first PTE */
+ PointerPte = MiAddressToPte(BaseAddress);
+
+ /* Get the page frame number of the first page */
+ PageFrameNumber = PFN_FROM_PTE(PointerPte);
+
+ /* Get the first pages's PFN entry */
+ Pfn = MI_PFN_ELEMENT(PageFrameNumber);
+
+ /* Get the MDL from the PFN */
+ Mdl = *(PMDL*)&Pfn->OriginalPte;
+ *(PMDL*)&Pfn->OriginalPte = NULL;
+
+ /* Get the page array and count from the MDL */
+ MdlPages = (PPFN_NUMBER)(Mdl + 1);
+ PageCount = BYTES_TO_PAGES(Mdl->ByteCount);
+
+ /* Release the system PTEs */
+ MiReleaseSystemPtes(PointerPte, PageCount, SystemPteSpace);
+
+ /* Free the pages and the MDL */
+ MmFreePagesFromMdl(Mdl);
+ ExFreePool(Mdl);
+}
/**********************************************************************
* NAME EXPORTED
Modified: branches/ros-amd64-bringup/reactos/ntoskrnl/mm/sysldr.c
URL:
http://svn.reactos.org/svn/reactos/branches/ros-amd64-bringup/reactos/ntosk…
==============================================================================
--- branches/ros-amd64-bringup/reactos/ntoskrnl/mm/sysldr.c [iso-8859-1] (original)
+++ branches/ros-amd64-bringup/reactos/ntoskrnl/mm/sysldr.c [iso-8859-1] Fri Dec 4
14:06:00 2009
@@ -780,8 +780,8 @@
}
}
- /* FIXME: Free the driver */
- //MmFreeSection(LdrEntry->DllBase);
+ /* Free the driver */
+ MmFreeSection(LdrEntry->DllBase);
/* Check if we're linked in */
if (LdrEntry->InLoadOrderLinks.Flink)