1 /* $Id: page.c,v 1.9 2000/06/25 03:59:16 dwelch Exp $
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)
12 /* INCLUDES ***************************************************************/
14 #include <ddk/ntddk.h>
15 #include <internal/mm.h>
16 #include <internal/mmhal.h>
18 #include <internal/string.h>
19 #include <internal/bitops.h>
20 #include <internal/ex.h>
23 #include <internal/debug.h>
25 /* GLOBALS *****************************************************************/
27 extern ULONG MiNrFreePages
;
29 #define PA_BIT_PRESENT (0)
30 #define PA_BIT_READWRITE (1)
31 #define PA_BIT_USER (2)
32 #define PA_BIT_DIRTY (6)
34 #define PA_PRESENT (1<<PA_BIT_PRESENT)
35 #define PA_DIRTY (1<<PA_BIT_DIRTY)
37 #define PAGETABLE_MAP (0xf0000000)
38 #define PAGEDIRECTORY_MAP (0xf0000000 + (PAGETABLE_MAP / (1024)))
40 /* FUNCTIONS ***************************************************************/
42 static ULONG
ProtectToPTE(ULONG flProtect
)
46 if (flProtect
& PAGE_NOACCESS
|| flProtect
& PAGE_GUARD
)
50 if (flProtect
& PAGE_READWRITE
|| flProtect
& PAGE_EXECUTE_READWRITE
)
52 Attributes
= PA_WRITE
| PA_USER
;
54 if (flProtect
& PAGE_READONLY
|| flProtect
& PAGE_EXECUTE
||
55 flProtect
& PAGE_EXECUTE_READ
)
57 Attributes
= PA_READ
| PA_USER
;
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)))
66 NTSTATUS
Mmi386ReleaseMmInfo(PEPROCESS Process
)
68 DPRINT("Mmi386ReleaseMmInfo(Process %x)\n",Process
);
70 MmDereferencePage(Process
->Pcb
.PageTableDirectory
);
71 Process
->Pcb
.PageTableDirectory
= NULL
;
73 DPRINT("Finished Mmi386ReleaseMmInfo()\n");
74 return(STATUS_SUCCESS
);
77 NTSTATUS
MmCopyMmInfo(PEPROCESS Src
, PEPROCESS Dest
)
79 PULONG PhysPageDirectory
;
81 PULONG CurrentPageDirectory
;
82 PKPROCESS KProcess
= &Dest
->Pcb
;
85 DPRINT("MmCopyMmInfo(Src %x, Dest %x)\n", Src
, Dest
);
87 PageDirectory
= ExAllocatePage();
88 if (PageDirectory
== NULL
)
90 return(STATUS_UNSUCCESSFUL
);
92 PhysPageDirectory
= (PULONG
)(MmGetPhysicalAddress(PageDirectory
)).u
.LowPart
;
93 KProcess
->PageTableDirectory
= PhysPageDirectory
;
94 CurrentPageDirectory
= (PULONG
)PAGEDIRECTORY_MAP
;
96 memset(PageDirectory
,0,PAGESIZE
);
97 for (i
=768; i
<896; i
++)
99 PageDirectory
[i
] = CurrentPageDirectory
[i
];
101 DPRINT("Addr %x\n",PAGETABLE_MAP
/ (4*1024*1024));
102 PageDirectory
[PAGETABLE_MAP
/ (4*1024*1024)] =
103 (ULONG
)PhysPageDirectory
| 0x7;
105 ExUnmapPage(PageDirectory
);
107 DPRINT("Finished MmCopyMmInfo()\n");
108 return(STATUS_SUCCESS
);
111 VOID
MmDeletePageTable(PEPROCESS Process
, PVOID Address
)
113 PEPROCESS CurrentProcess
= PsGetCurrentProcess();
115 if (Process
!= NULL
&& Process
!= CurrentProcess
)
117 KeAttachProcess(Process
);
119 *(ADDR_TO_PDE(Address
)) = 0;
121 if (Process
!= NULL
&& Process
!= CurrentProcess
)
127 ULONG
MmGetPageEntryForProcess(PEPROCESS Process
, PVOID Address
)
130 PEPROCESS CurrentProcess
= PsGetCurrentProcess();
132 if (Process
!= NULL
&& Process
!= CurrentProcess
)
134 KeAttachProcess(Process
);
136 Entry
= *MmGetPageEntry(Address
);
137 if (Process
!= NULL
&& Process
!= CurrentProcess
)
144 ULONG
MmGetPhysicalAddressForProcess(PEPROCESS Process
,
149 PageEntry
= MmGetPageEntryForProcess(Process
, Address
);
151 if (!(PageEntry
& PA_PRESENT
))
155 return(PAGE_MASK(PageEntry
));
158 VOID
MmDeletePageEntry(PEPROCESS Process
, PVOID Address
, BOOL FreePage
)
162 PEPROCESS CurrentProcess
= PsGetCurrentProcess();
164 if (Process
!= NULL
&& Process
!= CurrentProcess
)
166 KeAttachProcess(Process
);
168 page_dir
= ADDR_TO_PDE(Address
);
169 if ((*page_dir
) == 0)
171 if (Process
!= NULL
&& Process
!= CurrentProcess
)
177 page_tlb
= ADDR_TO_PTE(Address
);
178 if (FreePage
&& PAGE_MASK(*page_tlb
) != 0)
180 if (PAGE_MASK(*page_tlb
) >= 0x400000)
182 DbgPrint("MmDeletePageEntry(Address %x) Physical %x Free %d, "
184 Address
, PAGE_MASK(*page_tlb
), MiNrFreePages
,
188 MmDereferencePage((PVOID
)PAGE_MASK(*page_tlb
));
191 if (Process
!= NULL
&& Process
!= CurrentProcess
)
197 BOOLEAN
MmIsPageTablePresent(PVOID PAddress
)
200 ULONG Address
= (ULONG
)PAddress
;
202 page_dir
= ADDR_TO_PDE(Address
);
203 return((*page_dir
) == 0);
206 PULONG
MmGetPageEntry(PVOID PAddress
)
208 * FUNCTION: Get a pointer to the page table entry for a virtual address
213 ULONG Address
= (ULONG
)PAddress
;
215 DPRINT("MmGetPageEntry(Address %x)\n", Address
);
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)
221 (*page_dir
) = ((ULONG
)MmAllocPage()) | 0x7;
222 memset((PVOID
)PAGE_ROUND_DOWN(ADDR_TO_PTE(Address
)), 0, PAGESIZE
);
225 page_tlb
= ADDR_TO_PTE(Address
);
226 DPRINT("page_tlb %x\n",page_tlb
);
230 BOOLEAN
MmIsPageDirty(PEPROCESS Process
, PVOID Address
)
232 return((MmGetPageEntryForProcess(Process
, Address
)) & PA_DIRTY
);
235 BOOLEAN
MmIsPagePresent(PEPROCESS Process
, PVOID Address
)
237 return((MmGetPageEntryForProcess(Process
, Address
)) & PA_PRESENT
);
241 VOID
MmSetPage(PEPROCESS Process
,
244 ULONG PhysicalAddress
)
246 PEPROCESS CurrentProcess
= PsGetCurrentProcess();
247 ULONG Attributes
= 0;
249 if (((ULONG
)PhysicalAddress
) >= 0x400000)
251 DbgPrint("MmSetPage(Process %x, Address %x, PhysicalAddress %x)\n",
252 Process
, Address
, PhysicalAddress
);
256 Attributes
= ProtectToPTE(flProtect
);
258 if (Process
!= NULL
&& Process
!= CurrentProcess
)
260 KeAttachProcess(Process
);
262 (*MmGetPageEntry(Address
)) = PhysicalAddress
| Attributes
;
264 if (Process
!= NULL
&& Process
!= CurrentProcess
)
270 VOID
MmSetPageProtect(PEPROCESS Process
,
274 ULONG Attributes
= 0;
276 PEPROCESS CurrentProcess
= PsGetCurrentProcess();
278 Attributes
= ProtectToPTE(flProtect
);
280 if (Process
!= CurrentProcess
)
282 KeAttachProcess(Process
);
284 PageEntry
= MmGetPageEntry(Address
);
285 (*PageEntry
) = PAGE_MASK(*PageEntry
) | Attributes
;
287 if (Process
!= CurrentProcess
)
293 PHYSICAL_ADDRESS STDCALL
MmGetPhysicalAddress(PVOID vaddr
)
295 * FUNCTION: Returns the physical address corresponding to a virtual address
302 DPRINT("MmGetPhysicalAddress(vaddr %x)\n", vaddr
);
304 p
.u
.LowPart
= PAGE_MASK(*MmGetPageEntry(vaddr
));