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.45 2002/10/01 19:27:25 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 ***************************************************************/
31 #include <ddk/ntddk.h>
32 #include <internal/mm.h>
33 #include <internal/i386/mm.h>
34 #include <internal/ex.h>
35 #include <internal/ps.h>
38 #include <internal/debug.h>
40 /* GLOBALS *****************************************************************/
42 #define PA_BIT_PRESENT (0)
43 #define PA_BIT_READWRITE (1)
44 #define PA_BIT_USER (2)
47 #define PA_BIT_ACCESSED (5)
48 #define PA_BIT_DIRTY (6)
50 #define PA_PRESENT (1 << PA_BIT_PRESENT)
51 #define PA_READWRITE (1 << PA_BIT_READWRITE)
52 #define PA_USER (1 << PA_BIT_USER)
53 #define PA_DIRTY (1 << PA_BIT_DIRTY)
54 #define PA_WT (1 << PA_BIT_WT)
55 #define PA_CD (1 << PA_BIT_CD)
56 #define PA_ACCESSED (1 << PA_BIT_ACCESSED)
57 #define PA_DIRTY (1 << PA_BIT_DIRTY)
59 #define PAGETABLE_MAP (0xf0000000)
60 #define PAGEDIRECTORY_MAP (0xf0000000 + (PAGETABLE_MAP / (1024)))
62 ULONG MmGlobalKernelPageDirectory
[1024] = {0, };
64 #define PTE_TO_PAGE(X) ((LARGE_INTEGER)(LONGLONG)(PAGE_MASK(X)))
66 /* FUNCTIONS ***************************************************************/
69 MmGetPageDirectory(VOID
)
71 unsigned int page_dir
=0;
72 __asm__("movl %%cr3,%0\n\t"
74 return((PULONG
)page_dir
);
78 ProtectToPTE(ULONG flProtect
)
82 if (flProtect
& PAGE_NOACCESS
|| flProtect
& PAGE_GUARD
)
86 else if (flProtect
& PAGE_READWRITE
|| flProtect
& PAGE_EXECUTE_READWRITE
)
88 Attributes
= PA_PRESENT
| PA_READWRITE
;
90 else if (flProtect
& PAGE_READONLY
|| flProtect
& PAGE_EXECUTE
||
91 flProtect
& PAGE_EXECUTE_READ
)
93 Attributes
= PA_PRESENT
;
97 DPRINT1("Unknown main protection type.\n");
100 if (!(flProtect
& PAGE_SYSTEM
))
102 Attributes
= Attributes
| PA_USER
;
104 if (flProtect
& PAGE_NOCACHE
)
106 Attributes
= Attributes
| PA_CD
;
108 if (flProtect
& PAGE_WRITETHROUGH
)
110 Attributes
= Attributes
| PA_WT
;
115 #define ADDR_TO_PAGE_TABLE(v) (((ULONG)(v)) / (4 * 1024 * 1024))
117 #define ADDR_TO_PDE(v) (PULONG)(PAGEDIRECTORY_MAP + \
118 (((ULONG)v / (1024 * 1024))&(~0x3)))
119 #define ADDR_TO_PTE(v) (PULONG)(PAGETABLE_MAP + ((((ULONG)v / 1024))&(~0x3)))
121 #define ADDR_TO_PDE_OFFSET(v) (((ULONG)v / (4 * 1024 * 1024)))
123 NTSTATUS
Mmi386ReleaseMmInfo(PEPROCESS Process
)
125 DPRINT("Mmi386ReleaseMmInfo(Process %x)\n",Process
);
127 MmReleasePageMemoryConsumer(MC_NPPOOL
, Process
->Pcb
.DirectoryTableBase
);
128 Process
->Pcb
.DirectoryTableBase
.QuadPart
= 0LL;
130 DPRINT("Finished Mmi386ReleaseMmInfo()\n");
131 return(STATUS_SUCCESS
);
134 NTSTATUS
MmCopyMmInfo(PEPROCESS Src
, PEPROCESS Dest
)
136 PHYSICAL_ADDRESS PhysPageDirectory
;
137 PULONG PageDirectory
;
138 PULONG CurrentPageDirectory
;
139 PKPROCESS KProcess
= &Dest
->Pcb
;
142 DPRINT("MmCopyMmInfo(Src %x, Dest %x)\n", Src
, Dest
);
144 PageDirectory
= ExAllocatePage();
145 if (PageDirectory
== NULL
)
147 return(STATUS_UNSUCCESSFUL
);
149 PhysPageDirectory
= MmGetPhysicalAddress(PageDirectory
);
150 KProcess
->DirectoryTableBase
= PhysPageDirectory
;
151 CurrentPageDirectory
= (PULONG
)PAGEDIRECTORY_MAP
;
153 memset(PageDirectory
,0,PAGE_SIZE
);
154 for (i
=768; i
<896; i
++)
156 PageDirectory
[i
] = CurrentPageDirectory
[i
];
158 for (i
=961; i
<1024; i
++)
160 PageDirectory
[i
] = CurrentPageDirectory
[i
];
162 DPRINT("Addr %x\n",PAGETABLE_MAP
/ (4*1024*1024));
163 PageDirectory
[PAGETABLE_MAP
/ (4*1024*1024)] =
164 (ULONG
)PhysPageDirectory
.QuadPart
| 0x7;
166 ExUnmapPage(PageDirectory
);
168 DPRINT("Finished MmCopyMmInfo()\n");
169 return(STATUS_SUCCESS
);
172 VOID
MmDeletePageTable(PEPROCESS Process
, PVOID Address
)
174 PEPROCESS CurrentProcess
= PsGetCurrentProcess();
176 if (Process
!= NULL
&& Process
!= CurrentProcess
)
178 KeAttachProcess(Process
);
180 *(ADDR_TO_PDE(Address
)) = 0;
181 if (Address
>= (PVOID
)KERNEL_BASE
)
183 MmGlobalKernelPageDirectory
[ADDR_TO_PDE_OFFSET(Address
)] = 0;
186 if (Process
!= NULL
&& Process
!= CurrentProcess
)
192 VOID
MmFreePageTable(PEPROCESS Process
, PVOID Address
)
194 PEPROCESS CurrentProcess
= PsGetCurrentProcess();
199 if (Process
!= NULL
&& Process
!= CurrentProcess
)
201 KeAttachProcess(Process
);
203 PageTable
= (PULONG
)PAGE_ROUND_DOWN((PVOID
)ADDR_TO_PTE(Address
));
204 for (i
= 0; i
< 1024; i
++)
206 if (PageTable
[i
] != 0)
208 DbgPrint("Page table entry not clear at %x/%x (is %x)\n",
209 ((ULONG
)Address
/ 4*1024*1024), i
, PageTable
[i
]);
213 npage
= *(ADDR_TO_PDE(Address
));
214 *(ADDR_TO_PDE(Address
)) = 0;
215 if (Address
>= (PVOID
)KERNEL_BASE
)
217 MmGlobalKernelPageDirectory
[ADDR_TO_PDE_OFFSET(Address
)] = 0;
219 MmReleasePageMemoryConsumer(MC_NPPOOL
, PTE_TO_PAGE(npage
));
221 if (Process
!= NULL
&& Process
!= CurrentProcess
)
227 NTSTATUS
MmGetPageEntry2(PVOID PAddress
, PULONG
* Pte
, BOOLEAN MayWait
)
229 * FUNCTION: Get a pointer to the page table entry for a virtual address
233 ULONG Address
= (ULONG
)PAddress
;
234 PHYSICAL_ADDRESS npage
;
236 DPRINT("MmGetPageEntry(Address %x)\n", Address
);
238 Pde
= ADDR_TO_PDE(Address
);
241 if (Address
>= KERNEL_BASE
&&
242 MmGlobalKernelPageDirectory
[ADDR_TO_PDE_OFFSET(Address
)] != 0)
244 (*Pde
) = MmGlobalKernelPageDirectory
[ADDR_TO_PDE_OFFSET(Address
)];
250 Status
= MmRequestPageMemoryConsumer(MC_NPPOOL
, MayWait
, &npage
);
251 if (!NT_SUCCESS(Status
))
255 (*Pde
) = npage
.QuadPart
| 0x7;
256 if (Address
>= KERNEL_BASE
)
258 MmGlobalKernelPageDirectory
[ADDR_TO_PDE_OFFSET(Address
)] =
261 memset((PVOID
)PAGE_ROUND_DOWN(ADDR_TO_PTE(Address
)), 0, PAGE_SIZE
);
265 *Pte
= ADDR_TO_PTE(Address
);
266 return(STATUS_SUCCESS
);
269 ULONG
MmGetPageEntryForProcess(PEPROCESS Process
, PVOID Address
)
272 PEPROCESS CurrentProcess
= PsGetCurrentProcess();
274 if (Process
!= NULL
&& Process
!= CurrentProcess
)
276 KeAttachProcess(Process
);
278 Entry
= *MmGetPageEntry(Address
);
279 if (Process
!= NULL
&& Process
!= CurrentProcess
)
286 ULONG
MmGetPageEntry1(PVOID PAddress
)
288 * FUNCTION: Get a pointer to the page table entry for a virtual address
293 ULONG Address
= (ULONG
)PAddress
;
295 DPRINT("MmGetPageEntry(Address %x)\n", Address
);
297 page_dir
= ADDR_TO_PDE(Address
);
298 if ((*page_dir
) == 0 &&
299 MmGlobalKernelPageDirectory
[ADDR_TO_PDE_OFFSET(Address
)] != 0)
301 (*page_dir
) = MmGlobalKernelPageDirectory
[ADDR_TO_PDE_OFFSET(Address
)];
304 DPRINT("page_dir %x *page_dir %x\n",page_dir
,*page_dir
);
305 if ((*page_dir
) == 0)
309 page_tlb
= ADDR_TO_PTE(Address
);
310 DPRINT("page_tlb %x\n",page_tlb
);
314 ULONG
MmGetPageEntryForProcess1(PEPROCESS Process
, PVOID Address
)
317 PEPROCESS CurrentProcess
= PsGetCurrentProcess();
319 if (Process
!= NULL
&& Process
!= CurrentProcess
)
321 KeAttachProcess(Process
);
323 Entry
= MmGetPageEntry1(Address
);
324 if (Process
!= NULL
&& Process
!= CurrentProcess
)
333 MmGetPhysicalAddressForProcess(PEPROCESS Process
,
338 PageEntry
= MmGetPageEntryForProcess(Process
, Address
);
340 if (!(PageEntry
& PA_PRESENT
))
342 return((LARGE_INTEGER
)0LL);
344 return(PTE_TO_PAGE(PageEntry
));
348 MmDisableVirtualMapping(PEPROCESS Process
, PVOID Address
, BOOL
* WasDirty
, PHYSICAL_ADDRESS
* PhysicalAddr
)
350 * FUNCTION: Delete a virtual mapping
355 PEPROCESS CurrentProcess
= PsGetCurrentProcess();
359 * If we are setting a page in another process we need to be in its
362 if (Process
!= NULL
&& Process
!= CurrentProcess
)
364 KeAttachProcess(Process
);
368 * Set the page directory entry, we may have to copy the entry from
369 * the global page directory.
371 Pde
= ADDR_TO_PDE(Address
);
373 MmGlobalKernelPageDirectory
[ADDR_TO_PDE_OFFSET(Address
)] != 0)
375 (*Pde
) = MmGlobalKernelPageDirectory
[ADDR_TO_PDE_OFFSET(Address
)];
384 * Atomically set the entry to zero and get the old value.
386 Pte
= *ADDR_TO_PTE(Address
);
387 *ADDR_TO_PTE(Address
) = Pte
& (~PA_PRESENT
);
389 WasValid
= (PAGE_MASK(Pte
) != 0);
396 * If necessary go back to the original context
398 if (Process
!= NULL
&& Process
!= CurrentProcess
)
404 * Return some information to the caller
406 if (WasDirty
!= NULL
)
408 *WasDirty
= Pte
& PA_DIRTY
;
410 if (PhysicalAddr
!= NULL
)
412 PhysicalAddr
->u
.HighPart
= 0;
413 PhysicalAddr
->u
.LowPart
= PAGE_MASK(Pte
);
418 MmDeleteVirtualMapping(PEPROCESS Process
, PVOID Address
, BOOL FreePage
,
419 BOOL
* WasDirty
, PHYSICAL_ADDRESS
* PhysicalAddr
)
421 * FUNCTION: Delete a virtual mapping
426 PEPROCESS CurrentProcess
= PsGetCurrentProcess();
430 * If we are setting a page in another process we need to be in its
433 if (Process
!= NULL
&& Process
!= CurrentProcess
)
435 KeAttachProcess(Process
);
439 * Set the page directory entry, we may have to copy the entry from
440 * the global page directory.
442 Pde
= ADDR_TO_PDE(Address
);
444 MmGlobalKernelPageDirectory
[ADDR_TO_PDE_OFFSET(Address
)] != 0)
446 (*Pde
) = MmGlobalKernelPageDirectory
[ADDR_TO_PDE_OFFSET(Address
)];
451 if (Process
!= NULL
&& Process
!= CurrentProcess
)
455 if (WasDirty
!= NULL
)
459 if (PhysicalAddr
!= NULL
)
461 *PhysicalAddr
= (LARGE_INTEGER
)0LL;
467 * Atomically set the entry to zero and get the old value.
469 Pte
= (ULONG
)InterlockedExchange((PLONG
)ADDR_TO_PTE(Address
), 0);
471 WasValid
= (PAGE_MASK(Pte
) != 0);
474 MmMarkPageUnmapped(PTE_TO_PAGE(Pte
));
476 if (FreePage
&& WasValid
)
478 MmReleasePageMemoryConsumer(MC_NPPOOL
, PTE_TO_PAGE(Pte
));
482 * Decrement the reference count for this page table.
484 if (Process
!= NULL
&& WasValid
&&
485 Process
->AddressSpace
.PageTableRefCountTable
!= NULL
&&
486 ADDR_TO_PAGE_TABLE(Address
) < 768)
490 Ptrc
= Process
->AddressSpace
.PageTableRefCountTable
;
492 Ptrc
[ADDR_TO_PAGE_TABLE(Address
)]--;
493 if (Ptrc
[ADDR_TO_PAGE_TABLE(Address
)] == 0)
495 MmFreePageTable(Process
, Address
);
500 * If necessary go back to the original context
502 if (Process
!= NULL
&& Process
!= CurrentProcess
)
508 * Return some information to the caller
510 if (WasDirty
!= NULL
)
521 if (PhysicalAddr
!= NULL
)
523 *PhysicalAddr
= PTE_TO_PAGE(Pte
);
528 MmDeletePageFileMapping(PEPROCESS Process
, PVOID Address
,
529 SWAPENTRY
* SwapEntry
)
531 * FUNCTION: Delete a virtual mapping
536 PEPROCESS CurrentProcess
= PsGetCurrentProcess();
537 BOOLEAN WasValid
= FALSE
;
540 * If we are setting a page in another process we need to be in its
543 if (Process
!= NULL
&& Process
!= CurrentProcess
)
545 KeAttachProcess(Process
);
549 * Set the page directory entry, we may have to copy the entry from
550 * the global page directory.
552 Pde
= ADDR_TO_PDE(Address
);
554 MmGlobalKernelPageDirectory
[ADDR_TO_PDE_OFFSET(Address
)] != 0)
556 (*Pde
) = MmGlobalKernelPageDirectory
[ADDR_TO_PDE_OFFSET(Address
)];
561 if (Process
!= NULL
&& Process
!= CurrentProcess
)
570 * Atomically set the entry to zero and get the old value.
572 Pte
= (ULONG
)InterlockedExchange((PLONG
)ADDR_TO_PTE(Address
), 0);
576 * Decrement the reference count for this page table.
578 if (Process
!= NULL
&& WasValid
&&
579 Process
->AddressSpace
.PageTableRefCountTable
!= NULL
&&
580 ADDR_TO_PAGE_TABLE(Address
) < 768)
584 Ptrc
= Process
->AddressSpace
.PageTableRefCountTable
;
586 Ptrc
[ADDR_TO_PAGE_TABLE(Address
)]--;
587 if (Ptrc
[ADDR_TO_PAGE_TABLE(Address
)] == 0)
589 MmFreePageTable(Process
, Address
);
594 * If necessary go back to the original context
596 if (Process
!= NULL
&& Process
!= CurrentProcess
)
602 * Return some information to the caller
604 *SwapEntry
= Pte
>> 1;
608 Mmi386MakeKernelPageTableGlobal(PVOID PAddress
)
611 ULONG Address
= (ULONG
)PAddress
;
613 page_dir
= ADDR_TO_PDE(Address
);
614 if ((*page_dir
) == 0 &&
615 MmGlobalKernelPageDirectory
[ADDR_TO_PDE_OFFSET(Address
)] != 0)
617 (*page_dir
) = MmGlobalKernelPageDirectory
[ADDR_TO_PDE_OFFSET(Address
)];
624 BOOLEAN
MmIsPageTablePresent(PVOID PAddress
)
627 ULONG Address
= (ULONG
)PAddress
;
629 page_dir
= ADDR_TO_PDE(Address
);
630 if ((*page_dir
) == 0 &&
631 MmGlobalKernelPageDirectory
[ADDR_TO_PDE_OFFSET(Address
)] != 0)
633 (*page_dir
) = MmGlobalKernelPageDirectory
[ADDR_TO_PDE_OFFSET(Address
)];
636 return((*page_dir
) == 0);
639 NTSTATUS
MmCreatePageTable(PVOID PAddress
)
642 ULONG Address
= (ULONG
)PAddress
;
643 PHYSICAL_ADDRESS npage
;
645 DPRINT("MmGetPageEntry(Address %x)\n", Address
);
647 page_dir
= ADDR_TO_PDE(Address
);
648 DPRINT("page_dir %x *page_dir %x\n",page_dir
,*page_dir
);
649 if ((*page_dir
) == 0 &&
650 MmGlobalKernelPageDirectory
[ADDR_TO_PDE_OFFSET(Address
)] != 0)
652 (*page_dir
) = MmGlobalKernelPageDirectory
[ADDR_TO_PDE_OFFSET(Address
)];
655 if ((*page_dir
) == 0)
658 Status
= MmRequestPageMemoryConsumer(MC_NPPOOL
, FALSE
, &npage
);
659 if (!NT_SUCCESS(Status
))
663 (*page_dir
) = npage
.QuadPart
| 0x7;
664 memset((PVOID
)PAGE_ROUND_DOWN(ADDR_TO_PTE(Address
)), 0, PAGE_SIZE
);
667 return(STATUS_SUCCESS
);
670 PULONG
MmGetPageEntry(PVOID PAddress
)
672 * FUNCTION: Get a pointer to the page table entry for a virtual address
677 ULONG Address
= (ULONG
)PAddress
;
678 PHYSICAL_ADDRESS npage
;
680 DPRINT("MmGetPageEntry(Address %x)\n", Address
);
682 page_dir
= ADDR_TO_PDE(Address
);
683 DPRINT("page_dir %x *page_dir %x\n",page_dir
,*page_dir
);
684 if ((*page_dir
) == 0 &&
685 MmGlobalKernelPageDirectory
[ADDR_TO_PDE_OFFSET(Address
)] != 0)
687 (*page_dir
) = MmGlobalKernelPageDirectory
[ADDR_TO_PDE_OFFSET(Address
)];
690 if ((*page_dir
) == 0)
693 Status
= MmRequestPageMemoryConsumer(MC_NPPOOL
, FALSE
, &npage
);
694 if (!NT_SUCCESS(Status
))
698 (*page_dir
) = npage
.QuadPart
| 0x7;
699 memset((PVOID
)PAGE_ROUND_DOWN(ADDR_TO_PTE(Address
)), 0, PAGE_SIZE
);
702 page_tlb
= ADDR_TO_PTE(Address
);
703 DPRINT("page_tlb %x\n",page_tlb
);
707 BOOLEAN
MmIsDirtyPage(PEPROCESS Process
, PVOID Address
)
709 return((MmGetPageEntryForProcess(Process
, Address
)) & PA_DIRTY
);
713 MmIsAccessedAndResetAccessPage(PEPROCESS Process
, PVOID Address
)
716 PEPROCESS CurrentProcess
= PsGetCurrentProcess();
719 if (Process
!= CurrentProcess
)
721 KeAttachProcess(Process
);
723 PageEntry
= MmGetPageEntry(Address
);
724 Accessed
= (*PageEntry
) & PA_ACCESSED
;
727 (*PageEntry
) = (*PageEntry
) & (~PA_ACCESSED
);
730 if (Process
!= CurrentProcess
)
738 VOID
MmSetCleanPage(PEPROCESS Process
, PVOID Address
)
741 PEPROCESS CurrentProcess
= PsGetCurrentProcess();
743 if (Process
!= CurrentProcess
)
745 KeAttachProcess(Process
);
747 PageEntry
= MmGetPageEntry(Address
);
748 (*PageEntry
) = (*PageEntry
) & (~PA_DIRTY
);
750 if (Process
!= CurrentProcess
)
756 VOID
MmSetDirtyPage(PEPROCESS Process
, PVOID Address
)
759 PEPROCESS CurrentProcess
= PsGetCurrentProcess();
761 if (Process
!= CurrentProcess
)
763 KeAttachProcess(Process
);
765 PageEntry
= MmGetPageEntry(Address
);
766 (*PageEntry
) = (*PageEntry
) | PA_DIRTY
;
768 if (Process
!= CurrentProcess
)
774 VOID
MmEnableVirtualMapping(PEPROCESS Process
, PVOID Address
)
777 PEPROCESS CurrentProcess
= PsGetCurrentProcess();
779 if (Process
!= CurrentProcess
)
781 KeAttachProcess(Process
);
783 PageEntry
= MmGetPageEntry(Address
);
784 (*PageEntry
) = (*PageEntry
) | PA_PRESENT
;
786 if (Process
!= CurrentProcess
)
792 BOOLEAN
MmIsPagePresent(PEPROCESS Process
, PVOID Address
)
794 return((MmGetPageEntryForProcess1(Process
, Address
)) & PA_PRESENT
);
797 BOOLEAN
MmIsPageSwapEntry(PEPROCESS Process
, PVOID Address
)
800 Pte
= MmGetPageEntryForProcess1(Process
, Address
);
801 return((!(Pte
& PA_PRESENT
)) && Pte
!= 0);
805 MmCreateVirtualMappingForKernel(PVOID Address
,
807 PHYSICAL_ADDRESS PhysicalAddress
)
809 PEPROCESS CurrentProcess
;
813 PEPROCESS Process
= NULL
;
817 CurrentProcess
= PsGetCurrentProcess();
821 CurrentProcess
= NULL
;
824 if (Process
== NULL
&& Address
< (PVOID
)KERNEL_BASE
)
826 DPRINT1("No process\n");
829 if (Process
!= NULL
&& Address
>= (PVOID
)KERNEL_BASE
)
831 DPRINT1("Setting kernel address with process context\n");
834 Attributes
= ProtectToPTE(flProtect
);
836 if (Process
!= NULL
&& Process
!= CurrentProcess
)
838 KeAttachProcess(Process
);
841 Status
= MmGetPageEntry2(Address
, &Pte
, FALSE
);
842 if (!NT_SUCCESS(Status
))
844 if (Process
!= NULL
&& Process
!= CurrentProcess
)
850 if (PAGE_MASK((*Pte
)) != 0 && !((*Pte
) & PA_PRESENT
))
854 if (PAGE_MASK((*Pte
)) != 0)
856 MmMarkPageUnmapped(PTE_TO_PAGE((*Pte
)));
858 *Pte
= PhysicalAddress
.QuadPart
| Attributes
;
859 if (Process
!= NULL
&&
860 Process
->AddressSpace
.PageTableRefCountTable
!= NULL
&&
861 ADDR_TO_PAGE_TABLE(Address
) < 768 &&
862 Attributes
& PA_PRESENT
)
866 Ptrc
= Process
->AddressSpace
.PageTableRefCountTable
;
868 Ptrc
[ADDR_TO_PAGE_TABLE(Address
)]++;
871 if (Process
!= NULL
&& Process
!= CurrentProcess
)
875 return(STATUS_SUCCESS
);
879 MmCreatePageFileMapping(PEPROCESS Process
,
883 PEPROCESS CurrentProcess
;
889 CurrentProcess
= PsGetCurrentProcess();
893 CurrentProcess
= NULL
;
896 if (Process
== NULL
&& Address
< (PVOID
)KERNEL_BASE
)
898 DPRINT1("No process\n");
901 if (Process
!= NULL
&& Address
>= (PVOID
)KERNEL_BASE
)
903 DPRINT1("Setting kernel address with process context\n");
906 if (SwapEntry
& (1 << 31))
911 if (Process
!= NULL
&& Process
!= CurrentProcess
)
913 KeAttachProcess(Process
);
916 Status
= MmGetPageEntry2(Address
, &Pte
, FALSE
);
917 if (!NT_SUCCESS(Status
))
919 if (Process
!= NULL
&& Process
!= CurrentProcess
)
925 if (PAGE_MASK((*Pte
)) != 0)
927 MmMarkPageUnmapped(PTE_TO_PAGE((*Pte
)));
929 *Pte
= SwapEntry
<< 1;
930 if (Process
!= NULL
&&
931 Process
->AddressSpace
.PageTableRefCountTable
!= NULL
&&
932 ADDR_TO_PAGE_TABLE(Address
) < 768)
936 Ptrc
= Process
->AddressSpace
.PageTableRefCountTable
;
938 Ptrc
[ADDR_TO_PAGE_TABLE(Address
)]++;
941 if (Process
!= NULL
&& Process
!= CurrentProcess
)
945 return(STATUS_SUCCESS
);
949 MmCreateVirtualMappingUnsafe(PEPROCESS Process
,
952 PHYSICAL_ADDRESS PhysicalAddress
,
955 PEPROCESS CurrentProcess
;
962 CurrentProcess
= PsGetCurrentProcess();
966 CurrentProcess
= NULL
;
969 if (Process
== NULL
&& Address
< (PVOID
)KERNEL_BASE
)
971 DPRINT1("No process\n");
974 if (Process
!= NULL
&& Address
>= (PVOID
)KERNEL_BASE
)
976 DPRINT1("Setting kernel address with process context\n");
979 MmMarkPageMapped(PhysicalAddress
);
981 Attributes
= ProtectToPTE(flProtect
);
982 if (!(Attributes
& PA_PRESENT
) && PhysicalAddress
.QuadPart
!= 0)
984 DPRINT1("Setting physical address but not allowing access at address "
985 "0x%.8X with attributes %x/%x.\n",
986 Address
, Attributes
, flProtect
);
990 if (Process
!= NULL
&& Process
!= CurrentProcess
)
992 KeAttachProcess(Process
);
995 Status
= MmGetPageEntry2(Address
, &Pte
, MayWait
);
996 if (!NT_SUCCESS(Status
))
998 if (Process
!= NULL
&& Process
!= CurrentProcess
)
1004 if (PAGE_MASK((*Pte
)) != 0 && !((*Pte
) & PA_PRESENT
))
1008 if (PAGE_MASK((*Pte
)) != 0)
1010 MmMarkPageUnmapped(PTE_TO_PAGE((*Pte
)));
1012 *Pte
= PhysicalAddress
.QuadPart
| Attributes
;
1013 if (Process
!= NULL
&&
1014 Process
->AddressSpace
.PageTableRefCountTable
!= NULL
&&
1015 ADDR_TO_PAGE_TABLE(Address
) < 768 &&
1016 Attributes
& PA_PRESENT
)
1020 Ptrc
= Process
->AddressSpace
.PageTableRefCountTable
;
1022 Ptrc
[ADDR_TO_PAGE_TABLE(Address
)]++;
1025 if (Process
!= NULL
&& Process
!= CurrentProcess
)
1029 return(STATUS_SUCCESS
);
1033 MmCreateVirtualMapping(PEPROCESS Process
,
1036 PHYSICAL_ADDRESS PhysicalAddress
,
1039 if (!MmIsUsablePage(PhysicalAddress
))
1041 DPRINT1("Page at address %x not usable\n", PhysicalAddress
);
1045 return(MmCreateVirtualMappingUnsafe(Process
,
1053 MmGetPageProtect(PEPROCESS Process
, PVOID Address
)
1058 Entry
= MmGetPageEntryForProcess1(Process
, Address
);
1060 if (!(Entry
& PA_PRESENT
))
1062 Protect
= PAGE_NOACCESS
;
1064 else if (Entry
& PA_READWRITE
)
1066 Protect
= PAGE_READWRITE
;
1070 Protect
= PAGE_EXECUTE_READ
;
1076 MmSetPageProtect(PEPROCESS Process
, PVOID Address
, ULONG flProtect
)
1078 ULONG Attributes
= 0;
1080 PEPROCESS CurrentProcess
= PsGetCurrentProcess();
1082 DPRINT("MmSetPageProtect(Process %x Address %x flProtect %x)\n",
1083 Process
, Address
, flProtect
);
1085 Attributes
= ProtectToPTE(flProtect
);
1086 if (Process
!= NULL
&& Process
!= CurrentProcess
)
1088 KeAttachProcess(Process
);
1090 PageEntry
= MmGetPageEntry(Address
);
1091 (*PageEntry
) = PAGE_MASK(*PageEntry
) | Attributes
;
1093 if (Process
!= NULL
&& Process
!= CurrentProcess
)
1099 PHYSICAL_ADDRESS STDCALL
1100 MmGetPhysicalAddress(PVOID vaddr
)
1102 * FUNCTION: Returns the physical address corresponding to a virtual address
1108 DPRINT("MmGetPhysicalAddress(vaddr %x)\n", vaddr
);
1110 Pte
= *MmGetPageEntry(vaddr
);
1111 if (Pte
& PA_PRESENT
)
1113 p
.QuadPart
= PAGE_MASK(Pte
);