ReactOS 0.4.15-dev-6068-g8061a6f
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 MmCreateVirtualMappingUnsafe (PEPROCESS Process, PVOID Address, ULONG flProtect, 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.

242{
243 PMMPTE PointerPte;
244 MMPTE OldPte;
245 BOOLEAN ValidPde;
246
247 OldPte.u.Long = 0;
248
249 DPRINT("MmDeleteVirtualMapping(%p, %p, %p, %p)\n", Process, Address, WasDirty, Page);
250
252
253 /* And we should be at low IRQL */
255
256 /* Make sure our PDE is valid, and that everything is going fine */
257 if (Process == NULL)
258 {
260 {
261 DPRINT1("NULL process given for user-mode mapping at %p\n", Address);
262 KeBugCheck(MEMORY_MANAGEMENT);
263 }
264#if (_MI_PAGING_LEVELS == 2)
265 ValidPde = MiSynchronizeSystemPde(MiAddressToPde(Address));
266#else
268#endif
269 }
270 else
271 {
273 {
274 DPRINT1("Process %p given for kernel-mode mapping at %p\n", Process, Address);
275 KeBugCheck(MEMORY_MANAGEMENT);
276 }
277
278 /* Only for current process !!! */
281
282 ValidPde = MiIsPageTablePresent(Address);
283 if (ValidPde)
284 {
286 }
287 }
288
289 /* Get the PTE if we're having anything */
290 if (ValidPde)
291 {
292 PointerPte = MiAddressToPte(Address);
293 OldPte.u.Long = InterlockedExchangePte(PointerPte, 0);
294
296
297 if (OldPte.u.Long != 0)
298 {
299 /* It must have been present, or not a swap entry */
300 ASSERT(OldPte.u.Hard.Valid || !FlagOn(OldPte.u.Long, 0x800));
301 if (WasDirty != NULL)
302 {
303 *WasDirty = !!OldPte.u.Hard.Dirty;
304 }
305 if (Page != NULL)
306 {
307 *Page = OldPte.u.Hard.PageFrameNumber;
308 }
309 }
310 }
311
312 if (Process != NULL)
313 {
314 /* Remove PDE reference, if needed */
315 if (OldPte.u.Long != 0)
316 {
318 {
319 KIRQL OldIrql = MiAcquirePfnLock();
321 MiReleasePfnLock(OldIrql);
322 }
323 }
324
326 }
327
328 return OldPte.u.Long != 0;
329}
unsigned char BOOLEAN
#define DPRINT1
Definition: precomp.h:8
DECLSPEC_NORETURN VOID NTAPI KeBugCheck(ULONG BugCheckCode)
Definition: bug.c:1431
#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:2475
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
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 _Out_opt_ PPFN_NUMBER Page
Definition: mm.h:1298
_In_ PVOID _Out_opt_ BOOLEAN * WasDirty
Definition: mm.h:1296
#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
ULONG64 Dirty
Definition: mmtypes.h:164
ULONG64 Valid
Definition: mmtypes.h:150
ULONG64 PageFrameNumber
Definition: mmtypes.h:171
MMPTE_HARDWARE Hard
Definition: mmtypes.h:217
ULONG_PTR Long
Definition: mmtypes.h:215
union _MMPTE::@2307 u
uint32_t ULONG_PTR
Definition: typedefs.h:65
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:792
#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:533
#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:1282
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:2427
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 MmCreateVirtualMappingUnsafe().

◆ 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
Definition: mm.h:374
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:883

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

◆ MmCreatePageFileMapping()

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

Definition at line 549 of file page.c.

552{
553 PMMPTE PointerPte;
554 ULONG_PTR Pte;
555
556 /* This should not be called for kernel space anymore */
557 ASSERT(Process != NULL);
559
560 /* And we don't support creating for other process */
562
563 if (SwapEntry & (1 << 31))
564 {
565 KeBugCheck(MEMORY_MANAGEMENT);
566 }
567
568 /* We are tinkering with the PDE here. Ensure it will be there */
571
573
574 PointerPte = MiAddressToPte(Address);
575 Pte = InterlockedExchangePte(PointerPte, SwapEntry << 1);
576 if (Pte != 0)
577 {
578 KeBugCheckEx(MEMORY_MANAGEMENT, SwapEntry, (ULONG_PTR)Process, (ULONG_PTR)Address, 0);
579 }
580
581 /* This used to be a 0 PTE, now we need a valid PDE to keep it around */
584
585 return STATUS_SUCCESS;
586}
FORCEINLINE USHORT MiIncrementPageTableReferences(IN PVOID Address)
Definition: miarm.h:2481
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

◆ MmCreateVirtualMapping()

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

Definition at line 672 of file page.c.

676{
678 if (!MmIsPageInUse(Page))
679 {
680 DPRINT1("Page %lx is not in use\n", Page);
681 KeBugCheck(MEMORY_MANAGEMENT);
682 }
683
685}
BOOLEAN NTAPI MmIsPageInUse(PFN_NUMBER Page)
Definition: freelist.c:558
NTSTATUS NTAPI MmCreateVirtualMappingUnsafe(PEPROCESS Process, PVOID Address, ULONG flProtect, PFN_NUMBER Page)
Definition: page.c:591

◆ MmCreateVirtualMappingUnsafe()

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

Definition at line 591 of file page.c.

595{
596 ULONG ProtectionMask;
597 PMMPTE PointerPte;
599 ULONG_PTR Pte;
600
601 DPRINT("MmCreateVirtualMappingUnsafe(%p, %p, %lu, %x)\n",
602 Process, Address, flProtect, Page);
603
605
606 ProtectionMask = MiMakeProtectionMask(flProtect);
607 /* Caller must have checked ! */
608 ASSERT(ProtectionMask != MM_INVALID_PROTECTION);
609 ASSERT(ProtectionMask != MM_NOACCESS);
610 ASSERT(ProtectionMask != MM_ZERO_ACCESS);
611
612 /* Make sure our PDE is valid, and that everything is going fine */
613 if (Process == NULL)
614 {
615 /* We don't support this in legacy Mm for kernel mappings */
616 ASSERT(ProtectionMask != MM_WRITECOPY);
617 ASSERT(ProtectionMask != MM_EXECUTE_WRITECOPY);
618
620 {
621 DPRINT1("NULL process given for user-mode mapping at %p\n", Address);
622 KeBugCheck(MEMORY_MANAGEMENT);
623 }
624#if _MI_PAGING_LEVELS == 2
625 if (!MiSynchronizeSystemPde(MiAddressToPde(Address)))
627#endif
628 }
629 else
630 {
632 {
633 DPRINT1("Process %p given for kernel-mode mapping at %p -- 1 page starting at %Ix\n",
635 KeBugCheck(MEMORY_MANAGEMENT);
636 }
637
638 /* Only for current process !!! */
641
643 }
644
645 PointerPte = MiAddressToPte(Address);
646
647 MI_MAKE_HARDWARE_PTE(&TempPte, PointerPte, ProtectionMask, Page);
648
649 Pte = InterlockedExchangePte(PointerPte, TempPte.u.Long);
650 /* There should not have been anything valid here */
651 if (Pte != 0)
652 {
653 DPRINT1("Bad PTE %lx at %p for %p\n", Pte, PointerPte, Address);
654 KeBugCheck(MEMORY_MANAGEMENT);
655 }
656
657 /* We don't need to flush the TLB here because it only caches valid translations
658 * and we're moving this PTE from invalid to valid so it can't be cached right now */
659
661 {
662 /* Add PDE reference */
665 }
666
667 return(STATUS_SUCCESS);
668}
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
uint32_t ULONG
Definition: typedefs.h:59

◆ MmDeletePageFileMapping()

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

Definition at line 334 of file page.c.

338{
339 PMMPTE PointerPte;
340 MMPTE OldPte;
341
342 /* This should not be called for kernel space anymore */
343 ASSERT(Process != NULL);
345
346 /* And we don't support deleting for other process */
348
349 /* And we should be at low IRQL */
351
352 /* We are tinkering with the PDE here. Ensure it will be there */
354
355 /* Callers must ensure there is actually something there */
356 ASSERT(MiAddressToPde(Address)->u.Long != 0);
357
359
360 PointerPte = MiAddressToPte(Address);
361 OldPte.u.Long = InterlockedExchangePte(PointerPte, 0);
362 /* This must be a swap entry ! */
363 if (!FlagOn(OldPte.u.Long, 0x800) || OldPte.u.Hard.Valid)
364 {
365 KeBugCheckEx(MEMORY_MANAGEMENT, OldPte.u.Long, (ULONG_PTR)Process, (ULONG_PTR)Address, 0);
366 }
367
368 /* This used to be a non-zero PTE, now we can let the PDE go. */
370 {
371 /* We can let it go */
372 KIRQL OldIrql = MiAcquirePfnLock();
373 MiDeletePde(MiPteToPde(PointerPte), Process);
374 MiReleasePfnLock(OldIrql);
375 }
376
378
379 *SwapEntry = OldPte.u.Long >> 1;
380}
#define MiPteToPde(_Pte)
Definition: mm.h:121

◆ MmGetPageFileMapping()

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

Definition at line 511 of file page.c.

512{
513 PMMPTE PointerPte;
514
515 /* We never set swap entries for kernel addresses */
517 {
518 ASSERT(Process == NULL);
519 *SwapEntry = 0;
520 return;
521 }
522
523 ASSERT(Process != NULL);
525
527
529 {
530 /* There can't be a swap entry if there is no PDE */
532 *SwapEntry = 0;
533 return;
534 }
535
537
538 PointerPte = MiAddressToPte(Address);
539 if (!PointerPte->u.Hard.Valid && FlagOn(PointerPte->u.Long, 0x800))
540 *SwapEntry = PointerPte->u.Long >> 1;
541 else
542 *SwapEntry = 0;
543
545}
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 689 of file page.c.

690{
691 PMMPTE PointerPte;
693
695 {
696 ASSERT(Process == NULL);
697
698#if _MI_PAGING_LEVELS == 2
699 if (!MiSynchronizeSystemPde(MiAddressToPde(Address)))
700#else
702#endif
703 {
704 return PAGE_NOACCESS;
705 }
706 }
707 else
708 {
710 ASSERT(Process != NULL);
711
713
715
717 {
718 /* It can't be present if there is no PDE */
720 return PAGE_NOACCESS;
721 }
722
724 }
725
726 PointerPte = MiAddressToPte(Address);
727
728 if (!PointerPte->u.Flush.Valid)
729 {
731 }
732 else
733 {
734 if (PointerPte->u.Flush.CopyOnWrite)
736 else if (PointerPte->u.Flush.Write)
738 else
740#if _MI_PAGING_LEVELS >= 3
741 /* PAE & AMD64 long mode support NoExecute bit */
742 if (!PointerPte->u.Flush.NoExecute)
743 Protect <<= 4;
744#endif
745 if (PointerPte->u.Flush.CacheDisable)
747 if (PointerPte->u.Flush.WriteThrough)
749 }
750
753
754 return(Protect);
755}
#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 851 of file page.c.

852{
853 /* Nothing to do here */
854}

◆ MmIsDisabledPage()

BOOLEAN NTAPI MmIsDisabledPage ( PEPROCESS  Process,
PVOID  Address 
)

Definition at line 427 of file page.c.

428{
429 BOOLEAN Ret;
430 PMMPTE PointerPte;
431
433 {
434 ASSERT(Process == NULL);
435#if _MI_PAGING_LEVELS == 2
436 if (!MiSynchronizeSystemPde(MiAddressToPde(Address)))
437#else
439#endif
440 {
441 /* It's not disabled if it's not present */
442 return FALSE;
443 }
444 }
445 else
446 {
447 ASSERT(Process != NULL);
449
451
453 {
454 /* It can't be disabled if there is no PDE */
456 return FALSE;
457 }
458
460 }
461
462 PointerPte = MiAddressToPte(Address);
463 Ret = !PointerPte->u.Hard.Valid
464 && !FlagOn(PointerPte->u.Long, 0x800)
465 && (PointerPte->u.Hard.PageFrameNumber != 0);
466
469
470 return Ret;
471}

◆ MmIsPagePresent()

BOOLEAN NTAPI MmIsPagePresent ( PEPROCESS  Process,
PVOID  Address 
)

Definition at line 384 of file page.c.

385{
386 BOOLEAN Ret;
387
389 {
390 ASSERT(Process == NULL);
391#if _MI_PAGING_LEVELS == 2
392 if (!MiSynchronizeSystemPde(MiAddressToPde(Address)))
393#else
395#endif
396 {
397 /* It can't be present if there is no PDE */
398 return FALSE;
399 }
400
401 return MiAddressToPte(Address)->u.Hard.Valid;
402 }
403
404 ASSERT(Process != NULL);
406
408
410 {
411 /* It can't be present if there is no PDE */
413 return FALSE;
414 }
415
417
418 Ret = MiAddressToPte(Address)->u.Hard.Valid;
419
421
422 return Ret;
423}

◆ MmIsPageSwapEntry()

BOOLEAN NTAPI MmIsPageSwapEntry ( PEPROCESS  Process,
PVOID  Address 
)

Definition at line 475 of file page.c.

476{
477 BOOLEAN Ret;
478 PMMPTE PointerPte;
479
480 /* We never set swap entries for kernel addresses */
482 {
483 ASSERT(Process == NULL);
484 return FALSE;
485 }
486
487 ASSERT(Process != NULL);
489
491
493 {
494 /* There can't be a swap entry if there is no PDE */
496 return FALSE;
497 }
498
500
501 PointerPte = MiAddressToPte(Address);
502 Ret = !PointerPte->u.Hard.Valid && FlagOn(PointerPte->u.Long, 0x800);
503
505
506 return Ret;
507}

◆ MmSetDirtyBit()

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

Definition at line 816 of file page.c.

817{
818 PMMPTE PointerPte;
819
820 DPRINT("MmSetDirtyBit(Process %p Address %p Bit %x)\n",
821 Process, Address, Bit);
822
823 ASSERT(Process != NULL);
825
827
829
831
832 PointerPte = MiAddressToPte(Address);
833 // We shouldnl't set dirty bit on non-mapped adresses
834 if (!PointerPte->u.Hard.Valid && (FlagOn(PointerPte->u.Long, 0x800) || (PointerPte->u.Hard.PageFrameNumber == 0)))
835 {
836 DPRINT1("Invalid Pte %lx\n", PointerPte->u.Long);
837 KeBugCheck(MEMORY_MANAGEMENT);
838 }
839
840 PointerPte->u.Hard.Dirty = !!Bit;
841
842 if (!Bit)
844
846}

◆ MmSetPageProtect()

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

Definition at line 759 of file page.c.

760{
761 ULONG ProtectionMask;
762 PMMPTE PointerPte;
763 MMPTE TempPte, OldPte;
764
765 DPRINT("MmSetPageProtect(Process %p Address %p flProtect %x)\n",
766 Process, Address, flProtect);
767
768 ASSERT(Process != NULL);
770
772
773 ProtectionMask = MiMakeProtectionMask(flProtect);
774 /* Caller must have checked ! */
775 ASSERT(ProtectionMask != MM_INVALID_PROTECTION);
776
778
780
781 PointerPte = MiAddressToPte(Address);
782
783 /* Sanity check */
784 ASSERT(PointerPte->u.Hard.Owner == 1);
785
786 TempPte.u.Long = 0;
787 TempPte.u.Hard.PageFrameNumber = PointerPte->u.Hard.PageFrameNumber;
788 TempPte.u.Long |= MmProtectToPteMask[ProtectionMask];
789 TempPte.u.Hard.Owner = 1;
790
791 /* Only set valid bit if we have to */
792 if ((ProtectionMask != MM_NOACCESS) && !FlagOn(ProtectionMask, MM_GUARDPAGE))
793 TempPte.u.Hard.Valid = 1;
794
795 /* Keep dirty & accessed bits */
796 TempPte.u.Hard.Accessed = PointerPte->u.Hard.Accessed;
797 TempPte.u.Hard.Dirty = PointerPte->u.Hard.Dirty;
798
799 OldPte.u.Long = InterlockedExchangePte(PointerPte, TempPte.u.Long);
800
801 // We should be able to bring a page back from PAGE_NOACCESS
802 if (!OldPte.u.Hard.Valid && (FlagOn(OldPte.u.Long, 0x800) || (OldPte.u.Hard.PageFrameNumber == 0)))
803 {
804 DPRINT1("Invalid Pte %lx\n", OldPte.u.Long);
805 KeBugCheck(MEMORY_MANAGEMENT);
806 }
807
808 if (OldPte.u.Long != TempPte.u.Long)
810
812}
#define MM_GUARDPAGE
Definition: miarm.h:57
const ULONG_PTR MmProtectToPteMask[32]
Definition: page.c:25
ULONG PageFrameNumber
Definition: mmtypes.h:109
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.