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.54 2002/01/23 23:39:26 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
;
47 extern PVOID MmSharedDataPagePhysicalAddress
;
49 /* FUNCTIONS ****************************************************************/
51 NTSTATUS
MmReleaseMemoryArea(PEPROCESS Process
, PMEMORY_AREA Marea
)
55 DPRINT("MmReleaseMemoryArea(Process %x, Marea %x)\n",Process
,Marea
);
57 DPRINT("Releasing %x between %x %x (type %d)\n",
58 Marea
, Marea
->BaseAddress
, Marea
->BaseAddress
+ Marea
->Length
,
63 case MEMORY_AREA_SECTION_VIEW_COMMIT
:
64 case MEMORY_AREA_SECTION_VIEW_RESERVE
:
65 Status
= MmUnmapViewOfSection(Process
, Marea
->BaseAddress
);
66 assert(Status
== STATUS_SUCCESS
);
67 return(STATUS_SUCCESS
);
69 case MEMORY_AREA_VIRTUAL_MEMORY
:
70 MmFreeVirtualMemory(Process
, Marea
);
73 case MEMORY_AREA_SHARED_DATA
:
74 Status
= MmFreeMemoryArea(&Process
->AddressSpace
,
85 return(STATUS_SUCCESS
);
88 NTSTATUS
MmReleaseMmInfo(PEPROCESS Process
)
90 PLIST_ENTRY CurrentEntry
;
93 DPRINT("MmReleaseMmInfo(Process %x (%s))\n", Process
,
94 Process
->ImageFileName
);
96 MmLockAddressSpace(&Process
->AddressSpace
);
98 CurrentEntry
= Process
->AddressSpace
.MAreaListHead
.Flink
;
99 while (CurrentEntry
!= &Process
->AddressSpace
.MAreaListHead
)
101 Current
= CONTAINING_RECORD(CurrentEntry
, MEMORY_AREA
, Entry
);
102 CurrentEntry
= CurrentEntry
->Flink
;
104 MmReleaseMemoryArea(Process
, Current
);
107 Mmi386ReleaseMmInfo(Process
);
109 MmUnlockAddressSpace(&Process
->AddressSpace
);
110 MmDestroyAddressSpace(&Process
->AddressSpace
);
112 DPRINT("Finished MmReleaseMmInfo()\n");
113 return(STATUS_SUCCESS
);
116 BOOLEAN STDCALL
MmIsNonPagedSystemAddressValid(PVOID VirtualAddress
)
121 BOOLEAN STDCALL
MmIsAddressValid(PVOID VirtualAddress
)
123 * FUNCTION: Checks whether the given address is valid for a read or write
125 * VirtualAddress = address to check
126 * RETURNS: True if the access would be valid
127 * False if the access would cause a page fault
128 * NOTES: This function checks whether a byte access to the page would
129 * succeed. Is this realistic for RISC processors which don't
130 * allow byte granular access?
133 MEMORY_AREA
* MemoryArea
;
134 PMADDRESS_SPACE AddressSpace
;
136 AddressSpace
= &PsGetCurrentProcess()->AddressSpace
;
138 MmLockAddressSpace(AddressSpace
);
139 MemoryArea
= MmOpenMemoryAreaByAddress(AddressSpace
,
142 if (MemoryArea
== NULL
)
144 MmUnlockAddressSpace(AddressSpace
);
147 MmUnlockAddressSpace(AddressSpace
);
151 NTSTATUS
MmAccessFault(KPROCESSOR_MODE Mode
,
155 PMADDRESS_SPACE AddressSpace
;
156 MEMORY_AREA
* MemoryArea
;
158 BOOLEAN Locked
= FromMdl
;
160 DPRINT("MmAccessFault(Mode %d, Address %x)\n", Mode
, Address
);
162 if (KeGetCurrentIrql() >= DISPATCH_LEVEL
)
164 DbgPrint("Page fault at high IRQL was %d\n", KeGetCurrentIrql());
165 return(STATUS_UNSUCCESSFUL
);
167 if (PsGetCurrentProcess() == NULL
)
169 DbgPrint("No current process\n");
170 return(STATUS_UNSUCCESSFUL
);
174 * Find the memory area for the faulting address
176 if (Address
>= KERNEL_BASE
)
181 if (Mode
!= KernelMode
)
183 DbgPrint("%s:%d\n",__FILE__
,__LINE__
);
184 return(STATUS_UNSUCCESSFUL
);
186 AddressSpace
= MmGetKernelAddressSpace();
190 AddressSpace
= &PsGetCurrentProcess()->AddressSpace
;
195 MmLockAddressSpace(AddressSpace
);
197 MemoryArea
= MmOpenMemoryAreaByAddress(AddressSpace
, (PVOID
)Address
);
198 if (MemoryArea
== NULL
)
200 DbgPrint("%s:%d\n",__FILE__
,__LINE__
);
203 MmUnlockAddressSpace(AddressSpace
);
205 return(STATUS_UNSUCCESSFUL
);
208 switch (MemoryArea
->Type
)
210 case MEMORY_AREA_SYSTEM
:
211 Status
= STATUS_UNSUCCESSFUL
;
214 case MEMORY_AREA_PAGED_POOL
:
215 Status
= STATUS_SUCCESS
;
218 case MEMORY_AREA_SECTION_VIEW_COMMIT
:
219 Status
= MmAccessFaultSectionView(AddressSpace
,
225 case MEMORY_AREA_VIRTUAL_MEMORY
:
226 Status
= STATUS_UNSUCCESSFUL
;
229 case MEMORY_AREA_SHARED_DATA
:
230 Status
= STATUS_UNSUCCESSFUL
;
234 Status
= STATUS_UNSUCCESSFUL
;
237 DPRINT("Completed page fault handling\n");
240 MmUnlockAddressSpace(AddressSpace
);
245 NTSTATUS
MmCommitPagedPoolAddress(PVOID Address
)
249 Status
= MmRequestPageMemoryConsumer(MC_PPOOL
, FALSE
, &AllocatedPage
);
250 if (!NT_SUCCESS(Status
))
252 MmUnlockAddressSpace(MmGetKernelAddressSpace());
253 Status
= MmRequestPageMemoryConsumer(MC_PPOOL
, TRUE
, &AllocatedPage
);
254 MmLockAddressSpace(MmGetKernelAddressSpace());
257 MmCreateVirtualMapping(NULL
,
258 (PVOID
)PAGE_ROUND_DOWN(Address
),
260 (ULONG
)AllocatedPage
,
262 if (!NT_SUCCESS(Status
))
264 MmUnlockAddressSpace(MmGetKernelAddressSpace());
266 MmCreateVirtualMapping(NULL
,
267 (PVOID
)PAGE_ROUND_DOWN(Address
),
269 (ULONG
)AllocatedPage
,
271 MmLockAddressSpace(MmGetKernelAddressSpace());
276 NTSTATUS
MmNotPresentFault(KPROCESSOR_MODE Mode
,
280 PMADDRESS_SPACE AddressSpace
;
281 MEMORY_AREA
* MemoryArea
;
283 BOOLEAN Locked
= FromMdl
;
285 DPRINT("MmNotPresentFault(Mode %d, Address %x)\n", Mode
, Address
);
287 if (KeGetCurrentIrql() >= DISPATCH_LEVEL
)
289 DbgPrint("Page fault at high IRQL was %d\n", KeGetCurrentIrql());
290 return(STATUS_UNSUCCESSFUL
);
292 if (PsGetCurrentProcess() == NULL
)
294 DbgPrint("No current process\n");
295 return(STATUS_UNSUCCESSFUL
);
299 * Find the memory area for the faulting address
301 if (Address
>= KERNEL_BASE
)
306 if (Mode
!= KernelMode
)
308 DbgPrint("%s:%d\n",__FILE__
,__LINE__
);
309 return(STATUS_UNSUCCESSFUL
);
311 AddressSpace
= MmGetKernelAddressSpace();
315 AddressSpace
= &PsGetCurrentProcess()->AddressSpace
;
320 MmLockAddressSpace(AddressSpace
);
324 * Call the memory area specific fault handler
328 MemoryArea
= MmOpenMemoryAreaByAddress(AddressSpace
, (PVOID
)Address
);
329 if (MemoryArea
== NULL
)
333 MmUnlockAddressSpace(AddressSpace
);
335 return (STATUS_UNSUCCESSFUL
);
338 switch (MemoryArea
->Type
)
340 case MEMORY_AREA_PAGED_POOL
:
342 Status
= MmCommitPagedPoolAddress((PVOID
)Address
);
346 case MEMORY_AREA_SYSTEM
:
347 Status
= STATUS_UNSUCCESSFUL
;
350 case MEMORY_AREA_SECTION_VIEW_COMMIT
:
351 Status
= MmNotPresentFaultSectionView(AddressSpace
,
357 case MEMORY_AREA_VIRTUAL_MEMORY
:
358 Status
= MmNotPresentFaultVirtualMemory(AddressSpace
,
364 case MEMORY_AREA_SHARED_DATA
:
366 MmCreateVirtualMapping(PsGetCurrentProcess(),
367 (PVOID
)PAGE_ROUND_DOWN(Address
),
369 (ULONG
)MmSharedDataPagePhysicalAddress
,
371 if (!NT_SUCCESS(Status
))
373 MmUnlockAddressSpace(&PsGetCurrentProcess()->AddressSpace
);
375 MmCreateVirtualMapping(PsGetCurrentProcess(),
376 (PVOID
)PAGE_ROUND_DOWN(Address
),
378 (ULONG
)MmSharedDataPagePhysicalAddress
,
380 MmLockAddressSpace(&PsGetCurrentProcess()->AddressSpace
);
385 Status
= STATUS_UNSUCCESSFUL
;
389 while (Status
== STATUS_MM_RESTART_OPERATION
);
391 DPRINT("Completed page fault handling\n");
394 MmUnlockAddressSpace(AddressSpace
);
399 /* Miscellanea functions: they may fit somewhere else */
402 MmAdjustWorkingSetSize (DWORD Unknown0
,
413 MmDbgTranslatePhysicalAddress (
430 return (STATUS_NOT_IMPLEMENTED
);
436 MmSetAddressRangeModified (