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
KeContextToTrapFrame(IN PCONTEXT Context,IN OUT PKEXCEPTION_FRAME ExceptionFrame,IN OUT PKTRAP_FRAME TrapFrame,IN ULONG ContextFlags,IN KPROCESSOR_MODE PreviousMode)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
KeTrapFrameToContext(IN PKTRAP_FRAME TrapFrame,IN PKEXCEPTION_FRAME ExceptionFrame,IN OUT PCONTEXT Context)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
KiDispatchException(IN PEXCEPTION_RECORD ExceptionRecord,IN PKEXCEPTION_FRAME ExceptionFrame,IN PKTRAP_FRAME TrapFrame,IN KPROCESSOR_MODE PreviousMode,IN BOOLEAN FirstChance)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
KeRaiseUserException(_In_ NTSTATUS ExceptionCode)266 KeRaiseUserException(
267 _In_ NTSTATUS ExceptionCode)
268 {
269 ASSERT(FALSE);
270 return STATUS_NOT_IMPLEMENTED;
271 }
272