2008-03-09 14:11:42 +00:00
|
|
|
/*
|
2005-01-26 13:58:37 +00:00
|
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
|
|
* PROJECT: ReactOS kernel
|
|
|
|
* FILE: ntoskrnl/mm/i386/page.c
|
|
|
|
* PURPOSE: Low level memory managment manipulation
|
|
|
|
*
|
|
|
|
* PROGRAMMERS: David Welch (welch@cwcom.net)
|
1999-11-12 12:01:17 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
/* INCLUDES ***************************************************************/
|
|
|
|
|
2004-08-15 16:39:12 +00:00
|
|
|
#include <ntoskrnl.h>
|
1999-11-12 12:01:17 +00:00
|
|
|
#define NDEBUG
|
2008-08-30 16:31:06 +00:00
|
|
|
#include <debug.h>
|
2010-07-25 01:22:15 +00:00
|
|
|
#include "../ARM3/miarm.h"
|
1999-11-12 12:01:17 +00:00
|
|
|
|
2005-11-28 23:25:31 +00:00
|
|
|
#if defined (ALLOC_PRAGMA)
|
|
|
|
#pragma alloc_text(INIT, MmInitGlobalKernelPageDirectory)
|
|
|
|
#pragma alloc_text(INIT, MiInitPageDirectoryMap)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
1999-11-12 12:01:17 +00:00
|
|
|
/* GLOBALS *****************************************************************/
|
|
|
|
|
2002-05-14 21:19:21 +00:00
|
|
|
#define PA_BIT_PRESENT (0)
|
|
|
|
#define PA_BIT_READWRITE (1)
|
|
|
|
#define PA_BIT_USER (2)
|
|
|
|
#define PA_BIT_WT (3)
|
|
|
|
#define PA_BIT_CD (4)
|
|
|
|
#define PA_BIT_ACCESSED (5)
|
|
|
|
#define PA_BIT_DIRTY (6)
|
2011-12-25 18:21:05 +00:00
|
|
|
#define PA_BIT_GLOBAL (8)
|
2002-05-14 21:19:21 +00:00
|
|
|
|
|
|
|
#define PA_PRESENT (1 << PA_BIT_PRESENT)
|
|
|
|
#define PA_READWRITE (1 << PA_BIT_READWRITE)
|
|
|
|
#define PA_USER (1 << PA_BIT_USER)
|
|
|
|
#define PA_DIRTY (1 << PA_BIT_DIRTY)
|
|
|
|
#define PA_WT (1 << PA_BIT_WT)
|
|
|
|
#define PA_CD (1 << PA_BIT_CD)
|
|
|
|
#define PA_ACCESSED (1 << PA_BIT_ACCESSED)
|
2004-08-14 09:17:05 +00:00
|
|
|
#define PA_GLOBAL (1 << PA_BIT_GLOBAL)
|
1999-11-12 12:01:17 +00:00
|
|
|
|
2011-12-25 18:21:05 +00:00
|
|
|
#define HYPERSPACE (0xc0400000)
|
|
|
|
#define IS_HYPERSPACE(v) (((ULONG)(v) >= HYPERSPACE && (ULONG)(v) < HYPERSPACE + 0x400000))
|
2005-01-25 22:50:47 +00:00
|
|
|
|
2004-09-09 20:42:33 +00:00
|
|
|
ULONG MmGlobalKernelPageDirectory[1024];
|
2001-02-18 22:16:05 +00:00
|
|
|
|
2004-08-01 07:27:25 +00:00
|
|
|
#define PTE_TO_PFN(X) ((X) >> PAGE_SHIFT)
|
2005-05-09 01:38:29 +00:00
|
|
|
#define PFN_TO_PTE(X) ((X) << PAGE_SHIFT)
|
2004-09-07 11:08:16 +00:00
|
|
|
|
|
|
|
#if defined(__GNUC__)
|
2002-06-04 David Welch <welch@whitehall1-5.seh.ox.ac.uk>
* ntoskrnl/ke/i386/exp.c (KiDoubleFaultHandler): Print CR3
correctly.
2002-06-04 David Welch <welch@whitehall1-5.seh.ox.ac.uk>
* ntoskrnl/include/internal/ps.h: Added KTHREAD_STACK_LIMIT definition.
* ntoskrnl/ke/i386/tskswitch.S (Ki386ContextSwitch): Force all the
pages of the kernel stack to be accessible from this process.
2002-06-04 David Welch <welch@cwcom.net>
* ntoskrnl/cc/view.c (ReadCacheSegmentChain): Changes to use
PHYSICAL_ADDRESS type for physical addresses.
* ntoskrnl/cc/copy.c (CcRosCreateCacheSegment): Changes to use
PHYSICAL_ADDRESS type for physical addresses.
* ntoskrnl/cc/copy.c (CcFreeCachePage): Changes to use
PHYSICAL_ADDRESS type for physical addresses.
* ntoskrnl/include/internal/mm.h: Changed prototypes to use
PHYSICAL_ADDRESS type for physical addresses.
* ntoskrnl/include/internal/ps.h (KPROCESS): Changed type of
page directory base to PHYSICAL_ADDRESS.
* ntoskrnl/include/internal/i386/mm.h: Changed prototypes to use
PHYSICAL_ADDRESS type for physical addresses.
* ntoskrnl/ke/kthread.c (KeFreeStackPage): Changes to use
PHYSICAL_ADDRESS type for physical addresses.
* ntoskrnl/ke/kthread.c (KeInitializeThread): Changes to use
PHYSICAL_ADDRESS type for physical addresses.
* ntoskrnl/ke/process.c (KeAttachProcess, KeDetachProcess): Changes
to use PHYSICAL_ADDRESS type for physical addresses.
* ntoskrnl/ke/kernel.c (PcrPages, KeApplicationProcessorInit): Changes
to use PHYSICAL_ADDRESS type for physical addresses.
* ntoskrnl/mm/balance.c (MM_ALLOCATION_REQUEST): Changes to use
PHYSICAL_ADDRESS type for physical addresses.
* ntoskrnl/mm/balance.c (MmReleasePageMemoryConsumer): Changes to use
PHYSICAL_ADDRESS type for physical addresses.
* ntoskrnl/mm/balance.c (MmRequestPageMemoryConsumer): Changes to use
PHYSICAL_ADDRESS type for physical addresses.
* ntoskrnl/mm/cont.c (MmFreeContinuousPage): Changes to use
PHYSICAL_ADDRESS type for physical addresses.
* ntoskrnl/mm/cont.c (MmAllocateContinuousAlignedMemory): Changes to
use PHYSICAL_ADDRESS type for physical addresses.
* ntoskrnl/mm/freelist.c (MmTransferOwnershipPage,
MmGetLRUFirstUserPage, MmGetLRUNextUserPage, MmGetContinuousPages,
MmInitializePageList, MmSetFlagsPage, MmSetRmapListHeadPage,
MmGetRmapListHeadPage, MmMarkPageMapped, MmMarkPageUnmapped,
MmGetFlagsPage, MmSetSavedSwapEntryPage, MmGetSavedSwapEntryPage,
MmReferencePage, MmGetReferenceCountPage, MmIsUsablePage,
MmDereferencePage, MmGetLockCountPage, MmLockPage, MmUnlockPage,
MmAllocPage): Changes to use PHYSICAL_ADDRESS type for physical
addresses.
* ntoskrnl/mm/iospace.c (MmMapIoSpace): Changes to use
PHYSICAL_ADDRESS type for physical addresses.
* ntoskrnl/mm/kmap.c (ExAllocatePage, MiZeroPage, MiCopyFromUserPage,
ExAllocatePageWithPhysPage): Changes to use PHYSICAL_ADDRESS type for
physical addresses.
* ntoskrnl/mm/marea.c (MmFreeMemoryArea): Changes to use
PHYSICAL_ADDRESS type for physical addresses.
* ntoskrnl/mm/mdl.c (MmUnlockPages, MmMapLockedPages,
MmProbeAndLockPages): Changes to use PHYSICAL_ADDRESS type for
physical addresses.
* ntoskrnl/mm/mm.c (MmSharedDataPagePhysicalAddress,
MmCommitPagedPoolAddress, MmNotPresentFault): Changes to use
PHYSICAL_ADDRESS type for physical addresses.
* ntoskrnl/mm/mminit.c (MmInitVirtualMemory): Changes to use
PHYSICAL_ADDRESS type for physical addresses.
* ntoskrnl/mm/ncache.c (MmAllocateNonCachedMemory,
MmFreeNonCachedPage): Changes to use PHYSICAL_ADDRESS type for
physical addresses.
* ntoskrnl/mm/npool.c (grow_kernel_pool): Changes to use
PHYSICAL_ADDRESS type for physical addresses.
* ntoskrnl/mm/rmap.c (MmPageOutPhysicalAddress, MmInsertRmap,
MmDeleteAllRmaps, MmDeleteRmap): Changes to use
PHYSICAL_ADDRESS type for physical addresses.
* ntoskrnl/mm/section.c (MiReadPage, MmNotPresentFaultSectionView,
MmAccessFaultSectionView, MmPageOutDeleteMapping,
MmPageOutSectionView, MmFreeSectionPage): Changes to use
PHYSICAL_ADDRESS type for physical addresses.
* ntoskrnl/mm/slab.c (ExGrowSlabCache): Changes to use
PHYSICAL_ADDRESS type for physical address.
* ntoskrnl/mm/virtual.c (MmPageOutVirtualMemory,
MmNotPresentFaultVirtualMemory, MmFreeVirtualMemoryPage): Changes to
use PHYSICAL_ADDRESS type for physical address.
* ntoskrnl/mm/wset.c (MmTrimUserMemory): Changes to use
PHYSICAL_ADDRESS type for physical address.
* ntoskrnl/mm/page.c (Mmi386ReleaseMmInfo, MmCopyMmInfo,
MmGetPhysicalAddressForProcess, MmCreateVirtualMapping,
MmCreateVirtualMappingUnsafe, MmCreateVirtualMappingForProcess,
MmDeleteVirtualMapping): Changes to use PHYSICAL_ADDRESS type for
physical address.
* ntoskrnl/ps/process (PsInitProcessManagment): Changes to use
PHYSICAL_ADDRESS type for physical address.
* ntoskrnl/ps/thread.c (PsAllocateCallbackStack): Changes to use
PHYSICAL_ADDRESS type for physical address.
2002-06-04 David Welch <welch@cwcom.net>
* Lots of change since the ChangeLog was last updated.
svn path=/trunk/; revision=3000
2002-06-04 15:26:58 +00:00
|
|
|
#define PTE_TO_PAGE(X) ((LARGE_INTEGER)(LONGLONG)(PAGE_MASK(X)))
|
2003-12-30 18:52:06 +00:00
|
|
|
#else
|
|
|
|
__inline LARGE_INTEGER PTE_TO_PAGE(ULONG npage)
|
|
|
|
{
|
2008-07-31 07:04:58 +00:00
|
|
|
LARGE_INTEGER dummy;
|
|
|
|
dummy.QuadPart = (LONGLONG)(PAGE_MASK(npage));
|
|
|
|
return dummy;
|
2003-12-30 18:52:06 +00:00
|
|
|
}
|
|
|
|
#endif
|
2002-06-04 David Welch <welch@whitehall1-5.seh.ox.ac.uk>
* ntoskrnl/ke/i386/exp.c (KiDoubleFaultHandler): Print CR3
correctly.
2002-06-04 David Welch <welch@whitehall1-5.seh.ox.ac.uk>
* ntoskrnl/include/internal/ps.h: Added KTHREAD_STACK_LIMIT definition.
* ntoskrnl/ke/i386/tskswitch.S (Ki386ContextSwitch): Force all the
pages of the kernel stack to be accessible from this process.
2002-06-04 David Welch <welch@cwcom.net>
* ntoskrnl/cc/view.c (ReadCacheSegmentChain): Changes to use
PHYSICAL_ADDRESS type for physical addresses.
* ntoskrnl/cc/copy.c (CcRosCreateCacheSegment): Changes to use
PHYSICAL_ADDRESS type for physical addresses.
* ntoskrnl/cc/copy.c (CcFreeCachePage): Changes to use
PHYSICAL_ADDRESS type for physical addresses.
* ntoskrnl/include/internal/mm.h: Changed prototypes to use
PHYSICAL_ADDRESS type for physical addresses.
* ntoskrnl/include/internal/ps.h (KPROCESS): Changed type of
page directory base to PHYSICAL_ADDRESS.
* ntoskrnl/include/internal/i386/mm.h: Changed prototypes to use
PHYSICAL_ADDRESS type for physical addresses.
* ntoskrnl/ke/kthread.c (KeFreeStackPage): Changes to use
PHYSICAL_ADDRESS type for physical addresses.
* ntoskrnl/ke/kthread.c (KeInitializeThread): Changes to use
PHYSICAL_ADDRESS type for physical addresses.
* ntoskrnl/ke/process.c (KeAttachProcess, KeDetachProcess): Changes
to use PHYSICAL_ADDRESS type for physical addresses.
* ntoskrnl/ke/kernel.c (PcrPages, KeApplicationProcessorInit): Changes
to use PHYSICAL_ADDRESS type for physical addresses.
* ntoskrnl/mm/balance.c (MM_ALLOCATION_REQUEST): Changes to use
PHYSICAL_ADDRESS type for physical addresses.
* ntoskrnl/mm/balance.c (MmReleasePageMemoryConsumer): Changes to use
PHYSICAL_ADDRESS type for physical addresses.
* ntoskrnl/mm/balance.c (MmRequestPageMemoryConsumer): Changes to use
PHYSICAL_ADDRESS type for physical addresses.
* ntoskrnl/mm/cont.c (MmFreeContinuousPage): Changes to use
PHYSICAL_ADDRESS type for physical addresses.
* ntoskrnl/mm/cont.c (MmAllocateContinuousAlignedMemory): Changes to
use PHYSICAL_ADDRESS type for physical addresses.
* ntoskrnl/mm/freelist.c (MmTransferOwnershipPage,
MmGetLRUFirstUserPage, MmGetLRUNextUserPage, MmGetContinuousPages,
MmInitializePageList, MmSetFlagsPage, MmSetRmapListHeadPage,
MmGetRmapListHeadPage, MmMarkPageMapped, MmMarkPageUnmapped,
MmGetFlagsPage, MmSetSavedSwapEntryPage, MmGetSavedSwapEntryPage,
MmReferencePage, MmGetReferenceCountPage, MmIsUsablePage,
MmDereferencePage, MmGetLockCountPage, MmLockPage, MmUnlockPage,
MmAllocPage): Changes to use PHYSICAL_ADDRESS type for physical
addresses.
* ntoskrnl/mm/iospace.c (MmMapIoSpace): Changes to use
PHYSICAL_ADDRESS type for physical addresses.
* ntoskrnl/mm/kmap.c (ExAllocatePage, MiZeroPage, MiCopyFromUserPage,
ExAllocatePageWithPhysPage): Changes to use PHYSICAL_ADDRESS type for
physical addresses.
* ntoskrnl/mm/marea.c (MmFreeMemoryArea): Changes to use
PHYSICAL_ADDRESS type for physical addresses.
* ntoskrnl/mm/mdl.c (MmUnlockPages, MmMapLockedPages,
MmProbeAndLockPages): Changes to use PHYSICAL_ADDRESS type for
physical addresses.
* ntoskrnl/mm/mm.c (MmSharedDataPagePhysicalAddress,
MmCommitPagedPoolAddress, MmNotPresentFault): Changes to use
PHYSICAL_ADDRESS type for physical addresses.
* ntoskrnl/mm/mminit.c (MmInitVirtualMemory): Changes to use
PHYSICAL_ADDRESS type for physical addresses.
* ntoskrnl/mm/ncache.c (MmAllocateNonCachedMemory,
MmFreeNonCachedPage): Changes to use PHYSICAL_ADDRESS type for
physical addresses.
* ntoskrnl/mm/npool.c (grow_kernel_pool): Changes to use
PHYSICAL_ADDRESS type for physical addresses.
* ntoskrnl/mm/rmap.c (MmPageOutPhysicalAddress, MmInsertRmap,
MmDeleteAllRmaps, MmDeleteRmap): Changes to use
PHYSICAL_ADDRESS type for physical addresses.
* ntoskrnl/mm/section.c (MiReadPage, MmNotPresentFaultSectionView,
MmAccessFaultSectionView, MmPageOutDeleteMapping,
MmPageOutSectionView, MmFreeSectionPage): Changes to use
PHYSICAL_ADDRESS type for physical addresses.
* ntoskrnl/mm/slab.c (ExGrowSlabCache): Changes to use
PHYSICAL_ADDRESS type for physical address.
* ntoskrnl/mm/virtual.c (MmPageOutVirtualMemory,
MmNotPresentFaultVirtualMemory, MmFreeVirtualMemoryPage): Changes to
use PHYSICAL_ADDRESS type for physical address.
* ntoskrnl/mm/wset.c (MmTrimUserMemory): Changes to use
PHYSICAL_ADDRESS type for physical address.
* ntoskrnl/mm/page.c (Mmi386ReleaseMmInfo, MmCopyMmInfo,
MmGetPhysicalAddressForProcess, MmCreateVirtualMapping,
MmCreateVirtualMappingUnsafe, MmCreateVirtualMappingForProcess,
MmDeleteVirtualMapping): Changes to use PHYSICAL_ADDRESS type for
physical address.
* ntoskrnl/ps/process (PsInitProcessManagment): Changes to use
PHYSICAL_ADDRESS type for physical address.
* ntoskrnl/ps/thread.c (PsAllocateCallbackStack): Changes to use
PHYSICAL_ADDRESS type for physical address.
2002-06-04 David Welch <welch@cwcom.net>
* Lots of change since the ChangeLog was last updated.
svn path=/trunk/; revision=3000
2002-06-04 15:26:58 +00:00
|
|
|
|
2010-07-25 01:22:15 +00:00
|
|
|
const
|
|
|
|
ULONG
|
|
|
|
MmProtectToPteMask[32] =
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// These are the base MM_ protection flags
|
|
|
|
//
|
|
|
|
0,
|
|
|
|
PTE_READONLY | PTE_ENABLE_CACHE,
|
|
|
|
PTE_EXECUTE | PTE_ENABLE_CACHE,
|
|
|
|
PTE_EXECUTE_READ | PTE_ENABLE_CACHE,
|
|
|
|
PTE_READWRITE | PTE_ENABLE_CACHE,
|
|
|
|
PTE_WRITECOPY | PTE_ENABLE_CACHE,
|
|
|
|
PTE_EXECUTE_READWRITE | PTE_ENABLE_CACHE,
|
|
|
|
PTE_EXECUTE_WRITECOPY | PTE_ENABLE_CACHE,
|
|
|
|
//
|
|
|
|
// These OR in the MM_NOCACHE flag
|
|
|
|
//
|
|
|
|
0,
|
|
|
|
PTE_READONLY | PTE_DISABLE_CACHE,
|
|
|
|
PTE_EXECUTE | PTE_DISABLE_CACHE,
|
|
|
|
PTE_EXECUTE_READ | PTE_DISABLE_CACHE,
|
|
|
|
PTE_READWRITE | PTE_DISABLE_CACHE,
|
|
|
|
PTE_WRITECOPY | PTE_DISABLE_CACHE,
|
|
|
|
PTE_EXECUTE_READWRITE | PTE_DISABLE_CACHE,
|
|
|
|
PTE_EXECUTE_WRITECOPY | PTE_DISABLE_CACHE,
|
|
|
|
//
|
|
|
|
// These OR in the MM_DECOMMIT flag, which doesn't seem supported on x86/64/ARM
|
|
|
|
//
|
|
|
|
0,
|
|
|
|
PTE_READONLY | PTE_ENABLE_CACHE,
|
|
|
|
PTE_EXECUTE | PTE_ENABLE_CACHE,
|
|
|
|
PTE_EXECUTE_READ | PTE_ENABLE_CACHE,
|
|
|
|
PTE_READWRITE | PTE_ENABLE_CACHE,
|
|
|
|
PTE_WRITECOPY | PTE_ENABLE_CACHE,
|
|
|
|
PTE_EXECUTE_READWRITE | PTE_ENABLE_CACHE,
|
|
|
|
PTE_EXECUTE_WRITECOPY | PTE_ENABLE_CACHE,
|
|
|
|
//
|
|
|
|
// These OR in the MM_NOACCESS flag, which seems to enable WriteCombining?
|
|
|
|
//
|
|
|
|
0,
|
|
|
|
PTE_READONLY | PTE_WRITECOMBINED_CACHE,
|
|
|
|
PTE_EXECUTE | PTE_WRITECOMBINED_CACHE,
|
|
|
|
PTE_EXECUTE_READ | PTE_WRITECOMBINED_CACHE,
|
|
|
|
PTE_READWRITE | PTE_WRITECOMBINED_CACHE,
|
|
|
|
PTE_WRITECOPY | PTE_WRITECOMBINED_CACHE,
|
|
|
|
PTE_EXECUTE_READWRITE | PTE_WRITECOMBINED_CACHE,
|
|
|
|
PTE_EXECUTE_WRITECOPY | PTE_WRITECOMBINED_CACHE,
|
|
|
|
};
|
|
|
|
|
2010-10-16 21:02:48 +00:00
|
|
|
const
|
|
|
|
ULONG MmProtectToValue[32] =
|
|
|
|
{
|
|
|
|
PAGE_NOACCESS,
|
|
|
|
PAGE_READONLY,
|
|
|
|
PAGE_EXECUTE,
|
|
|
|
PAGE_EXECUTE_READ,
|
|
|
|
PAGE_READWRITE,
|
|
|
|
PAGE_WRITECOPY,
|
|
|
|
PAGE_EXECUTE_READWRITE,
|
|
|
|
PAGE_EXECUTE_WRITECOPY,
|
|
|
|
PAGE_NOACCESS,
|
|
|
|
PAGE_NOCACHE | PAGE_READONLY,
|
|
|
|
PAGE_NOCACHE | PAGE_EXECUTE,
|
|
|
|
PAGE_NOCACHE | PAGE_EXECUTE_READ,
|
|
|
|
PAGE_NOCACHE | PAGE_READWRITE,
|
|
|
|
PAGE_NOCACHE | PAGE_WRITECOPY,
|
|
|
|
PAGE_NOCACHE | PAGE_EXECUTE_READWRITE,
|
|
|
|
PAGE_NOCACHE | PAGE_EXECUTE_WRITECOPY,
|
|
|
|
PAGE_NOACCESS,
|
|
|
|
PAGE_GUARD | PAGE_READONLY,
|
|
|
|
PAGE_GUARD | PAGE_EXECUTE,
|
|
|
|
PAGE_GUARD | PAGE_EXECUTE_READ,
|
|
|
|
PAGE_GUARD | PAGE_READWRITE,
|
|
|
|
PAGE_GUARD | PAGE_WRITECOPY,
|
|
|
|
PAGE_GUARD | PAGE_EXECUTE_READWRITE,
|
|
|
|
PAGE_GUARD | PAGE_EXECUTE_WRITECOPY,
|
|
|
|
PAGE_NOACCESS,
|
|
|
|
PAGE_WRITECOMBINE | PAGE_READONLY,
|
|
|
|
PAGE_WRITECOMBINE | PAGE_EXECUTE,
|
|
|
|
PAGE_WRITECOMBINE | PAGE_EXECUTE_READ,
|
|
|
|
PAGE_WRITECOMBINE | PAGE_READWRITE,
|
|
|
|
PAGE_WRITECOMBINE | PAGE_WRITECOPY,
|
|
|
|
PAGE_WRITECOMBINE | PAGE_EXECUTE_READWRITE,
|
|
|
|
PAGE_WRITECOMBINE | PAGE_EXECUTE_WRITECOPY
|
|
|
|
};
|
|
|
|
|
1999-11-12 12:01:17 +00:00
|
|
|
/* FUNCTIONS ***************************************************************/
|
|
|
|
|
2004-11-27 16:37:52 +00:00
|
|
|
BOOLEAN MmUnmapPageTable(PULONG Pt);
|
|
|
|
|
|
|
|
VOID
|
|
|
|
MiFlushTlb(PULONG Pt, PVOID Address)
|
|
|
|
{
|
2008-07-31 07:04:58 +00:00
|
|
|
if ((Pt && MmUnmapPageTable(Pt)) || Address >= MmSystemRangeStart)
|
|
|
|
{
|
2009-11-04 22:51:00 +00:00
|
|
|
KeInvalidateTlbEntry(Address);
|
2008-07-31 07:04:58 +00:00
|
|
|
}
|
2004-11-27 16:37:52 +00:00
|
|
|
}
|
|
|
|
|
2004-04-10 22:36:07 +00:00
|
|
|
static ULONG
|
2001-01-08 02:14:06 +00:00
|
|
|
ProtectToPTE(ULONG flProtect)
|
1999-11-12 12:01:17 +00:00
|
|
|
{
|
2008-07-31 07:04:58 +00:00
|
|
|
ULONG Attributes = 0;
|
2011-12-25 18:21:05 +00:00
|
|
|
|
2008-07-31 07:04:58 +00:00
|
|
|
if (flProtect & (PAGE_NOACCESS|PAGE_GUARD))
|
|
|
|
{
|
|
|
|
Attributes = 0;
|
|
|
|
}
|
|
|
|
else if (flProtect & PAGE_IS_WRITABLE)
|
|
|
|
{
|
|
|
|
Attributes = PA_PRESENT | PA_READWRITE;
|
|
|
|
}
|
|
|
|
else if (flProtect & (PAGE_IS_READABLE | PAGE_IS_EXECUTABLE))
|
|
|
|
{
|
|
|
|
Attributes = PA_PRESENT;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
DPRINT1("Unknown main protection type.\n");
|
2008-11-26 18:56:41 +00:00
|
|
|
KeBugCheck(MEMORY_MANAGEMENT);
|
2008-07-31 07:04:58 +00:00
|
|
|
}
|
2011-12-25 18:21:05 +00:00
|
|
|
|
2008-07-31 07:04:58 +00:00
|
|
|
if (flProtect & PAGE_SYSTEM)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Attributes = Attributes | PA_USER;
|
|
|
|
}
|
|
|
|
if (flProtect & PAGE_NOCACHE)
|
|
|
|
{
|
|
|
|
Attributes = Attributes | PA_CD;
|
|
|
|
}
|
|
|
|
if (flProtect & PAGE_WRITETHROUGH)
|
|
|
|
{
|
|
|
|
Attributes = Attributes | PA_WT;
|
|
|
|
}
|
|
|
|
return(Attributes);
|
1999-11-12 12:01:17 +00:00
|
|
|
}
|
|
|
|
|
2005-05-09 01:38:29 +00:00
|
|
|
static PULONG
|
2006-05-18 20:32:17 +00:00
|
|
|
MmGetPageTableForProcess(PEPROCESS Process, PVOID Address, BOOLEAN Create)
|
2000-08-20 17:02:10 +00:00
|
|
|
{
|
2008-07-31 07:04:58 +00:00
|
|
|
ULONG PdeOffset = ADDR_TO_PDE_OFFSET(Address);
|
|
|
|
NTSTATUS Status;
|
2010-07-15 22:50:12 +00:00
|
|
|
PFN_NUMBER Pfn;
|
2008-07-31 07:04:58 +00:00
|
|
|
ULONG Entry;
|
|
|
|
PULONG Pt, PageDir;
|
2011-12-25 18:21:05 +00:00
|
|
|
|
2011-11-15 22:34:04 +00:00
|
|
|
if (Address < MmSystemRangeStart)
|
2008-07-31 07:04:58 +00:00
|
|
|
{
|
2011-11-15 22:34:04 +00:00
|
|
|
/* We should have a process for user land addresses */
|
|
|
|
ASSERT(Process != NULL);
|
2011-11-24 11:22:18 +00:00
|
|
|
|
2011-11-15 22:34:04 +00:00
|
|
|
if(Process != PsGetCurrentProcess())
|
2008-07-31 07:04:58 +00:00
|
|
|
{
|
2011-11-15 22:34:04 +00:00
|
|
|
PageDir = MmCreateHyperspaceMapping(PTE_TO_PFN(Process->Pcb.DirectoryTableBase[0]));
|
|
|
|
if (PageDir == NULL)
|
|
|
|
{
|
|
|
|
KeBugCheck(MEMORY_MANAGEMENT);
|
|
|
|
}
|
|
|
|
if (0 == InterlockedCompareExchangePte(&PageDir[PdeOffset], 0, 0))
|
|
|
|
{
|
|
|
|
if (Create == FALSE)
|
|
|
|
{
|
|
|
|
MmDeleteHyperspaceMapping(PageDir);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
MI_SET_USAGE(MI_USAGE_LEGACY_PAGE_DIRECTORY);
|
2011-11-24 11:22:18 +00:00
|
|
|
|
|
|
|
MI_SET_PROCESS2(Process->ImageFileName);
|
|
|
|
|
2011-11-15 22:34:04 +00:00
|
|
|
Status = MmRequestPageMemoryConsumer(MC_SYSTEM, FALSE, &Pfn);
|
|
|
|
if (!NT_SUCCESS(Status) || Pfn == 0)
|
|
|
|
{
|
|
|
|
KeBugCheck(MEMORY_MANAGEMENT);
|
|
|
|
}
|
|
|
|
Entry = InterlockedCompareExchangePte(&PageDir[PdeOffset], PFN_TO_PTE(Pfn) | PA_PRESENT | PA_READWRITE | PA_USER, 0);
|
|
|
|
if (Entry != 0)
|
|
|
|
{
|
|
|
|
MmReleasePageMemoryConsumer(MC_SYSTEM, Pfn);
|
|
|
|
Pfn = PTE_TO_PFN(Entry);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Pfn = PTE_TO_PFN(PageDir[PdeOffset]);
|
|
|
|
}
|
|
|
|
MmDeleteHyperspaceMapping(PageDir);
|
|
|
|
Pt = MmCreateHyperspaceMapping(Pfn);
|
|
|
|
if (Pt == NULL)
|
|
|
|
{
|
|
|
|
KeBugCheck(MEMORY_MANAGEMENT);
|
|
|
|
}
|
|
|
|
return Pt + MiAddressToPteOffset(Address);
|
2008-07-31 07:04:58 +00:00
|
|
|
}
|
2011-11-15 22:34:04 +00:00
|
|
|
/* This is for our process */
|
|
|
|
PageDir = (PULONG)MiAddressToPde(Address);
|
|
|
|
if (0 == InterlockedCompareExchangePte(PageDir, 0, 0))
|
2008-07-31 07:04:58 +00:00
|
|
|
{
|
|
|
|
if (Create == FALSE)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
2010-11-02 15:16:22 +00:00
|
|
|
MI_SET_USAGE(MI_USAGE_LEGACY_PAGE_DIRECTORY);
|
2011-11-24 11:22:18 +00:00
|
|
|
MI_SET_PROCESS2(Process->ImageFileName);
|
|
|
|
|
2010-10-19 16:58:27 +00:00
|
|
|
Status = MmRequestPageMemoryConsumer(MC_SYSTEM, FALSE, &Pfn);
|
2008-07-31 07:04:58 +00:00
|
|
|
if (!NT_SUCCESS(Status) || Pfn == 0)
|
|
|
|
{
|
2008-11-26 18:56:41 +00:00
|
|
|
KeBugCheck(MEMORY_MANAGEMENT);
|
2008-07-31 07:04:58 +00:00
|
|
|
}
|
2011-11-15 22:34:04 +00:00
|
|
|
Entry = InterlockedCompareExchangePte(PageDir, PFN_TO_PTE(Pfn) | PA_PRESENT | PA_READWRITE | PA_USER, 0);
|
2008-07-31 07:04:58 +00:00
|
|
|
if (Entry != 0)
|
|
|
|
{
|
2010-10-19 16:58:27 +00:00
|
|
|
MmReleasePageMemoryConsumer(MC_SYSTEM, Pfn);
|
2008-07-31 07:04:58 +00:00
|
|
|
}
|
|
|
|
}
|
2011-11-15 22:34:04 +00:00
|
|
|
return (PULONG)MiAddressToPte(Address);
|
2008-07-31 07:04:58 +00:00
|
|
|
}
|
2011-12-25 18:21:05 +00:00
|
|
|
|
2011-11-15 22:34:04 +00:00
|
|
|
/* This is for kernel land address */
|
2008-07-31 07:04:58 +00:00
|
|
|
PageDir = (PULONG)MiAddressToPde(Address);
|
2008-08-16 01:58:59 +00:00
|
|
|
if (0 == InterlockedCompareExchangePte(PageDir, 0, 0))
|
2008-07-31 07:04:58 +00:00
|
|
|
{
|
2011-11-15 23:50:04 +00:00
|
|
|
if (0 == InterlockedCompareExchangePte(&MmGlobalKernelPageDirectory[PdeOffset], 0, 0))
|
2008-07-31 07:04:58 +00:00
|
|
|
{
|
2011-11-15 23:50:04 +00:00
|
|
|
if (Create == FALSE)
|
2008-07-31 07:04:58 +00:00
|
|
|
{
|
2011-11-15 23:50:04 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
MI_SET_USAGE(MI_USAGE_LEGACY_PAGE_DIRECTORY);
|
|
|
|
if (Process) MI_SET_PROCESS2(Process->ImageFileName);
|
|
|
|
if (!Process) MI_SET_PROCESS2("Kernel Legacy");
|
|
|
|
Status = MmRequestPageMemoryConsumer(MC_SYSTEM, FALSE, &Pfn);
|
|
|
|
if (!NT_SUCCESS(Status) || Pfn == 0)
|
|
|
|
{
|
|
|
|
KeBugCheck(MEMORY_MANAGEMENT);
|
|
|
|
}
|
|
|
|
Entry = PFN_TO_PTE(Pfn) | PA_PRESENT | PA_READWRITE;
|
|
|
|
if(0 != InterlockedCompareExchangePte(&MmGlobalKernelPageDirectory[PdeOffset], Entry, 0))
|
|
|
|
{
|
|
|
|
MmReleasePageMemoryConsumer(MC_SYSTEM, Pfn);
|
2008-07-31 07:04:58 +00:00
|
|
|
}
|
2008-08-16 01:58:59 +00:00
|
|
|
InterlockedExchangePte(PageDir, MmGlobalKernelPageDirectory[PdeOffset]);
|
2011-11-15 23:50:04 +00:00
|
|
|
return (PULONG)MiAddressToPte(Address);
|
2008-07-31 07:04:58 +00:00
|
|
|
}
|
2011-11-15 23:50:04 +00:00
|
|
|
InterlockedExchangePte(PageDir, MmGlobalKernelPageDirectory[PdeOffset]);
|
2008-07-31 07:04:58 +00:00
|
|
|
}
|
|
|
|
return (PULONG)MiAddressToPte(Address);
|
2000-07-06 14:34:52 +00:00
|
|
|
}
|
|
|
|
|
2004-09-07 11:08:16 +00:00
|
|
|
BOOLEAN MmUnmapPageTable(PULONG Pt)
|
2000-07-06 14:34:52 +00:00
|
|
|
{
|
2011-11-22 22:01:06 +00:00
|
|
|
if (!IS_HYPERSPACE(Pt))
|
2008-07-31 07:04:58 +00:00
|
|
|
{
|
|
|
|
return TRUE;
|
|
|
|
}
|
2011-12-25 18:21:05 +00:00
|
|
|
|
2008-07-31 07:04:58 +00:00
|
|
|
if (Pt)
|
|
|
|
{
|
|
|
|
MmDeleteHyperspaceMapping((PVOID)PAGE_ROUND_DOWN(Pt));
|
|
|
|
}
|
|
|
|
return FALSE;
|
2004-09-09 20:42:33 +00:00
|
|
|
}
|
|
|
|
|
2006-05-18 20:32:17 +00:00
|
|
|
static ULONG MmGetPageEntryForProcess(PEPROCESS Process, PVOID Address)
|
2004-09-07 11:08:16 +00:00
|
|
|
{
|
2008-07-31 07:04:58 +00:00
|
|
|
ULONG Pte;
|
|
|
|
PULONG Pt;
|
2011-12-25 18:21:05 +00:00
|
|
|
|
2008-07-31 07:04:58 +00:00
|
|
|
Pt = MmGetPageTableForProcess(Process, Address, FALSE);
|
|
|
|
if (Pt)
|
|
|
|
{
|
|
|
|
Pte = *Pt;
|
|
|
|
MmUnmapPageTable(Pt);
|
|
|
|
return Pte;
|
|
|
|
}
|
|
|
|
return 0;
|
2004-09-07 11:08:16 +00:00
|
|
|
}
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2010-07-15 22:50:12 +00:00
|
|
|
PFN_NUMBER
|
2005-09-14 01:05:50 +00:00
|
|
|
NTAPI
|
2006-05-18 20:32:17 +00:00
|
|
|
MmGetPfnForProcess(PEPROCESS Process,
|
2004-08-01 07:27:25 +00:00
|
|
|
PVOID Address)
|
1999-11-24 11:51:55 +00:00
|
|
|
{
|
2008-07-31 07:04:58 +00:00
|
|
|
ULONG Entry;
|
|
|
|
Entry = MmGetPageEntryForProcess(Process, Address);
|
|
|
|
if (!(Entry & PA_PRESENT))
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return(PTE_TO_PFN(Entry));
|
1999-11-24 11:51:55 +00:00
|
|
|
}
|
2002-11-05 21:13:15 +00:00
|
|
|
|
2001-12-31 01:53:46 +00:00
|
|
|
VOID
|
2005-09-14 01:05:50 +00:00
|
|
|
NTAPI
|
2010-07-15 22:50:12 +00:00
|
|
|
MmDisableVirtualMapping(PEPROCESS Process, PVOID Address, BOOLEAN* WasDirty, PPFN_NUMBER Page)
|
2001-12-31 01:53:46 +00:00
|
|
|
/*
|
2005-05-09 01:38:29 +00:00
|
|
|
* FUNCTION: Delete a virtual mapping
|
2001-12-31 01:53:46 +00:00
|
|
|
*/
|
|
|
|
{
|
2008-07-31 07:04:58 +00:00
|
|
|
BOOLEAN WasValid;
|
|
|
|
ULONG Pte;
|
|
|
|
PULONG Pt;
|
2011-12-25 18:21:05 +00:00
|
|
|
|
2008-07-31 07:04:58 +00:00
|
|
|
Pt = MmGetPageTableForProcess(Process, Address, FALSE);
|
|
|
|
if (Pt == NULL)
|
|
|
|
{
|
2008-11-26 18:56:41 +00:00
|
|
|
KeBugCheck(MEMORY_MANAGEMENT);
|
2008-07-31 07:04:58 +00:00
|
|
|
}
|
2011-12-29 23:48:49 +00:00
|
|
|
|
2008-07-31 07:04:58 +00:00
|
|
|
/*
|
|
|
|
* Atomically disable the present bit and get the old value.
|
|
|
|
*/
|
|
|
|
do
|
|
|
|
{
|
2004-09-09 20:42:33 +00:00
|
|
|
Pte = *Pt;
|
2008-08-16 01:58:59 +00:00
|
|
|
} while (Pte != InterlockedCompareExchangePte(Pt, Pte & ~PA_PRESENT, Pte));
|
2011-12-25 18:21:05 +00:00
|
|
|
|
2011-12-29 23:48:49 +00:00
|
|
|
MiFlushTlb(Pt, Address);
|
2011-12-25 18:21:05 +00:00
|
|
|
|
2011-12-29 23:48:49 +00:00
|
|
|
WasValid = (Pte & PA_PRESENT);
|
2008-07-31 07:04:58 +00:00
|
|
|
if (!WasValid)
|
|
|
|
{
|
2008-11-26 18:56:41 +00:00
|
|
|
KeBugCheck(MEMORY_MANAGEMENT);
|
2008-07-31 07:04:58 +00:00
|
|
|
}
|
2011-12-25 18:21:05 +00:00
|
|
|
|
2008-07-31 07:04:58 +00:00
|
|
|
/*
|
|
|
|
* Return some information to the caller
|
|
|
|
*/
|
|
|
|
if (WasDirty != NULL)
|
|
|
|
{
|
|
|
|
*WasDirty = Pte & PA_DIRTY;
|
|
|
|
}
|
|
|
|
if (Page != NULL)
|
|
|
|
{
|
|
|
|
*Page = PTE_TO_PFN(Pte);
|
|
|
|
}
|
2001-12-31 01:53:46 +00:00
|
|
|
}
|
2002-11-05 21:13:15 +00:00
|
|
|
|
2003-07-13 14:36:32 +00:00
|
|
|
VOID
|
2005-09-14 01:05:50 +00:00
|
|
|
NTAPI
|
2003-07-13 14:36:32 +00:00
|
|
|
MmRawDeleteVirtualMapping(PVOID Address)
|
|
|
|
{
|
2008-07-31 07:04:58 +00:00
|
|
|
PULONG Pt;
|
2011-12-25 18:21:05 +00:00
|
|
|
|
2008-07-31 07:04:58 +00:00
|
|
|
Pt = MmGetPageTableForProcess(NULL, Address, FALSE);
|
|
|
|
if (Pt && *Pt)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Set the entry to zero
|
|
|
|
*/
|
2008-08-16 01:58:59 +00:00
|
|
|
InterlockedExchangePte(Pt, 0);
|
2008-07-31 07:04:58 +00:00
|
|
|
MiFlushTlb(Pt, Address);
|
|
|
|
}
|
2003-07-13 14:36:32 +00:00
|
|
|
}
|
|
|
|
|
2001-03-25 03:34:30 +00:00
|
|
|
VOID
|
2005-09-14 01:05:50 +00:00
|
|
|
NTAPI
|
2006-05-18 20:32:17 +00:00
|
|
|
MmDeleteVirtualMapping(PEPROCESS Process, PVOID Address, BOOLEAN FreePage,
|
2010-07-15 22:50:12 +00:00
|
|
|
BOOLEAN* WasDirty, PPFN_NUMBER Page)
|
2000-08-20 17:02:10 +00:00
|
|
|
/*
|
2005-05-09 01:38:29 +00:00
|
|
|
* FUNCTION: Delete a virtual mapping
|
2000-08-20 17:02:10 +00:00
|
|
|
*/
|
1999-11-12 12:01:17 +00:00
|
|
|
{
|
2008-07-31 07:04:58 +00:00
|
|
|
BOOLEAN WasValid = FALSE;
|
2010-07-15 22:50:12 +00:00
|
|
|
PFN_NUMBER Pfn;
|
2008-07-31 07:04:58 +00:00
|
|
|
ULONG Pte;
|
|
|
|
PULONG Pt;
|
2011-12-25 18:21:05 +00:00
|
|
|
|
2008-07-31 07:04:58 +00:00
|
|
|
DPRINT("MmDeleteVirtualMapping(%x, %x, %d, %x, %x)\n",
|
|
|
|
Process, Address, FreePage, WasDirty, Page);
|
2011-12-25 18:21:05 +00:00
|
|
|
|
2008-07-31 07:04:58 +00:00
|
|
|
Pt = MmGetPageTableForProcess(Process, Address, FALSE);
|
2011-12-25 18:21:05 +00:00
|
|
|
|
2008-07-31 07:04:58 +00:00
|
|
|
if (Pt == NULL)
|
|
|
|
{
|
|
|
|
if (WasDirty != NULL)
|
|
|
|
{
|
2004-09-09 20:42:33 +00:00
|
|
|
*WasDirty = FALSE;
|
2008-07-31 07:04:58 +00:00
|
|
|
}
|
|
|
|
if (Page != NULL)
|
|
|
|
{
|
2004-09-09 20:42:33 +00:00
|
|
|
*Page = 0;
|
2008-07-31 07:04:58 +00:00
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
2011-12-25 18:21:05 +00:00
|
|
|
|
2008-07-31 07:04:58 +00:00
|
|
|
/*
|
|
|
|
* Atomically set the entry to zero and get the old value.
|
|
|
|
*/
|
2008-08-16 01:58:59 +00:00
|
|
|
Pte = InterlockedExchangePte(Pt, 0);
|
2011-12-25 18:21:05 +00:00
|
|
|
|
2011-12-29 23:48:49 +00:00
|
|
|
WasValid = (Pte & PA_PRESENT);
|
2008-07-31 07:04:58 +00:00
|
|
|
if (WasValid)
|
|
|
|
{
|
2011-12-26 23:12:38 +00:00
|
|
|
/* Flush the TLB since we transitioned this PTE
|
|
|
|
* from valid to invalid so any stale translations
|
|
|
|
* are removed from the cache */
|
2011-11-22 22:01:06 +00:00
|
|
|
MiFlushTlb(Pt, Address);
|
2011-12-26 23:12:38 +00:00
|
|
|
|
|
|
|
Pfn = PTE_TO_PFN(Pte);
|
|
|
|
|
|
|
|
if (FreePage)
|
|
|
|
{
|
|
|
|
MmReleasePageMemoryConsumer(MC_SYSTEM, Pfn);
|
|
|
|
Pfn = 0;
|
|
|
|
}
|
2008-07-31 07:04:58 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2011-11-22 22:01:06 +00:00
|
|
|
MmUnmapPageTable(Pt);
|
2011-12-26 23:12:38 +00:00
|
|
|
Pfn = 0;
|
2008-07-31 07:04:58 +00:00
|
|
|
}
|
2011-12-25 18:21:05 +00:00
|
|
|
|
2008-07-31 07:04:58 +00:00
|
|
|
/*
|
|
|
|
* Return some information to the caller
|
|
|
|
*/
|
|
|
|
if (WasDirty != NULL)
|
|
|
|
{
|
|
|
|
*WasDirty = Pte & PA_DIRTY ? TRUE : FALSE;
|
|
|
|
}
|
|
|
|
if (Page != NULL)
|
|
|
|
{
|
|
|
|
*Page = Pfn;
|
|
|
|
}
|
1999-11-12 12:01:17 +00:00
|
|
|
}
|
|
|
|
|
[CACHE]
The cache manager rewrite I started years ago has finally appeared in
ReactOS' trunk and although at this point it's not quite perfectly
integrated, it's enough to boot up the bootcd or livecd. To check out
the more mature original, check out arty-newcc-reactos, branch
arty-newcc on bitbucket.org . Amine Khaldi encouraged me quite a bit
to not give up on it, and was able to reach out and be an advocate
when i really wasn't able to. Others agree that the time has come to
begin removing the old cache manager. I expect the remaining problems
in the version going to trunk will be taken care of relatively
quickly.
The motivation for this effort lies in the particularly hairy
relationship between ReactOS' cache manager and data sections. This
code completely removes page sharing between cache manager and section
and reimagines cache manager as being a facility layered on the memory
manager, not really caring about individual pages, but simply managing
data section objects where caching might occur.
It took me about 2 years to do the first pass of this rewrite and most
of this year to fix some lingering issues, properly implement demand
paging in ReactOS (code which didn't come with this patch in a
recognizable form), and finish getting the PrivateCacheMap and
SharedCacheMap relationship correct.
Currently, the new ntoskrnl/cache directory contains an own
implementation of data file sections. After things have settled down,
we can begin to deprecate and remove the parts of ReactOS' section
implementation that depend on a close relationship with cache
manager. Eventually, I think that the extra code added to
ntoskrnl/cache/section will be removed and ReactOS' own sections will
replace the use of the special MM_CACHE_SECTION_SEGMENT in the cache
path.
Note also, that this makes all cache manager (and new section parts)
use wide file offsets. If my section code were to take over other
parts of the ReactOS memory manager, they would also benefit from
these improvements.
I invite anyone who wants to to peek at this code and fix whatever
bugs can be found.
svn path=/trunk/; revision=49423
2010-11-02 02:32:39 +00:00
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
MmGetPageFileMapping(PEPROCESS Process, PVOID Address,
|
2011-12-25 18:21:05 +00:00
|
|
|
SWAPENTRY* SwapEntry)
|
[CACHE]
The cache manager rewrite I started years ago has finally appeared in
ReactOS' trunk and although at this point it's not quite perfectly
integrated, it's enough to boot up the bootcd or livecd. To check out
the more mature original, check out arty-newcc-reactos, branch
arty-newcc on bitbucket.org . Amine Khaldi encouraged me quite a bit
to not give up on it, and was able to reach out and be an advocate
when i really wasn't able to. Others agree that the time has come to
begin removing the old cache manager. I expect the remaining problems
in the version going to trunk will be taken care of relatively
quickly.
The motivation for this effort lies in the particularly hairy
relationship between ReactOS' cache manager and data sections. This
code completely removes page sharing between cache manager and section
and reimagines cache manager as being a facility layered on the memory
manager, not really caring about individual pages, but simply managing
data section objects where caching might occur.
It took me about 2 years to do the first pass of this rewrite and most
of this year to fix some lingering issues, properly implement demand
paging in ReactOS (code which didn't come with this patch in a
recognizable form), and finish getting the PrivateCacheMap and
SharedCacheMap relationship correct.
Currently, the new ntoskrnl/cache directory contains an own
implementation of data file sections. After things have settled down,
we can begin to deprecate and remove the parts of ReactOS' section
implementation that depend on a close relationship with cache
manager. Eventually, I think that the extra code added to
ntoskrnl/cache/section will be removed and ReactOS' own sections will
replace the use of the special MM_CACHE_SECTION_SEGMENT in the cache
path.
Note also, that this makes all cache manager (and new section parts)
use wide file offsets. If my section code were to take over other
parts of the ReactOS memory manager, they would also benefit from
these improvements.
I invite anyone who wants to to peek at this code and fix whatever
bugs can be found.
svn path=/trunk/; revision=49423
2010-11-02 02:32:39 +00:00
|
|
|
/*
|
|
|
|
* FUNCTION: Get a page file mapping
|
|
|
|
*/
|
|
|
|
{
|
2011-12-25 18:21:05 +00:00
|
|
|
ULONG Entry = MmGetPageEntryForProcess(Process, Address);
|
|
|
|
*SwapEntry = Entry >> 1;
|
[CACHE]
The cache manager rewrite I started years ago has finally appeared in
ReactOS' trunk and although at this point it's not quite perfectly
integrated, it's enough to boot up the bootcd or livecd. To check out
the more mature original, check out arty-newcc-reactos, branch
arty-newcc on bitbucket.org . Amine Khaldi encouraged me quite a bit
to not give up on it, and was able to reach out and be an advocate
when i really wasn't able to. Others agree that the time has come to
begin removing the old cache manager. I expect the remaining problems
in the version going to trunk will be taken care of relatively
quickly.
The motivation for this effort lies in the particularly hairy
relationship between ReactOS' cache manager and data sections. This
code completely removes page sharing between cache manager and section
and reimagines cache manager as being a facility layered on the memory
manager, not really caring about individual pages, but simply managing
data section objects where caching might occur.
It took me about 2 years to do the first pass of this rewrite and most
of this year to fix some lingering issues, properly implement demand
paging in ReactOS (code which didn't come with this patch in a
recognizable form), and finish getting the PrivateCacheMap and
SharedCacheMap relationship correct.
Currently, the new ntoskrnl/cache directory contains an own
implementation of data file sections. After things have settled down,
we can begin to deprecate and remove the parts of ReactOS' section
implementation that depend on a close relationship with cache
manager. Eventually, I think that the extra code added to
ntoskrnl/cache/section will be removed and ReactOS' own sections will
replace the use of the special MM_CACHE_SECTION_SEGMENT in the cache
path.
Note also, that this makes all cache manager (and new section parts)
use wide file offsets. If my section code were to take over other
parts of the ReactOS memory manager, they would also benefit from
these improvements.
I invite anyone who wants to to peek at this code and fix whatever
bugs can be found.
svn path=/trunk/; revision=49423
2010-11-02 02:32:39 +00:00
|
|
|
}
|
|
|
|
|
2001-12-31 19:06:49 +00:00
|
|
|
VOID
|
2005-09-14 01:05:50 +00:00
|
|
|
NTAPI
|
2006-05-18 20:32:17 +00:00
|
|
|
MmDeletePageFileMapping(PEPROCESS Process, PVOID Address,
|
2004-04-10 22:36:07 +00:00
|
|
|
SWAPENTRY* SwapEntry)
|
2001-12-31 19:06:49 +00:00
|
|
|
/*
|
2005-05-09 01:38:29 +00:00
|
|
|
* FUNCTION: Delete a virtual mapping
|
2001-12-31 19:06:49 +00:00
|
|
|
*/
|
|
|
|
{
|
2008-07-31 07:04:58 +00:00
|
|
|
ULONG Pte;
|
|
|
|
PULONG Pt;
|
2011-12-25 18:21:05 +00:00
|
|
|
|
2008-07-31 07:04:58 +00:00
|
|
|
Pt = MmGetPageTableForProcess(Process, Address, FALSE);
|
2011-12-25 18:21:05 +00:00
|
|
|
|
2008-07-31 07:04:58 +00:00
|
|
|
if (Pt == NULL)
|
|
|
|
{
|
|
|
|
*SwapEntry = 0;
|
|
|
|
return;
|
|
|
|
}
|
2011-12-25 18:21:05 +00:00
|
|
|
|
2008-07-31 07:04:58 +00:00
|
|
|
/*
|
|
|
|
* Atomically set the entry to zero and get the old value.
|
|
|
|
*/
|
2008-08-16 01:58:59 +00:00
|
|
|
Pte = InterlockedExchangePte(Pt, 0);
|
2011-12-25 18:21:05 +00:00
|
|
|
|
2011-12-26 23:12:38 +00:00
|
|
|
/* We don't need to flush here because page file entries
|
|
|
|
* are invalid translations, so the processor won't cache them */
|
2011-11-22 22:01:06 +00:00
|
|
|
MmUnmapPageTable(Pt);
|
2011-12-25 18:21:05 +00:00
|
|
|
|
2011-12-29 23:48:49 +00:00
|
|
|
if (Pte & PA_PRESENT)
|
2011-11-22 22:01:06 +00:00
|
|
|
{
|
|
|
|
KeBugCheck(MEMORY_MANAGEMENT);
|
|
|
|
}
|
2011-12-25 18:21:05 +00:00
|
|
|
|
2008-07-31 07:04:58 +00:00
|
|
|
/*
|
|
|
|
* Return some information to the caller
|
|
|
|
*/
|
|
|
|
*SwapEntry = Pte >> 1;
|
2001-12-31 19:06:49 +00:00
|
|
|
}
|
|
|
|
|
2004-04-10 22:36:07 +00:00
|
|
|
BOOLEAN
|
2001-02-18 22:16:05 +00:00
|
|
|
Mmi386MakeKernelPageTableGlobal(PVOID PAddress)
|
|
|
|
{
|
2008-07-31 07:04:58 +00:00
|
|
|
PULONG Pt, Pde;
|
|
|
|
Pde = (PULONG)MiAddressToPde(PAddress);
|
|
|
|
if (*Pde == 0)
|
|
|
|
{
|
|
|
|
Pt = MmGetPageTableForProcess(NULL, PAddress, FALSE);
|
|
|
|
if (Pt != NULL)
|
|
|
|
{
|
2004-09-09 20:42:33 +00:00
|
|
|
return TRUE;
|
2008-07-31 07:04:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return(FALSE);
|
1999-11-12 12:01:17 +00:00
|
|
|
}
|
|
|
|
|
2005-09-14 01:05:50 +00:00
|
|
|
BOOLEAN
|
|
|
|
NTAPI
|
2006-05-18 20:32:17 +00:00
|
|
|
MmIsDirtyPage(PEPROCESS Process, PVOID Address)
|
2000-06-25 03:59:17 +00:00
|
|
|
{
|
2008-07-31 07:04:58 +00:00
|
|
|
return MmGetPageEntryForProcess(Process, Address) & PA_DIRTY ? TRUE : FALSE;
|
2000-06-25 03:59:17 +00:00
|
|
|
}
|
|
|
|
|
2005-09-14 01:05:50 +00:00
|
|
|
VOID
|
|
|
|
NTAPI
|
2006-05-18 20:32:17 +00:00
|
|
|
MmSetCleanPage(PEPROCESS Process, PVOID Address)
|
2000-07-07 10:30:57 +00:00
|
|
|
{
|
2008-02-28 14:05:47 +00:00
|
|
|
PULONG Pt;
|
|
|
|
ULONG Pte;
|
2011-12-25 18:21:05 +00:00
|
|
|
|
2008-02-28 14:05:47 +00:00
|
|
|
if (Address < MmSystemRangeStart && Process == NULL)
|
|
|
|
{
|
|
|
|
DPRINT1("MmSetCleanPage is called for user space without a process.\n");
|
2008-11-26 18:56:41 +00:00
|
|
|
KeBugCheck(MEMORY_MANAGEMENT);
|
2008-02-28 14:05:47 +00:00
|
|
|
}
|
2011-12-25 18:21:05 +00:00
|
|
|
|
2008-02-28 14:05:47 +00:00
|
|
|
Pt = MmGetPageTableForProcess(Process, Address, FALSE);
|
|
|
|
if (Pt == NULL)
|
|
|
|
{
|
2008-11-26 18:56:41 +00:00
|
|
|
KeBugCheck(MEMORY_MANAGEMENT);
|
2008-02-28 14:05:47 +00:00
|
|
|
}
|
2011-12-25 18:21:05 +00:00
|
|
|
|
2008-02-28 14:05:47 +00:00
|
|
|
do
|
|
|
|
{
|
|
|
|
Pte = *Pt;
|
2008-08-16 01:58:59 +00:00
|
|
|
} while (Pte != InterlockedCompareExchangePte(Pt, Pte & ~PA_DIRTY, Pte));
|
2011-12-25 18:21:05 +00:00
|
|
|
|
2011-12-29 23:48:49 +00:00
|
|
|
if (!(Pte & PA_PRESENT))
|
|
|
|
{
|
|
|
|
KeBugCheck(MEMORY_MANAGEMENT);
|
|
|
|
}
|
|
|
|
else if (Pte & PA_DIRTY)
|
2008-02-28 14:05:47 +00:00
|
|
|
{
|
|
|
|
MiFlushTlb(Pt, Address);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
MmUnmapPageTable(Pt);
|
|
|
|
}
|
2000-07-07 10:30:57 +00:00
|
|
|
}
|
|
|
|
|
2005-09-14 01:05:50 +00:00
|
|
|
VOID
|
|
|
|
NTAPI
|
2006-05-18 20:32:17 +00:00
|
|
|
MmSetDirtyPage(PEPROCESS Process, PVOID Address)
|
2002-01-08 00:49:02 +00:00
|
|
|
{
|
2008-07-31 07:04:58 +00:00
|
|
|
PULONG Pt;
|
|
|
|
ULONG Pte;
|
2011-12-25 18:21:05 +00:00
|
|
|
|
2008-07-31 07:04:58 +00:00
|
|
|
if (Address < MmSystemRangeStart && Process == NULL)
|
|
|
|
{
|
|
|
|
DPRINT1("MmSetDirtyPage is called for user space without a process.\n");
|
2008-11-26 18:56:41 +00:00
|
|
|
KeBugCheck(MEMORY_MANAGEMENT);
|
2008-07-31 07:04:58 +00:00
|
|
|
}
|
2011-12-25 18:21:05 +00:00
|
|
|
|
2008-07-31 07:04:58 +00:00
|
|
|
Pt = MmGetPageTableForProcess(Process, Address, FALSE);
|
|
|
|
if (Pt == NULL)
|
|
|
|
{
|
2008-11-26 18:56:41 +00:00
|
|
|
KeBugCheck(MEMORY_MANAGEMENT);
|
2008-07-31 07:04:58 +00:00
|
|
|
}
|
2011-12-25 18:21:05 +00:00
|
|
|
|
2008-07-31 07:04:58 +00:00
|
|
|
do
|
|
|
|
{
|
|
|
|
Pte = *Pt;
|
2008-08-16 01:58:59 +00:00
|
|
|
} while (Pte != InterlockedCompareExchangePte(Pt, Pte | PA_DIRTY, Pte));
|
2011-12-29 23:48:49 +00:00
|
|
|
|
|
|
|
if (!(Pte & PA_PRESENT))
|
|
|
|
{
|
|
|
|
KeBugCheck(MEMORY_MANAGEMENT);
|
|
|
|
}
|
|
|
|
else if (!(Pte & PA_DIRTY))
|
2008-07-31 07:04:58 +00:00
|
|
|
{
|
|
|
|
MiFlushTlb(Pt, Address);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
MmUnmapPageTable(Pt);
|
|
|
|
}
|
2008-02-15 06:53:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
MmEnableVirtualMapping(PEPROCESS Process, PVOID Address)
|
|
|
|
{
|
2008-07-31 07:04:58 +00:00
|
|
|
PULONG Pt;
|
|
|
|
ULONG Pte;
|
2011-12-25 18:21:05 +00:00
|
|
|
|
2008-07-31 07:04:58 +00:00
|
|
|
Pt = MmGetPageTableForProcess(Process, Address, FALSE);
|
|
|
|
if (Pt == NULL)
|
|
|
|
{
|
2011-11-22 22:01:06 +00:00
|
|
|
//HACK to get DPH working, waiting for MM rewrite :-/
|
|
|
|
//KeBugCheck(MEMORY_MANAGEMENT);
|
|
|
|
return;
|
2008-07-31 07:04:58 +00:00
|
|
|
}
|
2011-12-25 18:21:05 +00:00
|
|
|
|
2011-11-22 22:01:06 +00:00
|
|
|
/* Do not mark a 0 page as present */
|
|
|
|
if(0 == InterlockedCompareExchangePte(Pt, 0, 0))
|
|
|
|
return;
|
2011-12-25 18:21:05 +00:00
|
|
|
|
2008-07-31 07:04:58 +00:00
|
|
|
do
|
|
|
|
{
|
|
|
|
Pte = *Pt;
|
2008-08-16 01:58:59 +00:00
|
|
|
} while (Pte != InterlockedCompareExchangePte(Pt, Pte | PA_PRESENT, Pte));
|
2011-12-26 23:12:38 +00:00
|
|
|
|
|
|
|
/* We don't need to flush the TLB here because it
|
|
|
|
* won't cache translations for non-present pages */
|
|
|
|
MmUnmapPageTable(Pt);
|
2001-12-31 01:53:46 +00:00
|
|
|
}
|
2002-11-05 21:13:15 +00:00
|
|
|
|
2005-09-14 01:05:50 +00:00
|
|
|
BOOLEAN
|
|
|
|
NTAPI
|
2006-05-18 20:32:17 +00:00
|
|
|
MmIsPagePresent(PEPROCESS Process, PVOID Address)
|
1999-11-12 12:01:17 +00:00
|
|
|
{
|
2009-02-19 11:47:34 +00:00
|
|
|
return MmGetPageEntryForProcess(Process, Address) & PA_PRESENT;
|
1999-11-12 12:01:17 +00:00
|
|
|
}
|
|
|
|
|
2005-09-14 01:05:50 +00:00
|
|
|
BOOLEAN
|
|
|
|
NTAPI
|
2006-05-18 20:32:17 +00:00
|
|
|
MmIsPageSwapEntry(PEPROCESS Process, PVOID Address)
|
2001-12-31 19:06:49 +00:00
|
|
|
{
|
2008-07-31 07:04:58 +00:00
|
|
|
ULONG Entry;
|
|
|
|
Entry = MmGetPageEntryForProcess(Process, Address);
|
2011-12-29 23:48:49 +00:00
|
|
|
return !(Entry & PA_PRESENT) && Entry != 0;
|
2001-12-31 19:06:49 +00:00
|
|
|
}
|
|
|
|
|
2004-04-10 22:36:07 +00:00
|
|
|
NTSTATUS
|
2005-09-14 01:05:50 +00:00
|
|
|
NTAPI
|
2006-05-18 20:32:17 +00:00
|
|
|
MmCreatePageFileMapping(PEPROCESS Process,
|
2004-04-10 22:36:07 +00:00
|
|
|
PVOID Address,
|
|
|
|
SWAPENTRY SwapEntry)
|
2001-12-31 19:06:49 +00:00
|
|
|
{
|
2008-07-31 07:04:58 +00:00
|
|
|
PULONG Pt;
|
|
|
|
ULONG Pte;
|
2011-12-25 18:21:05 +00:00
|
|
|
|
2008-07-31 07:04:58 +00:00
|
|
|
if (Process == NULL && Address < MmSystemRangeStart)
|
|
|
|
{
|
|
|
|
DPRINT1("No process\n");
|
2008-11-26 18:56:41 +00:00
|
|
|
KeBugCheck(MEMORY_MANAGEMENT);
|
2008-07-31 07:04:58 +00:00
|
|
|
}
|
|
|
|
if (Process != NULL && Address >= MmSystemRangeStart)
|
|
|
|
{
|
|
|
|
DPRINT1("Setting kernel address with process context\n");
|
2008-11-26 18:56:41 +00:00
|
|
|
KeBugCheck(MEMORY_MANAGEMENT);
|
2008-07-31 07:04:58 +00:00
|
|
|
}
|
2009-03-10 20:52:39 +00:00
|
|
|
|
2008-07-31 07:04:58 +00:00
|
|
|
if (SwapEntry & (1 << 31))
|
|
|
|
{
|
2008-11-26 18:56:41 +00:00
|
|
|
KeBugCheck(MEMORY_MANAGEMENT);
|
2008-07-31 07:04:58 +00:00
|
|
|
}
|
2011-12-25 18:21:05 +00:00
|
|
|
|
2008-07-31 07:04:58 +00:00
|
|
|
Pt = MmGetPageTableForProcess(Process, Address, TRUE);
|
|
|
|
if (Pt == NULL)
|
|
|
|
{
|
2008-11-26 18:56:41 +00:00
|
|
|
KeBugCheck(MEMORY_MANAGEMENT);
|
2008-07-31 07:04:58 +00:00
|
|
|
}
|
2011-11-22 22:01:06 +00:00
|
|
|
Pte = InterlockedExchangePte(Pt, SwapEntry << 1);
|
2011-12-29 23:48:49 +00:00
|
|
|
if (Pte != 0)
|
2011-11-22 22:01:06 +00:00
|
|
|
{
|
|
|
|
KeBugCheck(MEMORY_MANAGEMENT);
|
|
|
|
}
|
2011-12-26 23:12:38 +00:00
|
|
|
|
|
|
|
/* We don't need to flush the TLB here because it
|
|
|
|
* only caches valid translations and a zero PTE
|
|
|
|
* is not a valid translation */
|
2011-11-22 22:01:06 +00:00
|
|
|
MmUnmapPageTable(Pt);
|
2011-12-25 18:21:05 +00:00
|
|
|
|
2008-07-31 07:04:58 +00:00
|
|
|
return(STATUS_SUCCESS);
|
2001-12-31 19:06:49 +00:00
|
|
|
}
|
|
|
|
|
2003-08-27 21:28:08 +00:00
|
|
|
|
2004-04-10 22:36:07 +00:00
|
|
|
NTSTATUS
|
2005-09-14 01:05:50 +00:00
|
|
|
NTAPI
|
2006-05-18 20:32:17 +00:00
|
|
|
MmCreateVirtualMappingUnsafe(PEPROCESS Process,
|
2004-04-10 22:36:07 +00:00
|
|
|
PVOID Address,
|
|
|
|
ULONG flProtect,
|
2010-07-15 22:50:12 +00:00
|
|
|
PPFN_NUMBER Pages,
|
2004-08-01 07:27:25 +00:00
|
|
|
ULONG PageCount)
|
1999-11-12 12:01:17 +00:00
|
|
|
{
|
2008-07-31 07:04:58 +00:00
|
|
|
ULONG Attributes;
|
|
|
|
PVOID Addr;
|
|
|
|
ULONG i;
|
|
|
|
ULONG oldPdeOffset, PdeOffset;
|
|
|
|
PULONG Pt = NULL;
|
|
|
|
ULONG Pte;
|
|
|
|
DPRINT("MmCreateVirtualMappingUnsafe(%x, %x, %x, %x (%x), %d)\n",
|
|
|
|
Process, Address, flProtect, Pages, *Pages, PageCount);
|
2011-12-25 18:21:05 +00:00
|
|
|
|
2011-11-15 23:50:04 +00:00
|
|
|
ASSERT(((ULONG_PTR)Address % PAGE_SIZE) == 0);
|
2011-12-25 18:21:05 +00:00
|
|
|
|
2008-07-31 07:04:58 +00:00
|
|
|
if (Process == NULL)
|
|
|
|
{
|
|
|
|
if (Address < MmSystemRangeStart)
|
|
|
|
{
|
|
|
|
DPRINT1("No process\n");
|
2008-11-26 18:56:41 +00:00
|
|
|
KeBugCheck(MEMORY_MANAGEMENT);
|
2008-07-31 07:04:58 +00:00
|
|
|
}
|
|
|
|
if (PageCount > 0x10000 ||
|
|
|
|
(ULONG_PTR) Address / PAGE_SIZE + PageCount > 0x100000)
|
|
|
|
{
|
2009-02-19 11:47:34 +00:00
|
|
|
DPRINT1("Page count too large\n");
|
2008-11-26 18:56:41 +00:00
|
|
|
KeBugCheck(MEMORY_MANAGEMENT);
|
2008-07-31 07:04:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (Address >= MmSystemRangeStart)
|
|
|
|
{
|
|
|
|
DPRINT1("Setting kernel address with process context\n");
|
2008-11-26 18:56:41 +00:00
|
|
|
KeBugCheck(MEMORY_MANAGEMENT);
|
2008-07-31 07:04:58 +00:00
|
|
|
}
|
|
|
|
if (PageCount > (ULONG_PTR)MmSystemRangeStart / PAGE_SIZE ||
|
|
|
|
(ULONG_PTR) Address / PAGE_SIZE + PageCount >
|
|
|
|
(ULONG_PTR)MmSystemRangeStart / PAGE_SIZE)
|
|
|
|
{
|
2009-02-19 11:47:34 +00:00
|
|
|
DPRINT1("Page Count too large\n");
|
2008-11-26 18:56:41 +00:00
|
|
|
KeBugCheck(MEMORY_MANAGEMENT);
|
2008-07-31 07:04:58 +00:00
|
|
|
}
|
|
|
|
}
|
2011-12-25 18:21:05 +00:00
|
|
|
|
2008-07-31 07:04:58 +00:00
|
|
|
Attributes = ProtectToPTE(flProtect);
|
|
|
|
Attributes &= 0xfff;
|
|
|
|
if (Address >= MmSystemRangeStart)
|
|
|
|
{
|
|
|
|
Attributes &= ~PA_USER;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Attributes |= PA_USER;
|
|
|
|
}
|
2011-12-25 18:21:05 +00:00
|
|
|
|
2008-07-31 07:04:58 +00:00
|
|
|
Addr = Address;
|
2011-11-15 23:50:04 +00:00
|
|
|
/* MmGetPageTableForProcess should be called on the first run, so
|
|
|
|
* let this trigger it */
|
2008-07-31 07:04:58 +00:00
|
|
|
oldPdeOffset = ADDR_TO_PDE_OFFSET(Addr) + 1;
|
|
|
|
for (i = 0; i < PageCount; i++, Addr = (PVOID)((ULONG_PTR)Addr + PAGE_SIZE))
|
|
|
|
{
|
|
|
|
if (!(Attributes & PA_PRESENT) && Pages[i] != 0)
|
|
|
|
{
|
2004-09-09 20:42:33 +00:00
|
|
|
DPRINT1("Setting physical address but not allowing access at address "
|
|
|
|
"0x%.8X with attributes %x/%x.\n",
|
|
|
|
Addr, Attributes, flProtect);
|
2008-11-26 18:56:41 +00:00
|
|
|
KeBugCheck(MEMORY_MANAGEMENT);
|
2008-07-31 07:04:58 +00:00
|
|
|
}
|
|
|
|
PdeOffset = ADDR_TO_PDE_OFFSET(Addr);
|
|
|
|
if (oldPdeOffset != PdeOffset)
|
|
|
|
{
|
2011-11-15 23:50:04 +00:00
|
|
|
if(Pt) MmUnmapPageTable(Pt);
|
2008-07-31 07:04:58 +00:00
|
|
|
Pt = MmGetPageTableForProcess(Process, Addr, TRUE);
|
|
|
|
if (Pt == NULL)
|
|
|
|
{
|
2008-11-26 18:56:41 +00:00
|
|
|
KeBugCheck(MEMORY_MANAGEMENT);
|
2008-07-31 07:04:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2004-09-09 20:42:33 +00:00
|
|
|
Pt++;
|
2008-07-31 07:04:58 +00:00
|
|
|
}
|
|
|
|
oldPdeOffset = PdeOffset;
|
2011-12-25 18:21:05 +00:00
|
|
|
|
2011-12-26 23:12:38 +00:00
|
|
|
Pte = InterlockedExchangePte(Pt, PFN_TO_PTE(Pages[i]) | Attributes);
|
2011-12-29 23:48:49 +00:00
|
|
|
|
2011-11-15 22:34:04 +00:00
|
|
|
/* There should not be anything valid here */
|
2011-12-29 23:48:49 +00:00
|
|
|
if (Pte != 0)
|
2008-07-31 07:04:58 +00:00
|
|
|
{
|
2009-02-19 11:47:34 +00:00
|
|
|
DPRINT1("Bad PTE %lx\n", Pte);
|
2008-11-26 18:56:41 +00:00
|
|
|
KeBugCheck(MEMORY_MANAGEMENT);
|
2008-07-31 07:04:58 +00:00
|
|
|
}
|
2011-12-26 23:12:38 +00:00
|
|
|
|
|
|
|
/* We don't need to flush the TLB here because it only caches valid translations
|
|
|
|
* and we're moving this PTE from invalid to valid so it can't be cached right now */
|
2008-07-31 07:04:58 +00:00
|
|
|
}
|
2011-12-25 18:21:05 +00:00
|
|
|
|
2011-11-15 23:50:04 +00:00
|
|
|
ASSERT(Addr > Address);
|
|
|
|
MmUnmapPageTable(Pt);
|
2011-12-25 18:21:05 +00:00
|
|
|
|
2008-07-31 07:04:58 +00:00
|
|
|
return(STATUS_SUCCESS);
|
1999-11-12 12:01:17 +00:00
|
|
|
}
|
|
|
|
|
2004-04-10 22:36:07 +00:00
|
|
|
NTSTATUS
|
2005-09-14 01:05:50 +00:00
|
|
|
NTAPI
|
2006-05-18 20:32:17 +00:00
|
|
|
MmCreateVirtualMapping(PEPROCESS Process,
|
2004-04-10 22:36:07 +00:00
|
|
|
PVOID Address,
|
|
|
|
ULONG flProtect,
|
2010-07-15 22:50:12 +00:00
|
|
|
PPFN_NUMBER Pages,
|
2004-08-01 07:27:25 +00:00
|
|
|
ULONG PageCount)
|
2001-03-26 20:46:53 +00:00
|
|
|
{
|
2008-07-31 07:04:58 +00:00
|
|
|
ULONG i;
|
2011-12-25 18:21:05 +00:00
|
|
|
|
2008-07-31 07:04:58 +00:00
|
|
|
for (i = 0; i < PageCount; i++)
|
|
|
|
{
|
|
|
|
if (!MmIsPageInUse(Pages[i]))
|
|
|
|
{
|
|
|
|
DPRINT1("Page at address %x not in use\n", PFN_TO_PTE(Pages[i]));
|
2008-11-26 18:56:41 +00:00
|
|
|
KeBugCheck(MEMORY_MANAGEMENT);
|
2008-07-31 07:04:58 +00:00
|
|
|
}
|
|
|
|
}
|
2011-12-25 18:21:05 +00:00
|
|
|
|
2008-07-31 07:04:58 +00:00
|
|
|
return(MmCreateVirtualMappingUnsafe(Process,
|
|
|
|
Address,
|
|
|
|
flProtect,
|
|
|
|
Pages,
|
|
|
|
PageCount));
|
2001-03-26 20:46:53 +00:00
|
|
|
}
|
|
|
|
|
2001-02-10 22:51:11 +00:00
|
|
|
ULONG
|
2005-09-14 01:05:50 +00:00
|
|
|
NTAPI
|
2006-05-18 20:32:17 +00:00
|
|
|
MmGetPageProtect(PEPROCESS Process, PVOID Address)
|
2001-02-10 22:51:11 +00:00
|
|
|
{
|
2008-07-31 07:04:58 +00:00
|
|
|
ULONG Entry;
|
|
|
|
ULONG Protect;
|
2011-12-25 18:21:05 +00:00
|
|
|
|
2008-07-31 07:04:58 +00:00
|
|
|
Entry = MmGetPageEntryForProcess(Process, Address);
|
2011-12-25 18:21:05 +00:00
|
|
|
|
|
|
|
|
2008-07-31 07:04:58 +00:00
|
|
|
if (!(Entry & PA_PRESENT))
|
|
|
|
{
|
|
|
|
Protect = PAGE_NOACCESS;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (Entry & PA_READWRITE)
|
|
|
|
{
|
|
|
|
Protect = PAGE_READWRITE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Protect = PAGE_EXECUTE_READ;
|
|
|
|
}
|
|
|
|
if (Entry & PA_CD)
|
|
|
|
{
|
|
|
|
Protect |= PAGE_NOCACHE;
|
|
|
|
}
|
|
|
|
if (Entry & PA_WT)
|
|
|
|
{
|
|
|
|
Protect |= PAGE_WRITETHROUGH;
|
|
|
|
}
|
|
|
|
if (!(Entry & PA_USER))
|
|
|
|
{
|
|
|
|
Protect |= PAGE_SYSTEM;
|
|
|
|
}
|
2011-12-25 18:21:05 +00:00
|
|
|
|
2008-07-31 07:04:58 +00:00
|
|
|
}
|
|
|
|
return(Protect);
|
2001-02-10 22:51:11 +00:00
|
|
|
}
|
|
|
|
|
2004-04-10 22:36:07 +00:00
|
|
|
VOID
|
2005-09-14 01:05:50 +00:00
|
|
|
NTAPI
|
2006-05-18 20:32:17 +00:00
|
|
|
MmSetPageProtect(PEPROCESS Process, PVOID Address, ULONG flProtect)
|
1999-11-12 12:01:17 +00:00
|
|
|
{
|
2008-07-31 07:04:58 +00:00
|
|
|
ULONG Attributes = 0;
|
|
|
|
PULONG Pt;
|
2011-11-22 22:01:06 +00:00
|
|
|
ULONG Pte;
|
2011-12-25 18:21:05 +00:00
|
|
|
|
2008-07-31 07:04:58 +00:00
|
|
|
DPRINT("MmSetPageProtect(Process %x Address %x flProtect %x)\n",
|
|
|
|
Process, Address, flProtect);
|
2011-12-25 18:21:05 +00:00
|
|
|
|
2008-07-31 07:04:58 +00:00
|
|
|
Attributes = ProtectToPTE(flProtect);
|
2009-02-19 11:47:34 +00:00
|
|
|
|
2008-07-31 07:04:58 +00:00
|
|
|
Attributes &= 0xfff;
|
|
|
|
if (Address >= MmSystemRangeStart)
|
|
|
|
{
|
|
|
|
Attributes &= ~PA_USER;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Attributes |= PA_USER;
|
|
|
|
}
|
2011-12-25 18:21:05 +00:00
|
|
|
|
2008-07-31 07:04:58 +00:00
|
|
|
Pt = MmGetPageTableForProcess(Process, Address, FALSE);
|
|
|
|
if (Pt == NULL)
|
|
|
|
{
|
2008-11-26 18:56:41 +00:00
|
|
|
KeBugCheck(MEMORY_MANAGEMENT);
|
2008-07-31 07:04:58 +00:00
|
|
|
}
|
2011-11-22 22:01:06 +00:00
|
|
|
Pte = InterlockedExchangePte(Pt, PAGE_MASK(*Pt) | Attributes | (*Pt & (PA_ACCESSED|PA_DIRTY)));
|
2011-12-25 18:21:05 +00:00
|
|
|
|
2011-12-29 23:48:49 +00:00
|
|
|
if (!(Pte & PA_PRESENT))
|
2011-11-22 22:01:06 +00:00
|
|
|
{
|
|
|
|
DPRINT1("Invalid Pte %lx\n", Pte);
|
2011-12-26 23:12:38 +00:00
|
|
|
KeBugCheck(MEMORY_MANAGEMENT);
|
2011-11-22 22:01:06 +00:00
|
|
|
}
|
2011-12-26 23:12:38 +00:00
|
|
|
|
2011-11-22 22:01:06 +00:00
|
|
|
if((Pte & Attributes) != Attributes)
|
|
|
|
MiFlushTlb(Pt, Address);
|
|
|
|
else
|
|
|
|
MmUnmapPageTable(Pt);
|
1999-11-12 12:01:17 +00:00
|
|
|
}
|
|
|
|
|
2003-07-11 01:23:16 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2008-11-29 20:47:48 +00:00
|
|
|
PHYSICAL_ADDRESS NTAPI
|
2001-01-08 02:14:06 +00:00
|
|
|
MmGetPhysicalAddress(PVOID vaddr)
|
1999-11-12 12:01:17 +00:00
|
|
|
/*
|
|
|
|
* FUNCTION: Returns the physical address corresponding to a virtual address
|
|
|
|
*/
|
|
|
|
{
|
2008-07-31 07:04:58 +00:00
|
|
|
PHYSICAL_ADDRESS p;
|
|
|
|
ULONG Pte;
|
2011-12-25 18:21:05 +00:00
|
|
|
|
2008-07-31 07:04:58 +00:00
|
|
|
DPRINT("MmGetPhysicalAddress(vaddr %x)\n", vaddr);
|
|
|
|
Pte = MmGetPageEntryForProcess(NULL, vaddr);
|
2011-12-26 23:12:38 +00:00
|
|
|
if (Pte != 0 && (Pte & PA_PRESENT))
|
2008-07-31 07:04:58 +00:00
|
|
|
{
|
|
|
|
p.QuadPart = PAGE_MASK(Pte);
|
|
|
|
p.u.LowPart |= (ULONG_PTR)vaddr & (PAGE_SIZE - 1);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
p.QuadPart = 0;
|
|
|
|
}
|
|
|
|
return p;
|
1999-11-12 12:01:17 +00:00
|
|
|
}
|
2000-04-02 13:32:43 +00:00
|
|
|
|
2005-09-14 01:05:50 +00:00
|
|
|
VOID
|
|
|
|
INIT_FUNCTION
|
|
|
|
NTAPI
|
2004-09-09 20:42:33 +00:00
|
|
|
MmInitGlobalKernelPageDirectory(VOID)
|
|
|
|
{
|
2008-07-31 07:04:58 +00:00
|
|
|
ULONG i;
|
|
|
|
PULONG CurrentPageDirectory = (PULONG)PAGEDIRECTORY_MAP;
|
2011-12-25 18:21:05 +00:00
|
|
|
|
2008-07-31 07:04:58 +00:00
|
|
|
DPRINT("MmInitGlobalKernelPageDirectory()\n");
|
2011-12-25 18:21:05 +00:00
|
|
|
|
2008-07-31 07:04:58 +00:00
|
|
|
for (i = ADDR_TO_PDE_OFFSET(MmSystemRangeStart); i < 1024; i++)
|
|
|
|
{
|
|
|
|
if (i != ADDR_TO_PDE_OFFSET(PAGETABLE_MAP) &&
|
|
|
|
i != ADDR_TO_PDE_OFFSET(HYPERSPACE) &&
|
|
|
|
0 == MmGlobalKernelPageDirectory[i] && 0 != CurrentPageDirectory[i])
|
|
|
|
{
|
2004-09-09 20:42:33 +00:00
|
|
|
MmGlobalKernelPageDirectory[i] = CurrentPageDirectory[i];
|
2008-07-31 07:04:58 +00:00
|
|
|
}
|
|
|
|
}
|
2003-05-07 21:41:03 +00:00
|
|
|
}
|
2004-09-09 20:42:33 +00:00
|
|
|
|
2000-04-02 13:32:43 +00:00
|
|
|
/* EOF */
|