undefined.c (e6e746bfb086d563bf0ad454a33ecbcab8836dbf) undefined.c (ae4fa2223a960ae069fb91224700fe94e94cb2b9)
1/* $NetBSD: undefined.c,v 1.22 2003/11/29 22:21:29 bjh21 Exp $ */
2
3/*-
4 * Copyright (c) 2001 Ben Harris.
5 * Copyright (c) 1995 Mark Brinicombe.
6 * Copyright (c) 1995 Brini.
7 * All rights reserved.
8 *

--- 72 unchanged lines hidden (view full) ---

81#ifdef DDB
82#include <ddb/db_output.h>
83#endif
84
85#ifdef KDB
86#include <machine/db_machdep.h>
87#endif
88
1/* $NetBSD: undefined.c,v 1.22 2003/11/29 22:21:29 bjh21 Exp $ */
2
3/*-
4 * Copyright (c) 2001 Ben Harris.
5 * Copyright (c) 1995 Mark Brinicombe.
6 * Copyright (c) 1995 Brini.
7 * All rights reserved.
8 *

--- 72 unchanged lines hidden (view full) ---

81#ifdef DDB
82#include <ddb/db_output.h>
83#endif
84
85#ifdef KDB
86#include <machine/db_machdep.h>
87#endif
88
89#define ARM_COPROC_INSN(insn) (((insn) & (1 << 27)) != 0)
90#define ARM_VFP_INSN(insn) ((((insn) & 0xfe000000) == 0xf2000000) || \
91 (((insn) & 0xff100000) == 0xf4000000))
92#define ARM_COPROC(insn) (((insn) >> 8) & 0xf)
93
94#define THUMB_32BIT_INSN(insn) ((insn) >= 0xe800)
95#define THUMB_COPROC_INSN(insn) (((insn) & (3 << 26)) == (3 << 26))
96#define THUMB_COPROC_UNDEFINED(insn) (((insn) & 0x3e << 20) == 0)
97#define THUMB_VFP_INSN(insn) (((insn) & (3 << 24)) == (3 << 24))
98#define THUMB_COPROC(insn) (((insn) >> 8) & 0xf)
99
100#define COPROC_VFP 10
101
89#ifdef KDTRACE_HOOKS
90int (*dtrace_invop_jump_addr)(struct trapframe *);
91#endif
92
93static int gdb_trapper(u_int, u_int, struct trapframe *, int);
94
95LIST_HEAD(, undefined_handler) undefined_handlers[MAX_COPROCS];
96

--- 77 unchanged lines hidden (view full) ---

174undefinedinstruction(struct trapframe *frame)
175{
176 struct thread *td;
177 u_int fault_pc;
178 int fault_instruction;
179 int fault_code;
180 int coprocessor;
181 struct undefined_handler *uh;
102#ifdef KDTRACE_HOOKS
103int (*dtrace_invop_jump_addr)(struct trapframe *);
104#endif
105
106static int gdb_trapper(u_int, u_int, struct trapframe *, int);
107
108LIST_HEAD(, undefined_handler) undefined_handlers[MAX_COPROCS];
109

--- 77 unchanged lines hidden (view full) ---

187undefinedinstruction(struct trapframe *frame)
188{
189 struct thread *td;
190 u_int fault_pc;
191 int fault_instruction;
192 int fault_code;
193 int coprocessor;
194 struct undefined_handler *uh;
195 int error;
182#ifdef VERBOSE_ARM32
183 int s;
184#endif
185 ksiginfo_t ksi;
186
187 /* Enable interrupts if they were enabled before the exception. */
188 if (__predict_true(frame->tf_spsr & PSR_I) == 0)
189 enable_interrupts(PSR_I);
190 if (__predict_true(frame->tf_spsr & PSR_F) == 0)
191 enable_interrupts(PSR_F);
192
193 PCPU_INC(cnt.v_trap);
194
196#ifdef VERBOSE_ARM32
197 int s;
198#endif
199 ksiginfo_t ksi;
200
201 /* Enable interrupts if they were enabled before the exception. */
202 if (__predict_true(frame->tf_spsr & PSR_I) == 0)
203 enable_interrupts(PSR_I);
204 if (__predict_true(frame->tf_spsr & PSR_F) == 0)
205 enable_interrupts(PSR_F);
206
207 PCPU_INC(cnt.v_trap);
208
209#if __ARM_ARCH >= 7
210 if ((frame->tf_spsr & PSR_T) != 0)
211 frame->tf_pc -= THUMB_INSN_SIZE;
212 else
213#endif
214 frame->tf_pc -= INSN_SIZE;
195 fault_pc = frame->tf_pc;
196
197 /*
198 * Get the current thread/proc structure or thread0/proc0 if there is
199 * none.
200 */
201 td = curthread == NULL ? &thread0 : curthread;
202
215 fault_pc = frame->tf_pc;
216
217 /*
218 * Get the current thread/proc structure or thread0/proc0 if there is
219 * none.
220 */
221 td = curthread == NULL ? &thread0 : curthread;
222
203 /*
204 * Make sure the program counter is correctly aligned so we
205 * don't take an alignment fault trying to read the opcode.
206 */
207 if (__predict_false((fault_pc & 3) != 0)) {
223 coprocessor = 0;
224 if ((frame->tf_spsr & PSR_T) == 0) {
225 /*
226 * Make sure the program counter is correctly aligned so we
227 * don't take an alignment fault trying to read the opcode.
228 */
229 if (__predict_false((fault_pc & 3) != 0)) {
230 ksiginfo_init_trap(&ksi);
231 ksi.ksi_signo = SIGILL;
232 ksi.ksi_code = ILL_ILLADR;
233 ksi.ksi_addr = (u_int32_t *)(intptr_t) fault_pc;
234 trapsignal(td, &ksi);
235 userret(td, frame);
236 return;
237 }
238
239 /*
240 * Should use fuword() here .. but in the interests of
241 * squeezing every bit of speed we will just use ReadWord().
242 * We know the instruction can be read as was just executed
243 * so this will never fail unless the kernel is screwed up
244 * in which case it does not really matter does it ?
245 */
246
247 fault_instruction = *(u_int32_t *)fault_pc;
248
249 /* Check for coprocessor instruction */
250
251 /*
252 * According to the datasheets you only need to look at bit
253 * 27 of the instruction to tell the difference between and
254 * undefined instruction and a coprocessor instruction
255 * following an undefined instruction trap.
256 */
257
258 if (ARM_COPROC_INSN(fault_instruction))
259 coprocessor = ARM_COPROC(fault_instruction);
260 else { /* check for special instructions */
261 if (ARM_VFP_INSN(fault_instruction))
262 coprocessor = COPROC_VFP; /* vfp / simd */
263 }
264 } else {
265#if __ARM_ARCH >= 7
266 fault_instruction = *(uint16_t *)fault_pc;
267 if (THUMB_32BIT_INSN(fault_instruction)) {
268 fault_instruction <<= 16;
269 fault_instruction |= *(uint16_t *)(fault_pc + 2);
270
271 /*
272 * Is it a Coprocessor, Advanced SIMD, or
273 * Floating-point instruction.
274 */
275 if (THUMB_COPROC_INSN(fault_instruction)) {
276 if (THUMB_COPROC_UNDEFINED(fault_instruction)) {
277 /* undefined insn */
278 } else if (THUMB_VFP_INSN(fault_instruction))
279 coprocessor = COPROC_VFP;
280 else
281 coprocessor =
282 THUMB_COPROC(fault_instruction);
283 }
284 }
285#else
286 /*
287 * No support for Thumb-2 on this cpu
288 */
208 ksiginfo_init_trap(&ksi);
209 ksi.ksi_signo = SIGILL;
210 ksi.ksi_code = ILL_ILLADR;
211 ksi.ksi_addr = (u_int32_t *)(intptr_t) fault_pc;
212 trapsignal(td, &ksi);
213 userret(td, frame);
214 return;
289 ksiginfo_init_trap(&ksi);
290 ksi.ksi_signo = SIGILL;
291 ksi.ksi_code = ILL_ILLADR;
292 ksi.ksi_addr = (u_int32_t *)(intptr_t) fault_pc;
293 trapsignal(td, &ksi);
294 userret(td, frame);
295 return;
215 }
216
217 /*
218 * Should use fuword() here .. but in the interests of squeezing every
219 * bit of speed we will just use ReadWord(). We know the instruction
220 * can be read as was just executed so this will never fail unless the
221 * kernel is screwed up in which case it does not really matter does
222 * it ?
223 */
224
225 fault_instruction = *(u_int32_t *)fault_pc;
226
227 /* Update vmmeter statistics */
228#if 0
229 uvmexp.traps++;
230#endif
296#endif
231 /* Check for coprocessor instruction */
232
233 /*
234 * According to the datasheets you only need to look at bit 27 of the
235 * instruction to tell the difference between and undefined
236 * instruction and a coprocessor instruction following an undefined
237 * instruction trap.
238 */
239
240 coprocessor = 0;
241 if ((fault_instruction & (1 << 27)) != 0)
242 coprocessor = (fault_instruction >> 8) & 0x0f;
243#ifdef VFP
244 else { /* check for special instructions */
245 if (((fault_instruction & 0xfe000000) == 0xf2000000) ||
246 ((fault_instruction & 0xff100000) == 0xf4000000))
247 coprocessor = 10; /* vfp / simd */
248 }
297 }
249#endif /* VFP */
250
251 if ((frame->tf_spsr & PSR_MODE) == PSR_USR32_MODE) {
252 /*
253 * Modify the fault_code to reflect the USR/SVC state at
254 * time of fault.
255 */
256 fault_code = FAULT_USER;
257 td->td_frame = frame;
258 } else
259 fault_code = 0;
260
261 /* OK this is were we do something about the instruction. */
262 LIST_FOREACH(uh, &undefined_handlers[coprocessor], uh_link)
263 if (uh->uh_handler(fault_pc, fault_instruction, frame,
264 fault_code) == 0)
265 break;
266
298
299 if ((frame->tf_spsr & PSR_MODE) == PSR_USR32_MODE) {
300 /*
301 * Modify the fault_code to reflect the USR/SVC state at
302 * time of fault.
303 */
304 fault_code = FAULT_USER;
305 td->td_frame = frame;
306 } else
307 fault_code = 0;
308
309 /* OK this is were we do something about the instruction. */
310 LIST_FOREACH(uh, &undefined_handlers[coprocessor], uh_link)
311 if (uh->uh_handler(fault_pc, fault_instruction, frame,
312 fault_code) == 0)
313 break;
314
267 if (fault_code & FAULT_USER && fault_instruction == PTRACE_BREAKPOINT) {
268 PROC_LOCK(td->td_proc);
269 _PHOLD(td->td_proc);
270 ptrace_clear_single_step(td);
271 _PRELE(td->td_proc);
272 PROC_UNLOCK(td->td_proc);
273 return;
315 if (fault_code & FAULT_USER) {
316 /* TODO: No support for ptrace from Thumb-2 */
317 if ((frame->tf_spsr & PSR_T) == 0 &&
318 fault_instruction == PTRACE_BREAKPOINT) {
319 PROC_LOCK(td->td_proc);
320 _PHOLD(td->td_proc);
321 error = ptrace_clear_single_step(td);
322 _PRELE(td->td_proc);
323 PROC_UNLOCK(td->td_proc);
324 if (error != 0) {
325 ksiginfo_init_trap(&ksi);
326 ksi.ksi_signo = SIGILL;
327 ksi.ksi_code = ILL_ILLOPC;
328 ksi.ksi_addr = (u_int32_t *)(intptr_t) fault_pc;
329 trapsignal(td, &ksi);
330 }
331 return;
332 }
274 }
275
276 if (uh == NULL && (fault_code & FAULT_USER)) {
277 /* Fault has not been handled */
278 ksiginfo_init_trap(&ksi);
279 ksi.ksi_signo = SIGILL;
280 ksi.ksi_code = ILL_ILLOPC;
281 ksi.ksi_addr = (u_int32_t *)(intptr_t) fault_pc;

--- 24 unchanged lines hidden ---
333 }
334
335 if (uh == NULL && (fault_code & FAULT_USER)) {
336 /* Fault has not been handled */
337 ksiginfo_init_trap(&ksi);
338 ksi.ksi_signo = SIGILL;
339 ksi.ksi_code = ILL_ILLOPC;
340 ksi.ksi_addr = (u_int32_t *)(intptr_t) fault_pc;

--- 24 unchanged lines hidden ---