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.
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 (