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 (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);