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.
19 /* $Id: mm.c,v 1.60 2002/09/08 10:23:35 chorns Exp $
21 * COPYRIGHT: See COPYING in the top directory
22 * PROJECT: ReactOS kernel
23 * FILE: ntoskrnl/mm/mm.c
24 * PURPOSE: kernel memory managment functions
25 * PROGRAMMER: David Welch (welch@cwcom.net)
30 /* INCLUDES *****************************************************************/
32 #include <ddk/ntddk.h>
33 #include <internal/i386/segment.h>
34 #include <internal/mm.h>
35 #include <internal/ntoskrnl.h>
36 #include <internal/io.h>
37 #include <internal/ps.h>
40 #include <internal/debug.h>
42 /* GLOBALS *****************************************************************/
44 PVOID EXPORTED MmUserProbeAddress
= NULL
;
45 PVOID EXPORTED MmHighestUserAddress
= NULL
;
48 /* FUNCTIONS ****************************************************************/
50 NTSTATUS
MmReleaseMemoryArea(PEPROCESS Process
, PMEMORY_AREA Marea
)
54 DPRINT("MmReleaseMemoryArea(Process %x, Marea %x)\n",Process
,Marea
);
56 DPRINT("Releasing %x between %x %x (type %d)\n",
57 Marea
, Marea
->BaseAddress
, Marea
->BaseAddress
+ Marea
->Length
,
62 case MEMORY_AREA_SECTION_VIEW
:
63 Status
= MmUnmapViewOfSection(Process
, Marea
->BaseAddress
);
64 assert(Status
== STATUS_SUCCESS
);
65 return(STATUS_SUCCESS
);
67 case MEMORY_AREA_VIRTUAL_MEMORY
:
68 MmFreeVirtualMemory(Process
, Marea
);
71 case MEMORY_AREA_SHARED_DATA
:
72 Status
= MmFreeMemoryArea(&Process
->AddressSpace
,
83 return(STATUS_SUCCESS
);
86 NTSTATUS
MmReleaseMmInfo(PEPROCESS Process
)
88 PLIST_ENTRY CurrentEntry
;
91 DPRINT("MmReleaseMmInfo(Process %x (%s))\n", Process
,
92 Process
->ImageFileName
);
94 MmLockAddressSpace(&Process
->AddressSpace
);
96 CurrentEntry
= Process
->AddressSpace
.MAreaListHead
.Flink
;
97 while (CurrentEntry
!= &Process
->AddressSpace
.MAreaListHead
)
99 Current
= CONTAINING_RECORD(CurrentEntry
, MEMORY_AREA
, Entry
);
100 CurrentEntry
= CurrentEntry
->Flink
;
102 MmReleaseMemoryArea(Process
, Current
);
105 Mmi386ReleaseMmInfo(Process
);
107 MmUnlockAddressSpace(&Process
->AddressSpace
);
108 MmDestroyAddressSpace(&Process
->AddressSpace
);
110 DPRINT("Finished MmReleaseMmInfo()\n");
111 return(STATUS_SUCCESS
);
114 BOOLEAN STDCALL
MmIsNonPagedSystemAddressValid(PVOID VirtualAddress
)
119 BOOLEAN STDCALL
MmIsAddressValid(PVOID VirtualAddress
)
121 * FUNCTION: Checks whether the given address is valid for a read or write
123 * VirtualAddress = address to check
124 * RETURNS: True if the access would be valid
125 * False if the access would cause a page fault
126 * NOTES: This function checks whether a byte access to the page would
127 * succeed. Is this realistic for RISC processors which don't
128 * allow byte granular access?
131 MEMORY_AREA
* MemoryArea
;
132 PMADDRESS_SPACE AddressSpace
;
134 AddressSpace
= &PsGetCurrentProcess()->AddressSpace
;
136 MmLockAddressSpace(AddressSpace
);
137 MemoryArea
= MmOpenMemoryAreaByAddress(AddressSpace
,
140 if (MemoryArea
== NULL
)
142 MmUnlockAddressSpace(AddressSpace
);
145 MmUnlockAddressSpace(AddressSpace
);
149 NTSTATUS
MmAccessFault(KPROCESSOR_MODE Mode
,
153 PMADDRESS_SPACE AddressSpace
;
154 MEMORY_AREA
* MemoryArea
;
156 BOOLEAN Locked
= FromMdl
;
158 DPRINT("MmAccessFault(Mode %d, Address %x)\n", Mode
, Address
);
160 if (KeGetCurrentIrql() >= DISPATCH_LEVEL
)
162 DbgPrint("Page fault at high IRQL was %d\n", KeGetCurrentIrql());
163 return(STATUS_UNSUCCESSFUL
);
165 if (PsGetCurrentProcess() == NULL
)
167 DbgPrint("No current process\n");
168 return(STATUS_UNSUCCESSFUL
);
172 * Find the memory area for the faulting address
174 if (Address
>= KERNEL_BASE
)
179 if (Mode
!= KernelMode
)
181 DbgPrint("%s:%d\n",__FILE__
,__LINE__
);
182 return(STATUS_UNSUCCESSFUL
);
184 AddressSpace
= MmGetKernelAddressSpace();
188 AddressSpace
= &PsGetCurrentProcess()->AddressSpace
;
193 MmLockAddressSpace(AddressSpace
);
195 MemoryArea
= MmOpenMemoryAreaByAddress(AddressSpace
, (PVOID
)Address
);
196 if (MemoryArea
== NULL
)
198 DbgPrint("%s:%d\n",__FILE__
,__LINE__
);
201 MmUnlockAddressSpace(AddressSpace
);
203 return(STATUS_UNSUCCESSFUL
);
206 switch (MemoryArea
->Type
)
208 case MEMORY_AREA_SYSTEM
:
209 Status
= STATUS_UNSUCCESSFUL
;
212 case MEMORY_AREA_PAGED_POOL
:
213 Status
= STATUS_SUCCESS
;
216 case MEMORY_AREA_SECTION_VIEW
:
217 Status
= MmAccessFaultSectionView(AddressSpace
,
223 case MEMORY_AREA_VIRTUAL_MEMORY
:
224 Status
= STATUS_UNSUCCESSFUL
;
227 case MEMORY_AREA_SHARED_DATA
:
228 Status
= STATUS_UNSUCCESSFUL
;
232 Status
= STATUS_UNSUCCESSFUL
;
235 DPRINT("Completed page fault handling\n");
238 MmUnlockAddressSpace(AddressSpace
);
243 NTSTATUS
MmCommitPagedPoolAddress(PVOID Address
)
246 PHYSICAL_ADDRESS AllocatedPage
;
247 Status
= MmRequestPageMemoryConsumer(MC_PPOOL
, FALSE
, &AllocatedPage
);
248 if (!NT_SUCCESS(Status
))
250 MmUnlockAddressSpace(MmGetKernelAddressSpace());
251 Status
= MmRequestPageMemoryConsumer(MC_PPOOL
, TRUE
, &AllocatedPage
);
252 MmLockAddressSpace(MmGetKernelAddressSpace());
255 MmCreateVirtualMapping(NULL
,
256 (PVOID
)PAGE_ROUND_DOWN(Address
),
260 if (!NT_SUCCESS(Status
))
262 MmUnlockAddressSpace(MmGetKernelAddressSpace());
264 MmCreateVirtualMapping(NULL
,
265 (PVOID
)PAGE_ROUND_DOWN(Address
),
269 MmLockAddressSpace(MmGetKernelAddressSpace());
274 NTSTATUS
MmNotPresentFault(KPROCESSOR_MODE Mode
,
278 PMADDRESS_SPACE AddressSpace
;
279 MEMORY_AREA
* MemoryArea
;
281 BOOLEAN Locked
= FromMdl
;
283 DPRINT("MmNotPresentFault(Mode %d, Address %x)\n", Mode
, Address
);
285 if (KeGetCurrentIrql() >= DISPATCH_LEVEL
)
287 DbgPrint("Page fault at high IRQL was %d\n", KeGetCurrentIrql());
288 return(STATUS_UNSUCCESSFUL
);
290 if (PsGetCurrentProcess() == NULL
)
292 DbgPrint("No current process\n");
293 return(STATUS_UNSUCCESSFUL
);
297 * Find the memory area for the faulting address
299 if (Address
>= KERNEL_BASE
)
304 if (Mode
!= KernelMode
)
306 DbgPrint("%s:%d\n",__FILE__
,__LINE__
);
307 return(STATUS_UNSUCCESSFUL
);
309 AddressSpace
= MmGetKernelAddressSpace();
313 AddressSpace
= &PsGetCurrentProcess()->AddressSpace
;
318 MmLockAddressSpace(AddressSpace
);
322 * Call the memory area specific fault handler
326 MemoryArea
= MmOpenMemoryAreaByAddress(AddressSpace
, (PVOID
)Address
);
327 if (MemoryArea
== NULL
)
331 MmUnlockAddressSpace(AddressSpace
);
333 return (STATUS_UNSUCCESSFUL
);
336 switch (MemoryArea
->Type
)
338 case MEMORY_AREA_PAGED_POOL
:
340 Status
= MmCommitPagedPoolAddress((PVOID
)Address
);
344 case MEMORY_AREA_SYSTEM
:
345 Status
= STATUS_UNSUCCESSFUL
;
348 case MEMORY_AREA_SECTION_VIEW
:
349 Status
= MmNotPresentFaultSectionView(AddressSpace
,
355 case MEMORY_AREA_VIRTUAL_MEMORY
:
356 Status
= MmNotPresentFaultVirtualMemory(AddressSpace
,
362 case MEMORY_AREA_SHARED_DATA
:
364 MmCreateVirtualMapping(PsGetCurrentProcess(),
365 (PVOID
)PAGE_ROUND_DOWN(Address
),
367 MmSharedDataPagePhysicalAddress
,
369 if (!NT_SUCCESS(Status
))
371 MmUnlockAddressSpace(&PsGetCurrentProcess()->AddressSpace
);
373 MmCreateVirtualMapping(PsGetCurrentProcess(),
374 (PVOID
)PAGE_ROUND_DOWN(Address
),
376 MmSharedDataPagePhysicalAddress
,
378 MmLockAddressSpace(&PsGetCurrentProcess()->AddressSpace
);
383 Status
= STATUS_UNSUCCESSFUL
;
387 while (Status
== STATUS_MM_RESTART_OPERATION
);
389 DPRINT("Completed page fault handling\n");
392 MmUnlockAddressSpace(AddressSpace
);
397 /* Miscellanea functions: they may fit somewhere else */
400 MmAdjustWorkingSetSize (DWORD Unknown0
,
411 MmDbgTranslatePhysicalAddress (
428 return (STATUS_NOT_IMPLEMENTED
);
434 MmSetAddressRangeModified (