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
7 * PROGRAMMERS: David Welch (welch@cwcom.net)
10 /* INCLUDES ***************************************************************/
16 #if defined (ALLOC_PRAGMA)
17 #pragma alloc_text(INIT, MmInitGlobalKernelPageDirectory)
18 #pragma alloc_text(INIT, MiInitPageDirectoryMap)
22 /* GLOBALS *****************************************************************/
24 #define PA_BIT_PRESENT (0)
25 #define PA_BIT_READWRITE (1)
26 #define PA_BIT_USER (2)
29 #define PA_BIT_ACCESSED (5)
30 #define PA_BIT_DIRTY (6)
31 #define PA_BIT_GLOBAL (8)
33 #define PA_PRESENT (1 << PA_BIT_PRESENT)
34 #define PA_READWRITE (1 << PA_BIT_READWRITE)
35 #define PA_USER (1 << PA_BIT_USER)
36 #define PA_DIRTY (1 << PA_BIT_DIRTY)
37 #define PA_WT (1 << PA_BIT_WT)
38 #define PA_CD (1 << PA_BIT_CD)
39 #define PA_ACCESSED (1 << PA_BIT_ACCESSED)
40 #define PA_GLOBAL (1 << PA_BIT_GLOBAL)
42 #define HYPERSPACE (0xc0400000)
43 #define IS_HYPERSPACE(v) (((ULONG)(v) >= HYPERSPACE && (ULONG)(v) < HYPERSPACE + 0x400000))
45 ULONG MmGlobalKernelPageDirectory
[1024];
47 #define PTE_TO_PFN(X) ((X) >> PAGE_SHIFT)
48 #define PFN_TO_PTE(X) ((X) << PAGE_SHIFT)
51 #define PTE_TO_PAGE(X) ((LARGE_INTEGER)(LONGLONG)(PAGE_MASK(X)))
53 __inline LARGE_INTEGER
PTE_TO_PAGE(ULONG npage
)
56 dummy
.QuadPart
= (LONGLONG
)(PAGE_MASK(npage
));
61 /* FUNCTIONS ***************************************************************/
63 BOOLEAN
MmUnmapPageTable(PULONG Pt
);
66 MiFlushTlb(PULONG Pt
, PVOID Address
)
68 if ((Pt
&& MmUnmapPageTable(Pt
)) || Address
>= MmSystemRangeStart
)
75 ProtectToPTE(ULONG flProtect
)
79 if (flProtect
& (PAGE_NOACCESS
|PAGE_GUARD
))
83 else if (flProtect
& PAGE_IS_WRITABLE
)
85 Attributes
= PA_PRESENT
| PA_READWRITE
;
87 else if (flProtect
& (PAGE_IS_READABLE
| PAGE_IS_EXECUTABLE
))
89 Attributes
= PA_PRESENT
;
93 DPRINT1("Unknown main protection type.\n");
94 KeBugCheck(MEMORY_MANAGEMENT
);
97 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
;
117 Mmi386ReleaseMmInfo(PEPROCESS Process
)
119 PUSHORT LdtDescriptor
;
124 DPRINT("Mmi386ReleaseMmInfo(Process %x)\n",Process
);
126 LdtDescriptor
= (PUSHORT
) &Process
->Pcb
.LdtDescriptor
;
127 LdtBase
= LdtDescriptor
[1] |
128 ((LdtDescriptor
[2] & 0xff) << 16) |
129 ((LdtDescriptor
[3] & ~0xff) << 16);
131 DPRINT("LdtBase: %x\n", LdtBase
);
135 ExFreePool((PVOID
) LdtBase
);
138 PageDir
= MmCreateHyperspaceMapping(PTE_TO_PFN(Process
->Pcb
.DirectoryTableBase
[0]));
139 for (i
= 0; i
< ADDR_TO_PDE_OFFSET(MmSystemRangeStart
); i
++)
143 MiZeroPage(PTE_TO_PFN(PageDir
[i
]));
144 MmReleasePageMemoryConsumer(MC_NPPOOL
, PTE_TO_PFN(PageDir
[i
]));
147 MmReleasePageMemoryConsumer(MC_NPPOOL
, PTE_TO_PFN(PageDir
[ADDR_TO_PDE_OFFSET(HYPERSPACE
)]));
148 MmDeleteHyperspaceMapping(PageDir
);
149 MmReleasePageMemoryConsumer(MC_NPPOOL
, PTE_TO_PFN(Process
->Pcb
.DirectoryTableBase
[0]));
151 Process
->Pcb
.DirectoryTableBase
[0] = 0;
152 Process
->Pcb
.DirectoryTableBase
[1] = 0;
154 DPRINT("Finished Mmi386ReleaseMmInfo()\n");
155 return(STATUS_SUCCESS
);
160 MmInitializeHandBuiltProcess(IN PEPROCESS Process
,
161 IN PULONG DirectoryTableBase
)
163 /* Share the directory base with the idle process */
164 DirectoryTableBase
[0] = PsGetCurrentProcess()->Pcb
.DirectoryTableBase
[0];
165 DirectoryTableBase
[1] = PsGetCurrentProcess()->Pcb
.DirectoryTableBase
[1];
167 /* Initialize the Addresss Space */
168 KeInitializeGuardedMutex(&Process
->AddressCreationLock
);
169 Process
->Vm
.WorkingSetExpansionLinks
.Flink
= NULL
;
170 ASSERT(Process
->VadRoot
.NumberGenericTableElements
== 0);
171 Process
->VadRoot
.BalancedRoot
.u1
.Parent
= &Process
->VadRoot
.BalancedRoot
;
173 /* The process now has an address space */
174 Process
->HasAddressSpace
= TRUE
;
175 return STATUS_SUCCESS
;
180 MmCreateProcessAddressSpace(IN ULONG MinWs
,
181 IN PEPROCESS Process
,
182 IN PULONG DirectoryTableBase
)
187 PULONG PageDirectory
;
189 DPRINT("MmCopyMmInfo(Src %x, Dest %x)\n", MinWs
, Process
);
191 for (i
= 0; i
< 2; i
++)
193 Status
= MmRequestPageMemoryConsumer(MC_NPPOOL
, FALSE
, &Pfn
[i
]);
194 if (!NT_SUCCESS(Status
))
196 for (j
= 0; j
< i
; j
++)
198 MmReleasePageMemoryConsumer(MC_NPPOOL
, Pfn
[j
]);
205 PageDirectory
= MmCreateHyperspaceMapping(Pfn
[0]);
207 memcpy(PageDirectory
+ ADDR_TO_PDE_OFFSET(MmSystemRangeStart
),
208 MmGlobalKernelPageDirectory
+ ADDR_TO_PDE_OFFSET(MmSystemRangeStart
),
209 (1024 - ADDR_TO_PDE_OFFSET(MmSystemRangeStart
)) * sizeof(ULONG
));
211 DPRINT("Addr %x\n",ADDR_TO_PDE_OFFSET(PAGETABLE_MAP
));
212 PageDirectory
[ADDR_TO_PDE_OFFSET(PAGETABLE_MAP
)] = PFN_TO_PTE(Pfn
[0]) | PA_PRESENT
| PA_READWRITE
;
213 PageDirectory
[ADDR_TO_PDE_OFFSET(HYPERSPACE
)] = PFN_TO_PTE(Pfn
[1]) | PA_PRESENT
| PA_READWRITE
;
215 MmDeleteHyperspaceMapping(PageDirectory
);
217 DirectoryTableBase
[0] = PFN_TO_PTE(Pfn
[0]);
218 DirectoryTableBase
[1] = 0;
219 DPRINT("Finished MmCopyMmInfo(): 0x%x\n", DirectoryTableBase
[0]);
224 MmGetPageTableForProcess(PEPROCESS Process
, PVOID Address
, BOOLEAN Create
)
226 ULONG PdeOffset
= ADDR_TO_PDE_OFFSET(Address
);
232 if (Address
< MmSystemRangeStart
&& Process
&& Process
!= PsGetCurrentProcess())
234 PageDir
= MmCreateHyperspaceMapping(PTE_TO_PFN(Process
->Pcb
.DirectoryTableBase
[0]));
237 KeBugCheck(MEMORY_MANAGEMENT
);
239 if (0 == InterlockedCompareExchangePte(&PageDir
[PdeOffset
], 0, 0))
243 MmDeleteHyperspaceMapping(PageDir
);
246 Status
= MmRequestPageMemoryConsumer(MC_NPPOOL
, FALSE
, &Pfn
);
247 if (!NT_SUCCESS(Status
) || Pfn
== 0)
249 KeBugCheck(MEMORY_MANAGEMENT
);
251 Entry
= InterlockedCompareExchangePte(&PageDir
[PdeOffset
], PFN_TO_PTE(Pfn
) | PA_PRESENT
| PA_READWRITE
| PA_USER
, 0);
254 MmReleasePageMemoryConsumer(MC_NPPOOL
, Pfn
);
255 Pfn
= PTE_TO_PFN(Entry
);
260 Pfn
= PTE_TO_PFN(PageDir
[PdeOffset
]);
262 MmDeleteHyperspaceMapping(PageDir
);
263 Pt
= MmCreateHyperspaceMapping(Pfn
);
266 KeBugCheck(MEMORY_MANAGEMENT
);
268 return Pt
+ ADDR_TO_PTE_OFFSET(Address
);
270 PageDir
= (PULONG
)MiAddressToPde(Address
);
271 if (0 == InterlockedCompareExchangePte(PageDir
, 0, 0))
273 if (Address
>= MmSystemRangeStart
)
275 if (0 == InterlockedCompareExchangePte(&MmGlobalKernelPageDirectory
[PdeOffset
], 0, 0))
281 Status
= MmRequestPageMemoryConsumer(MC_SYSTEM
, FALSE
, &Pfn
);
282 if (!NT_SUCCESS(Status
) || Pfn
== 0)
284 KeBugCheck(MEMORY_MANAGEMENT
);
286 Entry
= PFN_TO_PTE(Pfn
) | PA_PRESENT
| PA_READWRITE
;
287 if (Ke386GlobalPagesEnabled
)
291 if(0 != InterlockedCompareExchangePte(&MmGlobalKernelPageDirectory
[PdeOffset
], Entry
, 0))
293 MmReleasePageMemoryConsumer(MC_SYSTEM
, Pfn
);
295 InterlockedExchangePte(PageDir
, MmGlobalKernelPageDirectory
[PdeOffset
]);
296 RtlZeroMemory(MiPteToAddress(PageDir
), PAGE_SIZE
);
297 return (PULONG
)MiAddressToPte(Address
);
299 InterlockedExchangePte(PageDir
, MmGlobalKernelPageDirectory
[PdeOffset
]);
307 Status
= MmRequestPageMemoryConsumer(MC_NPPOOL
, FALSE
, &Pfn
);
308 if (!NT_SUCCESS(Status
) || Pfn
== 0)
310 KeBugCheck(MEMORY_MANAGEMENT
);
312 Entry
= InterlockedCompareExchangePte(PageDir
, PFN_TO_PTE(Pfn
) | PA_PRESENT
| PA_READWRITE
| PA_USER
, 0);
315 MmReleasePageMemoryConsumer(MC_NPPOOL
, Pfn
);
319 return (PULONG
)MiAddressToPte(Address
);
322 BOOLEAN
MmUnmapPageTable(PULONG Pt
)
324 if (Pt
>= (PULONG
)PAGETABLE_MAP
&& Pt
< (PULONG
)PAGETABLE_MAP
+ 1024*1024)
331 MmDeleteHyperspaceMapping((PVOID
)PAGE_ROUND_DOWN(Pt
));
336 static ULONG
MmGetPageEntryForProcess(PEPROCESS Process
, PVOID Address
)
341 Pt
= MmGetPageTableForProcess(Process
, Address
, FALSE
);
345 MmUnmapPageTable(Pt
);
353 MmGetPfnForProcess(PEPROCESS Process
,
357 Entry
= MmGetPageEntryForProcess(Process
, Address
);
358 if (!(Entry
& PA_PRESENT
))
362 return(PTE_TO_PFN(Entry
));
367 MmDisableVirtualMapping(PEPROCESS Process
, PVOID Address
, BOOLEAN
* WasDirty
, PPFN_TYPE Page
)
369 * FUNCTION: Delete a virtual mapping
376 Pt
= MmGetPageTableForProcess(Process
, Address
, FALSE
);
379 KeBugCheck(MEMORY_MANAGEMENT
);
382 * Atomically disable the present bit and get the old value.
387 } while (Pte
!= InterlockedCompareExchangePte(Pt
, Pte
& ~PA_PRESENT
, Pte
));
389 MiFlushTlb(Pt
, Address
);
390 WasValid
= (PAGE_MASK(Pte
) != 0);
393 KeBugCheck(MEMORY_MANAGEMENT
);
397 * Return some information to the caller
399 if (WasDirty
!= NULL
)
401 *WasDirty
= Pte
& PA_DIRTY
;
405 *Page
= PTE_TO_PFN(Pte
);
411 MmRawDeleteVirtualMapping(PVOID Address
)
415 Pt
= MmGetPageTableForProcess(NULL
, Address
, FALSE
);
419 * Set the entry to zero
421 InterlockedExchangePte(Pt
, 0);
422 MiFlushTlb(Pt
, Address
);
428 MmDeleteVirtualMapping(PEPROCESS Process
, PVOID Address
, BOOLEAN FreePage
,
429 BOOLEAN
* WasDirty
, PPFN_TYPE Page
)
431 * FUNCTION: Delete a virtual mapping
434 BOOLEAN WasValid
= FALSE
;
439 DPRINT("MmDeleteVirtualMapping(%x, %x, %d, %x, %x)\n",
440 Process
, Address
, FreePage
, WasDirty
, Page
);
442 Pt
= MmGetPageTableForProcess(Process
, Address
, FALSE
);
446 if (WasDirty
!= NULL
)
458 * Atomically set the entry to zero and get the old value.
460 Pte
= InterlockedExchangePte(Pt
, 0);
462 MiFlushTlb(Pt
, Address
);
464 WasValid
= (PAGE_MASK(Pte
) != 0);
467 Pfn
= PTE_TO_PFN(Pte
);
474 if (FreePage
&& WasValid
)
476 MmReleasePageMemoryConsumer(MC_NPPOOL
, Pfn
);
480 * Return some information to the caller
482 if (WasDirty
!= NULL
)
484 *WasDirty
= Pte
& PA_DIRTY
? TRUE
: FALSE
;
494 MmDeletePageFileMapping(PEPROCESS Process
, PVOID Address
,
495 SWAPENTRY
* SwapEntry
)
497 * FUNCTION: Delete a virtual mapping
503 Pt
= MmGetPageTableForProcess(Process
, Address
, FALSE
);
512 * Atomically set the entry to zero and get the old value.
514 Pte
= InterlockedExchangePte(Pt
, 0);
516 MiFlushTlb(Pt
, Address
);
519 * Return some information to the caller
521 *SwapEntry
= Pte
>> 1;
525 Mmi386MakeKernelPageTableGlobal(PVOID PAddress
)
528 Pde
= (PULONG
)MiAddressToPde(PAddress
);
531 Pt
= MmGetPageTableForProcess(NULL
, PAddress
, FALSE
);
542 MmIsDirtyPage(PEPROCESS Process
, PVOID Address
)
544 return MmGetPageEntryForProcess(Process
, Address
) & PA_DIRTY
? TRUE
: FALSE
;
549 MmSetCleanPage(PEPROCESS Process
, PVOID Address
)
554 if (Address
< MmSystemRangeStart
&& Process
== NULL
)
556 DPRINT1("MmSetCleanPage is called for user space without a process.\n");
557 KeBugCheck(MEMORY_MANAGEMENT
);
560 Pt
= MmGetPageTableForProcess(Process
, Address
, FALSE
);
564 KeBugCheck(MEMORY_MANAGEMENT
);
570 } while (Pte
!= InterlockedCompareExchangePte(Pt
, Pte
& ~PA_DIRTY
, Pte
));
574 MiFlushTlb(Pt
, Address
);
578 MmUnmapPageTable(Pt
);
584 MmSetDirtyPage(PEPROCESS Process
, PVOID Address
)
589 if (Address
< MmSystemRangeStart
&& Process
== NULL
)
591 DPRINT1("MmSetDirtyPage is called for user space without a process.\n");
592 KeBugCheck(MEMORY_MANAGEMENT
);
595 Pt
= MmGetPageTableForProcess(Process
, Address
, FALSE
);
598 KeBugCheck(MEMORY_MANAGEMENT
);
604 } while (Pte
!= InterlockedCompareExchangePte(Pt
, Pte
| PA_DIRTY
, Pte
));
605 if (!(Pte
& PA_DIRTY
))
607 MiFlushTlb(Pt
, Address
);
611 MmUnmapPageTable(Pt
);
617 MmEnableVirtualMapping(PEPROCESS Process
, PVOID Address
)
622 Pt
= MmGetPageTableForProcess(Process
, Address
, FALSE
);
625 KeBugCheck(MEMORY_MANAGEMENT
);
631 } while (Pte
!= InterlockedCompareExchangePte(Pt
, Pte
| PA_PRESENT
, Pte
));
632 if (!(Pte
& PA_PRESENT
))
634 MiFlushTlb(Pt
, Address
);
638 MmUnmapPageTable(Pt
);
644 MmIsPagePresent(PEPROCESS Process
, PVOID Address
)
646 return MmGetPageEntryForProcess(Process
, Address
) & PA_PRESENT
;
651 MmIsPageSwapEntry(PEPROCESS Process
, PVOID Address
)
654 Entry
= MmGetPageEntryForProcess(Process
, Address
);
655 return !(Entry
& PA_PRESENT
) && (Entry
& 0x800) && Entry
!= 0;
660 MmCreatePageFileMapping(PEPROCESS Process
,
667 if (Process
== NULL
&& Address
< MmSystemRangeStart
)
669 DPRINT1("No process\n");
670 KeBugCheck(MEMORY_MANAGEMENT
);
672 if (Process
!= NULL
&& Address
>= MmSystemRangeStart
)
674 DPRINT1("Setting kernel address with process context\n");
675 KeBugCheck(MEMORY_MANAGEMENT
);
678 if (SwapEntry
& (1 << 31))
680 KeBugCheck(MEMORY_MANAGEMENT
);
683 Pt
= MmGetPageTableForProcess(Process
, Address
, TRUE
);
686 KeBugCheck(MEMORY_MANAGEMENT
);
689 InterlockedExchangePte(Pt
, SwapEntry
<< 1);
692 MiFlushTlb(Pt
, Address
);
696 MmUnmapPageTable(Pt
);
699 return(STATUS_SUCCESS
);
705 MmCreateVirtualMappingUnsafe(PEPROCESS Process
,
714 ULONG oldPdeOffset
, PdeOffset
;
717 BOOLEAN NoExecute
= FALSE
;
719 DPRINT("MmCreateVirtualMappingUnsafe(%x, %x, %x, %x (%x), %d)\n",
720 Process
, Address
, flProtect
, Pages
, *Pages
, PageCount
);
724 if (Address
< MmSystemRangeStart
)
726 DPRINT1("No process\n");
727 KeBugCheck(MEMORY_MANAGEMENT
);
729 if (PageCount
> 0x10000 ||
730 (ULONG_PTR
) Address
/ PAGE_SIZE
+ PageCount
> 0x100000)
732 DPRINT1("Page count too large\n");
733 KeBugCheck(MEMORY_MANAGEMENT
);
738 if (Address
>= MmSystemRangeStart
)
740 DPRINT1("Setting kernel address with process context\n");
741 KeBugCheck(MEMORY_MANAGEMENT
);
743 if (PageCount
> (ULONG_PTR
)MmSystemRangeStart
/ PAGE_SIZE
||
744 (ULONG_PTR
) Address
/ PAGE_SIZE
+ PageCount
>
745 (ULONG_PTR
)MmSystemRangeStart
/ PAGE_SIZE
)
747 DPRINT1("Page Count too large\n");
748 KeBugCheck(MEMORY_MANAGEMENT
);
752 Attributes
= ProtectToPTE(flProtect
);
753 if (Attributes
& 0x80000000)
758 if (Address
>= MmSystemRangeStart
)
760 Attributes
&= ~PA_USER
;
761 if (Ke386GlobalPagesEnabled
)
763 Attributes
|= PA_GLOBAL
;
768 Attributes
|= PA_USER
;
772 oldPdeOffset
= ADDR_TO_PDE_OFFSET(Addr
) + 1;
773 for (i
= 0; i
< PageCount
; i
++, Addr
= (PVOID
)((ULONG_PTR
)Addr
+ PAGE_SIZE
))
775 if (!(Attributes
& PA_PRESENT
) && Pages
[i
] != 0)
777 DPRINT1("Setting physical address but not allowing access at address "
778 "0x%.8X with attributes %x/%x.\n",
779 Addr
, Attributes
, flProtect
);
780 KeBugCheck(MEMORY_MANAGEMENT
);
782 PdeOffset
= ADDR_TO_PDE_OFFSET(Addr
);
783 if (oldPdeOffset
!= PdeOffset
)
785 MmUnmapPageTable(Pt
);
786 Pt
= MmGetPageTableForProcess(Process
, Addr
, TRUE
);
789 KeBugCheck(MEMORY_MANAGEMENT
);
796 oldPdeOffset
= PdeOffset
;
799 if (PAGE_MASK(Pte
) != 0 && !(Pte
& PA_PRESENT
) && (Pte
& 0x800))
801 DPRINT1("Bad PTE %lx\n", Pte
);
802 KeBugCheck(MEMORY_MANAGEMENT
);
804 InterlockedExchangePte(Pt
, PFN_TO_PTE(Pages
[i
]) | Attributes
);
807 if (Address
> MmSystemRangeStart
||
808 (Pt
>= (PULONG
)PAGETABLE_MAP
&& Pt
< (PULONG
)PAGETABLE_MAP
+ 1024*1024))
810 MiFlushTlb(Pt
, Address
);
816 MmUnmapPageTable(Pt
);
819 return(STATUS_SUCCESS
);
824 MmCreateVirtualMapping(PEPROCESS Process
,
832 for (i
= 0; i
< PageCount
; i
++)
834 if (!MmIsPageInUse(Pages
[i
]))
836 DPRINT1("Page at address %x not in use\n", PFN_TO_PTE(Pages
[i
]));
837 KeBugCheck(MEMORY_MANAGEMENT
);
841 return(MmCreateVirtualMappingUnsafe(Process
,
850 MmGetPageProtect(PEPROCESS Process
, PVOID Address
)
855 Entry
= MmGetPageEntryForProcess(Process
, Address
);
858 if (!(Entry
& PA_PRESENT
))
860 Protect
= PAGE_NOACCESS
;
864 if (Entry
& PA_READWRITE
)
866 Protect
= PAGE_READWRITE
;
870 Protect
= PAGE_EXECUTE_READ
;
874 Protect
|= PAGE_NOCACHE
;
878 Protect
|= PAGE_WRITETHROUGH
;
880 if (!(Entry
& PA_USER
))
882 Protect
|= PAGE_SYSTEM
;
891 MmSetPageProtect(PEPROCESS Process
, PVOID Address
, ULONG flProtect
)
893 ULONG Attributes
= 0;
894 BOOLEAN NoExecute
= FALSE
;
897 DPRINT("MmSetPageProtect(Process %x Address %x flProtect %x)\n",
898 Process
, Address
, flProtect
);
900 Attributes
= ProtectToPTE(flProtect
);
902 if (Attributes
& 0x80000000)
907 if (Address
>= MmSystemRangeStart
)
909 Attributes
&= ~PA_USER
;
910 if (Ke386GlobalPagesEnabled
)
912 Attributes
|= PA_GLOBAL
;
917 Attributes
|= PA_USER
;
920 Pt
= MmGetPageTableForProcess(Process
, Address
, FALSE
);
923 KeBugCheck(MEMORY_MANAGEMENT
);
925 InterlockedExchangePte(Pt
, PAGE_MASK(*Pt
) | Attributes
| (*Pt
& (PA_ACCESSED
|PA_DIRTY
)));
926 MiFlushTlb(Pt
, Address
);
932 PHYSICAL_ADDRESS NTAPI
933 MmGetPhysicalAddress(PVOID vaddr
)
935 * FUNCTION: Returns the physical address corresponding to a virtual address
941 DPRINT("MmGetPhysicalAddress(vaddr %x)\n", vaddr
);
942 Pte
= MmGetPageEntryForProcess(NULL
, vaddr
);
943 if (Pte
!= 0 && Pte
& PA_PRESENT
)
945 p
.QuadPart
= PAGE_MASK(Pte
);
946 p
.u
.LowPart
|= (ULONG_PTR
)vaddr
& (PAGE_SIZE
- 1);
957 MmUpdatePageDir(PEPROCESS Process
, PVOID Address
, ULONG Size
)
959 ULONG StartOffset
, EndOffset
, Offset
;
963 // Check if the process isn't there anymore
964 // This is probably a bad sign, since it means the caller is setting cr3 to
967 if ((PTE_TO_PFN(Process
->Pcb
.DirectoryTableBase
[0]) == 0) && (Process
!= PsGetCurrentProcess()))
969 DPRINT1("Process: %16s is dead: %p\n", Process
->ImageFileName
, Process
->Pcb
.DirectoryTableBase
[0]);
974 if (Address
< MmSystemRangeStart
)
976 KeBugCheck(MEMORY_MANAGEMENT
);
979 StartOffset
= ADDR_TO_PDE_OFFSET(Address
);
980 EndOffset
= ADDR_TO_PDE_OFFSET((PVOID
)((ULONG_PTR
)Address
+ Size
));
982 if (Process
!= NULL
&& Process
!= PsGetCurrentProcess())
984 Pde
= MmCreateHyperspaceMapping(PTE_TO_PFN(Process
->Pcb
.DirectoryTableBase
[0]));
988 Pde
= (PULONG
)PAGEDIRECTORY_MAP
;
990 for (Offset
= StartOffset
; Offset
<= EndOffset
; Offset
++)
992 if (Offset
!= ADDR_TO_PDE_OFFSET(PAGETABLE_MAP
))
994 InterlockedCompareExchangePte(&Pde
[Offset
], MmGlobalKernelPageDirectory
[Offset
], 0);
997 if (Pde
!= (PULONG
)PAGEDIRECTORY_MAP
)
999 MmDeleteHyperspaceMapping(Pde
);
1003 extern MMPTE HyperTemplatePte
;
1008 MmInitGlobalKernelPageDirectory(VOID
)
1011 PULONG CurrentPageDirectory
= (PULONG
)PAGEDIRECTORY_MAP
;
1013 DPRINT("MmInitGlobalKernelPageDirectory()\n");
1018 HyperTemplatePte
.u
.Long
= (PA_PRESENT
| PA_READWRITE
| PA_DIRTY
| PA_ACCESSED
);
1019 if (Ke386GlobalPagesEnabled
) HyperTemplatePte
.u
.Long
|= PA_GLOBAL
;
1021 for (i
= ADDR_TO_PDE_OFFSET(MmSystemRangeStart
); i
< 1024; i
++)
1023 if (i
!= ADDR_TO_PDE_OFFSET(PAGETABLE_MAP
) &&
1024 i
!= ADDR_TO_PDE_OFFSET(HYPERSPACE
) &&
1025 0 == MmGlobalKernelPageDirectory
[i
] && 0 != CurrentPageDirectory
[i
])
1027 MmGlobalKernelPageDirectory
[i
] = CurrentPageDirectory
[i
];
1028 if (Ke386GlobalPagesEnabled
)
1030 MmGlobalKernelPageDirectory
[i
] |= PA_GLOBAL
;
1031 CurrentPageDirectory
[i
] |= PA_GLOBAL
;