3 * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 /* $Id: page.c,v 1.42 2002/09/07 15:13:03 chorns Exp $
21 * PROJECT: ReactOS kernel
22 * FILE: ntoskrnl/mm/i386/page.c
23 * PURPOSE: low level memory managment manipulation
24 * PROGRAMER: David Welch (welch@cwcom.net)
29 /* INCLUDES ***************************************************************/
34 #include <internal/debug.h>
37 /* GLOBALS *****************************************************************/
39 #define PA_BIT_PRESENT (0)
40 #define PA_BIT_READWRITE (1)
41 #define PA_BIT_USER (2)
44 #define PA_BIT_ACCESSED (5)
45 #define PA_BIT_DIRTY (6)
47 #define PA_PRESENT (1 << PA_BIT_PRESENT)
48 #define PA_READWRITE (1 << PA_BIT_READWRITE)
49 #define PA_USER (1 << PA_BIT_USER)
50 #define PA_DIRTY (1 << PA_BIT_DIRTY)
51 #define PA_WT (1 << PA_BIT_WT)
52 #define PA_CD (1 << PA_BIT_CD)
53 #define PA_ACCESSED (1 << PA_BIT_ACCESSED)
54 #define PA_DIRTY (1 << PA_BIT_DIRTY)
56 #define PAGETABLE_MAP (0xf0000000)
57 #define PAGEDIRECTORY_MAP (0xf0000000 + (PAGETABLE_MAP / (1024)))
59 ULONG MmGlobalKernelPageDirectory
[1024] = {0, };
61 #define PTE_TO_PAGE(X) ((LARGE_INTEGER)(LONGLONG)(PAGE_MASK(X)))
63 /* FUNCTIONS ***************************************************************/
66 MmGetPageDirectory(VOID
)
68 unsigned int page_dir
=0;
69 __asm__("movl %%cr3,%0\n\t"
71 return((PULONG
)page_dir
);
75 ProtectToPTE(ULONG flProtect
)
79 if (flProtect
& PAGE_NOACCESS
|| flProtect
& PAGE_GUARD
)
83 else if (flProtect
& PAGE_READWRITE
|| flProtect
& PAGE_EXECUTE_READWRITE
)
85 Attributes
= PA_PRESENT
| PA_READWRITE
;
87 else if (flProtect
& PAGE_READONLY
|| flProtect
& PAGE_EXECUTE
||
88 flProtect
& PAGE_EXECUTE_READ
)
90 Attributes
= PA_PRESENT
;
94 DPRINT1("Unknown main protection type.\n");
97 if (!(flProtect
& PAGE_SYSTEM
))
99 Attributes
= Attributes
| PA_USER
;
101 if (flProtect
& PAGE_NOCACHE
)
103 Attributes
= Attributes
| PA_CD
;
105 if (flProtect
& PAGE_WRITETHROUGH
)
107 Attributes
= Attributes
| PA_WT
;
112 #define ADDR_TO_PAGE_TABLE(v) (((ULONG)(v)) / (4 * 1024 * 1024))
114 #define ADDR_TO_PDE(v) (PULONG)(PAGEDIRECTORY_MAP + \
115 (((ULONG)v / (1024 * 1024))&(~0x3)))
116 #define ADDR_TO_PTE(v) (PULONG)(PAGETABLE_MAP + ((((ULONG)v / 1024))&(~0x3)))
118 #define ADDR_TO_PDE_OFFSET(v) (((ULONG)v / (4 * 1024 * 1024)))
120 NTSTATUS
Mmi386ReleaseMmInfo(PEPROCESS Process
)
122 DPRINT("Mmi386ReleaseMmInfo(Process %x)\n",Process
);
124 MmReleasePageMemoryConsumer(MC_NPPOOL
, Process
->Pcb
.DirectoryTableBase
);
125 Process
->Pcb
.DirectoryTableBase
.QuadPart
= 0LL;
127 DPRINT("Finished Mmi386ReleaseMmInfo()\n");
128 return(STATUS_SUCCESS
);
131 NTSTATUS
MmCopyMmInfo(PEPROCESS Src
, PEPROCESS Dest
)
133 PHYSICAL_ADDRESS PhysPageDirectory
;
134 PULONG PageDirectory
;
135 PULONG CurrentPageDirectory
;
136 PKPROCESS KProcess
= &Dest
->Pcb
;
139 DPRINT("MmCopyMmInfo(Src %x, Dest %x)\n", Src
, Dest
);
141 PageDirectory
= ExAllocatePage();
142 if (PageDirectory
== NULL
)
144 return(STATUS_UNSUCCESSFUL
);
146 PhysPageDirectory
= MmGetPhysicalAddress(PageDirectory
);
147 KProcess
->DirectoryTableBase
= PhysPageDirectory
;
148 CurrentPageDirectory
= (PULONG
)PAGEDIRECTORY_MAP
;
150 memset(PageDirectory
,0,PAGE_SIZE
);
151 for (i
=768; i
<896; i
++)
153 PageDirectory
[i
] = CurrentPageDirectory
[i
];
155 for (i
=961; i
<1024; i
++)
157 PageDirectory
[i
] = CurrentPageDirectory
[i
];
159 DPRINT("Addr %x\n",PAGETABLE_MAP
/ (4*1024*1024));
160 PageDirectory
[PAGETABLE_MAP
/ (4*1024*1024)] =
161 (ULONG
)PhysPageDirectory
.QuadPart
| 0x7;
163 ExUnmapPage(PageDirectory
);
165 DPRINT("Finished MmCopyMmInfo()\n");
166 return(STATUS_SUCCESS
);
169 VOID
MmDeletePageTable(PEPROCESS Process
, PVOID Address
)
171 PEPROCESS CurrentProcess
= PsGetCurrentProcess();
173 if (Process
!= NULL
&& Process
!= CurrentProcess
)
175 KeAttachProcess(Process
);
177 *(ADDR_TO_PDE(Address
)) = 0;
178 if (Address
>= (PVOID
)KERNEL_BASE
)
180 MmGlobalKernelPageDirectory
[ADDR_TO_PDE_OFFSET(Address
)] = 0;
183 if (Process
!= NULL
&& Process
!= CurrentProcess
)
189 VOID
MmFreePageTable(PEPROCESS Process
, PVOID Address
)
191 PEPROCESS CurrentProcess
= PsGetCurrentProcess();
196 if (Process
!= NULL
&& Process
!= CurrentProcess
)
198 KeAttachProcess(Process
);
200 PageTable
= (PULONG
)PAGE_ROUND_DOWN((PVOID
)ADDR_TO_PTE(Address
));
201 for (i
= 0; i
< 1024; i
++)
203 if (PageTable
[i
] != 0)
205 DbgPrint("Page table entry not clear at %x/%x (is %x)\n",
206 ((ULONG
)Address
/ 4*1024*1024), i
, PageTable
[i
]);
210 npage
= *(ADDR_TO_PDE(Address
));
211 *(ADDR_TO_PDE(Address
)) = 0;
212 if (Address
>= (PVOID
)KERNEL_BASE
)
214 MmGlobalKernelPageDirectory
[ADDR_TO_PDE_OFFSET(Address
)] = 0;
216 MmReleasePageMemoryConsumer(MC_NPPOOL
, PTE_TO_PAGE(npage
));
218 if (Process
!= NULL
&& Process
!= CurrentProcess
)
224 NTSTATUS
MmGetPageEntry2(PVOID PAddress
, PULONG
* Pte
, BOOLEAN MayWait
)
226 * FUNCTION: Get a pointer to the page table entry for a virtual address
230 ULONG Address
= (ULONG
)PAddress
;
231 PHYSICAL_ADDRESS npage
;
233 DPRINT("MmGetPageEntry(Address %x)\n", Address
);
235 Pde
= ADDR_TO_PDE(Address
);
238 if (Address
>= KERNEL_BASE
&&
239 MmGlobalKernelPageDirectory
[ADDR_TO_PDE_OFFSET(Address
)] != 0)
241 (*Pde
) = MmGlobalKernelPageDirectory
[ADDR_TO_PDE_OFFSET(Address
)];
247 Status
= MmRequestPageMemoryConsumer(MC_NPPOOL
, MayWait
, &npage
);
248 if (!NT_SUCCESS(Status
))
252 (*Pde
) = npage
.QuadPart
| 0x7;
253 if (Address
>= KERNEL_BASE
)
255 MmGlobalKernelPageDirectory
[ADDR_TO_PDE_OFFSET(Address
)] =
258 memset((PVOID
)PAGE_ROUND_DOWN(ADDR_TO_PTE(Address
)), 0, PAGE_SIZE
);
262 *Pte
= ADDR_TO_PTE(Address
);
263 return(STATUS_SUCCESS
);
266 ULONG
MmGetPageEntryForProcess(PEPROCESS Process
, PVOID Address
)
269 PEPROCESS CurrentProcess
= PsGetCurrentProcess();
271 if (Process
!= NULL
&& Process
!= CurrentProcess
)
273 KeAttachProcess(Process
);
275 Entry
= *MmGetPageEntry(Address
);
276 if (Process
!= NULL
&& Process
!= CurrentProcess
)
283 ULONG
MmGetPageEntry1(PVOID PAddress
)
285 * FUNCTION: Get a pointer to the page table entry for a virtual address
290 ULONG Address
= (ULONG
)PAddress
;
292 DPRINT("MmGetPageEntry(Address %x)\n", Address
);
294 page_dir
= ADDR_TO_PDE(Address
);
295 if ((*page_dir
) == 0 &&
296 MmGlobalKernelPageDirectory
[ADDR_TO_PDE_OFFSET(Address
)] != 0)
298 (*page_dir
) = MmGlobalKernelPageDirectory
[ADDR_TO_PDE_OFFSET(Address
)];
301 DPRINT("page_dir %x *page_dir %x\n",page_dir
,*page_dir
);
302 if ((*page_dir
) == 0)
306 page_tlb
= ADDR_TO_PTE(Address
);
307 DPRINT("page_tlb %x\n",page_tlb
);
311 ULONG
MmGetPageEntryForProcess1(PEPROCESS Process
, PVOID Address
)
314 PEPROCESS CurrentProcess
= PsGetCurrentProcess();
316 if (Process
!= NULL
&& Process
!= CurrentProcess
)
318 KeAttachProcess(Process
);
320 Entry
= MmGetPageEntry1(Address
);
321 if (Process
!= NULL
&& Process
!= CurrentProcess
)
330 MmGetPhysicalAddressForProcess(PEPROCESS Process
,
335 PageEntry
= MmGetPageEntryForProcess(Process
, Address
);
337 if (!(PageEntry
& PA_PRESENT
))
339 return((LARGE_INTEGER
)0LL);
341 return(PTE_TO_PAGE(PageEntry
));
345 MmDisableVirtualMapping(PEPROCESS Process
, PVOID Address
, BOOL
* WasDirty
, PHYSICAL_ADDRESS
* PhysicalAddr
)
347 * FUNCTION: Delete a virtual mapping
352 PEPROCESS CurrentProcess
= PsGetCurrentProcess();
356 * If we are setting a page in another process we need to be in its
359 if (Process
!= NULL
&& Process
!= CurrentProcess
)
361 KeAttachProcess(Process
);
365 * Set the page directory entry, we may have to copy the entry from
366 * the global page directory.
368 Pde
= ADDR_TO_PDE(Address
);
370 MmGlobalKernelPageDirectory
[ADDR_TO_PDE_OFFSET(Address
)] != 0)
372 (*Pde
) = MmGlobalKernelPageDirectory
[ADDR_TO_PDE_OFFSET(Address
)];
381 * Atomically set the entry to zero and get the old value.
383 Pte
= *ADDR_TO_PTE(Address
);
384 *ADDR_TO_PTE(Address
) = Pte
& (~PA_PRESENT
);
386 WasValid
= (PAGE_MASK(Pte
) != 0);
393 * If necessary go back to the original context
395 if (Process
!= NULL
&& Process
!= CurrentProcess
)
401 * Return some information to the caller
403 if (WasDirty
!= NULL
)
405 *WasDirty
= Pte
& PA_DIRTY
;
407 if (PhysicalAddr
!= NULL
)
409 PhysicalAddr
->u
.HighPart
= 0;
410 PhysicalAddr
->u
.LowPart
= PAGE_MASK(Pte
);
415 MmDeleteVirtualMapping(PEPROCESS Process
, PVOID Address
, BOOL FreePage
,
416 BOOL
* WasDirty
, PHYSICAL_ADDRESS
* PhysicalAddr
)
418 * FUNCTION: Delete a virtual mapping
423 PEPROCESS CurrentProcess
= PsGetCurrentProcess();
427 * If we are setting a page in another process we need to be in its
430 if (Process
!= NULL
&& Process
!= CurrentProcess
)
432 KeAttachProcess(Process
);
436 * Set the page directory entry, we may have to copy the entry from
437 * the global page directory.
439 Pde
= ADDR_TO_PDE(Address
);
441 MmGlobalKernelPageDirectory
[ADDR_TO_PDE_OFFSET(Address
)] != 0)
443 (*Pde
) = MmGlobalKernelPageDirectory
[ADDR_TO_PDE_OFFSET(Address
)];
448 if (Process
!= NULL
&& Process
!= CurrentProcess
)
452 if (WasDirty
!= NULL
)
456 if (PhysicalAddr
!= NULL
)
458 *PhysicalAddr
= (LARGE_INTEGER
)0LL;
464 * Atomically set the entry to zero and get the old value.
466 Pte
= (ULONG
)InterlockedExchange((PLONG
)ADDR_TO_PTE(Address
), 0);
468 WasValid
= (PAGE_MASK(Pte
) != 0);
471 MmMarkPageUnmapped(PTE_TO_PAGE(Pte
));
473 if (FreePage
&& WasValid
)
475 MmReleasePageMemoryConsumer(MC_NPPOOL
, PTE_TO_PAGE(Pte
));
479 * Decrement the reference count for this page table.
481 if (Process
!= NULL
&& WasValid
&&
482 Process
->AddressSpace
.PageTableRefCountTable
!= NULL
&&
483 ADDR_TO_PAGE_TABLE(Address
) < 768)
487 Ptrc
= Process
->AddressSpace
.PageTableRefCountTable
;
489 Ptrc
[ADDR_TO_PAGE_TABLE(Address
)]--;
490 if (Ptrc
[ADDR_TO_PAGE_TABLE(Address
)] == 0)
492 MmFreePageTable(Process
, Address
);
497 * If necessary go back to the original context
499 if (Process
!= NULL
&& Process
!= CurrentProcess
)
505 * Return some information to the caller
507 if (WasDirty
!= NULL
)
518 if (PhysicalAddr
!= NULL
)
520 *PhysicalAddr
= PTE_TO_PAGE(Pte
);
525 MmDeletePageFileMapping(PEPROCESS Process
, PVOID Address
,
526 SWAPENTRY
* SwapEntry
)
528 * FUNCTION: Delete a virtual mapping
533 PEPROCESS CurrentProcess
= PsGetCurrentProcess();
537 * If we are setting a page in another process we need to be in its
540 if (Process
!= NULL
&& Process
!= CurrentProcess
)
542 KeAttachProcess(Process
);
546 * Set the page directory entry, we may have to copy the entry from
547 * the global page directory.
549 Pde
= ADDR_TO_PDE(Address
);
551 MmGlobalKernelPageDirectory
[ADDR_TO_PDE_OFFSET(Address
)] != 0)
553 (*Pde
) = MmGlobalKernelPageDirectory
[ADDR_TO_PDE_OFFSET(Address
)];
558 if (Process
!= NULL
&& Process
!= CurrentProcess
)
567 * Atomically set the entry to zero and get the old value.
569 Pte
= (ULONG
)InterlockedExchange((PLONG
)ADDR_TO_PTE(Address
), 0);
573 * Decrement the reference count for this page table.
575 if (Process
!= NULL
&& WasValid
&&
576 Process
->AddressSpace
.PageTableRefCountTable
!= NULL
&&
577 ADDR_TO_PAGE_TABLE(Address
) < 768)
581 Ptrc
= Process
->AddressSpace
.PageTableRefCountTable
;
583 Ptrc
[ADDR_TO_PAGE_TABLE(Address
)]--;
584 if (Ptrc
[ADDR_TO_PAGE_TABLE(Address
)] == 0)
586 MmFreePageTable(Process
, Address
);
591 * If necessary go back to the original context
593 if (Process
!= NULL
&& Process
!= CurrentProcess
)
599 * Return some information to the caller
601 *SwapEntry
= Pte
>> 1;
605 Mmi386MakeKernelPageTableGlobal(PVOID PAddress
)
608 ULONG Address
= (ULONG
)PAddress
;
610 page_dir
= ADDR_TO_PDE(Address
);
611 if ((*page_dir
) == 0 &&
612 MmGlobalKernelPageDirectory
[ADDR_TO_PDE_OFFSET(Address
)] != 0)
614 (*page_dir
) = MmGlobalKernelPageDirectory
[ADDR_TO_PDE_OFFSET(Address
)];
621 BOOLEAN
MmIsPageTablePresent(PVOID PAddress
)
624 ULONG Address
= (ULONG
)PAddress
;
626 page_dir
= ADDR_TO_PDE(Address
);
627 if ((*page_dir
) == 0 &&
628 MmGlobalKernelPageDirectory
[ADDR_TO_PDE_OFFSET(Address
)] != 0)
630 (*page_dir
) = MmGlobalKernelPageDirectory
[ADDR_TO_PDE_OFFSET(Address
)];
633 return((*page_dir
) == 0);
636 NTSTATUS
MmCreatePageTable(PVOID PAddress
)
639 ULONG Address
= (ULONG
)PAddress
;
640 PHYSICAL_ADDRESS npage
;
642 DPRINT("MmGetPageEntry(Address %x)\n", Address
);
644 page_dir
= ADDR_TO_PDE(Address
);
645 DPRINT("page_dir %x *page_dir %x\n",page_dir
,*page_dir
);
646 if ((*page_dir
) == 0 &&
647 MmGlobalKernelPageDirectory
[ADDR_TO_PDE_OFFSET(Address
)] != 0)
649 (*page_dir
) = MmGlobalKernelPageDirectory
[ADDR_TO_PDE_OFFSET(Address
)];
652 if ((*page_dir
) == 0)
655 Status
= MmRequestPageMemoryConsumer(MC_NPPOOL
, FALSE
, &npage
);
656 if (!NT_SUCCESS(Status
))
660 (*page_dir
) = npage
.QuadPart
| 0x7;
661 memset((PVOID
)PAGE_ROUND_DOWN(ADDR_TO_PTE(Address
)), 0, PAGE_SIZE
);
664 return(STATUS_SUCCESS
);
667 PULONG
MmGetPageEntry(PVOID PAddress
)
669 * FUNCTION: Get a pointer to the page table entry for a virtual address
674 ULONG Address
= (ULONG
)PAddress
;
675 PHYSICAL_ADDRESS npage
;
677 DPRINT("MmGetPageEntry(Address %x)\n", Address
);
679 page_dir
= ADDR_TO_PDE(Address
);
680 DPRINT("page_dir %x *page_dir %x\n",page_dir
,*page_dir
);
681 if ((*page_dir
) == 0 &&
682 MmGlobalKernelPageDirectory
[ADDR_TO_PDE_OFFSET(Address
)] != 0)
684 (*page_dir
) = MmGlobalKernelPageDirectory
[ADDR_TO_PDE_OFFSET(Address
)];
687 if ((*page_dir
) == 0)
690 Status
= MmRequestPageMemoryConsumer(MC_NPPOOL
, FALSE
, &npage
);
691 if (!NT_SUCCESS(Status
))
695 (*page_dir
) = npage
.QuadPart
| 0x7;
696 memset((PVOID
)PAGE_ROUND_DOWN(ADDR_TO_PTE(Address
)), 0, PAGE_SIZE
);
699 page_tlb
= ADDR_TO_PTE(Address
);
700 DPRINT("page_tlb %x\n",page_tlb
);
704 BOOLEAN
MmIsDirtyPage(PEPROCESS Process
, PVOID Address
)
706 return((MmGetPageEntryForProcess(Process
, Address
)) & PA_DIRTY
);
710 MmIsAccessedAndResetAccessPage(PEPROCESS Process
, PVOID Address
)
713 PEPROCESS CurrentProcess
= PsGetCurrentProcess();
716 if (Process
!= CurrentProcess
)
718 KeAttachProcess(Process
);
720 PageEntry
= MmGetPageEntry(Address
);
721 Accessed
= (*PageEntry
) & PA_ACCESSED
;
724 (*PageEntry
) = (*PageEntry
) & (~PA_ACCESSED
);
727 if (Process
!= CurrentProcess
)
735 VOID
MmSetCleanPage(PEPROCESS Process
, PVOID Address
)
738 PEPROCESS CurrentProcess
= PsGetCurrentProcess();
740 if (Process
!= CurrentProcess
)
742 KeAttachProcess(Process
);
744 PageEntry
= MmGetPageEntry(Address
);
745 (*PageEntry
) = (*PageEntry
) & (~PA_DIRTY
);
747 if (Process
!= CurrentProcess
)
753 VOID
MmSetDirtyPage(PEPROCESS Process
, PVOID Address
)
756 PEPROCESS CurrentProcess
= PsGetCurrentProcess();
758 if (Process
!= CurrentProcess
)
760 KeAttachProcess(Process
);
762 PageEntry
= MmGetPageEntry(Address
);
763 (*PageEntry
) = (*PageEntry
) | PA_DIRTY
;
765 if (Process
!= CurrentProcess
)
771 VOID
MmEnableVirtualMapping(PEPROCESS Process
, PVOID Address
)
774 PEPROCESS CurrentProcess
= PsGetCurrentProcess();
776 if (Process
!= CurrentProcess
)
778 KeAttachProcess(Process
);
780 PageEntry
= MmGetPageEntry(Address
);
781 (*PageEntry
) = (*PageEntry
) | PA_PRESENT
;
783 if (Process
!= CurrentProcess
)
789 BOOLEAN
MmIsPagePresent(PEPROCESS Process
, PVOID Address
)
791 return((MmGetPageEntryForProcess1(Process
, Address
)) & PA_PRESENT
);
794 BOOLEAN
MmIsPageSwapEntry(PEPROCESS Process
, PVOID Address
)
797 Pte
= MmGetPageEntryForProcess1(Process
, Address
);
798 return((!(Pte
& PA_PRESENT
)) && Pte
!= 0);
802 MmCreateVirtualMappingForKernel(PVOID Address
,
804 PHYSICAL_ADDRESS PhysicalAddress
)
806 PEPROCESS CurrentProcess
;
810 PEPROCESS Process
= NULL
;
814 CurrentProcess
= PsGetCurrentProcess();
818 CurrentProcess
= NULL
;
821 if (Process
== NULL
&& Address
< (PVOID
)KERNEL_BASE
)
823 DPRINT1("No process\n");
826 if (Process
!= NULL
&& Address
>= (PVOID
)KERNEL_BASE
)
828 DPRINT1("Setting kernel address with process context\n");
831 Attributes
= ProtectToPTE(flProtect
);
833 if (Process
!= NULL
&& Process
!= CurrentProcess
)
835 KeAttachProcess(Process
);
838 Status
= MmGetPageEntry2(Address
, &Pte
, FALSE
);
839 if (!NT_SUCCESS(Status
))
841 if (Process
!= NULL
&& Process
!= CurrentProcess
)
847 if (PAGE_MASK((*Pte
)) != 0 && !((*Pte
) & PA_PRESENT
))
851 if (PAGE_MASK((*Pte
)) != 0)
853 MmMarkPageUnmapped(PTE_TO_PAGE((*Pte
)));
855 *Pte
= PhysicalAddress
.QuadPart
| Attributes
;
856 if (Process
!= NULL
&&
857 Process
->AddressSpace
.PageTableRefCountTable
!= NULL
&&
858 ADDR_TO_PAGE_TABLE(Address
) < 768 &&
859 Attributes
& PA_PRESENT
)
863 Ptrc
= Process
->AddressSpace
.PageTableRefCountTable
;
865 Ptrc
[ADDR_TO_PAGE_TABLE(Address
)]++;
868 if (Process
!= NULL
&& Process
!= CurrentProcess
)
872 return(STATUS_SUCCESS
);
876 MmCreatePageFileMapping(PEPROCESS Process
,
880 PEPROCESS CurrentProcess
;
886 CurrentProcess
= PsGetCurrentProcess();
890 CurrentProcess
= NULL
;
893 if (Process
== NULL
&& Address
< (PVOID
)KERNEL_BASE
)
895 DPRINT1("No process\n");
898 if (Process
!= NULL
&& Address
>= (PVOID
)KERNEL_BASE
)
900 DPRINT1("Setting kernel address with process context\n");
903 if (SwapEntry
& (1 << 31))
908 if (Process
!= NULL
&& Process
!= CurrentProcess
)
910 KeAttachProcess(Process
);
913 Status
= MmGetPageEntry2(Address
, &Pte
, FALSE
);
914 if (!NT_SUCCESS(Status
))
916 if (Process
!= NULL
&& Process
!= CurrentProcess
)
922 if (PAGE_MASK((*Pte
)) != 0)
924 MmMarkPageUnmapped(PTE_TO_PAGE((*Pte
)));
926 *Pte
= SwapEntry
<< 1;
927 if (Process
!= NULL
&&
928 Process
->AddressSpace
.PageTableRefCountTable
!= NULL
&&
929 ADDR_TO_PAGE_TABLE(Address
) < 768)
933 Ptrc
= Process
->AddressSpace
.PageTableRefCountTable
;
935 Ptrc
[ADDR_TO_PAGE_TABLE(Address
)]++;
938 if (Process
!= NULL
&& Process
!= CurrentProcess
)
942 return(STATUS_SUCCESS
);
946 MmCreateVirtualMappingUnsafe(PEPROCESS Process
,
949 PHYSICAL_ADDRESS PhysicalAddress
,
952 PEPROCESS CurrentProcess
;
959 CurrentProcess
= PsGetCurrentProcess();
963 CurrentProcess
= NULL
;
966 if (Process
== NULL
&& Address
< (PVOID
)KERNEL_BASE
)
968 DPRINT1("No process\n");
971 if (Process
!= NULL
&& Address
>= (PVOID
)KERNEL_BASE
)
973 DPRINT1("Setting kernel address with process context\n");
976 MmMarkPageMapped(PhysicalAddress
);
978 Attributes
= ProtectToPTE(flProtect
);
979 if (!(Attributes
& PA_PRESENT
) && PhysicalAddress
.QuadPart
!= 0)
981 DPRINT1("Setting physical address but not allowing access at address "
982 "0x%.8X with attributes %x/%x.\n",
983 Address
, Attributes
, flProtect
);
987 if (Process
!= NULL
&& Process
!= CurrentProcess
)
989 KeAttachProcess(Process
);
992 Status
= MmGetPageEntry2(Address
, &Pte
, MayWait
);
993 if (!NT_SUCCESS(Status
))
995 if (Process
!= NULL
&& Process
!= CurrentProcess
)
1001 if (PAGE_MASK((*Pte
)) != 0 && !((*Pte
) & PA_PRESENT
))
1005 if (PAGE_MASK((*Pte
)) != 0)
1007 MmMarkPageUnmapped(PTE_TO_PAGE((*Pte
)));
1009 *Pte
= PhysicalAddress
.QuadPart
| Attributes
;
1010 if (Process
!= NULL
&&
1011 Process
->AddressSpace
.PageTableRefCountTable
!= NULL
&&
1012 ADDR_TO_PAGE_TABLE(Address
) < 768 &&
1013 Attributes
& PA_PRESENT
)
1017 Ptrc
= Process
->AddressSpace
.PageTableRefCountTable
;
1019 Ptrc
[ADDR_TO_PAGE_TABLE(Address
)]++;
1022 if (Process
!= NULL
&& Process
!= CurrentProcess
)
1026 return(STATUS_SUCCESS
);
1030 MmCreateVirtualMapping(PEPROCESS Process
,
1033 PHYSICAL_ADDRESS PhysicalAddress
,
1036 if (!MmIsUsablePage(PhysicalAddress
))
1038 DPRINT1("Page at address %x not usable\n", PhysicalAddress
);
1042 return(MmCreateVirtualMappingUnsafe(Process
,
1050 MmGetPageProtect(PEPROCESS Process
, PVOID Address
)
1055 Entry
= MmGetPageEntryForProcess1(Process
, Address
);
1057 if (!(Entry
& PA_PRESENT
))
1059 Protect
= PAGE_NOACCESS
;
1061 else if (Entry
& PA_READWRITE
)
1063 Protect
= PAGE_READWRITE
;
1067 Protect
= PAGE_EXECUTE_READ
;
1073 MmSetPageProtect(PEPROCESS Process
, PVOID Address
, ULONG flProtect
)
1075 ULONG Attributes
= 0;
1077 PEPROCESS CurrentProcess
= PsGetCurrentProcess();
1079 DPRINT("MmSetPageProtect(Process %x Address %x flProtect %x)\n",
1080 Process
, Address
, flProtect
);
1082 Attributes
= ProtectToPTE(flProtect
);
1083 if (Process
!= NULL
&& Process
!= CurrentProcess
)
1085 KeAttachProcess(Process
);
1087 PageEntry
= MmGetPageEntry(Address
);
1088 (*PageEntry
) = PAGE_MASK(*PageEntry
) | Attributes
;
1090 if (Process
!= NULL
&& Process
!= CurrentProcess
)
1096 PHYSICAL_ADDRESS STDCALL
1097 MmGetPhysicalAddress(PVOID vaddr
)
1099 * FUNCTION: Returns the physical address corresponding to a virtual address
1105 DPRINT("MmGetPhysicalAddress(vaddr %x)\n", vaddr
);
1107 Pte
= *MmGetPageEntry(vaddr
);
1108 if (Pte
& PA_PRESENT
)
1110 p
.QuadPart
= PAGE_MASK(Pte
);