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 LDR_DATA_TABLE_ENTRY NtoskrnlModuleObject
;
19 extern LDR_DATA_TABLE_ENTRY HalModuleObject
;
21 ULONG EXPORTED MmUserProbeAddress
= 0;
22 PVOID EXPORTED MmHighestUserAddress
= NULL
;
23 PBOOLEAN EXPORTED Mm64BitPhysicalAddress
= FALSE
;
24 PVOID EXPORTED MmSystemRangeStart
= NULL
;
28 /* FUNCTIONS ****************************************************************/
31 NTSTATUS
MmReleaseMemoryArea(PEPROCESS Process
, PMEMORY_AREA Marea
)
35 DPRINT("MmReleaseMemoryArea(Process %x, Marea %x)\n",Process
,Marea
);
37 DPRINT("Releasing %x between %x %x (type %d)\n",
38 Marea
, Marea
->StartingAddress
, Marea
->EndingAddress
,
43 case MEMORY_AREA_SECTION_VIEW
:
44 Status
= MmUnmapViewOfSection(Process
, (PVOID
)Marea
->StartingAddress
);
45 ASSERT(Status
== STATUS_SUCCESS
);
46 return(STATUS_SUCCESS
);
48 case MEMORY_AREA_VIRTUAL_MEMORY
:
49 case MEMORY_AREA_PEB_OR_TEB
:
50 MmFreeVirtualMemory(Process
, Marea
);
53 case MEMORY_AREA_SHARED_DATA
:
54 case MEMORY_AREA_NO_ACCESS
:
55 Status
= MmFreeMemoryArea(&Process
->AddressSpace
,
61 case MEMORY_AREA_MDL_MAPPING
:
62 KEBUGCHECK(PROCESS_HAS_LOCKED_PAGES
);
69 return(STATUS_SUCCESS
);
72 NTSTATUS
MmReleaseMmInfo(PEPROCESS Process
)
74 DPRINT("MmReleaseMmInfo(Process %x (%s))\n", Process
,
75 Process
->ImageFileName
);
77 MmLockAddressSpace(&Process
->AddressSpace
);
79 while (Process
->AddressSpace
.MemoryAreaRoot
!= NULL
)
80 MmReleaseMemoryArea(Process
, Process
->AddressSpace
.MemoryAreaRoot
);
82 Mmi386ReleaseMmInfo(Process
);
84 MmUnlockAddressSpace(&Process
->AddressSpace
);
85 MmDestroyAddressSpace(&Process
->AddressSpace
);
87 DPRINT("Finished MmReleaseMmInfo()\n");
88 return(STATUS_SUCCESS
);
94 BOOLEAN STDCALL
MmIsNonPagedSystemAddressValid(PVOID VirtualAddress
)
96 return MmIsAddressValid(VirtualAddress
);
102 BOOLEAN STDCALL
MmIsAddressValid(PVOID VirtualAddress
)
104 * FUNCTION: Checks whether the given address is valid for a read or write
106 * VirtualAddress = address to check
107 * RETURNS: True if the access would be valid
108 * False if the access would cause a page fault
109 * NOTES: This function checks whether a byte access to the page would
110 * succeed. Is this realistic for RISC processors which don't
111 * allow byte granular access?
114 MEMORY_AREA
* MemoryArea
;
115 PMADDRESS_SPACE AddressSpace
;
117 if (VirtualAddress
>= MmSystemRangeStart
)
119 AddressSpace
= MmGetKernelAddressSpace();
123 AddressSpace
= &PsGetCurrentProcess()->AddressSpace
;
126 MmLockAddressSpace(AddressSpace
);
127 MemoryArea
= MmLocateMemoryAreaByAddress(AddressSpace
,
130 if (MemoryArea
== NULL
|| MemoryArea
->DeleteInProgress
)
132 MmUnlockAddressSpace(AddressSpace
);
135 MmUnlockAddressSpace(AddressSpace
);
139 NTSTATUS
MmAccessFault(KPROCESSOR_MODE Mode
,
143 PMADDRESS_SPACE AddressSpace
;
144 MEMORY_AREA
* MemoryArea
;
146 BOOLEAN Locked
= FromMdl
;
148 DPRINT("MmAccessFault(Mode %d, Address %x)\n", Mode
, Address
);
150 if (KeGetCurrentIrql() >= DISPATCH_LEVEL
)
152 CPRINT("Page fault at high IRQL was %d\n", KeGetCurrentIrql());
153 return(STATUS_UNSUCCESSFUL
);
155 if (PsGetCurrentProcess() == NULL
)
157 CPRINT("No current process\n");
158 return(STATUS_UNSUCCESSFUL
);
162 * Find the memory area for the faulting address
164 if (Address
>= (ULONG_PTR
)MmSystemRangeStart
)
169 if (Mode
!= KernelMode
)
171 DbgPrint("%s:%d\n",__FILE__
,__LINE__
);
172 return(STATUS_UNSUCCESSFUL
);
174 AddressSpace
= MmGetKernelAddressSpace();
178 AddressSpace
= &PsGetCurrentProcess()->AddressSpace
;
183 MmLockAddressSpace(AddressSpace
);
187 MemoryArea
= MmLocateMemoryAreaByAddress(AddressSpace
, (PVOID
)Address
);
188 if (MemoryArea
== NULL
|| MemoryArea
->DeleteInProgress
)
192 MmUnlockAddressSpace(AddressSpace
);
194 return (STATUS_UNSUCCESSFUL
);
197 switch (MemoryArea
->Type
)
199 case MEMORY_AREA_SYSTEM
:
200 Status
= STATUS_UNSUCCESSFUL
;
203 case MEMORY_AREA_PAGED_POOL
:
204 Status
= STATUS_SUCCESS
;
207 case MEMORY_AREA_SECTION_VIEW
:
208 Status
= MmAccessFaultSectionView(AddressSpace
,
214 case MEMORY_AREA_VIRTUAL_MEMORY
:
215 Status
= STATUS_UNSUCCESSFUL
;
218 case MEMORY_AREA_SHARED_DATA
:
219 Status
= STATUS_UNSUCCESSFUL
;
223 Status
= STATUS_UNSUCCESSFUL
;
227 while (Status
== STATUS_MM_RESTART_OPERATION
);
229 DPRINT("Completed page fault handling\n");
232 MmUnlockAddressSpace(AddressSpace
);
237 NTSTATUS
MmCommitPagedPoolAddress(PVOID Address
, BOOLEAN Locked
)
240 PFN_TYPE AllocatedPage
;
241 Status
= MmRequestPageMemoryConsumer(MC_PPOOL
, FALSE
, &AllocatedPage
);
242 if (!NT_SUCCESS(Status
))
244 MmUnlockAddressSpace(MmGetKernelAddressSpace());
245 Status
= MmRequestPageMemoryConsumer(MC_PPOOL
, TRUE
, &AllocatedPage
);
246 MmLockAddressSpace(MmGetKernelAddressSpace());
249 MmCreateVirtualMapping(NULL
,
250 (PVOID
)PAGE_ROUND_DOWN(Address
),
256 MmLockPage(AllocatedPage
);
261 NTSTATUS
MmNotPresentFault(KPROCESSOR_MODE Mode
,
265 PMADDRESS_SPACE AddressSpace
;
266 MEMORY_AREA
* MemoryArea
;
268 BOOLEAN Locked
= FromMdl
;
271 DPRINT("MmNotPresentFault(Mode %d, Address %x)\n", Mode
, Address
);
273 if (KeGetCurrentIrql() >= DISPATCH_LEVEL
)
275 CPRINT("Page fault at high IRQL was %d, address %x\n", KeGetCurrentIrql(), Address
);
276 return(STATUS_UNSUCCESSFUL
);
278 if (PsGetCurrentProcess() == NULL
)
280 /* Allow this! It lets us page alloc much earlier! It won't be needed
281 * after my init patch anyways
283 CPRINT("No current process\n");
284 if (Address
< (ULONG_PTR
)MmSystemRangeStart
)
286 return(STATUS_UNSUCCESSFUL
);
291 * Find the memory area for the faulting address
293 if (Address
>= (ULONG_PTR
)MmSystemRangeStart
)
298 if (Mode
!= KernelMode
)
300 CPRINT("Address: %x\n", Address
);
301 return(STATUS_UNSUCCESSFUL
);
303 AddressSpace
= MmGetKernelAddressSpace();
307 AddressSpace
= &PsGetCurrentProcess()->AddressSpace
;
312 MmLockAddressSpace(AddressSpace
);
316 * Call the memory area specific fault handler
320 MemoryArea
= MmLocateMemoryAreaByAddress(AddressSpace
, (PVOID
)Address
);
321 if (MemoryArea
== NULL
|| MemoryArea
->DeleteInProgress
)
325 MmUnlockAddressSpace(AddressSpace
);
327 return (STATUS_UNSUCCESSFUL
);
330 switch (MemoryArea
->Type
)
332 case MEMORY_AREA_PAGED_POOL
:
334 Status
= MmCommitPagedPoolAddress((PVOID
)Address
, Locked
);
338 case MEMORY_AREA_SYSTEM
:
339 Status
= STATUS_UNSUCCESSFUL
;
342 case MEMORY_AREA_SECTION_VIEW
:
343 Status
= MmNotPresentFaultSectionView(AddressSpace
,
349 case MEMORY_AREA_VIRTUAL_MEMORY
:
350 case MEMORY_AREA_PEB_OR_TEB
:
351 Status
= MmNotPresentFaultVirtualMemory(AddressSpace
,
357 case MEMORY_AREA_SHARED_DATA
:
358 Pfn
= MmSharedDataPagePhysicalAddress
.QuadPart
>> PAGE_SHIFT
;
360 MmCreateVirtualMapping(PsGetCurrentProcess(),
361 (PVOID
)PAGE_ROUND_DOWN(Address
),
368 Status
= STATUS_UNSUCCESSFUL
;
372 while (Status
== STATUS_MM_RESTART_OPERATION
);
374 DPRINT("Completed page fault handling\n");
377 MmUnlockAddressSpace(AddressSpace
);
382 /* Miscellanea functions: they may fit somewhere else */
388 MmAdjustWorkingSetSize (DWORD Unknown0
,
399 MmDbgTranslatePhysicalAddress (
419 return (STATUS_NOT_IMPLEMENTED
);
428 MmSetAddressRangeModified (
442 MmGetSystemRoutineAddress (
443 IN PUNICODE_STRING SystemRoutineName
447 ANSI_STRING AnsiRoutineName
;
450 if(!NT_SUCCESS(RtlUnicodeStringToAnsiString(&AnsiRoutineName
,
457 Status
= LdrGetProcedureAddress(NtoskrnlModuleObject
.DllBase
,
462 if(!NT_SUCCESS(Status
))
464 Status
= LdrGetProcedureAddress(HalModuleObject
.DllBase
,
470 RtlFreeAnsiString(&AnsiRoutineName
);
472 return (NT_SUCCESS(Status
) ? ProcAddress
: NULL
);