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

Go to the source code of this file.

Macros

#define NDEBUG
 
#define MODULE_INVOLVED_IN_ARM3
 
#define HYDRA_PROCESS   (PEPROCESS)1
 
#define _BYTE_MASK(Bit0, Bit1, Bit2, Bit3, Bit4, Bit5, Bit6, Bit7)
 

Functions

static NTSTATUS NTAPI MiCheckForUserStackOverflow (IN PVOID Address, IN PVOID TrapInformation)
 
FORCEINLINE BOOLEAN MiIsAccessAllowed (_In_ ULONG ProtectionMask, _In_ BOOLEAN Write, _In_ BOOLEAN Execute)
 
static NTSTATUS NTAPI MiAccessCheck (IN PMMPTE PointerPte, IN BOOLEAN StoreInstruction, IN KPROCESSOR_MODE PreviousMode, IN ULONG_PTR ProtectionMask, IN PVOID TrapFrame, IN BOOLEAN LockHeld)
 
static PMMPTE NTAPI MiCheckVirtualAddress (IN PVOID VirtualAddress, OUT PULONG ProtectCode, OUT PMMVAD *ProtoVad)
 
NTSTATUS FASTCALL MiCheckPdeForPagedPool (IN PVOID Address)
 
VOID NTAPI MiZeroPfn (IN PFN_NUMBER PageFrameNumber)
 
VOID NTAPI MiCopyPfn (_In_ PFN_NUMBER DestPage, _In_ PFN_NUMBER SrcPage)
 
static NTSTATUS NTAPI MiResolveDemandZeroFault (IN PVOID Address, IN PMMPTE PointerPte, IN ULONG Protection, IN PEPROCESS Process, IN KIRQL OldIrql)
 
static NTSTATUS NTAPI MiCompleteProtoPteFault (IN BOOLEAN StoreInstruction, IN PVOID Address, IN PMMPTE PointerPte, IN PMMPTE PointerProtoPte, IN KIRQL OldIrql, IN PMMPFN *LockedProtoPfn)
 
static NTSTATUS NTAPI MiResolvePageFileFault (_In_ BOOLEAN StoreInstruction, _In_ PVOID FaultingAddress, _In_ PMMPTE PointerPte, _In_ PEPROCESS CurrentProcess, _Inout_ KIRQL *OldIrql)
 
static NTSTATUS NTAPI MiResolveTransitionFault (IN BOOLEAN StoreInstruction, IN PVOID FaultingAddress, IN PMMPTE PointerPte, IN PEPROCESS CurrentProcess, IN KIRQL OldIrql, OUT PKEVENT **InPageBlock)
 
static NTSTATUS NTAPI MiResolveProtoPteFault (IN BOOLEAN StoreInstruction, IN PVOID Address, IN PMMPTE PointerPte, IN PMMPTE PointerProtoPte, IN OUT PMMPFN *OutPfn, OUT PVOID *PageFileData, OUT PMMPTE PteValue, IN PEPROCESS Process, IN KIRQL OldIrql, IN PVOID TrapInformation)
 
NTSTATUS NTAPI MiDispatchFault (IN ULONG FaultCode, IN PVOID Address, IN PMMPTE PointerPte, IN PMMPTE PointerProtoPte, IN BOOLEAN Recursive, IN PEPROCESS Process, IN PVOID TrapInformation, IN PMMVAD Vad)
 
NTSTATUS NTAPI MmArmAccessFault (IN ULONG FaultCode, IN PVOID Address, IN KPROCESSOR_MODE Mode, IN PVOID TrapInformation)
 
NTSTATUS NTAPI MmGetExecuteOptions (IN PULONG ExecuteOptions)
 
NTSTATUS NTAPI MmSetExecuteOptions (IN ULONG ExecuteOptions)
 

Macro Definition Documentation

◆ _BYTE_MASK

#define _BYTE_MASK (   Bit0,
  Bit1,
  Bit2,
  Bit3,
  Bit4,
  Bit5,
  Bit6,
  Bit7 
)
Value:
(Bit0) | ((Bit1) << 1) | ((Bit2) << 2) | ((Bit3) << 3) | \
((Bit4) << 4) | ((Bit5) << 5) | ((Bit6) << 6) | ((Bit7) << 7)

◆ HYDRA_PROCESS

#define HYDRA_PROCESS   (PEPROCESS)1

Definition at line 20 of file pagfault.c.

◆ MODULE_INVOLVED_IN_ARM3

#define MODULE_INVOLVED_IN_ARM3

Definition at line 15 of file pagfault.c.

◆ NDEBUG

#define NDEBUG

Definition at line 12 of file pagfault.c.

Function Documentation

◆ MiAccessCheck()

static NTSTATUS NTAPI MiAccessCheck ( IN PMMPTE  PointerPte,
IN BOOLEAN  StoreInstruction,
IN KPROCESSOR_MODE  PreviousMode,
IN ULONG_PTR  ProtectionMask,
IN PVOID  TrapFrame,
IN BOOLEAN  LockHeld 
)
static

Definition at line 168 of file pagfault.c.

174 {
175  MMPTE TempPte;
176 
177  /* Check for invalid user-mode access */
178  if ((PreviousMode == UserMode) && (PointerPte > MiHighestUserPte))
179  {
181  }
182 
183  /* Capture the PTE -- is it valid? */
184  TempPte = *PointerPte;
185  if (TempPte.u.Hard.Valid)
186  {
187  /* Was someone trying to write to it? */
188  if (StoreInstruction)
189  {
190  /* Is it writable?*/
193  {
194  /* Then there's nothing to worry about */
195  return STATUS_SUCCESS;
196  }
197 
198  /* Oops! This isn't allowed */
200  }
201 
202  /* Someone was trying to read from a valid PTE, that's fine too */
203  return STATUS_SUCCESS;
204  }
205 
206  /* Check if the protection on the page allows what is being attempted */
207  if (!MiIsAccessAllowed(ProtectionMask, StoreInstruction, FALSE))
208  {
210  }
211 
212  /* Check if this is a guard page */
213  if ((ProtectionMask & MM_PROTECT_SPECIAL) == MM_GUARDPAGE)
214  {
215  ASSERT(ProtectionMask != MM_DECOMMIT);
216 
217  /* Attached processes can't expand their stack */
219 
220  /* No support for prototype PTEs yet */
221  ASSERT(TempPte.u.Soft.Prototype == 0);
222 
223  /* Remove the guard page bit, and return a guard page violation */
224  TempPte.u.Soft.Protection = ProtectionMask & ~MM_GUARDPAGE;
225  ASSERT(TempPte.u.Long != 0);
226  MI_WRITE_INVALID_PTE(PointerPte, TempPte);
228  }
229 
230  /* Nothing to do */
231  return STATUS_SUCCESS;
232 }
#define MM_DECOMMIT
Definition: miarm.h:64
#define STATUS_GUARD_PAGE_VIOLATION
Definition: ntstatus.h:182
#define MI_IS_PAGE_COPY_ON_WRITE(x)
Definition: mm.h:110
#define FALSE
Definition: types.h:117
BOOLEAN NTAPI KeIsAttachedProcess(VOID)
Definition: procobj.c:693
FORCEINLINE BOOLEAN MiIsAccessAllowed(_In_ ULONG ProtectionMask, _In_ BOOLEAN Write, _In_ BOOLEAN Execute)
Definition: pagfault.c:138
_In_ KPROCESSOR_MODE PreviousMode
Definition: sefuncs.h:103
#define ASSERT(a)
Definition: mode.c:44
HARDWARE_PTE_ARMV6 TempPte
Definition: winldr.c:76
#define MM_GUARDPAGE
Definition: miarm.h:57
#define MI_IS_PAGE_WRITEABLE(x)
Definition: mm.h:106
FORCEINLINE VOID MI_WRITE_INVALID_PTE(IN PMMPTE PointerPte, IN MMPTE InvalidPte)
Definition: miarm.h:997
#define STATUS_ACCESS_VIOLATION
Definition: ntstatus.h:242
#define MM_PROTECT_SPECIAL
Definition: miarm.h:59
#define STATUS_SUCCESS
Definition: shellext.h:65
PMMPTE MiHighestUserPte
Definition: mminit.c:233

Referenced by MiResolveProtoPteFault(), and MmArmAccessFault().

◆ MiCheckForUserStackOverflow()

static NTSTATUS NTAPI MiCheckForUserStackOverflow ( IN PVOID  Address,
IN PVOID  TrapInformation 
)
static

Definition at line 30 of file pagfault.c.

32 {
33  PETHREAD CurrentThread = PsGetCurrentThread();
34  PTEB Teb = CurrentThread->Tcb.Teb;
35  PVOID StackBase, DeallocationStack, NextStackAddress;
36  SIZE_T GuaranteedSize;
38 
39  /* Do we own the address space lock? */
40  if (CurrentThread->AddressSpaceOwner == 1)
41  {
42  /* This isn't valid */
43  DPRINT1("Process owns address space lock\n");
46  }
47 
48  /* Are we attached? */
49  if (KeIsAttachedProcess())
50  {
51  /* This isn't valid */
52  DPRINT1("Process is attached\n");
54  }
55 
56  /* Read the current settings */
57  StackBase = Teb->NtTib.StackBase;
58  DeallocationStack = Teb->DeallocationStack;
59  GuaranteedSize = Teb->GuaranteedStackBytes;
60  DPRINT("Handling guard page fault with Stacks Addresses 0x%p and 0x%p, guarantee: %lx\n",
61  StackBase, DeallocationStack, GuaranteedSize);
62 
63  /* Guarantees make this code harder, for now, assume there aren't any */
64  ASSERT(GuaranteedSize == 0);
65 
66  /* So allocate only the minimum guard page size */
67  GuaranteedSize = PAGE_SIZE;
68 
69  /* Does this faulting stack address actually exist in the stack? */
70  if ((Address >= StackBase) || (Address < DeallocationStack))
71  {
72  /* That's odd... */
73  DPRINT1("Faulting address outside of stack bounds. Address=%p, StackBase=%p, DeallocationStack=%p\n",
74  Address, StackBase, DeallocationStack);
76  }
77 
78  /* This is where the stack will start now */
79  NextStackAddress = (PVOID)((ULONG_PTR)PAGE_ALIGN(Address) - GuaranteedSize);
80 
81  /* Do we have at least one page between here and the end of the stack? */
82  if (((ULONG_PTR)NextStackAddress - PAGE_SIZE) <= (ULONG_PTR)DeallocationStack)
83  {
84  /* We don't -- Trying to make this guard page valid now */
85  DPRINT1("Close to our death...\n");
86 
87  /* Calculate the next memory address */
88  NextStackAddress = (PVOID)((ULONG_PTR)PAGE_ALIGN(DeallocationStack) + GuaranteedSize);
89 
90  /* Allocate the memory */
91  Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
92  &NextStackAddress,
93  0,
94  &GuaranteedSize,
95  MEM_COMMIT,
97  if (NT_SUCCESS(Status))
98  {
99  /* Success! */
100  Teb->NtTib.StackLimit = NextStackAddress;
101  }
102  else
103  {
104  DPRINT1("Failed to allocate memory\n");
105  }
106 
107  return STATUS_STACK_OVERFLOW;
108  }
109 
110  /* Don't handle this flag yet */
112 
113  /* Update the stack limit */
114  Teb->NtTib.StackLimit = (PVOID)((ULONG_PTR)NextStackAddress + GuaranteedSize);
115 
116  /* Now move the guard page to the next page */
117  Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
118  &NextStackAddress,
119  0,
120  &GuaranteedSize,
121  MEM_COMMIT,
124  {
125  /* We did it! */
126  DPRINT("Guard page handled successfully for %p\n", Address);
128  }
129 
130  /* Fail, we couldn't move the guard page */
131  DPRINT1("Guard page failure: %lx\n", Status);
132  ASSERT(FALSE);
133  return STATUS_STACK_OVERFLOW;
134 }
PPEB Peb
Definition: dllmain.c:27
BOOLEAN NTAPI KeAreAllApcsDisabled(VOID)
Definition: apc.c:985
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
#define TRUE
Definition: types.h:120
#define PAGE_GUARD
Definition: nt_native.h:1310
LONG NTSTATUS
Definition: precomp.h:26
KTHREAD Tcb
Definition: pstypes.h:1103
#define STATUS_GUARD_PAGE_VIOLATION
Definition: ntstatus.h:182
#define MEM_COMMIT
Definition: nt_native.h:1313
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define STATUS_ALREADY_COMMITTED
Definition: ntstatus.h:270
ULONG NtGlobalFlag
Definition: ntddk_ex.h:270
#define STATUS_PAGE_FAULT_GUARD_PAGE
Definition: ntstatus.h:97
#define FALSE
Definition: types.h:117
BOOLEAN NTAPI KeIsAttachedProcess(VOID)
Definition: procobj.c:693
#define PsGetCurrentProcess
Definition: psfuncs.h:17
static WCHAR Address[46]
Definition: ping.c:68
void * PVOID
Definition: retypes.h:9
#define NtCurrentProcess()
Definition: nt_native.h:1657
Status
Definition: gdiplustypes.h:24
ULONG GuaranteedStackBytes
Definition: winternl.h:279
#define ASSERT(a)
Definition: mode.c:44
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
PVOID DeallocationStack
Definition: compat.h:737
#define PAGE_ALIGN(Va)
#define PAGE_SIZE
Definition: env_spec_w32.h:49
#define FLG_DISABLE_STACK_EXTENSION
Definition: pstypes.h:71
ULONG_PTR SIZE_T
Definition: typedefs.h:80
Definition: compat.h:694
PVOID StackBase
Definition: compat.h:571
#define STATUS_STACK_OVERFLOW
Definition: ntstatus.h:489
PVOID Teb
Definition: ketypes.h:1749
#define DPRINT1
Definition: precomp.h:8
#define ULONG_PTR
Definition: config.h:101
PVOID StackLimit
Definition: compat.h:572
#define DPRINT
Definition: sndvol32.h:71
NT_TIB NtTib
Definition: ntddk_ex.h:332
#define PAGE_READWRITE
Definition: nt_native.h:1304

Referenced by MmArmAccessFault().

◆ MiCheckPdeForPagedPool()

NTSTATUS FASTCALL MiCheckPdeForPagedPool ( IN PVOID  Address)

Definition at line 475 of file pagfault.c.

476 {
478 }
#define STATUS_ACCESS_VIOLATION
Definition: ntstatus.h:242

Referenced by MiDeletePte(), MiInitializePfn(), MiInitializePfnAndMakePteValid(), and MmArmAccessFault().

◆ MiCheckVirtualAddress()

static PMMPTE NTAPI MiCheckVirtualAddress ( IN PVOID  VirtualAddress,
OUT PULONG  ProtectCode,
OUT PMMVAD ProtoVad 
)
static

Definition at line 237 of file pagfault.c.

240 {
241  PMMVAD Vad;
242  PMMPTE PointerPte;
243 
244  /* No prototype/section support for now */
245  *ProtoVad = NULL;
246 
247  /* User or kernel fault? */
249  {
250  /* Special case for shared data */
252  {
253  /* It's a read-only page */
254  *ProtectCode = MM_READONLY;
255  return MmSharedUserDataPte;
256  }
257 
258  /* Find the VAD, it might not exist if the address is bogus */
260  if (!Vad)
261  {
262  /* Bogus virtual address */
263  *ProtectCode = MM_NOACCESS;
264  return NULL;
265  }
266 
267  /* ReactOS does not handle physical memory VADs yet */
269 
270  /* Check if it's a section, or just an allocation */
271  if (Vad->u.VadFlags.PrivateMemory)
272  {
273  /* ReactOS does not handle AWE VADs yet */
274  ASSERT(Vad->u.VadFlags.VadType != VadAwe);
275 
276  /* This must be a TEB/PEB VAD */
277  if (Vad->u.VadFlags.MemCommit)
278  {
279  /* It's committed, so return the VAD protection */
280  *ProtectCode = (ULONG)Vad->u.VadFlags.Protection;
281  }
282  else
283  {
284  /* It has not yet been committed, so return no access */
285  *ProtectCode = MM_NOACCESS;
286  }
287 
288  /* In both cases, return no PTE */
289  return NULL;
290  }
291  else
292  {
293  /* ReactOS does not supoprt these VADs yet */
295  ASSERT(Vad->u2.VadFlags2.ExtendableFile == 0);
296 
297  /* Return the proto VAD */
298  *ProtoVad = Vad;
299 
300  /* Get the prototype PTE for this page */
301  PointerPte = (((ULONG_PTR)VirtualAddress >> PAGE_SHIFT) - Vad->StartingVpn) + Vad->FirstPrototypePte;
302  ASSERT(PointerPte != NULL);
303  ASSERT(PointerPte <= Vad->LastContiguousPte);
304 
305  /* Return the Prototype PTE and the protection for the page mapping */
306  *ProtectCode = (ULONG)Vad->u.VadFlags.Protection;
307  return PointerPte;
308  }
309  }
311  {
312  /* This should never happen, as these addresses are handled by the double-maping */
315  {
316  /* Fail such access */
317  *ProtectCode = MM_NOACCESS;
318  return NULL;
319  }
320 
321  /* Return full access rights */
322  *ProtectCode = MM_EXECUTE_READWRITE;
323  return NULL;
324  }
326  {
327  /* ReactOS does not have an image list yet, so bail out to failure case */
329  }
330 
331  /* Default case -- failure */
332  *ProtectCode = MM_NOACCESS;
333  return NULL;
334 }
#define MI_IS_PAGE_TABLE_ADDRESS(Address)
Definition: miarm.h:177
#define MM_HIGHEST_USER_ADDRESS
Definition: armddk.h:17
#define PAGE_SHIFT
Definition: env_spec_w32.h:45
#define MI_IS_SESSION_ADDRESS(Address)
Definition: miarm.h:171
#define MM_NOACCESS
Definition: miarm.h:65
PMM_SESSION_SPACE MmSessionSpace
Definition: session.c:21
ULONG_PTR Protection
Definition: mmtypes.h:693
#define MM_SHARED_USER_DATA_VA
Definition: mmtypes.h:48
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
MMVAD_FLAGS VadFlags
Definition: mmtypes.h:731
union _MMVAD::@2564 u2
#define MiAddressToPte(x)
Definition: mmx86.c:19
PMMPTE LastPteForPagedPool
Definition: mm.h:489
MM_PAGED_POOL_INFO MmPagedPoolInfo
Definition: pool.c:25
PMMVAD NTAPI MiLocateAddress(IN PVOID VirtualAddress)
Definition: vadnode.c:48
ULONG ExtendableFile
Definition: mmtypes.h:709
_Must_inspect_result_ _In_ WDFDMATRANSACTION _In_ PFN_WDF_PROGRAM_DMA _In_ WDF_DMA_DIRECTION _In_ PMDL _In_ PVOID VirtualAddress
ULONG_PTR StartingVpn
Definition: mmtypes.h:726
PMMPTE MmSharedUserDataPte
Definition: mminit.c:26
MMVAD_FLAGS2 VadFlags2
Definition: mmtypes.h:739
ULONG_PTR MemCommit
Definition: mmtypes.h:692
ULONG_PTR PrivateMemory
Definition: mmtypes.h:695
#define ASSERT(a)
Definition: mode.c:44
struct _MMPTE * PMMPTE
#define PAGE_ALIGN(Va)
union _MMVAD::@2563 u
LIST_ENTRY ImageList
Definition: miarm.h:494
PVOID MmPagedPoolStart
Definition: miarm.h:579
#define MM_EXECUTE_READWRITE
Definition: miarm.h:49
#define NULL
Definition: types.h:112
unsigned int ULONG
Definition: retypes.h:1
#define ULONG_PTR
Definition: config.h:101
PMMPTE FirstPrototypePte
Definition: mmtypes.h:734
#define MM_READONLY
Definition: bootanim.c:18
ULONG_PTR VadType
Definition: mmtypes.h:691

Referenced by MmArmAccessFault().

◆ MiCompleteProtoPteFault()

static NTSTATUS NTAPI MiCompleteProtoPteFault ( IN BOOLEAN  StoreInstruction,
IN PVOID  Address,
IN PMMPTE  PointerPte,
IN PMMPTE  PointerProtoPte,
IN KIRQL  OldIrql,
IN PMMPFN LockedProtoPfn 
)
static

Definition at line 765 of file pagfault.c.

771 {
772  MMPTE TempPte;
773  PMMPTE OriginalPte, PageTablePte;
774  ULONG_PTR Protection;
775  PFN_NUMBER PageFrameIndex;
776  PMMPFN Pfn1, Pfn2;
777  BOOLEAN OriginalProtection, DirtyPage;
778 
779  /* Must be called with an valid prototype PTE, with the PFN lock held */
781  ASSERT(PointerProtoPte->u.Hard.Valid == 1);
782 
783  /* Get the page */
784  PageFrameIndex = PFN_FROM_PTE(PointerProtoPte);
785 
786  /* Get the PFN entry and set it as a prototype PTE */
787  Pfn1 = MiGetPfnEntry(PageFrameIndex);
788  Pfn1->u3.e1.PrototypePte = 1;
789 
790  /* Increment the share count for the page table */
791  PageTablePte = MiAddressToPte(PointerPte);
792  Pfn2 = MiGetPfnEntry(PageTablePte->u.Hard.PageFrameNumber);
793  Pfn2->u2.ShareCount++;
794 
795  /* Check where we should be getting the protection information from */
796  if (PointerPte->u.Soft.PageFileHigh == MI_PTE_LOOKUP_NEEDED)
797  {
798  /* Get the protection from the PTE, there's no real Proto PTE data */
799  Protection = PointerPte->u.Soft.Protection;
800 
801  /* Remember that we did not use the proto protection */
802  OriginalProtection = FALSE;
803  }
804  else
805  {
806  /* Get the protection from the original PTE link */
807  OriginalPte = &Pfn1->OriginalPte;
808  Protection = OriginalPte->u.Soft.Protection;
809 
810  /* Remember that we used the original protection */
811  OriginalProtection = TRUE;
812 
813  /* Check if this was a write on a read only proto */
814  if ((StoreInstruction) && !(Protection & MM_READWRITE))
815  {
816  /* Clear the flag */
817  StoreInstruction = 0;
818  }
819  }
820 
821  /* Check if this was a write on a non-COW page */
822  DirtyPage = FALSE;
823  if ((StoreInstruction) && ((Protection & MM_WRITECOPY) != MM_WRITECOPY))
824  {
825  /* Then the page should be marked dirty */
826  DirtyPage = TRUE;
827 
828  /* ReactOS check */
829  ASSERT(Pfn1->OriginalPte.u.Soft.Prototype != 0);
830  }
831 
832  /* Did we get a locked incoming PFN? */
833  if (*LockedProtoPfn)
834  {
835  /* Drop a reference */
836  ASSERT((*LockedProtoPfn)->u3.e2.ReferenceCount >= 1);
837  MiDereferencePfnAndDropLockCount(*LockedProtoPfn);
838  *LockedProtoPfn = NULL;
839  }
840 
841  /* Release the PFN lock */
842  MiReleasePfnLock(OldIrql);
843 
844  /* Remove special/caching bits */
845  Protection &= ~MM_PROTECT_SPECIAL;
846 
847  /* Setup caching */
848  if (Pfn1->u3.e1.CacheAttribute == MiWriteCombined)
849  {
850  /* Write combining, no caching */
853  }
854  else if (Pfn1->u3.e1.CacheAttribute == MiNonCached)
855  {
856  /* Write through, no caching */
859  }
860 
861  /* Check if this is a kernel or user address */
863  {
864  /* Build the user PTE */
865  MI_MAKE_HARDWARE_PTE_USER(&TempPte, PointerPte, Protection, PageFrameIndex);
866  }
867  else
868  {
869  /* Build the kernel PTE */
870  MI_MAKE_HARDWARE_PTE(&TempPte, PointerPte, Protection, PageFrameIndex);
871  }
872 
873  /* Set the dirty flag if needed */
874  if (DirtyPage) MI_MAKE_DIRTY_PAGE(&TempPte);
875 
876  /* Write the PTE */
877  MI_WRITE_VALID_PTE(PointerPte, TempPte);
878 
879  /* Reset the protection if needed */
880  if (OriginalProtection) Protection = MM_ZERO_ACCESS;
881 
882  /* Return success */
883  ASSERT(PointerPte == MiAddressToPte(Address));
884  return STATUS_SUCCESS;
885 }
#define MI_PAGE_WRITE_COMBINED(x)
Definition: mm.h:103
#define MI_ASSERT_PFN_LOCK_HELD()
Definition: mm.h:1016
FORCEINLINE VOID MiDereferencePfnAndDropLockCount(IN PMMPFN Pfn1)
Definition: miarm.h:1620
#define TRUE
Definition: types.h:120
#define MI_PTE_LOOKUP_NEEDED
Definition: miarm.h:246
#define MM_READWRITE
Definition: bootanim.c:19
uint32_t ULONG_PTR
Definition: typedefs.h:65
USHORT PrototypePte
Definition: mm.h:363
MMPFNENTRY e1
Definition: mm.h:397
#define MI_MAKE_DIRTY_PAGE(x)
Definition: mm.h:98
#define MM_WRITECOPY
Definition: miarm.h:48
USHORT CacheAttribute
Definition: mm.h:367
#define MiAddressToPte(x)
Definition: mmx86.c:19
ULONG PFN_NUMBER
Definition: ke.h:9
#define FALSE
Definition: types.h:117
FORCEINLINE VOID MI_WRITE_VALID_PTE(IN PMMPTE PointerPte, IN MMPTE TempPte)
Definition: miarm.h:964
ULONG_PTR ShareCount
Definition: mm.h:390
unsigned char BOOLEAN
static WCHAR Address[46]
Definition: ping.c:68
ULONG64 Protection
Definition: mmtypes.h:88
#define MM_ZERO_ACCESS
Definition: miarm.h:43
union _MMPFN::@1751 u3
#define ASSERT(a)
Definition: mode.c:44
HARDWARE_PTE_ARMV6 TempPte
Definition: winldr.c:76
#define MI_PAGE_WRITE_THROUGH(x)
Definition: mm.h:102
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:792
Definition: mm.h:373
ULONG64 Prototype
Definition: mmtypes.h:89
FORCEINLINE PMMPFN MiGetPfnEntry(IN PFN_NUMBER Pfn)
Definition: mm.h:1020
union _MMPTE::@2282 u
FORCEINLINE VOID MI_MAKE_HARDWARE_PTE_USER(IN PMMPTE NewPte, IN PMMPTE MappingPte, IN ULONG_PTR ProtectionMask, IN PFN_NUMBER PageFrameNumber)
Definition: miarm.h:832
MMPTE_HARDWARE Hard
Definition: mmtypes.h:217
#define MI_PAGE_DISABLE_CACHE(x)
Definition: mm.h:101
MMPTE_SOFTWARE Soft
Definition: mmtypes.h:219
#define NULL
Definition: types.h:112
MMPTE OriginalPte
Definition: mm.h:407
ULONG64 PageFrameNumber
Definition: mmtypes.h:171
#define MM_PROTECT_SPECIAL
Definition: miarm.h:59
#define STATUS_SUCCESS
Definition: shellext.h:65
union _MMPFN::@1750 u2
#define PFN_FROM_PTE(v)
Definition: mm.h:92
#define MmSystemRangeStart
Definition: mm.h:32
FORCEINLINE VOID MI_MAKE_HARDWARE_PTE(IN PMMPTE NewPte, IN PMMPTE MappingPte, IN ULONG_PTR ProtectionMask, IN PFN_NUMBER PageFrameNumber)
Definition: miarm.h:812

Referenced by MiDispatchFault(), and MiResolveProtoPteFault().

◆ MiCopyPfn()

VOID NTAPI MiCopyPfn ( _In_ PFN_NUMBER  DestPage,
_In_ PFN_NUMBER  SrcPage 
)

Definition at line 529 of file pagfault.c.

532 {
533  PMMPTE SysPtes;
534  MMPTE TempPte;
535  PMMPFN DestPfn, SrcPfn;
536  PVOID DestAddress;
537  const VOID* SrcAddress;
538 
539  /* Get the PFNs */
540  DestPfn = MiGetPfnEntry(DestPage);
541  ASSERT(DestPfn);
542  SrcPfn = MiGetPfnEntry(SrcPage);
543  ASSERT(SrcPfn);
544 
545  /* Grab 2 system PTEs */
546  SysPtes = MiReserveSystemPtes(2, SystemPteSpace);
547  ASSERT(SysPtes);
548 
549  /* Initialize the destination PTE */
551  TempPte.u.Hard.PageFrameNumber = DestPage;
552 
553  /* Setup caching */
554  if (DestPfn->u3.e1.CacheAttribute == MiWriteCombined)
555  {
556  /* Write combining, no caching */
559  }
560  else if (DestPfn->u3.e1.CacheAttribute == MiNonCached)
561  {
562  /* Write through, no caching */
565  }
566 
567  /* Make the system PTE valid with our PFN */
568  MI_WRITE_VALID_PTE(&SysPtes[0], TempPte);
569 
570  /* Initialize the source PTE */
572  TempPte.u.Hard.PageFrameNumber = SrcPage;
573 
574  /* Setup caching */
575  if (SrcPfn->u3.e1.CacheAttribute == MiNonCached)
576  {
578  }
579 
580  /* Make the system PTE valid with our PFN */
581  MI_WRITE_VALID_PTE(&SysPtes[1], TempPte);
582 
583  /* Get the addresses and perform the copy */
584  DestAddress = MiPteToAddress(&SysPtes[0]);
585  SrcAddress = MiPteToAddress(&SysPtes[1]);
586  RtlCopyMemory(DestAddress, SrcAddress, PAGE_SIZE);
587 
588  /* Now get rid of it */
589  MiReleaseSystemPtes(SysPtes, 2, SystemPteSpace);
590 }
#define MI_PAGE_WRITE_COMBINED(x)
Definition: mm.h:103
PMMPTE NTAPI MiReserveSystemPtes(IN ULONG NumberOfPtes, IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType)
Definition: syspte.c:246
MMPFNENTRY e1
Definition: mm.h:397
USHORT CacheAttribute
Definition: mm.h:367
FORCEINLINE VOID MI_WRITE_VALID_PTE(IN PMMPTE PointerPte, IN MMPTE TempPte)
Definition: miarm.h:964
VOID NTAPI MiReleaseSystemPtes(IN PMMPTE StartingPte, IN ULONG NumberOfPtes, IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType)
Definition: syspte.c:264
union _MMPFN::@1751 u3
#define ASSERT(a)
Definition: mode.c:44
HARDWARE_PTE_ARMV6 TempPte
Definition: winldr.c:76
MMPTE ValidKernelPte
Definition: init.c:29
#define MI_PAGE_WRITE_THROUGH(x)
Definition: mm.h:102
Definition: mm.h:373
#define PAGE_SIZE
Definition: env_spec_w32.h:49
FORCEINLINE PMMPFN MiGetPfnEntry(IN PFN_NUMBER Pfn)
Definition: mm.h:1020
#define MI_PAGE_DISABLE_CACHE(x)
Definition: mm.h:101
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
FORCEINLINE PVOID MiPteToAddress(PMMPTE PointerPte)
Definition: mm.h:208
ULONG PageFrameNumber
Definition: mmtypes.h:109

Referenced by MiResolveProtoPteFault(), and MmArmAccessFault().

◆ MiDispatchFault()

NTSTATUS NTAPI MiDispatchFault ( IN ULONG  FaultCode,
IN PVOID  Address,
IN PMMPTE  PointerPte,
IN PMMPTE  PointerProtoPte,
IN BOOLEAN  Recursive,
IN PEPROCESS  Process,
IN PVOID  TrapInformation,
IN PMMVAD  Vad 
)

Definition at line 1319 of file pagfault.c.

1327 {
1328  MMPTE TempPte;
1329  KIRQL OldIrql, LockIrql;
1330  NTSTATUS Status;
1331  PMMPTE SuperProtoPte;
1332  PMMPFN Pfn1, OutPfn = NULL;
1333  PFN_NUMBER PageFrameIndex;
1334  PFN_COUNT PteCount, ProcessedPtes;
1335  DPRINT("ARM3 Page Fault Dispatcher for address: %p in process: %p\n",
1336  Address,
1337  Process);
1338 
1339  /* Make sure the addresses are ok */
1340  ASSERT(PointerPte == MiAddressToPte(Address));
1341 
1342  //
1343  // Make sure APCs are off and we're not at dispatch
1344  //
1346  ASSERT(OldIrql <= APC_LEVEL);
1348 
1349  //
1350  // Grab a copy of the PTE
1351  //
1352  TempPte = *PointerPte;
1353 
1354  /* Do we have a prototype PTE? */
1355  if (PointerProtoPte)
1356  {
1357  /* This should never happen */
1358  ASSERT(!MI_IS_PHYSICAL_ADDRESS(PointerProtoPte));
1359 
1360  /* Check if this is a kernel-mode address */
1361  SuperProtoPte = MiAddressToPte(PointerProtoPte);
1362  if (Address >= MmSystemRangeStart)
1363  {
1364  /* Lock the PFN database */
1365  LockIrql = MiAcquirePfnLock();
1366 
1367  /* Has the PTE been made valid yet? */
1368  if (!SuperProtoPte->u.Hard.Valid)
1369  {
1370  ASSERT(FALSE);
1371  }
1372  else if (PointerPte->u.Hard.Valid == 1)
1373  {
1374  ASSERT(FALSE);
1375  }
1376 
1377  /* Resolve the fault -- this will release the PFN lock */
1379  Address,
1380  PointerPte,
1381  PointerProtoPte,
1382  &OutPfn,
1383  NULL,
1384  NULL,
1385  Process,
1386  LockIrql,
1387  TrapInformation);
1389 
1390  /* Complete this as a transition fault */
1392  ASSERT(OldIrql <= APC_LEVEL);
1394  return Status;
1395  }
1396  else
1397  {
1398  /* We only handle the lookup path */
1399  ASSERT(PointerPte->u.Soft.PageFileHigh == MI_PTE_LOOKUP_NEEDED);
1400 
1401  /* Is there a non-image VAD? */
1402  if ((Vad) &&
1403  (Vad->u.VadFlags.VadType != VadImageMap) &&
1404  !(Vad->u2.VadFlags2.ExtendableFile))
1405  {
1406  /* One day, ReactOS will cluster faults */
1408  DPRINT("Should cluster fault, but won't\n");
1409  }
1410 
1411  /* Only one PTE to handle for now */
1412  PteCount = 1;
1413  ProcessedPtes = 0;
1414 
1415  /* Lock the PFN database */
1416  LockIrql = MiAcquirePfnLock();
1417 
1418  /* We only handle the valid path */
1419  ASSERT(SuperProtoPte->u.Hard.Valid == 1);
1420 
1421  /* Capture the PTE */
1422  TempPte = *PointerProtoPte;
1423 
1424  /* Loop to handle future case of clustered faults */
1425  while (TRUE)
1426  {
1427  /* For our current usage, this should be true */
1428  if (TempPte.u.Hard.Valid == 1)
1429  {
1430  /* Bump the share count on the PTE */
1431  PageFrameIndex = PFN_FROM_PTE(&TempPte);
1432  Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);
1433  Pfn1->u2.ShareCount++;
1434  }
1435  else if ((TempPte.u.Soft.Prototype == 0) &&
1436  (TempPte.u.Soft.Transition == 1))
1437  {
1438  /* This is a standby page, bring it back from the cache */
1439  PageFrameIndex = TempPte.u.Trans.PageFrameNumber;
1440  DPRINT("oooh, shiny, a soft fault! 0x%lx\n", PageFrameIndex);
1441  Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);
1443 
1444  /* Should not yet happen in ReactOS */
1445  ASSERT(Pfn1->u3.e1.ReadInProgress == 0);
1446  ASSERT(Pfn1->u4.InPageError == 0);
1447 
1448  /* Get the page */
1449  MiUnlinkPageFromList(Pfn1);
1450 
1451  /* Bump its reference count */
1452  ASSERT(Pfn1->u2.ShareCount == 0);
1453  InterlockedIncrement16((PSHORT)&Pfn1->u3.e2.ReferenceCount);
1454  Pfn1->u2.ShareCount++;
1455 
1456  /* Make it valid again */
1457  /* This looks like another macro.... */
1458  Pfn1->u3.e1.PageLocation = ActiveAndValid;
1459  ASSERT(PointerProtoPte->u.Hard.Valid == 0);
1460  ASSERT(PointerProtoPte->u.Trans.Prototype == 0);
1461  ASSERT(PointerProtoPte->u.Trans.Transition == 1);
1462  TempPte.u.Long = (PointerProtoPte->u.Long & ~0xFFF) |
1463  MmProtectToPteMask[PointerProtoPte->u.Trans.Protection];
1464  TempPte.u.Hard.Valid = 1;
1466 
1467  /* Is the PTE writeable? */
1468  if ((Pfn1->u3.e1.Modified) &&
1471  {
1472  /* Make it dirty */
1474  }
1475  else
1476  {
1477  /* Make it clean */
1479  }
1480 
1481  /* Write the valid PTE */
1482  MI_WRITE_VALID_PTE(PointerProtoPte, TempPte);
1483  ASSERT(PointerPte->u.Hard.Valid == 0);
1484  }
1485  else
1486  {
1487  /* Page is invalid, get out of the loop */
1488  break;
1489  }
1490 
1491  /* One more done, was it the last? */
1492  if (++ProcessedPtes == PteCount)
1493  {
1494  /* Complete the fault */
1496  Address,
1497  PointerPte,
1498  PointerProtoPte,
1499  LockIrql,
1500  &OutPfn);
1501 
1502  /* THIS RELEASES THE PFN LOCK! */
1503  break;
1504  }
1505 
1506  /* No clustered faults yet */
1507  ASSERT(FALSE);
1508  }
1509 
1510  /* Did we resolve the fault? */
1511  if (ProcessedPtes)
1512  {
1513  /* Bump the transition count */
1514  InterlockedExchangeAddSizeT(&KeGetCurrentPrcb()->MmTransitionCount, ProcessedPtes);
1515  ProcessedPtes--;
1516 
1517  /* Loop all the processing we did */
1518  ASSERT(ProcessedPtes == 0);
1519 
1520  /* Complete this as a transition fault */
1522  ASSERT(OldIrql <= APC_LEVEL);
1525  }
1526 
1527  /* We did not -- PFN lock is still held, prepare to resolve prototype PTE fault */
1528  OutPfn = MI_PFN_ELEMENT(SuperProtoPte->u.Hard.PageFrameNumber);
1530  ASSERT(OutPfn->u3.e2.ReferenceCount > 1);
1531  ASSERT(PointerPte->u.Hard.Valid == 0);
1532 
1533  /* Resolve the fault -- this will release the PFN lock */
1535  Address,
1536  PointerPte,
1537  PointerProtoPte,
1538  &OutPfn,
1539  NULL,
1540  NULL,
1541  Process,
1542  LockIrql,
1543  TrapInformation);
1544  //ASSERT(Status != STATUS_ISSUE_PAGING_IO);
1545  //ASSERT(Status != STATUS_REFAULT);
1546  //ASSERT(Status != STATUS_PTE_CHANGED);
1547 
1548  /* Did the routine clean out the PFN or should we? */
1549  if (OutPfn)
1550  {
1551  /* We had a locked PFN, so acquire the PFN lock to dereference it */
1552  ASSERT(PointerProtoPte != NULL);
1553  OldIrql = MiAcquirePfnLock();
1554 
1555  /* Dereference the locked PFN */
1557  ASSERT(OutPfn->u3.e2.ReferenceCount >= 1);
1558 
1559  /* And now release the lock */
1560  MiReleasePfnLock(OldIrql);
1561  }
1562 
1563  /* Complete this as a transition fault */
1565  ASSERT(OldIrql <= APC_LEVEL);
1567  return Status;
1568  }
1569  }
1570 
1571  /* Is this a transition PTE */
1572  if (TempPte.u.Soft.Transition)
1573  {
1574  PKEVENT* InPageBlock = NULL;
1575  PKEVENT PreviousPageEvent;
1576  KEVENT CurrentPageEvent;
1577 
1578  /* Lock the PFN database */
1579  LockIrql = MiAcquirePfnLock();
1580 
1581  /* Resolve */
1582  Status = MiResolveTransitionFault(!MI_IS_NOT_PRESENT_FAULT(FaultCode), Address, PointerPte, Process, LockIrql, &InPageBlock);
1583 
1585 
1586  if (InPageBlock != NULL)
1587  {
1588  /* Another thread is reading or writing this page. Put us into the waiting queue. */
1589  KeInitializeEvent(&CurrentPageEvent, NotificationEvent, FALSE);
1590  PreviousPageEvent = *InPageBlock;
1591  *InPageBlock = &CurrentPageEvent;
1592  }
1593 
1594  /* And now release the lock and leave*/
1595  MiReleasePfnLock(LockIrql);
1596 
1597  if (InPageBlock != NULL)
1598  {
1599  KeWaitForSingleObject(&CurrentPageEvent, WrPageIn, KernelMode, FALSE, NULL);
1600 
1601  /* Let's the chain go on */
1602  if (PreviousPageEvent)
1603  {
1604  KeSetEvent(PreviousPageEvent, IO_NO_INCREMENT, FALSE);
1605  }
1606  }
1607 
1609  ASSERT(OldIrql <= APC_LEVEL);
1611  return Status;
1612  }
1613 
1614  /* Should we page the data back in ? */
1615  if (TempPte.u.Soft.PageFileHigh != 0)
1616  {
1617  /* Lock the PFN database */
1618  LockIrql = MiAcquirePfnLock();
1619 
1620  /* Resolve */
1621  Status = MiResolvePageFileFault(!MI_IS_NOT_PRESENT_FAULT(FaultCode), Address, PointerPte, Process, &LockIrql);
1622 
1623  /* And now release the lock and leave*/
1624  MiReleasePfnLock(LockIrql);
1625 
1627  ASSERT(OldIrql <= APC_LEVEL);
1629  return Status;
1630  }
1631 
1632  //
1633  // The PTE must be invalid but not completely empty. It must also not be a
1634  // prototype a transition or a paged-out PTE as those scenarii should've been handled above.
1635  // These are all Windows checks
1636  //
1637  ASSERT(TempPte.u.Hard.Valid == 0);
1638  ASSERT(TempPte.u.Soft.Prototype == 0);
1639  ASSERT(TempPte.u.Soft.Transition == 0);
1640  ASSERT(TempPte.u.Soft.PageFileHigh == 0);
1641  ASSERT(TempPte.u.Long != 0);
1642 
1643  //
1644  // If we got this far, the PTE can only be a demand zero PTE, which is what
1645  // we want. Go handle it!
1646  //
1648  PointerPte,
1649  (ULONG)TempPte.u.Soft.Protection,
1650  Process,
1651  MM_NOIRQL);
1653  if (NT_SUCCESS(Status))
1654  {
1655 #if MI_TRACE_PFNS
1656  /* Update debug info */
1657  if (TrapInformation)
1658  MiGetPfnEntry(PointerPte->u.Hard.PageFrameNumber)->CallSite = (PVOID)((PKTRAP_FRAME)TrapInformation)->Eip;
1659  else
1660  MiGetPfnEntry(PointerPte->u.Hard.PageFrameNumber)->CallSite = _ReturnAddress();
1661 #endif
1662 
1663  //
1664  // Make sure we're returning in a sane state and pass the status down
1665  //
1668  return Status;
1669  }
1670 
1671  //
1672  // Generate an access fault
1673  //
1674  return STATUS_ACCESS_VIOLATION;
1675 }
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
#define MM_HIGHEST_USER_ADDRESS
Definition: armddk.h:17
#define MI_IS_NOT_PRESENT_FAULT(FaultCode)
Definition: mm.h:121
BOOLEAN NTAPI KeAreAllApcsDisabled(VOID)
Definition: apc.c:985
VOID NTAPI MiUnlinkPageFromList(IN PMMPFN Pfn)
Definition: pfnlist.c:265
FORCEINLINE VOID MiDereferencePfnAndDropLockCount(IN PMMPFN Pfn1)
Definition: miarm.h:1620
#define MI_MAKE_ACCESSED_PAGE(x)
Definition: mm.h:100
signed short * PSHORT
Definition: retypes.h:6
ULONG PFN_COUNT
Definition: mmtypes.h:102
#define TRUE
Definition: types.h:120
static NTSTATUS NTAPI MiResolvePageFileFault(_In_ BOOLEAN StoreInstruction, _In_ PVOID FaultingAddress, _In_ PMMPTE PointerPte, _In_ PEPROCESS CurrentProcess, _Inout_ KIRQL *OldIrql)
Definition: pagfault.c:890
USHORT ReadInProgress
Definition: mm.h:361
LONG NTSTATUS
Definition: precomp.h:26
FORCEINLINE struct _KPRCB * KeGetCurrentPrcb(VOID)
Definition: ketypes.h:1080
#define MI_PTE_LOOKUP_NEEDED
Definition: miarm.h:246
USHORT Modified
Definition: mm.h:360
#define MI_IS_PAGE_COPY_ON_WRITE(x)
Definition: mm.h:110
LONG NTAPI KeSetEvent(IN PKEVENT Event, IN KPRIORITY Increment, IN BOOLEAN Wait)
Definition: eventobj.c:159
NTSTATUS NTAPI KeWaitForSingleObject(IN PVOID Object, IN KWAIT_REASON WaitReason, IN KPROCESSOR_MODE WaitMode, IN BOOLEAN Alertable, IN PLARGE_INTEGER Timeout OPTIONAL)
Definition: wait.c:416
FORCEINLINE VOID MiReferenceUsedPageAndBumpLockCount(IN PMMPFN Pfn1)
Definition: miarm.h:1747
USHORT PageLocation
Definition: mm.h:365
struct _MMPFN::@1751::@1757 e2
UCHAR KIRQL
Definition: env_spec_w32.h:591
MMPFNENTRY e1
Definition: mm.h:397
#define MI_MAKE_DIRTY_PAGE(x)
Definition: mm.h:98
#define MiAddressToPte(x)
Definition: mmx86.c:19
#define MM_NOIRQL
Definition: mm.h:70
ULONG PFN_NUMBER
Definition: ke.h:9
const ULONG MmProtectToPteMask[32]
Definition: page.c:22
#define FALSE
Definition: types.h:117
FORCEINLINE VOID MI_WRITE_VALID_PTE(IN PMMPTE PointerPte, IN MMPTE TempPte)
Definition: miarm.h:964
#define MI_MAKE_CLEAN_PAGE(x)
Definition: mm.h:99
ULONG_PTR ShareCount
Definition: mm.h:390
#define STATUS_PAGE_FAULT_TRANSITION
Definition: ntstatus.h:94
static WCHAR Address[46]
Definition: ping.c:68
void * PVOID
Definition: retypes.h:9
Status
Definition: gdiplustypes.h:24
union _MMPFN::@1751 u3
#define ASSERT(a)
Definition: mode.c:44
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
ULONG64 Valid
Definition: mmtypes.h:150
union _MMPFN::@1754 u4
#define InterlockedIncrement16
Definition: interlocked.h:206
HARDWARE_PTE_ARMV6 TempPte
Definition: winldr.c:76
#define InterlockedExchangeAddSizeT(a, b)
Definition: interlocked.h:196
FORCEINLINE PMMPFN MI_PFN_ELEMENT(IN PFN_NUMBER Pfn)
Definition: miarm.h:1579
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:792
Definition: mm.h:373
#define MI_IS_PAGE_WRITEABLE(x)
Definition: mm.h:106
FORCEINLINE PMMPFN MiGetPfnEntry(IN PFN_NUMBER Pfn)
Definition: mm.h:1020
union _MMPTE::@2282 u
MMPTE_HARDWARE Hard
Definition: mmtypes.h:217
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define STATUS_ACCESS_VIOLATION
Definition: ntstatus.h:242
static NTSTATUS NTAPI MiResolveTransitionFault(IN BOOLEAN StoreInstruction, IN PVOID FaultingAddress, IN PMMPTE PointerPte, IN PEPROCESS CurrentProcess, IN KIRQL OldIrql, OUT PKEVENT **InPageBlock)
Definition: pagfault.c:978
static NTSTATUS NTAPI MiCompleteProtoPteFault(IN BOOLEAN StoreInstruction, IN PVOID Address, IN PMMPTE PointerPte, IN PMMPTE PointerProtoPte, IN KIRQL OldIrql, IN PMMPFN *LockedProtoPfn)
Definition: pagfault.c:765
#define NULL
Definition: types.h:112
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:219
void * _ReturnAddress(void)
unsigned int ULONG
Definition: retypes.h:1
#define IO_NO_INCREMENT
Definition: iotypes.h:598
static NTSTATUS NTAPI MiResolveProtoPteFault(IN BOOLEAN StoreInstruction, IN PVOID Address, IN PMMPTE PointerPte, IN PMMPTE PointerProtoPte, IN OUT PMMPFN *OutPfn, OUT PVOID *PageFileData, OUT PMMPTE PteValue, IN PEPROCESS Process, IN KIRQL OldIrql, IN PVOID TrapInformation)
Definition: pagfault.c:1110
ULONG64 PageFrameNumber
Definition: mmtypes.h:171
ULONG_PTR InPageError
Definition: mm.h:419
#define STATUS_SUCCESS
Definition: shellext.h:65
#define DPRINT
Definition: sndvol32.h:71
static NTSTATUS NTAPI MiResolveDemandZeroFault(IN PVOID Address, IN PMMPTE PointerPte, IN ULONG Protection, IN PEPROCESS Process, IN KIRQL OldIrql)
Definition: pagfault.c:595
union _MMPFN::@1750 u2
FORCEINLINE BOOLEAN MI_IS_PHYSICAL_ADDRESS(IN PVOID Address)
Definition: miarm.h:950
#define APC_LEVEL
Definition: env_spec_w32.h:695
#define PFN_FROM_PTE(v)
Definition: mm.h:92
#define MmSystemRangeStart
Definition: mm.h:32
ULONG PageFrameNumber
Definition: mmtypes.h:109

Referenced by MmArmAccessFault().

◆ MiIsAccessAllowed()

FORCEINLINE BOOLEAN MiIsAccessAllowed ( _In_ ULONG  ProtectionMask,
_In_ BOOLEAN  Write,
_In_ BOOLEAN  Execute 
)

Definition at line 138 of file pagfault.c.

142 {
143  #define _BYTE_MASK(Bit0, Bit1, Bit2, Bit3, Bit4, Bit5, Bit6, Bit7) \
144  (Bit0) | ((Bit1) << 1) | ((Bit2) << 2) | ((Bit3) << 3) | \
145  ((Bit4) << 4) | ((Bit5) << 5) | ((Bit6) << 6) | ((Bit7) << 7)
146  static const UCHAR AccessAllowedMask[2][2] =
147  {
148  { // Protect 0 1 2 3 4 5 6 7
149  _BYTE_MASK(0, 1, 1, 1, 1, 1, 1, 1), // READ
150  _BYTE_MASK(0, 0, 1, 1, 0, 0, 1, 1), // EXECUTE READ
151  },
152  {
153  _BYTE_MASK(0, 0, 0, 0, 1, 1, 1, 1), // WRITE
154  _BYTE_MASK(0, 0, 0, 0, 0, 0, 1, 1), // EXECUTE WRITE
155  }
156  };
157 
158  /* We want only the lower access bits */
159  ProtectionMask &= MM_PROTECT_ACCESS;
160 
161  /* Look it up in the table */
162  return (AccessAllowedMask[Write != 0][Execute != 0] >> ProtectionMask) & 1;
163 }
#define _BYTE_MASK(Bit0, Bit1, Bit2, Bit3, Bit4, Bit5, Bit6, Bit7)
static BOOL Write(PBYTE Address, PBYTE Data, SIZE_T Size)
Definition: vmhorizon.c:15
#define MM_PROTECT_ACCESS
Definition: miarm.h:51
return pDmaTrans Execute(Context)
unsigned char UCHAR
Definition: xmlstorage.h:181

Referenced by MiAccessCheck().

◆ MiResolveDemandZeroFault()

static NTSTATUS NTAPI MiResolveDemandZeroFault ( IN PVOID  Address,
IN PMMPTE  PointerPte,
IN ULONG  Protection,
IN PEPROCESS  Process,
IN KIRQL  OldIrql 
)
static

Definition at line 595 of file pagfault.c.

600 {
601  PFN_NUMBER PageFrameNumber = 0;
602  MMPTE TempPte;
603  BOOLEAN NeedZero = FALSE, HaveLock = FALSE;
604  ULONG Color;
605  PMMPFN Pfn1;
606  DPRINT("ARM3 Demand Zero Page Fault Handler for address: %p in process: %p\n",
607  Address,
608  Process);
609 
610  /* Must currently only be called by paging path */
611  if ((Process > HYDRA_PROCESS) && (OldIrql == MM_NOIRQL))
612  {
613  /* Sanity check */
614  ASSERT(MI_IS_PAGE_TABLE_ADDRESS(PointerPte));
615 
616  /* No forking yet */
617  ASSERT(Process->ForkInProgress == NULL);
618 
619  /* Get process color */
621  ASSERT(Color != 0xFFFFFFFF);
622 
623  /* We'll need a zero page */
624  NeedZero = TRUE;
625  }
626  else
627  {
628  /* Check if we need a zero page */
629  NeedZero = (OldIrql != MM_NOIRQL);
630 
631  /* Session-backed image views must be zeroed */
632  if ((Process == HYDRA_PROCESS) &&
635  {
636  NeedZero = TRUE;
637  }
638 
639  /* Hardcode unknown color */
640  Color = 0xFFFFFFFF;
641  }
642 
643  /* Check if the PFN database should be acquired */
644  if (OldIrql == MM_NOIRQL)
645  {
646  /* Acquire it and remember we should release it after */
647  OldIrql = MiAcquirePfnLock();
648  HaveLock = TRUE;
649  }
650 
651  /* We either manually locked the PFN DB, or already came with it locked */
653  ASSERT(PointerPte->u.Hard.Valid == 0);
654 
655  /* Assert we have enough pages */
656  ASSERT(MmAvailablePages >= 32);
657 
658 #if MI_TRACE_PFNS
659  if (UserPdeFault) MI_SET_USAGE(MI_USAGE_PAGE_TABLE);
660  if (!UserPdeFault) MI_SET_USAGE(MI_USAGE_DEMAND_ZERO);
661 #endif
662  if (Process == HYDRA_PROCESS) MI_SET_PROCESS2("Hydra");
663  else if (Process) MI_SET_PROCESS2(Process->ImageFileName);
664  else MI_SET_PROCESS2("Kernel Demand 0");
665 
666  /* Do we need a zero page? */
667  if (Color != 0xFFFFFFFF)
668  {
669  /* Try to get one, if we couldn't grab a free page and zero it */
670  PageFrameNumber = MiRemoveZeroPageSafe(Color);
671  if (!PageFrameNumber)
672  {
673  /* We'll need a free page and zero it manually */
674  PageFrameNumber = MiRemoveAnyPage(Color);
675  NeedZero = TRUE;
676  }
677  else
678  {
679  /* Page guaranteed to be zero-filled */
680  NeedZero = FALSE;
681  }
682  }
683  else
684  {
685  /* Get a color, and see if we should grab a zero or non-zero page */
687  if (!NeedZero)
688  {
689  /* Process or system doesn't want a zero page, grab anything */
690  PageFrameNumber = MiRemoveAnyPage(Color);
691  }
692  else
693  {
694  /* System wants a zero page, obtain one */
695  PageFrameNumber = MiRemoveZeroPage(Color);
696  /* No need to zero-fill it */
697  NeedZero = FALSE;
698  }
699  }
700 
701  /* Initialize it */
702  MiInitializePfn(PageFrameNumber, PointerPte, TRUE);
703 
704  /* Increment demand zero faults */
705  KeGetCurrentPrcb()->MmDemandZeroCount++;
706 
707  /* Do we have the lock? */
708  if (HaveLock)
709  {
710  /* Release it */
711  MiReleasePfnLock(OldIrql);
712 
713  /* Update performance counters */
714  if (Process > HYDRA_PROCESS) Process->NumberOfPrivatePages++;
715  }
716 
717  /* Zero the page if need be */
718  if (NeedZero) MiZeroPfn(PageFrameNumber);
719 
720  /* Fault on user PDE, or fault on user PTE? */
721  if (PointerPte <= MiHighestUserPte)
722  {
723  /* User fault, build a user PTE */
725  PointerPte,
726  Protection,
727  PageFrameNumber);
728  }
729  else
730  {
731  /* This is a user-mode PDE, create a kernel PTE for it */
733  PointerPte,
734  Protection,
735  PageFrameNumber);
736  }
737 
738  /* Set it dirty if it's a writable page */
740 
741  /* Write it */
742  MI_WRITE_VALID_PTE(PointerPte, TempPte);
743 
744  /* Did we manually acquire the lock */
745  if (HaveLock)
746  {
747  /* Get the PFN entry */
748  Pfn1 = MI_PFN_ELEMENT(PageFrameNumber);
749 
750  /* Windows does these sanity checks */
751  ASSERT(Pfn1->u1.Event == 0);
752  ASSERT(Pfn1->u3.e1.PrototypePte == 0);
753  }
754 
755  //
756  // It's all good now
757  //
758  DPRINT("Demand zero page has now been paged in\n");
760 }
#define MI_IS_PAGE_TABLE_ADDRESS(Address)
Definition: miarm.h:177
VOID NTAPI MiInitializePfn(IN PFN_NUMBER PageFrameIndex, IN PMMPTE PointerPte, IN BOOLEAN Modified)
Definition: pfnlist.c:962
#define MI_ASSERT_PFN_LOCK_HELD()
Definition: mm.h:1016
#define TRUE
Definition: types.h:120
#define HYDRA_PROCESS
Definition: pagfault.c:20
FORCEINLINE struct _KPRCB * KeGetCurrentPrcb(VOID)
Definition: ketypes.h:1080
#define MI_GET_NEXT_COLOR()
Definition: miarm.h:237
PVOID MiSessionSpaceWs
Definition: mminit.c:130
PFN_NUMBER MmAvailablePages
Definition: freelist.c:26
struct Color Color
PFN_NUMBER NTAPI MiRemoveZeroPage(IN ULONG Color)
Definition: pfnlist.c:533
USHORT PrototypePte
Definition: mm.h:363
MMPFNENTRY e1
Definition: mm.h:397
#define MI_MAKE_DIRTY_PAGE(x)
Definition: mm.h:98
#define MM_NOIRQL
Definition: mm.h:70
ULONG PFN_NUMBER
Definition: ke.h:9
#define FALSE
Definition: types.h:117
FORCEINLINE VOID MI_WRITE_VALID_PTE(IN PMMPTE PointerPte, IN MMPTE TempPte)
Definition: miarm.h:964
PKEVENT Event
Definition: mm.h:379
#define MI_SET_PROCESS2(x)
Definition: mm.h:319
FORCEINLINE PFN_NUMBER MiRemoveZeroPageSafe(IN ULONG Color)
Definition: miarm.h:2420
unsigned char BOOLEAN
static WCHAR Address[46]
Definition: ping.c:68
#define MI_SET_USAGE(x)
Definition: mm.h:317
union _MMPFN::@1751 u3
#define ASSERT(a)
Definition: mode.c:44
#define MI_GET_NEXT_PROCESS_COLOR(x)
Definition: miarm.h:238
VOID NTAPI MiZeroPfn(IN PFN_NUMBER PageFrameNumber)
Definition: pagfault.c:483
HARDWARE_PTE_ARMV6 TempPte
Definition: winldr.c:76
FORCEINLINE PMMPFN MI_PFN_ELEMENT(IN PFN_NUMBER Pfn)
Definition: miarm.h:1579
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:792
Definition: mm.h:373
#define MI_IS_PAGE_WRITEABLE(x)
Definition: mm.h:106
FORCEINLINE VOID MI_MAKE_HARDWARE_PTE_USER(IN PMMPTE NewPte, IN PMMPTE MappingPte, IN ULONG_PTR ProtectionMask, IN PFN_NUMBER PageFrameNumber)
Definition: miarm.h:832
PFN_NUMBER NTAPI MiRemoveAnyPage(IN ULONG Color)
Definition: pfnlist.c:477
PVOID MiSessionViewStart
Definition: init.c:30
#define NULL
Definition: types.h:112
union _MMPFN::@1749 u1
#define MI_IS_SESSION_IMAGE_ADDRESS(Address)
Definition: miarm.h:168
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:219
unsigned int ULONG
Definition: retypes.h:1
PMMPTE MiHighestUserPte
Definition: mminit.c:233
#define DPRINT
Definition: sndvol32.h:71
#define STATUS_PAGE_FAULT_DEMAND_ZERO
Definition: ntstatus.h:95
FORCEINLINE VOID MI_MAKE_HARDWARE_PTE(IN PMMPTE NewPte, IN PMMPTE MappingPte, IN ULONG_PTR ProtectionMask, IN PFN_NUMBER PageFrameNumber)
Definition: miarm.h:812

Referenced by MiDispatchFault(), MiResolveProtoPteFault(), and MmArmAccessFault().

◆ MiResolvePageFileFault()

static NTSTATUS NTAPI MiResolvePageFileFault ( _In_ BOOLEAN  StoreInstruction,
_In_ PVOID  FaultingAddress,
_In_ PMMPTE  PointerPte,
_In_ PEPROCESS  CurrentProcess,
_Inout_ KIRQL OldIrql 
)
static

Definition at line 890 of file pagfault.c.

895 {
896  ULONG Color;
899  MMPTE TempPte = *PointerPte;
900  PMMPFN Pfn1;
901  ULONG PageFileIndex = TempPte.u.Soft.PageFileLow;
902  ULONG_PTR PageFileOffset = TempPte.u.Soft.PageFileHigh;
903  ULONG Protection = TempPte.u.Soft.Protection;
904 
905  /* Things we don't support yet */
907  ASSERT(*OldIrql != MM_NOIRQL);
908 
911 
912  /* We must hold the PFN lock */
914 
915  /* Some sanity checks */
916  ASSERT(TempPte.u.Hard.Valid == 0);
917  ASSERT(TempPte.u.Soft.PageFileHigh != 0);
918  ASSERT(TempPte.u.Soft.PageFileHigh != MI_PTE_LOOKUP_NEEDED);
919 
920  /* Get any page, it will be overwritten */
923 
924  /* Initialize this PFN */
925  MiInitializePfn(Page, PointerPte, StoreInstruction);
926 
927  /* Sets the PFN as being in IO operation */
928  Pfn1 = MI_PFN_ELEMENT(Page);
929  ASSERT(Pfn1->u1.Event == NULL);
930  ASSERT(Pfn1->u3.e1.ReadInProgress == 0);
931  ASSERT(Pfn1->u3.e1.WriteInProgress == 0);
932  Pfn1->u3.e1.ReadInProgress = 1;
933 
934  /* We must write the PTE now as the PFN lock will be released while performing the IO operation */
935  MI_MAKE_TRANSITION_PTE(&TempPte, Page, Protection);
936 
937  MI_WRITE_INVALID_PTE(PointerPte, TempPte);
938 
939  /* Release the PFN lock while we proceed */
940  MiReleasePfnLock(*OldIrql);
941 
942  /* Do the paging IO */
943  Status = MiReadPageFile(Page, PageFileIndex, PageFileOffset);
944 
945  /* Lock the PFN database again */
946  *OldIrql = MiAcquirePfnLock();
947 
948  /* Nobody should have changed that while we were not looking */
949  ASSERT(Pfn1->u3.e1.ReadInProgress == 1);
950  ASSERT(Pfn1->u3.e1.WriteInProgress == 0);
951 
952  if (!NT_SUCCESS(Status))
953  {
954  /* Malheur! */
955  ASSERT(FALSE);
956  Pfn1->u4.InPageError = 1;
957  Pfn1->u1.ReadStatus = Status;
958  }
959 
960  /* And the PTE can finally be valid */
961  MI_MAKE_HARDWARE_PTE(&TempPte, PointerPte, Protection, Page);
962  MI_WRITE_VALID_PTE(PointerPte, TempPte);
963 
964  Pfn1->u3.e1.ReadInProgress = 0;
965  /* Did someone start to wait on us while we proceeded ? */
966  if (Pfn1->u1.Event)
967  {
968  /* Tell them we're done */
970  }
971 
972  return Status;
973 }
VOID NTAPI MiInitializePfn(IN PFN_NUMBER PageFrameIndex, IN PMMPTE PointerPte, IN BOOLEAN Modified)
Definition: pfnlist.c:962
#define MI_ASSERT_PFN_LOCK_HELD()
Definition: mm.h:1016
USHORT ReadInProgress
Definition: mm.h:361
#define HYDRA_PROCESS
Definition: pagfault.c:20
LONG NTSTATUS
Definition: precomp.h:26
NTSTATUS NTAPI MiReadPageFile(_In_ PFN_NUMBER Page, _In_ ULONG PageFileIndex, _In_ ULONG_PTR PageFileOffset)
Definition: pagefile.c:194
#define MI_PTE_LOOKUP_NEEDED
Definition: miarm.h:246
LONG NTAPI KeSetEvent(IN PKEVENT Event, IN KPRIORITY Increment, IN BOOLEAN Wait)
Definition: eventobj.c:159
struct Color Color
uint32_t ULONG_PTR
Definition: typedefs.h:65
MMPFNENTRY e1
Definition: mm.h:397
#define MM_NOIRQL
Definition: mm.h:70
ULONG PFN_NUMBER
Definition: ke.h:9
#define FALSE
Definition: types.h:117
FORCEINLINE VOID MI_WRITE_VALID_PTE(IN PMMPTE PointerPte, IN MMPTE TempPte)
Definition: miarm.h:964
#define MI_SET_PROCESS(x)
Definition: mm.h:318
PKEVENT Event
Definition: mm.h:379
FORCEINLINE VOID MI_MAKE_TRANSITION_PTE(_Out_ PMMPTE NewPte, _In_ PFN_NUMBER Page, _In_ ULONG Protection)
Definition: miarm.h:934
PFN_NUMBER Page
Definition: section.c:4924
#define MI_SET_USAGE(x)
Definition: mm.h:317
USHORT WriteInProgress
Definition: mm.h:362
Status
Definition: gdiplustypes.h:24
union _MMPFN::@1751 u3
ULONG CurrentProcess
Definition: shell.c:125
#define ASSERT(a)
Definition: mode.c:44
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define MI_GET_NEXT_PROCESS_COLOR(x)
Definition: miarm.h:238
union _MMPFN::@1754 u4
HARDWARE_PTE_ARMV6 TempPte
Definition: winldr.c:76
FORCEINLINE PMMPFN MI_PFN_ELEMENT(IN PFN_NUMBER Pfn)
Definition: miarm.h:1579
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:792
Definition: mm.h:373
NTSTATUS ReadStatus
Definition: mm.h:380
PFN_NUMBER NTAPI MiRemoveAnyPage(IN ULONG Color)
Definition: pfnlist.c:477
FORCEINLINE VOID MI_WRITE_INVALID_PTE(IN PMMPTE PointerPte, IN MMPTE InvalidPte)
Definition: miarm.h:997
#define NULL
Definition: types.h:112
union _MMPFN::@1749 u1
unsigned int ULONG
Definition: retypes.h:1
#define IO_NO_INCREMENT
Definition: iotypes.h:598
ULONG_PTR InPageError
Definition: mm.h:419
FORCEINLINE VOID MI_MAKE_HARDWARE_PTE(IN PMMPTE NewPte, IN PMMPTE MappingPte, IN ULONG_PTR ProtectionMask, IN PFN_NUMBER PageFrameNumber)
Definition: miarm.h:812

Referenced by MiDispatchFault().

◆ MiResolveProtoPteFault()

static NTSTATUS NTAPI MiResolveProtoPteFault ( IN BOOLEAN  StoreInstruction,
IN PVOID  Address,
IN PMMPTE  PointerPte,
IN PMMPTE  PointerProtoPte,
IN OUT PMMPFN OutPfn,
OUT PVOID PageFileData,
OUT PMMPTE  PteValue,
IN PEPROCESS  Process,
IN KIRQL  OldIrql,
IN PVOID  TrapInformation 
)
static

Definition at line 1110 of file pagfault.c.

1120 {
1121  MMPTE TempPte, PteContents;
1122  PMMPFN Pfn1;
1123  PFN_NUMBER PageFrameIndex;
1124  NTSTATUS Status;
1125  PKEVENT* InPageBlock = NULL;
1126  ULONG Protection;
1127 
1128  /* Must be called with an invalid, prototype PTE, with the PFN lock held */
1130  ASSERT(PointerPte->u.Hard.Valid == 0);
1131  ASSERT(PointerPte->u.Soft.Prototype == 1);
1132 
1133  /* Read the prototype PTE and check if it's valid */
1134  TempPte = *PointerProtoPte;
1135  if (TempPte.u.Hard.Valid == 1)
1136  {
1137  /* One more user of this mapped page */
1138  PageFrameIndex = PFN_FROM_PTE(&TempPte);
1139  Pfn1 = MiGetPfnEntry(PageFrameIndex);
1140  Pfn1->u2.ShareCount++;
1141 
1142  /* Call it a transition */
1143  InterlockedIncrement(&KeGetCurrentPrcb()->MmTransitionCount);
1144 
1145  /* Complete the prototype PTE fault -- this will release the PFN lock */
1146  return MiCompleteProtoPteFault(StoreInstruction,
1147  Address,
1148  PointerPte,
1149  PointerProtoPte,
1150  OldIrql,
1151  OutPfn);
1152  }
1153 
1154  /* Make sure there's some protection mask */
1155  if (TempPte.u.Long == 0)
1156  {
1157  /* Release the lock */
1158  DPRINT1("Access on reserved section?\n");
1159  MiReleasePfnLock(OldIrql);
1160  return STATUS_ACCESS_VIOLATION;
1161  }
1162 
1163  /* There is no such thing as a decommitted prototype PTE */
1164  ASSERT(TempPte.u.Long != MmDecommittedPte.u.Long);
1165 
1166  /* Check for access rights on the PTE proper */
1167  PteContents = *PointerPte;
1168  if (PteContents.u.Soft.PageFileHigh != MI_PTE_LOOKUP_NEEDED)
1169  {
1170  if (!PteContents.u.Proto.ReadOnly)
1171  {
1172  Protection = TempPte.u.Soft.Protection;
1173  }
1174  else
1175  {
1176  Protection = MM_READONLY;
1177  }
1178  /* Check for page acess in software */
1179  Status = MiAccessCheck(PointerProtoPte,
1180  StoreInstruction,
1181  KernelMode,
1182  TempPte.u.Soft.Protection,
1183  TrapInformation,
1184  TRUE);
1186  }
1187  else
1188  {
1189  Protection = PteContents.u.Soft.Protection;
1190  }
1191 
1192  /* Check for writing copy on write page */
1193  if (((Protection & MM_WRITECOPY) == MM_WRITECOPY) && StoreInstruction)
1194  {
1195  PFN_NUMBER PageFrameIndex, ProtoPageFrameIndex;
1196  ULONG Color;
1197 
1198  /* Resolve the proto fault as if it was a read operation */
1200  Address,
1201  PointerPte,
1202  PointerProtoPte,
1203  OutPfn,
1204  PageFileData,
1205  PteValue,
1206  Process,
1207  OldIrql,
1208  TrapInformation);
1209 
1210  if (!NT_SUCCESS(Status))
1211  {
1212  return Status;
1213  }
1214 
1215  /* Lock again the PFN lock, MiResolveProtoPteFault unlocked it */
1216  OldIrql = MiAcquirePfnLock();
1217 
1218  /* And re-read the proto PTE */
1219  TempPte = *PointerProtoPte;
1220  ASSERT(TempPte.u.Hard.Valid == 1);
1221  ProtoPageFrameIndex = PFN_FROM_PTE(&TempPte);
1222 
1225 
1226  /* Get a new page for the private copy */
1227  if (Process > HYDRA_PROCESS)
1229  else
1231 
1232  PageFrameIndex = MiRemoveAnyPage(Color);
1233 
1234  /* Perform the copy */
1235  MiCopyPfn(PageFrameIndex, ProtoPageFrameIndex);
1236 
1237  /* This will drop everything MiResolveProtoPteFault referenced */
1238  MiDeletePte(PointerPte, Address, Process, PointerProtoPte);
1239 
1240  /* Because now we use this */
1241  Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);
1242  MiInitializePfn(PageFrameIndex, PointerPte, TRUE);
1243 
1244  /* Fix the protection */
1245  Protection &= ~MM_WRITECOPY;
1246  Protection |= MM_READWRITE;
1248  {
1249  /* Build the user PTE */
1250  MI_MAKE_HARDWARE_PTE_USER(&PteContents, PointerPte, Protection, PageFrameIndex);
1251  }
1252  else
1253  {
1254  /* Build the kernel PTE */
1255  MI_MAKE_HARDWARE_PTE(&PteContents, PointerPte, Protection, PageFrameIndex);
1256  }
1257 
1258  /* And finally, write the valid PTE */
1259  MI_WRITE_VALID_PTE(PointerPte, PteContents);
1260 
1261  /* The caller expects us to release the PFN lock */
1262  MiReleasePfnLock(OldIrql);
1263  return Status;
1264  }
1265 
1266  /* Check for clone PTEs */
1267  if (PointerPte <= MiHighestUserPte) ASSERT(Process->CloneRoot == NULL);
1268 
1269  /* We don't support mapped files yet */
1270  ASSERT(TempPte.u.Soft.Prototype == 0);
1271 
1272  /* We might however have transition PTEs */
1273  if (TempPte.u.Soft.Transition == 1)
1274  {
1275  /* Resolve the transition fault */
1276  ASSERT(OldIrql != MM_NOIRQL);
1277  Status = MiResolveTransitionFault(StoreInstruction,
1278  Address,
1279  PointerProtoPte,
1280  Process,
1281  OldIrql,
1282  &InPageBlock);
1284  }
1285  else
1286  {
1287  /* We also don't support paged out pages */
1288  ASSERT(TempPte.u.Soft.PageFileHigh == 0);
1289 
1290  /* Resolve the demand zero fault */
1292  PointerProtoPte,
1293  (ULONG)TempPte.u.Soft.Protection,
1294  Process,
1295  OldIrql);
1296 #if MI_TRACE_PFNS
1297  /* Update debug info */
1298  if (TrapInformation)
1299  MiGetPfnEntry(PointerProtoPte->u.Hard.PageFrameNumber)->CallSite = (PVOID)((PKTRAP_FRAME)TrapInformation)->Eip;
1300  else
1301  MiGetPfnEntry(PointerProtoPte->u.Hard.PageFrameNumber)->CallSite = _ReturnAddress();
1302 #endif
1303 
1305  }
1306 
1307  /* Complete the prototype PTE fault -- this will release the PFN lock */
1308  ASSERT(PointerPte->u.Hard.Valid == 0);
1309  return MiCompleteProtoPteFault(StoreInstruction,
1310  Address,
1311  PointerPte,
1312  PointerProtoPte,
1313  OldIrql,
1314  OutPfn);
1315 }
VOID NTAPI MiInitializePfn(IN PFN_NUMBER PageFrameIndex, IN PMMPTE PointerPte, IN BOOLEAN Modified)
Definition: pfnlist.c:962
#define MI_ASSERT_PFN_LOCK_HELD()
Definition: mm.h:1016
#define TRUE
Definition: types.h:120
#define HYDRA_PROCESS
Definition: pagfault.c:20
LONG NTSTATUS
Definition: precomp.h:26
FORCEINLINE struct _KPRCB * KeGetCurrentPrcb(VOID)
Definition: ketypes.h:1080
static NTSTATUS NTAPI MiAccessCheck(IN PMMPTE PointerPte, IN BOOLEAN StoreInstruction, IN KPROCESSOR_MODE PreviousMode, IN ULONG_PTR ProtectionMask, IN PVOID TrapFrame, IN BOOLEAN LockHeld)
Definition: pagfault.c:168
VOID NTAPI MiCopyPfn(_In_ PFN_NUMBER DestPage, _In_ PFN_NUMBER SrcPage)
Definition: pagfault.c:529
#define MI_GET_NEXT_COLOR()
Definition: miarm.h:237
#define MI_PTE_LOOKUP_NEEDED
Definition: miarm.h:246
#define MM_READWRITE
Definition: bootanim.c:19
struct Color Color
VOID NTAPI MiDeletePte(IN PMMPTE PointerPte, IN PVOID VirtualAddress, IN PEPROCESS CurrentProcess, IN PMMPTE PrototypePte)
Definition: virtual.c:369
#define MM_WRITECOPY
Definition: miarm.h:48
#define MM_NOIRQL
Definition: mm.h:70
ULONG PFN_NUMBER
Definition: ke.h:9
#define FALSE
Definition: types.h:117
FORCEINLINE VOID MI_WRITE_VALID_PTE(IN PMMPTE PointerPte, IN MMPTE TempPte)
Definition: miarm.h:964
#define MI_SET_PROCESS(x)
Definition: mm.h:318
ULONG_PTR ShareCount
Definition: mm.h:390
static WCHAR Address[46]
Definition: ping.c:68
#define MI_SET_USAGE(x)
Definition: mm.h:317
ULONG64 Protection
Definition: mmtypes.h:88
void * PVOID
Definition: retypes.h:9
Status
Definition: gdiplustypes.h:24
#define ASSERT(a)
Definition: mode.c:44
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define MI_GET_NEXT_PROCESS_COLOR(x)
Definition: miarm.h:238
HARDWARE_PTE_ARMV6 TempPte
Definition: winldr.c:76
FORCEINLINE PMMPFN MI_PFN_ELEMENT(IN PFN_NUMBER Pfn)
Definition: miarm.h:1579
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:792
ULONG64 PageFileHigh
Definition: mmtypes.h:93
Definition: mm.h:373
FORCEINLINE PMMPFN MiGetPfnEntry(IN PFN_NUMBER Pfn)
Definition: mm.h:1020
union _MMPTE::@2282 u
ULONG_PTR Long
Definition: mmtypes.h:215
FORCEINLINE VOID MI_MAKE_HARDWARE_PTE_USER(IN PMMPTE NewPte, IN PMMPTE MappingPte, IN ULONG_PTR ProtectionMask, IN PFN_NUMBER PageFrameNumber)
Definition: miarm.h:832
PFN_NUMBER NTAPI MiRemoveAnyPage(IN ULONG Color)
Definition: pfnlist.c:477
#define InterlockedIncrement
Definition: armddk.h:53
#define STATUS_ACCESS_VIOLATION
Definition: ntstatus.h:242
static NTSTATUS NTAPI MiResolveTransitionFault(IN BOOLEAN StoreInstruction, IN PVOID FaultingAddress, IN PMMPTE PointerPte, IN PEPROCESS CurrentProcess, IN KIRQL OldIrql, OUT PKEVENT **InPageBlock)
Definition: pagfault.c:978
MMPTE_SOFTWARE Soft
Definition: mmtypes.h:219
static NTSTATUS NTAPI MiCompleteProtoPteFault(IN BOOLEAN StoreInstruction, IN PVOID Address, IN PMMPTE PointerPte, IN PMMPTE PointerProtoPte, IN KIRQL OldIrql, IN PMMPFN *LockedProtoPfn)
Definition: pagfault.c:765
#define NULL
Definition: types.h:112
#define DPRINT1
Definition: precomp.h:8
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:219
void * _ReturnAddress(void)
ULONG64 ReadOnly
Definition: mmtypes.h:119
unsigned int ULONG
Definition: retypes.h:1
static NTSTATUS NTAPI MiResolveProtoPteFault(IN BOOLEAN StoreInstruction, IN PVOID Address, IN PMMPTE PointerPte, IN PMMPTE PointerProtoPte, IN OUT PMMPFN *OutPfn, OUT PVOID *PageFileData, OUT PMMPTE PteValue, IN PEPROCESS Process, IN KIRQL OldIrql, IN PVOID TrapInformation)
Definition: pagfault.c:1110
#define STATUS_SUCCESS
Definition: shellext.h:65
MMPTE MmDecommittedPte
Definition: init.c:44
PMMPTE MiHighestUserPte
Definition: mminit.c:233
static NTSTATUS NTAPI MiResolveDemandZeroFault(IN PVOID Address, IN PMMPTE PointerPte, IN ULONG Protection, IN PEPROCESS Process, IN KIRQL OldIrql)
Definition: pagfault.c:595
union _MMPFN::@1750 u2
#define MM_READONLY
Definition: bootanim.c:18
#define PFN_FROM_PTE(v)
Definition: mm.h:92
#define MmSystemRangeStart
Definition: mm.h:32
MMPTE_PROTOTYPE Proto
Definition: mmtypes.h:218
FORCEINLINE VOID MI_MAKE_HARDWARE_PTE(IN PMMPTE NewPte, IN PMMPTE MappingPte, IN ULONG_PTR ProtectionMask, IN PFN_NUMBER PageFrameNumber)
Definition: miarm.h:812

Referenced by MiDispatchFault().

◆ MiResolveTransitionFault()

static NTSTATUS NTAPI MiResolveTransitionFault ( IN BOOLEAN  StoreInstruction,
IN PVOID  FaultingAddress,
IN PMMPTE  PointerPte,
IN PEPROCESS  CurrentProcess,
IN KIRQL  OldIrql,
OUT PKEVENT **  InPageBlock 
)
static

Definition at line 978 of file pagfault.c.

984 {
985  PFN_NUMBER PageFrameIndex;
986  PMMPFN Pfn1;
987  MMPTE TempPte;
988  PMMPTE PointerToPteForProtoPage;
989  DPRINT("Transition fault on 0x%p with PTE 0x%p in process %s\n",
990  FaultingAddress, PointerPte, CurrentProcess->ImageFileName);
991 
992  /* Windowss does this check */
993  ASSERT(*InPageBlock == NULL);
994 
995  /* ARM3 doesn't support this path */
997 
998  /* Capture the PTE and make sure it's in transition format */
999  TempPte = *PointerPte;
1000  ASSERT((TempPte.u.Soft.Valid == 0) &&
1001  (TempPte.u.Soft.Prototype == 0) &&
1002  (TempPte.u.Soft.Transition == 1));
1003 
1004  /* Get the PFN and the PFN entry */
1005  PageFrameIndex = TempPte.u.Trans.PageFrameNumber;
1006  DPRINT("Transition PFN: %lx\n", PageFrameIndex);
1007  Pfn1 = MiGetPfnEntry(PageFrameIndex);
1008 
1009  /* One more transition fault! */
1010  InterlockedIncrement(&KeGetCurrentPrcb()->MmTransitionCount);
1011 
1012  /* This is from ARM3 -- Windows normally handles this here */
1013  ASSERT(Pfn1->u4.InPageError == 0);
1014 
1015  /* See if we should wait before terminating the fault */
1016  if ((Pfn1->u3.e1.ReadInProgress == 1)
1017  || ((Pfn1->u3.e1.WriteInProgress == 1) && StoreInstruction))
1018  {
1019  DPRINT1("The page is currently in a page transition !\n");
1020  *InPageBlock = &Pfn1->u1.Event;
1021  if (PointerPte == Pfn1->PteAddress)
1022  {
1023  DPRINT1("And this if for this particular PTE.\n");
1024  /* The PTE will be made valid by the thread serving the fault */
1025  return STATUS_SUCCESS; // FIXME: Maybe something more descriptive
1026  }
1027  }
1028 
1029  /* Windows checks there's some free pages and this isn't an in-page error */
1030  ASSERT(MmAvailablePages > 0);
1031  ASSERT(Pfn1->u4.InPageError == 0);
1032 
1033  /* ReactOS checks for this */
1034  ASSERT(MmAvailablePages > 32);
1035 
1036  /* Was this a transition page in the valid list, or free/zero list? */
1037  if (Pfn1->u3.e1.PageLocation == ActiveAndValid)
1038  {
1039  /* All Windows does here is a bunch of sanity checks */
1040  DPRINT("Transition in active list\n");
1043  ASSERT(Pfn1->u2.ShareCount != 0);
1044  ASSERT(Pfn1->u3.e2.ReferenceCount != 0);
1045  }
1046  else
1047  {
1048  /* Otherwise, the page is removed from its list */
1049  DPRINT("Transition page in free/zero list\n");
1050  MiUnlinkPageFromList(Pfn1);
1052  }
1053 
1054  /* At this point, there should no longer be any in-page errors */
1055  ASSERT(Pfn1->u4.InPageError == 0);
1056 
1057  /* Check if this was a PFN with no more share references */
1058  if (Pfn1->u2.ShareCount == 0) MiDropLockCount(Pfn1);
1059 
1060  /* Bump the share count and make the page valid */
1061  Pfn1->u2.ShareCount++;
1062  Pfn1->u3.e1.PageLocation = ActiveAndValid;
1063 
1064  /* Prototype PTEs are in paged pool, which itself might be in transition */
1065  if (FaultingAddress >= MmSystemRangeStart)
1066  {
1067  /* Check if this is a paged pool PTE in transition state */
1068  PointerToPteForProtoPage = MiAddressToPte(PointerPte);
1069  TempPte = *PointerToPteForProtoPage;
1070  if ((TempPte.u.Hard.Valid == 0) && (TempPte.u.Soft.Transition == 1))
1071  {
1072  /* This isn't yet supported */
1073  DPRINT1("Double transition fault not yet supported\n");
1074  ASSERT(FALSE);
1075  }
1076  }
1077 
1078  /* Build the final PTE */
1079  ASSERT(PointerPte->u.Hard.Valid == 0);
1080  ASSERT(PointerPte->u.Trans.Prototype == 0);
1081  ASSERT(PointerPte->u.Trans.Transition == 1);
1082  TempPte.u.Long = (PointerPte->u.Long & ~0xFFF) |
1083  (MmProtectToPteMask[PointerPte->u.Trans.Protection]) |
1084  MiDetermineUserGlobalPteMask(PointerPte);
1085 
1086  /* Is the PTE writeable? */
1087  if ((Pfn1->u3.e1.Modified) &&
1090  {
1091  /* Make it dirty */
1093  }
1094  else
1095  {
1096  /* Make it clean */
1098  }
1099 
1100  /* Write the valid PTE */
1101  MI_WRITE_VALID_PTE(PointerPte, TempPte);
1102 
1103  /* Return success */
1105 }
VOID NTAPI MiUnlinkPageFromList(IN PMMPFN Pfn)
Definition: pfnlist.c:265
USHORT ReadInProgress
Definition: mm.h:361
FORCEINLINE struct _KPRCB * KeGetCurrentPrcb(VOID)
Definition: ketypes.h:1080
FORCEINLINE VOID MiReferenceUnusedPageAndBumpLockCount(IN PMMPFN Pfn1)
Definition: miarm.h:1792
USHORT Modified
Definition: mm.h:360
PVOID MmPagedPoolEnd
Definition: init.c:26
#define MI_IS_PAGE_COPY_ON_WRITE(x)
Definition: mm.h:110
PFN_NUMBER MmAvailablePages
Definition: freelist.c:26
USHORT PageLocation
Definition: mm.h:365
struct _MMPFN::@1751::@1757 e2
MMPFNENTRY e1
Definition: mm.h:397
#define MI_MAKE_DIRTY_PAGE(x)
Definition: mm.h:98
#define MiAddressToPte(x)
Definition: mmx86.c:19
#define MM_NOIRQL
Definition: mm.h:70
ULONG PFN_NUMBER
Definition: ke.h:9
const ULONG MmProtectToPteMask[32]
Definition: page.c:22
#define FALSE
Definition: types.h:117
FORCEINLINE VOID MI_WRITE_VALID_PTE(IN PMMPTE PointerPte, IN MMPTE TempPte)
Definition: miarm.h:964
#define MI_MAKE_CLEAN_PAGE(x)
Definition: mm.h:99
ULONG_PTR ShareCount
Definition: mm.h:390
PKEVENT Event
Definition: mm.h:379
#define STATUS_PAGE_FAULT_TRANSITION
Definition: ntstatus.h:94
FORCEINLINE ULONG_PTR MiDetermineUserGlobalPteMask(IN PVOID PointerPte)
Definition: miarm.h:741
USHORT WriteInProgress
Definition: mm.h:362
union _MMPFN::@1751 u3
ULONG CurrentProcess
Definition: shell.c:125
#define ASSERT(a)
Definition: mode.c:44
union _MMPFN::@1754 u4
HARDWARE_PTE_ARMV6 TempPte
Definition: winldr.c:76
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:792
FORCEINLINE VOID MiDropLockCount(IN PMMPFN Pfn1)
Definition: miarm.h:1590
Definition: mm.h:373
#define MI_IS_PAGE_WRITEABLE(x)
Definition: mm.h:106
FORCEINLINE PMMPFN MiGetPfnEntry(IN PFN_NUMBER Pfn)
Definition: mm.h:1020
PVOID MmPagedPoolStart
Definition: miarm.h:579
#define InterlockedIncrement
Definition: armddk.h:53
PMMPTE PteAddress
Definition: mm.h:386
#define NULL
Definition: types.h:112
union _MMPFN::@1749 u1
#define DPRINT1
Definition: precomp.h:8
ULONG_PTR InPageError
Definition: mm.h:419
#define STATUS_SUCCESS
Definition: shellext.h:65
#define DPRINT
Definition: sndvol32.h:71
union _MMPFN::@1750 u2
#define MmSystemRangeStart
Definition: mm.h:32
ULONG PageFrameNumber
Definition: mmtypes.h:109

Referenced by MiDispatchFault(), and MiResolveProtoPteFault().

◆ MiZeroPfn()

VOID NTAPI MiZeroPfn ( IN PFN_NUMBER  PageFrameNumber)

Definition at line 483 of file pagfault.c.

484 {
485  PMMPTE ZeroPte;
486  MMPTE TempPte;
487  PMMPFN Pfn1;
488  PVOID ZeroAddress;
489 
490  /* Get the PFN for this page */
491  Pfn1 = MiGetPfnEntry(PageFrameNumber);
492  ASSERT(Pfn1);
493 
494  /* Grab a system PTE we can use to zero the page */
495  ZeroPte = MiReserveSystemPtes(1, SystemPteSpace);
496  ASSERT(ZeroPte);
497 
498  /* Initialize the PTE for it */
500  TempPte.u.Hard.PageFrameNumber = PageFrameNumber;
501 
502  /* Setup caching */
503  if (Pfn1->u3.e1.CacheAttribute == MiWriteCombined)
504  {
505  /* Write combining, no caching */
508  }
509  else if (Pfn1->u3.e1.CacheAttribute == MiNonCached)
510  {
511  /* Write through, no caching */
514  }
515 
516  /* Make the system PTE valid with our PFN */
517  MI_WRITE_VALID_PTE(ZeroPte, TempPte);
518 
519  /* Get the address it maps to, and zero it out */
520  ZeroAddress = MiPteToAddress(ZeroPte);
521  KeZeroPages(ZeroAddress, PAGE_SIZE);
522 
523  /* Now get rid of it */
524  MiReleaseSystemPtes(ZeroPte, 1, SystemPteSpace);
525 }
#define MI_PAGE_WRITE_COMBINED(x)
Definition: mm.h:103
PMMPTE NTAPI MiReserveSystemPtes(IN ULONG NumberOfPtes, IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType)
Definition: syspte.c:246
MMPFNENTRY e1
Definition: mm.h:397
USHORT CacheAttribute
Definition: mm.h:367
FORCEINLINE VOID MI_WRITE_VALID_PTE(IN PMMPTE PointerPte, IN MMPTE TempPte)
Definition: miarm.h:964
VOID NTAPI MiReleaseSystemPtes(IN PMMPTE StartingPte, IN ULONG NumberOfPtes, IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType)
Definition: syspte.c:264
union _MMPFN::@1751 u3
VOID FASTCALL KeZeroPages(IN PVOID Address, IN ULONG Size)
Definition: cpu.c:56
#define ASSERT(a)
Definition: mode.c:44
HARDWARE_PTE_ARMV6 TempPte
Definition: winldr.c:76
MMPTE ValidKernelPte
Definition: init.c:29
#define MI_PAGE_WRITE_THROUGH(x)
Definition: mm.h:102
Definition: mm.h:373
#define PAGE_SIZE
Definition: env_spec_w32.h:49
FORCEINLINE PMMPFN MiGetPfnEntry(IN PFN_NUMBER Pfn)
Definition: mm.h:1020
#define MI_PAGE_DISABLE_CACHE(x)
Definition: mm.h:101
FORCEINLINE PVOID MiPteToAddress(PMMPTE PointerPte)
Definition: mm.h:208
ULONG PageFrameNumber
Definition: mmtypes.h:109

Referenced by MiResolveDemandZeroFault(), and MmArmAccessFault().

◆ MmArmAccessFault()

NTSTATUS NTAPI MmArmAccessFault ( IN ULONG  FaultCode,
IN PVOID  Address,
IN KPROCESSOR_MODE  Mode,
IN PVOID  TrapInformation 
)

Definition at line 1679 of file pagfault.c.

1683 {
1684  KIRQL OldIrql = KeGetCurrentIrql(), LockIrql;
1685  PMMPTE ProtoPte = NULL;
1686  PMMPTE PointerPte = MiAddressToPte(Address);
1687  PMMPDE PointerPde = MiAddressToPde(Address);
1688 #if (_MI_PAGING_LEVELS >= 3)
1689  PMMPDE PointerPpe = MiAddressToPpe(Address);
1690 #if (_MI_PAGING_LEVELS == 4)
1691  PMMPDE PointerPxe = MiAddressToPxe(Address);
1692 #endif
1693 #endif
1694  MMPTE TempPte;
1695  PETHREAD CurrentThread;
1697  NTSTATUS Status;
1698  PMMSUPPORT WorkingSet;
1699  ULONG ProtectionCode;
1700  PMMVAD Vad = NULL;
1701  PFN_NUMBER PageFrameIndex;
1702  ULONG Color;
1703  BOOLEAN IsSessionAddress;
1704  PMMPFN Pfn1;
1705  DPRINT("ARM3 FAULT AT: %p\n", Address);
1706 
1707  /* Check for page fault on high IRQL */
1708  if (OldIrql > APC_LEVEL)
1709  {
1710 #if (_MI_PAGING_LEVELS < 3)
1711  /* Could be a page table for paged pool, which we'll allow */
1712  if (MI_IS_SYSTEM_PAGE_TABLE_ADDRESS(Address)) MiSynchronizeSystemPde((PMMPDE)PointerPte);
1714 #endif
1715  /* Check if any of the top-level pages are invalid */
1716  if (
1717 #if (_MI_PAGING_LEVELS == 4)
1718  (PointerPxe->u.Hard.Valid == 0) ||
1719 #endif
1720 #if (_MI_PAGING_LEVELS >= 3)
1721  (PointerPpe->u.Hard.Valid == 0) ||
1722 #endif
1723  (PointerPde->u.Hard.Valid == 0) ||
1724  (PointerPte->u.Hard.Valid == 0))
1725  {
1726  /* This fault is not valid, print out some debugging help */
1727  DbgPrint("MM:***PAGE FAULT AT IRQL > 1 Va %p, IRQL %lx\n",
1728  Address,
1729  OldIrql);
1730  if (TrapInformation)
1731  {
1732  PKTRAP_FRAME TrapFrame = TrapInformation;
1733 #ifdef _M_IX86
1734  DbgPrint("MM:***EIP %p, EFL %p\n", TrapFrame->Eip, TrapFrame->EFlags);
1735  DbgPrint("MM:***EAX %p, ECX %p EDX %p\n", TrapFrame->Eax, TrapFrame->Ecx, TrapFrame->Edx);
1736  DbgPrint("MM:***EBX %p, ESI %p EDI %p\n", TrapFrame->Ebx, TrapFrame->Esi, TrapFrame->Edi);
1737 #elif defined(_M_AMD64)
1738  DbgPrint("MM:***RIP %p, EFL %p\n", TrapFrame->Rip, TrapFrame->EFlags);
1739  DbgPrint("MM:***RAX %p, RCX %p RDX %p\n", TrapFrame->Rax, TrapFrame->Rcx, TrapFrame->Rdx);
1740  DbgPrint("MM:***RBX %p, RSI %p RDI %p\n", TrapFrame->Rbx, TrapFrame->Rsi, TrapFrame->Rdi);
1741 #elif defined(_M_ARM)
1742  DbgPrint("MM:***PC %p\n", TrapFrame->Pc);
1743  DbgPrint("MM:***R0 %p, R1 %p R2 %p, R3 %p\n", TrapFrame->R0, TrapFrame->R1, TrapFrame->R2, TrapFrame->R3);
1744  DbgPrint("MM:***R11 %p, R12 %p SP %p, LR %p\n", TrapFrame->R11, TrapFrame->R12, TrapFrame->Sp, TrapFrame->Lr);
1745 #endif
1746  }
1747 
1748  /* Tell the trap handler to fail */
1749  return STATUS_IN_PAGE_ERROR | 0x10000000;
1750  }
1751 
1752  /* Not yet implemented in ReactOS */
1753  ASSERT(MI_IS_PAGE_LARGE(PointerPde) == FALSE);
1754  ASSERT((!MI_IS_NOT_PRESENT_FAULT(FaultCode) && MI_IS_PAGE_COPY_ON_WRITE(PointerPte)) == FALSE);
1755 
1756  /* Check if this was a write */
1757  if (MI_IS_WRITE_ACCESS(FaultCode))
1758  {
1759  /* Was it to a read-only page? */
1760  Pfn1 = MI_PFN_ELEMENT(PointerPte->u.Hard.PageFrameNumber);
1761  if (!(PointerPte->u.Long & PTE_READWRITE) &&
1763  {
1764  /* Crash with distinguished bugcheck code */
1765  KeBugCheckEx(ATTEMPTED_WRITE_TO_READONLY_MEMORY,
1766  (ULONG_PTR)Address,
1767  PointerPte->u.Long,
1768  (ULONG_PTR)TrapInformation,
1769  10);
1770  }
1771  }
1772 
1773  /* Nothing is actually wrong */
1774  DPRINT1("Fault at IRQL %u is ok (%p)\n", OldIrql, Address);
1775  return STATUS_SUCCESS;
1776  }
1777 
1778  /* Check for kernel fault address */
1779  if (Address >= MmSystemRangeStart)
1780  {
1781  /* Bail out, if the fault came from user mode */
1782  if (Mode == UserMode) return STATUS_ACCESS_VIOLATION;
1783 
1784 #if (_MI_PAGING_LEVELS == 2)
1785  if (MI_IS_SYSTEM_PAGE_TABLE_ADDRESS(Address)) MiSynchronizeSystemPde((PMMPDE)PointerPte);
1787 #endif
1788 
1789  /* Check if the higher page table entries are invalid */
1790  if (
1791 #if (_MI_PAGING_LEVELS == 4)
1792  /* AMD64 system, check if PXE is invalid */
1793  (PointerPxe->u.Hard.Valid == 0) ||
1794 #endif
1795 #if (_MI_PAGING_LEVELS >= 3)
1796  /* PAE/AMD64 system, check if PPE is invalid */
1797  (PointerPpe->u.Hard.Valid == 0) ||
1798 #endif
1799  /* Always check if the PDE is valid */
1800  (PointerPde->u.Hard.Valid == 0))
1801  {
1802  /* PXE/PPE/PDE (still) not valid, kill the system */
1803  KeBugCheckEx(PAGE_FAULT_IN_NONPAGED_AREA,
1804  (ULONG_PTR)Address,
1805  FaultCode,
1806  (ULONG_PTR)TrapInformation,
1807  2);
1808  }
1809 
1810  /* Not handling session faults yet */
1811  IsSessionAddress = MI_IS_SESSION_ADDRESS(Address);
1812 
1813  /* The PDE is valid, so read the PTE */
1814  TempPte = *PointerPte;
1815  if (TempPte.u.Hard.Valid == 1)
1816  {
1817  /* Check if this was system space or session space */
1818  if (!IsSessionAddress)
1819  {
1820  /* Check if the PTE is still valid under PFN lock */
1821  OldIrql = MiAcquirePfnLock();
1822  TempPte = *PointerPte;
1823  if (TempPte.u.Hard.Valid)
1824  {
1825  /* Check if this was a write */
1826  if (MI_IS_WRITE_ACCESS(FaultCode))
1827  {
1828  /* Was it to a read-only page? */
1829  Pfn1 = MI_PFN_ELEMENT(PointerPte->u.Hard.PageFrameNumber);
1830  if (!(PointerPte->u.Long & PTE_READWRITE) &&
1832  {
1833  /* Crash with distinguished bugcheck code */
1834  KeBugCheckEx(ATTEMPTED_WRITE_TO_READONLY_MEMORY,
1835  (ULONG_PTR)Address,
1836  PointerPte->u.Long,
1837  (ULONG_PTR)TrapInformation,
1838  11);
1839  }
1840  }
1841 
1842  /* Check for execution of non-executable memory */
1843  if (MI_IS_INSTRUCTION_FETCH(FaultCode) &&
1845  {
1846  KeBugCheckEx(ATTEMPTED_EXECUTE_OF_NOEXECUTE_MEMORY,
1847  (ULONG_PTR)Address,
1848  (ULONG_PTR)TempPte.u.Long,
1849  (ULONG_PTR)TrapInformation,
1850  1);
1851  }
1852  }
1853 
1854  /* Release PFN lock and return all good */
1855  MiReleasePfnLock(OldIrql);
1856  return STATUS_SUCCESS;
1857  }
1858  }
1859 #if (_MI_PAGING_LEVELS == 2)
1860  /* Check if this was a session PTE that needs to remap the session PDE */
1862  {
1863  /* Do the remapping */
1864  Status = MiCheckPdeForSessionSpace(Address);
1865  if (!NT_SUCCESS(Status))
1866  {
1867  /* It failed, this address is invalid */
1868  KeBugCheckEx(PAGE_FAULT_IN_NONPAGED_AREA,
1869  (ULONG_PTR)Address,
1870  FaultCode,
1871  (ULONG_PTR)TrapInformation,
1872  6);
1873  }
1874  }
1875 #else
1876 
1877 _WARN("Session space stuff is not implemented yet!")
1878 
1879 #endif
1880 
1881  /* Check for a fault on the page table or hyperspace */
1883  {
1884 #if (_MI_PAGING_LEVELS < 3)
1885  /* Windows does this check but I don't understand why -- it's done above! */
1887 #endif
1888  /* Handle this as a user mode fault */
1889  goto UserFault;
1890  }
1891 
1892  /* Get the current thread */
1893  CurrentThread = PsGetCurrentThread();
1894 
1895  /* What kind of address is this */
1896  if (!IsSessionAddress)
1897  {
1898  /* Use the system working set */
1899  WorkingSet = &MmSystemCacheWs;
1900  CurrentProcess = NULL;
1901 
1902  /* Make sure we don't have a recursive working set lock */
1903  if ((CurrentThread->OwnsProcessWorkingSetExclusive) ||
1904  (CurrentThread->OwnsProcessWorkingSetShared) ||
1905  (CurrentThread->OwnsSystemWorkingSetExclusive) ||
1906  (CurrentThread->OwnsSystemWorkingSetShared) ||
1907  (CurrentThread->OwnsSessionWorkingSetExclusive) ||
1908  (CurrentThread->OwnsSessionWorkingSetShared))
1909  {
1910  /* Fail */
1911  return STATUS_IN_PAGE_ERROR | 0x10000000;
1912  }
1913  }
1914  else
1915  {
1916  /* Use the session process and working set */
1918  WorkingSet = &MmSessionSpace->GlobalVirtualAddress->Vm;
1919 
1920  /* Make sure we don't have a recursive working set lock */
1921  if ((CurrentThread->OwnsSessionWorkingSetExclusive) ||
1922  (CurrentThread->OwnsSessionWorkingSetShared))
1923  {
1924  /* Fail */
1925  return STATUS_IN_PAGE_ERROR | 0x10000000;
1926  }
1927  }
1928 
1929  /* Acquire the working set lock */
1930  KeRaiseIrql(APC_LEVEL, &LockIrql);
1931  MiLockWorkingSet(CurrentThread, WorkingSet);
1932 
1933  /* Re-read PTE now that we own the lock */
1934  TempPte = *PointerPte;
1935  if (TempPte.u.Hard.Valid == 1)
1936  {
1937  /* Check if this was a write */
1938  if (MI_IS_WRITE_ACCESS(FaultCode))
1939  {
1940  /* Was it to a read-only page that is not copy on write? */
1941  Pfn1 = MI_PFN_ELEMENT(PointerPte->u.Hard.PageFrameNumber);
1942  if (!(TempPte.u.Long & PTE_READWRITE) &&
1943  !(Pfn1->OriginalPte.u.Soft.Protection & MM_READWRITE) &&
1945  {
1946  /* Case not yet handled */
1947  ASSERT(!IsSessionAddress);
1948 
1949  /* Crash with distinguished bugcheck code */
1950  KeBugCheckEx(ATTEMPTED_WRITE_TO_READONLY_MEMORY,
1951  (ULONG_PTR)Address,
1952  TempPte.u.Long,
1953  (ULONG_PTR)TrapInformation,
1954  12);
1955  }
1956  }
1957 
1958  /* Check for execution of non-executable memory */
1959  if (MI_IS_INSTRUCTION_FETCH(FaultCode) &&
1961  {
1962  KeBugCheckEx(ATTEMPTED_EXECUTE_OF_NOEXECUTE_MEMORY,
1963  (ULONG_PTR)Address,
1964  (ULONG_PTR)TempPte.u.Long,
1965  (ULONG_PTR)TrapInformation,
1966  2);
1967  }
1968 
1969  /* Check for read-only write in session space */
1970  if ((IsSessionAddress) &&
1971  MI_IS_WRITE_ACCESS(FaultCode) &&
1973  {
1974  /* Sanity check */
1976 
1977  /* Was this COW? */
1979  {
1980  /* Then this is not allowed */
1981  KeBugCheckEx(ATTEMPTED_WRITE_TO_READONLY_MEMORY,
1982  (ULONG_PTR)Address,
1983  (ULONG_PTR)TempPte.u.Long,
1984  (ULONG_PTR)TrapInformation,
1985  13);
1986  }
1987 
1988  /* Otherwise, handle COW */
1989  ASSERT(FALSE);
1990  }
1991 
1992  /* Release the working set */
1993  MiUnlockWorkingSet(CurrentThread, WorkingSet);
1994  KeLowerIrql(LockIrql);
1995 
1996  /* Otherwise, the PDE was probably invalid, and all is good now */
1997  return STATUS_SUCCESS;
1998  }
1999 
2000  /* Check one kind of prototype PTE */
2001  if (TempPte.u.Soft.Prototype)
2002  {
2003  /* Make sure protected pool is on, and that this is a pool address */
2005  (((Address >= MmNonPagedPoolStart) &&
2009  (Address < MmNonPagedPoolEnd))))
2010  {
2011  /* Bad boy, bad boy, whatcha gonna do, whatcha gonna do when ARM3 comes for you! */
2012  KeBugCheckEx(DRIVER_CAUGHT_MODIFYING_FREED_POOL,
2013  (ULONG_PTR)Address,
2014  FaultCode,
2015  Mode,
2016  4);
2017  }
2018 
2019  /* Get the prototype PTE! */
2020  ProtoPte = MiProtoPteToPte(&TempPte);
2021 
2022  /* Do we need to locate the prototype PTE in session space? */
2023  if ((IsSessionAddress) &&
2024  (TempPte.u.Soft.PageFileHigh == MI_PTE_LOOKUP_NEEDED))
2025  {
2026  /* Yep, go find it as well as the VAD for it */
2027  ProtoPte = MiCheckVirtualAddress(Address,
2028  &ProtectionCode,
2029  &Vad);
2030  ASSERT(ProtoPte != NULL);
2031  }
2032  }
2033  else
2034  {
2035  /* We don't implement transition PTEs */
2036  ASSERT(TempPte.u.Soft.Transition == 0);
2037 
2038  /* Check for no-access PTE */
2039  if (TempPte.u.Soft.Protection == MM_NOACCESS)
2040  {
2041  /* Bugcheck the system! */
2042  KeBugCheckEx(PAGE_FAULT_IN_NONPAGED_AREA,
2043  (ULONG_PTR)Address,
2044  FaultCode,
2045  (ULONG_PTR)TrapInformation,
2046  1);
2047  }
2048 
2049  /* Check for no protecton at all */
2050  if (TempPte.u.Soft.Protection == MM_ZERO_ACCESS)
2051  {
2052  /* Bugcheck the system! */
2053  KeBugCheckEx(PAGE_FAULT_IN_NONPAGED_AREA,
2054  (ULONG_PTR)Address,
2055  FaultCode,
2056  (ULONG_PTR)TrapInformation,
2057  0);
2058  }
2059  }
2060 
2061  /* Check for demand page */
2062  if (MI_IS_WRITE_ACCESS(FaultCode) &&
2063  !(ProtoPte) &&
2064  !(IsSessionAddress) &&
2065  !(TempPte.u.Hard.Valid))
2066  {
2067  /* Get the protection code */
2068  ASSERT(TempPte.u.Soft.Transition == 0);
2069  if (!(TempPte.u.Soft.Protection & MM_READWRITE))
2070  {
2071  /* Bugcheck the system! */
2072  KeBugCheckEx(ATTEMPTED_WRITE_TO_READONLY_MEMORY,
2073  (ULONG_PTR)Address,
2074  TempPte.u.Long,
2075  (ULONG_PTR)TrapInformation,
2076  14);
2077  }
2078  }
2079 
2080  /* Now do the real fault handling */
2081  Status = MiDispatchFault(FaultCode,
2082  Address,
2083  PointerPte,
2084  ProtoPte,
2085  FALSE,
2087  TrapInformation,
2088  NULL);
2089 
2090  /* Release the working set */
2092  MiUnlockWorkingSet(CurrentThread, WorkingSet);
2093  KeLowerIrql(LockIrql);
2094 
2095  /* We are done! */
2096  DPRINT("Fault resolved with status: %lx\n", Status);
2097  return Status;
2098  }
2099 
2100  /* This is a user fault */
2101 UserFault:
2102  CurrentThread = PsGetCurrentThread();
2103  CurrentProcess = (PEPROCESS)CurrentThread->Tcb.ApcState.Process;
2104 
2105  /* Lock the working set */
2106  MiLockProcessWorkingSet(CurrentProcess, CurrentThread);
2107 
2108  ProtectionCode = MM_INVALID_PROTECTION;
2109 
2110 #if (_MI_PAGING_LEVELS == 4)
2111  /* Check if the PXE is valid */
2112  if (PointerPxe->u.Hard.Valid == 0)
2113  {
2114  /* Right now, we only handle scenarios where the PXE is totally empty */
2115  ASSERT(PointerPxe->u.Long == 0);
2116 
2117  /* This is only possible for user mode addresses! */
2118  ASSERT(PointerPte <= MiHighestUserPte);
2119 
2120  /* Check if we have a VAD */
2121  MiCheckVirtualAddress(Address, &ProtectionCode, &Vad);
2122  if (ProtectionCode == MM_NOACCESS)
2123  {
2124  MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
2125  return STATUS_ACCESS_VIOLATION;
2126  }
2127 
2128  /* Resolve a demand zero fault */
2129  MiResolveDemandZeroFault(PointerPpe,
2130  PointerPxe,
2133  MM_NOIRQL);
2134 
2135  /* We should come back with a valid PXE */
2136  ASSERT(PointerPxe->u.Hard.Valid == 1);
2137  }
2138 #endif
2139 
2140 #if (_MI_PAGING_LEVELS >= 3)
2141  /* Check if the PPE is valid */
2142  if (PointerPpe->u.Hard.Valid == 0)
2143  {
2144  /* Right now, we only handle scenarios where the PPE is totally empty */
2145  ASSERT(PointerPpe->u.Long == 0);
2146 
2147  /* This is only possible for user mode addresses! */
2148  ASSERT(PointerPte <= MiHighestUserPte);
2149 
2150  /* Check if we have a VAD, unless we did this already */
2151  if (ProtectionCode == MM_INVALID_PROTECTION)
2152  {
2153  MiCheckVirtualAddress(Address, &ProtectionCode, &Vad);
2154  }
2155 
2156  if (ProtectionCode == MM_NOACCESS)
2157  {
2158  MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
2159  return STATUS_ACCESS_VIOLATION;
2160  }
2161 
2162  /* Resolve a demand zero fault */
2163  MiResolveDemandZeroFault(PointerPde,
2164  PointerPpe,
2167  MM_NOIRQL);
2168 
2169  /* We should come back with a valid PPE */
2170  ASSERT(PointerPpe->u.Hard.Valid == 1);
2171  MiIncrementPageTableReferences(PointerPde);
2172  }
2173 #endif
2174 
2175  /* Check if the PDE is invalid */
2176  if (PointerPde->u.Hard.Valid == 0)
2177  {
2178  /* Right now, we only handle scenarios where the PDE is totally empty */
2179  ASSERT(PointerPde->u.Long == 0);
2180 
2181  /* And go dispatch the fault on the PDE. This should handle the demand-zero */
2182 #if MI_TRACE_PFNS
2183  UserPdeFault = TRUE;
2184 #endif
2185  /* Check if we have a VAD, unless we did this already */
2186  if (ProtectionCode == MM_INVALID_PROTECTION)
2187  {
2188  MiCheckVirtualAddress(Address, &ProtectionCode, &Vad);
2189  }
2190 
2191  if (ProtectionCode == MM_NOACCESS)
2192  {
2193 #if (_MI_PAGING_LEVELS == 2)
2194  /* Could be a page table for paged pool */
2196 #endif
2197  /* Has the code above changed anything -- is this now a valid PTE? */
2198  Status = (PointerPde->u.Hard.Valid == 1) ? STATUS_SUCCESS : STATUS_ACCESS_VIOLATION;
2199 
2200  /* Either this was a bogus VA or we've fixed up a paged pool PDE */
2201  MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
2202  return Status;
2203  }
2204 
2205  /* Resolve a demand zero fault */
2206  MiResolveDemandZeroFault(PointerPte,
2207  PointerPde,
2210  MM_NOIRQL);
2211 #if _MI_PAGING_LEVELS >= 3
2212  MiIncrementPageTableReferences(PointerPte);
2213 #endif
2214 
2215 #if MI_TRACE_PFNS
2216  UserPdeFault = FALSE;
2217  /* Update debug info */
2218  if (TrapInformation)
2219  MiGetPfnEntry(PointerPde->u.Hard.PageFrameNumber)->CallSite = (PVOID)((PKTRAP_FRAME)TrapInformation)->Eip;
2220  else
2221  MiGetPfnEntry(PointerPde->u.Hard.PageFrameNumber)->CallSite = _ReturnAddress();
2222 #endif
2223  /* We should come back with APCs enabled, and with a valid PDE */
2225  ASSERT(PointerPde->u.Hard.Valid == 1);
2226  }
2227  else
2228  {
2229  /* Not yet implemented in ReactOS */
2230  ASSERT(MI_IS_PAGE_LARGE(PointerPde) == FALSE);
2231  }
2232 
2233  /* Now capture the PTE. */
2234  TempPte = *PointerPte;
2235 
2236  /* Check if the PTE is valid */
2237  if (TempPte.u.Hard.Valid)
2238  {
2239  /* Check if this is a write on a readonly PTE */
2240  if (MI_IS_WRITE_ACCESS(FaultCode))
2241  {
2242  /* Is this a copy on write PTE? */
2244  {
2245  PFN_NUMBER PageFrameIndex, OldPageFrameIndex;
2246  PMMPFN Pfn1;
2247 
2248  LockIrql = MiAcquirePfnLock();
2249 
2250  ASSERT(MmAvailablePages > 0);
2251 
2254 
2255  /* Allocate a new page and copy it */
2257  OldPageFrameIndex = PFN_FROM_PTE(&TempPte);
2258 
2259  MiCopyPfn(PageFrameIndex, OldPageFrameIndex);
2260 
2261  /* Dereference whatever this PTE is referencing */
2262  Pfn1 = MI_PFN_ELEMENT(OldPageFrameIndex);
2263  ASSERT(Pfn1->u3.e1.PrototypePte == 1);
2264  ASSERT(!MI_IS_PFN_DELETED(Pfn1));
2265  ProtoPte = Pfn1->PteAddress;
2266  MiDeletePte(PointerPte, Address, CurrentProcess, ProtoPte);
2267 
2268  /* And make a new shiny one with our page */
2269  MiInitializePfn(PageFrameIndex, PointerPte, TRUE);
2270  TempPte.u.Hard.PageFrameNumber = PageFrameIndex;
2271  TempPte.u.Hard.Write = 1;
2272  TempPte.u.Hard.CopyOnWrite = 0;
2273 
2274  MI_WRITE_VALID_PTE(PointerPte, TempPte);
2275 
2276  MiReleasePfnLock(LockIrql);
2277 
2278  /* Return the status */
2279  MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
2281  }
2282 
2283  /* Is this a read-only PTE? */
2285  {
2286  /* Return the status */
2287  MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
2288  return STATUS_ACCESS_VIOLATION;
2289  }
2290  }
2291 
2292  /* Check for execution of non-executable memory */
2293  if (MI_IS_INSTRUCTION_FETCH(FaultCode) &&
2295  {
2296  /* Return the status */
2297  MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
2298  return STATUS_ACCESS_VIOLATION;
2299  }
2300 
2301  /* The fault has already been resolved by a different thread */
2302  MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
2303  return STATUS_SUCCESS;
2304  }
2305 
2306  /* Quick check for demand-zero */
2307  if ((TempPte.u.Long == (MM_READWRITE << MM_PTE_SOFTWARE_PROTECTION_BITS)) ||
2309  {
2310  /* Resolve the fault */
2312  PointerPte,
2313  TempPte.u.Soft.Protection,
2315  MM_NOIRQL);
2316 
2317 #if MI_TRACE_PFNS
2318  /* Update debug info */
2319  if (TrapInformation)
2320  MiGetPfnEntry(PointerPte->u.Hard.PageFrameNumber)->CallSite = (PVOID)((PKTRAP_FRAME)TrapInformation)->Eip;
2321  else
2322  MiGetPfnEntry(PointerPte->u.Hard.PageFrameNumber)->CallSite = _ReturnAddress();
2323 #endif
2324 
2325  /* Return the status */
2326  MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
2328  }
2329 
2330  /* Check for zero PTE */
2331  if (TempPte.u.Long == 0)
2332  {
2333  /* Check if this address range belongs to a valid allocation (VAD) */
2334  ProtoPte = MiCheckVirtualAddress(Address, &ProtectionCode, &Vad);
2335  if (ProtectionCode == MM_NOACCESS)
2336  {
2337 #if (_MI_PAGING_LEVELS == 2)
2338  /* Could be a page table for paged pool */
2340 #endif
2341  /* Has the code above changed anything -- is this now a valid PTE? */
2342  Status = (PointerPte->u.Hard.Valid == 1) ? STATUS_SUCCESS : STATUS_ACCESS_VIOLATION;
2343 
2344  /* Either this was a bogus VA or we've fixed up a paged pool PDE */
2345  MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
2346  return Status;
2347  }
2348 
2349  /*
2350  * Check if this is a real user-mode address or actually a kernel-mode
2351  * page table for a user mode address
2352  */
2354 #if _MI_PAGING_LEVELS >= 3
2355  || MiIsUserPte(Address)
2356 #if _MI_PAGING_LEVELS == 4
2357  || MiIsUserPde(Address)
2358 #endif
2359 #endif
2360  )
2361  {
2362  /* Add an additional page table reference */
2364  }
2365 
2366  /* Is this a guard page? */
2367  if ((ProtectionCode & MM_PROTECT_SPECIAL) == MM_GUARDPAGE)
2368  {
2369  /* The VAD protection cannot be MM_DECOMMIT! */
2370  ASSERT(ProtectionCode != MM_DECOMMIT);
2371 
2372  /* Remove the bit */
2373  TempPte.u.Soft.Protection = ProtectionCode & ~MM_GUARDPAGE;
2374  MI_WRITE_INVALID_PTE(PointerPte, TempPte);
2375 
2376  /* Not supported */
2377  ASSERT(ProtoPte == NULL);
2378  ASSERT(CurrentThread->ApcNeeded == 0);
2379 
2380  /* Drop the working set lock */
2381  MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
2383 
2384  /* Handle stack expansion */
2385  return MiCheckForUserStackOverflow(Address, TrapInformation);
2386  }
2387 
2388  /* Did we get a prototype PTE back? */
2389  if (!ProtoPte)
2390  {
2391  /* Is this PTE actually part of the PDE-PTE self-mapping directory? */
2392  if (PointerPde == MiAddressToPde(PTE_BASE))
2393  {
2394  /* Then it's really a demand-zero PDE (on behalf of user-mode) */
2395 #ifdef _M_ARM
2396  _WARN("This is probably completely broken!");
2398 #else
2399  MI_WRITE_INVALID_PDE(PointerPte, DemandZeroPde);
2400 #endif
2401  }
2402  else
2403  {
2404  /* No, create a new PTE. First, write the protection */
2405  TempPte.u.Soft.Protection = ProtectionCode;
2406  MI_WRITE_INVALID_PTE(PointerPte, TempPte);
2407  }
2408 
2409  /* Lock the PFN database since we're going to grab a page */
2410  OldIrql = MiAcquirePfnLock();
2411 
2412  /* Make sure we have enough pages */
2413  ASSERT(MmAvailablePages >= 32);
2414 
2415  /* Try to get a zero page */
2417  MI_SET_PROCESS2(CurrentProcess->ImageFileName);
2419  PageFrameIndex = MiRemoveZeroPageSafe(Color);
2420  if (!PageFrameIndex)
2421  {
2422  /* Grab a page out of there. Later we should grab a colored zero page */
2423  PageFrameIndex = MiRemoveAnyPage(Color);
2424  ASSERT(PageFrameIndex);
2425 
2426  /* Release the lock since we need to do some zeroing */
2427  MiReleasePfnLock(OldIrql);
2428 
2429  /* Zero out the page, since it's for user-mode */
2430  MiZeroPfn(PageFrameIndex);
2431 
2432  /* Grab the lock again so we can initialize the PFN entry */
2433  OldIrql = MiAcquirePfnLock();
2434  }
2435 
2436  /* Initialize the PFN entry now */
2437  MiInitializePfn(PageFrameIndex, PointerPte, 1);
2438 
2439  /* Increment the count of pages in the process */
2440  CurrentProcess->NumberOfPrivatePages++;
2441 
2442  /* One more demand-zero fault */
2443  KeGetCurrentPrcb()->MmDemandZeroCount++;
2444 
2445  /* And we're done with the lock */
2446  MiReleasePfnLock(OldIrql);
2447 
2448  /* Fault on user PDE, or fault on user PTE? */
2449  if (PointerPte <= MiHighestUserPte)
2450  {
2451  /* User fault, build a user PTE */
2453  PointerPte,
2454  PointerPte->u.Soft.Protection,
2455  PageFrameIndex);
2456  }
2457  else
2458  {
2459  /* This is a user-mode PDE, create a kernel PTE for it */
2461  PointerPte,
2462  PointerPte->u.Soft.Protection,
2463  PageFrameIndex);
2464  }
2465 
2466  /* Write the dirty bit for writeable pages */
2468 
2469  /* And now write down the PTE, making the address valid */
2470  MI_WRITE_VALID_PTE(PointerPte, TempPte);
2471  Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);
2472  ASSERT(Pfn1->u1.Event == NULL);
2473 
2474  /* Demand zero */
2476  MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
2478  }
2479 
2480  /* We should have a valid protection here */
2481  ASSERT(ProtectionCode != 0x100);
2482 
2483  /* Write the prototype PTE */
2485  TempPte.u.Soft.Protection = ProtectionCode;
2486  ASSERT(TempPte.u.Long != 0);
2487  MI_WRITE_INVALID_PTE(PointerPte, TempPte);
2488  }
2489  else
2490  {
2491  /* Get the protection code and check if this is a proto PTE */
2492  ProtectionCode = (ULONG)TempPte.u.Soft.Protection;
2493  if (TempPte.u.Soft.Prototype)
2494  {
2495  /* Do we need to go find the real PTE? */
2496  if (TempPte.u.Soft.PageFileHigh == MI_PTE_LOOKUP_NEEDED)
2497  {
2498  /* Get the prototype pte and VAD for it */
2499  ProtoPte = MiCheckVirtualAddress(Address,
2500  &ProtectionCode,
2501  &Vad);
2502  if (!ProtoPte)
2503  {
2505  MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
2506  return STATUS_ACCESS_VIOLATION;
2507  }
2508  }
2509  else
2510  {
2511  /* Get the prototype PTE! */
2512  ProtoPte = MiProtoPteToPte(&TempPte);
2513 
2514  /* Is it read-only */
2515  if (TempPte.u.Proto.ReadOnly)
2516  {
2517  /* Set read-only code */
2518  ProtectionCode = MM_READONLY;
2519  }
2520  else
2521  {
2522  /* Set unknown protection */
2523  ProtectionCode = 0x100;
2524  ASSERT(CurrentProcess->CloneRoot != NULL);
2525  }
2526  }
2527  }
2528  }
2529 
2530  /* Do we have a valid protection code? */
2531  if (ProtectionCode != 0x100)
2532  {
2533  /* Run a software access check first, including to detect guard pages */
2534  Status = MiAccessCheck(PointerPte,
2535  !MI_IS_NOT_PRESENT_FAULT(FaultCode),
2536  Mode,
2537  ProtectionCode,
2538  TrapInformation,
2539  FALSE);
2540  if (Status != STATUS_SUCCESS)
2541  {
2542  /* Not supported */
2543  ASSERT(CurrentThread->ApcNeeded == 0);
2544 
2545  /* Drop the working set lock */
2546  MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
2548 
2549  /* Did we hit a guard page? */
2551  {
2552  /* Handle stack expansion */
2553  return MiCheckForUserStackOverflow(Address, TrapInformation);
2554  }
2555 
2556  /* Otherwise, fail back to the caller directly */
2557  return Status;
2558  }
2559  }
2560 
2561  /* Dispatch the fault */
2562  Status = MiDispatchFault(FaultCode,
2563  Address,
2564  PointerPte,
2565  ProtoPte,
2566  FALSE,
2568  TrapInformation,
2569  Vad);
2570 
2571  /* Return the status */
2573  MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
2574  return Status;
2575 }
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
ULONG R12
Definition: ketypes.h:364
#define MM_HIGHEST_USER_ADDRESS
Definition: armddk.h:17
VOID NTAPI MiInitializePfn(IN PFN_NUMBER PageFrameIndex, IN PMMPTE PointerPte, IN BOOLEAN Modified)
Definition: pfnlist.c:962
#define MM_INVALID_PROTECTION
Definition: miarm.h:67
MMPTE PrototypePte
Definition: init.c:40
#define _MI_PAGING_LEVELS
Definition: mm.h:6
UINT64 Rbx
Definition: ketypes.h:374
#define MI_IS_NOT_PRESENT_FAULT(FaultCode)
Definition: mm.h:121
#define DbgPrint
Definition: hal.h:12
#define MiAddressToPde(x)
Definition: mmx86.c:20
BOOLEAN NTAPI KeAreAllApcsDisabled(VOID)
Definition: apc.c:985
_In_ ULONG Mode
Definition: hubbusif.h:303
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
ULONG OwnsSystemWorkingSetShared
Definition: pstypes.h:1224
NTSTATUS NTAPI MiDispatchFault(IN ULONG FaultCode, IN PVOID Address, IN PMMPTE PointerPte, IN PMMPTE PointerProtoPte, IN BOOLEAN Recursive, IN PEPROCESS Process, IN PVOID TrapInformation, IN PMMVAD Vad)
Definition: pagfault.c:1319
#define TRUE
Definition: types.h:120
#define MI_IS_SESSION_ADDRESS(Address)
Definition: miarm.h:171
#define HYDRA_PROCESS
Definition: pagfault.c:20
#define MM_DECOMMIT
Definition: miarm.h:64
LONG NTSTATUS
Definition: precomp.h:26
FORCEINLINE PMMPTE MiAddressToPpe(PVOID Address)
Definition: mm.h:161
KTHREAD Tcb
Definition: pstypes.h:1103
FORCEINLINE struct _KPRCB * KeGetCurrentPrcb(VOID)
Definition: ketypes.h:1080
#define MI_IS_PAGE_EXECUTABLE(x)
Definition: mm.h:111
struct _EPROCESS * PEPROCESS
Definition: nt_native.h:30
static NTSTATUS NTAPI MiAccessCheck(IN PMMPTE PointerPte, IN BOOLEAN StoreInstruction, IN KPROCESSOR_MODE PreviousMode, IN ULONG_PTR ProtectionMask, IN PVOID TrapFrame, IN BOOLEAN LockHeld)
Definition: pagfault.c:168
VOID NTAPI MiCopyPfn(_In_ PFN_NUMBER DestPage, _In_ PFN_NUMBER SrcPage)
Definition: pagfault.c:529
PVOID MmNonPagedPoolExpansionStart
Definition: init.c:25
#define STATUS_GUARD_PAGE_VIOLATION
Definition: ntstatus.h:182
#define MI_PTE_LOOKUP_NEEDED
Definition: miarm.h:246
#define MM_READWRITE
Definition: bootanim.c:19
#define MM_NOACCESS
Definition: miarm.h:65
PMM_SESSION_SPACE MmSessionSpace
Definition: session.c:21
FORCEINLINE VOID MiLockProcessWorkingSet(IN PEPROCESS Process, IN PETHREAD Thread)
Definition: miarm.h:1129
#define MM_PTE_SOFTWARE_PROTECTION_BITS
Definition: mm.h:75
#define MI_IS_PAGE_COPY_ON_WRITE(x)
Definition: mm.h:110
#define MI_IS_WRITE_ACCESS(FaultCode)
Definition: mm.h:122
ULONG R3
Definition: ketypes.h:363
ULONG Esi
Definition: ketypes.h:264
if(dx==0 &&dy==0)
Definition: linetemp.h:174
PFN_NUMBER MmAvailablePages
Definition: freelist.c:26
ULONG Pc
Definition: ketypes.h:368
ULONG Lr
Definition: ketypes.h:366
struct Color Color
ULONG R2
Definition: ketypes.h:362
ULONG Edi
Definition: ketypes.h:263
VOID NTAPI MiDeletePte(IN PMMPTE PointerPte, IN PVOID VirtualAddress, IN PEPROCESS CurrentProcess, IN PMMPTE PrototypePte)
Definition: virtual.c:369
PVOID MmNonPagedPoolEnd
Definition: mminit.c:99
uint32_t ULONG_PTR
Definition: typedefs.h:65
ULONG R0
Definition: ketypes.h:360
USHORT PrototypePte
Definition: mm.h:363
static PMMPTE NTAPI MiCheckVirtualAddress(IN PVOID VirtualAddress, OUT PULONG ProtectCode, OUT PMMVAD *ProtoVad)
Definition: pagfault.c:237
UCHAR KIRQL
Definition: env_spec_w32.h:591
MMPFNENTRY e1
Definition: mm.h:397
#define STATUS_WAIT_1
Definition: ntstatus.h:71
#define MI_MAKE_DIRTY_PAGE(x)
Definition: mm.h:98
ULONG OwnsSessionWorkingSetShared
Definition: pstypes.h:1226
#define MiAddressToPte(x)
Definition: mmx86.c:19
#define MM_NOIRQL
Definition: mm.h:70
ULONG PFN_NUMBER
Definition: ke.h:9
ULONG Eax
Definition: ketypes.h:259
UINT64 Rsi
Definition: ketypes.h:376
#define FALSE
Definition: types.h:117
FORCEINLINE VOID MI_WRITE_VALID_PTE(IN PMMPTE PointerPte, IN MMPTE TempPte)
Definition: miarm.h:964
#define MI_SET_PROCESS(x)
Definition: mm.h:318
FORCEINLINE VOID MI_WRITE_INVALID_PDE(IN PMMPDE PointerPde, IN MMPDE InvalidPde)
Definition: miarm.h:1040
#define _WARN(msg)
Definition: debug.h:263
UINT64 Rax
Definition: ketypes.h:323
KAPC_STATE ApcState
Definition: ketypes.h:1720
PKEVENT Event
Definition: mm.h:379
FORCEINLINE BOOLEAN MiIsUserPde(PVOID Address)
Definition: miarm.h:722
#define MI_SET_PROCESS2(x)
Definition: mm.h:319
ULONG OwnsSessionWorkingSetExclusive
Definition: pstypes.h:1225
FORCEINLINE PFN_NUMBER MiRemoveZeroPageSafe(IN ULONG Color)
Definition: miarm.h:2420
unsigned char BOOLEAN
MMSUPPORT MmSystemCacheWs
Definition: init.c:55
static WCHAR Address[46]
Definition: ping.c:68
#define MiProtoPteToPte(x)
Definition: mm.h:316
FORCEINLINE VOID MiUnlockWorkingSet(IN PETHREAD Thread, IN PMMSUPPORT WorkingSet)
Definition: miarm.h:1356
#define MI_IS_SYSTEM_PAGE_TABLE_ADDRESS(Address)
Definition: miarm.h:180
#define MI_SET_USAGE(x)
Definition: mm.h:317
ULONG64 Protection
Definition: mmtypes.h:88
void * PVOID
Definition: retypes.h:9
#define MM_ZERO_ACCESS
Definition: miarm.h:43
Status
Definition: gdiplustypes.h:24
FORCEINLINE PMMPTE MiAddressToPxe(PVOID Address)
Definition: mm.h:171
union _MMPFN::@1751 u3
struct _MM_SESSION_SPACE * GlobalVirtualAddress
Definition: miarm.h:475
ULONG CurrentProcess
Definition: shell.c:125
#define ASSERT(a)
Definition: mode.c:44
#define MI_IS_SESSION_PTE(Pte)
Definition: miarm.h:174
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define MI_GET_NEXT_PROCESS_COLOR(x)
Definition: miarm.h:238
ULONG64 Valid
Definition: mmtypes.h:150
#define MI_IS_PFN_DELETED(x)
Definition: miarm.h:195
#define STATUS_PAGE_FAULT_COPY_ON_WRITE
Definition: ntstatus.h:96
VOID NTAPI MiZeroPfn(IN PFN_NUMBER PageFrameNumber)
Definition: pagfault.c:483
HARDWARE_PTE_ARMV6 TempPte
Definition: winldr.c:76
FORCEINLINE BOOLEAN MiIsUserPte(PVOID Address)
Definition: miarm.h:730
#define MI_IS_PAGE_LARGE(x)
Definition: mm.h:104
UINT64 Rdx
Definition: ketypes.h:325
FORCEINLINE USHORT MiIncrementPageTableReferences(IN PVOID Address)
Definition: miarm.h:2478
FORCEINLINE PMMPFN MI_PFN_ELEMENT(IN PFN_NUMBER Pfn)
Definition: miarm.h:1579
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:792
#define MM_GUARDPAGE
Definition: miarm.h:57
Definition: mm.h:373
#define MI_IS_PAGE_WRITEABLE(x)
Definition: mm.h:106
#define PTE_BASE
Definition: mmx86.c:14
ULONG OwnsSystemWorkingSetExclusive
Definition: pstypes.h:1223
ULONG Ecx
Definition: ketypes.h:258
BOOLEAN MmProtectFreedNonPagedPool
Definition: pool.c:31
ULONG Eip
Definition: ketypes.h:268
FORCEINLINE PMMPFN MiGetPfnEntry(IN PFN_NUMBER Pfn)
Definition: mm.h:1020
union _MMPTE::@2282 u
UINT64 R11
Definition: ketypes.h:329
#define MI_IS_INSTRUCTION_FETCH(FaultCode)
Definition: mm.h:125
#define MI_IS_PAGE_TABLE_OR_HYPER_ADDRESS(Address)
Definition: miarm.h:183
ULONG_PTR Long
Definition: mmtypes.h:215
PVOID MmNonPagedPoolStart
Definition: init.c:24
#define MM_EXECUTE_READWRITE
Definition: miarm.h:49
FORCEINLINE VOID MI_MAKE_HARDWARE_PTE_USER(IN PMMPTE NewPte, IN PMMPTE MappingPte, IN ULONG_PTR ProtectionMask, IN PFN_NUMBER PageFrameNumber)
Definition: miarm.h:832
NTSTATUS FASTCALL MiCheckPdeForPagedPool(IN PVOID Address)
Definition: pagfault.c:475
PFN_NUMBER NTAPI MiRemoveAnyPage(IN ULONG Color)
Definition: pfnlist.c:477
MMPTE_HARDWARE Hard
Definition: mmtypes.h:217
FORCEINLINE VOID MI_WRITE_INVALID_PTE(IN PMMPTE PointerPte, IN MMPTE InvalidPte)
Definition: miarm.h:997
ULONG Ebx
Definition: ketypes.h:265
#define STATUS_ACCESS_VIOLATION
Definition: ntstatus.h:242
ULONG Sp
Definition: ketypes.h:365
static NTSTATUS NTAPI MiCheckForUserStackOverflow(IN PVOID Address, IN PVOID TrapInformation)
Definition: pagfault.c:30
PMMPTE PteAddress
Definition: mm.h:386
ULONG OwnsProcessWorkingSetShared
Definition: pstypes.h:1222
MMPTE_SOFTWARE Soft
Definition: mmtypes.h:219
#define NULL
Definition: types.h:112
MMPTE OriginalPte
Definition: mm.h:407
UINT64 Rdi
Definition: ketypes.h:375
MMPDE DemandZeroPde
Definition: init.c:36
VOID NTAPI KeRaiseIrql(KIRQL NewIrql, PKIRQL OldIrql)
Definition: spinlock.c:27
union _MMPFN::@1749 u1
ULONG R1
Definition: ketypes.h:361
#define DPRINT1
Definition: precomp.h:8
#define MI_IS_SESSION_IMAGE_ADDRESS(Address)
Definition: miarm.h:168
void * _ReturnAddress(void)
UINT64 Rip
Definition: ketypes.h:384
unsigned int ULONG
Definition: retypes.h:1
ULONG64 PageFrameNumber
Definition: mmtypes.h:171
#define MM_PROTECT_SPECIAL
Definition: miarm.h:59
ULONG OwnsProcessWorkingSetExclusive
Definition: pstypes.h:1221
#define STATUS_IN_PAGE_ERROR
Definition: ntstatus.h:243
#define STATUS_SUCCESS
Definition: shellext.h:65
ULONG MmSizeOfNonPagedPoolInBytes
Definition: init.c:21
FORCEINLINE VOID MiLockWorkingSet(IN PETHREAD Thread, IN PMMSUPPORT WorkingSet)
Definition: miarm.h:1270
PMMPTE MiHighestUserPte
Definition: mminit.c:233
#define DPRINT
Definition: sndvol32.h:71
VOID NTAPI KeLowerIrql(KIRQL NewIrql)
Definition: spinlock.c:39
static NTSTATUS NTAPI MiResolveDemandZeroFault(IN PVOID Address, IN PMMPTE PointerPte, IN ULONG Protection, IN PEPROCESS Process, IN KIRQL OldIrql)
Definition: pagfault.c:595
UINT64 Rcx
Definition: ketypes.h:324
#define MM_READONLY
Definition: bootanim.c:18
#define STATUS_PAGE_FAULT_DEMAND_ZERO
Definition: ntstatus.h:95
#define APC_LEVEL
Definition: env_spec_w32.h:695
#define PFN_FROM_PTE(v)
Definition: mm.h:92
#define MmSystemRangeStart
Definition: mm.h:32
ULONG EFlags
Definition: ketypes.h:389
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
ULONG Edx
Definition: ketypes.h:257
FORCEINLINE VOID MI_MAKE_HARDWARE_PTE(IN PMMPTE NewPte, IN PMMPTE MappingPte, IN ULONG_PTR ProtectionMask, IN PFN_NUMBER PageFrameNumber)
Definition: miarm.h:812
FORCEINLINE VOID MiUnlockProcessWorkingSet(IN PEPROCESS Process, IN PETHREAD Thread)
Definition: miarm.h:1199
ULONG PageFrameNumber
Definition: mmtypes.h:109

Referenced by MmAccessFault().

◆ MmGetExecuteOptions()

NTSTATUS NTAPI MmGetExecuteOptions ( IN PULONG  ExecuteOptions)

Definition at line 2579 of file pagfault.c.

2580 {
2583 
2584  *ExecuteOptions = 0;
2585 
2586  if (CurrentProcess->Flags.ExecuteDisable)
2587  {
2588  *ExecuteOptions |= MEM_EXECUTE_OPTION_DISABLE;
2589  }
2590 
2591  if (CurrentProcess->Flags.ExecuteEnable)
2592  {
2593  *ExecuteOptions |= MEM_EXECUTE_OPTION_ENABLE;
2594  }
2595 
2596  if (CurrentProcess->Flags.DisableThunkEmulation)
2597  {
2598  *ExecuteOptions |= MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION;
2599  }
2600 
2601  if (CurrentProcess->Flags.Permanent)
2602  {
2603  *ExecuteOptions |= MEM_EXECUTE_OPTION_PERMANENT;
2604  }
2605 
2606  if (CurrentProcess->Flags.ExecuteDispatchEnable)
2607  {
2608  *ExecuteOptions |= MEM_EXECUTE_OPTION_EXECUTE_DISPATCH_ENABLE;
2609  }
2610 
2611  if (CurrentProcess->Flags.ImageDispatchEnable)
2612  {
2613  *ExecuteOptions |= MEM_EXECUTE_OPTION_IMAGE_DISPATCH_ENABLE;
2614  }
2615 
2616  return STATUS_SUCCESS;
2617 }
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
#define MEM_EXECUTE_OPTION_IMAGE_DISPATCH_ENABLE
Definition: mmtypes.h:78
#define MEM_EXECUTE_OPTION_EXECUTE_DISPATCH_ENABLE
Definition: mmtypes.h:77
#define PsGetCurrentProcess
Definition: psfuncs.h:17
#define MEM_EXECUTE_OPTION_ENABLE
Definition: mmtypes.h:74
ULONG CurrentProcess
Definition: shell.c:125
#define ASSERT(a)
Definition: mode.c:44
#define MEM_EXECUTE_OPTION_DISABLE
Definition: mmtypes.h:73
#define PASSIVE_LEVEL
Definition: env_spec_w32.h:693
#define MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION
Definition: mmtypes.h:75
#define MEM_EXECUTE_OPTION_PERMANENT
Definition: mmtypes.h:76
#define STATUS_SUCCESS
Definition: shellext.h:65

Referenced by NtQueryInformationProcess().

◆ MmSetExecuteOptions()

NTSTATUS NTAPI MmSetExecuteOptions ( IN ULONG  ExecuteOptions)

Definition at line 2621 of file pagfault.c.

2622 {
2624  KLOCK_QUEUE_HANDLE ProcessLock;
2627 
2628  /* Only accept valid flags */
2629  if (ExecuteOptions & ~MEM_EXECUTE_OPTION_VALID_FLAGS)
2630  {
2631  /* Fail */
2632  DPRINT1("Invalid no-execute options\n");
2633  return STATUS_INVALID_PARAMETER;
2634  }
2635 
2636  /* Change the NX state in the process lock */
2638 
2639  /* Don't change anything if the permanent flag was set */
2640  if (!CurrentProcess->Flags.Permanent)
2641  {
2642  /* Start by assuming it's not disabled */
2643  CurrentProcess->Flags.ExecuteDisable = FALSE;
2644 
2645  /* Now process each flag and turn the equivalent bit on */
2646  if (ExecuteOptions & MEM_EXECUTE_OPTION_DISABLE)
2647  {
2648  CurrentProcess->Flags.ExecuteDisable = TRUE;
2649  }
2650  if (ExecuteOptions & MEM_EXECUTE_OPTION_ENABLE)
2651  {
2652  CurrentProcess->Flags.ExecuteEnable = TRUE;
2653  }
2654  if (ExecuteOptions & MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION)
2655  {
2656  CurrentProcess->Flags.DisableThunkEmulation = TRUE;
2657  }
2658  if (ExecuteOptions & MEM_EXECUTE_OPTION_PERMANENT)
2659  {
2660  CurrentProcess->Flags.Permanent = TRUE;
2661  }
2662  if (ExecuteOptions & MEM_EXECUTE_OPTION_EXECUTE_DISPATCH_ENABLE)
2663  {
2664  CurrentProcess->Flags.ExecuteDispatchEnable = TRUE;
2665  }
2666  if (ExecuteOptions & MEM_EXECUTE_OPTION_IMAGE_DISPATCH_ENABLE)
2667  {
2668  CurrentProcess->Flags.ImageDispatchEnable = TRUE;
2669  }
2670 
2671  /* These are turned on by default if no-execution is also eanbled */
2672  if (CurrentProcess->Flags.ExecuteEnable)
2673  {
2674  CurrentProcess->Flags.ExecuteDispatchEnable = TRUE;
2675  CurrentProcess->Flags.ImageDispatchEnable = TRUE;
2676  }
2677 
2678  /* All good */
2680  }
2681 
2682  /* Release the lock and return status */
2683  KiReleaseProcessLock(&ProcessLock);
2684  return Status;
2685 }
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
#define MEM_EXECUTE_OPTION_IMAGE_DISPATCH_ENABLE
Definition: mmtypes.h:78
FORCEINLINE VOID KiAcquireProcessLockRaiseToSynch(IN PKPROCESS Process, IN PKLOCK_QUEUE_HANDLE Handle)
Definition: ke_x.h:651
#define TRUE
Definition: types.h:120
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define MEM_EXECUTE_OPTION_EXECUTE_DISPATCH_ENABLE
Definition: mmtypes.h:77
LONG NTSTATUS
Definition: precomp.h:26
#define MEM_EXECUTE_OPTION_VALID_FLAGS
Definition: mmtypes.h:79
#define FALSE
Definition: types.h:117
#define PsGetCurrentProcess
Definition: psfuncs.h:17
#define MEM_EXECUTE_OPTION_ENABLE
Definition: mmtypes.h:74
Status
Definition: gdiplustypes.h:24
ULONG CurrentProcess
Definition: shell.c:125
#define ASSERT(a)
Definition: mode.c:44
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
FORCEINLINE VOID KiReleaseProcessLock(IN PKLOCK_QUEUE_HANDLE Handle)
Definition: ke_x.h:660
#define MEM_EXECUTE_OPTION_DISABLE
Definition: mmtypes.h:73
#define PASSIVE_LEVEL
Definition: env_spec_w32.h:693
#define MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION
Definition: mmtypes.h:75
#define MEM_EXECUTE_OPTION_PERMANENT
Definition: mmtypes.h:76
#define DPRINT1
Definition: precomp.h:8
#define STATUS_SUCCESS
Definition: shellext.h:65

Referenced by NtSetInformationProcess().