- 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.


svn path=/trunk/; revision=41708
This commit is contained in:
ReactOS Portable Systems Group 2009-06-30 08:55:18 +00:00
parent bd27f08336
commit f91f8ec7cf
3 changed files with 215 additions and 129 deletions

View file

@ -0,0 +1,214 @@
/*
* 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 *******************************************************************/
#include <ntoskrnl.h>
#define NDEBUG
#include <debug.h>
#line 15 "ARM³::NCACHE"
#define MODULE_INVOLVED_IN_ARM3
#include "../ARM3/miarm.h"
/* GLOBALS ********************************************************************/
/*
* @implemented
*/
PVOID
NTAPI
MmAllocateNonCachedMemory(IN ULONG NumberOfBytes)
{
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,
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;
}
/*
* @implemented
*/
VOID
NTAPI
MmFreeNonCachedMemory(IN PVOID BaseAddress,
IN ULONG NumberOfBytes)
{
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 */

View file

@ -1,128 +0,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 */

View file

@ -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>