2 * COPYRIGHT: See COPYING in the top directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/mm/i386/page.c
5 * PURPOSE: low level memory managment manipulation
6 * PROGRAMER: David Welch (welch@cwcom.net)
11 /* INCLUDES ***************************************************************/
13 #include <ddk/ntddk.h>
14 #include <internal/mm.h>
15 #include <internal/mmhal.h>
17 #include <internal/string.h>
18 #include <internal/bitops.h>
19 #include <internal/ex.h>
22 #include <internal/debug.h>
24 /* GLOBALS *****************************************************************/
26 extern ULONG MiNrFreePages
;
28 #define PA_BIT_PRESENT (0)
29 #define PA_BIT_READWRITE (1)
30 #define PA_BIT_USER (2)
32 #define PA_PRESENT (1<<PA_BIT_PRESENT)
34 #define PAGETABLE_MAP (0xf0000000)
35 #define PAGEDIRECTORY_MAP (0xf0000000 + (PAGETABLE_MAP / (1024)))
37 /* FUNCTIONS ***************************************************************/
39 static ULONG
ProtectToPTE(ULONG flProtect
)
43 if (flProtect
& PAGE_NOACCESS
|| flProtect
& PAGE_GUARD
)
47 if (flProtect
& PAGE_READWRITE
|| flProtect
& PAGE_EXECUTE_READWRITE
)
49 Attributes
= PA_WRITE
| PA_USER
;
51 if (flProtect
& PAGE_READONLY
|| flProtect
& PAGE_EXECUTE
||
52 flProtect
& PAGE_EXECUTE_READ
)
54 Attributes
= PA_READ
| PA_USER
;
59 #define ADDR_TO_PDE(v) (PULONG)(PAGEDIRECTORY_MAP + \
60 (((ULONG)v / (1024 * 1024))&(~0x3)))
61 #define ADDR_TO_PTE(v) (PULONG)(PAGETABLE_MAP + ((ULONG)v / 1024))
63 NTSTATUS
Mmi386ReleaseMmInfo(PEPROCESS Process
)
65 DPRINT("Mmi386ReleaseMmInfo(Process %x)\n",Process
);
67 MmFreePage(Process
->Pcb
.PageTableDirectory
, 1);
68 Process
->Pcb
.PageTableDirectory
= NULL
;
70 DPRINT("Finished Mmi386ReleaseMmInfo()\n");
71 return(STATUS_SUCCESS
);
74 NTSTATUS
MmCopyMmInfo(PEPROCESS Src
, PEPROCESS Dest
)
76 PULONG PhysPageDirectory
;
78 PULONG CurrentPageDirectory
;
79 PKPROCESS KProcess
= &Dest
->Pcb
;
82 DPRINT("MmCopyMmInfo(Src %x, Dest %x)\n", Src
, Dest
);
84 PageDirectory
= ExAllocatePage();
85 if (PageDirectory
== NULL
)
87 return(STATUS_UNSUCCESSFUL
);
89 PhysPageDirectory
= (PULONG
)(MmGetPhysicalAddress(PageDirectory
)).u
.LowPart
;
90 KProcess
->PageTableDirectory
= PhysPageDirectory
;
91 CurrentPageDirectory
= (PULONG
)PAGEDIRECTORY_MAP
;
93 memset(PageDirectory
,0,PAGESIZE
);
94 for (i
=768; i
<896; i
++)
96 PageDirectory
[i
] = CurrentPageDirectory
[i
];
98 DPRINT("Addr %x\n",0xf0000000 / (4*1024*1024));
99 PageDirectory
[0xf0000000 / (4*1024*1024)] = (ULONG
)PhysPageDirectory
| 0x7;
101 ExUnmapPage(PageDirectory
);
103 DPRINT("Finished MmCopyMmInfo()\n");
104 return(STATUS_SUCCESS
);
107 VOID
MmDeletePageTable(PEPROCESS Process
, PVOID Address
)
109 PEPROCESS CurrentProcess
= PsGetCurrentProcess();
111 if (Process
!= NULL
&& Process
!= CurrentProcess
)
113 KeAttachProcess(Process
);
115 *(ADDR_TO_PDE(Address
)) = 0;
117 if (Process
!= NULL
&& Process
!= CurrentProcess
)
123 ULONG
MmGetPageEntryForProcess(PEPROCESS Process
, PVOID Address
)
126 PEPROCESS CurrentProcess
= PsGetCurrentProcess();
128 if (Process
!= NULL
&& Process
!= CurrentProcess
)
130 KeAttachProcess(Process
);
132 Entry
= *MmGetPageEntry(Address
);
133 if (Process
!= NULL
&& Process
!= CurrentProcess
)
140 ULONG
MmGetPhysicalAddressForProcess(PEPROCESS Process
,
145 PageEntry
= MmGetPageEntryForProcess(Process
, Address
);
147 if (!(PageEntry
& PA_PRESENT
))
151 return(PAGE_MASK(PageEntry
));
154 VOID
MmDeletePageEntry(PEPROCESS Process
, PVOID Address
, BOOL FreePage
)
158 PEPROCESS CurrentProcess
= PsGetCurrentProcess();
160 if (Process
!= NULL
&& Process
!= CurrentProcess
)
162 KeAttachProcess(Process
);
164 page_dir
= ADDR_TO_PDE(Address
);
165 if ((*page_dir
) == 0)
167 if (Process
!= NULL
&& Process
!= CurrentProcess
)
173 page_tlb
= ADDR_TO_PTE(Address
);
174 if (FreePage
&& PAGE_MASK(*page_tlb
) != 0)
176 if (PAGE_MASK(*page_tlb
) >= 0x400000)
178 DbgPrint("MmDeletePageEntry(Address %x) Physical %x Free %d, "
180 Address
, PAGE_MASK(*page_tlb
), MiNrFreePages
,
184 MmFreePage((PVOID
)PAGE_MASK(*page_tlb
),1);
187 if (Process
!= NULL
&& Process
!= CurrentProcess
)
195 PULONG
MmGetPageEntry(PVOID PAddress
)
197 * FUNCTION: Get a pointer to the page table entry for a virtual address
202 ULONG Address
= (ULONG
)PAddress
;
204 DPRINT("MmGetPageEntry(Address %x)\n", Address
);
206 page_dir
= ADDR_TO_PDE(Address
);
207 DPRINT("page_dir %x *page_dir %x\n",page_dir
,*page_dir
);
208 if ((*page_dir
) == 0)
210 (*page_dir
) = ((ULONG
)MmAllocPage()) | 0x7;
213 page_tlb
= ADDR_TO_PTE(Address
);
214 DPRINT("page_tlb %x\n",page_tlb
);
218 BOOLEAN
MmIsPagePresent(PEPROCESS Process
, PVOID Address
)
220 return((MmGetPageEntryForProcess(Process
, Address
)) & PA_PRESENT
);
224 VOID
MmSetPage(PEPROCESS Process
,
227 ULONG PhysicalAddress
)
229 PEPROCESS CurrentProcess
= PsGetCurrentProcess();
230 ULONG Attributes
= 0;
232 if (PAGE_ROUND_DOWN(Address
) == 0x77631000)
234 DPRINT1("MmSetPage(Process %x, Address %x, flProtect %x, "
235 "PhysicalAddress %x)\n",Process
,Address
,flProtect
,
239 if (((ULONG
)PhysicalAddress
) >= 0x400000)
241 DbgPrint("MmSetPage(Process %x, Address %x, PhysicalAddress %x)\n",
242 Process
, Address
, PhysicalAddress
);
246 Attributes
= ProtectToPTE(flProtect
);
248 if (Process
!= NULL
&& Process
!= CurrentProcess
)
250 KeAttachProcess(Process
);
252 (*MmGetPageEntry(Address
)) = PhysicalAddress
| Attributes
;
254 if (Process
!= NULL
&& Process
!= CurrentProcess
)
260 VOID
MmSetPageProtect(PEPROCESS Process
,
264 ULONG Attributes
= 0;
266 PEPROCESS CurrentProcess
= PsGetCurrentProcess();
268 Attributes
= ProtectToPTE(flProtect
);
270 if (Process
!= CurrentProcess
)
272 KeAttachProcess(Process
);
274 PageEntry
= MmGetPageEntry(Address
);
275 (*PageEntry
) = PAGE_MASK(*PageEntry
) | Attributes
;
277 if (Process
!= CurrentProcess
)
283 PHYSICAL_ADDRESS
MmGetPhysicalAddress(PVOID vaddr
)
285 * FUNCTION: Returns the physical address corresponding to a virtual address
292 DPRINT("MmGetPhysicalAddress(vaddr %x)\n", vaddr
);
294 p
.u
.LowPart
= PAGE_MASK(*MmGetPageEntry(vaddr
));