1 /* 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) 7 */ 8 9 /* INCLUDES *******************************************************************/ 10 11 #include <ntoskrnl.h> 12 #include <cache/section/newmm.h> 13 #define NDEBUG 14 #include <debug.h> 15 16 #define MODULE_INVOLVED_IN_ARM3 17 #include "ARM3/miarm.h" 18 19 /* PRIVATE FUNCTIONS **********************************************************/ 20 21 NTSTATUS 22 NTAPI 23 MmpAccessFault(KPROCESSOR_MODE Mode, 24 ULONG_PTR Address, 25 BOOLEAN FromMdl) 26 { 27 PMMSUPPORT AddressSpace; 28 MEMORY_AREA* MemoryArea; 29 NTSTATUS Status; 30 31 DPRINT("MmAccessFault(Mode %d, Address %x)\n", Mode, Address); 32 33 if (KeGetCurrentIrql() >= DISPATCH_LEVEL) 34 { 35 DPRINT1("Page fault at high IRQL was %u\n", KeGetCurrentIrql()); 36 return(STATUS_UNSUCCESSFUL); 37 } 38 39 /* 40 * Find the memory area for the faulting address 41 */ 42 if (Address >= (ULONG_PTR)MmSystemRangeStart) 43 { 44 /* 45 * Check permissions 46 */ 47 if (Mode != KernelMode) 48 { 49 DPRINT1("MmAccessFault(Mode %d, Address %x)\n", Mode, Address); 50 return(STATUS_ACCESS_VIOLATION); 51 } 52 AddressSpace = MmGetKernelAddressSpace(); 53 } 54 else 55 { 56 AddressSpace = &PsGetCurrentProcess()->Vm; 57 } 58 59 if (!FromMdl) 60 { 61 MmLockAddressSpace(AddressSpace); 62 } 63 do 64 { 65 MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, (PVOID)Address); 66 if (MemoryArea == NULL || MemoryArea->DeleteInProgress) 67 { 68 if (!FromMdl) 69 { 70 MmUnlockAddressSpace(AddressSpace); 71 } 72 return (STATUS_ACCESS_VIOLATION); 73 } 74 75 switch (MemoryArea->Type) 76 { 77 case MEMORY_AREA_SECTION_VIEW: 78 Status = MmAccessFaultSectionView(AddressSpace, 79 MemoryArea, 80 (PVOID)Address); 81 break; 82 #ifdef NEWCC 83 case MEMORY_AREA_CACHE: 84 // This code locks for itself to keep from having to break a lock 85 // passed in. 86 if (!FromMdl) 87 MmUnlockAddressSpace(AddressSpace); 88 Status = MmAccessFaultCacheSection(Mode, Address, FromMdl); 89 if (!FromMdl) 90 MmLockAddressSpace(AddressSpace); 91 break; 92 #endif 93 default: 94 Status = STATUS_ACCESS_VIOLATION; 95 break; 96 } 97 } 98 while (Status == STATUS_MM_RESTART_OPERATION); 99 100 DPRINT("Completed page fault handling\n"); 101 if (!FromMdl) 102 { 103 MmUnlockAddressSpace(AddressSpace); 104 } 105 return(Status); 106 } 107 108 NTSTATUS 109 NTAPI 110 MmNotPresentFault(KPROCESSOR_MODE Mode, 111 ULONG_PTR Address, 112 BOOLEAN FromMdl) 113 { 114 PMMSUPPORT AddressSpace; 115 MEMORY_AREA* MemoryArea; 116 NTSTATUS Status; 117 118 DPRINT("MmNotPresentFault(Mode %d, Address %x)\n", Mode, Address); 119 120 if (KeGetCurrentIrql() >= DISPATCH_LEVEL) 121 { 122 DPRINT1("Page fault at high IRQL was %u, address %x\n", KeGetCurrentIrql(), Address); 123 return(STATUS_UNSUCCESSFUL); 124 } 125 126 /* 127 * Find the memory area for the faulting address 128 */ 129 if (Address >= (ULONG_PTR)MmSystemRangeStart) 130 { 131 /* 132 * Check permissions 133 */ 134 if (Mode != KernelMode) 135 { 136 DPRINT1("Address: %x\n", Address); 137 return(STATUS_ACCESS_VIOLATION); 138 } 139 AddressSpace = MmGetKernelAddressSpace(); 140 } 141 else 142 { 143 AddressSpace = &PsGetCurrentProcess()->Vm; 144 } 145 146 if (!FromMdl) 147 { 148 MmLockAddressSpace(AddressSpace); 149 } 150 151 /* 152 * Call the memory area specific fault handler 153 */ 154 do 155 { 156 MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, (PVOID)Address); 157 if (MemoryArea == NULL || MemoryArea->DeleteInProgress) 158 { 159 if (!FromMdl) 160 { 161 MmUnlockAddressSpace(AddressSpace); 162 } 163 return (STATUS_ACCESS_VIOLATION); 164 } 165 166 switch (MemoryArea->Type) 167 { 168 case MEMORY_AREA_SECTION_VIEW: 169 Status = MmNotPresentFaultSectionView(AddressSpace, 170 MemoryArea, 171 (PVOID)Address, 172 FromMdl); 173 break; 174 #ifdef NEWCC 175 case MEMORY_AREA_CACHE: 176 // This code locks for itself to keep from having to break a lock 177 // passed in. 178 if (!FromMdl) 179 MmUnlockAddressSpace(AddressSpace); 180 Status = MmNotPresentFaultCacheSection(Mode, Address, FromMdl); 181 if (!FromMdl) 182 MmLockAddressSpace(AddressSpace); 183 break; 184 #endif 185 default: 186 Status = STATUS_ACCESS_VIOLATION; 187 break; 188 } 189 } 190 while (Status == STATUS_MM_RESTART_OPERATION); 191 192 DPRINT("Completed page fault handling\n"); 193 if (!FromMdl) 194 { 195 MmUnlockAddressSpace(AddressSpace); 196 } 197 return(Status); 198 } 199 200 extern BOOLEAN Mmi386MakeKernelPageTableGlobal(PVOID Address); 201 202 NTSTATUS 203 NTAPI 204 MmAccessFault(IN ULONG FaultCode, 205 IN PVOID Address, 206 IN KPROCESSOR_MODE Mode, 207 IN PVOID TrapInformation) 208 { 209 PMEMORY_AREA MemoryArea = NULL; 210 211 /* Cute little hack for ROS */ 212 if ((ULONG_PTR)Address >= (ULONG_PTR)MmSystemRangeStart) 213 { 214 #ifdef _M_IX86 215 /* Check for an invalid page directory in kernel mode */ 216 if (Mmi386MakeKernelPageTableGlobal(Address)) 217 { 218 /* All is well with the world */ 219 return STATUS_SUCCESS; 220 } 221 #endif 222 } 223 224 /* Handle shared user page, which doesn't have a VAD / MemoryArea */ 225 if (PAGE_ALIGN(Address) == (PVOID)MM_SHARED_USER_DATA_VA) 226 { 227 /* This is an ARM3 fault */ 228 DPRINT("ARM3 fault %p\n", MemoryArea); 229 return MmArmAccessFault(FaultCode, Address, Mode, TrapInformation); 230 } 231 232 /* Is there a ReactOS address space yet? */ 233 if (MmGetKernelAddressSpace()) 234 { 235 /* Check if this is an ARM3 memory area */ 236 MemoryArea = MmLocateMemoryAreaByAddress(MmGetKernelAddressSpace(), Address); 237 if (!(MemoryArea) && (Address <= MM_HIGHEST_USER_ADDRESS)) 238 { 239 /* Could this be a VAD fault from user-mode? */ 240 MemoryArea = MmLocateMemoryAreaByAddress(MmGetCurrentAddressSpace(), Address); 241 } 242 } 243 244 /* Is this an ARM3 memory area, or is there no address space yet? */ 245 if (((MemoryArea) && (MemoryArea->Type == MEMORY_AREA_OWNED_BY_ARM3)) || 246 (!(MemoryArea) && ((ULONG_PTR)Address >= (ULONG_PTR)MmPagedPoolStart)) || 247 (!MmGetKernelAddressSpace())) 248 { 249 /* This is an ARM3 fault */ 250 DPRINT("ARM3 fault %p\n", MemoryArea); 251 return MmArmAccessFault(FaultCode, Address, Mode, TrapInformation); 252 } 253 254 /* Keep same old ReactOS Behaviour */ 255 if (!MI_IS_NOT_PRESENT_FAULT(FaultCode)) 256 { 257 /* Call access fault */ 258 return MmpAccessFault(Mode, (ULONG_PTR)Address, TrapInformation ? FALSE : TRUE); 259 } 260 else 261 { 262 /* Call not present */ 263 return MmNotPresentFault(Mode, (ULONG_PTR)Address, TrapInformation ? FALSE : TRUE); 264 } 265 } 266 267