ReactOS 0.4.15-dev-7958-gcd0bb1a
page.c File Reference
#include <ntoskrnl.h>
#include <debug.h>
#include <mm/ARM3/miarm.h>
Include dependency graph for page.c:

Go to the source code of this file.

Macros

#define NDEBUG
 

Functions

NTSTATUS NTAPI MiFillSystemPageDirectory (IN PVOID Base, IN SIZE_T NumberOfBytes)
 
static BOOLEAN MiIsPageTablePresent (PVOID Address)
 
PFN_NUMBER NTAPI MmGetPfnForProcess (PEPROCESS Process, PVOID Address)
 
 _Success_ (return)
 Deletes the virtual mapping and optionally gives back the page & dirty bit.
 
VOID NTAPI MmDeletePageFileMapping (PEPROCESS Process, PVOID Address, SWAPENTRY *SwapEntry)
 
BOOLEAN NTAPI MmIsPagePresent (PEPROCESS Process, PVOID Address)
 
BOOLEAN NTAPI MmIsDisabledPage (PEPROCESS Process, PVOID Address)
 
BOOLEAN NTAPI MmIsPageSwapEntry (PEPROCESS Process, PVOID Address)
 
VOID NTAPI MmGetPageFileMapping (PEPROCESS Process, PVOID Address, SWAPENTRY *SwapEntry)
 
NTSTATUS NTAPI MmCreatePageFileMapping (PEPROCESS Process, PVOID Address, SWAPENTRY SwapEntry)
 
NTSTATUS NTAPI MmCreateVirtualMappingUnsafeEx (_Inout_opt_ PEPROCESS Process, _In_ PVOID Address, _In_ ULONG flProtect, _In_ PFN_NUMBER Page, _In_ BOOLEAN IsPhysical)
 
NTSTATUS NTAPI MmCreateVirtualMappingUnsafe (_Inout_opt_ PEPROCESS Process, _In_ PVOID Address, _In_ ULONG flProtect, _In_ PFN_NUMBER Page)
 
NTSTATUS NTAPI MmCreatePhysicalMapping (_Inout_opt_ PEPROCESS Process, _In_ PVOID Address, _In_ ULONG flProtect, _In_ PFN_NUMBER Page)
 
NTSTATUS NTAPI MmCreateVirtualMapping (PEPROCESS Process, PVOID Address, ULONG flProtect, PFN_NUMBER Page)
 
ULONG NTAPI MmGetPageProtect (PEPROCESS Process, PVOID Address)
 
VOID NTAPI MmSetPageProtect (PEPROCESS Process, PVOID Address, ULONG flProtect)
 
VOID NTAPI MmSetDirtyBit (PEPROCESS Process, PVOID Address, BOOLEAN Bit)
 
VOID NTAPI MmInitGlobalKernelPageDirectory (VOID)
 

Variables

const ULONG_PTR MmProtectToPteMask [32]
 
const ULONG MmProtectToValue [32]
 

Macro Definition Documentation

◆ NDEBUG

#define NDEBUG

Definition at line 13 of file page.c.

Function Documentation

◆ _Success_()

_Success_ ( return  )

Deletes the virtual mapping and optionally gives back the page & dirty bit.

Parameters
Process- The process this address belongs to, or NULL if system address.
Address- The address to unmap.
WasDirty- Optional param receiving the dirty bit of the PTE.
Page- Optional param receiving the page number previously mapped to this address.
Returns
Whether there was actually a page mapped at the given address.

Definition at line 235 of file page.c.

243{
244 PMMPTE PointerPte;
245 MMPTE OldPte;
246 BOOLEAN ValidPde;
247
248 OldPte.u.Long = 0;
249
250 DPRINT("MmDeleteVirtualMapping(%p, %p, %p, %p)\n", Process, Address, WasDirty, Page);
251
253
254 /* And we should be at low IRQL */
256
257 /* Make sure our PDE is valid, and that everything is going fine */
258 if (Process == NULL)
259 {
261 {
262 DPRINT1("NULL process given for user-mode mapping at %p\n", Address);
263 KeBugCheck(MEMORY_MANAGEMENT);
264 }
265#if (_MI_PAGING_LEVELS == 2)
266 ValidPde = MiSynchronizeSystemPde(MiAddressToPde(Address));
267#else
269#endif
270 }
271 else
272 {
274 {
275 DPRINT1("Process %p given for kernel-mode mapping at %p\n", Process, Address);
276 KeBugCheck(MEMORY_MANAGEMENT);
277 }
278
279 /* Only for current process !!! */
282
283 ValidPde = MiIsPageTablePresent(Address);
284 if (ValidPde)
285 {
287 }
288 }
289
290 /* Get the PTE if we're having anything */
291 if (ValidPde)
292 {
293 PointerPte = MiAddressToPte(Address);
294 OldPte.u.Long = InterlockedExchangePte(PointerPte, 0);
295
297
298 if (OldPte.u.Long != 0)
299 {
300 /* It must have been present, or not a swap entry */
301 ASSERT(OldPte.u.Hard.Valid || !FlagOn(OldPte.u.Long, 0x800));
302 if (WasDirty != NULL)
303 {
304 *WasDirty = !!OldPte.u.Hard.Dirty;
305 }
306 if (Page != NULL)
307 {
308 *Page = OldPte.u.Hard.PageFrameNumber;
309 }
310 }
311 }
312
313 if (Process != NULL)
314 {
315 /* Remove PDE reference, if needed */
316 if (OldPte.u.Long != 0)
317 {
319 {
320 KIRQL OldIrql = MiAcquirePfnLock();
322 MiReleasePfnLock(OldIrql);
323 }
324 }
325
326 if (!IsPhysical && OldPte.u.Hard.Valid)
327 {
328 PMMPFN Pfn1;
330
331 OldIrql = MiAcquirePfnLock();
332 Pfn1 = &MmPfnDatabase[OldPte.u.Hard.PageFrameNumber];
334 ASSERT(Pfn1->u2.ShareCount > 0);
335 if (--Pfn1->u2.ShareCount == 0)
336 {
338 }
339 MiReleasePfnLock(OldIrql);
340 }
341
343 }
344
345 return OldPte.u.Long != 0;
346}
unsigned char BOOLEAN
#define DPRINT1
Definition: precomp.h:8
DECLSPEC_NORETURN VOID NTAPI KeBugCheck(ULONG BugCheckCode)
Definition: bug.c:1430
#define NULL
Definition: types.h:112
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
#define PAGE_SIZE
Definition: env_spec_w32.h:49
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
#define FlagOn(_F, _SF)
Definition: ext2fs.h:179
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:223
#define Add2Ptr(PTR, INC)
FORCEINLINE VOID MiDeletePde(_In_ PMMPDE PointerPde, _In_ PEPROCESS CurrentProcess)
Definition: miarm.h:2541
FORCEINLINE USHORT MiDecrementPageTableReferences(IN PVOID Address)
Definition: miarm.h:2507
FORCEINLINE VOID MiUnlockProcessWorkingSetUnsafe(IN PEPROCESS Process, IN PETHREAD Thread)
Definition: miarm.h:1239
VOID NTAPI MiMakePdeExistAndMakeValid(IN PMMPDE PointerPde, IN PEPROCESS TargetProcess, IN KIRQL OldIrql)
Definition: virtual.c:2481
FORCEINLINE VOID MiLockProcessWorkingSetUnsafe(IN PEPROCESS Process, IN PETHREAD Thread)
Definition: miarm.h:1169
#define MiAddressToPte(x)
Definition: mmx86.c:19
#define MiAddressToPde(x)
Definition: mmx86.c:20
#define ASSERT(a)
Definition: mode.c:44
@ ActiveAndValid
Definition: mmtypes.h:159
@ TransitionPage
Definition: mmtypes.h:160
FORCEINLINE VOID KeInvalidateTlbEntry(IN PVOID Address)
Definition: ke.h:264
FORCEINLINE BOOLEAN MiIsPdeForAddressValid(PVOID Address)
Definition: mm.h:366
#define MmSystemRangeStart
Definition: mm.h:32
#define MM_NOIRQL
Definition: mm.h:70
_In_ PVOID _Out_opt_ BOOLEAN * WasDirty
Definition: mm.h:1304
PMMPFN MmPfnDatabase
Definition: freelist.c:24
_In_ PVOID _Out_opt_ BOOLEAN _Out_opt_ PPFN_NUMBER Page
Definition: mm.h:1306
#define InterlockedExchangePte(PointerPte, Value)
Definition: mm.h:190
static BOOLEAN MiIsPageTablePresent(PVOID Address)
Definition: page.c:119
static WCHAR Address[46]
Definition: ping.c:68
#define DPRINT
Definition: sndvol32.h:71
USHORT PageLocation
Definition: mm.h:365
Definition: mm.h:374
union _MMPFN::@1794 u2
union _MMPFN::@1795 u3
MMPFNENTRY e1
Definition: mm.h:397
ULONG_PTR ShareCount
Definition: mm.h:390
ULONG64 Dirty
Definition: mmtypes.h:164
ULONG64 Valid
Definition: mmtypes.h:150
ULONG64 PageFrameNumber
Definition: mmtypes.h:171
union _MMPTE::@2330 u
MMPTE_HARDWARE Hard
Definition: mmtypes.h:217
ULONG_PTR Long
Definition: mmtypes.h:215
uint32_t ULONG_PTR
Definition: typedefs.h:65
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:778
#define PsGetCurrentProcess
Definition: psfuncs.h:17

◆ MiFillSystemPageDirectory()

NTSTATUS NTAPI MiFillSystemPageDirectory ( IN PVOID  Base,
IN SIZE_T  NumberOfBytes 
)

Definition at line 462 of file section.c.

464{
465 PMMPDE PointerPde, LastPde, SystemMapPde;
467 PFN_NUMBER PageFrameIndex, ParentPage;
469 PAGED_CODE();
470
471 /* Find the PDEs needed for this mapping */
472 PointerPde = MiAddressToPde(Base);
473 LastPde = MiAddressToPde((PVOID)((ULONG_PTR)Base + NumberOfBytes - 1));
474
475#if (_MI_PAGING_LEVELS == 2)
476 /* Find the system double-mapped PDE that describes this mapping */
477 SystemMapPde = &MmSystemPagePtes[((ULONG_PTR)PointerPde & (SYSTEM_PD_SIZE - 1)) / sizeof(MMPTE)];
478#else
479 /* We don't have a double mapping */
480 SystemMapPde = PointerPde;
481#endif
482
483 /* Use the PDE template and loop the PDEs */
485 while (PointerPde <= LastPde)
486 {
487 /* Lock the PFN database */
488 OldIrql = MiAcquirePfnLock();
489
490 /* Check if we don't already have this PDE mapped */
491 if (SystemMapPde->u.Hard.Valid == 0)
492 {
493 /* Grab a page for it */
495 MI_SET_PROCESS2(PsGetCurrentProcess()->ImageFileName);
496 PageFrameIndex = MiRemoveZeroPage(MI_GET_NEXT_COLOR());
497 ASSERT(PageFrameIndex);
498 TempPde.u.Hard.PageFrameNumber = PageFrameIndex;
499
500#if (_MI_PAGING_LEVELS == 2)
501 ParentPage = MmSystemPageDirectory[(PointerPde - MiAddressToPde(NULL)) / PDE_PER_PAGE];
502#else
503 ParentPage = MiPdeToPpe(PointerPde)->u.Hard.PageFrameNumber;
504#endif
505 /* Initialize its PFN entry, with the parent system page directory page table */
506 MiInitializePfnForOtherProcess(PageFrameIndex,
507 (PMMPTE)PointerPde,
508 ParentPage);
509
510 /* Make the system PDE entry valid */
511 MI_WRITE_VALID_PDE(SystemMapPde, TempPde);
512
513 /* The system PDE entry might be the PDE itself, so check for this */
514 if (PointerPde->u.Hard.Valid == 0)
515 {
516 /* It's different, so make the real PDE valid too */
517 MI_WRITE_VALID_PDE(PointerPde, TempPde);
518 }
519 }
520
521 /* Release the lock and keep going with the next PDE */
522 MiReleasePfnLock(OldIrql);
523 SystemMapPde++;
524 PointerPde++;
525 }
526}
#define PAGED_CODE()
HARDWARE_PDE_ARMV6 TempPde
Definition: winldr.c:78
#define ULONG_PTR
Definition: config.h:101
PFN_NUMBER NTAPI MiRemoveZeroPage(IN ULONG Color)
Definition: pfnlist.c:537
#define MI_GET_NEXT_COLOR()
Definition: miarm.h:232
VOID NTAPI MiInitializePfnForOtherProcess(IN PFN_NUMBER PageFrameIndex, IN PVOID PteAddress, IN PFN_NUMBER PteFrame)
Definition: pfnlist.c:1301
FORCEINLINE VOID MI_WRITE_VALID_PDE(IN PMMPDE PointerPde, IN MMPDE TempPde)
Definition: miarm.h:1018
#define SYSTEM_PD_SIZE
Definition: miarm.h:32
_In_opt_ ULONG Base
Definition: rtlfuncs.h:2439
FORCEINLINE PMMPDE MiPdeToPpe(PMMPDE PointerPde)
Definition: mm.h:292
#define PDE_PER_PAGE
Definition: mm.h:21
#define MI_SET_PROCESS2(x)
Definition: mm.h:319
@ MI_USAGE_PAGE_TABLE
Definition: mm.h:334
#define MI_SET_USAGE(x)
Definition: mm.h:317
PMMPDE MmSystemPagePtes
Definition: init.c:41
PFN_NUMBER MmSystemPageDirectory[PPE_PER_PAGE]
Definition: init.c:40
MMPTE ValidKernelPde
Definition: init.c:28
ULONG PFN_NUMBER
Definition: ke.h:9
ULONG PageFrameNumber
Definition: mmtypes.h:74
_Must_inspect_result_ typedef _In_ PHYSICAL_ADDRESS _Inout_ PLARGE_INTEGER NumberOfBytes
Definition: iotypes.h:1036

Referenced by MiMapViewInSystemSpace(), and MmCreateVirtualMappingUnsafeEx().

◆ MiIsPageTablePresent()

static BOOLEAN MiIsPageTablePresent ( PVOID  Address)
static

Definition at line 119 of file page.c.

120{
121#if _MI_PAGING_LEVELS == 2
123
124 /* Some sanity check while we're here */
125 ASSERT(Ret == (MiAddressToPde(Address)->u.Hard.Valid != 0));
126
127 return Ret;
128#else
129 PMMPDE PointerPde;
130 PMMPPE PointerPpe;
131#if _MI_PAGING_LEVELS == 4
132 PMMPXE PointerPxe;
133#endif
134 PMMPFN Pfn;
135
136 /* Make sure we're locked */
137 ASSERT((PsGetCurrentThread()->OwnsProcessWorkingSetExclusive) || (PsGetCurrentThread()->OwnsProcessWorkingSetShared));
138
139 /* Must not hold the PFN lock! */
141
142 /* Check if PXE or PPE have references first. */
143#if _MI_PAGING_LEVELS == 4
144 PointerPxe = MiAddressToPxe(Address);
145 if ((PointerPxe->u.Hard.Valid == 1) || (PointerPxe->u.Soft.Transition == 1))
146 {
147 Pfn = MiGetPfnEntry(PFN_FROM_PXE(PointerPxe));
149 return FALSE;
150 }
151 else if (PointerPxe->u.Soft.UsedPageTableEntries == 0)
152 {
153 return FALSE;
154 }
155
156 if (PointerPxe->u.Hard.Valid == 0)
157 {
159 }
160#endif
161
162 PointerPpe = MiAddressToPpe(Address);
163 if ((PointerPpe->u.Hard.Valid == 1) || (PointerPpe->u.Soft.Transition == 1))
164 {
165 Pfn = MiGetPfnEntry(PFN_FROM_PPE(PointerPpe));
167 return FALSE;
168 }
169 else if (PointerPpe->u.Soft.UsedPageTableEntries == 0)
170 {
171 return FALSE;
172 }
173
174 if (PointerPpe->u.Hard.Valid == 0)
175 {
177 }
178
179 PointerPde = MiAddressToPde(Address);
180 if ((PointerPde->u.Hard.Valid == 0) && (PointerPde->u.Soft.Transition == 0))
181 {
182 return PointerPde->u.Soft.UsedPageTableEntries != 0;
183 }
184
185 /* This lies on the PFN */
186 Pfn = MiGetPfnEntry(PFN_FROM_PDE(PointerPde));
187 return Pfn->OriginalPte.u.Soft.UsedPageTableEntries != 0;
188#endif
189}
#define FALSE
Definition: types.h:117
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble * u
Definition: glfuncs.h:240
ULONG NTAPI MiMakeSystemAddressValid(IN PVOID PageTableVirtualAddress, IN PEPROCESS CurrentProcess)
Definition: virtual.c:183
PMMWSL MmWorkingSetList
Definition: wslist.cpp:19
#define PFN_FROM_PXE(v)
Definition: mm.h:95
#define MiGetPdeOffset(x)
Definition: mm.h:195
#define PFN_FROM_PPE(v)
Definition: mm.h:94
FORCEINLINE PMMPTE MiAddressToPpe(PVOID Address)
Definition: mm.h:161
FORCEINLINE PMMPTE MiAddressToPxe(PVOID Address)
Definition: mm.h:171
#define PFN_FROM_PDE(v)
Definition: mm.h:93
#define MiPteToAddress(_Pte)
Definition: mm.h:116
FORCEINLINE PMMPFN MiGetPfnEntry(IN PFN_NUMBER Pfn)
Definition: mm.h:1047
MMPTE OriginalPte
Definition: mm.h:407
ULONG64 UsedPageTableEntries
Definition: mmtypes.h:91
ULONG64 Transition
Definition: mmtypes.h:90
MMPTE_SOFTWARE Soft
Definition: mmtypes.h:219
USHORT UsedPageTableEntries[768]
Definition: mmtypes.h:886

Referenced by _Success_(), MmGetPageFileMapping(), MmGetPageProtect(), MmGetPfnForProcess(), MmIsDisabledPage(), MmIsPagePresent(), and MmIsPageSwapEntry().

◆ MmCreatePageFileMapping()

NTSTATUS NTAPI MmCreatePageFileMapping ( PEPROCESS  Process,
PVOID  Address,
SWAPENTRY  SwapEntry 
)

Definition at line 587 of file page.c.

590{
591 PMMPTE PointerPte;
592 ULONG_PTR Pte;
593
594 /* This should not be called for kernel space anymore */
595 ASSERT(Process != NULL);
597
598 /* And we don't support creating for other process */
600
601 if (SwapEntry & ((ULONG_PTR)1 << (RTL_BITS_OF(SWAPENTRY) - 1)))
602 {
603 KeBugCheck(MEMORY_MANAGEMENT);
604 }
605
606 /* We are tinkering with the PDE here. Ensure it will be there */
609
611
612 PointerPte = MiAddressToPte(Address);
613 Pte = InterlockedExchangePte(PointerPte, SwapEntry << 1);
614 if (Pte != 0)
615 {
616 KeBugCheckEx(MEMORY_MANAGEMENT, SwapEntry, (ULONG_PTR)Process, (ULONG_PTR)Address, 0);
617 }
618
619 /* This used to be a 0 PTE, now we need a valid PDE to keep it around */
622
623 return STATUS_SUCCESS;
624}
FORCEINLINE USHORT MiIncrementPageTableReferences(IN PVOID Address)
Definition: miarm.h:2481
#define RTL_BITS_OF(sizeOfArg)
Definition: ntbasedef.h:668
ULONG_PTR SWAPENTRY
Definition: mm.h:57
VOID NTAPI KeBugCheckEx(_In_ ULONG BugCheckCode, _In_ ULONG_PTR BugCheckParameter1, _In_ ULONG_PTR BugCheckParameter2, _In_ ULONG_PTR BugCheckParameter3, _In_ ULONG_PTR BugCheckParameter4)
Definition: rtlcompat.c:108
#define STATUS_SUCCESS
Definition: shellext.h:65

◆ MmCreatePhysicalMapping()

NTSTATUS NTAPI MmCreatePhysicalMapping ( _Inout_opt_ PEPROCESS  Process,
_In_ PVOID  Address,
_In_ ULONG  flProtect,
_In_ PFN_NUMBER  Page 
)

Definition at line 735 of file page.c.

740{
742}
#define TRUE
Definition: types.h:120
NTSTATUS NTAPI MmCreateVirtualMappingUnsafeEx(_Inout_opt_ PEPROCESS Process, _In_ PVOID Address, _In_ ULONG flProtect, _In_ PFN_NUMBER Page, _In_ BOOLEAN IsPhysical)
Definition: page.c:629

Referenced by MmNotPresentFaultSectionView().

◆ MmCreateVirtualMapping()

NTSTATUS NTAPI MmCreateVirtualMapping ( PEPROCESS  Process,
PVOID  Address,
ULONG  flProtect,
PFN_NUMBER  Page 
)

Definition at line 746 of file page.c.

750{
752 if (!MmIsPageInUse(Page))
753 {
754 DPRINT1("Page %lx is not in use\n", Page);
755 KeBugCheck(MEMORY_MANAGEMENT);
756 }
757
759}
BOOLEAN NTAPI MmIsPageInUse(PFN_NUMBER Page)
Definition: freelist.c:558
NTSTATUS NTAPI MmCreateVirtualMappingUnsafe(_Inout_opt_ PEPROCESS Process, _In_ PVOID Address, _In_ ULONG flProtect, _In_ PFN_NUMBER Page)
Definition: page.c:724

◆ MmCreateVirtualMappingUnsafe()

NTSTATUS NTAPI MmCreateVirtualMappingUnsafe ( _Inout_opt_ PEPROCESS  Process,
_In_ PVOID  Address,
_In_ ULONG  flProtect,
_In_ PFN_NUMBER  Page 
)

Definition at line 724 of file page.c.

729{
731}

◆ MmCreateVirtualMappingUnsafeEx()

NTSTATUS NTAPI MmCreateVirtualMappingUnsafeEx ( _Inout_opt_ PEPROCESS  Process,
_In_ PVOID  Address,
_In_ ULONG  flProtect,
_In_ PFN_NUMBER  Page,
_In_ BOOLEAN  IsPhysical 
)

Definition at line 629 of file page.c.

635{
636 ULONG ProtectionMask;
637 PMMPTE PointerPte;
639 ULONG_PTR Pte;
640
641 DPRINT("MmCreateVirtualMappingUnsafe(%p, %p, %lu, %x)\n",
642 Process, Address, flProtect, Page);
643
645
646 ProtectionMask = MiMakeProtectionMask(flProtect);
647 /* Caller must have checked ! */
648 ASSERT(ProtectionMask != MM_INVALID_PROTECTION);
649 ASSERT(ProtectionMask != MM_NOACCESS);
650 ASSERT(ProtectionMask != MM_ZERO_ACCESS);
651
652 /* Make sure our PDE is valid, and that everything is going fine */
653 if (Process == NULL)
654 {
655 /* We don't support this in legacy Mm for kernel mappings */
656 ASSERT(ProtectionMask != MM_WRITECOPY);
657 ASSERT(ProtectionMask != MM_EXECUTE_WRITECOPY);
658
660 {
661 DPRINT1("NULL process given for user-mode mapping at %p\n", Address);
662 KeBugCheck(MEMORY_MANAGEMENT);
663 }
664#if _MI_PAGING_LEVELS == 2
665 if (!MiSynchronizeSystemPde(MiAddressToPde(Address)))
667#endif
668 }
669 else
670 {
672 {
673 DPRINT1("Process %p given for kernel-mode mapping at %p -- 1 page starting at %Ix\n",
675 KeBugCheck(MEMORY_MANAGEMENT);
676 }
677
678 /* Only for current process !!! */
681
683 }
684
685 PointerPte = MiAddressToPte(Address);
686
687 MI_MAKE_HARDWARE_PTE(&TempPte, PointerPte, ProtectionMask, Page);
688
689 Pte = InterlockedExchangePte(PointerPte, TempPte.u.Long);
690 /* There should not have been anything valid here */
691 if (Pte != 0)
692 {
693 DPRINT1("Bad PTE %lx at %p for %p\n", Pte, PointerPte, Address);
694 KeBugCheck(MEMORY_MANAGEMENT);
695 }
696
697 if (!IsPhysical)
698 {
699 PMMPFN Pfn1;
701
702 OldIrql = MiAcquirePfnLock();
703 Pfn1 = &MmPfnDatabase[TempPte.u.Hard.PageFrameNumber];
704 Pfn1->u2.ShareCount++;
706 MiReleasePfnLock(OldIrql);
707 }
708
709 /* We don't need to flush the TLB here because it only caches valid translations
710 * and we're moving this PTE from invalid to valid so it can't be cached right now */
711
713 {
714 /* Add PDE reference */
717 }
718
719 return(STATUS_SUCCESS);
720}
HARDWARE_PTE_ARMV6 TempPte
Definition: winldr.c:76
#define MM_EXECUTE_WRITECOPY
Definition: miarm.h:50
#define MM_INVALID_PROTECTION
Definition: miarm.h:67
#define MM_NOACCESS
Definition: miarm.h:65
#define MM_ZERO_ACCESS
Definition: miarm.h:43
FORCEINLINE VOID MI_MAKE_HARDWARE_PTE(IN PMMPTE NewPte, IN PMMPTE MappingPte, IN ULONG_PTR ProtectionMask, IN PFN_NUMBER PageFrameNumber)
Definition: miarm.h:807
ULONG NTAPI MiMakeProtectionMask(IN ULONG Protect)
Definition: section.c:140
#define MM_WRITECOPY
Definition: miarm.h:48
NTSTATUS NTAPI MiFillSystemPageDirectory(IN PVOID Base, IN SIZE_T NumberOfBytes)
Definition: section.c:462
ULONG PageFrameNumber
Definition: mmtypes.h:109
uint32_t ULONG
Definition: typedefs.h:59

Referenced by MmCreatePhysicalMapping(), and MmCreateVirtualMappingUnsafe().

◆ MmDeletePageFileMapping()

VOID NTAPI MmDeletePageFileMapping ( PEPROCESS  Process,
PVOID  Address,
SWAPENTRY SwapEntry 
)

Definition at line 372 of file page.c.

376{
377 PMMPTE PointerPte;
378 MMPTE OldPte;
379
380 /* This should not be called for kernel space anymore */
381 ASSERT(Process != NULL);
383
384 /* And we don't support deleting for other process */
386
387 /* And we should be at low IRQL */
389
390 /* We are tinkering with the PDE here. Ensure it will be there */
392
393 /* Callers must ensure there is actually something there */
394 ASSERT(MiAddressToPde(Address)->u.Long != 0);
395
397
398 PointerPte = MiAddressToPte(Address);
399 OldPte.u.Long = InterlockedExchangePte(PointerPte, 0);
400 /* This must be a swap entry ! */
401 if (!FlagOn(OldPte.u.Long, 0x800) || OldPte.u.Hard.Valid)
402 {
403 KeBugCheckEx(MEMORY_MANAGEMENT, OldPte.u.Long, (ULONG_PTR)Process, (ULONG_PTR)Address, 0);
404 }
405
406 /* This used to be a non-zero PTE, now we can let the PDE go. */
408 {
409 /* We can let it go */
410 KIRQL OldIrql = MiAcquirePfnLock();
411 MiDeletePde(MiPteToPde(PointerPte), Process);
412 MiReleasePfnLock(OldIrql);
413 }
414
416
417 *SwapEntry = OldPte.u.Long >> 1;
418}
#define MiPteToPde(_Pte)
Definition: mm.h:121

◆ MmGetPageFileMapping()

VOID NTAPI MmGetPageFileMapping ( PEPROCESS  Process,
PVOID  Address,
SWAPENTRY SwapEntry 
)

Definition at line 549 of file page.c.

550{
551 PMMPTE PointerPte;
552
553 /* We never set swap entries for kernel addresses */
555 {
556 ASSERT(Process == NULL);
557 *SwapEntry = 0;
558 return;
559 }
560
561 ASSERT(Process != NULL);
563
565
567 {
568 /* There can't be a swap entry if there is no PDE */
570 *SwapEntry = 0;
571 return;
572 }
573
575
576 PointerPte = MiAddressToPte(Address);
577 if (!PointerPte->u.Hard.Valid && FlagOn(PointerPte->u.Long, 0x800))
578 *SwapEntry = PointerPte->u.Long >> 1;
579 else
580 *SwapEntry = 0;
581
583}
FORCEINLINE VOID MiLockProcessWorkingSetShared(IN PEPROCESS Process, IN PETHREAD Thread)
Definition: miarm.h:1146
FORCEINLINE VOID MiUnlockProcessWorkingSetShared(IN PEPROCESS Process, IN PETHREAD Thread)
Definition: miarm.h:1215

Referenced by MmAlterViewAttributes(), MmNotPresentFaultSectionView(), and MmPageOutCacheSection().

◆ MmGetPageProtect()

ULONG NTAPI MmGetPageProtect ( PEPROCESS  Process,
PVOID  Address 
)

Definition at line 763 of file page.c.

764{
765 PMMPTE PointerPte;
767
769 {
770 ASSERT(Process == NULL);
771
772#if _MI_PAGING_LEVELS == 2
773 if (!MiSynchronizeSystemPde(MiAddressToPde(Address)))
774#else
776#endif
777 {
778 return PAGE_NOACCESS;
779 }
780 }
781 else
782 {
784 ASSERT(Process != NULL);
785
787
789
791 {
792 /* It can't be present if there is no PDE */
794 return PAGE_NOACCESS;
795 }
796
798 }
799
800 PointerPte = MiAddressToPte(Address);
801
802 if (!PointerPte->u.Flush.Valid)
803 {
805 }
806 else
807 {
808 if (PointerPte->u.Flush.CopyOnWrite)
810 else if (PointerPte->u.Flush.Write)
812 else
814#if _MI_PAGING_LEVELS >= 3
815 /* PAE & AMD64 long mode support NoExecute bit */
816 if (!PointerPte->u.Flush.NoExecute)
817 Protect <<= 4;
818#endif
819 if (PointerPte->u.Flush.CacheDisable)
821 if (PointerPte->u.Flush.WriteThrough)
823 }
824
827
828 return(Protect);
829}
#define PAGE_READONLY
Definition: compat.h:138
#define PAGE_WRITECOPY
Definition: nt_native.h:1305
#define PAGE_NOCACHE
Definition: nt_native.h:1311
#define PAGE_READWRITE
Definition: nt_native.h:1304
#define PAGE_NOACCESS
Definition: nt_native.h:1302
#define PAGE_WRITETHROUGH
Definition: mm.h:109
ULONG64 WriteThrough
Definition: mmtypes.h:69
ULONG64 Write
Definition: mmtypes.h:67
ULONG64 Valid
Definition: mmtypes.h:66
ULONG64 CacheDisable
Definition: mmtypes.h:70
ULONG64 NoExecute
Definition: mmtypes.h:81
ULONG64 CopyOnWrite
Definition: mmtypes.h:75
HARDWARE_PTE Flush
Definition: mmtypes.h:216
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID _In_ ULONG_PTR _In_ SIZE_T _Inout_opt_ PLARGE_INTEGER _Inout_ PSIZE_T _In_ SECTION_INHERIT _In_ ULONG _In_ ULONG Protect
Definition: zwfuncs.h:221

◆ MmGetPfnForProcess()

PFN_NUMBER NTAPI MmGetPfnForProcess ( PEPROCESS  Process,
PVOID  Address 
)

Definition at line 193 of file page.c.

195{
196 PMMPTE PointerPte;
198
199 /* Must be called for user mode only */
200 ASSERT(Process != NULL);
202
203 /* And for our process */
205
206 /* Lock for reading */
208
210 {
212 return 0;
213 }
214
215 /* Make sure we can read the PTE */
217
218 PointerPte = MiAddressToPte(Address);
219 Page = PointerPte->u.Hard.Valid ? PFN_FROM_PTE(PointerPte) : 0;
220
222 return Page;
223}
#define PFN_FROM_PTE(v)
Definition: mm.h:92

◆ MmInitGlobalKernelPageDirectory()

VOID NTAPI MmInitGlobalKernelPageDirectory ( VOID  )

Definition at line 925 of file page.c.

926{
927 /* Nothing to do here */
928}

◆ MmIsDisabledPage()

BOOLEAN NTAPI MmIsDisabledPage ( PEPROCESS  Process,
PVOID  Address 
)

Definition at line 465 of file page.c.

466{
467 BOOLEAN Ret;
468 PMMPTE PointerPte;
469
471 {
472 ASSERT(Process == NULL);
473#if _MI_PAGING_LEVELS == 2
474 if (!MiSynchronizeSystemPde(MiAddressToPde(Address)))
475#else
477#endif
478 {
479 /* It's not disabled if it's not present */
480 return FALSE;
481 }
482 }
483 else
484 {
485 ASSERT(Process != NULL);
487
489
491 {
492 /* It can't be disabled if there is no PDE */
494 return FALSE;
495 }
496
498 }
499
500 PointerPte = MiAddressToPte(Address);
501 Ret = !PointerPte->u.Hard.Valid
502 && !FlagOn(PointerPte->u.Long, 0x800)
503 && (PointerPte->u.Hard.PageFrameNumber != 0);
504
507
508 return Ret;
509}

◆ MmIsPagePresent()

BOOLEAN NTAPI MmIsPagePresent ( PEPROCESS  Process,
PVOID  Address 
)

Definition at line 422 of file page.c.

423{
424 BOOLEAN Ret;
425
427 {
428 ASSERT(Process == NULL);
429#if _MI_PAGING_LEVELS == 2
430 if (!MiSynchronizeSystemPde(MiAddressToPde(Address)))
431#else
433#endif
434 {
435 /* It can't be present if there is no PDE */
436 return FALSE;
437 }
438
439 return MiAddressToPte(Address)->u.Hard.Valid;
440 }
441
442 ASSERT(Process != NULL);
444
446
448 {
449 /* It can't be present if there is no PDE */
451 return FALSE;
452 }
453
455
456 Ret = MiAddressToPte(Address)->u.Hard.Valid;
457
459
460 return Ret;
461}

◆ MmIsPageSwapEntry()

BOOLEAN NTAPI MmIsPageSwapEntry ( PEPROCESS  Process,
PVOID  Address 
)

Definition at line 513 of file page.c.

514{
515 BOOLEAN Ret;
516 PMMPTE PointerPte;
517
518 /* We never set swap entries for kernel addresses */
520 {
521 ASSERT(Process == NULL);
522 return FALSE;
523 }
524
525 ASSERT(Process != NULL);
527
529
531 {
532 /* There can't be a swap entry if there is no PDE */
534 return FALSE;
535 }
536
538
539 PointerPte = MiAddressToPte(Address);
540 Ret = !PointerPte->u.Hard.Valid && FlagOn(PointerPte->u.Long, 0x800);
541
543
544 return Ret;
545}

◆ MmSetDirtyBit()

VOID NTAPI MmSetDirtyBit ( PEPROCESS  Process,
PVOID  Address,
BOOLEAN  Bit 
)

Definition at line 890 of file page.c.

891{
892 PMMPTE PointerPte;
893
894 DPRINT("MmSetDirtyBit(Process %p Address %p Bit %x)\n",
895 Process, Address, Bit);
896
897 ASSERT(Process != NULL);
899
901
903
905
906 PointerPte = MiAddressToPte(Address);
907 // We shouldnl't set dirty bit on non-mapped addresses
908 if (!PointerPte->u.Hard.Valid && (FlagOn(PointerPte->u.Long, 0x800) || (PointerPte->u.Hard.PageFrameNumber == 0)))
909 {
910 DPRINT1("Invalid Pte %lx\n", PointerPte->u.Long);
911 KeBugCheck(MEMORY_MANAGEMENT);
912 }
913
914 PointerPte->u.Hard.Dirty = !!Bit;
915
916 if (!Bit)
918
920}

◆ MmSetPageProtect()

VOID NTAPI MmSetPageProtect ( PEPROCESS  Process,
PVOID  Address,
ULONG  flProtect 
)

Definition at line 833 of file page.c.

834{
835 ULONG ProtectionMask;
836 PMMPTE PointerPte;
837 MMPTE TempPte, OldPte;
838
839 DPRINT("MmSetPageProtect(Process %p Address %p flProtect %x)\n",
840 Process, Address, flProtect);
841
842 ASSERT(Process != NULL);
844
846
847 ProtectionMask = MiMakeProtectionMask(flProtect);
848 /* Caller must have checked ! */
849 ASSERT(ProtectionMask != MM_INVALID_PROTECTION);
850
852
854
855 PointerPte = MiAddressToPte(Address);
856
857 /* Sanity check */
858 ASSERT(PointerPte->u.Hard.Owner == 1);
859
860 TempPte.u.Long = 0;
861 TempPte.u.Hard.PageFrameNumber = PointerPte->u.Hard.PageFrameNumber;
862 TempPte.u.Long |= MmProtectToPteMask[ProtectionMask];
863 TempPte.u.Hard.Owner = 1;
864
865 /* Only set valid bit if we have to */
866 if ((ProtectionMask != MM_NOACCESS) && !FlagOn(ProtectionMask, MM_GUARDPAGE))
867 TempPte.u.Hard.Valid = 1;
868
869 /* Keep dirty & accessed bits */
870 TempPte.u.Hard.Accessed = PointerPte->u.Hard.Accessed;
871 TempPte.u.Hard.Dirty = PointerPte->u.Hard.Dirty;
872
873 OldPte.u.Long = InterlockedExchangePte(PointerPte, TempPte.u.Long);
874
875 // We should be able to bring a page back from PAGE_NOACCESS
876 if (!OldPte.u.Hard.Valid && (FlagOn(OldPte.u.Long, 0x800) || (OldPte.u.Hard.PageFrameNumber == 0)))
877 {
878 DPRINT1("Invalid Pte %lx\n", OldPte.u.Long);
879 KeBugCheck(MEMORY_MANAGEMENT);
880 }
881
882 if (OldPte.u.Long != TempPte.u.Long)
884
886}
#define MM_GUARDPAGE
Definition: miarm.h:57
const ULONG_PTR MmProtectToPteMask[32]
Definition: page.c:25
ULONG64 Accessed
Definition: mmtypes.h:163
ULONG64 Owner
Definition: mmtypes.h:160

Variable Documentation

◆ MmProtectToPteMask

const ULONG_PTR MmProtectToPteMask[32]

◆ MmProtectToValue

const ULONG MmProtectToValue[32]

Definition at line 74 of file page.c.