3 * COPYRIGHT: See COPYING in the top directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/mm/mm.c
6 * PURPOSE: Kernel memory managment functions
7 * PROGRAMMERS: David Welch (welch@cwcom.net)
10 /* INCLUDES *****************************************************************/
14 #include <internal/debug.h>
16 /* GLOBALS *****************************************************************/
18 extern MODULE_OBJECT NtoskrnlModuleObject
;
19 extern MODULE_OBJECT HalModuleObject
;
21 ULONG EXPORTED MmUserProbeAddress
= 0;
22 PVOID EXPORTED MmHighestUserAddress
= NULL
;
23 PBOOLEAN EXPORTED Mm64BitPhysicalAddress
= FALSE
;
24 PVOID EXPORTED MmSystemRangeStart
= NULL
;
28 /* FUNCTIONS ****************************************************************/
32 MmCopyToCaller(PVOID Dest
, const VOID
*Src
, ULONG NumberOfBytes
)
36 if (ExGetPreviousMode() == UserMode
)
38 if ((ULONG_PTR
)Dest
>= KERNEL_BASE
)
40 return(STATUS_ACCESS_VIOLATION
);
42 Status
= MmSafeCopyToUser(Dest
, Src
, NumberOfBytes
);
47 memcpy(Dest
, Src
, NumberOfBytes
);
48 return(STATUS_SUCCESS
);
53 MmCopyFromCaller(PVOID Dest
, const VOID
*Src
, ULONG NumberOfBytes
)
57 if (ExGetPreviousMode() == UserMode
)
59 if ((ULONG_PTR
)Src
>= KERNEL_BASE
)
61 return(STATUS_ACCESS_VIOLATION
);
63 Status
= MmSafeCopyFromUser(Dest
, Src
, NumberOfBytes
);
68 memcpy(Dest
, Src
, NumberOfBytes
);
69 return(STATUS_SUCCESS
);
75 NTSTATUS
MmReleaseMemoryArea(PEPROCESS Process
, PMEMORY_AREA Marea
)
79 DPRINT("MmReleaseMemoryArea(Process %x, Marea %x)\n",Process
,Marea
);
81 DPRINT("Releasing %x between %x %x (type %d)\n",
82 Marea
, Marea
->StartingAddress
, Marea
->EndingAddress
,
87 case MEMORY_AREA_SECTION_VIEW
:
88 Status
= MmUnmapViewOfSection(Process
, (PVOID
)Marea
->StartingAddress
);
89 ASSERT(Status
== STATUS_SUCCESS
);
90 return(STATUS_SUCCESS
);
92 case MEMORY_AREA_VIRTUAL_MEMORY
:
93 case MEMORY_AREA_PEB_OR_TEB
:
94 MmFreeVirtualMemory(Process
, Marea
);
97 case MEMORY_AREA_SHARED_DATA
:
98 case MEMORY_AREA_NO_ACCESS
:
99 Status
= MmFreeMemoryArea(&Process
->AddressSpace
,
105 case MEMORY_AREA_MDL_MAPPING
:
106 KEBUGCHECK(PROCESS_HAS_LOCKED_PAGES
);
113 return(STATUS_SUCCESS
);
116 NTSTATUS
MmReleaseMmInfo(PEPROCESS Process
)
118 DPRINT("MmReleaseMmInfo(Process %x (%s))\n", Process
,
119 Process
->ImageFileName
);
121 MmLockAddressSpace(&Process
->AddressSpace
);
123 while (Process
->AddressSpace
.MemoryAreaRoot
!= NULL
)
124 MmReleaseMemoryArea(Process
, Process
->AddressSpace
.MemoryAreaRoot
);
126 Mmi386ReleaseMmInfo(Process
);
128 MmUnlockAddressSpace(&Process
->AddressSpace
);
129 MmDestroyAddressSpace(&Process
->AddressSpace
);
131 DPRINT("Finished MmReleaseMmInfo()\n");
132 return(STATUS_SUCCESS
);
138 BOOLEAN STDCALL
MmIsNonPagedSystemAddressValid(PVOID VirtualAddress
)
140 return MmIsAddressValid(VirtualAddress
);
146 BOOLEAN STDCALL
MmIsAddressValid(PVOID VirtualAddress
)
148 * FUNCTION: Checks whether the given address is valid for a read or write
150 * VirtualAddress = address to check
151 * RETURNS: True if the access would be valid
152 * False if the access would cause a page fault
153 * NOTES: This function checks whether a byte access to the page would
154 * succeed. Is this realistic for RISC processors which don't
155 * allow byte granular access?
158 MEMORY_AREA
* MemoryArea
;
159 PMADDRESS_SPACE AddressSpace
;
161 if ((ULONG_PTR
)VirtualAddress
>= KERNEL_BASE
)
163 AddressSpace
= MmGetKernelAddressSpace();
167 AddressSpace
= &PsGetCurrentProcess()->AddressSpace
;
170 MmLockAddressSpace(AddressSpace
);
171 MemoryArea
= MmLocateMemoryAreaByAddress(AddressSpace
,
174 if (MemoryArea
== NULL
|| MemoryArea
->DeleteInProgress
)
176 MmUnlockAddressSpace(AddressSpace
);
179 MmUnlockAddressSpace(AddressSpace
);
183 NTSTATUS
MmAccessFault(KPROCESSOR_MODE Mode
,
187 PMADDRESS_SPACE AddressSpace
;
188 MEMORY_AREA
* MemoryArea
;
190 BOOLEAN Locked
= FromMdl
;
192 DPRINT("MmAccessFault(Mode %d, Address %x)\n", Mode
, Address
);
194 if (KeGetCurrentIrql() >= DISPATCH_LEVEL
)
196 DbgPrint("Page fault at high IRQL was %d\n", KeGetCurrentIrql());
197 return(STATUS_UNSUCCESSFUL
);
199 if (PsGetCurrentProcess() == NULL
)
201 DbgPrint("No current process\n");
202 return(STATUS_UNSUCCESSFUL
);
206 * Find the memory area for the faulting address
208 if (Address
>= KERNEL_BASE
)
213 if (Mode
!= KernelMode
)
215 DbgPrint("%s:%d\n",__FILE__
,__LINE__
);
216 return(STATUS_UNSUCCESSFUL
);
218 AddressSpace
= MmGetKernelAddressSpace();
222 AddressSpace
= &PsGetCurrentProcess()->AddressSpace
;
227 MmLockAddressSpace(AddressSpace
);
231 MemoryArea
= MmLocateMemoryAreaByAddress(AddressSpace
, (PVOID
)Address
);
232 if (MemoryArea
== NULL
|| MemoryArea
->DeleteInProgress
)
236 MmUnlockAddressSpace(AddressSpace
);
238 return (STATUS_UNSUCCESSFUL
);
241 switch (MemoryArea
->Type
)
243 case MEMORY_AREA_SYSTEM
:
244 Status
= STATUS_UNSUCCESSFUL
;
247 case MEMORY_AREA_PAGED_POOL
:
248 Status
= STATUS_SUCCESS
;
251 case MEMORY_AREA_SECTION_VIEW
:
252 Status
= MmAccessFaultSectionView(AddressSpace
,
258 case MEMORY_AREA_VIRTUAL_MEMORY
:
259 Status
= STATUS_UNSUCCESSFUL
;
262 case MEMORY_AREA_SHARED_DATA
:
263 Status
= STATUS_UNSUCCESSFUL
;
267 Status
= STATUS_UNSUCCESSFUL
;
271 while (Status
== STATUS_MM_RESTART_OPERATION
);
273 DPRINT("Completed page fault handling\n");
276 MmUnlockAddressSpace(AddressSpace
);
281 NTSTATUS
MmCommitPagedPoolAddress(PVOID Address
, BOOLEAN Locked
)
284 PFN_TYPE AllocatedPage
;
285 Status
= MmRequestPageMemoryConsumer(MC_PPOOL
, FALSE
, &AllocatedPage
);
286 if (!NT_SUCCESS(Status
))
288 MmUnlockAddressSpace(MmGetKernelAddressSpace());
289 Status
= MmRequestPageMemoryConsumer(MC_PPOOL
, TRUE
, &AllocatedPage
);
290 MmLockAddressSpace(MmGetKernelAddressSpace());
293 MmCreateVirtualMapping(NULL
,
294 (PVOID
)PAGE_ROUND_DOWN(Address
),
300 MmLockPage(AllocatedPage
);
305 NTSTATUS
MmNotPresentFault(KPROCESSOR_MODE Mode
,
309 PMADDRESS_SPACE AddressSpace
;
310 MEMORY_AREA
* MemoryArea
;
312 BOOLEAN Locked
= FromMdl
;
315 DPRINT("MmNotPresentFault(Mode %d, Address %x)\n", Mode
, Address
);
317 if (KeGetCurrentIrql() >= DISPATCH_LEVEL
)
319 DbgPrint("Page fault at high IRQL was %d\n", KeGetCurrentIrql());
320 return(STATUS_UNSUCCESSFUL
);
322 if (PsGetCurrentProcess() == NULL
)
324 DbgPrint("No current process\n");
325 return(STATUS_UNSUCCESSFUL
);
329 * Find the memory area for the faulting address
331 if (Address
>= KERNEL_BASE
)
336 if (Mode
!= KernelMode
)
338 DbgPrint("%s:%d\n",__FILE__
,__LINE__
);
339 return(STATUS_UNSUCCESSFUL
);
341 AddressSpace
= MmGetKernelAddressSpace();
345 AddressSpace
= &PsGetCurrentProcess()->AddressSpace
;
350 MmLockAddressSpace(AddressSpace
);
354 * Call the memory area specific fault handler
358 MemoryArea
= MmLocateMemoryAreaByAddress(AddressSpace
, (PVOID
)Address
);
359 if (MemoryArea
== NULL
|| MemoryArea
->DeleteInProgress
)
363 MmUnlockAddressSpace(AddressSpace
);
365 return (STATUS_UNSUCCESSFUL
);
368 switch (MemoryArea
->Type
)
370 case MEMORY_AREA_PAGED_POOL
:
372 Status
= MmCommitPagedPoolAddress((PVOID
)Address
, Locked
);
376 case MEMORY_AREA_SYSTEM
:
377 Status
= STATUS_UNSUCCESSFUL
;
380 case MEMORY_AREA_SECTION_VIEW
:
381 Status
= MmNotPresentFaultSectionView(AddressSpace
,
387 case MEMORY_AREA_VIRTUAL_MEMORY
:
388 case MEMORY_AREA_PEB_OR_TEB
:
389 Status
= MmNotPresentFaultVirtualMemory(AddressSpace
,
395 case MEMORY_AREA_SHARED_DATA
:
396 Pfn
= MmSharedDataPagePhysicalAddress
.QuadPart
>> PAGE_SHIFT
;
398 MmCreateVirtualMapping(PsGetCurrentProcess(),
399 (PVOID
)PAGE_ROUND_DOWN(Address
),
406 Status
= STATUS_UNSUCCESSFUL
;
410 while (Status
== STATUS_MM_RESTART_OPERATION
);
412 DPRINT("Completed page fault handling\n");
415 MmUnlockAddressSpace(AddressSpace
);
420 /* Miscellanea functions: they may fit somewhere else */
426 MmAdjustWorkingSetSize (DWORD Unknown0
,
437 MmDbgTranslatePhysicalAddress (
457 return (STATUS_NOT_IMPLEMENTED
);
466 MmSetAddressRangeModified (
480 MmGetSystemRoutineAddress (
481 IN PUNICODE_STRING SystemRoutineName
485 ANSI_STRING AnsiRoutineName
;
488 if(!NT_SUCCESS(RtlUnicodeStringToAnsiString(&AnsiRoutineName
,
495 Status
= LdrGetProcedureAddress(NtoskrnlModuleObject
.Base
,
500 if(!NT_SUCCESS(Status
))
502 Status
= LdrGetProcedureAddress(HalModuleObject
.Base
,
508 RtlFreeAnsiString(&AnsiRoutineName
);
510 return (NT_SUCCESS(Status
) ? ProcAddress
: NULL
);