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 PMM_AVL_TABLE MmKernelAddressSpace
;
27 /* FUNCTIONS ****************************************************************/
31 MiSyncForProcessAttach(IN PKTHREAD Thread
,
34 PETHREAD Ethread
= CONTAINING_RECORD(Thread
, ETHREAD
, Tcb
);
36 /* Hack Sync because Mm is broken */
37 MmUpdatePageDir(Process
, Ethread
->ThreadsProcess
, sizeof(EPROCESS
));
38 MmUpdatePageDir(Process
,
39 (PVOID
)Thread
->StackLimit
,
41 KERNEL_LARGE_STACK_SIZE
: KERNEL_STACK_SIZE
);
46 MiSyncForContextSwitch(IN PKTHREAD Thread
)
48 PVOID Process
= PsGetCurrentProcess();
49 PETHREAD Ethread
= CONTAINING_RECORD(Thread
, ETHREAD
, Tcb
);
51 /* Hack Sync because Mm is broken */
52 MmUpdatePageDir(Process
, Ethread
->ThreadsProcess
, sizeof(EPROCESS
));
53 MmUpdatePageDir(Process
,
54 (PVOID
)Thread
->StackLimit
,
56 KERNEL_LARGE_STACK_SIZE
: KERNEL_STACK_SIZE
);
62 BOOLEAN NTAPI
MmIsNonPagedSystemAddressValid(PVOID VirtualAddress
)
64 return MmIsAddressValid(VirtualAddress
);
70 BOOLEAN NTAPI
MmIsAddressValid(PVOID VirtualAddress
)
72 * FUNCTION: Checks whether the given address is valid for a read or write
74 * VirtualAddress = address to check
75 * RETURNS: True if the access would be valid
76 * False if the access would cause a page fault
77 * NOTES: This function checks whether a byte access to the page would
78 * succeed. Is this realistic for RISC processors which don't
79 * allow byte granular access?
82 MEMORY_AREA
* MemoryArea
;
83 PMM_AVL_TABLE AddressSpace
;
85 if (VirtualAddress
>= MmSystemRangeStart
)
87 AddressSpace
= MmGetKernelAddressSpace();
91 AddressSpace
= &PsGetCurrentProcess()->VadRoot
;
94 MmLockAddressSpace(AddressSpace
);
95 MemoryArea
= MmLocateMemoryAreaByAddress(AddressSpace
,
98 if (MemoryArea
== NULL
|| MemoryArea
->DeleteInProgress
)
100 MmUnlockAddressSpace(AddressSpace
);
103 MmUnlockAddressSpace(AddressSpace
);
109 MmpAccessFault(KPROCESSOR_MODE Mode
,
113 PMM_AVL_TABLE AddressSpace
;
114 MEMORY_AREA
* MemoryArea
;
116 BOOLEAN Locked
= FromMdl
;
118 DPRINT("MmAccessFault(Mode %d, Address %x)\n", Mode
, Address
);
120 if (KeGetCurrentIrql() >= DISPATCH_LEVEL
)
122 DPRINT1("Page fault at high IRQL was %d\n", KeGetCurrentIrql());
123 return(STATUS_UNSUCCESSFUL
);
125 if (PsGetCurrentProcess() == NULL
)
127 DPRINT("No current process\n");
128 return(STATUS_UNSUCCESSFUL
);
132 * Find the memory area for the faulting address
134 if (Address
>= (ULONG_PTR
)MmSystemRangeStart
)
139 if (Mode
!= KernelMode
)
141 DPRINT1("MmAccessFault(Mode %d, Address %x)\n", Mode
, Address
);
142 return(STATUS_ACCESS_VIOLATION
);
144 AddressSpace
= MmGetKernelAddressSpace();
148 AddressSpace
= &PsGetCurrentProcess()->VadRoot
;
153 MmLockAddressSpace(AddressSpace
);
157 MemoryArea
= MmLocateMemoryAreaByAddress(AddressSpace
, (PVOID
)Address
);
158 if (MemoryArea
== NULL
|| MemoryArea
->DeleteInProgress
)
162 MmUnlockAddressSpace(AddressSpace
);
164 return (STATUS_ACCESS_VIOLATION
);
167 switch (MemoryArea
->Type
)
169 case MEMORY_AREA_SYSTEM
:
170 Status
= STATUS_ACCESS_VIOLATION
;
173 case MEMORY_AREA_PAGED_POOL
:
174 Status
= STATUS_SUCCESS
;
177 case MEMORY_AREA_SECTION_VIEW
:
178 Status
= MmAccessFaultSectionView(AddressSpace
,
184 case MEMORY_AREA_VIRTUAL_MEMORY
:
185 Status
= STATUS_ACCESS_VIOLATION
;
188 case MEMORY_AREA_SHARED_DATA
:
189 Status
= STATUS_ACCESS_VIOLATION
;
193 Status
= STATUS_ACCESS_VIOLATION
;
197 while (Status
== STATUS_MM_RESTART_OPERATION
);
199 DPRINT("Completed page fault handling\n");
202 MmUnlockAddressSpace(AddressSpace
);
209 MmNotPresentFault(KPROCESSOR_MODE Mode
,
213 PMM_AVL_TABLE AddressSpace
;
214 MEMORY_AREA
* MemoryArea
;
216 BOOLEAN Locked
= FromMdl
;
219 DPRINT("MmNotPresentFault(Mode %d, Address %x)\n", Mode
, Address
);
221 if (KeGetCurrentIrql() >= DISPATCH_LEVEL
)
223 DPRINT1("Page fault at high IRQL was %d, address %x\n", KeGetCurrentIrql(), Address
);
224 return(STATUS_UNSUCCESSFUL
);
228 * Find the memory area for the faulting address
230 if (Address
>= (ULONG_PTR
)MmSystemRangeStart
)
235 if (Mode
!= KernelMode
)
237 DPRINT1("Address: %x\n", Address
);
238 return(STATUS_ACCESS_VIOLATION
);
240 AddressSpace
= MmGetKernelAddressSpace();
244 AddressSpace
= &PsGetCurrentProcess()->VadRoot
;
249 MmLockAddressSpace(AddressSpace
);
253 * Call the memory area specific fault handler
257 MemoryArea
= MmLocateMemoryAreaByAddress(AddressSpace
, (PVOID
)Address
);
258 if (MemoryArea
== NULL
|| MemoryArea
->DeleteInProgress
)
262 MmUnlockAddressSpace(AddressSpace
);
264 return (STATUS_ACCESS_VIOLATION
);
267 switch (MemoryArea
->Type
)
269 case MEMORY_AREA_PAGED_POOL
:
271 Status
= MmCommitPagedPoolAddress((PVOID
)Address
, Locked
);
275 case MEMORY_AREA_SYSTEM
:
276 Status
= STATUS_ACCESS_VIOLATION
;
279 case MEMORY_AREA_SECTION_VIEW
:
280 Status
= MmNotPresentFaultSectionView(AddressSpace
,
286 case MEMORY_AREA_VIRTUAL_MEMORY
:
287 case MEMORY_AREA_PEB_OR_TEB
:
288 Status
= MmNotPresentFaultVirtualMemory(AddressSpace
,
294 case MEMORY_AREA_SHARED_DATA
:
295 Pfn
= MmSharedDataPagePhysicalAddress
.LowPart
>> PAGE_SHIFT
;
297 MmCreateVirtualMapping(PsGetCurrentProcess(),
298 (PVOID
)PAGE_ROUND_DOWN(Address
),
305 Status
= STATUS_ACCESS_VIOLATION
;
309 while (Status
== STATUS_MM_RESTART_OPERATION
);
311 DPRINT("Completed page fault handling\n");
314 MmUnlockAddressSpace(AddressSpace
);
319 extern BOOLEAN
Mmi386MakeKernelPageTableGlobal(PVOID Address
);
323 MmAccessFault(IN BOOLEAN StoreInstruction
,
325 IN KPROCESSOR_MODE Mode
,
326 IN PVOID TrapInformation
)
328 /* Cute little hack for ROS */
329 if ((ULONG_PTR
)Address
>= (ULONG_PTR
)MmSystemRangeStart
)
332 /* Check for an invalid page directory in kernel mode */
333 if (Mmi386MakeKernelPageTableGlobal(Address
))
335 /* All is well with the world */
336 return STATUS_SUCCESS
;
341 /* Keep same old ReactOS Behaviour */
342 if (StoreInstruction
)
344 /* Call access fault */
345 return MmpAccessFault(Mode
, (ULONG_PTR
)Address
, TrapInformation
? FALSE
: TRUE
);
349 /* Call not present */
350 return MmNotPresentFault(Mode
, (ULONG_PTR
)Address
, TrapInformation
? FALSE
: TRUE
);
356 MmCommitPagedPoolAddress(PVOID Address
, BOOLEAN Locked
)
359 PFN_TYPE AllocatedPage
;
360 Status
= MmRequestPageMemoryConsumer(MC_PPOOL
, FALSE
, &AllocatedPage
);
361 if (!NT_SUCCESS(Status
))
363 MmUnlockAddressSpace(MmGetKernelAddressSpace());
364 Status
= MmRequestPageMemoryConsumer(MC_PPOOL
, TRUE
, &AllocatedPage
);
365 MmLockAddressSpace(MmGetKernelAddressSpace());
368 MmCreateVirtualMapping(NULL
,
369 (PVOID
)PAGE_ROUND_DOWN(Address
),
375 MmLockPage(AllocatedPage
);
382 /* Miscellanea functions: they may fit somewhere else */
389 MmIsRecursiveIoFault (VOID
)
391 PETHREAD Thread
= PsGetCurrentThread();
393 return (Thread
->DisablePageFaultClustering
| Thread
->ForwardClusterOnly
);
401 MmMapUserAddressesToPage(IN PVOID BaseAddress
,
402 IN SIZE_T NumberOfBytes
,
403 IN PVOID PageAddress
)
406 return STATUS_NOT_IMPLEMENTED
;
413 MmAdjustWorkingSetSize (ULONG Unknown0
,
427 MmSetAddressRangeModified (
438 NtGetWriteWatch(IN HANDLE ProcessHandle
,
440 IN PVOID BaseAddress
,
441 IN SIZE_T RegionSize
,
442 IN PVOID
*UserAddressArray
,
443 OUT PULONG_PTR EntriesInUserAddressArray
,
444 OUT PULONG Granularity
)
447 return STATUS_NOT_IMPLEMENTED
;
452 NtResetWriteWatch(IN HANDLE ProcessHandle
,
453 IN PVOID BaseAddress
,
454 IN SIZE_T RegionSize
)
457 return STATUS_NOT_IMPLEMENTED
;