1 /* 2 * PROJECT: ReactOS Kernel 3 * LICENSE: BSD - See COPYING.ARM in the top level directory 4 * FILE: ntoskrnl/ke/arm/exp.c 5 * PURPOSE: Implements exception helper routines for ARM machines 6 * PROGRAMMERS: ReactOS Portable Systems Group 7 */ 8 9 /* INCLUDES *******************************************************************/ 10 11 #include <ntoskrnl.h> 12 #define NDEBUG 13 #include <debug.h> 14 15 /* FUNCTIONS ******************************************************************/ 16 17 VOID 18 NTAPI 19 KeContextToTrapFrame(IN PCONTEXT Context, 20 IN OUT PKEXCEPTION_FRAME ExceptionFrame, 21 IN OUT PKTRAP_FRAME TrapFrame, 22 IN ULONG ContextFlags, 23 IN KPROCESSOR_MODE PreviousMode) 24 { 25 KIRQL OldIrql; 26 27 // 28 // Do this at APC_LEVEL 29 // 30 OldIrql = KeGetCurrentIrql(); 31 if (OldIrql < APC_LEVEL) KeRaiseIrql(APC_LEVEL, &OldIrql); 32 33 // 34 // Start with the Control flags 35 // 36 if ((Context->ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL) 37 { 38 // 39 // So this basically means all the special stuff 40 // 41 42 // 43 // ARM has register banks 44 // 45 TrapFrame->Sp = Context->Sp; 46 TrapFrame->Lr = Context->Lr; 47 48 // 49 // The rest is already in the right mode 50 // 51 TrapFrame->Pc = Context->Pc; 52 TrapFrame->Cpsr = Context->Cpsr; 53 } 54 55 // 56 // Now do the integers 57 // 58 if ((Context->ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER) 59 { 60 // 61 // Basically everything else but FPU 62 // 63 TrapFrame->R0 = Context->R0; 64 TrapFrame->R1 = Context->R1; 65 TrapFrame->R2 = Context->R2; 66 TrapFrame->R3 = Context->R3; 67 ExceptionFrame->R4 = Context->R4; 68 ExceptionFrame->R5 = Context->R5; 69 ExceptionFrame->R6 = Context->R6; 70 ExceptionFrame->R7 = Context->R7; 71 ExceptionFrame->R8 = Context->R8; 72 ExceptionFrame->R9 = Context->R9; 73 ExceptionFrame->R10 = Context->R10; 74 ExceptionFrame->R11 = Context->R11; 75 TrapFrame->R12 = Context->R12; 76 } 77 78 // 79 // Restore IRQL 80 // 81 if (OldIrql < APC_LEVEL) KeLowerIrql(OldIrql); 82 } 83 84 VOID 85 NTAPI 86 KeTrapFrameToContext(IN PKTRAP_FRAME TrapFrame, 87 IN PKEXCEPTION_FRAME ExceptionFrame, 88 IN OUT PCONTEXT Context) 89 { 90 KIRQL OldIrql; 91 92 // 93 // Do this at APC_LEVEL 94 // 95 OldIrql = KeGetCurrentIrql(); 96 if (OldIrql < APC_LEVEL) KeRaiseIrql(APC_LEVEL, &OldIrql); 97 98 // 99 // Start with the Control flags 100 // 101 if ((Context->ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL) 102 { 103 // 104 // So this basically means all the special stuff 105 // 106 107 // 108 // ARM has register banks 109 // 110 Context->Sp = TrapFrame->Sp; 111 Context->Lr = TrapFrame->Lr; 112 113 // 114 // The rest is already in the right mode 115 // 116 Context->Pc = TrapFrame->Pc; 117 Context->Cpsr = TrapFrame->Cpsr; 118 } 119 120 // 121 // Now do the integers 122 // 123 if ((Context->ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER) 124 { 125 // 126 // Basically everything else but FPU 127 // 128 Context->R0 = TrapFrame->R0; 129 Context->R1 = TrapFrame->R1; 130 Context->R2 = TrapFrame->R2; 131 Context->R3 = TrapFrame->R3; 132 Context->R4 = ExceptionFrame->R4; 133 Context->R5 = ExceptionFrame->R5; 134 Context->R6 = ExceptionFrame->R6; 135 Context->R7 = ExceptionFrame->R7; 136 Context->R8 = ExceptionFrame->R8; 137 Context->R9 = ExceptionFrame->R9; 138 Context->R10 = ExceptionFrame->R10; 139 Context->R11 = ExceptionFrame->R11; 140 Context->R12 = TrapFrame->R12; 141 } 142 143 // 144 // Restore IRQL 145 // 146 if (OldIrql < APC_LEVEL) KeLowerIrql(OldIrql); 147 } 148 149 VOID 150 NTAPI 151 KiDispatchException(IN PEXCEPTION_RECORD ExceptionRecord, 152 IN PKEXCEPTION_FRAME ExceptionFrame, 153 IN PKTRAP_FRAME TrapFrame, 154 IN KPROCESSOR_MODE PreviousMode, 155 IN BOOLEAN FirstChance) 156 { 157 CONTEXT Context; 158 159 /* Increase number of Exception Dispatches */ 160 KeGetCurrentPrcb()->KeExceptionDispatchCount++; 161 162 /* Set the context flags */ 163 Context.ContextFlags = CONTEXT_FULL; 164 165 /* Check if User Mode or if the kernel debugger is enabled */ 166 if ((PreviousMode == UserMode) || (KeGetPcr()->KdVersionBlock)) 167 { 168 /* FIXME-V6: VFP Support */ 169 } 170 171 /* Get a Context */ 172 KeTrapFrameToContext(TrapFrame, ExceptionFrame, &Context); 173 174 /* Look at our exception code */ 175 switch (ExceptionRecord->ExceptionCode) 176 { 177 /* Breakpoint */ 178 case STATUS_BREAKPOINT: 179 180 /* Decrement PC by four */ 181 Context.Pc -= sizeof(ULONG); 182 break; 183 184 /* Internal exception */ 185 case KI_EXCEPTION_ACCESS_VIOLATION: 186 187 /* Set correct code */ 188 ExceptionRecord->ExceptionCode = STATUS_ACCESS_VIOLATION; 189 if (PreviousMode == UserMode) 190 { 191 /* FIXME: Handle no execute */ 192 } 193 break; 194 } 195 196 /* Handle kernel-mode first, it's simpler */ 197 if (PreviousMode == KernelMode) 198 { 199 /* Check if this is a first-chance exception */ 200 if (FirstChance != FALSE) 201 { 202 /* Break into the debugger for the first time */ 203 if (KiDebugRoutine(TrapFrame, 204 ExceptionFrame, 205 ExceptionRecord, 206 &Context, 207 PreviousMode, 208 FALSE)) 209 { 210 /* Exception was handled */ 211 goto Handled; 212 } 213 214 /* If the Debugger couldn't handle it, dispatch the exception */ 215 if (RtlDispatchException(ExceptionRecord, &Context)) goto Handled; 216 } 217 218 /* This is a second-chance exception, only for the debugger */ 219 if (KiDebugRoutine(TrapFrame, 220 ExceptionFrame, 221 ExceptionRecord, 222 &Context, 223 PreviousMode, 224 TRUE)) 225 { 226 /* Exception was handled */ 227 goto Handled; 228 } 229 230 /* Third strike; you're out */ 231 KeBugCheckEx(KMODE_EXCEPTION_NOT_HANDLED, 232 ExceptionRecord->ExceptionCode, 233 (ULONG_PTR)ExceptionRecord->ExceptionAddress, 234 (ULONG_PTR)TrapFrame, 235 0); 236 } 237 else 238 { 239 /* FIXME: TODO */ 240 /* 3rd strike, kill the process */ 241 DPRINT1("Kill %.16s, ExceptionCode: %lx, ExceptionAddress: %lx\n", 242 PsGetCurrentProcess()->ImageFileName, 243 ExceptionRecord->ExceptionCode, 244 ExceptionRecord->ExceptionAddress); 245 246 ZwTerminateProcess(NtCurrentProcess(), ExceptionRecord->ExceptionCode); 247 KeBugCheckEx(KMODE_EXCEPTION_NOT_HANDLED, 248 ExceptionRecord->ExceptionCode, 249 (ULONG_PTR)ExceptionRecord->ExceptionAddress, 250 (ULONG_PTR)TrapFrame, 251 0); 252 } 253 254 Handled: 255 /* Convert the context back into Trap/Exception Frames */ 256 KeContextToTrapFrame(&Context, 257 ExceptionFrame, 258 TrapFrame, 259 Context.ContextFlags, 260 PreviousMode); 261 return; 262 } 263 264 NTSTATUS 265 NTAPI 266 KeRaiseUserException( 267 _In_ NTSTATUS ExceptionCode) 268 { 269 ASSERT(FALSE); 270 return STATUS_NOT_IMPLEMENTED; 271 } 272