ReactOS  0.4.15-dev-2991-g632fa1c
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:1739
#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::@2547 u
#define MiAddressToPte(x)
Definition: mmx86.c:19
PMMPTE LastPteForPagedPool
Definition: mm.h:478
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
union _MMVAD::@2548 u2
MMVAD_FLAGS2 VadFlags2
Definition: mmtypes.h:739
ULONG_PTR MemCommit
Definition: mmtypes.h:692
#define MM_READONLY
Definition: inbv.c:11
ULONG_PTR PrivateMemory
Definition: mmtypes.h:695
#define ASSERT(a)
Definition: mode.c:44
struct _MMPTE * PMMPTE
#define PAGE_ALIGN(Va)
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
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 758 of file pagfault.c.

764 {
765  MMPTE TempPte;
766  PMMPTE OriginalPte, PageTablePte;
767  ULONG_PTR Protection;
768  PFN_NUMBER PageFrameIndex;
769  PMMPFN Pfn1, Pfn2;
770  BOOLEAN OriginalProtection, DirtyPage;
771 
772  /* Must be called with an valid prototype PTE, with the PFN lock held */
774  ASSERT(PointerProtoPte->u.Hard.Valid == 1);
775 
776  /* Get the page */
777  PageFrameIndex = PFN_FROM_PTE(PointerProtoPte);
778 
779  /* Get the PFN entry and set it as a prototype PTE */
780  Pfn1 = MiGetPfnEntry(PageFrameIndex);
781  Pfn1->u3.e1.PrototypePte = 1;
782 
783  /* Increment the share count for the page table */
784  PageTablePte = MiAddressToPte(PointerPte);
785  Pfn2 = MiGetPfnEntry(PageTablePte->u.Hard.PageFrameNumber);
786  Pfn2->u2.ShareCount++;
787 
788  /* Check where we should be getting the protection information from */
789  if (PointerPte->u.Soft.PageFileHigh == MI_PTE_LOOKUP_NEEDED)
790  {
791  /* Get the protection from the PTE, there's no real Proto PTE data */
792  Protection = PointerPte->u.Soft.Protection;
793 
794  /* Remember that we did not use the proto protection */
795  OriginalProtection = FALSE;
796  }
797  else
798  {
799  /* Get the protection from the original PTE link */
800  OriginalPte = &Pfn1->OriginalPte;
801  Protection = OriginalPte->u.Soft.Protection;
802 
803  /* Remember that we used the original protection */
804  OriginalProtection = TRUE;
805 
806  /* Check if this was a write on a read only proto */
807  if ((StoreInstruction) && !(Protection & MM_READWRITE))
808  {
809  /* Clear the flag */
810  StoreInstruction = 0;
811  }
812  }
813 
814  /* Check if this was a write on a non-COW page */
815  DirtyPage = FALSE;
816  if ((StoreInstruction) && ((Protection & MM_WRITECOPY) != MM_WRITECOPY))
817  {
818  /* Then the page should be marked dirty */
819  DirtyPage = TRUE;
820 
821  /* ReactOS check */
822  ASSERT(Pfn1->OriginalPte.u.Soft.Prototype != 0);
823  }
824 
825  /* Did we get a locked incoming PFN? */
826  if (*LockedProtoPfn)
827  {
828  /* Drop a reference */
829  ASSERT((*LockedProtoPfn)->u3.e2.ReferenceCount >= 1);
830  MiDereferencePfnAndDropLockCount(*LockedProtoPfn);
831  *LockedProtoPfn = NULL;
832  }
833 
834  /* Release the PFN lock */
835  MiReleasePfnLock(OldIrql);
836 
837  /* Remove special/caching bits */
838  Protection &= ~MM_PROTECT_SPECIAL;
839 
840  /* Setup caching */
841  if (Pfn1->u3.e1.CacheAttribute == MiWriteCombined)
842  {
843  /* Write combining, no caching */
846  }
847  else if (Pfn1->u3.e1.CacheAttribute == MiNonCached)
848  {
849  /* Write through, no caching */
852  }
853 
854  /* Check if this is a kernel or user address */
856  {
857  /* Build the user PTE */
858  MI_MAKE_HARDWARE_PTE_USER(&TempPte, PointerPte, Protection, PageFrameIndex);
859  }
860  else
861  {
862  /* Build the kernel PTE */
863  MI_MAKE_HARDWARE_PTE(&TempPte, PointerPte, Protection, PageFrameIndex);
864  }
865 
866  /* Set the dirty flag if needed */
867  if (DirtyPage) MI_MAKE_DIRTY_PAGE(&TempPte);
868 
869  /* Write the PTE */
870  MI_WRITE_VALID_PTE(PointerPte, TempPte);
871 
872  /* Reset the protection if needed */
873  if (OriginalProtection) Protection = MM_ZERO_ACCESS;
874 
875  /* Return success */
876  ASSERT(PointerPte == MiAddressToPte(Address));
877  return STATUS_SUCCESS;
878 }
#define MI_PAGE_WRITE_COMBINED(x)
Definition: mm.h:103
#define MI_ASSERT_PFN_LOCK_HELD()
Definition: mm.h:996
FORCEINLINE VOID MiDereferencePfnAndDropLockCount(IN PMMPFN Pfn1)
Definition: miarm.h:1620
#define TRUE
Definition: types.h:120
union _MMPFN::@1761 u3
#define MI_PTE_LOOKUP_NEEDED
Definition: miarm.h:246
uint32_t ULONG_PTR
Definition: typedefs.h:65
USHORT PrototypePte
Definition: mm.h:352
MMPFNENTRY e1
Definition: mm.h:386
#define MI_MAKE_DIRTY_PAGE(x)
Definition: mm.h:98
#define MM_WRITECOPY
Definition: miarm.h:48
USHORT CacheAttribute
Definition: mm.h:356
#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:379
unsigned char BOOLEAN
static WCHAR Address[46]
Definition: ping.c:68
ULONG64 Protection
Definition: mmtypes.h:88
union _MMPFN::@1760 u2
KIRQL OldIrql
Definition: mm.h:1502
#define MM_ZERO_ACCESS
Definition: miarm.h:43
#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
#define MM_READWRITE
Definition: inbv.c:12
Definition: mm.h:362
ULONG64 Prototype
Definition: mmtypes.h:89
FORCEINLINE PMMPFN MiGetPfnEntry(IN PFN_NUMBER Pfn)
Definition: mm.h:1000
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:396
ULONG64 PageFrameNumber
Definition: mmtypes.h:171
#define MM_PROTECT_SPECIAL
Definition: miarm.h:59
#define STATUS_SUCCESS
Definition: shellext.h:65
union _MMPTE::@2287 u
#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
union _MMPFN::@1761 u3
MMPFNENTRY e1
Definition: mm.h:386
USHORT CacheAttribute
Definition: mm.h:356
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
#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:362
#define PAGE_SIZE
Definition: env_spec_w32.h:49
FORCEINLINE PMMPFN MiGetPfnEntry(IN PFN_NUMBER Pfn)
Definition: mm.h:1000
#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:201
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 1312 of file pagfault.c.

1320 {
1321  MMPTE TempPte;
1322  KIRQL OldIrql, LockIrql;
1323  NTSTATUS Status;
1324  PMMPTE SuperProtoPte;
1325  PMMPFN Pfn1, OutPfn = NULL;
1326  PFN_NUMBER PageFrameIndex;
1327  PFN_COUNT PteCount, ProcessedPtes;
1328  DPRINT("ARM3 Page Fault Dispatcher for address: %p in process: %p\n",
1329  Address,
1330  Process);
1331 
1332  /* Make sure the addresses are ok */
1333  ASSERT(PointerPte == MiAddressToPte(Address));
1334 
1335  //
1336  // Make sure APCs are off and we're not at dispatch
1337  //
1339  ASSERT(OldIrql <= APC_LEVEL);
1341 
1342  //
1343  // Grab a copy of the PTE
1344  //
1345  TempPte = *PointerPte;
1346 
1347  /* Do we have a prototype PTE? */
1348  if (PointerProtoPte)
1349  {
1350  /* This should never happen */
1351  ASSERT(!MI_IS_PHYSICAL_ADDRESS(PointerProtoPte));
1352 
1353  /* Check if this is a kernel-mode address */
1354  SuperProtoPte = MiAddressToPte(PointerProtoPte);
1355  if (Address >= MmSystemRangeStart)
1356  {
1357  /* Lock the PFN database */
1358  LockIrql = MiAcquirePfnLock();
1359 
1360  /* Has the PTE been made valid yet? */
1361  if (!SuperProtoPte->u.Hard.Valid)
1362  {
1363  ASSERT(FALSE);
1364  }
1365  else if (PointerPte->u.Hard.Valid == 1)
1366  {
1367  ASSERT(FALSE);
1368  }
1369 
1370  /* Resolve the fault -- this will release the PFN lock */
1372  Address,
1373  PointerPte,
1374  PointerProtoPte,
1375  &OutPfn,
1376  NULL,
1377  NULL,
1378  Process,
1379  LockIrql,
1380  TrapInformation);
1382 
1383  /* Complete this as a transition fault */
1385  ASSERT(OldIrql <= APC_LEVEL);
1387  return Status;
1388  }
1389  else
1390  {
1391  /* We only handle the lookup path */
1392  ASSERT(PointerPte->u.Soft.PageFileHigh == MI_PTE_LOOKUP_NEEDED);
1393 
1394  /* Is there a non-image VAD? */
1395  if ((Vad) &&
1396  (Vad->u.VadFlags.VadType != VadImageMap) &&
1397  !(Vad->u2.VadFlags2.ExtendableFile))
1398  {
1399  /* One day, ReactOS will cluster faults */
1401  DPRINT("Should cluster fault, but won't\n");
1402  }
1403 
1404  /* Only one PTE to handle for now */
1405  PteCount = 1;
1406  ProcessedPtes = 0;
1407 
1408  /* Lock the PFN database */
1409  LockIrql = MiAcquirePfnLock();
1410 
1411  /* We only handle the valid path */
1412  ASSERT(SuperProtoPte->u.Hard.Valid == 1);
1413 
1414  /* Capture the PTE */
1415  TempPte = *PointerProtoPte;
1416 
1417  /* Loop to handle future case of clustered faults */
1418  while (TRUE)
1419  {
1420  /* For our current usage, this should be true */
1421  if (TempPte.u.Hard.Valid == 1)
1422  {
1423  /* Bump the share count on the PTE */
1424  PageFrameIndex = PFN_FROM_PTE(&TempPte);
1425  Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);
1426  Pfn1->u2.ShareCount++;
1427  }
1428  else if ((TempPte.u.Soft.Prototype == 0) &&
1429  (TempPte.u.Soft.Transition == 1))
1430  {
1431  /* This is a standby page, bring it back from the cache */
1432  PageFrameIndex = TempPte.u.Trans.PageFrameNumber;
1433  DPRINT("oooh, shiny, a soft fault! 0x%lx\n", PageFrameIndex);
1434  Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);
1436 
1437  /* Should not yet happen in ReactOS */
1438  ASSERT(Pfn1->u3.e1.ReadInProgress == 0);
1439  ASSERT(Pfn1->u4.InPageError == 0);
1440 
1441  /* Get the page */
1442  MiUnlinkPageFromList(Pfn1);
1443 
1444  /* Bump its reference count */
1445  ASSERT(Pfn1->u2.ShareCount == 0);
1446  InterlockedIncrement16((PSHORT)&Pfn1->u3.e2.ReferenceCount);
1447  Pfn1->u2.ShareCount++;
1448 
1449  /* Make it valid again */
1450  /* This looks like another macro.... */
1451  Pfn1->u3.e1.PageLocation = ActiveAndValid;
1452  ASSERT(PointerProtoPte->u.Hard.Valid == 0);
1453  ASSERT(PointerProtoPte->u.Trans.Prototype == 0);
1454  ASSERT(PointerProtoPte->u.Trans.Transition == 1);
1455  TempPte.u.Long = (PointerProtoPte->u.Long & ~0xFFF) |
1456  MmProtectToPteMask[PointerProtoPte->u.Trans.Protection];
1457  TempPte.u.Hard.Valid = 1;
1459 
1460  /* Is the PTE writeable? */
1461  if ((Pfn1->u3.e1.Modified) &&
1464  {
1465  /* Make it dirty */
1467  }
1468  else
1469  {
1470  /* Make it clean */
1472  }
1473 
1474  /* Write the valid PTE */
1475  MI_WRITE_VALID_PTE(PointerProtoPte, TempPte);
1476  ASSERT(PointerPte->u.Hard.Valid == 0);
1477  }
1478  else
1479  {
1480  /* Page is invalid, get out of the loop */
1481  break;
1482  }
1483 
1484  /* One more done, was it the last? */
1485  if (++ProcessedPtes == PteCount)
1486  {
1487  /* Complete the fault */
1489  Address,
1490  PointerPte,
1491  PointerProtoPte,
1492  LockIrql,
1493  &OutPfn);
1494 
1495  /* THIS RELEASES THE PFN LOCK! */
1496  break;
1497  }
1498 
1499  /* No clustered faults yet */
1500  ASSERT(FALSE);
1501  }
1502 
1503  /* Did we resolve the fault? */
1504  if (ProcessedPtes)
1505  {
1506  /* Bump the transition count */
1507  InterlockedExchangeAddSizeT(&KeGetCurrentPrcb()->MmTransitionCount, ProcessedPtes);
1508  ProcessedPtes--;
1509 
1510  /* Loop all the processing we did */
1511  ASSERT(ProcessedPtes == 0);
1512 
1513  /* Complete this as a transition fault */
1515  ASSERT(OldIrql <= APC_LEVEL);
1518  }
1519 
1520  /* We did not -- PFN lock is still held, prepare to resolve prototype PTE fault */
1521  OutPfn = MI_PFN_ELEMENT(SuperProtoPte->u.Hard.PageFrameNumber);
1523  ASSERT(OutPfn->u3.e2.ReferenceCount > 1);
1524  ASSERT(PointerPte->u.Hard.Valid == 0);
1525 
1526  /* Resolve the fault -- this will release the PFN lock */
1528  Address,
1529  PointerPte,
1530  PointerProtoPte,
1531  &OutPfn,
1532  NULL,
1533  NULL,
1534  Process,
1535  LockIrql,
1536  TrapInformation);
1537  //ASSERT(Status != STATUS_ISSUE_PAGING_IO);
1538  //ASSERT(Status != STATUS_REFAULT);
1539  //ASSERT(Status != STATUS_PTE_CHANGED);
1540 
1541  /* Did the routine clean out the PFN or should we? */
1542  if (OutPfn)
1543  {
1544  /* We had a locked PFN, so acquire the PFN lock to dereference it */
1545  ASSERT(PointerProtoPte != NULL);
1546  OldIrql = MiAcquirePfnLock();
1547 
1548  /* Dereference the locked PFN */
1550  ASSERT(OutPfn->u3.e2.ReferenceCount >= 1);
1551 
1552  /* And now release the lock */
1553  MiReleasePfnLock(OldIrql);
1554  }
1555 
1556  /* Complete this as a transition fault */
1558  ASSERT(OldIrql <= APC_LEVEL);
1560  return Status;
1561  }
1562  }
1563 
1564  /* Is this a transition PTE */
1565  if (TempPte.u.Soft.Transition)
1566  {
1567  PKEVENT* InPageBlock = NULL;
1568  PKEVENT PreviousPageEvent;
1569  KEVENT CurrentPageEvent;
1570 
1571  /* Lock the PFN database */
1572  LockIrql = MiAcquirePfnLock();
1573 
1574  /* Resolve */
1575  Status = MiResolveTransitionFault(!MI_IS_NOT_PRESENT_FAULT(FaultCode), Address, PointerPte, Process, LockIrql, &InPageBlock);
1576 
1578 
1579  if (InPageBlock != NULL)
1580  {
1581  /* Another thread is reading or writing this page. Put us into the waiting queue. */
1582  KeInitializeEvent(&CurrentPageEvent, NotificationEvent, FALSE);
1583  PreviousPageEvent = *InPageBlock;
1584  *InPageBlock = &CurrentPageEvent;
1585  }
1586 
1587  /* And now release the lock and leave*/
1588  MiReleasePfnLock(LockIrql);
1589 
1590  if (InPageBlock != NULL)
1591  {
1592  KeWaitForSingleObject(&CurrentPageEvent, WrPageIn, KernelMode, FALSE, NULL);
1593 
1594  /* Let's the chain go on */
1595  if (PreviousPageEvent)
1596  {
1597  KeSetEvent(PreviousPageEvent, IO_NO_INCREMENT, FALSE);
1598  }
1599  }
1600 
1602  ASSERT(OldIrql <= APC_LEVEL);
1604  return Status;
1605  }
1606 
1607  /* Should we page the data back in ? */
1608  if (TempPte.u.Soft.PageFileHigh != 0)
1609  {
1610  /* Lock the PFN database */
1611  LockIrql = MiAcquirePfnLock();
1612 
1613  /* Resolve */
1614  Status = MiResolvePageFileFault(!MI_IS_NOT_PRESENT_FAULT(FaultCode), Address, PointerPte, Process, &LockIrql);
1615 
1616  /* And now release the lock and leave*/
1617  MiReleasePfnLock(LockIrql);
1618 
1620  ASSERT(OldIrql <= APC_LEVEL);
1622  return Status;
1623  }
1624 
1625  //
1626  // The PTE must be invalid but not completely empty. It must also not be a
1627  // prototype a transition or a paged-out PTE as those scenarii should've been handled above.
1628  // These are all Windows checks
1629  //
1630  ASSERT(TempPte.u.Hard.Valid == 0);
1631  ASSERT(TempPte.u.Soft.Prototype == 0);
1632  ASSERT(TempPte.u.Soft.Transition == 0);
1633  ASSERT(TempPte.u.Soft.PageFileHigh == 0);
1634  ASSERT(TempPte.u.Long != 0);
1635 
1636  //
1637  // If we got this far, the PTE can only be a demand zero PTE, which is what
1638  // we want. Go handle it!
1639  //
1641  PointerPte,
1642  (ULONG)TempPte.u.Soft.Protection,
1643  Process,
1644  MM_NOIRQL);
1646  if (NT_SUCCESS(Status))
1647  {
1648 #if MI_TRACE_PFNS
1649  /* Update debug info */
1650  if (TrapInformation)
1651  MiGetPfnEntry(PointerPte->u.Hard.PageFrameNumber)->CallSite = (PVOID)((PKTRAP_FRAME)TrapInformation)->Eip;
1652  else
1653  MiGetPfnEntry(PointerPte->u.Hard.PageFrameNumber)->CallSite = _ReturnAddress();
1654 #endif
1655 
1656  //
1657  // Make sure we're returning in a sane state and pass the status down
1658  //
1661  return Status;
1662  }
1663 
1664  //
1665  // Generate an access fault
1666  //
1667  return STATUS_ACCESS_VIOLATION;
1668 }
#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:883
USHORT ReadInProgress
Definition: mm.h:350
LONG NTSTATUS
Definition: precomp.h:26
FORCEINLINE struct _KPRCB * KeGetCurrentPrcb(VOID)
Definition: ketypes.h:1079
union _MMPFN::@1761 u3
#define MI_PTE_LOOKUP_NEEDED
Definition: miarm.h:246
USHORT Modified
Definition: mm.h:349
#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:354
UCHAR KIRQL
Definition: env_spec_w32.h:591
MMPFNENTRY e1
Definition: mm.h:386
#define MI_MAKE_DIRTY_PAGE(x)
Definition: mm.h:98
#define MiAddressToPte(x)
Definition: mmx86.c:19
#define MM_NOIRQL
Definition: mm.h:59
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:379
#define STATUS_PAGE_FAULT_TRANSITION
Definition: ntstatus.h:94
static WCHAR Address[46]
Definition: ping.c:68
void * PVOID
Definition: retypes.h:9
union _MMPFN::@1760 u2
KIRQL OldIrql
Definition: mm.h:1502
Status
Definition: gdiplustypes.h:24
#define ASSERT(a)
Definition: mode.c:44
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
ULONG64 Valid
Definition: mmtypes.h:150
#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
Definition: mm.h:362
#define MI_IS_PAGE_WRITEABLE(x)
Definition: mm.h:106
FORCEINLINE PMMPFN MiGetPfnEntry(IN PFN_NUMBER Pfn)
Definition: mm.h:1000
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
struct _MMPFN::@1761::@1767 e2
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:971
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:758
#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:1103
ULONG64 PageFrameNumber
Definition: mmtypes.h:171
ULONG_PTR InPageError
Definition: mm.h:408
#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
FORCEINLINE BOOLEAN MI_IS_PHYSICAL_ADDRESS(IN PVOID Address)
Definition: miarm.h:950
union _MMPTE::@2287 u
#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
union _MMPFN::@1764 u4

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
unsigned char UCHAR
Definition: xmlstorage.h:181
static INT Execute(LPTSTR Full, LPTSTR First, LPTSTR Rest, PARSED_COMMAND *Cmd)
Definition: cmd.c:347

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  }
678  else
679  {
680  /* Get a color, and see if we should grab a zero or non-zero page */
682  if (!NeedZero)
683  {
684  /* Process or system doesn't want a zero page, grab anything */
685  PageFrameNumber = MiRemoveAnyPage(Color);
686  }
687  else
688  {
689  /* System wants a zero page, obtain one */
690  PageFrameNumber = MiRemoveZeroPage(Color);
691  }
692  }
693 
694  /* Initialize it */
695  MiInitializePfn(PageFrameNumber, PointerPte, TRUE);
696 
697  /* Increment demand zero faults */
698  KeGetCurrentPrcb()->MmDemandZeroCount++;
699 
700  /* Do we have the lock? */
701  if (HaveLock)
702  {
703  /* Release it */
704  MiReleasePfnLock(OldIrql);
705 
706  /* Update performance counters */
707  if (Process > HYDRA_PROCESS) Process->NumberOfPrivatePages++;
708  }
709 
710  /* Zero the page if need be */
711  if (NeedZero) MiZeroPfn(PageFrameNumber);
712 
713  /* Fault on user PDE, or fault on user PTE? */
714  if (PointerPte <= MiHighestUserPte)
715  {
716  /* User fault, build a user PTE */
718  PointerPte,
719  Protection,
720  PageFrameNumber);
721  }
722  else
723  {
724  /* This is a user-mode PDE, create a kernel PTE for it */
726  PointerPte,
727  Protection,
728  PageFrameNumber);
729  }
730 
731  /* Set it dirty if it's a writable page */
733 
734  /* Write it */
735  MI_WRITE_VALID_PTE(PointerPte, TempPte);
736 
737  /* Did we manually acquire the lock */
738  if (HaveLock)
739  {
740  /* Get the PFN entry */
741  Pfn1 = MI_PFN_ELEMENT(PageFrameNumber);
742 
743  /* Windows does these sanity checks */
744  ASSERT(Pfn1->u1.Event == 0);
745  ASSERT(Pfn1->u3.e1.PrototypePte == 0);
746  }
747 
748  //
749  // It's all good now
750  //
751  DPRINT("Demand zero page has now been paged in\n");
753 }
#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:972
#define MI_ASSERT_PFN_LOCK_HELD()
Definition: mm.h:996
#define TRUE
Definition: types.h:120
#define HYDRA_PROCESS
Definition: pagfault.c:20
FORCEINLINE struct _KPRCB * KeGetCurrentPrcb(VOID)
Definition: ketypes.h:1079
union _MMPFN::@1761 u3
#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:352
MMPFNENTRY e1
Definition: mm.h:386
#define MI_MAKE_DIRTY_PAGE(x)
Definition: mm.h:98
#define MM_NOIRQL
Definition: mm.h:59
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:368
#define MI_SET_PROCESS2(x)
Definition: mm.h:308
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:306
KIRQL OldIrql
Definition: mm.h:1502
#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
Definition: mm.h:362
#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::@1759 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 883 of file pagfault.c.

888 {
889  ULONG Color;
892  MMPTE TempPte = *PointerPte;
893  PMMPFN Pfn1;
894  ULONG PageFileIndex = TempPte.u.Soft.PageFileLow;
895  ULONG_PTR PageFileOffset = TempPte.u.Soft.PageFileHigh;
896  ULONG Protection = TempPte.u.Soft.Protection;
897 
898  /* Things we don't support yet */
900  ASSERT(*OldIrql != MM_NOIRQL);
901 
904 
905  /* We must hold the PFN lock */
907 
908  /* Some sanity checks */
909  ASSERT(TempPte.u.Hard.Valid == 0);
910  ASSERT(TempPte.u.Soft.PageFileHigh != 0);
911  ASSERT(TempPte.u.Soft.PageFileHigh != MI_PTE_LOOKUP_NEEDED);
912 
913  /* Get any page, it will be overwritten */
916 
917  /* Initialize this PFN */
918  MiInitializePfn(Page, PointerPte, StoreInstruction);
919 
920  /* Sets the PFN as being in IO operation */
921  Pfn1 = MI_PFN_ELEMENT(Page);
922  ASSERT(Pfn1->u1.Event == NULL);
923  ASSERT(Pfn1->u3.e1.ReadInProgress == 0);
924  ASSERT(Pfn1->u3.e1.WriteInProgress == 0);
925  Pfn1->u3.e1.ReadInProgress = 1;
926 
927  /* We must write the PTE now as the PFN lock will be released while performing the IO operation */
928  MI_MAKE_TRANSITION_PTE(&TempPte, Page, Protection);
929 
930  MI_WRITE_INVALID_PTE(PointerPte, TempPte);
931 
932  /* Release the PFN lock while we proceed */
933  MiReleasePfnLock(*OldIrql);
934 
935  /* Do the paging IO */
936  Status = MiReadPageFile(Page, PageFileIndex, PageFileOffset);
937 
938  /* Lock the PFN database again */
939  *OldIrql = MiAcquirePfnLock();
940 
941  /* Nobody should have changed that while we were not looking */
942  ASSERT(Pfn1->u3.e1.ReadInProgress == 1);
943  ASSERT(Pfn1->u3.e1.WriteInProgress == 0);
944 
945  if (!NT_SUCCESS(Status))
946  {
947  /* Malheur! */
948  ASSERT(FALSE);
949  Pfn1->u4.InPageError = 1;
950  Pfn1->u1.ReadStatus = Status;
951  }
952 
953  /* And the PTE can finally be valid */
954  MI_MAKE_HARDWARE_PTE(&TempPte, PointerPte, Protection, Page);
955  MI_WRITE_VALID_PTE(PointerPte, TempPte);
956 
957  Pfn1->u3.e1.ReadInProgress = 0;
958  /* Did someone start to wait on us while we proceeded ? */
959  if (Pfn1->u1.Event)
960  {
961  /* Tell them we're done */
963  }
964 
965  return Status;
966 }
VOID NTAPI MiInitializePfn(IN PFN_NUMBER PageFrameIndex, IN PMMPTE PointerPte, IN BOOLEAN Modified)
Definition: pfnlist.c:972
#define MI_ASSERT_PFN_LOCK_HELD()
Definition: mm.h:996
USHORT ReadInProgress
Definition: mm.h:350
#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
union _MMPFN::@1761 u3
#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:386
#define MM_NOIRQL
Definition: mm.h:59
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:307
PKEVENT Event
Definition: mm.h:368
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:4888
#define MI_SET_USAGE(x)
Definition: mm.h:306
USHORT WriteInProgress
Definition: mm.h:351
KIRQL OldIrql
Definition: mm.h:1502
Status
Definition: gdiplustypes.h:24
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
HARDWARE_PTE_ARMV6 TempPte
Definition: winldr.c:76
FORCEINLINE PMMPFN MI_PFN_ELEMENT(IN PFN_NUMBER Pfn)
Definition: miarm.h:1579
Definition: mm.h:362
NTSTATUS ReadStatus
Definition: mm.h:369
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::@1759 u1
unsigned int ULONG
Definition: retypes.h:1
#define IO_NO_INCREMENT
Definition: iotypes.h:598
ULONG_PTR InPageError
Definition: mm.h:408
FORCEINLINE VOID MI_MAKE_HARDWARE_PTE(IN PMMPTE NewPte, IN PMMPTE MappingPte, IN ULONG_PTR ProtectionMask, IN PFN_NUMBER PageFrameNumber)
Definition: miarm.h:812
union _MMPFN::@1764 u4

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 1103 of file pagfault.c.

1113 {
1114  MMPTE TempPte, PteContents;
1115  PMMPFN Pfn1;
1116  PFN_NUMBER PageFrameIndex;
1117  NTSTATUS Status;
1118  PKEVENT* InPageBlock = NULL;
1119  ULONG Protection;
1120 
1121  /* Must be called with an invalid, prototype PTE, with the PFN lock held */
1123  ASSERT(PointerPte->u.Hard.Valid == 0);
1124  ASSERT(PointerPte->u.Soft.Prototype == 1);
1125 
1126  /* Read the prototype PTE and check if it's valid */
1127  TempPte = *PointerProtoPte;
1128  if (TempPte.u.Hard.Valid == 1)
1129  {
1130  /* One more user of this mapped page */
1131  PageFrameIndex = PFN_FROM_PTE(&TempPte);
1132  Pfn1 = MiGetPfnEntry(PageFrameIndex);
1133  Pfn1->u2.ShareCount++;
1134 
1135  /* Call it a transition */
1136  InterlockedIncrement(&KeGetCurrentPrcb()->MmTransitionCount);
1137 
1138  /* Complete the prototype PTE fault -- this will release the PFN lock */
1139  return MiCompleteProtoPteFault(StoreInstruction,
1140  Address,
1141  PointerPte,
1142  PointerProtoPte,
1143  OldIrql,
1144  OutPfn);
1145  }
1146 
1147  /* Make sure there's some protection mask */
1148  if (TempPte.u.Long == 0)
1149  {
1150  /* Release the lock */
1151  DPRINT1("Access on reserved section?\n");
1152  MiReleasePfnLock(OldIrql);
1153  return STATUS_ACCESS_VIOLATION;
1154  }
1155 
1156  /* There is no such thing as a decommitted prototype PTE */
1157  ASSERT(TempPte.u.Long != MmDecommittedPte.u.Long);
1158 
1159  /* Check for access rights on the PTE proper */
1160  PteContents = *PointerPte;
1161  if (PteContents.u.Soft.PageFileHigh != MI_PTE_LOOKUP_NEEDED)
1162  {
1163  if (!PteContents.u.Proto.ReadOnly)
1164  {
1165  Protection = TempPte.u.Soft.Protection;
1166  }
1167  else
1168  {
1169  Protection = MM_READONLY;
1170  }
1171  /* Check for page acess in software */
1172  Status = MiAccessCheck(PointerProtoPte,
1173  StoreInstruction,
1174  KernelMode,
1175  TempPte.u.Soft.Protection,
1176  TrapInformation,
1177  TRUE);
1179  }
1180  else
1181  {
1182  Protection = PteContents.u.Soft.Protection;
1183  }
1184 
1185  /* Check for writing copy on write page */
1186  if (((Protection & MM_WRITECOPY) == MM_WRITECOPY) && StoreInstruction)
1187  {
1188  PFN_NUMBER PageFrameIndex, ProtoPageFrameIndex;
1189  ULONG Color;
1190 
1191  /* Resolve the proto fault as if it was a read operation */
1193  Address,
1194  PointerPte,
1195  PointerProtoPte,
1196  OutPfn,
1197  PageFileData,
1198  PteValue,
1199  Process,
1200  OldIrql,
1201  TrapInformation);
1202 
1203  if (!NT_SUCCESS(Status))
1204  {
1205  return Status;
1206  }
1207 
1208  /* Lock again the PFN lock, MiResolveProtoPteFault unlocked it */
1209  OldIrql = MiAcquirePfnLock();
1210 
1211  /* And re-read the proto PTE */
1212  TempPte = *PointerProtoPte;
1213  ASSERT(TempPte.u.Hard.Valid == 1);
1214  ProtoPageFrameIndex = PFN_FROM_PTE(&TempPte);
1215 
1218 
1219  /* Get a new page for the private copy */
1220  if (Process > HYDRA_PROCESS)
1222  else
1224 
1225  PageFrameIndex = MiRemoveAnyPage(Color);
1226 
1227  /* Perform the copy */
1228  MiCopyPfn(PageFrameIndex, ProtoPageFrameIndex);
1229 
1230  /* This will drop everything MiResolveProtoPteFault referenced */
1231  MiDeletePte(PointerPte, Address, Process, PointerProtoPte);
1232 
1233  /* Because now we use this */
1234  Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);
1235  MiInitializePfn(PageFrameIndex, PointerPte, TRUE);
1236 
1237  /* Fix the protection */
1238  Protection &= ~MM_WRITECOPY;
1239  Protection |= MM_READWRITE;
1241  {
1242  /* Build the user PTE */
1243  MI_MAKE_HARDWARE_PTE_USER(&PteContents, PointerPte, Protection, PageFrameIndex);
1244  }
1245  else
1246  {
1247  /* Build the kernel PTE */
1248  MI_MAKE_HARDWARE_PTE(&PteContents, PointerPte, Protection, PageFrameIndex);
1249  }
1250 
1251  /* And finally, write the valid PTE */
1252  MI_WRITE_VALID_PTE(PointerPte, PteContents);
1253 
1254  /* The caller expects us to release the PFN lock */
1255  MiReleasePfnLock(OldIrql);
1256  return Status;
1257  }
1258 
1259  /* Check for clone PTEs */
1260  if (PointerPte <= MiHighestUserPte) ASSERT(Process->CloneRoot == NULL);
1261 
1262  /* We don't support mapped files yet */
1263  ASSERT(TempPte.u.Soft.Prototype == 0);
1264 
1265  /* We might however have transition PTEs */
1266  if (TempPte.u.Soft.Transition == 1)
1267  {
1268  /* Resolve the transition fault */
1269  ASSERT(OldIrql != MM_NOIRQL);
1270  Status = MiResolveTransitionFault(StoreInstruction,
1271  Address,
1272  PointerProtoPte,
1273  Process,
1274  OldIrql,
1275  &InPageBlock);
1277  }
1278  else
1279  {
1280  /* We also don't support paged out pages */
1281  ASSERT(TempPte.u.Soft.PageFileHigh == 0);
1282 
1283  /* Resolve the demand zero fault */
1285  PointerProtoPte,
1286  (ULONG)TempPte.u.Soft.Protection,
1287  Process,
1288  OldIrql);
1289 #if MI_TRACE_PFNS
1290  /* Update debug info */
1291  if (TrapInformation)
1292  MiGetPfnEntry(PointerProtoPte->u.Hard.PageFrameNumber)->CallSite = (PVOID)((PKTRAP_FRAME)TrapInformation)->Eip;
1293  else
1294  MiGetPfnEntry(PointerProtoPte->u.Hard.PageFrameNumber)->CallSite = _ReturnAddress();
1295 #endif
1296 
1298  }
1299 
1300  /* Complete the prototype PTE fault -- this will release the PFN lock */
1301  ASSERT(PointerPte->u.Hard.Valid == 0);
1302  return MiCompleteProtoPteFault(StoreInstruction,
1303  Address,
1304  PointerPte,
1305  PointerProtoPte,
1306  OldIrql,
1307  OutPfn);
1308 }
VOID NTAPI MiInitializePfn(IN PFN_NUMBER PageFrameIndex, IN PMMPTE PointerPte, IN BOOLEAN Modified)
Definition: pfnlist.c:972
#define MI_ASSERT_PFN_LOCK_HELD()
Definition: mm.h:996
#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:1079
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
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:59
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:307
ULONG_PTR ShareCount
Definition: mm.h:379
static WCHAR Address[46]
Definition: ping.c:68
#define MI_SET_USAGE(x)
Definition: mm.h:306
ULONG64 Protection
Definition: mmtypes.h:88
void * PVOID
Definition: retypes.h:9
union _MMPFN::@1760 u2
KIRQL OldIrql
Definition: mm.h:1502
Status
Definition: gdiplustypes.h:24
#define MM_READONLY
Definition: inbv.c:11
#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
#define MM_READWRITE
Definition: inbv.c:12
ULONG64 PageFileHigh
Definition: mmtypes.h:93
Definition: mm.h:362
FORCEINLINE PMMPFN MiGetPfnEntry(IN PFN_NUMBER Pfn)
Definition: mm.h:1000
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:971
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:758
#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:1103
#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 _MMPTE::@2287 u
#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 971 of file pagfault.c.

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

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
union _MMPFN::@1761 u3
MMPFNENTRY e1
Definition: mm.h:386
USHORT CacheAttribute
Definition: mm.h:356
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
VOID FASTCALL KeZeroPages(IN PVOID Address, IN ULONG Size)
Definition: stubs.c:94
#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:362
#define PAGE_SIZE
Definition: env_spec_w32.h:49
FORCEINLINE PMMPFN MiGetPfnEntry(IN PFN_NUMBER Pfn)
Definition: mm.h:1000
#define MI_PAGE_DISABLE_CACHE(x)
Definition: mm.h:101
FORCEINLINE PVOID MiPteToAddress(PMMPTE PointerPte)
Definition: mm.h:201
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 1672 of file pagfault.c.

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

2573 {
2576 
2577  *ExecuteOptions = 0;
2578 
2579  if (CurrentProcess->Flags.ExecuteDisable)
2580  {
2581  *ExecuteOptions |= MEM_EXECUTE_OPTION_DISABLE;
2582  }
2583 
2584  if (CurrentProcess->Flags.ExecuteEnable)
2585  {
2586  *ExecuteOptions |= MEM_EXECUTE_OPTION_ENABLE;
2587  }
2588 
2589  if (CurrentProcess->Flags.DisableThunkEmulation)
2590  {
2591  *ExecuteOptions |= MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION;
2592  }
2593 
2594  if (CurrentProcess->Flags.Permanent)
2595  {
2596  *ExecuteOptions |= MEM_EXECUTE_OPTION_PERMANENT;
2597  }
2598 
2599  if (CurrentProcess->Flags.ExecuteDispatchEnable)
2600  {
2601  *ExecuteOptions |= MEM_EXECUTE_OPTION_EXECUTE_DISPATCH_ENABLE;
2602  }
2603 
2604  if (CurrentProcess->Flags.ImageDispatchEnable)
2605  {
2606  *ExecuteOptions |= MEM_EXECUTE_OPTION_IMAGE_DISPATCH_ENABLE;
2607  }
2608 
2609  return STATUS_SUCCESS;
2610 }
#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 2614 of file pagfault.c.

2615 {
2617  KLOCK_QUEUE_HANDLE ProcessLock;
2620 
2621  /* Only accept valid flags */
2622  if (ExecuteOptions & ~MEM_EXECUTE_OPTION_VALID_FLAGS)
2623  {
2624  /* Fail */
2625  DPRINT1("Invalid no-execute options\n");
2626  return STATUS_INVALID_PARAMETER;
2627  }
2628 
2629  /* Change the NX state in the process lock */
2631 
2632  /* Don't change anything if the permanent flag was set */
2633  if (!CurrentProcess->Flags.Permanent)
2634  {
2635  /* Start by assuming it's not disabled */
2636  CurrentProcess->Flags.ExecuteDisable = FALSE;
2637 
2638  /* Now process each flag and turn the equivalent bit on */
2639  if (ExecuteOptions & MEM_EXECUTE_OPTION_DISABLE)
2640  {
2641  CurrentProcess->Flags.ExecuteDisable = TRUE;
2642  }
2643  if (ExecuteOptions & MEM_EXECUTE_OPTION_ENABLE)
2644  {
2645  CurrentProcess->Flags.ExecuteEnable = TRUE;
2646  }
2647  if (ExecuteOptions & MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION)
2648  {
2649  CurrentProcess->Flags.DisableThunkEmulation = TRUE;
2650  }
2651  if (ExecuteOptions & MEM_EXECUTE_OPTION_PERMANENT)
2652  {
2653  CurrentProcess->Flags.Permanent = TRUE;
2654  }
2655  if (ExecuteOptions & MEM_EXECUTE_OPTION_EXECUTE_DISPATCH_ENABLE)
2656  {
2657  CurrentProcess->Flags.ExecuteDispatchEnable = TRUE;
2658  }
2659  if (ExecuteOptions & MEM_EXECUTE_OPTION_IMAGE_DISPATCH_ENABLE)
2660  {
2661  CurrentProcess->Flags.ImageDispatchEnable = TRUE;
2662  }
2663 
2664  /* These are turned on by default if no-execution is also eanbled */
2665  if (CurrentProcess->Flags.ExecuteEnable)
2666  {
2667  CurrentProcess->Flags.ExecuteDispatchEnable = TRUE;
2668  CurrentProcess->Flags.ImageDispatchEnable = TRUE;
2669  }
2670 
2671  /* All good */
2673  }
2674 
2675  /* Release the lock and return status */
2676  KiReleaseProcessLock(&ProcessLock);
2677  return Status;
2678 }
#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().