ReactOS  0.4.15-dev-2087-g6bfb76b
fault.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1998-2005 ReactOS Team (and the authors from the programmers section)
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  *
19  * PROJECT: ReactOS kernel
20  * FILE: ntoskrnl/cache/section/fault.c
21  * PURPOSE: Consolidate fault handlers for sections
22  *
23  * PROGRAMMERS: Arty
24  * Rex Jolliff
25  * David Welch
26  * Eric Kohl
27  * Emanuele Aliberti
28  * Eugene Ingerman
29  * Casper Hornstrup
30  * KJK::Hyperion
31  * Guido de Jong
32  * Ge van Geldorp
33  * Royce Mitchell III
34  * Filip Navara
35  * Aleksey Bragin
36  * Jason Filby
37  * Thomas Weidenmueller
38  * Gunnar Andre' Dalsnes
39  * Mike Nordell
40  * Alex Ionescu
41  * Gregor Anich
42  * Steven Edwards
43  * Herve Poussineau
44  */
45 
46 /*
47 
48 I've generally organized fault handling code in newmm as handlers that run
49 under a single lock acquisition, check the state, and either take necessary
50 action atomically, or place a wait entry and return a continuation to the
51 caller. This lends itself to code that has a simple, structured form,
52 doesn't make assumptions about lock taking and breaking, and provides an
53 obvious, graphic seperation between code that may block and code that isn't
54 allowed to. This file contains the non-blocking half.
55 
56 In order to request a blocking operation to happen outside locks, place a
57 function pointer in the provided MM_REQUIRED_RESOURCES struct and return
58 STATUS_MORE_PROCESSING_REQUIRED. The function indicated will receive the
59 provided struct and take action outside of any mm related locks and at
60 PASSIVE_LEVEL. The same fault handler will be called again after the
61 blocking operation succeeds. In this way, the fault handler can accumulate
62 state, but will freely work while competing with other threads.
63 
64 Fault handlers in this file should check for an MM_WAIT_ENTRY in a page
65 table they're using and return STATUS_SUCCESS + 1 if it's found. In that
66 case, the caller will wait on the wait entry event until the competing thread
67 is finished, and recall this handler in the current thread.
68 
69 Another thing to note here is that we require mappings to exactly mirror
70 rmaps, so each mapping should be immediately followed by an rmap addition.
71 
72 */
73 
74 /* INCLUDES *****************************************************************/
75 
76 #include <ntoskrnl.h>
77 #include "newmm.h"
78 #define NDEBUG
79 #include <debug.h>
80 #include <mm/ARM3/miarm.h>
81 
82 #define DPRINTC DPRINT
83 
84 extern KEVENT MmWaitPageEvent;
85 
86 #ifdef NEWCC
88 
89 /*
90 
91 Multiple stage handling of a not-present fault in a data section.
92 
93 Required->State is used to accumulate flags that indicate the next action
94 the handler should take.
95 
96 State & 2 is currently used to indicate that the page acquired by a previous
97 callout is a global page to the section and should be placed in the section
98 page table.
99 
100 Note that the primitive tail recursion done here reaches the base case when
101 the page is present.
102 
103 */
104 
105 NTSTATUS
106 NTAPI
107 MmNotPresentFaultCachePage (
113 {
115  PVOID PAddress;
116  ULONG Consumer;
118  LARGE_INTEGER FileOffset, TotalOffset;
122  KIRQL OldIrql;
123 
124  DPRINT("Not Present: %p %p (%p-%p)\n",
125  AddressSpace,
126  Address,
129 
130  /*
131  * There is a window between taking the page fault and locking the
132  * address space when another thread could load the page so we check
133  * that.
134  */
136  {
137  DPRINT("Done\n");
138  return STATUS_SUCCESS;
139  }
140 
141  PAddress = MM_ROUND_DOWN(Address, PAGE_SIZE);
142  TotalOffset.QuadPart = (ULONG_PTR)PAddress -
144 
145  Segment = MemoryArea->Data.SectionData.Segment;
146 
147  TotalOffset.QuadPart += MemoryArea->Data.SectionData.ViewOffset.QuadPart;
148  FileOffset = TotalOffset;
149 
150  //Consumer = (Segment->Flags & MM_DATAFILE_SEGMENT) ? MC_CACHE : MC_USER;
151  Consumer = MC_CACHE;
152 
153  if (Segment->FileObject)
154  {
155  __debugbreak();
156  DPRINT("FileName %wZ\n", &Segment->FileObject->FileName);
157  }
158 
159  DPRINT("Total Offset %08x%08x\n", TotalOffset.HighPart, TotalOffset.LowPart);
160 
161  /* Lock the segment */
163 
164  /* Get the entry corresponding to the offset within the section */
165  Entry = MmGetPageEntrySectionSegment(Segment, &TotalOffset);
166 
168 
169  if (Required->State && Required->Page[0])
170  {
171  DPRINT("Have file and page, set page %x in section @ %x #\n",
172  Required->Page[0],
173  TotalOffset.LowPart);
174 
175  if (Required->SwapEntry)
176  MmSetSavedSwapEntryPage(Required->Page[0], Required->SwapEntry);
177 
178  if (Required->State & 2)
179  {
180  DPRINT("Set in section @ %x\n", TotalOffset.LowPart);
182  &TotalOffset,
183  Entry = MAKE_PFN_SSE(Required->Page[0]));
184  if (!NT_SUCCESS(Status))
185  {
186  MmReleasePageMemoryConsumer(MC_CACHE, Required->Page[0]);
187  }
190  DPRINT("Status %x\n", Status);
192  }
193  else
194  {
195  DPRINT("Set %x in address space @ %p\n", Required->Page[0], Address);
197  Address,
198  Attributes,
199  Required->Page,
200  1);
201  if (NT_SUCCESS(Status))
202  {
203  MmInsertRmap(Required->Page[0], Process, Address);
204  }
205  else
206  {
207  /* Drop the reference for our address space ... */
208  MmReleasePageMemoryConsumer(MC_CACHE, Required->Page[0]);
209  }
211  DPRINTC("XXX Set Event %x\n", Status);
213  DPRINT("Status %x\n", Status);
214  return Status;
215  }
216  }
217  else if (MM_IS_WAIT_PTE(Entry))
218  {
219  // Whenever MM_WAIT_ENTRY is required as a swap entry, we need to
220  // ask the fault handler to wait until we should continue. Rathern
221  // than recopy this boilerplate code everywhere, we just ask them
222  // to wait.
224  return STATUS_SUCCESS + 1;
225  }
226  else if (Entry)
227  {
229  DPRINT("Take reference to page %x #\n", Page);
230 
231  if (MiGetPfnEntry(Page) == NULL)
232  {
233  DPRINT1("Found no PFN entry for page 0x%x in page entry 0x%x (segment: 0x%p, offset: %08x%08x)\n",
234  Page,
235  Entry,
236  Segment,
237  TotalOffset.HighPart,
238  TotalOffset.LowPart);
239  KeBugCheck(CACHE_MANAGER);
240  }
241 
245 
247  if (NT_SUCCESS(Status))
248  {
250  }
251  DPRINT("XXX Set Event %x\n", Status);
254  DPRINT("Status %x\n", Status);
255  return Status;
256  }
257  else
258  {
259  DPRINT("Get page into section\n");
260  /*
261  * If the entry is zero (and it can't change because we have
262  * locked the segment) then we need to load the page.
263  */
264  //DPRINT1("Read from file %08x %wZ\n", FileOffset.LowPart, &Section->FileObject->FileName);
265  Required->State = 2;
266  Required->Context = Segment->FileObject;
267  Required->Consumer = Consumer;
268  Required->FileOffset = FileOffset;
269  Required->Amount = PAGE_SIZE;
270  Required->DoAcquisition = MiReadFilePage;
271 
273  &TotalOffset,
274  MAKE_SWAP_SSE(MM_WAIT_ENTRY));
275 
278  }
279  ASSERT(FALSE);
281 }
282 
283 NTSTATUS
284 NTAPI
285 MiCopyPageToPage(PFN_NUMBER DestPage, PFN_NUMBER SrcPage)
286 {
288  KIRQL Irql, Irql2;
289  PVOID TempAddress, TempSource;
290 
292  TempAddress = MiMapPageInHyperSpace(Process, DestPage, &Irql);
293  if (TempAddress == NULL)
294  {
295  return STATUS_NO_MEMORY;
296  }
297  TempSource = MiMapPageInHyperSpace(Process, SrcPage, &Irql2);
298  if (!TempSource) {
299  MiUnmapPageInHyperSpace(Process, TempAddress, Irql);
300  return STATUS_NO_MEMORY;
301  }
302 
303  memcpy(TempAddress, TempSource, PAGE_SIZE);
304 
305  MiUnmapPageInHyperSpace(Process, TempSource, Irql2);
306  MiUnmapPageInHyperSpace(Process, TempAddress, Irql);
307  return STATUS_SUCCESS;
308 }
309 
310 /*
311 
312 This function is deceptively named, in that it does the actual work of handling
313 access faults on data sections. In the case of the code that's present here,
314 we don't allow cow sections, but we do need this to unset the initial
315 PAGE_READONLY condition of pages faulted into the cache so that we can add
316 a dirty bit in the section page table on the first modification.
317 
318 In the ultimate form of this code, CoW is reenabled.
319 
320 */
321 
322 NTSTATUS
323 NTAPI
324 MiCowCacheSectionPage (
330 {
332  PFN_NUMBER NewPage, OldPage;
334  PVOID PAddress;
337 
338  DPRINT("MmAccessFaultSectionView(%p, %p, %p, %u)\n",
339  AddressSpace,
340  MemoryArea,
341  Address,
342  Locked);
343 
344  Segment = MemoryArea->Data.SectionData.Segment;
345 
346  /* Lock the segment */
348 
349  /* Find the offset of the page */
350  PAddress = MM_ROUND_DOWN(Address, PAGE_SIZE);
351  Offset.QuadPart = (ULONG_PTR)PAddress - MA_GetStartingAddress(MemoryArea) +
352  MemoryArea->Data.SectionData.ViewOffset.QuadPart;
353 
354  if (!Segment->WriteCopy /*&&
355  !MemoryArea->Data.SectionData.WriteCopyView*/ ||
356  Segment->Image.Characteristics & IMAGE_SCN_MEM_SHARED)
357  {
358 #if 0
359  if (Region->Protect == PAGE_READWRITE ||
360  Region->Protect == PAGE_EXECUTE_READWRITE)
361 #endif
362  {
364  DPRINTC("setting non-cow page %p %p:%p offset %I64x (%Ix) to writable\n",
365  Segment,
366  Process,
367  PAddress,
370  if (Segment->FileObject)
371  {
372  DPRINTC("file %wZ\n", &Segment->FileObject->FileName);
373  }
375  DPRINT("Entry %x\n", Entry);
376  if (Entry &&
379 
381  &Offset,
382  DIRTY_SSE(Entry));
383  }
385  MmSetDirtyPage(Process, PAddress);
387  DPRINT("Done\n");
388  return STATUS_SUCCESS;
389  }
390 #if 0
391  else
392  {
393  DPRINT("Not supposed to be writable\n");
396  }
397 #endif
398  }
399 
400  if (!Required->Page[0])
401  {
402  SWAPENTRY SwapEntry;
404  {
405  MmGetPageFileMapping(Process, Address, &SwapEntry);
407  if (SwapEntry == MM_WAIT_ENTRY)
408  return STATUS_SUCCESS + 1; // Wait ... somebody else is getting it right now
409  else
410  return STATUS_SUCCESS; // Nonwait swap entry ... handle elsewhere
411  }
412  /* Call out to acquire a page to copy to. We'll be re-called when
413  * the page has been allocated. */
415  Required->Consumer = MC_CACHE;
416  Required->Amount = 1;
417  Required->File = __FILE__;
418  Required->Line = __LINE__;
419  Required->DoAcquisition = MiGetOnePage;
420  MmCreatePageFileMapping(Process, Address, MM_WAIT_ENTRY);
423  }
424 
425  NewPage = Required->Page[0];
426  OldPage = Required->Page[1];
427 
428  DPRINT("Allocated page %x\n", NewPage);
429 
430  /* Unshare the old page */
431  MmDeleteRmap(OldPage, Process, PAddress);
432 
433  /* Copy the old page */
434  DPRINT("Copying\n");
435  MiCopyPageToPage(NewPage, OldPage);
436 
437  /* Set the PTE to point to the new page */
439  Address,
441  &NewPage,
442  1);
443 
444  if (!NT_SUCCESS(Status))
445  {
446  DPRINT1("MmCreateVirtualMapping failed, not out of memory\n");
447  ASSERT(FALSE);
449  return Status;
450  }
451 
452  MmInsertRmap(NewPage, Process, PAddress);
453  MmReleasePageMemoryConsumer(MC_CACHE, OldPage);
455 
456  DPRINT("Address 0x%p\n", Address);
457  return STATUS_SUCCESS;
458 }
459 #endif
460 
462 
463 #ifdef NEWCC
464 typedef struct _WORK_QUEUE_WITH_CONTEXT
465 {
471  KEVENT Wait;
472  AcquireResource DoAcquisition;
474 
475 /*
476 
477 This is the work item used do blocking resource acquisition when a fault
478 handler returns STATUS_MORE_PROCESSING_REQUIRED. It's used to allow resource
479 acquisition to take place on a different stack, and outside of any locks used
480 by fault handling, making recursive fault handling possible when required.
481 
482 */
483 
484 _Function_class_(WORKER_THREAD_ROUTINE)
485 VOID
486 NTAPI
487 MmpFaultWorker(PVOID Parameter)
488 {
490 
491  DPRINT("Calling work\n");
492  WorkItem->Status = WorkItem->Required->DoAcquisition(WorkItem->AddressSpace,
493  WorkItem->MemoryArea,
494  WorkItem->Required);
495  DPRINT("Status %x\n", WorkItem->Status);
497 }
498 
499 /*
500 
501 This code seperates the action of fault handling into an upper and lower
502 handler to allow the inner handler to optionally be called in work item
503 if the stack is getting too deep. My experiments show that the third
504 recursive page fault taken at PASSIVE_LEVEL must be shunted away to a
505 worker thread. In the ultimate form of this code, the primary fault handler
506 makes this decision by using a thread-local counter to detect a too-deep
507 fault stack and call the inner fault handler in a worker thread if required.
508 
509 Note that faults are taken at passive level and have access to ordinary
510 driver entry points such as those that read and write files, and filesystems
511 should use paged structures whenever possible. This makes recursive faults
512 both a perfectly normal occurrance, and a worthwhile case to handle.
513 
514 The code below will repeatedly call MiCowSectionPage as long as it returns
515 either STATUS_SUCCESS + 1 or STATUS_MORE_PROCESSING_REQUIRED. In the more
516 processing required case, we call out to a blocking resource acquisition
517 function and then recall the faut handler with the shared state represented
518 by the MM_REQUIRED_RESOURCES struct.
519 
520 In the other case, we wait on the wait entry event and recall the handler.
521 Each time the wait entry event is signalled, one thread has removed an
522 MM_WAIT_ENTRY from a page table.
523 
524 In the ultimate form of this code, there is a single system wide fault handler
525 for each of access fault and not present and each memory area contains a
526 function pointer that indicates the active fault handler. Since the mm code
527 in reactos is currently fragmented, I didn't bring this change to trunk.
528 
529 */
530 
531 NTSTATUS
532 NTAPI
533 MmpSectionAccessFaultInner(KPROCESSOR_MODE Mode,
536  BOOLEAN FromMdl,
538 {
541  BOOLEAN Locked = FromMdl;
544 
546 
547  DPRINT("MmAccessFault(Mode %d, Address %Ix)\n", Mode, Address);
548 
550  {
551  DPRINT1("Page fault at high IRQL was %u\n", KeGetCurrentIrql());
552  return STATUS_UNSUCCESSFUL;
553  }
554 
555  /* Find the memory area for the faulting address */
557  {
558  /* Check permissions */
559  if (Mode != KernelMode)
560  {
561  DPRINT("MmAccessFault(Mode %d, Address %Ix)\n", Mode, Address);
563  }
565  }
566  else
567  {
569  }
570 
571  if (!FromMdl)
572  {
574  }
575 
576  do
577  {
579  if (MemoryArea == NULL ||
581  {
582  if (!FromMdl)
583  {
585  }
586  DPRINT("Address: %Ix\n", Address);
588  }
589 
590  DPRINT("Type %x (%p -> %p)\n",
591  MemoryArea->Type,
594 
595  Resources.DoAcquisition = NULL;
596 
597  // Note: fault handlers are called with address space locked
598  // We return STATUS_MORE_PROCESSING_REQUIRED if anything is needed
599  Status = MiCowCacheSectionPage(AddressSpace,
600  MemoryArea,
601  (PVOID)Address,
602  Locked,
603  &Resources);
604 
605  if (!FromMdl)
606  {
608  }
609 
610  if (Status == STATUS_SUCCESS + 1)
611  {
612  /* Wait page ... */
613  DPRINT("Waiting for %Ix\n", Address);
615  DPRINT("Restarting fault %Ix\n", Address);
617  }
619  {
620  /* Clean slate */
621  RtlZeroMemory(&Resources, sizeof(Resources));
622  }
624  {
625  if (Thread->ActiveFaultCount > 0)
626  {
627  DPRINT("Already fault handling ... going to work item (%Ix)\n",
628  Address);
629  Context.AddressSpace = AddressSpace;
630  Context.MemoryArea = MemoryArea;
631  Context.Required = &Resources;
633 
634  ExInitializeWorkItem(&Context.WorkItem,
635  MmpFaultWorker,
636  &Context);
637 
638  DPRINT("Queue work item\n");
640  DPRINT("Wait\n");
642  Status = Context.Status;
643  DPRINT("Status %x\n", Status);
644  }
645  else
646  {
647  Status = Resources.DoAcquisition(AddressSpace, MemoryArea, &Resources);
648  }
649 
650  if (NT_SUCCESS(Status))
651  {
653  }
654  }
655 
656  if (!FromMdl)
657  {
659  }
660  }
662 
663  if (!NT_SUCCESS(Status) && MemoryArea->Type == 1)
664  {
665  DPRINT1("Completed page fault handling %Ix %x\n", Address, Status);
666  DPRINT1("Type %x (%p -> %p)\n",
667  MemoryArea->Type,
670  }
671 
672  if (!FromMdl)
673  {
675  }
676 
677  return Status;
678 }
679 
680 /*
681 
682 This is the outer fault handler mentioned in the description of
683 MmpSectionAccsesFaultInner. It increments a fault depth count in the current
684 thread.
685 
686 In the ultimate form of this code, the lower fault handler will optionally
687 use the count to keep the kernel stack from overflowing.
688 
689 */
690 
691 NTSTATUS
692 NTAPI
695  BOOLEAN FromMdl)
696 {
700 
701  DPRINT("MmpAccessFault(Mode %d, Address %Ix)\n", Mode, Address);
702 
704 
706  {
707  DPRINT1("Page fault at high IRQL %u, address %Ix\n",
709  Address);
710  return STATUS_UNSUCCESSFUL;
711  }
712 
713  /* Find the memory area for the faulting address */
715  {
716  /* Check permissions */
717  if (Mode != KernelMode)
718  {
719  DPRINT1("Address: %p:%Ix\n", PsGetCurrentProcess(), Address);
721  }
723  }
724  else
725  {
727  }
728 
730  Status = MmpSectionAccessFaultInner(Mode,
731  AddressSpace,
732  Address,
733  FromMdl,
734  Thread);
736 
737  return Status;
738 }
739 
740 /*
741 
742 As above, this code seperates the active part of fault handling from a carrier
743 that can use the thread's active fault count to determine whether a work item
744 is required. Also as above, this function repeatedly calls the active not
745 present fault handler until a clear success or failure is received, using a
746 return of STATUS_MORE_PROCESSING_REQUIRED or STATUS_SUCCESS + 1.
747 
748 */
749 
750 NTSTATUS
751 NTAPI
752 MmNotPresentFaultCacheSectionInner(KPROCESSOR_MODE Mode,
755  BOOLEAN FromMdl,
757 {
758  BOOLEAN Locked = FromMdl;
763 
765 
766  if (!FromMdl)
767  {
769  }
770 
771  /* Call the memory area specific fault handler */
772  do
773  {
776  {
778  if (MemoryArea)
779  {
780  DPRINT1("Type %x DIP %x\n",
781  MemoryArea->Type,
783  }
784  else
785  {
786  DPRINT1("No memory area\n");
787  }
788  DPRINT1("Process %p, Address %Ix\n",
790  Address);
791  break;
792  }
793 
794  DPRINTC("Type %x (%p -> %08Ix -> %p) in %p\n",
795  MemoryArea->Type,
797  Address,
800 
801  Resources.DoAcquisition = NULL;
802 
803  // Note: fault handlers are called with address space locked
804  // We return STATUS_MORE_PROCESSING_REQUIRED if anything is needed
805 
806  Status = MmNotPresentFaultCachePage(AddressSpace,
807  MemoryArea,
808  (PVOID)Address,
809  Locked,
810  &Resources);
811 
812  if (!FromMdl)
813  {
815  }
816 
817  if (Status == STATUS_SUCCESS)
818  {
819  ; // Nothing
820  }
821  else if (Status == STATUS_SUCCESS + 1)
822  {
823  /* Wait page ... */
824  DPRINT("Waiting for %Ix\n", Address);
826  DPRINT("Done waiting for %Ix\n", Address);
828  }
830  {
831  /* Clean slate */
832  DPRINT("Clear resource\n");
833  RtlZeroMemory(&Resources, sizeof(Resources));
834  }
836  {
837  if (Thread->ActiveFaultCount > 2)
838  {
839  DPRINTC("Already fault handling ... going to work item (%Ix)\n", Address);
840  Context.AddressSpace = AddressSpace;
841  Context.MemoryArea = MemoryArea;
842  Context.Required = &Resources;
844 
845  ExInitializeWorkItem(&Context.WorkItem,
846  (PWORKER_THREAD_ROUTINE)MmpFaultWorker,
847  &Context);
848 
849  DPRINT("Queue work item\n");
851  DPRINT("Wait\n");
853  Status = Context.Status;
854  DPRINTC("Status %x\n", Status);
855  }
856  else
857  {
858  DPRINT("DoAcquisition %p\n", Resources.DoAcquisition);
859 
860  Status = Resources.DoAcquisition(AddressSpace,
861  MemoryArea,
862  &Resources);
863 
864  DPRINT("DoAcquisition %p -> %x\n",
865  Resources.DoAcquisition,
866  Status);
867  }
868 
869  if (NT_SUCCESS(Status))
870  {
872  }
873  }
874  else if (NT_SUCCESS(Status))
875  {
876  ASSERT(FALSE);
877  }
878 
879  if (!FromMdl)
880  {
882  }
883  }
885 
886  DPRINTC("Completed page fault handling: %p:%Ix %x\n",
888  Address,
889  Status);
890 
891  if (!FromMdl)
892  {
894  }
895 
897  DPRINT("Done %x\n", Status);
898 
899  return Status;
900 }
901 
902 /*
903 
904 Call the inner not present fault handler, keeping track of the fault count.
905 In the ultimate form of this code, optionally use a worker thread the handle
906 the fault in order to sidestep stack overflow in the multiple fault case.
907 
908 */
909 
910 NTSTATUS
911 NTAPI
914  BOOLEAN FromMdl)
915 {
919 
920  Address &= ~(PAGE_SIZE - 1);
921  DPRINT("MmNotPresentFault(Mode %d, Address %Ix)\n", Mode, Address);
922 
924 
926  {
927  DPRINT1("Page fault at high IRQL %u, address %Ix\n",
929  Address);
930 
931  ASSERT(FALSE);
932  return STATUS_UNSUCCESSFUL;
933  }
934 
935  /* Find the memory area for the faulting address */
937  {
938  /* Check permissions */
939  if (Mode != KernelMode)
940  {
941  DPRINTC("Address: %x\n", Address);
943  }
945  }
946  else
947  {
949  }
950 
952  Status = MmNotPresentFaultCacheSectionInner(Mode,
953  AddressSpace,
954  Address,
955  FromMdl,
956  Thread);
958 
961  DPRINT("MmAccessFault %p:%Ix -> %x\n",
963  Address,
964  Status);
965 
966  return Status;
967 }
968 #endif
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
NTSTATUS NTAPI MmAccessFaultCacheSection(KPROCESSOR_MODE Mode, ULONG_PTR Address, BOOLEAN FromMdl)
#define MmGetPageEntrySectionSegment(S, O)
Definition: mm.h:1448
VOID NTAPI ExQueueWorkItem(IN PWORK_QUEUE_ITEM WorkItem, IN WORK_QUEUE_TYPE QueueType)
Definition: work.c:711
VOID NTAPI MmInsertRmap(PFN_NUMBER Page, struct _EPROCESS *Process, PVOID Address)
ULONG Type
Definition: mm.h:219
#define MiSetPageEvent(Process, Address)
Definition: newmm.h:25
struct _Entry Entry
Definition: kefuncs.h:627
_In_ ULONG Mode
Definition: hubbusif.h:303
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
#define STATUS_MORE_PROCESSING_REQUIRED
Definition: shellext.h:68
NTSTATUS NTAPI MmCreateVirtualMapping(struct _EPROCESS *Process, PVOID Address, ULONG flProtect, PPFN_NUMBER Pages, ULONG PageCount)
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_MM_RESTART_OPERATION
Definition: mm.h:82
#define PFN_FROM_SSE(E)
Definition: mm.h:1237
_In_ WDFDPC _In_ BOOLEAN Wait
Definition: wdfdpc.h:167
VOID NTAPI MmDeleteRmap(PFN_NUMBER Page, struct _EPROCESS *Process, PVOID Address)
_In_ ULONG _In_ PHYSICAL_ADDRESS _Inout_ PULONG AddressSpace
Definition: iofuncs.h:2268
FORCEINLINE VOID MmUnlockAddressSpace(PMMSUPPORT AddressSpace)
Definition: mm.h:1526
LONG NTSTATUS
Definition: precomp.h:26
NTSTATUS NTAPI MmReleasePageMemoryConsumer(ULONG Consumer, PFN_NUMBER Page)
Definition: balance.c:77
#define MmSetPageEntrySectionSegment(S, O, E)
Definition: mm.h:1446
FORCEINLINE KIRQL MiAcquirePfnLock(VOID)
Definition: mm.h:886
NTSTATUS NTAPI MmCreatePageFileMapping(struct _EPROCESS *Process, PVOID Address, SWAPENTRY SwapEntry)
#define MiWaitForPageEvent(Process, Address)
Definition: newmm.h:20
NTSTATUS NTAPI MiReadFilePage(PMMSUPPORT AddressSpace, PMEMORY_AREA MemoryArea, PMM_REQUIRED_RESOURCES RequiredResources)
Definition: reqtools.c:133
_In_ PVOID Parameter
Definition: ldrtypes.h:241
PMEMORY_AREA NTAPI MmLocateMemoryAreaByAddress(PMMSUPPORT AddressSpace, PVOID Address)
Definition: marea.c:60
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
#define MmLockSectionSegment(x)
Definition: mm.h:1262
_Out_ PKIRQL Irql
Definition: csq.h:179
void __cdecl __debugbreak(void)
Definition: intrin_ppc.h:698
FORCEINLINE VOID MiReleasePfnLock(_In_ KIRQL OldIrql)
Definition: mm.h:893
#define DIRTY_SSE(E)
Definition: mm.h:1244
uint32_t ULONG_PTR
Definition: typedefs.h:65
UCHAR KIRQL
Definition: env_spec_w32.h:591
BOOLEAN NTAPI MmIsPagePresent(struct _EPROCESS *Process, PVOID Address)
ULONG PFN_NUMBER
Definition: ke.h:9
VOID NTAPI MmSetDirtyPage(struct _EPROCESS *Process, PVOID Address)
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
#define FALSE
Definition: types.h:117
NTSTATUS NTAPI MiGetOnePage(PMMSUPPORT AddressSpace, PMEMORY_AREA MemoryArea, PMM_REQUIRED_RESOURCES RequiredResources)
Definition: reqtools.c:83
DECLSPEC_NORETURN VOID NTAPI KeBugCheck(ULONG BugCheckCode)
Definition: bug.c:1427
_In_ PMEMORY_AREA _In_ PVOID _In_ BOOLEAN Locked
Definition: newmm.h:217
#define PsGetCurrentProcess
Definition: psfuncs.h:17
PVOID NTAPI MiMapPageInHyperSpace(IN PEPROCESS Process, IN PFN_NUMBER Page, IN PKIRQL OldIrql)
Definition: hypermap.c:28
unsigned char BOOLEAN
static WCHAR Address[46]
Definition: ping.c:68
WDF_EXTERN_C_START typedef _In_ WDFCMRESLIST Resources
Definition: wdfpdo.h:63
PFN_NUMBER Page
Definition: section.c:4831
#define MM_IS_WAIT_PTE(E)
Definition: mm.h:1239
VOID NTAPI MmGetPageFileMapping(struct _EPROCESS *Process, PVOID Address, SWAPENTRY *SwapEntry)
#define MmUnlockSectionSegment(x)
Definition: mm.h:1270
_Inout_ PVOID Segment
Definition: exfuncs.h:1101
KEVENT MmWaitPageEvent
Definition: fault.c:461
Status
Definition: gdiplustypes.h:24
#define ExInitializeWorkItem(Item, Routine, Context)
Definition: exfuncs.h:265
#define ASSERT(a)
Definition: mode.c:45
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define DPRINTC
Definition: fault.c:82
BOOLEAN DeleteInProgress
Definition: mm.h:221
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
#define MA_GetEndingAddress(_MemoryArea)
Definition: mm.h:213
VOID NTAPI MmSetPageProtect(struct _EPROCESS *Process, PVOID Address, ULONG flProtect)
#define _Inout_
Definition: no_sal2.h:162
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7
BOOLEAN NTAPI MmIsPageSwapEntry(struct _EPROCESS *Process, PVOID Address)
struct _WORK_QUEUE_WITH_CONTEXT * PWORK_QUEUE_WITH_CONTEXT
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
VOID NTAPI MiUnmapPageInHyperSpace(IN PEPROCESS Process, IN PVOID Address, IN KIRQL OldIrql)
Definition: hypermap.c:91
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:790
#define MM_ROUND_DOWN(x, s)
Definition: mm.h:109
ULONG LowPart
Definition: typedefs.h:106
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define IMAGE_SCN_MEM_SHARED
Definition: ntimage.h:238
#define PAGE_SIZE
Definition: env_spec_w32.h:49
#define _Function_class_(n)
Definition: no_sal2.h:398
FORCEINLINE PMMPFN MiGetPfnEntry(IN PFN_NUMBER Pfn)
Definition: mm.h:925
#define MA_GetStartingAddress(_MemoryArea)
Definition: mm.h:212
PMMWSL MmWorkingSetList
Definition: procsup.c:21
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
#define _In_
Definition: no_sal2.h:158
FORCEINLINE PMMSUPPORT MmGetKernelAddressSpace(VOID)
Definition: mm.h:1548
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define STATUS_ACCESS_VIOLATION
Definition: ntstatus.h:242
PFN_NUMBER NTAPI MmGetPfnForProcess(struct _EPROCESS *Process, PVOID Address)
_In_ PFCB _In_ LONGLONG FileOffset
Definition: cdprocs.h:159
#define IS_SWAP_FROM_SSE(E)
Definition: mm.h:1238
ULONG_PTR SWAPENTRY
Definition: mm.h:47
#define STATUS_NO_MEMORY
Definition: ntstatus.h:260
FORCEINLINE PEPROCESS MmGetAddressSpaceOwner(IN PMMSUPPORT AddressSpace)
Definition: mm.h:1533
WORK_QUEUE_ITEM WorkItem
Definition: pinsup.c:167
UCHAR ActiveFaultCount
Definition: pstypes.h:1185
#define NULL
Definition: types.h:112
#define PAGE_READONLY
Definition: compat.h:138
struct _MEMORY_AREA::@1775 SectionData
#define DPRINT1
Definition: precomp.h:8
VOID NTAPI MmSetSavedSwapEntryPage(PFN_NUMBER Page, SWAPENTRY SavedSwapEntry)
Definition: freelist.c:483
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:219
struct tagContext Context
Definition: acpixf.h:1034
#define MAKE_SWAP_SSE(S)
Definition: mm.h:1243
#define MAKE_PFN_SSE(P)
Definition: mm.h:1241
unsigned int ULONG
Definition: retypes.h:1
#define IO_NO_INCREMENT
Definition: iotypes.h:598
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define ULONG_PTR
Definition: config.h:101
#define PAGE_EXECUTE_READWRITE
Definition: nt_native.h:1308
NTSTATUS NTAPI MmNotPresentFaultCacheSection(KPROCESSOR_MODE Mode, ULONG_PTR Address, BOOLEAN FromMdl)
#define STATUS_SUCCESS
Definition: shellext.h:65
_Must_inspect_result_ _In_ PWDF_WORKITEM_CONFIG _In_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFWORKITEM * WorkItem
Definition: wdfworkitem.h:110
struct _MEMORY_AREA struct _MM_REQUIRED_RESOURCES * Required
Definition: newmm.h:48
#define DPRINT
Definition: sndvol32.h:71
VOID NTAPI MmReferencePage(PFN_NUMBER Page)
Definition: freelist.c:518
struct _MEMORY_AREA * MemoryArea
Definition: newmm.h:47
FORCEINLINE VOID MmLockAddressSpace(PMMSUPPORT AddressSpace)
Definition: mm.h:1519
#define MmSystemRangeStart
Definition: mm.h:32
base of all file and directory entries
Definition: entries.h:82
struct _WORK_QUEUE_WITH_CONTEXT WORK_QUEUE_WITH_CONTEXT
LONGLONG QuadPart
Definition: typedefs.h:114
WORKER_THREAD_ROUTINE * PWORKER_THREAD_ROUTINE
Definition: extypes.h:200
#define PAGE_READWRITE
Definition: nt_native.h:1304
_Must_inspect_result_ _In_ WDFDMAENABLER _In_ _In_opt_ PWDF_OBJECT_ATTRIBUTES Attributes