2 * COPYRIGHT: See COPYING in the top directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/mm/mmfault.c
5 * PURPOSE: Kernel memory managment functions
6 * PROGRAMMERS: David Welch (welch@cwcom.net)
9 /* INCLUDES *******************************************************************/
15 /* PRIVATE FUNCTIONS **********************************************************/
19 MiSyncForProcessAttach(IN PKTHREAD Thread
,
22 PETHREAD Ethread
= CONTAINING_RECORD(Thread
, ETHREAD
, Tcb
);
24 /* Hack Sync because Mm is broken */
25 MmUpdatePageDir(Process
, Ethread
, sizeof(ETHREAD
));
26 MmUpdatePageDir(Process
, Ethread
->ThreadsProcess
, sizeof(EPROCESS
));
27 MmUpdatePageDir(Process
,
28 (PVOID
)Thread
->StackLimit
,
30 KERNEL_LARGE_STACK_SIZE
: KERNEL_STACK_SIZE
);
35 MiSyncForContextSwitch(IN PKTHREAD Thread
)
37 PVOID Process
= PsGetCurrentProcess();
38 PETHREAD Ethread
= CONTAINING_RECORD(Thread
, ETHREAD
, Tcb
);
40 /* Hack Sync because Mm is broken */
41 MmUpdatePageDir(Process
, Ethread
->ThreadsProcess
, sizeof(EPROCESS
));
42 MmUpdatePageDir(Process
,
43 (PVOID
)Thread
->StackLimit
,
45 KERNEL_LARGE_STACK_SIZE
: KERNEL_STACK_SIZE
);
50 MmpAccessFault(KPROCESSOR_MODE Mode
,
54 PMMSUPPORT AddressSpace
;
55 MEMORY_AREA
* MemoryArea
;
57 BOOLEAN Locked
= FromMdl
;
59 DPRINT("MmAccessFault(Mode %d, Address %x)\n", Mode
, Address
);
61 if (KeGetCurrentIrql() >= DISPATCH_LEVEL
)
63 DPRINT1("Page fault at high IRQL was %d\n", KeGetCurrentIrql());
64 return(STATUS_UNSUCCESSFUL
);
68 * Find the memory area for the faulting address
70 if (Address
>= (ULONG_PTR
)MmSystemRangeStart
)
75 if (Mode
!= KernelMode
)
77 DPRINT1("MmAccessFault(Mode %d, Address %x)\n", Mode
, Address
);
78 return(STATUS_ACCESS_VIOLATION
);
80 AddressSpace
= MmGetKernelAddressSpace();
84 AddressSpace
= &PsGetCurrentProcess()->Vm
;
89 MmLockAddressSpace(AddressSpace
);
93 MemoryArea
= MmLocateMemoryAreaByAddress(AddressSpace
, (PVOID
)Address
);
94 if (MemoryArea
== NULL
|| MemoryArea
->DeleteInProgress
)
98 MmUnlockAddressSpace(AddressSpace
);
100 return (STATUS_ACCESS_VIOLATION
);
103 switch (MemoryArea
->Type
)
105 case MEMORY_AREA_SYSTEM
:
106 Status
= STATUS_ACCESS_VIOLATION
;
109 case MEMORY_AREA_PAGED_POOL
:
110 Status
= STATUS_SUCCESS
;
113 case MEMORY_AREA_SECTION_VIEW
:
114 Status
= MmAccessFaultSectionView(AddressSpace
,
120 case MEMORY_AREA_VIRTUAL_MEMORY
:
121 Status
= STATUS_ACCESS_VIOLATION
;
124 case MEMORY_AREA_SHARED_DATA
:
125 Status
= STATUS_ACCESS_VIOLATION
;
129 Status
= STATUS_ACCESS_VIOLATION
;
133 while (Status
== STATUS_MM_RESTART_OPERATION
);
135 DPRINT("Completed page fault handling\n");
138 MmUnlockAddressSpace(AddressSpace
);
145 MmNotPresentFault(KPROCESSOR_MODE Mode
,
149 PMMSUPPORT AddressSpace
;
150 MEMORY_AREA
* MemoryArea
;
152 BOOLEAN Locked
= FromMdl
;
153 extern PMMPTE MmSharedUserDataPte
;
155 DPRINT("MmNotPresentFault(Mode %d, Address %x)\n", Mode
, Address
);
157 if (KeGetCurrentIrql() >= DISPATCH_LEVEL
)
159 DPRINT1("Page fault at high IRQL was %d, address %x\n", KeGetCurrentIrql(), Address
);
160 return(STATUS_UNSUCCESSFUL
);
164 * Find the memory area for the faulting address
166 if (Address
>= (ULONG_PTR
)MmSystemRangeStart
)
171 if (Mode
!= KernelMode
)
173 DPRINT1("Address: %x\n", Address
);
174 return(STATUS_ACCESS_VIOLATION
);
176 AddressSpace
= MmGetKernelAddressSpace();
180 AddressSpace
= &PsGetCurrentProcess()->Vm
;
185 MmLockAddressSpace(AddressSpace
);
189 * Call the memory area specific fault handler
193 MemoryArea
= MmLocateMemoryAreaByAddress(AddressSpace
, (PVOID
)Address
);
194 if (MemoryArea
== NULL
|| MemoryArea
->DeleteInProgress
)
198 MmUnlockAddressSpace(AddressSpace
);
200 return (STATUS_ACCESS_VIOLATION
);
203 switch (MemoryArea
->Type
)
205 case MEMORY_AREA_PAGED_POOL
:
207 Status
= MmCommitPagedPoolAddress((PVOID
)Address
, Locked
);
211 case MEMORY_AREA_SYSTEM
:
212 Status
= STATUS_ACCESS_VIOLATION
;
215 case MEMORY_AREA_SECTION_VIEW
:
216 Status
= MmNotPresentFaultSectionView(AddressSpace
,
222 case MEMORY_AREA_VIRTUAL_MEMORY
:
223 case MEMORY_AREA_PEB_OR_TEB
:
224 Status
= MmNotPresentFaultVirtualMemory(AddressSpace
,
230 case MEMORY_AREA_SHARED_DATA
:
231 *MiAddressToPte(USER_SHARED_DATA
) = *MmSharedUserDataPte
;
232 Status
= STATUS_SUCCESS
;
236 Status
= STATUS_ACCESS_VIOLATION
;
240 while (Status
== STATUS_MM_RESTART_OPERATION
);
242 DPRINT("Completed page fault handling\n");
245 MmUnlockAddressSpace(AddressSpace
);
250 extern BOOLEAN
Mmi386MakeKernelPageTableGlobal(PVOID Address
);
254 MmAccessFault(IN BOOLEAN StoreInstruction
,
256 IN KPROCESSOR_MODE Mode
,
257 IN PVOID TrapInformation
)
259 /* Cute little hack for ROS */
260 if ((ULONG_PTR
)Address
>= (ULONG_PTR
)MmSystemRangeStart
)
263 /* Check for an invalid page directory in kernel mode */
264 if (Mmi386MakeKernelPageTableGlobal(Address
))
266 /* All is well with the world */
267 return STATUS_SUCCESS
;
272 /* Keep same old ReactOS Behaviour */
273 if (StoreInstruction
)
275 /* Call access fault */
276 return MmpAccessFault(Mode
, (ULONG_PTR
)Address
, TrapInformation
? FALSE
: TRUE
);
280 /* Call not present */
281 return MmNotPresentFault(Mode
, (ULONG_PTR
)Address
, TrapInformation
? FALSE
: TRUE
);
287 MmCommitPagedPoolAddress(PVOID Address
, BOOLEAN Locked
)
290 PFN_TYPE AllocatedPage
;
291 Status
= MmRequestPageMemoryConsumer(MC_PPOOL
, FALSE
, &AllocatedPage
);
292 if (!NT_SUCCESS(Status
))
294 MmUnlockAddressSpace(MmGetKernelAddressSpace());
295 Status
= MmRequestPageMemoryConsumer(MC_PPOOL
, TRUE
, &AllocatedPage
);
296 MmLockAddressSpace(MmGetKernelAddressSpace());
299 MmCreateVirtualMapping(NULL
,
300 (PVOID
)PAGE_ROUND_DOWN(Address
),
306 MmLockPage(AllocatedPage
);
311 /* PUBLIC FUNCTIONS ***********************************************************/
318 MmIsAddressValid(IN PVOID VirtualAddress
)
320 MEMORY_AREA
* MemoryArea
;
321 PMMSUPPORT AddressSpace
;
323 DPRINT1("WARNING: %s returns bogus result\n", __FUNCTION__
);
325 if (VirtualAddress
>= MmSystemRangeStart
)
327 AddressSpace
= MmGetKernelAddressSpace();
331 AddressSpace
= &PsGetCurrentProcess()->Vm
;
334 MmLockAddressSpace(AddressSpace
);
335 MemoryArea
= MmLocateMemoryAreaByAddress(AddressSpace
,
338 if (MemoryArea
== NULL
|| MemoryArea
->DeleteInProgress
)
340 MmUnlockAddressSpace(AddressSpace
);
343 MmUnlockAddressSpace(AddressSpace
);