2005-01-05 19:27:58 +00:00
|
|
|
/* $Id$
|
2000-04-02 13:32:43 +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
|
|
|
|
#include <internal/debug.h>
|
|
|
|
|
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)
|
2004-08-14 09:17: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
|
|
|
|
2005-07-06 00:29:39 +00:00
|
|
|
#define PAGETABLE_MAP (0xc0000000)
|
|
|
|
#define PAGEDIRECTORY_MAP (0xc0000000 + (PAGETABLE_MAP / (1024)))
|
1999-11-12 12:01:17 +00:00
|
|
|
|
2005-07-06 00:29:39 +00:00
|
|
|
#define PAE_PAGEDIRECTORY_MAP (0xc0000000 + (PAGETABLE_MAP / (512)))
|
2004-09-09 20:42:33 +00:00
|
|
|
|
2005-07-06 00:29:39 +00:00
|
|
|
#define HYPERSPACE (Ke386Pae ? 0xc0800000 : 0xc0400000)
|
2005-07-16 09:01:07 +00:00
|
|
|
#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];
|
2004-10-05 18:53:28 +00:00
|
|
|
ULONGLONG MmGlobalKernelPageDirectoryForPAE[2048];
|
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
|
|
|
|
2004-09-09 20:42:33 +00:00
|
|
|
#define PAE_PTE_TO_PFN(X) (PAE_PAGE_MASK(X) >> PAGE_SHIFT)
|
|
|
|
#define PAE_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)
|
|
|
|
{
|
2004-04-10 22:36:07 +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
|
|
|
|
2004-09-26 16:32:18 +00:00
|
|
|
extern BOOLEAN Ke386Pae;
|
|
|
|
extern BOOLEAN Ke386NoExecute;
|
2004-08-14 09:17:05 +00:00
|
|
|
|
1999-11-12 12:01:17 +00:00
|
|
|
/* FUNCTIONS ***************************************************************/
|
|
|
|
|
2004-11-27 16:37:52 +00:00
|
|
|
BOOLEAN MmUnmapPageTable(PULONG Pt);
|
|
|
|
|
2007-11-06 14:34:32 +00:00
|
|
|
ULONG_PTR
|
|
|
|
NTAPI
|
|
|
|
MiFlushTlbIpiRoutine(ULONG_PTR Address)
|
2004-11-27 16:37:52 +00:00
|
|
|
{
|
2007-11-06 14:34:32 +00:00
|
|
|
if (Address == (ULONG_PTR)-1)
|
2004-11-27 16:37:52 +00:00
|
|
|
{
|
|
|
|
KeFlushCurrentTb();
|
|
|
|
}
|
2007-11-06 14:34:32 +00:00
|
|
|
else if (Address == (ULONG_PTR)-2)
|
2004-11-27 16:37:52 +00:00
|
|
|
{
|
2006-10-25 18:23:45 +00:00
|
|
|
KeFlushCurrentTb();
|
2004-11-27 16:37:52 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2007-11-06 14:34:32 +00:00
|
|
|
__invlpg((PVOID)Address);
|
2004-11-27 16:37:52 +00:00
|
|
|
}
|
2007-11-06 14:34:32 +00:00
|
|
|
return 0;
|
2004-11-27 16:37:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
|
|
MiFlushTlb(PULONG Pt, PVOID Address)
|
|
|
|
{
|
2005-01-05 19:27:58 +00:00
|
|
|
#ifdef CONFIG_SMP
|
2004-11-27 16:37:52 +00:00
|
|
|
if (Pt)
|
|
|
|
{
|
|
|
|
MmUnmapPageTable(Pt);
|
|
|
|
}
|
2007-11-06 14:34:32 +00:00
|
|
|
if (KeNumberProcessors > 1)
|
2004-11-27 16:37:52 +00:00
|
|
|
{
|
2007-11-06 14:34:32 +00:00
|
|
|
KeIpiGenericCall(MiFlushTlbIpiRoutine, (ULONG_PTR)Address);
|
2004-11-27 16:37:52 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2007-11-06 14:34:32 +00:00
|
|
|
MiFlushTlbIpiRoutine((ULONG_PTR)Address);
|
2004-11-27 16:37:52 +00:00
|
|
|
}
|
|
|
|
#else
|
2005-07-06 08:20:26 +00:00
|
|
|
if ((Pt && MmUnmapPageTable(Pt)) || Address >= MmSystemRangeStart)
|
2004-11-27 16:37:52 +00:00
|
|
|
{
|
2006-10-25 18:23:45 +00:00
|
|
|
__invlpg(Address);
|
2004-11-27 16:37:52 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2004-04-10 22:36:07 +00:00
|
|
|
PULONG
|
2001-01-08 02:14:06 +00:00
|
|
|
MmGetPageDirectory(VOID)
|
2000-10-07 13:41:58 +00:00
|
|
|
{
|
2006-10-25 17:15:11 +00:00
|
|
|
return (PULONG)__readcr3();
|
2000-10-07 13:41:58 +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
|
|
|
{
|
2004-04-10 22:36:07 +00:00
|
|
|
ULONG Attributes = 0;
|
|
|
|
|
2004-08-01 07:27:25 +00:00
|
|
|
if (flProtect & (PAGE_NOACCESS|PAGE_GUARD))
|
2004-04-10 22:36:07 +00:00
|
|
|
{
|
2001-01-08 02:14:06 +00:00
|
|
|
Attributes = 0;
|
2004-04-10 22:36:07 +00:00
|
|
|
}
|
2004-12-30 08:05:12 +00:00
|
|
|
else if (flProtect & PAGE_IS_WRITABLE)
|
2004-04-10 22:36:07 +00:00
|
|
|
{
|
2002-01-01 03:29:16 +00:00
|
|
|
Attributes = PA_PRESENT | PA_READWRITE;
|
2004-04-10 22:36:07 +00:00
|
|
|
}
|
2004-12-30 08:05:12 +00:00
|
|
|
else if (flProtect & (PAGE_IS_READABLE | PAGE_IS_EXECUTABLE))
|
2004-04-10 22:36:07 +00:00
|
|
|
{
|
|
|
|
Attributes = PA_PRESENT;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2002-01-01 03:29:16 +00:00
|
|
|
DPRINT1("Unknown main protection type.\n");
|
2003-07-21 21:53:53 +00:00
|
|
|
KEBUGCHECK(0);
|
2004-04-10 22:36:07 +00:00
|
|
|
}
|
2005-05-09 01:38:29 +00:00
|
|
|
if (Ke386NoExecute &&
|
2004-12-30 08:05:12 +00:00
|
|
|
!(flProtect & PAGE_IS_EXECUTABLE))
|
2004-09-26 16:32:18 +00:00
|
|
|
{
|
|
|
|
Attributes = Attributes | 0x80000000;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (flProtect & PAGE_SYSTEM)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
else
|
2004-04-10 22:36:07 +00:00
|
|
|
{
|
2002-01-01 03:29:16 +00:00
|
|
|
Attributes = Attributes | PA_USER;
|
2004-04-10 22:36:07 +00:00
|
|
|
}
|
|
|
|
if (flProtect & PAGE_NOCACHE)
|
|
|
|
{
|
2002-01-01 03:29:16 +00:00
|
|
|
Attributes = Attributes | PA_CD;
|
2004-04-10 22:36:07 +00:00
|
|
|
}
|
|
|
|
if (flProtect & PAGE_WRITETHROUGH)
|
|
|
|
{
|
2002-01-01 03:29:16 +00:00
|
|
|
Attributes = Attributes | PA_WT;
|
2004-04-10 22:36:07 +00:00
|
|
|
}
|
|
|
|
return(Attributes);
|
1999-11-12 12:01:17 +00:00
|
|
|
}
|
|
|
|
|
2004-09-07 11:08:16 +00:00
|
|
|
#define ADDR_TO_PAGE_TABLE(v) (((ULONG)(v)) / (1024 * PAGE_SIZE))
|
2000-08-20 17:02:10 +00:00
|
|
|
|
1999-11-12 12:01:17 +00:00
|
|
|
#define ADDR_TO_PDE(v) (PULONG)(PAGEDIRECTORY_MAP + \
|
2003-06-01 19:50:04 +00:00
|
|
|
((((ULONG)(v)) / (1024 * 1024))&(~0x3)))
|
2004-01-05 14:28:21 +00:00
|
|
|
#define ADDR_TO_PTE(v) (PULONG)(PAGETABLE_MAP + ((((ULONG)(v) / 1024))&(~0x3)))
|
1999-11-12 12:01:17 +00:00
|
|
|
|
2004-09-07 11:08:16 +00:00
|
|
|
#define ADDR_TO_PDE_OFFSET(v) ((((ULONG)(v)) / (1024 * PAGE_SIZE)))
|
|
|
|
|
2005-05-09 01:38:29 +00:00
|
|
|
#define ADDR_TO_PTE_OFFSET(v) ((((ULONG)(v)) % (1024 * PAGE_SIZE)) / PAGE_SIZE)
|
2001-02-18 22:16:05 +00:00
|
|
|
|
2004-09-09 20:42:33 +00:00
|
|
|
|
|
|
|
#define PAE_ADDR_TO_PAGE_TABLE(v) (((ULONG)(v)) / (512 * PAGE_SIZE))
|
|
|
|
|
|
|
|
#define PAE_ADDR_TO_PDE(v) (PULONGLONG) (PAE_PAGEDIRECTORY_MAP + \
|
|
|
|
((((ULONG_PTR)(v)) / (512 * 512))&(~0x7)))
|
|
|
|
#define PAE_ADDR_TO_PTE(v) (PULONGLONG) (PAGETABLE_MAP + ((((ULONG_PTR)(v) / 512))&(~0x7)))
|
|
|
|
|
|
|
|
|
|
|
|
#define PAE_ADDR_TO_PDTE_OFFSET(v) (((ULONG_PTR)(v)) / (512 * 512 * PAGE_SIZE))
|
|
|
|
|
2004-10-05 18:53:28 +00:00
|
|
|
#define PAE_ADDR_TO_PDE_PAGE_OFFSET(v) ((((ULONG_PTR)(v)) % (512 * 512 * PAGE_SIZE)) / (512 * PAGE_SIZE))
|
|
|
|
|
|
|
|
#define PAE_ADDR_TO_PDE_OFFSET(v) (((ULONG_PTR)(v))/ (512 * PAGE_SIZE))
|
2004-09-09 20:42:33 +00:00
|
|
|
|
|
|
|
#define PAE_ADDR_TO_PTE_OFFSET(v) ((((ULONG_PTR)(v)) % (512 * PAGE_SIZE)) / PAGE_SIZE)
|
|
|
|
|
|
|
|
|
2005-09-14 01:05:50 +00:00
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
2006-05-18 20:32:17 +00:00
|
|
|
Mmi386ReleaseMmInfo(PEPROCESS Process)
|
1999-11-12 12:01:17 +00:00
|
|
|
{
|
2003-08-21 04:17:15 +00:00
|
|
|
PUSHORT LdtDescriptor;
|
|
|
|
ULONG LdtBase;
|
2004-09-07 11:08:16 +00:00
|
|
|
ULONG i, j;
|
2003-08-21 04:17:15 +00:00
|
|
|
|
1999-11-12 12:01:17 +00:00
|
|
|
DPRINT("Mmi386ReleaseMmInfo(Process %x)\n",Process);
|
2003-08-19 23:59:08 +00:00
|
|
|
|
2005-05-05 22:40:05 +00:00
|
|
|
LdtDescriptor = (PUSHORT) &Process->Pcb.LdtDescriptor;
|
2003-08-21 04:17:15 +00:00
|
|
|
LdtBase = LdtDescriptor[1] |
|
2004-04-10 22:36:07 +00:00
|
|
|
((LdtDescriptor[2] & 0xff) << 16) |
|
|
|
|
((LdtDescriptor[3] & ~0xff) << 16);
|
2003-08-19 23:59:08 +00:00
|
|
|
|
|
|
|
DPRINT("LdtBase: %x\n", LdtBase);
|
2004-04-10 22:36:07 +00:00
|
|
|
|
2003-08-19 23:59:08 +00:00
|
|
|
if (LdtBase)
|
2004-04-10 22:36:07 +00:00
|
|
|
{
|
|
|
|
ExFreePool((PVOID) LdtBase);
|
|
|
|
}
|
2004-09-09 20:42:33 +00:00
|
|
|
|
2004-09-26 16:32:18 +00:00
|
|
|
if (Ke386Pae)
|
2004-09-07 11:08:16 +00:00
|
|
|
{
|
2004-09-09 20:42:33 +00:00
|
|
|
PULONGLONG PageDirTable;
|
|
|
|
PULONGLONG PageDir;
|
|
|
|
PULONGLONG Pde;
|
|
|
|
ULONG k;
|
|
|
|
|
2005-01-25 22:50:47 +00:00
|
|
|
PageDirTable = (PULONGLONG)MmCreateHyperspaceMapping(PAE_PTE_TO_PFN(Process->Pcb.DirectoryTableBase.QuadPart));
|
2004-09-09 20:42:33 +00:00
|
|
|
for (i = 0; i < 4; i++)
|
2004-09-07 11:08:16 +00:00
|
|
|
{
|
2005-01-25 22:50:47 +00:00
|
|
|
PageDir = (PULONGLONG)MmCreateHyperspaceMapping(PAE_PTE_TO_PFN(PageDirTable[i]));
|
2005-07-06 08:20:26 +00:00
|
|
|
if (i < PAE_ADDR_TO_PDTE_OFFSET(MmSystemRangeStart))
|
2004-09-07 11:08:16 +00:00
|
|
|
{
|
2004-09-09 20:42:33 +00:00
|
|
|
for (j = 0; j < 512; j++)
|
2004-09-07 11:08:16 +00:00
|
|
|
{
|
2004-09-09 20:42:33 +00:00
|
|
|
if (PageDir[j] != 0LL)
|
2004-09-07 11:08:16 +00:00
|
|
|
{
|
2005-05-09 01:38:29 +00:00
|
|
|
DPRINT1("ProcessId %d, Pde for %08x - %08x is not freed, RefCount %d\n",
|
2004-09-09 20:42:33 +00:00
|
|
|
Process->UniqueProcessId,
|
2005-05-09 01:38:29 +00:00
|
|
|
(i * 512 + j) * 512 * PAGE_SIZE, (i * 512 + j + 1) * 512 * PAGE_SIZE - 1,
|
2006-05-18 20:10:44 +00:00
|
|
|
((PMADDRESS_SPACE)&Process->VadRoot)->PageTableRefCountTable[i*512 + j]);
|
2005-01-25 22:50:47 +00:00
|
|
|
Pde = MmCreateHyperspaceMapping(PAE_PTE_TO_PFN(PageDir[j]));
|
2004-09-09 20:42:33 +00:00
|
|
|
for (k = 0; k < 512; k++)
|
|
|
|
{
|
|
|
|
if(Pde[k] != 0)
|
|
|
|
{
|
|
|
|
if (Pde[k] & PA_PRESENT)
|
|
|
|
{
|
|
|
|
DPRINT1("Page at %08x is not freed\n",
|
|
|
|
(i * 512 + j) * 512 * PAGE_SIZE + k * PAGE_SIZE);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
DPRINT1("Swapentry %x at %x is not freed\n",
|
|
|
|
(i * 512 + j) * 512 * PAGE_SIZE + k * PAGE_SIZE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2005-01-25 22:50:47 +00:00
|
|
|
MmDeleteHyperspaceMapping(Pde);
|
2004-09-09 20:42:33 +00:00
|
|
|
MmReleasePageMemoryConsumer(MC_NPPOOL, PAE_PTE_TO_PFN(PageDir[j]));
|
2004-09-07 11:08:16 +00:00
|
|
|
}
|
2004-09-09 20:42:33 +00:00
|
|
|
}
|
|
|
|
}
|
2005-01-26 19:43:03 +00:00
|
|
|
if (i == PAE_ADDR_TO_PDTE_OFFSET(HYPERSPACE))
|
2005-01-25 22:50:47 +00:00
|
|
|
{
|
|
|
|
MmReleasePageMemoryConsumer(MC_NPPOOL, PAE_PTE_TO_PFN(PageDir[PAE_ADDR_TO_PDE_PAGE_OFFSET(HYPERSPACE)]));
|
|
|
|
MmReleasePageMemoryConsumer(MC_NPPOOL, PAE_PTE_TO_PFN(PageDir[PAE_ADDR_TO_PDE_PAGE_OFFSET(HYPERSPACE)+1]));
|
|
|
|
}
|
|
|
|
MmDeleteHyperspaceMapping(PageDir);
|
|
|
|
MmReleasePageMemoryConsumer(MC_NPPOOL, PAE_PTE_TO_PFN(PageDirTable[i]));
|
2004-09-09 20:42:33 +00:00
|
|
|
}
|
2005-01-25 22:50:47 +00:00
|
|
|
MmDeleteHyperspaceMapping((PVOID)PageDirTable);
|
|
|
|
MmReleasePageMemoryConsumer(MC_NPPOOL, PAE_PTE_TO_PFN(Process->Pcb.DirectoryTableBase.QuadPart));
|
2004-09-09 20:42:33 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
PULONG Pde;
|
|
|
|
PULONG PageDir;
|
2005-01-25 22:50:47 +00:00
|
|
|
PageDir = MmCreateHyperspaceMapping(PTE_TO_PFN(Process->Pcb.DirectoryTableBase.u.LowPart));
|
2005-07-06 08:20:26 +00:00
|
|
|
for (i = 0; i < ADDR_TO_PDE_OFFSET(MmSystemRangeStart); i++)
|
2004-09-09 20:42:33 +00:00
|
|
|
{
|
|
|
|
if (PageDir[i] != 0)
|
|
|
|
{
|
2005-05-09 01:38:29 +00:00
|
|
|
DPRINT1("Pde for %08x - %08x is not freed, RefCount %d\n",
|
|
|
|
i * 4 * 1024 * 1024, (i + 1) * 4 * 1024 * 1024 - 1,
|
2006-05-18 20:10:44 +00:00
|
|
|
((PMADDRESS_SPACE)&Process->VadRoot)->PageTableRefCountTable[i]);
|
2005-01-25 22:50:47 +00:00
|
|
|
Pde = MmCreateHyperspaceMapping(PTE_TO_PFN(PageDir[i]));
|
2004-09-09 20:42:33 +00:00
|
|
|
for (j = 0; j < 1024; j++)
|
|
|
|
{
|
|
|
|
if(Pde[j] != 0)
|
2004-09-07 11:08:16 +00:00
|
|
|
{
|
2004-09-09 20:42:33 +00:00
|
|
|
if (Pde[j] & PA_PRESENT)
|
|
|
|
{
|
|
|
|
DPRINT1("Page at %08x is not freed\n",
|
|
|
|
i * 4 * 1024 * 1024 + j * PAGE_SIZE);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
DPRINT1("Swapentry %x at %x is not freed\n",
|
|
|
|
Pde[j], i * 4 * 1024 * 1024 + j * PAGE_SIZE);
|
|
|
|
}
|
2004-09-07 11:08:16 +00:00
|
|
|
}
|
|
|
|
}
|
2005-01-25 22:50:47 +00:00
|
|
|
MmDeleteHyperspaceMapping(Pde);
|
2004-09-09 20:42:33 +00:00
|
|
|
MmReleasePageMemoryConsumer(MC_NPPOOL, PTE_TO_PFN(PageDir[i]));
|
2004-09-07 11:08:16 +00:00
|
|
|
}
|
|
|
|
}
|
2005-01-25 22:50:47 +00:00
|
|
|
MmReleasePageMemoryConsumer(MC_NPPOOL, PTE_TO_PFN(PageDir[ADDR_TO_PDE_OFFSET(HYPERSPACE)]));
|
|
|
|
MmDeleteHyperspaceMapping(PageDir);
|
|
|
|
MmReleasePageMemoryConsumer(MC_NPPOOL, PTE_TO_PFN(Process->Pcb.DirectoryTableBase.u.LowPart));
|
2004-09-07 11:08:16 +00:00
|
|
|
}
|
2004-04-10 22:36:07 +00:00
|
|
|
|
2003-12-30 18:52:06 +00:00
|
|
|
#if defined(__GNUC__)
|
2004-04-10 22:36:07 +00:00
|
|
|
|
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
|
|
|
Process->Pcb.DirectoryTableBase.QuadPart = 0LL;
|
2003-12-30 18:52:06 +00:00
|
|
|
#else
|
2004-04-10 22:36:07 +00:00
|
|
|
|
2003-12-30 18:52:06 +00:00
|
|
|
Process->Pcb.DirectoryTableBase.QuadPart = 0;
|
|
|
|
#endif
|
2004-04-10 22:36:07 +00:00
|
|
|
|
1999-11-12 12:01:17 +00:00
|
|
|
DPRINT("Finished Mmi386ReleaseMmInfo()\n");
|
|
|
|
return(STATUS_SUCCESS);
|
|
|
|
}
|
|
|
|
|
2005-05-09 01:38:29 +00:00
|
|
|
NTSTATUS
|
- PS_UNKNOWN_VALUE determines if the process should be created with large pages: rename to PS_LARGE_PAGES
- Do Address Space initialization as per "Windows Internals II" slides, either for the Boot, System, Cloned User or New User Process cases.
- Rename MmCreateProcessAddressSpace to MmInitializeProcessAddressSpace, and MmCopyMmInfo to MmCreateProcessAddressSpace. What ReactOS did is correct as per "Windows Internals II", but the names were inverted.
- Clone the Object Table if we are the boot process, and only initialize part of the address space (since we don't need things like guard page, TEB, etc), however, do initialize and map the shared user data section.
- Make the initial system process and idle process share the same page directory instead of creating a new one.
- Use the same priority class as the parent process, if the process was in the idle or below-normal priority class.
- Only duplicate handles if the caller requested it, instead of always duplicating the process's handles!
- Generate a null image file name for system processes.
- Rename ObpCreateHandleTable to ObInitProcess and better handle race and out-of-memory conditions. Detect if auditing required, but don't do anything about it.
- Initialize the Idle/System process address space much earlier in the boot process, in MmInitSystem.
Thanks to Alex for providing various information, and answering all my questions.
svn path=/trunk/; revision=29223
2007-09-26 20:55:26 +00:00
|
|
|
NTAPI
|
|
|
|
MmInitializeHandBuiltProcess(IN PEPROCESS Process,
|
|
|
|
IN PLARGE_INTEGER DirectoryTableBase)
|
|
|
|
{
|
|
|
|
/* Share the directory base with the idle process */
|
|
|
|
*DirectoryTableBase = PsGetCurrentProcess()->Pcb.DirectoryTableBase;
|
|
|
|
|
|
|
|
/* Initialize the Addresss Space */
|
|
|
|
MmInitializeAddressSpace(Process, (PMADDRESS_SPACE)&Process->VadRoot);
|
|
|
|
|
|
|
|
/* The process now has an address space */
|
|
|
|
Process->HasAddressSpace = TRUE;
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOLEAN
|
2005-04-18 00:42:31 +00:00
|
|
|
STDCALL
|
- PS_UNKNOWN_VALUE determines if the process should be created with large pages: rename to PS_LARGE_PAGES
- Do Address Space initialization as per "Windows Internals II" slides, either for the Boot, System, Cloned User or New User Process cases.
- Rename MmCreateProcessAddressSpace to MmInitializeProcessAddressSpace, and MmCopyMmInfo to MmCreateProcessAddressSpace. What ReactOS did is correct as per "Windows Internals II", but the names were inverted.
- Clone the Object Table if we are the boot process, and only initialize part of the address space (since we don't need things like guard page, TEB, etc), however, do initialize and map the shared user data section.
- Make the initial system process and idle process share the same page directory instead of creating a new one.
- Use the same priority class as the parent process, if the process was in the idle or below-normal priority class.
- Only duplicate handles if the caller requested it, instead of always duplicating the process's handles!
- Generate a null image file name for system processes.
- Rename ObpCreateHandleTable to ObInitProcess and better handle race and out-of-memory conditions. Detect if auditing required, but don't do anything about it.
- Initialize the Idle/System process address space much earlier in the boot process, in MmInitSystem.
Thanks to Alex for providing various information, and answering all my questions.
svn path=/trunk/; revision=29223
2007-09-26 20:55:26 +00:00
|
|
|
MmCreateProcessAddressSpace(IN ULONG MinWs,
|
|
|
|
IN PEPROCESS Process,
|
|
|
|
IN PLARGE_INTEGER DirectoryTableBase)
|
1999-11-12 12:01:17 +00:00
|
|
|
{
|
2005-01-25 22:50:47 +00:00
|
|
|
NTSTATUS Status;
|
|
|
|
ULONG i, j;
|
|
|
|
PFN_TYPE Pfn[7];
|
|
|
|
ULONG Count;
|
2005-05-09 01:38:29 +00:00
|
|
|
|
- PS_UNKNOWN_VALUE determines if the process should be created with large pages: rename to PS_LARGE_PAGES
- Do Address Space initialization as per "Windows Internals II" slides, either for the Boot, System, Cloned User or New User Process cases.
- Rename MmCreateProcessAddressSpace to MmInitializeProcessAddressSpace, and MmCopyMmInfo to MmCreateProcessAddressSpace. What ReactOS did is correct as per "Windows Internals II", but the names were inverted.
- Clone the Object Table if we are the boot process, and only initialize part of the address space (since we don't need things like guard page, TEB, etc), however, do initialize and map the shared user data section.
- Make the initial system process and idle process share the same page directory instead of creating a new one.
- Use the same priority class as the parent process, if the process was in the idle or below-normal priority class.
- Only duplicate handles if the caller requested it, instead of always duplicating the process's handles!
- Generate a null image file name for system processes.
- Rename ObpCreateHandleTable to ObInitProcess and better handle race and out-of-memory conditions. Detect if auditing required, but don't do anything about it.
- Initialize the Idle/System process address space much earlier in the boot process, in MmInitSystem.
Thanks to Alex for providing various information, and answering all my questions.
svn path=/trunk/; revision=29223
2007-09-26 20:55:26 +00:00
|
|
|
DPRINT("MmCopyMmInfo(Src %x, Dest %x)\n", MinWs, Process);
|
2004-04-10 22:36:07 +00:00
|
|
|
|
2005-01-25 22:50:47 +00:00
|
|
|
Count = Ke386Pae ? 7 : 2;
|
|
|
|
|
|
|
|
for (i = 0; i < Count; i++)
|
|
|
|
{
|
|
|
|
Status = MmRequestPageMemoryConsumer(MC_NPPOOL, FALSE, &Pfn[i]);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
- PS_UNKNOWN_VALUE determines if the process should be created with large pages: rename to PS_LARGE_PAGES
- Do Address Space initialization as per "Windows Internals II" slides, either for the Boot, System, Cloned User or New User Process cases.
- Rename MmCreateProcessAddressSpace to MmInitializeProcessAddressSpace, and MmCopyMmInfo to MmCreateProcessAddressSpace. What ReactOS did is correct as per "Windows Internals II", but the names were inverted.
- Clone the Object Table if we are the boot process, and only initialize part of the address space (since we don't need things like guard page, TEB, etc), however, do initialize and map the shared user data section.
- Make the initial system process and idle process share the same page directory instead of creating a new one.
- Use the same priority class as the parent process, if the process was in the idle or below-normal priority class.
- Only duplicate handles if the caller requested it, instead of always duplicating the process's handles!
- Generate a null image file name for system processes.
- Rename ObpCreateHandleTable to ObInitProcess and better handle race and out-of-memory conditions. Detect if auditing required, but don't do anything about it.
- Initialize the Idle/System process address space much earlier in the boot process, in MmInitSystem.
Thanks to Alex for providing various information, and answering all my questions.
svn path=/trunk/; revision=29223
2007-09-26 20:55:26 +00:00
|
|
|
for (j = 0; j < i; j++)
|
|
|
|
{
|
|
|
|
MmReleasePageMemoryConsumer(MC_NPPOOL, Pfn[j]);
|
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
2005-01-25 22:50:47 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-09-26 16:32:18 +00:00
|
|
|
if (Ke386Pae)
|
2004-04-10 22:36:07 +00:00
|
|
|
{
|
2004-09-09 20:42:33 +00:00
|
|
|
PULONGLONG PageDirTable;
|
|
|
|
PULONGLONG PageDir;
|
|
|
|
|
2005-01-25 22:50:47 +00:00
|
|
|
PageDirTable = MmCreateHyperspaceMapping(Pfn[0]);
|
2004-09-09 20:42:33 +00:00
|
|
|
for (i = 0; i < 4; i++)
|
|
|
|
{
|
2005-01-25 22:50:47 +00:00
|
|
|
PageDirTable[i] = PAE_PFN_TO_PTE(Pfn[1+i]) | PA_PRESENT;
|
2004-09-09 20:42:33 +00:00
|
|
|
}
|
2005-01-25 22:50:47 +00:00
|
|
|
MmDeleteHyperspaceMapping(PageDirTable);
|
2005-07-06 08:20:26 +00:00
|
|
|
for (i = PAE_ADDR_TO_PDTE_OFFSET(MmSystemRangeStart); i < 4; i++)
|
2004-09-09 20:42:33 +00:00
|
|
|
{
|
2005-01-25 22:50:47 +00:00
|
|
|
PageDir = (PULONGLONG)MmCreateHyperspaceMapping(Pfn[i+1]);
|
2004-10-05 18:53:28 +00:00
|
|
|
memcpy(PageDir, &MmGlobalKernelPageDirectoryForPAE[i * 512], 512 * sizeof(ULONGLONG));
|
|
|
|
if (PAE_ADDR_TO_PDTE_OFFSET(PAGETABLE_MAP) == i)
|
2004-09-09 20:42:33 +00:00
|
|
|
{
|
2004-10-05 18:53:28 +00:00
|
|
|
for (j = 0; j < 4; j++)
|
|
|
|
{
|
2005-01-25 22:50:47 +00:00
|
|
|
PageDir[PAE_ADDR_TO_PDE_PAGE_OFFSET(PAGETABLE_MAP) + j] = PAE_PFN_TO_PTE(Pfn[1+j]) | PA_PRESENT | PA_READWRITE;
|
2004-10-05 18:53:28 +00:00
|
|
|
}
|
2004-09-09 20:42:33 +00:00
|
|
|
}
|
2005-01-25 22:50:47 +00:00
|
|
|
if (PAE_ADDR_TO_PDTE_OFFSET(HYPERSPACE) == i)
|
|
|
|
{
|
|
|
|
PageDir[PAE_ADDR_TO_PDE_PAGE_OFFSET(HYPERSPACE)] = PAE_PFN_TO_PTE(Pfn[5]) | PA_PRESENT | PA_READWRITE;
|
|
|
|
PageDir[PAE_ADDR_TO_PDE_PAGE_OFFSET(HYPERSPACE)+1] = PAE_PFN_TO_PTE(Pfn[6]) | PA_PRESENT | PA_READWRITE;
|
|
|
|
}
|
|
|
|
MmDeleteHyperspaceMapping(PageDir);
|
2004-09-09 20:42:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
PULONG PageDirectory;
|
2005-01-25 22:50:47 +00:00
|
|
|
PageDirectory = MmCreateHyperspaceMapping(Pfn[0]);
|
2003-05-17 13:45:04 +00:00
|
|
|
|
2005-07-06 08:20:26 +00:00
|
|
|
memcpy(PageDirectory + ADDR_TO_PDE_OFFSET(MmSystemRangeStart),
|
|
|
|
MmGlobalKernelPageDirectory + ADDR_TO_PDE_OFFSET(MmSystemRangeStart),
|
|
|
|
(1024 - ADDR_TO_PDE_OFFSET(MmSystemRangeStart)) * sizeof(ULONG));
|
2004-04-10 22:36:07 +00:00
|
|
|
|
2005-01-25 22:50:47 +00:00
|
|
|
DPRINT("Addr %x\n",ADDR_TO_PDE_OFFSET(PAGETABLE_MAP));
|
|
|
|
PageDirectory[ADDR_TO_PDE_OFFSET(PAGETABLE_MAP)] = PFN_TO_PTE(Pfn[0]) | PA_PRESENT | PA_READWRITE;
|
|
|
|
PageDirectory[ADDR_TO_PDE_OFFSET(HYPERSPACE)] = PFN_TO_PTE(Pfn[1]) | PA_PRESENT | PA_READWRITE;
|
2004-04-10 22:36:07 +00:00
|
|
|
|
2005-01-25 22:50:47 +00:00
|
|
|
MmDeleteHyperspaceMapping(PageDirectory);
|
2004-09-09 20:42:33 +00:00
|
|
|
}
|
2005-04-18 00:42:31 +00:00
|
|
|
|
|
|
|
DirectoryTableBase->QuadPart = PFN_TO_PTE(Pfn[0]);
|
|
|
|
DPRINT("Finished MmCopyMmInfo(): %I64x\n", DirectoryTableBase->QuadPart);
|
- PS_UNKNOWN_VALUE determines if the process should be created with large pages: rename to PS_LARGE_PAGES
- Do Address Space initialization as per "Windows Internals II" slides, either for the Boot, System, Cloned User or New User Process cases.
- Rename MmCreateProcessAddressSpace to MmInitializeProcessAddressSpace, and MmCopyMmInfo to MmCreateProcessAddressSpace. What ReactOS did is correct as per "Windows Internals II", but the names were inverted.
- Clone the Object Table if we are the boot process, and only initialize part of the address space (since we don't need things like guard page, TEB, etc), however, do initialize and map the shared user data section.
- Make the initial system process and idle process share the same page directory instead of creating a new one.
- Use the same priority class as the parent process, if the process was in the idle or below-normal priority class.
- Only duplicate handles if the caller requested it, instead of always duplicating the process's handles!
- Generate a null image file name for system processes.
- Rename ObpCreateHandleTable to ObInitProcess and better handle race and out-of-memory conditions. Detect if auditing required, but don't do anything about it.
- Initialize the Idle/System process address space much earlier in the boot process, in MmInitSystem.
Thanks to Alex for providing various information, and answering all my questions.
svn path=/trunk/; revision=29223
2007-09-26 20:55:26 +00:00
|
|
|
return TRUE;
|
1999-11-12 12:01:17 +00:00
|
|
|
}
|
|
|
|
|
2005-09-14 01:05:50 +00:00
|
|
|
VOID
|
|
|
|
NTAPI
|
2006-05-18 20:32:17 +00:00
|
|
|
MmDeletePageTable(PEPROCESS Process, PVOID Address)
|
1999-11-12 12:01:17 +00:00
|
|
|
{
|
2006-05-18 20:32:17 +00:00
|
|
|
PEPROCESS CurrentProcess = PsGetCurrentProcess();
|
2004-04-10 22:36:07 +00:00
|
|
|
|
1999-11-12 12:01:17 +00:00
|
|
|
if (Process != NULL && Process != CurrentProcess)
|
2004-04-10 22:36:07 +00:00
|
|
|
{
|
2004-11-11 22:23:52 +00:00
|
|
|
KeAttachProcess(&Process->Pcb);
|
2004-04-10 22:36:07 +00:00
|
|
|
}
|
2004-09-09 20:42:33 +00:00
|
|
|
|
2004-09-26 16:32:18 +00:00
|
|
|
if (Ke386Pae)
|
2004-09-09 20:42:33 +00:00
|
|
|
{
|
|
|
|
ULONGLONG ZeroPde = 0LL;
|
2006-03-04 17:27:40 +00:00
|
|
|
(void)ExfpInterlockedExchange64UL(PAE_ADDR_TO_PDE(Address), &ZeroPde);
|
2005-08-16 16:17:47 +00:00
|
|
|
MiFlushTlb((PULONG)PAE_ADDR_TO_PDE(Address), PAE_ADDR_TO_PTE(Address));
|
2004-09-09 20:42:33 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*(ADDR_TO_PDE(Address)) = 0;
|
2005-08-16 16:17:47 +00:00
|
|
|
MiFlushTlb(ADDR_TO_PDE(Address), ADDR_TO_PTE(Address));
|
2004-09-09 20:42:33 +00:00
|
|
|
}
|
2005-07-06 08:20:26 +00:00
|
|
|
if (Address >= MmSystemRangeStart)
|
2004-04-10 22:36:07 +00:00
|
|
|
{
|
|
|
|
KEBUGCHECK(0);
|
|
|
|
// MmGlobalKernelPageDirectory[ADDR_TO_PDE_OFFSET(Address)] = 0;
|
|
|
|
}
|
1999-11-12 12:01:17 +00:00
|
|
|
if (Process != NULL && Process != CurrentProcess)
|
2004-04-10 22:36:07 +00:00
|
|
|
{
|
|
|
|
KeDetachProcess();
|
|
|
|
}
|
1999-11-12 12:01:17 +00:00
|
|
|
}
|
|
|
|
|
2005-09-14 01:05:50 +00:00
|
|
|
VOID
|
|
|
|
NTAPI
|
2006-05-18 20:32:17 +00:00
|
|
|
MmFreePageTable(PEPROCESS Process, PVOID Address)
|
2000-08-20 17:02:10 +00:00
|
|
|
{
|
2006-05-18 20:32:17 +00:00
|
|
|
PEPROCESS CurrentProcess = PsGetCurrentProcess();
|
2000-08-20 17:02:10 +00:00
|
|
|
ULONG i;
|
2004-09-09 20:42:33 +00:00
|
|
|
PFN_TYPE Pfn;
|
2004-04-10 22:36:07 +00:00
|
|
|
|
2004-09-09 20:42:33 +00:00
|
|
|
DPRINT("ProcessId %d, Address %x\n", Process->UniqueProcessId, Address);
|
2000-08-20 17:02:10 +00:00
|
|
|
if (Process != NULL && Process != CurrentProcess)
|
2002-11-05 20:39:03 +00:00
|
|
|
{
|
2004-11-11 22:23:52 +00:00
|
|
|
KeAttachProcess(&Process->Pcb);
|
2002-11-05 20:39:03 +00:00
|
|
|
}
|
2004-09-26 16:32:18 +00:00
|
|
|
if (Ke386Pae)
|
2002-11-05 20:39:03 +00:00
|
|
|
{
|
2004-09-09 20:42:33 +00:00
|
|
|
PULONGLONG PageTable;
|
|
|
|
ULONGLONG ZeroPte = 0LL;
|
|
|
|
PageTable = (PULONGLONG)PAGE_ROUND_DOWN((PVOID)PAE_ADDR_TO_PTE(Address));
|
|
|
|
for (i = 0; i < 512; i++)
|
2002-11-05 20:39:03 +00:00
|
|
|
{
|
2004-09-09 20:42:33 +00:00
|
|
|
if (PageTable[i] != 0LL)
|
|
|
|
{
|
|
|
|
DbgPrint("Page table entry not clear at %x/%x (is %I64x)\n",
|
|
|
|
((ULONG)Address / (4*1024*1024)), i, PageTable[i]);
|
|
|
|
KEBUGCHECK(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Pfn = PAE_PTE_TO_PFN(*(PAE_ADDR_TO_PDE(Address)));
|
2006-03-04 17:27:40 +00:00
|
|
|
(void)ExfpInterlockedExchange64UL(PAE_ADDR_TO_PDE(Address), &ZeroPte);
|
2005-08-16 16:17:47 +00:00
|
|
|
MiFlushTlb((PULONG)PAE_ADDR_TO_PDE(Address), PAE_ADDR_TO_PTE(Address));
|
2004-09-09 20:42:33 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
PULONG PageTable;
|
|
|
|
PageTable = (PULONG)PAGE_ROUND_DOWN((PVOID)ADDR_TO_PTE(Address));
|
|
|
|
for (i = 0; i < 1024; i++)
|
|
|
|
{
|
|
|
|
if (PageTable[i] != 0)
|
|
|
|
{
|
|
|
|
DbgPrint("Page table entry not clear at %x/%x (is %x)\n",
|
|
|
|
((ULONG)Address / (4*1024*1024)), i, PageTable[i]);
|
|
|
|
KEBUGCHECK(0);
|
|
|
|
}
|
2002-11-05 20:39:03 +00:00
|
|
|
}
|
2004-09-09 20:42:33 +00:00
|
|
|
Pfn = PTE_TO_PFN(*(ADDR_TO_PDE(Address)));
|
|
|
|
*(ADDR_TO_PDE(Address)) = 0;
|
2005-08-16 16:17:47 +00:00
|
|
|
MiFlushTlb(ADDR_TO_PDE(Address), ADDR_TO_PTE(Address));
|
2002-11-05 20:39:03 +00:00
|
|
|
}
|
|
|
|
|
2005-07-06 08:20:26 +00:00
|
|
|
if (Address >= MmSystemRangeStart)
|
2002-11-05 20:39:03 +00:00
|
|
|
{
|
2004-04-10 22:36:07 +00:00
|
|
|
// MmGlobalKernelPageDirectory[ADDR_TO_PDE_OFFSET(Address)] = 0;
|
2003-07-21 21:53:53 +00:00
|
|
|
KEBUGCHECK(0);
|
2002-11-05 20:39:03 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2004-09-09 20:42:33 +00:00
|
|
|
MmReleasePageMemoryConsumer(MC_NPPOOL, Pfn);
|
2002-11-05 20:39:03 +00:00
|
|
|
}
|
2000-08-20 17:02:10 +00:00
|
|
|
if (Process != NULL && Process != CurrentProcess)
|
2002-11-05 20:39:03 +00:00
|
|
|
{
|
|
|
|
KeDetachProcess();
|
|
|
|
}
|
2000-08-20 17:02:10 +00:00
|
|
|
}
|
|
|
|
|
2004-09-09 20:42:33 +00:00
|
|
|
static PULONGLONG
|
2006-05-18 20:32:17 +00:00
|
|
|
MmGetPageTableForProcessForPAE(PEPROCESS Process, PVOID Address, BOOLEAN Create)
|
2004-09-09 20:42:33 +00:00
|
|
|
{
|
|
|
|
NTSTATUS Status;
|
|
|
|
PFN_TYPE Pfn;
|
|
|
|
ULONGLONG Entry;
|
|
|
|
ULONGLONG ZeroEntry = 0LL;
|
|
|
|
PULONGLONG Pt;
|
|
|
|
PULONGLONG PageDir;
|
|
|
|
PULONGLONG PageDirTable;
|
|
|
|
|
|
|
|
DPRINT("MmGetPageTableForProcessForPAE(%x %x %d)\n",
|
|
|
|
Process, Address, Create);
|
2005-07-05 00:57:47 +00:00
|
|
|
if (Address >= (PVOID)PAGETABLE_MAP && Address < (PVOID)((ULONG_PTR)PAGETABLE_MAP + 0x800000))
|
2004-09-09 20:42:33 +00:00
|
|
|
{
|
|
|
|
KEBUGCHECK(0);
|
|
|
|
}
|
2006-05-18 20:32:17 +00:00
|
|
|
if (Address < MmSystemRangeStart && Process && Process != PsGetCurrentProcess())
|
2004-09-09 20:42:33 +00:00
|
|
|
{
|
2005-01-25 22:50:47 +00:00
|
|
|
PageDirTable = MmCreateHyperspaceMapping(PAE_PTE_TO_PFN(Process->Pcb.DirectoryTableBase.QuadPart));
|
2004-09-09 20:42:33 +00:00
|
|
|
if (PageDirTable == NULL)
|
|
|
|
{
|
|
|
|
KEBUGCHECK(0);
|
|
|
|
}
|
2005-01-25 22:50:47 +00:00
|
|
|
PageDir = MmCreateHyperspaceMapping(PAE_PTE_TO_PFN(PageDirTable[PAE_ADDR_TO_PDTE_OFFSET(Address)]));
|
|
|
|
MmDeleteHyperspaceMapping(PageDirTable);
|
2004-09-09 20:42:33 +00:00
|
|
|
if (PageDir == NULL)
|
|
|
|
{
|
|
|
|
KEBUGCHECK(0);
|
|
|
|
}
|
2004-10-05 18:53:28 +00:00
|
|
|
PageDir += PAE_ADDR_TO_PDE_PAGE_OFFSET(Address);
|
2004-12-24 17:07:00 +00:00
|
|
|
Entry = ExfInterlockedCompareExchange64UL(PageDir, &ZeroEntry, &ZeroEntry);
|
2004-09-09 20:42:33 +00:00
|
|
|
if (Entry == 0LL)
|
|
|
|
{
|
|
|
|
if (Create == FALSE)
|
|
|
|
{
|
2005-01-25 22:50:47 +00:00
|
|
|
MmDeleteHyperspaceMapping(PageDir);
|
2004-09-09 20:42:33 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
Status = MmRequestPageMemoryConsumer(MC_NPPOOL, FALSE, &Pfn);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
KEBUGCHECK(0);
|
|
|
|
}
|
2005-05-09 01:38:29 +00:00
|
|
|
Entry = PFN_TO_PTE(Pfn) | PA_PRESENT | PA_READWRITE | PA_USER;
|
2004-12-24 17:07:00 +00:00
|
|
|
Entry = ExfInterlockedCompareExchange64UL(PageDir, &Entry, &ZeroEntry);
|
2004-09-09 20:42:33 +00:00
|
|
|
if (Entry != 0LL)
|
|
|
|
{
|
|
|
|
MmReleasePageMemoryConsumer(MC_NPPOOL, Pfn);
|
|
|
|
Pfn = PAE_PTE_TO_PFN(Entry);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Pfn = PAE_PTE_TO_PFN(Entry);
|
|
|
|
}
|
2005-01-25 22:50:47 +00:00
|
|
|
MmDeleteHyperspaceMapping(PageDir);
|
|
|
|
Pt = MmCreateHyperspaceMapping(Pfn);
|
2004-09-09 20:42:33 +00:00
|
|
|
if (Pt == NULL)
|
|
|
|
{
|
|
|
|
KEBUGCHECK(0);
|
|
|
|
}
|
|
|
|
return Pt + PAE_ADDR_TO_PTE_OFFSET(Address);
|
|
|
|
}
|
|
|
|
PageDir = PAE_ADDR_TO_PDE(Address);
|
2004-12-24 17:07:00 +00:00
|
|
|
if (0LL == ExfInterlockedCompareExchange64UL(PageDir, &ZeroEntry, &ZeroEntry))
|
2004-09-09 20:42:33 +00:00
|
|
|
{
|
2005-07-06 08:20:26 +00:00
|
|
|
if (Address >= MmSystemRangeStart)
|
2004-09-09 20:42:33 +00:00
|
|
|
{
|
|
|
|
if (MmGlobalKernelPageDirectoryForPAE[PAE_ADDR_TO_PDE_OFFSET(Address)] == 0LL)
|
|
|
|
{
|
|
|
|
if (Create == FALSE)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
Status = MmRequestPageMemoryConsumer(MC_NPPOOL, FALSE, &Pfn);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
KEBUGCHECK(0);
|
|
|
|
}
|
|
|
|
Entry = PAE_PFN_TO_PTE(Pfn) | PA_PRESENT | PA_READWRITE;
|
2004-11-13 23:08:35 +00:00
|
|
|
if (Ke386GlobalPagesEnabled)
|
2004-09-09 20:42:33 +00:00
|
|
|
{
|
|
|
|
Entry |= PA_GLOBAL;
|
|
|
|
}
|
2004-12-24 17:07:00 +00:00
|
|
|
if (0LL != ExfInterlockedCompareExchange64UL(&MmGlobalKernelPageDirectoryForPAE[PAE_ADDR_TO_PDE_OFFSET(Address)], &Entry, &ZeroEntry))
|
2004-09-09 20:42:33 +00:00
|
|
|
{
|
|
|
|
MmReleasePageMemoryConsumer(MC_NPPOOL, Pfn);
|
|
|
|
}
|
|
|
|
}
|
2006-03-04 17:27:40 +00:00
|
|
|
(void)ExfInterlockedCompareExchange64UL(PageDir, &MmGlobalKernelPageDirectoryForPAE[PAE_ADDR_TO_PDE_OFFSET(Address)], &ZeroEntry);
|
2004-09-09 20:42:33 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (Create == FALSE)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
Status = MmRequestPageMemoryConsumer(MC_NPPOOL, FALSE, &Pfn);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
KEBUGCHECK(0);
|
|
|
|
}
|
|
|
|
Entry = PFN_TO_PTE(Pfn) | PA_PRESENT | PA_READWRITE | PA_USER;
|
2004-12-24 17:07:00 +00:00
|
|
|
Entry = ExfInterlockedCompareExchange64UL(PageDir, &Entry, &ZeroEntry);
|
2004-09-09 20:42:33 +00:00
|
|
|
if (Entry != 0LL)
|
|
|
|
{
|
|
|
|
MmReleasePageMemoryConsumer(MC_NPPOOL, Pfn);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2005-05-09 01:38:29 +00:00
|
|
|
return (PULONGLONG)PAE_ADDR_TO_PTE(Address);
|
2004-09-09 20:42:33 +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
|
|
|
{
|
2004-09-07 11:08:16 +00:00
|
|
|
ULONG PdeOffset = ADDR_TO_PDE_OFFSET(Address);
|
2002-11-05 20:39:03 +00:00
|
|
|
NTSTATUS Status;
|
2004-09-07 11:08:16 +00:00
|
|
|
PFN_TYPE Pfn;
|
|
|
|
ULONG Entry;
|
|
|
|
PULONG Pt, PageDir;
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2006-05-18 20:32:17 +00:00
|
|
|
if (Address < MmSystemRangeStart && Process && Process != PsGetCurrentProcess())
|
2004-09-07 11:08:16 +00:00
|
|
|
{
|
2007-08-05 11:27:39 +00:00
|
|
|
PageDir = MmCreateHyperspaceMapping(PTE_TO_PFN(Process->Pcb.DirectoryTableBase.LowPart));
|
2004-09-07 11:08:16 +00:00
|
|
|
if (PageDir == NULL)
|
|
|
|
{
|
|
|
|
KEBUGCHECK(0);
|
|
|
|
}
|
2005-01-05 19:27:58 +00:00
|
|
|
if (0 == InterlockedCompareExchangeUL(&PageDir[PdeOffset], 0, 0))
|
2004-09-07 11:08:16 +00:00
|
|
|
{
|
|
|
|
if (Create == FALSE)
|
|
|
|
{
|
2005-01-25 22:50:47 +00:00
|
|
|
MmDeleteHyperspaceMapping(PageDir);
|
2004-09-07 11:08:16 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
Status = MmRequestPageMemoryConsumer(MC_NPPOOL, FALSE, &Pfn);
|
|
|
|
if (!NT_SUCCESS(Status) || Pfn == 0)
|
|
|
|
{
|
|
|
|
KEBUGCHECK(0);
|
|
|
|
}
|
2004-12-24 17:07:00 +00:00
|
|
|
Entry = InterlockedCompareExchangeUL(&PageDir[PdeOffset], PFN_TO_PTE(Pfn) | PA_PRESENT | PA_READWRITE | PA_USER, 0);
|
2004-09-07 11:08:16 +00:00
|
|
|
if (Entry != 0)
|
|
|
|
{
|
|
|
|
MmReleasePageMemoryConsumer(MC_NPPOOL, Pfn);
|
|
|
|
Pfn = PTE_TO_PFN(Entry);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Pfn = PTE_TO_PFN(PageDir[PdeOffset]);
|
|
|
|
}
|
2005-01-25 22:50:47 +00:00
|
|
|
MmDeleteHyperspaceMapping(PageDir);
|
|
|
|
Pt = MmCreateHyperspaceMapping(Pfn);
|
2004-09-07 11:08:16 +00:00
|
|
|
if (Pt == NULL)
|
|
|
|
{
|
|
|
|
KEBUGCHECK(0);
|
|
|
|
}
|
|
|
|
return Pt + ADDR_TO_PTE_OFFSET(Address);
|
|
|
|
}
|
|
|
|
PageDir = ADDR_TO_PDE(Address);
|
2005-01-05 19:27:58 +00:00
|
|
|
if (0 == InterlockedCompareExchangeUL(PageDir, 0, 0))
|
2002-11-05 20:39:03 +00:00
|
|
|
{
|
2005-07-06 08:20:26 +00:00
|
|
|
if (Address >= MmSystemRangeStart)
|
2002-11-05 20:39:03 +00:00
|
|
|
{
|
2005-01-05 19:27:58 +00:00
|
|
|
if (0 == InterlockedCompareExchangeUL(&MmGlobalKernelPageDirectory[PdeOffset], 0, 0))
|
2004-08-01 07:27:25 +00:00
|
|
|
{
|
2004-09-07 11:08:16 +00:00
|
|
|
if (Create == FALSE)
|
|
|
|
{
|
2004-08-01 07:27:25 +00:00
|
|
|
return NULL;
|
2004-09-07 11:08:16 +00:00
|
|
|
}
|
2004-08-01 07:27:25 +00:00
|
|
|
Status = MmRequestPageMemoryConsumer(MC_NPPOOL, FALSE, &Pfn);
|
2004-09-07 11:08:16 +00:00
|
|
|
if (!NT_SUCCESS(Status) || Pfn == 0)
|
|
|
|
{
|
|
|
|
KEBUGCHECK(0);
|
|
|
|
}
|
|
|
|
Entry = PFN_TO_PTE(Pfn) | PA_PRESENT | PA_READWRITE;
|
2004-11-13 23:08:35 +00:00
|
|
|
if (Ke386GlobalPagesEnabled)
|
2004-08-14 09:17:05 +00:00
|
|
|
{
|
2004-09-07 11:08:16 +00:00
|
|
|
Entry |= PA_GLOBAL;
|
2004-08-14 09:17:05 +00:00
|
|
|
}
|
2004-12-24 17:07:00 +00:00
|
|
|
if(0 != InterlockedCompareExchangeUL(&MmGlobalKernelPageDirectory[PdeOffset], Entry, 0))
|
2004-08-01 07:27:25 +00:00
|
|
|
{
|
2004-09-07 11:08:16 +00:00
|
|
|
MmReleasePageMemoryConsumer(MC_NPPOOL, Pfn);
|
2004-08-01 07:27:25 +00:00
|
|
|
}
|
|
|
|
}
|
2006-03-04 17:27:40 +00:00
|
|
|
(void)InterlockedExchangeUL(PageDir, MmGlobalKernelPageDirectory[PdeOffset]);
|
2002-11-05 20:39:03 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2004-09-07 11:08:16 +00:00
|
|
|
if (Create == FALSE)
|
|
|
|
{
|
2004-08-01 07:27:25 +00:00
|
|
|
return NULL;
|
2004-09-07 11:08:16 +00:00
|
|
|
}
|
2004-08-01 07:27:25 +00:00
|
|
|
Status = MmRequestPageMemoryConsumer(MC_NPPOOL, FALSE, &Pfn);
|
2004-09-07 11:08:16 +00:00
|
|
|
if (!NT_SUCCESS(Status) || Pfn == 0)
|
2004-08-01 07:27:25 +00:00
|
|
|
{
|
2004-09-07 11:08:16 +00:00
|
|
|
KEBUGCHECK(0);
|
|
|
|
}
|
2004-12-24 17:07:00 +00:00
|
|
|
Entry = InterlockedCompareExchangeUL(PageDir, PFN_TO_PTE(Pfn) | PA_PRESENT | PA_READWRITE | PA_USER, 0);
|
2004-09-07 11:08:16 +00:00
|
|
|
if (Entry != 0)
|
|
|
|
{
|
|
|
|
MmReleasePageMemoryConsumer(MC_NPPOOL, Pfn);
|
2004-08-01 07:27:25 +00:00
|
|
|
}
|
2004-04-10 22:36:07 +00:00
|
|
|
}
|
2002-11-05 20:39:03 +00:00
|
|
|
}
|
2005-05-09 01:38:29 +00:00
|
|
|
return (PULONG)ADDR_TO_PTE(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
|
|
|
{
|
2004-09-26 16:32:18 +00:00
|
|
|
if (Ke386Pae)
|
2004-09-09 20:42:33 +00:00
|
|
|
{
|
|
|
|
if ((PULONGLONG)Pt >= (PULONGLONG)PAGETABLE_MAP && (PULONGLONG)Pt < (PULONGLONG)PAGETABLE_MAP + 4*512*512)
|
|
|
|
{
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
2004-04-10 22:36:07 +00:00
|
|
|
{
|
2004-09-09 20:42:33 +00:00
|
|
|
if (Pt >= (PULONG)PAGETABLE_MAP && Pt < (PULONG)PAGETABLE_MAP + 1024*1024)
|
|
|
|
{
|
|
|
|
return TRUE;
|
|
|
|
}
|
2004-04-10 22:36:07 +00:00
|
|
|
}
|
2004-09-07 11:08:16 +00:00
|
|
|
if (Pt)
|
2004-04-10 22:36:07 +00:00
|
|
|
{
|
2005-01-25 22:50:47 +00:00
|
|
|
MmDeleteHyperspaceMapping((PVOID)PAGE_ROUND_DOWN(Pt));
|
2004-04-10 22:36:07 +00:00
|
|
|
}
|
2004-09-07 11:08:16 +00:00
|
|
|
return FALSE;
|
2004-09-09 20:42:33 +00:00
|
|
|
}
|
|
|
|
|
2006-05-18 20:32:17 +00:00
|
|
|
static ULONGLONG MmGetPageEntryForProcessForPAE(PEPROCESS Process, PVOID Address)
|
2004-09-09 20:42:33 +00:00
|
|
|
{
|
|
|
|
ULONGLONG Pte;
|
|
|
|
PULONGLONG Pt;
|
2004-09-07 11:08:16 +00:00
|
|
|
|
2004-09-09 20:42:33 +00:00
|
|
|
Pt = MmGetPageTableForProcessForPAE(Process, Address, FALSE);
|
|
|
|
if (Pt)
|
|
|
|
{
|
|
|
|
Pte = *Pt;
|
|
|
|
MmUnmapPageTable((PULONG)Pt);
|
|
|
|
return Pte;
|
|
|
|
}
|
|
|
|
return 0;
|
2000-07-06 14:34:52 +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
|
|
|
{
|
|
|
|
ULONG Pte;
|
|
|
|
PULONG Pt;
|
|
|
|
|
|
|
|
Pt = MmGetPageTableForProcess(Process, Address, FALSE);
|
|
|
|
if (Pt)
|
|
|
|
{
|
|
|
|
Pte = *Pt;
|
|
|
|
MmUnmapPageTable(Pt);
|
|
|
|
return Pte;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2004-08-01 07:27:25 +00:00
|
|
|
PFN_TYPE
|
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
|
|
|
{
|
2004-04-10 22:36:07 +00:00
|
|
|
|
2004-09-26 16:32:18 +00:00
|
|
|
if (Ke386Pae)
|
2004-09-09 20:42:33 +00:00
|
|
|
{
|
|
|
|
ULONGLONG Entry;
|
|
|
|
Entry = MmGetPageEntryForProcessForPAE(Process, Address);
|
|
|
|
if (!(Entry & PA_PRESENT))
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return(PAE_PTE_TO_PFN(Entry));
|
|
|
|
}
|
|
|
|
else
|
2004-04-10 22:36:07 +00:00
|
|
|
{
|
2004-09-09 20:42:33 +00:00
|
|
|
ULONG Entry;
|
|
|
|
Entry = MmGetPageEntryForProcess(Process, Address);
|
|
|
|
if (!(Entry & PA_PRESENT))
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return(PTE_TO_PFN(Entry));
|
2004-04-10 22:36:07 +00:00
|
|
|
}
|
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
|
2006-05-18 20:32:17 +00:00
|
|
|
MmDisableVirtualMapping(PEPROCESS Process, PVOID Address, BOOLEAN* WasDirty, PPFN_TYPE 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
|
|
|
*/
|
|
|
|
{
|
2002-05-14 21:19:21 +00:00
|
|
|
BOOLEAN WasValid;
|
2004-09-26 16:32:18 +00:00
|
|
|
if (Ke386Pae)
|
2004-04-10 22:36:07 +00:00
|
|
|
{
|
2004-09-09 20:42:33 +00:00
|
|
|
ULONGLONG Pte;
|
|
|
|
ULONGLONG tmpPte;
|
|
|
|
PULONGLONG Pt;
|
2001-12-31 01:53:46 +00:00
|
|
|
|
2004-09-09 20:42:33 +00:00
|
|
|
Pt = MmGetPageTableForProcessForPAE(Process, Address, FALSE);
|
|
|
|
if (Pt == NULL)
|
|
|
|
{
|
|
|
|
KEBUGCHECK(0);
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* Atomically disable the present bit and get the old value.
|
|
|
|
*/
|
|
|
|
do
|
|
|
|
{
|
|
|
|
Pte = *Pt;
|
|
|
|
tmpPte = Pte & ~PA_PRESENT;
|
2005-05-09 01:38:29 +00:00
|
|
|
} while (Pte != ExfInterlockedCompareExchange64UL(Pt, &tmpPte, &Pte));
|
2004-09-07 11:08:16 +00:00
|
|
|
|
2004-11-27 16:37:52 +00:00
|
|
|
MiFlushTlb((PULONG)Pt, Address);
|
2004-09-09 20:42:33 +00:00
|
|
|
WasValid = PAE_PAGE_MASK(Pte) != 0LL ? TRUE : FALSE;
|
|
|
|
if (!WasValid)
|
|
|
|
{
|
|
|
|
KEBUGCHECK(0);
|
|
|
|
}
|
2001-12-31 01:53:46 +00:00
|
|
|
|
2004-09-09 20:42:33 +00:00
|
|
|
/*
|
|
|
|
* Return some information to the caller
|
|
|
|
*/
|
|
|
|
if (WasDirty != NULL)
|
|
|
|
{
|
|
|
|
*WasDirty = Pte & PA_DIRTY ? TRUE : FALSE;
|
|
|
|
}
|
|
|
|
if (Page != NULL)
|
|
|
|
{
|
|
|
|
*Page = PAE_PTE_TO_PFN(Pte);
|
|
|
|
}
|
2004-09-07 11:08:16 +00:00
|
|
|
}
|
2004-09-09 20:42:33 +00:00
|
|
|
else
|
2004-09-07 11:08:16 +00:00
|
|
|
{
|
2004-09-09 20:42:33 +00:00
|
|
|
ULONG Pte;
|
|
|
|
PULONG Pt;
|
2001-12-31 01:53:46 +00:00
|
|
|
|
2004-09-09 20:42:33 +00:00
|
|
|
Pt = MmGetPageTableForProcess(Process, Address, FALSE);
|
|
|
|
if (Pt == NULL)
|
|
|
|
{
|
|
|
|
KEBUGCHECK(0);
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* Atomically disable the present bit and get the old value.
|
|
|
|
*/
|
|
|
|
do
|
|
|
|
{
|
|
|
|
Pte = *Pt;
|
2005-05-09 01:38:29 +00:00
|
|
|
} while (Pte != InterlockedCompareExchangeUL(Pt, Pte & ~PA_PRESENT, Pte));
|
2004-09-09 20:42:33 +00:00
|
|
|
|
2004-11-27 16:37:52 +00:00
|
|
|
MiFlushTlb(Pt, Address);
|
2004-09-09 20:42:33 +00:00
|
|
|
WasValid = (PAGE_MASK(Pte) != 0);
|
|
|
|
if (!WasValid)
|
|
|
|
{
|
|
|
|
KEBUGCHECK(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Return some information to the caller
|
|
|
|
*/
|
|
|
|
if (WasDirty != NULL)
|
|
|
|
{
|
|
|
|
*WasDirty = Pte & PA_DIRTY;
|
|
|
|
}
|
|
|
|
if (Page != NULL)
|
|
|
|
{
|
|
|
|
*Page = PTE_TO_PFN(Pte);
|
|
|
|
}
|
2004-04-10 22:36:07 +00:00
|
|
|
}
|
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)
|
|
|
|
{
|
2004-09-26 16:32:18 +00:00
|
|
|
if (Ke386Pae)
|
2004-04-10 22:36:07 +00:00
|
|
|
{
|
2004-09-09 20:42:33 +00:00
|
|
|
PULONGLONG Pt;
|
|
|
|
ULONGLONG ZeroPte = 0LL;
|
|
|
|
Pt = MmGetPageTableForProcessForPAE(NULL, Address, FALSE);
|
|
|
|
if (Pt)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Set the entry to zero
|
|
|
|
*/
|
2006-03-04 17:27:40 +00:00
|
|
|
(void)ExfpInterlockedExchange64UL(Pt, &ZeroPte);
|
2004-11-27 16:37:52 +00:00
|
|
|
MiFlushTlb((PULONG)Pt, Address);
|
2004-09-09 20:42:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
PULONG Pt;
|
|
|
|
|
|
|
|
Pt = MmGetPageTableForProcess(NULL, Address, FALSE);
|
|
|
|
if (Pt && *Pt)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Set the entry to zero
|
|
|
|
*/
|
2006-03-04 17:27:40 +00:00
|
|
|
(void)InterlockedExchangeUL(Pt, 0);
|
2004-11-27 16:37:52 +00:00
|
|
|
MiFlushTlb(Pt, Address);
|
2004-09-09 20:42:33 +00:00
|
|
|
}
|
2004-04-10 22:36:07 +00:00
|
|
|
}
|
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,
|
2006-01-08 06:23:17 +00:00
|
|
|
BOOLEAN* WasDirty, PPFN_TYPE 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
|
|
|
{
|
2004-09-09 20:42:33 +00:00
|
|
|
BOOLEAN WasValid = FALSE;
|
|
|
|
PFN_TYPE Pfn;
|
2001-02-10 22:51:11 +00:00
|
|
|
|
2004-09-07 11:08:16 +00:00
|
|
|
DPRINT("MmDeleteVirtualMapping(%x, %x, %d, %x, %x)\n",
|
2004-09-09 20:42:33 +00:00
|
|
|
Process, Address, FreePage, WasDirty, Page);
|
2004-09-26 16:32:18 +00:00
|
|
|
if (Ke386Pae)
|
2004-09-09 20:42:33 +00:00
|
|
|
{
|
|
|
|
ULONGLONG Pte;
|
|
|
|
PULONGLONG Pt;
|
2001-03-25 03:34:30 +00:00
|
|
|
|
2004-09-09 20:42:33 +00:00
|
|
|
Pt = MmGetPageTableForProcessForPAE(Process, Address, FALSE);
|
|
|
|
if (Pt == NULL)
|
|
|
|
{
|
|
|
|
if (WasDirty != NULL)
|
|
|
|
{
|
|
|
|
*WasDirty = FALSE;
|
|
|
|
}
|
|
|
|
if (Page != NULL)
|
|
|
|
{
|
|
|
|
*Page = 0;
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
2004-09-07 11:08:16 +00:00
|
|
|
|
2004-09-09 20:42:33 +00:00
|
|
|
/*
|
|
|
|
* Atomically set the entry to zero and get the old value.
|
|
|
|
*/
|
|
|
|
Pte = 0LL;
|
2004-12-24 17:07:00 +00:00
|
|
|
Pte = ExfpInterlockedExchange64UL(Pt, &Pte);
|
2004-09-09 20:42:33 +00:00
|
|
|
|
2004-11-27 16:37:52 +00:00
|
|
|
MiFlushTlb((PULONG)Pt, Address);
|
2004-09-09 20:42:33 +00:00
|
|
|
|
|
|
|
WasValid = PAE_PAGE_MASK(Pte) != 0 ? TRUE : FALSE;
|
|
|
|
if (WasValid)
|
|
|
|
{
|
|
|
|
Pfn = PAE_PTE_TO_PFN(Pte);
|
|
|
|
MmMarkPageUnmapped(Pfn);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Pfn = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (FreePage && WasValid)
|
|
|
|
{
|
|
|
|
MmReleasePageMemoryConsumer(MC_NPPOOL, Pfn);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Return some information to the caller
|
|
|
|
*/
|
2004-04-10 22:36:07 +00:00
|
|
|
if (WasDirty != NULL)
|
|
|
|
{
|
2004-09-09 20:42:33 +00:00
|
|
|
*WasDirty = Pte & PA_DIRTY ? TRUE : FALSE;
|
2004-04-10 22:36:07 +00:00
|
|
|
}
|
2004-08-01 07:27:25 +00:00
|
|
|
if (Page != NULL)
|
2004-04-10 22:36:07 +00:00
|
|
|
{
|
2004-09-09 20:42:33 +00:00
|
|
|
*Page = Pfn;
|
2004-04-10 22:36:07 +00:00
|
|
|
}
|
|
|
|
}
|
2004-09-09 20:42:33 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
ULONG Pte;
|
|
|
|
PULONG Pt;
|
2001-03-25 03:34:30 +00:00
|
|
|
|
2004-09-09 20:42:33 +00:00
|
|
|
Pt = MmGetPageTableForProcess(Process, Address, FALSE);
|
2004-09-07 11:08:16 +00:00
|
|
|
|
2004-09-09 20:42:33 +00:00
|
|
|
if (Pt == NULL)
|
|
|
|
{
|
|
|
|
if (WasDirty != NULL)
|
|
|
|
{
|
|
|
|
*WasDirty = FALSE;
|
|
|
|
}
|
|
|
|
if (Page != NULL)
|
|
|
|
{
|
|
|
|
*Page = 0;
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
2004-09-07 11:08:16 +00:00
|
|
|
|
2004-09-09 20:42:33 +00:00
|
|
|
/*
|
|
|
|
* Atomically set the entry to zero and get the old value.
|
|
|
|
*/
|
2004-12-24 17:07:00 +00:00
|
|
|
Pte = InterlockedExchangeUL(Pt, 0);
|
2004-09-07 11:08:16 +00:00
|
|
|
|
2004-11-27 16:37:52 +00:00
|
|
|
MiFlushTlb(Pt, Address);
|
2004-09-09 20:42:33 +00:00
|
|
|
|
|
|
|
WasValid = (PAGE_MASK(Pte) != 0);
|
|
|
|
if (WasValid)
|
|
|
|
{
|
|
|
|
Pfn = PTE_TO_PFN(Pte);
|
|
|
|
MmMarkPageUnmapped(Pfn);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Pfn = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (FreePage && WasValid)
|
|
|
|
{
|
|
|
|
MmReleasePageMemoryConsumer(MC_NPPOOL, Pfn);
|
|
|
|
}
|
2001-03-25 03:34:30 +00:00
|
|
|
|
2004-09-09 20:42:33 +00:00
|
|
|
/*
|
|
|
|
* Return some information to the caller
|
|
|
|
*/
|
|
|
|
if (WasDirty != NULL)
|
|
|
|
{
|
|
|
|
*WasDirty = Pte & PA_DIRTY ? TRUE : FALSE;
|
|
|
|
}
|
|
|
|
if (Page != NULL)
|
|
|
|
{
|
|
|
|
*Page = Pfn;
|
|
|
|
}
|
|
|
|
}
|
2001-03-25 03:34:30 +00:00
|
|
|
/*
|
|
|
|
* Decrement the reference count for this page table.
|
|
|
|
*/
|
2001-02-10 22:51:11 +00:00
|
|
|
if (Process != NULL && WasValid &&
|
2006-05-18 20:10:44 +00:00
|
|
|
((PMADDRESS_SPACE)&Process->VadRoot)->PageTableRefCountTable != NULL &&
|
2005-07-06 08:20:26 +00:00
|
|
|
Address < MmSystemRangeStart)
|
2004-04-10 22:36:07 +00:00
|
|
|
{
|
|
|
|
PUSHORT Ptrc;
|
2004-09-09 20:42:33 +00:00
|
|
|
ULONG Idx;
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2006-05-18 20:10:44 +00:00
|
|
|
Ptrc = ((PMADDRESS_SPACE)&Process->VadRoot)->PageTableRefCountTable;
|
2004-09-26 16:32:18 +00:00
|
|
|
Idx = Ke386Pae ? PAE_ADDR_TO_PAGE_TABLE(Address) : ADDR_TO_PAGE_TABLE(Address);
|
2004-04-10 22:36:07 +00:00
|
|
|
|
2004-09-09 20:42:33 +00:00
|
|
|
Ptrc[Idx]--;
|
|
|
|
if (Ptrc[Idx] == 0)
|
2004-04-10 22:36:07 +00:00
|
|
|
{
|
|
|
|
MmFreePageTable(Process, Address);
|
|
|
|
}
|
|
|
|
}
|
1999-11-12 12:01:17 +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
|
|
|
*/
|
|
|
|
{
|
2004-09-26 16:32:18 +00:00
|
|
|
if (Ke386Pae)
|
2004-04-10 22:36:07 +00:00
|
|
|
{
|
2004-09-09 20:42:33 +00:00
|
|
|
ULONGLONG Pte;
|
|
|
|
PULONGLONG Pt;
|
2001-12-31 19:06:49 +00:00
|
|
|
|
2004-09-09 20:42:33 +00:00
|
|
|
Pt = MmGetPageTableForProcessForPAE(Process, Address, FALSE);
|
|
|
|
if (Pt == NULL)
|
|
|
|
{
|
|
|
|
*SwapEntry = 0;
|
|
|
|
return;
|
|
|
|
}
|
2001-12-31 19:06:49 +00:00
|
|
|
|
2004-09-09 20:42:33 +00:00
|
|
|
/*
|
|
|
|
* Atomically set the entry to zero and get the old value.
|
|
|
|
*/
|
|
|
|
Pte = 0LL;
|
2004-12-24 17:07:00 +00:00
|
|
|
Pte = ExfpInterlockedExchange64UL(Pt, &Pte);
|
2002-11-05 20:39:03 +00:00
|
|
|
|
2004-11-27 16:37:52 +00:00
|
|
|
MiFlushTlb((PULONG)Pt, Address);
|
2004-09-09 20:42:33 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Decrement the reference count for this page table.
|
|
|
|
*/
|
|
|
|
if (Process != NULL && Pte &&
|
2006-05-18 20:10:44 +00:00
|
|
|
((PMADDRESS_SPACE)&Process->VadRoot)->PageTableRefCountTable != NULL &&
|
2005-07-06 08:20:26 +00:00
|
|
|
Address < MmSystemRangeStart)
|
2004-09-09 20:42:33 +00:00
|
|
|
{
|
|
|
|
PUSHORT Ptrc;
|
|
|
|
|
2006-05-18 20:10:44 +00:00
|
|
|
Ptrc = ((PMADDRESS_SPACE)&Process->VadRoot)->PageTableRefCountTable;
|
2004-09-09 20:42:33 +00:00
|
|
|
|
|
|
|
Ptrc[PAE_ADDR_TO_PAGE_TABLE(Address)]--;
|
|
|
|
if (Ptrc[PAE_ADDR_TO_PAGE_TABLE(Address)] == 0)
|
|
|
|
{
|
|
|
|
MmFreePageTable(Process, Address);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Return some information to the caller
|
|
|
|
*/
|
|
|
|
*SwapEntry = Pte >> 1;
|
|
|
|
}
|
|
|
|
else
|
2004-04-10 22:36:07 +00:00
|
|
|
{
|
2004-09-09 20:42:33 +00:00
|
|
|
ULONG Pte;
|
|
|
|
PULONG Pt;
|
2004-04-10 22:36:07 +00:00
|
|
|
|
2004-09-09 20:42:33 +00:00
|
|
|
Pt = MmGetPageTableForProcess(Process, Address, FALSE);
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2004-09-09 20:42:33 +00:00
|
|
|
if (Pt == NULL)
|
|
|
|
{
|
|
|
|
*SwapEntry = 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Atomically set the entry to zero and get the old value.
|
|
|
|
*/
|
2004-12-24 17:07:00 +00:00
|
|
|
Pte = InterlockedExchangeUL(Pt, 0);
|
2004-04-10 22:36:07 +00:00
|
|
|
|
2004-11-27 16:37:52 +00:00
|
|
|
MiFlushTlb(Pt, Address);
|
2001-12-31 19:06:49 +00:00
|
|
|
|
2004-09-09 20:42:33 +00:00
|
|
|
/*
|
|
|
|
* Decrement the reference count for this page table.
|
|
|
|
*/
|
|
|
|
if (Process != NULL && Pte &&
|
2006-05-18 20:10:44 +00:00
|
|
|
((PMADDRESS_SPACE)&Process->VadRoot)->PageTableRefCountTable != NULL &&
|
2005-07-06 08:20:26 +00:00
|
|
|
Address < MmSystemRangeStart)
|
2004-09-09 20:42:33 +00:00
|
|
|
{
|
|
|
|
PUSHORT Ptrc;
|
2001-12-31 19:06:49 +00:00
|
|
|
|
2006-05-18 20:10:44 +00:00
|
|
|
Ptrc = ((PMADDRESS_SPACE)&Process->VadRoot)->PageTableRefCountTable;
|
2004-09-09 20:42:33 +00:00
|
|
|
|
|
|
|
Ptrc[ADDR_TO_PAGE_TABLE(Address)]--;
|
|
|
|
if (Ptrc[ADDR_TO_PAGE_TABLE(Address)] == 0)
|
|
|
|
{
|
|
|
|
MmFreePageTable(Process, Address);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 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)
|
|
|
|
{
|
2004-09-26 16:32:18 +00:00
|
|
|
if (Ke386Pae)
|
2002-11-05 20:39:03 +00:00
|
|
|
{
|
2004-09-09 20:42:33 +00:00
|
|
|
PULONGLONG Pt;
|
|
|
|
PULONGLONG Pde;
|
|
|
|
Pde = PAE_ADDR_TO_PDE(PAddress);
|
|
|
|
if (*Pde == 0LL)
|
|
|
|
{
|
|
|
|
Pt = MmGetPageTableForProcessForPAE(NULL, PAddress, FALSE);
|
2004-08-01 07:27:25 +00:00
|
|
|
#if 0
|
2004-09-09 20:42:33 +00:00
|
|
|
/* Non existing mappings are not cached within the tlb. We must not invalidate this entry */
|
|
|
|
FLASH_TLB_ONE(PAddress);
|
2004-08-01 07:27:25 +00:00
|
|
|
#endif
|
2004-09-09 20:42:33 +00:00
|
|
|
if (Pt != NULL)
|
|
|
|
{
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
PULONG Pt, Pde;
|
|
|
|
Pde = ADDR_TO_PDE(PAddress);
|
|
|
|
if (*Pde == 0)
|
2002-11-05 20:39:03 +00:00
|
|
|
{
|
2004-09-09 20:42:33 +00:00
|
|
|
Pt = MmGetPageTableForProcess(NULL, PAddress, FALSE);
|
|
|
|
#if 0
|
|
|
|
/* Non existing mappings are not cached within the tlb. We must not invalidate this entry */
|
|
|
|
FLASH_TLB_ONE(PAddress);
|
|
|
|
#endif
|
|
|
|
if (Pt != NULL)
|
|
|
|
{
|
|
|
|
return TRUE;
|
|
|
|
}
|
2002-11-05 20:39:03 +00:00
|
|
|
}
|
|
|
|
}
|
2004-08-01 07:27:25 +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
|
|
|
{
|
2004-09-26 16:32:18 +00:00
|
|
|
if (Ke386Pae)
|
2004-09-09 20:42:33 +00:00
|
|
|
{
|
|
|
|
return MmGetPageEntryForProcessForPAE(Process, Address) & PA_DIRTY ? TRUE : FALSE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return MmGetPageEntryForProcess(Process, Address) & PA_DIRTY ? TRUE : FALSE;
|
|
|
|
}
|
2000-06-25 03:59:17 +00:00
|
|
|
}
|
|
|
|
|
2004-04-10 22:36:07 +00:00
|
|
|
BOOLEAN
|
2005-09-14 01:05:50 +00:00
|
|
|
NTAPI
|
2006-05-18 20:32:17 +00:00
|
|
|
MmIsAccessedAndResetAccessPage(PEPROCESS Process, PVOID Address)
|
2001-03-25 03:34:30 +00:00
|
|
|
{
|
2005-07-06 08:20:26 +00:00
|
|
|
if (Address < MmSystemRangeStart && Process == NULL)
|
2004-04-10 22:36:07 +00:00
|
|
|
{
|
2004-09-09 20:42:33 +00:00
|
|
|
DPRINT1("MmIsAccessedAndResetAccessPage is called for user space without a process.\n");
|
2004-08-01 07:27:25 +00:00
|
|
|
KEBUGCHECK(0);
|
|
|
|
}
|
2004-09-26 16:32:18 +00:00
|
|
|
if (Ke386Pae)
|
2004-08-01 07:27:25 +00:00
|
|
|
{
|
2004-09-09 20:42:33 +00:00
|
|
|
PULONGLONG Pt;
|
|
|
|
ULONGLONG Pte;
|
|
|
|
ULONGLONG tmpPte;
|
2004-09-07 11:08:16 +00:00
|
|
|
|
2004-09-09 20:42:33 +00:00
|
|
|
Pt = MmGetPageTableForProcessForPAE(Process, Address, FALSE);
|
|
|
|
if (Pt == NULL)
|
2004-09-07 11:08:16 +00:00
|
|
|
{
|
2004-09-09 20:42:33 +00:00
|
|
|
KEBUGCHECK(0);
|
|
|
|
}
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2004-09-09 20:42:33 +00:00
|
|
|
do
|
|
|
|
{
|
|
|
|
Pte = *Pt;
|
|
|
|
tmpPte = Pte & ~PA_ACCESSED;
|
2004-12-24 17:07:00 +00:00
|
|
|
} while (Pte != ExfInterlockedCompareExchange64UL(Pt, &tmpPte, &Pte));
|
2004-09-09 20:42:33 +00:00
|
|
|
|
|
|
|
if (Pte & PA_ACCESSED)
|
|
|
|
{
|
2004-11-27 16:37:52 +00:00
|
|
|
MiFlushTlb((PULONG)Pt, Address);
|
2004-09-09 20:42:33 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
MmUnmapPageTable((PULONG)Pt);
|
|
|
|
return FALSE;
|
2004-09-07 11:08:16 +00:00
|
|
|
}
|
2004-04-10 22:36:07 +00:00
|
|
|
}
|
2004-09-07 11:08:16 +00:00
|
|
|
else
|
2004-04-10 22:36:07 +00:00
|
|
|
{
|
2004-09-09 20:42:33 +00:00
|
|
|
PULONG Pt;
|
|
|
|
ULONG Pte;
|
|
|
|
|
|
|
|
Pt = MmGetPageTableForProcess(Process, Address, FALSE);
|
|
|
|
if (Pt == NULL)
|
|
|
|
{
|
|
|
|
KEBUGCHECK(0);
|
|
|
|
}
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2004-09-09 20:42:33 +00:00
|
|
|
do
|
|
|
|
{
|
|
|
|
Pte = *Pt;
|
2004-12-24 17:07:00 +00:00
|
|
|
} while (Pte != InterlockedCompareExchangeUL(Pt, Pte & ~PA_ACCESSED, Pte));
|
2004-09-09 20:42:33 +00:00
|
|
|
|
|
|
|
if (Pte & PA_ACCESSED)
|
|
|
|
{
|
2004-11-27 16:37:52 +00:00
|
|
|
MiFlushTlb(Pt, Address);
|
2004-09-09 20:42:33 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
MmUnmapPageTable(Pt);
|
|
|
|
return FALSE;
|
|
|
|
}
|
2004-04-10 22:36:07 +00:00
|
|
|
}
|
2001-03-25 03:34:30 +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
|
|
|
{
|
2005-07-06 08:20:26 +00:00
|
|
|
if (Address < MmSystemRangeStart && Process == NULL)
|
2004-04-10 22:36:07 +00:00
|
|
|
{
|
2004-09-07 11:08:16 +00:00
|
|
|
DPRINT1("MmSetCleanPage is called for user space without a process.\n");
|
|
|
|
KEBUGCHECK(0);
|
2004-04-10 22:36:07 +00:00
|
|
|
}
|
2004-09-26 16:32:18 +00:00
|
|
|
if (Ke386Pae)
|
2004-09-09 20:42:33 +00:00
|
|
|
{
|
|
|
|
PULONGLONG Pt;
|
|
|
|
ULONGLONG Pte;
|
|
|
|
ULONGLONG tmpPte;
|
2004-09-07 11:08:16 +00:00
|
|
|
|
2004-09-09 20:42:33 +00:00
|
|
|
Pt = MmGetPageTableForProcessForPAE(Process, Address, FALSE);
|
2004-09-07 11:08:16 +00:00
|
|
|
|
2004-09-09 20:42:33 +00:00
|
|
|
if (Pt == NULL)
|
|
|
|
{
|
|
|
|
KEBUGCHECK(0);
|
|
|
|
}
|
2004-09-07 11:08:16 +00:00
|
|
|
|
2004-09-09 20:42:33 +00:00
|
|
|
do
|
|
|
|
{
|
|
|
|
Pte = *Pt;
|
|
|
|
tmpPte = Pte & ~PA_DIRTY;
|
2004-12-24 17:07:00 +00:00
|
|
|
} while (Pte != ExfInterlockedCompareExchange64UL(Pt, &tmpPte, &Pte));
|
2004-09-07 11:08:16 +00:00
|
|
|
|
2004-09-09 20:42:33 +00:00
|
|
|
if (Pte & PA_DIRTY)
|
2004-09-07 11:08:16 +00:00
|
|
|
{
|
2004-11-27 16:37:52 +00:00
|
|
|
MiFlushTlb((PULONG)Pt, Address);
|
2004-09-09 20:42:33 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
MmUnmapPageTable((PULONG)Pt);
|
2004-09-07 11:08:16 +00:00
|
|
|
}
|
2004-08-01 07:27:25 +00:00
|
|
|
}
|
2004-09-07 11:08:16 +00:00
|
|
|
else
|
2004-04-10 22:36:07 +00:00
|
|
|
{
|
2004-09-09 20:42:33 +00:00
|
|
|
PULONG Pt;
|
|
|
|
ULONG Pte;
|
|
|
|
|
|
|
|
Pt = MmGetPageTableForProcess(Process, Address, FALSE);
|
|
|
|
|
|
|
|
if (Pt == NULL)
|
|
|
|
{
|
|
|
|
KEBUGCHECK(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
Pte = *Pt;
|
2004-12-24 17:07:00 +00:00
|
|
|
} while (Pte != InterlockedCompareExchangeUL(Pt, Pte & ~PA_DIRTY, Pte));
|
2004-09-09 20:42:33 +00:00
|
|
|
|
|
|
|
if (Pte & PA_DIRTY)
|
|
|
|
{
|
2004-11-27 16:37:52 +00:00
|
|
|
MiFlushTlb(Pt, Address);
|
2004-09-09 20:42:33 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
MmUnmapPageTable(Pt);
|
|
|
|
}
|
2004-04-10 22:36:07 +00:00
|
|
|
}
|
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
|
|
|
{
|
2005-07-06 08:20:26 +00:00
|
|
|
if (Address < MmSystemRangeStart && Process == NULL)
|
2004-04-10 22:36:07 +00:00
|
|
|
{
|
2004-09-07 11:08:16 +00:00
|
|
|
DPRINT1("MmSetDirtyPage is called for user space without a process.\n");
|
|
|
|
KEBUGCHECK(0);
|
2004-04-10 22:36:07 +00:00
|
|
|
}
|
2004-09-26 16:32:18 +00:00
|
|
|
if (Ke386Pae)
|
2004-08-01 07:27:25 +00:00
|
|
|
{
|
2004-09-09 20:42:33 +00:00
|
|
|
PULONGLONG Pt;
|
|
|
|
ULONGLONG Pte;
|
|
|
|
ULONGLONG tmpPte;
|
2004-09-07 11:08:16 +00:00
|
|
|
|
2004-09-09 20:42:33 +00:00
|
|
|
Pt = MmGetPageTableForProcessForPAE(Process, Address, FALSE);
|
|
|
|
if (Pt == NULL)
|
2004-09-07 11:08:16 +00:00
|
|
|
{
|
2004-09-09 20:42:33 +00:00
|
|
|
KEBUGCHECK(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
Pte = *Pt;
|
2005-05-09 01:38:29 +00:00
|
|
|
tmpPte = Pte | PA_DIRTY;
|
2004-12-24 17:07:00 +00:00
|
|
|
} while (Pte != ExfInterlockedCompareExchange64UL(Pt, &tmpPte, &Pte));
|
2004-09-09 20:42:33 +00:00
|
|
|
if (!(Pte & PA_DIRTY))
|
|
|
|
{
|
2004-11-27 16:37:52 +00:00
|
|
|
MiFlushTlb((PULONG)Pt, Address);
|
2004-09-09 20:42:33 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
MmUnmapPageTable((PULONG)Pt);
|
2004-09-07 11:08:16 +00:00
|
|
|
}
|
2004-08-01 07:27:25 +00:00
|
|
|
}
|
2004-09-07 11:08:16 +00:00
|
|
|
else
|
2004-04-10 22:36:07 +00:00
|
|
|
{
|
2004-09-09 20:42:33 +00:00
|
|
|
PULONG Pt;
|
|
|
|
ULONG Pte;
|
|
|
|
|
|
|
|
Pt = MmGetPageTableForProcess(Process, Address, FALSE);
|
|
|
|
if (Pt == NULL)
|
|
|
|
{
|
|
|
|
KEBUGCHECK(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
Pte = *Pt;
|
2004-12-24 17:07:00 +00:00
|
|
|
} while (Pte != InterlockedCompareExchangeUL(Pt, Pte | PA_DIRTY, Pte));
|
2004-09-09 20:42:33 +00:00
|
|
|
if (!(Pte & PA_DIRTY))
|
|
|
|
{
|
2004-11-27 16:37:52 +00:00
|
|
|
MiFlushTlb(Pt, Address);
|
2004-09-09 20:42:33 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
MmUnmapPageTable(Pt);
|
|
|
|
}
|
2004-04-10 22:36:07 +00:00
|
|
|
}
|
2002-01-08 00:49:02 +00:00
|
|
|
}
|
2002-11-05 21:13:15 +00:00
|
|
|
|
2005-09-14 01:05:50 +00:00
|
|
|
VOID
|
|
|
|
NTAPI
|
2006-05-18 20:32:17 +00:00
|
|
|
MmEnableVirtualMapping(PEPROCESS Process, PVOID Address)
|
2001-12-31 01:53:46 +00:00
|
|
|
{
|
2004-09-26 16:32:18 +00:00
|
|
|
if (Ke386Pae)
|
2004-08-01 07:27:25 +00:00
|
|
|
{
|
2004-09-09 20:42:33 +00:00
|
|
|
PULONGLONG Pt;
|
|
|
|
ULONGLONG Pte;
|
|
|
|
ULONGLONG tmpPte;
|
2004-09-07 11:08:16 +00:00
|
|
|
|
2004-09-09 20:42:33 +00:00
|
|
|
Pt = MmGetPageTableForProcessForPAE(Process, Address, FALSE);
|
|
|
|
if (Pt == NULL)
|
2004-09-07 11:08:16 +00:00
|
|
|
{
|
2004-09-09 20:42:33 +00:00
|
|
|
KEBUGCHECK(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
Pte = *Pt;
|
|
|
|
tmpPte = Pte | PA_PRESENT;
|
2004-12-24 17:07:00 +00:00
|
|
|
} while (Pte != ExfInterlockedCompareExchange64UL(Pt, &tmpPte, &Pte));
|
2004-09-09 20:42:33 +00:00
|
|
|
if (!(Pte & PA_PRESENT))
|
|
|
|
{
|
2004-11-27 16:37:52 +00:00
|
|
|
MiFlushTlb((PULONG)Pt, Address);
|
2004-09-09 20:42:33 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
MmUnmapPageTable((PULONG)Pt);
|
2004-09-07 11:08:16 +00:00
|
|
|
}
|
2004-08-01 07:27:25 +00:00
|
|
|
}
|
2004-09-07 11:08:16 +00:00
|
|
|
else
|
2004-04-10 22:36:07 +00:00
|
|
|
{
|
2004-09-09 20:42:33 +00:00
|
|
|
PULONG Pt;
|
|
|
|
ULONG Pte;
|
|
|
|
|
|
|
|
Pt = MmGetPageTableForProcess(Process, Address, FALSE);
|
|
|
|
if (Pt == NULL)
|
|
|
|
{
|
|
|
|
KEBUGCHECK(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
Pte = *Pt;
|
2004-12-24 17:07:00 +00:00
|
|
|
} while (Pte != InterlockedCompareExchangeUL(Pt, Pte | PA_PRESENT, Pte));
|
2004-09-09 20:42:33 +00:00
|
|
|
if (!(Pte & PA_PRESENT))
|
|
|
|
{
|
2004-11-27 16:37:52 +00:00
|
|
|
MiFlushTlb(Pt, Address);
|
2004-09-09 20:42:33 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
MmUnmapPageTable(Pt);
|
|
|
|
}
|
2004-04-10 22:36:07 +00:00
|
|
|
}
|
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
|
|
|
{
|
2004-09-26 16:32:18 +00:00
|
|
|
if (Ke386Pae)
|
2004-09-09 20:42:33 +00:00
|
|
|
{
|
|
|
|
return MmGetPageEntryForProcessForPAE(Process, Address) & PA_PRESENT ? TRUE : FALSE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return MmGetPageEntryForProcess(Process, Address) & PA_PRESENT ? TRUE : 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
|
|
|
MmIsPageSwapEntry(PEPROCESS Process, PVOID Address)
|
2001-12-31 19:06:49 +00:00
|
|
|
{
|
2004-09-26 16:32:18 +00:00
|
|
|
if (Ke386Pae)
|
2004-09-09 20:42:33 +00:00
|
|
|
{
|
|
|
|
ULONGLONG Entry;
|
|
|
|
Entry = MmGetPageEntryForProcessForPAE(Process, Address);
|
|
|
|
return !(Entry & PA_PRESENT) && Entry != 0 ? TRUE : FALSE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ULONG Entry;
|
|
|
|
Entry = MmGetPageEntryForProcess(Process, Address);
|
|
|
|
return !(Entry & PA_PRESENT) && Entry != 0 ? TRUE : FALSE;
|
|
|
|
}
|
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
|
2004-05-20 08:37:21 +00:00
|
|
|
MmCreateVirtualMappingForKernel(PVOID Address,
|
|
|
|
ULONG flProtect,
|
2004-08-01 07:27:25 +00:00
|
|
|
PPFN_TYPE Pages,
|
|
|
|
ULONG PageCount)
|
2003-08-27 21:28:08 +00:00
|
|
|
{
|
2004-09-09 20:42:33 +00:00
|
|
|
ULONG Attributes;
|
2004-08-01 07:27:25 +00:00
|
|
|
ULONG i;
|
|
|
|
PVOID Addr;
|
2004-09-07 11:08:16 +00:00
|
|
|
ULONG PdeOffset, oldPdeOffset;
|
2004-09-26 16:32:18 +00:00
|
|
|
BOOLEAN NoExecute = FALSE;
|
2004-09-07 11:08:16 +00:00
|
|
|
|
|
|
|
DPRINT("MmCreateVirtualMappingForKernel(%x, %x, %x, %d)\n",
|
|
|
|
Address, flProtect, Pages, PageCount);
|
2003-08-27 21:28:08 +00:00
|
|
|
|
2005-07-06 08:20:26 +00:00
|
|
|
if (Address < MmSystemRangeStart)
|
2004-04-10 22:36:07 +00:00
|
|
|
{
|
2004-05-20 08:37:21 +00:00
|
|
|
DPRINT1("MmCreateVirtualMappingForKernel is called for user space\n");
|
2004-04-10 22:36:07 +00:00
|
|
|
KEBUGCHECK(0);
|
|
|
|
}
|
|
|
|
|
2003-08-27 21:28:08 +00:00
|
|
|
Attributes = ProtectToPTE(flProtect);
|
2004-09-26 16:32:18 +00:00
|
|
|
if (Attributes & 0x80000000)
|
|
|
|
{
|
|
|
|
NoExecute = TRUE;
|
|
|
|
}
|
|
|
|
Attributes &= 0xfff;
|
2004-11-13 23:08:35 +00:00
|
|
|
if (Ke386GlobalPagesEnabled)
|
2004-08-14 09:17:05 +00:00
|
|
|
{
|
|
|
|
Attributes |= PA_GLOBAL;
|
|
|
|
}
|
2004-09-07 11:08:16 +00:00
|
|
|
|
2004-08-01 07:27:25 +00:00
|
|
|
Addr = Address;
|
2004-09-07 11:08:16 +00:00
|
|
|
|
2004-09-26 16:32:18 +00:00
|
|
|
if (Ke386Pae)
|
2004-04-10 22:36:07 +00:00
|
|
|
{
|
2004-09-09 20:42:33 +00:00
|
|
|
PULONGLONG Pt = NULL;
|
|
|
|
ULONGLONG Pte;
|
2004-04-10 22:36:07 +00:00
|
|
|
|
2004-09-09 20:42:33 +00:00
|
|
|
oldPdeOffset = PAE_ADDR_TO_PDE_OFFSET(Addr) + 1;
|
2005-07-05 00:57:47 +00:00
|
|
|
for (i = 0; i < PageCount; i++, Addr = (PVOID)((ULONG_PTR)Addr + PAGE_SIZE))
|
2004-08-01 07:27:25 +00:00
|
|
|
{
|
2004-09-09 20:42:33 +00:00
|
|
|
if (!(Attributes & PA_PRESENT) && Pages[i] != 0)
|
|
|
|
{
|
|
|
|
DPRINT1("Setting physical address but not allowing access at address "
|
|
|
|
"0x%.8X with attributes %x/%x.\n",
|
|
|
|
Addr, Attributes, flProtect);
|
|
|
|
KEBUGCHECK(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
PdeOffset = PAE_ADDR_TO_PDE_OFFSET(Addr);
|
|
|
|
if (oldPdeOffset != PdeOffset)
|
|
|
|
{
|
|
|
|
Pt = MmGetPageTableForProcessForPAE(NULL, Addr, TRUE);
|
|
|
|
if (Pt == NULL)
|
|
|
|
{
|
|
|
|
KEBUGCHECK(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Pt++;
|
|
|
|
}
|
|
|
|
oldPdeOffset = PdeOffset;
|
|
|
|
|
|
|
|
Pte = PFN_TO_PTE(Pages[i]) | Attributes;
|
2004-09-26 16:32:18 +00:00
|
|
|
if (NoExecute)
|
|
|
|
{
|
|
|
|
Pte |= 0x8000000000000000LL;
|
|
|
|
}
|
2004-12-24 17:07:00 +00:00
|
|
|
Pte = ExfpInterlockedExchange64UL(Pt, &Pte);
|
2004-09-09 20:42:33 +00:00
|
|
|
if (Pte != 0LL)
|
|
|
|
{
|
|
|
|
KEBUGCHECK(0);
|
|
|
|
}
|
2004-08-01 07:27:25 +00:00
|
|
|
}
|
2004-09-09 20:42:33 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
PULONG Pt;
|
|
|
|
ULONG Pte;
|
|
|
|
|
|
|
|
oldPdeOffset = ADDR_TO_PDE_OFFSET(Addr);
|
|
|
|
Pt = MmGetPageTableForProcess(NULL, Addr, TRUE);
|
|
|
|
if (Pt == NULL)
|
2004-08-01 07:27:25 +00:00
|
|
|
{
|
2004-09-09 20:42:33 +00:00
|
|
|
KEBUGCHECK(0);
|
2004-08-01 07:27:25 +00:00
|
|
|
}
|
2004-09-09 20:42:33 +00:00
|
|
|
Pt--;
|
2004-09-07 11:08:16 +00:00
|
|
|
|
2005-07-05 00:57:47 +00:00
|
|
|
for (i = 0; i < PageCount; i++, Addr = (PVOID)((ULONG_PTR)Addr + PAGE_SIZE))
|
2004-08-01 07:27:25 +00:00
|
|
|
{
|
2004-09-09 20:42:33 +00:00
|
|
|
if (!(Attributes & PA_PRESENT) && Pages[i] != 0)
|
|
|
|
{
|
|
|
|
DPRINT1("Setting physical address but not allowing access at address "
|
|
|
|
"0x%.8X with attributes %x/%x.\n",
|
|
|
|
Addr, Attributes, flProtect);
|
|
|
|
KEBUGCHECK(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
PdeOffset = ADDR_TO_PDE_OFFSET(Addr);
|
|
|
|
if (oldPdeOffset != PdeOffset)
|
|
|
|
{
|
|
|
|
Pt = MmGetPageTableForProcess(NULL, Addr, TRUE);
|
|
|
|
if (Pt == NULL)
|
|
|
|
{
|
|
|
|
KEBUGCHECK(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Pt++;
|
|
|
|
}
|
|
|
|
oldPdeOffset = PdeOffset;
|
|
|
|
|
|
|
|
Pte = *Pt;
|
|
|
|
if (Pte != 0)
|
|
|
|
{
|
|
|
|
KEBUGCHECK(0);
|
|
|
|
}
|
2006-03-04 17:27:40 +00:00
|
|
|
(void)InterlockedExchangeUL(Pt, PFN_TO_PTE(Pages[i]) | Attributes);
|
2004-08-01 07:27:25 +00:00
|
|
|
}
|
2004-04-10 22:36:07 +00:00
|
|
|
}
|
2004-05-20 08:37:21 +00:00
|
|
|
|
2001-04-17 04:11:01 +00:00
|
|
|
return(STATUS_SUCCESS);
|
|
|
|
}
|
|
|
|
|
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
|
|
|
{
|
2005-07-06 08:20:26 +00:00
|
|
|
if (Process == NULL && Address < MmSystemRangeStart)
|
2004-04-10 22:36:07 +00:00
|
|
|
{
|
2001-12-31 19:06:49 +00:00
|
|
|
DPRINT1("No process\n");
|
2003-07-21 21:53:53 +00:00
|
|
|
KEBUGCHECK(0);
|
2004-04-10 22:36:07 +00:00
|
|
|
}
|
2005-07-06 08:20:26 +00:00
|
|
|
if (Process != NULL && Address >= MmSystemRangeStart)
|
2004-04-10 22:36:07 +00:00
|
|
|
{
|
2001-12-31 19:06:49 +00:00
|
|
|
DPRINT1("Setting kernel address with process context\n");
|
2003-07-21 21:53:53 +00:00
|
|
|
KEBUGCHECK(0);
|
2004-04-10 22:36:07 +00:00
|
|
|
}
|
|
|
|
if (SwapEntry & (1 << 31))
|
|
|
|
{
|
2003-07-21 21:53:53 +00:00
|
|
|
KEBUGCHECK(0);
|
2004-04-10 22:36:07 +00:00
|
|
|
}
|
|
|
|
|
2004-09-26 16:32:18 +00:00
|
|
|
if (Ke386Pae)
|
2004-04-10 22:36:07 +00:00
|
|
|
{
|
2004-09-09 20:42:33 +00:00
|
|
|
PULONGLONG Pt;
|
|
|
|
ULONGLONG Pte;
|
|
|
|
ULONGLONG tmpPte;
|
|
|
|
|
|
|
|
Pt = MmGetPageTableForProcessForPAE(Process, Address, TRUE);
|
|
|
|
if (Pt == NULL)
|
2004-09-07 11:08:16 +00:00
|
|
|
{
|
2004-09-09 20:42:33 +00:00
|
|
|
KEBUGCHECK(0);
|
|
|
|
}
|
|
|
|
tmpPte = SwapEntry << 1;
|
2004-12-24 17:07:00 +00:00
|
|
|
Pte = ExfpInterlockedExchange64UL(Pt, &tmpPte);
|
2004-09-09 20:42:33 +00:00
|
|
|
if (PAE_PAGE_MASK((Pte)) != 0)
|
|
|
|
{
|
|
|
|
MmMarkPageUnmapped(PAE_PTE_TO_PFN((Pte)));
|
|
|
|
}
|
|
|
|
|
2005-05-09 01:38:29 +00:00
|
|
|
if (Pte != 0)
|
2004-09-09 20:42:33 +00:00
|
|
|
{
|
2004-11-27 16:37:52 +00:00
|
|
|
MiFlushTlb((PULONG)Pt, Address);
|
2004-09-09 20:42:33 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
MmUnmapPageTable((PULONG)Pt);
|
2004-09-07 11:08:16 +00:00
|
|
|
}
|
2004-04-10 22:36:07 +00:00
|
|
|
}
|
2004-09-07 11:08:16 +00:00
|
|
|
else
|
|
|
|
{
|
2004-09-09 20:42:33 +00:00
|
|
|
PULONG Pt;
|
|
|
|
ULONG Pte;
|
2004-09-07 11:08:16 +00:00
|
|
|
|
2004-09-09 20:42:33 +00:00
|
|
|
Pt = MmGetPageTableForProcess(Process, Address, TRUE);
|
|
|
|
if (Pt == NULL)
|
|
|
|
{
|
|
|
|
KEBUGCHECK(0);
|
|
|
|
}
|
|
|
|
Pte = *Pt;
|
|
|
|
if (PAGE_MASK((Pte)) != 0)
|
|
|
|
{
|
|
|
|
MmMarkPageUnmapped(PTE_TO_PFN((Pte)));
|
|
|
|
}
|
2006-03-04 17:27:40 +00:00
|
|
|
(void)InterlockedExchangeUL(Pt, SwapEntry << 1);
|
2005-05-09 01:38:29 +00:00
|
|
|
if (Pte != 0)
|
2004-09-09 20:42:33 +00:00
|
|
|
{
|
2004-11-27 16:37:52 +00:00
|
|
|
MiFlushTlb(Pt, Address);
|
2004-09-09 20:42:33 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
MmUnmapPageTable(Pt);
|
|
|
|
}
|
|
|
|
}
|
2004-04-10 22:36:07 +00:00
|
|
|
if (Process != NULL &&
|
2006-05-18 20:10:44 +00:00
|
|
|
((PMADDRESS_SPACE)&Process->VadRoot)->PageTableRefCountTable != NULL &&
|
2005-07-06 08:20:26 +00:00
|
|
|
Address < MmSystemRangeStart)
|
2004-04-10 22:36:07 +00:00
|
|
|
{
|
2004-09-09 20:42:33 +00:00
|
|
|
PUSHORT Ptrc;
|
|
|
|
ULONG Idx;
|
2004-04-10 22:36:07 +00:00
|
|
|
|
2006-05-18 20:10:44 +00:00
|
|
|
Ptrc = ((PMADDRESS_SPACE)&Process->VadRoot)->PageTableRefCountTable;
|
2004-09-26 16:32:18 +00:00
|
|
|
Idx = Ke386Pae ? PAE_ADDR_TO_PAGE_TABLE(Address) : ADDR_TO_PAGE_TABLE(Address);
|
2004-09-09 20:42:33 +00:00
|
|
|
Ptrc[Idx]++;
|
2004-04-10 22:36:07 +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,
|
2004-08-01 07:27:25 +00:00
|
|
|
PPFN_TYPE Pages,
|
|
|
|
ULONG PageCount)
|
1999-11-12 12:01:17 +00:00
|
|
|
{
|
2001-04-13 16:12:26 +00:00
|
|
|
ULONG Attributes;
|
2004-09-07 11:08:16 +00:00
|
|
|
PVOID Addr;
|
2004-08-01 07:27:25 +00:00
|
|
|
ULONG i;
|
2004-09-07 11:08:16 +00:00
|
|
|
ULONG oldPdeOffset, PdeOffset;
|
2004-09-26 16:32:18 +00:00
|
|
|
BOOLEAN NoExecute = FALSE;
|
2001-04-13 16:12:26 +00:00
|
|
|
|
2004-09-26 16:32:18 +00:00
|
|
|
DPRINT("MmCreateVirtualMappingUnsafe(%x, %x, %x, %x (%x), %d)\n",
|
|
|
|
Process, Address, flProtect, Pages, *Pages, PageCount);
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2004-09-07 11:08:16 +00:00
|
|
|
if (Process == NULL)
|
2004-04-10 22:36:07 +00:00
|
|
|
{
|
2005-07-06 08:20:26 +00:00
|
|
|
if (Address < MmSystemRangeStart)
|
2004-09-07 11:08:16 +00:00
|
|
|
{
|
|
|
|
DPRINT1("No process\n");
|
|
|
|
KEBUGCHECK(0);
|
|
|
|
}
|
2005-05-09 01:38:29 +00:00
|
|
|
if (PageCount > 0x10000 ||
|
2004-09-07 11:08:16 +00:00
|
|
|
(ULONG_PTR) Address / PAGE_SIZE + PageCount > 0x100000)
|
|
|
|
{
|
|
|
|
DPRINT1("Page count to large\n");
|
|
|
|
KEBUGCHECK(0);
|
|
|
|
}
|
2004-04-10 22:36:07 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2005-07-06 08:20:26 +00:00
|
|
|
if (Address >= MmSystemRangeStart)
|
2004-09-07 11:08:16 +00:00
|
|
|
{
|
|
|
|
DPRINT1("Setting kernel address with process context\n");
|
|
|
|
KEBUGCHECK(0);
|
|
|
|
}
|
2005-07-06 08:20:26 +00:00
|
|
|
if (PageCount > (ULONG_PTR)MmSystemRangeStart / PAGE_SIZE ||
|
|
|
|
(ULONG_PTR) Address / PAGE_SIZE + PageCount >
|
|
|
|
(ULONG_PTR)MmSystemRangeStart / PAGE_SIZE)
|
2004-09-07 11:08:16 +00:00
|
|
|
{
|
|
|
|
DPRINT1("Page Count to large\n");
|
|
|
|
KEBUGCHECK(0);
|
|
|
|
}
|
2004-04-10 22:36:07 +00:00
|
|
|
}
|
|
|
|
|
1999-11-12 12:01:17 +00:00
|
|
|
Attributes = ProtectToPTE(flProtect);
|
2004-09-26 16:32:18 +00:00
|
|
|
if (Attributes & 0x80000000)
|
|
|
|
{
|
|
|
|
NoExecute = TRUE;
|
|
|
|
}
|
|
|
|
Attributes &= 0xfff;
|
2005-07-06 08:20:26 +00:00
|
|
|
if (Address >= MmSystemRangeStart)
|
2004-08-10 19:57:58 +00:00
|
|
|
{
|
|
|
|
Attributes &= ~PA_USER;
|
2004-11-13 23:08:35 +00:00
|
|
|
if (Ke386GlobalPagesEnabled)
|
2004-08-14 09:17:05 +00:00
|
|
|
{
|
|
|
|
Attributes |= PA_GLOBAL;
|
|
|
|
}
|
2004-08-10 19:57:58 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Attributes |= PA_USER;
|
|
|
|
}
|
2004-04-10 22:36:07 +00:00
|
|
|
|
2004-09-07 11:08:16 +00:00
|
|
|
Addr = Address;
|
2004-04-10 22:36:07 +00:00
|
|
|
|
2004-09-26 16:32:18 +00:00
|
|
|
if (Ke386Pae)
|
2004-04-10 22:36:07 +00:00
|
|
|
{
|
2004-09-09 20:42:33 +00:00
|
|
|
ULONGLONG Pte, tmpPte;
|
|
|
|
PULONGLONG Pt = NULL;
|
2004-09-07 11:08:16 +00:00
|
|
|
|
2004-09-09 20:42:33 +00:00
|
|
|
oldPdeOffset = PAE_ADDR_TO_PDE_OFFSET(Addr) + 1;
|
2005-07-05 00:57:47 +00:00
|
|
|
for (i = 0; i < PageCount; i++, Addr = (PVOID)((ULONG_PTR)Addr + PAGE_SIZE))
|
2004-08-01 07:27:25 +00:00
|
|
|
{
|
2004-09-09 20:42:33 +00:00
|
|
|
if (!(Attributes & PA_PRESENT) && Pages[i] != 0)
|
|
|
|
{
|
|
|
|
DPRINT1("Setting physical address but not allowing access at address "
|
|
|
|
"0x%.8X with attributes %x/%x.\n",
|
|
|
|
Addr, Attributes, flProtect);
|
|
|
|
KEBUGCHECK(0);
|
|
|
|
}
|
|
|
|
PdeOffset = PAE_ADDR_TO_PDE_OFFSET(Addr);
|
|
|
|
if (oldPdeOffset != PdeOffset)
|
|
|
|
{
|
|
|
|
MmUnmapPageTable((PULONG)Pt);
|
|
|
|
Pt = MmGetPageTableForProcessForPAE(Process, Addr, TRUE);
|
|
|
|
if (Pt == NULL)
|
|
|
|
{
|
|
|
|
KEBUGCHECK(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Pt++;
|
|
|
|
}
|
|
|
|
oldPdeOffset = PdeOffset;
|
|
|
|
|
|
|
|
MmMarkPageMapped(Pages[i]);
|
|
|
|
tmpPte = PAE_PFN_TO_PTE(Pages[i]) | Attributes;
|
2004-09-26 16:32:18 +00:00
|
|
|
if (NoExecute)
|
|
|
|
{
|
|
|
|
tmpPte |= 0x8000000000000000LL;
|
|
|
|
}
|
2004-12-24 17:07:00 +00:00
|
|
|
Pte = ExfpInterlockedExchange64UL(Pt, &tmpPte);
|
2004-09-09 20:42:33 +00:00
|
|
|
if (PAE_PAGE_MASK((Pte)) != 0LL && !((Pte) & PA_PRESENT))
|
|
|
|
{
|
|
|
|
KEBUGCHECK(0);
|
|
|
|
}
|
|
|
|
if (PAE_PAGE_MASK((Pte)) != 0LL)
|
|
|
|
{
|
|
|
|
MmMarkPageUnmapped(PAE_PTE_TO_PFN((Pte)));
|
|
|
|
}
|
2005-07-06 08:20:26 +00:00
|
|
|
if (Address < MmSystemRangeStart &&
|
2006-05-18 20:10:44 +00:00
|
|
|
((PMADDRESS_SPACE)&Process->VadRoot)->PageTableRefCountTable != NULL &&
|
2004-09-09 20:42:33 +00:00
|
|
|
Attributes & PA_PRESENT)
|
|
|
|
{
|
|
|
|
PUSHORT Ptrc;
|
|
|
|
|
2006-05-18 20:10:44 +00:00
|
|
|
Ptrc = ((PMADDRESS_SPACE)&Process->VadRoot)->PageTableRefCountTable;
|
2004-09-09 20:42:33 +00:00
|
|
|
|
|
|
|
Ptrc[PAE_ADDR_TO_PAGE_TABLE(Addr)]++;
|
|
|
|
}
|
|
|
|
if (Pte != 0LL)
|
|
|
|
{
|
2005-07-06 08:20:26 +00:00
|
|
|
if (Address > MmSystemRangeStart ||
|
2004-09-09 20:42:33 +00:00
|
|
|
(Pt >= (PULONGLONG)PAGETABLE_MAP && Pt < (PULONGLONG)PAGETABLE_MAP + 4*512*512))
|
|
|
|
{
|
2004-11-27 16:37:52 +00:00
|
|
|
MiFlushTlb((PULONG)Pt, Address);
|
2004-09-09 20:42:33 +00:00
|
|
|
}
|
|
|
|
}
|
2004-08-01 07:27:25 +00:00
|
|
|
}
|
2004-09-09 20:42:33 +00:00
|
|
|
if (Addr > Address)
|
2004-08-01 07:27:25 +00:00
|
|
|
{
|
2004-09-09 20:42:33 +00:00
|
|
|
MmUnmapPageTable((PULONG)Pt);
|
2004-08-01 07:27:25 +00:00
|
|
|
}
|
2004-09-09 20:42:33 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
PULONG Pt = NULL;
|
|
|
|
ULONG Pte;
|
|
|
|
oldPdeOffset = ADDR_TO_PDE_OFFSET(Addr) + 1;
|
2005-07-05 00:57:47 +00:00
|
|
|
for (i = 0; i < PageCount; i++, Addr = (PVOID)((ULONG_PTR)Addr + PAGE_SIZE))
|
2004-08-01 07:27:25 +00:00
|
|
|
{
|
2004-09-09 20:42:33 +00:00
|
|
|
if (!(Attributes & PA_PRESENT) && Pages[i] != 0)
|
|
|
|
{
|
|
|
|
DPRINT1("Setting physical address but not allowing access at address "
|
|
|
|
"0x%.8X with attributes %x/%x.\n",
|
|
|
|
Addr, Attributes, flProtect);
|
|
|
|
KEBUGCHECK(0);
|
|
|
|
}
|
|
|
|
PdeOffset = ADDR_TO_PDE_OFFSET(Addr);
|
|
|
|
if (oldPdeOffset != PdeOffset)
|
|
|
|
{
|
|
|
|
MmUnmapPageTable(Pt);
|
|
|
|
Pt = MmGetPageTableForProcess(Process, Addr, TRUE);
|
|
|
|
if (Pt == NULL)
|
|
|
|
{
|
|
|
|
KEBUGCHECK(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Pt++;
|
|
|
|
}
|
|
|
|
oldPdeOffset = PdeOffset;
|
2004-04-10 22:36:07 +00:00
|
|
|
|
2004-09-09 20:42:33 +00:00
|
|
|
Pte = *Pt;
|
|
|
|
MmMarkPageMapped(Pages[i]);
|
|
|
|
if (PAGE_MASK((Pte)) != 0 && !((Pte) & PA_PRESENT))
|
|
|
|
{
|
|
|
|
KEBUGCHECK(0);
|
|
|
|
}
|
|
|
|
if (PAGE_MASK((Pte)) != 0)
|
|
|
|
{
|
|
|
|
MmMarkPageUnmapped(PTE_TO_PFN((Pte)));
|
|
|
|
}
|
2006-03-04 17:27:40 +00:00
|
|
|
(void)InterlockedExchangeUL(Pt, PFN_TO_PTE(Pages[i]) | Attributes);
|
2005-07-06 08:20:26 +00:00
|
|
|
if (Address < MmSystemRangeStart &&
|
2006-05-18 20:10:44 +00:00
|
|
|
((PMADDRESS_SPACE)&Process->VadRoot)->PageTableRefCountTable != NULL &&
|
2004-09-09 20:42:33 +00:00
|
|
|
Attributes & PA_PRESENT)
|
|
|
|
{
|
|
|
|
PUSHORT Ptrc;
|
2004-04-10 22:36:07 +00:00
|
|
|
|
2006-05-18 20:10:44 +00:00
|
|
|
Ptrc = ((PMADDRESS_SPACE)&Process->VadRoot)->PageTableRefCountTable;
|
2004-09-09 20:42:33 +00:00
|
|
|
|
|
|
|
Ptrc[ADDR_TO_PAGE_TABLE(Addr)]++;
|
|
|
|
}
|
|
|
|
if (Pte != 0)
|
2004-09-07 11:08:16 +00:00
|
|
|
{
|
2005-07-06 08:20:26 +00:00
|
|
|
if (Address > MmSystemRangeStart ||
|
2004-09-09 20:42:33 +00:00
|
|
|
(Pt >= (PULONG)PAGETABLE_MAP && Pt < (PULONG)PAGETABLE_MAP + 1024*1024))
|
|
|
|
{
|
2004-11-27 16:37:52 +00:00
|
|
|
MiFlushTlb(Pt, Address);
|
2004-09-09 20:42:33 +00:00
|
|
|
}
|
2004-09-07 11:08:16 +00:00
|
|
|
}
|
2004-08-01 07:27:25 +00:00
|
|
|
}
|
2004-09-09 20:42:33 +00:00
|
|
|
if (Addr > Address)
|
|
|
|
{
|
|
|
|
MmUnmapPageTable(Pt);
|
|
|
|
}
|
2004-04-10 22:36:07 +00:00
|
|
|
}
|
2000-08-20 17:02:10 +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,
|
2004-08-01 07:27:25 +00:00
|
|
|
PPFN_TYPE Pages,
|
|
|
|
ULONG PageCount)
|
2001-03-26 20:46:53 +00:00
|
|
|
{
|
2004-08-01 07:27:25 +00:00
|
|
|
ULONG i;
|
|
|
|
|
|
|
|
for (i = 0; i < PageCount; i++)
|
2004-04-10 22:36:07 +00:00
|
|
|
{
|
2008-02-14 20:30:31 +00:00
|
|
|
if (!MmIsPageInUse(Pages[i]))
|
2004-08-01 07:27:25 +00:00
|
|
|
{
|
2008-02-14 20:30:31 +00:00
|
|
|
DPRINT1("Page at address %x not in use\n", PFN_TO_PTE(Pages[i]));
|
|
|
|
KEBUGCHECK(0);
|
2004-08-01 07:27:25 +00:00
|
|
|
}
|
2004-04-10 22:36:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return(MmCreateVirtualMappingUnsafe(Process,
|
|
|
|
Address,
|
|
|
|
flProtect,
|
2004-08-01 07:27:25 +00:00
|
|
|
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
|
|
|
{
|
2004-04-10 22:36:07 +00:00
|
|
|
ULONG Entry;
|
|
|
|
ULONG Protect;
|
2004-09-26 16:32:18 +00:00
|
|
|
if (Ke386Pae)
|
2004-09-09 20:42:33 +00:00
|
|
|
{
|
|
|
|
Entry = MmGetPageEntryForProcessForPAE(Process, Address);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Entry = MmGetPageEntryForProcess(Process, Address);
|
|
|
|
}
|
2001-02-10 22:51:11 +00:00
|
|
|
|
2004-04-10 22:36:07 +00:00
|
|
|
if (!(Entry & PA_PRESENT))
|
|
|
|
{
|
2001-02-10 22:51:11 +00:00
|
|
|
Protect = PAGE_NOACCESS;
|
2004-04-10 22:36:07 +00:00
|
|
|
}
|
2005-05-09 01:38:29 +00:00
|
|
|
else
|
2004-04-10 22:36:07 +00:00
|
|
|
{
|
2004-08-10 19:57:58 +00:00
|
|
|
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;
|
|
|
|
}
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2004-04-10 22:36:07 +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
|
|
|
{
|
|
|
|
ULONG Attributes = 0;
|
2004-09-26 16:32:18 +00:00
|
|
|
BOOLEAN NoExecute = FALSE;
|
1999-11-12 12:01:17 +00:00
|
|
|
|
2001-04-13 16:12:26 +00:00
|
|
|
DPRINT("MmSetPageProtect(Process %x Address %x flProtect %x)\n",
|
2004-04-10 22:36:07 +00:00
|
|
|
Process, Address, flProtect);
|
2001-04-13 16:12:26 +00:00
|
|
|
|
|
|
|
Attributes = ProtectToPTE(flProtect);
|
2004-09-26 16:32:18 +00:00
|
|
|
if (Attributes & 0x80000000)
|
|
|
|
{
|
|
|
|
NoExecute = TRUE;
|
|
|
|
}
|
|
|
|
Attributes &= 0xfff;
|
2005-07-06 08:20:26 +00:00
|
|
|
if (Address >= MmSystemRangeStart)
|
2004-08-10 19:57:58 +00:00
|
|
|
{
|
|
|
|
Attributes &= ~PA_USER;
|
2004-11-13 23:08:35 +00:00
|
|
|
if (Ke386GlobalPagesEnabled)
|
2004-08-14 09:17:05 +00:00
|
|
|
{
|
|
|
|
Attributes |= PA_GLOBAL;
|
|
|
|
}
|
2004-08-10 19:57:58 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Attributes |= PA_USER;
|
|
|
|
}
|
2004-09-26 16:32:18 +00:00
|
|
|
if (Ke386Pae)
|
2004-08-01 07:27:25 +00:00
|
|
|
{
|
2004-09-09 20:42:33 +00:00
|
|
|
PULONGLONG Pt;
|
|
|
|
ULONGLONG tmpPte, Pte;
|
|
|
|
|
|
|
|
Pt = MmGetPageTableForProcessForPAE(Process, Address, FALSE);
|
|
|
|
if (Pt == NULL)
|
|
|
|
{
|
2004-09-26 16:32:18 +00:00
|
|
|
DPRINT1("Address %x\n", Address);
|
2004-09-09 20:42:33 +00:00
|
|
|
KEBUGCHECK(0);
|
|
|
|
}
|
|
|
|
do
|
|
|
|
{
|
|
|
|
Pte = *Pt;
|
|
|
|
tmpPte = PAE_PAGE_MASK(Pte) | Attributes | (Pte & (PA_ACCESSED|PA_DIRTY));
|
2004-09-26 16:32:18 +00:00
|
|
|
if (NoExecute)
|
|
|
|
{
|
|
|
|
tmpPte |= 0x8000000000000000LL;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
tmpPte &= ~0x8000000000000000LL;
|
|
|
|
}
|
2004-12-24 17:07:00 +00:00
|
|
|
} while (Pte != ExfInterlockedCompareExchange64UL(Pt, &tmpPte, &Pte));
|
2004-09-09 20:42:33 +00:00
|
|
|
|
2004-11-27 16:37:52 +00:00
|
|
|
MiFlushTlb((PULONG)Pt, Address);
|
2004-08-01 07:27:25 +00:00
|
|
|
}
|
2004-09-09 20:42:33 +00:00
|
|
|
else
|
2004-04-10 22:36:07 +00:00
|
|
|
{
|
2004-09-09 20:42:33 +00:00
|
|
|
PULONG Pt;
|
|
|
|
|
|
|
|
Pt = MmGetPageTableForProcess(Process, Address, FALSE);
|
|
|
|
if (Pt == NULL)
|
|
|
|
{
|
|
|
|
KEBUGCHECK(0);
|
|
|
|
}
|
2005-05-01 19:30:06 +00:00
|
|
|
InterlockedExchange((PLONG)Pt, PAGE_MASK(*Pt) | Attributes | (*Pt & (PA_ACCESSED|PA_DIRTY)));
|
2004-11-27 16:37:52 +00:00
|
|
|
MiFlushTlb(Pt, Address);
|
2004-04-10 22:36:07 +00:00
|
|
|
}
|
1999-11-12 12:01:17 +00:00
|
|
|
}
|
|
|
|
|
2003-07-11 01:23:16 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2004-04-10 22:36:07 +00:00
|
|
|
PHYSICAL_ADDRESS STDCALL
|
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
|
|
|
|
*/
|
|
|
|
{
|
1999-12-22 14:48:30 +00:00
|
|
|
PHYSICAL_ADDRESS p;
|
1999-11-12 12:01:17 +00:00
|
|
|
|
1999-12-22 14:48:30 +00:00
|
|
|
DPRINT("MmGetPhysicalAddress(vaddr %x)\n", vaddr);
|
2004-09-26 16:32:18 +00:00
|
|
|
if (Ke386Pae)
|
2004-04-10 22:36:07 +00:00
|
|
|
{
|
2004-09-09 20:42:33 +00:00
|
|
|
ULONGLONG Pte;
|
|
|
|
Pte = MmGetPageEntryForProcessForPAE(NULL, vaddr);
|
|
|
|
if (Pte != 0 && Pte & PA_PRESENT)
|
|
|
|
{
|
|
|
|
p.QuadPart = PAE_PAGE_MASK(Pte);
|
|
|
|
p.u.LowPart |= (ULONG_PTR)vaddr & (PAGE_SIZE - 1);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
p.QuadPart = 0;
|
|
|
|
}
|
2004-04-10 22:36:07 +00:00
|
|
|
}
|
2001-12-31 19:06:49 +00:00
|
|
|
else
|
2004-04-10 22:36:07 +00:00
|
|
|
{
|
2004-09-09 20:42:33 +00:00
|
|
|
ULONG Pte;
|
|
|
|
Pte = MmGetPageEntryForProcess(NULL, vaddr);
|
|
|
|
if (Pte != 0 && Pte & PA_PRESENT)
|
|
|
|
{
|
|
|
|
p.QuadPart = PAGE_MASK(Pte);
|
|
|
|
p.u.LowPart |= (ULONG_PTR)vaddr & (PAGE_SIZE - 1);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
p.QuadPart = 0;
|
|
|
|
}
|
2004-04-10 22:36:07 +00:00
|
|
|
}
|
1999-12-22 14:48:30 +00:00
|
|
|
return p;
|
1999-11-12 12:01:17 +00:00
|
|
|
}
|
2000-04-02 13:32:43 +00:00
|
|
|
|
2005-01-25 22:50:47 +00:00
|
|
|
PVOID
|
2005-09-14 01:05:50 +00:00
|
|
|
NTAPI
|
2005-01-25 22:50:47 +00:00
|
|
|
MmCreateHyperspaceMapping(PFN_TYPE Page)
|
|
|
|
{
|
|
|
|
PVOID Address;
|
2005-07-05 22:35:29 +00:00
|
|
|
ULONG i;
|
2005-01-25 22:50:47 +00:00
|
|
|
|
|
|
|
if (Ke386Pae)
|
|
|
|
{
|
|
|
|
ULONGLONG Entry;
|
|
|
|
ULONGLONG ZeroEntry = 0LL;
|
|
|
|
PULONGLONG Pte;
|
|
|
|
|
|
|
|
Entry = PFN_TO_PTE(Page) | PA_PRESENT | PA_READWRITE;
|
|
|
|
Pte = PAE_ADDR_TO_PTE(HYPERSPACE) + Page % 1024;
|
|
|
|
|
|
|
|
if (Page & 1024)
|
|
|
|
{
|
|
|
|
for (i = Page %1024; i < 1024; i++, Pte++)
|
|
|
|
{
|
|
|
|
if (0LL == ExfInterlockedCompareExchange64UL(Pte, &Entry, &ZeroEntry))
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (i >= 1024)
|
|
|
|
{
|
|
|
|
Pte = PAE_ADDR_TO_PTE(HYPERSPACE);
|
|
|
|
for (i = 0; i < Page % 1024; i++, Pte++)
|
|
|
|
{
|
|
|
|
if (0LL == ExfInterlockedCompareExchange64UL(Pte, &Entry, &ZeroEntry))
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (i >= Page % 1024)
|
|
|
|
{
|
|
|
|
KEBUGCHECK(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2005-05-09 01:38:29 +00:00
|
|
|
else
|
2005-01-25 22:50:47 +00:00
|
|
|
{
|
2005-07-07 19:54:25 +00:00
|
|
|
for (i = Page %1024; (LONG)i >= 0; i--, Pte--)
|
2005-01-25 22:50:47 +00:00
|
|
|
{
|
|
|
|
if (0LL == ExfInterlockedCompareExchange64UL(Pte, &Entry, &ZeroEntry))
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2005-07-07 19:54:25 +00:00
|
|
|
if ((LONG)i < 0)
|
2005-01-25 22:50:47 +00:00
|
|
|
{
|
|
|
|
Pte = PAE_ADDR_TO_PTE(HYPERSPACE) + 1023;
|
|
|
|
for (i = 1023; i > Page % 1024; i--, Pte--)
|
|
|
|
{
|
|
|
|
if (0LL == ExfInterlockedCompareExchange64UL(Pte, &Entry, &ZeroEntry))
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (i <= Page % 1024)
|
|
|
|
{
|
|
|
|
KEBUGCHECK(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ULONG Entry;
|
|
|
|
PULONG Pte;
|
|
|
|
Entry = PFN_TO_PTE(Page) | PA_PRESENT | PA_READWRITE;
|
|
|
|
Pte = ADDR_TO_PTE(HYPERSPACE) + Page % 1024;
|
|
|
|
if (Page & 1024)
|
|
|
|
{
|
|
|
|
for (i = Page % 1024; i < 1024; i++, Pte++)
|
|
|
|
{
|
|
|
|
if (0 == InterlockedCompareExchange((PLONG)Pte, (LONG)Entry, 0))
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (i >= 1024)
|
|
|
|
{
|
|
|
|
Pte = ADDR_TO_PTE(HYPERSPACE);
|
|
|
|
for (i = 0; i < Page % 1024; i++, Pte++)
|
|
|
|
{
|
|
|
|
if (0 == InterlockedCompareExchange((PLONG)Pte, (LONG)Entry, 0))
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (i >= Page % 1024)
|
|
|
|
{
|
|
|
|
KEBUGCHECK(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2005-07-07 19:54:25 +00:00
|
|
|
for (i = Page % 1024; (LONG)i >= 0; i--, Pte--)
|
2005-01-25 22:50:47 +00:00
|
|
|
{
|
|
|
|
if (0 == InterlockedCompareExchange((PLONG)Pte, (LONG)Entry, 0))
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2005-07-07 19:54:25 +00:00
|
|
|
if ((LONG)i < 0)
|
2005-01-25 22:50:47 +00:00
|
|
|
{
|
|
|
|
Pte = ADDR_TO_PTE(HYPERSPACE) + 1023;
|
|
|
|
for (i = 1023; i > Page % 1024; i--, Pte--)
|
|
|
|
{
|
|
|
|
if (0 == InterlockedCompareExchange((PLONG)Pte, (LONG)Entry, 0))
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (i <= Page % 1024)
|
|
|
|
{
|
|
|
|
KEBUGCHECK(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2005-07-05 00:57:47 +00:00
|
|
|
Address = (PVOID)((ULONG_PTR)HYPERSPACE + i * PAGE_SIZE);
|
2006-10-25 18:23:45 +00:00
|
|
|
__invlpg(Address);
|
2005-01-25 22:50:47 +00:00
|
|
|
return Address;
|
|
|
|
}
|
|
|
|
|
2005-05-09 01:38:29 +00:00
|
|
|
PFN_TYPE
|
2005-09-14 01:05:50 +00:00
|
|
|
NTAPI
|
2005-01-25 22:50:47 +00:00
|
|
|
MmChangeHyperspaceMapping(PVOID Address, PFN_TYPE NewPage)
|
|
|
|
{
|
|
|
|
PFN_TYPE Pfn;
|
|
|
|
ASSERT (IS_HYPERSPACE(Address));
|
|
|
|
if (Ke386Pae)
|
|
|
|
{
|
|
|
|
ULONGLONG Entry = PAE_PFN_TO_PTE(NewPage) | PA_PRESENT | PA_READWRITE;
|
|
|
|
Entry = (ULONG)ExfpInterlockedExchange64UL(PAE_ADDR_TO_PTE(Address), &Entry);
|
|
|
|
Pfn = PAE_PTE_TO_PFN(Entry);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ULONG Entry;
|
2005-05-01 19:30:06 +00:00
|
|
|
Entry = InterlockedExchange((PLONG)ADDR_TO_PTE(Address), PFN_TO_PTE(NewPage) | PA_PRESENT | PA_READWRITE);
|
2005-01-25 22:50:47 +00:00
|
|
|
Pfn = PTE_TO_PFN(Entry);
|
|
|
|
}
|
2006-10-25 18:23:45 +00:00
|
|
|
__invlpg(Address);
|
2005-01-25 22:50:47 +00:00
|
|
|
return Pfn;
|
|
|
|
}
|
|
|
|
|
|
|
|
PFN_TYPE
|
2005-09-14 01:05:50 +00:00
|
|
|
NTAPI
|
2005-01-25 22:50:47 +00:00
|
|
|
MmDeleteHyperspaceMapping(PVOID Address)
|
|
|
|
{
|
|
|
|
PFN_TYPE Pfn;
|
|
|
|
ASSERT (IS_HYPERSPACE(Address));
|
|
|
|
if (Ke386Pae)
|
|
|
|
{
|
|
|
|
ULONGLONG Entry = 0LL;
|
|
|
|
Entry = (ULONG)ExfpInterlockedExchange64UL(PAE_ADDR_TO_PTE(Address), &Entry);
|
|
|
|
Pfn = PAE_PTE_TO_PFN(Entry);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ULONG Entry;
|
2005-05-01 19:30:06 +00:00
|
|
|
Entry = InterlockedExchange((PLONG)ADDR_TO_PTE(Address), 0);
|
2005-01-25 22:50:47 +00:00
|
|
|
Pfn = PTE_TO_PFN(Entry);
|
|
|
|
}
|
2006-10-25 18:23:45 +00:00
|
|
|
__invlpg(Address);
|
2005-01-25 22:50:47 +00:00
|
|
|
return Pfn;
|
|
|
|
}
|
|
|
|
|
2005-09-14 01:05:50 +00:00
|
|
|
VOID
|
|
|
|
NTAPI
|
2006-05-18 20:32:17 +00:00
|
|
|
MmUpdatePageDir(PEPROCESS Process, PVOID Address, ULONG Size)
|
2003-05-07 21:41:03 +00:00
|
|
|
{
|
2005-05-09 01:38:29 +00:00
|
|
|
ULONG StartOffset, EndOffset, Offset;
|
2003-05-07 21:41:03 +00:00
|
|
|
|
2005-07-06 08:20:26 +00:00
|
|
|
if (Address < MmSystemRangeStart)
|
2004-08-19 21:47:51 +00:00
|
|
|
{
|
|
|
|
KEBUGCHECK(0);
|
|
|
|
}
|
2004-09-26 16:32:18 +00:00
|
|
|
if (Ke386Pae)
|
2004-08-19 21:47:51 +00:00
|
|
|
{
|
2004-09-09 20:42:33 +00:00
|
|
|
PULONGLONG PageDirTable;
|
|
|
|
PULONGLONG Pde;
|
|
|
|
ULONGLONG ZeroPde = 0LL;
|
2004-10-05 18:53:28 +00:00
|
|
|
ULONG i;
|
2004-09-09 20:42:33 +00:00
|
|
|
|
2005-07-05 00:57:47 +00:00
|
|
|
for (i = PAE_ADDR_TO_PDTE_OFFSET(Address); i <= PAE_ADDR_TO_PDTE_OFFSET((PVOID)((ULONG_PTR)Address + Size)); i++)
|
2004-09-09 20:42:33 +00:00
|
|
|
{
|
2004-10-05 18:53:28 +00:00
|
|
|
if (i == PAE_ADDR_TO_PDTE_OFFSET(Address))
|
|
|
|
{
|
|
|
|
StartOffset = PAE_ADDR_TO_PDE_PAGE_OFFSET(Address);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
StartOffset = 0;
|
|
|
|
}
|
2005-07-05 00:57:47 +00:00
|
|
|
if (i == PAE_ADDR_TO_PDTE_OFFSET((PVOID)((ULONG_PTR)Address + Size)))
|
2004-10-05 18:53:28 +00:00
|
|
|
{
|
2005-07-05 00:57:47 +00:00
|
|
|
EndOffset = PAE_ADDR_TO_PDE_PAGE_OFFSET((PVOID)((ULONG_PTR)Address + Size));
|
2004-10-05 18:53:28 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
EndOffset = 511;
|
|
|
|
}
|
2004-09-09 20:42:33 +00:00
|
|
|
|
2006-05-18 20:32:17 +00:00
|
|
|
if (Process != NULL && Process != PsGetCurrentProcess())
|
2004-09-09 20:42:33 +00:00
|
|
|
{
|
2005-01-25 22:50:47 +00:00
|
|
|
PageDirTable = MmCreateHyperspaceMapping(PAE_PTE_TO_PFN(Process->Pcb.DirectoryTableBase.QuadPart));
|
|
|
|
Pde = (PULONGLONG)MmCreateHyperspaceMapping(PTE_TO_PFN(PageDirTable[i]));
|
|
|
|
MmDeleteHyperspaceMapping(PageDirTable);
|
2004-10-05 18:53:28 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Pde = (PULONGLONG)PAE_PAGEDIRECTORY_MAP + i*512;
|
|
|
|
}
|
|
|
|
|
2005-05-09 01:38:29 +00:00
|
|
|
for (Offset = StartOffset; Offset <= EndOffset; Offset++)
|
2004-10-05 18:53:28 +00:00
|
|
|
{
|
|
|
|
if (i * 512 + Offset < PAE_ADDR_TO_PDE_OFFSET(PAGETABLE_MAP) || i * 512 + Offset >= PAE_ADDR_TO_PDE_OFFSET(PAGETABLE_MAP)+4)
|
|
|
|
{
|
2006-03-04 17:27:40 +00:00
|
|
|
(void)ExfInterlockedCompareExchange64UL(&Pde[Offset], &MmGlobalKernelPageDirectoryForPAE[i*512 + Offset], &ZeroPde);
|
2004-10-05 18:53:28 +00:00
|
|
|
}
|
2004-09-09 20:42:33 +00:00
|
|
|
}
|
2004-10-05 18:53:28 +00:00
|
|
|
MmUnmapPageTable((PULONG)Pde);
|
2004-09-09 20:42:33 +00:00
|
|
|
}
|
2004-08-19 21:47:51 +00:00
|
|
|
}
|
|
|
|
else
|
2004-04-10 22:36:07 +00:00
|
|
|
{
|
2004-09-09 20:42:33 +00:00
|
|
|
PULONG Pde;
|
|
|
|
StartOffset = ADDR_TO_PDE_OFFSET(Address);
|
2005-07-05 00:57:47 +00:00
|
|
|
EndOffset = ADDR_TO_PDE_OFFSET((PVOID)((ULONG_PTR)Address + Size));
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2006-05-18 20:32:17 +00:00
|
|
|
if (Process != NULL && Process != PsGetCurrentProcess())
|
2004-09-09 20:42:33 +00:00
|
|
|
{
|
2005-01-25 22:50:47 +00:00
|
|
|
Pde = MmCreateHyperspaceMapping(PTE_TO_PFN(Process->Pcb.DirectoryTableBase.u.LowPart));
|
2004-09-09 20:42:33 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Pde = (PULONG)PAGEDIRECTORY_MAP;
|
|
|
|
}
|
2005-05-09 01:38:29 +00:00
|
|
|
for (Offset = StartOffset; Offset <= EndOffset; Offset++)
|
2004-09-09 20:42:33 +00:00
|
|
|
{
|
|
|
|
if (Offset != ADDR_TO_PDE_OFFSET(PAGETABLE_MAP))
|
|
|
|
{
|
2006-03-04 17:27:40 +00:00
|
|
|
(void)InterlockedCompareExchangeUL(&Pde[Offset], MmGlobalKernelPageDirectory[Offset], 0);
|
2004-09-09 20:42:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (Pde != (PULONG)PAGEDIRECTORY_MAP)
|
|
|
|
{
|
2005-01-25 22:50:47 +00:00
|
|
|
MmDeleteHyperspaceMapping(Pde);
|
2004-09-09 20:42:33 +00:00
|
|
|
}
|
2004-04-10 22:36:07 +00:00
|
|
|
}
|
2004-09-09 20:42:33 +00:00
|
|
|
}
|
2005-01-25 22:50:47 +00:00
|
|
|
|
2005-09-14 01:05:50 +00:00
|
|
|
VOID
|
|
|
|
INIT_FUNCTION
|
|
|
|
NTAPI
|
2004-09-09 20:42:33 +00:00
|
|
|
MmInitGlobalKernelPageDirectory(VOID)
|
|
|
|
{
|
|
|
|
ULONG i;
|
2005-01-25 22:50:47 +00:00
|
|
|
|
|
|
|
DPRINT("MmInitGlobalKernelPageDirectory()\n");
|
|
|
|
|
2004-09-26 16:32:18 +00:00
|
|
|
if (Ke386Pae)
|
2004-04-10 22:36:07 +00:00
|
|
|
{
|
2004-10-05 18:53:28 +00:00
|
|
|
PULONGLONG CurrentPageDirectory = (PULONGLONG)PAE_PAGEDIRECTORY_MAP;
|
2005-07-06 08:20:26 +00:00
|
|
|
for (i = PAE_ADDR_TO_PDE_OFFSET(MmSystemRangeStart); i < 4 * 512; i++)
|
2004-08-19 21:47:51 +00:00
|
|
|
{
|
2005-01-25 22:50:47 +00:00
|
|
|
if (!(i >= PAE_ADDR_TO_PDE_OFFSET(PAGETABLE_MAP) && i < PAE_ADDR_TO_PDE_OFFSET(PAGETABLE_MAP) + 4) &&
|
|
|
|
!(i >= PAE_ADDR_TO_PDE_OFFSET(HYPERSPACE) && i < PAE_ADDR_TO_PDE_OFFSET(HYPERSPACE) + 2) &&
|
|
|
|
0LL == MmGlobalKernelPageDirectoryForPAE[i] && 0LL != CurrentPageDirectory[i])
|
2004-09-09 20:42:33 +00:00
|
|
|
{
|
2006-03-04 17:27:40 +00:00
|
|
|
(void)ExfpInterlockedExchange64UL(&MmGlobalKernelPageDirectoryForPAE[i], &CurrentPageDirectory[i]);
|
2004-11-13 23:08:35 +00:00
|
|
|
if (Ke386GlobalPagesEnabled)
|
2004-09-09 20:42:33 +00:00
|
|
|
{
|
|
|
|
MmGlobalKernelPageDirectoryForPAE[i] |= PA_GLOBAL;
|
2005-01-05 19:27:58 +00:00
|
|
|
CurrentPageDirectory[i] |= PA_GLOBAL;
|
2004-09-09 20:42:33 +00:00
|
|
|
}
|
|
|
|
}
|
2004-08-19 21:47:51 +00:00
|
|
|
}
|
|
|
|
}
|
2004-09-09 20:42:33 +00:00
|
|
|
else
|
2004-08-19 21:47:51 +00:00
|
|
|
{
|
2004-09-09 20:42:33 +00:00
|
|
|
PULONG CurrentPageDirectory = (PULONG)PAGEDIRECTORY_MAP;
|
2005-07-06 08:20:26 +00:00
|
|
|
for (i = ADDR_TO_PDE_OFFSET(MmSystemRangeStart); i < 1024; i++)
|
2004-09-09 20:42:33 +00:00
|
|
|
{
|
|
|
|
if (i != ADDR_TO_PDE_OFFSET(PAGETABLE_MAP) &&
|
2005-01-25 22:50:47 +00:00
|
|
|
i != ADDR_TO_PDE_OFFSET(HYPERSPACE) &&
|
2004-09-09 20:42:33 +00:00
|
|
|
0 == MmGlobalKernelPageDirectory[i] && 0 != CurrentPageDirectory[i])
|
|
|
|
{
|
|
|
|
MmGlobalKernelPageDirectory[i] = CurrentPageDirectory[i];
|
2004-11-13 23:08:35 +00:00
|
|
|
if (Ke386GlobalPagesEnabled)
|
2004-09-09 20:42:33 +00:00
|
|
|
{
|
|
|
|
MmGlobalKernelPageDirectory[i] |= PA_GLOBAL;
|
2005-01-05 19:27:58 +00:00
|
|
|
CurrentPageDirectory[i] |= PA_GLOBAL;
|
2004-09-09 20:42:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2004-04-10 22:36:07 +00:00
|
|
|
}
|
2003-05-07 21:41:03 +00:00
|
|
|
}
|
2004-09-09 20:42:33 +00:00
|
|
|
|
|
|
|
ULONG
|
2005-09-14 01:05:50 +00:00
|
|
|
NTAPI
|
2004-09-09 20:42:33 +00:00
|
|
|
MiGetUserPageDirectoryCount(VOID)
|
|
|
|
{
|
2005-07-06 08:20:26 +00:00
|
|
|
return Ke386Pae ? PAE_ADDR_TO_PDE_OFFSET(MmSystemRangeStart) : ADDR_TO_PDE_OFFSET(MmSystemRangeStart);
|
2004-09-09 20:42:33 +00:00
|
|
|
}
|
|
|
|
|
2005-09-14 01:05:50 +00:00
|
|
|
VOID
|
|
|
|
INIT_FUNCTION
|
|
|
|
NTAPI
|
2004-09-09 20:42:33 +00:00
|
|
|
MiInitPageDirectoryMap(VOID)
|
|
|
|
{
|
|
|
|
MEMORY_AREA* kernel_map_desc = NULL;
|
2005-01-25 22:50:47 +00:00
|
|
|
MEMORY_AREA* hyperspace_desc = NULL;
|
2004-09-09 20:42:33 +00:00
|
|
|
PHYSICAL_ADDRESS BoundaryAddressMultiple;
|
|
|
|
PVOID BaseAddress;
|
2005-07-16 09:01:07 +00:00
|
|
|
NTSTATUS Status;
|
2004-09-09 20:42:33 +00:00
|
|
|
|
2005-01-25 22:50:47 +00:00
|
|
|
DPRINT("MiInitPageDirectoryMap()\n");
|
|
|
|
|
2004-09-09 20:42:33 +00:00
|
|
|
BoundaryAddressMultiple.QuadPart = 0;
|
2004-09-26 16:32:18 +00:00
|
|
|
BaseAddress = (PVOID)PAGETABLE_MAP;
|
2005-11-13 17:28:24 +00:00
|
|
|
Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
|
2005-07-16 09:01:07 +00:00
|
|
|
MEMORY_AREA_SYSTEM,
|
|
|
|
&BaseAddress,
|
|
|
|
Ke386Pae ? 0x800000 : 0x400000,
|
2005-11-13 17:28:24 +00:00
|
|
|
PAGE_READWRITE,
|
2005-07-16 09:01:07 +00:00
|
|
|
&kernel_map_desc,
|
|
|
|
TRUE,
|
2005-11-13 17:28:24 +00:00
|
|
|
0,
|
2005-07-16 09:01:07 +00:00
|
|
|
BoundaryAddressMultiple);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
KEBUGCHECK(0);
|
|
|
|
}
|
2005-01-25 22:50:47 +00:00
|
|
|
BaseAddress = (PVOID)HYPERSPACE;
|
2005-11-13 17:28:24 +00:00
|
|
|
Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
|
2005-07-16 09:01:07 +00:00
|
|
|
MEMORY_AREA_SYSTEM,
|
|
|
|
&BaseAddress,
|
|
|
|
0x400000,
|
2005-11-13 17:28:24 +00:00
|
|
|
PAGE_READWRITE,
|
2005-07-16 09:01:07 +00:00
|
|
|
&hyperspace_desc,
|
|
|
|
TRUE,
|
2005-11-13 17:28:24 +00:00
|
|
|
0,
|
2005-07-16 09:01:07 +00:00
|
|
|
BoundaryAddressMultiple);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
KEBUGCHECK(0);
|
|
|
|
}
|
2003-05-17 13:45:04 +00:00
|
|
|
}
|
|
|
|
|
2000-04-02 13:32:43 +00:00
|
|
|
/* EOF */
|