Removed from redundant files from the mm directory
[reactos.git] / reactos / ntoskrnl / mm / i386 / page.c
1 /* $Id: page.c,v 1.9 2000/06/25 03:59:16 dwelch Exp $
2 *
3 * COPYRIGHT: See COPYING in the top directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/mm/i386/page.c
6 * PURPOSE: low level memory managment manipulation
7 * PROGRAMER: David Welch (welch@cwcom.net)
8 * UPDATE HISTORY:
9 * 9/3/98: Created
10 */
11
12 /* INCLUDES ***************************************************************/
13
14 #include <ddk/ntddk.h>
15 #include <internal/mm.h>
16 #include <internal/mmhal.h>
17 #include <string.h>
18 #include <internal/string.h>
19 #include <internal/bitops.h>
20 #include <internal/ex.h>
21
22 #define NDEBUG
23 #include <internal/debug.h>
24
25 /* GLOBALS *****************************************************************/
26
27 extern ULONG MiNrFreePages;
28
29 #define PA_BIT_PRESENT (0)
30 #define PA_BIT_READWRITE (1)
31 #define PA_BIT_USER (2)
32 #define PA_BIT_DIRTY (6)
33
34 #define PA_PRESENT (1<<PA_BIT_PRESENT)
35 #define PA_DIRTY (1<<PA_BIT_DIRTY)
36
37 #define PAGETABLE_MAP (0xf0000000)
38 #define PAGEDIRECTORY_MAP (0xf0000000 + (PAGETABLE_MAP / (1024)))
39
40 /* FUNCTIONS ***************************************************************/
41
42 static ULONG ProtectToPTE(ULONG flProtect)
43 {
44 ULONG Attributes = 0;
45
46 if (flProtect & PAGE_NOACCESS || flProtect & PAGE_GUARD)
47 {
48 Attributes = 0;
49 }
50 if (flProtect & PAGE_READWRITE || flProtect & PAGE_EXECUTE_READWRITE)
51 {
52 Attributes = PA_WRITE | PA_USER;
53 }
54 if (flProtect & PAGE_READONLY || flProtect & PAGE_EXECUTE ||
55 flProtect & PAGE_EXECUTE_READ)
56 {
57 Attributes = PA_READ | PA_USER;
58 }
59 return(Attributes);
60 }
61
62 #define ADDR_TO_PDE(v) (PULONG)(PAGEDIRECTORY_MAP + \
63 (((ULONG)v / (1024 * 1024))&(~0x3)))
64 #define ADDR_TO_PTE(v) (PULONG)(PAGETABLE_MAP + ((((ULONG)v / 1024))&(~0x3)))
65
66 NTSTATUS Mmi386ReleaseMmInfo(PEPROCESS Process)
67 {
68 DPRINT("Mmi386ReleaseMmInfo(Process %x)\n",Process);
69
70 MmDereferencePage(Process->Pcb.PageTableDirectory);
71 Process->Pcb.PageTableDirectory = NULL;
72
73 DPRINT("Finished Mmi386ReleaseMmInfo()\n");
74 return(STATUS_SUCCESS);
75 }
76
77 NTSTATUS MmCopyMmInfo(PEPROCESS Src, PEPROCESS Dest)
78 {
79 PULONG PhysPageDirectory;
80 PULONG PageDirectory;
81 PULONG CurrentPageDirectory;
82 PKPROCESS KProcess = &Dest->Pcb;
83 ULONG i;
84
85 DPRINT("MmCopyMmInfo(Src %x, Dest %x)\n", Src, Dest);
86
87 PageDirectory = ExAllocatePage();
88 if (PageDirectory == NULL)
89 {
90 return(STATUS_UNSUCCESSFUL);
91 }
92 PhysPageDirectory = (PULONG)(MmGetPhysicalAddress(PageDirectory)).u.LowPart;
93 KProcess->PageTableDirectory = PhysPageDirectory;
94 CurrentPageDirectory = (PULONG)PAGEDIRECTORY_MAP;
95
96 memset(PageDirectory,0,PAGESIZE);
97 for (i=768; i<896; i++)
98 {
99 PageDirectory[i] = CurrentPageDirectory[i];
100 }
101 DPRINT("Addr %x\n",PAGETABLE_MAP / (4*1024*1024));
102 PageDirectory[PAGETABLE_MAP / (4*1024*1024)] =
103 (ULONG)PhysPageDirectory | 0x7;
104
105 ExUnmapPage(PageDirectory);
106
107 DPRINT("Finished MmCopyMmInfo()\n");
108 return(STATUS_SUCCESS);
109 }
110
111 VOID MmDeletePageTable(PEPROCESS Process, PVOID Address)
112 {
113 PEPROCESS CurrentProcess = PsGetCurrentProcess();
114
115 if (Process != NULL && Process != CurrentProcess)
116 {
117 KeAttachProcess(Process);
118 }
119 *(ADDR_TO_PDE(Address)) = 0;
120 FLUSH_TLB;
121 if (Process != NULL && Process != CurrentProcess)
122 {
123 KeDetachProcess();
124 }
125 }
126
127 ULONG MmGetPageEntryForProcess(PEPROCESS Process, PVOID Address)
128 {
129 ULONG Entry;
130 PEPROCESS CurrentProcess = PsGetCurrentProcess();
131
132 if (Process != NULL && Process != CurrentProcess)
133 {
134 KeAttachProcess(Process);
135 }
136 Entry = *MmGetPageEntry(Address);
137 if (Process != NULL && Process != CurrentProcess)
138 {
139 KeDetachProcess();
140 }
141 return(Entry);
142 }
143
144 ULONG MmGetPhysicalAddressForProcess(PEPROCESS Process,
145 PVOID Address)
146 {
147 ULONG PageEntry;
148
149 PageEntry = MmGetPageEntryForProcess(Process, Address);
150
151 if (!(PageEntry & PA_PRESENT))
152 {
153 return(0);
154 }
155 return(PAGE_MASK(PageEntry));
156 }
157
158 VOID MmDeletePageEntry(PEPROCESS Process, PVOID Address, BOOL FreePage)
159 {
160 PULONG page_tlb;
161 PULONG page_dir;
162 PEPROCESS CurrentProcess = PsGetCurrentProcess();
163
164 if (Process != NULL && Process != CurrentProcess)
165 {
166 KeAttachProcess(Process);
167 }
168 page_dir = ADDR_TO_PDE(Address);
169 if ((*page_dir) == 0)
170 {
171 if (Process != NULL && Process != CurrentProcess)
172 {
173 KeDetachProcess();
174 }
175 return;
176 }
177 page_tlb = ADDR_TO_PTE(Address);
178 if (FreePage && PAGE_MASK(*page_tlb) != 0)
179 {
180 if (PAGE_MASK(*page_tlb) >= 0x400000)
181 {
182 DbgPrint("MmDeletePageEntry(Address %x) Physical %x Free %d, "
183 "Entry %x\n",
184 Address, PAGE_MASK(*page_tlb), MiNrFreePages,
185 *page_tlb);
186 KeBugCheck(0);
187 }
188 MmDereferencePage((PVOID)PAGE_MASK(*page_tlb));
189 }
190 *page_tlb = 0;
191 if (Process != NULL && Process != CurrentProcess)
192 {
193 KeDetachProcess();
194 }
195 }
196
197 BOOLEAN MmIsPageTablePresent(PVOID PAddress)
198 {
199 PULONG page_dir;
200 ULONG Address = (ULONG)PAddress;
201
202 page_dir = ADDR_TO_PDE(Address);
203 return((*page_dir) == 0);
204 }
205
206 PULONG MmGetPageEntry(PVOID PAddress)
207 /*
208 * FUNCTION: Get a pointer to the page table entry for a virtual address
209 */
210 {
211 PULONG page_tlb;
212 PULONG page_dir;
213 ULONG Address = (ULONG)PAddress;
214
215 DPRINT("MmGetPageEntry(Address %x)\n", Address);
216
217 page_dir = ADDR_TO_PDE(Address);
218 DPRINT("page_dir %x *page_dir %x\n",page_dir,*page_dir);
219 if ((*page_dir) == 0)
220 {
221 (*page_dir) = ((ULONG)MmAllocPage()) | 0x7;
222 memset((PVOID)PAGE_ROUND_DOWN(ADDR_TO_PTE(Address)), 0, PAGESIZE);
223 FLUSH_TLB;
224 }
225 page_tlb = ADDR_TO_PTE(Address);
226 DPRINT("page_tlb %x\n",page_tlb);
227 return(page_tlb);
228 }
229
230 BOOLEAN MmIsPageDirty(PEPROCESS Process, PVOID Address)
231 {
232 return((MmGetPageEntryForProcess(Process, Address)) & PA_DIRTY);
233 }
234
235 BOOLEAN MmIsPagePresent(PEPROCESS Process, PVOID Address)
236 {
237 return((MmGetPageEntryForProcess(Process, Address)) & PA_PRESENT);
238 }
239
240
241 VOID MmSetPage(PEPROCESS Process,
242 PVOID Address,
243 ULONG flProtect,
244 ULONG PhysicalAddress)
245 {
246 PEPROCESS CurrentProcess = PsGetCurrentProcess();
247 ULONG Attributes = 0;
248
249 if (((ULONG)PhysicalAddress) >= 0x400000)
250 {
251 DbgPrint("MmSetPage(Process %x, Address %x, PhysicalAddress %x)\n",
252 Process, Address, PhysicalAddress);
253 KeBugCheck(0);
254 }
255
256 Attributes = ProtectToPTE(flProtect);
257
258 if (Process != NULL && Process != CurrentProcess)
259 {
260 KeAttachProcess(Process);
261 }
262 (*MmGetPageEntry(Address)) = PhysicalAddress | Attributes;
263 FLUSH_TLB;
264 if (Process != NULL && Process != CurrentProcess)
265 {
266 KeDetachProcess();
267 }
268 }
269
270 VOID MmSetPageProtect(PEPROCESS Process,
271 PVOID Address,
272 ULONG flProtect)
273 {
274 ULONG Attributes = 0;
275 PULONG PageEntry;
276 PEPROCESS CurrentProcess = PsGetCurrentProcess();
277
278 Attributes = ProtectToPTE(flProtect);
279
280 if (Process != CurrentProcess)
281 {
282 KeAttachProcess(Process);
283 }
284 PageEntry = MmGetPageEntry(Address);
285 (*PageEntry) = PAGE_MASK(*PageEntry) | Attributes;
286 FLUSH_TLB;
287 if (Process != CurrentProcess)
288 {
289 KeDetachProcess();
290 }
291 }
292
293 PHYSICAL_ADDRESS STDCALL MmGetPhysicalAddress(PVOID vaddr)
294 /*
295 * FUNCTION: Returns the physical address corresponding to a virtual address
296 */
297 {
298 PHYSICAL_ADDRESS p;
299
300 p.QuadPart = 0;
301
302 DPRINT("MmGetPhysicalAddress(vaddr %x)\n", vaddr);
303
304 p.u.LowPart = PAGE_MASK(*MmGetPageEntry(vaddr));
305 p.u.HighPart = 0;
306
307 return p;
308 }
309
310
311 /* EOF */