mirror of
https://github.com/ApfelTeeSaft/reactos.git
synced 2026-08-29 04:13:32 +00:00
indent using astyle v1.15.3: astyle --style=ansi -c -s3 -S --convert-tabs %1
svn path=/trunk/; revision=9077
This commit is contained in:
+553
-553
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,4 @@
|
||||
/* $Id: aspace.c,v 1.16 2004/03/04 00:07:01 navaraf Exp $
|
||||
/* $Id: aspace.c,v 1.17 2004/04/10 22:35:25 gdalsnes Exp $
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
@@ -26,30 +26,30 @@ STATIC MADDRESS_SPACE KernelAddressSpace;
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
VOID
|
||||
VOID
|
||||
MmLockAddressSpace(PMADDRESS_SPACE AddressSpace)
|
||||
{
|
||||
/*
|
||||
* Don't bother with locking if we are the first thread.
|
||||
*/
|
||||
if (KeGetCurrentThread() == NULL)
|
||||
{
|
||||
/*
|
||||
* Don't bother with locking if we are the first thread.
|
||||
*/
|
||||
if (KeGetCurrentThread() == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
ExAcquireFastMutex(&AddressSpace->Lock);
|
||||
}
|
||||
ExAcquireFastMutex(&AddressSpace->Lock);
|
||||
}
|
||||
|
||||
VOID
|
||||
VOID
|
||||
MmUnlockAddressSpace(PMADDRESS_SPACE AddressSpace)
|
||||
{
|
||||
/*
|
||||
* Don't bother locking if we are the first thread.
|
||||
*/
|
||||
if (KeGetCurrentThread() == NULL)
|
||||
{
|
||||
/*
|
||||
* Don't bother locking if we are the first thread.
|
||||
*/
|
||||
if (KeGetCurrentThread() == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
ExReleaseFastMutex(&AddressSpace->Lock);
|
||||
}
|
||||
ExReleaseFastMutex(&AddressSpace->Lock);
|
||||
}
|
||||
|
||||
VOID INIT_FUNCTION
|
||||
@@ -68,44 +68,44 @@ PMADDRESS_SPACE MmGetKernelAddressSpace(VOID)
|
||||
return(&KernelAddressSpace);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTSTATUS
|
||||
MmInitializeAddressSpace(PEPROCESS Process,
|
||||
PMADDRESS_SPACE AddressSpace)
|
||||
PMADDRESS_SPACE AddressSpace)
|
||||
{
|
||||
InitializeListHead(&AddressSpace->MAreaListHead);
|
||||
ExInitializeFastMutex(&AddressSpace->Lock);
|
||||
if (Process != NULL)
|
||||
{
|
||||
AddressSpace->LowestAddress = MM_LOWEST_USER_ADDRESS;
|
||||
}
|
||||
{
|
||||
AddressSpace->LowestAddress = MM_LOWEST_USER_ADDRESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
AddressSpace->LowestAddress = KERNEL_BASE;
|
||||
}
|
||||
{
|
||||
AddressSpace->LowestAddress = KERNEL_BASE;
|
||||
}
|
||||
AddressSpace->Process = Process;
|
||||
if (Process != NULL)
|
||||
{
|
||||
AddressSpace->PageTableRefCountTable =
|
||||
ExAllocatePoolWithTag(NonPagedPool, 768 * sizeof(USHORT),
|
||||
TAG_PTRC);
|
||||
RtlZeroMemory(AddressSpace->PageTableRefCountTable, 768 * sizeof(USHORT));
|
||||
AddressSpace->PageTableRefCountTableSize = 768;
|
||||
}
|
||||
{
|
||||
AddressSpace->PageTableRefCountTable =
|
||||
ExAllocatePoolWithTag(NonPagedPool, 768 * sizeof(USHORT),
|
||||
TAG_PTRC);
|
||||
RtlZeroMemory(AddressSpace->PageTableRefCountTable, 768 * sizeof(USHORT));
|
||||
AddressSpace->PageTableRefCountTableSize = 768;
|
||||
}
|
||||
else
|
||||
{
|
||||
AddressSpace->PageTableRefCountTable = NULL;
|
||||
AddressSpace->PageTableRefCountTableSize = 0;
|
||||
}
|
||||
{
|
||||
AddressSpace->PageTableRefCountTable = NULL;
|
||||
AddressSpace->PageTableRefCountTableSize = 0;
|
||||
}
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTSTATUS
|
||||
MmDestroyAddressSpace(PMADDRESS_SPACE AddressSpace)
|
||||
{
|
||||
if (AddressSpace->PageTableRefCountTable != NULL)
|
||||
{
|
||||
if (AddressSpace->PageTableRefCountTable != NULL)
|
||||
{
|
||||
ExFreePool(AddressSpace->PageTableRefCountTable);
|
||||
}
|
||||
}
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
+278
-260
@@ -16,7 +16,7 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
/* $Id: balance.c,v 1.26 2004/03/05 11:31:59 hbirr Exp $
|
||||
/* $Id: balance.c,v 1.27 2004/04/10 22:35:25 gdalsnes Exp $
|
||||
*
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: ntoskrnl/mm/balance.c
|
||||
@@ -39,17 +39,19 @@
|
||||
|
||||
typedef struct _MM_MEMORY_CONSUMER
|
||||
{
|
||||
ULONG PagesUsed;
|
||||
ULONG PagesTarget;
|
||||
NTSTATUS (*Trim)(ULONG Target, ULONG Priority, PULONG NrFreed);
|
||||
} MM_MEMORY_CONSUMER, *PMM_MEMORY_CONSUMER;
|
||||
ULONG PagesUsed;
|
||||
ULONG PagesTarget;
|
||||
NTSTATUS (*Trim)(ULONG Target, ULONG Priority, PULONG NrFreed);
|
||||
}
|
||||
MM_MEMORY_CONSUMER, *PMM_MEMORY_CONSUMER;
|
||||
|
||||
typedef struct _MM_ALLOCATION_REQUEST
|
||||
{
|
||||
PHYSICAL_ADDRESS Page;
|
||||
LIST_ENTRY ListEntry;
|
||||
KEVENT Event;
|
||||
} MM_ALLOCATION_REQUEST, *PMM_ALLOCATION_REQUEST;
|
||||
PHYSICAL_ADDRESS Page;
|
||||
LIST_ENTRY ListEntry;
|
||||
KEVENT Event;
|
||||
}
|
||||
MM_ALLOCATION_REQUEST, *PMM_ALLOCATION_REQUEST;
|
||||
|
||||
/* GLOBALS ******************************************************************/
|
||||
|
||||
@@ -72,381 +74,397 @@ static LONG MiBalancerWork = 0;
|
||||
|
||||
VOID MmPrintMemoryStatistic(VOID)
|
||||
{
|
||||
DbgPrint("MC_CACHE %d, MC_USER %d, MC_PPOOL %d, MC_NPPOOL %d, MiNrAvailablePages %d\n",
|
||||
MiMemoryConsumers[MC_CACHE].PagesUsed, MiMemoryConsumers[MC_USER].PagesUsed,
|
||||
MiMemoryConsumers[MC_PPOOL].PagesUsed, MiMemoryConsumers[MC_NPPOOL].PagesUsed,
|
||||
MiNrAvailablePages);
|
||||
DbgPrint("MC_CACHE %d, MC_USER %d, MC_PPOOL %d, MC_NPPOOL %d, MiNrAvailablePages %d\n",
|
||||
MiMemoryConsumers[MC_CACHE].PagesUsed, MiMemoryConsumers[MC_USER].PagesUsed,
|
||||
MiMemoryConsumers[MC_PPOOL].PagesUsed, MiMemoryConsumers[MC_NPPOOL].PagesUsed,
|
||||
MiNrAvailablePages);
|
||||
}
|
||||
|
||||
VOID INIT_FUNCTION
|
||||
MmInitializeBalancer(ULONG NrAvailablePages, ULONG NrSystemPages)
|
||||
{
|
||||
memset(MiMemoryConsumers, 0, sizeof(MiMemoryConsumers));
|
||||
InitializeListHead(&AllocationListHead);
|
||||
KeInitializeSpinLock(&AllocationListLock);
|
||||
memset(MiMemoryConsumers, 0, sizeof(MiMemoryConsumers));
|
||||
InitializeListHead(&AllocationListHead);
|
||||
KeInitializeSpinLock(&AllocationListLock);
|
||||
|
||||
MiNrAvailablePages = MiNrTotalPages = NrAvailablePages;
|
||||
MiNrAvailablePages = MiNrTotalPages = NrAvailablePages;
|
||||
|
||||
/* Set up targets. */
|
||||
MiMinimumAvailablePages = 64;
|
||||
MiMemoryConsumers[MC_CACHE].PagesTarget = NrAvailablePages / 2;
|
||||
MiMemoryConsumers[MC_USER].PagesTarget =
|
||||
NrAvailablePages - MiMinimumAvailablePages;
|
||||
MiMemoryConsumers[MC_PPOOL].PagesTarget = NrAvailablePages / 2;
|
||||
MiMemoryConsumers[MC_NPPOOL].PagesTarget = 0xFFFFFFFF;
|
||||
MiMemoryConsumers[MC_NPPOOL].PagesUsed = NrSystemPages;
|
||||
/* Set up targets. */
|
||||
MiMinimumAvailablePages = 64;
|
||||
MiMemoryConsumers[MC_CACHE].PagesTarget = NrAvailablePages / 2;
|
||||
MiMemoryConsumers[MC_USER].PagesTarget =
|
||||
NrAvailablePages - MiMinimumAvailablePages;
|
||||
MiMemoryConsumers[MC_PPOOL].PagesTarget = NrAvailablePages / 2;
|
||||
MiMemoryConsumers[MC_NPPOOL].PagesTarget = 0xFFFFFFFF;
|
||||
MiMemoryConsumers[MC_NPPOOL].PagesUsed = NrSystemPages;
|
||||
}
|
||||
|
||||
VOID INIT_FUNCTION
|
||||
MmInitializeMemoryConsumer(ULONG Consumer,
|
||||
NTSTATUS (*Trim)(ULONG Target, ULONG Priority,
|
||||
PULONG NrFreed))
|
||||
MmInitializeMemoryConsumer(ULONG Consumer,
|
||||
NTSTATUS (*Trim)(ULONG Target, ULONG Priority,
|
||||
PULONG NrFreed))
|
||||
{
|
||||
MiMemoryConsumers[Consumer].Trim = Trim;
|
||||
MiMemoryConsumers[Consumer].Trim = Trim;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
MmReleasePageMemoryConsumer(ULONG Consumer, PHYSICAL_ADDRESS Page)
|
||||
{
|
||||
PMM_ALLOCATION_REQUEST Request;
|
||||
PLIST_ENTRY Entry;
|
||||
KIRQL oldIrql;
|
||||
ULONG OldAvailable;
|
||||
PMM_ALLOCATION_REQUEST Request;
|
||||
PLIST_ENTRY Entry;
|
||||
KIRQL oldIrql;
|
||||
ULONG OldAvailable;
|
||||
|
||||
#if defined(__GNUC__)
|
||||
if (Page.QuadPart == 0LL)
|
||||
|
||||
if (Page.QuadPart == 0LL)
|
||||
#else
|
||||
if (Page.QuadPart == 0)
|
||||
|
||||
if (Page.QuadPart == 0)
|
||||
#endif
|
||||
{
|
||||
|
||||
{
|
||||
DPRINT1("Tried to release page zero.\n");
|
||||
KEBUGCHECK(0);
|
||||
}
|
||||
}
|
||||
|
||||
KeAcquireSpinLock(&AllocationListLock, &oldIrql);
|
||||
if (MmGetReferenceCountPage(Page) == 1)
|
||||
{
|
||||
KeAcquireSpinLock(&AllocationListLock, &oldIrql);
|
||||
if (MmGetReferenceCountPage(Page) == 1)
|
||||
{
|
||||
InterlockedDecrement((LONG *)&MiMemoryConsumers[Consumer].PagesUsed);
|
||||
OldAvailable = InterlockedIncrement((LONG *)&MiNrAvailablePages);
|
||||
if (IsListEmpty(&AllocationListHead) || OldAvailable + 1 < MiMinimumAvailablePages)
|
||||
{
|
||||
KeReleaseSpinLock(&AllocationListLock, oldIrql);
|
||||
MmDereferencePage(Page);
|
||||
}
|
||||
{
|
||||
KeReleaseSpinLock(&AllocationListLock, oldIrql);
|
||||
MmDereferencePage(Page);
|
||||
}
|
||||
else
|
||||
{
|
||||
Entry = RemoveHeadList(&AllocationListHead);
|
||||
Request = CONTAINING_RECORD(Entry, MM_ALLOCATION_REQUEST, ListEntry);
|
||||
KeReleaseSpinLock(&AllocationListLock, oldIrql);
|
||||
Request->Page = Page;
|
||||
KeSetEvent(&Request->Event, IO_NO_INCREMENT, FALSE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
Entry = RemoveHeadList(&AllocationListHead);
|
||||
Request = CONTAINING_RECORD(Entry, MM_ALLOCATION_REQUEST, ListEntry);
|
||||
KeReleaseSpinLock(&AllocationListLock, oldIrql);
|
||||
Request->Page = Page;
|
||||
KeSetEvent(&Request->Event, IO_NO_INCREMENT, FALSE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
KeReleaseSpinLock(&AllocationListLock, oldIrql);
|
||||
MmDereferencePage(Page);
|
||||
}
|
||||
}
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
VOID
|
||||
MiTrimMemoryConsumer(ULONG Consumer)
|
||||
{
|
||||
LONG Target;
|
||||
ULONG NrFreedPages;
|
||||
LONG Target;
|
||||
ULONG NrFreedPages;
|
||||
|
||||
Target = MiMemoryConsumers[Consumer].PagesUsed -
|
||||
MiMemoryConsumers[Consumer].PagesTarget;
|
||||
if (Target < 1)
|
||||
{
|
||||
Target = MiMemoryConsumers[Consumer].PagesUsed -
|
||||
MiMemoryConsumers[Consumer].PagesTarget;
|
||||
if (Target < 1)
|
||||
{
|
||||
Target = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (MiMemoryConsumers[Consumer].Trim != NULL)
|
||||
{
|
||||
if (MiMemoryConsumers[Consumer].Trim != NULL)
|
||||
{
|
||||
MiMemoryConsumers[Consumer].Trim(Target, 0, &NrFreedPages);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
MmRebalanceMemoryConsumers(VOID)
|
||||
{
|
||||
LONG Target;
|
||||
ULONG i;
|
||||
ULONG NrFreedPages;
|
||||
NTSTATUS Status;
|
||||
LONG Target;
|
||||
ULONG i;
|
||||
ULONG NrFreedPages;
|
||||
NTSTATUS Status;
|
||||
|
||||
Target = (MiMinimumAvailablePages - MiNrAvailablePages) + MiPagesRequired;
|
||||
Target = max(Target, (LONG) MiMinimumPagesPerRun);
|
||||
Target = (MiMinimumAvailablePages - MiNrAvailablePages) + MiPagesRequired;
|
||||
Target = max(Target, (LONG) MiMinimumPagesPerRun);
|
||||
|
||||
for (i = 0; i < MC_MAXIMUM && Target > 0; i++)
|
||||
{
|
||||
for (i = 0; i < MC_MAXIMUM && Target > 0; i++)
|
||||
{
|
||||
if (MiMemoryConsumers[i].Trim != NULL)
|
||||
{
|
||||
Status = MiMemoryConsumers[i].Trim(Target, 0, &NrFreedPages);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
KEBUGCHECK(0);
|
||||
}
|
||||
Target = Target - NrFreedPages;
|
||||
}
|
||||
}
|
||||
{
|
||||
Status = MiMemoryConsumers[i].Trim(Target, 0, &NrFreedPages);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
KEBUGCHECK(0);
|
||||
}
|
||||
Target = Target - NrFreedPages;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static BOOLEAN
|
||||
MiIsBalancerThread(VOID)
|
||||
{
|
||||
return MiBalancerThreadHandle != NULL &&
|
||||
PsGetCurrentThread() == MiBalancerThreadId.UniqueThread;
|
||||
return MiBalancerThreadHandle != NULL &&
|
||||
PsGetCurrentThread() == MiBalancerThreadId.UniqueThread;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
MmRequestPageMemoryConsumer(ULONG Consumer, BOOLEAN CanWait,
|
||||
PHYSICAL_ADDRESS* AllocatedPage)
|
||||
MmRequestPageMemoryConsumer(ULONG Consumer, BOOLEAN CanWait,
|
||||
PHYSICAL_ADDRESS* AllocatedPage)
|
||||
{
|
||||
ULONG OldUsed;
|
||||
ULONG OldAvailable;
|
||||
PHYSICAL_ADDRESS Page;
|
||||
KIRQL oldIrql;
|
||||
|
||||
/*
|
||||
* Make sure we don't exceed our individual target.
|
||||
*/
|
||||
OldUsed = InterlockedIncrement((LONG *)&MiMemoryConsumers[Consumer].PagesUsed);
|
||||
if (OldUsed >= (MiMemoryConsumers[Consumer].PagesTarget - 1) &&
|
||||
!MiIsBalancerThread())
|
||||
{
|
||||
if (!CanWait)
|
||||
{
|
||||
InterlockedDecrement((LONG *)&MiMemoryConsumers[Consumer].PagesUsed);
|
||||
return(STATUS_NO_MEMORY);
|
||||
}
|
||||
MiTrimMemoryConsumer(Consumer);
|
||||
}
|
||||
ULONG OldUsed;
|
||||
ULONG OldAvailable;
|
||||
PHYSICAL_ADDRESS Page;
|
||||
KIRQL oldIrql;
|
||||
|
||||
OldAvailable = InterlockedDecrement((LONG *)&MiNrAvailablePages);
|
||||
/*
|
||||
* Allocate always memory for the non paged pool and for the pager thread.
|
||||
*/
|
||||
if (Consumer == MC_NPPOOL || MiIsBalancerThread())
|
||||
{
|
||||
/*
|
||||
* Make sure we don't exceed our individual target.
|
||||
*/
|
||||
OldUsed = InterlockedIncrement((LONG *)&MiMemoryConsumers[Consumer].PagesUsed);
|
||||
if (OldUsed >= (MiMemoryConsumers[Consumer].PagesTarget - 1) &&
|
||||
!MiIsBalancerThread())
|
||||
{
|
||||
if (!CanWait)
|
||||
{
|
||||
InterlockedDecrement((LONG *)&MiMemoryConsumers[Consumer].PagesUsed);
|
||||
return(STATUS_NO_MEMORY);
|
||||
}
|
||||
MiTrimMemoryConsumer(Consumer);
|
||||
}
|
||||
|
||||
OldAvailable = InterlockedDecrement((LONG *)&MiNrAvailablePages);
|
||||
/*
|
||||
* Allocate always memory for the non paged pool and for the pager thread.
|
||||
*/
|
||||
if (Consumer == MC_NPPOOL || MiIsBalancerThread())
|
||||
{
|
||||
Page = MmAllocPage(Consumer, 0);
|
||||
#if defined(__GNUC__)
|
||||
|
||||
if (Page.QuadPart == 0LL)
|
||||
#else
|
||||
|
||||
if (Page.QuadPart == 0)
|
||||
#endif
|
||||
{
|
||||
KEBUGCHECK(0);
|
||||
}
|
||||
|
||||
{
|
||||
KEBUGCHECK(0);
|
||||
}
|
||||
*AllocatedPage = Page;
|
||||
if (OldAvailable < MiMinimumAvailablePages &&
|
||||
MiBalancerThreadHandle != NULL)
|
||||
{
|
||||
KeSetEvent(&MiBalancerEvent, IO_NO_INCREMENT, FALSE);
|
||||
}
|
||||
MiBalancerThreadHandle != NULL)
|
||||
{
|
||||
KeSetEvent(&MiBalancerEvent, IO_NO_INCREMENT, FALSE);
|
||||
}
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure we don't exceed global targets.
|
||||
*/
|
||||
if (OldAvailable < MiMinimumAvailablePages)
|
||||
{
|
||||
/*
|
||||
* Make sure we don't exceed global targets.
|
||||
*/
|
||||
if (OldAvailable < MiMinimumAvailablePages)
|
||||
{
|
||||
MM_ALLOCATION_REQUEST Request;
|
||||
|
||||
if (!CanWait)
|
||||
{
|
||||
InterlockedIncrement((LONG *)&MiNrAvailablePages);
|
||||
InterlockedDecrement((LONG *)&MiMemoryConsumers[Consumer].PagesUsed);
|
||||
return(STATUS_NO_MEMORY);
|
||||
}
|
||||
{
|
||||
InterlockedIncrement((LONG *)&MiNrAvailablePages);
|
||||
InterlockedDecrement((LONG *)&MiMemoryConsumers[Consumer].PagesUsed);
|
||||
return(STATUS_NO_MEMORY);
|
||||
}
|
||||
|
||||
/* Insert an allocation request. */
|
||||
#if defined(__GNUC__)
|
||||
Request.Page.QuadPart = 0LL;
|
||||
#else
|
||||
|
||||
Request.Page.QuadPart = 0;
|
||||
#endif
|
||||
|
||||
KeInitializeEvent(&Request.Event, NotificationEvent, FALSE);
|
||||
InterlockedIncrement((LONG *)&MiPagesRequired);
|
||||
|
||||
KeAcquireSpinLock(&AllocationListLock, &oldIrql);
|
||||
KeAcquireSpinLock(&AllocationListLock, &oldIrql);
|
||||
|
||||
if (MiBalancerThreadHandle != NULL)
|
||||
{
|
||||
KeSetEvent(&MiBalancerEvent, IO_NO_INCREMENT, FALSE);
|
||||
}
|
||||
{
|
||||
KeSetEvent(&MiBalancerEvent, IO_NO_INCREMENT, FALSE);
|
||||
}
|
||||
InsertTailList(&AllocationListHead, &Request.ListEntry);
|
||||
KeReleaseSpinLock(&AllocationListLock, oldIrql);
|
||||
|
||||
KeWaitForSingleObject(&Request.Event,
|
||||
0,
|
||||
KernelMode,
|
||||
FALSE,
|
||||
NULL);
|
||||
|
||||
0,
|
||||
KernelMode,
|
||||
FALSE,
|
||||
NULL);
|
||||
|
||||
Page = Request.Page;
|
||||
#if defined(__GNUC__)
|
||||
|
||||
if (Page.QuadPart == 0LL)
|
||||
#else
|
||||
|
||||
if (Page.QuadPart == 0)
|
||||
#endif
|
||||
{
|
||||
KEBUGCHECK(0);
|
||||
}
|
||||
|
||||
{
|
||||
KEBUGCHECK(0);
|
||||
}
|
||||
MmTransferOwnershipPage(Page, Consumer);
|
||||
*AllocatedPage = Page;
|
||||
InterlockedDecrement((LONG *)&MiPagesRequired);
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
/*
|
||||
* Actually allocate the page.
|
||||
*/
|
||||
Page = MmAllocPage(Consumer, 0);
|
||||
#if defined(__GNUC__)
|
||||
if (Page.QuadPart == 0LL)
|
||||
#else
|
||||
if (Page.QuadPart == 0)
|
||||
#endif
|
||||
{
|
||||
KEBUGCHECK(0);
|
||||
}
|
||||
*AllocatedPage = Page;
|
||||
}
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
/*
|
||||
* Actually allocate the page.
|
||||
*/
|
||||
Page = MmAllocPage(Consumer, 0);
|
||||
#if defined(__GNUC__)
|
||||
|
||||
if (Page.QuadPart == 0LL)
|
||||
#else
|
||||
|
||||
if (Page.QuadPart == 0)
|
||||
#endif
|
||||
|
||||
{
|
||||
KEBUGCHECK(0);
|
||||
}
|
||||
*AllocatedPage = Page;
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
VOID STDCALL
|
||||
MiBalancerThread(PVOID Unused)
|
||||
{
|
||||
PVOID WaitObjects[2];
|
||||
NTSTATUS Status;
|
||||
ULONG i;
|
||||
ULONG NrFreedPages;
|
||||
ULONG NrPagesUsed;
|
||||
ULONG Target;
|
||||
BOOLEAN ShouldRun;
|
||||
PVOID WaitObjects[2];
|
||||
NTSTATUS Status;
|
||||
ULONG i;
|
||||
ULONG NrFreedPages;
|
||||
ULONG NrPagesUsed;
|
||||
ULONG Target;
|
||||
BOOLEAN ShouldRun;
|
||||
|
||||
|
||||
WaitObjects[0] = &MiBalancerEvent;
|
||||
WaitObjects[1] = &MiBalancerTimer;
|
||||
WaitObjects[0] = &MiBalancerEvent;
|
||||
WaitObjects[1] = &MiBalancerTimer;
|
||||
|
||||
while (1)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
Status = KeWaitForMultipleObjects(2,
|
||||
WaitObjects,
|
||||
WaitAny,
|
||||
Executive,
|
||||
KernelMode,
|
||||
FALSE,
|
||||
NULL,
|
||||
NULL);
|
||||
WaitObjects,
|
||||
WaitAny,
|
||||
Executive,
|
||||
KernelMode,
|
||||
FALSE,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
if (Status == STATUS_SUCCESS)
|
||||
{
|
||||
/* MiBalancerEvent */
|
||||
CHECKPOINT;
|
||||
while (MiNrAvailablePages < MiMinimumAvailablePages + 5)
|
||||
{
|
||||
for (i = 0; i < MC_MAXIMUM; i++)
|
||||
{
|
||||
if (MiMemoryConsumers[i].Trim != NULL)
|
||||
{
|
||||
NrFreedPages = 0;
|
||||
Status = MiMemoryConsumers[i].Trim(MiMinimumPagesPerRun, 0, &NrFreedPages);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
KEBUGCHECK(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
InterlockedExchange(&MiBalancerWork, 0);
|
||||
CHECKPOINT;
|
||||
}
|
||||
{
|
||||
/* MiBalancerEvent */
|
||||
CHECKPOINT;
|
||||
while (MiNrAvailablePages < MiMinimumAvailablePages + 5)
|
||||
{
|
||||
for (i = 0; i < MC_MAXIMUM; i++)
|
||||
{
|
||||
if (MiMemoryConsumers[i].Trim != NULL)
|
||||
{
|
||||
NrFreedPages = 0;
|
||||
Status = MiMemoryConsumers[i].Trim(MiMinimumPagesPerRun, 0, &NrFreedPages);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
KEBUGCHECK(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
InterlockedExchange(&MiBalancerWork, 0);
|
||||
CHECKPOINT;
|
||||
}
|
||||
else if (Status == STATUS_SUCCESS + 1)
|
||||
{
|
||||
/* MiBalancerTimer */
|
||||
ShouldRun = MiNrAvailablePages < MiMinimumAvailablePages + 5 ? TRUE : FALSE;
|
||||
for (i = 0; i < MC_MAXIMUM; i++)
|
||||
{
|
||||
if (MiMemoryConsumers[i].Trim != NULL)
|
||||
{
|
||||
NrPagesUsed = MiMemoryConsumers[i].PagesUsed;
|
||||
if (NrPagesUsed > MiMemoryConsumers[i].PagesTarget || ShouldRun)
|
||||
{
|
||||
if (NrPagesUsed > MiMemoryConsumers[i].PagesTarget)
|
||||
{
|
||||
Target = max (NrPagesUsed - MiMemoryConsumers[i].PagesTarget,
|
||||
MiMinimumPagesPerRun);
|
||||
}
|
||||
else
|
||||
{
|
||||
Target = MiMinimumPagesPerRun;
|
||||
}
|
||||
NrFreedPages = 0;
|
||||
Status = MiMemoryConsumers[i].Trim(Target, 0, &NrFreedPages);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
KEBUGCHECK(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
/* MiBalancerTimer */
|
||||
ShouldRun = MiNrAvailablePages < MiMinimumAvailablePages + 5 ? TRUE : FALSE;
|
||||
for (i = 0; i < MC_MAXIMUM; i++)
|
||||
{
|
||||
if (MiMemoryConsumers[i].Trim != NULL)
|
||||
{
|
||||
NrPagesUsed = MiMemoryConsumers[i].PagesUsed;
|
||||
if (NrPagesUsed > MiMemoryConsumers[i].PagesTarget || ShouldRun)
|
||||
{
|
||||
if (NrPagesUsed > MiMemoryConsumers[i].PagesTarget)
|
||||
{
|
||||
Target = max (NrPagesUsed - MiMemoryConsumers[i].PagesTarget,
|
||||
MiMinimumPagesPerRun);
|
||||
}
|
||||
else
|
||||
{
|
||||
Target = MiMinimumPagesPerRun;
|
||||
}
|
||||
NrFreedPages = 0;
|
||||
Status = MiMemoryConsumers[i].Trim(Target, 0, &NrFreedPages);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
KEBUGCHECK(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINT1("KeWaitForMultipleObjects failt, status = %x\n", Status);
|
||||
KEBUGCHECK(0);
|
||||
}
|
||||
}
|
||||
{
|
||||
DPRINT1("KeWaitForMultipleObjects failt, status = %x\n", Status);
|
||||
KEBUGCHECK(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VOID INIT_FUNCTION
|
||||
MiInitBalancerThread(VOID)
|
||||
{
|
||||
KPRIORITY Priority;
|
||||
NTSTATUS Status;
|
||||
KPRIORITY Priority;
|
||||
NTSTATUS Status;
|
||||
#if !defined(__GNUC__)
|
||||
LARGE_INTEGER dummyJunkNeeded;
|
||||
dummyJunkNeeded.QuadPart = -20000000; /* 2 sec */;
|
||||
|
||||
LARGE_INTEGER dummyJunkNeeded;
|
||||
dummyJunkNeeded.QuadPart = -20000000; /* 2 sec */
|
||||
;
|
||||
#endif
|
||||
|
||||
CHECKPOINT;
|
||||
CHECKPOINT;
|
||||
|
||||
KeInitializeEvent(&MiBalancerEvent, SynchronizationEvent, FALSE);
|
||||
KeInitializeTimerEx(&MiBalancerTimer, SynchronizationTimer);
|
||||
KeSetTimerEx(&MiBalancerTimer,
|
||||
KeInitializeEvent(&MiBalancerEvent, SynchronizationEvent, FALSE);
|
||||
KeInitializeTimerEx(&MiBalancerTimer, SynchronizationTimer);
|
||||
KeSetTimerEx(&MiBalancerTimer,
|
||||
#if defined(__GNUC__)
|
||||
(LARGE_INTEGER)(LONGLONG)-20000000LL, /* 2 sec */
|
||||
(LARGE_INTEGER)(LONGLONG)-20000000LL, /* 2 sec */
|
||||
#else
|
||||
dummyJunkNeeded,
|
||||
dummyJunkNeeded,
|
||||
#endif
|
||||
2000, /* 2 sec */
|
||||
NULL);
|
||||
2000, /* 2 sec */
|
||||
NULL);
|
||||
|
||||
Status = PsCreateSystemThread(&MiBalancerThreadHandle,
|
||||
THREAD_ALL_ACCESS,
|
||||
NULL,
|
||||
NULL,
|
||||
&MiBalancerThreadId,
|
||||
(PKSTART_ROUTINE) MiBalancerThread,
|
||||
NULL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
Status = PsCreateSystemThread(&MiBalancerThreadHandle,
|
||||
THREAD_ALL_ACCESS,
|
||||
NULL,
|
||||
NULL,
|
||||
&MiBalancerThreadId,
|
||||
(PKSTART_ROUTINE) MiBalancerThread,
|
||||
NULL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
KEBUGCHECK(0);
|
||||
}
|
||||
|
||||
Priority = LOW_REALTIME_PRIORITY + 1;
|
||||
NtSetInformationThread(MiBalancerThreadHandle,
|
||||
ThreadPriority,
|
||||
&Priority,
|
||||
sizeof(Priority));
|
||||
|
||||
}
|
||||
|
||||
Priority = LOW_REALTIME_PRIORITY + 1;
|
||||
NtSetInformationThread(MiBalancerThreadHandle,
|
||||
ThreadPriority,
|
||||
&Priority,
|
||||
sizeof(Priority));
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
+152
-148
@@ -1,4 +1,4 @@
|
||||
/* $Id: cont.c,v 1.30 2003/12/31 05:33:03 jfilby Exp $
|
||||
/* $Id: cont.c,v 1.31 2004/04/10 22:35:25 gdalsnes Exp $
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
@@ -20,24 +20,24 @@
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
VOID STATIC
|
||||
MmFreeContinuousPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address,
|
||||
PHYSICAL_ADDRESS PhysAddr, SWAPENTRY SwapEntry,
|
||||
BOOLEAN Dirty)
|
||||
MmFreeContinuousPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address,
|
||||
PHYSICAL_ADDRESS PhysAddr, SWAPENTRY SwapEntry,
|
||||
BOOLEAN Dirty)
|
||||
{
|
||||
assert(SwapEntry == 0);
|
||||
if (PhysAddr.QuadPart != 0)
|
||||
{
|
||||
assert(SwapEntry == 0);
|
||||
if (PhysAddr.QuadPart != 0)
|
||||
{
|
||||
MmReleasePageMemoryConsumer(MC_NPPOOL, PhysAddr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PVOID STDCALL
|
||||
MmAllocateContiguousAlignedMemory(IN ULONG NumberOfBytes,
|
||||
IN PHYSICAL_ADDRESS LowestAcceptableAddress OPTIONAL,
|
||||
IN PHYSICAL_ADDRESS HighestAcceptableAddress,
|
||||
IN PHYSICAL_ADDRESS BoundaryAddressMultiple OPTIONAL,
|
||||
IN MEMORY_CACHING_TYPE CacheType OPTIONAL,
|
||||
IN ULONG Alignment)
|
||||
IN PHYSICAL_ADDRESS LowestAcceptableAddress OPTIONAL,
|
||||
IN PHYSICAL_ADDRESS HighestAcceptableAddress,
|
||||
IN PHYSICAL_ADDRESS BoundaryAddressMultiple OPTIONAL,
|
||||
IN MEMORY_CACHING_TYPE CacheType OPTIONAL,
|
||||
IN ULONG Alignment)
|
||||
{
|
||||
PMEMORY_AREA MArea;
|
||||
NTSTATUS Status;
|
||||
@@ -45,7 +45,7 @@ MmAllocateContiguousAlignedMemory(IN ULONG NumberOfBytes,
|
||||
PHYSICAL_ADDRESS PBase;
|
||||
ULONG Attributes;
|
||||
ULONG i;
|
||||
|
||||
|
||||
Attributes = PAGE_EXECUTE_READWRITE | PAGE_SYSTEM;
|
||||
if (CacheType == MmNonCached || CacheType == MmWriteCombined)
|
||||
{
|
||||
@@ -55,227 +55,231 @@ MmAllocateContiguousAlignedMemory(IN ULONG NumberOfBytes,
|
||||
{
|
||||
Attributes |= PAGE_WRITECOMBINE;
|
||||
}
|
||||
|
||||
|
||||
MmLockAddressSpace(MmGetKernelAddressSpace());
|
||||
Status = MmCreateMemoryArea(NULL,
|
||||
MmGetKernelAddressSpace(),
|
||||
MEMORY_AREA_CONTINUOUS_MEMORY,
|
||||
&BaseAddress,
|
||||
NumberOfBytes,
|
||||
0,
|
||||
&MArea,
|
||||
FALSE,
|
||||
FALSE,
|
||||
BoundaryAddressMultiple);
|
||||
MmGetKernelAddressSpace(),
|
||||
MEMORY_AREA_CONTINUOUS_MEMORY,
|
||||
&BaseAddress,
|
||||
NumberOfBytes,
|
||||
0,
|
||||
&MArea,
|
||||
FALSE,
|
||||
FALSE,
|
||||
BoundaryAddressMultiple);
|
||||
MmUnlockAddressSpace(MmGetKernelAddressSpace());
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return(NULL);
|
||||
}
|
||||
{
|
||||
return(NULL);
|
||||
}
|
||||
DPRINT( "Base = %x\n", BaseAddress );
|
||||
PBase = MmGetContinuousPages(NumberOfBytes,
|
||||
LowestAcceptableAddress,
|
||||
HighestAcceptableAddress,
|
||||
Alignment);
|
||||
LowestAcceptableAddress,
|
||||
HighestAcceptableAddress,
|
||||
Alignment);
|
||||
#if defined(__GNUC__)
|
||||
|
||||
if (PBase.QuadPart == 0LL)
|
||||
#else
|
||||
|
||||
if (PBase.QuadPart == 0)
|
||||
#endif
|
||||
{
|
||||
MmLockAddressSpace(MmGetKernelAddressSpace());
|
||||
MmFreeMemoryArea(MmGetKernelAddressSpace(),
|
||||
BaseAddress,
|
||||
0,
|
||||
NULL,
|
||||
NULL);
|
||||
MmUnlockAddressSpace(MmGetKernelAddressSpace());
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
{
|
||||
MmLockAddressSpace(MmGetKernelAddressSpace());
|
||||
MmFreeMemoryArea(MmGetKernelAddressSpace(),
|
||||
BaseAddress,
|
||||
0,
|
||||
NULL,
|
||||
NULL);
|
||||
MmUnlockAddressSpace(MmGetKernelAddressSpace());
|
||||
return(NULL);
|
||||
}
|
||||
for (i = 0; i < (PAGE_ROUND_UP(NumberOfBytes) / 4096); i++)
|
||||
{
|
||||
{
|
||||
#if !defined(__GNUC__)
|
||||
LARGE_INTEGER dummyJunkNeeded;
|
||||
dummyJunkNeeded.QuadPart = PBase.QuadPart + (i * 4096);
|
||||
LARGE_INTEGER dummyJunkNeeded;
|
||||
dummyJunkNeeded.QuadPart = PBase.QuadPart + (i * 4096);
|
||||
#endif
|
||||
MmCreateVirtualMapping(NULL,
|
||||
(char*)BaseAddress + (i * 4096),
|
||||
Attributes,
|
||||
|
||||
MmCreateVirtualMapping(NULL,
|
||||
(char*)BaseAddress + (i * 4096),
|
||||
Attributes,
|
||||
#if defined(__GNUC__)
|
||||
(LARGE_INTEGER)(PBase.QuadPart + (i * 4096)),
|
||||
(LARGE_INTEGER)(PBase.QuadPart + (i * 4096)),
|
||||
#else
|
||||
dummyJunkNeeded,
|
||||
dummyJunkNeeded,
|
||||
#endif
|
||||
TRUE);
|
||||
}
|
||||
TRUE);
|
||||
}
|
||||
return(BaseAddress);
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* NAME EXPORTED
|
||||
* MmAllocateContiguousMemory@12
|
||||
* NAME EXPORTED
|
||||
* MmAllocateContiguousMemory@12
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Allocates a range of physically contiguous cache aligned
|
||||
* memory from the non-paged pool.
|
||||
*
|
||||
* Allocates a range of physically contiguous cache aligned
|
||||
* memory from the non-paged pool.
|
||||
*
|
||||
* ARGUMENTS
|
||||
* NumberOfBytes
|
||||
* Size of the memory block to allocate;
|
||||
*
|
||||
* HighestAcceptableAddress
|
||||
* Highest address valid for the caller.
|
||||
*
|
||||
* NumberOfBytes
|
||||
* Size of the memory block to allocate;
|
||||
*
|
||||
* HighestAcceptableAddress
|
||||
* Highest address valid for the caller.
|
||||
*
|
||||
* RETURN VALUE
|
||||
* The virtual address of the memory block on success;
|
||||
* NULL on error.
|
||||
* The virtual address of the memory block on success;
|
||||
* NULL on error.
|
||||
*
|
||||
* NOTE
|
||||
* Description taken from include/ddk/mmfuncs.h.
|
||||
* Code taken from ntoskrnl/mm/special.c.
|
||||
* Description taken from include/ddk/mmfuncs.h.
|
||||
* Code taken from ntoskrnl/mm/special.c.
|
||||
*
|
||||
* REVISIONS
|
||||
*
|
||||
* @implemented
|
||||
*/
|
||||
PVOID STDCALL
|
||||
PVOID STDCALL
|
||||
MmAllocateContiguousMemory (IN ULONG NumberOfBytes,
|
||||
IN PHYSICAL_ADDRESS HighestAcceptableAddress)
|
||||
IN PHYSICAL_ADDRESS HighestAcceptableAddress)
|
||||
{
|
||||
PHYSICAL_ADDRESS LowestAcceptableAddress;
|
||||
PHYSICAL_ADDRESS BoundaryAddressMultiple;
|
||||
|
||||
LowestAcceptableAddress.QuadPart = 0;
|
||||
BoundaryAddressMultiple.QuadPart = 0;
|
||||
|
||||
return(MmAllocateContiguousAlignedMemory(NumberOfBytes,
|
||||
LowestAcceptableAddress,
|
||||
HighestAcceptableAddress,
|
||||
BoundaryAddressMultiple,
|
||||
MmCached,
|
||||
PAGE_SIZE));
|
||||
PHYSICAL_ADDRESS LowestAcceptableAddress;
|
||||
PHYSICAL_ADDRESS BoundaryAddressMultiple;
|
||||
|
||||
LowestAcceptableAddress.QuadPart = 0;
|
||||
BoundaryAddressMultiple.QuadPart = 0;
|
||||
|
||||
return(MmAllocateContiguousAlignedMemory(NumberOfBytes,
|
||||
LowestAcceptableAddress,
|
||||
HighestAcceptableAddress,
|
||||
BoundaryAddressMultiple,
|
||||
MmCached,
|
||||
PAGE_SIZE));
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* NAME EXPORTED
|
||||
* MmFreeContiguousMemory@4
|
||||
* NAME EXPORTED
|
||||
* MmFreeContiguousMemory@4
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Releases a range of physically contiguous memory allocated
|
||||
* with MmAllocateContiguousMemory.
|
||||
*
|
||||
* Releases a range of physically contiguous memory allocated
|
||||
* with MmAllocateContiguousMemory.
|
||||
*
|
||||
* ARGUMENTS
|
||||
* BaseAddress
|
||||
* Virtual address of the memory to be freed.
|
||||
* BaseAddress
|
||||
* Virtual address of the memory to be freed.
|
||||
*
|
||||
* RETURN VALUE
|
||||
* None.
|
||||
* None.
|
||||
*
|
||||
* NOTE
|
||||
* Description taken from include/ddk/mmfuncs.h.
|
||||
* Code taken from ntoskrnl/mm/special.c.
|
||||
* Description taken from include/ddk/mmfuncs.h.
|
||||
* Code taken from ntoskrnl/mm/special.c.
|
||||
*
|
||||
* REVISIONS
|
||||
*
|
||||
* @implemented
|
||||
*/
|
||||
VOID STDCALL
|
||||
VOID STDCALL
|
||||
MmFreeContiguousMemory(IN PVOID BaseAddress)
|
||||
{
|
||||
MmLockAddressSpace(MmGetKernelAddressSpace());
|
||||
MmFreeMemoryArea(MmGetKernelAddressSpace(),
|
||||
BaseAddress,
|
||||
0,
|
||||
MmFreeContinuousPage,
|
||||
NULL);
|
||||
BaseAddress,
|
||||
0,
|
||||
MmFreeContinuousPage,
|
||||
NULL);
|
||||
MmUnlockAddressSpace(MmGetKernelAddressSpace());
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* NAME EXPORTED
|
||||
* MmAllocateContiguousMemorySpecifyCache@32
|
||||
* NAME EXPORTED
|
||||
* MmAllocateContiguousMemorySpecifyCache@32
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Allocates a range of physically contiguous memory
|
||||
* with a cache parameter.
|
||||
*
|
||||
* Allocates a range of physically contiguous memory
|
||||
* with a cache parameter.
|
||||
*
|
||||
* ARGUMENTS
|
||||
* NumberOfBytes
|
||||
* Size of the memory block to allocate;
|
||||
*
|
||||
* LowestAcceptableAddress
|
||||
* Lowest address valid for the caller.
|
||||
*
|
||||
* HighestAcceptableAddress
|
||||
* Highest address valid for the caller.
|
||||
*
|
||||
* BoundaryAddressMultiple
|
||||
* Address multiple not to be crossed by allocated buffer (optional).
|
||||
*
|
||||
* CacheType
|
||||
* Type of caching to use.
|
||||
*
|
||||
* NumberOfBytes
|
||||
* Size of the memory block to allocate;
|
||||
*
|
||||
* LowestAcceptableAddress
|
||||
* Lowest address valid for the caller.
|
||||
*
|
||||
* HighestAcceptableAddress
|
||||
* Highest address valid for the caller.
|
||||
*
|
||||
* BoundaryAddressMultiple
|
||||
* Address multiple not to be crossed by allocated buffer (optional).
|
||||
*
|
||||
* CacheType
|
||||
* Type of caching to use.
|
||||
*
|
||||
* RETURN VALUE
|
||||
* The virtual address of the memory block on success;
|
||||
* NULL on error.
|
||||
* The virtual address of the memory block on success;
|
||||
* NULL on error.
|
||||
*
|
||||
* REVISIONS
|
||||
*
|
||||
* @implemented
|
||||
*/
|
||||
PVOID STDCALL
|
||||
PVOID STDCALL
|
||||
MmAllocateContiguousMemorySpecifyCache (IN ULONG NumberOfBytes,
|
||||
IN PHYSICAL_ADDRESS LowestAcceptableAddress,
|
||||
IN PHYSICAL_ADDRESS HighestAcceptableAddress,
|
||||
IN PHYSICAL_ADDRESS BoundaryAddressMultiple OPTIONAL,
|
||||
IN MEMORY_CACHING_TYPE CacheType)
|
||||
IN PHYSICAL_ADDRESS LowestAcceptableAddress,
|
||||
IN PHYSICAL_ADDRESS HighestAcceptableAddress,
|
||||
IN PHYSICAL_ADDRESS BoundaryAddressMultiple OPTIONAL,
|
||||
IN MEMORY_CACHING_TYPE CacheType)
|
||||
{
|
||||
return(MmAllocateContiguousAlignedMemory(NumberOfBytes,
|
||||
LowestAcceptableAddress,
|
||||
HighestAcceptableAddress,
|
||||
BoundaryAddressMultiple,
|
||||
CacheType,
|
||||
PAGE_SIZE));
|
||||
return(MmAllocateContiguousAlignedMemory(NumberOfBytes,
|
||||
LowestAcceptableAddress,
|
||||
HighestAcceptableAddress,
|
||||
BoundaryAddressMultiple,
|
||||
CacheType,
|
||||
PAGE_SIZE));
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* NAME EXPORTED
|
||||
* MmFreeContiguousMemorySpecifyCache@12
|
||||
* NAME EXPORTED
|
||||
* MmFreeContiguousMemorySpecifyCache@12
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Releases a range of physically contiguous memory allocated
|
||||
* with MmAllocateContiguousMemorySpecifyCache.
|
||||
*
|
||||
* Releases a range of physically contiguous memory allocated
|
||||
* with MmAllocateContiguousMemorySpecifyCache.
|
||||
*
|
||||
* ARGUMENTS
|
||||
* BaseAddress
|
||||
* Virtual address of the memory to be freed.
|
||||
* BaseAddress
|
||||
* Virtual address of the memory to be freed.
|
||||
*
|
||||
* NumberOfBytes
|
||||
* Size of the memory block to free.
|
||||
*
|
||||
* CacheType
|
||||
* Type of caching used.
|
||||
*
|
||||
* NumberOfBytes
|
||||
* Size of the memory block to free.
|
||||
*
|
||||
* CacheType
|
||||
* Type of caching used.
|
||||
*
|
||||
* RETURN VALUE
|
||||
* None.
|
||||
* None.
|
||||
*
|
||||
* REVISIONS
|
||||
*
|
||||
* @implemented
|
||||
*/
|
||||
VOID STDCALL
|
||||
VOID STDCALL
|
||||
MmFreeContiguousMemorySpecifyCache(IN PVOID BaseAddress,
|
||||
IN ULONG NumberOfBytes,
|
||||
IN MEMORY_CACHING_TYPE CacheType)
|
||||
IN ULONG NumberOfBytes,
|
||||
IN MEMORY_CACHING_TYPE CacheType)
|
||||
{
|
||||
MmLockAddressSpace(MmGetKernelAddressSpace());
|
||||
MmFreeMemoryArea(MmGetKernelAddressSpace(),
|
||||
BaseAddress,
|
||||
NumberOfBytes,
|
||||
MmFreeContinuousPage,
|
||||
NULL);
|
||||
BaseAddress,
|
||||
NumberOfBytes,
|
||||
MmFreeContinuousPage,
|
||||
NULL);
|
||||
MmUnlockAddressSpace(MmGetKernelAddressSpace());
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $Id: drvlck.c,v 1.4 2003/07/10 21:05:03 royce Exp $
|
||||
/* $Id: drvlck.c,v 1.5 2004/04/10 22:35:25 gdalsnes Exp $
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
@@ -30,8 +30,8 @@ MmUnlockPagableImageSection(IN PVOID ImageSectionHandle)
|
||||
* MmLockPagableDataSection
|
||||
*/
|
||||
{
|
||||
// MmUnlockMemoryArea((MEMORY_AREA *)ImageSectionHandle);
|
||||
UNIMPLEMENTED;
|
||||
// MmUnlockMemoryArea((MEMORY_AREA *)ImageSectionHandle);
|
||||
UNIMPLEMENTED;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -42,8 +42,8 @@ MmUnlockPagableImageSection(IN PVOID ImageSectionHandle)
|
||||
VOID STDCALL
|
||||
MmLockPagableSectionByHandle(IN PVOID ImageSectionHandle)
|
||||
{
|
||||
// MmLockMemoryArea((MEMORY_AREA *)ImageSectionHandle);
|
||||
UNIMPLEMENTED;
|
||||
// MmLockMemoryArea((MEMORY_AREA *)ImageSectionHandle);
|
||||
UNIMPLEMENTED;
|
||||
}
|
||||
|
||||
|
||||
@@ -51,10 +51,10 @@ MmLockPagableSectionByHandle(IN PVOID ImageSectionHandle)
|
||||
PVOID
|
||||
MmLockPagableCodeSection(IN PVOID AddressWithinSection)
|
||||
{
|
||||
PVOID Handle;
|
||||
Handle = MmOpenMemoryAreaByAddress(NULL,AddressWithinSection);
|
||||
MmLockPagableSectionByHandle(Handle);
|
||||
return(Handle);
|
||||
PVOID Handle;
|
||||
Handle = MmOpenMemoryAreaByAddress(NULL,AddressWithinSection);
|
||||
MmLockPagableSectionByHandle(Handle);
|
||||
return(Handle);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -65,10 +65,10 @@ MmLockPagableCodeSection(IN PVOID AddressWithinSection)
|
||||
PVOID STDCALL
|
||||
MmLockPagableDataSection(IN PVOID AddressWithinSection)
|
||||
{
|
||||
PVOID Handle;
|
||||
Handle = MmOpenMemoryAreaByAddress(NULL,AddressWithinSection);
|
||||
MmLockPagableSectionByHandle(Handle);
|
||||
return(Handle);
|
||||
PVOID Handle;
|
||||
Handle = MmOpenMemoryAreaByAddress(NULL,AddressWithinSection);
|
||||
MmLockPagableSectionByHandle(Handle);
|
||||
return(Handle);
|
||||
}
|
||||
|
||||
|
||||
@@ -77,8 +77,7 @@ MmLockPagableDataSection(IN PVOID AddressWithinSection)
|
||||
*/
|
||||
VOID STDCALL
|
||||
MmUnlockPagableImageSection(IN PVOID ImageSectionHandle)
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
|
||||
/*
|
||||
@@ -86,8 +85,7 @@ MmUnlockPagableImageSection(IN PVOID ImageSectionHandle)
|
||||
*/
|
||||
VOID STDCALL
|
||||
MmPageEntireDriver(IN PVOID AddressWithinSection)
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
|
||||
/*
|
||||
@@ -95,7 +93,6 @@ MmPageEntireDriver(IN PVOID AddressWithinSection)
|
||||
*/
|
||||
VOID STDCALL
|
||||
MmResetDriverPaging(IN PVOID AddressWithinSection)
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
/* EOF */
|
||||
|
||||
+617
-582
File diff suppressed because it is too large
Load Diff
+673
-667
File diff suppressed because it is too large
Load Diff
@@ -28,68 +28,68 @@ extern VOID MmSafeCopyToUserRestart(VOID);
|
||||
|
||||
extern ULONG MmGlobalKernelPageDirectory[1024];
|
||||
|
||||
BOOLEAN
|
||||
BOOLEAN
|
||||
Mmi386MakeKernelPageTableGlobal(PVOID Address);
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
NTSTATUS MmPageFault(ULONG Cs,
|
||||
PULONG Eip,
|
||||
PULONG Eax,
|
||||
ULONG Cr2,
|
||||
ULONG ErrorCode)
|
||||
PULONG Eip,
|
||||
PULONG Eax,
|
||||
ULONG Cr2,
|
||||
ULONG ErrorCode)
|
||||
{
|
||||
KPROCESSOR_MODE Mode;
|
||||
NTSTATUS Status;
|
||||
|
||||
|
||||
DPRINT("MmPageFault(Eip %x, Cr2 %x, ErrorCode %x)\n",
|
||||
Eip, Cr2, ErrorCode);
|
||||
|
||||
Eip, Cr2, ErrorCode);
|
||||
|
||||
if (ErrorCode & 0x4)
|
||||
{
|
||||
Mode = UserMode;
|
||||
}
|
||||
{
|
||||
Mode = UserMode;
|
||||
}
|
||||
else
|
||||
{
|
||||
Mode = KernelMode;
|
||||
}
|
||||
|
||||
if (Mode == KernelMode && Cr2 >= KERNEL_BASE &&
|
||||
Mmi386MakeKernelPageTableGlobal((PVOID)Cr2))
|
||||
{
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
{
|
||||
Mode = KernelMode;
|
||||
}
|
||||
|
||||
if (Mode == KernelMode && Cr2 >= KERNEL_BASE &&
|
||||
Mmi386MakeKernelPageTableGlobal((PVOID)Cr2))
|
||||
{
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
if (ErrorCode & 0x1)
|
||||
{
|
||||
Status = MmAccessFault(Mode, Cr2, FALSE);
|
||||
}
|
||||
{
|
||||
Status = MmAccessFault(Mode, Cr2, FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = MmNotPresentFault(Mode, Cr2, FALSE);
|
||||
}
|
||||
|
||||
{
|
||||
Status = MmNotPresentFault(Mode, Cr2, FALSE);
|
||||
}
|
||||
|
||||
if (KeGetCurrentThread() != NULL &&
|
||||
KeGetCurrentThread()->Alerted[1] != 0 &&
|
||||
Cs != KERNEL_CS)
|
||||
{
|
||||
KiDeliverNormalApc();
|
||||
}
|
||||
KeGetCurrentThread()->Alerted[1] != 0 &&
|
||||
Cs != KERNEL_CS)
|
||||
{
|
||||
KiDeliverNormalApc();
|
||||
}
|
||||
if (!NT_SUCCESS(Status) && (Mode == KernelMode) &&
|
||||
((*Eip) >= (ULONG)MmSafeCopyFromUserUnsafeStart) &&
|
||||
((*Eip) <= (ULONG)MmSafeCopyFromUserRestart))
|
||||
{
|
||||
(*Eip) = (ULONG)MmSafeCopyFromUserRestart;
|
||||
(*Eax) = STATUS_ACCESS_VIOLATION;
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
((*Eip) >= (ULONG)MmSafeCopyFromUserUnsafeStart) &&
|
||||
((*Eip) <= (ULONG)MmSafeCopyFromUserRestart))
|
||||
{
|
||||
(*Eip) = (ULONG)MmSafeCopyFromUserRestart;
|
||||
(*Eax) = STATUS_ACCESS_VIOLATION;
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
if (!NT_SUCCESS(Status) && (Mode == KernelMode) &&
|
||||
((*Eip) >= (ULONG)MmSafeCopyToUserUnsafeStart) &&
|
||||
((*Eip) <= (ULONG)MmSafeCopyToUserRestart))
|
||||
{
|
||||
(*Eip) = (ULONG)MmSafeCopyToUserRestart;
|
||||
(*Eax) = STATUS_ACCESS_VIOLATION;
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
((*Eip) >= (ULONG)MmSafeCopyToUserUnsafeStart) &&
|
||||
((*Eip) <= (ULONG)MmSafeCopyToUserRestart))
|
||||
{
|
||||
(*Eip) = (ULONG)MmSafeCopyToUserRestart;
|
||||
(*Eax) = STATUS_ACCESS_VIOLATION;
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
return(Status);
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
/* $Id: iospace.c,v 1.25 2004/01/09 22:52:30 gvg Exp $
|
||||
/* $Id: iospace.c,v 1.26 2004/04/10 22:35:25 gdalsnes Exp $
|
||||
*
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: ntoskrnl/mm/iospace.c
|
||||
@@ -38,37 +38,37 @@
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
/**********************************************************************
|
||||
* NAME EXPORTED
|
||||
* MmMapIoSpace@16
|
||||
* NAME EXPORTED
|
||||
* MmMapIoSpace@16
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Maps a physical memory range into system space.
|
||||
*
|
||||
* Maps a physical memory range into system space.
|
||||
*
|
||||
* ARGUMENTS
|
||||
* PhysicalAddress
|
||||
* First physical address to map;
|
||||
*
|
||||
* NumberOfBytes
|
||||
* Number of bytes to map;
|
||||
*
|
||||
* CacheEnable
|
||||
* TRUE if the range can be cached.
|
||||
* PhysicalAddress
|
||||
* First physical address to map;
|
||||
*
|
||||
* NumberOfBytes
|
||||
* Number of bytes to map;
|
||||
*
|
||||
* CacheEnable
|
||||
* TRUE if the range can be cached.
|
||||
*
|
||||
* RETURN VALUE
|
||||
* The base virtual address which maps the region.
|
||||
* The base virtual address which maps the region.
|
||||
*
|
||||
* NOTE
|
||||
* Description moved here from include/ddk/mmfuncs.h.
|
||||
* Code taken from ntoskrnl/mm/special.c.
|
||||
* Description moved here from include/ddk/mmfuncs.h.
|
||||
* Code taken from ntoskrnl/mm/special.c.
|
||||
*
|
||||
* REVISIONS
|
||||
*
|
||||
* @implemented
|
||||
*/
|
||||
PVOID STDCALL
|
||||
PVOID STDCALL
|
||||
MmMapIoSpace (IN PHYSICAL_ADDRESS PhysicalAddress,
|
||||
IN ULONG NumberOfBytes,
|
||||
IN BOOLEAN CacheEnable)
|
||||
IN ULONG NumberOfBytes,
|
||||
IN BOOLEAN CacheEnable)
|
||||
{
|
||||
PVOID Result;
|
||||
MEMORY_AREA* marea;
|
||||
@@ -83,110 +83,113 @@ MmMapIoSpace (IN PHYSICAL_ADDRESS PhysicalAddress,
|
||||
MmLockAddressSpace(MmGetKernelAddressSpace());
|
||||
Result = NULL;
|
||||
Status = MmCreateMemoryArea (NULL,
|
||||
MmGetKernelAddressSpace(),
|
||||
MEMORY_AREA_IO_MAPPING,
|
||||
&Result,
|
||||
NumberOfBytes,
|
||||
0,
|
||||
&marea,
|
||||
FALSE,
|
||||
FALSE,
|
||||
BoundaryAddressMultiple);
|
||||
MmGetKernelAddressSpace(),
|
||||
MEMORY_AREA_IO_MAPPING,
|
||||
&Result,
|
||||
NumberOfBytes,
|
||||
0,
|
||||
&marea,
|
||||
FALSE,
|
||||
FALSE,
|
||||
BoundaryAddressMultiple);
|
||||
MmUnlockAddressSpace(MmGetKernelAddressSpace());
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("MmMapIoSpace failed (%lx)\n", Status);
|
||||
return (NULL);
|
||||
}
|
||||
{
|
||||
DPRINT("MmMapIoSpace failed (%lx)\n", Status);
|
||||
return (NULL);
|
||||
}
|
||||
Attributes = PAGE_EXECUTE_READWRITE | PAGE_SYSTEM;
|
||||
if (!CacheEnable)
|
||||
{
|
||||
Attributes |= (PAGE_NOCACHE | PAGE_WRITETHROUGH);
|
||||
}
|
||||
{
|
||||
Attributes |= (PAGE_NOCACHE | PAGE_WRITETHROUGH);
|
||||
}
|
||||
for (i = 0; (i < (PAGE_ROUND_UP(NumberOfBytes) / PAGE_SIZE)); i++)
|
||||
{
|
||||
{
|
||||
#if !defined(__GNUC__)
|
||||
PHYSICAL_ADDRESS dummyJunkNeeded;
|
||||
dummyJunkNeeded.QuadPart = PhysicalAddress.QuadPart + (i * PAGE_SIZE);
|
||||
PHYSICAL_ADDRESS dummyJunkNeeded;
|
||||
dummyJunkNeeded.QuadPart = PhysicalAddress.QuadPart + (i * PAGE_SIZE);
|
||||
#endif
|
||||
Status =
|
||||
MmCreateVirtualMappingForKernel((char*)Result + (i * PAGE_SIZE),
|
||||
Attributes,
|
||||
|
||||
Status =
|
||||
MmCreateVirtualMappingForKernel((char*)Result + (i * PAGE_SIZE),
|
||||
Attributes,
|
||||
#if defined(__GNUC__)
|
||||
(PHYSICAL_ADDRESS)
|
||||
(PhysicalAddress.QuadPart +
|
||||
(i * PAGE_SIZE))
|
||||
(PHYSICAL_ADDRESS)
|
||||
(PhysicalAddress.QuadPart +
|
||||
(i * PAGE_SIZE))
|
||||
#else
|
||||
dummyJunkNeeded
|
||||
dummyJunkNeeded
|
||||
#endif
|
||||
);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DbgPrint("Unable to create virtual mapping\n");
|
||||
KEBUGCHECK(0);
|
||||
}
|
||||
);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DbgPrint("Unable to create virtual mapping\n");
|
||||
KEBUGCHECK(0);
|
||||
}
|
||||
#if defined(__GNUC__)
|
||||
MmMarkPageMapped((PHYSICAL_ADDRESS) (PhysicalAddress.QuadPart +
|
||||
(i * PAGE_SIZE)));
|
||||
MmMarkPageMapped((PHYSICAL_ADDRESS) (PhysicalAddress.QuadPart +
|
||||
(i * PAGE_SIZE)));
|
||||
#else
|
||||
MmMarkPageMapped(dummyJunkNeeded);
|
||||
|
||||
MmMarkPageMapped(dummyJunkNeeded);
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
return ((PVOID)((char*)Result + PhysicalAddress.QuadPart % PAGE_SIZE));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* NAME EXPORTED
|
||||
* MmUnmapIoSpace@8
|
||||
* NAME EXPORTED
|
||||
* MmUnmapIoSpace@8
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Unmaps a physical memory range from system space.
|
||||
*
|
||||
* Unmaps a physical memory range from system space.
|
||||
*
|
||||
* ARGUMENTS
|
||||
* BaseAddress
|
||||
* The base virtual address which maps the region;
|
||||
*
|
||||
* NumberOfBytes
|
||||
* Number of bytes to unmap.
|
||||
* BaseAddress
|
||||
* The base virtual address which maps the region;
|
||||
*
|
||||
* NumberOfBytes
|
||||
* Number of bytes to unmap.
|
||||
*
|
||||
* RETURN VALUE
|
||||
* None.
|
||||
* None.
|
||||
*
|
||||
* NOTE
|
||||
* Code taken from ntoskrnl/mm/special.c.
|
||||
* Code taken from ntoskrnl/mm/special.c.
|
||||
*
|
||||
* REVISIONS
|
||||
*
|
||||
* @implemented
|
||||
*/
|
||||
VOID STDCALL
|
||||
VOID STDCALL
|
||||
MmUnmapIoSpace (IN PVOID BaseAddress,
|
||||
IN ULONG NumberOfBytes)
|
||||
IN ULONG NumberOfBytes)
|
||||
{
|
||||
MmLockAddressSpace(MmGetKernelAddressSpace());
|
||||
MmFreeMemoryArea(MmGetKernelAddressSpace(),
|
||||
(PVOID)(((ULONG)BaseAddress / PAGE_SIZE) * PAGE_SIZE),
|
||||
NumberOfBytes,
|
||||
NULL,
|
||||
NULL);
|
||||
(PVOID)(((ULONG)BaseAddress / PAGE_SIZE) * PAGE_SIZE),
|
||||
NumberOfBytes,
|
||||
NULL,
|
||||
NULL);
|
||||
MmUnlockAddressSpace(MmGetKernelAddressSpace());
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* NAME EXPORTED
|
||||
* MmMapVideoDisplay@16
|
||||
* NAME EXPORTED
|
||||
* MmMapVideoDisplay@16
|
||||
*
|
||||
* @implemented
|
||||
*/
|
||||
PVOID STDCALL
|
||||
MmMapVideoDisplay (IN PHYSICAL_ADDRESS PhysicalAddress,
|
||||
IN ULONG NumberOfBytes,
|
||||
IN MEMORY_CACHING_TYPE CacheType)
|
||||
MmMapVideoDisplay (IN PHYSICAL_ADDRESS PhysicalAddress,
|
||||
IN ULONG NumberOfBytes,
|
||||
IN MEMORY_CACHING_TYPE CacheType)
|
||||
{
|
||||
return MmMapIoSpace (PhysicalAddress, NumberOfBytes, (BOOLEAN)CacheType);
|
||||
return MmMapIoSpace (PhysicalAddress, NumberOfBytes, (BOOLEAN)CacheType);
|
||||
}
|
||||
|
||||
|
||||
@@ -194,10 +197,10 @@ MmMapVideoDisplay (IN PHYSICAL_ADDRESS PhysicalAddress,
|
||||
* @implemented
|
||||
*/
|
||||
VOID STDCALL
|
||||
MmUnmapVideoDisplay (IN PVOID BaseAddress,
|
||||
IN ULONG NumberOfBytes)
|
||||
MmUnmapVideoDisplay (IN PVOID BaseAddress,
|
||||
IN ULONG NumberOfBytes)
|
||||
{
|
||||
MmUnmapIoSpace (BaseAddress, NumberOfBytes);
|
||||
MmUnmapIoSpace (BaseAddress, NumberOfBytes);
|
||||
}
|
||||
|
||||
|
||||
|
||||
+52
-52
@@ -1,4 +1,4 @@
|
||||
/* $Id: kmap.c,v 1.31 2004/01/05 14:28:21 weiden Exp $
|
||||
/* $Id: kmap.c,v 1.32 2004/04/10 22:35:25 gdalsnes Exp $
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
@@ -36,64 +36,64 @@ extern ULONG MiKernelMapLength;
|
||||
|
||||
/* FUNCTIONS ***************************************************************/
|
||||
|
||||
VOID
|
||||
VOID
|
||||
ExUnmapPage(PVOID Addr)
|
||||
{
|
||||
KIRQL oldIrql;
|
||||
ULONG Base = ((char*)Addr - (char*)MiKernelMapStart) / PAGE_SIZE;
|
||||
|
||||
|
||||
DPRINT("ExUnmapPage(Addr %x)\n",Addr);
|
||||
|
||||
|
||||
MmDeleteVirtualMapping(NULL, (PVOID)Addr, FALSE, NULL, NULL);
|
||||
KeAcquireSpinLock(&AllocMapLock, &oldIrql);
|
||||
KeAcquireSpinLock(&AllocMapLock, &oldIrql);
|
||||
RtlClearBits(&AllocMap, Base, 1);
|
||||
AllocMapHint = min(AllocMapHint, Base);
|
||||
KeReleaseSpinLock(&AllocMapLock, oldIrql);
|
||||
}
|
||||
|
||||
PVOID
|
||||
PVOID
|
||||
ExAllocatePage(VOID)
|
||||
{
|
||||
PHYSICAL_ADDRESS PhysPage;
|
||||
NTSTATUS Status;
|
||||
PHYSICAL_ADDRESS PhysPage;
|
||||
NTSTATUS Status;
|
||||
|
||||
Status = MmRequestPageMemoryConsumer(MC_NPPOOL, FALSE, &PhysPage);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
Status = MmRequestPageMemoryConsumer(MC_NPPOOL, FALSE, &PhysPage);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
return(ExAllocatePageWithPhysPage(PhysPage));
|
||||
return(ExAllocatePageWithPhysPage(PhysPage));
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
MiZeroPage(PHYSICAL_ADDRESS PhysPage)
|
||||
{
|
||||
PVOID TempAddress;
|
||||
PVOID TempAddress;
|
||||
|
||||
TempAddress = ExAllocatePageWithPhysPage(PhysPage);
|
||||
if (TempAddress == NULL)
|
||||
{
|
||||
TempAddress = ExAllocatePageWithPhysPage(PhysPage);
|
||||
if (TempAddress == NULL)
|
||||
{
|
||||
return(STATUS_NO_MEMORY);
|
||||
}
|
||||
memset(TempAddress, 0, PAGE_SIZE);
|
||||
ExUnmapPage(TempAddress);
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
memset(TempAddress, 0, PAGE_SIZE);
|
||||
ExUnmapPage(TempAddress);
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
MiCopyFromUserPage(PHYSICAL_ADDRESS DestPhysPage, PVOID SourceAddress)
|
||||
{
|
||||
PVOID TempAddress;
|
||||
PVOID TempAddress;
|
||||
|
||||
TempAddress = ExAllocatePageWithPhysPage(DestPhysPage);
|
||||
if (TempAddress == NULL)
|
||||
{
|
||||
TempAddress = ExAllocatePageWithPhysPage(DestPhysPage);
|
||||
if (TempAddress == NULL)
|
||||
{
|
||||
return(STATUS_NO_MEMORY);
|
||||
}
|
||||
memcpy(TempAddress, SourceAddress, PAGE_SIZE);
|
||||
ExUnmapPage(TempAddress);
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
memcpy(TempAddress, SourceAddress, PAGE_SIZE);
|
||||
ExUnmapPage(TempAddress);
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
PVOID
|
||||
@@ -111,15 +111,15 @@ ExAllocatePageWithPhysPage(PHYSICAL_ADDRESS PhysPage)
|
||||
AllocMapHint = Base + 1;
|
||||
KeReleaseSpinLock(&AllocMapLock, oldlvl);
|
||||
Addr = (char*)MiKernelMapStart + Base * PAGE_SIZE;
|
||||
Status = MmCreateVirtualMapping(NULL,
|
||||
Addr,
|
||||
PAGE_READWRITE | PAGE_SYSTEM,
|
||||
PhysPage,
|
||||
TRUE);
|
||||
Status = MmCreateVirtualMapping(NULL,
|
||||
Addr,
|
||||
PAGE_READWRITE | PAGE_SYSTEM,
|
||||
PhysPage,
|
||||
TRUE);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DbgPrint("Unable to create virtual mapping\n");
|
||||
KEBUGCHECK(0);
|
||||
DbgPrint("Unable to create virtual mapping\n");
|
||||
KEBUGCHECK(0);
|
||||
}
|
||||
return Addr;
|
||||
}
|
||||
@@ -138,22 +138,22 @@ MiInitKernelMap(VOID)
|
||||
VOID
|
||||
MiFreeNonPagedPoolRegion(PVOID Addr, ULONG Count, BOOLEAN Free)
|
||||
{
|
||||
ULONG i;
|
||||
ULONG Base = ((char*)Addr - (char*)MiKernelMapStart) / PAGE_SIZE;
|
||||
KIRQL oldlvl;
|
||||
|
||||
for (i = 0; i < Count; i++)
|
||||
{
|
||||
MmDeleteVirtualMapping(NULL,
|
||||
(char*)Addr + (i * PAGE_SIZE),
|
||||
Free,
|
||||
NULL,
|
||||
NULL);
|
||||
}
|
||||
KeAcquireSpinLock(&AllocMapLock, &oldlvl);
|
||||
RtlClearBits(&AllocMap, Base, Count);
|
||||
AllocMapHint = min(AllocMapHint, Base);
|
||||
KeReleaseSpinLock(&AllocMapLock, oldlvl);
|
||||
ULONG i;
|
||||
ULONG Base = ((char*)Addr - (char*)MiKernelMapStart) / PAGE_SIZE;
|
||||
KIRQL oldlvl;
|
||||
|
||||
for (i = 0; i < Count; i++)
|
||||
{
|
||||
MmDeleteVirtualMapping(NULL,
|
||||
(char*)Addr + (i * PAGE_SIZE),
|
||||
Free,
|
||||
NULL,
|
||||
NULL);
|
||||
}
|
||||
KeAcquireSpinLock(&AllocMapLock, &oldlvl);
|
||||
RtlClearBits(&AllocMap, Base, Count);
|
||||
AllocMapHint = min(AllocMapHint, Base);
|
||||
KeReleaseSpinLock(&AllocMapLock, oldlvl);
|
||||
}
|
||||
|
||||
PVOID
|
||||
|
||||
+352
-348
@@ -45,163 +45,163 @@ VOID MmDumpMemoryAreas(PLIST_ENTRY ListHead)
|
||||
{
|
||||
PLIST_ENTRY current_entry;
|
||||
MEMORY_AREA* current;
|
||||
|
||||
|
||||
DbgPrint("MmDumpMemoryAreas()\n");
|
||||
|
||||
|
||||
current_entry = ListHead->Flink;
|
||||
while (current_entry!=ListHead)
|
||||
{
|
||||
current = CONTAINING_RECORD(current_entry,MEMORY_AREA,Entry);
|
||||
DbgPrint("Base %x Length %x End %x Attributes %x Flink %x\n",
|
||||
current->BaseAddress,current->Length,
|
||||
(char*)current->BaseAddress+current->Length,current->Attributes,
|
||||
current->Entry.Flink);
|
||||
current_entry = current_entry->Flink;
|
||||
}
|
||||
{
|
||||
current = CONTAINING_RECORD(current_entry,MEMORY_AREA,Entry);
|
||||
DbgPrint("Base %x Length %x End %x Attributes %x Flink %x\n",
|
||||
current->BaseAddress,current->Length,
|
||||
(char*)current->BaseAddress+current->Length,current->Attributes,
|
||||
current->Entry.Flink);
|
||||
current_entry = current_entry->Flink;
|
||||
}
|
||||
DbgPrint("Finished MmDumpMemoryAreas()\n");
|
||||
}
|
||||
|
||||
MEMORY_AREA* MmOpenMemoryAreaByAddress(PMADDRESS_SPACE AddressSpace,
|
||||
PVOID Address)
|
||||
PVOID Address)
|
||||
{
|
||||
PLIST_ENTRY current_entry;
|
||||
MEMORY_AREA* current;
|
||||
PLIST_ENTRY previous_entry;
|
||||
|
||||
DPRINT("MmOpenMemoryAreaByAddress(AddressSpace %x, Address %x)\n",
|
||||
AddressSpace, Address);
|
||||
|
||||
AddressSpace, Address);
|
||||
|
||||
previous_entry = &AddressSpace->MAreaListHead;
|
||||
current_entry = AddressSpace->MAreaListHead.Flink;
|
||||
while (current_entry != &AddressSpace->MAreaListHead)
|
||||
{
|
||||
current = CONTAINING_RECORD(current_entry,
|
||||
MEMORY_AREA,
|
||||
Entry);
|
||||
assert(current_entry->Blink->Flink == current_entry);
|
||||
assert(current_entry->Flink->Blink == current_entry);
|
||||
assert(previous_entry->Flink == current_entry);
|
||||
if (current->BaseAddress <= Address &&
|
||||
(PVOID)((char*)current->BaseAddress + current->Length) > Address)
|
||||
{
|
||||
DPRINT("%s() = %x\n",__FUNCTION__,current);
|
||||
return(current);
|
||||
}
|
||||
if (current->BaseAddress > Address)
|
||||
{
|
||||
DPRINT("%s() = NULL\n",__FUNCTION__);
|
||||
return(NULL);
|
||||
}
|
||||
previous_entry = current_entry;
|
||||
current_entry = current_entry->Flink;
|
||||
}
|
||||
{
|
||||
current = CONTAINING_RECORD(current_entry,
|
||||
MEMORY_AREA,
|
||||
Entry);
|
||||
assert(current_entry->Blink->Flink == current_entry);
|
||||
assert(current_entry->Flink->Blink == current_entry);
|
||||
assert(previous_entry->Flink == current_entry);
|
||||
if (current->BaseAddress <= Address &&
|
||||
(PVOID)((char*)current->BaseAddress + current->Length) > Address)
|
||||
{
|
||||
DPRINT("%s() = %x\n",__FUNCTION__,current);
|
||||
return(current);
|
||||
}
|
||||
if (current->BaseAddress > Address)
|
||||
{
|
||||
DPRINT("%s() = NULL\n",__FUNCTION__);
|
||||
return(NULL);
|
||||
}
|
||||
previous_entry = current_entry;
|
||||
current_entry = current_entry->Flink;
|
||||
}
|
||||
DPRINT("%s() = NULL\n",__FUNCTION__);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
MEMORY_AREA* MmOpenMemoryAreaByRegion(PMADDRESS_SPACE AddressSpace,
|
||||
PVOID Address,
|
||||
ULONG Length)
|
||||
MEMORY_AREA* MmOpenMemoryAreaByRegion(PMADDRESS_SPACE AddressSpace,
|
||||
PVOID Address,
|
||||
ULONG Length)
|
||||
{
|
||||
PLIST_ENTRY current_entry;
|
||||
MEMORY_AREA* current;
|
||||
ULONG Extent;
|
||||
|
||||
|
||||
DPRINT("MmOpenMemoryByRegion(AddressSpace %x, Address %x, Length %x)\n",
|
||||
AddressSpace, Address, Length);
|
||||
|
||||
AddressSpace, Address, Length);
|
||||
|
||||
current_entry = AddressSpace->MAreaListHead.Flink;
|
||||
while (current_entry != &AddressSpace->MAreaListHead)
|
||||
{
|
||||
current = CONTAINING_RECORD(current_entry,
|
||||
MEMORY_AREA,
|
||||
Entry);
|
||||
DPRINT("current->BaseAddress %x current->Length %x\n",
|
||||
current->BaseAddress,current->Length);
|
||||
if (current->BaseAddress >= Address &&
|
||||
current->BaseAddress < (PVOID)((char*)Address+Length))
|
||||
{
|
||||
DPRINT("Finished MmOpenMemoryAreaByRegion() = %x\n",
|
||||
current);
|
||||
return(current);
|
||||
}
|
||||
Extent = (ULONG)current->BaseAddress + current->Length;
|
||||
if (Extent > (ULONG)Address &&
|
||||
Extent < (ULONG)((char*)Address+Length))
|
||||
{
|
||||
DPRINT("Finished MmOpenMemoryAreaByRegion() = %x\n",
|
||||
current);
|
||||
return(current);
|
||||
}
|
||||
if (current->BaseAddress <= Address &&
|
||||
Extent >= (ULONG)((char*)Address+Length))
|
||||
{
|
||||
DPRINT("Finished MmOpenMemoryAreaByRegion() = %x\n",
|
||||
current);
|
||||
return(current);
|
||||
}
|
||||
if (current->BaseAddress >= (PVOID)((char*)Address+Length))
|
||||
{
|
||||
DPRINT("Finished MmOpenMemoryAreaByRegion()= NULL\n",0);
|
||||
return(NULL);
|
||||
}
|
||||
current_entry = current_entry->Flink;
|
||||
}
|
||||
{
|
||||
current = CONTAINING_RECORD(current_entry,
|
||||
MEMORY_AREA,
|
||||
Entry);
|
||||
DPRINT("current->BaseAddress %x current->Length %x\n",
|
||||
current->BaseAddress,current->Length);
|
||||
if (current->BaseAddress >= Address &&
|
||||
current->BaseAddress < (PVOID)((char*)Address+Length))
|
||||
{
|
||||
DPRINT("Finished MmOpenMemoryAreaByRegion() = %x\n",
|
||||
current);
|
||||
return(current);
|
||||
}
|
||||
Extent = (ULONG)current->BaseAddress + current->Length;
|
||||
if (Extent > (ULONG)Address &&
|
||||
Extent < (ULONG)((char*)Address+Length))
|
||||
{
|
||||
DPRINT("Finished MmOpenMemoryAreaByRegion() = %x\n",
|
||||
current);
|
||||
return(current);
|
||||
}
|
||||
if (current->BaseAddress <= Address &&
|
||||
Extent >= (ULONG)((char*)Address+Length))
|
||||
{
|
||||
DPRINT("Finished MmOpenMemoryAreaByRegion() = %x\n",
|
||||
current);
|
||||
return(current);
|
||||
}
|
||||
if (current->BaseAddress >= (PVOID)((char*)Address+Length))
|
||||
{
|
||||
DPRINT("Finished MmOpenMemoryAreaByRegion()= NULL\n",0);
|
||||
return(NULL);
|
||||
}
|
||||
current_entry = current_entry->Flink;
|
||||
}
|
||||
DPRINT("Finished MmOpenMemoryAreaByRegion() = NULL\n",0);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
static VOID MmInsertMemoryArea(PMADDRESS_SPACE AddressSpace,
|
||||
MEMORY_AREA* marea)
|
||||
MEMORY_AREA* marea)
|
||||
{
|
||||
PLIST_ENTRY ListHead;
|
||||
PLIST_ENTRY current_entry;
|
||||
PLIST_ENTRY inserted_entry = &marea->Entry;
|
||||
MEMORY_AREA* current;
|
||||
MEMORY_AREA* next;
|
||||
|
||||
MEMORY_AREA* next;
|
||||
|
||||
DPRINT("MmInsertMemoryArea(marea %x)\n", marea);
|
||||
DPRINT("marea->BaseAddress %x\n", marea->BaseAddress);
|
||||
DPRINT("marea->Length %x\n", marea->Length);
|
||||
|
||||
|
||||
ListHead = &AddressSpace->MAreaListHead;
|
||||
|
||||
|
||||
current_entry = ListHead->Flink;
|
||||
if (IsListEmpty(ListHead))
|
||||
{
|
||||
InsertHeadList(ListHead,&marea->Entry);
|
||||
return;
|
||||
}
|
||||
{
|
||||
InsertHeadList(ListHead,&marea->Entry);
|
||||
return;
|
||||
}
|
||||
current = CONTAINING_RECORD(current_entry,MEMORY_AREA,Entry);
|
||||
if (current->BaseAddress > marea->BaseAddress)
|
||||
{
|
||||
InsertHeadList(ListHead,&marea->Entry);
|
||||
return;
|
||||
}
|
||||
{
|
||||
InsertHeadList(ListHead,&marea->Entry);
|
||||
return;
|
||||
}
|
||||
while (current_entry->Flink!=ListHead)
|
||||
{
|
||||
current = CONTAINING_RECORD(current_entry,MEMORY_AREA,Entry);
|
||||
next = CONTAINING_RECORD(current_entry->Flink,MEMORY_AREA,Entry);
|
||||
if (current->BaseAddress < marea->BaseAddress &&
|
||||
current->Entry.Flink==ListHead)
|
||||
{
|
||||
current_entry->Flink = inserted_entry;
|
||||
inserted_entry->Flink=ListHead;
|
||||
inserted_entry->Blink=current_entry;
|
||||
ListHead->Blink = inserted_entry;
|
||||
return;
|
||||
}
|
||||
if (current->BaseAddress < marea->BaseAddress &&
|
||||
next->BaseAddress > marea->BaseAddress)
|
||||
{
|
||||
inserted_entry->Flink = current_entry->Flink;
|
||||
inserted_entry->Blink = current_entry;
|
||||
inserted_entry->Flink->Blink = inserted_entry;
|
||||
current_entry->Flink=inserted_entry;
|
||||
return;
|
||||
}
|
||||
current_entry = current_entry->Flink;
|
||||
}
|
||||
{
|
||||
current = CONTAINING_RECORD(current_entry,MEMORY_AREA,Entry);
|
||||
next = CONTAINING_RECORD(current_entry->Flink,MEMORY_AREA,Entry);
|
||||
if (current->BaseAddress < marea->BaseAddress &&
|
||||
current->Entry.Flink==ListHead)
|
||||
{
|
||||
current_entry->Flink = inserted_entry;
|
||||
inserted_entry->Flink=ListHead;
|
||||
inserted_entry->Blink=current_entry;
|
||||
ListHead->Blink = inserted_entry;
|
||||
return;
|
||||
}
|
||||
if (current->BaseAddress < marea->BaseAddress &&
|
||||
next->BaseAddress > marea->BaseAddress)
|
||||
{
|
||||
inserted_entry->Flink = current_entry->Flink;
|
||||
inserted_entry->Blink = current_entry;
|
||||
inserted_entry->Flink->Blink = inserted_entry;
|
||||
current_entry->Flink=inserted_entry;
|
||||
return;
|
||||
}
|
||||
current_entry = current_entry->Flink;
|
||||
}
|
||||
InsertTailList(ListHead,inserted_entry);
|
||||
}
|
||||
|
||||
@@ -214,136 +214,136 @@ PVOID MmFindGapBottomUp(PMADDRESS_SPACE AddressSpace, ULONG Length)
|
||||
MEMORY_AREA* next;
|
||||
ULONG Gap;
|
||||
PVOID Address;
|
||||
|
||||
|
||||
DPRINT("MmFindGapBottomUp(Length %x)\n",Length);
|
||||
|
||||
|
||||
ListHead = &AddressSpace->MAreaListHead;
|
||||
|
||||
|
||||
current_entry = ListHead->Flink;
|
||||
while (current_entry->Flink!=ListHead)
|
||||
{
|
||||
current = CONTAINING_RECORD(current_entry,MEMORY_AREA,Entry);
|
||||
next = CONTAINING_RECORD(current_entry->Flink,MEMORY_AREA,Entry);
|
||||
Gap = (char*)next->BaseAddress - ((char*)current->BaseAddress + PAGE_ROUND_UP(current->Length));
|
||||
if (Gap >= Length)
|
||||
{
|
||||
return((char*)current->BaseAddress + PAGE_ROUND_UP(current->Length));
|
||||
}
|
||||
current_entry = current_entry->Flink;
|
||||
}
|
||||
|
||||
{
|
||||
current = CONTAINING_RECORD(current_entry,MEMORY_AREA,Entry);
|
||||
next = CONTAINING_RECORD(current_entry->Flink,MEMORY_AREA,Entry);
|
||||
Gap = (char*)next->BaseAddress - ((char*)current->BaseAddress + PAGE_ROUND_UP(current->Length));
|
||||
if (Gap >= Length)
|
||||
{
|
||||
return((char*)current->BaseAddress + PAGE_ROUND_UP(current->Length));
|
||||
}
|
||||
current_entry = current_entry->Flink;
|
||||
}
|
||||
|
||||
if (current_entry == ListHead)
|
||||
{
|
||||
Address = (PVOID)AddressSpace->LowestAddress;
|
||||
}
|
||||
{
|
||||
Address = (PVOID)AddressSpace->LowestAddress;
|
||||
}
|
||||
else
|
||||
{
|
||||
current = CONTAINING_RECORD(current_entry,MEMORY_AREA,Entry);
|
||||
Address = (char*)current->BaseAddress + PAGE_ROUND_UP(current->Length);
|
||||
}
|
||||
{
|
||||
current = CONTAINING_RECORD(current_entry,MEMORY_AREA,Entry);
|
||||
Address = (char*)current->BaseAddress + PAGE_ROUND_UP(current->Length);
|
||||
}
|
||||
/* Check if enough space for the block */
|
||||
if (AddressSpace->LowestAddress < KERNEL_BASE)
|
||||
{
|
||||
if ((ULONG)Address >= KERNEL_BASE || Length > KERNEL_BASE - (ULONG)Address)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
{
|
||||
if ((ULONG)Address >= KERNEL_BASE || Length > KERNEL_BASE - (ULONG)Address)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Length >= 0xFFFFFFFF - (ULONG)Address)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
{
|
||||
if (Length >= 0xFFFFFFFF - (ULONG)Address)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return Address;
|
||||
}
|
||||
|
||||
|
||||
PVOID MmFindGapTopDown(PMADDRESS_SPACE AddressSpace, ULONG Length)
|
||||
{
|
||||
PLIST_ENTRY ListHead;
|
||||
PLIST_ENTRY current_entry;
|
||||
MEMORY_AREA* current;
|
||||
ULONG Gap;
|
||||
PVOID Address;
|
||||
PVOID TopAddress;
|
||||
PVOID BottomAddress;
|
||||
PVOID HighestAddress;
|
||||
PLIST_ENTRY ListHead;
|
||||
PLIST_ENTRY current_entry;
|
||||
MEMORY_AREA* current;
|
||||
ULONG Gap;
|
||||
PVOID Address;
|
||||
PVOID TopAddress;
|
||||
PVOID BottomAddress;
|
||||
PVOID HighestAddress;
|
||||
|
||||
DPRINT("MmFindGapTopDown(Length %lx)\n",Length);
|
||||
DPRINT("MmFindGapTopDown(Length %lx)\n",Length);
|
||||
|
||||
if (AddressSpace->LowestAddress < KERNEL_BASE) //(ULONG_PTR)MmSystemRangeStart)
|
||||
{
|
||||
if (AddressSpace->LowestAddress < KERNEL_BASE) //(ULONG_PTR)MmSystemRangeStart)
|
||||
{
|
||||
HighestAddress = MmHighestUserAddress;
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
HighestAddress = (PVOID)0xFFFFFFFF;
|
||||
}
|
||||
}
|
||||
|
||||
TopAddress = HighestAddress;
|
||||
TopAddress = HighestAddress;
|
||||
|
||||
ListHead = &AddressSpace->MAreaListHead;
|
||||
current_entry = ListHead->Blink;
|
||||
while (current_entry->Blink != ListHead)
|
||||
{
|
||||
ListHead = &AddressSpace->MAreaListHead;
|
||||
current_entry = ListHead->Blink;
|
||||
while (current_entry->Blink != ListHead)
|
||||
{
|
||||
current = CONTAINING_RECORD(current_entry,MEMORY_AREA,Entry);
|
||||
BottomAddress = (char*)current->BaseAddress + PAGE_ROUND_UP(current->Length);
|
||||
DPRINT("Base %p Length %lx\n", current->BaseAddress, PAGE_ROUND_UP(current->Length));
|
||||
|
||||
if (BottomAddress < HighestAddress)
|
||||
{
|
||||
Gap = (char*)TopAddress - (char*)BottomAddress + 1;
|
||||
DPRINT("Bottom %p Top %p Gap %lx\n", BottomAddress, TopAddress, Gap);
|
||||
if (Gap >= Length)
|
||||
{
|
||||
DPRINT("Found gap at %p\n", (char*)TopAddress - Length);
|
||||
return((char*)TopAddress - Length + 1);
|
||||
}
|
||||
TopAddress = (char*)current->BaseAddress - 1;
|
||||
}
|
||||
{
|
||||
Gap = (char*)TopAddress - (char*)BottomAddress + 1;
|
||||
DPRINT("Bottom %p Top %p Gap %lx\n", BottomAddress, TopAddress, Gap);
|
||||
if (Gap >= Length)
|
||||
{
|
||||
DPRINT("Found gap at %p\n", (char*)TopAddress - Length);
|
||||
return((char*)TopAddress - Length + 1);
|
||||
}
|
||||
TopAddress = (char*)current->BaseAddress - 1;
|
||||
}
|
||||
current_entry = current_entry->Blink;
|
||||
}
|
||||
}
|
||||
|
||||
if (current_entry == ListHead)
|
||||
{
|
||||
if (current_entry == ListHead)
|
||||
{
|
||||
Address = (char*)HighestAddress - Length + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
Address = (char*)TopAddress - Length + 1;
|
||||
}
|
||||
|
||||
/* Check if enough space for the block */
|
||||
if (AddressSpace->LowestAddress < KERNEL_BASE)
|
||||
{
|
||||
if ((ULONG)Address >= KERNEL_BASE || Length > KERNEL_BASE - (ULONG)Address)
|
||||
{
|
||||
DPRINT("Failed to find gap\n");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Length >= 0xFFFFFFFF - (ULONG)Address)
|
||||
{
|
||||
DPRINT("Failed to find gap\n");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
{
|
||||
Address = (char*)TopAddress - Length + 1;
|
||||
}
|
||||
|
||||
DPRINT("Found gap at %p\n", Address);
|
||||
return Address;
|
||||
/* Check if enough space for the block */
|
||||
if (AddressSpace->LowestAddress < KERNEL_BASE)
|
||||
{
|
||||
if ((ULONG)Address >= KERNEL_BASE || Length > KERNEL_BASE - (ULONG)Address)
|
||||
{
|
||||
DPRINT("Failed to find gap\n");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Length >= 0xFFFFFFFF - (ULONG)Address)
|
||||
{
|
||||
DPRINT("Failed to find gap\n");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
DPRINT("Found gap at %p\n", Address);
|
||||
return Address;
|
||||
}
|
||||
|
||||
|
||||
PVOID MmFindGap(PMADDRESS_SPACE AddressSpace, ULONG Length, BOOL TopDown)
|
||||
{
|
||||
if (TopDown)
|
||||
return MmFindGapTopDown(AddressSpace, Length);
|
||||
if (TopDown)
|
||||
return MmFindGapTopDown(AddressSpace, Length);
|
||||
|
||||
return MmFindGapBottomUp(AddressSpace, Length);
|
||||
return MmFindGapBottomUp(AddressSpace, Length);
|
||||
}
|
||||
|
||||
|
||||
@@ -357,92 +357,94 @@ MmInitMemoryAreas(VOID)
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTSTATUS
|
||||
MmFreeMemoryArea(PMADDRESS_SPACE AddressSpace,
|
||||
PVOID BaseAddress,
|
||||
ULONG Length,
|
||||
VOID (*FreePage)(PVOID Context, MEMORY_AREA* MemoryArea,
|
||||
PVOID Address, PHYSICAL_ADDRESS PhysAddr,
|
||||
SWAPENTRY SwapEntry, BOOLEAN Dirty),
|
||||
PVOID FreePageContext)
|
||||
PVOID BaseAddress,
|
||||
ULONG Length,
|
||||
VOID (*FreePage)(PVOID Context, MEMORY_AREA* MemoryArea,
|
||||
PVOID Address, PHYSICAL_ADDRESS PhysAddr,
|
||||
SWAPENTRY SwapEntry, BOOLEAN Dirty),
|
||||
PVOID FreePageContext)
|
||||
{
|
||||
MEMORY_AREA* MemoryArea;
|
||||
ULONG i;
|
||||
PEPROCESS CurrentProcess = PsGetCurrentProcess();
|
||||
|
||||
|
||||
DPRINT("MmFreeMemoryArea(AddressSpace %x, BaseAddress %x, Length %x,"
|
||||
"FreePageContext %d)\n",AddressSpace,BaseAddress,Length,
|
||||
FreePageContext);
|
||||
"FreePageContext %d)\n",AddressSpace,BaseAddress,Length,
|
||||
FreePageContext);
|
||||
|
||||
MemoryArea = MmOpenMemoryAreaByAddress(AddressSpace,
|
||||
BaseAddress);
|
||||
BaseAddress);
|
||||
if (MemoryArea == NULL)
|
||||
{
|
||||
KEBUGCHECK(0);
|
||||
return(STATUS_UNSUCCESSFUL);
|
||||
}
|
||||
if (AddressSpace->Process != NULL &&
|
||||
AddressSpace->Process != CurrentProcess)
|
||||
{
|
||||
KeAttachProcess(AddressSpace->Process);
|
||||
}
|
||||
for (i=0; i<(PAGE_ROUND_UP(MemoryArea->Length)/PAGE_SIZE); i++)
|
||||
{
|
||||
#if defined(__GNUC__)
|
||||
PHYSICAL_ADDRESS PhysAddr = (PHYSICAL_ADDRESS)0LL;
|
||||
#else
|
||||
PHYSICAL_ADDRESS PhysAddr = { 0 };
|
||||
#endif
|
||||
BOOL Dirty = FALSE;
|
||||
SWAPENTRY SwapEntry = 0;
|
||||
|
||||
if (MmIsPageSwapEntry(AddressSpace->Process,
|
||||
(char*)MemoryArea->BaseAddress + (i * PAGE_SIZE)))
|
||||
{
|
||||
MmDeletePageFileMapping(AddressSpace->Process,
|
||||
(char*)MemoryArea->BaseAddress + (i * PAGE_SIZE),
|
||||
&SwapEntry);
|
||||
}
|
||||
else
|
||||
{
|
||||
MmDeleteVirtualMapping(AddressSpace->Process,
|
||||
(char*)MemoryArea->BaseAddress + (i*PAGE_SIZE),
|
||||
FALSE, &Dirty, &PhysAddr);
|
||||
|
||||
}
|
||||
if (FreePage != NULL)
|
||||
{
|
||||
FreePage(FreePageContext, MemoryArea,
|
||||
(char*)MemoryArea->BaseAddress + (i * PAGE_SIZE), PhysAddr,
|
||||
SwapEntry, (BOOLEAN)Dirty);
|
||||
}
|
||||
}
|
||||
{
|
||||
KEBUGCHECK(0);
|
||||
return(STATUS_UNSUCCESSFUL);
|
||||
}
|
||||
if (AddressSpace->Process != NULL &&
|
||||
AddressSpace->Process != CurrentProcess)
|
||||
{
|
||||
KeDetachProcess();
|
||||
}
|
||||
AddressSpace->Process != CurrentProcess)
|
||||
{
|
||||
KeAttachProcess(AddressSpace->Process);
|
||||
}
|
||||
for (i=0; i<(PAGE_ROUND_UP(MemoryArea->Length)/PAGE_SIZE); i++)
|
||||
{
|
||||
#if defined(__GNUC__)
|
||||
PHYSICAL_ADDRESS PhysAddr = (PHYSICAL_ADDRESS)0LL;
|
||||
#else
|
||||
|
||||
PHYSICAL_ADDRESS PhysAddr = { 0 };
|
||||
#endif
|
||||
|
||||
BOOL Dirty = FALSE;
|
||||
SWAPENTRY SwapEntry = 0;
|
||||
|
||||
if (MmIsPageSwapEntry(AddressSpace->Process,
|
||||
(char*)MemoryArea->BaseAddress + (i * PAGE_SIZE)))
|
||||
{
|
||||
MmDeletePageFileMapping(AddressSpace->Process,
|
||||
(char*)MemoryArea->BaseAddress + (i * PAGE_SIZE),
|
||||
&SwapEntry);
|
||||
}
|
||||
else
|
||||
{
|
||||
MmDeleteVirtualMapping(AddressSpace->Process,
|
||||
(char*)MemoryArea->BaseAddress + (i*PAGE_SIZE),
|
||||
FALSE, &Dirty, &PhysAddr);
|
||||
|
||||
}
|
||||
if (FreePage != NULL)
|
||||
{
|
||||
FreePage(FreePageContext, MemoryArea,
|
||||
(char*)MemoryArea->BaseAddress + (i * PAGE_SIZE), PhysAddr,
|
||||
SwapEntry, (BOOLEAN)Dirty);
|
||||
}
|
||||
}
|
||||
if (AddressSpace->Process != NULL &&
|
||||
AddressSpace->Process != CurrentProcess)
|
||||
{
|
||||
KeDetachProcess();
|
||||
}
|
||||
RemoveEntryList(&MemoryArea->Entry);
|
||||
ExFreePool(MemoryArea);
|
||||
|
||||
|
||||
DPRINT("MmFreeMemoryArea() succeeded\n");
|
||||
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
PMEMORY_AREA MmSplitMemoryArea(PEPROCESS Process,
|
||||
PMADDRESS_SPACE AddressSpace,
|
||||
PMEMORY_AREA OriginalMemoryArea,
|
||||
PVOID BaseAddress,
|
||||
ULONG Length,
|
||||
ULONG NewType,
|
||||
ULONG NewAttributes)
|
||||
PMADDRESS_SPACE AddressSpace,
|
||||
PMEMORY_AREA OriginalMemoryArea,
|
||||
PVOID BaseAddress,
|
||||
ULONG Length,
|
||||
ULONG NewType,
|
||||
ULONG NewAttributes)
|
||||
{
|
||||
PMEMORY_AREA Result;
|
||||
PMEMORY_AREA Split;
|
||||
|
||||
Result = ExAllocatePoolWithTag(NonPagedPool, sizeof(MEMORY_AREA),
|
||||
TAG_MAREA);
|
||||
|
||||
Result = ExAllocatePoolWithTag(NonPagedPool, sizeof(MEMORY_AREA),
|
||||
TAG_MAREA);
|
||||
RtlZeroMemory(Result,sizeof(MEMORY_AREA));
|
||||
Result->Type = NewType;
|
||||
Result->BaseAddress = BaseAddress;
|
||||
@@ -450,45 +452,45 @@ PMEMORY_AREA MmSplitMemoryArea(PEPROCESS Process,
|
||||
Result->Attributes = NewAttributes;
|
||||
Result->LockCount = 0;
|
||||
Result->Process = Process;
|
||||
|
||||
if (BaseAddress == OriginalMemoryArea->BaseAddress)
|
||||
{
|
||||
OriginalMemoryArea->BaseAddress = (char*)BaseAddress + Length;
|
||||
OriginalMemoryArea->Length = OriginalMemoryArea->Length - Length;
|
||||
MmInsertMemoryArea(AddressSpace, Result);
|
||||
return(Result);
|
||||
}
|
||||
if (((char*)BaseAddress + Length) ==
|
||||
((char*)OriginalMemoryArea->BaseAddress + OriginalMemoryArea->Length))
|
||||
{
|
||||
OriginalMemoryArea->Length = OriginalMemoryArea->Length - Length;
|
||||
MmInsertMemoryArea(AddressSpace, Result);
|
||||
|
||||
return(Result);
|
||||
}
|
||||
|
||||
if (BaseAddress == OriginalMemoryArea->BaseAddress)
|
||||
{
|
||||
OriginalMemoryArea->BaseAddress = (char*)BaseAddress + Length;
|
||||
OriginalMemoryArea->Length = OriginalMemoryArea->Length - Length;
|
||||
MmInsertMemoryArea(AddressSpace, Result);
|
||||
return(Result);
|
||||
}
|
||||
if (((char*)BaseAddress + Length) ==
|
||||
((char*)OriginalMemoryArea->BaseAddress + OriginalMemoryArea->Length))
|
||||
{
|
||||
OriginalMemoryArea->Length = OriginalMemoryArea->Length - Length;
|
||||
MmInsertMemoryArea(AddressSpace, Result);
|
||||
|
||||
return(Result);
|
||||
}
|
||||
|
||||
Split = ExAllocatePoolWithTag(NonPagedPool, sizeof(MEMORY_AREA),
|
||||
TAG_MAREA);
|
||||
TAG_MAREA);
|
||||
RtlCopyMemory(Split,OriginalMemoryArea,sizeof(MEMORY_AREA));
|
||||
Split->BaseAddress = (char*)BaseAddress + Length;
|
||||
Split->Length = OriginalMemoryArea->Length - (((ULONG)BaseAddress)
|
||||
+ Length);
|
||||
|
||||
Split->Length = OriginalMemoryArea->Length - (((ULONG)BaseAddress)
|
||||
+ Length);
|
||||
|
||||
OriginalMemoryArea->Length = (char*)BaseAddress - (char*)OriginalMemoryArea->BaseAddress;
|
||||
|
||||
|
||||
return(Split);
|
||||
}
|
||||
|
||||
NTSTATUS MmCreateMemoryArea(PEPROCESS Process,
|
||||
PMADDRESS_SPACE AddressSpace,
|
||||
ULONG Type,
|
||||
PVOID* BaseAddress,
|
||||
ULONG Length,
|
||||
ULONG Attributes,
|
||||
MEMORY_AREA** Result,
|
||||
BOOL FixedAddress,
|
||||
BOOL TopDown,
|
||||
PHYSICAL_ADDRESS BoundaryAddressMultiple)
|
||||
PMADDRESS_SPACE AddressSpace,
|
||||
ULONG Type,
|
||||
PVOID* BaseAddress,
|
||||
ULONG Length,
|
||||
ULONG Attributes,
|
||||
MEMORY_AREA** Result,
|
||||
BOOL FixedAddress,
|
||||
BOOL TopDown,
|
||||
PHYSICAL_ADDRESS BoundaryAddressMultiple)
|
||||
/*
|
||||
* FUNCTION: Create a memory area
|
||||
* ARGUMENTS:
|
||||
@@ -505,64 +507,66 @@ NTSTATUS MmCreateMemoryArea(PEPROCESS Process,
|
||||
PVOID EndAddress;
|
||||
ULONG tmpLength;
|
||||
DPRINT("MmCreateMemoryArea(Type %d, BaseAddress %x,"
|
||||
"*BaseAddress %x, Length %x, Attributes %x, Result %x)\n",
|
||||
Type,BaseAddress,*BaseAddress,Length,Attributes,Result);
|
||||
"*BaseAddress %x, Length %x, Attributes %x, Result %x)\n",
|
||||
Type,BaseAddress,*BaseAddress,Length,Attributes,Result);
|
||||
|
||||
if ((*BaseAddress) == 0 && !FixedAddress)
|
||||
{
|
||||
tmpLength = PAGE_ROUND_UP(Length);
|
||||
*BaseAddress = MmFindGap(AddressSpace,
|
||||
PAGE_ROUND_UP(Length) +(PAGE_SIZE*2),
|
||||
TopDown);
|
||||
if ((*BaseAddress) == 0)
|
||||
{
|
||||
DPRINT("No suitable gap\n");
|
||||
return(STATUS_NO_MEMORY);
|
||||
}
|
||||
{
|
||||
tmpLength = PAGE_ROUND_UP(Length);
|
||||
*BaseAddress = MmFindGap(AddressSpace,
|
||||
PAGE_ROUND_UP(Length) +(PAGE_SIZE*2),
|
||||
TopDown);
|
||||
if ((*BaseAddress) == 0)
|
||||
{
|
||||
DPRINT("No suitable gap\n");
|
||||
return(STATUS_NO_MEMORY);
|
||||
}
|
||||
#if defined(__GNUC__)
|
||||
(*BaseAddress)=(*BaseAddress)+PAGE_SIZE;
|
||||
(*BaseAddress)=(*BaseAddress)+PAGE_SIZE;
|
||||
#else
|
||||
{
|
||||
char* pTemp = *BaseAddress;
|
||||
pTemp += PAGE_SIZE;
|
||||
*BaseAddress = pTemp;
|
||||
}
|
||||
|
||||
{
|
||||
char* pTemp = *BaseAddress;
|
||||
pTemp += PAGE_SIZE;
|
||||
*BaseAddress = pTemp;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
tmpLength = (ULONG)*BaseAddress + Length - PAGE_ROUND_DOWN((*BaseAddress));
|
||||
(*BaseAddress) = (PVOID)PAGE_ROUND_DOWN((*BaseAddress));
|
||||
{
|
||||
tmpLength = (ULONG)*BaseAddress + Length - PAGE_ROUND_DOWN((*BaseAddress));
|
||||
(*BaseAddress) = (PVOID)PAGE_ROUND_DOWN((*BaseAddress));
|
||||
|
||||
if (AddressSpace->LowestAddress == KERNEL_BASE &&
|
||||
(*BaseAddress) < (PVOID)KERNEL_BASE)
|
||||
{
|
||||
return STATUS_ACCESS_VIOLATION;
|
||||
}
|
||||
if (AddressSpace->LowestAddress == KERNEL_BASE &&
|
||||
(*BaseAddress) < (PVOID)KERNEL_BASE)
|
||||
{
|
||||
return STATUS_ACCESS_VIOLATION;
|
||||
}
|
||||
|
||||
if (AddressSpace->LowestAddress < KERNEL_BASE &&
|
||||
(PVOID)((char*)(*BaseAddress) + tmpLength) > (PVOID)KERNEL_BASE)
|
||||
{
|
||||
return STATUS_ACCESS_VIOLATION;
|
||||
}
|
||||
if (AddressSpace->LowestAddress < KERNEL_BASE &&
|
||||
(PVOID)((char*)(*BaseAddress) + tmpLength) > (PVOID)KERNEL_BASE)
|
||||
{
|
||||
return STATUS_ACCESS_VIOLATION;
|
||||
}
|
||||
|
||||
if (BoundaryAddressMultiple.QuadPart != 0)
|
||||
{
|
||||
EndAddress = ((char*)(*BaseAddress)) + tmpLength-1;
|
||||
assert(((DWORD_PTR)*BaseAddress/BoundaryAddressMultiple.QuadPart) == ((DWORD_PTR)EndAddress/BoundaryAddressMultiple.QuadPart));
|
||||
}
|
||||
if (BoundaryAddressMultiple.QuadPart != 0)
|
||||
{
|
||||
EndAddress = ((char*)(*BaseAddress)) + tmpLength-1;
|
||||
assert(((DWORD_PTR)*BaseAddress/BoundaryAddressMultiple.QuadPart) == ((DWORD_PTR)EndAddress/BoundaryAddressMultiple.QuadPart));
|
||||
}
|
||||
|
||||
if (MmOpenMemoryAreaByRegion(AddressSpace,
|
||||
*BaseAddress,
|
||||
tmpLength)!=NULL)
|
||||
{
|
||||
DPRINT("Memory area already occupied\n");
|
||||
return(STATUS_CONFLICTING_ADDRESSES);
|
||||
}
|
||||
}
|
||||
if (MmOpenMemoryAreaByRegion(AddressSpace,
|
||||
*BaseAddress,
|
||||
tmpLength)!=NULL)
|
||||
{
|
||||
DPRINT("Memory area already occupied\n");
|
||||
return(STATUS_CONFLICTING_ADDRESSES);
|
||||
}
|
||||
}
|
||||
|
||||
*Result = ExAllocatePoolWithTag(NonPagedPool, sizeof(MEMORY_AREA),
|
||||
TAG_MAREA);
|
||||
TAG_MAREA);
|
||||
RtlZeroMemory(*Result,sizeof(MEMORY_AREA));
|
||||
(*Result)->Type = Type;
|
||||
(*Result)->BaseAddress = *BaseAddress;
|
||||
@@ -572,9 +576,9 @@ NTSTATUS MmCreateMemoryArea(PEPROCESS Process,
|
||||
(*Result)->Process = Process;
|
||||
(*Result)->PageOpCount = 0;
|
||||
(*Result)->DeleteInProgress = FALSE;
|
||||
|
||||
|
||||
MmInsertMemoryArea(AddressSpace, *Result);
|
||||
|
||||
|
||||
DPRINT("MmCreateMemoryArea() succeeded\n");
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
+314
-301
@@ -1,4 +1,4 @@
|
||||
/* $Id: mdl.c,v 1.60 2004/03/13 19:14:16 dwelch Exp $
|
||||
/* $Id: mdl.c,v 1.61 2004/04/10 22:35:25 gdalsnes Exp $
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
@@ -36,55 +36,55 @@ static KSPIN_LOCK MiMdlMappingRegionLock;
|
||||
VOID INIT_FUNCTION
|
||||
MmInitializeMdlImplementation(VOID)
|
||||
{
|
||||
MEMORY_AREA* Result;
|
||||
NTSTATUS Status;
|
||||
PVOID Buffer;
|
||||
PHYSICAL_ADDRESS BoundaryAddressMultiple;
|
||||
MEMORY_AREA* Result;
|
||||
NTSTATUS Status;
|
||||
PVOID Buffer;
|
||||
PHYSICAL_ADDRESS BoundaryAddressMultiple;
|
||||
|
||||
BoundaryAddressMultiple.QuadPart = 0;
|
||||
MiMdlMappingRegionHint = 0;
|
||||
MiMdlMappingRegionBase = NULL;
|
||||
BoundaryAddressMultiple.QuadPart = 0;
|
||||
MiMdlMappingRegionHint = 0;
|
||||
MiMdlMappingRegionBase = NULL;
|
||||
|
||||
MmLockAddressSpace(MmGetKernelAddressSpace());
|
||||
Status = MmCreateMemoryArea(NULL,
|
||||
MmGetKernelAddressSpace(),
|
||||
MEMORY_AREA_MDL_MAPPING,
|
||||
&MiMdlMappingRegionBase,
|
||||
MI_MDL_MAPPING_REGION_SIZE,
|
||||
0,
|
||||
&Result,
|
||||
FALSE,
|
||||
FALSE,
|
||||
BoundaryAddressMultiple);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
MmLockAddressSpace(MmGetKernelAddressSpace());
|
||||
Status = MmCreateMemoryArea(NULL,
|
||||
MmGetKernelAddressSpace(),
|
||||
MEMORY_AREA_MDL_MAPPING,
|
||||
&MiMdlMappingRegionBase,
|
||||
MI_MDL_MAPPING_REGION_SIZE,
|
||||
0,
|
||||
&Result,
|
||||
FALSE,
|
||||
FALSE,
|
||||
BoundaryAddressMultiple);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
MmUnlockAddressSpace(MmGetKernelAddressSpace());
|
||||
KEBUGCHECK(0);
|
||||
}
|
||||
MmUnlockAddressSpace(MmGetKernelAddressSpace());
|
||||
}
|
||||
MmUnlockAddressSpace(MmGetKernelAddressSpace());
|
||||
|
||||
Buffer = ExAllocatePool(NonPagedPool, MI_MDL_MAPPING_REGION_SIZE / (PAGE_SIZE * 8));
|
||||
Buffer = ExAllocatePool(NonPagedPool, MI_MDL_MAPPING_REGION_SIZE / (PAGE_SIZE * 8));
|
||||
|
||||
RtlInitializeBitMap(&MiMdlMappingRegionAllocMap, Buffer, MI_MDL_MAPPING_REGION_SIZE / PAGE_SIZE);
|
||||
RtlClearAllBits(&MiMdlMappingRegionAllocMap);
|
||||
RtlInitializeBitMap(&MiMdlMappingRegionAllocMap, Buffer, MI_MDL_MAPPING_REGION_SIZE / PAGE_SIZE);
|
||||
RtlClearAllBits(&MiMdlMappingRegionAllocMap);
|
||||
|
||||
KeInitializeSpinLock(&MiMdlMappingRegionLock);
|
||||
KeInitializeSpinLock(&MiMdlMappingRegionLock);
|
||||
}
|
||||
|
||||
PVOID
|
||||
PVOID
|
||||
MmGetMdlPageAddress(PMDL Mdl, PVOID Offset)
|
||||
{
|
||||
PULONG MdlPages;
|
||||
|
||||
|
||||
MdlPages = (PULONG)(Mdl + 1);
|
||||
|
||||
|
||||
return((PVOID)MdlPages[((ULONG)Offset) / PAGE_SIZE]);
|
||||
}
|
||||
|
||||
/*
|
||||
* @unimplemented
|
||||
*/
|
||||
VOID STDCALL
|
||||
VOID STDCALL
|
||||
MmUnlockPages(PMDL Mdl)
|
||||
/*
|
||||
* FUNCTION: Unlocks the physical pages described by a given MDL
|
||||
@@ -97,37 +97,39 @@ MmUnlockPages(PMDL Mdl)
|
||||
{
|
||||
ULONG i;
|
||||
PULONG MdlPages;
|
||||
|
||||
/*
|
||||
|
||||
/*
|
||||
* FIXME: I don't know whether this right, but it looks sensible
|
||||
*/
|
||||
if ((Mdl->MdlFlags & MDL_SOURCE_IS_NONPAGED_POOL) ||
|
||||
(Mdl->MdlFlags & MDL_IO_PAGE_READ))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
(Mdl->MdlFlags & MDL_IO_PAGE_READ))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* FIXME: Seems sensible
|
||||
*/
|
||||
if (!(Mdl->MdlFlags & MDL_PAGES_LOCKED))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
MdlPages = (PULONG)(Mdl + 1);
|
||||
for (i=0; i<(PAGE_ROUND_UP(Mdl->ByteCount+Mdl->ByteOffset)/PAGE_SIZE); i++)
|
||||
{
|
||||
{
|
||||
#if defined(__GNUC__)
|
||||
MmUnlockPage((LARGE_INTEGER)(LONGLONG)MdlPages[i]);
|
||||
MmDereferencePage((LARGE_INTEGER)(LONGLONG)MdlPages[i]);
|
||||
MmUnlockPage((LARGE_INTEGER)(LONGLONG)MdlPages[i]);
|
||||
MmDereferencePage((LARGE_INTEGER)(LONGLONG)MdlPages[i]);
|
||||
#else
|
||||
PHYSICAL_ADDRESS dummyJunkNeeded;
|
||||
dummyJunkNeeded.QuadPart = MdlPages[i];
|
||||
MmUnlockPage(dummyJunkNeeded);
|
||||
MmDereferencePage(dummyJunkNeeded);
|
||||
|
||||
PHYSICAL_ADDRESS dummyJunkNeeded;
|
||||
dummyJunkNeeded.QuadPart = MdlPages[i];
|
||||
MmUnlockPage(dummyJunkNeeded);
|
||||
MmDereferencePage(dummyJunkNeeded);
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
Mdl->MdlFlags = Mdl->MdlFlags & (~MDL_PAGES_LOCKED);
|
||||
}
|
||||
|
||||
@@ -157,103 +159,105 @@ MmMapLockedPages(PMDL Mdl, KPROCESSOR_MODE AccessMode)
|
||||
DPRINT("MmMapLockedPages(Mdl %x, AccessMode %x)\n", Mdl, AccessMode);
|
||||
|
||||
if ((Mdl->MdlFlags & MDL_SOURCE_IS_NONPAGED_POOL) && AccessMode != UserMode)
|
||||
{
|
||||
return(Mdl->MappedSystemVa);
|
||||
}
|
||||
{
|
||||
return(Mdl->MappedSystemVa);
|
||||
}
|
||||
|
||||
/* Calculate the number of pages required. */
|
||||
RegionSize = PAGE_ROUND_UP(Mdl->ByteCount + Mdl->ByteOffset) / PAGE_SIZE;
|
||||
|
||||
if (AccessMode == UserMode)
|
||||
{
|
||||
MEMORY_AREA *Result;
|
||||
LARGE_INTEGER BoundaryAddressMultiple;
|
||||
NTSTATUS Status;
|
||||
{
|
||||
MEMORY_AREA *Result;
|
||||
LARGE_INTEGER BoundaryAddressMultiple;
|
||||
NTSTATUS Status;
|
||||
|
||||
BoundaryAddressMultiple.QuadPart = 0;
|
||||
Base = NULL;
|
||||
BoundaryAddressMultiple.QuadPart = 0;
|
||||
Base = NULL;
|
||||
|
||||
CurrentProcess = OldProcess = PsGetCurrentProcess();
|
||||
if (Mdl->Process != CurrentProcess)
|
||||
{
|
||||
KeAttachProcess(Mdl->Process);
|
||||
CurrentProcess = Mdl->Process;
|
||||
}
|
||||
CurrentProcess = OldProcess = PsGetCurrentProcess();
|
||||
if (Mdl->Process != CurrentProcess)
|
||||
{
|
||||
KeAttachProcess(Mdl->Process);
|
||||
CurrentProcess = Mdl->Process;
|
||||
}
|
||||
|
||||
MmLockAddressSpace(&CurrentProcess->AddressSpace);
|
||||
Status = MmCreateMemoryArea(CurrentProcess,
|
||||
&CurrentProcess->AddressSpace,
|
||||
MEMORY_AREA_MDL_MAPPING,
|
||||
&Base,
|
||||
RegionSize * PAGE_SIZE,
|
||||
0, /* PAGE_READWRITE? */
|
||||
&Result,
|
||||
FALSE,
|
||||
FALSE,
|
||||
BoundaryAddressMultiple);
|
||||
MmUnlockAddressSpace(&CurrentProcess->AddressSpace);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
KEBUGCHECK(0);
|
||||
/* FIXME: handle this? */
|
||||
}
|
||||
}
|
||||
MmLockAddressSpace(&CurrentProcess->AddressSpace);
|
||||
Status = MmCreateMemoryArea(CurrentProcess,
|
||||
&CurrentProcess->AddressSpace,
|
||||
MEMORY_AREA_MDL_MAPPING,
|
||||
&Base,
|
||||
RegionSize * PAGE_SIZE,
|
||||
0, /* PAGE_READWRITE? */
|
||||
&Result,
|
||||
FALSE,
|
||||
FALSE,
|
||||
BoundaryAddressMultiple);
|
||||
MmUnlockAddressSpace(&CurrentProcess->AddressSpace);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
KEBUGCHECK(0);
|
||||
/* FIXME: handle this? */
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CurrentProcess = OldProcess = NULL;
|
||||
{
|
||||
CurrentProcess = OldProcess = NULL;
|
||||
|
||||
/* Allocate that number of pages from the mdl mapping region. */
|
||||
KeAcquireSpinLock(&MiMdlMappingRegionLock, &oldIrql);
|
||||
/* Allocate that number of pages from the mdl mapping region. */
|
||||
KeAcquireSpinLock(&MiMdlMappingRegionLock, &oldIrql);
|
||||
|
||||
StartingOffset = RtlFindClearBitsAndSet(&MiMdlMappingRegionAllocMap, RegionSize, MiMdlMappingRegionHint);
|
||||
StartingOffset = RtlFindClearBitsAndSet(&MiMdlMappingRegionAllocMap, RegionSize, MiMdlMappingRegionHint);
|
||||
|
||||
if (StartingOffset == 0xffffffff)
|
||||
{
|
||||
DPRINT1("Out of MDL mapping space\n");
|
||||
KEBUGCHECK(0);
|
||||
}
|
||||
if (StartingOffset == 0xffffffff)
|
||||
{
|
||||
DPRINT1("Out of MDL mapping space\n");
|
||||
KEBUGCHECK(0);
|
||||
}
|
||||
|
||||
Base = (char*)MiMdlMappingRegionBase + StartingOffset * PAGE_SIZE;
|
||||
Base = (char*)MiMdlMappingRegionBase + StartingOffset * PAGE_SIZE;
|
||||
|
||||
if (MiMdlMappingRegionHint == StartingOffset)
|
||||
{
|
||||
MiMdlMappingRegionHint +=RegionSize;
|
||||
}
|
||||
if (MiMdlMappingRegionHint == StartingOffset)
|
||||
{
|
||||
MiMdlMappingRegionHint +=RegionSize;
|
||||
}
|
||||
|
||||
KeReleaseSpinLock(&MiMdlMappingRegionLock, oldIrql);
|
||||
}
|
||||
KeReleaseSpinLock(&MiMdlMappingRegionLock, oldIrql);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Set the virtual mappings for the MDL pages. */
|
||||
MdlPages = (PULONG)(Mdl + 1);
|
||||
for (i = 0; i < RegionSize; i++)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
{
|
||||
NTSTATUS Status;
|
||||
#if !defined(__GNUC__)
|
||||
PHYSICAL_ADDRESS dummyJunkNeeded;
|
||||
dummyJunkNeeded.QuadPart = MdlPages[i];
|
||||
|
||||
PHYSICAL_ADDRESS dummyJunkNeeded;
|
||||
dummyJunkNeeded.QuadPart = MdlPages[i];
|
||||
#endif
|
||||
Status = MmCreateVirtualMapping(CurrentProcess,
|
||||
(PVOID)((ULONG)Base+(i*PAGE_SIZE)),
|
||||
PAGE_READWRITE,
|
||||
|
||||
Status = MmCreateVirtualMapping(CurrentProcess,
|
||||
(PVOID)((ULONG)Base+(i*PAGE_SIZE)),
|
||||
PAGE_READWRITE,
|
||||
#if defined(__GNUC__)
|
||||
(LARGE_INTEGER)(LONGLONG)MdlPages[i],
|
||||
(LARGE_INTEGER)(LONGLONG)MdlPages[i],
|
||||
#else
|
||||
dummyJunkNeeded,
|
||||
dummyJunkNeeded,
|
||||
#endif
|
||||
FALSE);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DbgPrint("Unable to create virtual mapping\n");
|
||||
KEBUGCHECK(0);
|
||||
}
|
||||
}
|
||||
FALSE);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DbgPrint("Unable to create virtual mapping\n");
|
||||
KEBUGCHECK(0);
|
||||
}
|
||||
}
|
||||
|
||||
if (AccessMode == UserMode && CurrentProcess != OldProcess)
|
||||
{
|
||||
KeDetachProcess();
|
||||
}
|
||||
{
|
||||
KeDetachProcess();
|
||||
}
|
||||
|
||||
/* Mark the MDL has having being mapped. */
|
||||
Mdl->MdlFlags = Mdl->MdlFlags | MDL_MAPPED_TO_SYSTEM_VA;
|
||||
@@ -273,62 +277,64 @@ MmUnmapLockedPages(PVOID BaseAddress, PMDL Mdl)
|
||||
* MemoryDescriptorList = MDL describing the mapped pages
|
||||
*/
|
||||
{
|
||||
KIRQL oldIrql;
|
||||
ULONG i;
|
||||
ULONG RegionSize;
|
||||
ULONG Base;
|
||||
PEPROCESS CurrentProcess, OldProcess;
|
||||
KIRQL oldIrql;
|
||||
ULONG i;
|
||||
ULONG RegionSize;
|
||||
ULONG Base;
|
||||
PEPROCESS CurrentProcess, OldProcess;
|
||||
|
||||
DPRINT("MmUnmapLockedPages(BaseAddress %x, Mdl %x)\n", BaseAddress, Mdl);
|
||||
DPRINT("MmUnmapLockedPages(BaseAddress %x, Mdl %x)\n", BaseAddress, Mdl);
|
||||
|
||||
/*
|
||||
* In this case, the MDL has the same system address as the base address
|
||||
* so there is no need to free it
|
||||
*/
|
||||
if ((Mdl->MdlFlags & MDL_SOURCE_IS_NONPAGED_POOL) &&
|
||||
((ULONG_PTR)BaseAddress >= KERNEL_BASE))
|
||||
{
|
||||
/*
|
||||
* In this case, the MDL has the same system address as the base address
|
||||
* so there is no need to free it
|
||||
*/
|
||||
if ((Mdl->MdlFlags & MDL_SOURCE_IS_NONPAGED_POOL) &&
|
||||
((ULONG_PTR)BaseAddress >= KERNEL_BASE))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ((ULONG_PTR)BaseAddress >= KERNEL_BASE)
|
||||
{
|
||||
if ((ULONG_PTR)BaseAddress >= KERNEL_BASE)
|
||||
{
|
||||
CurrentProcess = OldProcess = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
CurrentProcess = OldProcess = PsGetCurrentProcess();
|
||||
if (Mdl->Process != CurrentProcess)
|
||||
{
|
||||
KeAttachProcess(Mdl->Process);
|
||||
CurrentProcess = Mdl->Process;
|
||||
}
|
||||
}
|
||||
{
|
||||
KeAttachProcess(Mdl->Process);
|
||||
CurrentProcess = Mdl->Process;
|
||||
}
|
||||
}
|
||||
|
||||
/* Calculate the number of pages we mapped. */
|
||||
RegionSize = PAGE_ROUND_UP(Mdl->ByteCount + Mdl->ByteOffset) / PAGE_SIZE;
|
||||
/* Calculate the number of pages we mapped. */
|
||||
RegionSize = PAGE_ROUND_UP(Mdl->ByteCount + Mdl->ByteOffset) / PAGE_SIZE;
|
||||
#if defined(__GNUC__)
|
||||
BaseAddress -= Mdl->ByteOffset;
|
||||
|
||||
BaseAddress -= Mdl->ByteOffset;
|
||||
#else
|
||||
{
|
||||
char* pTemp = BaseAddress;
|
||||
pTemp -= Mdl->ByteOffset;
|
||||
BaseAddress = pTemp;
|
||||
}
|
||||
|
||||
{
|
||||
char* pTemp = BaseAddress;
|
||||
pTemp -= Mdl->ByteOffset;
|
||||
BaseAddress = pTemp;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Unmap all the pages. */
|
||||
for (i = 0; i < RegionSize; i++)
|
||||
{
|
||||
/* Unmap all the pages. */
|
||||
for (i = 0; i < RegionSize; i++)
|
||||
{
|
||||
MmDeleteVirtualMapping(NULL,
|
||||
(char*)BaseAddress + (i * PAGE_SIZE),
|
||||
FALSE,
|
||||
NULL,
|
||||
NULL);
|
||||
}
|
||||
(char*)BaseAddress + (i * PAGE_SIZE),
|
||||
FALSE,
|
||||
NULL,
|
||||
NULL);
|
||||
}
|
||||
|
||||
if ((DWORD)BaseAddress >= KERNEL_BASE)
|
||||
{
|
||||
if ((DWORD)BaseAddress >= KERNEL_BASE)
|
||||
{
|
||||
KeAcquireSpinLock(&MiMdlMappingRegionLock, &oldIrql);
|
||||
/* Deallocate all the pages used. */
|
||||
Base = (ULONG)((char*)BaseAddress - (char*)MiMdlMappingRegionBase) / PAGE_SIZE;
|
||||
@@ -338,55 +344,55 @@ MmUnmapLockedPages(PVOID BaseAddress, PMDL Mdl)
|
||||
MiMdlMappingRegionHint = min (MiMdlMappingRegionHint, Base);
|
||||
|
||||
KeReleaseSpinLock(&MiMdlMappingRegionLock, oldIrql);
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
MEMORY_AREA *Marea;
|
||||
|
||||
Marea = MmOpenMemoryAreaByAddress( &CurrentProcess->AddressSpace, BaseAddress );
|
||||
if (Marea == NULL)
|
||||
{
|
||||
DPRINT1( "Couldn't open memory area when unmapping user-space pages!\n" );
|
||||
KEBUGCHECK(0);
|
||||
}
|
||||
{
|
||||
DPRINT1( "Couldn't open memory area when unmapping user-space pages!\n" );
|
||||
KEBUGCHECK(0);
|
||||
}
|
||||
|
||||
MmFreeMemoryArea( &CurrentProcess->AddressSpace, Marea->BaseAddress, 0, NULL, NULL );
|
||||
|
||||
if (CurrentProcess != OldProcess)
|
||||
{
|
||||
KeDetachProcess();
|
||||
}
|
||||
}
|
||||
{
|
||||
KeDetachProcess();
|
||||
}
|
||||
}
|
||||
|
||||
/* Reset the MDL state. */
|
||||
Mdl->MdlFlags = Mdl->MdlFlags & ~MDL_MAPPED_TO_SYSTEM_VA;
|
||||
Mdl->MappedSystemVa = NULL;
|
||||
/* Reset the MDL state. */
|
||||
Mdl->MdlFlags = Mdl->MdlFlags & ~MDL_MAPPED_TO_SYSTEM_VA;
|
||||
Mdl->MappedSystemVa = NULL;
|
||||
}
|
||||
|
||||
|
||||
VOID
|
||||
VOID
|
||||
MmBuildMdlFromPages(PMDL Mdl, PULONG Pages)
|
||||
{
|
||||
ULONG i;
|
||||
PULONG MdlPages;
|
||||
|
||||
Mdl->MdlFlags = Mdl->MdlFlags |
|
||||
(MDL_PAGES_LOCKED | MDL_IO_PAGE_READ);
|
||||
|
||||
|
||||
Mdl->MdlFlags = Mdl->MdlFlags |
|
||||
(MDL_PAGES_LOCKED | MDL_IO_PAGE_READ);
|
||||
|
||||
MdlPages = (PULONG)(Mdl + 1);
|
||||
|
||||
|
||||
for (i=0;i<(PAGE_ROUND_UP(Mdl->ByteOffset+Mdl->ByteCount)/PAGE_SIZE);i++)
|
||||
{
|
||||
MdlPages[i] = Pages[i];
|
||||
}
|
||||
{
|
||||
MdlPages[i] = Pages[i];
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* @unimplemented
|
||||
*/
|
||||
VOID STDCALL MmProbeAndLockPages (PMDL Mdl,
|
||||
KPROCESSOR_MODE AccessMode,
|
||||
LOCK_OPERATION Operation)
|
||||
KPROCESSOR_MODE AccessMode,
|
||||
LOCK_OPERATION Operation)
|
||||
/*
|
||||
* FUNCTION: Probes the specified pages, makes them resident and locks them
|
||||
* ARGUMENTS:
|
||||
@@ -403,106 +409,113 @@ VOID STDCALL MmProbeAndLockPages (PMDL Mdl,
|
||||
PEPROCESS CurrentProcess = NULL;
|
||||
|
||||
DPRINT("MmProbeAndLockPages(Mdl %x)\n", Mdl);
|
||||
|
||||
|
||||
/*
|
||||
* FIXME: Check behaviour against NT
|
||||
*/
|
||||
if (Mdl->MdlFlags & MDL_PAGES_LOCKED)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (Mdl->StartVa >= (PVOID)KERNEL_BASE)
|
||||
{
|
||||
Mode = KernelMode;
|
||||
}
|
||||
{
|
||||
Mode = KernelMode;
|
||||
}
|
||||
else
|
||||
{
|
||||
Mode = UserMode;
|
||||
CurrentProcess = PsGetCurrentProcess();
|
||||
if (Mdl->Process != CurrentProcess)
|
||||
{
|
||||
KeAttachProcess(Mdl->Process);
|
||||
}
|
||||
}
|
||||
{
|
||||
Mode = UserMode;
|
||||
CurrentProcess = PsGetCurrentProcess();
|
||||
if (Mdl->Process != CurrentProcess)
|
||||
{
|
||||
KeAttachProcess(Mdl->Process);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Lock the pages
|
||||
*/
|
||||
|
||||
MmLockAddressSpace(&Mdl->Process->AddressSpace);
|
||||
MdlPages = (ULONG *)(Mdl + 1);
|
||||
MdlPages = (ULONG *)(Mdl + 1);
|
||||
NrPages = PAGE_ROUND_UP(Mdl->ByteOffset + Mdl->ByteCount) / PAGE_SIZE;
|
||||
for (i = 0; i < NrPages; i++)
|
||||
{
|
||||
PVOID Address;
|
||||
|
||||
Address = (char*)Mdl->StartVa + (i*PAGE_SIZE);
|
||||
|
||||
if (!MmIsPagePresent(NULL, Address))
|
||||
{
|
||||
Status = MmNotPresentFault(Mode, (ULONG)Address, TRUE);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
for (j = 0; j < i; j++)
|
||||
{
|
||||
{
|
||||
PVOID Address;
|
||||
|
||||
Address = (char*)Mdl->StartVa + (i*PAGE_SIZE);
|
||||
|
||||
if (!MmIsPagePresent(NULL, Address))
|
||||
{
|
||||
Status = MmNotPresentFault(Mode, (ULONG)Address, TRUE);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
for (j = 0; j < i; j++)
|
||||
{
|
||||
#if defined(__GNUC__)
|
||||
MmUnlockPage((LARGE_INTEGER)(LONGLONG)MdlPages[j]);
|
||||
MmDereferencePage((LARGE_INTEGER)(LONGLONG)MdlPages[j]);
|
||||
MmUnlockPage((LARGE_INTEGER)(LONGLONG)MdlPages[j]);
|
||||
MmDereferencePage((LARGE_INTEGER)(LONGLONG)MdlPages[j]);
|
||||
#else
|
||||
PHYSICAL_ADDRESS dummyJunkNeeded;
|
||||
dummyJunkNeeded.QuadPart = MdlPages[j];
|
||||
MmUnlockPage(dummyJunkNeeded);
|
||||
MmDereferencePage(dummyJunkNeeded);
|
||||
|
||||
PHYSICAL_ADDRESS dummyJunkNeeded;
|
||||
dummyJunkNeeded.QuadPart = MdlPages[j];
|
||||
MmUnlockPage(dummyJunkNeeded);
|
||||
MmDereferencePage(dummyJunkNeeded);
|
||||
#endif
|
||||
}
|
||||
ExRaiseStatus(Status);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
MmLockPage(MmGetPhysicalAddressForProcess(NULL, Address));
|
||||
}
|
||||
if ((Operation == IoWriteAccess || Operation == IoModifyAccess) &&
|
||||
(!(MmGetPageProtect(NULL, (PVOID)Address) & PAGE_READWRITE)))
|
||||
{
|
||||
Status = MmAccessFault(Mode, (ULONG)Address, TRUE);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
for (j = 0; j < i; j++)
|
||||
{
|
||||
|
||||
}
|
||||
ExRaiseStatus(Status);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
MmLockPage(MmGetPhysicalAddressForProcess(NULL, Address));
|
||||
}
|
||||
if ((Operation == IoWriteAccess || Operation == IoModifyAccess) &&
|
||||
(!(MmGetPageProtect(NULL, (PVOID)Address) & PAGE_READWRITE)))
|
||||
{
|
||||
Status = MmAccessFault(Mode, (ULONG)Address, TRUE);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
for (j = 0; j < i; j++)
|
||||
{
|
||||
#if defined(__GNUC__)
|
||||
MmUnlockPage((LARGE_INTEGER)(LONGLONG)MdlPages[j]);
|
||||
MmDereferencePage(
|
||||
(LARGE_INTEGER)(LONGLONG)MdlPages[j]);
|
||||
MmUnlockPage((LARGE_INTEGER)(LONGLONG)MdlPages[j]);
|
||||
MmDereferencePage(
|
||||
(LARGE_INTEGER)(LONGLONG)MdlPages[j]);
|
||||
#else
|
||||
PHYSICAL_ADDRESS dummyJunkNeeded;
|
||||
dummyJunkNeeded.QuadPart = MdlPages[j];
|
||||
MmUnlockPage(dummyJunkNeeded);
|
||||
MmDereferencePage(dummyJunkNeeded);
|
||||
|
||||
PHYSICAL_ADDRESS dummyJunkNeeded;
|
||||
dummyJunkNeeded.QuadPart = MdlPages[j];
|
||||
MmUnlockPage(dummyJunkNeeded);
|
||||
MmDereferencePage(dummyJunkNeeded);
|
||||
#endif
|
||||
}
|
||||
ExRaiseStatus(Status);
|
||||
}
|
||||
}
|
||||
MdlPages[i] = MmGetPhysicalAddressForProcess(NULL, Address).u.LowPart;
|
||||
|
||||
}
|
||||
ExRaiseStatus(Status);
|
||||
}
|
||||
}
|
||||
MdlPages[i] = MmGetPhysicalAddressForProcess(NULL, Address).u.LowPart;
|
||||
#if defined(__GNUC__)
|
||||
MmReferencePage((LARGE_INTEGER)(LONGLONG)MdlPages[i]);
|
||||
|
||||
MmReferencePage((LARGE_INTEGER)(LONGLONG)MdlPages[i]);
|
||||
#else
|
||||
{
|
||||
PHYSICAL_ADDRESS dummyJunkNeeded;
|
||||
dummyJunkNeeded.QuadPart = MdlPages[i];
|
||||
MmReferencePage(dummyJunkNeeded);
|
||||
}
|
||||
|
||||
{
|
||||
PHYSICAL_ADDRESS dummyJunkNeeded;
|
||||
dummyJunkNeeded.QuadPart = MdlPages[i];
|
||||
MmReferencePage(dummyJunkNeeded);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
MmUnlockAddressSpace(&Mdl->Process->AddressSpace);
|
||||
if (Mode == UserMode && Mdl->Process != CurrentProcess)
|
||||
{
|
||||
KeDetachProcess();
|
||||
}
|
||||
{
|
||||
KeDetachProcess();
|
||||
}
|
||||
Mdl->MdlFlags = Mdl->MdlFlags | MDL_PAGES_LOCKED;
|
||||
}
|
||||
|
||||
@@ -510,8 +523,8 @@ VOID STDCALL MmProbeAndLockPages (PMDL Mdl,
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
ULONG STDCALL MmSizeOfMdl (PVOID Base,
|
||||
ULONG Length)
|
||||
ULONG STDCALL MmSizeOfMdl (PVOID Base,
|
||||
ULONG Length)
|
||||
/*
|
||||
* FUNCTION: Returns the number of bytes to allocate for an MDL describing
|
||||
* the given address range
|
||||
@@ -521,9 +534,9 @@ ULONG STDCALL MmSizeOfMdl (PVOID Base,
|
||||
*/
|
||||
{
|
||||
ULONG len;
|
||||
|
||||
|
||||
len = ADDRESS_AND_SIZE_TO_SPAN_PAGES(Base,Length);
|
||||
|
||||
|
||||
return(sizeof(MDL)+(len*sizeof(ULONG)));
|
||||
}
|
||||
|
||||
@@ -531,8 +544,8 @@ ULONG STDCALL MmSizeOfMdl (PVOID Base,
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
VOID STDCALL
|
||||
MmBuildMdlForNonPagedPool (PMDL Mdl)
|
||||
VOID STDCALL
|
||||
MmBuildMdlForNonPagedPool (PMDL Mdl)
|
||||
/*
|
||||
* FUNCTION: Fills in the corresponding physical page array of a given
|
||||
* MDL for a buffer in nonpaged system space
|
||||
@@ -542,13 +555,13 @@ MmBuildMdlForNonPagedPool (PMDL Mdl)
|
||||
*/
|
||||
{
|
||||
ULONG va;
|
||||
Mdl->MdlFlags = Mdl->MdlFlags |
|
||||
(MDL_SOURCE_IS_NONPAGED_POOL | MDL_PAGES_LOCKED);
|
||||
Mdl->MdlFlags = Mdl->MdlFlags |
|
||||
(MDL_SOURCE_IS_NONPAGED_POOL | MDL_PAGES_LOCKED);
|
||||
for (va=0; va < ((Mdl->Size - sizeof(MDL)) / sizeof(ULONG)); va++)
|
||||
{
|
||||
((PULONG)(Mdl + 1))[va] =
|
||||
(MmGetPhysicalAddress((char*)Mdl->StartVa + (va * PAGE_SIZE))).u.LowPart;
|
||||
}
|
||||
{
|
||||
((PULONG)(Mdl + 1))[va] =
|
||||
(MmGetPhysicalAddress((char*)Mdl->StartVa + (va * PAGE_SIZE))).u.LowPart;
|
||||
}
|
||||
Mdl->MappedSystemVa = (char*)Mdl->StartVa + Mdl->ByteOffset;
|
||||
}
|
||||
|
||||
@@ -556,10 +569,10 @@ MmBuildMdlForNonPagedPool (PMDL Mdl)
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
PMDL STDCALL
|
||||
MmCreateMdl (PMDL MemoryDescriptorList,
|
||||
PVOID Base,
|
||||
ULONG Length)
|
||||
PMDL STDCALL
|
||||
MmCreateMdl (PMDL MemoryDescriptorList,
|
||||
PVOID Base,
|
||||
ULONG Length)
|
||||
/*
|
||||
* FUNCTION: Allocates and initalizes an MDL
|
||||
* ARGUMENTS:
|
||||
@@ -571,17 +584,17 @@ MmCreateMdl (PMDL MemoryDescriptorList,
|
||||
*/
|
||||
{
|
||||
if (MemoryDescriptorList == NULL)
|
||||
{
|
||||
ULONG Size;
|
||||
|
||||
Size = MmSizeOfMdl(Base,Length);
|
||||
MemoryDescriptorList =
|
||||
(PMDL)ExAllocatePoolWithTag(NonPagedPool, Size, TAG_MDL);
|
||||
if (MemoryDescriptorList == NULL)
|
||||
{
|
||||
return(NULL);
|
||||
}
|
||||
}
|
||||
{
|
||||
ULONG Size;
|
||||
|
||||
Size = MmSizeOfMdl(Base,Length);
|
||||
MemoryDescriptorList =
|
||||
(PMDL)ExAllocatePoolWithTag(NonPagedPool, Size, TAG_MDL);
|
||||
if (MemoryDescriptorList == NULL)
|
||||
{
|
||||
return(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
MmInitializeMdl(MemoryDescriptorList, (char*)Base, Length);
|
||||
|
||||
@@ -591,8 +604,8 @@ MmCreateMdl (PMDL MemoryDescriptorList,
|
||||
/*
|
||||
* @unimplemented
|
||||
*/
|
||||
VOID STDCALL
|
||||
MmMapMemoryDumpMdl (PVOID Unknown0)
|
||||
VOID STDCALL
|
||||
MmMapMemoryDumpMdl (PVOID Unknown0)
|
||||
/*
|
||||
* FIXME: Has something to do with crash dumps. Do we want to implement
|
||||
* this?
|
||||
@@ -603,30 +616,30 @@ MmMapMemoryDumpMdl (PVOID Unknown0)
|
||||
|
||||
PMDL STDCALL
|
||||
MmAllocatePagesForMdl ( IN PHYSICAL_ADDRESS LowAddress,
|
||||
IN PHYSICAL_ADDRESS HighAddress,
|
||||
IN PHYSICAL_ADDRESS SkipBytes,
|
||||
IN SIZE_T Totalbytes )
|
||||
IN PHYSICAL_ADDRESS HighAddress,
|
||||
IN PHYSICAL_ADDRESS SkipBytes,
|
||||
IN SIZE_T Totalbytes )
|
||||
{
|
||||
DPRINT1("MmAllocatePagesForMdl(): Unimplemented.\n");
|
||||
return(NULL);
|
||||
DPRINT1("MmAllocatePagesForMdl(): Unimplemented.\n");
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
VOID STDCALL
|
||||
MmFreePagesFromMdl ( IN PMDL Mdl )
|
||||
{
|
||||
DPRINT1("MmFreePagesFromMdl(): Unimplemented.\n");
|
||||
DPRINT1("MmFreePagesFromMdl(): Unimplemented.\n");
|
||||
}
|
||||
|
||||
PVOID STDCALL
|
||||
MmMapLockedPagesSpecifyCache ( IN PMDL Mdl,
|
||||
IN KPROCESSOR_MODE AccessMode,
|
||||
IN MEMORY_CACHING_TYPE CacheType,
|
||||
IN PVOID BaseAddress,
|
||||
IN ULONG BugCheckOnFailure,
|
||||
IN ULONG Priority )
|
||||
IN KPROCESSOR_MODE AccessMode,
|
||||
IN MEMORY_CACHING_TYPE CacheType,
|
||||
IN PVOID BaseAddress,
|
||||
IN ULONG BugCheckOnFailure,
|
||||
IN ULONG Priority )
|
||||
{
|
||||
DPRINT1("MmMapLockedPagesSpecifyCache(): Ignoring extra parameters.\n");
|
||||
return MmMapLockedPages (Mdl, AccessMode);
|
||||
DPRINT1("MmMapLockedPagesSpecifyCache(): Ignoring extra parameters.\n");
|
||||
return MmMapLockedPages (Mdl, AccessMode);
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
||||
+262
-262
@@ -16,7 +16,7 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
/* $Id: mm.c,v 1.72 2004/04/08 20:49:15 jfilby Exp $
|
||||
/* $Id: mm.c,v 1.73 2004/04/10 22:35:25 gdalsnes Exp $
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top directory
|
||||
* PROJECT: ReactOS kernel
|
||||
@@ -53,41 +53,41 @@ MM_STATS MmStats;
|
||||
NTSTATUS MmReleaseMemoryArea(PEPROCESS Process, PMEMORY_AREA Marea)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
|
||||
|
||||
DPRINT("MmReleaseMemoryArea(Process %x, Marea %x)\n",Process,Marea);
|
||||
|
||||
|
||||
DPRINT("Releasing %x between %x %x (type %d)\n",
|
||||
Marea, Marea->BaseAddress, (char*)Marea->BaseAddress + Marea->Length,
|
||||
Marea->Type);
|
||||
|
||||
Marea, Marea->BaseAddress, (char*)Marea->BaseAddress + Marea->Length,
|
||||
Marea->Type);
|
||||
|
||||
switch (Marea->Type)
|
||||
{
|
||||
case MEMORY_AREA_SECTION_VIEW:
|
||||
Status = MmUnmapViewOfSection(Process, Marea->BaseAddress);
|
||||
assert(Status == STATUS_SUCCESS);
|
||||
return(STATUS_SUCCESS);
|
||||
{
|
||||
case MEMORY_AREA_SECTION_VIEW:
|
||||
Status = MmUnmapViewOfSection(Process, Marea->BaseAddress);
|
||||
assert(Status == STATUS_SUCCESS);
|
||||
return(STATUS_SUCCESS);
|
||||
|
||||
case MEMORY_AREA_VIRTUAL_MEMORY:
|
||||
MmFreeVirtualMemory(Process, Marea);
|
||||
break;
|
||||
case MEMORY_AREA_VIRTUAL_MEMORY:
|
||||
MmFreeVirtualMemory(Process, Marea);
|
||||
break;
|
||||
|
||||
case MEMORY_AREA_SHARED_DATA:
|
||||
case MEMORY_AREA_NO_ACCESS:
|
||||
Status = MmFreeMemoryArea(&Process->AddressSpace,
|
||||
Marea->BaseAddress,
|
||||
0,
|
||||
NULL,
|
||||
NULL);
|
||||
break;
|
||||
case MEMORY_AREA_SHARED_DATA:
|
||||
case MEMORY_AREA_NO_ACCESS:
|
||||
Status = MmFreeMemoryArea(&Process->AddressSpace,
|
||||
Marea->BaseAddress,
|
||||
0,
|
||||
NULL,
|
||||
NULL);
|
||||
break;
|
||||
|
||||
case MEMORY_AREA_MDL_MAPPING:
|
||||
KEBUGCHECK(PROCESS_HAS_LOCKED_PAGES);
|
||||
break;
|
||||
case MEMORY_AREA_MDL_MAPPING:
|
||||
KEBUGCHECK(PROCESS_HAS_LOCKED_PAGES);
|
||||
break;
|
||||
|
||||
default:
|
||||
KEBUGCHECK(0);
|
||||
}
|
||||
|
||||
default:
|
||||
KEBUGCHECK(0);
|
||||
}
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
@@ -95,24 +95,24 @@ NTSTATUS MmReleaseMmInfo(PEPROCESS Process)
|
||||
{
|
||||
PLIST_ENTRY CurrentEntry;
|
||||
PMEMORY_AREA Current;
|
||||
|
||||
|
||||
DPRINT("MmReleaseMmInfo(Process %x (%s))\n", Process,
|
||||
Process->ImageFileName);
|
||||
|
||||
Process->ImageFileName);
|
||||
|
||||
MmLockAddressSpace(&Process->AddressSpace);
|
||||
|
||||
while(!IsListEmpty(&Process->AddressSpace.MAreaListHead))
|
||||
{
|
||||
CurrentEntry = Process->AddressSpace.MAreaListHead.Flink;
|
||||
Current = CONTAINING_RECORD(CurrentEntry, MEMORY_AREA, Entry);
|
||||
MmReleaseMemoryArea(Process, Current);
|
||||
}
|
||||
|
||||
{
|
||||
CurrentEntry = Process->AddressSpace.MAreaListHead.Flink;
|
||||
Current = CONTAINING_RECORD(CurrentEntry, MEMORY_AREA, Entry);
|
||||
MmReleaseMemoryArea(Process, Current);
|
||||
}
|
||||
|
||||
Mmi386ReleaseMmInfo(Process);
|
||||
|
||||
|
||||
MmUnlockAddressSpace(&Process->AddressSpace);
|
||||
MmDestroyAddressSpace(&Process->AddressSpace);
|
||||
|
||||
|
||||
DPRINT("Finished MmReleaseMmInfo()\n");
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
@@ -142,282 +142,282 @@ BOOLEAN STDCALL MmIsAddressValid(PVOID VirtualAddress)
|
||||
{
|
||||
MEMORY_AREA* MemoryArea;
|
||||
PMADDRESS_SPACE AddressSpace;
|
||||
|
||||
|
||||
if ((ULONG)VirtualAddress >= KERNEL_BASE)
|
||||
{
|
||||
AddressSpace = MmGetKernelAddressSpace();
|
||||
}
|
||||
{
|
||||
AddressSpace = MmGetKernelAddressSpace();
|
||||
}
|
||||
else
|
||||
{
|
||||
AddressSpace = &PsGetCurrentProcess()->AddressSpace;
|
||||
}
|
||||
|
||||
{
|
||||
AddressSpace = &PsGetCurrentProcess()->AddressSpace;
|
||||
}
|
||||
|
||||
MmLockAddressSpace(AddressSpace);
|
||||
MemoryArea = MmOpenMemoryAreaByAddress(AddressSpace,
|
||||
VirtualAddress);
|
||||
|
||||
VirtualAddress);
|
||||
|
||||
if (MemoryArea == NULL || MemoryArea->DeleteInProgress)
|
||||
{
|
||||
MmUnlockAddressSpace(AddressSpace);
|
||||
return(FALSE);
|
||||
}
|
||||
{
|
||||
MmUnlockAddressSpace(AddressSpace);
|
||||
return(FALSE);
|
||||
}
|
||||
MmUnlockAddressSpace(AddressSpace);
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
NTSTATUS MmAccessFault(KPROCESSOR_MODE Mode,
|
||||
ULONG Address,
|
||||
BOOLEAN FromMdl)
|
||||
ULONG Address,
|
||||
BOOLEAN FromMdl)
|
||||
{
|
||||
PMADDRESS_SPACE AddressSpace;
|
||||
MEMORY_AREA* MemoryArea;
|
||||
NTSTATUS Status;
|
||||
BOOLEAN Locked = FromMdl;
|
||||
|
||||
|
||||
DPRINT("MmAccessFault(Mode %d, Address %x)\n", Mode, Address);
|
||||
|
||||
|
||||
if (KeGetCurrentIrql() >= DISPATCH_LEVEL)
|
||||
{
|
||||
DbgPrint("Page fault at high IRQL was %d\n", KeGetCurrentIrql());
|
||||
return(STATUS_UNSUCCESSFUL);
|
||||
}
|
||||
{
|
||||
DbgPrint("Page fault at high IRQL was %d\n", KeGetCurrentIrql());
|
||||
return(STATUS_UNSUCCESSFUL);
|
||||
}
|
||||
if (PsGetCurrentProcess() == NULL)
|
||||
{
|
||||
DbgPrint("No current process\n");
|
||||
return(STATUS_UNSUCCESSFUL);
|
||||
}
|
||||
|
||||
{
|
||||
DbgPrint("No current process\n");
|
||||
return(STATUS_UNSUCCESSFUL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the memory area for the faulting address
|
||||
*/
|
||||
if (Address >= KERNEL_BASE)
|
||||
{
|
||||
/*
|
||||
* Check permissions
|
||||
*/
|
||||
if (Mode != KernelMode)
|
||||
{
|
||||
DbgPrint("%s:%d\n",__FILE__,__LINE__);
|
||||
return(STATUS_UNSUCCESSFUL);
|
||||
}
|
||||
AddressSpace = MmGetKernelAddressSpace();
|
||||
}
|
||||
{
|
||||
/*
|
||||
* Check permissions
|
||||
*/
|
||||
if (Mode != KernelMode)
|
||||
{
|
||||
DbgPrint("%s:%d\n",__FILE__,__LINE__);
|
||||
return(STATUS_UNSUCCESSFUL);
|
||||
}
|
||||
AddressSpace = MmGetKernelAddressSpace();
|
||||
}
|
||||
else
|
||||
{
|
||||
AddressSpace = &PsGetCurrentProcess()->AddressSpace;
|
||||
}
|
||||
|
||||
{
|
||||
AddressSpace = &PsGetCurrentProcess()->AddressSpace;
|
||||
}
|
||||
|
||||
if (!FromMdl)
|
||||
{
|
||||
MmLockAddressSpace(AddressSpace);
|
||||
}
|
||||
{
|
||||
MmLockAddressSpace(AddressSpace);
|
||||
}
|
||||
do
|
||||
{
|
||||
MemoryArea = MmOpenMemoryAreaByAddress(AddressSpace, (PVOID)Address);
|
||||
if (MemoryArea == NULL || MemoryArea->DeleteInProgress)
|
||||
{
|
||||
if (!FromMdl)
|
||||
{
|
||||
MmUnlockAddressSpace(AddressSpace);
|
||||
}
|
||||
return (STATUS_UNSUCCESSFUL);
|
||||
}
|
||||
|
||||
switch (MemoryArea->Type)
|
||||
{
|
||||
case MEMORY_AREA_SYSTEM:
|
||||
Status = STATUS_UNSUCCESSFUL;
|
||||
break;
|
||||
{
|
||||
MemoryArea = MmOpenMemoryAreaByAddress(AddressSpace, (PVOID)Address);
|
||||
if (MemoryArea == NULL || MemoryArea->DeleteInProgress)
|
||||
{
|
||||
if (!FromMdl)
|
||||
{
|
||||
MmUnlockAddressSpace(AddressSpace);
|
||||
}
|
||||
return (STATUS_UNSUCCESSFUL);
|
||||
}
|
||||
|
||||
case MEMORY_AREA_PAGED_POOL:
|
||||
Status = STATUS_SUCCESS;
|
||||
break;
|
||||
switch (MemoryArea->Type)
|
||||
{
|
||||
case MEMORY_AREA_SYSTEM:
|
||||
Status = STATUS_UNSUCCESSFUL;
|
||||
break;
|
||||
|
||||
case MEMORY_AREA_SECTION_VIEW:
|
||||
Status = MmAccessFaultSectionView(AddressSpace,
|
||||
MemoryArea,
|
||||
(PVOID)Address,
|
||||
Locked);
|
||||
break;
|
||||
case MEMORY_AREA_PAGED_POOL:
|
||||
Status = STATUS_SUCCESS;
|
||||
break;
|
||||
|
||||
case MEMORY_AREA_VIRTUAL_MEMORY:
|
||||
Status = STATUS_UNSUCCESSFUL;
|
||||
break;
|
||||
case MEMORY_AREA_SECTION_VIEW:
|
||||
Status = MmAccessFaultSectionView(AddressSpace,
|
||||
MemoryArea,
|
||||
(PVOID)Address,
|
||||
Locked);
|
||||
break;
|
||||
|
||||
case MEMORY_AREA_SHARED_DATA:
|
||||
Status = STATUS_UNSUCCESSFUL;
|
||||
break;
|
||||
case MEMORY_AREA_VIRTUAL_MEMORY:
|
||||
Status = STATUS_UNSUCCESSFUL;
|
||||
break;
|
||||
|
||||
default:
|
||||
Status = STATUS_UNSUCCESSFUL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
case MEMORY_AREA_SHARED_DATA:
|
||||
Status = STATUS_UNSUCCESSFUL;
|
||||
break;
|
||||
|
||||
default:
|
||||
Status = STATUS_UNSUCCESSFUL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (Status == STATUS_MM_RESTART_OPERATION);
|
||||
|
||||
DPRINT("Completed page fault handling\n");
|
||||
if (!FromMdl)
|
||||
{
|
||||
MmUnlockAddressSpace(AddressSpace);
|
||||
}
|
||||
{
|
||||
MmUnlockAddressSpace(AddressSpace);
|
||||
}
|
||||
return(Status);
|
||||
}
|
||||
|
||||
NTSTATUS MmCommitPagedPoolAddress(PVOID Address, BOOLEAN Locked)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PHYSICAL_ADDRESS AllocatedPage;
|
||||
Status = MmRequestPageMemoryConsumer(MC_PPOOL, FALSE, &AllocatedPage);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PHYSICAL_ADDRESS AllocatedPage;
|
||||
Status = MmRequestPageMemoryConsumer(MC_PPOOL, FALSE, &AllocatedPage);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
MmUnlockAddressSpace(MmGetKernelAddressSpace());
|
||||
Status = MmRequestPageMemoryConsumer(MC_PPOOL, TRUE, &AllocatedPage);
|
||||
MmLockAddressSpace(MmGetKernelAddressSpace());
|
||||
}
|
||||
Status =
|
||||
MmCreateVirtualMapping(NULL,
|
||||
(PVOID)PAGE_ROUND_DOWN(Address),
|
||||
PAGE_READWRITE,
|
||||
AllocatedPage,
|
||||
FALSE);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
}
|
||||
Status =
|
||||
MmCreateVirtualMapping(NULL,
|
||||
(PVOID)PAGE_ROUND_DOWN(Address),
|
||||
PAGE_READWRITE,
|
||||
AllocatedPage,
|
||||
FALSE);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
MmUnlockAddressSpace(MmGetKernelAddressSpace());
|
||||
Status =
|
||||
MmCreateVirtualMapping(NULL,
|
||||
(PVOID)PAGE_ROUND_DOWN(Address),
|
||||
PAGE_READWRITE,
|
||||
AllocatedPage,
|
||||
FALSE);
|
||||
Status =
|
||||
MmCreateVirtualMapping(NULL,
|
||||
(PVOID)PAGE_ROUND_DOWN(Address),
|
||||
PAGE_READWRITE,
|
||||
AllocatedPage,
|
||||
FALSE);
|
||||
MmLockAddressSpace(MmGetKernelAddressSpace());
|
||||
}
|
||||
if (Locked)
|
||||
{
|
||||
}
|
||||
if (Locked)
|
||||
{
|
||||
MmLockPage(AllocatedPage);
|
||||
}
|
||||
return(Status);
|
||||
}
|
||||
return(Status);
|
||||
}
|
||||
|
||||
NTSTATUS MmNotPresentFault(KPROCESSOR_MODE Mode,
|
||||
ULONG Address,
|
||||
BOOLEAN FromMdl)
|
||||
ULONG Address,
|
||||
BOOLEAN FromMdl)
|
||||
{
|
||||
PMADDRESS_SPACE AddressSpace;
|
||||
MEMORY_AREA* MemoryArea;
|
||||
NTSTATUS Status;
|
||||
BOOLEAN Locked = FromMdl;
|
||||
|
||||
|
||||
DPRINT("MmNotPresentFault(Mode %d, Address %x)\n", Mode, Address);
|
||||
|
||||
|
||||
if (KeGetCurrentIrql() >= DISPATCH_LEVEL)
|
||||
{
|
||||
DbgPrint("Page fault at high IRQL was %d\n", KeGetCurrentIrql());
|
||||
return(STATUS_UNSUCCESSFUL);
|
||||
}
|
||||
{
|
||||
DbgPrint("Page fault at high IRQL was %d\n", KeGetCurrentIrql());
|
||||
return(STATUS_UNSUCCESSFUL);
|
||||
}
|
||||
if (PsGetCurrentProcess() == NULL)
|
||||
{
|
||||
DbgPrint("No current process\n");
|
||||
return(STATUS_UNSUCCESSFUL);
|
||||
}
|
||||
|
||||
{
|
||||
DbgPrint("No current process\n");
|
||||
return(STATUS_UNSUCCESSFUL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the memory area for the faulting address
|
||||
*/
|
||||
if (Address >= KERNEL_BASE)
|
||||
{
|
||||
/*
|
||||
* Check permissions
|
||||
*/
|
||||
if (Mode != KernelMode)
|
||||
{
|
||||
DbgPrint("%s:%d\n",__FILE__,__LINE__);
|
||||
return(STATUS_UNSUCCESSFUL);
|
||||
}
|
||||
AddressSpace = MmGetKernelAddressSpace();
|
||||
}
|
||||
{
|
||||
/*
|
||||
* Check permissions
|
||||
*/
|
||||
if (Mode != KernelMode)
|
||||
{
|
||||
DbgPrint("%s:%d\n",__FILE__,__LINE__);
|
||||
return(STATUS_UNSUCCESSFUL);
|
||||
}
|
||||
AddressSpace = MmGetKernelAddressSpace();
|
||||
}
|
||||
else
|
||||
{
|
||||
AddressSpace = &PsGetCurrentProcess()->AddressSpace;
|
||||
}
|
||||
|
||||
{
|
||||
AddressSpace = &PsGetCurrentProcess()->AddressSpace;
|
||||
}
|
||||
|
||||
if (!FromMdl)
|
||||
{
|
||||
MmLockAddressSpace(AddressSpace);
|
||||
}
|
||||
{
|
||||
MmLockAddressSpace(AddressSpace);
|
||||
}
|
||||
|
||||
/*
|
||||
* Call the memory area specific fault handler
|
||||
*/
|
||||
do
|
||||
{
|
||||
MemoryArea = MmOpenMemoryAreaByAddress(AddressSpace, (PVOID)Address);
|
||||
if (MemoryArea == NULL || MemoryArea->DeleteInProgress)
|
||||
{
|
||||
if (!FromMdl)
|
||||
{
|
||||
MmUnlockAddressSpace(AddressSpace);
|
||||
}
|
||||
return (STATUS_UNSUCCESSFUL);
|
||||
}
|
||||
{
|
||||
MemoryArea = MmOpenMemoryAreaByAddress(AddressSpace, (PVOID)Address);
|
||||
if (MemoryArea == NULL || MemoryArea->DeleteInProgress)
|
||||
{
|
||||
if (!FromMdl)
|
||||
{
|
||||
MmUnlockAddressSpace(AddressSpace);
|
||||
}
|
||||
return (STATUS_UNSUCCESSFUL);
|
||||
}
|
||||
|
||||
switch (MemoryArea->Type)
|
||||
{
|
||||
case MEMORY_AREA_PAGED_POOL:
|
||||
{
|
||||
Status = MmCommitPagedPoolAddress((PVOID)Address, Locked);
|
||||
break;
|
||||
}
|
||||
switch (MemoryArea->Type)
|
||||
{
|
||||
case MEMORY_AREA_PAGED_POOL:
|
||||
{
|
||||
Status = MmCommitPagedPoolAddress((PVOID)Address, Locked);
|
||||
break;
|
||||
}
|
||||
|
||||
case MEMORY_AREA_SYSTEM:
|
||||
Status = STATUS_UNSUCCESSFUL;
|
||||
break;
|
||||
|
||||
case MEMORY_AREA_SECTION_VIEW:
|
||||
Status = MmNotPresentFaultSectionView(AddressSpace,
|
||||
MemoryArea,
|
||||
(PVOID)Address,
|
||||
Locked);
|
||||
break;
|
||||
|
||||
case MEMORY_AREA_VIRTUAL_MEMORY:
|
||||
Status = MmNotPresentFaultVirtualMemory(AddressSpace,
|
||||
MemoryArea,
|
||||
(PVOID)Address,
|
||||
Locked);
|
||||
break;
|
||||
|
||||
case MEMORY_AREA_SHARED_DATA:
|
||||
Status =
|
||||
MmCreateVirtualMapping(PsGetCurrentProcess(),
|
||||
(PVOID)PAGE_ROUND_DOWN(Address),
|
||||
PAGE_READONLY,
|
||||
MmSharedDataPagePhysicalAddress,
|
||||
FALSE);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
MmUnlockAddressSpace(&PsGetCurrentProcess()->AddressSpace);
|
||||
Status =
|
||||
MmCreateVirtualMapping(PsGetCurrentProcess(),
|
||||
(PVOID)PAGE_ROUND_DOWN(Address),
|
||||
PAGE_READONLY,
|
||||
MmSharedDataPagePhysicalAddress,
|
||||
TRUE);
|
||||
MmLockAddressSpace(&PsGetCurrentProcess()->AddressSpace);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
Status = STATUS_UNSUCCESSFUL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
case MEMORY_AREA_SYSTEM:
|
||||
Status = STATUS_UNSUCCESSFUL;
|
||||
break;
|
||||
|
||||
case MEMORY_AREA_SECTION_VIEW:
|
||||
Status = MmNotPresentFaultSectionView(AddressSpace,
|
||||
MemoryArea,
|
||||
(PVOID)Address,
|
||||
Locked);
|
||||
break;
|
||||
|
||||
case MEMORY_AREA_VIRTUAL_MEMORY:
|
||||
Status = MmNotPresentFaultVirtualMemory(AddressSpace,
|
||||
MemoryArea,
|
||||
(PVOID)Address,
|
||||
Locked);
|
||||
break;
|
||||
|
||||
case MEMORY_AREA_SHARED_DATA:
|
||||
Status =
|
||||
MmCreateVirtualMapping(PsGetCurrentProcess(),
|
||||
(PVOID)PAGE_ROUND_DOWN(Address),
|
||||
PAGE_READONLY,
|
||||
MmSharedDataPagePhysicalAddress,
|
||||
FALSE);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
MmUnlockAddressSpace(&PsGetCurrentProcess()->AddressSpace);
|
||||
Status =
|
||||
MmCreateVirtualMapping(PsGetCurrentProcess(),
|
||||
(PVOID)PAGE_ROUND_DOWN(Address),
|
||||
PAGE_READONLY,
|
||||
MmSharedDataPagePhysicalAddress,
|
||||
TRUE);
|
||||
MmLockAddressSpace(&PsGetCurrentProcess()->AddressSpace);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
Status = STATUS_UNSUCCESSFUL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (Status == STATUS_MM_RESTART_OPERATION);
|
||||
|
||||
DPRINT("Completed page fault handling\n");
|
||||
if (!FromMdl)
|
||||
{
|
||||
MmUnlockAddressSpace(AddressSpace);
|
||||
}
|
||||
{
|
||||
MmUnlockAddressSpace(AddressSpace);
|
||||
}
|
||||
return(Status);
|
||||
}
|
||||
|
||||
@@ -427,24 +427,24 @@ NTSTATUS MmNotPresentFault(KPROCESSOR_MODE Mode,
|
||||
* @unimplemented
|
||||
*/
|
||||
DWORD STDCALL
|
||||
MmAdjustWorkingSetSize (DWORD Unknown0,
|
||||
DWORD Unknown1,
|
||||
DWORD Unknown2)
|
||||
MmAdjustWorkingSetSize (DWORD Unknown0,
|
||||
DWORD Unknown1,
|
||||
DWORD Unknown2)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return (0);
|
||||
UNIMPLEMENTED;
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
DWORD
|
||||
STDCALL
|
||||
MmDbgTranslatePhysicalAddress (
|
||||
DWORD Unknown0,
|
||||
DWORD Unknown1
|
||||
)
|
||||
DWORD Unknown0,
|
||||
DWORD Unknown1
|
||||
)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return (0);
|
||||
UNIMPLEMENTED;
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
@@ -454,11 +454,11 @@ MmDbgTranslatePhysicalAddress (
|
||||
NTSTATUS
|
||||
STDCALL
|
||||
MmGrowKernelStack (
|
||||
DWORD Unknown0
|
||||
)
|
||||
DWORD Unknown0
|
||||
)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return (STATUS_NOT_IMPLEMENTED);
|
||||
UNIMPLEMENTED;
|
||||
return (STATUS_NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
|
||||
@@ -468,12 +468,12 @@ MmGrowKernelStack (
|
||||
BOOLEAN
|
||||
STDCALL
|
||||
MmSetAddressRangeModified (
|
||||
DWORD Unknown0,
|
||||
DWORD Unknown1
|
||||
)
|
||||
DWORD Unknown0,
|
||||
DWORD Unknown1
|
||||
)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return (FALSE);
|
||||
UNIMPLEMENTED;
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
||||
+199
-197
@@ -1,4 +1,4 @@
|
||||
/* $Id: mminit.c,v 1.62 2004/03/16 22:45:56 dwelch Exp $
|
||||
/* $Id: mminit.c,v 1.63 2004/04/10 22:35:25 gdalsnes Exp $
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top directory
|
||||
* PROJECT: ReactOS kernel
|
||||
@@ -48,7 +48,7 @@ static MEMORY_AREA* kernel_data_desc = NULL;
|
||||
static MEMORY_AREA* kernel_param_desc = NULL;
|
||||
static MEMORY_AREA* kernel_pool_desc = NULL;
|
||||
static MEMORY_AREA* kernel_shared_data_desc = NULL;
|
||||
static MEMORY_AREA* kernel_mapped_vga_framebuffer_desc = NULL;
|
||||
static MEMORY_AREA* kernel_mapped_vga_framebuffer_desc = NULL;
|
||||
static MEMORY_AREA* MiKernelMapDescriptor = NULL;
|
||||
static MEMORY_AREA* MiPagedPoolDescriptor = NULL;
|
||||
|
||||
@@ -78,12 +78,11 @@ MM_SYSTEM_SIZE STDCALL MmQuerySystemSize(VOID)
|
||||
}
|
||||
|
||||
VOID MiShutdownMemoryManager(VOID)
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
VOID INIT_FUNCTION
|
||||
MmInitVirtualMemory(ULONG LastKernelAddress,
|
||||
ULONG KernelLength)
|
||||
ULONG KernelLength)
|
||||
/*
|
||||
* FUNCTION: Intialize the memory areas list
|
||||
* ARGUMENTS:
|
||||
@@ -97,9 +96,9 @@ MmInitVirtualMemory(ULONG LastKernelAddress,
|
||||
NTSTATUS Status;
|
||||
PHYSICAL_ADDRESS BoundaryAddressMultiple;
|
||||
//ULONG i;
|
||||
|
||||
|
||||
DPRINT("MmInitVirtualMemory(%x, %x)\n",LastKernelAddress, KernelLength);
|
||||
|
||||
|
||||
BoundaryAddressMultiple.QuadPart = 0;
|
||||
LastKernelAddress = PAGE_ROUND_UP(LastKernelAddress);
|
||||
|
||||
@@ -124,58 +123,58 @@ MmInitVirtualMemory(ULONG LastKernelAddress,
|
||||
*/
|
||||
BaseAddress = (PVOID)0xf0000000;
|
||||
MmCreateMemoryArea(NULL,
|
||||
MmGetKernelAddressSpace(),
|
||||
MEMORY_AREA_SYSTEM,
|
||||
&BaseAddress,
|
||||
0x400000,
|
||||
0,
|
||||
&kernel_map_desc,
|
||||
FALSE,
|
||||
FALSE,
|
||||
BoundaryAddressMultiple);
|
||||
MmGetKernelAddressSpace(),
|
||||
MEMORY_AREA_SYSTEM,
|
||||
&BaseAddress,
|
||||
0x400000,
|
||||
0,
|
||||
&kernel_map_desc,
|
||||
FALSE,
|
||||
FALSE,
|
||||
BoundaryAddressMultiple);
|
||||
|
||||
BaseAddress = (PVOID)KPCR_BASE;
|
||||
MmCreateMemoryArea(NULL,
|
||||
MmGetKernelAddressSpace(),
|
||||
MEMORY_AREA_SYSTEM,
|
||||
&BaseAddress,
|
||||
PAGE_SIZE * MAXIMUM_PROCESSORS,
|
||||
0,
|
||||
&kernel_kpcr_desc,
|
||||
FALSE,
|
||||
FALSE,
|
||||
BoundaryAddressMultiple);
|
||||
MmGetKernelAddressSpace(),
|
||||
MEMORY_AREA_SYSTEM,
|
||||
&BaseAddress,
|
||||
PAGE_SIZE * MAXIMUM_PROCESSORS,
|
||||
0,
|
||||
&kernel_kpcr_desc,
|
||||
FALSE,
|
||||
FALSE,
|
||||
BoundaryAddressMultiple);
|
||||
|
||||
BaseAddress = (PVOID)0xFF3A0000;
|
||||
MmCreateMemoryArea(NULL,
|
||||
MmGetKernelAddressSpace(),
|
||||
MEMORY_AREA_SYSTEM,
|
||||
&BaseAddress,
|
||||
0x20000,
|
||||
0,
|
||||
&kernel_mapped_vga_framebuffer_desc,
|
||||
FALSE,
|
||||
FALSE,
|
||||
BoundaryAddressMultiple);
|
||||
MmGetKernelAddressSpace(),
|
||||
MEMORY_AREA_SYSTEM,
|
||||
&BaseAddress,
|
||||
0x20000,
|
||||
0,
|
||||
&kernel_mapped_vga_framebuffer_desc,
|
||||
FALSE,
|
||||
FALSE,
|
||||
BoundaryAddressMultiple);
|
||||
|
||||
BaseAddress = (PVOID)KERNEL_BASE;
|
||||
Length = PAGE_ROUND_UP(((ULONG)&_text_end__)) - KERNEL_BASE;
|
||||
ParamLength = ParamLength - Length;
|
||||
|
||||
|
||||
/*
|
||||
* No need to lock the address space at this point since no
|
||||
* other threads are running.
|
||||
*/
|
||||
MmCreateMemoryArea(NULL,
|
||||
MmGetKernelAddressSpace(),
|
||||
MEMORY_AREA_SYSTEM,
|
||||
&BaseAddress,
|
||||
Length,
|
||||
0,
|
||||
&kernel_text_desc,
|
||||
FALSE,
|
||||
FALSE,
|
||||
BoundaryAddressMultiple);
|
||||
MmGetKernelAddressSpace(),
|
||||
MEMORY_AREA_SYSTEM,
|
||||
&BaseAddress,
|
||||
Length,
|
||||
0,
|
||||
&kernel_text_desc,
|
||||
FALSE,
|
||||
FALSE,
|
||||
BoundaryAddressMultiple);
|
||||
|
||||
BaseAddress = (PVOID)PAGE_ROUND_UP(((ULONG)&_text_end__));
|
||||
assert (BaseAddress == (PVOID)&_init_start__);
|
||||
@@ -184,17 +183,17 @@ MmInitVirtualMemory(ULONG LastKernelAddress,
|
||||
ParamLength = ParamLength - Length;
|
||||
|
||||
MmCreateMemoryArea(NULL,
|
||||
MmGetKernelAddressSpace(),
|
||||
MEMORY_AREA_SYSTEM,
|
||||
&BaseAddress,
|
||||
Length,
|
||||
0,
|
||||
&kernel_init_desc,
|
||||
FALSE,
|
||||
FALSE,
|
||||
BoundaryAddressMultiple);
|
||||
MmGetKernelAddressSpace(),
|
||||
MEMORY_AREA_SYSTEM,
|
||||
&BaseAddress,
|
||||
Length,
|
||||
0,
|
||||
&kernel_init_desc,
|
||||
FALSE,
|
||||
FALSE,
|
||||
BoundaryAddressMultiple);
|
||||
|
||||
Length = PAGE_ROUND_UP(((ULONG)&_bss_end__)) -
|
||||
Length = PAGE_ROUND_UP(((ULONG)&_bss_end__)) -
|
||||
PAGE_ROUND_UP(((ULONG)&_init_end__));
|
||||
ParamLength = ParamLength - Length;
|
||||
DPRINT("Length %x\n",Length);
|
||||
@@ -206,64 +205,64 @@ MmInitVirtualMemory(ULONG LastKernelAddress,
|
||||
* the only thread running.
|
||||
*/
|
||||
MmCreateMemoryArea(NULL,
|
||||
MmGetKernelAddressSpace(),
|
||||
MEMORY_AREA_SYSTEM,
|
||||
&BaseAddress,
|
||||
Length,
|
||||
0,
|
||||
&kernel_data_desc,
|
||||
FALSE,
|
||||
FALSE,
|
||||
BoundaryAddressMultiple);
|
||||
MmGetKernelAddressSpace(),
|
||||
MEMORY_AREA_SYSTEM,
|
||||
&BaseAddress,
|
||||
Length,
|
||||
0,
|
||||
&kernel_data_desc,
|
||||
FALSE,
|
||||
FALSE,
|
||||
BoundaryAddressMultiple);
|
||||
|
||||
BaseAddress = (PVOID)PAGE_ROUND_UP(((ULONG)&_bss_end__));
|
||||
Length = LastKernelAddress - (ULONG)BaseAddress;
|
||||
MmCreateMemoryArea(NULL,
|
||||
MmGetKernelAddressSpace(),
|
||||
MEMORY_AREA_SYSTEM,
|
||||
&BaseAddress,
|
||||
Length,
|
||||
0,
|
||||
&kernel_param_desc,
|
||||
FALSE,
|
||||
FALSE,
|
||||
BoundaryAddressMultiple);
|
||||
|
||||
MmGetKernelAddressSpace(),
|
||||
MEMORY_AREA_SYSTEM,
|
||||
&BaseAddress,
|
||||
Length,
|
||||
0,
|
||||
&kernel_param_desc,
|
||||
FALSE,
|
||||
FALSE,
|
||||
BoundaryAddressMultiple);
|
||||
|
||||
BaseAddress = MiNonPagedPoolStart;
|
||||
MmCreateMemoryArea(NULL,
|
||||
MmGetKernelAddressSpace(),
|
||||
MEMORY_AREA_SYSTEM,
|
||||
&BaseAddress,
|
||||
MiNonPagedPoolLength,
|
||||
0,
|
||||
&kernel_pool_desc,
|
||||
FALSE,
|
||||
FALSE,
|
||||
BoundaryAddressMultiple);
|
||||
MmGetKernelAddressSpace(),
|
||||
MEMORY_AREA_SYSTEM,
|
||||
&BaseAddress,
|
||||
MiNonPagedPoolLength,
|
||||
0,
|
||||
&kernel_pool_desc,
|
||||
FALSE,
|
||||
FALSE,
|
||||
BoundaryAddressMultiple);
|
||||
|
||||
BaseAddress = MiKernelMapStart;
|
||||
Status = MmCreateMemoryArea(NULL,
|
||||
MmGetKernelAddressSpace(),
|
||||
MEMORY_AREA_SYSTEM,
|
||||
&BaseAddress,
|
||||
MiKernelMapLength,
|
||||
0,
|
||||
&MiKernelMapDescriptor,
|
||||
FALSE,
|
||||
FALSE,
|
||||
BoundaryAddressMultiple);
|
||||
|
||||
MmGetKernelAddressSpace(),
|
||||
MEMORY_AREA_SYSTEM,
|
||||
&BaseAddress,
|
||||
MiKernelMapLength,
|
||||
0,
|
||||
&MiKernelMapDescriptor,
|
||||
FALSE,
|
||||
FALSE,
|
||||
BoundaryAddressMultiple);
|
||||
|
||||
BaseAddress = MmPagedPoolBase;
|
||||
Status = MmCreateMemoryArea(NULL,
|
||||
MmGetKernelAddressSpace(),
|
||||
MEMORY_AREA_PAGED_POOL,
|
||||
&BaseAddress,
|
||||
MmPagedPoolSize,
|
||||
0,
|
||||
&MiPagedPoolDescriptor,
|
||||
FALSE,
|
||||
FALSE,
|
||||
BoundaryAddressMultiple);
|
||||
MmGetKernelAddressSpace(),
|
||||
MEMORY_AREA_PAGED_POOL,
|
||||
&BaseAddress,
|
||||
MmPagedPoolSize,
|
||||
0,
|
||||
&MiPagedPoolDescriptor,
|
||||
FALSE,
|
||||
FALSE,
|
||||
BoundaryAddressMultiple);
|
||||
|
||||
MmInitializePagedPool();
|
||||
|
||||
@@ -273,27 +272,27 @@ MmInitVirtualMemory(ULONG LastKernelAddress,
|
||||
BaseAddress = (PVOID)KI_USER_SHARED_DATA;
|
||||
Length = PAGE_SIZE;
|
||||
MmCreateMemoryArea(NULL,
|
||||
MmGetKernelAddressSpace(),
|
||||
MEMORY_AREA_SYSTEM,
|
||||
&BaseAddress,
|
||||
Length,
|
||||
0,
|
||||
&kernel_shared_data_desc,
|
||||
FALSE,
|
||||
FALSE,
|
||||
BoundaryAddressMultiple);
|
||||
Status = MmRequestPageMemoryConsumer(MC_NPPOOL, TRUE,
|
||||
&MmSharedDataPagePhysicalAddress);
|
||||
MmGetKernelAddressSpace(),
|
||||
MEMORY_AREA_SYSTEM,
|
||||
&BaseAddress,
|
||||
Length,
|
||||
0,
|
||||
&kernel_shared_data_desc,
|
||||
FALSE,
|
||||
FALSE,
|
||||
BoundaryAddressMultiple);
|
||||
Status = MmRequestPageMemoryConsumer(MC_NPPOOL, TRUE,
|
||||
&MmSharedDataPagePhysicalAddress);
|
||||
Status = MmCreateVirtualMapping(NULL,
|
||||
(PVOID)KI_USER_SHARED_DATA,
|
||||
PAGE_READWRITE,
|
||||
MmSharedDataPagePhysicalAddress,
|
||||
TRUE);
|
||||
(PVOID)KI_USER_SHARED_DATA,
|
||||
PAGE_READWRITE,
|
||||
MmSharedDataPagePhysicalAddress,
|
||||
TRUE);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DbgPrint("Unable to create virtual mapping\n");
|
||||
KEBUGCHECK(0);
|
||||
}
|
||||
{
|
||||
DbgPrint("Unable to create virtual mapping\n");
|
||||
KEBUGCHECK(0);
|
||||
}
|
||||
RtlZeroMemory(BaseAddress, Length);
|
||||
|
||||
/*
|
||||
@@ -304,11 +303,11 @@ MmInitVirtualMemory(ULONG LastKernelAddress,
|
||||
|
||||
VOID INIT_FUNCTION
|
||||
MmInit1(ULONG FirstKrnlPhysAddr,
|
||||
ULONG LastKrnlPhysAddr,
|
||||
ULONG LastKernelAddress,
|
||||
PADDRESS_RANGE BIOSMemoryMap,
|
||||
ULONG AddressRangeCount,
|
||||
ULONG MaxMem)
|
||||
ULONG LastKrnlPhysAddr,
|
||||
ULONG LastKernelAddress,
|
||||
PADDRESS_RANGE BIOSMemoryMap,
|
||||
ULONG AddressRangeCount,
|
||||
ULONG MaxMem)
|
||||
/*
|
||||
* FUNCTION: Initalize memory managment
|
||||
*/
|
||||
@@ -316,37 +315,38 @@ MmInit1(ULONG FirstKrnlPhysAddr,
|
||||
ULONG i;
|
||||
ULONG kernel_len;
|
||||
#ifndef MP
|
||||
|
||||
extern unsigned int unmap_me, unmap_me2, unmap_me3;
|
||||
#endif
|
||||
|
||||
DPRINT("MmInit1(FirstKrnlPhysAddr, %x, LastKrnlPhysAddr %x, LastKernelAddress %x)\n",
|
||||
FirstKrnlPhysAddr,
|
||||
LastKrnlPhysAddr,
|
||||
LastKernelAddress);
|
||||
FirstKrnlPhysAddr,
|
||||
LastKrnlPhysAddr,
|
||||
LastKernelAddress);
|
||||
|
||||
|
||||
if ((BIOSMemoryMap != NULL) && (AddressRangeCount > 0))
|
||||
{
|
||||
// If we have a bios memory map, recalulate the memory size
|
||||
ULONG last = 0;
|
||||
for (i = 0; i < AddressRangeCount; i++)
|
||||
{
|
||||
if (BIOSMemoryMap[i].Type == 1
|
||||
&& (BIOSMemoryMap[i].BaseAddrLow + BIOSMemoryMap[i].LengthLow + PAGE_SIZE -1) / PAGE_SIZE > last)
|
||||
{
|
||||
last = (BIOSMemoryMap[i].BaseAddrLow + BIOSMemoryMap[i].LengthLow + PAGE_SIZE -1) / PAGE_SIZE;
|
||||
}
|
||||
}
|
||||
if ((last - 256) * 4 > KeLoaderBlock.MemHigher)
|
||||
{
|
||||
KeLoaderBlock.MemHigher = (last - 256) * 4;
|
||||
}
|
||||
}
|
||||
{
|
||||
// If we have a bios memory map, recalulate the memory size
|
||||
ULONG last = 0;
|
||||
for (i = 0; i < AddressRangeCount; i++)
|
||||
{
|
||||
if (BIOSMemoryMap[i].Type == 1
|
||||
&& (BIOSMemoryMap[i].BaseAddrLow + BIOSMemoryMap[i].LengthLow + PAGE_SIZE -1) / PAGE_SIZE > last)
|
||||
{
|
||||
last = (BIOSMemoryMap[i].BaseAddrLow + BIOSMemoryMap[i].LengthLow + PAGE_SIZE -1) / PAGE_SIZE;
|
||||
}
|
||||
}
|
||||
if ((last - 256) * 4 > KeLoaderBlock.MemHigher)
|
||||
{
|
||||
KeLoaderBlock.MemHigher = (last - 256) * 4;
|
||||
}
|
||||
}
|
||||
|
||||
if (KeLoaderBlock.MemHigher >= (MaxMem - 1) * 1024)
|
||||
{
|
||||
KeLoaderBlock.MemHigher = (MaxMem - 1) * 1024;
|
||||
}
|
||||
{
|
||||
KeLoaderBlock.MemHigher = (MaxMem - 1) * 1024;
|
||||
}
|
||||
|
||||
/*
|
||||
* FIXME: Set this based on the system command line
|
||||
@@ -354,7 +354,7 @@ MmInit1(ULONG FirstKrnlPhysAddr,
|
||||
MmSystemRangeStart = (PVOID)KERNEL_BASE; // 0xC0000000
|
||||
MmUserProbeAddress = (PVOID)0x7fff0000;
|
||||
MmHighestUserAddress = (PVOID)0x7ffeffff;
|
||||
|
||||
|
||||
MmInitGlobalKernelPageDirectory();
|
||||
|
||||
/*
|
||||
@@ -370,7 +370,7 @@ MmInit1(ULONG FirstKrnlPhysAddr,
|
||||
MmStats.PagingRequestsInLastMinute = 0;
|
||||
MmStats.PagingRequestsInLastFiveMinutes = 0;
|
||||
MmStats.PagingRequestsInLastFifteenMinutes = 0;
|
||||
|
||||
|
||||
/*
|
||||
* Initialize the kernel address space
|
||||
*/
|
||||
@@ -380,7 +380,7 @@ MmInit1(ULONG FirstKrnlPhysAddr,
|
||||
* Unmap low memory
|
||||
*/
|
||||
#ifndef MP
|
||||
/* In SMP mode we unmap the low memory in MmInit3.
|
||||
/* In SMP mode we unmap the low memory in MmInit3.
|
||||
The APIC needs the mapping of the first pages
|
||||
while the processors are starting up. */
|
||||
MmDeletePageTable(NULL, 0);
|
||||
@@ -391,35 +391,36 @@ MmInit1(ULONG FirstKrnlPhysAddr,
|
||||
* memory)
|
||||
*/
|
||||
DPRINT("first krnl %x\nlast krnl %x\n",FirstKrnlPhysAddr,
|
||||
LastKrnlPhysAddr);
|
||||
|
||||
LastKrnlPhysAddr);
|
||||
|
||||
/*
|
||||
* Free physical memory not used by the kernel
|
||||
*/
|
||||
MmStats.NrTotalPages = KeLoaderBlock.MemHigher/4;
|
||||
if (!MmStats.NrTotalPages)
|
||||
{
|
||||
DbgPrint("Memory not detected, default to 8 MB\n");
|
||||
MmStats.NrTotalPages = 2048;
|
||||
}
|
||||
{
|
||||
DbgPrint("Memory not detected, default to 8 MB\n");
|
||||
MmStats.NrTotalPages = 2048;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* add 1MB for standard memory (not extended) */
|
||||
MmStats.NrTotalPages += 256;
|
||||
}
|
||||
{
|
||||
/* add 1MB for standard memory (not extended) */
|
||||
MmStats.NrTotalPages += 256;
|
||||
}
|
||||
#ifdef BIOS_MEM_FIX
|
||||
MmStats.NrTotalPages += 16;
|
||||
#endif
|
||||
|
||||
DbgPrint("Used memory %dKb\n", (MmStats.NrTotalPages * PAGE_SIZE) / 1024);
|
||||
|
||||
LastKernelAddress = (ULONG)MmInitializePageList((PVOID)FirstKrnlPhysAddr,
|
||||
(PVOID)LastKrnlPhysAddr,
|
||||
MmStats.NrTotalPages,
|
||||
PAGE_ROUND_UP(LastKernelAddress),
|
||||
BIOSMemoryMap,
|
||||
AddressRangeCount);
|
||||
(PVOID)LastKrnlPhysAddr,
|
||||
MmStats.NrTotalPages,
|
||||
PAGE_ROUND_UP(LastKernelAddress),
|
||||
BIOSMemoryMap,
|
||||
AddressRangeCount);
|
||||
kernel_len = LastKrnlPhysAddr - FirstKrnlPhysAddr;
|
||||
|
||||
|
||||
/*
|
||||
* Create a trap for null pointer references and protect text
|
||||
* segment
|
||||
@@ -427,27 +428,27 @@ MmInit1(ULONG FirstKrnlPhysAddr,
|
||||
CHECKPOINT;
|
||||
DPRINT("_text_start__ %x _init_end__ %x\n",(int)&_text_start__,(int)&_init_end__);
|
||||
for (i=PAGE_ROUND_DOWN(((int)&_text_start__));
|
||||
i<PAGE_ROUND_UP(((int)&_init_end__));i=i+PAGE_SIZE)
|
||||
{
|
||||
MmSetPageProtect(NULL,
|
||||
(PVOID)i,
|
||||
PAGE_EXECUTE_READ);
|
||||
}
|
||||
i<PAGE_ROUND_UP(((int)&_init_end__));i=i+PAGE_SIZE)
|
||||
{
|
||||
MmSetPageProtect(NULL,
|
||||
(PVOID)i,
|
||||
PAGE_EXECUTE_READ);
|
||||
}
|
||||
|
||||
DPRINT("Invalidating between %x and %x\n",
|
||||
LastKernelAddress, 0xc0600000);
|
||||
LastKernelAddress, 0xc0600000);
|
||||
for (i=(LastKernelAddress); i<0xc0600000; i+=PAGE_SIZE)
|
||||
{
|
||||
MmRawDeleteVirtualMapping((PVOID)(i));
|
||||
}
|
||||
{
|
||||
MmRawDeleteVirtualMapping((PVOID)(i));
|
||||
}
|
||||
|
||||
DPRINT("Invalidating between %x and %x\n",
|
||||
0xd0100000, 0xd0400000);
|
||||
0xd0100000, 0xd0400000);
|
||||
for (i=0xd0100000; i<0xd0400000; i+=PAGE_SIZE)
|
||||
{
|
||||
MmRawDeleteVirtualMapping((PVOID)(i));
|
||||
}
|
||||
|
||||
{
|
||||
MmRawDeleteVirtualMapping((PVOID)(i));
|
||||
}
|
||||
|
||||
DPRINT("Almost done MmInit()\n");
|
||||
#ifndef MP
|
||||
/* FIXME: This is broken in SMP mode */
|
||||
@@ -479,10 +480,11 @@ MmInit3(VOID)
|
||||
* Unmap low memory
|
||||
*/
|
||||
#ifdef MP
|
||||
/* In SMP mode we can unmap the low memory
|
||||
/* In SMP mode we can unmap the low memory
|
||||
if all processors are started. */
|
||||
MmDeletePageTable(NULL, 0);
|
||||
#endif
|
||||
|
||||
MmInitZeroPageThread();
|
||||
MmCreatePhysicalMemorySection();
|
||||
MiInitBalancerThread();
|
||||
@@ -496,25 +498,25 @@ MmInit3(VOID)
|
||||
}
|
||||
|
||||
VOID STATIC
|
||||
MiFreeInitMemoryPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address,
|
||||
PHYSICAL_ADDRESS PhysAddr, SWAPENTRY SwapEntry,
|
||||
BOOLEAN Dirty)
|
||||
MiFreeInitMemoryPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address,
|
||||
PHYSICAL_ADDRESS PhysAddr, SWAPENTRY SwapEntry,
|
||||
BOOLEAN Dirty)
|
||||
{
|
||||
assert(SwapEntry == 0);
|
||||
if (PhysAddr.QuadPart != 0)
|
||||
{
|
||||
assert(SwapEntry == 0);
|
||||
if (PhysAddr.QuadPart != 0)
|
||||
{
|
||||
MmReleasePageMemoryConsumer(MC_NPPOOL, PhysAddr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
VOID
|
||||
MiFreeInitMemory(VOID)
|
||||
{
|
||||
MmLockAddressSpace(MmGetKernelAddressSpace());
|
||||
MmFreeMemoryArea(MmGetKernelAddressSpace(),
|
||||
(PVOID)&_init_start__,
|
||||
PAGE_ROUND_UP((ULONG)&_init_end__) - (ULONG)_init_start__,
|
||||
MiFreeInitMemoryPage,
|
||||
NULL);
|
||||
MmUnlockAddressSpace(MmGetKernelAddressSpace());
|
||||
MmLockAddressSpace(MmGetKernelAddressSpace());
|
||||
MmFreeMemoryArea(MmGetKernelAddressSpace(),
|
||||
(PVOID)&_init_start__,
|
||||
PAGE_ROUND_UP((ULONG)&_init_end__) - (ULONG)_init_start__,
|
||||
MiFreeInitMemoryPage,
|
||||
NULL);
|
||||
MmUnlockAddressSpace(MmGetKernelAddressSpace());
|
||||
}
|
||||
|
||||
+70
-66
@@ -16,7 +16,7 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
/* $Id: mpw.c,v 1.17 2003/12/30 18:52:05 fireball Exp $
|
||||
/* $Id: mpw.c,v 1.18 2004/04/10 22:35:25 gdalsnes Exp $
|
||||
*
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: ntoskrnl/mm/mpw.c
|
||||
@@ -49,100 +49,104 @@ static volatile BOOLEAN MpwThreadShouldTerminate;
|
||||
NTSTATUS STDCALL
|
||||
MmWriteDirtyPages(ULONG Target, PULONG Actual)
|
||||
{
|
||||
PHYSICAL_ADDRESS Page;
|
||||
PHYSICAL_ADDRESS NextPage;
|
||||
NTSTATUS Status;
|
||||
PHYSICAL_ADDRESS Page;
|
||||
PHYSICAL_ADDRESS NextPage;
|
||||
NTSTATUS Status;
|
||||
|
||||
Page = MmGetLRUFirstUserPage();
|
||||
Page = MmGetLRUFirstUserPage();
|
||||
#if defined(__GNUC__)
|
||||
while (Page.QuadPart != 0LL && Target > 0)
|
||||
|
||||
while (Page.QuadPart != 0LL && Target > 0)
|
||||
#else
|
||||
while (Page.QuadPart && Target > 0)
|
||||
|
||||
while (Page.QuadPart && Target > 0)
|
||||
#endif
|
||||
{
|
||||
|
||||
{
|
||||
/*
|
||||
* FIXME: While the current page is write back it is possible
|
||||
* that the next page is freed and not longer a user page.
|
||||
*/
|
||||
NextPage = MmGetLRUNextUserPage(Page);
|
||||
if (MmIsDirtyPageRmap(Page))
|
||||
{
|
||||
Status = MmWritePagePhysicalAddress(Page);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
Target--;
|
||||
}
|
||||
}
|
||||
{
|
||||
Status = MmWritePagePhysicalAddress(Page);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
Target--;
|
||||
}
|
||||
}
|
||||
Page = NextPage;
|
||||
}
|
||||
*Actual = Target;
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
*Actual = Target;
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
NTSTATUS STDCALL
|
||||
MmMpwThreadMain(PVOID Ignored)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
ULONG PagesWritten;
|
||||
LARGE_INTEGER Timeout;
|
||||
|
||||
Timeout.QuadPart = -50000000;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
ULONG PagesWritten;
|
||||
LARGE_INTEGER Timeout;
|
||||
|
||||
Timeout.QuadPart = -50000000;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
Status = KeWaitForSingleObject(&MpwThreadEvent,
|
||||
0,
|
||||
KernelMode,
|
||||
FALSE,
|
||||
&Timeout);
|
||||
0,
|
||||
KernelMode,
|
||||
FALSE,
|
||||
&Timeout);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DbgPrint("MpwThread: Wait failed\n");
|
||||
KEBUGCHECK(0);
|
||||
return(STATUS_UNSUCCESSFUL);
|
||||
}
|
||||
{
|
||||
DbgPrint("MpwThread: Wait failed\n");
|
||||
KEBUGCHECK(0);
|
||||
return(STATUS_UNSUCCESSFUL);
|
||||
}
|
||||
if (MpwThreadShouldTerminate)
|
||||
{
|
||||
DbgPrint("MpwThread: Terminating\n");
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
{
|
||||
DbgPrint("MpwThread: Terminating\n");
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
PagesWritten = 0;
|
||||
#if 0
|
||||
/*
|
||||
/*
|
||||
* FIXME: MmWriteDirtyPages doesn't work correctly.
|
||||
*/
|
||||
MmWriteDirtyPages(128, &PagesWritten);
|
||||
#endif
|
||||
|
||||
CcRosFlushDirtyPages(128, &PagesWritten);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NTSTATUS MmInitMpwThread(VOID)
|
||||
{
|
||||
KPRIORITY Priority;
|
||||
NTSTATUS Status;
|
||||
|
||||
MpwThreadShouldTerminate = FALSE;
|
||||
KeInitializeEvent(&MpwThreadEvent, SynchronizationEvent, FALSE);
|
||||
|
||||
Status = PsCreateSystemThread(&MpwThreadHandle,
|
||||
THREAD_ALL_ACCESS,
|
||||
NULL,
|
||||
NULL,
|
||||
&MpwThreadId,
|
||||
(PKSTART_ROUTINE) MmMpwThreadMain,
|
||||
NULL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
KPRIORITY Priority;
|
||||
NTSTATUS Status;
|
||||
|
||||
MpwThreadShouldTerminate = FALSE;
|
||||
KeInitializeEvent(&MpwThreadEvent, SynchronizationEvent, FALSE);
|
||||
|
||||
Status = PsCreateSystemThread(&MpwThreadHandle,
|
||||
THREAD_ALL_ACCESS,
|
||||
NULL,
|
||||
NULL,
|
||||
&MpwThreadId,
|
||||
(PKSTART_ROUTINE) MmMpwThreadMain,
|
||||
NULL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return(Status);
|
||||
}
|
||||
|
||||
Priority = 1;
|
||||
NtSetInformationThread(MpwThreadHandle,
|
||||
ThreadPriority,
|
||||
&Priority,
|
||||
sizeof(Priority));
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
Priority = 1;
|
||||
NtSetInformationThread(MpwThreadHandle,
|
||||
ThreadPriority,
|
||||
&Priority,
|
||||
sizeof(Priority));
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $Id: ncache.c,v 1.27 2003/12/31 05:33:04 jfilby Exp $
|
||||
/* $Id: ncache.c,v 1.28 2004/04/10 22:35:25 gdalsnes Exp $
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
@@ -22,30 +22,30 @@
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* NAME EXPORTED
|
||||
* MmAllocateNonCachedMemory@4
|
||||
* NAME EXPORTED
|
||||
* MmAllocateNonCachedMemory@4
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Allocates a virtual address range of noncached and cache
|
||||
* aligned memory.
|
||||
*
|
||||
* Allocates a virtual address range of noncached and cache
|
||||
* aligned memory.
|
||||
*
|
||||
* ARGUMENTS
|
||||
* NumberOfBytes
|
||||
* Size of region to allocate.
|
||||
*
|
||||
* NumberOfBytes
|
||||
* Size of region to allocate.
|
||||
*
|
||||
* RETURN VALUE
|
||||
* The base address of the range on success;
|
||||
* NULL on failure.
|
||||
* 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.
|
||||
* Description taken from include/ddk/mmfuncs.h.
|
||||
* Code taken from ntoskrnl/mm/special.c.
|
||||
*
|
||||
* REVISIONS
|
||||
*
|
||||
* @implemented
|
||||
*/
|
||||
PVOID STDCALL
|
||||
PVOID STDCALL
|
||||
MmAllocateNonCachedMemory(IN ULONG NumberOfBytes)
|
||||
{
|
||||
PVOID Result;
|
||||
@@ -59,85 +59,85 @@ MmAllocateNonCachedMemory(IN ULONG NumberOfBytes)
|
||||
MmLockAddressSpace(MmGetKernelAddressSpace());
|
||||
Result = NULL;
|
||||
Status = MmCreateMemoryArea (NULL,
|
||||
MmGetKernelAddressSpace(),
|
||||
MEMORY_AREA_NO_CACHE,
|
||||
&Result,
|
||||
NumberOfBytes,
|
||||
0,
|
||||
&marea,
|
||||
FALSE,
|
||||
FALSE,
|
||||
BoundaryAddressMultiple);
|
||||
MmGetKernelAddressSpace(),
|
||||
MEMORY_AREA_NO_CACHE,
|
||||
&Result,
|
||||
NumberOfBytes,
|
||||
0,
|
||||
&marea,
|
||||
FALSE,
|
||||
FALSE,
|
||||
BoundaryAddressMultiple);
|
||||
MmUnlockAddressSpace(MmGetKernelAddressSpace());
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return (NULL);
|
||||
}
|
||||
Attributes = PAGE_READWRITE | PAGE_SYSTEM | PAGE_NOCACHE |
|
||||
PAGE_WRITETHROUGH;
|
||||
{
|
||||
return (NULL);
|
||||
}
|
||||
Attributes = PAGE_READWRITE | PAGE_SYSTEM | PAGE_NOCACHE |
|
||||
PAGE_WRITETHROUGH;
|
||||
for (i = 0; i < (PAGE_ROUND_UP(NumberOfBytes) / PAGE_SIZE); i++)
|
||||
{
|
||||
PHYSICAL_ADDRESS NPage;
|
||||
{
|
||||
PHYSICAL_ADDRESS NPage;
|
||||
|
||||
Status = MmRequestPageMemoryConsumer(MC_NPPOOL, TRUE, &NPage);
|
||||
MmCreateVirtualMapping (NULL,
|
||||
(char*)Result + (i * PAGE_SIZE),
|
||||
Attributes,
|
||||
NPage,
|
||||
TRUE);
|
||||
}
|
||||
Status = MmRequestPageMemoryConsumer(MC_NPPOOL, TRUE, &NPage);
|
||||
MmCreateVirtualMapping (NULL,
|
||||
(char*)Result + (i * PAGE_SIZE),
|
||||
Attributes,
|
||||
NPage,
|
||||
TRUE);
|
||||
}
|
||||
return ((PVOID)Result);
|
||||
}
|
||||
|
||||
VOID STATIC
|
||||
MmFreeNonCachedPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address,
|
||||
PHYSICAL_ADDRESS PhysAddr, SWAPENTRY SwapEntry,
|
||||
BOOLEAN Dirty)
|
||||
MmFreeNonCachedPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address,
|
||||
PHYSICAL_ADDRESS PhysAddr, SWAPENTRY SwapEntry,
|
||||
BOOLEAN Dirty)
|
||||
{
|
||||
assert(SwapEntry == 0);
|
||||
if (PhysAddr.QuadPart != 0)
|
||||
{
|
||||
assert(SwapEntry == 0);
|
||||
if (PhysAddr.QuadPart != 0)
|
||||
{
|
||||
MmReleasePageMemoryConsumer(MC_NPPOOL, PhysAddr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* NAME EXPORTED
|
||||
* MmFreeNonCachedMemory@8
|
||||
* NAME EXPORTED
|
||||
* MmFreeNonCachedMemory@8
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Releases a range of noncached memory allocated with
|
||||
* MmAllocateNonCachedMemory.
|
||||
*
|
||||
* Releases a range of noncached memory allocated with
|
||||
* MmAllocateNonCachedMemory.
|
||||
*
|
||||
* ARGUMENTS
|
||||
* BaseAddress
|
||||
* Virtual address to be freed;
|
||||
*
|
||||
* NumberOfBytes
|
||||
* Size of the region to be freed.
|
||||
*
|
||||
* BaseAddress
|
||||
* Virtual address to be freed;
|
||||
*
|
||||
* NumberOfBytes
|
||||
* Size of the region to be freed.
|
||||
*
|
||||
* RETURN VALUE
|
||||
* None.
|
||||
* None.
|
||||
*
|
||||
* NOTE
|
||||
* Description taken from include/ddk/mmfuncs.h.
|
||||
* Code taken from ntoskrnl/mm/special.c.
|
||||
* Description taken from include/ddk/mmfuncs.h.
|
||||
* Code taken from ntoskrnl/mm/special.c.
|
||||
*
|
||||
* REVISIONS
|
||||
*
|
||||
* @implemented
|
||||
*/
|
||||
VOID STDCALL MmFreeNonCachedMemory (IN PVOID BaseAddress,
|
||||
IN ULONG NumberOfBytes)
|
||||
IN ULONG NumberOfBytes)
|
||||
{
|
||||
MmLockAddressSpace(MmGetKernelAddressSpace());
|
||||
MmFreeMemoryArea (MmGetKernelAddressSpace(),
|
||||
BaseAddress,
|
||||
NumberOfBytes,
|
||||
MmFreeNonCachedPage,
|
||||
NULL);
|
||||
MmUnlockAddressSpace(MmGetKernelAddressSpace());
|
||||
MmLockAddressSpace(MmGetKernelAddressSpace());
|
||||
MmFreeMemoryArea (MmGetKernelAddressSpace(),
|
||||
BaseAddress,
|
||||
NumberOfBytes,
|
||||
MmFreeNonCachedPage,
|
||||
NULL);
|
||||
MmUnlockAddressSpace(MmGetKernelAddressSpace());
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
||||
+1107
-1087
File diff suppressed because it is too large
Load Diff
+572
-556
File diff suppressed because it is too large
Load Diff
+165
-165
@@ -1,4 +1,4 @@
|
||||
/* $Id: pageop.c,v 1.19 2004/03/05 11:31:59 hbirr Exp $
|
||||
/* $Id: pageop.c,v 1.20 2004/04/10 22:35:25 gdalsnes Exp $
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
@@ -32,227 +32,227 @@ static NPAGED_LOOKASIDE_LIST MmPageOpLookasideList;
|
||||
|
||||
VOID
|
||||
MmReleasePageOp(PMM_PAGEOP PageOp)
|
||||
/*
|
||||
* FUNCTION: Release a reference to a page operation descriptor
|
||||
*/
|
||||
/*
|
||||
* FUNCTION: Release a reference to a page operation descriptor
|
||||
*/
|
||||
{
|
||||
KIRQL oldIrql;
|
||||
PMM_PAGEOP PrevPageOp;
|
||||
KIRQL oldIrql;
|
||||
PMM_PAGEOP PrevPageOp;
|
||||
|
||||
KeAcquireSpinLock(&MmPageOpHashTableLock, &oldIrql);
|
||||
PageOp->ReferenceCount--;
|
||||
if (PageOp->ReferenceCount > 0)
|
||||
{
|
||||
KeAcquireSpinLock(&MmPageOpHashTableLock, &oldIrql);
|
||||
PageOp->ReferenceCount--;
|
||||
if (PageOp->ReferenceCount > 0)
|
||||
{
|
||||
KeReleaseSpinLock(&MmPageOpHashTableLock, oldIrql);
|
||||
return;
|
||||
}
|
||||
InterlockedDecrement((LONG *)&PageOp->MArea->PageOpCount);
|
||||
PrevPageOp = MmPageOpHashTable[PageOp->Hash];
|
||||
if (PrevPageOp == PageOp)
|
||||
{
|
||||
}
|
||||
InterlockedDecrement((LONG *)&PageOp->MArea->PageOpCount);
|
||||
PrevPageOp = MmPageOpHashTable[PageOp->Hash];
|
||||
if (PrevPageOp == PageOp)
|
||||
{
|
||||
MmPageOpHashTable[PageOp->Hash] = PageOp->Next;
|
||||
KeReleaseSpinLock(&MmPageOpHashTableLock, oldIrql);
|
||||
ExFreeToNPagedLookasideList(&MmPageOpLookasideList, PageOp);
|
||||
return;
|
||||
}
|
||||
while (PrevPageOp->Next != NULL)
|
||||
{
|
||||
}
|
||||
while (PrevPageOp->Next != NULL)
|
||||
{
|
||||
if (PrevPageOp->Next == PageOp)
|
||||
{
|
||||
PrevPageOp->Next = PageOp->Next;
|
||||
KeReleaseSpinLock(&MmPageOpHashTableLock, oldIrql);
|
||||
ExFreeToNPagedLookasideList(&MmPageOpLookasideList, PageOp);
|
||||
return;
|
||||
}
|
||||
{
|
||||
PrevPageOp->Next = PageOp->Next;
|
||||
KeReleaseSpinLock(&MmPageOpHashTableLock, oldIrql);
|
||||
ExFreeToNPagedLookasideList(&MmPageOpLookasideList, PageOp);
|
||||
return;
|
||||
}
|
||||
PrevPageOp = PrevPageOp->Next;
|
||||
}
|
||||
KeReleaseSpinLock(&MmPageOpHashTableLock, oldIrql);
|
||||
KEBUGCHECK(0);
|
||||
}
|
||||
KeReleaseSpinLock(&MmPageOpHashTableLock, oldIrql);
|
||||
KEBUGCHECK(0);
|
||||
}
|
||||
|
||||
PMM_PAGEOP
|
||||
MmCheckForPageOp(PMEMORY_AREA MArea, ULONG Pid, PVOID Address,
|
||||
PMM_SECTION_SEGMENT Segment, ULONG Offset)
|
||||
PMM_SECTION_SEGMENT Segment, ULONG Offset)
|
||||
{
|
||||
ULONG Hash;
|
||||
KIRQL oldIrql;
|
||||
PMM_PAGEOP PageOp;
|
||||
|
||||
/*
|
||||
* Calcuate the hash value for pageop structure
|
||||
*/
|
||||
if (MArea->Type == MEMORY_AREA_SECTION_VIEW)
|
||||
{
|
||||
ULONG Hash;
|
||||
KIRQL oldIrql;
|
||||
PMM_PAGEOP PageOp;
|
||||
|
||||
/*
|
||||
* Calcuate the hash value for pageop structure
|
||||
*/
|
||||
if (MArea->Type == MEMORY_AREA_SECTION_VIEW)
|
||||
{
|
||||
Hash = (((ULONG)Segment) | (((ULONG)Offset) / PAGE_SIZE));
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
Hash = (((ULONG)Pid) | (((ULONG)Address) / PAGE_SIZE));
|
||||
}
|
||||
Hash = Hash % PAGEOP_HASH_TABLE_SIZE;
|
||||
}
|
||||
Hash = Hash % PAGEOP_HASH_TABLE_SIZE;
|
||||
|
||||
KeAcquireSpinLock(&MmPageOpHashTableLock, &oldIrql);
|
||||
KeAcquireSpinLock(&MmPageOpHashTableLock, &oldIrql);
|
||||
|
||||
/*
|
||||
* Check for an existing pageop structure
|
||||
*/
|
||||
PageOp = MmPageOpHashTable[Hash];
|
||||
while (PageOp != NULL)
|
||||
{
|
||||
/*
|
||||
* Check for an existing pageop structure
|
||||
*/
|
||||
PageOp = MmPageOpHashTable[Hash];
|
||||
while (PageOp != NULL)
|
||||
{
|
||||
if (MArea->Type == MEMORY_AREA_SECTION_VIEW)
|
||||
{
|
||||
if (PageOp->Segment == Segment &&
|
||||
PageOp->Offset == Offset)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
{
|
||||
if (PageOp->Segment == Segment &&
|
||||
PageOp->Offset == Offset)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (PageOp->Pid == Pid &&
|
||||
PageOp->Address == Address)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
{
|
||||
if (PageOp->Pid == Pid &&
|
||||
PageOp->Address == Address)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
PageOp = PageOp->Next;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we found an existing pageop then increment the reference count
|
||||
* and return it.
|
||||
*/
|
||||
if (PageOp != NULL)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* If we found an existing pageop then increment the reference count
|
||||
* and return it.
|
||||
*/
|
||||
if (PageOp != NULL)
|
||||
{
|
||||
PageOp->ReferenceCount++;
|
||||
KeReleaseSpinLock(&MmPageOpHashTableLock, oldIrql);
|
||||
return(PageOp);
|
||||
}
|
||||
KeReleaseSpinLock(&MmPageOpHashTableLock, oldIrql);
|
||||
return(NULL);
|
||||
}
|
||||
KeReleaseSpinLock(&MmPageOpHashTableLock, oldIrql);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
PMM_PAGEOP
|
||||
MmGetPageOp(PMEMORY_AREA MArea, ULONG Pid, PVOID Address,
|
||||
PMM_SECTION_SEGMENT Segment, ULONG Offset, ULONG OpType, BOOL First)
|
||||
/*
|
||||
* FUNCTION: Get a page operation descriptor corresponding to
|
||||
* the memory area and either the segment, offset pair or the
|
||||
* pid, address pair.
|
||||
*/
|
||||
PMM_SECTION_SEGMENT Segment, ULONG Offset, ULONG OpType, BOOL First)
|
||||
/*
|
||||
* FUNCTION: Get a page operation descriptor corresponding to
|
||||
* the memory area and either the segment, offset pair or the
|
||||
* pid, address pair.
|
||||
*/
|
||||
{
|
||||
ULONG Hash;
|
||||
KIRQL oldIrql;
|
||||
PMM_PAGEOP PageOp;
|
||||
ULONG Hash;
|
||||
KIRQL oldIrql;
|
||||
PMM_PAGEOP PageOp;
|
||||
|
||||
/*
|
||||
* Calcuate the hash value for pageop structure
|
||||
*/
|
||||
if (MArea->Type == MEMORY_AREA_SECTION_VIEW)
|
||||
{
|
||||
/*
|
||||
* Calcuate the hash value for pageop structure
|
||||
*/
|
||||
if (MArea->Type == MEMORY_AREA_SECTION_VIEW)
|
||||
{
|
||||
Hash = (((ULONG)Segment) | (((ULONG)Offset) / PAGE_SIZE));
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
Hash = (((ULONG)Pid) | (((ULONG)Address) / PAGE_SIZE));
|
||||
}
|
||||
Hash = Hash % PAGEOP_HASH_TABLE_SIZE;
|
||||
}
|
||||
Hash = Hash % PAGEOP_HASH_TABLE_SIZE;
|
||||
|
||||
KeAcquireSpinLock(&MmPageOpHashTableLock, &oldIrql);
|
||||
KeAcquireSpinLock(&MmPageOpHashTableLock, &oldIrql);
|
||||
|
||||
/*
|
||||
* Check for an existing pageop structure
|
||||
*/
|
||||
PageOp = MmPageOpHashTable[Hash];
|
||||
while (PageOp != NULL)
|
||||
{
|
||||
/*
|
||||
* Check for an existing pageop structure
|
||||
*/
|
||||
PageOp = MmPageOpHashTable[Hash];
|
||||
while (PageOp != NULL)
|
||||
{
|
||||
if (MArea->Type == MEMORY_AREA_SECTION_VIEW)
|
||||
{
|
||||
if (PageOp->Segment == Segment &&
|
||||
PageOp->Offset == Offset)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
{
|
||||
if (PageOp->Segment == Segment &&
|
||||
PageOp->Offset == Offset)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (PageOp->Pid == Pid &&
|
||||
PageOp->Address == Address)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
{
|
||||
if (PageOp->Pid == Pid &&
|
||||
PageOp->Address == Address)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
PageOp = PageOp->Next;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we found an existing pageop then increment the reference count
|
||||
* and return it.
|
||||
*/
|
||||
if (PageOp != NULL)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* If we found an existing pageop then increment the reference count
|
||||
* and return it.
|
||||
*/
|
||||
if (PageOp != NULL)
|
||||
{
|
||||
if (First)
|
||||
{
|
||||
PageOp = NULL;
|
||||
}
|
||||
{
|
||||
PageOp = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
PageOp->ReferenceCount++;
|
||||
}
|
||||
{
|
||||
PageOp->ReferenceCount++;
|
||||
}
|
||||
KeReleaseSpinLock(&MmPageOpHashTableLock, oldIrql);
|
||||
return(PageOp);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Otherwise add a new pageop.
|
||||
*/
|
||||
PageOp = ExAllocateFromNPagedLookasideList(&MmPageOpLookasideList);
|
||||
if (PageOp == NULL)
|
||||
{
|
||||
/*
|
||||
* Otherwise add a new pageop.
|
||||
*/
|
||||
PageOp = ExAllocateFromNPagedLookasideList(&MmPageOpLookasideList);
|
||||
if (PageOp == NULL)
|
||||
{
|
||||
KeReleaseSpinLock(&MmPageOpHashTableLock, oldIrql);
|
||||
KEBUGCHECK(0);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
if (MArea->Type != MEMORY_AREA_SECTION_VIEW)
|
||||
{
|
||||
}
|
||||
|
||||
if (MArea->Type != MEMORY_AREA_SECTION_VIEW)
|
||||
{
|
||||
PageOp->Pid = Pid;
|
||||
PageOp->Address = Address;
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
PageOp->Segment = Segment;
|
||||
PageOp->Offset = Offset;
|
||||
}
|
||||
PageOp->ReferenceCount = 1;
|
||||
PageOp->Next = MmPageOpHashTable[Hash];
|
||||
PageOp->Hash = Hash;
|
||||
PageOp->Thread = PsGetCurrentThread();
|
||||
PageOp->Abandoned = FALSE;
|
||||
PageOp->Status = STATUS_PENDING;
|
||||
PageOp->OpType = OpType;
|
||||
PageOp->MArea = MArea;
|
||||
KeInitializeEvent(&PageOp->CompletionEvent, NotificationEvent, FALSE);
|
||||
MmPageOpHashTable[Hash] = PageOp;
|
||||
InterlockedIncrement((LONG *)&MArea->PageOpCount);
|
||||
}
|
||||
PageOp->ReferenceCount = 1;
|
||||
PageOp->Next = MmPageOpHashTable[Hash];
|
||||
PageOp->Hash = Hash;
|
||||
PageOp->Thread = PsGetCurrentThread();
|
||||
PageOp->Abandoned = FALSE;
|
||||
PageOp->Status = STATUS_PENDING;
|
||||
PageOp->OpType = OpType;
|
||||
PageOp->MArea = MArea;
|
||||
KeInitializeEvent(&PageOp->CompletionEvent, NotificationEvent, FALSE);
|
||||
MmPageOpHashTable[Hash] = PageOp;
|
||||
InterlockedIncrement((LONG *)&MArea->PageOpCount);
|
||||
|
||||
KeReleaseSpinLock(&MmPageOpHashTableLock, oldIrql);
|
||||
return(PageOp);
|
||||
KeReleaseSpinLock(&MmPageOpHashTableLock, oldIrql);
|
||||
return(PageOp);
|
||||
}
|
||||
|
||||
VOID INIT_FUNCTION
|
||||
MmInitializePageOp(VOID)
|
||||
{
|
||||
memset(MmPageOpHashTable, 0, sizeof(MmPageOpHashTable));
|
||||
KeInitializeSpinLock(&MmPageOpHashTableLock);
|
||||
memset(MmPageOpHashTable, 0, sizeof(MmPageOpHashTable));
|
||||
KeInitializeSpinLock(&MmPageOpHashTableLock);
|
||||
|
||||
ExInitializeNPagedLookasideList (&MmPageOpLookasideList,
|
||||
NULL,
|
||||
NULL,
|
||||
0,
|
||||
sizeof(MM_PAGEOP),
|
||||
TAG_MM_PAGEOP,
|
||||
50);
|
||||
ExInitializeNPagedLookasideList (&MmPageOpLookasideList,
|
||||
NULL,
|
||||
NULL,
|
||||
0,
|
||||
sizeof(MM_PAGEOP),
|
||||
TAG_MM_PAGEOP,
|
||||
50);
|
||||
}
|
||||
|
||||
|
||||
|
||||
+46
-45
@@ -1,4 +1,4 @@
|
||||
/* $Id: pager.c,v 1.16 2003/11/16 15:20:39 hbirr Exp $
|
||||
/* $Id: pager.c,v 1.17 2004/04/10 22:35:25 gdalsnes Exp $
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
@@ -35,25 +35,25 @@ static ULONG PagerThreadWorkCount;
|
||||
BOOLEAN
|
||||
MiIsPagerThread(VOID)
|
||||
{
|
||||
return(PsGetCurrentThreadId() == PagerThreadId.UniqueThread);
|
||||
return(PsGetCurrentThreadId() == PagerThreadId.UniqueThread);
|
||||
}
|
||||
|
||||
VOID
|
||||
MiStartPagerThread(VOID)
|
||||
{
|
||||
ULONG WasWorking;
|
||||
ULONG WasWorking;
|
||||
|
||||
WasWorking = InterlockedIncrement(&PagerThreadWorkCount);
|
||||
if (WasWorking == 1)
|
||||
{
|
||||
WasWorking = InterlockedIncrement(&PagerThreadWorkCount);
|
||||
if (WasWorking == 1)
|
||||
{
|
||||
KeSetEvent(&PagerThreadEvent, IO_NO_INCREMENT, FALSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
MiStopPagerThread(VOID)
|
||||
{
|
||||
(VOID)InterlockedDecrement(&PagerThreadWorkCount);
|
||||
(VOID)InterlockedDecrement(&PagerThreadWorkCount);
|
||||
}
|
||||
|
||||
static NTSTATUS STDCALL
|
||||
@@ -62,53 +62,54 @@ MmPagerThreadMain(PVOID Ignored)
|
||||
NTSTATUS Status;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
/* Wake for a low memory situation or a terminate request. */
|
||||
Status = KeWaitForSingleObject(&PagerThreadEvent,
|
||||
0,
|
||||
KernelMode,
|
||||
FALSE,
|
||||
NULL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DbgPrint("PagerThread: Wait failed\n");
|
||||
KEBUGCHECK(0);
|
||||
}
|
||||
if (PagerThreadShouldTerminate)
|
||||
{
|
||||
DbgPrint("PagerThread: Terminating\n");
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
do
|
||||
{
|
||||
/* Try and make some memory available to the system. */
|
||||
MmRebalanceMemoryConsumers();
|
||||
} while(PagerThreadWorkCount > 0);
|
||||
}
|
||||
{
|
||||
/* Wake for a low memory situation or a terminate request. */
|
||||
Status = KeWaitForSingleObject(&PagerThreadEvent,
|
||||
0,
|
||||
KernelMode,
|
||||
FALSE,
|
||||
NULL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DbgPrint("PagerThread: Wait failed\n");
|
||||
KEBUGCHECK(0);
|
||||
}
|
||||
if (PagerThreadShouldTerminate)
|
||||
{
|
||||
DbgPrint("PagerThread: Terminating\n");
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
do
|
||||
{
|
||||
/* Try and make some memory available to the system. */
|
||||
MmRebalanceMemoryConsumers();
|
||||
}
|
||||
while(PagerThreadWorkCount > 0);
|
||||
}
|
||||
}
|
||||
|
||||
NTSTATUS MmInitPagerThread(VOID)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
|
||||
|
||||
PagerThreadShouldTerminate = FALSE;
|
||||
PagerThreadWorkCount = 0;
|
||||
KeInitializeEvent(&PagerThreadEvent,
|
||||
SynchronizationEvent,
|
||||
FALSE);
|
||||
|
||||
SynchronizationEvent,
|
||||
FALSE);
|
||||
|
||||
Status = PsCreateSystemThread(&PagerThreadHandle,
|
||||
THREAD_ALL_ACCESS,
|
||||
NULL,
|
||||
NULL,
|
||||
&PagerThreadId,
|
||||
(PKSTART_ROUTINE) MmPagerThreadMain,
|
||||
NULL);
|
||||
THREAD_ALL_ACCESS,
|
||||
NULL,
|
||||
NULL,
|
||||
&PagerThreadId,
|
||||
(PKSTART_ROUTINE) MmPagerThreadMain,
|
||||
NULL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return(Status);
|
||||
}
|
||||
|
||||
{
|
||||
return(Status);
|
||||
}
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $Id: pagfault.c,v 1.5 2003/07/10 21:05:03 royce Exp $ */
|
||||
/* $Id: pagfault.c,v 1.6 2004/04/10 22:35:25 gdalsnes Exp $ */
|
||||
#include <ddk/ntddk.h>
|
||||
#include <internal/ps.h>
|
||||
|
||||
@@ -8,14 +8,14 @@
|
||||
BOOLEAN
|
||||
STDCALL
|
||||
MmIsRecursiveIoFault (
|
||||
VOID
|
||||
)
|
||||
VOID
|
||||
)
|
||||
{
|
||||
PETHREAD Thread = PsGetCurrentThread ();
|
||||
PETHREAD Thread = PsGetCurrentThread ();
|
||||
|
||||
return ( Thread->DisablePageFaultClustering
|
||||
| Thread->ForwardClusterOnly
|
||||
);
|
||||
return ( Thread->DisablePageFaultClustering
|
||||
| Thread->ForwardClusterOnly
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
+64
-57
@@ -1,4 +1,4 @@
|
||||
/* $Id: pool.c,v 1.27 2004/02/26 18:54:52 navaraf Exp $
|
||||
/* $Id: pool.c,v 1.28 2004/04/10 22:35:25 gdalsnes Exp $
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
@@ -25,40 +25,40 @@
|
||||
|
||||
STATIC PVOID STDCALL
|
||||
EiAllocatePool(POOL_TYPE PoolType,
|
||||
ULONG NumberOfBytes,
|
||||
ULONG Tag,
|
||||
PVOID Caller)
|
||||
ULONG NumberOfBytes,
|
||||
ULONG Tag,
|
||||
PVOID Caller)
|
||||
{
|
||||
PVOID Block;
|
||||
|
||||
|
||||
|
||||
|
||||
switch(PoolType)
|
||||
{
|
||||
{
|
||||
case NonPagedPool:
|
||||
case NonPagedPoolMustSucceed:
|
||||
case NonPagedPoolCacheAligned:
|
||||
case NonPagedPoolCacheAlignedMustS:
|
||||
Block =
|
||||
ExAllocateNonPagedPoolWithTag(PoolType,
|
||||
NumberOfBytes,
|
||||
Tag,
|
||||
Caller);
|
||||
break;
|
||||
|
||||
Block =
|
||||
ExAllocateNonPagedPoolWithTag(PoolType,
|
||||
NumberOfBytes,
|
||||
Tag,
|
||||
Caller);
|
||||
break;
|
||||
|
||||
case PagedPool:
|
||||
case PagedPoolCacheAligned:
|
||||
Block = ExAllocatePagedPoolWithTag(PoolType,NumberOfBytes,Tag);
|
||||
break;
|
||||
|
||||
Block = ExAllocatePagedPoolWithTag(PoolType,NumberOfBytes,Tag);
|
||||
break;
|
||||
|
||||
default:
|
||||
return(NULL);
|
||||
};
|
||||
|
||||
if ((PoolType==NonPagedPoolMustSucceed ||
|
||||
PoolType==NonPagedPoolCacheAlignedMustS) && Block==NULL)
|
||||
{
|
||||
KEBUGCHECK(MUST_SUCCEED_POOL_EMPTY);
|
||||
}
|
||||
return(NULL);
|
||||
};
|
||||
|
||||
if ((PoolType==NonPagedPoolMustSucceed ||
|
||||
PoolType==NonPagedPoolCacheAlignedMustS) && Block==NULL)
|
||||
{
|
||||
KEBUGCHECK(MUST_SUCCEED_POOL_EMPTY);
|
||||
}
|
||||
return(Block);
|
||||
}
|
||||
|
||||
@@ -91,18 +91,21 @@ ExAllocatePool (POOL_TYPE PoolType, ULONG NumberOfBytes)
|
||||
{
|
||||
PVOID Block;
|
||||
#if defined(__GNUC__)
|
||||
|
||||
Block = EiAllocatePool(PoolType,
|
||||
NumberOfBytes,
|
||||
TAG_NONE,
|
||||
(PVOID)__builtin_return_address(0));
|
||||
NumberOfBytes,
|
||||
TAG_NONE,
|
||||
(PVOID)__builtin_return_address(0));
|
||||
#elif defined(_MSC_VER)
|
||||
|
||||
Block = EiAllocatePool(PoolType,
|
||||
NumberOfBytes,
|
||||
TAG_NONE,
|
||||
&ExAllocatePool);
|
||||
NumberOfBytes,
|
||||
TAG_NONE,
|
||||
&ExAllocatePool);
|
||||
#else
|
||||
#error Unknown compiler
|
||||
#endif
|
||||
|
||||
return(Block);
|
||||
}
|
||||
|
||||
@@ -115,18 +118,21 @@ ExAllocatePoolWithTag (ULONG PoolType, ULONG NumberOfBytes, ULONG Tag)
|
||||
{
|
||||
PVOID Block;
|
||||
#if defined(__GNUC__)
|
||||
|
||||
Block = EiAllocatePool(PoolType,
|
||||
NumberOfBytes,
|
||||
Tag,
|
||||
(PVOID)__builtin_return_address(0));
|
||||
NumberOfBytes,
|
||||
Tag,
|
||||
(PVOID)__builtin_return_address(0));
|
||||
#elif defined(_MSC_VER)
|
||||
|
||||
Block = EiAllocatePool(PoolType,
|
||||
NumberOfBytes,
|
||||
Tag,
|
||||
&ExAllocatePoolWithTag);
|
||||
NumberOfBytes,
|
||||
Tag,
|
||||
&ExAllocatePoolWithTag);
|
||||
#else
|
||||
#error Unknown compiler
|
||||
#endif
|
||||
|
||||
return(Block);
|
||||
}
|
||||
|
||||
@@ -137,7 +143,7 @@ ExAllocatePoolWithTag (ULONG PoolType, ULONG NumberOfBytes, ULONG Tag)
|
||||
PVOID STDCALL
|
||||
ExAllocatePoolWithQuota (POOL_TYPE PoolType, ULONG NumberOfBytes)
|
||||
{
|
||||
return(ExAllocatePoolWithQuotaTag(PoolType, NumberOfBytes, TAG_NONE));
|
||||
return(ExAllocatePoolWithQuotaTag(PoolType, NumberOfBytes, TAG_NONE));
|
||||
}
|
||||
|
||||
|
||||
@@ -145,20 +151,21 @@ ExAllocatePoolWithQuota (POOL_TYPE PoolType, ULONG NumberOfBytes)
|
||||
* @unimplemented
|
||||
*/
|
||||
PVOID STDCALL
|
||||
ExAllocatePoolWithQuotaTag (IN POOL_TYPE PoolType,
|
||||
IN ULONG NumberOfBytes,
|
||||
IN ULONG Tag)
|
||||
ExAllocatePoolWithQuotaTag (IN POOL_TYPE PoolType,
|
||||
IN ULONG NumberOfBytes,
|
||||
IN ULONG Tag)
|
||||
{
|
||||
#if 0
|
||||
PVOID Block;
|
||||
Block = EiAllocatePool(PoolType,
|
||||
NumberOfBytes,
|
||||
Tag,
|
||||
(PVOID)__builtin_return_address(0));
|
||||
return(Block);
|
||||
PVOID Block;
|
||||
Block = EiAllocatePool(PoolType,
|
||||
NumberOfBytes,
|
||||
Tag,
|
||||
(PVOID)__builtin_return_address(0));
|
||||
return(Block);
|
||||
#else
|
||||
UNIMPLEMENTED;
|
||||
return(NULL);
|
||||
|
||||
UNIMPLEMENTED;
|
||||
return(NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -168,14 +175,14 @@ ExAllocatePoolWithQuotaTag (IN POOL_TYPE PoolType,
|
||||
VOID STDCALL
|
||||
ExFreePool(IN PVOID Block)
|
||||
{
|
||||
if (Block >= MmPagedPoolBase && (char*)Block < ((char*)MmPagedPoolBase + MmPagedPoolSize))
|
||||
{
|
||||
if (Block >= MmPagedPoolBase && (char*)Block < ((char*)MmPagedPoolBase + MmPagedPoolSize))
|
||||
{
|
||||
ExFreePagedPool(Block);
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
ExFreeNonPagedPool(Block);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -184,8 +191,8 @@ ExFreePool(IN PVOID Block)
|
||||
VOID STDCALL
|
||||
ExFreePoolWithTag(IN PVOID Block, IN ULONG Tag)
|
||||
{
|
||||
/* FIXME: Validate the tag */
|
||||
ExFreePool(Block);
|
||||
/* FIXME: Validate the tag */
|
||||
ExFreePool(Block);
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
||||
+331
-325
@@ -1,4 +1,4 @@
|
||||
/* $Id: ppool.c,v 1.27 2004/03/30 09:28:44 gvg Exp $
|
||||
/* $Id: ppool.c,v 1.28 2004/04/10 22:35:25 gdalsnes Exp $
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
@@ -34,18 +34,21 @@
|
||||
|
||||
typedef struct _MM_PPOOL_FREE_BLOCK_HEADER
|
||||
{
|
||||
ULONG Size;
|
||||
struct _MM_PPOOL_FREE_BLOCK_HEADER* NextFree;
|
||||
} MM_PPOOL_FREE_BLOCK_HEADER, *PMM_PPOOL_FREE_BLOCK_HEADER;
|
||||
ULONG Size;
|
||||
struct _MM_PPOOL_FREE_BLOCK_HEADER* NextFree;
|
||||
}
|
||||
MM_PPOOL_FREE_BLOCK_HEADER, *PMM_PPOOL_FREE_BLOCK_HEADER;
|
||||
|
||||
typedef struct _MM_PPOOL_USED_BLOCK_HEADER
|
||||
{
|
||||
ULONG Size;
|
||||
ULONG Size;
|
||||
#if MM_PPOOL_REDZONE_BYTES
|
||||
ULONG UserSize; // how many bytes the user actually asked for...
|
||||
struct _MM_PPOOL_USED_BLOCK_HEADER* NextUsed;
|
||||
|
||||
ULONG UserSize; // how many bytes the user actually asked for...
|
||||
struct _MM_PPOOL_USED_BLOCK_HEADER* NextUsed;
|
||||
#endif//MM_PPOOL_REDZONE_BYTES
|
||||
} MM_PPOOL_USED_BLOCK_HEADER, *PMM_PPOOL_USED_BLOCK_HEADER;
|
||||
}
|
||||
MM_PPOOL_USED_BLOCK_HEADER, *PMM_PPOOL_USED_BLOCK_HEADER;
|
||||
|
||||
PVOID MmPagedPoolBase;
|
||||
ULONG MmPagedPoolSize;
|
||||
@@ -63,49 +66,50 @@ inline static void* block_to_address ( PVOID blk )
|
||||
* address (internal)
|
||||
*/
|
||||
{
|
||||
return ( (void *) ((char*)blk + sizeof(MM_PPOOL_USED_BLOCK_HEADER) + MM_PPOOL_REDZONE_BYTES) );
|
||||
return ( (void *) ((char*)blk + sizeof(MM_PPOOL_USED_BLOCK_HEADER) + MM_PPOOL_REDZONE_BYTES) );
|
||||
}
|
||||
|
||||
inline static PMM_PPOOL_USED_BLOCK_HEADER address_to_block(PVOID addr)
|
||||
{
|
||||
return (PMM_PPOOL_USED_BLOCK_HEADER)
|
||||
( ((char*)addr) - sizeof(MM_PPOOL_USED_BLOCK_HEADER) - MM_PPOOL_REDZONE_BYTES );
|
||||
return (PMM_PPOOL_USED_BLOCK_HEADER)
|
||||
( ((char*)addr) - sizeof(MM_PPOOL_USED_BLOCK_HEADER) - MM_PPOOL_REDZONE_BYTES );
|
||||
}
|
||||
|
||||
VOID INIT_FUNCTION
|
||||
MmInitializePagedPool(VOID)
|
||||
{
|
||||
MmPagedPoolFirstFreeBlock = (PMM_PPOOL_FREE_BLOCK_HEADER)MmPagedPoolBase;
|
||||
/*
|
||||
* We are still at a high IRQL level at this point so explicitly commit
|
||||
* the first page of the paged pool before writing the first block header.
|
||||
*/
|
||||
MmCommitPagedPoolAddress((PVOID)MmPagedPoolFirstFreeBlock, FALSE);
|
||||
MmPagedPoolFirstFreeBlock->Size = MmPagedPoolSize;
|
||||
MmPagedPoolFirstFreeBlock->NextFree = NULL;
|
||||
MmPagedPoolFirstFreeBlock = (PMM_PPOOL_FREE_BLOCK_HEADER)MmPagedPoolBase;
|
||||
/*
|
||||
* We are still at a high IRQL level at this point so explicitly commit
|
||||
* the first page of the paged pool before writing the first block header.
|
||||
*/
|
||||
MmCommitPagedPoolAddress((PVOID)MmPagedPoolFirstFreeBlock, FALSE);
|
||||
MmPagedPoolFirstFreeBlock->Size = MmPagedPoolSize;
|
||||
MmPagedPoolFirstFreeBlock->NextFree = NULL;
|
||||
|
||||
#if MM_PPOOL_REDZONE_BYTES
|
||||
MmPagedPoolFirstUsedBlock = NULL;
|
||||
|
||||
MmPagedPoolFirstUsedBlock = NULL;
|
||||
#endif//MM_PPOOL_REDZONE_BYTES
|
||||
|
||||
ExInitializeFastMutex(&MmPagedPoolLock);
|
||||
ExInitializeFastMutex(&MmPagedPoolLock);
|
||||
}
|
||||
|
||||
#ifdef ENABLE_VALIDATE_POOL
|
||||
static void VerifyPagedPool ( int line )
|
||||
{
|
||||
PMM_PPOOL_FREE_BLOCK_HEADER p = MmPagedPoolFirstFreeBlock;
|
||||
int count = 0;
|
||||
DPRINT ( "VerifyPagedPool(%i):\n", line );
|
||||
while ( p )
|
||||
{
|
||||
DPRINT ( " 0x%x: %lu bytes (next 0x%x)\n", p, p->Size, p->NextFree );
|
||||
ASSERT_PTR(p);
|
||||
ASSERT_SIZE(p->Size);
|
||||
count++;
|
||||
p = p->NextFree;
|
||||
}
|
||||
DPRINT ( "VerifyPagedPool(%i): (%lu blocks)\n", line, count );
|
||||
PMM_PPOOL_FREE_BLOCK_HEADER p = MmPagedPoolFirstFreeBlock;
|
||||
int count = 0;
|
||||
DPRINT ( "VerifyPagedPool(%i):\n", line );
|
||||
while ( p )
|
||||
{
|
||||
DPRINT ( " 0x%x: %lu bytes (next 0x%x)\n", p, p->Size, p->NextFree );
|
||||
ASSERT_PTR(p);
|
||||
ASSERT_SIZE(p->Size);
|
||||
count++;
|
||||
p = p->NextFree;
|
||||
}
|
||||
DPRINT ( "VerifyPagedPool(%i): (%lu blocks)\n", line, count );
|
||||
}
|
||||
#define VerifyPagedPool() VerifyPagedPool(__LINE__)
|
||||
#else
|
||||
@@ -116,38 +120,38 @@ VOID STDCALL
|
||||
MmDbgPagedPoolRedZoneCheck ( const char* file, int line )
|
||||
{
|
||||
#if MM_PPOOL_REDZONE_BYTES
|
||||
PMM_PPOOL_USED_BLOCK_HEADER pUsed = MmPagedPoolFirstUsedBlock;
|
||||
int i;
|
||||
BOOL bLow = TRUE;
|
||||
BOOL bHigh = TRUE;
|
||||
PMM_PPOOL_USED_BLOCK_HEADER pUsed = MmPagedPoolFirstUsedBlock;
|
||||
int i;
|
||||
BOOL bLow = TRUE;
|
||||
BOOL bHigh = TRUE;
|
||||
|
||||
while ( pUsed )
|
||||
{
|
||||
PUCHAR Addr = (PUCHAR)block_to_address(pUsed);
|
||||
for ( i = 0; i < MM_PPOOL_REDZONE_BYTES; i++ )
|
||||
{
|
||||
bLow = bLow && ( *(Addr-i-1) == MM_PPOOL_REDZONE_VALUE );
|
||||
bHigh = bHigh && ( *(Addr+pUsed->UserSize+i) == MM_PPOOL_REDZONE_VALUE );
|
||||
}
|
||||
if ( !bLow || !bHigh )
|
||||
{
|
||||
const char* violation = "High and Low-side";
|
||||
if ( bHigh ) // high is okay, so it was just low failed
|
||||
violation = "Low-side";
|
||||
else if ( bLow ) // low side is okay, so it was just high failed
|
||||
violation = "High-side";
|
||||
DbgPrint("%s(%i): %s redzone violation detected for paged pool address 0x%x\n",
|
||||
file, line, violation, Addr );
|
||||
KEBUGCHECK(0);
|
||||
}
|
||||
pUsed = pUsed->NextUsed;
|
||||
}
|
||||
while ( pUsed )
|
||||
{
|
||||
PUCHAR Addr = (PUCHAR)block_to_address(pUsed);
|
||||
for ( i = 0; i < MM_PPOOL_REDZONE_BYTES; i++ )
|
||||
{
|
||||
bLow = bLow && ( *(Addr-i-1) == MM_PPOOL_REDZONE_VALUE );
|
||||
bHigh = bHigh && ( *(Addr+pUsed->UserSize+i) == MM_PPOOL_REDZONE_VALUE );
|
||||
}
|
||||
if ( !bLow || !bHigh )
|
||||
{
|
||||
const char* violation = "High and Low-side";
|
||||
if ( bHigh ) // high is okay, so it was just low failed
|
||||
violation = "Low-side";
|
||||
else if ( bLow ) // low side is okay, so it was just high failed
|
||||
violation = "High-side";
|
||||
DbgPrint("%s(%i): %s redzone violation detected for paged pool address 0x%x\n",
|
||||
file, line, violation, Addr );
|
||||
KEBUGCHECK(0);
|
||||
}
|
||||
pUsed = pUsed->NextUsed;
|
||||
}
|
||||
#endif//MM_PPOOL_REDZONE_BYTES
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* NAME INTERNAL
|
||||
* ExAllocatePagedPoolWithTag@12
|
||||
* NAME INTERNAL
|
||||
* ExAllocatePagedPoolWithTag@12
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
@@ -156,181 +160,182 @@ MmDbgPagedPoolRedZoneCheck ( const char* file, int line )
|
||||
* RETURN VALUE
|
||||
*/
|
||||
PVOID STDCALL
|
||||
ExAllocatePagedPoolWithTag (IN POOL_TYPE PoolType,
|
||||
IN ULONG NumberOfBytes,
|
||||
IN ULONG Tag)
|
||||
ExAllocatePagedPoolWithTag (IN POOL_TYPE PoolType,
|
||||
IN ULONG NumberOfBytes,
|
||||
IN ULONG Tag)
|
||||
{
|
||||
PMM_PPOOL_FREE_BLOCK_HEADER BestBlock;
|
||||
PMM_PPOOL_FREE_BLOCK_HEADER CurrentBlock;
|
||||
ULONG BlockSize;
|
||||
PMM_PPOOL_USED_BLOCK_HEADER NewBlock;
|
||||
PMM_PPOOL_FREE_BLOCK_HEADER NextBlock;
|
||||
PMM_PPOOL_FREE_BLOCK_HEADER PreviousBlock;
|
||||
PMM_PPOOL_FREE_BLOCK_HEADER BestPreviousBlock;
|
||||
PVOID BlockAddress;
|
||||
ULONG Alignment;
|
||||
PMM_PPOOL_FREE_BLOCK_HEADER BestBlock;
|
||||
PMM_PPOOL_FREE_BLOCK_HEADER CurrentBlock;
|
||||
ULONG BlockSize;
|
||||
PMM_PPOOL_USED_BLOCK_HEADER NewBlock;
|
||||
PMM_PPOOL_FREE_BLOCK_HEADER NextBlock;
|
||||
PMM_PPOOL_FREE_BLOCK_HEADER PreviousBlock;
|
||||
PMM_PPOOL_FREE_BLOCK_HEADER BestPreviousBlock;
|
||||
PVOID BlockAddress;
|
||||
ULONG Alignment;
|
||||
|
||||
ExAcquireFastMutex(&MmPagedPoolLock);
|
||||
ExAcquireFastMutex(&MmPagedPoolLock);
|
||||
|
||||
/*
|
||||
* Don't bother allocating anything for a zero-byte block.
|
||||
*/
|
||||
if (NumberOfBytes == 0)
|
||||
{
|
||||
/*
|
||||
* Don't bother allocating anything for a zero-byte block.
|
||||
*/
|
||||
if (NumberOfBytes == 0)
|
||||
{
|
||||
MmDbgPagedPoolRedZoneCheck(__FILE__,__LINE__);
|
||||
ExReleaseFastMutex(&MmPagedPoolLock);
|
||||
return(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
DPRINT ( "ExAllocatePagedPoolWithTag(%i,%lu,%lu)\n", PoolType, NumberOfBytes, Tag );
|
||||
VerifyPagedPool();
|
||||
DPRINT ( "ExAllocatePagedPoolWithTag(%i,%lu,%lu)\n", PoolType, NumberOfBytes, Tag );
|
||||
VerifyPagedPool();
|
||||
|
||||
if (NumberOfBytes >= PAGE_SIZE)
|
||||
{
|
||||
if (NumberOfBytes >= PAGE_SIZE)
|
||||
{
|
||||
Alignment = PAGE_SIZE;
|
||||
}
|
||||
else if (PoolType == PagedPoolCacheAligned)
|
||||
{
|
||||
}
|
||||
else if (PoolType == PagedPoolCacheAligned)
|
||||
{
|
||||
Alignment = MM_CACHE_LINE_SIZE;
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
Alignment = MM_POOL_ALIGNMENT;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the total number of bytes we will need.
|
||||
*/
|
||||
BlockSize = NumberOfBytes + sizeof(MM_PPOOL_USED_BLOCK_HEADER) + 2*MM_PPOOL_REDZONE_BYTES;
|
||||
if (BlockSize < sizeof(MM_PPOOL_FREE_BLOCK_HEADER))
|
||||
{
|
||||
/* At least we need the size of the free block header. */
|
||||
BlockSize = sizeof(MM_PPOOL_FREE_BLOCK_HEADER);
|
||||
}
|
||||
/*
|
||||
* Calculate the total number of bytes we will need.
|
||||
*/
|
||||
BlockSize = NumberOfBytes + sizeof(MM_PPOOL_USED_BLOCK_HEADER) + 2*MM_PPOOL_REDZONE_BYTES;
|
||||
if (BlockSize < sizeof(MM_PPOOL_FREE_BLOCK_HEADER))
|
||||
{
|
||||
/* At least we need the size of the free block header. */
|
||||
BlockSize = sizeof(MM_PPOOL_FREE_BLOCK_HEADER);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Find the best-fitting block.
|
||||
*/
|
||||
PreviousBlock = NULL;
|
||||
BestPreviousBlock = BestBlock = NULL;
|
||||
CurrentBlock = MmPagedPoolFirstFreeBlock;
|
||||
if ( Alignment > 0 )
|
||||
{
|
||||
/*
|
||||
* Find the best-fitting block.
|
||||
*/
|
||||
PreviousBlock = NULL;
|
||||
BestPreviousBlock = BestBlock = NULL;
|
||||
CurrentBlock = MmPagedPoolFirstFreeBlock;
|
||||
if ( Alignment > 0 )
|
||||
{
|
||||
PVOID BestAlignedAddr = NULL;
|
||||
while ( CurrentBlock != NULL )
|
||||
{
|
||||
PVOID Addr = block_to_address(CurrentBlock);
|
||||
PVOID CurrentBlockEnd = (char*)CurrentBlock + CurrentBlock->Size;
|
||||
/* calculate last size-aligned address available within this block */
|
||||
PVOID AlignedAddr = MM_ROUND_DOWN((char*)CurrentBlockEnd-NumberOfBytes-MM_PPOOL_REDZONE_BYTES, Alignment);
|
||||
assert ( (char*)AlignedAddr+NumberOfBytes+MM_PPOOL_REDZONE_BYTES <= (char*)CurrentBlockEnd );
|
||||
{
|
||||
PVOID Addr = block_to_address(CurrentBlock);
|
||||
PVOID CurrentBlockEnd = (char*)CurrentBlock + CurrentBlock->Size;
|
||||
/* calculate last size-aligned address available within this block */
|
||||
PVOID AlignedAddr = MM_ROUND_DOWN((char*)CurrentBlockEnd-NumberOfBytes-MM_PPOOL_REDZONE_BYTES, Alignment);
|
||||
assert ( (char*)AlignedAddr+NumberOfBytes+MM_PPOOL_REDZONE_BYTES <= (char*)CurrentBlockEnd );
|
||||
|
||||
/* special case, this address is already size-aligned, and the right size */
|
||||
if ( Addr == AlignedAddr )
|
||||
{
|
||||
BestAlignedAddr = AlignedAddr;
|
||||
BestPreviousBlock = PreviousBlock;
|
||||
BestBlock = CurrentBlock;
|
||||
break;
|
||||
}
|
||||
else if ( Addr < (PVOID)address_to_block(AlignedAddr) )
|
||||
{
|
||||
/*
|
||||
* there's enough room to allocate our size-aligned memory out
|
||||
* of this block, see if it's a better choice than any previous
|
||||
* finds
|
||||
*/
|
||||
if ( BestBlock == NULL || BestBlock->Size > CurrentBlock->Size )
|
||||
{
|
||||
BestAlignedAddr = AlignedAddr;
|
||||
BestPreviousBlock = PreviousBlock;
|
||||
BestBlock = CurrentBlock;
|
||||
}
|
||||
}
|
||||
/* special case, this address is already size-aligned, and the right size */
|
||||
if ( Addr == AlignedAddr )
|
||||
{
|
||||
BestAlignedAddr = AlignedAddr;
|
||||
BestPreviousBlock = PreviousBlock;
|
||||
BestBlock = CurrentBlock;
|
||||
break;
|
||||
}
|
||||
else if ( Addr < (PVOID)address_to_block(AlignedAddr) )
|
||||
{
|
||||
/*
|
||||
* there's enough room to allocate our size-aligned memory out
|
||||
* of this block, see if it's a better choice than any previous
|
||||
* finds
|
||||
*/
|
||||
if ( BestBlock == NULL || BestBlock->Size > CurrentBlock->Size )
|
||||
{
|
||||
BestAlignedAddr = AlignedAddr;
|
||||
BestPreviousBlock = PreviousBlock;
|
||||
BestBlock = CurrentBlock;
|
||||
}
|
||||
}
|
||||
|
||||
PreviousBlock = CurrentBlock;
|
||||
CurrentBlock = CurrentBlock->NextFree;
|
||||
}
|
||||
PreviousBlock = CurrentBlock;
|
||||
CurrentBlock = CurrentBlock->NextFree;
|
||||
}
|
||||
|
||||
/*
|
||||
* we found a best block can/should we chop a few bytes off the beginning
|
||||
* into a separate memory block?
|
||||
*/
|
||||
if ( BestBlock != NULL )
|
||||
{
|
||||
PVOID Addr = block_to_address(BestBlock);
|
||||
if ( BestAlignedAddr != Addr )
|
||||
{
|
||||
PMM_PPOOL_FREE_BLOCK_HEADER NewFreeBlock =
|
||||
(PMM_PPOOL_FREE_BLOCK_HEADER)address_to_block(BestAlignedAddr);
|
||||
assert ( BestAlignedAddr > Addr );
|
||||
NewFreeBlock->Size = (char*)Addr + BestBlock->Size - (char*)BestAlignedAddr;
|
||||
ASSERT_SIZE(NewFreeBlock->Size);
|
||||
BestBlock->Size = (size_t)NewFreeBlock - (size_t)Addr;
|
||||
ASSERT_SIZE(BestBlock->Size);
|
||||
{
|
||||
PVOID Addr = block_to_address(BestBlock);
|
||||
if ( BestAlignedAddr != Addr )
|
||||
{
|
||||
PMM_PPOOL_FREE_BLOCK_HEADER NewFreeBlock =
|
||||
(PMM_PPOOL_FREE_BLOCK_HEADER)address_to_block(BestAlignedAddr);
|
||||
assert ( BestAlignedAddr > Addr );
|
||||
NewFreeBlock->Size = (char*)Addr + BestBlock->Size - (char*)BestAlignedAddr;
|
||||
ASSERT_SIZE(NewFreeBlock->Size);
|
||||
BestBlock->Size = (size_t)NewFreeBlock - (size_t)Addr;
|
||||
ASSERT_SIZE(BestBlock->Size);
|
||||
|
||||
DPRINT ( "breaking off preceding bytes into their own block...\n" );
|
||||
DPRINT ( "NewFreeBlock 0x%x Size %lu (Old Block's new size %lu) NextFree 0x%x\n",
|
||||
NewFreeBlock, NewFreeBlock->Size, BestBlock->Size, BestBlock->NextFree );
|
||||
DPRINT ( "breaking off preceding bytes into their own block...\n" );
|
||||
DPRINT ( "NewFreeBlock 0x%x Size %lu (Old Block's new size %lu) NextFree 0x%x\n",
|
||||
NewFreeBlock, NewFreeBlock->Size, BestBlock->Size, BestBlock->NextFree );
|
||||
|
||||
/* insert the new block into the chain */
|
||||
NewFreeBlock->NextFree = BestBlock->NextFree;
|
||||
BestBlock->NextFree = NewFreeBlock;
|
||||
/* insert the new block into the chain */
|
||||
NewFreeBlock->NextFree = BestBlock->NextFree;
|
||||
BestBlock->NextFree = NewFreeBlock;
|
||||
|
||||
/* we want the following code to use our size-aligned block */
|
||||
BestPreviousBlock = BestBlock;
|
||||
BestBlock = NewFreeBlock;
|
||||
/* we want the following code to use our size-aligned block */
|
||||
BestPreviousBlock = BestBlock;
|
||||
BestBlock = NewFreeBlock;
|
||||
|
||||
//VerifyPagedPool();
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* non-size-aligned block search
|
||||
*/
|
||||
else while ( CurrentBlock != NULL )
|
||||
{
|
||||
if ( CurrentBlock->Size >= BlockSize
|
||||
&& ( BestBlock == NULL || BestBlock->Size > CurrentBlock->Size )
|
||||
)
|
||||
{
|
||||
BestPreviousBlock = PreviousBlock;
|
||||
BestBlock = CurrentBlock;
|
||||
}
|
||||
//VerifyPagedPool();
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* non-size-aligned block search
|
||||
*/
|
||||
else
|
||||
while ( CurrentBlock != NULL )
|
||||
{
|
||||
if ( CurrentBlock->Size >= BlockSize
|
||||
&& ( BestBlock == NULL || BestBlock->Size > CurrentBlock->Size )
|
||||
)
|
||||
{
|
||||
BestPreviousBlock = PreviousBlock;
|
||||
BestBlock = CurrentBlock;
|
||||
}
|
||||
|
||||
PreviousBlock = CurrentBlock;
|
||||
CurrentBlock = CurrentBlock->NextFree;
|
||||
}
|
||||
PreviousBlock = CurrentBlock;
|
||||
CurrentBlock = CurrentBlock->NextFree;
|
||||
}
|
||||
|
||||
/*
|
||||
* We didn't find anything suitable at all.
|
||||
*/
|
||||
if (BestBlock == NULL)
|
||||
{
|
||||
/*
|
||||
* We didn't find anything suitable at all.
|
||||
*/
|
||||
if (BestBlock == NULL)
|
||||
{
|
||||
DPRINT1("Trying to allocate %lu bytes from paged pool - nothing suitable found, returning NULL\n",
|
||||
NumberOfBytes );
|
||||
ExReleaseFastMutex(&MmPagedPoolLock);
|
||||
return(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
DPRINT("BestBlock 0x%x NextFree 0x%x\n", BestBlock, BestBlock->NextFree );
|
||||
DPRINT("BestBlock 0x%x NextFree 0x%x\n", BestBlock, BestBlock->NextFree );
|
||||
|
||||
//VerifyPagedPool();
|
||||
//VerifyPagedPool();
|
||||
|
||||
/*
|
||||
* Is there enough space to create a second block from the unused portion.
|
||||
*/
|
||||
if ( BestBlock->Size > BlockSize
|
||||
&& (BestBlock->Size - BlockSize) > sizeof(MM_PPOOL_FREE_BLOCK_HEADER)
|
||||
)
|
||||
{
|
||||
/*
|
||||
* Is there enough space to create a second block from the unused portion.
|
||||
*/
|
||||
if ( BestBlock->Size > BlockSize
|
||||
&& (BestBlock->Size - BlockSize) > sizeof(MM_PPOOL_FREE_BLOCK_HEADER)
|
||||
)
|
||||
{
|
||||
ULONG NewSize = BestBlock->Size - BlockSize;
|
||||
ASSERT_SIZE ( NewSize );
|
||||
|
||||
//DPRINT("creating 2nd block from unused portion\n");
|
||||
DPRINT("BestBlock 0x%x Size 0x%x BlockSize 0x%x NewSize 0x%x\n",
|
||||
BestBlock, BestBlock->Size, BlockSize, NewSize );
|
||||
BestBlock, BestBlock->Size, BlockSize, NewSize );
|
||||
|
||||
/*
|
||||
* Create the new free block.
|
||||
@@ -349,15 +354,15 @@ ExAllocatePagedPoolWithTag (IN POOL_TYPE PoolType,
|
||||
*/
|
||||
//DPRINT("replacing old free block with it");
|
||||
if (BestPreviousBlock == NULL)
|
||||
{
|
||||
//DPRINT("(from beginning)");
|
||||
MmPagedPoolFirstFreeBlock = NextBlock;
|
||||
}
|
||||
{
|
||||
//DPRINT("(from beginning)");
|
||||
MmPagedPoolFirstFreeBlock = NextBlock;
|
||||
}
|
||||
else
|
||||
{
|
||||
//DPRINT("(from previous)");
|
||||
BestPreviousBlock->NextFree = NextBlock;
|
||||
}
|
||||
{
|
||||
//DPRINT("(from previous)");
|
||||
BestPreviousBlock->NextFree = NextBlock;
|
||||
}
|
||||
//DPRINT(".\n");
|
||||
|
||||
/*
|
||||
@@ -369,9 +374,9 @@ ExAllocatePagedPoolWithTag (IN POOL_TYPE PoolType,
|
||||
NewBlock->Size = BlockSize;
|
||||
ASSERT_SIZE ( NewBlock->Size );
|
||||
//DPRINT(".\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
ULONG NewSize = BestBlock->Size;
|
||||
|
||||
/*
|
||||
@@ -379,13 +384,13 @@ ExAllocatePagedPoolWithTag (IN POOL_TYPE PoolType,
|
||||
*/
|
||||
//DPRINT ( "Removing selected block from free block list\n" );
|
||||
if (BestPreviousBlock == NULL)
|
||||
{
|
||||
MmPagedPoolFirstFreeBlock = BestBlock->NextFree;
|
||||
}
|
||||
{
|
||||
MmPagedPoolFirstFreeBlock = BestBlock->NextFree;
|
||||
}
|
||||
else
|
||||
{
|
||||
BestPreviousBlock->NextFree = BestBlock->NextFree;
|
||||
}
|
||||
{
|
||||
BestPreviousBlock->NextFree = BestBlock->NextFree;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up the header of the new block
|
||||
@@ -393,167 +398,168 @@ ExAllocatePagedPoolWithTag (IN POOL_TYPE PoolType,
|
||||
NewBlock = (PMM_PPOOL_USED_BLOCK_HEADER)BestBlock;
|
||||
NewBlock->Size = NewSize;
|
||||
ASSERT_SIZE ( NewBlock->Size );
|
||||
}
|
||||
}
|
||||
|
||||
#if MM_PPOOL_REDZONE_BYTES
|
||||
// now add the block to the used block list
|
||||
NewBlock->NextUsed = MmPagedPoolFirstUsedBlock;
|
||||
MmPagedPoolFirstUsedBlock = NewBlock;
|
||||
// now add the block to the used block list
|
||||
NewBlock->NextUsed = MmPagedPoolFirstUsedBlock;
|
||||
MmPagedPoolFirstUsedBlock = NewBlock;
|
||||
#endif//MM_PPOOL_REDZONE_BYTES
|
||||
|
||||
VerifyPagedPool();
|
||||
VerifyPagedPool();
|
||||
|
||||
ExReleaseFastMutex(&MmPagedPoolLock);
|
||||
ExReleaseFastMutex(&MmPagedPoolLock);
|
||||
|
||||
BlockAddress = block_to_address ( NewBlock );
|
||||
/* RtlZeroMemory(BlockAddress, NumberOfBytes);*/
|
||||
BlockAddress = block_to_address ( NewBlock );
|
||||
/* RtlZeroMemory(BlockAddress, NumberOfBytes);*/
|
||||
|
||||
#if MM_PPOOL_REDZONE_BYTES
|
||||
NewBlock->UserSize = NumberOfBytes;
|
||||
// write out buffer-overrun detection bytes
|
||||
{
|
||||
PUCHAR Addr = (PUCHAR)BlockAddress;
|
||||
//DbgPrint ( "writing buffer-overrun detection bytes" );
|
||||
memset ( Addr - MM_PPOOL_REDZONE_BYTES,
|
||||
MM_PPOOL_REDZONE_VALUE, MM_PPOOL_REDZONE_BYTES );
|
||||
memset ( Addr + NewBlock->UserSize, MM_PPOOL_REDZONE_VALUE,
|
||||
MM_PPOOL_REDZONE_BYTES );
|
||||
/*for ( i = 0; i < MM_PPOOL_REDZONE_BYTES; i++ )
|
||||
{
|
||||
//DbgPrint(".");
|
||||
*(Addr-i-1) = 0xCD;
|
||||
//DbgPrint("o");
|
||||
*(Addr+NewBlock->UserSize+i) = 0xCD;
|
||||
}*/
|
||||
//DbgPrint ( "done!\n" );
|
||||
}
|
||||
|
||||
NewBlock->UserSize = NumberOfBytes;
|
||||
// write out buffer-overrun detection bytes
|
||||
{
|
||||
PUCHAR Addr = (PUCHAR)BlockAddress;
|
||||
//DbgPrint ( "writing buffer-overrun detection bytes" );
|
||||
memset ( Addr - MM_PPOOL_REDZONE_BYTES,
|
||||
MM_PPOOL_REDZONE_VALUE, MM_PPOOL_REDZONE_BYTES );
|
||||
memset ( Addr + NewBlock->UserSize, MM_PPOOL_REDZONE_VALUE,
|
||||
MM_PPOOL_REDZONE_BYTES );
|
||||
/*for ( i = 0; i < MM_PPOOL_REDZONE_BYTES; i++ )
|
||||
{
|
||||
//DbgPrint(".");
|
||||
*(Addr-i-1) = 0xCD;
|
||||
//DbgPrint("o");
|
||||
*(Addr+NewBlock->UserSize+i) = 0xCD;
|
||||
}*/
|
||||
//DbgPrint ( "done!\n" );
|
||||
}
|
||||
|
||||
#endif//MM_PPOOL_REDZONE_BYTES
|
||||
|
||||
return(BlockAddress);
|
||||
return(BlockAddress);
|
||||
}
|
||||
|
||||
VOID STDCALL
|
||||
ExFreePagedPool(IN PVOID Block)
|
||||
{
|
||||
PMM_PPOOL_FREE_BLOCK_HEADER PreviousBlock;
|
||||
PMM_PPOOL_USED_BLOCK_HEADER UsedBlock = address_to_block(Block);
|
||||
ULONG UsedSize = UsedBlock->Size;
|
||||
PMM_PPOOL_FREE_BLOCK_HEADER FreeBlock =
|
||||
(PMM_PPOOL_FREE_BLOCK_HEADER)UsedBlock;
|
||||
PMM_PPOOL_FREE_BLOCK_HEADER NextBlock;
|
||||
PMM_PPOOL_FREE_BLOCK_HEADER NextNextBlock;
|
||||
PMM_PPOOL_FREE_BLOCK_HEADER PreviousBlock;
|
||||
PMM_PPOOL_USED_BLOCK_HEADER UsedBlock = address_to_block(Block);
|
||||
ULONG UsedSize = UsedBlock->Size;
|
||||
PMM_PPOOL_FREE_BLOCK_HEADER FreeBlock =
|
||||
(PMM_PPOOL_FREE_BLOCK_HEADER)UsedBlock;
|
||||
PMM_PPOOL_FREE_BLOCK_HEADER NextBlock;
|
||||
PMM_PPOOL_FREE_BLOCK_HEADER NextNextBlock;
|
||||
|
||||
#if MM_PPOOL_REDZONE_BYTES
|
||||
// write out buffer-overrun detection bytes
|
||||
{
|
||||
int i;
|
||||
PUCHAR Addr = (PUCHAR)Block;
|
||||
//DbgPrint ( "checking buffer-overrun detection bytes..." );
|
||||
for ( i = 0; i < MM_PPOOL_REDZONE_BYTES; i++ )
|
||||
{
|
||||
if (*(Addr-i-1) != MM_PPOOL_REDZONE_VALUE)
|
||||
// write out buffer-overrun detection bytes
|
||||
{
|
||||
int i;
|
||||
PUCHAR Addr = (PUCHAR)Block;
|
||||
//DbgPrint ( "checking buffer-overrun detection bytes..." );
|
||||
for ( i = 0; i < MM_PPOOL_REDZONE_BYTES; i++ )
|
||||
{
|
||||
DPRINT1("Attempt to free memory %#08x. Redzone underrun!\n", Block);
|
||||
}
|
||||
if (*(Addr+UsedBlock->UserSize+i) != MM_PPOOL_REDZONE_VALUE)
|
||||
{
|
||||
DPRINT1("Attempt to free memory %#08x. Redzone overrun!\n", Block);
|
||||
}
|
||||
if (*(Addr-i-1) != MM_PPOOL_REDZONE_VALUE)
|
||||
{
|
||||
DPRINT1("Attempt to free memory %#08x. Redzone underrun!\n", Block);
|
||||
}
|
||||
if (*(Addr+UsedBlock->UserSize+i) != MM_PPOOL_REDZONE_VALUE)
|
||||
{
|
||||
DPRINT1("Attempt to free memory %#08x. Redzone overrun!\n", Block);
|
||||
}
|
||||
|
||||
assert ( *(Addr-i-1) == MM_PPOOL_REDZONE_VALUE );
|
||||
assert ( *(Addr+UsedBlock->UserSize+i) == MM_PPOOL_REDZONE_VALUE );
|
||||
}
|
||||
//DbgPrint ( "done!\n" );
|
||||
}
|
||||
assert ( *(Addr-i-1) == MM_PPOOL_REDZONE_VALUE );
|
||||
assert ( *(Addr+UsedBlock->UserSize+i) == MM_PPOOL_REDZONE_VALUE );
|
||||
}
|
||||
//DbgPrint ( "done!\n" );
|
||||
}
|
||||
#endif//MM_PPOOL_REDZONE_BYTES
|
||||
|
||||
ExAcquireFastMutex(&MmPagedPoolLock);
|
||||
ExAcquireFastMutex(&MmPagedPoolLock);
|
||||
|
||||
#if MM_PPOOL_REDZONE_BYTES
|
||||
// remove from used list...
|
||||
{
|
||||
PMM_PPOOL_USED_BLOCK_HEADER pPrev = MmPagedPoolFirstUsedBlock;
|
||||
if ( pPrev == UsedBlock )
|
||||
{
|
||||
// special-case, our freeing block is first in list...
|
||||
MmPagedPoolFirstUsedBlock = pPrev->NextUsed;
|
||||
}
|
||||
else
|
||||
{
|
||||
while ( pPrev && pPrev->NextUsed != UsedBlock )
|
||||
pPrev = pPrev->NextUsed;
|
||||
// if this assert fails - memory has been corrupted
|
||||
// ( or I have a logic error...! )
|
||||
assert ( pPrev->NextUsed == UsedBlock );
|
||||
pPrev->NextUsed = UsedBlock->NextUsed;
|
||||
}
|
||||
}
|
||||
// remove from used list...
|
||||
{
|
||||
PMM_PPOOL_USED_BLOCK_HEADER pPrev = MmPagedPoolFirstUsedBlock;
|
||||
if ( pPrev == UsedBlock )
|
||||
{
|
||||
// special-case, our freeing block is first in list...
|
||||
MmPagedPoolFirstUsedBlock = pPrev->NextUsed;
|
||||
}
|
||||
else
|
||||
{
|
||||
while ( pPrev && pPrev->NextUsed != UsedBlock )
|
||||
pPrev = pPrev->NextUsed;
|
||||
// if this assert fails - memory has been corrupted
|
||||
// ( or I have a logic error...! )
|
||||
assert ( pPrev->NextUsed == UsedBlock );
|
||||
pPrev->NextUsed = UsedBlock->NextUsed;
|
||||
}
|
||||
}
|
||||
#endif//MM_PPOOL_REDZONE_BYTES
|
||||
|
||||
/*
|
||||
* Begin setting up the newly freed block's header.
|
||||
*/
|
||||
FreeBlock->Size = UsedSize;
|
||||
ASSERT_SIZE ( FreeBlock->Size );
|
||||
/*
|
||||
* Begin setting up the newly freed block's header.
|
||||
*/
|
||||
FreeBlock->Size = UsedSize;
|
||||
ASSERT_SIZE ( FreeBlock->Size );
|
||||
|
||||
/*
|
||||
* Find the blocks immediately before and after the newly freed block on the free list.
|
||||
*/
|
||||
PreviousBlock = NULL;
|
||||
NextBlock = MmPagedPoolFirstFreeBlock;
|
||||
while (NextBlock != NULL && NextBlock < FreeBlock)
|
||||
{
|
||||
/*
|
||||
* Find the blocks immediately before and after the newly freed block on the free list.
|
||||
*/
|
||||
PreviousBlock = NULL;
|
||||
NextBlock = MmPagedPoolFirstFreeBlock;
|
||||
while (NextBlock != NULL && NextBlock < FreeBlock)
|
||||
{
|
||||
PreviousBlock = NextBlock;
|
||||
NextBlock = NextBlock->NextFree;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Insert the freed block on the free list.
|
||||
*/
|
||||
if (PreviousBlock == NULL)
|
||||
{
|
||||
/*
|
||||
* Insert the freed block on the free list.
|
||||
*/
|
||||
if (PreviousBlock == NULL)
|
||||
{
|
||||
FreeBlock->NextFree = MmPagedPoolFirstFreeBlock;
|
||||
MmPagedPoolFirstFreeBlock = FreeBlock;
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
PreviousBlock->NextFree = FreeBlock;
|
||||
FreeBlock->NextFree = NextBlock;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If the next block is immediately adjacent to the newly freed one then
|
||||
* merge them.
|
||||
*/
|
||||
if (NextBlock != NULL &&
|
||||
((char*)FreeBlock + FreeBlock->Size) == (char*)NextBlock)
|
||||
{
|
||||
/*
|
||||
* If the next block is immediately adjacent to the newly freed one then
|
||||
* merge them.
|
||||
*/
|
||||
if (NextBlock != NULL &&
|
||||
((char*)FreeBlock + FreeBlock->Size) == (char*)NextBlock)
|
||||
{
|
||||
FreeBlock->Size = FreeBlock->Size + NextBlock->Size;
|
||||
ASSERT_SIZE ( FreeBlock->Size );
|
||||
FreeBlock->NextFree = NextBlock->NextFree;
|
||||
NextNextBlock = NextBlock->NextFree;
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
NextNextBlock = NextBlock;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If the previous block is adjacent to the newly freed one then
|
||||
* merge them.
|
||||
*/
|
||||
if (PreviousBlock != NULL &&
|
||||
((char*)PreviousBlock + PreviousBlock->Size) == (char*)FreeBlock)
|
||||
{
|
||||
/*
|
||||
* If the previous block is adjacent to the newly freed one then
|
||||
* merge them.
|
||||
*/
|
||||
if (PreviousBlock != NULL &&
|
||||
((char*)PreviousBlock + PreviousBlock->Size) == (char*)FreeBlock)
|
||||
{
|
||||
PreviousBlock->Size = PreviousBlock->Size + FreeBlock->Size;
|
||||
ASSERT_SIZE ( PreviousBlock->Size );
|
||||
PreviousBlock->NextFree = NextNextBlock;
|
||||
}
|
||||
}
|
||||
|
||||
VerifyPagedPool();
|
||||
VerifyPagedPool();
|
||||
|
||||
ExReleaseFastMutex(&MmPagedPoolLock);
|
||||
ExReleaseFastMutex(&MmPagedPoolLock);
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
||||
+204
-200
@@ -16,14 +16,14 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
/* $Id: region.c,v 1.6 2003/12/30 18:52:05 fireball Exp $
|
||||
/* $Id: region.c,v 1.7 2004/04/10 22:35:25 gdalsnes Exp $
|
||||
*
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: ntoskrnl/mm/region.c
|
||||
* PROGRAMMER: David Welch
|
||||
* PURPOSE:
|
||||
*/
|
||||
|
||||
|
||||
/* INCLUDE *****************************************************************/
|
||||
|
||||
#include <ddk/ntddk.h>
|
||||
@@ -43,279 +43,283 @@
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
VOID STATIC
|
||||
VOID STATIC
|
||||
InsertAfterEntry(PLIST_ENTRY Previous,
|
||||
PLIST_ENTRY Entry)
|
||||
PLIST_ENTRY Entry)
|
||||
/*
|
||||
* FUNCTION: Insert a list entry after another entry in the list
|
||||
*/
|
||||
{
|
||||
Previous->Flink->Blink = Entry;
|
||||
|
||||
|
||||
Entry->Flink = Previous->Flink;
|
||||
Entry->Blink = Previous;
|
||||
|
||||
|
||||
Previous->Flink = Entry;
|
||||
}
|
||||
|
||||
PMM_REGION STATIC
|
||||
MmSplitRegion(PMM_REGION InitialRegion, PVOID InitialBaseAddress,
|
||||
PVOID StartAddress, ULONG Length, ULONG NewType,
|
||||
ULONG NewProtect, PMADDRESS_SPACE AddressSpace,
|
||||
PMM_ALTER_REGION_FUNC AlterFunc)
|
||||
PVOID StartAddress, ULONG Length, ULONG NewType,
|
||||
ULONG NewProtect, PMADDRESS_SPACE AddressSpace,
|
||||
PMM_ALTER_REGION_FUNC AlterFunc)
|
||||
{
|
||||
PMM_REGION NewRegion1;
|
||||
PMM_REGION NewRegion2;
|
||||
ULONG InternalLength;
|
||||
|
||||
/* Allocate this in front otherwise the failure case is too difficult. */
|
||||
NewRegion2 = ExAllocatePoolWithTag(NonPagedPool, sizeof(MM_REGION),
|
||||
TAG_MM_REGION);
|
||||
if (NewRegion2 == NULL)
|
||||
{
|
||||
return(NULL);
|
||||
}
|
||||
PMM_REGION NewRegion1;
|
||||
PMM_REGION NewRegion2;
|
||||
ULONG InternalLength;
|
||||
|
||||
/* Create the new region. */
|
||||
NewRegion1 = ExAllocatePoolWithTag(NonPagedPool, sizeof(MM_REGION),
|
||||
TAG_MM_REGION);
|
||||
if (NewRegion1 == NULL)
|
||||
{
|
||||
/* Allocate this in front otherwise the failure case is too difficult. */
|
||||
NewRegion2 = ExAllocatePoolWithTag(NonPagedPool, sizeof(MM_REGION),
|
||||
TAG_MM_REGION);
|
||||
if (NewRegion2 == NULL)
|
||||
{
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/* Create the new region. */
|
||||
NewRegion1 = ExAllocatePoolWithTag(NonPagedPool, sizeof(MM_REGION),
|
||||
TAG_MM_REGION);
|
||||
if (NewRegion1 == NULL)
|
||||
{
|
||||
ExFreePool(NewRegion2);
|
||||
return(NULL);
|
||||
}
|
||||
NewRegion1->Type = NewType;
|
||||
NewRegion1->Protect = NewProtect;
|
||||
InternalLength = ((char*)InitialBaseAddress + InitialRegion->Length) - (char*)StartAddress;
|
||||
InternalLength = min(InternalLength, Length);
|
||||
NewRegion1->Length = InternalLength;
|
||||
InsertAfterEntry(&InitialRegion->RegionListEntry,
|
||||
&NewRegion1->RegionListEntry);
|
||||
}
|
||||
NewRegion1->Type = NewType;
|
||||
NewRegion1->Protect = NewProtect;
|
||||
InternalLength = ((char*)InitialBaseAddress + InitialRegion->Length) - (char*)StartAddress;
|
||||
InternalLength = min(InternalLength, Length);
|
||||
NewRegion1->Length = InternalLength;
|
||||
InsertAfterEntry(&InitialRegion->RegionListEntry,
|
||||
&NewRegion1->RegionListEntry);
|
||||
|
||||
/*
|
||||
* Call our helper function to do the changes on the addresses contained
|
||||
* in the initial region.
|
||||
*/
|
||||
AlterFunc(AddressSpace, StartAddress, InternalLength, InitialRegion->Type,
|
||||
InitialRegion->Protect, NewType, NewProtect);
|
||||
/*
|
||||
* Call our helper function to do the changes on the addresses contained
|
||||
* in the initial region.
|
||||
*/
|
||||
AlterFunc(AddressSpace, StartAddress, InternalLength, InitialRegion->Type,
|
||||
InitialRegion->Protect, NewType, NewProtect);
|
||||
|
||||
/*
|
||||
* If necessary create a new region for the portion of the initial region
|
||||
* beyond the range of addresses to alter.
|
||||
*/
|
||||
if (((char*)InitialBaseAddress + InitialRegion->Length) > ((char*)StartAddress + Length))
|
||||
{
|
||||
/*
|
||||
* If necessary create a new region for the portion of the initial region
|
||||
* beyond the range of addresses to alter.
|
||||
*/
|
||||
if (((char*)InitialBaseAddress + InitialRegion->Length) > ((char*)StartAddress + Length))
|
||||
{
|
||||
NewRegion2->Type = InitialRegion->Type;
|
||||
NewRegion2->Protect = InitialRegion->Protect;
|
||||
NewRegion2->Length = ((char*)InitialBaseAddress + InitialRegion->Length) -
|
||||
((char*)StartAddress + Length);
|
||||
InsertAfterEntry(&NewRegion1->RegionListEntry,
|
||||
&NewRegion2->RegionListEntry);
|
||||
}
|
||||
else
|
||||
{
|
||||
NewRegion2->Length = ((char*)InitialBaseAddress + InitialRegion->Length) -
|
||||
((char*)StartAddress + Length);
|
||||
InsertAfterEntry(&NewRegion1->RegionListEntry,
|
||||
&NewRegion2->RegionListEntry);
|
||||
}
|
||||
else
|
||||
{
|
||||
ExFreePool(NewRegion2);
|
||||
}
|
||||
}
|
||||
|
||||
/* Either remove or shrink the initial region. */
|
||||
if (InitialBaseAddress == StartAddress)
|
||||
{
|
||||
/* Either remove or shrink the initial region. */
|
||||
if (InitialBaseAddress == StartAddress)
|
||||
{
|
||||
RemoveEntryList(&InitialRegion->RegionListEntry);
|
||||
ExFreePool(InitialRegion);
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
InitialRegion->Length = (char*)StartAddress - (char*)InitialBaseAddress;
|
||||
}
|
||||
|
||||
return(NewRegion1);
|
||||
}
|
||||
|
||||
return(NewRegion1);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
MmAlterRegion(PMADDRESS_SPACE AddressSpace, PVOID BaseAddress,
|
||||
PLIST_ENTRY RegionListHead, PVOID StartAddress, ULONG Length,
|
||||
ULONG NewType, ULONG NewProtect, PMM_ALTER_REGION_FUNC AlterFunc)
|
||||
MmAlterRegion(PMADDRESS_SPACE AddressSpace, PVOID BaseAddress,
|
||||
PLIST_ENTRY RegionListHead, PVOID StartAddress, ULONG Length,
|
||||
ULONG NewType, ULONG NewProtect, PMM_ALTER_REGION_FUNC AlterFunc)
|
||||
{
|
||||
PMM_REGION InitialRegion;
|
||||
PVOID InitialBaseAddress;
|
||||
PMM_REGION NewRegion;
|
||||
PLIST_ENTRY CurrentEntry;
|
||||
PMM_REGION CurrentRegion = NULL;
|
||||
PVOID CurrentBaseAddress;
|
||||
ULONG RemainingLength;
|
||||
PMM_REGION InitialRegion;
|
||||
PVOID InitialBaseAddress;
|
||||
PMM_REGION NewRegion;
|
||||
PLIST_ENTRY CurrentEntry;
|
||||
PMM_REGION CurrentRegion = NULL;
|
||||
PVOID CurrentBaseAddress;
|
||||
ULONG RemainingLength;
|
||||
|
||||
/*
|
||||
* Find the first region containing part of the range of addresses to
|
||||
* be altered.
|
||||
*/
|
||||
InitialRegion = MmFindRegion(BaseAddress, RegionListHead, StartAddress,
|
||||
&InitialBaseAddress);
|
||||
if (((char*)StartAddress + Length) >
|
||||
((char*)InitialBaseAddress + InitialRegion->Length))
|
||||
{
|
||||
RemainingLength = ((char*)StartAddress + Length) -
|
||||
((char*)InitialBaseAddress + InitialRegion->Length);
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Find the first region containing part of the range of addresses to
|
||||
* be altered.
|
||||
*/
|
||||
InitialRegion = MmFindRegion(BaseAddress, RegionListHead, StartAddress,
|
||||
&InitialBaseAddress);
|
||||
if (((char*)StartAddress + Length) >
|
||||
((char*)InitialBaseAddress + InitialRegion->Length))
|
||||
{
|
||||
RemainingLength = ((char*)StartAddress + Length) -
|
||||
((char*)InitialBaseAddress + InitialRegion->Length);
|
||||
}
|
||||
else
|
||||
{
|
||||
RemainingLength = 0;
|
||||
}
|
||||
/*
|
||||
* If necessary then split the region into the affected and unaffected parts.
|
||||
*/
|
||||
if (InitialRegion->Type != NewType || InitialRegion->Protect != NewProtect)
|
||||
{
|
||||
NewRegion = MmSplitRegion(InitialRegion, InitialBaseAddress,
|
||||
StartAddress, Length, NewType, NewProtect,
|
||||
AddressSpace, AlterFunc);
|
||||
}
|
||||
/*
|
||||
* If necessary then split the region into the affected and unaffected parts.
|
||||
*/
|
||||
if (InitialRegion->Type != NewType || InitialRegion->Protect != NewProtect)
|
||||
{
|
||||
NewRegion = MmSplitRegion(InitialRegion, InitialBaseAddress,
|
||||
StartAddress, Length, NewType, NewProtect,
|
||||
AddressSpace, AlterFunc);
|
||||
if (NewRegion == NULL)
|
||||
{
|
||||
return(STATUS_NO_MEMORY);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
return(STATUS_NO_MEMORY);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NewRegion = InitialRegion;
|
||||
}
|
||||
|
||||
/*
|
||||
* Free any complete regions that are containing in the range of addresses
|
||||
* and call the helper function to actually do the changes.
|
||||
*/
|
||||
CurrentEntry = NewRegion->RegionListEntry.Flink;
|
||||
CurrentRegion = CONTAINING_RECORD(CurrentEntry, MM_REGION,
|
||||
RegionListEntry);
|
||||
CurrentBaseAddress = (char*)StartAddress + NewRegion->Length;
|
||||
while (RemainingLength > 0 && CurrentRegion->Length <= RemainingLength)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* Free any complete regions that are containing in the range of addresses
|
||||
* and call the helper function to actually do the changes.
|
||||
*/
|
||||
CurrentEntry = NewRegion->RegionListEntry.Flink;
|
||||
CurrentRegion = CONTAINING_RECORD(CurrentEntry, MM_REGION,
|
||||
RegionListEntry);
|
||||
CurrentBaseAddress = (char*)StartAddress + NewRegion->Length;
|
||||
while (RemainingLength > 0 && CurrentRegion->Length <= RemainingLength)
|
||||
{
|
||||
if (CurrentRegion->Type != NewType &&
|
||||
CurrentRegion->Protect != NewProtect)
|
||||
{
|
||||
AlterFunc(AddressSpace, CurrentBaseAddress, CurrentRegion->Length,
|
||||
CurrentRegion->Type, CurrentRegion->Protect,
|
||||
NewType, NewProtect);
|
||||
}
|
||||
CurrentRegion->Protect != NewProtect)
|
||||
{
|
||||
AlterFunc(AddressSpace, CurrentBaseAddress, CurrentRegion->Length,
|
||||
CurrentRegion->Type, CurrentRegion->Protect,
|
||||
NewType, NewProtect);
|
||||
}
|
||||
#if defined(__GNUC__)
|
||||
CurrentBaseAddress += CurrentRegion->Length;
|
||||
#else
|
||||
|
||||
{
|
||||
char* pTemp = CurrentBaseAddress;
|
||||
pTemp += CurrentRegion->Length;
|
||||
CurrentBaseAddress = pTemp;
|
||||
char* pTemp = CurrentBaseAddress;
|
||||
pTemp += CurrentRegion->Length;
|
||||
CurrentBaseAddress = pTemp;
|
||||
}
|
||||
#endif
|
||||
NewRegion->Length += CurrentRegion->Length;
|
||||
RemainingLength -= CurrentRegion->Length;
|
||||
CurrentEntry = CurrentEntry->Flink;
|
||||
CurrentEntry = CurrentEntry->Flink;
|
||||
RemoveEntryList(&CurrentRegion->RegionListEntry);
|
||||
ExFreePool(CurrentRegion);
|
||||
CurrentRegion = CONTAINING_RECORD(CurrentEntry, MM_REGION,
|
||||
RegionListEntry);
|
||||
}
|
||||
CurrentRegion = CONTAINING_RECORD(CurrentEntry, MM_REGION,
|
||||
RegionListEntry);
|
||||
}
|
||||
|
||||
/*
|
||||
* Split any final region.
|
||||
*/
|
||||
if (RemainingLength > 0)
|
||||
{
|
||||
CurrentRegion = CONTAINING_RECORD(CurrentEntry, MM_REGION,
|
||||
RegionListEntry);
|
||||
/*
|
||||
* Split any final region.
|
||||
*/
|
||||
if (RemainingLength > 0)
|
||||
{
|
||||
CurrentRegion = CONTAINING_RECORD(CurrentEntry, MM_REGION,
|
||||
RegionListEntry);
|
||||
if (CurrentRegion->Type != NewType &&
|
||||
CurrentRegion->Protect != NewProtect)
|
||||
{
|
||||
AlterFunc(AddressSpace, CurrentBaseAddress, CurrentRegion->Length,
|
||||
CurrentRegion->Type, CurrentRegion->Protect,
|
||||
NewType, NewProtect);
|
||||
}
|
||||
CurrentRegion->Protect != NewProtect)
|
||||
{
|
||||
AlterFunc(AddressSpace, CurrentBaseAddress, CurrentRegion->Length,
|
||||
CurrentRegion->Type, CurrentRegion->Protect,
|
||||
NewType, NewProtect);
|
||||
}
|
||||
NewRegion->Length += RemainingLength;
|
||||
CurrentRegion->Length -= RemainingLength;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If the region after the new region has the same type then merge them.
|
||||
*/
|
||||
if (NewRegion->RegionListEntry.Flink != RegionListHead)
|
||||
{
|
||||
/*
|
||||
* If the region after the new region has the same type then merge them.
|
||||
*/
|
||||
if (NewRegion->RegionListEntry.Flink != RegionListHead)
|
||||
{
|
||||
CurrentEntry = NewRegion->RegionListEntry.Flink;
|
||||
CurrentRegion = CONTAINING_RECORD(CurrentEntry, MM_REGION,
|
||||
RegionListEntry);
|
||||
CurrentRegion = CONTAINING_RECORD(CurrentEntry, MM_REGION,
|
||||
RegionListEntry);
|
||||
if (CurrentRegion->Type == NewRegion->Type &&
|
||||
CurrentRegion->Protect == NewRegion->Protect)
|
||||
{
|
||||
NewRegion->Length += CurrentRegion->Length;
|
||||
RemoveEntryList(&CurrentRegion->RegionListEntry);
|
||||
ExFreePool(CurrentRegion);
|
||||
}
|
||||
}
|
||||
CurrentRegion->Protect == NewRegion->Protect)
|
||||
{
|
||||
NewRegion->Length += CurrentRegion->Length;
|
||||
RemoveEntryList(&CurrentRegion->RegionListEntry);
|
||||
ExFreePool(CurrentRegion);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If the region before the new region has the same type then merge them.
|
||||
*/
|
||||
if (NewRegion->RegionListEntry.Blink != RegionListHead)
|
||||
{
|
||||
/*
|
||||
* If the region before the new region has the same type then merge them.
|
||||
*/
|
||||
if (NewRegion->RegionListEntry.Blink != RegionListHead)
|
||||
{
|
||||
CurrentEntry = NewRegion->RegionListEntry.Blink;
|
||||
CurrentRegion = CONTAINING_RECORD(CurrentEntry, MM_REGION,
|
||||
RegionListEntry);
|
||||
CurrentRegion = CONTAINING_RECORD(CurrentEntry, MM_REGION,
|
||||
RegionListEntry);
|
||||
if (CurrentRegion->Type == NewRegion->Type &&
|
||||
CurrentRegion->Protect == NewRegion->Protect)
|
||||
{
|
||||
NewRegion->Length += CurrentRegion->Length;
|
||||
RemoveEntryList(&CurrentRegion->RegionListEntry);
|
||||
ExFreePool(CurrentRegion);
|
||||
}
|
||||
}
|
||||
CurrentRegion->Protect == NewRegion->Protect)
|
||||
{
|
||||
NewRegion->Length += CurrentRegion->Length;
|
||||
RemoveEntryList(&CurrentRegion->RegionListEntry);
|
||||
ExFreePool(CurrentRegion);
|
||||
}
|
||||
}
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
VOID
|
||||
MmInitialiseRegion(PLIST_ENTRY RegionListHead, ULONG Length, ULONG Type,
|
||||
ULONG Protect)
|
||||
ULONG Protect)
|
||||
{
|
||||
PMM_REGION Region;
|
||||
PMM_REGION Region;
|
||||
|
||||
Region = ExAllocatePoolWithTag(NonPagedPool, sizeof(MM_REGION),
|
||||
TAG_MM_REGION);
|
||||
Region->Type = Type;
|
||||
Region->Protect = Protect;
|
||||
Region->Length = Length;
|
||||
InitializeListHead(RegionListHead);
|
||||
InsertHeadList(RegionListHead, &Region->RegionListEntry);
|
||||
Region = ExAllocatePoolWithTag(NonPagedPool, sizeof(MM_REGION),
|
||||
TAG_MM_REGION);
|
||||
Region->Type = Type;
|
||||
Region->Protect = Protect;
|
||||
Region->Length = Length;
|
||||
InitializeListHead(RegionListHead);
|
||||
InsertHeadList(RegionListHead, &Region->RegionListEntry);
|
||||
}
|
||||
|
||||
PMM_REGION
|
||||
MmFindRegion(PVOID BaseAddress, PLIST_ENTRY RegionListHead, PVOID Address,
|
||||
PVOID* RegionBaseAddress)
|
||||
PVOID* RegionBaseAddress)
|
||||
{
|
||||
PLIST_ENTRY current_entry;
|
||||
PMM_REGION current;
|
||||
PVOID StartAddress = BaseAddress;
|
||||
|
||||
current_entry = RegionListHead->Flink;
|
||||
while (current_entry != RegionListHead)
|
||||
{
|
||||
PLIST_ENTRY current_entry;
|
||||
PMM_REGION current;
|
||||
PVOID StartAddress = BaseAddress;
|
||||
|
||||
current_entry = RegionListHead->Flink;
|
||||
while (current_entry != RegionListHead)
|
||||
{
|
||||
current = CONTAINING_RECORD(current_entry, MM_REGION, RegionListEntry);
|
||||
|
||||
if (StartAddress <= Address &&
|
||||
((char*)StartAddress + current->Length) > (char*)Address)
|
||||
{
|
||||
if (RegionBaseAddress != NULL)
|
||||
{
|
||||
*RegionBaseAddress = StartAddress;
|
||||
}
|
||||
return(current);
|
||||
}
|
||||
if (StartAddress <= Address &&
|
||||
((char*)StartAddress + current->Length) > (char*)Address)
|
||||
{
|
||||
if (RegionBaseAddress != NULL)
|
||||
{
|
||||
*RegionBaseAddress = StartAddress;
|
||||
}
|
||||
return(current);
|
||||
}
|
||||
|
||||
current_entry = current_entry->Flink;
|
||||
#if defined(__GNUC__)
|
||||
|
||||
StartAddress += current->Length;
|
||||
#else
|
||||
|
||||
{
|
||||
char* pTemp = StartAddress;
|
||||
pTemp += current->Length;
|
||||
StartAddress = pTemp;
|
||||
char* pTemp = StartAddress;
|
||||
pTemp += current->Length;
|
||||
StartAddress = pTemp;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return(NULL);
|
||||
|
||||
}
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
+286
-285
@@ -16,7 +16,7 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
/* $Id: rmap.c,v 1.27 2004/03/05 11:31:59 hbirr Exp $
|
||||
/* $Id: rmap.c,v 1.28 2004/04/10 22:35:25 gdalsnes Exp $
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top directory
|
||||
* PROJECT: ReactOS kernel
|
||||
@@ -40,10 +40,11 @@
|
||||
|
||||
typedef struct _MM_RMAP_ENTRY
|
||||
{
|
||||
struct _MM_RMAP_ENTRY* Next;
|
||||
PEPROCESS Process;
|
||||
PVOID Address;
|
||||
} MM_RMAP_ENTRY, *PMM_RMAP_ENTRY;
|
||||
struct _MM_RMAP_ENTRY* Next;
|
||||
PEPROCESS Process;
|
||||
PVOID Address;
|
||||
}
|
||||
MM_RMAP_ENTRY, *PMM_RMAP_ENTRY;
|
||||
|
||||
#define TAG_RMAP TAG('R', 'M', 'A', 'P')
|
||||
|
||||
@@ -57,126 +58,100 @@ static NPAGED_LOOKASIDE_LIST RmapLookasideList;
|
||||
VOID INIT_FUNCTION
|
||||
MmInitializeRmapList(VOID)
|
||||
{
|
||||
ExInitializeFastMutex(&RmapListLock);
|
||||
ExInitializeNPagedLookasideList (&RmapLookasideList,
|
||||
NULL,
|
||||
NULL,
|
||||
0,
|
||||
sizeof(MM_RMAP_ENTRY),
|
||||
TAG_RMAP,
|
||||
50);
|
||||
ExInitializeFastMutex(&RmapListLock);
|
||||
ExInitializeNPagedLookasideList (&RmapLookasideList,
|
||||
NULL,
|
||||
NULL,
|
||||
0,
|
||||
sizeof(MM_RMAP_ENTRY),
|
||||
TAG_RMAP,
|
||||
50);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
MmWritePagePhysicalAddress(PHYSICAL_ADDRESS PhysicalAddress)
|
||||
{
|
||||
PMM_RMAP_ENTRY entry;
|
||||
PMEMORY_AREA MemoryArea;
|
||||
PMADDRESS_SPACE AddressSpace;
|
||||
ULONG Type;
|
||||
PVOID Address;
|
||||
PEPROCESS Process;
|
||||
PMM_PAGEOP PageOp;
|
||||
ULONG Offset;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
PMM_RMAP_ENTRY entry;
|
||||
PMEMORY_AREA MemoryArea;
|
||||
PMADDRESS_SPACE AddressSpace;
|
||||
ULONG Type;
|
||||
PVOID Address;
|
||||
PEPROCESS Process;
|
||||
PMM_PAGEOP PageOp;
|
||||
ULONG Offset;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
|
||||
/*
|
||||
* Check that the address still has a valid rmap; then reference the
|
||||
* process so it isn't freed while we are working.
|
||||
*/
|
||||
ExAcquireFastMutex(&RmapListLock);
|
||||
entry = MmGetRmapListHeadPage(PhysicalAddress);
|
||||
if (entry == NULL)
|
||||
{
|
||||
/*
|
||||
* Check that the address still has a valid rmap; then reference the
|
||||
* process so it isn't freed while we are working.
|
||||
*/
|
||||
ExAcquireFastMutex(&RmapListLock);
|
||||
entry = MmGetRmapListHeadPage(PhysicalAddress);
|
||||
if (entry == NULL)
|
||||
{
|
||||
ExReleaseFastMutex(&RmapListLock);
|
||||
return(STATUS_UNSUCCESSFUL);
|
||||
}
|
||||
Process = entry->Process;
|
||||
Address = entry->Address;
|
||||
if ((((ULONG)Address) & 0xFFF) != 0)
|
||||
{
|
||||
}
|
||||
Process = entry->Process;
|
||||
Address = entry->Address;
|
||||
if ((((ULONG)Address) & 0xFFF) != 0)
|
||||
{
|
||||
KEBUGCHECK(0);
|
||||
}
|
||||
if (Address < (PVOID)KERNEL_BASE)
|
||||
{
|
||||
}
|
||||
if (Address < (PVOID)KERNEL_BASE)
|
||||
{
|
||||
Status = ObReferenceObjectByPointer(Process, PROCESS_ALL_ACCESS, NULL, KernelMode);
|
||||
ExReleaseFastMutex(&RmapListLock);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
AddressSpace = &Process->AddressSpace;
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
ExReleaseFastMutex(&RmapListLock);
|
||||
AddressSpace = MmGetKernelAddressSpace();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Lock the address space; then check that the address we are using
|
||||
* still corresponds to a valid memory area (the page might have been
|
||||
* freed or paged out after we read the rmap entry.)
|
||||
*/
|
||||
MmLockAddressSpace(AddressSpace);
|
||||
MemoryArea = MmOpenMemoryAreaByAddress(AddressSpace, Address);
|
||||
if (MemoryArea == NULL || MemoryArea->DeleteInProgress)
|
||||
{
|
||||
/*
|
||||
* Lock the address space; then check that the address we are using
|
||||
* still corresponds to a valid memory area (the page might have been
|
||||
* freed or paged out after we read the rmap entry.)
|
||||
*/
|
||||
MmLockAddressSpace(AddressSpace);
|
||||
MemoryArea = MmOpenMemoryAreaByAddress(AddressSpace, Address);
|
||||
if (MemoryArea == NULL || MemoryArea->DeleteInProgress)
|
||||
{
|
||||
MmUnlockAddressSpace(AddressSpace);
|
||||
if (Address < (PVOID)KERNEL_BASE)
|
||||
{
|
||||
ObDereferenceObject(Process);
|
||||
}
|
||||
{
|
||||
ObDereferenceObject(Process);
|
||||
}
|
||||
return(STATUS_UNSUCCESSFUL);
|
||||
}
|
||||
}
|
||||
|
||||
Type = MemoryArea->Type;
|
||||
if (Type == MEMORY_AREA_SECTION_VIEW)
|
||||
{
|
||||
Type = MemoryArea->Type;
|
||||
if (Type == MEMORY_AREA_SECTION_VIEW)
|
||||
{
|
||||
Offset = (ULONG)((char*)Address - (ULONG)MemoryArea->BaseAddress);
|
||||
|
||||
/*
|
||||
* Get or create a pageop
|
||||
*/
|
||||
PageOp = MmGetPageOp(MemoryArea, 0, 0,
|
||||
MemoryArea->Data.SectionData.Segment,
|
||||
Offset, MM_PAGEOP_PAGEOUT, TRUE);
|
||||
PageOp = MmGetPageOp(MemoryArea, 0, 0,
|
||||
MemoryArea->Data.SectionData.Segment,
|
||||
Offset, MM_PAGEOP_PAGEOUT, TRUE);
|
||||
|
||||
if (PageOp == NULL)
|
||||
{
|
||||
MmUnlockAddressSpace(AddressSpace);
|
||||
if (Address < (PVOID)KERNEL_BASE)
|
||||
{
|
||||
ObDereferenceObject(Process);
|
||||
}
|
||||
return(STATUS_UNSUCCESSFUL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Release locks now we have a page op.
|
||||
*/
|
||||
MmUnlockAddressSpace(AddressSpace);
|
||||
|
||||
/*
|
||||
* Do the actual page out work.
|
||||
*/
|
||||
Status = MmWritePageSectionView(AddressSpace, MemoryArea,
|
||||
Address, PageOp);
|
||||
}
|
||||
else if (Type == MEMORY_AREA_VIRTUAL_MEMORY)
|
||||
{
|
||||
PageOp = MmGetPageOp(MemoryArea, Address < (PVOID)KERNEL_BASE ? Process->UniqueProcessId : 0,
|
||||
Address, NULL, 0, MM_PAGEOP_PAGEOUT, TRUE);
|
||||
|
||||
if (PageOp == NULL)
|
||||
{
|
||||
MmUnlockAddressSpace(AddressSpace);
|
||||
if (Address < (PVOID)KERNEL_BASE)
|
||||
{
|
||||
ObDereferenceObject(Process);
|
||||
}
|
||||
return(STATUS_UNSUCCESSFUL);
|
||||
}
|
||||
{
|
||||
MmUnlockAddressSpace(AddressSpace);
|
||||
if (Address < (PVOID)KERNEL_BASE)
|
||||
{
|
||||
ObDereferenceObject(Process);
|
||||
}
|
||||
return(STATUS_UNSUCCESSFUL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Release locks now we have a page op.
|
||||
@@ -186,95 +161,121 @@ MmWritePagePhysicalAddress(PHYSICAL_ADDRESS PhysicalAddress)
|
||||
/*
|
||||
* Do the actual page out work.
|
||||
*/
|
||||
Status = MmWritePageVirtualMemory(AddressSpace, MemoryArea,
|
||||
Address, PageOp);
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = MmWritePageSectionView(AddressSpace, MemoryArea,
|
||||
Address, PageOp);
|
||||
}
|
||||
else if (Type == MEMORY_AREA_VIRTUAL_MEMORY)
|
||||
{
|
||||
PageOp = MmGetPageOp(MemoryArea, Address < (PVOID)KERNEL_BASE ? Process->UniqueProcessId : 0,
|
||||
Address, NULL, 0, MM_PAGEOP_PAGEOUT, TRUE);
|
||||
|
||||
if (PageOp == NULL)
|
||||
{
|
||||
MmUnlockAddressSpace(AddressSpace);
|
||||
if (Address < (PVOID)KERNEL_BASE)
|
||||
{
|
||||
ObDereferenceObject(Process);
|
||||
}
|
||||
return(STATUS_UNSUCCESSFUL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Release locks now we have a page op.
|
||||
*/
|
||||
MmUnlockAddressSpace(AddressSpace);
|
||||
|
||||
/*
|
||||
* Do the actual page out work.
|
||||
*/
|
||||
Status = MmWritePageVirtualMemory(AddressSpace, MemoryArea,
|
||||
Address, PageOp);
|
||||
}
|
||||
else
|
||||
{
|
||||
KEBUGCHECK(0);
|
||||
}
|
||||
if (Address < (PVOID)KERNEL_BASE)
|
||||
{
|
||||
}
|
||||
if (Address < (PVOID)KERNEL_BASE)
|
||||
{
|
||||
ObDereferenceObject(Process);
|
||||
}
|
||||
return(Status);
|
||||
}
|
||||
return(Status);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
MmPageOutPhysicalAddress(PHYSICAL_ADDRESS PhysicalAddress)
|
||||
{
|
||||
PMM_RMAP_ENTRY entry;
|
||||
PMEMORY_AREA MemoryArea;
|
||||
PMADDRESS_SPACE AddressSpace;
|
||||
ULONG Type;
|
||||
PVOID Address;
|
||||
PEPROCESS Process;
|
||||
PMM_PAGEOP PageOp;
|
||||
ULONG Offset;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
PMM_RMAP_ENTRY entry;
|
||||
PMEMORY_AREA MemoryArea;
|
||||
PMADDRESS_SPACE AddressSpace;
|
||||
ULONG Type;
|
||||
PVOID Address;
|
||||
PEPROCESS Process;
|
||||
PMM_PAGEOP PageOp;
|
||||
ULONG Offset;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
|
||||
ExAcquireFastMutex(&RmapListLock);
|
||||
entry = MmGetRmapListHeadPage(PhysicalAddress);
|
||||
if (entry == NULL || MmGetLockCountPage(PhysicalAddress) != 0)
|
||||
{
|
||||
ExAcquireFastMutex(&RmapListLock);
|
||||
entry = MmGetRmapListHeadPage(PhysicalAddress);
|
||||
if (entry == NULL || MmGetLockCountPage(PhysicalAddress) != 0)
|
||||
{
|
||||
ExReleaseFastMutex(&RmapListLock);
|
||||
return(STATUS_UNSUCCESSFUL);
|
||||
}
|
||||
Process = entry->Process;
|
||||
Address = entry->Address;
|
||||
if ((((ULONG)Address) & 0xFFF) != 0)
|
||||
{
|
||||
}
|
||||
Process = entry->Process;
|
||||
Address = entry->Address;
|
||||
if ((((ULONG)Address) & 0xFFF) != 0)
|
||||
{
|
||||
KEBUGCHECK(0);
|
||||
}
|
||||
}
|
||||
|
||||
if (Address < (PVOID)KERNEL_BASE)
|
||||
{
|
||||
if (Address < (PVOID)KERNEL_BASE)
|
||||
{
|
||||
Status = ObReferenceObjectByPointer(Process, PROCESS_ALL_ACCESS, NULL, KernelMode);
|
||||
ExReleaseFastMutex(&RmapListLock);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
AddressSpace = &Process->AddressSpace;
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
ExReleaseFastMutex(&RmapListLock);
|
||||
AddressSpace = MmGetKernelAddressSpace();
|
||||
}
|
||||
}
|
||||
|
||||
MmLockAddressSpace(AddressSpace);
|
||||
MemoryArea = MmOpenMemoryAreaByAddress(AddressSpace, Address);
|
||||
if (MemoryArea == NULL || MemoryArea->DeleteInProgress)
|
||||
{
|
||||
MmLockAddressSpace(AddressSpace);
|
||||
MemoryArea = MmOpenMemoryAreaByAddress(AddressSpace, Address);
|
||||
if (MemoryArea == NULL || MemoryArea->DeleteInProgress)
|
||||
{
|
||||
MmUnlockAddressSpace(AddressSpace);
|
||||
if (Address < (PVOID)KERNEL_BASE)
|
||||
{
|
||||
ObDereferenceObject(Process);
|
||||
}
|
||||
{
|
||||
ObDereferenceObject(Process);
|
||||
}
|
||||
return(STATUS_UNSUCCESSFUL);
|
||||
}
|
||||
Type = MemoryArea->Type;
|
||||
if (Type == MEMORY_AREA_SECTION_VIEW)
|
||||
{
|
||||
}
|
||||
Type = MemoryArea->Type;
|
||||
if (Type == MEMORY_AREA_SECTION_VIEW)
|
||||
{
|
||||
Offset = (ULONG)((char*)Address - (ULONG)MemoryArea->BaseAddress);
|
||||
|
||||
/*
|
||||
* Get or create a pageop
|
||||
*/
|
||||
PageOp = MmGetPageOp(MemoryArea, 0, 0,
|
||||
MemoryArea->Data.SectionData.Segment,
|
||||
Offset, MM_PAGEOP_PAGEOUT, TRUE);
|
||||
PageOp = MmGetPageOp(MemoryArea, 0, 0,
|
||||
MemoryArea->Data.SectionData.Segment,
|
||||
Offset, MM_PAGEOP_PAGEOUT, TRUE);
|
||||
if (PageOp == NULL)
|
||||
{
|
||||
MmUnlockAddressSpace(AddressSpace);
|
||||
if (Address < (PVOID)KERNEL_BASE)
|
||||
{
|
||||
ObDereferenceObject(Process);
|
||||
}
|
||||
return(STATUS_UNSUCCESSFUL);
|
||||
}
|
||||
|
||||
{
|
||||
MmUnlockAddressSpace(AddressSpace);
|
||||
if (Address < (PVOID)KERNEL_BASE)
|
||||
{
|
||||
ObDereferenceObject(Process);
|
||||
}
|
||||
return(STATUS_UNSUCCESSFUL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Release locks now we have a page op.
|
||||
*/
|
||||
@@ -283,22 +284,22 @@ MmPageOutPhysicalAddress(PHYSICAL_ADDRESS PhysicalAddress)
|
||||
/*
|
||||
* Do the actual page out work.
|
||||
*/
|
||||
Status = MmPageOutSectionView(AddressSpace, MemoryArea,
|
||||
Address, PageOp);
|
||||
}
|
||||
else if (Type == MEMORY_AREA_VIRTUAL_MEMORY)
|
||||
{
|
||||
Status = MmPageOutSectionView(AddressSpace, MemoryArea,
|
||||
Address, PageOp);
|
||||
}
|
||||
else if (Type == MEMORY_AREA_VIRTUAL_MEMORY)
|
||||
{
|
||||
PageOp = MmGetPageOp(MemoryArea, Address < (PVOID)KERNEL_BASE ? Process->UniqueProcessId : 0,
|
||||
Address, NULL, 0, MM_PAGEOP_PAGEOUT, TRUE);
|
||||
Address, NULL, 0, MM_PAGEOP_PAGEOUT, TRUE);
|
||||
if (PageOp == NULL)
|
||||
{
|
||||
MmUnlockAddressSpace(AddressSpace);
|
||||
if (Address < (PVOID)KERNEL_BASE)
|
||||
{
|
||||
ObDereferenceObject(Process);
|
||||
}
|
||||
return(STATUS_UNSUCCESSFUL);
|
||||
}
|
||||
{
|
||||
MmUnlockAddressSpace(AddressSpace);
|
||||
if (Address < (PVOID)KERNEL_BASE)
|
||||
{
|
||||
ObDereferenceObject(Process);
|
||||
}
|
||||
return(STATUS_UNSUCCESSFUL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Release locks now we have a page op.
|
||||
@@ -308,177 +309,177 @@ MmPageOutPhysicalAddress(PHYSICAL_ADDRESS PhysicalAddress)
|
||||
/*
|
||||
* Do the actual page out work.
|
||||
*/
|
||||
Status = MmPageOutVirtualMemory(AddressSpace, MemoryArea,
|
||||
Address, PageOp);
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = MmPageOutVirtualMemory(AddressSpace, MemoryArea,
|
||||
Address, PageOp);
|
||||
}
|
||||
else
|
||||
{
|
||||
KEBUGCHECK(0);
|
||||
}
|
||||
if (Address < (PVOID)KERNEL_BASE)
|
||||
{
|
||||
}
|
||||
if (Address < (PVOID)KERNEL_BASE)
|
||||
{
|
||||
ObDereferenceObject(Process);
|
||||
}
|
||||
return(Status);
|
||||
}
|
||||
return(Status);
|
||||
}
|
||||
|
||||
VOID
|
||||
MmSetCleanAllRmaps(PHYSICAL_ADDRESS PhysicalAddress)
|
||||
{
|
||||
PMM_RMAP_ENTRY current_entry;
|
||||
PMM_RMAP_ENTRY current_entry;
|
||||
|
||||
ExAcquireFastMutex(&RmapListLock);
|
||||
current_entry = MmGetRmapListHeadPage(PhysicalAddress);
|
||||
if (current_entry == NULL)
|
||||
{
|
||||
ExAcquireFastMutex(&RmapListLock);
|
||||
current_entry = MmGetRmapListHeadPage(PhysicalAddress);
|
||||
if (current_entry == NULL)
|
||||
{
|
||||
DPRINT1("MmIsDirtyRmap: No rmaps.\n");
|
||||
KEBUGCHECK(0);
|
||||
}
|
||||
while (current_entry != NULL)
|
||||
{
|
||||
}
|
||||
while (current_entry != NULL)
|
||||
{
|
||||
MmSetCleanPage(current_entry->Process, current_entry->Address);
|
||||
current_entry = current_entry->Next;
|
||||
}
|
||||
ExReleaseFastMutex(&RmapListLock);
|
||||
}
|
||||
ExReleaseFastMutex(&RmapListLock);
|
||||
}
|
||||
|
||||
VOID
|
||||
MmSetDirtyAllRmaps(PHYSICAL_ADDRESS PhysicalAddress)
|
||||
{
|
||||
PMM_RMAP_ENTRY current_entry;
|
||||
PMM_RMAP_ENTRY current_entry;
|
||||
|
||||
ExAcquireFastMutex(&RmapListLock);
|
||||
current_entry = MmGetRmapListHeadPage(PhysicalAddress);
|
||||
if (current_entry == NULL)
|
||||
{
|
||||
ExAcquireFastMutex(&RmapListLock);
|
||||
current_entry = MmGetRmapListHeadPage(PhysicalAddress);
|
||||
if (current_entry == NULL)
|
||||
{
|
||||
DPRINT1("MmIsDirtyRmap: No rmaps.\n");
|
||||
KEBUGCHECK(0);
|
||||
}
|
||||
while (current_entry != NULL)
|
||||
{
|
||||
}
|
||||
while (current_entry != NULL)
|
||||
{
|
||||
MmSetDirtyPage(current_entry->Process, current_entry->Address);
|
||||
current_entry = current_entry->Next;
|
||||
}
|
||||
ExReleaseFastMutex(&RmapListLock);
|
||||
}
|
||||
ExReleaseFastMutex(&RmapListLock);
|
||||
}
|
||||
|
||||
BOOL
|
||||
MmIsDirtyPageRmap(PHYSICAL_ADDRESS PhysicalAddress)
|
||||
{
|
||||
PMM_RMAP_ENTRY current_entry;
|
||||
PMM_RMAP_ENTRY current_entry;
|
||||
|
||||
ExAcquireFastMutex(&RmapListLock);
|
||||
current_entry = MmGetRmapListHeadPage(PhysicalAddress);
|
||||
if (current_entry == NULL)
|
||||
{
|
||||
ExAcquireFastMutex(&RmapListLock);
|
||||
current_entry = MmGetRmapListHeadPage(PhysicalAddress);
|
||||
if (current_entry == NULL)
|
||||
{
|
||||
ExReleaseFastMutex(&RmapListLock);
|
||||
return(FALSE);
|
||||
}
|
||||
while (current_entry != NULL)
|
||||
{
|
||||
}
|
||||
while (current_entry != NULL)
|
||||
{
|
||||
if (MmIsDirtyPage(current_entry->Process, current_entry->Address))
|
||||
{
|
||||
ExReleaseFastMutex(&RmapListLock);
|
||||
return(TRUE);
|
||||
}
|
||||
{
|
||||
ExReleaseFastMutex(&RmapListLock);
|
||||
return(TRUE);
|
||||
}
|
||||
current_entry = current_entry->Next;
|
||||
}
|
||||
ExReleaseFastMutex(&RmapListLock);
|
||||
return(FALSE);
|
||||
}
|
||||
ExReleaseFastMutex(&RmapListLock);
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
VOID
|
||||
MmInsertRmap(PHYSICAL_ADDRESS PhysicalAddress, PEPROCESS Process,
|
||||
PVOID Address)
|
||||
MmInsertRmap(PHYSICAL_ADDRESS PhysicalAddress, PEPROCESS Process,
|
||||
PVOID Address)
|
||||
{
|
||||
PMM_RMAP_ENTRY current_entry;
|
||||
PMM_RMAP_ENTRY new_entry;
|
||||
PMM_RMAP_ENTRY current_entry;
|
||||
PMM_RMAP_ENTRY new_entry;
|
||||
|
||||
Address = (PVOID)PAGE_ROUND_DOWN(Address);
|
||||
Address = (PVOID)PAGE_ROUND_DOWN(Address);
|
||||
|
||||
new_entry = ExAllocateFromNPagedLookasideList(&RmapLookasideList);
|
||||
if (new_entry == NULL)
|
||||
{
|
||||
new_entry = ExAllocateFromNPagedLookasideList(&RmapLookasideList);
|
||||
if (new_entry == NULL)
|
||||
{
|
||||
KEBUGCHECK(0);
|
||||
}
|
||||
new_entry->Address = Address;
|
||||
new_entry->Process = Process;
|
||||
}
|
||||
new_entry->Address = Address;
|
||||
new_entry->Process = Process;
|
||||
|
||||
if (MmGetPhysicalAddressForProcess(Process, Address).QuadPart !=
|
||||
PhysicalAddress.QuadPart)
|
||||
{
|
||||
if (MmGetPhysicalAddressForProcess(Process, Address).QuadPart !=
|
||||
PhysicalAddress.QuadPart)
|
||||
{
|
||||
DPRINT1("Insert rmap (%d, 0x%.8X) 0x%.8X which doesn't match physical "
|
||||
"address 0x%.8X\n", Process->UniqueProcessId, Address,
|
||||
MmGetPhysicalAddressForProcess(Process, Address).u.LowPart,
|
||||
PhysicalAddress.u.LowPart);
|
||||
"address 0x%.8X\n", Process->UniqueProcessId, Address,
|
||||
MmGetPhysicalAddressForProcess(Process, Address).u.LowPart,
|
||||
PhysicalAddress.u.LowPart);
|
||||
KEBUGCHECK(0);
|
||||
}
|
||||
}
|
||||
|
||||
ExAcquireFastMutex(&RmapListLock);
|
||||
current_entry = MmGetRmapListHeadPage(PhysicalAddress);
|
||||
new_entry->Next = current_entry;
|
||||
MmSetRmapListHeadPage(PhysicalAddress, new_entry);
|
||||
ExReleaseFastMutex(&RmapListLock);
|
||||
ExAcquireFastMutex(&RmapListLock);
|
||||
current_entry = MmGetRmapListHeadPage(PhysicalAddress);
|
||||
new_entry->Next = current_entry;
|
||||
MmSetRmapListHeadPage(PhysicalAddress, new_entry);
|
||||
ExReleaseFastMutex(&RmapListLock);
|
||||
}
|
||||
|
||||
VOID
|
||||
MmDeleteAllRmaps(PHYSICAL_ADDRESS PhysicalAddress, PVOID Context,
|
||||
VOID (*DeleteMapping)(PVOID Context, PEPROCESS Process,
|
||||
PVOID Address))
|
||||
MmDeleteAllRmaps(PHYSICAL_ADDRESS PhysicalAddress, PVOID Context,
|
||||
VOID (*DeleteMapping)(PVOID Context, PEPROCESS Process,
|
||||
PVOID Address))
|
||||
{
|
||||
PMM_RMAP_ENTRY current_entry;
|
||||
PMM_RMAP_ENTRY previous_entry;
|
||||
PMM_RMAP_ENTRY current_entry;
|
||||
PMM_RMAP_ENTRY previous_entry;
|
||||
|
||||
ExAcquireFastMutex(&RmapListLock);
|
||||
current_entry = MmGetRmapListHeadPage(PhysicalAddress);
|
||||
if (current_entry == NULL)
|
||||
{
|
||||
ExAcquireFastMutex(&RmapListLock);
|
||||
current_entry = MmGetRmapListHeadPage(PhysicalAddress);
|
||||
if (current_entry == NULL)
|
||||
{
|
||||
DPRINT1("MmDeleteAllRmaps: No rmaps.\n");
|
||||
KEBUGCHECK(0);
|
||||
}
|
||||
MmSetRmapListHeadPage(PhysicalAddress, NULL);
|
||||
while (current_entry != NULL)
|
||||
{
|
||||
}
|
||||
MmSetRmapListHeadPage(PhysicalAddress, NULL);
|
||||
while (current_entry != NULL)
|
||||
{
|
||||
previous_entry = current_entry;
|
||||
current_entry = current_entry->Next;
|
||||
if (DeleteMapping)
|
||||
{
|
||||
DeleteMapping(Context, previous_entry->Process,
|
||||
previous_entry->Address);
|
||||
}
|
||||
{
|
||||
DeleteMapping(Context, previous_entry->Process,
|
||||
previous_entry->Address);
|
||||
}
|
||||
ExFreeToNPagedLookasideList(&RmapLookasideList, previous_entry);
|
||||
}
|
||||
ExReleaseFastMutex(&RmapListLock);
|
||||
}
|
||||
ExReleaseFastMutex(&RmapListLock);
|
||||
}
|
||||
|
||||
VOID
|
||||
MmDeleteRmap(PHYSICAL_ADDRESS PhysicalAddress, PEPROCESS Process,
|
||||
PVOID Address)
|
||||
MmDeleteRmap(PHYSICAL_ADDRESS PhysicalAddress, PEPROCESS Process,
|
||||
PVOID Address)
|
||||
{
|
||||
PMM_RMAP_ENTRY current_entry, previous_entry;
|
||||
PMM_RMAP_ENTRY current_entry, previous_entry;
|
||||
|
||||
ExAcquireFastMutex(&RmapListLock);
|
||||
previous_entry = NULL;
|
||||
current_entry = MmGetRmapListHeadPage(PhysicalAddress);
|
||||
while (current_entry != NULL)
|
||||
{
|
||||
if (current_entry->Process == Process &&
|
||||
current_entry->Address == Address)
|
||||
{
|
||||
if (previous_entry == NULL)
|
||||
{
|
||||
MmSetRmapListHeadPage(PhysicalAddress, current_entry->Next);
|
||||
}
|
||||
else
|
||||
{
|
||||
previous_entry->Next = current_entry->Next;
|
||||
}
|
||||
ExReleaseFastMutex(&RmapListLock);
|
||||
ExFreeToNPagedLookasideList(&RmapLookasideList, current_entry);
|
||||
return;
|
||||
}
|
||||
ExAcquireFastMutex(&RmapListLock);
|
||||
previous_entry = NULL;
|
||||
current_entry = MmGetRmapListHeadPage(PhysicalAddress);
|
||||
while (current_entry != NULL)
|
||||
{
|
||||
if (current_entry->Process == Process &&
|
||||
current_entry->Address == Address)
|
||||
{
|
||||
if (previous_entry == NULL)
|
||||
{
|
||||
MmSetRmapListHeadPage(PhysicalAddress, current_entry->Next);
|
||||
}
|
||||
else
|
||||
{
|
||||
previous_entry->Next = current_entry->Next;
|
||||
}
|
||||
ExReleaseFastMutex(&RmapListLock);
|
||||
ExFreeToNPagedLookasideList(&RmapLookasideList, current_entry);
|
||||
return;
|
||||
}
|
||||
previous_entry = current_entry;
|
||||
current_entry = current_entry->Next;
|
||||
}
|
||||
KEBUGCHECK(0);
|
||||
}
|
||||
KEBUGCHECK(0);
|
||||
}
|
||||
|
||||
+2824
-2820
File diff suppressed because it is too large
Load Diff
+195
-192
@@ -16,7 +16,7 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
/* $Id: slab.c,v 1.11 2004/03/04 00:07:02 navaraf Exp $
|
||||
/* $Id: slab.c,v 1.12 2004/04/10 22:35:26 gdalsnes Exp $
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top directory
|
||||
* PROJECT: ReactOS kernel
|
||||
@@ -44,27 +44,30 @@ struct _SLAB_CACHE_PAGE;
|
||||
|
||||
typedef struct _SLAB_CACHE
|
||||
{
|
||||
SLAB_CACHE_CONSTRUCTOR Constructor;
|
||||
SLAB_CACHE_DESTRUCTOR Destructor;
|
||||
ULONG BaseSize;
|
||||
ULONG ObjectSize;
|
||||
ULONG ObjectsPerPage;
|
||||
LIST_ENTRY PageListHead;
|
||||
struct _SLAB_CACHE_PAGE* FirstFreePage;
|
||||
KSPIN_LOCK SlabLock;
|
||||
} SLAB_CACHE, *PSLAB_CACHE;
|
||||
SLAB_CACHE_CONSTRUCTOR Constructor;
|
||||
SLAB_CACHE_DESTRUCTOR Destructor;
|
||||
ULONG BaseSize;
|
||||
ULONG ObjectSize;
|
||||
ULONG ObjectsPerPage;
|
||||
LIST_ENTRY PageListHead;
|
||||
struct _SLAB_CACHE_PAGE* FirstFreePage;
|
||||
KSPIN_LOCK SlabLock;
|
||||
}
|
||||
SLAB_CACHE, *PSLAB_CACHE;
|
||||
|
||||
typedef struct _SLAB_CACHE_BUFCTL
|
||||
{
|
||||
struct _SLAB_CACHE_BUFCTL* NextFree;
|
||||
} SLAB_CACHE_BUFCTL, *PSLAB_CACHE_BUFCTL;
|
||||
struct _SLAB_CACHE_BUFCTL* NextFree;
|
||||
}
|
||||
SLAB_CACHE_BUFCTL, *PSLAB_CACHE_BUFCTL;
|
||||
|
||||
typedef struct _SLAB_CACHE_PAGE
|
||||
{
|
||||
LIST_ENTRY PageListEntry;
|
||||
PSLAB_CACHE_BUFCTL FirstFreeBuffer;
|
||||
ULONG ReferenceCount;
|
||||
} SLAB_CACHE_PAGE, *PSLAB_CACHE_PAGE;
|
||||
LIST_ENTRY PageListEntry;
|
||||
PSLAB_CACHE_BUFCTL FirstFreeBuffer;
|
||||
ULONG ReferenceCount;
|
||||
}
|
||||
SLAB_CACHE_PAGE, *PSLAB_CACHE_PAGE;
|
||||
|
||||
/* GLOBALS ******************************************************************/
|
||||
|
||||
@@ -72,252 +75,252 @@ typedef struct _SLAB_CACHE_PAGE
|
||||
|
||||
PSLAB_CACHE
|
||||
ExCreateSlabCache(PUNICODE_STRING Name, ULONG Size, ULONG Align,
|
||||
SLAB_CACHE_CONSTRUCTOR Constructor,
|
||||
SLAB_CACHE_DESTRUCTOR Destructor)
|
||||
SLAB_CACHE_CONSTRUCTOR Constructor,
|
||||
SLAB_CACHE_DESTRUCTOR Destructor)
|
||||
{
|
||||
PSLAB_CACHE Slab;
|
||||
ULONG ObjectSize;
|
||||
ULONG AlignSize;
|
||||
PSLAB_CACHE Slab;
|
||||
ULONG ObjectSize;
|
||||
ULONG AlignSize;
|
||||
|
||||
Slab = ExAllocatePool(NonPagedPool, sizeof(SLAB_CACHE));
|
||||
if (Slab == NULL)
|
||||
{
|
||||
Slab = ExAllocatePool(NonPagedPool, sizeof(SLAB_CACHE));
|
||||
if (Slab == NULL)
|
||||
{
|
||||
return(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
Slab->Constructor = Constructor;
|
||||
Slab->Destructor = Destructor;
|
||||
Slab->BaseSize = Size;
|
||||
ObjectSize = Size + sizeof(SLAB_CACHE_BUFCTL);
|
||||
AlignSize = Align - (ObjectSize % Align);
|
||||
Slab->ObjectSize = ObjectSize + AlignSize;
|
||||
Slab->ObjectsPerPage =
|
||||
(PAGE_SIZE - sizeof(SLAB_CACHE_PAGE)) / Slab->ObjectSize;
|
||||
Slab->FirstFreePage = NULL;
|
||||
InitializeListHead(&Slab->PageListHead);
|
||||
KeInitializeSpinLock(&Slab->SlabLock);
|
||||
|
||||
return(Slab);
|
||||
Slab->Constructor = Constructor;
|
||||
Slab->Destructor = Destructor;
|
||||
Slab->BaseSize = Size;
|
||||
ObjectSize = Size + sizeof(SLAB_CACHE_BUFCTL);
|
||||
AlignSize = Align - (ObjectSize % Align);
|
||||
Slab->ObjectSize = ObjectSize + AlignSize;
|
||||
Slab->ObjectsPerPage =
|
||||
(PAGE_SIZE - sizeof(SLAB_CACHE_PAGE)) / Slab->ObjectSize;
|
||||
Slab->FirstFreePage = NULL;
|
||||
InitializeListHead(&Slab->PageListHead);
|
||||
KeInitializeSpinLock(&Slab->SlabLock);
|
||||
|
||||
return(Slab);
|
||||
}
|
||||
|
||||
PSLAB_CACHE_PAGE
|
||||
ExGrowSlabCache(PSLAB_CACHE Slab)
|
||||
{
|
||||
PSLAB_CACHE_PAGE SlabPage;
|
||||
PHYSICAL_ADDRESS PhysicalPage;
|
||||
PVOID Page;
|
||||
NTSTATUS Status;
|
||||
ULONG i;
|
||||
PSLAB_CACHE_BUFCTL BufCtl;
|
||||
PVOID Object;
|
||||
|
||||
Status = MmRequestPageMemoryConsumer(MC_NPPOOL, TRUE, &PhysicalPage);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return(NULL);
|
||||
}
|
||||
PSLAB_CACHE_PAGE SlabPage;
|
||||
PHYSICAL_ADDRESS PhysicalPage;
|
||||
PVOID Page;
|
||||
NTSTATUS Status;
|
||||
ULONG i;
|
||||
PSLAB_CACHE_BUFCTL BufCtl;
|
||||
PVOID Object;
|
||||
|
||||
Page = ExAllocatePageWithPhysPage(PhysicalPage);
|
||||
if (Page == NULL)
|
||||
{
|
||||
Status = MmRequestPageMemoryConsumer(MC_NPPOOL, TRUE, &PhysicalPage);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
Page = ExAllocatePageWithPhysPage(PhysicalPage);
|
||||
if (Page == NULL)
|
||||
{
|
||||
MmReleasePageMemoryConsumer(MC_NPPOOL, PhysicalPage);
|
||||
return(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
SlabPage = (PSLAB_CACHE_PAGE)((char*)Page + PAGE_SIZE - sizeof(SLAB_CACHE_PAGE));
|
||||
SlabPage->ReferenceCount = 0;
|
||||
SlabPage->FirstFreeBuffer = (PSLAB_CACHE_BUFCTL)Page;
|
||||
for (i = 0; i < Slab->ObjectsPerPage; i++)
|
||||
{
|
||||
SlabPage = (PSLAB_CACHE_PAGE)((char*)Page + PAGE_SIZE - sizeof(SLAB_CACHE_PAGE));
|
||||
SlabPage->ReferenceCount = 0;
|
||||
SlabPage->FirstFreeBuffer = (PSLAB_CACHE_BUFCTL)Page;
|
||||
for (i = 0; i < Slab->ObjectsPerPage; i++)
|
||||
{
|
||||
BufCtl = (PSLAB_CACHE_BUFCTL)((char*)Page + (i * Slab->ObjectSize));
|
||||
Object = (PVOID)(BufCtl + 1);
|
||||
if (Slab->Constructor != NULL)
|
||||
{
|
||||
Slab->Constructor(Object, Slab->BaseSize);
|
||||
}
|
||||
{
|
||||
Slab->Constructor(Object, Slab->BaseSize);
|
||||
}
|
||||
if (i == (Slab->ObjectsPerPage - 1))
|
||||
{
|
||||
BufCtl->NextFree =
|
||||
(PSLAB_CACHE_BUFCTL)((char*)Page + ((i + 1) * Slab->ObjectSize));
|
||||
}
|
||||
{
|
||||
BufCtl->NextFree =
|
||||
(PSLAB_CACHE_BUFCTL)((char*)Page + ((i + 1) * Slab->ObjectSize));
|
||||
}
|
||||
else
|
||||
{
|
||||
BufCtl->NextFree = NULL;
|
||||
}
|
||||
}
|
||||
{
|
||||
BufCtl->NextFree = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return(SlabPage);
|
||||
return(SlabPage);
|
||||
}
|
||||
|
||||
PVOID
|
||||
ExAllocateSlabCache(PSLAB_CACHE Slab, BOOLEAN MayWait)
|
||||
{
|
||||
KIRQL oldIrql;
|
||||
PSLAB_CACHE_PAGE Page;
|
||||
PVOID Object;
|
||||
BOOLEAN NewPage;
|
||||
KIRQL oldIrql;
|
||||
PSLAB_CACHE_PAGE Page;
|
||||
PVOID Object;
|
||||
BOOLEAN NewPage;
|
||||
|
||||
KeAcquireSpinLock(&Slab->SlabLock, &oldIrql);
|
||||
|
||||
/*
|
||||
* Check if there is a page with free objects
|
||||
* present, if so allocate from it, if
|
||||
* not grow the slab.
|
||||
*/
|
||||
if (Slab->FirstFreePage == NULL)
|
||||
{
|
||||
KeAcquireSpinLock(&Slab->SlabLock, &oldIrql);
|
||||
|
||||
/*
|
||||
* Check if there is a page with free objects
|
||||
* present, if so allocate from it, if
|
||||
* not grow the slab.
|
||||
*/
|
||||
if (Slab->FirstFreePage == NULL)
|
||||
{
|
||||
KeReleaseSpinLock(&Slab->SlabLock, oldIrql);
|
||||
Page = ExGrowSlabCache(Slab);
|
||||
NewPage = TRUE;
|
||||
KeAcquireSpinLock(&Slab->SlabLock, &oldIrql);
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
Page = Slab->FirstFreePage;
|
||||
NewPage = FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* We shouldn't have got a page without free buffers.
|
||||
*/
|
||||
if (Page->FirstFreeBuffer == NULL)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* We shouldn't have got a page without free buffers.
|
||||
*/
|
||||
if (Page->FirstFreeBuffer == NULL)
|
||||
{
|
||||
DPRINT1("First free page had no free buffers.\n");
|
||||
KEBUGCHECK(0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate the first free object from the page.
|
||||
*/
|
||||
Object = (PVOID)((char*)Page->FirstFreeBuffer + sizeof(SLAB_CACHE_BUFCTL));
|
||||
Page->FirstFreeBuffer = Page->FirstFreeBuffer->NextFree;
|
||||
Page->ReferenceCount++;
|
||||
/*
|
||||
* Allocate the first free object from the page.
|
||||
*/
|
||||
Object = (PVOID)((char*)Page->FirstFreeBuffer + sizeof(SLAB_CACHE_BUFCTL));
|
||||
Page->FirstFreeBuffer = Page->FirstFreeBuffer->NextFree;
|
||||
Page->ReferenceCount++;
|
||||
|
||||
/*
|
||||
* If we just allocated all the objects from this page
|
||||
* and it was the first free page then adjust the
|
||||
* first free page pointer and move the page to the head
|
||||
* of the list.
|
||||
*/
|
||||
if (Page->ReferenceCount == Slab->ObjectsPerPage && !NewPage)
|
||||
{
|
||||
/*
|
||||
* If we just allocated all the objects from this page
|
||||
* and it was the first free page then adjust the
|
||||
* first free page pointer and move the page to the head
|
||||
* of the list.
|
||||
*/
|
||||
if (Page->ReferenceCount == Slab->ObjectsPerPage && !NewPage)
|
||||
{
|
||||
if (Page->PageListEntry.Flink == &Slab->PageListHead)
|
||||
{
|
||||
Slab->FirstFreePage = NULL;
|
||||
}
|
||||
{
|
||||
Slab->FirstFreePage = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
PSLAB_CACHE_PAGE NextPage;
|
||||
|
||||
NextPage = CONTAINING_RECORD(Page->PageListEntry.Flink,
|
||||
SLAB_CACHE_PAGE,
|
||||
PageListEntry);
|
||||
Slab->FirstFreePage = NextPage;
|
||||
}
|
||||
{
|
||||
PSLAB_CACHE_PAGE NextPage;
|
||||
|
||||
NextPage = CONTAINING_RECORD(Page->PageListEntry.Flink,
|
||||
SLAB_CACHE_PAGE,
|
||||
PageListEntry);
|
||||
Slab->FirstFreePage = NextPage;
|
||||
}
|
||||
RemoveEntryList(&Page->PageListEntry);
|
||||
InsertHeadList(&Slab->PageListHead, &Page->PageListEntry);
|
||||
}
|
||||
/*
|
||||
* Otherwise if we created a new page then add it to the end of
|
||||
* the page list.
|
||||
*/
|
||||
else if (NewPage)
|
||||
{
|
||||
}
|
||||
/*
|
||||
* Otherwise if we created a new page then add it to the end of
|
||||
* the page list.
|
||||
*/
|
||||
else if (NewPage)
|
||||
{
|
||||
InsertTailList(&Slab->PageListHead, &Page->PageListEntry);
|
||||
if (Slab->FirstFreePage == NULL)
|
||||
{
|
||||
Slab->FirstFreePage = Page;
|
||||
}
|
||||
}
|
||||
KeReleaseSpinLock(&Slab->SlabLock, oldIrql);
|
||||
return(Object);
|
||||
{
|
||||
Slab->FirstFreePage = Page;
|
||||
}
|
||||
}
|
||||
KeReleaseSpinLock(&Slab->SlabLock, oldIrql);
|
||||
return(Object);
|
||||
}
|
||||
|
||||
VOID
|
||||
ExFreeFromPageSlabCache(PSLAB_CACHE Slab,
|
||||
PSLAB_CACHE_PAGE Page,
|
||||
PVOID Object)
|
||||
PSLAB_CACHE_PAGE Page,
|
||||
PVOID Object)
|
||||
{
|
||||
PSLAB_CACHE_BUFCTL BufCtl;
|
||||
PSLAB_CACHE_BUFCTL BufCtl;
|
||||
|
||||
BufCtl = (PSLAB_CACHE_BUFCTL)((char*)Object - sizeof(SLAB_CACHE_BUFCTL));
|
||||
BufCtl->NextFree = Page->FirstFreeBuffer;
|
||||
Page->FirstFreeBuffer = BufCtl;
|
||||
Page->ReferenceCount--;
|
||||
BufCtl = (PSLAB_CACHE_BUFCTL)((char*)Object - sizeof(SLAB_CACHE_BUFCTL));
|
||||
BufCtl->NextFree = Page->FirstFreeBuffer;
|
||||
Page->FirstFreeBuffer = BufCtl;
|
||||
Page->ReferenceCount--;
|
||||
}
|
||||
|
||||
VOID
|
||||
ExFreeSlabCache(PSLAB_CACHE Slab, PVOID Object)
|
||||
{
|
||||
KIRQL oldIrql;
|
||||
PLIST_ENTRY current_entry;
|
||||
PSLAB_CACHE_PAGE current;
|
||||
KIRQL oldIrql;
|
||||
PLIST_ENTRY current_entry;
|
||||
PSLAB_CACHE_PAGE current;
|
||||
|
||||
KeAcquireSpinLock(&Slab->SlabLock, &oldIrql);
|
||||
current_entry = Slab->PageListHead.Flink;
|
||||
while (current_entry != &Slab->PageListHead)
|
||||
{
|
||||
KeAcquireSpinLock(&Slab->SlabLock, &oldIrql);
|
||||
current_entry = Slab->PageListHead.Flink;
|
||||
while (current_entry != &Slab->PageListHead)
|
||||
{
|
||||
PVOID Base;
|
||||
|
||||
current = CONTAINING_RECORD(current_entry,
|
||||
SLAB_CACHE_PAGE,
|
||||
PageListEntry);
|
||||
SLAB_CACHE_PAGE,
|
||||
PageListEntry);
|
||||
Base = (PVOID)((char*)current + sizeof(SLAB_CACHE_PAGE) - PAGE_SIZE);
|
||||
if (Base >= Object &&
|
||||
((char*)Base + PAGE_SIZE - sizeof(SLAB_CACHE_PAGE)) >=
|
||||
((char*)Object + Slab->ObjectSize))
|
||||
{
|
||||
ExFreeFromPageSlabCache(Slab, current, Object);
|
||||
/*
|
||||
* If the page just become free then rearrange things.
|
||||
*/
|
||||
if (current->ReferenceCount == 0)
|
||||
{
|
||||
RemoveEntryList(¤t->PageListEntry);
|
||||
InsertTailList(&Slab->PageListHead, ¤t->PageListEntry);
|
||||
if (Slab->FirstFreePage == NULL)
|
||||
{
|
||||
Slab->FirstFreePage = current;
|
||||
}
|
||||
}
|
||||
KeReleaseSpinLock(&Slab->SlabLock, oldIrql);
|
||||
return;
|
||||
}
|
||||
}
|
||||
DPRINT1("Tried to free object not in cache.\n");
|
||||
KEBUGCHECK(0);
|
||||
if (Base >= Object &&
|
||||
((char*)Base + PAGE_SIZE - sizeof(SLAB_CACHE_PAGE)) >=
|
||||
((char*)Object + Slab->ObjectSize))
|
||||
{
|
||||
ExFreeFromPageSlabCache(Slab, current, Object);
|
||||
/*
|
||||
* If the page just become free then rearrange things.
|
||||
*/
|
||||
if (current->ReferenceCount == 0)
|
||||
{
|
||||
RemoveEntryList(¤t->PageListEntry);
|
||||
InsertTailList(&Slab->PageListHead, ¤t->PageListEntry);
|
||||
if (Slab->FirstFreePage == NULL)
|
||||
{
|
||||
Slab->FirstFreePage = current;
|
||||
}
|
||||
}
|
||||
KeReleaseSpinLock(&Slab->SlabLock, oldIrql);
|
||||
return;
|
||||
}
|
||||
}
|
||||
DPRINT1("Tried to free object not in cache.\n");
|
||||
KEBUGCHECK(0);
|
||||
}
|
||||
|
||||
VOID
|
||||
ExDestroySlabCache(PSLAB_CACHE Slab)
|
||||
{
|
||||
PLIST_ENTRY current_entry;
|
||||
PSLAB_CACHE_PAGE current;
|
||||
ULONG i;
|
||||
PVOID Object;
|
||||
PLIST_ENTRY current_entry;
|
||||
PSLAB_CACHE_PAGE current;
|
||||
ULONG i;
|
||||
PVOID Object;
|
||||
|
||||
current_entry = Slab->PageListHead.Flink;
|
||||
while (current_entry != &Slab->PageListHead)
|
||||
{
|
||||
current_entry = Slab->PageListHead.Flink;
|
||||
while (current_entry != &Slab->PageListHead)
|
||||
{
|
||||
PVOID Base;
|
||||
PHYSICAL_ADDRESS PhysicalPage;
|
||||
|
||||
current = CONTAINING_RECORD(current_entry,
|
||||
SLAB_CACHE_PAGE,
|
||||
PageListEntry);
|
||||
SLAB_CACHE_PAGE,
|
||||
PageListEntry);
|
||||
Base = (PVOID)((char*)current + sizeof(SLAB_CACHE_PAGE) - PAGE_SIZE);
|
||||
if (Slab->Destructor != NULL)
|
||||
{
|
||||
for (i = 0; i < Slab->ObjectsPerPage; i++)
|
||||
{
|
||||
Object = (char*)Base + (i * Slab->ObjectSize) +
|
||||
sizeof(SLAB_CACHE_BUFCTL);
|
||||
Slab->Destructor(Object, Slab->BaseSize);
|
||||
}
|
||||
}
|
||||
{
|
||||
for (i = 0; i < Slab->ObjectsPerPage; i++)
|
||||
{
|
||||
Object = (char*)Base + (i * Slab->ObjectSize) +
|
||||
sizeof(SLAB_CACHE_BUFCTL);
|
||||
Slab->Destructor(Object, Slab->BaseSize);
|
||||
}
|
||||
}
|
||||
PhysicalPage = MmGetPhysicalAddressForProcess(NULL, Base);
|
||||
ExUnmapPage(Base);
|
||||
MmReleasePageMemoryConsumer(MC_NPPOOL, PhysicalPage);
|
||||
}
|
||||
ExFreePool(Slab);
|
||||
}
|
||||
ExFreePool(Slab);
|
||||
}
|
||||
|
||||
+331
-331
@@ -16,14 +16,14 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
/* $Id: virtual.c,v 1.71 2003/12/14 17:44:02 hbirr Exp $
|
||||
/* $Id: virtual.c,v 1.72 2004/04/10 22:35:26 gdalsnes Exp $
|
||||
*
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: ntoskrnl/mm/virtual.c
|
||||
* PURPOSE: Implementing operations on virtual memory.
|
||||
* PROGRAMMER: David Welch
|
||||
*/
|
||||
|
||||
|
||||
/* INCLUDE *****************************************************************/
|
||||
|
||||
#include <ddk/ntddk.h>
|
||||
@@ -39,11 +39,11 @@
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
NTSTATUS STDCALL
|
||||
NtFlushVirtualMemory(IN HANDLE ProcessHandle,
|
||||
IN PVOID BaseAddress,
|
||||
IN ULONG NumberOfBytesToFlush,
|
||||
OUT PULONG NumberOfBytesFlushed OPTIONAL)
|
||||
NTSTATUS STDCALL
|
||||
NtFlushVirtualMemory(IN HANDLE ProcessHandle,
|
||||
IN PVOID BaseAddress,
|
||||
IN ULONG NumberOfBytesToFlush,
|
||||
OUT PULONG NumberOfBytesFlushed OPTIONAL)
|
||||
/*
|
||||
* FUNCTION: Flushes virtual memory to file
|
||||
* ARGUMENTS:
|
||||
@@ -55,152 +55,152 @@ NtFlushVirtualMemory(IN HANDLE ProcessHandle,
|
||||
* RETURNS: Status
|
||||
*/
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return(STATUS_NOT_IMPLEMENTED);
|
||||
UNIMPLEMENTED;
|
||||
return(STATUS_NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
NTSTATUS STDCALL
|
||||
NtLockVirtualMemory(HANDLE ProcessHandle,
|
||||
PVOID BaseAddress,
|
||||
ULONG NumberOfBytesToLock,
|
||||
PULONG NumberOfBytesLocked) // ULONG LockOption?
|
||||
NTSTATUS STDCALL
|
||||
NtLockVirtualMemory(HANDLE ProcessHandle,
|
||||
PVOID BaseAddress,
|
||||
ULONG NumberOfBytesToLock,
|
||||
PULONG NumberOfBytesLocked) // ULONG LockOption?
|
||||
{
|
||||
// AG [08-20-03] : I have *no* idea if this is correct, I just used the
|
||||
// other functions as a template and made a few intelligent guesses...
|
||||
// AG [08-20-03] : I have *no* idea if this is correct, I just used the
|
||||
// other functions as a template and made a few intelligent guesses...
|
||||
|
||||
NTSTATUS Status;
|
||||
PMDL Mdl;
|
||||
PEPROCESS Process;
|
||||
|
||||
DPRINT("NtLockVirtualMemory(ProcessHandle %x, BaseAddress %x, "
|
||||
"NumberOfBytesToLock %d), NumberOfBytesLocked %x\n",ProcessHandle,BaseAddress,
|
||||
NumberOfBytesToLock, NumberOfBytesLocked);
|
||||
|
||||
Status = ObReferenceObjectByHandle(ProcessHandle,
|
||||
PROCESS_VM_WRITE,
|
||||
NULL,
|
||||
UserMode,
|
||||
(PVOID*)(&Process),
|
||||
NULL);
|
||||
if (Status != STATUS_SUCCESS)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PMDL Mdl;
|
||||
PEPROCESS Process;
|
||||
|
||||
DPRINT("NtLockVirtualMemory(ProcessHandle %x, BaseAddress %x, "
|
||||
"NumberOfBytesToLock %d), NumberOfBytesLocked %x\n",ProcessHandle,BaseAddress,
|
||||
NumberOfBytesToLock, NumberOfBytesLocked);
|
||||
|
||||
Status = ObReferenceObjectByHandle(ProcessHandle,
|
||||
PROCESS_VM_WRITE,
|
||||
NULL,
|
||||
UserMode,
|
||||
(PVOID*)(&Process),
|
||||
NULL);
|
||||
if (Status != STATUS_SUCCESS)
|
||||
{
|
||||
return(Status);
|
||||
}
|
||||
|
||||
Mdl = MmCreateMdl(NULL,
|
||||
BaseAddress,
|
||||
NumberOfBytesToLock);
|
||||
MmProbeAndLockPages(Mdl,
|
||||
UserMode,
|
||||
IoWriteAccess);
|
||||
|
||||
ExFreePool(Mdl); // Are we supposed to do this here?
|
||||
|
||||
ObDereferenceObject(Process);
|
||||
|
||||
*NumberOfBytesLocked = NumberOfBytesToLock;
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
Mdl = MmCreateMdl(NULL,
|
||||
BaseAddress,
|
||||
NumberOfBytesToLock);
|
||||
MmProbeAndLockPages(Mdl,
|
||||
UserMode,
|
||||
IoWriteAccess);
|
||||
|
||||
ExFreePool(Mdl); // Are we supposed to do this here?
|
||||
|
||||
ObDereferenceObject(Process);
|
||||
|
||||
*NumberOfBytesLocked = NumberOfBytesToLock;
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
NTSTATUS STDCALL
|
||||
NTSTATUS STDCALL
|
||||
NtQueryVirtualMemory (IN HANDLE ProcessHandle,
|
||||
IN PVOID Address,
|
||||
IN CINT VirtualMemoryInformationClass,
|
||||
OUT PVOID VirtualMemoryInformation,
|
||||
IN ULONG Length,
|
||||
OUT PULONG UnsafeResultLength)
|
||||
IN PVOID Address,
|
||||
IN CINT VirtualMemoryInformationClass,
|
||||
OUT PVOID VirtualMemoryInformation,
|
||||
IN ULONG Length,
|
||||
OUT PULONG UnsafeResultLength)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PEPROCESS Process;
|
||||
MEMORY_AREA* MemoryArea;
|
||||
ULONG ResultLength = 0;
|
||||
PMADDRESS_SPACE AddressSpace;
|
||||
|
||||
|
||||
DPRINT("NtQueryVirtualMemory(ProcessHandle %x, Address %x, "
|
||||
"VirtualMemoryInformationClass %d, VirtualMemoryInformation %x, "
|
||||
"Length %lu ResultLength %x)\n",ProcessHandle,Address,
|
||||
VirtualMemoryInformationClass,VirtualMemoryInformation,
|
||||
Length,ResultLength);
|
||||
|
||||
|
||||
Status = ObReferenceObjectByHandle(ProcessHandle,
|
||||
PROCESS_QUERY_INFORMATION,
|
||||
NULL,
|
||||
UserMode,
|
||||
(PVOID*)(&Process),
|
||||
NULL);
|
||||
|
||||
PROCESS_QUERY_INFORMATION,
|
||||
NULL,
|
||||
UserMode,
|
||||
(PVOID*)(&Process),
|
||||
NULL);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("NtQueryVirtualMemory() = %x\n",Status);
|
||||
return(Status);
|
||||
}
|
||||
|
||||
{
|
||||
DPRINT("NtQueryVirtualMemory() = %x\n",Status);
|
||||
return(Status);
|
||||
}
|
||||
|
||||
AddressSpace = &Process->AddressSpace;
|
||||
MmLockAddressSpace(AddressSpace);
|
||||
MemoryArea = MmOpenMemoryAreaByAddress(AddressSpace,
|
||||
Address);
|
||||
Address);
|
||||
switch(VirtualMemoryInformationClass)
|
||||
{
|
||||
case MemoryBasicInformation:
|
||||
{
|
||||
PMEMORY_BASIC_INFORMATION Info =
|
||||
(PMEMORY_BASIC_INFORMATION)VirtualMemoryInformation;
|
||||
|
||||
if (Length != sizeof(MEMORY_BASIC_INFORMATION))
|
||||
{
|
||||
MmUnlockAddressSpace(AddressSpace);
|
||||
ObDereferenceObject(Process);
|
||||
return(STATUS_INFO_LENGTH_MISMATCH);
|
||||
}
|
||||
|
||||
if (MemoryArea == NULL)
|
||||
{
|
||||
Info->State = MEM_FREE;
|
||||
Info->BaseAddress = (PVOID)PAGE_ROUND_DOWN(Address);
|
||||
Status = STATUS_SUCCESS;
|
||||
ResultLength = sizeof(MEMORY_BASIC_INFORMATION);
|
||||
}
|
||||
else if (MemoryArea->Type == MEMORY_AREA_VIRTUAL_MEMORY)
|
||||
{
|
||||
Status = MmQueryAnonMem(MemoryArea, Address, Info,
|
||||
&ResultLength);
|
||||
}
|
||||
else if (MemoryArea->Type == MEMORY_AREA_SECTION_VIEW)
|
||||
{
|
||||
Status = MmQuerySectionView(MemoryArea, Address, Info,
|
||||
&ResultLength);
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = STATUS_UNSUCCESSFUL;
|
||||
ResultLength = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
Status = STATUS_INVALID_INFO_CLASS;
|
||||
ResultLength = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
{
|
||||
case MemoryBasicInformation:
|
||||
{
|
||||
PMEMORY_BASIC_INFORMATION Info =
|
||||
(PMEMORY_BASIC_INFORMATION)VirtualMemoryInformation;
|
||||
|
||||
if (Length != sizeof(MEMORY_BASIC_INFORMATION))
|
||||
{
|
||||
MmUnlockAddressSpace(AddressSpace);
|
||||
ObDereferenceObject(Process);
|
||||
return(STATUS_INFO_LENGTH_MISMATCH);
|
||||
}
|
||||
|
||||
if (MemoryArea == NULL)
|
||||
{
|
||||
Info->State = MEM_FREE;
|
||||
Info->BaseAddress = (PVOID)PAGE_ROUND_DOWN(Address);
|
||||
Status = STATUS_SUCCESS;
|
||||
ResultLength = sizeof(MEMORY_BASIC_INFORMATION);
|
||||
}
|
||||
else if (MemoryArea->Type == MEMORY_AREA_VIRTUAL_MEMORY)
|
||||
{
|
||||
Status = MmQueryAnonMem(MemoryArea, Address, Info,
|
||||
&ResultLength);
|
||||
}
|
||||
else if (MemoryArea->Type == MEMORY_AREA_SECTION_VIEW)
|
||||
{
|
||||
Status = MmQuerySectionView(MemoryArea, Address, Info,
|
||||
&ResultLength);
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = STATUS_UNSUCCESSFUL;
|
||||
ResultLength = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
Status = STATUS_INVALID_INFO_CLASS;
|
||||
ResultLength = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
MmUnlockAddressSpace(AddressSpace);
|
||||
ObDereferenceObject(Process);
|
||||
if (UnsafeResultLength != NULL)
|
||||
{
|
||||
MmCopyToCaller(UnsafeResultLength, &ResultLength, sizeof(ULONG));
|
||||
}
|
||||
{
|
||||
MmCopyToCaller(UnsafeResultLength, &ResultLength, sizeof(ULONG));
|
||||
}
|
||||
return(Status);
|
||||
}
|
||||
|
||||
NTSTATUS STDCALL
|
||||
NtProtectVirtualMemory(IN HANDLE ProcessHandle,
|
||||
IN PVOID BaseAddress,
|
||||
IN ULONG NumberOfBytesToProtect,
|
||||
IN ULONG NewAccessProtection,
|
||||
OUT PULONG UnsafeOldAccessProtection)
|
||||
NtProtectVirtualMemory(IN HANDLE ProcessHandle,
|
||||
IN PVOID BaseAddress,
|
||||
IN ULONG NumberOfBytesToProtect,
|
||||
IN ULONG NewAccessProtection,
|
||||
OUT PULONG UnsafeOldAccessProtection)
|
||||
{
|
||||
PMEMORY_AREA MemoryArea;
|
||||
PEPROCESS Process;
|
||||
@@ -209,210 +209,210 @@ NtProtectVirtualMemory(IN HANDLE ProcessHandle,
|
||||
ULONG OldAccessProtection;
|
||||
|
||||
NumberOfBytesToProtect =
|
||||
PAGE_ROUND_UP(BaseAddress + NumberOfBytesToProtect) -
|
||||
PAGE_ROUND_DOWN(BaseAddress);
|
||||
PAGE_ROUND_UP(BaseAddress + NumberOfBytesToProtect) -
|
||||
PAGE_ROUND_DOWN(BaseAddress);
|
||||
BaseAddress = (PVOID)PAGE_ROUND_DOWN(BaseAddress);
|
||||
|
||||
|
||||
Status = ObReferenceObjectByHandle(ProcessHandle,
|
||||
PROCESS_VM_OPERATION,
|
||||
PsProcessType,
|
||||
UserMode,
|
||||
(PVOID*)(&Process),
|
||||
NULL);
|
||||
PROCESS_VM_OPERATION,
|
||||
PsProcessType,
|
||||
UserMode,
|
||||
(PVOID*)(&Process),
|
||||
NULL);
|
||||
if (Status != STATUS_SUCCESS)
|
||||
{
|
||||
DPRINT("NtProtectVirtualMemory() = %x\n",Status);
|
||||
return(Status);
|
||||
}
|
||||
{
|
||||
DPRINT("NtProtectVirtualMemory() = %x\n",Status);
|
||||
return(Status);
|
||||
}
|
||||
|
||||
AddressSpace = &Process->AddressSpace;
|
||||
|
||||
|
||||
MmLockAddressSpace(AddressSpace);
|
||||
MemoryArea = MmOpenMemoryAreaByAddress(AddressSpace,
|
||||
BaseAddress);
|
||||
BaseAddress);
|
||||
if (MemoryArea == NULL)
|
||||
{
|
||||
MmUnlockAddressSpace(AddressSpace);
|
||||
ObDereferenceObject(Process);
|
||||
return(STATUS_UNSUCCESSFUL);
|
||||
}
|
||||
|
||||
{
|
||||
MmUnlockAddressSpace(AddressSpace);
|
||||
ObDereferenceObject(Process);
|
||||
return(STATUS_UNSUCCESSFUL);
|
||||
}
|
||||
|
||||
if (MemoryArea->Type == MEMORY_AREA_VIRTUAL_MEMORY)
|
||||
{
|
||||
Status = MmProtectAnonMem(AddressSpace, MemoryArea, BaseAddress,
|
||||
NumberOfBytesToProtect, NewAccessProtection,
|
||||
&OldAccessProtection);
|
||||
}
|
||||
{
|
||||
Status = MmProtectAnonMem(AddressSpace, MemoryArea, BaseAddress,
|
||||
NumberOfBytesToProtect, NewAccessProtection,
|
||||
&OldAccessProtection);
|
||||
}
|
||||
else if (MemoryArea->Type == MEMORY_AREA_SECTION_VIEW)
|
||||
{
|
||||
Status = MmProtectSectionView(AddressSpace, MemoryArea, BaseAddress,
|
||||
NumberOfBytesToProtect,
|
||||
NewAccessProtection,
|
||||
&OldAccessProtection);
|
||||
}
|
||||
|
||||
{
|
||||
Status = MmProtectSectionView(AddressSpace, MemoryArea, BaseAddress,
|
||||
NumberOfBytesToProtect,
|
||||
NewAccessProtection,
|
||||
&OldAccessProtection);
|
||||
}
|
||||
|
||||
MmUnlockAddressSpace(AddressSpace);
|
||||
ObDereferenceObject(Process);
|
||||
|
||||
MmCopyToCaller(UnsafeOldAccessProtection, &OldAccessProtection,
|
||||
sizeof(ULONG));
|
||||
MmCopyToCaller(UnsafeOldAccessProtection, &OldAccessProtection,
|
||||
sizeof(ULONG));
|
||||
|
||||
return(Status);
|
||||
}
|
||||
|
||||
NTSTATUS STDCALL
|
||||
NtReadVirtualMemory(IN HANDLE ProcessHandle,
|
||||
IN PVOID BaseAddress,
|
||||
OUT PVOID Buffer,
|
||||
IN ULONG NumberOfBytesToRead,
|
||||
OUT PULONG NumberOfBytesRead)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PMDL Mdl;
|
||||
PVOID SystemAddress;
|
||||
PEPROCESS Process;
|
||||
|
||||
DPRINT("NtReadVirtualMemory(ProcessHandle %x, BaseAddress %x, "
|
||||
"Buffer %x, NumberOfBytesToRead %d)\n",ProcessHandle,BaseAddress,
|
||||
Buffer,NumberOfBytesToRead);
|
||||
|
||||
Status = ObReferenceObjectByHandle(ProcessHandle,
|
||||
PROCESS_VM_WRITE,
|
||||
NULL,
|
||||
UserMode,
|
||||
(PVOID*)(&Process),
|
||||
NULL);
|
||||
if (Status != STATUS_SUCCESS)
|
||||
{
|
||||
return(Status);
|
||||
}
|
||||
|
||||
Mdl = MmCreateMdl(NULL,
|
||||
Buffer,
|
||||
NumberOfBytesToRead);
|
||||
MmProbeAndLockPages(Mdl,
|
||||
UserMode,
|
||||
IoWriteAccess);
|
||||
|
||||
KeAttachProcess(Process);
|
||||
|
||||
SystemAddress = MmGetSystemAddressForMdl(Mdl);
|
||||
memcpy(SystemAddress, BaseAddress, NumberOfBytesToRead);
|
||||
|
||||
KeDetachProcess();
|
||||
|
||||
if (Mdl->MappedSystemVa != NULL)
|
||||
{
|
||||
MmUnmapLockedPages(Mdl->MappedSystemVa, Mdl);
|
||||
}
|
||||
MmUnlockPages(Mdl);
|
||||
ExFreePool(Mdl);
|
||||
|
||||
ObDereferenceObject(Process);
|
||||
|
||||
*NumberOfBytesRead = NumberOfBytesToRead;
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
NTSTATUS STDCALL
|
||||
NtUnlockVirtualMemory(HANDLE ProcessHandle,
|
||||
PVOID BaseAddress,
|
||||
ULONG NumberOfBytesToUnlock,
|
||||
PULONG NumberOfBytesUnlocked OPTIONAL)
|
||||
{
|
||||
// AG [08-20-03] : I have *no* idea if this is correct, I just used the
|
||||
// other functions as a template and made a few intelligent guesses...
|
||||
|
||||
NTSTATUS Status;
|
||||
PMDL Mdl;
|
||||
PEPROCESS Process;
|
||||
|
||||
DPRINT("NtUnlockVirtualMemory(ProcessHandle %x, BaseAddress %x, "
|
||||
"NumberOfBytesToUnlock %d), NumberOfBytesUnlocked %x\n",ProcessHandle,BaseAddress,
|
||||
NumberOfBytesToUnlock, NumberOfBytesUnlocked);
|
||||
|
||||
Status = ObReferenceObjectByHandle(ProcessHandle,
|
||||
PROCESS_VM_WRITE,
|
||||
NULL,
|
||||
UserMode,
|
||||
(PVOID*)(&Process),
|
||||
NULL);
|
||||
if (Status != STATUS_SUCCESS)
|
||||
{
|
||||
return(Status);
|
||||
}
|
||||
|
||||
Mdl = MmCreateMdl(NULL,
|
||||
BaseAddress,
|
||||
NumberOfBytesToUnlock);
|
||||
|
||||
ObDereferenceObject(Process);
|
||||
|
||||
if (Mdl->MappedSystemVa != NULL)
|
||||
{
|
||||
MmUnmapLockedPages(Mdl->MappedSystemVa, Mdl);
|
||||
}
|
||||
MmUnlockPages(Mdl);
|
||||
ExFreePool(Mdl);
|
||||
|
||||
*NumberOfBytesUnlocked = NumberOfBytesToUnlock;
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS STDCALL
|
||||
NtWriteVirtualMemory(IN HANDLE ProcessHandle,
|
||||
IN PVOID BaseAddress,
|
||||
IN PVOID Buffer,
|
||||
IN ULONG NumberOfBytesToWrite,
|
||||
OUT PULONG NumberOfBytesWritten)
|
||||
NTSTATUS STDCALL
|
||||
NtReadVirtualMemory(IN HANDLE ProcessHandle,
|
||||
IN PVOID BaseAddress,
|
||||
OUT PVOID Buffer,
|
||||
IN ULONG NumberOfBytesToRead,
|
||||
OUT PULONG NumberOfBytesRead)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PMDL Mdl;
|
||||
PVOID SystemAddress;
|
||||
PEPROCESS Process;
|
||||
|
||||
DPRINT("NtWriteVirtualMemory(ProcessHandle %x, BaseAddress %x, "
|
||||
"Buffer %x, NumberOfBytesToWrite %d)\n",ProcessHandle,BaseAddress,
|
||||
Buffer,NumberOfBytesToWrite);
|
||||
|
||||
|
||||
DPRINT("NtReadVirtualMemory(ProcessHandle %x, BaseAddress %x, "
|
||||
"Buffer %x, NumberOfBytesToRead %d)\n",ProcessHandle,BaseAddress,
|
||||
Buffer,NumberOfBytesToRead);
|
||||
|
||||
Status = ObReferenceObjectByHandle(ProcessHandle,
|
||||
PROCESS_VM_WRITE,
|
||||
NULL,
|
||||
UserMode,
|
||||
(PVOID*)(&Process),
|
||||
NULL);
|
||||
PROCESS_VM_WRITE,
|
||||
NULL,
|
||||
UserMode,
|
||||
(PVOID*)(&Process),
|
||||
NULL);
|
||||
if (Status != STATUS_SUCCESS)
|
||||
{
|
||||
return(Status);
|
||||
}
|
||||
|
||||
Mdl = MmCreateMdl(NULL,
|
||||
Buffer,
|
||||
NumberOfBytesToWrite);
|
||||
{
|
||||
return(Status);
|
||||
}
|
||||
|
||||
Mdl = MmCreateMdl(NULL,
|
||||
Buffer,
|
||||
NumberOfBytesToRead);
|
||||
MmProbeAndLockPages(Mdl,
|
||||
UserMode,
|
||||
IoReadAccess);
|
||||
|
||||
UserMode,
|
||||
IoWriteAccess);
|
||||
|
||||
KeAttachProcess(Process);
|
||||
|
||||
|
||||
SystemAddress = MmGetSystemAddressForMdl(Mdl);
|
||||
memcpy(BaseAddress, SystemAddress, NumberOfBytesToWrite);
|
||||
|
||||
memcpy(SystemAddress, BaseAddress, NumberOfBytesToRead);
|
||||
|
||||
KeDetachProcess();
|
||||
|
||||
|
||||
if (Mdl->MappedSystemVa != NULL)
|
||||
{
|
||||
MmUnmapLockedPages(Mdl->MappedSystemVa, Mdl);
|
||||
}
|
||||
MmUnlockPages(Mdl);
|
||||
ExFreePool(Mdl);
|
||||
|
||||
ObDereferenceObject(Process);
|
||||
|
||||
*NumberOfBytesRead = NumberOfBytesToRead;
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
NTSTATUS STDCALL
|
||||
NtUnlockVirtualMemory(HANDLE ProcessHandle,
|
||||
PVOID BaseAddress,
|
||||
ULONG NumberOfBytesToUnlock,
|
||||
PULONG NumberOfBytesUnlocked OPTIONAL)
|
||||
{
|
||||
// AG [08-20-03] : I have *no* idea if this is correct, I just used the
|
||||
// other functions as a template and made a few intelligent guesses...
|
||||
|
||||
NTSTATUS Status;
|
||||
PMDL Mdl;
|
||||
PEPROCESS Process;
|
||||
|
||||
DPRINT("NtUnlockVirtualMemory(ProcessHandle %x, BaseAddress %x, "
|
||||
"NumberOfBytesToUnlock %d), NumberOfBytesUnlocked %x\n",ProcessHandle,BaseAddress,
|
||||
NumberOfBytesToUnlock, NumberOfBytesUnlocked);
|
||||
|
||||
Status = ObReferenceObjectByHandle(ProcessHandle,
|
||||
PROCESS_VM_WRITE,
|
||||
NULL,
|
||||
UserMode,
|
||||
(PVOID*)(&Process),
|
||||
NULL);
|
||||
if (Status != STATUS_SUCCESS)
|
||||
{
|
||||
return(Status);
|
||||
}
|
||||
|
||||
Mdl = MmCreateMdl(NULL,
|
||||
BaseAddress,
|
||||
NumberOfBytesToUnlock);
|
||||
|
||||
ObDereferenceObject(Process);
|
||||
|
||||
if (Mdl->MappedSystemVa != NULL)
|
||||
{
|
||||
MmUnmapLockedPages(Mdl->MappedSystemVa, Mdl);
|
||||
}
|
||||
{
|
||||
MmUnmapLockedPages(Mdl->MappedSystemVa, Mdl);
|
||||
}
|
||||
MmUnlockPages(Mdl);
|
||||
ExFreePool(Mdl);
|
||||
|
||||
|
||||
*NumberOfBytesUnlocked = NumberOfBytesToUnlock;
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS STDCALL
|
||||
NtWriteVirtualMemory(IN HANDLE ProcessHandle,
|
||||
IN PVOID BaseAddress,
|
||||
IN PVOID Buffer,
|
||||
IN ULONG NumberOfBytesToWrite,
|
||||
OUT PULONG NumberOfBytesWritten)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PMDL Mdl;
|
||||
PVOID SystemAddress;
|
||||
PEPROCESS Process;
|
||||
|
||||
DPRINT("NtWriteVirtualMemory(ProcessHandle %x, BaseAddress %x, "
|
||||
"Buffer %x, NumberOfBytesToWrite %d)\n",ProcessHandle,BaseAddress,
|
||||
Buffer,NumberOfBytesToWrite);
|
||||
|
||||
Status = ObReferenceObjectByHandle(ProcessHandle,
|
||||
PROCESS_VM_WRITE,
|
||||
NULL,
|
||||
UserMode,
|
||||
(PVOID*)(&Process),
|
||||
NULL);
|
||||
if (Status != STATUS_SUCCESS)
|
||||
{
|
||||
return(Status);
|
||||
}
|
||||
|
||||
Mdl = MmCreateMdl(NULL,
|
||||
Buffer,
|
||||
NumberOfBytesToWrite);
|
||||
MmProbeAndLockPages(Mdl,
|
||||
UserMode,
|
||||
IoReadAccess);
|
||||
|
||||
KeAttachProcess(Process);
|
||||
|
||||
SystemAddress = MmGetSystemAddressForMdl(Mdl);
|
||||
memcpy(BaseAddress, SystemAddress, NumberOfBytesToWrite);
|
||||
|
||||
KeDetachProcess();
|
||||
|
||||
ObDereferenceObject(Process);
|
||||
|
||||
if (Mdl->MappedSystemVa != NULL)
|
||||
{
|
||||
MmUnmapLockedPages(Mdl->MappedSystemVa, Mdl);
|
||||
}
|
||||
MmUnlockPages(Mdl);
|
||||
ExFreePool(Mdl);
|
||||
|
||||
*NumberOfBytesWritten = NumberOfBytesToWrite;
|
||||
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
@@ -424,15 +424,15 @@ MmSecureVirtualMemory (PVOID Address,
|
||||
SIZE_T Length,
|
||||
ULONG Mode)
|
||||
{
|
||||
/* Only works for user space */
|
||||
if (MmHighestUserAddress < Address)
|
||||
{
|
||||
/* Only works for user space */
|
||||
if (MmHighestUserAddress < Address)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
UNIMPLEMENTED;
|
||||
UNIMPLEMENTED;
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -442,12 +442,12 @@ MmSecureVirtualMemory (PVOID Address,
|
||||
VOID STDCALL
|
||||
MmUnsecureVirtualMemory(PVOID SecureMem)
|
||||
{
|
||||
if (NULL == SecureMem)
|
||||
{
|
||||
if (NULL == SecureMem)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
UNIMPLEMENTED;
|
||||
UNIMPLEMENTED;
|
||||
}
|
||||
|
||||
|
||||
@@ -456,23 +456,23 @@ MmUnsecureVirtualMemory(PVOID SecureMem)
|
||||
*/
|
||||
VOID STDCALL
|
||||
ProbeForRead (IN PVOID Address,
|
||||
IN ULONG Length,
|
||||
IN ULONG Alignment)
|
||||
IN ULONG Length,
|
||||
IN ULONG Alignment)
|
||||
{
|
||||
assert (Alignment ==1 || Alignment == 2 || Alignment == 4 || Alignment == 8);
|
||||
assert (Alignment ==1 || Alignment == 2 || Alignment == 4 || Alignment == 8);
|
||||
|
||||
if (Length == 0)
|
||||
return;
|
||||
if (Length == 0)
|
||||
return;
|
||||
|
||||
if (((ULONG_PTR)Address & (Alignment - 1)) != 0)
|
||||
{
|
||||
if (((ULONG_PTR)Address & (Alignment - 1)) != 0)
|
||||
{
|
||||
ExRaiseStatus (STATUS_DATATYPE_MISALIGNMENT);
|
||||
}
|
||||
else if ((ULONG_PTR)Address + Length < (ULONG_PTR)Address ||
|
||||
(ULONG_PTR)Address + Length > (ULONG_PTR)MmUserProbeAddress)
|
||||
{
|
||||
}
|
||||
else if ((ULONG_PTR)Address + Length < (ULONG_PTR)Address ||
|
||||
(ULONG_PTR)Address + Length > (ULONG_PTR)MmUserProbeAddress)
|
||||
{
|
||||
ExRaiseStatus (STATUS_ACCESS_VIOLATION);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -481,35 +481,35 @@ ProbeForRead (IN PVOID Address,
|
||||
*/
|
||||
VOID STDCALL
|
||||
ProbeForWrite (IN PVOID Address,
|
||||
IN ULONG Length,
|
||||
IN ULONG Alignment)
|
||||
IN ULONG Length,
|
||||
IN ULONG Alignment)
|
||||
{
|
||||
PULONG Ptr;
|
||||
ULONG x;
|
||||
ULONG i;
|
||||
PULONG Ptr;
|
||||
ULONG x;
|
||||
ULONG i;
|
||||
|
||||
assert (Alignment ==1 || Alignment == 2 || Alignment == 4 || Alignment == 8);
|
||||
assert (Alignment ==1 || Alignment == 2 || Alignment == 4 || Alignment == 8);
|
||||
|
||||
if (Length == 0)
|
||||
return;
|
||||
if (Length == 0)
|
||||
return;
|
||||
|
||||
if (((ULONG_PTR)Address & (Alignment - 1)) != 0)
|
||||
{
|
||||
if (((ULONG_PTR)Address & (Alignment - 1)) != 0)
|
||||
{
|
||||
ExRaiseStatus (STATUS_DATATYPE_MISALIGNMENT);
|
||||
}
|
||||
else if ((ULONG_PTR)Address + Length < (ULONG_PTR)Address ||
|
||||
(ULONG_PTR)Address + Length > (ULONG_PTR)MmUserProbeAddress)
|
||||
{
|
||||
}
|
||||
else if ((ULONG_PTR)Address + Length < (ULONG_PTR)Address ||
|
||||
(ULONG_PTR)Address + Length > (ULONG_PTR)MmUserProbeAddress)
|
||||
{
|
||||
ExRaiseStatus (STATUS_ACCESS_VIOLATION);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for accessible pages */
|
||||
for (i = 0; i < Length; i += PAGE_SIZE)
|
||||
{
|
||||
/* Check for accessible pages */
|
||||
for (i = 0; i < Length; i += PAGE_SIZE)
|
||||
{
|
||||
Ptr = (PULONG)(((ULONG_PTR)Address & ~(PAGE_SIZE - 1)) + i);
|
||||
x = *Ptr;
|
||||
*Ptr = x;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
||||
+18
-18
@@ -16,7 +16,7 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
/* $Id: wset.c,v 1.17 2003/07/12 01:52:10 dwelch Exp $
|
||||
/* $Id: wset.c,v 1.18 2004/04/10 22:35:26 gdalsnes Exp $
|
||||
*
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: ntoskrnl/mm/wset.c
|
||||
@@ -41,30 +41,30 @@
|
||||
NTSTATUS
|
||||
MmTrimUserMemory(ULONG Target, ULONG Priority, PULONG NrFreedPages)
|
||||
{
|
||||
PHYSICAL_ADDRESS CurrentPhysicalAddress;
|
||||
PHYSICAL_ADDRESS NextPhysicalAddress;
|
||||
NTSTATUS Status;
|
||||
PHYSICAL_ADDRESS CurrentPhysicalAddress;
|
||||
PHYSICAL_ADDRESS NextPhysicalAddress;
|
||||
NTSTATUS Status;
|
||||
|
||||
(*NrFreedPages) = 0;
|
||||
(*NrFreedPages) = 0;
|
||||
|
||||
CurrentPhysicalAddress = MmGetLRUFirstUserPage();
|
||||
while (CurrentPhysicalAddress.QuadPart != 0 && Target > 0)
|
||||
{
|
||||
CurrentPhysicalAddress = MmGetLRUFirstUserPage();
|
||||
while (CurrentPhysicalAddress.QuadPart != 0 && Target > 0)
|
||||
{
|
||||
NextPhysicalAddress = MmGetLRUNextUserPage(CurrentPhysicalAddress);
|
||||
|
||||
Status = MmPageOutPhysicalAddress(CurrentPhysicalAddress);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("Succeeded\n");
|
||||
Target--;
|
||||
(*NrFreedPages)++;
|
||||
}
|
||||
{
|
||||
DPRINT("Succeeded\n");
|
||||
Target--;
|
||||
(*NrFreedPages)++;
|
||||
}
|
||||
else if (Status == STATUS_PAGEFILE_QUOTA)
|
||||
{
|
||||
MmSetLRULastPage(CurrentPhysicalAddress);
|
||||
}
|
||||
{
|
||||
MmSetLRULastPage(CurrentPhysicalAddress);
|
||||
}
|
||||
|
||||
CurrentPhysicalAddress = NextPhysicalAddress;
|
||||
}
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user