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.59 2002/09/07 15:12:59 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 *****************************************************************/
35 #include <internal/debug.h>
38 /* GLOBALS *****************************************************************/
42 /* FUNCTIONS ****************************************************************/
44 NTSTATUS
MmReleaseMemoryArea(PEPROCESS Process
, PMEMORY_AREA Marea
)
48 DPRINT("MmReleaseMemoryArea(Process %x, Marea %x)\n",Process
,Marea
);
50 DPRINT("Releasing %x between %x %x (type %d)\n",
51 Marea
, Marea
->BaseAddress
, Marea
->BaseAddress
+ Marea
->Length
,
56 case MEMORY_AREA_SECTION_VIEW
:
57 Status
= MmUnmapViewOfSection(Process
, Marea
->BaseAddress
);
58 assert(Status
== STATUS_SUCCESS
);
59 return(STATUS_SUCCESS
);
61 case MEMORY_AREA_VIRTUAL_MEMORY
:
62 MmFreeVirtualMemory(Process
, Marea
);
65 case MEMORY_AREA_SHARED_DATA
:
66 Status
= MmFreeMemoryArea(&Process
->AddressSpace
,
77 return(STATUS_SUCCESS
);
80 NTSTATUS
MmReleaseMmInfo(PEPROCESS Process
)
82 PLIST_ENTRY CurrentEntry
;
85 DPRINT("MmReleaseMmInfo(Process %x (%s))\n", Process
,
86 Process
->ImageFileName
);
88 MmLockAddressSpace(&Process
->AddressSpace
);
90 CurrentEntry
= Process
->AddressSpace
.MAreaListHead
.Flink
;
91 while (CurrentEntry
!= &Process
->AddressSpace
.MAreaListHead
)
93 Current
= CONTAINING_RECORD(CurrentEntry
, MEMORY_AREA
, Entry
);
94 CurrentEntry
= CurrentEntry
->Flink
;
96 MmReleaseMemoryArea(Process
, Current
);
99 Mmi386ReleaseMmInfo(Process
);
101 MmUnlockAddressSpace(&Process
->AddressSpace
);
102 MmDestroyAddressSpace(&Process
->AddressSpace
);
104 DPRINT("Finished MmReleaseMmInfo()\n");
105 return(STATUS_SUCCESS
);
108 BOOLEAN STDCALL
MmIsNonPagedSystemAddressValid(PVOID VirtualAddress
)
113 BOOLEAN STDCALL
MmIsAddressValid(PVOID VirtualAddress
)
115 * FUNCTION: Checks whether the given address is valid for a read or write
117 * VirtualAddress = address to check
118 * RETURNS: True if the access would be valid
119 * False if the access would cause a page fault
120 * NOTES: This function checks whether a byte access to the page would
121 * succeed. Is this realistic for RISC processors which don't
122 * allow byte granular access?
125 MEMORY_AREA
* MemoryArea
;
126 PMADDRESS_SPACE AddressSpace
;
128 AddressSpace
= &PsGetCurrentProcess()->AddressSpace
;
130 MmLockAddressSpace(AddressSpace
);
131 MemoryArea
= MmOpenMemoryAreaByAddress(AddressSpace
,
134 if (MemoryArea
== NULL
)
136 MmUnlockAddressSpace(AddressSpace
);
139 MmUnlockAddressSpace(AddressSpace
);
143 NTSTATUS
MmAccessFault(KPROCESSOR_MODE Mode
,
147 PMADDRESS_SPACE AddressSpace
;
148 MEMORY_AREA
* MemoryArea
;
150 BOOLEAN Locked
= FromMdl
;
152 DPRINT("MmAccessFault(Mode %d, Address %x)\n", Mode
, Address
);
154 if (KeGetCurrentIrql() >= DISPATCH_LEVEL
)
156 DbgPrint("Page fault at high IRQL was %d\n", KeGetCurrentIrql());
157 KeDumpStackFrames((PULONG
)__builtin_frame_address(0));
158 return(STATUS_UNSUCCESSFUL
);
160 if (PsGetCurrentProcess() == NULL
)
162 DbgPrint("No current process\n");
163 return(STATUS_UNSUCCESSFUL
);
167 * Find the memory area for the faulting address
169 if (Address
>= KERNEL_BASE
)
174 if (Mode
!= KernelMode
)
176 DbgPrint("%s:%d\n",__FILE__
,__LINE__
);
177 return(STATUS_UNSUCCESSFUL
);
179 AddressSpace
= MmGetKernelAddressSpace();
183 AddressSpace
= &PsGetCurrentProcess()->AddressSpace
;
188 MmLockAddressSpace(AddressSpace
);
190 MemoryArea
= MmOpenMemoryAreaByAddress(AddressSpace
, (PVOID
)Address
);
191 if (MemoryArea
== NULL
)
193 DbgPrint("%s:%d\n",__FILE__
,__LINE__
);
196 MmUnlockAddressSpace(AddressSpace
);
198 return(STATUS_UNSUCCESSFUL
);
201 switch (MemoryArea
->Type
)
203 case MEMORY_AREA_SYSTEM
:
204 Status
= STATUS_UNSUCCESSFUL
;
207 case MEMORY_AREA_PAGED_POOL
:
208 Status
= STATUS_SUCCESS
;
211 case MEMORY_AREA_SECTION_VIEW
:
212 Status
= MmAccessFaultSectionView(AddressSpace
,
218 case MEMORY_AREA_VIRTUAL_MEMORY
:
219 Status
= STATUS_UNSUCCESSFUL
;
222 case MEMORY_AREA_SHARED_DATA
:
223 Status
= STATUS_UNSUCCESSFUL
;
227 Status
= STATUS_UNSUCCESSFUL
;
230 DPRINT("Completed page fault handling\n");
233 MmUnlockAddressSpace(AddressSpace
);
238 NTSTATUS
MmCommitPagedPoolAddress(PVOID Address
)
241 PHYSICAL_ADDRESS AllocatedPage
;
242 Status
= MmRequestPageMemoryConsumer(MC_PPOOL
, FALSE
, &AllocatedPage
);
243 if (!NT_SUCCESS(Status
))
245 MmUnlockAddressSpace(MmGetKernelAddressSpace());
246 Status
= MmRequestPageMemoryConsumer(MC_PPOOL
, TRUE
, &AllocatedPage
);
247 MmLockAddressSpace(MmGetKernelAddressSpace());
250 MmCreateVirtualMapping(NULL
,
251 (PVOID
)PAGE_ROUND_DOWN(Address
),
255 if (!NT_SUCCESS(Status
))
257 MmUnlockAddressSpace(MmGetKernelAddressSpace());
259 MmCreateVirtualMapping(NULL
,
260 (PVOID
)PAGE_ROUND_DOWN(Address
),
264 MmLockAddressSpace(MmGetKernelAddressSpace());
269 NTSTATUS
MmNotPresentFault(KPROCESSOR_MODE Mode
,
273 PMADDRESS_SPACE AddressSpace
;
274 MEMORY_AREA
* MemoryArea
;
276 BOOLEAN Locked
= FromMdl
;
278 DPRINT("MmNotPresentFault(Mode %d, Address %x)\n", Mode
, Address
);
280 if (KeGetCurrentIrql() >= DISPATCH_LEVEL
)
282 DbgPrint("Page fault at high IRQL was %d\n", KeGetCurrentIrql());
283 return(STATUS_UNSUCCESSFUL
);
285 if (PsGetCurrentProcess() == NULL
)
287 DbgPrint("No current process\n");
288 return(STATUS_UNSUCCESSFUL
);
292 * Find the memory area for the faulting address
294 if (Address
>= KERNEL_BASE
)
299 if (Mode
!= KernelMode
)
301 DbgPrint("%s:%d\n",__FILE__
,__LINE__
);
302 return(STATUS_UNSUCCESSFUL
);
304 AddressSpace
= MmGetKernelAddressSpace();
308 AddressSpace
= &PsGetCurrentProcess()->AddressSpace
;
313 MmLockAddressSpace(AddressSpace
);
317 * Call the memory area specific fault handler
321 MemoryArea
= MmOpenMemoryAreaByAddress(AddressSpace
, (PVOID
)Address
);
322 if (MemoryArea
== NULL
)
326 MmUnlockAddressSpace(AddressSpace
);
328 return (STATUS_UNSUCCESSFUL
);
331 switch (MemoryArea
->Type
)
333 case MEMORY_AREA_PAGED_POOL
:
335 Status
= MmCommitPagedPoolAddress((PVOID
)Address
);
339 case MEMORY_AREA_SYSTEM
:
340 Status
= STATUS_UNSUCCESSFUL
;
343 case MEMORY_AREA_SECTION_VIEW
:
344 Status
= MmNotPresentFaultSectionView(AddressSpace
,
350 case MEMORY_AREA_VIRTUAL_MEMORY
:
351 Status
= MmNotPresentFaultVirtualMemory(AddressSpace
,
357 case MEMORY_AREA_SHARED_DATA
:
359 MmCreateVirtualMapping(PsGetCurrentProcess(),
360 (PVOID
)PAGE_ROUND_DOWN(Address
),
362 MmSharedDataPagePhysicalAddress
,
364 if (!NT_SUCCESS(Status
))
366 MmUnlockAddressSpace(&PsGetCurrentProcess()->AddressSpace
);
368 MmCreateVirtualMapping(PsGetCurrentProcess(),
369 (PVOID
)PAGE_ROUND_DOWN(Address
),
371 MmSharedDataPagePhysicalAddress
,
373 MmLockAddressSpace(&PsGetCurrentProcess()->AddressSpace
);
378 Status
= STATUS_UNSUCCESSFUL
;
382 while (Status
== STATUS_MM_RESTART_OPERATION
);
384 DPRINT("Completed page fault handling\n");
387 MmUnlockAddressSpace(AddressSpace
);
392 /* Miscellanea functions: they may fit somewhere else */
395 MmAdjustWorkingSetSize (DWORD Unknown0
,
406 MmDbgTranslatePhysicalAddress (
423 return (STATUS_NOT_IMPLEMENTED
);
429 MmSetAddressRangeModified (