Author: ros-arm-bringup
Date: Tue Jun 30 12:55:18 2009
New Revision: 41708
URL:
http://svn.reactos.org/svn/reactos?rev=41708&view=rev
Log:
- Rewrite MmAllocateNonCachedMemory and MmFreeNonCachedMemory to use the new functionality
present in ARM3.
- These functions now use the MDL routines to allocate their physical memory, since the
constraints and requirements are identical as for a non-cached MDL mapping.
- As for the virtual address space, it is guaranteed once again by System PTEs!
- If it's not getting old already, optimizations to the System PTE code will, yet
again, yield improvements here as well.
- This is the last large kernel-facing memory allocator that needed updating to use System
PTEs instead.
- Only the pool allocator remains (which, for nonpaged pool, also uses System PTEs,
present in the nonpaged pool expansion VA).
- That effort will take significantly longer.
Added:
trunk/reactos/ntoskrnl/mm/ARM3/ncache.c
- copied, changed from r41647, trunk/reactos/ntoskrnl/mm/ncache.c
Removed:
trunk/reactos/ntoskrnl/mm/ncache.c
Modified:
trunk/reactos/ntoskrnl/ntoskrnl-generic.rbuild
Copied: trunk/reactos/ntoskrnl/mm/ARM3/ncache.c (from r41647,
trunk/reactos/ntoskrnl/mm/ncache.c)
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/ncache.c?…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/ncache.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/ARM3/ncache.c [iso-8859-1] Tue Jun 30 12:55:18 2009
@@ -1,128 +1,214 @@
/*
- * COPYRIGHT: See COPYING in the top level directory
- * PROJECT: ReactOS kernel
- * FILE: ntoskrnl/mm/ncache.c
- * PURPOSE: Manages non-cached memory
- *
- * PROGRAMMERS: David Welch (welch(a)cwcom.net)
+ * PROJECT: ReactOS Kernel
+ * LICENSE: BSD - See COPYING.ARM in the top level directory
+ * FILE: ntoskrnl/mm/ARM3/ncache.c
+ * PURPOSE: ARM Memory Manager Noncached Memory Allocator
+ * PROGRAMMERS: ReactOS Portable Systems Group
*/
-/* INCLUDES *****************************************************************/
+/* INCLUDES *******************************************************************/
#include <ntoskrnl.h>
#define NDEBUG
#include <debug.h>
-/* FUNCTIONS *****************************************************************/
-
-
-/**********************************************************************
- * NAME EXPORTED
- * MmAllocateNonCachedMemory@4
- *
- * DESCRIPTION
- * Allocates a virtual address range of noncached and cache
- * aligned memory.
- *
- * ARGUMENTS
- * NumberOfBytes
- * Size of region to allocate.
- *
- * RETURN VALUE
- * The base address of the range on success;
- * NULL on failure.
- *
- * NOTE
- * Description taken from include/ddk/mmfuncs.h.
- * Code taken from ntoskrnl/mm/special.c.
- *
- * REVISIONS
- *
+#line 15 "ARM³::NCACHE"
+#define MODULE_INVOLVED_IN_ARM3
+#include "../ARM3/miarm.h"
+
+/* GLOBALS ********************************************************************/
+
+/*
* @implemented
*/
-PVOID NTAPI
+PVOID
+NTAPI
MmAllocateNonCachedMemory(IN ULONG NumberOfBytes)
{
- PVOID Result;
- MEMORY_AREA* marea;
- NTSTATUS Status;
- ULONG Protect = PAGE_READWRITE|PAGE_SYSTEM|PAGE_NOCACHE|PAGE_WRITETHROUGH;
- PHYSICAL_ADDRESS BoundaryAddressMultiple;
-
- BoundaryAddressMultiple.QuadPart = 0;
- MmLockAddressSpace(MmGetKernelAddressSpace());
- Result = NULL;
- Status = MmCreateMemoryArea (MmGetKernelAddressSpace(),
- MEMORY_AREA_NO_CACHE,
- &Result,
+ PFN_NUMBER PageCount, MdlPageCount, PageFrameIndex;
+ PHYSICAL_ADDRESS LowAddress, HighAddress, SkipBytes;
+ MI_PFN_CACHE_ATTRIBUTE CacheAttribute;
+ PMDL Mdl;
+ PVOID BaseAddress;
+ PPFN_NUMBER MdlPages;
+ PMMPTE PointerPte;
+ MMPTE TempPte;
+
+ //
+ // Get the page count
+ //
+ ASSERT(NumberOfBytes != 0);
+ PageCount = BYTES_TO_PAGES(NumberOfBytes);
+
+ //
+ // Use the MDL allocator for simplicity, so setup the parameters
+ //
+ LowAddress.QuadPart = 0;
+ HighAddress.QuadPart = -1;
+ SkipBytes.QuadPart = 0;
+ CacheAttribute = MiPlatformCacheAttributes[0][MmNonCached];
+
+ //
+ // Now call the MDL allocator
+ //
+ Mdl = MiAllocatePagesForMdl(LowAddress,
+ HighAddress,
+ SkipBytes,
NumberOfBytes,
- Protect,
- &marea,
- FALSE,
- 0,
- BoundaryAddressMultiple);
- MmUnlockAddressSpace(MmGetKernelAddressSpace());
-
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("Allocating marea for noncached mem failed with Status "
- "0x%08X\n", Status);
- return (NULL);
- }
-
- /* Create a virtual mapping for this memory area */
- MmMapMemoryArea(Result, NumberOfBytes, MC_NPPOOL, Protect);
-
- return ((PVOID)Result);
+ CacheAttribute,
+ 0);
+ if (!Mdl) return NULL;
+
+ //
+ // Get the MDL VA and check how many pages we got (could be partial)
+ //
+ BaseAddress = (PVOID)((ULONG_PTR)Mdl->StartVa + Mdl->ByteOffset);
+ MdlPageCount = ADDRESS_AND_SIZE_TO_SPAN_PAGES(BaseAddress, Mdl->ByteCount);
+ if (PageCount != MdlPageCount)
+ {
+ //
+ // Unlike MDLs, partial isn't okay for a noncached allocation, so fail
+ //
+ ASSERT(PageCount > MdlPageCount);
+ MmFreePagesFromMdl(Mdl);
+ ExFreePool(Mdl);
+ return NULL;
+ }
+
+ //
+ // Allocate system PTEs for the base address
+ // We use an extra page to store the actual MDL pointer for the free later
+ //
+ PointerPte = MiReserveSystemPtes(PageCount + 1, SystemPteSpace);
+ if (!PointerPte)
+ {
+ //
+ // Out of memory...
+ //
+ MmFreePagesFromMdl(Mdl);
+ ExFreePool(Mdl);
+ return NULL;
+ }
+
+ //
+ // Store the MDL pointer
+ //
+ *(PMDL*)PointerPte++ = Mdl;
+
+ //
+ // Okay, now see what range we got
+ //
+ BaseAddress = MiPteToAddress(PointerPte);
+
+ //
+ // This is our array of pages
+ //
+ MdlPages = (PPFN_NUMBER)(Mdl + 1);
+
+ //
+ // Setup the template PTE
+ //
+ TempPte = HyperTemplatePte;
+
+ //
+ // Now check what kind of caching we should use
+ //
+ switch (CacheAttribute)
+ {
+ case MiNonCached:
+
+ //
+ // Disable caching
+ //
+ TempPte.u.Hard.CacheDisable = 1;
+ TempPte.u.Hard.WriteThrough = 1;
+ break;
+
+ case MiWriteCombined:
+
+ //
+ // Enable write combining
+ //
+ TempPte.u.Hard.CacheDisable = 1;
+ TempPte.u.Hard.WriteThrough = 0;
+ break;
+
+ default:
+ //
+ // Nothing to do
+ //
+ break;
+ }
+
+ //
+ // Now loop the MDL pages
+ //
+ do
+ {
+ //
+ // Get the PFN
+ //
+ PageFrameIndex = *MdlPages++;
+
+ //
+ // Set the PFN in the page and write it
+ //
+ TempPte.u.Hard.PageFrameNumber = PageFrameIndex;
+ ASSERT(PointerPte->u.Hard.Valid == 0);
+ ASSERT(TempPte.u.Hard.Valid == 1);
+ *PointerPte++ = TempPte;
+ } while (--PageCount);
+
+ //
+ // Return the base address
+ //
+ return BaseAddress;
+
}
-static VOID
-MmFreeNonCachedPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address,
- PFN_TYPE Page, SWAPENTRY SwapEntry,
- BOOLEAN Dirty)
-{
- ASSERT(SwapEntry == 0);
- if (Page != 0)
- {
- MmReleasePageMemoryConsumer(MC_NPPOOL, Page);
- }
-}
-
-/**********************************************************************
- * NAME EXPORTED
- * MmFreeNonCachedMemory@8
- *
- * DESCRIPTION
- * Releases a range of noncached memory allocated with
- * MmAllocateNonCachedMemory.
- *
- * ARGUMENTS
- * BaseAddress
- * Virtual address to be freed;
- *
- * NumberOfBytes
- * Size of the region to be freed.
- *
- * RETURN VALUE
- * None.
- *
- * NOTE
- * Description taken from include/ddk/mmfuncs.h.
- * Code taken from ntoskrnl/mm/special.c.
- *
- * REVISIONS
- *
+/*
* @implemented
*/
-VOID NTAPI MmFreeNonCachedMemory (IN PVOID BaseAddress,
- IN ULONG NumberOfBytes)
+VOID
+NTAPI
+MmFreeNonCachedMemory(IN PVOID BaseAddress,
+ IN ULONG NumberOfBytes)
{
- MmLockAddressSpace(MmGetKernelAddressSpace());
- MmFreeMemoryAreaByPtr(MmGetKernelAddressSpace(),
- BaseAddress,
- MmFreeNonCachedPage,
- NULL);
- MmUnlockAddressSpace(MmGetKernelAddressSpace());
+ PMDL Mdl;
+ PMMPTE PointerPte;
+ PFN_NUMBER PageCount;
+
+ //
+ // Sanity checks
+ //
+ ASSERT(NumberOfBytes != 0);
+ ASSERT(PAGE_ALIGN(BaseAddress) == BaseAddress);
+
+ //
+ // Get the page count
+ //
+ PageCount = BYTES_TO_PAGES(NumberOfBytes);
+
+ //
+ // Get the first PTE
+ //
+ PointerPte = MiAddressToPte(BaseAddress);
+
+ //
+ // Remember this is where we store the shadow MDL pointer
+ //
+ Mdl = *(PMDL*)(--PointerPte);
+
+ //
+ // Kill the MDL (and underlying pages)
+ //
+ MmFreePagesFromMdl(Mdl);
+ ExFreePool(Mdl);
+
+ //
+ // Now free the system PTEs for the underlying VA
+ //
+ MiReleaseSystemPtes(PointerPte, PageCount + 1, SystemPteSpace);
}
/* EOF */
Removed: trunk/reactos/ntoskrnl/mm/ncache.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ncache.c?rev=4…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/ncache.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/ncache.c (removed)
@@ -1,128 +1,0 @@
-/*
- * COPYRIGHT: See COPYING in the top level directory
- * PROJECT: ReactOS kernel
- * FILE: ntoskrnl/mm/ncache.c
- * PURPOSE: Manages non-cached memory
- *
- * PROGRAMMERS: David Welch (welch(a)cwcom.net)
- */
-
-/* INCLUDES *****************************************************************/
-
-#include <ntoskrnl.h>
-#define NDEBUG
-#include <debug.h>
-
-/* FUNCTIONS *****************************************************************/
-
-
-/**********************************************************************
- * NAME EXPORTED
- * MmAllocateNonCachedMemory@4
- *
- * DESCRIPTION
- * Allocates a virtual address range of noncached and cache
- * aligned memory.
- *
- * ARGUMENTS
- * NumberOfBytes
- * Size of region to allocate.
- *
- * RETURN VALUE
- * The base address of the range on success;
- * NULL on failure.
- *
- * NOTE
- * Description taken from include/ddk/mmfuncs.h.
- * Code taken from ntoskrnl/mm/special.c.
- *
- * REVISIONS
- *
- * @implemented
- */
-PVOID NTAPI
-MmAllocateNonCachedMemory(IN ULONG NumberOfBytes)
-{
- PVOID Result;
- MEMORY_AREA* marea;
- NTSTATUS Status;
- ULONG Protect = PAGE_READWRITE|PAGE_SYSTEM|PAGE_NOCACHE|PAGE_WRITETHROUGH;
- PHYSICAL_ADDRESS BoundaryAddressMultiple;
-
- BoundaryAddressMultiple.QuadPart = 0;
- MmLockAddressSpace(MmGetKernelAddressSpace());
- Result = NULL;
- Status = MmCreateMemoryArea (MmGetKernelAddressSpace(),
- MEMORY_AREA_NO_CACHE,
- &Result,
- NumberOfBytes,
- Protect,
- &marea,
- FALSE,
- 0,
- BoundaryAddressMultiple);
- MmUnlockAddressSpace(MmGetKernelAddressSpace());
-
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("Allocating marea for noncached mem failed with Status "
- "0x%08X\n", Status);
- return (NULL);
- }
-
- /* Create a virtual mapping for this memory area */
- MmMapMemoryArea(Result, NumberOfBytes, MC_NPPOOL, Protect);
-
- return ((PVOID)Result);
-}
-
-static VOID
-MmFreeNonCachedPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address,
- PFN_TYPE Page, SWAPENTRY SwapEntry,
- BOOLEAN Dirty)
-{
- ASSERT(SwapEntry == 0);
- if (Page != 0)
- {
- MmReleasePageMemoryConsumer(MC_NPPOOL, Page);
- }
-}
-
-/**********************************************************************
- * NAME EXPORTED
- * MmFreeNonCachedMemory@8
- *
- * DESCRIPTION
- * Releases a range of noncached memory allocated with
- * MmAllocateNonCachedMemory.
- *
- * ARGUMENTS
- * BaseAddress
- * Virtual address to be freed;
- *
- * NumberOfBytes
- * Size of the region to be freed.
- *
- * RETURN VALUE
- * None.
- *
- * NOTE
- * Description taken from include/ddk/mmfuncs.h.
- * Code taken from ntoskrnl/mm/special.c.
- *
- * REVISIONS
- *
- * @implemented
- */
-VOID NTAPI MmFreeNonCachedMemory (IN PVOID BaseAddress,
- IN ULONG NumberOfBytes)
-{
- MmLockAddressSpace(MmGetKernelAddressSpace());
- MmFreeMemoryAreaByPtr(MmGetKernelAddressSpace(),
- BaseAddress,
- MmFreeNonCachedPage,
- NULL);
- MmUnlockAddressSpace(MmGetKernelAddressSpace());
-}
-
-/* EOF */
Modified: trunk/reactos/ntoskrnl/ntoskrnl-generic.rbuild
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ntoskrnl-generic.…
==============================================================================
--- trunk/reactos/ntoskrnl/ntoskrnl-generic.rbuild [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/ntoskrnl-generic.rbuild [iso-8859-1] Tue Jun 30 12:55:18 2009
@@ -367,6 +367,7 @@
<file>init.c</file>
<file>iosup.c</file>
<file>mdlsup.c</file>
+ <file>ncache.c</file>
<file>pool.c</file>
<file>procsup.c</file>
<file>syspte.c</file>
@@ -380,7 +381,6 @@
<file>mmsup.c</file>
<file>mminit.c</file>
<file>mpw.c</file>
- <file>ncache.c</file>
<file>npool.c</file>
<file>pagefile.c</file>
<file>pageop.c</file>