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 !FromMdl); 82 break; 83 #ifdef NEWCC 84 case MEMORY_AREA_CACHE: 85 // This code locks for itself to keep from having to break a lock 86 // passed in. 87 if (!FromMdl) 88 MmUnlockAddressSpace(AddressSpace); 89 Status = MmAccessFaultCacheSection(Mode, Address, FromMdl); 90 if (!FromMdl) 91 MmLockAddressSpace(AddressSpace); 92 break; 93 #endif 94 default: 95 Status = STATUS_ACCESS_VIOLATION; 96 break; 97 } 98 } 99 while (Status == STATUS_MM_RESTART_OPERATION); 100 101 DPRINT("Completed page fault handling\n"); 102 if (!FromMdl) 103 { 104 MmUnlockAddressSpace(AddressSpace); 105 } 106 return(Status); 107 } 108 109 NTSTATUS 110 NTAPI 111 MmNotPresentFault(KPROCESSOR_MODE Mode, 112 ULONG_PTR Address, 113 BOOLEAN FromMdl) 114 { 115 PMMSUPPORT AddressSpace; 116 MEMORY_AREA* MemoryArea; 117 NTSTATUS Status; 118 119 DPRINT("MmNotPresentFault(Mode %d, Address %x)\n", Mode, Address); 120 121 if (KeGetCurrentIrql() >= DISPATCH_LEVEL) 122 { 123 DPRINT1("Page fault at high IRQL was %u, address %x\n", KeGetCurrentIrql(), Address); 124 return(STATUS_UNSUCCESSFUL); 125 } 126 127 /* 128 * Find the memory area for the faulting address 129 */ 130 if (Address >= (ULONG_PTR)MmSystemRangeStart) 131 { 132 /* 133 * Check permissions 134 */ 135 if (Mode != KernelMode) 136 { 137 DPRINT1("Address: %x\n", Address); 138 return(STATUS_ACCESS_VIOLATION); 139 } 140 AddressSpace = MmGetKernelAddressSpace(); 141 } 142 else 143 { 144 AddressSpace = &PsGetCurrentProcess()->Vm; 145 } 146 147 if (!FromMdl) 148 { 149 MmLockAddressSpace(AddressSpace); 150 } 151 152 /* 153 * Call the memory area specific fault handler 154 */ 155 do 156 { 157 MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, (PVOID)Address); 158 if (MemoryArea == NULL || MemoryArea->DeleteInProgress) 159 { 160 if (!FromMdl) 161 { 162 MmUnlockAddressSpace(AddressSpace); 163 } 164 return (STATUS_ACCESS_VIOLATION); 165 } 166 167 switch (MemoryArea->Type) 168 { 169 case MEMORY_AREA_SECTION_VIEW: 170 Status = MmNotPresentFaultSectionView(AddressSpace, 171 MemoryArea, 172 (PVOID)Address, 173 !FromMdl); 174 break; 175 #ifdef NEWCC 176 case MEMORY_AREA_CACHE: 177 // This code locks for itself to keep from having to break a lock 178 // passed in. 179 if (!FromMdl) 180 MmUnlockAddressSpace(AddressSpace); 181 Status = MmNotPresentFaultCacheSection(Mode, Address, FromMdl); 182 if (!FromMdl) 183 MmLockAddressSpace(AddressSpace); 184 break; 185 #endif 186 default: 187 Status = STATUS_ACCESS_VIOLATION; 188 break; 189 } 190 } 191 while (Status == STATUS_MM_RESTART_OPERATION); 192 193 DPRINT("Completed page fault handling\n"); 194 if (!FromMdl) 195 { 196 MmUnlockAddressSpace(AddressSpace); 197 } 198 return(Status); 199 } 200 201 extern BOOLEAN Mmi386MakeKernelPageTableGlobal(PVOID Address); 202 203 NTSTATUS 204 NTAPI 205 MmAccessFault(IN ULONG FaultCode, 206 IN PVOID Address, 207 IN KPROCESSOR_MODE Mode, 208 IN PVOID TrapInformation) 209 { 210 PMEMORY_AREA MemoryArea = NULL; 211 212 /* Cute little hack for ROS */ 213 if ((ULONG_PTR)Address >= (ULONG_PTR)MmSystemRangeStart) 214 { 215 #ifdef _M_IX86 216 /* Check for an invalid page directory in kernel mode */ 217 if (Mmi386MakeKernelPageTableGlobal(Address)) 218 { 219 /* All is well with the world */ 220 return STATUS_SUCCESS; 221 } 222 #endif 223 } 224 225 /* Handle shared user page, which doesn't have a VAD / MemoryArea */ 226 if (PAGE_ALIGN(Address) == (PVOID)MM_SHARED_USER_DATA_VA) 227 { 228 /* This is an ARM3 fault */ 229 DPRINT("ARM3 fault %p\n", MemoryArea); 230 return MmArmAccessFault(FaultCode, Address, Mode, TrapInformation); 231 } 232 233 /* Is there a ReactOS address space yet? */ 234 if (MmGetKernelAddressSpace()) 235 { 236 /* Check if this is an ARM3 memory area */ 237 MemoryArea = MmLocateMemoryAreaByAddress(MmGetKernelAddressSpace(), Address); 238 if (!(MemoryArea) && (Address <= MM_HIGHEST_USER_ADDRESS)) 239 { 240 /* Could this be a VAD fault from user-mode? */ 241 MemoryArea = MmLocateMemoryAreaByAddress(MmGetCurrentAddressSpace(), Address); 242 } 243 } 244 245 /* Is this an ARM3 memory area, or is there no address space yet? */ 246 if (((MemoryArea) && (MemoryArea->Type == MEMORY_AREA_OWNED_BY_ARM3)) || 247 (!(MemoryArea) && ((ULONG_PTR)Address >= (ULONG_PTR)MmPagedPoolStart)) || 248 (!MmGetKernelAddressSpace())) 249 { 250 /* This is an ARM3 fault */ 251 DPRINT("ARM3 fault %p\n", MemoryArea); 252 return MmArmAccessFault(FaultCode, Address, Mode, TrapInformation); 253 } 254 255 /* Keep same old ReactOS Behaviour */ 256 if (!MI_IS_NOT_PRESENT_FAULT(FaultCode)) 257 { 258 /* Call access fault */ 259 return MmpAccessFault(Mode, (ULONG_PTR)Address, TrapInformation ? FALSE : TRUE); 260 } 261 else 262 { 263 /* Call not present */ 264 return MmNotPresentFault(Mode, (ULONG_PTR)Address, TrapInformation ? FALSE : TRUE); 265 } 266 } 267 268