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?p... ============================================================================== --- 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@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=41... ============================================================================== --- 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@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.r... ============================================================================== --- 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>