mirror of
https://github.com/reactos/reactos.git
synced 2025-06-03 08:20:27 +00:00
[NTOSKRNL]
Apply indentation of 4 spaces, no code change. svn path=/trunk/; revision=64531
This commit is contained in:
parent
4b31efff8f
commit
c9252b32bd
9 changed files with 5340 additions and 5333 deletions
|
@ -26,9 +26,9 @@
|
||||||
/* TYPES ********************************************************************/
|
/* TYPES ********************************************************************/
|
||||||
typedef struct _MM_ALLOCATION_REQUEST
|
typedef struct _MM_ALLOCATION_REQUEST
|
||||||
{
|
{
|
||||||
PFN_NUMBER Page;
|
PFN_NUMBER Page;
|
||||||
LIST_ENTRY ListEntry;
|
LIST_ENTRY ListEntry;
|
||||||
KEVENT Event;
|
KEVENT Event;
|
||||||
}
|
}
|
||||||
MM_ALLOCATION_REQUEST, *PMM_ALLOCATION_REQUEST;
|
MM_ALLOCATION_REQUEST, *PMM_ALLOCATION_REQUEST;
|
||||||
/* GLOBALS ******************************************************************/
|
/* GLOBALS ******************************************************************/
|
||||||
|
@ -52,15 +52,15 @@ INIT_FUNCTION
|
||||||
NTAPI
|
NTAPI
|
||||||
MmInitializeBalancer(ULONG NrAvailablePages, ULONG NrSystemPages)
|
MmInitializeBalancer(ULONG NrAvailablePages, ULONG NrSystemPages)
|
||||||
{
|
{
|
||||||
memset(MiMemoryConsumers, 0, sizeof(MiMemoryConsumers));
|
memset(MiMemoryConsumers, 0, sizeof(MiMemoryConsumers));
|
||||||
InitializeListHead(&AllocationListHead);
|
InitializeListHead(&AllocationListHead);
|
||||||
KeInitializeSpinLock(&AllocationListLock);
|
KeInitializeSpinLock(&AllocationListLock);
|
||||||
|
|
||||||
MiNrTotalPages = NrAvailablePages;
|
MiNrTotalPages = NrAvailablePages;
|
||||||
|
|
||||||
/* Set up targets. */
|
/* Set up targets. */
|
||||||
MiMinimumAvailablePages = 128;
|
MiMinimumAvailablePages = 128;
|
||||||
MiMinimumPagesPerRun = 256;
|
MiMinimumPagesPerRun = 256;
|
||||||
if ((NrAvailablePages + NrSystemPages) >= 8192)
|
if ((NrAvailablePages + NrSystemPages) >= 8192)
|
||||||
{
|
{
|
||||||
MiMemoryConsumers[MC_CACHE].PagesTarget = NrAvailablePages / 4 * 3;
|
MiMemoryConsumers[MC_CACHE].PagesTarget = NrAvailablePages / 4 * 3;
|
||||||
|
@ -73,17 +73,17 @@ MmInitializeBalancer(ULONG NrAvailablePages, ULONG NrSystemPages)
|
||||||
{
|
{
|
||||||
MiMemoryConsumers[MC_CACHE].PagesTarget = NrAvailablePages / 8;
|
MiMemoryConsumers[MC_CACHE].PagesTarget = NrAvailablePages / 8;
|
||||||
}
|
}
|
||||||
MiMemoryConsumers[MC_USER].PagesTarget = NrAvailablePages - MiMinimumAvailablePages;
|
MiMemoryConsumers[MC_USER].PagesTarget = NrAvailablePages - MiMinimumAvailablePages;
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
INIT_FUNCTION
|
INIT_FUNCTION
|
||||||
NTAPI
|
NTAPI
|
||||||
MmInitializeMemoryConsumer(ULONG Consumer,
|
MmInitializeMemoryConsumer(
|
||||||
NTSTATUS (*Trim)(ULONG Target, ULONG Priority,
|
ULONG Consumer,
|
||||||
PULONG NrFreed))
|
NTSTATUS (*Trim)(ULONG Target, ULONG Priority, PULONG NrFreed))
|
||||||
{
|
{
|
||||||
MiMemoryConsumers[Consumer].Trim = Trim;
|
MiMemoryConsumers[Consumer].Trim = Trim;
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
|
@ -96,42 +96,42 @@ NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
MmReleasePageMemoryConsumer(ULONG Consumer, PFN_NUMBER Page)
|
MmReleasePageMemoryConsumer(ULONG Consumer, PFN_NUMBER Page)
|
||||||
{
|
{
|
||||||
PMM_ALLOCATION_REQUEST Request;
|
PMM_ALLOCATION_REQUEST Request;
|
||||||
PLIST_ENTRY Entry;
|
PLIST_ENTRY Entry;
|
||||||
KIRQL OldIrql;
|
KIRQL OldIrql;
|
||||||
|
|
||||||
if (Page == 0)
|
if (Page == 0)
|
||||||
{
|
{
|
||||||
DPRINT1("Tried to release page zero.\n");
|
DPRINT1("Tried to release page zero.\n");
|
||||||
KeBugCheck(MEMORY_MANAGEMENT);
|
KeBugCheck(MEMORY_MANAGEMENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (MmGetReferenceCountPage(Page) == 1)
|
if (MmGetReferenceCountPage(Page) == 1)
|
||||||
{
|
{
|
||||||
if(Consumer == MC_USER) MmRemoveLRUUserPage(Page);
|
if(Consumer == MC_USER) MmRemoveLRUUserPage(Page);
|
||||||
(void)InterlockedDecrementUL(&MiMemoryConsumers[Consumer].PagesUsed);
|
(void)InterlockedDecrementUL(&MiMemoryConsumers[Consumer].PagesUsed);
|
||||||
if ((Entry = ExInterlockedRemoveHeadList(&AllocationListHead, &AllocationListLock)) == NULL)
|
if ((Entry = ExInterlockedRemoveHeadList(&AllocationListHead, &AllocationListLock)) == NULL)
|
||||||
{
|
{
|
||||||
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
||||||
MmDereferencePage(Page);
|
MmDereferencePage(Page);
|
||||||
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Request = CONTAINING_RECORD(Entry, MM_ALLOCATION_REQUEST, ListEntry);
|
Request = CONTAINING_RECORD(Entry, MM_ALLOCATION_REQUEST, ListEntry);
|
||||||
MiZeroPhysicalPage(Page);
|
MiZeroPhysicalPage(Page);
|
||||||
Request->Page = Page;
|
Request->Page = Page;
|
||||||
KeSetEvent(&Request->Event, IO_NO_INCREMENT, FALSE);
|
KeSetEvent(&Request->Event, IO_NO_INCREMENT, FALSE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
||||||
MmDereferencePage(Page);
|
MmDereferencePage(Page);
|
||||||
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
||||||
}
|
}
|
||||||
|
|
||||||
return(STATUS_SUCCESS);
|
return(STATUS_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
ULONG
|
ULONG
|
||||||
|
@ -230,8 +230,8 @@ MmTrimUserMemory(ULONG Target, ULONG Priority, PULONG NrFreedPages)
|
||||||
static BOOLEAN
|
static BOOLEAN
|
||||||
MiIsBalancerThread(VOID)
|
MiIsBalancerThread(VOID)
|
||||||
{
|
{
|
||||||
return (MiBalancerThreadHandle != NULL) &&
|
return (MiBalancerThreadHandle != NULL) &&
|
||||||
(PsGetCurrentThreadId() == MiBalancerThreadId.UniqueThread);
|
(PsGetCurrentThreadId() == MiBalancerThreadId.UniqueThread);
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
|
@ -257,181 +257,182 @@ NTAPI
|
||||||
MmRequestPageMemoryConsumer(ULONG Consumer, BOOLEAN CanWait,
|
MmRequestPageMemoryConsumer(ULONG Consumer, BOOLEAN CanWait,
|
||||||
PPFN_NUMBER AllocatedPage)
|
PPFN_NUMBER AllocatedPage)
|
||||||
{
|
{
|
||||||
ULONG PagesUsed;
|
ULONG PagesUsed;
|
||||||
PFN_NUMBER Page;
|
PFN_NUMBER Page;
|
||||||
KIRQL OldIrql;
|
KIRQL OldIrql;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Make sure we don't exceed our individual target.
|
* Make sure we don't exceed our individual target.
|
||||||
*/
|
*/
|
||||||
PagesUsed = InterlockedIncrementUL(&MiMemoryConsumers[Consumer].PagesUsed);
|
PagesUsed = InterlockedIncrementUL(&MiMemoryConsumers[Consumer].PagesUsed);
|
||||||
if (PagesUsed > MiMemoryConsumers[Consumer].PagesTarget &&
|
if (PagesUsed > MiMemoryConsumers[Consumer].PagesTarget &&
|
||||||
!MiIsBalancerThread())
|
!MiIsBalancerThread())
|
||||||
{
|
{
|
||||||
MmRebalanceMemoryConsumers();
|
MmRebalanceMemoryConsumers();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Allocate always memory for the non paged pool and for the pager thread.
|
* Allocate always memory for the non paged pool and for the pager thread.
|
||||||
*/
|
*/
|
||||||
if ((Consumer == MC_SYSTEM) || MiIsBalancerThread())
|
if ((Consumer == MC_SYSTEM) || MiIsBalancerThread())
|
||||||
{
|
{
|
||||||
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
||||||
Page = MmAllocPage(Consumer);
|
Page = MmAllocPage(Consumer);
|
||||||
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
||||||
if (Page == 0)
|
if (Page == 0)
|
||||||
{
|
{
|
||||||
KeBugCheck(NO_PAGES_AVAILABLE);
|
KeBugCheck(NO_PAGES_AVAILABLE);
|
||||||
}
|
}
|
||||||
if (Consumer == MC_USER) MmInsertLRULastUserPage(Page);
|
if (Consumer == MC_USER) MmInsertLRULastUserPage(Page);
|
||||||
*AllocatedPage = Page;
|
*AllocatedPage = Page;
|
||||||
if (MmAvailablePages < MiMinimumAvailablePages)
|
if (MmAvailablePages < MiMinimumAvailablePages)
|
||||||
MmRebalanceMemoryConsumers();
|
MmRebalanceMemoryConsumers();
|
||||||
return(STATUS_SUCCESS);
|
return(STATUS_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Make sure we don't exceed global targets.
|
* Make sure we don't exceed global targets.
|
||||||
*/
|
*/
|
||||||
if (MmAvailablePages < MiMinimumAvailablePages)
|
if (MmAvailablePages < MiMinimumAvailablePages)
|
||||||
{
|
{
|
||||||
MM_ALLOCATION_REQUEST Request;
|
MM_ALLOCATION_REQUEST Request;
|
||||||
|
|
||||||
if (!CanWait)
|
if (!CanWait)
|
||||||
{
|
{
|
||||||
(void)InterlockedDecrementUL(&MiMemoryConsumers[Consumer].PagesUsed);
|
(void)InterlockedDecrementUL(&MiMemoryConsumers[Consumer].PagesUsed);
|
||||||
MmRebalanceMemoryConsumers();
|
MmRebalanceMemoryConsumers();
|
||||||
return(STATUS_NO_MEMORY);
|
return(STATUS_NO_MEMORY);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Insert an allocation request. */
|
/* Insert an allocation request. */
|
||||||
Request.Page = 0;
|
Request.Page = 0;
|
||||||
KeInitializeEvent(&Request.Event, NotificationEvent, FALSE);
|
KeInitializeEvent(&Request.Event, NotificationEvent, FALSE);
|
||||||
|
|
||||||
ExInterlockedInsertTailList(&AllocationListHead, &Request.ListEntry, &AllocationListLock);
|
ExInterlockedInsertTailList(&AllocationListHead, &Request.ListEntry, &AllocationListLock);
|
||||||
MmRebalanceMemoryConsumers();
|
MmRebalanceMemoryConsumers();
|
||||||
|
|
||||||
KeWaitForSingleObject(&Request.Event,
|
KeWaitForSingleObject(&Request.Event,
|
||||||
0,
|
0,
|
||||||
KernelMode,
|
KernelMode,
|
||||||
FALSE,
|
FALSE,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
Page = Request.Page;
|
Page = Request.Page;
|
||||||
if (Page == 0)
|
if (Page == 0)
|
||||||
{
|
{
|
||||||
KeBugCheck(NO_PAGES_AVAILABLE);
|
KeBugCheck(NO_PAGES_AVAILABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(Consumer == MC_USER) MmInsertLRULastUserPage(Page);
|
if(Consumer == MC_USER) MmInsertLRULastUserPage(Page);
|
||||||
*AllocatedPage = Page;
|
*AllocatedPage = Page;
|
||||||
|
|
||||||
if (MmAvailablePages < MiMinimumAvailablePages)
|
if (MmAvailablePages < MiMinimumAvailablePages)
|
||||||
{
|
{
|
||||||
MmRebalanceMemoryConsumers();
|
MmRebalanceMemoryConsumers();
|
||||||
}
|
}
|
||||||
|
|
||||||
return(STATUS_SUCCESS);
|
return(STATUS_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Actually allocate the page.
|
* Actually allocate the page.
|
||||||
*/
|
*/
|
||||||
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
||||||
Page = MmAllocPage(Consumer);
|
Page = MmAllocPage(Consumer);
|
||||||
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
||||||
if (Page == 0)
|
if (Page == 0)
|
||||||
{
|
{
|
||||||
KeBugCheck(NO_PAGES_AVAILABLE);
|
KeBugCheck(NO_PAGES_AVAILABLE);
|
||||||
}
|
}
|
||||||
if(Consumer == MC_USER) MmInsertLRULastUserPage(Page);
|
if(Consumer == MC_USER) MmInsertLRULastUserPage(Page);
|
||||||
*AllocatedPage = Page;
|
*AllocatedPage = Page;
|
||||||
|
|
||||||
if (MmAvailablePages < MiMinimumAvailablePages)
|
if (MmAvailablePages < MiMinimumAvailablePages)
|
||||||
{
|
{
|
||||||
MmRebalanceMemoryConsumers();
|
MmRebalanceMemoryConsumers();
|
||||||
}
|
}
|
||||||
|
|
||||||
return(STATUS_SUCCESS);
|
return(STATUS_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
VOID NTAPI
|
VOID NTAPI
|
||||||
MiBalancerThread(PVOID Unused)
|
MiBalancerThread(PVOID Unused)
|
||||||
{
|
{
|
||||||
PVOID WaitObjects[2];
|
PVOID WaitObjects[2];
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
ULONG i;
|
ULONG i;
|
||||||
|
|
||||||
WaitObjects[0] = &MiBalancerEvent;
|
WaitObjects[0] = &MiBalancerEvent;
|
||||||
WaitObjects[1] = &MiBalancerTimer;
|
WaitObjects[1] = &MiBalancerTimer;
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
Status = KeWaitForMultipleObjects(2,
|
Status = KeWaitForMultipleObjects(2,
|
||||||
WaitObjects,
|
WaitObjects,
|
||||||
WaitAny,
|
WaitAny,
|
||||||
Executive,
|
Executive,
|
||||||
KernelMode,
|
KernelMode,
|
||||||
FALSE,
|
FALSE,
|
||||||
NULL,
|
NULL,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
if (Status == STATUS_WAIT_0 || Status == STATUS_WAIT_1)
|
if (Status == STATUS_WAIT_0 || Status == STATUS_WAIT_1)
|
||||||
{
|
{
|
||||||
ULONG InitialTarget = 0;
|
ULONG InitialTarget = 0;
|
||||||
|
|
||||||
#if (_MI_PAGING_LEVELS == 2)
|
#if (_MI_PAGING_LEVELS == 2)
|
||||||
if (!MiIsBalancerThread())
|
if (!MiIsBalancerThread())
|
||||||
{
|
|
||||||
/* Clean up the unused PDEs */
|
|
||||||
ULONG_PTR Address;
|
|
||||||
PEPROCESS Process = PsGetCurrentProcess();
|
|
||||||
|
|
||||||
/* Acquire PFN lock */
|
|
||||||
KIRQL OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
|
||||||
PMMPDE pointerPde;
|
|
||||||
for (Address = (ULONG_PTR)MI_LOWEST_VAD_ADDRESS;
|
|
||||||
Address < (ULONG_PTR)MM_HIGHEST_VAD_ADDRESS;
|
|
||||||
Address += (PAGE_SIZE * PTE_COUNT))
|
|
||||||
{
|
{
|
||||||
if (MiQueryPageTableReferences((PVOID)Address) == 0)
|
/* Clean up the unused PDEs */
|
||||||
|
ULONG_PTR Address;
|
||||||
|
PEPROCESS Process = PsGetCurrentProcess();
|
||||||
|
|
||||||
|
/* Acquire PFN lock */
|
||||||
|
KIRQL OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
||||||
|
PMMPDE pointerPde;
|
||||||
|
for (Address = (ULONG_PTR)MI_LOWEST_VAD_ADDRESS;
|
||||||
|
Address < (ULONG_PTR)MM_HIGHEST_VAD_ADDRESS;
|
||||||
|
Address += (PAGE_SIZE * PTE_COUNT))
|
||||||
{
|
{
|
||||||
pointerPde = MiAddressToPde(Address);
|
if (MiQueryPageTableReferences((PVOID)Address) == 0)
|
||||||
if (pointerPde->u.Hard.Valid)
|
{
|
||||||
MiDeletePte(pointerPde, MiPdeToPte(pointerPde), Process, NULL);
|
pointerPde = MiAddressToPde(Address);
|
||||||
ASSERT(pointerPde->u.Hard.Valid == 0);
|
if (pointerPde->u.Hard.Valid)
|
||||||
|
MiDeletePte(pointerPde, MiPdeToPte(pointerPde), Process, NULL);
|
||||||
|
ASSERT(pointerPde->u.Hard.Valid == 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Release lock */
|
||||||
|
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
do
|
||||||
|
{
|
||||||
|
ULONG OldTarget = InitialTarget;
|
||||||
|
|
||||||
|
/* Trim each consumer */
|
||||||
|
for (i = 0; i < MC_MAXIMUM; i++)
|
||||||
|
{
|
||||||
|
InitialTarget = MiTrimMemoryConsumer(i, InitialTarget);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* No pages left to swap! */
|
||||||
|
if (InitialTarget != 0 &&
|
||||||
|
InitialTarget == OldTarget)
|
||||||
|
{
|
||||||
|
/* Game over */
|
||||||
|
KeBugCheck(NO_PAGES_AVAILABLE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Release lock */
|
while (InitialTarget != 0);
|
||||||
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
|
||||||
}
|
}
|
||||||
#endif
|
else
|
||||||
do
|
{
|
||||||
{
|
DPRINT1("KeWaitForMultipleObjects failed, status = %x\n", Status);
|
||||||
ULONG OldTarget = InitialTarget;
|
KeBugCheck(MEMORY_MANAGEMENT);
|
||||||
|
}
|
||||||
/* Trim each consumer */
|
}
|
||||||
for (i = 0; i < MC_MAXIMUM; i++)
|
|
||||||
{
|
|
||||||
InitialTarget = MiTrimMemoryConsumer(i, InitialTarget);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* No pages left to swap! */
|
|
||||||
if (InitialTarget != 0 &&
|
|
||||||
InitialTarget == OldTarget)
|
|
||||||
{
|
|
||||||
/* Game over */
|
|
||||||
KeBugCheck(NO_PAGES_AVAILABLE);
|
|
||||||
}
|
|
||||||
} while (InitialTarget != 0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DPRINT1("KeWaitForMultipleObjects failed, status = %x\n", Status);
|
|
||||||
KeBugCheck(MEMORY_MANAGEMENT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
|
@ -439,44 +440,44 @@ INIT_FUNCTION
|
||||||
NTAPI
|
NTAPI
|
||||||
MiInitBalancerThread(VOID)
|
MiInitBalancerThread(VOID)
|
||||||
{
|
{
|
||||||
KPRIORITY Priority;
|
KPRIORITY Priority;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
#if !defined(__GNUC__)
|
#if !defined(__GNUC__)
|
||||||
|
|
||||||
LARGE_INTEGER dummyJunkNeeded;
|
LARGE_INTEGER dummyJunkNeeded;
|
||||||
dummyJunkNeeded.QuadPart = -20000000; /* 2 sec */
|
dummyJunkNeeded.QuadPart = -20000000; /* 2 sec */
|
||||||
;
|
;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
KeInitializeEvent(&MiBalancerEvent, SynchronizationEvent, FALSE);
|
KeInitializeEvent(&MiBalancerEvent, SynchronizationEvent, FALSE);
|
||||||
KeInitializeTimerEx(&MiBalancerTimer, SynchronizationTimer);
|
KeInitializeTimerEx(&MiBalancerTimer, SynchronizationTimer);
|
||||||
KeSetTimerEx(&MiBalancerTimer,
|
KeSetTimerEx(&MiBalancerTimer,
|
||||||
#if defined(__GNUC__)
|
#if defined(__GNUC__)
|
||||||
(LARGE_INTEGER)(LONGLONG)-20000000LL, /* 2 sec */
|
(LARGE_INTEGER)(LONGLONG)-20000000LL, /* 2 sec */
|
||||||
#else
|
#else
|
||||||
dummyJunkNeeded,
|
dummyJunkNeeded,
|
||||||
#endif
|
#endif
|
||||||
2000, /* 2 sec */
|
2000, /* 2 sec */
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
Status = PsCreateSystemThread(&MiBalancerThreadHandle,
|
Status = PsCreateSystemThread(&MiBalancerThreadHandle,
|
||||||
THREAD_ALL_ACCESS,
|
THREAD_ALL_ACCESS,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
&MiBalancerThreadId,
|
&MiBalancerThreadId,
|
||||||
MiBalancerThread,
|
MiBalancerThread,
|
||||||
NULL);
|
NULL);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
KeBugCheck(MEMORY_MANAGEMENT);
|
KeBugCheck(MEMORY_MANAGEMENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
Priority = LOW_REALTIME_PRIORITY + 1;
|
Priority = LOW_REALTIME_PRIORITY + 1;
|
||||||
NtSetInformationThread(MiBalancerThreadHandle,
|
NtSetInformationThread(MiBalancerThreadHandle,
|
||||||
ThreadPriority,
|
ThreadPriority,
|
||||||
&Priority,
|
&Priority,
|
||||||
sizeof(Priority));
|
sizeof(Priority));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -448,76 +448,76 @@ VOID
|
||||||
NTAPI
|
NTAPI
|
||||||
MmSetSavedSwapEntryPage(PFN_NUMBER Pfn, SWAPENTRY SwapEntry)
|
MmSetSavedSwapEntryPage(PFN_NUMBER Pfn, SWAPENTRY SwapEntry)
|
||||||
{
|
{
|
||||||
KIRQL oldIrql;
|
KIRQL oldIrql;
|
||||||
PMMPFN Pfn1;
|
PMMPFN Pfn1;
|
||||||
|
|
||||||
Pfn1 = MiGetPfnEntry(Pfn);
|
Pfn1 = MiGetPfnEntry(Pfn);
|
||||||
ASSERT(Pfn1);
|
ASSERT(Pfn1);
|
||||||
ASSERT_IS_ROS_PFN(Pfn1);
|
ASSERT_IS_ROS_PFN(Pfn1);
|
||||||
|
|
||||||
oldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
oldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
||||||
Pfn1->u1.SwapEntry = SwapEntry;
|
Pfn1->u1.SwapEntry = SwapEntry;
|
||||||
KeReleaseQueuedSpinLock(LockQueuePfnLock, oldIrql);
|
KeReleaseQueuedSpinLock(LockQueuePfnLock, oldIrql);
|
||||||
}
|
}
|
||||||
|
|
||||||
SWAPENTRY
|
SWAPENTRY
|
||||||
NTAPI
|
NTAPI
|
||||||
MmGetSavedSwapEntryPage(PFN_NUMBER Pfn)
|
MmGetSavedSwapEntryPage(PFN_NUMBER Pfn)
|
||||||
{
|
{
|
||||||
SWAPENTRY SwapEntry;
|
SWAPENTRY SwapEntry;
|
||||||
KIRQL oldIrql;
|
KIRQL oldIrql;
|
||||||
PMMPFN Pfn1;
|
PMMPFN Pfn1;
|
||||||
|
|
||||||
Pfn1 = MiGetPfnEntry(Pfn);
|
Pfn1 = MiGetPfnEntry(Pfn);
|
||||||
ASSERT(Pfn1);
|
ASSERT(Pfn1);
|
||||||
ASSERT_IS_ROS_PFN(Pfn1);
|
ASSERT_IS_ROS_PFN(Pfn1);
|
||||||
|
|
||||||
oldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
oldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
||||||
SwapEntry = Pfn1->u1.SwapEntry;
|
SwapEntry = Pfn1->u1.SwapEntry;
|
||||||
KeReleaseQueuedSpinLock(LockQueuePfnLock, oldIrql);
|
KeReleaseQueuedSpinLock(LockQueuePfnLock, oldIrql);
|
||||||
|
|
||||||
return(SwapEntry);
|
return(SwapEntry);
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
NTAPI
|
NTAPI
|
||||||
MmReferencePage(PFN_NUMBER Pfn)
|
MmReferencePage(PFN_NUMBER Pfn)
|
||||||
{
|
{
|
||||||
PMMPFN Pfn1;
|
PMMPFN Pfn1;
|
||||||
|
|
||||||
DPRINT("MmReferencePage(PysicalAddress %x)\n", Pfn << PAGE_SHIFT);
|
DPRINT("MmReferencePage(PysicalAddress %x)\n", Pfn << PAGE_SHIFT);
|
||||||
|
|
||||||
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
|
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
|
||||||
ASSERT(Pfn != 0);
|
ASSERT(Pfn != 0);
|
||||||
ASSERT(Pfn <= MmHighestPhysicalPage);
|
ASSERT(Pfn <= MmHighestPhysicalPage);
|
||||||
|
|
||||||
Pfn1 = MiGetPfnEntry(Pfn);
|
Pfn1 = MiGetPfnEntry(Pfn);
|
||||||
ASSERT(Pfn1);
|
ASSERT(Pfn1);
|
||||||
ASSERT_IS_ROS_PFN(Pfn1);
|
ASSERT_IS_ROS_PFN(Pfn1);
|
||||||
|
|
||||||
ASSERT(Pfn1->u3.e2.ReferenceCount != 0);
|
ASSERT(Pfn1->u3.e2.ReferenceCount != 0);
|
||||||
Pfn1->u3.e2.ReferenceCount++;
|
Pfn1->u3.e2.ReferenceCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
ULONG
|
ULONG
|
||||||
NTAPI
|
NTAPI
|
||||||
MmGetReferenceCountPage(PFN_NUMBER Pfn)
|
MmGetReferenceCountPage(PFN_NUMBER Pfn)
|
||||||
{
|
{
|
||||||
KIRQL oldIrql;
|
KIRQL oldIrql;
|
||||||
ULONG RCount;
|
ULONG RCount;
|
||||||
PMMPFN Pfn1;
|
PMMPFN Pfn1;
|
||||||
|
|
||||||
DPRINT("MmGetReferenceCountPage(PhysicalAddress %x)\n", Pfn << PAGE_SHIFT);
|
DPRINT("MmGetReferenceCountPage(PhysicalAddress %x)\n", Pfn << PAGE_SHIFT);
|
||||||
|
|
||||||
oldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
oldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
||||||
Pfn1 = MiGetPfnEntry(Pfn);
|
Pfn1 = MiGetPfnEntry(Pfn);
|
||||||
ASSERT(Pfn1);
|
ASSERT(Pfn1);
|
||||||
ASSERT_IS_ROS_PFN(Pfn1);
|
ASSERT_IS_ROS_PFN(Pfn1);
|
||||||
|
|
||||||
RCount = Pfn1->u3.e2.ReferenceCount;
|
RCount = Pfn1->u3.e2.ReferenceCount;
|
||||||
|
|
||||||
KeReleaseQueuedSpinLock(LockQueuePfnLock, oldIrql);
|
KeReleaseQueuedSpinLock(LockQueuePfnLock, oldIrql);
|
||||||
return(RCount);
|
return(RCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
|
@ -531,17 +531,17 @@ VOID
|
||||||
NTAPI
|
NTAPI
|
||||||
MmDereferencePage(PFN_NUMBER Pfn)
|
MmDereferencePage(PFN_NUMBER Pfn)
|
||||||
{
|
{
|
||||||
PMMPFN Pfn1;
|
PMMPFN Pfn1;
|
||||||
DPRINT("MmDereferencePage(PhysicalAddress %x)\n", Pfn << PAGE_SHIFT);
|
DPRINT("MmDereferencePage(PhysicalAddress %x)\n", Pfn << PAGE_SHIFT);
|
||||||
|
|
||||||
Pfn1 = MiGetPfnEntry(Pfn);
|
Pfn1 = MiGetPfnEntry(Pfn);
|
||||||
ASSERT(Pfn1);
|
ASSERT(Pfn1);
|
||||||
ASSERT_IS_ROS_PFN(Pfn1);
|
ASSERT_IS_ROS_PFN(Pfn1);
|
||||||
|
|
||||||
ASSERT(Pfn1->u3.e2.ReferenceCount != 0);
|
ASSERT(Pfn1->u3.e2.ReferenceCount != 0);
|
||||||
Pfn1->u3.e2.ReferenceCount--;
|
Pfn1->u3.e2.ReferenceCount--;
|
||||||
if (Pfn1->u3.e2.ReferenceCount == 0)
|
if (Pfn1->u3.e2.ReferenceCount == 0)
|
||||||
{
|
{
|
||||||
/* Mark the page temporarily as valid, we're going to make it free soon */
|
/* Mark the page temporarily as valid, we're going to make it free soon */
|
||||||
Pfn1->u3.e1.PageLocation = ActiveAndValid;
|
Pfn1->u3.e1.PageLocation = ActiveAndValid;
|
||||||
|
|
||||||
|
@ -551,37 +551,37 @@ MmDereferencePage(PFN_NUMBER Pfn)
|
||||||
/* Bring it back into the free list */
|
/* Bring it back into the free list */
|
||||||
DPRINT("Legacy free: %lx\n", Pfn);
|
DPRINT("Legacy free: %lx\n", Pfn);
|
||||||
MiInsertPageInFreeList(Pfn);
|
MiInsertPageInFreeList(Pfn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PFN_NUMBER
|
PFN_NUMBER
|
||||||
NTAPI
|
NTAPI
|
||||||
MmAllocPage(ULONG Type)
|
MmAllocPage(ULONG Type)
|
||||||
{
|
{
|
||||||
PFN_NUMBER PfnOffset;
|
PFN_NUMBER PfnOffset;
|
||||||
PMMPFN Pfn1;
|
PMMPFN Pfn1;
|
||||||
|
|
||||||
PfnOffset = MiRemoveZeroPage(MI_GET_NEXT_COLOR());
|
PfnOffset = MiRemoveZeroPage(MI_GET_NEXT_COLOR());
|
||||||
|
|
||||||
if (!PfnOffset)
|
if (!PfnOffset)
|
||||||
{
|
{
|
||||||
DPRINT1("MmAllocPage(): Out of memory\n");
|
DPRINT1("MmAllocPage(): Out of memory\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
DPRINT("Legacy allocate: %lx\n", PfnOffset);
|
DPRINT("Legacy allocate: %lx\n", PfnOffset);
|
||||||
Pfn1 = MiGetPfnEntry(PfnOffset);
|
Pfn1 = MiGetPfnEntry(PfnOffset);
|
||||||
Pfn1->u3.e2.ReferenceCount = 1;
|
Pfn1->u3.e2.ReferenceCount = 1;
|
||||||
Pfn1->u3.e1.PageLocation = ActiveAndValid;
|
Pfn1->u3.e1.PageLocation = ActiveAndValid;
|
||||||
|
|
||||||
/* This marks the PFN as a ReactOS PFN */
|
/* This marks the PFN as a ReactOS PFN */
|
||||||
Pfn1->u4.AweAllocation = TRUE;
|
Pfn1->u4.AweAllocation = TRUE;
|
||||||
|
|
||||||
/* Allocate the extra ReactOS Data and zero it out */
|
/* Allocate the extra ReactOS Data and zero it out */
|
||||||
Pfn1->u1.SwapEntry = 0;
|
Pfn1->u1.SwapEntry = 0;
|
||||||
Pfn1->RmapListHead = NULL;
|
Pfn1->RmapListHead = NULL;
|
||||||
|
|
||||||
return PfnOffset;
|
return PfnOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -21,180 +21,180 @@
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
MmpAccessFault(KPROCESSOR_MODE Mode,
|
MmpAccessFault(KPROCESSOR_MODE Mode,
|
||||||
ULONG_PTR Address,
|
ULONG_PTR Address,
|
||||||
BOOLEAN FromMdl)
|
BOOLEAN FromMdl)
|
||||||
{
|
{
|
||||||
PMMSUPPORT AddressSpace;
|
PMMSUPPORT AddressSpace;
|
||||||
MEMORY_AREA* MemoryArea;
|
MEMORY_AREA* MemoryArea;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
|
||||||
DPRINT("MmAccessFault(Mode %d, Address %x)\n", Mode, Address);
|
DPRINT("MmAccessFault(Mode %d, Address %x)\n", Mode, Address);
|
||||||
|
|
||||||
if (KeGetCurrentIrql() >= DISPATCH_LEVEL)
|
if (KeGetCurrentIrql() >= DISPATCH_LEVEL)
|
||||||
{
|
{
|
||||||
DPRINT1("Page fault at high IRQL was %u\n", KeGetCurrentIrql());
|
DPRINT1("Page fault at high IRQL was %u\n", KeGetCurrentIrql());
|
||||||
return(STATUS_UNSUCCESSFUL);
|
return(STATUS_UNSUCCESSFUL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Find the memory area for the faulting address
|
* Find the memory area for the faulting address
|
||||||
*/
|
*/
|
||||||
if (Address >= (ULONG_PTR)MmSystemRangeStart)
|
if (Address >= (ULONG_PTR)MmSystemRangeStart)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Check permissions
|
* Check permissions
|
||||||
*/
|
*/
|
||||||
if (Mode != KernelMode)
|
if (Mode != KernelMode)
|
||||||
{
|
{
|
||||||
DPRINT1("MmAccessFault(Mode %d, Address %x)\n", Mode, Address);
|
DPRINT1("MmAccessFault(Mode %d, Address %x)\n", Mode, Address);
|
||||||
return(STATUS_ACCESS_VIOLATION);
|
return(STATUS_ACCESS_VIOLATION);
|
||||||
}
|
}
|
||||||
AddressSpace = MmGetKernelAddressSpace();
|
AddressSpace = MmGetKernelAddressSpace();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
AddressSpace = &PsGetCurrentProcess()->Vm;
|
AddressSpace = &PsGetCurrentProcess()->Vm;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!FromMdl)
|
if (!FromMdl)
|
||||||
{
|
{
|
||||||
MmLockAddressSpace(AddressSpace);
|
MmLockAddressSpace(AddressSpace);
|
||||||
}
|
}
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, (PVOID)Address);
|
MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, (PVOID)Address);
|
||||||
if (MemoryArea == NULL || MemoryArea->DeleteInProgress)
|
if (MemoryArea == NULL || MemoryArea->DeleteInProgress)
|
||||||
{
|
{
|
||||||
if (!FromMdl)
|
if (!FromMdl)
|
||||||
{
|
{
|
||||||
MmUnlockAddressSpace(AddressSpace);
|
MmUnlockAddressSpace(AddressSpace);
|
||||||
}
|
}
|
||||||
return (STATUS_ACCESS_VIOLATION);
|
return (STATUS_ACCESS_VIOLATION);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (MemoryArea->Type)
|
switch (MemoryArea->Type)
|
||||||
{
|
{
|
||||||
case MEMORY_AREA_SECTION_VIEW:
|
case MEMORY_AREA_SECTION_VIEW:
|
||||||
Status = MmAccessFaultSectionView(AddressSpace,
|
Status = MmAccessFaultSectionView(AddressSpace,
|
||||||
MemoryArea,
|
MemoryArea,
|
||||||
(PVOID)Address);
|
(PVOID)Address);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MEMORY_AREA_CACHE:
|
case MEMORY_AREA_CACHE:
|
||||||
// This code locks for itself to keep from having to break a lock
|
// This code locks for itself to keep from having to break a lock
|
||||||
// passed in.
|
// passed in.
|
||||||
if (!FromMdl)
|
if (!FromMdl)
|
||||||
MmUnlockAddressSpace(AddressSpace);
|
MmUnlockAddressSpace(AddressSpace);
|
||||||
Status = MmAccessFaultCacheSection(Mode, Address, FromMdl);
|
Status = MmAccessFaultCacheSection(Mode, Address, FromMdl);
|
||||||
if (!FromMdl)
|
if (!FromMdl)
|
||||||
MmLockAddressSpace(AddressSpace);
|
MmLockAddressSpace(AddressSpace);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
Status = STATUS_ACCESS_VIOLATION;
|
Status = STATUS_ACCESS_VIOLATION;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while (Status == STATUS_MM_RESTART_OPERATION);
|
while (Status == STATUS_MM_RESTART_OPERATION);
|
||||||
|
|
||||||
DPRINT("Completed page fault handling\n");
|
DPRINT("Completed page fault handling\n");
|
||||||
if (!FromMdl)
|
if (!FromMdl)
|
||||||
{
|
{
|
||||||
MmUnlockAddressSpace(AddressSpace);
|
MmUnlockAddressSpace(AddressSpace);
|
||||||
}
|
}
|
||||||
return(Status);
|
return(Status);
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
MmNotPresentFault(KPROCESSOR_MODE Mode,
|
MmNotPresentFault(KPROCESSOR_MODE Mode,
|
||||||
ULONG_PTR Address,
|
ULONG_PTR Address,
|
||||||
BOOLEAN FromMdl)
|
BOOLEAN FromMdl)
|
||||||
{
|
{
|
||||||
PMMSUPPORT AddressSpace;
|
PMMSUPPORT AddressSpace;
|
||||||
MEMORY_AREA* MemoryArea;
|
MEMORY_AREA* MemoryArea;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
|
||||||
DPRINT("MmNotPresentFault(Mode %d, Address %x)\n", Mode, Address);
|
DPRINT("MmNotPresentFault(Mode %d, Address %x)\n", Mode, Address);
|
||||||
|
|
||||||
if (KeGetCurrentIrql() >= DISPATCH_LEVEL)
|
if (KeGetCurrentIrql() >= DISPATCH_LEVEL)
|
||||||
{
|
{
|
||||||
DPRINT1("Page fault at high IRQL was %u, address %x\n", KeGetCurrentIrql(), Address);
|
DPRINT1("Page fault at high IRQL was %u, address %x\n", KeGetCurrentIrql(), Address);
|
||||||
return(STATUS_UNSUCCESSFUL);
|
return(STATUS_UNSUCCESSFUL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Find the memory area for the faulting address
|
* Find the memory area for the faulting address
|
||||||
*/
|
*/
|
||||||
if (Address >= (ULONG_PTR)MmSystemRangeStart)
|
if (Address >= (ULONG_PTR)MmSystemRangeStart)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Check permissions
|
* Check permissions
|
||||||
*/
|
*/
|
||||||
if (Mode != KernelMode)
|
if (Mode != KernelMode)
|
||||||
{
|
{
|
||||||
DPRINT1("Address: %x\n", Address);
|
DPRINT1("Address: %x\n", Address);
|
||||||
return(STATUS_ACCESS_VIOLATION);
|
return(STATUS_ACCESS_VIOLATION);
|
||||||
}
|
}
|
||||||
AddressSpace = MmGetKernelAddressSpace();
|
AddressSpace = MmGetKernelAddressSpace();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
AddressSpace = &PsGetCurrentProcess()->Vm;
|
AddressSpace = &PsGetCurrentProcess()->Vm;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!FromMdl)
|
if (!FromMdl)
|
||||||
{
|
{
|
||||||
MmLockAddressSpace(AddressSpace);
|
MmLockAddressSpace(AddressSpace);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Call the memory area specific fault handler
|
* Call the memory area specific fault handler
|
||||||
*/
|
*/
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, (PVOID)Address);
|
MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, (PVOID)Address);
|
||||||
if (MemoryArea == NULL || MemoryArea->DeleteInProgress)
|
if (MemoryArea == NULL || MemoryArea->DeleteInProgress)
|
||||||
{
|
{
|
||||||
if (!FromMdl)
|
if (!FromMdl)
|
||||||
{
|
{
|
||||||
MmUnlockAddressSpace(AddressSpace);
|
MmUnlockAddressSpace(AddressSpace);
|
||||||
}
|
}
|
||||||
return (STATUS_ACCESS_VIOLATION);
|
return (STATUS_ACCESS_VIOLATION);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (MemoryArea->Type)
|
switch (MemoryArea->Type)
|
||||||
{
|
{
|
||||||
case MEMORY_AREA_SECTION_VIEW:
|
case MEMORY_AREA_SECTION_VIEW:
|
||||||
Status = MmNotPresentFaultSectionView(AddressSpace,
|
Status = MmNotPresentFaultSectionView(AddressSpace,
|
||||||
MemoryArea,
|
MemoryArea,
|
||||||
(PVOID)Address,
|
(PVOID)Address,
|
||||||
FromMdl);
|
FromMdl);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MEMORY_AREA_CACHE:
|
case MEMORY_AREA_CACHE:
|
||||||
// This code locks for itself to keep from having to break a lock
|
// This code locks for itself to keep from having to break a lock
|
||||||
// passed in.
|
// passed in.
|
||||||
if (!FromMdl)
|
if (!FromMdl)
|
||||||
MmUnlockAddressSpace(AddressSpace);
|
MmUnlockAddressSpace(AddressSpace);
|
||||||
Status = MmNotPresentFaultCacheSection(Mode, Address, FromMdl);
|
Status = MmNotPresentFaultCacheSection(Mode, Address, FromMdl);
|
||||||
if (!FromMdl)
|
if (!FromMdl)
|
||||||
MmLockAddressSpace(AddressSpace);
|
MmLockAddressSpace(AddressSpace);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
Status = STATUS_ACCESS_VIOLATION;
|
Status = STATUS_ACCESS_VIOLATION;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while (Status == STATUS_MM_RESTART_OPERATION);
|
while (Status == STATUS_MM_RESTART_OPERATION);
|
||||||
|
|
||||||
DPRINT("Completed page fault handling\n");
|
DPRINT("Completed page fault handling\n");
|
||||||
if (!FromMdl)
|
if (!FromMdl)
|
||||||
{
|
{
|
||||||
MmUnlockAddressSpace(AddressSpace);
|
MmUnlockAddressSpace(AddressSpace);
|
||||||
}
|
}
|
||||||
return(Status);
|
return(Status);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern BOOLEAN Mmi386MakeKernelPageTableGlobal(PVOID Address);
|
extern BOOLEAN Mmi386MakeKernelPageTableGlobal(PVOID Address);
|
||||||
|
@ -235,8 +235,8 @@ MmAccessFault(IN BOOLEAN StoreInstruction,
|
||||||
|
|
||||||
/* Is this an ARM3 memory area, or is there no address space yet? */
|
/* Is this an ARM3 memory area, or is there no address space yet? */
|
||||||
if (((MemoryArea) && (MemoryArea->Type == MEMORY_AREA_OWNED_BY_ARM3)) ||
|
if (((MemoryArea) && (MemoryArea->Type == MEMORY_AREA_OWNED_BY_ARM3)) ||
|
||||||
(!(MemoryArea) && ((ULONG_PTR)Address >= (ULONG_PTR)MmPagedPoolStart)) ||
|
(!(MemoryArea) && ((ULONG_PTR)Address >= (ULONG_PTR)MmPagedPoolStart)) ||
|
||||||
(!MmGetKernelAddressSpace()))
|
(!MmGetKernelAddressSpace()))
|
||||||
{
|
{
|
||||||
/* This is an ARM3 fault */
|
/* This is an ARM3 fault */
|
||||||
DPRINT("ARM3 fault %p\n", MemoryArea);
|
DPRINT("ARM3 fault %p\n", MemoryArea);
|
||||||
|
|
|
@ -299,36 +299,36 @@ VOID
|
||||||
NTAPI
|
NTAPI
|
||||||
MmMpwThreadMain(PVOID Parameter)
|
MmMpwThreadMain(PVOID Parameter)
|
||||||
{
|
{
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
ULONG PagesWritten;
|
ULONG PagesWritten;
|
||||||
LARGE_INTEGER Timeout;
|
LARGE_INTEGER Timeout;
|
||||||
|
|
||||||
UNREFERENCED_PARAMETER(Parameter);
|
UNREFERENCED_PARAMETER(Parameter);
|
||||||
|
|
||||||
Timeout.QuadPart = -50000000;
|
Timeout.QuadPart = -50000000;
|
||||||
|
|
||||||
for(;;)
|
for(;;)
|
||||||
{
|
{
|
||||||
Status = KeWaitForSingleObject(&MpwThreadEvent,
|
Status = KeWaitForSingleObject(&MpwThreadEvent,
|
||||||
0,
|
0,
|
||||||
KernelMode,
|
KernelMode,
|
||||||
FALSE,
|
FALSE,
|
||||||
&Timeout);
|
&Timeout);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
DbgPrint("MpwThread: Wait failed\n");
|
DbgPrint("MpwThread: Wait failed\n");
|
||||||
KeBugCheck(MEMORY_MANAGEMENT);
|
KeBugCheck(MEMORY_MANAGEMENT);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
PagesWritten = 0;
|
PagesWritten = 0;
|
||||||
|
|
||||||
#ifndef NEWCC
|
#ifndef NEWCC
|
||||||
// XXX arty -- we flush when evicting pages or destorying cache
|
// XXX arty -- we flush when evicting pages or destorying cache
|
||||||
// sections.
|
// sections.
|
||||||
CcRosFlushDirtyPages(128, &PagesWritten, FALSE);
|
CcRosFlushDirtyPages(128, &PagesWritten, FALSE);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
|
@ -336,31 +336,31 @@ NTAPI
|
||||||
INIT_FUNCTION
|
INIT_FUNCTION
|
||||||
MmInitMpwThread(VOID)
|
MmInitMpwThread(VOID)
|
||||||
{
|
{
|
||||||
KPRIORITY Priority;
|
KPRIORITY Priority;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
CLIENT_ID MpwThreadId;
|
CLIENT_ID MpwThreadId;
|
||||||
|
|
||||||
KeInitializeEvent(&MpwThreadEvent, SynchronizationEvent, FALSE);
|
KeInitializeEvent(&MpwThreadEvent, SynchronizationEvent, FALSE);
|
||||||
|
|
||||||
Status = PsCreateSystemThread(&MpwThreadHandle,
|
Status = PsCreateSystemThread(&MpwThreadHandle,
|
||||||
THREAD_ALL_ACCESS,
|
THREAD_ALL_ACCESS,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
&MpwThreadId,
|
&MpwThreadId,
|
||||||
MmMpwThreadMain,
|
MmMpwThreadMain,
|
||||||
NULL);
|
NULL);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
return(Status);
|
return(Status);
|
||||||
}
|
}
|
||||||
|
|
||||||
Priority = 27;
|
Priority = 27;
|
||||||
NtSetInformationThread(MpwThreadHandle,
|
NtSetInformationThread(MpwThreadHandle,
|
||||||
ThreadPriority,
|
ThreadPriority,
|
||||||
&Priority,
|
&Priority,
|
||||||
sizeof(Priority));
|
sizeof(Priority));
|
||||||
|
|
||||||
return(STATUS_SUCCESS);
|
return(STATUS_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
|
@ -430,8 +430,8 @@ MmInitSystem(IN ULONG Phase,
|
||||||
// by the fault handler.
|
// by the fault handler.
|
||||||
//
|
//
|
||||||
MmSharedUserDataPte = ExAllocatePoolWithTag(PagedPool,
|
MmSharedUserDataPte = ExAllocatePoolWithTag(PagedPool,
|
||||||
sizeof(MMPTE),
|
sizeof(MMPTE),
|
||||||
' mM');
|
' mM');
|
||||||
if (!MmSharedUserDataPte) return FALSE;
|
if (!MmSharedUserDataPte) return FALSE;
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -22,12 +22,12 @@ InsertAfterEntry(PLIST_ENTRY Previous,
|
||||||
* FUNCTION: Insert a list entry after another entry in the list
|
* FUNCTION: Insert a list entry after another entry in the list
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
Previous->Flink->Blink = Entry;
|
Previous->Flink->Blink = Entry;
|
||||||
|
|
||||||
Entry->Flink = Previous->Flink;
|
Entry->Flink = Previous->Flink;
|
||||||
Entry->Blink = Previous;
|
Entry->Blink = Previous;
|
||||||
|
|
||||||
Previous->Flink = Entry;
|
Previous->Flink = Entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PMM_REGION
|
static PMM_REGION
|
||||||
|
@ -36,71 +36,71 @@ MmSplitRegion(PMM_REGION InitialRegion, PVOID InitialBaseAddress,
|
||||||
ULONG NewProtect, PMMSUPPORT AddressSpace,
|
ULONG NewProtect, PMMSUPPORT AddressSpace,
|
||||||
PMM_ALTER_REGION_FUNC AlterFunc)
|
PMM_ALTER_REGION_FUNC AlterFunc)
|
||||||
{
|
{
|
||||||
PMM_REGION NewRegion1;
|
PMM_REGION NewRegion1;
|
||||||
PMM_REGION NewRegion2;
|
PMM_REGION NewRegion2;
|
||||||
SIZE_T InternalLength;
|
SIZE_T InternalLength;
|
||||||
|
|
||||||
/* Allocate this in front otherwise the failure case is too difficult. */
|
/* Allocate this in front otherwise the failure case is too difficult. */
|
||||||
NewRegion2 = ExAllocatePoolWithTag(NonPagedPool, sizeof(MM_REGION),
|
NewRegion2 = ExAllocatePoolWithTag(NonPagedPool, sizeof(MM_REGION),
|
||||||
TAG_MM_REGION);
|
TAG_MM_REGION);
|
||||||
if (NewRegion2 == NULL)
|
if (NewRegion2 == NULL)
|
||||||
{
|
{
|
||||||
return(NULL);
|
return(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create the new region. */
|
/* Create the new region. */
|
||||||
NewRegion1 = ExAllocatePoolWithTag(NonPagedPool, sizeof(MM_REGION),
|
NewRegion1 = ExAllocatePoolWithTag(NonPagedPool, sizeof(MM_REGION),
|
||||||
TAG_MM_REGION);
|
TAG_MM_REGION);
|
||||||
if (NewRegion1 == NULL)
|
if (NewRegion1 == NULL)
|
||||||
{
|
{
|
||||||
ExFreePoolWithTag(NewRegion2, TAG_MM_REGION);
|
ExFreePoolWithTag(NewRegion2, TAG_MM_REGION);
|
||||||
return(NULL);
|
return(NULL);
|
||||||
}
|
}
|
||||||
NewRegion1->Type = NewType;
|
NewRegion1->Type = NewType;
|
||||||
NewRegion1->Protect = NewProtect;
|
NewRegion1->Protect = NewProtect;
|
||||||
InternalLength = ((char*)InitialBaseAddress + InitialRegion->Length) - (char*)StartAddress;
|
InternalLength = ((char*)InitialBaseAddress + InitialRegion->Length) - (char*)StartAddress;
|
||||||
InternalLength = min(InternalLength, Length);
|
InternalLength = min(InternalLength, Length);
|
||||||
NewRegion1->Length = InternalLength;
|
NewRegion1->Length = InternalLength;
|
||||||
InsertAfterEntry(&InitialRegion->RegionListEntry,
|
InsertAfterEntry(&InitialRegion->RegionListEntry,
|
||||||
&NewRegion1->RegionListEntry);
|
&NewRegion1->RegionListEntry);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Call our helper function to do the changes on the addresses contained
|
* Call our helper function to do the changes on the addresses contained
|
||||||
* in the initial region.
|
* in the initial region.
|
||||||
*/
|
*/
|
||||||
AlterFunc(AddressSpace, StartAddress, InternalLength, InitialRegion->Type,
|
AlterFunc(AddressSpace, StartAddress, InternalLength, InitialRegion->Type,
|
||||||
InitialRegion->Protect, NewType, NewProtect);
|
InitialRegion->Protect, NewType, NewProtect);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If necessary create a new region for the portion of the initial region
|
* If necessary create a new region for the portion of the initial region
|
||||||
* beyond the range of addresses to alter.
|
* beyond the range of addresses to alter.
|
||||||
*/
|
*/
|
||||||
if (((char*)InitialBaseAddress + InitialRegion->Length) > ((char*)StartAddress + Length))
|
if (((char*)InitialBaseAddress + InitialRegion->Length) > ((char*)StartAddress + Length))
|
||||||
{
|
{
|
||||||
NewRegion2->Type = InitialRegion->Type;
|
NewRegion2->Type = InitialRegion->Type;
|
||||||
NewRegion2->Protect = InitialRegion->Protect;
|
NewRegion2->Protect = InitialRegion->Protect;
|
||||||
NewRegion2->Length = ((char*)InitialBaseAddress + InitialRegion->Length) -
|
NewRegion2->Length = ((char*)InitialBaseAddress + InitialRegion->Length) -
|
||||||
((char*)StartAddress + Length);
|
((char*)StartAddress + Length);
|
||||||
InsertAfterEntry(&NewRegion1->RegionListEntry,
|
InsertAfterEntry(&NewRegion1->RegionListEntry,
|
||||||
&NewRegion2->RegionListEntry);
|
&NewRegion2->RegionListEntry);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ExFreePoolWithTag(NewRegion2, TAG_MM_REGION);
|
ExFreePoolWithTag(NewRegion2, TAG_MM_REGION);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Either remove or shrink the initial region. */
|
/* Either remove or shrink the initial region. */
|
||||||
if (InitialBaseAddress == StartAddress)
|
if (InitialBaseAddress == StartAddress)
|
||||||
{
|
{
|
||||||
RemoveEntryList(&InitialRegion->RegionListEntry);
|
RemoveEntryList(&InitialRegion->RegionListEntry);
|
||||||
ExFreePoolWithTag(InitialRegion, TAG_MM_REGION);
|
ExFreePoolWithTag(InitialRegion, TAG_MM_REGION);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
InitialRegion->Length = (char*)StartAddress - (char*)InitialBaseAddress;
|
InitialRegion->Length = (char*)StartAddress - (char*)InitialBaseAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
return(NewRegion1);
|
return(NewRegion1);
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
|
@ -109,129 +109,129 @@ MmAlterRegion(PMMSUPPORT AddressSpace, PVOID BaseAddress,
|
||||||
PLIST_ENTRY RegionListHead, PVOID StartAddress, SIZE_T Length,
|
PLIST_ENTRY RegionListHead, PVOID StartAddress, SIZE_T Length,
|
||||||
ULONG NewType, ULONG NewProtect, PMM_ALTER_REGION_FUNC AlterFunc)
|
ULONG NewType, ULONG NewProtect, PMM_ALTER_REGION_FUNC AlterFunc)
|
||||||
{
|
{
|
||||||
PMM_REGION InitialRegion;
|
PMM_REGION InitialRegion;
|
||||||
PVOID InitialBaseAddress = NULL;
|
PVOID InitialBaseAddress = NULL;
|
||||||
PMM_REGION NewRegion;
|
PMM_REGION NewRegion;
|
||||||
PLIST_ENTRY CurrentEntry;
|
PLIST_ENTRY CurrentEntry;
|
||||||
PMM_REGION CurrentRegion = NULL;
|
PMM_REGION CurrentRegion = NULL;
|
||||||
PVOID CurrentBaseAddress;
|
PVOID CurrentBaseAddress;
|
||||||
SIZE_T RemainingLength;
|
SIZE_T RemainingLength;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Find the first region containing part of the range of addresses to
|
* Find the first region containing part of the range of addresses to
|
||||||
* be altered.
|
* be altered.
|
||||||
*/
|
*/
|
||||||
InitialRegion = MmFindRegion(BaseAddress, RegionListHead, StartAddress,
|
InitialRegion = MmFindRegion(BaseAddress, RegionListHead, StartAddress,
|
||||||
&InitialBaseAddress);
|
&InitialBaseAddress);
|
||||||
/*
|
/*
|
||||||
* If necessary then split the region into the affected and unaffected parts.
|
* If necessary then split the region into the affected and unaffected parts.
|
||||||
*/
|
*/
|
||||||
if (InitialRegion->Type != NewType || InitialRegion->Protect != NewProtect)
|
if (InitialRegion->Type != NewType || InitialRegion->Protect != NewProtect)
|
||||||
{
|
{
|
||||||
NewRegion = MmSplitRegion(InitialRegion, InitialBaseAddress,
|
NewRegion = MmSplitRegion(InitialRegion, InitialBaseAddress,
|
||||||
StartAddress, Length, NewType, NewProtect,
|
StartAddress, Length, NewType, NewProtect,
|
||||||
AddressSpace, AlterFunc);
|
AddressSpace, AlterFunc);
|
||||||
if (NewRegion == NULL)
|
if (NewRegion == NULL)
|
||||||
{
|
{
|
||||||
return(STATUS_NO_MEMORY);
|
return(STATUS_NO_MEMORY);
|
||||||
}
|
}
|
||||||
if(NewRegion->Length < Length)
|
if(NewRegion->Length < Length)
|
||||||
RemainingLength = Length - NewRegion->Length;
|
RemainingLength = Length - NewRegion->Length;
|
||||||
else
|
else
|
||||||
RemainingLength = 0;
|
RemainingLength = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
NewRegion = InitialRegion;
|
NewRegion = InitialRegion;
|
||||||
if(((ULONG_PTR)InitialBaseAddress + NewRegion->Length) <
|
if(((ULONG_PTR)InitialBaseAddress + NewRegion->Length) <
|
||||||
((ULONG_PTR)StartAddress + Length))
|
((ULONG_PTR)StartAddress + Length))
|
||||||
RemainingLength = ((ULONG_PTR)StartAddress + Length) - ((ULONG_PTR)InitialBaseAddress + NewRegion->Length);
|
RemainingLength = ((ULONG_PTR)StartAddress + Length) - ((ULONG_PTR)InitialBaseAddress + NewRegion->Length);
|
||||||
else
|
else
|
||||||
RemainingLength = 0;
|
RemainingLength = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Free any complete regions that are containing in the range of addresses
|
* Free any complete regions that are containing in the range of addresses
|
||||||
* and call the helper function to actually do the changes.
|
* and call the helper function to actually do the changes.
|
||||||
*/
|
*/
|
||||||
CurrentEntry = NewRegion->RegionListEntry.Flink;
|
CurrentEntry = NewRegion->RegionListEntry.Flink;
|
||||||
CurrentRegion = CONTAINING_RECORD(CurrentEntry, MM_REGION,
|
CurrentRegion = CONTAINING_RECORD(CurrentEntry, MM_REGION,
|
||||||
RegionListEntry);
|
RegionListEntry);
|
||||||
CurrentBaseAddress = (char*)StartAddress + NewRegion->Length;
|
CurrentBaseAddress = (char*)StartAddress + NewRegion->Length;
|
||||||
while (RemainingLength > 0 && CurrentRegion->Length <= RemainingLength &&
|
while (RemainingLength > 0 && CurrentRegion->Length <= RemainingLength &&
|
||||||
CurrentEntry != RegionListHead)
|
CurrentEntry != RegionListHead)
|
||||||
{
|
{
|
||||||
if (CurrentRegion->Type != NewType ||
|
if (CurrentRegion->Type != NewType ||
|
||||||
CurrentRegion->Protect != NewProtect)
|
CurrentRegion->Protect != NewProtect)
|
||||||
{
|
{
|
||||||
AlterFunc(AddressSpace, CurrentBaseAddress, CurrentRegion->Length,
|
AlterFunc(AddressSpace, CurrentBaseAddress, CurrentRegion->Length,
|
||||||
CurrentRegion->Type, CurrentRegion->Protect,
|
CurrentRegion->Type, CurrentRegion->Protect,
|
||||||
NewType, NewProtect);
|
NewType, NewProtect);
|
||||||
}
|
}
|
||||||
|
|
||||||
CurrentBaseAddress = (PVOID)((ULONG_PTR)CurrentBaseAddress + CurrentRegion->Length);
|
CurrentBaseAddress = (PVOID)((ULONG_PTR)CurrentBaseAddress + CurrentRegion->Length);
|
||||||
NewRegion->Length += CurrentRegion->Length;
|
NewRegion->Length += CurrentRegion->Length;
|
||||||
RemainingLength -= CurrentRegion->Length;
|
RemainingLength -= CurrentRegion->Length;
|
||||||
CurrentEntry = CurrentEntry->Flink;
|
CurrentEntry = CurrentEntry->Flink;
|
||||||
RemoveEntryList(&CurrentRegion->RegionListEntry);
|
RemoveEntryList(&CurrentRegion->RegionListEntry);
|
||||||
ExFreePoolWithTag(CurrentRegion, TAG_MM_REGION);
|
ExFreePoolWithTag(CurrentRegion, TAG_MM_REGION);
|
||||||
CurrentRegion = CONTAINING_RECORD(CurrentEntry, MM_REGION,
|
CurrentRegion = CONTAINING_RECORD(CurrentEntry, MM_REGION,
|
||||||
RegionListEntry);
|
RegionListEntry);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Split any final region.
|
* Split any final region.
|
||||||
*/
|
*/
|
||||||
if (RemainingLength > 0 && CurrentEntry != RegionListHead)
|
if (RemainingLength > 0 && CurrentEntry != RegionListHead)
|
||||||
{
|
{
|
||||||
CurrentRegion = CONTAINING_RECORD(CurrentEntry, MM_REGION,
|
CurrentRegion = CONTAINING_RECORD(CurrentEntry, MM_REGION,
|
||||||
RegionListEntry);
|
RegionListEntry);
|
||||||
if (CurrentRegion->Type != NewType ||
|
if (CurrentRegion->Type != NewType ||
|
||||||
CurrentRegion->Protect != NewProtect)
|
CurrentRegion->Protect != NewProtect)
|
||||||
{
|
{
|
||||||
AlterFunc(AddressSpace, CurrentBaseAddress, RemainingLength,
|
AlterFunc(AddressSpace, CurrentBaseAddress, RemainingLength,
|
||||||
CurrentRegion->Type, CurrentRegion->Protect,
|
CurrentRegion->Type, CurrentRegion->Protect,
|
||||||
NewType, NewProtect);
|
NewType, NewProtect);
|
||||||
}
|
}
|
||||||
NewRegion->Length += RemainingLength;
|
NewRegion->Length += RemainingLength;
|
||||||
CurrentRegion->Length -= RemainingLength;
|
CurrentRegion->Length -= RemainingLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the region after the new region has the same type then merge them.
|
* If the region after the new region has the same type then merge them.
|
||||||
*/
|
*/
|
||||||
if (NewRegion->RegionListEntry.Flink != RegionListHead)
|
if (NewRegion->RegionListEntry.Flink != RegionListHead)
|
||||||
{
|
{
|
||||||
CurrentEntry = NewRegion->RegionListEntry.Flink;
|
CurrentEntry = NewRegion->RegionListEntry.Flink;
|
||||||
CurrentRegion = CONTAINING_RECORD(CurrentEntry, MM_REGION,
|
CurrentRegion = CONTAINING_RECORD(CurrentEntry, MM_REGION,
|
||||||
RegionListEntry);
|
RegionListEntry);
|
||||||
if (CurrentRegion->Type == NewRegion->Type &&
|
if (CurrentRegion->Type == NewRegion->Type &&
|
||||||
CurrentRegion->Protect == NewRegion->Protect)
|
CurrentRegion->Protect == NewRegion->Protect)
|
||||||
{
|
{
|
||||||
NewRegion->Length += CurrentRegion->Length;
|
NewRegion->Length += CurrentRegion->Length;
|
||||||
RemoveEntryList(&CurrentRegion->RegionListEntry);
|
RemoveEntryList(&CurrentRegion->RegionListEntry);
|
||||||
ExFreePoolWithTag(CurrentRegion, TAG_MM_REGION);
|
ExFreePoolWithTag(CurrentRegion, TAG_MM_REGION);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the region before the new region has the same type then merge them.
|
* If the region before the new region has the same type then merge them.
|
||||||
*/
|
*/
|
||||||
if (NewRegion->RegionListEntry.Blink != RegionListHead)
|
if (NewRegion->RegionListEntry.Blink != RegionListHead)
|
||||||
{
|
{
|
||||||
CurrentEntry = NewRegion->RegionListEntry.Blink;
|
CurrentEntry = NewRegion->RegionListEntry.Blink;
|
||||||
CurrentRegion = CONTAINING_RECORD(CurrentEntry, MM_REGION,
|
CurrentRegion = CONTAINING_RECORD(CurrentEntry, MM_REGION,
|
||||||
RegionListEntry);
|
RegionListEntry);
|
||||||
if (CurrentRegion->Type == NewRegion->Type &&
|
if (CurrentRegion->Type == NewRegion->Type &&
|
||||||
CurrentRegion->Protect == NewRegion->Protect)
|
CurrentRegion->Protect == NewRegion->Protect)
|
||||||
{
|
{
|
||||||
NewRegion->Length += CurrentRegion->Length;
|
NewRegion->Length += CurrentRegion->Length;
|
||||||
RemoveEntryList(&CurrentRegion->RegionListEntry);
|
RemoveEntryList(&CurrentRegion->RegionListEntry);
|
||||||
ExFreePoolWithTag(CurrentRegion, TAG_MM_REGION);
|
ExFreePoolWithTag(CurrentRegion, TAG_MM_REGION);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return(STATUS_SUCCESS);
|
return(STATUS_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
|
@ -239,17 +239,17 @@ NTAPI
|
||||||
MmInitializeRegion(PLIST_ENTRY RegionListHead, SIZE_T Length, ULONG Type,
|
MmInitializeRegion(PLIST_ENTRY RegionListHead, SIZE_T Length, ULONG Type,
|
||||||
ULONG Protect)
|
ULONG Protect)
|
||||||
{
|
{
|
||||||
PMM_REGION Region;
|
PMM_REGION Region;
|
||||||
|
|
||||||
Region = ExAllocatePoolWithTag(NonPagedPool, sizeof(MM_REGION),
|
Region = ExAllocatePoolWithTag(NonPagedPool, sizeof(MM_REGION),
|
||||||
TAG_MM_REGION);
|
TAG_MM_REGION);
|
||||||
if (!Region) return;
|
if (!Region) return;
|
||||||
|
|
||||||
Region->Type = Type;
|
Region->Type = Type;
|
||||||
Region->Protect = Protect;
|
Region->Protect = Protect;
|
||||||
Region->Length = Length;
|
Region->Length = Length;
|
||||||
InitializeListHead(RegionListHead);
|
InitializeListHead(RegionListHead);
|
||||||
InsertHeadList(RegionListHead, &Region->RegionListEntry);
|
InsertHeadList(RegionListHead, &Region->RegionListEntry);
|
||||||
}
|
}
|
||||||
|
|
||||||
PMM_REGION
|
PMM_REGION
|
||||||
|
@ -257,29 +257,29 @@ NTAPI
|
||||||
MmFindRegion(PVOID BaseAddress, PLIST_ENTRY RegionListHead, PVOID Address,
|
MmFindRegion(PVOID BaseAddress, PLIST_ENTRY RegionListHead, PVOID Address,
|
||||||
PVOID* RegionBaseAddress)
|
PVOID* RegionBaseAddress)
|
||||||
{
|
{
|
||||||
PLIST_ENTRY current_entry;
|
PLIST_ENTRY current_entry;
|
||||||
PMM_REGION current;
|
PMM_REGION current;
|
||||||
PVOID StartAddress = BaseAddress;
|
PVOID StartAddress = BaseAddress;
|
||||||
|
|
||||||
current_entry = RegionListHead->Flink;
|
current_entry = RegionListHead->Flink;
|
||||||
while (current_entry != RegionListHead)
|
while (current_entry != RegionListHead)
|
||||||
{
|
{
|
||||||
current = CONTAINING_RECORD(current_entry, MM_REGION, RegionListEntry);
|
current = CONTAINING_RECORD(current_entry, MM_REGION, RegionListEntry);
|
||||||
|
|
||||||
if (StartAddress <= Address &&
|
if (StartAddress <= Address &&
|
||||||
((char*)StartAddress + current->Length) > (char*)Address)
|
((char*)StartAddress + current->Length) > (char*)Address)
|
||||||
{
|
{
|
||||||
if (RegionBaseAddress != NULL)
|
if (RegionBaseAddress != NULL)
|
||||||
{
|
{
|
||||||
*RegionBaseAddress = StartAddress;
|
*RegionBaseAddress = StartAddress;
|
||||||
}
|
}
|
||||||
return(current);
|
return(current);
|
||||||
}
|
}
|
||||||
|
|
||||||
current_entry = current_entry->Flink;
|
current_entry = current_entry->Flink;
|
||||||
|
|
||||||
StartAddress = (PVOID)((ULONG_PTR)StartAddress + current->Length);
|
StartAddress = (PVOID)((ULONG_PTR)StartAddress + current->Length);
|
||||||
|
|
||||||
}
|
}
|
||||||
return(NULL);
|
return(NULL);
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,224 +42,224 @@ INIT_FUNCTION
|
||||||
NTAPI
|
NTAPI
|
||||||
MmInitializeRmapList(VOID)
|
MmInitializeRmapList(VOID)
|
||||||
{
|
{
|
||||||
ExInitializeFastMutex(&RmapListLock);
|
ExInitializeFastMutex(&RmapListLock);
|
||||||
ExInitializeNPagedLookasideList (&RmapLookasideList,
|
ExInitializeNPagedLookasideList (&RmapLookasideList,
|
||||||
NULL,
|
NULL,
|
||||||
RmapListFree,
|
RmapListFree,
|
||||||
0,
|
0,
|
||||||
sizeof(MM_RMAP_ENTRY),
|
sizeof(MM_RMAP_ENTRY),
|
||||||
TAG_RMAP,
|
TAG_RMAP,
|
||||||
50);
|
50);
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
MmPageOutPhysicalAddress(PFN_NUMBER Page)
|
MmPageOutPhysicalAddress(PFN_NUMBER Page)
|
||||||
{
|
{
|
||||||
PMM_RMAP_ENTRY entry;
|
PMM_RMAP_ENTRY entry;
|
||||||
PMEMORY_AREA MemoryArea;
|
PMEMORY_AREA MemoryArea;
|
||||||
PMMSUPPORT AddressSpace;
|
PMMSUPPORT AddressSpace;
|
||||||
ULONG Type;
|
ULONG Type;
|
||||||
PVOID Address;
|
PVOID Address;
|
||||||
PEPROCESS Process;
|
PEPROCESS Process;
|
||||||
ULONGLONG Offset;
|
ULONGLONG Offset;
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
|
|
||||||
ExAcquireFastMutex(&RmapListLock);
|
ExAcquireFastMutex(&RmapListLock);
|
||||||
entry = MmGetRmapListHeadPage(Page);
|
entry = MmGetRmapListHeadPage(Page);
|
||||||
|
|
||||||
#ifdef NEWCC
|
#ifdef NEWCC
|
||||||
// Special case for NEWCC: we can have a page that's only in a segment
|
// Special case for NEWCC: we can have a page that's only in a segment
|
||||||
// page table
|
// page table
|
||||||
if (entry && RMAP_IS_SEGMENT(entry->Address) && entry->Next == NULL)
|
if (entry && RMAP_IS_SEGMENT(entry->Address) && entry->Next == NULL)
|
||||||
{
|
{
|
||||||
/* NEWCC does locking itself */
|
/* NEWCC does locking itself */
|
||||||
ExReleaseFastMutex(&RmapListLock);
|
ExReleaseFastMutex(&RmapListLock);
|
||||||
return MmpPageOutPhysicalAddress(Page);
|
return MmpPageOutPhysicalAddress(Page);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
while (entry && RMAP_IS_SEGMENT(entry->Address))
|
while (entry && RMAP_IS_SEGMENT(entry->Address))
|
||||||
entry = entry->Next;
|
entry = entry->Next;
|
||||||
|
|
||||||
if (entry == NULL)
|
if (entry == NULL)
|
||||||
{
|
{
|
||||||
ExReleaseFastMutex(&RmapListLock);
|
ExReleaseFastMutex(&RmapListLock);
|
||||||
return(STATUS_UNSUCCESSFUL);
|
return(STATUS_UNSUCCESSFUL);
|
||||||
}
|
}
|
||||||
|
|
||||||
Process = entry->Process;
|
Process = entry->Process;
|
||||||
|
|
||||||
Address = entry->Address;
|
Address = entry->Address;
|
||||||
|
|
||||||
if ((((ULONG_PTR)Address) & 0xFFF) != 0)
|
if ((((ULONG_PTR)Address) & 0xFFF) != 0)
|
||||||
{
|
{
|
||||||
KeBugCheck(MEMORY_MANAGEMENT);
|
KeBugCheck(MEMORY_MANAGEMENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Address < MmSystemRangeStart)
|
if (Address < MmSystemRangeStart)
|
||||||
{
|
{
|
||||||
if (!ExAcquireRundownProtection(&Process->RundownProtect))
|
if (!ExAcquireRundownProtection(&Process->RundownProtect))
|
||||||
{
|
{
|
||||||
ExReleaseFastMutex(&RmapListLock);
|
ExReleaseFastMutex(&RmapListLock);
|
||||||
return STATUS_PROCESS_IS_TERMINATING;
|
return STATUS_PROCESS_IS_TERMINATING;
|
||||||
}
|
}
|
||||||
|
|
||||||
Status = ObReferenceObjectByPointer(Process, PROCESS_ALL_ACCESS, NULL, KernelMode);
|
Status = ObReferenceObjectByPointer(Process, PROCESS_ALL_ACCESS, NULL, KernelMode);
|
||||||
ExReleaseFastMutex(&RmapListLock);
|
ExReleaseFastMutex(&RmapListLock);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
ExReleaseRundownProtection(&Process->RundownProtect);
|
ExReleaseRundownProtection(&Process->RundownProtect);
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
AddressSpace = &Process->Vm;
|
AddressSpace = &Process->Vm;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ExReleaseFastMutex(&RmapListLock);
|
ExReleaseFastMutex(&RmapListLock);
|
||||||
AddressSpace = MmGetKernelAddressSpace();
|
AddressSpace = MmGetKernelAddressSpace();
|
||||||
}
|
}
|
||||||
|
|
||||||
MmLockAddressSpace(AddressSpace);
|
MmLockAddressSpace(AddressSpace);
|
||||||
MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, Address);
|
MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, Address);
|
||||||
if (MemoryArea == NULL || MemoryArea->DeleteInProgress)
|
if (MemoryArea == NULL || MemoryArea->DeleteInProgress)
|
||||||
{
|
{
|
||||||
MmUnlockAddressSpace(AddressSpace);
|
MmUnlockAddressSpace(AddressSpace);
|
||||||
if (Address < MmSystemRangeStart)
|
if (Address < MmSystemRangeStart)
|
||||||
{
|
{
|
||||||
ExReleaseRundownProtection(&Process->RundownProtect);
|
|
||||||
ObDereferenceObject(Process);
|
|
||||||
}
|
|
||||||
return(STATUS_UNSUCCESSFUL);
|
|
||||||
}
|
|
||||||
Type = MemoryArea->Type;
|
|
||||||
if (Type == MEMORY_AREA_SECTION_VIEW)
|
|
||||||
{
|
|
||||||
ULONG_PTR Entry;
|
|
||||||
Offset = MemoryArea->Data.SectionData.ViewOffset.QuadPart +
|
|
||||||
((ULONG_PTR)Address - (ULONG_PTR)MemoryArea->StartingAddress);
|
|
||||||
|
|
||||||
MmLockSectionSegment(MemoryArea->Data.SectionData.Segment);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Get or create a pageop
|
|
||||||
*/
|
|
||||||
Entry = MmGetPageEntrySectionSegment(MemoryArea->Data.SectionData.Segment,
|
|
||||||
(PLARGE_INTEGER)&Offset);
|
|
||||||
if (Entry && IS_SWAP_FROM_SSE(Entry) && SWAPENTRY_FROM_SSE(Entry) == MM_WAIT_ENTRY)
|
|
||||||
{
|
|
||||||
MmUnlockSectionSegment(MemoryArea->Data.SectionData.Segment);
|
|
||||||
MmUnlockAddressSpace(AddressSpace);
|
|
||||||
if (Address < MmSystemRangeStart)
|
|
||||||
{
|
|
||||||
ExReleaseRundownProtection(&Process->RundownProtect);
|
ExReleaseRundownProtection(&Process->RundownProtect);
|
||||||
ObDereferenceObject(Process);
|
ObDereferenceObject(Process);
|
||||||
}
|
}
|
||||||
return(STATUS_UNSUCCESSFUL);
|
return(STATUS_UNSUCCESSFUL);
|
||||||
}
|
}
|
||||||
|
Type = MemoryArea->Type;
|
||||||
|
if (Type == MEMORY_AREA_SECTION_VIEW)
|
||||||
|
{
|
||||||
|
ULONG_PTR Entry;
|
||||||
|
Offset = MemoryArea->Data.SectionData.ViewOffset.QuadPart +
|
||||||
|
((ULONG_PTR)Address - (ULONG_PTR)MemoryArea->StartingAddress);
|
||||||
|
|
||||||
MmSetPageEntrySectionSegment(MemoryArea->Data.SectionData.Segment, (PLARGE_INTEGER)&Offset, MAKE_SWAP_SSE(MM_WAIT_ENTRY));
|
MmLockSectionSegment(MemoryArea->Data.SectionData.Segment);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Release locks now we have a page op.
|
* Get or create a pageop
|
||||||
*/
|
*/
|
||||||
MmUnlockSectionSegment(MemoryArea->Data.SectionData.Segment);
|
Entry = MmGetPageEntrySectionSegment(MemoryArea->Data.SectionData.Segment,
|
||||||
MmUnlockAddressSpace(AddressSpace);
|
(PLARGE_INTEGER)&Offset);
|
||||||
|
if (Entry && IS_SWAP_FROM_SSE(Entry) && SWAPENTRY_FROM_SSE(Entry) == MM_WAIT_ENTRY)
|
||||||
|
{
|
||||||
|
MmUnlockSectionSegment(MemoryArea->Data.SectionData.Segment);
|
||||||
|
MmUnlockAddressSpace(AddressSpace);
|
||||||
|
if (Address < MmSystemRangeStart)
|
||||||
|
{
|
||||||
|
ExReleaseRundownProtection(&Process->RundownProtect);
|
||||||
|
ObDereferenceObject(Process);
|
||||||
|
}
|
||||||
|
return(STATUS_UNSUCCESSFUL);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
MmSetPageEntrySectionSegment(MemoryArea->Data.SectionData.Segment, (PLARGE_INTEGER)&Offset, MAKE_SWAP_SSE(MM_WAIT_ENTRY));
|
||||||
* Do the actual page out work.
|
|
||||||
*/
|
|
||||||
Status = MmPageOutSectionView(AddressSpace, MemoryArea, Address, Entry);
|
|
||||||
}
|
|
||||||
else if (Type == MEMORY_AREA_CACHE)
|
|
||||||
{
|
|
||||||
/* NEWCC does locking itself */
|
|
||||||
MmUnlockAddressSpace(AddressSpace);
|
|
||||||
Status = MmpPageOutPhysicalAddress(Page);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
KeBugCheck(MEMORY_MANAGEMENT);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Address < MmSystemRangeStart)
|
/*
|
||||||
{
|
* Release locks now we have a page op.
|
||||||
ExReleaseRundownProtection(&Process->RundownProtect);
|
*/
|
||||||
ObDereferenceObject(Process);
|
MmUnlockSectionSegment(MemoryArea->Data.SectionData.Segment);
|
||||||
}
|
MmUnlockAddressSpace(AddressSpace);
|
||||||
return(Status);
|
|
||||||
|
/*
|
||||||
|
* Do the actual page out work.
|
||||||
|
*/
|
||||||
|
Status = MmPageOutSectionView(AddressSpace, MemoryArea, Address, Entry);
|
||||||
|
}
|
||||||
|
else if (Type == MEMORY_AREA_CACHE)
|
||||||
|
{
|
||||||
|
/* NEWCC does locking itself */
|
||||||
|
MmUnlockAddressSpace(AddressSpace);
|
||||||
|
Status = MmpPageOutPhysicalAddress(Page);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
KeBugCheck(MEMORY_MANAGEMENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Address < MmSystemRangeStart)
|
||||||
|
{
|
||||||
|
ExReleaseRundownProtection(&Process->RundownProtect);
|
||||||
|
ObDereferenceObject(Process);
|
||||||
|
}
|
||||||
|
return(Status);
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
NTAPI
|
NTAPI
|
||||||
MmSetCleanAllRmaps(PFN_NUMBER Page)
|
MmSetCleanAllRmaps(PFN_NUMBER Page)
|
||||||
{
|
{
|
||||||
PMM_RMAP_ENTRY current_entry;
|
PMM_RMAP_ENTRY current_entry;
|
||||||
|
|
||||||
ExAcquireFastMutex(&RmapListLock);
|
ExAcquireFastMutex(&RmapListLock);
|
||||||
current_entry = MmGetRmapListHeadPage(Page);
|
current_entry = MmGetRmapListHeadPage(Page);
|
||||||
if (current_entry == NULL)
|
if (current_entry == NULL)
|
||||||
{
|
{
|
||||||
DPRINT1("MmIsDirtyRmap: No rmaps.\n");
|
DPRINT1("MmIsDirtyRmap: No rmaps.\n");
|
||||||
KeBugCheck(MEMORY_MANAGEMENT);
|
KeBugCheck(MEMORY_MANAGEMENT);
|
||||||
}
|
}
|
||||||
while (current_entry != NULL)
|
while (current_entry != NULL)
|
||||||
{
|
{
|
||||||
if (!RMAP_IS_SEGMENT(current_entry->Address))
|
if (!RMAP_IS_SEGMENT(current_entry->Address))
|
||||||
MmSetCleanPage(current_entry->Process, current_entry->Address);
|
MmSetCleanPage(current_entry->Process, current_entry->Address);
|
||||||
current_entry = current_entry->Next;
|
current_entry = current_entry->Next;
|
||||||
}
|
}
|
||||||
ExReleaseFastMutex(&RmapListLock);
|
ExReleaseFastMutex(&RmapListLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
NTAPI
|
NTAPI
|
||||||
MmSetDirtyAllRmaps(PFN_NUMBER Page)
|
MmSetDirtyAllRmaps(PFN_NUMBER Page)
|
||||||
{
|
{
|
||||||
PMM_RMAP_ENTRY current_entry;
|
PMM_RMAP_ENTRY current_entry;
|
||||||
|
|
||||||
ExAcquireFastMutex(&RmapListLock);
|
ExAcquireFastMutex(&RmapListLock);
|
||||||
current_entry = MmGetRmapListHeadPage(Page);
|
current_entry = MmGetRmapListHeadPage(Page);
|
||||||
if (current_entry == NULL)
|
if (current_entry == NULL)
|
||||||
{
|
{
|
||||||
DPRINT1("MmIsDirtyRmap: No rmaps.\n");
|
DPRINT1("MmIsDirtyRmap: No rmaps.\n");
|
||||||
KeBugCheck(MEMORY_MANAGEMENT);
|
KeBugCheck(MEMORY_MANAGEMENT);
|
||||||
}
|
}
|
||||||
while (current_entry != NULL)
|
while (current_entry != NULL)
|
||||||
{
|
{
|
||||||
if (!RMAP_IS_SEGMENT(current_entry->Address))
|
if (!RMAP_IS_SEGMENT(current_entry->Address))
|
||||||
MmSetDirtyPage(current_entry->Process, current_entry->Address);
|
MmSetDirtyPage(current_entry->Process, current_entry->Address);
|
||||||
current_entry = current_entry->Next;
|
current_entry = current_entry->Next;
|
||||||
}
|
}
|
||||||
ExReleaseFastMutex(&RmapListLock);
|
ExReleaseFastMutex(&RmapListLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
NTAPI
|
NTAPI
|
||||||
MmIsDirtyPageRmap(PFN_NUMBER Page)
|
MmIsDirtyPageRmap(PFN_NUMBER Page)
|
||||||
{
|
{
|
||||||
PMM_RMAP_ENTRY current_entry;
|
PMM_RMAP_ENTRY current_entry;
|
||||||
|
|
||||||
ExAcquireFastMutex(&RmapListLock);
|
ExAcquireFastMutex(&RmapListLock);
|
||||||
current_entry = MmGetRmapListHeadPage(Page);
|
current_entry = MmGetRmapListHeadPage(Page);
|
||||||
if (current_entry == NULL)
|
if (current_entry == NULL)
|
||||||
{
|
{
|
||||||
ExReleaseFastMutex(&RmapListLock);
|
ExReleaseFastMutex(&RmapListLock);
|
||||||
return(FALSE);
|
return(FALSE);
|
||||||
}
|
}
|
||||||
while (current_entry != NULL)
|
while (current_entry != NULL)
|
||||||
{
|
{
|
||||||
if (
|
if (
|
||||||
!RMAP_IS_SEGMENT(current_entry->Address) &&
|
!RMAP_IS_SEGMENT(current_entry->Address) &&
|
||||||
MmIsDirtyPage(current_entry->Process, current_entry->Address))
|
MmIsDirtyPage(current_entry->Process, current_entry->Address))
|
||||||
{
|
{
|
||||||
ExReleaseFastMutex(&RmapListLock);
|
ExReleaseFastMutex(&RmapListLock);
|
||||||
return(TRUE);
|
return(TRUE);
|
||||||
}
|
}
|
||||||
current_entry = current_entry->Next;
|
current_entry = current_entry->Next;
|
||||||
}
|
}
|
||||||
ExReleaseFastMutex(&RmapListLock);
|
ExReleaseFastMutex(&RmapListLock);
|
||||||
return(FALSE);
|
return(FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
|
@ -267,75 +267,75 @@ NTAPI
|
||||||
MmInsertRmap(PFN_NUMBER Page, PEPROCESS Process,
|
MmInsertRmap(PFN_NUMBER Page, PEPROCESS Process,
|
||||||
PVOID Address)
|
PVOID Address)
|
||||||
{
|
{
|
||||||
PMM_RMAP_ENTRY current_entry;
|
PMM_RMAP_ENTRY current_entry;
|
||||||
PMM_RMAP_ENTRY new_entry;
|
PMM_RMAP_ENTRY new_entry;
|
||||||
ULONG PrevSize;
|
ULONG PrevSize;
|
||||||
if (!RMAP_IS_SEGMENT(Address))
|
if (!RMAP_IS_SEGMENT(Address))
|
||||||
Address = (PVOID)PAGE_ROUND_DOWN(Address);
|
Address = (PVOID)PAGE_ROUND_DOWN(Address);
|
||||||
|
|
||||||
new_entry = ExAllocateFromNPagedLookasideList(&RmapLookasideList);
|
new_entry = ExAllocateFromNPagedLookasideList(&RmapLookasideList);
|
||||||
if (new_entry == NULL)
|
if (new_entry == NULL)
|
||||||
{
|
{
|
||||||
KeBugCheck(MEMORY_MANAGEMENT);
|
KeBugCheck(MEMORY_MANAGEMENT);
|
||||||
}
|
}
|
||||||
new_entry->Address = Address;
|
new_entry->Address = Address;
|
||||||
new_entry->Process = (PEPROCESS)Process;
|
new_entry->Process = (PEPROCESS)Process;
|
||||||
#if DBG
|
#if DBG
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
new_entry->Caller = __builtin_return_address(0);
|
new_entry->Caller = __builtin_return_address(0);
|
||||||
#else
|
#else
|
||||||
new_entry->Caller = _ReturnAddress();
|
new_entry->Caller = _ReturnAddress();
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (
|
if (
|
||||||
!RMAP_IS_SEGMENT(Address) &&
|
!RMAP_IS_SEGMENT(Address) &&
|
||||||
MmGetPfnForProcess(Process, Address) != Page)
|
MmGetPfnForProcess(Process, Address) != Page)
|
||||||
{
|
{
|
||||||
DPRINT1("Insert rmap (%d, 0x%.8X) 0x%.8X which doesn't match physical "
|
DPRINT1("Insert rmap (%d, 0x%.8X) 0x%.8X which doesn't match physical "
|
||||||
"address 0x%.8X\n", Process ? Process->UniqueProcessId : 0,
|
"address 0x%.8X\n", Process ? Process->UniqueProcessId : 0,
|
||||||
Address,
|
Address,
|
||||||
MmGetPfnForProcess(Process, Address) << PAGE_SHIFT,
|
MmGetPfnForProcess(Process, Address) << PAGE_SHIFT,
|
||||||
Page << PAGE_SHIFT);
|
Page << PAGE_SHIFT);
|
||||||
KeBugCheck(MEMORY_MANAGEMENT);
|
KeBugCheck(MEMORY_MANAGEMENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
ExAcquireFastMutex(&RmapListLock);
|
ExAcquireFastMutex(&RmapListLock);
|
||||||
current_entry = MmGetRmapListHeadPage(Page);
|
current_entry = MmGetRmapListHeadPage(Page);
|
||||||
new_entry->Next = current_entry;
|
new_entry->Next = current_entry;
|
||||||
#if DBG
|
#if DBG
|
||||||
while (current_entry)
|
while (current_entry)
|
||||||
{
|
{
|
||||||
if (current_entry->Address == new_entry->Address && current_entry->Process == new_entry->Process)
|
if (current_entry->Address == new_entry->Address && current_entry->Process == new_entry->Process)
|
||||||
{
|
{
|
||||||
DbgPrint("MmInsertRmap tries to add a second rmap entry for address %p\n current caller ",
|
DbgPrint("MmInsertRmap tries to add a second rmap entry for address %p\n current caller ",
|
||||||
current_entry->Address);
|
current_entry->Address);
|
||||||
DbgPrint("%p", new_entry->Caller);
|
DbgPrint("%p", new_entry->Caller);
|
||||||
DbgPrint("\n previous caller ");
|
DbgPrint("\n previous caller ");
|
||||||
DbgPrint("%p", current_entry->Caller);
|
DbgPrint("%p", current_entry->Caller);
|
||||||
DbgPrint("\n");
|
DbgPrint("\n");
|
||||||
KeBugCheck(MEMORY_MANAGEMENT);
|
KeBugCheck(MEMORY_MANAGEMENT);
|
||||||
}
|
}
|
||||||
current_entry = current_entry->Next;
|
current_entry = current_entry->Next;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
MmSetRmapListHeadPage(Page, new_entry);
|
MmSetRmapListHeadPage(Page, new_entry);
|
||||||
ExReleaseFastMutex(&RmapListLock);
|
ExReleaseFastMutex(&RmapListLock);
|
||||||
if (!RMAP_IS_SEGMENT(Address))
|
if (!RMAP_IS_SEGMENT(Address))
|
||||||
{
|
{
|
||||||
if (Process == NULL)
|
if (Process == NULL)
|
||||||
{
|
{
|
||||||
Process = PsInitialSystemProcess;
|
Process = PsInitialSystemProcess;
|
||||||
}
|
}
|
||||||
if (Process)
|
if (Process)
|
||||||
{
|
{
|
||||||
PrevSize = InterlockedExchangeAddUL(&Process->Vm.WorkingSetSize, PAGE_SIZE);
|
PrevSize = InterlockedExchangeAddUL(&Process->Vm.WorkingSetSize, PAGE_SIZE);
|
||||||
if (PrevSize >= Process->Vm.PeakWorkingSetSize)
|
if (PrevSize >= Process->Vm.PeakWorkingSetSize)
|
||||||
{
|
{
|
||||||
Process->Vm.PeakWorkingSetSize = PrevSize + PAGE_SIZE;
|
Process->Vm.PeakWorkingSetSize = PrevSize + PAGE_SIZE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
|
@ -344,47 +344,47 @@ MmDeleteAllRmaps(PFN_NUMBER Page, PVOID Context,
|
||||||
VOID (*DeleteMapping)(PVOID Context, PEPROCESS Process,
|
VOID (*DeleteMapping)(PVOID Context, PEPROCESS Process,
|
||||||
PVOID Address))
|
PVOID Address))
|
||||||
{
|
{
|
||||||
PMM_RMAP_ENTRY current_entry;
|
PMM_RMAP_ENTRY current_entry;
|
||||||
PMM_RMAP_ENTRY previous_entry;
|
PMM_RMAP_ENTRY previous_entry;
|
||||||
PEPROCESS Process;
|
PEPROCESS Process;
|
||||||
|
|
||||||
ExAcquireFastMutex(&RmapListLock);
|
ExAcquireFastMutex(&RmapListLock);
|
||||||
current_entry = MmGetRmapListHeadPage(Page);
|
current_entry = MmGetRmapListHeadPage(Page);
|
||||||
if (current_entry == NULL)
|
if (current_entry == NULL)
|
||||||
{
|
{
|
||||||
DPRINT1("MmDeleteAllRmaps: No rmaps.\n");
|
DPRINT1("MmDeleteAllRmaps: No rmaps.\n");
|
||||||
KeBugCheck(MEMORY_MANAGEMENT);
|
KeBugCheck(MEMORY_MANAGEMENT);
|
||||||
}
|
}
|
||||||
MmSetRmapListHeadPage(Page, NULL);
|
MmSetRmapListHeadPage(Page, NULL);
|
||||||
ExReleaseFastMutex(&RmapListLock);
|
ExReleaseFastMutex(&RmapListLock);
|
||||||
|
|
||||||
while (current_entry != NULL)
|
while (current_entry != NULL)
|
||||||
{
|
{
|
||||||
previous_entry = current_entry;
|
previous_entry = current_entry;
|
||||||
current_entry = current_entry->Next;
|
current_entry = current_entry->Next;
|
||||||
if (!RMAP_IS_SEGMENT(previous_entry->Address))
|
if (!RMAP_IS_SEGMENT(previous_entry->Address))
|
||||||
{
|
{
|
||||||
if (DeleteMapping)
|
if (DeleteMapping)
|
||||||
{
|
{
|
||||||
DeleteMapping(Context, previous_entry->Process,
|
DeleteMapping(Context, previous_entry->Process,
|
||||||
previous_entry->Address);
|
previous_entry->Address);
|
||||||
}
|
}
|
||||||
Process = previous_entry->Process;
|
Process = previous_entry->Process;
|
||||||
ExFreeToNPagedLookasideList(&RmapLookasideList, previous_entry);
|
ExFreeToNPagedLookasideList(&RmapLookasideList, previous_entry);
|
||||||
if (Process == NULL)
|
if (Process == NULL)
|
||||||
{
|
{
|
||||||
Process = PsInitialSystemProcess;
|
Process = PsInitialSystemProcess;
|
||||||
}
|
}
|
||||||
if (Process)
|
if (Process)
|
||||||
{
|
{
|
||||||
(void)InterlockedExchangeAddUL(&Process->Vm.WorkingSetSize, -PAGE_SIZE);
|
(void)InterlockedExchangeAddUL(&Process->Vm.WorkingSetSize, -PAGE_SIZE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ExFreeToNPagedLookasideList(&RmapLookasideList, previous_entry);
|
ExFreeToNPagedLookasideList(&RmapLookasideList, previous_entry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
|
@ -392,44 +392,44 @@ NTAPI
|
||||||
MmDeleteRmap(PFN_NUMBER Page, PEPROCESS Process,
|
MmDeleteRmap(PFN_NUMBER Page, PEPROCESS Process,
|
||||||
PVOID Address)
|
PVOID Address)
|
||||||
{
|
{
|
||||||
PMM_RMAP_ENTRY current_entry, previous_entry;
|
PMM_RMAP_ENTRY current_entry, previous_entry;
|
||||||
|
|
||||||
ExAcquireFastMutex(&RmapListLock);
|
ExAcquireFastMutex(&RmapListLock);
|
||||||
previous_entry = NULL;
|
previous_entry = NULL;
|
||||||
current_entry = MmGetRmapListHeadPage(Page);
|
current_entry = MmGetRmapListHeadPage(Page);
|
||||||
|
|
||||||
while (current_entry != NULL)
|
while (current_entry != NULL)
|
||||||
{
|
{
|
||||||
if (current_entry->Process == (PEPROCESS)Process &&
|
if (current_entry->Process == (PEPROCESS)Process &&
|
||||||
current_entry->Address == Address)
|
current_entry->Address == Address)
|
||||||
{
|
{
|
||||||
if (previous_entry == NULL)
|
if (previous_entry == NULL)
|
||||||
{
|
|
||||||
MmSetRmapListHeadPage(Page, current_entry->Next);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
previous_entry->Next = current_entry->Next;
|
|
||||||
}
|
|
||||||
ExReleaseFastMutex(&RmapListLock);
|
|
||||||
ExFreeToNPagedLookasideList(&RmapLookasideList, current_entry);
|
|
||||||
if (!RMAP_IS_SEGMENT(Address))
|
|
||||||
{
|
|
||||||
if (Process == NULL)
|
|
||||||
{
|
{
|
||||||
Process = PsInitialSystemProcess;
|
MmSetRmapListHeadPage(Page, current_entry->Next);
|
||||||
}
|
}
|
||||||
if (Process)
|
else
|
||||||
{
|
{
|
||||||
(void)InterlockedExchangeAddUL(&Process->Vm.WorkingSetSize, -PAGE_SIZE);
|
previous_entry->Next = current_entry->Next;
|
||||||
}
|
}
|
||||||
}
|
ExReleaseFastMutex(&RmapListLock);
|
||||||
return;
|
ExFreeToNPagedLookasideList(&RmapLookasideList, current_entry);
|
||||||
}
|
if (!RMAP_IS_SEGMENT(Address))
|
||||||
previous_entry = current_entry;
|
{
|
||||||
current_entry = current_entry->Next;
|
if (Process == NULL)
|
||||||
}
|
{
|
||||||
KeBugCheck(MEMORY_MANAGEMENT);
|
Process = PsInitialSystemProcess;
|
||||||
|
}
|
||||||
|
if (Process)
|
||||||
|
{
|
||||||
|
(void)InterlockedExchangeAddUL(&Process->Vm.WorkingSetSize, -PAGE_SIZE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
previous_entry = current_entry;
|
||||||
|
current_entry = current_entry->Next;
|
||||||
|
}
|
||||||
|
KeBugCheck(MEMORY_MANAGEMENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -450,27 +450,27 @@ PVOID
|
||||||
NTAPI
|
NTAPI
|
||||||
MmGetSegmentRmap(PFN_NUMBER Page, PULONG RawOffset)
|
MmGetSegmentRmap(PFN_NUMBER Page, PULONG RawOffset)
|
||||||
{
|
{
|
||||||
PCACHE_SECTION_PAGE_TABLE Result = NULL;
|
PCACHE_SECTION_PAGE_TABLE Result = NULL;
|
||||||
PMM_RMAP_ENTRY current_entry;//, previous_entry;
|
PMM_RMAP_ENTRY current_entry;//, previous_entry;
|
||||||
|
|
||||||
ExAcquireFastMutex(&RmapListLock);
|
ExAcquireFastMutex(&RmapListLock);
|
||||||
//previous_entry = NULL;
|
//previous_entry = NULL;
|
||||||
current_entry = MmGetRmapListHeadPage(Page);
|
current_entry = MmGetRmapListHeadPage(Page);
|
||||||
while (current_entry != NULL)
|
while (current_entry != NULL)
|
||||||
{
|
{
|
||||||
if (RMAP_IS_SEGMENT(current_entry->Address))
|
if (RMAP_IS_SEGMENT(current_entry->Address))
|
||||||
{
|
{
|
||||||
Result = (PCACHE_SECTION_PAGE_TABLE)current_entry->Process;
|
Result = (PCACHE_SECTION_PAGE_TABLE)current_entry->Process;
|
||||||
*RawOffset = (ULONG_PTR)current_entry->Address & ~RMAP_SEGMENT_MASK;
|
*RawOffset = (ULONG_PTR)current_entry->Address & ~RMAP_SEGMENT_MASK;
|
||||||
InterlockedIncrementUL(&Result->Segment->ReferenceCount);
|
InterlockedIncrementUL(&Result->Segment->ReferenceCount);
|
||||||
ExReleaseFastMutex(&RmapListLock);
|
ExReleaseFastMutex(&RmapListLock);
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
//previous_entry = current_entry;
|
//previous_entry = current_entry;
|
||||||
current_entry = current_entry->Next;
|
current_entry = current_entry->Next;
|
||||||
}
|
}
|
||||||
ExReleaseFastMutex(&RmapListLock);
|
ExReleaseFastMutex(&RmapListLock);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -483,29 +483,29 @@ VOID
|
||||||
NTAPI
|
NTAPI
|
||||||
MmDeleteSectionAssociation(PFN_NUMBER Page)
|
MmDeleteSectionAssociation(PFN_NUMBER Page)
|
||||||
{
|
{
|
||||||
PMM_RMAP_ENTRY current_entry, previous_entry;
|
PMM_RMAP_ENTRY current_entry, previous_entry;
|
||||||
|
|
||||||
ExAcquireFastMutex(&RmapListLock);
|
ExAcquireFastMutex(&RmapListLock);
|
||||||
previous_entry = NULL;
|
previous_entry = NULL;
|
||||||
current_entry = MmGetRmapListHeadPage(Page);
|
current_entry = MmGetRmapListHeadPage(Page);
|
||||||
while (current_entry != NULL)
|
while (current_entry != NULL)
|
||||||
{
|
{
|
||||||
if (RMAP_IS_SEGMENT(current_entry->Address))
|
if (RMAP_IS_SEGMENT(current_entry->Address))
|
||||||
{
|
{
|
||||||
if (previous_entry == NULL)
|
if (previous_entry == NULL)
|
||||||
{
|
{
|
||||||
MmSetRmapListHeadPage(Page, current_entry->Next);
|
MmSetRmapListHeadPage(Page, current_entry->Next);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
previous_entry->Next = current_entry->Next;
|
previous_entry->Next = current_entry->Next;
|
||||||
}
|
}
|
||||||
ExReleaseFastMutex(&RmapListLock);
|
ExReleaseFastMutex(&RmapListLock);
|
||||||
ExFreeToNPagedLookasideList(&RmapLookasideList, current_entry);
|
ExFreeToNPagedLookasideList(&RmapLookasideList, current_entry);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
previous_entry = current_entry;
|
previous_entry = current_entry;
|
||||||
current_entry = current_entry->Next;
|
current_entry = current_entry->Next;
|
||||||
}
|
}
|
||||||
ExReleaseFastMutex(&RmapListLock);
|
ExReleaseFastMutex(&RmapListLock);
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue