2 * COPYRIGHT: See COPYING in the top directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/mm/mm.c
5 * PURPOSE: Kernel memory managment functions
6 * PROGRAMMERS: David Welch (welch@cwcom.net)
9 /* INCLUDES *****************************************************************/
15 /* GLOBALS *****************************************************************/
17 ULONG_PTR MmUserProbeAddress
= 0;
18 PVOID MmHighestUserAddress
= NULL
;
19 PBOOLEAN Mm64BitPhysicalAddress
= FALSE
;
20 PVOID MmSystemRangeStart
= NULL
;
21 ULONG MmReadClusterSize
;
25 /* FUNCTIONS ****************************************************************/
29 MiSyncForProcessAttach(IN PKTHREAD Thread
,
32 PETHREAD Ethread
= CONTAINING_RECORD(Thread
, ETHREAD
, Tcb
);
34 /* Hack Sync because Mm is broken */
35 MmUpdatePageDir(Process
, Ethread
->ThreadsProcess
, sizeof(EPROCESS
));
36 MmUpdatePageDir(Process
,
37 (PVOID
)Thread
->StackLimit
,
39 KERNEL_LARGE_STACK_SIZE
: KERNEL_STACK_SIZE
);
44 MiSyncForContextSwitch(IN PKTHREAD Thread
)
46 PVOID Process
= PsGetCurrentProcess();
47 PETHREAD Ethread
= CONTAINING_RECORD(Thread
, ETHREAD
, Tcb
);
49 /* Hack Sync because Mm is broken */
50 MmUpdatePageDir(Process
, Ethread
->ThreadsProcess
, sizeof(EPROCESS
));
51 MmUpdatePageDir(Process
,
52 (PVOID
)Thread
->StackLimit
,
54 KERNEL_LARGE_STACK_SIZE
: KERNEL_STACK_SIZE
);
60 BOOLEAN NTAPI
MmIsNonPagedSystemAddressValid(PVOID VirtualAddress
)
62 return MmIsAddressValid(VirtualAddress
);
68 BOOLEAN NTAPI
MmIsAddressValid(PVOID VirtualAddress
)
70 * FUNCTION: Checks whether the given address is valid for a read or write
72 * VirtualAddress = address to check
73 * RETURNS: True if the access would be valid
74 * False if the access would cause a page fault
75 * NOTES: This function checks whether a byte access to the page would
76 * succeed. Is this realistic for RISC processors which don't
77 * allow byte granular access?
80 MEMORY_AREA
* MemoryArea
;
81 PMM_AVL_TABLE AddressSpace
;
83 if (VirtualAddress
>= MmSystemRangeStart
)
85 AddressSpace
= MmGetKernelAddressSpace();
89 AddressSpace
= &PsGetCurrentProcess()->VadRoot
;
92 MmLockAddressSpace(AddressSpace
);
93 MemoryArea
= MmLocateMemoryAreaByAddress(AddressSpace
,
96 if (MemoryArea
== NULL
|| MemoryArea
->DeleteInProgress
)
98 MmUnlockAddressSpace(AddressSpace
);
101 MmUnlockAddressSpace(AddressSpace
);
107 MmpAccessFault(KPROCESSOR_MODE Mode
,
111 PMM_AVL_TABLE AddressSpace
;
112 MEMORY_AREA
* MemoryArea
;
114 BOOLEAN Locked
= FromMdl
;
116 DPRINT("MmAccessFault(Mode %d, Address %x)\n", Mode
, Address
);
118 if (KeGetCurrentIrql() >= DISPATCH_LEVEL
)
120 DPRINT1("Page fault at high IRQL was %d\n", KeGetCurrentIrql());
121 return(STATUS_UNSUCCESSFUL
);
123 if (PsGetCurrentProcess() == NULL
)
125 DPRINT("No current process\n");
126 return(STATUS_UNSUCCESSFUL
);
130 * Find the memory area for the faulting address
132 if (Address
>= (ULONG_PTR
)MmSystemRangeStart
)
137 if (Mode
!= KernelMode
)
139 DPRINT1("MmAccessFault(Mode %d, Address %x)\n", Mode
, Address
);
140 DbgPrint("%s:%d\n",__FILE__
,__LINE__
);
141 return(STATUS_ACCESS_VIOLATION
);
143 AddressSpace
= MmGetKernelAddressSpace();
147 AddressSpace
= &PsGetCurrentProcess()->VadRoot
;
152 MmLockAddressSpace(AddressSpace
);
156 MemoryArea
= MmLocateMemoryAreaByAddress(AddressSpace
, (PVOID
)Address
);
157 if (MemoryArea
== NULL
|| MemoryArea
->DeleteInProgress
)
161 MmUnlockAddressSpace(AddressSpace
);
163 return (STATUS_ACCESS_VIOLATION
);
166 switch (MemoryArea
->Type
)
168 case MEMORY_AREA_SYSTEM
:
169 Status
= STATUS_ACCESS_VIOLATION
;
172 case MEMORY_AREA_PAGED_POOL
:
173 Status
= STATUS_SUCCESS
;
176 case MEMORY_AREA_SECTION_VIEW
:
177 Status
= MmAccessFaultSectionView(AddressSpace
,
183 case MEMORY_AREA_VIRTUAL_MEMORY
:
184 Status
= STATUS_ACCESS_VIOLATION
;
187 case MEMORY_AREA_SHARED_DATA
:
188 Status
= STATUS_ACCESS_VIOLATION
;
192 Status
= STATUS_ACCESS_VIOLATION
;
196 while (Status
== STATUS_MM_RESTART_OPERATION
);
198 DPRINT("Completed page fault handling\n");
201 MmUnlockAddressSpace(AddressSpace
);
208 MmNotPresentFault(KPROCESSOR_MODE Mode
,
212 PMM_AVL_TABLE AddressSpace
;
213 MEMORY_AREA
* MemoryArea
;
215 BOOLEAN Locked
= FromMdl
;
218 DPRINT("MmNotPresentFault(Mode %d, Address %x)\n", Mode
, Address
);
220 if (KeGetCurrentIrql() >= DISPATCH_LEVEL
)
222 DPRINT1("Page fault at high IRQL was %d, address %x\n", KeGetCurrentIrql(), Address
);
223 return(STATUS_UNSUCCESSFUL
);
227 * Find the memory area for the faulting address
229 if (Address
>= (ULONG_PTR
)MmSystemRangeStart
)
234 if (Mode
!= KernelMode
)
236 DPRINT1("Address: %x\n", Address
);
237 return(STATUS_ACCESS_VIOLATION
);
239 AddressSpace
= MmGetKernelAddressSpace();
243 AddressSpace
= &PsGetCurrentProcess()->VadRoot
;
248 MmLockAddressSpace(AddressSpace
);
252 * Call the memory area specific fault handler
256 MemoryArea
= MmLocateMemoryAreaByAddress(AddressSpace
, (PVOID
)Address
);
257 if (MemoryArea
== NULL
|| MemoryArea
->DeleteInProgress
)
261 MmUnlockAddressSpace(AddressSpace
);
263 return (STATUS_ACCESS_VIOLATION
);
266 switch (MemoryArea
->Type
)
268 case MEMORY_AREA_PAGED_POOL
:
270 Status
= MmCommitPagedPoolAddress((PVOID
)Address
, Locked
);
274 case MEMORY_AREA_SYSTEM
:
275 Status
= STATUS_ACCESS_VIOLATION
;
278 case MEMORY_AREA_SECTION_VIEW
:
279 Status
= MmNotPresentFaultSectionView(AddressSpace
,
285 case MEMORY_AREA_VIRTUAL_MEMORY
:
286 case MEMORY_AREA_PEB_OR_TEB
:
287 Status
= MmNotPresentFaultVirtualMemory(AddressSpace
,
293 case MEMORY_AREA_SHARED_DATA
:
294 Pfn
= MmSharedDataPagePhysicalAddress
.LowPart
>> PAGE_SHIFT
;
296 MmCreateVirtualMapping(PsGetCurrentProcess(),
297 (PVOID
)PAGE_ROUND_DOWN(Address
),
304 Status
= STATUS_ACCESS_VIOLATION
;
308 while (Status
== STATUS_MM_RESTART_OPERATION
);
310 DPRINT("Completed page fault handling\n");
313 MmUnlockAddressSpace(AddressSpace
);
318 extern BOOLEAN
Mmi386MakeKernelPageTableGlobal(PVOID Address
);
322 MmAccessFault(IN BOOLEAN StoreInstruction
,
324 IN KPROCESSOR_MODE Mode
,
325 IN PVOID TrapInformation
)
327 /* Cute little hack for ROS */
328 if ((ULONG_PTR
)Address
>= (ULONG_PTR
)MmSystemRangeStart
)
331 /* Check for an invalid page directory in kernel mode */
332 if (Mmi386MakeKernelPageTableGlobal(Address
))
334 /* All is well with the world */
335 return STATUS_SUCCESS
;
340 /* Keep same old ReactOS Behaviour */
341 if (StoreInstruction
)
343 /* Call access fault */
344 return MmpAccessFault(Mode
, (ULONG_PTR
)Address
, TrapInformation
? FALSE
: TRUE
);
348 /* Call not present */
349 return MmNotPresentFault(Mode
, (ULONG_PTR
)Address
, TrapInformation
? FALSE
: TRUE
);
355 MmCommitPagedPoolAddress(PVOID Address
, BOOLEAN Locked
)
358 PFN_TYPE AllocatedPage
;
359 Status
= MmRequestPageMemoryConsumer(MC_PPOOL
, FALSE
, &AllocatedPage
);
360 if (!NT_SUCCESS(Status
))
362 MmUnlockAddressSpace(MmGetKernelAddressSpace());
363 Status
= MmRequestPageMemoryConsumer(MC_PPOOL
, TRUE
, &AllocatedPage
);
364 MmLockAddressSpace(MmGetKernelAddressSpace());
367 MmCreateVirtualMapping(NULL
,
368 (PVOID
)PAGE_ROUND_DOWN(Address
),
374 MmLockPage(AllocatedPage
);
381 /* Miscellanea functions: they may fit somewhere else */
388 MmIsRecursiveIoFault (VOID
)
390 PETHREAD Thread
= PsGetCurrentThread();
392 return (Thread
->DisablePageFaultClustering
| Thread
->ForwardClusterOnly
);
400 MmMapUserAddressesToPage(IN PVOID BaseAddress
,
401 IN SIZE_T NumberOfBytes
,
402 IN PVOID PageAddress
)
405 return STATUS_NOT_IMPLEMENTED
;
412 MmAdjustWorkingSetSize (ULONG Unknown0
,
426 MmSetAddressRangeModified (
437 NtGetWriteWatch(IN HANDLE ProcessHandle
,
439 IN PVOID BaseAddress
,
441 IN PVOID
*UserAddressArray
,
442 OUT PULONG EntriesInUserAddressArray
,
443 OUT PULONG Granularity
)
446 return STATUS_NOT_IMPLEMENTED
;
451 NtResetWriteWatch(IN HANDLE ProcessHandle
,
452 IN PVOID BaseAddress
,
453 IN SIZE_T RegionSize
)
456 return STATUS_NOT_IMPLEMENTED
;