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 ULONG MmUserProbeAddress
= 0;
19 PVOID MmHighestUserAddress
= NULL
;
20 PBOOLEAN Mm64BitPhysicalAddress
= FALSE
;
21 PVOID MmSystemRangeStart
= NULL
;
22 ULONG MmReadClusterSize
;
26 /* FUNCTIONS ****************************************************************/
31 BOOLEAN STDCALL
MmIsNonPagedSystemAddressValid(PVOID VirtualAddress
)
33 return MmIsAddressValid(VirtualAddress
);
39 BOOLEAN STDCALL
MmIsAddressValid(PVOID VirtualAddress
)
41 * FUNCTION: Checks whether the given address is valid for a read or write
43 * VirtualAddress = address to check
44 * RETURNS: True if the access would be valid
45 * False if the access would cause a page fault
46 * NOTES: This function checks whether a byte access to the page would
47 * succeed. Is this realistic for RISC processors which don't
48 * allow byte granular access?
51 MEMORY_AREA
* MemoryArea
;
52 PMADDRESS_SPACE AddressSpace
;
54 if (VirtualAddress
>= MmSystemRangeStart
)
56 AddressSpace
= MmGetKernelAddressSpace();
60 AddressSpace
= (PMADDRESS_SPACE
)&(PsGetCurrentProcess())->VadRoot
;
63 MmLockAddressSpace(AddressSpace
);
64 MemoryArea
= MmLocateMemoryAreaByAddress(AddressSpace
,
67 if (MemoryArea
== NULL
|| MemoryArea
->DeleteInProgress
)
69 MmUnlockAddressSpace(AddressSpace
);
72 MmUnlockAddressSpace(AddressSpace
);
78 MmpAccessFault(KPROCESSOR_MODE Mode
,
82 PMADDRESS_SPACE AddressSpace
;
83 MEMORY_AREA
* MemoryArea
;
85 BOOLEAN Locked
= FromMdl
;
87 DPRINT("MmAccessFault(Mode %d, Address %x)\n", Mode
, Address
);
89 if (KeGetCurrentIrql() >= DISPATCH_LEVEL
)
91 CPRINT("Page fault at high IRQL was %d\n", KeGetCurrentIrql());
92 return(STATUS_UNSUCCESSFUL
);
94 if (PsGetCurrentProcess() == NULL
)
96 DPRINT("No current process\n");
97 return(STATUS_UNSUCCESSFUL
);
101 * Find the memory area for the faulting address
103 if (Address
>= (ULONG_PTR
)MmSystemRangeStart
)
108 if (Mode
!= KernelMode
)
110 DPRINT1("MmAccessFault(Mode %d, Address %x)\n", Mode
, Address
);
111 DbgPrint("%s:%d\n",__FILE__
,__LINE__
);
112 return(STATUS_ACCESS_VIOLATION
);
114 AddressSpace
= MmGetKernelAddressSpace();
118 AddressSpace
= (PMADDRESS_SPACE
)&(PsGetCurrentProcess())->VadRoot
;
123 MmLockAddressSpace(AddressSpace
);
127 MemoryArea
= MmLocateMemoryAreaByAddress(AddressSpace
, (PVOID
)Address
);
128 if (MemoryArea
== NULL
|| MemoryArea
->DeleteInProgress
)
132 MmUnlockAddressSpace(AddressSpace
);
134 return (STATUS_ACCESS_VIOLATION
);
137 switch (MemoryArea
->Type
)
139 case MEMORY_AREA_SYSTEM
:
140 Status
= STATUS_ACCESS_VIOLATION
;
143 case MEMORY_AREA_PAGED_POOL
:
144 Status
= STATUS_SUCCESS
;
147 case MEMORY_AREA_SECTION_VIEW
:
148 Status
= MmAccessFaultSectionView(AddressSpace
,
154 case MEMORY_AREA_VIRTUAL_MEMORY
:
155 Status
= STATUS_ACCESS_VIOLATION
;
158 case MEMORY_AREA_SHARED_DATA
:
159 Status
= STATUS_ACCESS_VIOLATION
;
163 Status
= STATUS_ACCESS_VIOLATION
;
167 while (Status
== STATUS_MM_RESTART_OPERATION
);
169 DPRINT("Completed page fault handling\n");
172 MmUnlockAddressSpace(AddressSpace
);
179 MmNotPresentFault(KPROCESSOR_MODE Mode
,
183 PMADDRESS_SPACE AddressSpace
;
184 MEMORY_AREA
* MemoryArea
;
186 BOOLEAN Locked
= FromMdl
;
189 DPRINT("MmNotPresentFault(Mode %d, Address %x)\n", Mode
, Address
);
191 if (KeGetCurrentIrql() >= DISPATCH_LEVEL
)
193 CPRINT("Page fault at high IRQL was %d, address %x\n", KeGetCurrentIrql(), Address
);
194 return(STATUS_UNSUCCESSFUL
);
196 if (PsGetCurrentProcess() == NULL
)
198 /* Allow this! It lets us page alloc much earlier! It won't be needed
199 * after my init patch anyways
201 DPRINT("No current process\n");
202 if (Address
< (ULONG_PTR
)MmSystemRangeStart
)
204 return(STATUS_ACCESS_VIOLATION
);
209 * Find the memory area for the faulting address
211 if (Address
>= (ULONG_PTR
)MmSystemRangeStart
)
216 if (Mode
!= KernelMode
)
218 CPRINT("Address: %x\n", Address
);
219 return(STATUS_ACCESS_VIOLATION
);
221 AddressSpace
= MmGetKernelAddressSpace();
225 AddressSpace
= (PMADDRESS_SPACE
)&(PsGetCurrentProcess())->VadRoot
;
230 MmLockAddressSpace(AddressSpace
);
234 * Call the memory area specific fault handler
238 MemoryArea
= MmLocateMemoryAreaByAddress(AddressSpace
, (PVOID
)Address
);
239 if (MemoryArea
== NULL
|| MemoryArea
->DeleteInProgress
)
243 MmUnlockAddressSpace(AddressSpace
);
245 return (STATUS_ACCESS_VIOLATION
);
248 switch (MemoryArea
->Type
)
250 case MEMORY_AREA_PAGED_POOL
:
252 Status
= MmCommitPagedPoolAddress((PVOID
)Address
, Locked
);
256 case MEMORY_AREA_SYSTEM
:
257 Status
= STATUS_ACCESS_VIOLATION
;
260 case MEMORY_AREA_SECTION_VIEW
:
261 Status
= MmNotPresentFaultSectionView(AddressSpace
,
267 case MEMORY_AREA_VIRTUAL_MEMORY
:
268 case MEMORY_AREA_PEB_OR_TEB
:
269 Status
= MmNotPresentFaultVirtualMemory(AddressSpace
,
275 case MEMORY_AREA_SHARED_DATA
:
276 Pfn
= MmSharedDataPagePhysicalAddress
.QuadPart
>> PAGE_SHIFT
;
278 MmCreateVirtualMapping(PsGetCurrentProcess(),
279 (PVOID
)PAGE_ROUND_DOWN(Address
),
286 Status
= STATUS_ACCESS_VIOLATION
;
290 while (Status
== STATUS_MM_RESTART_OPERATION
);
292 DPRINT("Completed page fault handling\n");
295 MmUnlockAddressSpace(AddressSpace
);
300 extern BOOLEAN
Mmi386MakeKernelPageTableGlobal(PVOID Address
);
304 MmAccessFault(IN BOOLEAN StoreInstruction
,
306 IN KPROCESSOR_MODE Mode
,
307 IN PVOID TrapInformation
)
309 /* Cute little hack for ROS */
310 if ((ULONG_PTR
)Address
>= (ULONG_PTR
)MmSystemRangeStart
)
312 /* Check for an invalid page directory in kernel mode */
313 if (Mmi386MakeKernelPageTableGlobal(Address
))
315 /* All is well with the world */
316 return STATUS_SUCCESS
;
320 /* Keep same old ReactOS Behaviour */
321 if (StoreInstruction
)
323 /* Call access fault */
324 return MmpAccessFault(Mode
, (ULONG_PTR
)Address
, TrapInformation
? FALSE
: TRUE
);
328 /* Call not present */
329 return MmNotPresentFault(Mode
, (ULONG_PTR
)Address
, TrapInformation
? FALSE
: TRUE
);
335 MmCommitPagedPoolAddress(PVOID Address
, BOOLEAN Locked
)
338 PFN_TYPE AllocatedPage
;
339 Status
= MmRequestPageMemoryConsumer(MC_PPOOL
, FALSE
, &AllocatedPage
);
340 if (!NT_SUCCESS(Status
))
342 MmUnlockAddressSpace(MmGetKernelAddressSpace());
343 Status
= MmRequestPageMemoryConsumer(MC_PPOOL
, TRUE
, &AllocatedPage
);
344 MmLockAddressSpace(MmGetKernelAddressSpace());
347 MmCreateVirtualMapping(NULL
,
348 (PVOID
)PAGE_ROUND_DOWN(Address
),
354 MmLockPage(AllocatedPage
);
361 /* Miscellanea functions: they may fit somewhere else */
367 MmAdjustWorkingSetSize (ULONG Unknown0
,
378 MmDbgTranslatePhysicalAddress (
392 MmSetAddressRangeModified (
403 NtGetWriteWatch(IN HANDLE ProcessHandle
,
405 IN PVOID BaseAddress
,
407 IN PVOID
*UserAddressArray
,
408 OUT PULONG EntriesInUserAddressArray
,
409 OUT PULONG Granularity
)
412 return STATUS_NOT_IMPLEMENTED
;
417 NtResetWriteWatch(IN HANDLE ProcessHandle
,
418 IN PVOID BaseAddress
,
422 return STATUS_NOT_IMPLEMENTED
;