ReactOS 0.4.15-dev-7958-gcd0bb1a
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
48I've generally organized fault handling code in newmm as handlers that run
49under a single lock acquisition, check the state, and either take necessary
50action atomically, or place a wait entry and return a continuation to the
51caller. This lends itself to code that has a simple, structured form,
52doesn't make assumptions about lock taking and breaking, and provides an
53obvious, graphic seperation between code that may block and code that isn't
54allowed to. This file contains the non-blocking half.
55
56In order to request a blocking operation to happen outside locks, place a
57function pointer in the provided MM_REQUIRED_RESOURCES struct and return
58STATUS_MORE_PROCESSING_REQUIRED. The function indicated will receive the
59provided struct and take action outside of any mm related locks and at
60PASSIVE_LEVEL. The same fault handler will be called again after the
61blocking operation succeeds. In this way, the fault handler can accumulate
62state, but will freely work while competing with other threads.
63
64Fault handlers in this file should check for an MM_WAIT_ENTRY in a page
65table they're using and return STATUS_SUCCESS + 1 if it's found. In that
66case, the caller will wait on the wait entry event until the competing thread
67is finished, and recall this handler in the current thread.
68
69Another thing to note here is that we require mappings to exactly mirror
70rmaps, 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
85
86#ifdef NEWCC
88
89/*
90
91Multiple stage handling of a not-present fault in a data section.
92
93Required->State is used to accumulate flags that indicate the next action
94the handler should take.
95
96State & 2 is currently used to indicate that the page acquired by a previous
97callout is a global page to the section and should be placed in the section
98page table.
99
100Note that the primitive tail recursion done here reaches the base case when
101the page is present.
102
103*/
104
106NTAPI
107MmNotPresentFaultCachePage (
113{
115 PVOID PAddress;
116 ULONG Consumer;
118 LARGE_INTEGER FileOffset, TotalOffset;
123
124 DPRINT("Not Present: %p %p (%p-%p)\n",
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 */
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 }
189 MiSetPageEvent(Process, Address);
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,
199 Required->Page,
200 1);
201 if (NT_SUCCESS(Status))
202 {
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);
212 MiSetPageEvent(Process, Address);
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
242 OldIrql = MiAcquirePfnLock();
244 MiReleasePfnLock(OldIrql);
245
247 if (NT_SUCCESS(Status))
248 {
250 }
251 DPRINT("XXX Set Event %x\n", Status);
252 MiSetPageEvent(Process, Address);
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
284NTAPI
285MiCopyPageToPage(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
312This function is deceptively named, in that it does the actual work of handling
313access faults on data sections. In the case of the code that's present here,
314we don't allow cow sections, but we do need this to unset the initial
315PAGE_READONLY condition of pages faulted into the cache so that we can add
316a dirty bit in the section page table on the first modification.
317
318In the ultimate form of this code, CoW is reenabled.
319
320*/
321
323NTAPI
324MiCowCacheSectionPage (
330{
332 PFN_NUMBER NewPage, OldPage;
334 PVOID PAddress;
337
338 DPRINT("MmAccessFaultSectionView(%p, %p, %p, %u)\n",
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,
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 {
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
464typedef struct _WORK_QUEUE_WITH_CONTEXT
465{
471 KEVENT Wait;
472 AcquireResource DoAcquisition;
474
475/*
476
477This is the work item used do blocking resource acquisition when a fault
478handler returns STATUS_MORE_PROCESSING_REQUIRED. It's used to allow resource
479acquisition to take place on a different stack, and outside of any locks used
480by fault handling, making recursive fault handling possible when required.
481
482*/
483
484_Function_class_(WORKER_THREAD_ROUTINE)
485VOID
486NTAPI
487MmpFaultWorker(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
501This code seperates the action of fault handling into an upper and lower
502handler to allow the inner handler to optionally be called in work item
503if the stack is getting too deep. My experiments show that the third
504recursive page fault taken at PASSIVE_LEVEL must be shunted away to a
505worker thread. In the ultimate form of this code, the primary fault handler
506makes this decision by using a thread-local counter to detect a too-deep
507fault stack and call the inner fault handler in a worker thread if required.
508
509Note that faults are taken at passive level and have access to ordinary
510driver entry points such as those that read and write files, and filesystems
511should use paged structures whenever possible. This makes recursive faults
512both a perfectly normal occurrance, and a worthwhile case to handle.
513
514The code below will repeatedly call MiCowSectionPage as long as it returns
515either STATUS_SUCCESS + 1 or STATUS_MORE_PROCESSING_REQUIRED. In the more
516processing required case, we call out to a blocking resource acquisition
517function and then recall the faut handler with the shared state represented
518by the MM_REQUIRED_RESOURCES struct.
519
520In the other case, we wait on the wait entry event and recall the handler.
521Each time the wait entry event is signalled, one thread has removed an
522MM_WAIT_ENTRY from a page table.
523
524In the ultimate form of this code, there is a single system wide fault handler
525for each of access fault and not present and each memory area contains a
526function pointer that indicates the active fault handler. Since the mm code
527in reactos is currently fragmented, I didn't bring this change to trunk.
528
529*/
530
532NTAPI
533MmpSectionAccessFaultInner(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",
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,
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);
614 MiWaitForPageEvent(MmGetAddressSpaceOwner(AddressSpace), Address);
615 DPRINT("Restarting fault %Ix\n", Address);
617 }
619 {
620 /* Clean slate */
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
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 {
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",
670 }
671
672 if (!FromMdl)
673 {
675 }
676
677 return Status;
678}
679
680/*
681
682This is the outer fault handler mentioned in the description of
683MmpSectionAccsesFaultInner. It increments a fault depth count in the current
684thread.
685
686In the ultimate form of this code, the lower fault handler will optionally
687use the count to keep the kernel stack from overflowing.
688
689*/
690
692NTAPI
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,
732 Address,
733 FromMdl,
734 Thread);
736
737 return Status;
738}
739
740/*
741
742As above, this code seperates the active part of fault handling from a carrier
743that can use the thread's active fault count to determine whether a work item
744is required. Also as above, this function repeatedly calls the active not
745present fault handler until a clear success or failure is received, using a
746return of STATUS_MORE_PROCESSING_REQUIRED or STATUS_SUCCESS + 1.
747
748*/
749
751NTAPI
752MmNotPresentFaultCacheSectionInner(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",
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",
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,
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);
825 MiWaitForPageEvent(MmGetAddressSpaceOwner(AddressSpace), Address);
826 DPRINT("Done waiting for %Ix\n", Address);
828 }
830 {
831 /* Clean slate */
832 DPRINT("Clear resource\n");
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
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,
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
904Call the inner not present fault handler, keeping track of the fault count.
905In the ultimate form of this code, optionally use a worker thread the handle
906the fault in order to sidestep stack overflow in the multiple fault case.
907
908*/
909
911NTAPI
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,
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
unsigned char BOOLEAN
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
DECLSPEC_NORETURN VOID NTAPI KeBugCheck(ULONG BugCheckCode)
Definition: bug.c:1430
_In_ PFCB _In_ LONGLONG FileOffset
Definition: cdprocs.h:160
_Out_ PKIRQL Irql
Definition: csq.h:179
#define NULL
Definition: types.h:112
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define PAGE_READONLY
Definition: compat.h:138
#define ULONG_PTR
Definition: config.h:101
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
#define KeWaitForSingleObject(pEvt, foo, a, b, c)
Definition: env_spec_w32.h:478
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define PAGE_SIZE
Definition: env_spec_w32.h:49
#define KeSetEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:476
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
#define DPRINTC
Definition: fault.c:82
KEVENT MmWaitPageEvent
Definition: fault.c:461
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:223
Status
Definition: gdiplustypes.h:25
_In_ ULONG Mode
Definition: hubbusif.h:303
void __cdecl __debugbreak(void)
Definition: intrin_ppc.h:698
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define ASSERT(a)
Definition: mode.c:44
#define _Function_class_(x)
Definition: ms_sal.h:2946
#define _Inout_
Definition: ms_sal.h:378
#define _In_
Definition: ms_sal.h:308
#define KernelMode
Definition: asm.h:34
NTSTATUS NTAPI MmAccessFaultCacheSection(KPROCESSOR_MODE Mode, ULONG_PTR Address, BOOLEAN FromMdl)
_In_ PMEMORY_AREA _In_ PVOID _In_ BOOLEAN _Inout_ PMM_REQUIRED_RESOURCES Required
Definition: newmm.h:210
_In_ PMEMORY_AREA MemoryArea
Definition: newmm.h:207
NTSTATUS NTAPI MiReadFilePage(PMMSUPPORT AddressSpace, PMEMORY_AREA MemoryArea, PMM_REQUIRED_RESOURCES RequiredResources)
Definition: reqtools.c:133
_In_ PMEMORY_AREA _In_ PVOID _In_ BOOLEAN Locked
Definition: newmm.h:209
NTSTATUS NTAPI MmNotPresentFaultCacheSection(KPROCESSOR_MODE Mode, ULONG_PTR Address, BOOLEAN FromMdl)
NTSTATUS NTAPI MiGetOnePage(PMMSUPPORT AddressSpace, PMEMORY_AREA MemoryArea, PMM_REQUIRED_RESOURCES RequiredResources)
Definition: reqtools.c:83
NTSTATUS(NTAPI * AcquireResource)(PMMSUPPORT AddressSpace, struct _MEMORY_AREA *MemoryArea, struct _MM_REQUIRED_RESOURCES *Required)
Definition: newmm.h:35
#define PAGE_READWRITE
Definition: nt_native.h:1304
#define PAGE_EXECUTE_READWRITE
Definition: nt_native.h:1308
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
@ NotificationEvent
#define IMAGE_SCN_MEM_SHARED
Definition: ntimage.h:238
PMMWSL MmWorkingSetList
Definition: wslist.cpp:19
#define MmSystemRangeStart
Definition: mm.h:32
#define MmSetDirtyPage(__P, __A)
Definition: mm.h:1252
#define MmGetPageEntrySectionSegment(S, O)
Definition: mm.h:1602
FORCEINLINE PMMPFN MiGetPfnEntry(IN PFN_NUMBER Pfn)
Definition: mm.h:1047
FORCEINLINE VOID MmLockAddressSpace(PMMSUPPORT AddressSpace)
Definition: mm.h:1691
VOID NTAPI MmSetPageProtect(struct _EPROCESS *Process, PVOID Address, ULONG flProtect)
#define DIRTY_SSE(E)
Definition: mm.h:1375
VOID NTAPI MiUnmapPageInHyperSpace(IN PEPROCESS Process, IN PVOID Address, IN KIRQL OldIrql)
Definition: hypermap.c:91
VOID NTAPI MmGetPageFileMapping(PEPROCESS Process, PVOID Address, SWAPENTRY *SwapEntry)
Definition: page.c:299
#define MmLockSectionSegment(x)
Definition: mm.h:1397
VOID NTAPI MmReferencePage(PFN_NUMBER Page)
Definition: freelist.c:518
PVOID NTAPI MiMapPageInHyperSpace(IN PEPROCESS Process, IN PFN_NUMBER Page, IN PKIRQL OldIrql)
Definition: hypermap.c:28
#define MmSetPageEntrySectionSegment(S, O, E)
Definition: mm.h:1600
#define MmUnlockSectionSegment(x)
Definition: mm.h:1405
BOOLEAN NTAPI MmIsPageSwapEntry(struct _EPROCESS *Process, PVOID Address)
_In_ PVOID _Out_opt_ BOOLEAN _Out_opt_ PPFN_NUMBER Page
Definition: mm.h:1306
PMEMORY_AREA NTAPI MmLocateMemoryAreaByAddress(PMMSUPPORT AddressSpace, PVOID Address)
Definition: marea.c:60
#define MAKE_PFN_SSE(P)
Definition: mm.h:1372
#define MAKE_SWAP_SSE(S)
Definition: mm.h:1374
ULONG_PTR SWAPENTRY
Definition: mm.h:57
#define MA_GetEndingAddress(_MemoryArea)
Definition: mm.h:245
PFN_NUMBER NTAPI MmGetPfnForProcess(struct _EPROCESS *Process, PVOID Address)
#define MA_GetStartingAddress(_MemoryArea)
Definition: mm.h:244
FORCEINLINE VOID MmUnlockAddressSpace(PMMSUPPORT AddressSpace)
Definition: mm.h:1704
FORCEINLINE PEPROCESS MmGetAddressSpaceOwner(IN PMMSUPPORT AddressSpace)
Definition: mm.h:1711
BOOLEAN NTAPI MmIsPagePresent(struct _EPROCESS *Process, PVOID Address)
VOID NTAPI MmSetSavedSwapEntryPage(PFN_NUMBER Page, SWAPENTRY SavedSwapEntry)
Definition: freelist.c:483
#define PFN_FROM_SSE(E)
Definition: mm.h:1368
NTSTATUS NTAPI MmCreateVirtualMapping(struct _EPROCESS *Process, PVOID Address, ULONG flProtect, PFN_NUMBER Page)
NTSTATUS NTAPI MmCreatePageFileMapping(struct _EPROCESS *Process, PVOID Address, SWAPENTRY SwapEntry)
VOID NTAPI MmDeleteRmap(PFN_NUMBER Page, struct _EPROCESS *Process, PVOID Address)
#define MM_ROUND_DOWN(x, s)
Definition: mm.h:131
#define MM_IS_WAIT_PTE(E)
Definition: mm.h:1370
#define IS_SWAP_FROM_SSE(E)
Definition: mm.h:1369
NTSTATUS NTAPI MmReleasePageMemoryConsumer(ULONG Consumer, PFN_NUMBER Page)
Definition: balance.c:72
FORCEINLINE PMMSUPPORT MmGetKernelAddressSpace(VOID)
Definition: mm.h:1726
VOID NTAPI MmInsertRmap(PFN_NUMBER Page, struct _EPROCESS *Process, PVOID Address)
#define STATUS_MM_RESTART_OPERATION
Definition: mm.h:104
#define STATUS_NO_MEMORY
Definition: ntstatus.h:260
#define STATUS_ACCESS_VIOLATION
Definition: ntstatus.h:242
static WCHAR Address[46]
Definition: ping.c:68
struct _WORK_QUEUE_WITH_CONTEXT * PWORK_QUEUE_WITH_CONTEXT
struct _WORK_QUEUE_WITH_CONTEXT WORK_QUEUE_WITH_CONTEXT
ULONG PFN_NUMBER
Definition: ke.h:9
#define STATUS_MORE_PROCESSING_REQUIRED
Definition: shellext.h:68
#define STATUS_SUCCESS
Definition: shellext.h:65
#define DPRINT
Definition: sndvol32.h:71
base of all file and directory entries
Definition: entries.h:83
UCHAR ActiveFaultCount
Definition: pstypes.h:1243
struct _MEMORY_AREA::@1792 SectionData
BOOLEAN DeleteInProgress
Definition: mm.h:253
ULONG Type
Definition: mm.h:251
WORK_QUEUE_ITEM WorkItem
Definition: pinsup.c:167
#define NTAPI
Definition: typedefs.h:36
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG_PTR
Definition: typedefs.h:65
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
LONGLONG QuadPart
Definition: typedefs.h:114
ULONG LowPart
Definition: typedefs.h:106
_Must_inspect_result_ _In_ WDFDMAENABLER _In_ _In_opt_ PWDF_OBJECT_ATTRIBUTES Attributes
_In_ WDFDPC _In_ BOOLEAN Wait
Definition: wdfdpc.h:170
_Must_inspect_result_ _In_ PWDF_WORKITEM_CONFIG _In_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFWORKITEM * WorkItem
Definition: wdfworkitem.h:115
VOID NTAPI ExQueueWorkItem(IN PWORK_QUEUE_ITEM WorkItem, IN WORK_QUEUE_TYPE QueueType)
Definition: work.c:723
_Inout_ PVOID Segment
Definition: exfuncs.h:1101
#define ExInitializeWorkItem(Item, Routine, Context)
Definition: exfuncs.h:265
@ DelayedWorkQueue
Definition: extypes.h:190
WORKER_THREAD_ROUTINE * PWORKER_THREAD_ROUTINE
Definition: extypes.h:200
_In_ ULONG _In_ PHYSICAL_ADDRESS _Inout_ PULONG AddressSpace
Definition: iofuncs.h:2274
#define IO_NO_INCREMENT
Definition: iotypes.h:598
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:778
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7
#define PsGetCurrentProcess
Definition: psfuncs.h:17
_Inout_opt_ PVOID Parameter
Definition: rtltypes.h:323