mirror of
https://github.com/reactos/reactos.git
synced 2025-01-03 21:09:19 +00:00
- 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:
parent
bd27f08336
commit
f91f8ec7cf
3 changed files with 215 additions and 129 deletions
214
reactos/ntoskrnl/mm/ARM3/ncache.c
Normal file
214
reactos/ntoskrnl/mm/ARM3/ncache.c
Normal 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 */
|
|
@ -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 */
|
|
|
@ -367,6 +367,7 @@
|
||||||
<file>init.c</file>
|
<file>init.c</file>
|
||||||
<file>iosup.c</file>
|
<file>iosup.c</file>
|
||||||
<file>mdlsup.c</file>
|
<file>mdlsup.c</file>
|
||||||
|
<file>ncache.c</file>
|
||||||
<file>pool.c</file>
|
<file>pool.c</file>
|
||||||
<file>procsup.c</file>
|
<file>procsup.c</file>
|
||||||
<file>syspte.c</file>
|
<file>syspte.c</file>
|
||||||
|
@ -380,7 +381,6 @@
|
||||||
<file>mmsup.c</file>
|
<file>mmsup.c</file>
|
||||||
<file>mminit.c</file>
|
<file>mminit.c</file>
|
||||||
<file>mpw.c</file>
|
<file>mpw.c</file>
|
||||||
<file>ncache.c</file>
|
|
||||||
<file>npool.c</file>
|
<file>npool.c</file>
|
||||||
<file>pagefile.c</file>
|
<file>pagefile.c</file>
|
||||||
<file>pageop.c</file>
|
<file>pageop.c</file>
|
||||||
|
|
Loading…
Reference in a new issue