ReactOS  0.4.13-dev-242-g611e6d7
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;
86 
87 /*
88 
89 Multiple stage handling of a not-present fault in a data section.
90 
91 Required->State is used to accumulate flags that indicate the next action
92 the handler should take.
93 
94 State & 2 is currently used to indicate that the page acquired by a previous
95 callout is a global page to the section and should be placed in the section
96 page table.
97 
98 Note that the primitive tail recursion done here reaches the base case when
99 the page is present.
100 
101 */
102 
103 NTSTATUS
104 NTAPI
111 {
113  PVOID PAddress;
114  ULONG Consumer;
116  LARGE_INTEGER FileOffset, TotalOffset;
120  KIRQL OldIrql;
121 
122  DPRINT("Not Present: %p %p (%p-%p)\n",
123  AddressSpace,
124  Address,
127 
128  /*
129  * There is a window between taking the page fault and locking the
130  * address space when another thread could load the page so we check
131  * that.
132  */
134  {
135  DPRINT("Done\n");
136  return STATUS_SUCCESS;
137  }
138 
139  PAddress = MM_ROUND_DOWN(Address, PAGE_SIZE);
140  TotalOffset.QuadPart = (ULONG_PTR)PAddress -
142 
143  Segment = MemoryArea->Data.SectionData.Segment;
144 
145  TotalOffset.QuadPart += MemoryArea->Data.SectionData.ViewOffset.QuadPart;
146  FileOffset = TotalOffset;
147 
148  //Consumer = (Segment->Flags & MM_DATAFILE_SEGMENT) ? MC_CACHE : MC_USER;
149  Consumer = MC_CACHE;
150 
151  if (Segment->FileObject)
152  {
153  DPRINT("FileName %wZ\n", &Segment->FileObject->FileName);
154  }
155 
156  DPRINT("Total Offset %08x%08x\n", TotalOffset.HighPart, TotalOffset.LowPart);
157 
158  /* Lock the segment */
160 
161  /* Get the entry corresponding to the offset within the section */
162  Entry = MmGetPageEntrySectionSegment(Segment, &TotalOffset);
163 
165 
166  if (Required->State && Required->Page[0])
167  {
168  DPRINT("Have file and page, set page %x in section @ %x #\n",
169  Required->Page[0],
170  TotalOffset.LowPart);
171 
172  if (Required->SwapEntry)
173  MmSetSavedSwapEntryPage(Required->Page[0], Required->SwapEntry);
174 
175  if (Required->State & 2)
176  {
177  DPRINT("Set in section @ %x\n", TotalOffset.LowPart);
179  &TotalOffset,
180  Entry = MAKE_PFN_SSE(Required->Page[0]));
181  if (!NT_SUCCESS(Status))
182  {
184  }
187  DPRINT("Status %x\n", Status);
189  }
190  else
191  {
192  DPRINT("Set %x in address space @ %p\n", Required->Page[0], Address);
194  Address,
195  Attributes,
196  Required->Page,
197  1);
198  if (NT_SUCCESS(Status))
199  {
200  MmInsertRmap(Required->Page[0], Process, Address);
201  }
202  else
203  {
204  /* Drop the reference for our address space ... */
206  }
208  DPRINTC("XXX Set Event %x\n", Status);
210  DPRINT("Status %x\n", Status);
211  return Status;
212  }
213  }
214  else if (MM_IS_WAIT_PTE(Entry))
215  {
216  // Whenever MM_WAIT_ENTRY is required as a swap entry, we need to
217  // ask the fault handler to wait until we should continue. Rathern
218  // than recopy this boilerplate code everywhere, we just ask them
219  // to wait.
221  return STATUS_SUCCESS + 1;
222  }
223  else if (Entry)
224  {
225  PFN_NUMBER Page = PFN_FROM_SSE(Entry);
226  DPRINT("Take reference to page %x #\n", Page);
227 
228  if (MiGetPfnEntry(Page) == NULL)
229  {
230  DPRINT1("Found no PFN entry for page 0x%x in page entry 0x%x (segment: 0x%p, offset: %08x%08x)\n",
231  Page,
232  Entry,
233  Segment,
234  TotalOffset.HighPart,
235  TotalOffset.LowPart);
236  KeBugCheck(CACHE_MANAGER);
237  }
238 
240  MmReferencePage(Page);
242 
244  if (NT_SUCCESS(Status))
245  {
246  MmInsertRmap(Page, Process, Address);
247  }
248  DPRINT("XXX Set Event %x\n", Status);
251  DPRINT("Status %x\n", Status);
252  return Status;
253  }
254  else
255  {
256  DPRINT("Get page into section\n");
257  /*
258  * If the entry is zero (and it can't change because we have
259  * locked the segment) then we need to load the page.
260  */
261  //DPRINT1("Read from file %08x %wZ\n", FileOffset.LowPart, &Section->FileObject->FileName);
262  Required->State = 2;
263  Required->Context = Segment->FileObject;
264  Required->Consumer = Consumer;
265  Required->FileOffset = FileOffset;
266  Required->Amount = PAGE_SIZE;
267  Required->DoAcquisition = MiReadFilePage;
268 
270  &TotalOffset,
272 
275  }
276  ASSERT(FALSE);
278 }
279 
280 NTSTATUS
281 NTAPI
283 {
285  KIRQL Irql, Irql2;
286  PVOID TempAddress, TempSource;
287 
289  TempAddress = MiMapPageInHyperSpace(Process, DestPage, &Irql);
290  if (TempAddress == NULL)
291  {
292  return STATUS_NO_MEMORY;
293  }
294  TempSource = MiMapPageInHyperSpace(Process, SrcPage, &Irql2);
295  if (!TempSource) {
296  MiUnmapPageInHyperSpace(Process, TempAddress, Irql);
297  return STATUS_NO_MEMORY;
298  }
299 
300  memcpy(TempAddress, TempSource, PAGE_SIZE);
301 
302  MiUnmapPageInHyperSpace(Process, TempSource, Irql2);
303  MiUnmapPageInHyperSpace(Process, TempAddress, Irql);
304  return STATUS_SUCCESS;
305 }
306 
307 /*
308 
309 This function is deceptively named, in that it does the actual work of handling
310 access faults on data sections. In the case of the code that's present here,
311 we don't allow cow sections, but we do need this to unset the initial
312 PAGE_READONLY condition of pages faulted into the cache so that we can add
313 a dirty bit in the section page table on the first modification.
314 
315 In the ultimate form of this code, CoW is reenabled.
316 
317 */
318 
319 NTSTATUS
320 NTAPI
327 {
329  PFN_NUMBER NewPage, OldPage;
331  PVOID PAddress;
334 
335  DPRINT("MmAccessFaultSectionView(%p, %p, %p, %u)\n",
336  AddressSpace,
337  MemoryArea,
338  Address,
339  Locked);
340 
341  Segment = MemoryArea->Data.SectionData.Segment;
342 
343  /* Lock the segment */
345 
346  /* Find the offset of the page */
347  PAddress = MM_ROUND_DOWN(Address, PAGE_SIZE);
348  Offset.QuadPart = (ULONG_PTR)PAddress - MA_GetStartingAddress(MemoryArea) +
349  MemoryArea->Data.SectionData.ViewOffset.QuadPart;
350 
351  if (!Segment->WriteCopy /*&&
352  !MemoryArea->Data.SectionData.WriteCopyView*/ ||
353  Segment->Image.Characteristics & IMAGE_SCN_MEM_SHARED)
354  {
355 #if 0
356  if (Region->Protect == PAGE_READWRITE ||
357  Region->Protect == PAGE_EXECUTE_READWRITE)
358 #endif
359  {
361  DPRINTC("setting non-cow page %p %p:%p offset %I64x (%Ix) to writable\n",
362  Segment,
363  Process,
364  PAddress,
365  Offset.QuadPart,
367  if (Segment->FileObject)
368  {
369  DPRINTC("file %wZ\n", &Segment->FileObject->FileName);
370  }
372  DPRINT("Entry %x\n", Entry);
373  if (Entry &&
376 
378  &Offset,
379  DIRTY_SSE(Entry));
380  }
382  MmSetDirtyPage(Process, PAddress);
384  DPRINT("Done\n");
385  return STATUS_SUCCESS;
386  }
387 #if 0
388  else
389  {
390  DPRINT("Not supposed to be writable\n");
393  }
394 #endif
395  }
396 
397  if (!Required->Page[0])
398  {
399  SWAPENTRY SwapEntry;
401  {
402  MmGetPageFileMapping(Process, Address, &SwapEntry);
404  if (SwapEntry == MM_WAIT_ENTRY)
405  return STATUS_SUCCESS + 1; // Wait ... somebody else is getting it right now
406  else
407  return STATUS_SUCCESS; // Nonwait swap entry ... handle elsewhere
408  }
409  /* Call out to acquire a page to copy to. We'll be re-called when
410  * the page has been allocated. */
412  Required->Consumer = MC_CACHE;
413  Required->Amount = 1;
414  Required->File = __FILE__;
415  Required->Line = __LINE__;
416  Required->DoAcquisition = MiGetOnePage;
420  }
421 
422  NewPage = Required->Page[0];
423  OldPage = Required->Page[1];
424 
425  DPRINT("Allocated page %x\n", NewPage);
426 
427  /* Unshare the old page */
428  MmDeleteRmap(OldPage, Process, PAddress);
429 
430  /* Copy the old page */
431  DPRINT("Copying\n");
432  MiCopyPageToPage(NewPage, OldPage);
433 
434  /* Set the PTE to point to the new page */
436  Address,
438  &NewPage,
439  1);
440 
441  if (!NT_SUCCESS(Status))
442  {
443  DPRINT1("MmCreateVirtualMapping failed, not out of memory\n");
444  ASSERT(FALSE);
446  return Status;
447  }
448 
449  MmInsertRmap(NewPage, Process, PAddress);
452 
453  DPRINT("Address 0x%p\n", Address);
454  return STATUS_SUCCESS;
455 }
456 
458 
459 typedef struct _WORK_QUEUE_WITH_CONTEXT
460 {
467  AcquireResource DoAcquisition;
469 
470 /*
471 
472 This is the work item used do blocking resource acquisition when a fault
473 handler returns STATUS_MORE_PROCESSING_REQUIRED. It's used to allow resource
474 acquisition to take place on a different stack, and outside of any locks used
475 by fault handling, making recursive fault handling possible when required.
476 
477 */
478 
479 _Function_class_(WORKER_THREAD_ROUTINE)
480 VOID
481 NTAPI
482 MmpFaultWorker(PVOID Parameter)
483 {
485 
486  DPRINT("Calling work\n");
487  WorkItem->Status = WorkItem->Required->DoAcquisition(WorkItem->AddressSpace,
488  WorkItem->MemoryArea,
489  WorkItem->Required);
490  DPRINT("Status %x\n", WorkItem->Status);
491  KeSetEvent(&WorkItem->Wait, IO_NO_INCREMENT, FALSE);
492 }
493 
494 /*
495 
496 This code seperates the action of fault handling into an upper and lower
497 handler to allow the inner handler to optionally be called in work item
498 if the stack is getting too deep. My experiments show that the third
499 recursive page fault taken at PASSIVE_LEVEL must be shunted away to a
500 worker thread. In the ultimate form of this code, the primary fault handler
501 makes this decision by using a thread-local counter to detect a too-deep
502 fault stack and call the inner fault handler in a worker thread if required.
503 
504 Note that faults are taken at passive level and have access to ordinary
505 driver entry points such as those that read and write files, and filesystems
506 should use paged structures whenever possible. This makes recursive faults
507 both a perfectly normal occurrance, and a worthwhile case to handle.
508 
509 The code below will repeatedly call MiCowSectionPage as long as it returns
510 either STATUS_SUCCESS + 1 or STATUS_MORE_PROCESSING_REQUIRED. In the more
511 processing required case, we call out to a blocking resource acquisition
512 function and then recall the faut handler with the shared state represented
513 by the MM_REQUIRED_RESOURCES struct.
514 
515 In the other case, we wait on the wait entry event and recall the handler.
516 Each time the wait entry event is signalled, one thread has removed an
517 MM_WAIT_ENTRY from a page table.
518 
519 In the ultimate form of this code, there is a single system wide fault handler
520 for each of access fault and not present and each memory area contains a
521 function pointer that indicates the active fault handler. Since the mm code
522 in reactos is currently fragmented, I didn't bring this change to trunk.
523 
524 */
525 
526 NTSTATUS
527 NTAPI
531  BOOLEAN FromMdl,
533 {
536  BOOLEAN Locked = FromMdl;
539 
541 
542  DPRINT("MmAccessFault(Mode %d, Address %Ix)\n", Mode, Address);
543 
545  {
546  DPRINT1("Page fault at high IRQL was %u\n", KeGetCurrentIrql());
547  return STATUS_UNSUCCESSFUL;
548  }
549 
550  /* Find the memory area for the faulting address */
552  {
553  /* Check permissions */
554  if (Mode != KernelMode)
555  {
556  DPRINT("MmAccessFault(Mode %d, Address %Ix)\n", Mode, Address);
558  }
560  }
561  else
562  {
564  }
565 
566  if (!FromMdl)
567  {
569  }
570 
571  do
572  {
574  if (MemoryArea == NULL ||
576  {
577  if (!FromMdl)
578  {
580  }
581  DPRINT("Address: %Ix\n", Address);
583  }
584 
585  DPRINT("Type %x (%p -> %p)\n",
586  MemoryArea->Type,
589 
590  Resources.DoAcquisition = NULL;
591 
592  // Note: fault handlers are called with address space locked
593  // We return STATUS_MORE_PROCESSING_REQUIRED if anything is needed
595  MemoryArea,
596  (PVOID)Address,
597  Locked,
598  &Resources);
599 
600  if (!FromMdl)
601  {
603  }
604 
605  if (Status == STATUS_SUCCESS + 1)
606  {
607  /* Wait page ... */
608  DPRINT("Waiting for %Ix\n", Address);
610  DPRINT("Restarting fault %Ix\n", Address);
612  }
614  {
615  /* Clean slate */
616  RtlZeroMemory(&Resources, sizeof(Resources));
617  }
619  {
620  if (Thread->ActiveFaultCount > 0)
621  {
622  DPRINT("Already fault handling ... going to work item (%Ix)\n",
623  Address);
624  Context.AddressSpace = AddressSpace;
625  Context.MemoryArea = MemoryArea;
626  Context.Required = &Resources;
628 
629  ExInitializeWorkItem(&Context.WorkItem,
630  MmpFaultWorker,
631  &Context);
632 
633  DPRINT("Queue work item\n");
635  DPRINT("Wait\n");
637  Status = Context.Status;
638  DPRINT("Status %x\n", Status);
639  }
640  else
641  {
642  Status = Resources.DoAcquisition(AddressSpace, MemoryArea, &Resources);
643  }
644 
645  if (NT_SUCCESS(Status))
646  {
648  }
649  }
650 
651  if (!FromMdl)
652  {
654  }
655  }
657 
658  if (!NT_SUCCESS(Status) && MemoryArea->Type == 1)
659  {
660  DPRINT1("Completed page fault handling %Ix %x\n", Address, Status);
661  DPRINT1("Type %x (%p -> %p)\n",
662  MemoryArea->Type,
665  }
666 
667  if (!FromMdl)
668  {
670  }
671 
672  return Status;
673 }
674 
675 /*
676 
677 This is the outer fault handler mentioned in the description of
678 MmpSectionAccsesFaultInner. It increments a fault depth count in the current
679 thread.
680 
681 In the ultimate form of this code, the lower fault handler will optionally
682 use the count to keep the kernel stack from overflowing.
683 
684 */
685 
686 NTSTATUS
687 NTAPI
690  BOOLEAN FromMdl)
691 {
695 
696  DPRINT("MmpAccessFault(Mode %d, Address %Ix)\n", Mode, Address);
697 
699 
701  {
702  DPRINT1("Page fault at high IRQL %u, address %Ix\n",
704  Address);
705  return STATUS_UNSUCCESSFUL;
706  }
707 
708  /* Find the memory area for the faulting address */
710  {
711  /* Check permissions */
712  if (Mode != KernelMode)
713  {
714  DPRINT1("Address: %p:%Ix\n", PsGetCurrentProcess(), Address);
716  }
718  }
719  else
720  {
722  }
723 
726  AddressSpace,
727  Address,
728  FromMdl,
729  Thread);
731 
732  return Status;
733 }
734 
735 /*
736 
737 As above, this code seperates the active part of fault handling from a carrier
738 that can use the thread's active fault count to determine whether a work item
739 is required. Also as above, this function repeatedly calls the active not
740 present fault handler until a clear success or failure is received, using a
741 return of STATUS_MORE_PROCESSING_REQUIRED or STATUS_SUCCESS + 1.
742 
743 */
744 
745 NTSTATUS
746 NTAPI
750  BOOLEAN FromMdl,
752 {
753  BOOLEAN Locked = FromMdl;
758 
760 
761  if (!FromMdl)
762  {
764  }
765 
766  /* Call the memory area specific fault handler */
767  do
768  {
771  {
773  if (MemoryArea)
774  {
775  DPRINT1("Type %x DIP %x\n",
776  MemoryArea->Type,
778  }
779  else
780  {
781  DPRINT1("No memory area\n");
782  }
783  DPRINT1("Process %p, Address %Ix\n",
785  Address);
786  break;
787  }
788 
789  DPRINTC("Type %x (%p -> %08Ix -> %p) in %p\n",
790  MemoryArea->Type,
792  Address,
795 
796  Resources.DoAcquisition = NULL;
797 
798  // Note: fault handlers are called with address space locked
799  // We return STATUS_MORE_PROCESSING_REQUIRED if anything is needed
800 
802  MemoryArea,
803  (PVOID)Address,
804  Locked,
805  &Resources);
806 
807  if (!FromMdl)
808  {
810  }
811 
812  if (Status == STATUS_SUCCESS)
813  {
814  ; // Nothing
815  }
816  else if (Status == STATUS_SUCCESS + 1)
817  {
818  /* Wait page ... */
819  DPRINT("Waiting for %Ix\n", Address);
821  DPRINT("Done waiting for %Ix\n", Address);
823  }
825  {
826  /* Clean slate */
827  DPRINT("Clear resource\n");
828  RtlZeroMemory(&Resources, sizeof(Resources));
829  }
831  {
832  if (Thread->ActiveFaultCount > 2)
833  {
834  DPRINTC("Already fault handling ... going to work item (%Ix)\n", Address);
835  Context.AddressSpace = AddressSpace;
836  Context.MemoryArea = MemoryArea;
837  Context.Required = &Resources;
839 
840  ExInitializeWorkItem(&Context.WorkItem,
841  (PWORKER_THREAD_ROUTINE)MmpFaultWorker,
842  &Context);
843 
844  DPRINT("Queue work item\n");
846  DPRINT("Wait\n");
848  Status = Context.Status;
849  DPRINTC("Status %x\n", Status);
850  }
851  else
852  {
853  DPRINT("DoAcquisition %p\n", Resources.DoAcquisition);
854 
855  Status = Resources.DoAcquisition(AddressSpace,
856  MemoryArea,
857  &Resources);
858 
859  DPRINT("DoAcquisition %p -> %x\n",
860  Resources.DoAcquisition,
861  Status);
862  }
863 
864  if (NT_SUCCESS(Status))
865  {
867  }
868  }
869  else if (NT_SUCCESS(Status))
870  {
871  ASSERT(FALSE);
872  }
873 
874  if (!FromMdl)
875  {
877  }
878  }
880 
881  DPRINTC("Completed page fault handling: %p:%Ix %x\n",
883  Address,
884  Status);
885 
886  if (!FromMdl)
887  {
889  }
890 
892  DPRINT("Done %x\n", Status);
893 
894  return Status;
895 }
896 
897 /*
898 
899 Call the inner not present fault handler, keeping track of the fault count.
900 In the ultimate form of this code, optionally use a worker thread the handle
901 the fault in order to sidestep stack overflow in the multiple fault case.
902 
903 */
904 
905 NTSTATUS
906 NTAPI
909  BOOLEAN FromMdl)
910 {
914 
915  Address &= ~(PAGE_SIZE - 1);
916  DPRINT("MmNotPresentFault(Mode %d, Address %Ix)\n", Mode, Address);
917 
919 
921  {
922  DPRINT1("Page fault at high IRQL %u, address %Ix\n",
924  Address);
925 
926  ASSERT(FALSE);
927  return STATUS_UNSUCCESSFUL;
928  }
929 
930  /* Find the memory area for the faulting address */
932  {
933  /* Check permissions */
934  if (Mode != KernelMode)
935  {
936  DPRINTC("Address: %x\n", Address);
938  }
940  }
941  else
942  {
944  }
945 
948  AddressSpace,
949  Address,
950  FromMdl,
951  Thread);
953 
956  DPRINT("MmAccessFault %p:%Ix -> %x\n",
958  Address,
959  Status);
960 
961  return Status;
962 }
#define MmSetPageEntrySectionSegment(S, O, E)
Definition: newmm.h:141
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
VOID NTAPI ExQueueWorkItem(IN PWORK_QUEUE_ITEM WorkItem, IN WORK_QUEUE_TYPE QueueType)
Definition: work.c:717
VOID NTAPI MmInsertRmap(PFN_NUMBER Page, struct _EPROCESS *Process, PVOID Address)
ULONG Type
Definition: mm.h:214
#define MiSetPageEvent(Process, Address)
Definition: newmm.h:43
struct _Entry Entry
Definition: kefuncs.h:640
#define PFN_FROM_SSE(E)
Definition: newmm.h:7
_In_ ULONG Mode
Definition: hubbusif.h:303
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
#define STATUS_MORE_PROCESSING_REQUIRED
Definition: shellext.h:63
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:80
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:1423
LONG NTSTATUS
Definition: precomp.h:26
NTSTATUS NTAPI MmReleasePageMemoryConsumer(ULONG Consumer, PFN_NUMBER Page)
Definition: balance.c:97
#define MAKE_PFN_SSE(P)
Definition: newmm.h:11
AcquireResource DoAcquisition
Definition: fault.c:467
FORCEINLINE KIRQL MiAcquirePfnLock(VOID)
Definition: mm.h:901
NTSTATUS NTAPI MmCreatePageFileMapping(struct _EPROCESS *Process, PVOID Address, SWAPENTRY SwapEntry)
#define MM_WAIT_ENTRY
Definition: mm.h:152
AcquireResource DoAcquisition
Definition: newmm.h:89
#define MiWaitForPageEvent(Process, Address)
Definition: newmm.h:38
NTSTATUS NTAPI MiReadFilePage(PMMSUPPORT AddressSpace, PMEMORY_AREA MemoryArea, PMM_REQUIRED_RESOURCES RequiredResources)
Definition: reqtools.c:133
_In_ PVOID Parameter
Definition: ldrtypes.h:240
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
_Out_ PKIRQL Irql
Definition: csq.h:179
FORCEINLINE VOID MiReleasePfnLock(_In_ KIRQL OldIrql)
Definition: mm.h:908
uint32_t ULONG_PTR
Definition: typedefs.h:63
UCHAR KIRQL
Definition: env_spec_w32.h:591
BOOLEAN NTAPI MmIsPagePresent(struct _EPROCESS *Process, PVOID Address)
ULONG PFN_NUMBER
Definition: ke.h:8
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
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
NTSTATUS NTAPI MiGetOnePage(PMMSUPPORT AddressSpace, PMEMORY_AREA MemoryArea, PMM_REQUIRED_RESOURCES RequiredResources)
Definition: reqtools.c:83
_In_ PMEMORY_AREA _In_ PVOID _In_ BOOLEAN Locked
Definition: newmm.h:260
#define PsGetCurrentProcess
Definition: psfuncs.h:17
PVOID NTAPI MiMapPageInHyperSpace(IN PEPROCESS Process, IN PFN_NUMBER Page, IN PKIRQL OldIrql)
Definition: hypermap.c:30
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
static WCHAR Address[46]
Definition: ping.c:68
NTSTATUS NTAPI MmNotPresentFaultCacheSectionInner(KPROCESSOR_MODE Mode, PMMSUPPORT AddressSpace, ULONG_PTR Address, BOOLEAN FromMdl, PETHREAD Thread)
Definition: fault.c:747
PMMSUPPORT AddressSpace
Definition: fault.c:462
void DPRINT(...)
Definition: polytest.cpp:61
VOID NTAPI KeBugCheck(ULONG BugCheckCode)
Definition: bug.c:1469
NTSTATUS NTAPI MiCopyPageToPage(PFN_NUMBER DestPage, PFN_NUMBER SrcPage)
Definition: fault.c:282
VOID NTAPI MmGetPageFileMapping(struct _EPROCESS *Process, PVOID Address, SWAPENTRY *SwapEntry)
_Inout_ PVOID Segment
Definition: exfuncs.h:893
KEVENT MmWaitPageEvent
Definition: fault.c:457
#define ExInitializeWorkItem(Item, Routine, Context)
Definition: exfuncs.h:265
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define DPRINTC
Definition: fault.c:82
BOOLEAN DeleteInProgress
Definition: mm.h:217
struct _MEMORY_AREA::@1716::@1717 SectionData
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
#define MA_GetEndingAddress(_MemoryArea)
Definition: mm.h:208
VOID NTAPI MmSetPageProtect(struct _EPROCESS *Process, PVOID Address, ULONG flProtect)
#define _Inout_
Definition: no_sal2.h:244
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7
BOOLEAN NTAPI MmIsPageSwapEntry(struct _EPROCESS *Process, PVOID Address)
NTSTATUS NTAPI MmpSectionAccessFaultInner(KPROCESSOR_MODE Mode, PMMSUPPORT AddressSpace, ULONG_PTR Address, BOOLEAN FromMdl, PETHREAD Thread)
Definition: fault.c:528
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
VOID NTAPI MiUnmapPageInHyperSpace(IN PEPROCESS Process, IN PVOID Address, IN KIRQL OldIrql)
Definition: hypermap.c:93
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:803
NTSTATUS NTAPI MmNotPresentFaultCacheSection(KPROCESSOR_MODE Mode, ULONG_PTR Address, BOOLEAN FromMdl)
Definition: fault.c:907
#define MM_ROUND_DOWN(x, s)
Definition: mm.h:111
ULONG LowPart
Definition: typedefs.h:104
#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
PMMWSL MmWorkingSetList
Definition: procsup.c:21
#define IS_SWAP_FROM_SSE(E)
Definition: newmm.h:8
FORCEINLINE PMMPFN MiGetPfnEntry(IN PFN_NUMBER Pfn)
Definition: mm.h:940
#define MA_GetStartingAddress(_MemoryArea)
Definition: mm.h:207
Status
Definition: gdiplustypes.h:24
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
#define _In_
Definition: no_sal2.h:204
FORCEINLINE PMMSUPPORT MmGetKernelAddressSpace(VOID)
Definition: mm.h:1445
_Must_inspect_result_ _In_ USHORT _In_ PHIDP_PREPARSED_DATA _Out_writes_to_ LengthAttributes PHIDP_EXTENDED_ATTRIBUTES Attributes
Definition: hidpi.h:348
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
PMM_REQUIRED_RESOURCES Required
Definition: fault.c:464
#define STATUS_ACCESS_VIOLATION
Definition: ntstatus.h:228
PFN_NUMBER NTAPI MmGetPfnForProcess(struct _EPROCESS *Process, PVOID Address)
_In_ PFCB _In_ LONGLONG FileOffset
Definition: cdprocs.h:151
ULONG_PTR SWAPENTRY
Definition: mm.h:47
#define STATUS_NO_MEMORY
Definition: ntstatus.h:246
FORCEINLINE PEPROCESS MmGetAddressSpaceOwner(IN PMMSUPPORT AddressSpace)
Definition: mm.h:1430
WORK_QUEUE_ITEM WorkItem
Definition: pinsup.c:167
UCHAR ActiveFaultCount
Definition: pstypes.h:1174
PMEMORY_AREA MemoryArea
Definition: fault.c:463
#define PAGE_READONLY
Definition: compat.h:127
#define DPRINT1
Definition: precomp.h:8
#define MmLockSectionSegment(x)
Definition: newmm.h:276
#define MM_IS_WAIT_PTE(E)
Definition: newmm.h:9
VOID NTAPI MmSetSavedSwapEntryPage(PFN_NUMBER Page, SWAPENTRY SavedSwapEntry)
Definition: freelist.c:454
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:219
#define MC_CACHE
Definition: mm.h:93
#define DIRTY_SSE(E)
Definition: newmm.h:14
_Function_class_(WORKER_THREAD_ROUTINE)
Definition: fault.c:479
NTSTATUS NTAPI MiCowCacheSectionPage(_In_ PMMSUPPORT AddressSpace, _In_ PMEMORY_AREA MemoryArea, _In_ PVOID Address, _In_ BOOLEAN Locked, _Inout_ PMM_REQUIRED_RESOURCES Required)
Definition: fault.c:321
struct tagContext Context
Definition: acpixf.h:1012
unsigned int ULONG
Definition: retypes.h:1
#define IO_NO_INCREMENT
Definition: iotypes.h:565
NTSTATUS NTAPI MmAccessFaultCacheSection(KPROCESSOR_MODE Mode, ULONG_PTR Address, BOOLEAN FromMdl)
Definition: fault.c:688
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
#define ULONG_PTR
Definition: config.h:101
#define PAGE_EXECUTE_READWRITE
Definition: nt_native.h:1308
struct _MEMORY_AREA struct _MM_REQUIRED_RESOURCES * Required
Definition: newmm.h:66
union _MEMORY_AREA::@1716 Data
#define MmUnlockSectionSegment(x)
Definition: newmm.h:284
return STATUS_SUCCESS
Definition: btrfs.c:2745
VOID NTAPI MmReferencePage(PFN_NUMBER Page)
Definition: freelist.c:489
#define MAKE_SWAP_SSE(S)
Definition: newmm.h:13
struct _MEMORY_AREA * MemoryArea
Definition: newmm.h:65
FORCEINLINE VOID MmLockAddressSpace(PMMSUPPORT AddressSpace)
Definition: mm.h:1416
#define MmSystemRangeStart
Definition: mm.h:32
struct _WORK_QUEUE_WITH_CONTEXT * PWORK_QUEUE_WITH_CONTEXT
base of all file and directory entries
Definition: entries.h:82
#define MmGetPageEntrySectionSegment(S, O)
Definition: newmm.h:143
NTSTATUS NTAPI MmNotPresentFaultCachePage(_In_ PMMSUPPORT AddressSpace, _In_ MEMORY_AREA *MemoryArea, _In_ PVOID Address, _In_ BOOLEAN Locked, _Inout_ PMM_REQUIRED_RESOURCES Required)
Definition: fault.c:105
LONGLONG QuadPart
Definition: typedefs.h:112
WORKER_THREAD_ROUTINE * PWORKER_THREAD_ROUTINE
Definition: extypes.h:200
#define PAGE_READWRITE
Definition: nt_native.h:1304
struct _WORK_QUEUE_WITH_CONTEXT WORK_QUEUE_WITH_CONTEXT