ReactOS  0.4.15-dev-2103-g9dff498
page.c
Go to the documentation of this file.
1 /*
2  * COPYRIGHT: See COPYING in the top level directory
3  * PROJECT: ReactOS kernel
4  * FILE: ntoskrnl/mm/i386/page.c
5  * PURPOSE: Low level memory managment manipulation
6  *
7  * PROGRAMMERS: David Welch (welch@cwcom.net)
8  */
9 
10 /* INCLUDES ***************************************************************/
11 
12 #include <ntoskrnl.h>
13 #define NDEBUG
14 #include <debug.h>
15 
16 #include <mm/ARM3/miarm.h>
17 
18 #define ADDR_TO_PDE_OFFSET MiAddressToPdeOffset
19 #define ADDR_TO_PAGE_TABLE(v) (((ULONG)(v)) / (1024 * PAGE_SIZE))
20 
21 /* GLOBALS *****************************************************************/
22 
23 #define PA_BIT_PRESENT (0)
24 #define PA_BIT_READWRITE (1)
25 #define PA_BIT_USER (2)
26 #define PA_BIT_WT (3)
27 #define PA_BIT_CD (4)
28 #define PA_BIT_ACCESSED (5)
29 #define PA_BIT_DIRTY (6)
30 #define PA_BIT_GLOBAL (8)
31 
32 #define PA_PRESENT (1 << PA_BIT_PRESENT)
33 #define PA_READWRITE (1 << PA_BIT_READWRITE)
34 #define PA_USER (1 << PA_BIT_USER)
35 #define PA_DIRTY (1 << PA_BIT_DIRTY)
36 #define PA_WT (1 << PA_BIT_WT)
37 #define PA_CD (1 << PA_BIT_CD)
38 #define PA_ACCESSED (1 << PA_BIT_ACCESSED)
39 #define PA_GLOBAL (1 << PA_BIT_GLOBAL)
40 
41 #define IS_HYPERSPACE(v) (((ULONG)(v) >= HYPER_SPACE && (ULONG)(v) <= HYPER_SPACE_END))
42 
43 #define PTE_TO_PFN(X) ((X) >> PAGE_SHIFT)
44 #define PFN_TO_PTE(X) ((X) << PAGE_SHIFT)
45 
46 #define PAGE_MASK(x) ((x)&(~0xfff))
47 
48 const
49 ULONG
51 {
52  //
53  // These are the base MM_ protection flags
54  //
55  0,
56  PTE_READONLY | PTE_ENABLE_CACHE,
57  PTE_EXECUTE | PTE_ENABLE_CACHE,
58  PTE_EXECUTE_READ | PTE_ENABLE_CACHE,
59  PTE_READWRITE | PTE_ENABLE_CACHE,
60  PTE_WRITECOPY | PTE_ENABLE_CACHE,
61  PTE_EXECUTE_READWRITE | PTE_ENABLE_CACHE,
62  PTE_EXECUTE_WRITECOPY | PTE_ENABLE_CACHE,
63  //
64  // These OR in the MM_NOCACHE flag
65  //
66  0,
67  PTE_READONLY | PTE_DISABLE_CACHE,
68  PTE_EXECUTE | PTE_DISABLE_CACHE,
69  PTE_EXECUTE_READ | PTE_DISABLE_CACHE,
70  PTE_READWRITE | PTE_DISABLE_CACHE,
71  PTE_WRITECOPY | PTE_DISABLE_CACHE,
72  PTE_EXECUTE_READWRITE | PTE_DISABLE_CACHE,
73  PTE_EXECUTE_WRITECOPY | PTE_DISABLE_CACHE,
74  //
75  // These OR in the MM_DECOMMIT flag, which doesn't seem supported on x86/64/ARM
76  //
77  0,
78  PTE_READONLY | PTE_ENABLE_CACHE,
79  PTE_EXECUTE | PTE_ENABLE_CACHE,
80  PTE_EXECUTE_READ | PTE_ENABLE_CACHE,
81  PTE_READWRITE | PTE_ENABLE_CACHE,
82  PTE_WRITECOPY | PTE_ENABLE_CACHE,
83  PTE_EXECUTE_READWRITE | PTE_ENABLE_CACHE,
84  PTE_EXECUTE_WRITECOPY | PTE_ENABLE_CACHE,
85  //
86  // These OR in the MM_NOACCESS flag, which seems to enable WriteCombining?
87  //
88  0,
89  PTE_READONLY | PTE_WRITECOMBINED_CACHE,
90  PTE_EXECUTE | PTE_WRITECOMBINED_CACHE,
91  PTE_EXECUTE_READ | PTE_WRITECOMBINED_CACHE,
92  PTE_READWRITE | PTE_WRITECOMBINED_CACHE,
93  PTE_WRITECOPY | PTE_WRITECOMBINED_CACHE,
94  PTE_EXECUTE_READWRITE | PTE_WRITECOMBINED_CACHE,
95  PTE_EXECUTE_WRITECOPY | PTE_WRITECOMBINED_CACHE,
96 };
97 
98 const
100 {
103  PAGE_EXECUTE,
133 };
134 
135 /* FUNCTIONS ***************************************************************/
136 
138 
139 VOID
141 {
142  if ((Pt && MmUnmapPageTable(Pt, OldIrql)) || Address >= MmSystemRangeStart)
143  {
145  }
146 }
147 
148 static ULONG
149 ProtectToPTE(ULONG flProtect)
150 {
151  ULONG Attributes = 0;
152 
153  if (flProtect & (PAGE_NOACCESS|PAGE_GUARD))
154  {
155  Attributes = 0;
156  }
157  else if (flProtect & PAGE_IS_WRITABLE)
158  {
160  }
161  else if (flProtect & (PAGE_IS_READABLE | PAGE_IS_EXECUTABLE))
162  {
164  }
165  else
166  {
167  DPRINT1("Unknown main protection type.\n");
168  KeBugCheck(MEMORY_MANAGEMENT);
169  }
170 
171  if (flProtect & PAGE_SYSTEM)
172  {
173  }
174  else
175  {
177  }
178  if (flProtect & PAGE_NOCACHE)
179  {
181  }
182  if (flProtect & PAGE_WRITETHROUGH)
183  {
185  }
186  return(Attributes);
187 }
188 
189 NTSTATUS
190 NTAPI
191 MiDispatchFault(IN ULONG FaultCode,
192  IN PVOID Address,
193  IN PMMPTE PointerPte,
194  IN PMMPTE PointerProtoPte,
195  IN BOOLEAN Recursive,
197  IN PVOID TrapInformation,
198  IN PVOID Vad);
199 
200 NTSTATUS
201 NTAPI
204 
205 static PULONG
207 {
208  PFN_NUMBER Pfn;
209  PULONG Pt;
210  PMMPDE PointerPde;
211 
213  {
214  /* We should have a process for user land addresses */
215  ASSERT(Process != NULL);
216 
218  {
219  PMMPDE PdeBase;
220  ULONG PdeOffset = MiGetPdeOffset(Address);
221 
223  PTE_TO_PFN(Process->Pcb.DirectoryTableBase[0]),
224  OldIrql);
225  if (PdeBase == NULL)
226  {
227  KeBugCheck(MEMORY_MANAGEMENT);
228  }
229  PointerPde = PdeBase + PdeOffset;
230  if (PointerPde->u.Hard.Valid == 0)
231  {
234 
235  if (!Create)
236  {
238  return NULL;
239  }
240 
242 
246  NULL,
247  FALSE,
248  Process,
249  NULL,
250  NULL);
251 
253  if (!NT_SUCCESS(Status))
254  return NULL;
255  }
256 
257  Pfn = PointerPde->u.Hard.PageFrameNumber;
260  if (Pt == NULL)
261  {
262  KeBugCheck(MEMORY_MANAGEMENT);
263  }
264  return Pt + MiAddressToPteOffset(Address);
265  }
266  /* This is for our process */
267  PointerPde = MiAddressToPde(Address);
269  if (PointerPde->u.Hard.Valid == 0)
270  {
272  if (Create == FALSE)
273  {
274  return NULL;
275  }
276  ASSERT(PointerPde->u.Long == 0);
277 
278  MI_WRITE_INVALID_PTE(PointerPde, DemandZeroPde);
279  // Tiny HACK: Parameter 1 is the architecture specific FaultCode for an access violation (i.e. page is present)
281  Pt,
282  PointerPde,
283  NULL,
284  FALSE,
286  NULL,
287  NULL);
290  ASSERT(PointerPde->u.Hard.Valid == 1);
291  }
292  return (PULONG)MiAddressToPte(Address);
293  }
294 
295  /* This is for kernel land address */
296  ASSERT(Process == NULL);
297  PointerPde = MiAddressToPde(Address);
299  if (PointerPde->u.Hard.Valid == 0)
300  {
301  /* Let ARM3 synchronize the PDE */
302  if(!MiSynchronizeSystemPde(PointerPde))
303  {
304  /* PDE (still) not valid, let ARM3 allocate one if asked */
305  if(Create == FALSE)
306  return NULL;
308  }
309  }
310  return Pt;
311 }
312 
314 {
315  if (!IS_HYPERSPACE(Pt))
316  {
317  return TRUE;
318  }
319 
321 
322  return FALSE;
323 }
324 
326 {
327  ULONG Pte;
328  PULONG Pt;
329  KIRQL OldIrql;
330 
332  if (Pt)
333  {
334  Pte = *Pt;
336  return Pte;
337  }
338  return 0;
339 }
340 
342 NTAPI
344  PVOID Address)
345 {
346  ULONG Entry;
348  if (!(Entry & PA_PRESENT))
349  {
350  return 0;
351  }
352  return(PTE_TO_PFN(Entry));
353 }
354 
355 VOID
356 NTAPI
358  BOOLEAN* WasDirty, PPFN_NUMBER Page)
359 /*
360  * FUNCTION: Delete a virtual mapping
361  */
362 {
363  BOOLEAN WasValid = FALSE;
364  PFN_NUMBER Pfn;
365  ULONG Pte;
366  PULONG Pt;
367  KIRQL OldIrql;
368 
369  DPRINT("MmDeleteVirtualMapping(%p, %p, %p, %p)\n",
370  Process, Address, WasDirty, Page);
371 
373 
374  if (Pt == NULL)
375  {
376  if (WasDirty != NULL)
377  {
378  *WasDirty = FALSE;
379  }
380  if (Page != NULL)
381  {
382  *Page = 0;
383  }
384  return;
385  }
386 
387  /*
388  * Atomically set the entry to zero and get the old value.
389  */
390  Pte = InterlockedExchangePte(Pt, 0);
391 
392  /* We count a mapping as valid if it's a present page, or it's a nonzero pfn with
393  * the swap bit unset, indicating a valid page protected to PAGE_NOACCESS. */
394  WasValid = (Pte & PA_PRESENT) || ((Pte >> PAGE_SHIFT) && !(Pte & 0x800));
395  if (WasValid)
396  {
397  /* Flush the TLB since we transitioned this PTE
398  * from valid to invalid so any stale translations
399  * are removed from the cache */
400  MiFlushTlb(Pt, Address, OldIrql);
401 
403  {
404  /* Remove PDE reference */
405  Process->Vm.VmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)]--;
406  ASSERT(Process->Vm.VmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)] < PTE_PER_PAGE);
407  }
408 
409  Pfn = PTE_TO_PFN(Pte);
410  }
411  else
412  {
414  Pfn = 0;
415  }
416 
417  /*
418  * Return some information to the caller
419  */
420  if (WasDirty != NULL)
421  {
422  *WasDirty = ((Pte & PA_DIRTY) && (Pte & PA_PRESENT)) ? TRUE : FALSE;
423  }
424  if (Page != NULL)
425  {
426  *Page = Pfn;
427  }
428 }
429 
430 VOID
431 NTAPI
433  SWAPENTRY* SwapEntry)
434 /*
435  * FUNCTION: Get a page file mapping
436  */
437 {
439  *SwapEntry = Entry >> 1;
440 }
441 
442 VOID
443 NTAPI
445  SWAPENTRY* SwapEntry)
446 /*
447  * FUNCTION: Delete a virtual mapping
448  */
449 {
450  ULONG Pte;
451  PULONG Pt;
452  KIRQL OldIrql;
453 
455 
456  if (Pt == NULL)
457  {
458  *SwapEntry = 0;
459  return;
460  }
461 
462  /*
463  * Atomically set the entry to zero and get the old value.
464  */
465  Pte = InterlockedExchangePte(Pt, 0);
466 
468  {
469  /* Remove PDE reference */
470  Process->Vm.VmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)]--;
471  ASSERT(Process->Vm.VmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)] < PTE_PER_PAGE);
472  }
473 
474  /* We don't need to flush here because page file entries
475  * are invalid translations, so the processor won't cache them */
477 
478  if ((Pte & PA_PRESENT) || !(Pte & 0x800))
479  {
480  DPRINT1("Pte %x (want not 1 and 0x800)\n", Pte);
481  KeBugCheck(MEMORY_MANAGEMENT);
482  }
483 
484  /*
485  * Return some information to the caller
486  */
487  *SwapEntry = Pte >> 1;
488 }
489 
490 BOOLEAN
492 {
493  PMMPDE PointerPde = MiAddressToPde(Address);
494  PMMPTE PointerPte = MiAddressToPte(Address);
495 
496  if (PointerPde->u.Hard.Valid == 0)
497  {
498  if(!MiSynchronizeSystemPde(PointerPde))
499  return FALSE;
500  return PointerPte->u.Hard.Valid != 0;
501  }
502  return FALSE;
503 }
504 
505 BOOLEAN
506 NTAPI
508 {
510 }
511 
512 VOID
513 NTAPI
515 {
516  PULONG Pt;
517  ULONG Pte;
518  KIRQL OldIrql;
519 
521  {
522  DPRINT1("MmSetCleanPage is called for user space without a process.\n");
523  KeBugCheck(MEMORY_MANAGEMENT);
524  }
525 
527  if (Pt == NULL)
528  {
529  KeBugCheck(MEMORY_MANAGEMENT);
530  }
531 
532  do
533  {
534  Pte = *Pt;
535  } while (Pte != InterlockedCompareExchangePte(Pt, Pte & ~PA_DIRTY, Pte));
536 
537  if (!(Pte & PA_PRESENT))
538  {
539  KeBugCheck(MEMORY_MANAGEMENT);
540  }
541  else if (Pte & PA_DIRTY)
542  {
543  MiFlushTlb(Pt, Address, OldIrql);
544  }
545  else
546  {
548  }
549 }
550 
551 VOID
552 NTAPI
554 {
555  PULONG Pt;
556  ULONG Pte;
557  KIRQL OldIrql;
558 
560  {
561  DPRINT1("MmSetDirtyPage is called for user space without a process.\n");
562  KeBugCheck(MEMORY_MANAGEMENT);
563  }
564 
566  if (Pt == NULL)
567  {
568  KeBugCheck(MEMORY_MANAGEMENT);
569  }
570 
571  do
572  {
573  Pte = *Pt;
574  } while (Pte != InterlockedCompareExchangePte(Pt, Pte | PA_DIRTY, Pte));
575 
576  if (!(Pte & PA_PRESENT))
577  {
578  KeBugCheck(MEMORY_MANAGEMENT);
579  }
580  else
581  {
582  /* The processor will never clear this bit itself, therefore
583  * we do not need to flush the TLB here when setting it */
585  }
586 }
587 
588 VOID
589 NTAPI
591 {
592  PULONG Pt;
593  LONG Pte;
594  KIRQL OldIrql;
595 
597  {
598  DPRINT1("MmClearPageAccessedBit is called for user space without a process.\n");
599  KeBugCheck(MEMORY_MANAGEMENT);
600  }
601 
603  if (Pt == NULL)
604  {
605  KeBugCheck(MEMORY_MANAGEMENT);
606  }
607 
608  do
609  {
610  Pte = *Pt;
611  } while (Pte != InterlockedCompareExchangePte(Pt, Pte & ~PA_ACCESSED, Pte));
612 
613  if (!(Pte & PA_PRESENT))
614  {
615  KeBugCheck(MEMORY_MANAGEMENT);
616  }
617 
618  MiFlushTlb(Pt, Address, OldIrql);
619 }
620 
621 BOOLEAN
622 NTAPI
624 {
626 }
627 
628 BOOLEAN
629 NTAPI
631 {
633 }
634 
635 BOOLEAN
636 NTAPI
638 {
640  return !(Entry & PA_PRESENT) && !(Entry & 0x800) && (Entry >> PAGE_SHIFT);
641 }
642 
643 BOOLEAN
644 NTAPI
646 {
647  ULONG Entry;
649  return !(Entry & PA_PRESENT) && (Entry & 0x800);
650 }
651 
652 NTSTATUS
653 NTAPI
655  PVOID Address,
656  SWAPENTRY SwapEntry)
657 {
658  PULONG Pt;
659  ULONG Pte;
660  KIRQL OldIrql;
661 
663  {
664  DPRINT1("No process\n");
665  KeBugCheck(MEMORY_MANAGEMENT);
666  }
667  if (Process != NULL && Address >= MmSystemRangeStart)
668  {
669  DPRINT1("Setting kernel address with process context\n");
670  KeBugCheck(MEMORY_MANAGEMENT);
671  }
672 
673  if (SwapEntry & (1 << 31))
674  {
675  KeBugCheck(MEMORY_MANAGEMENT);
676  }
677 
679  if (Pt == NULL)
680  {
681  /* Nobody should page out an address that hasn't even been mapped */
682  /* But we might place a wait entry first, requiring the page table */
683  if (SwapEntry != MM_WAIT_ENTRY)
684  {
685  KeBugCheck(MEMORY_MANAGEMENT);
686  }
688  }
689  Pte = InterlockedExchangePte(Pt, SwapEntry << 1);
690  if (Pte != 0)
691  {
692  KeBugCheckEx(MEMORY_MANAGEMENT, SwapEntry, (ULONG_PTR)Process, (ULONG_PTR)Address, 0);
693  }
694 
696  {
697  /* Add PDE reference */
698  Process->Vm.VmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)]++;
699  ASSERT(Process->Vm.VmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)] <= PTE_PER_PAGE);
700  }
701 
702  /* We don't need to flush the TLB here because it
703  * only caches valid translations and a zero PTE
704  * is not a valid translation */
706 
707  return(STATUS_SUCCESS);
708 }
709 
710 
711 NTSTATUS
712 NTAPI
714  PVOID Address,
715  ULONG flProtect,
716  PPFN_NUMBER Pages,
717  ULONG PageCount)
718 {
720  PVOID Addr;
721  ULONG i;
722  ULONG oldPdeOffset, PdeOffset;
723  PULONG Pt = NULL;
724  ULONG Pte;
725  KIRQL OldIrql;
726 
727  DPRINT("MmCreateVirtualMappingUnsafe(%p, %p, %lu, %p (%x), %lu)\n",
728  Process, Address, flProtect, Pages, *Pages, PageCount);
729 
730  ASSERT(((ULONG_PTR)Address % PAGE_SIZE) == 0);
731 
732  if (Process == NULL)
733  {
735  {
736  DPRINT1("NULL process given for user-mode mapping at %p -- %lu pages starting at %Ix\n", Address, PageCount, *Pages);
737  KeBugCheck(MEMORY_MANAGEMENT);
738  }
739  if (PageCount > 0x10000 ||
740  (ULONG_PTR) Address / PAGE_SIZE + PageCount > 0x100000)
741  {
742  DPRINT1("Page count too large for kernel-mode mapping at %p -- %lu pages starting at %Ix\n", Address, PageCount, *Pages);
743  KeBugCheck(MEMORY_MANAGEMENT);
744  }
745  }
746  else
747  {
749  {
750  DPRINT1("Process %p given for kernel-mode mapping at %p -- %lu pages starting at %Ix\n", Process, Address, PageCount, *Pages);
751  KeBugCheck(MEMORY_MANAGEMENT);
752  }
753  if (PageCount > (ULONG_PTR)MmSystemRangeStart / PAGE_SIZE ||
754  (ULONG_PTR) Address / PAGE_SIZE + PageCount >
756  {
757  DPRINT1("Page count too large for process %p user-mode mapping at %p -- %lu pages starting at %Ix\n", Process, Address, PageCount, *Pages);
758  KeBugCheck(MEMORY_MANAGEMENT);
759  }
760  }
761 
762  Attributes = ProtectToPTE(flProtect);
763  Attributes &= 0xfff;
765  {
766  Attributes &= ~PA_USER;
767  }
768  else
769  {
770  Attributes |= PA_USER;
771  }
772 
773  Addr = Address;
774  /* MmGetPageTableForProcess should be called on the first run, so
775  * let this trigger it */
776  oldPdeOffset = ADDR_TO_PDE_OFFSET(Addr) + 1;
777  for (i = 0; i < PageCount; i++, Addr = (PVOID)((ULONG_PTR)Addr + PAGE_SIZE))
778  {
779  if (!(Attributes & PA_PRESENT) && Pages[i] != 0)
780  {
781  DPRINT1("Setting physical address but not allowing access at address "
782  "0x%p with attributes %x/%x.\n",
783  Addr, Attributes, flProtect);
784  KeBugCheck(MEMORY_MANAGEMENT);
785  }
786  PdeOffset = ADDR_TO_PDE_OFFSET(Addr);
787  if (oldPdeOffset != PdeOffset)
788  {
789  if(Pt) MmUnmapPageTable(Pt, OldIrql);
791  if (Pt == NULL)
792  {
793  KeBugCheck(MEMORY_MANAGEMENT);
794  }
795  }
796  else
797  {
798  Pt++;
799  }
800  oldPdeOffset = PdeOffset;
801 
802  Pte = InterlockedExchangePte(Pt, PFN_TO_PTE(Pages[i]) | Attributes);
803 
804  /* There should not be anything valid here */
805  if (Pte != 0)
806  {
807  DPRINT1("Bad PTE %lx at %p for %p + %lu\n", Pte, Pt, Address, i);
808  KeBugCheck(MEMORY_MANAGEMENT);
809  }
810 
811  /* We don't need to flush the TLB here because it only caches valid translations
812  * and we're moving this PTE from invalid to valid so it can't be cached right now */
813 
814  if (Addr < MmSystemRangeStart)
815  {
816  /* Add PDE reference */
817  Process->Vm.VmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Addr)]++;
818  ASSERT(Process->Vm.VmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Addr)] <= PTE_PER_PAGE);
819  }
820  }
821 
822  ASSERT(Addr > Address);
824 
825  return(STATUS_SUCCESS);
826 }
827 
828 NTSTATUS
829 NTAPI
831  PVOID Address,
832  ULONG flProtect,
833  PPFN_NUMBER Pages,
834  ULONG PageCount)
835 {
836  ULONG i;
837 
839  for (i = 0; i < PageCount; i++)
840  {
841  if (!MmIsPageInUse(Pages[i]))
842  {
843  DPRINT1("Page at address %x not in use\n", PFN_TO_PTE(Pages[i]));
844  KeBugCheck(MEMORY_MANAGEMENT);
845  }
846  }
847 
849  Address,
850  flProtect,
851  Pages,
852  PageCount));
853 }
854 
855 ULONG
856 NTAPI
858 {
859  ULONG Entry;
860  ULONG Protect;
861 
863 
864 
865  if (!(Entry & PA_PRESENT))
866  {
868  }
869  else
870  {
871  if (Entry & PA_READWRITE)
872  {
874  }
875  else
876  {
878  }
879  if (Entry & PA_CD)
880  {
882  }
883  if (Entry & PA_WT)
884  {
886  }
887  if (!(Entry & PA_USER))
888  {
889  Protect |= PAGE_SYSTEM;
890  }
891 
892  }
893  return(Protect);
894 }
895 
896 VOID
897 NTAPI
899 {
900  ULONG Attributes = 0;
901  PULONG Pt;
902  ULONG Pte;
903  KIRQL OldIrql;
904 
905  DPRINT("MmSetPageProtect(Process %p Address %p flProtect %x)\n",
906  Process, Address, flProtect);
907 
908  Attributes = ProtectToPTE(flProtect);
909 
910  Attributes &= 0xfff;
912  {
913  Attributes &= ~PA_USER;
914  }
915  else
916  {
917  Attributes |= PA_USER;
918  }
919 
921  if (Pt == NULL)
922  {
923  KeBugCheck(MEMORY_MANAGEMENT);
924  }
925  Pte = InterlockedExchangePte(Pt, PAGE_MASK(*Pt) | Attributes | (*Pt & (PA_ACCESSED|PA_DIRTY)));
926 
927  // We should be able to bring a page back from PAGE_NOACCESS
928  if ((Pte & 0x800) || !(Pte >> PAGE_SHIFT))
929  {
930  DPRINT1("Invalid Pte %lx\n", Pte);
931  KeBugCheck(MEMORY_MANAGEMENT);
932  }
933 
934  if((Pte & Attributes) != Attributes)
935  MiFlushTlb(Pt, Address, OldIrql);
936  else
938 }
939 
940 CODE_SEG("INIT")
941 VOID
942 NTAPI
944 {
945  /* Nothing to do here */
946 }
947 
948 /* EOF */
#define PAGE_WRITETHROUGH
Definition: mm.h:87
#define PAGE_NOCACHE
Definition: nt_native.h:1311
VOID NTAPI MmDeletePageFileMapping(PEPROCESS Process, PVOID Address, SWAPENTRY *SwapEntry)
Definition: page.c:471
#define PAGE_SHIFT
Definition: env_spec_w32.h:45
#define IN
Definition: typedefs.h:39
BOOLEAN Mmi386MakeKernelPageTableGlobal(PVOID Address)
Definition: page.c:491
KAPC_STATE
Definition: ketypes.h:1280
BOOLEAN NTAPI MmIsPagePresent(PEPROCESS Process, PVOID Address)
Definition: page.c:297
#define PAGE_IS_EXECUTABLE
Definition: mm.h:137
#define MiAddressToPde(x)
Definition: mmx86.c:20
BOOLEAN NTAPI KeAreAllApcsDisabled(VOID)
Definition: apc.c:985
struct _Entry Entry
Definition: kefuncs.h:627
union _MMPTE::@2304 u
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID _In_ ULONG_PTR _In_ SIZE_T _Inout_opt_ PLARGE_INTEGER _Inout_ PSIZE_T _In_ SECTION_INHERIT _In_ ULONG _In_ ULONG Protect
Definition: zwfuncs.h:214
BOOLEAN NTAPI MmIsDisabledPage(PEPROCESS Process, PVOID Address)
Definition: page.c:306
#define TRUE
Definition: types.h:120
BOOLEAN NTAPI MmIsPageInUse(PFN_NUMBER Page)
Definition: freelist.c:559
#define BooleanFlagOn(F, SF)
Definition: ext2fs.h:183
_In_ BOOLEAN Create
Definition: pstypes.h:519
#define PAGE_GUARD
Definition: nt_native.h:1310
static ULONG ProtectToPTE(ULONG flProtect)
Definition: page.c:149
_In_ CLIPOBJ _In_ BRUSHOBJ _In_ LONG x1
Definition: winddi.h:3706
VOID NTAPI MmDeleteVirtualMapping(PEPROCESS Process, PVOID Address, BOOLEAN *WasDirty, PPFN_NUMBER Page)
Definition: page.c:428
LONG NTSTATUS
Definition: precomp.h:26
#define PA_DIRTY
Definition: page.c:35
_In_opt_ ULONG Base
Definition: rtlfuncs.h:2373
#define InterlockedExchangePte(pte1, pte2)
Definition: page.c:19
VOID NTAPI MmSetDirtyPage(PEPROCESS Process, PVOID Address)
Definition: page.c:405
#define PTE_TO_PFN(X)
Definition: page.c:43
BOOLEAN NTAPI MmIsDirtyPage(PEPROCESS Process, PVOID Address)
Definition: page.c:342
VOID NTAPI MmInitGlobalKernelPageDirectory(VOID)
Definition: page.c:278
VOID NTAPI MmSetCleanPage(PEPROCESS Process, PVOID Address)
Definition: page.c:382
#define MiGetPdeOffset(x)
Definition: mm.h:188
#define PFN_TO_PTE(X)
Definition: page.c:44
#define PA_WT
Definition: page.c:36
uint32_t ULONG_PTR
Definition: typedefs.h:65
UCHAR KIRQL
Definition: env_spec_w32.h:591
ULONG * PPFN_NUMBER
Definition: ke.h:9
#define MiAddressToPte(x)
Definition: mmx86.c:19
#define PAGE_EXECUTE_WRITECOPY
Definition: nt_native.h:1309
ULONG PFN_NUMBER
Definition: ke.h:9
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
#define FALSE
Definition: types.h:117
VOID NTAPI KeStackAttachProcess(IN PKPROCESS Process, OUT PRKAPC_STATE ApcState)
Definition: procobj.c:701
#define PAGE_IS_WRITABLE
Definition: mm.h:131
#define PA_ACCESSED
Definition: page.c:38
DECLSPEC_NORETURN VOID NTAPI KeBugCheck(ULONG BugCheckCode)
Definition: bug.c:1427
long LONG
Definition: pedump.c:60
static PULONG MmGetPageTableForProcess(PEPROCESS Process, PVOID Address, BOOLEAN Create, PKIRQL OldIrql)
Definition: page.c:206
NTSTATUS NTAPI MmCreatePageFileMapping(PEPROCESS Process, PVOID Address, SWAPENTRY SwapEntry)
Definition: page.c:499
BOOLEAN NTAPI MmIsPageSwapEntry(PEPROCESS Process, PVOID Address)
Definition: page.c:318
#define PsGetCurrentProcess
Definition: psfuncs.h:17
PVOID NTAPI MiMapPageInHyperSpace(IN PEPROCESS Process, IN PFN_NUMBER Page, IN PKIRQL OldIrql)
Definition: hypermap.c:28
#define PAGE_NOACCESS
Definition: nt_native.h:1302
unsigned char BOOLEAN
#define PA_PRESENT
Definition: page.c:32
static WCHAR Address[46]
Definition: ping.c:68
#define PAGE_EXECUTE
Definition: nt_native.h:1306
ULONG NTAPI MmGetPageProtect(PEPROCESS Process, PVOID Address)
Definition: page.c:351
PFN_NUMBER Page
Definition: section.c:4843
NTSTATUS NTAPI MmCreateVirtualMappingUnsafe(PEPROCESS Process, PVOID Address, ULONG PageProtection, PPFN_NUMBER Pages, ULONG PageCount)
Definition: page.c:543
void * PVOID
Definition: retypes.h:9
PFN_NUMBER NTAPI MmGetPfnForProcess(PEPROCESS Process, PVOID Address)
Definition: page.c:287
#define InterlockedCompareExchangePte(PointerPte, Exchange, Comperand)
Definition: mm.h:158
#define PA_READWRITE
Definition: page.c:33
Status
Definition: gdiplustypes.h:24
#define DBG_UNREFERENCED_LOCAL_VARIABLE(L)
Definition: ntbasedef.h:319
#define IS_HYPERSPACE(v)
Definition: page.c:41
FORCEINLINE VOID KeInvalidateTlbEntry(IN PVOID Address)
Definition: ke.h:201
#define PAGE_MASK(x)
Definition: page.c:46
#define ASSERT(a)
Definition: mode.c:45
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
BOOLEAN NTAPI MmIsPageAccessed(PEPROCESS Process, PVOID Address)
Definition: page.c:623
const ULONG64 MmProtectToPteMask[32]
Definition: page.c:32
ULONG64 Valid
Definition: mmtypes.h:150
#define PA_CD
Definition: page.c:37
MMPDE DemandZeroPde
Definition: page.c:114
#define PTE_PER_PAGE
Definition: mm.h:20
CODE_SEG("INIT")
Definition: fsrtlpc.c:19
NTSTATUS NTAPI MiFillSystemPageDirectory(IN PVOID Base, IN SIZE_T NumberOfBytes)
Definition: section.c:480
#define PAGE_SYSTEM
Definition: mm.h:88
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
KIRQL * PKIRQL
Definition: env_spec_w32.h:592
VOID MiFlushTlb(PMMPTE Pte, PVOID Address, KIRQL OldIrql)
Definition: page.c:128
#define ADDR_TO_PDE_OFFSET
Definition: page.c:18
#define PAGE_SIZE
Definition: env_spec_w32.h:49
const ULONG MmProtectToValue[32]
Definition: page.c:81
VOID NTAPI MmSetPageProtect(PEPROCESS Process, PVOID Address, ULONG flProtect)
Definition: page.c:362
ULONG_PTR Long
Definition: mmtypes.h:215
ULONG_PTR SIZE_T
Definition: typedefs.h:80
MMPTE_HARDWARE Hard
Definition: mmtypes.h:217
FORCEINLINE VOID MI_WRITE_INVALID_PTE(IN PMMPTE PointerPte, IN MMPTE InvalidPte)
Definition: miarm.h:975
#define PAGE_WRITECOMBINE
Definition: mmtypes.h:78
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
VOID NTAPI KeUnstackDetachProcess(IN PRKAPC_STATE ApcState)
Definition: procobj.c:753
ULONG_PTR SWAPENTRY
Definition: mm.h:47
_Out_ PKAPC_STATE ApcState
Definition: mm.h:1587
#define PA_USER
Definition: page.c:34
_Must_inspect_result_ typedef _In_ PHYSICAL_ADDRESS _Inout_ PLARGE_INTEGER NumberOfBytes
Definition: iotypes.h:1035
unsigned int * PULONG
Definition: retypes.h:1
VOID NTAPI MmGetPageFileMapping(PEPROCESS Process, PVOID Address, SWAPENTRY *SwapEntry)
Definition: page.c:327
#define NULL
Definition: types.h:112
#define PAGE_READONLY
Definition: compat.h:138
#define PAGE_WRITECOPY
Definition: nt_native.h:1305
static BOOLEAN MmUnmapPageTable(PULONG Pt, KIRQL OldIrql)
Definition: page.c:313
VOID NTAPI MmClearPageAccessedBit(PEPROCESS Process, PVOID Address)
Definition: page.c:590
#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
unsigned int ULONG
Definition: retypes.h:1
ULONG64 PageFrameNumber
Definition: mmtypes.h:171
#define PAGE_EXECUTE_READ
Definition: nt_native.h:1307
#define MiAddressToPteOffset(x)
Definition: mmx86.c:21
#define PAGE_EXECUTE_READWRITE
Definition: nt_native.h:1308
#define STATUS_SUCCESS
Definition: shellext.h:65
#define DPRINT
Definition: sndvol32.h:71
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 PVOID Vad)
#define MmSystemRangeStart
Definition: mm.h:32
NTSTATUS NTAPI MmCreateVirtualMapping(PEPROCESS Process, PVOID Address, ULONG Protect, PPFN_NUMBER Pages, ULONG PageCount)
Definition: page.c:599
base of all file and directory entries
Definition: entries.h:82
static ULONG MmGetPageEntryForProcess(PEPROCESS Process, PVOID Address)
Definition: page.c:325
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
#define PAGE_IS_READABLE
Definition: mm.h:123
#define PAGE_READWRITE
Definition: nt_native.h:1304
_Must_inspect_result_ _In_ WDFDMAENABLER _In_ _In_opt_ PWDF_OBJECT_ATTRIBUTES Attributes