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 MmUserProbeAddress
= 0;
22 PVOID MmHighestUserAddress
= NULL
;
23 PBOOLEAN Mm64BitPhysicalAddress
= FALSE
;
24 PVOID MmSystemRangeStart
= NULL
;
28 /* FUNCTIONS ****************************************************************/
33 MmReleaseMmInfo(PEPROCESS Process
)
36 PMEMORY_AREA MemoryArea
;
38 DPRINT("MmReleaseMmInfo(Process %x (%s))\n", Process
,
39 Process
->ImageFileName
);
41 MmLockAddressSpace(&Process
->AddressSpace
);
43 while ((MemoryArea
= Process
->AddressSpace
.MemoryAreaRoot
) != NULL
)
45 switch (MemoryArea
->Type
)
47 case MEMORY_AREA_SECTION_VIEW
:
48 Address
= (PVOID
)MemoryArea
->StartingAddress
;
49 MmUnlockAddressSpace(&Process
->AddressSpace
);
50 MmUnmapViewOfSection(Process
, Address
);
51 MmLockAddressSpace(&Process
->AddressSpace
);
54 case MEMORY_AREA_VIRTUAL_MEMORY
:
55 case MEMORY_AREA_PEB_OR_TEB
:
56 MmFreeVirtualMemory(Process
, MemoryArea
);
59 case MEMORY_AREA_SHARED_DATA
:
60 case MEMORY_AREA_NO_ACCESS
:
61 MmFreeMemoryArea(&Process
->AddressSpace
,
67 case MEMORY_AREA_MDL_MAPPING
:
68 KEBUGCHECK(PROCESS_HAS_LOCKED_PAGES
);
76 Mmi386ReleaseMmInfo(Process
);
78 MmUnlockAddressSpace(&Process
->AddressSpace
);
79 MmDestroyAddressSpace(&Process
->AddressSpace
);
81 DPRINT("Finished MmReleaseMmInfo()\n");
82 return(STATUS_SUCCESS
);
88 BOOLEAN STDCALL
MmIsNonPagedSystemAddressValid(PVOID VirtualAddress
)
90 return MmIsAddressValid(VirtualAddress
);
96 BOOLEAN STDCALL
MmIsAddressValid(PVOID VirtualAddress
)
98 * FUNCTION: Checks whether the given address is valid for a read or write
100 * VirtualAddress = address to check
101 * RETURNS: True if the access would be valid
102 * False if the access would cause a page fault
103 * NOTES: This function checks whether a byte access to the page would
104 * succeed. Is this realistic for RISC processors which don't
105 * allow byte granular access?
108 MEMORY_AREA
* MemoryArea
;
109 PMADDRESS_SPACE AddressSpace
;
111 if (VirtualAddress
>= MmSystemRangeStart
)
113 AddressSpace
= MmGetKernelAddressSpace();
117 AddressSpace
= &PsGetCurrentProcess()->AddressSpace
;
120 MmLockAddressSpace(AddressSpace
);
121 MemoryArea
= MmLocateMemoryAreaByAddress(AddressSpace
,
124 if (MemoryArea
== NULL
|| MemoryArea
->DeleteInProgress
)
126 MmUnlockAddressSpace(AddressSpace
);
129 MmUnlockAddressSpace(AddressSpace
);
135 MmAccessFault(KPROCESSOR_MODE Mode
,
139 PMADDRESS_SPACE AddressSpace
;
140 MEMORY_AREA
* MemoryArea
;
142 BOOLEAN Locked
= FromMdl
;
144 DPRINT("MmAccessFault(Mode %d, Address %x)\n", Mode
, Address
);
146 if (KeGetCurrentIrql() >= DISPATCH_LEVEL
)
148 CPRINT("Page fault at high IRQL was %d\n", KeGetCurrentIrql());
149 return(STATUS_UNSUCCESSFUL
);
151 if (PsGetCurrentProcess() == NULL
)
153 CPRINT("No current process\n");
154 return(STATUS_UNSUCCESSFUL
);
158 * Find the memory area for the faulting address
160 if (Address
>= (ULONG_PTR
)MmSystemRangeStart
)
165 if (Mode
!= KernelMode
)
167 DbgPrint("%s:%d\n",__FILE__
,__LINE__
);
168 return(STATUS_UNSUCCESSFUL
);
170 AddressSpace
= MmGetKernelAddressSpace();
174 AddressSpace
= &PsGetCurrentProcess()->AddressSpace
;
179 MmLockAddressSpace(AddressSpace
);
183 MemoryArea
= MmLocateMemoryAreaByAddress(AddressSpace
, (PVOID
)Address
);
184 if (MemoryArea
== NULL
|| MemoryArea
->DeleteInProgress
)
188 MmUnlockAddressSpace(AddressSpace
);
190 return (STATUS_UNSUCCESSFUL
);
193 switch (MemoryArea
->Type
)
195 case MEMORY_AREA_SYSTEM
:
196 Status
= STATUS_UNSUCCESSFUL
;
199 case MEMORY_AREA_PAGED_POOL
:
200 Status
= STATUS_SUCCESS
;
203 case MEMORY_AREA_SECTION_VIEW
:
204 Status
= MmAccessFaultSectionView(AddressSpace
,
210 case MEMORY_AREA_VIRTUAL_MEMORY
:
211 Status
= STATUS_UNSUCCESSFUL
;
214 case MEMORY_AREA_SHARED_DATA
:
215 Status
= STATUS_UNSUCCESSFUL
;
219 Status
= STATUS_UNSUCCESSFUL
;
223 while (Status
== STATUS_MM_RESTART_OPERATION
);
225 DPRINT("Completed page fault handling\n");
228 MmUnlockAddressSpace(AddressSpace
);
235 MmCommitPagedPoolAddress(PVOID Address
, BOOLEAN Locked
)
238 PFN_TYPE AllocatedPage
;
239 Status
= MmRequestPageMemoryConsumer(MC_PPOOL
, FALSE
, &AllocatedPage
);
240 if (!NT_SUCCESS(Status
))
242 MmUnlockAddressSpace(MmGetKernelAddressSpace());
243 Status
= MmRequestPageMemoryConsumer(MC_PPOOL
, TRUE
, &AllocatedPage
);
244 MmLockAddressSpace(MmGetKernelAddressSpace());
247 MmCreateVirtualMapping(NULL
,
248 (PVOID
)PAGE_ROUND_DOWN(Address
),
254 MmLockPage(AllocatedPage
);
261 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
);