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.
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 PhysPageDirectory.u.LowPart | PA_PRESENT | PA_READWRITE;
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)
184 // MmGlobalKernelPageDirectory[ADDR_TO_PDE_OFFSET(Address)] = 0;
187 if (Process != NULL && Process != CurrentProcess)
193 VOID MmFreePageTable(PEPROCESS Process, PVOID Address)
195 PEPROCESS CurrentProcess = PsGetCurrentProcess();
200 if (Process != NULL && Process != CurrentProcess)
202 KeAttachProcess(Process);
205 PageTable = (PULONG)PAGE_ROUND_DOWN((PVOID)ADDR_TO_PTE(Address));
206 for (i = 0; i < 1024; i++)
208 if (PageTable[i] != 0)
210 DbgPrint("Page table entry not clear at %x/%x (is %x)\n",
211 ((ULONG)Address / 4*1024*1024), i, PageTable[i]);
215 npage = *(ADDR_TO_PDE(Address));
216 *(ADDR_TO_PDE(Address)) = 0;
219 if (Address >= (PVOID)KERNEL_BASE)
221 // MmGlobalKernelPageDirectory[ADDR_TO_PDE_OFFSET(Address)] = 0;
226 MmReleasePageMemoryConsumer(MC_NPPOOL, PTE_TO_PAGE(npage));
228 if (Process != NULL && Process != CurrentProcess)
234 NTSTATUS MmGetPageEntry2(PVOID PAddress, PULONG* Pte, BOOLEAN MayWait)
236 * FUNCTION: Get a pointer to the page table entry for a virtual address
240 PHYSICAL_ADDRESS npage;
241 BOOLEAN Free = FALSE;
245 DPRINT("MmGetPageEntry(Address %x)\n", PAddress);
247 Pde = ADDR_TO_PDE(PAddress);
250 if (PAddress >= (PVOID)KERNEL_BASE)
252 kePde = MmGlobalKernelPageDirectory + ADDR_TO_PDE_OFFSET(PAddress);
253 oldIrql = KeRaiseIrqlToSynchLevel();
261 KeLowerIrql(oldIrql);
262 Status = MmRequestPageMemoryConsumer(MC_NPPOOL, MayWait, &npage);
263 if (!NT_SUCCESS(Status))
267 oldIrql = KeRaiseIrqlToSynchLevel();
268 /* An other thread can set this pde entry, we must check again */
271 *kePde = npage.u.LowPart | PA_PRESENT | PA_READWRITE;
280 KeLowerIrql(oldIrql);
284 Status = MmRequestPageMemoryConsumer(MC_NPPOOL, MayWait, &npage);
285 if (!NT_SUCCESS(Status))
289 *Pde = npage.u.LowPart | PA_PRESENT | PA_READWRITE | PA_USER;
293 *Pte = (PULONG)ADDR_TO_PTE(PAddress);
296 MmReleasePageMemoryConsumer(MC_NPPOOL, npage);
298 return STATUS_SUCCESS;
301 ULONG MmGetPageEntryForProcess(PEPROCESS Process, PVOID Address)
304 PEPROCESS CurrentProcess = PsGetCurrentProcess();
306 if (Process != NULL && Process != CurrentProcess)
308 KeAttachProcess(Process);
310 Entry = *MmGetPageEntry(Address);
311 if (Process != NULL && Process != CurrentProcess)
318 ULONG MmGetPageEntry1(PVOID PAddress)
320 * FUNCTION: Get a pointer to the page table entry for a virtual address
326 DPRINT("MmGetPageEntry(Address %x)\n", PAddress);
328 Pde = ADDR_TO_PDE(PAddress);
331 if (PAddress >= (PVOID)KERNEL_BASE)
333 kePde = MmGlobalKernelPageDirectory + ADDR_TO_PDE_OFFSET(PAddress);
338 Entry = *(PULONG)ADDR_TO_PTE(PAddress);
344 Entry = *(PULONG)ADDR_TO_PTE(PAddress);
349 ULONG MmGetPageEntryForProcess1(PEPROCESS Process, PVOID Address)
352 PEPROCESS CurrentProcess = PsGetCurrentProcess();
354 if (Process != NULL && Process != CurrentProcess)
356 KeAttachProcess(Process);
358 Entry = MmGetPageEntry1(Address);
359 if (Process != NULL && Process != CurrentProcess)
368 MmGetPhysicalAddressForProcess(PEPROCESS Process,
373 PageEntry = MmGetPageEntryForProcess(Process, Address);
375 if (!(PageEntry & PA_PRESENT))
377 return((LARGE_INTEGER)0LL);
379 return(PTE_TO_PAGE(PageEntry));
383 MmDisableVirtualMapping(PEPROCESS Process, PVOID Address, BOOL* WasDirty, PHYSICAL_ADDRESS* PhysicalAddr)
385 * FUNCTION: Delete a virtual mapping
390 PEPROCESS CurrentProcess = PsGetCurrentProcess();
394 * If we are setting a page in another process we need to be in its
397 if (Process != NULL && Process != CurrentProcess)
399 KeAttachProcess(Process);
403 * Set the page directory entry, we may have to copy the entry from
404 * the global page directory.
406 Pde = ADDR_TO_PDE(Address);
408 MmGlobalKernelPageDirectory[ADDR_TO_PDE_OFFSET(Address)] != 0)
410 (*Pde) = MmGlobalKernelPageDirectory[ADDR_TO_PDE_OFFSET(Address)];
419 * Atomically set the entry to zero and get the old value.
421 Pte = *ADDR_TO_PTE(Address);
422 *ADDR_TO_PTE(Address) = Pte & (~PA_PRESENT);
424 WasValid = (PAGE_MASK(Pte) != 0);
431 * If necessary go back to the original context
433 if (Process != NULL && Process != CurrentProcess)
439 * Return some information to the caller
441 if (WasDirty != NULL)
443 *WasDirty = Pte & PA_DIRTY;
445 if (PhysicalAddr != NULL)
447 PhysicalAddr->u.HighPart = 0;
448 PhysicalAddr->u.LowPart = PAGE_MASK(Pte);
453 MmDeleteVirtualMapping(PEPROCESS Process, PVOID Address, BOOL FreePage,
454 BOOL* WasDirty, PHYSICAL_ADDRESS* PhysicalAddr)
456 * FUNCTION: Delete a virtual mapping
461 PEPROCESS CurrentProcess = PsGetCurrentProcess();
465 * If we are setting a page in another process we need to be in its
468 if (Process != NULL && Process != CurrentProcess)
470 KeAttachProcess(Process);
474 * Set the page directory entry, we may have to copy the entry from
475 * the global page directory.
477 Pde = ADDR_TO_PDE(Address);
478 if (*Pde == 0 && Address >= (PVOID)KERNEL_BASE)
480 kePde = MmGlobalKernelPageDirectory + ADDR_TO_PDE_OFFSET(Address);
490 if (Process != NULL && Process != CurrentProcess)
494 if (WasDirty != NULL)
498 if (PhysicalAddr != NULL)
500 *PhysicalAddr = (LARGE_INTEGER)0LL;
506 * Atomically set the entry to zero and get the old value.
508 Pte = (ULONG)InterlockedExchange((PLONG)ADDR_TO_PTE(Address), 0);
510 WasValid = (PAGE_MASK(Pte) != 0);
513 MmMarkPageUnmapped(PTE_TO_PAGE(Pte));
515 if (FreePage && WasValid)
517 MmReleasePageMemoryConsumer(MC_NPPOOL, PTE_TO_PAGE(Pte));
521 * Decrement the reference count for this page table.
523 if (Process != NULL && WasValid &&
524 Process->AddressSpace.PageTableRefCountTable != NULL &&
525 Address < (PVOID)KERNEL_BASE)
529 Ptrc = Process->AddressSpace.PageTableRefCountTable;
531 Ptrc[ADDR_TO_PAGE_TABLE(Address)]--;
532 if (Ptrc[ADDR_TO_PAGE_TABLE(Address)] == 0)
534 MmFreePageTable(Process, Address);
539 * If necessary go back to the original context
541 if (Process != NULL && Process != CurrentProcess)
547 * Return some information to the caller
549 if (WasDirty != NULL)
560 if (PhysicalAddr != NULL)
562 *PhysicalAddr = PTE_TO_PAGE(Pte);
567 MmDeletePageFileMapping(PEPROCESS Process, PVOID Address,
568 SWAPENTRY* SwapEntry)
570 * FUNCTION: Delete a virtual mapping
575 PEPROCESS CurrentProcess = PsGetCurrentProcess();
576 BOOLEAN WasValid = FALSE;
579 * If we are setting a page in another process we need to be in its
582 if (Process != NULL && Process != CurrentProcess)
584 KeAttachProcess(Process);
588 * Set the page directory entry, we may have to copy the entry from
589 * the global page directory.
591 Pde = ADDR_TO_PDE(Address);
594 if (Address >= (PVOID)KERNEL_BASE)
596 kePde = MmGlobalKernelPageDirectory + ADDR_TO_PDE_OFFSET(Address);
606 if (Process != NULL && Process != CurrentProcess)
615 * Atomically set the entry to zero and get the old value.
617 Pte = (ULONG)InterlockedExchange((PLONG)ADDR_TO_PTE(Address), 0);
620 WasValid = PAGE_MASK(Pte) == 0 ? FALSE : TRUE;
623 * Decrement the reference count for this page table.
625 if (Process != NULL && WasValid &&
626 Process->AddressSpace.PageTableRefCountTable != NULL &&
627 Address < (PVOID)KERNEL_BASE)
631 Ptrc = Process->AddressSpace.PageTableRefCountTable;
633 Ptrc[ADDR_TO_PAGE_TABLE(Address)]--;
634 if (Ptrc[ADDR_TO_PAGE_TABLE(Address)] == 0)
636 MmFreePageTable(Process, Address);
641 * If necessary go back to the original context
643 if (Process != NULL && Process != CurrentProcess)
649 * Return some information to the caller
651 *SwapEntry = Pte >> 1;
655 Mmi386MakeKernelPageTableGlobal(PVOID PAddress)
659 Pde = ADDR_TO_PDE(PAddress);
662 kePde = MmGlobalKernelPageDirectory + ADDR_TO_PDE_OFFSET(PAddress);
673 BOOLEAN MmIsPageTablePresent(PVOID PAddress)
677 Pde = ADDR_TO_PDE(PAddress);
680 kePde = MmGlobalKernelPageDirectory + ADDR_TO_PDE_OFFSET(PAddress);
691 NTSTATUS MmCreatePageTable(PVOID PAddress)
694 PHYSICAL_ADDRESS npage;
697 DPRINT("MmGetPageEntry(Address %x)\n", PAddress);
699 Pde = ADDR_TO_PDE(PAddress);
700 DPRINT("page_dir %x *page_dir %x\n", Pde, *Pde);
701 if (*Pde == 0 && PAddress >= (PVOID)KERNEL_BASE)
703 kePde = MmGlobalKernelPageDirectory + ADDR_TO_PDE_OFFSET(PAddress);
708 return STATUS_SUCCESS;
710 /* Should we create a kernel page table? */
711 DPRINT1("!!!!!!!!!!!!!!!!!!\n");
712 return STATUS_UNSUCCESSFUL;
717 Status = MmRequestPageMemoryConsumer(MC_NPPOOL, FALSE, &npage);
718 if (!NT_SUCCESS(Status))
723 *Pde = npage.u.LowPart | PA_PRESENT | PA_READWRITE | PA_USER;
726 return(STATUS_SUCCESS);
729 PULONG MmGetPageEntry(PVOID PAddress)
731 * FUNCTION: Get a pointer to the page table entry for a virtual address
735 PHYSICAL_ADDRESS npage;
737 BOOLEAN Free = FALSE;
740 DPRINT("MmGetPageEntry(Address %x)\n", PAddress);
742 Pde = ADDR_TO_PDE(PAddress);
743 DPRINT("page_dir %x *page_dir %x\n",Pde,*Pde);
746 if (PAddress >= (PVOID)KERNEL_BASE)
748 oldIrql = KeRaiseIrqlToSynchLevel();
749 kePde = MmGlobalKernelPageDirectory + ADDR_TO_PDE_OFFSET(PAddress);
757 KeLowerIrql(oldIrql);
758 Status = MmRequestPageMemoryConsumer(MC_NPPOOL, FALSE, &npage);
759 if (!NT_SUCCESS(Status))
764 oldIrql = KeRaiseIrqlToSynchLevel();
773 *Pde = *kePde = npage.u.LowPart | PA_PRESENT | PA_READWRITE;
777 KeLowerIrql(oldIrql);
781 Status = MmRequestPageMemoryConsumer(MC_NPPOOL, FALSE, &npage);
782 if (!NT_SUCCESS(Status))
787 *Pde = npage.u.LowPart | PA_PRESENT | PA_READWRITE | PA_USER;
792 MmReleasePageMemoryConsumer(MC_NPPOOL, npage);
796 return ADDR_TO_PTE(PAddress);
799 BOOLEAN MmIsDirtyPage(PEPROCESS Process, PVOID Address)
801 return((MmGetPageEntryForProcess(Process, Address)) & PA_DIRTY);
805 MmIsAccessedAndResetAccessPage(PEPROCESS Process, PVOID Address)
808 PEPROCESS CurrentProcess = PsGetCurrentProcess();
811 if (Process != CurrentProcess)
813 KeAttachProcess(Process);
815 PageEntry = MmGetPageEntry(Address);
816 Accessed = (*PageEntry) & PA_ACCESSED;
819 (*PageEntry) = (*PageEntry) & (~PA_ACCESSED);
822 if (Process != CurrentProcess)
830 VOID MmSetCleanPage(PEPROCESS Process, PVOID Address)
833 PEPROCESS CurrentProcess = PsGetCurrentProcess();
835 if (Process != CurrentProcess)
837 KeAttachProcess(Process);
839 PageEntry = MmGetPageEntry(Address);
840 (*PageEntry) = (*PageEntry) & (~PA_DIRTY);
842 if (Process != CurrentProcess)
848 VOID MmSetDirtyPage(PEPROCESS Process, PVOID Address)
851 PEPROCESS CurrentProcess = PsGetCurrentProcess();
853 if (Process != CurrentProcess)
855 KeAttachProcess(Process);
857 PageEntry = MmGetPageEntry(Address);
858 (*PageEntry) = (*PageEntry) | PA_DIRTY;
860 if (Process != CurrentProcess)
866 VOID MmEnableVirtualMapping(PEPROCESS Process, PVOID Address)
869 PEPROCESS CurrentProcess = PsGetCurrentProcess();
871 if (Process != CurrentProcess)
873 KeAttachProcess(Process);
875 PageEntry = MmGetPageEntry(Address);
876 (*PageEntry) = (*PageEntry) | PA_PRESENT;
878 if (Process != CurrentProcess)
884 BOOLEAN MmIsPagePresent(PEPROCESS Process, PVOID Address)
886 return((MmGetPageEntryForProcess1(Process, Address)) & PA_PRESENT);
889 BOOLEAN MmIsPageSwapEntry(PEPROCESS Process, PVOID Address)
892 Pte = MmGetPageEntryForProcess1(Process, Address);
893 return((!(Pte & PA_PRESENT)) && Pte != 0);
897 MmCreateVirtualMappingForKernel(PVOID Address,
899 PHYSICAL_ADDRESS PhysicalAddress)
901 PEPROCESS CurrentProcess;
905 PEPROCESS Process = NULL;
909 CurrentProcess = PsGetCurrentProcess();
913 CurrentProcess = NULL;
916 if (Process == NULL && Address < (PVOID)KERNEL_BASE)
918 DPRINT1("No process\n");
921 if (Process != NULL && Address >= (PVOID)KERNEL_BASE)
923 DPRINT1("Setting kernel address with process context\n");
926 Attributes = ProtectToPTE(flProtect);
928 if (Process != NULL && Process != CurrentProcess)
930 KeAttachProcess(Process);
933 Status = MmGetPageEntry2(Address, &Pte, FALSE);
934 if (!NT_SUCCESS(Status))
936 if (Process != NULL && Process != CurrentProcess)
942 if (PAGE_MASK((*Pte)) != 0 && !((*Pte) & PA_PRESENT))
946 if (PAGE_MASK((*Pte)) != 0)
948 MmMarkPageUnmapped(PTE_TO_PAGE((*Pte)));
950 *Pte = PhysicalAddress.QuadPart | Attributes;
951 if (Process != NULL &&
952 Process->AddressSpace.PageTableRefCountTable != NULL &&
953 ADDR_TO_PAGE_TABLE(Address) < 768 &&
954 Attributes & PA_PRESENT)
958 Ptrc = Process->AddressSpace.PageTableRefCountTable;
960 Ptrc[ADDR_TO_PAGE_TABLE(Address)]++;
963 if (Process != NULL && Process != CurrentProcess)
967 return(STATUS_SUCCESS);
971 MmCreatePageFileMapping(PEPROCESS Process,
975 PEPROCESS CurrentProcess;
981 CurrentProcess = PsGetCurrentProcess();
985 CurrentProcess = NULL;
988 if (Process == NULL && Address < (PVOID)KERNEL_BASE)
990 DPRINT1("No process\n");
993 if (Process != NULL && Address >= (PVOID)KERNEL_BASE)
995 DPRINT1("Setting kernel address with process context\n");
998 if (SwapEntry & (1 << 31))
1003 if (Process != NULL && Process != CurrentProcess)
1005 KeAttachProcess(Process);
1008 Status = MmGetPageEntry2(Address, &Pte, FALSE);
1009 if (!NT_SUCCESS(Status))
1011 if (Process != NULL && Process != CurrentProcess)
1017 if (PAGE_MASK((*Pte)) != 0)
1019 MmMarkPageUnmapped(PTE_TO_PAGE((*Pte)));
1021 *Pte = SwapEntry << 1;
1022 if (Process != NULL &&
1023 Process->AddressSpace.PageTableRefCountTable != NULL &&
1024 ADDR_TO_PAGE_TABLE(Address) < 768)
1028 Ptrc = Process->AddressSpace.PageTableRefCountTable;
1030 Ptrc[ADDR_TO_PAGE_TABLE(Address)]++;
1033 if (Process != NULL && Process != CurrentProcess)
1037 return(STATUS_SUCCESS);
1041 MmCreateVirtualMappingUnsafe(PEPROCESS Process,
1044 PHYSICAL_ADDRESS PhysicalAddress,
1047 PEPROCESS CurrentProcess;
1052 if (Process != NULL)
1054 CurrentProcess = PsGetCurrentProcess();
1058 CurrentProcess = NULL;
1061 if (Process == NULL && Address < (PVOID)KERNEL_BASE)
1063 DPRINT1("No process\n");
1066 if (Process != NULL && Address >= (PVOID)KERNEL_BASE)
1068 DPRINT1("Setting kernel address with process context\n");
1071 MmMarkPageMapped(PhysicalAddress);
1073 Attributes = ProtectToPTE(flProtect);
1074 if (!(Attributes & PA_PRESENT) && PhysicalAddress.QuadPart != 0)
1076 DPRINT1("Setting physical address but not allowing access at address "
1077 "0x%.8X with attributes %x/%x.\n",
1078 Address, Attributes, flProtect);
1082 if (Process != NULL && Process != CurrentProcess)
1084 KeAttachProcess(Process);
1087 Status = MmGetPageEntry2(Address, &Pte, MayWait);
1088 if (!NT_SUCCESS(Status))
1090 if (Process != NULL && Process != CurrentProcess)
1096 if (PAGE_MASK((*Pte)) != 0 && !((*Pte) & PA_PRESENT))
1100 if (PAGE_MASK((*Pte)) != 0)
1102 MmMarkPageUnmapped(PTE_TO_PAGE((*Pte)));
1104 *Pte = PhysicalAddress.QuadPart | Attributes;
1105 if (Process != NULL &&
1106 Process->AddressSpace.PageTableRefCountTable != NULL &&
1107 ADDR_TO_PAGE_TABLE(Address) < 768 &&
1108 Attributes & PA_PRESENT)
1112 Ptrc = Process->AddressSpace.PageTableRefCountTable;
1114 Ptrc[ADDR_TO_PAGE_TABLE(Address)]++;
1117 if (Process != NULL && Process != CurrentProcess)
1121 return(STATUS_SUCCESS);
1125 MmCreateVirtualMapping(PEPROCESS Process,
1128 PHYSICAL_ADDRESS PhysicalAddress,
1131 if (!MmIsUsablePage(PhysicalAddress))
1133 DPRINT1("Page at address %x not usable\n", PhysicalAddress);
1137 return(MmCreateVirtualMappingUnsafe(Process,
1145 MmGetPageProtect(PEPROCESS Process, PVOID Address)
1150 Entry = MmGetPageEntryForProcess1(Process, Address);
1152 if (!(Entry & PA_PRESENT))
1154 Protect = PAGE_NOACCESS;
1156 else if (Entry & PA_READWRITE)
1158 Protect = PAGE_READWRITE;
1162 Protect = PAGE_EXECUTE_READ;
1168 MmSetPageProtect(PEPROCESS Process, PVOID Address, ULONG flProtect)
1170 ULONG Attributes = 0;
1172 PEPROCESS CurrentProcess = PsGetCurrentProcess();
1174 DPRINT("MmSetPageProtect(Process %x Address %x flProtect %x)\n",
1175 Process, Address, flProtect);
1177 Attributes = ProtectToPTE(flProtect);
1178 if (Process != NULL && Process != CurrentProcess)
1180 KeAttachProcess(Process);
1182 PageEntry = MmGetPageEntry(Address);
1183 (*PageEntry) = PAGE_MASK(*PageEntry) | Attributes;
1185 if (Process != NULL && Process != CurrentProcess)
1191 PHYSICAL_ADDRESS STDCALL
1192 MmGetPhysicalAddress(PVOID vaddr)
1194 * FUNCTION: Returns the physical address corresponding to a virtual address
1200 DPRINT("MmGetPhysicalAddress(vaddr %x)\n", vaddr);
1202 Pte = *MmGetPageEntry(vaddr);
1203 if (Pte & PA_PRESENT)
1205 p.QuadPart = PAGE_MASK(Pte);