1 /* traps.c: high-level exception handler for FR-V
3 * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
12 #include <linux/config.h>
13 #include <linux/sched.h>
14 #include <linux/signal.h>
15 #include <linux/kernel.h>
17 #include <linux/types.h>
18 #include <linux/user.h>
19 #include <linux/string.h>
20 #include <linux/linkage.h>
21 #include <linux/init.h>
23 #include <asm/setup.h>
25 #include <asm/system.h>
26 #include <asm/uaccess.h>
27 #include <asm/pgtable.h>
28 #include <asm/siginfo.h>
29 #include <asm/unaligned.h>
31 void show_backtrace(struct pt_regs
*, unsigned long);
33 extern asmlinkage
void __break_hijack_kernel_event(void);
35 /*****************************************************************************/
37 * instruction access error
39 asmlinkage
void insn_access_error(unsigned long esfr1
, unsigned long epcr0
, unsigned long esr0
)
43 die_if_kernel("-- Insn Access Error --\n"
48 info
.si_signo
= SIGSEGV
;
49 info
.si_code
= SEGV_ACCERR
;
51 info
.si_addr
= (void *) ((epcr0
& EPCR0_V
) ? (epcr0
& EPCR0_PC
) : __frame
->pc
);
53 force_sig_info(info
.si_signo
, &info
, current
);
54 } /* end insn_access_error() */
56 /*****************************************************************************/
59 * - illegal instruction
60 * - privileged instruction
64 asmlinkage
void illegal_instruction(unsigned long esfr1
, unsigned long epcr0
, unsigned long esr0
)
68 die_if_kernel("-- Illegal Instruction --\n"
75 info
.si_addr
= (void *) ((epcr0
& EPCR0_PC
) ? (epcr0
& EPCR0_PC
) : __frame
->pc
);
77 switch (__frame
->tbr
& TBR_TT
) {
78 case TBR_TT_ILLEGAL_INSTR
:
79 info
.si_signo
= SIGILL
;
80 info
.si_code
= ILL_ILLOPC
;
82 case TBR_TT_PRIV_INSTR
:
83 info
.si_signo
= SIGILL
;
84 info
.si_code
= ILL_PRVOPC
;
86 case TBR_TT_TRAP2
... TBR_TT_TRAP126
:
87 info
.si_signo
= SIGILL
;
88 info
.si_code
= ILL_ILLTRP
;
90 /* GDB uses "tira gr0, #1" as a breakpoint instruction. */
93 info
.si_signo
= SIGTRAP
;
95 (__frame
->__status
& REG__STATUS_STEPPED
) ? TRAP_TRACE
: TRAP_BRKPT
;
99 force_sig_info(info
.si_signo
, &info
, current
);
100 } /* end illegal_instruction() */
102 /*****************************************************************************/
106 asmlinkage
void media_exception(unsigned long msr0
, unsigned long msr1
)
110 die_if_kernel("-- Media Exception --\n"
115 info
.si_signo
= SIGFPE
;
116 info
.si_code
= FPE_MDAOVF
;
118 info
.si_addr
= (void *) __frame
->pc
;
120 force_sig_info(info
.si_signo
, &info
, current
);
121 } /* end media_exception() */
123 /*****************************************************************************/
125 * instruction or data access exception
127 asmlinkage
void memory_access_exception(unsigned long esr0
,
136 if ((esr0
& ESRx_EC
) == ESRx_EC_DATA_ACCESS
)
137 if (handle_misalignment(esr0
, ear0
, epcr0
) == 0)
140 if ((fixup
= search_exception_table(__frame
->pc
)) != 0) {
146 die_if_kernel("-- Memory Access Exception --\n"
152 info
.si_signo
= SIGSEGV
;
153 info
.si_code
= SEGV_ACCERR
;
157 if ((esr0
& (ESRx_VALID
| ESR0_EAV
)) == (ESRx_VALID
| ESR0_EAV
))
158 info
.si_addr
= (void *) ear0
;
160 force_sig_info(info
.si_signo
, &info
, current
);
162 } /* end memory_access_exception() */
164 /*****************************************************************************/
167 * - double-word data load from CPU control area (0xFExxxxxx)
168 * - read performed on inactive or self-refreshing SDRAM
169 * - error notification from slave device
170 * - misaligned address
171 * - access to out of bounds memory region
172 * - user mode accessing privileged memory region
173 * - write to R/O memory region
175 asmlinkage
void data_access_error(unsigned long esfr1
, unsigned long esr15
, unsigned long ear15
)
179 die_if_kernel("-- Data Access Error --\n"
184 info
.si_signo
= SIGSEGV
;
185 info
.si_code
= SEGV_ACCERR
;
187 info
.si_addr
= (void *)
188 (((esr15
& (ESRx_VALID
|ESR15_EAV
)) == (ESRx_VALID
|ESR15_EAV
)) ? ear15
: 0);
190 force_sig_info(info
.si_signo
, &info
, current
);
191 } /* end data_access_error() */
193 /*****************************************************************************/
195 * data store error - should only happen if accessing inactive or self-refreshing SDRAM
197 asmlinkage
void data_store_error(unsigned long esfr1
, unsigned long esr15
)
199 die_if_kernel("-- Data Store Error --\n"
203 } /* end data_store_error() */
205 /*****************************************************************************/
209 asmlinkage
void division_exception(unsigned long esfr1
, unsigned long esr0
, unsigned long isr
)
213 die_if_kernel("-- Division Exception --\n"
218 info
.si_signo
= SIGFPE
;
219 info
.si_code
= FPE_INTDIV
;
221 info
.si_addr
= (void *) __frame
->pc
;
223 force_sig_info(info
.si_signo
, &info
, current
);
224 } /* end division_exception() */
226 /*****************************************************************************/
230 asmlinkage
void compound_exception(unsigned long esfr1
,
231 unsigned long esr0
, unsigned long esr14
, unsigned long esr15
,
232 unsigned long msr0
, unsigned long msr1
)
234 die_if_kernel("-- Compound Exception --\n"
240 esr0
, esr14
, esr15
, msr0
, msr1
);
242 } /* end compound_exception() */
244 /*****************************************************************************/
246 * The architecture-independent backtrace generator
248 void dump_stack(void)
250 show_stack(NULL
, NULL
);
253 void show_stack(struct task_struct
*task
, unsigned long *sp
)
257 void show_trace_task(struct task_struct
*tsk
)
259 printk("CONTEXT: stack=0x%lx frame=0x%p LR=0x%lx RET=0x%lx\n",
260 tsk
->thread
.sp
, tsk
->thread
.frame
, tsk
->thread
.lr
, tsk
->thread
.sched_lr
);
263 static const char *regnames
[] = {
264 "PSR ", "ISR ", "CCR ", "CCCR",
265 "LR ", "LCR ", "PC ", "_stt",
266 "sys ", "GR8*", "GNE0", "GNE1",
268 "TBR ", "SP ", "FP ", "GR3 ",
269 "GR4 ", "GR5 ", "GR6 ", "GR7 ",
270 "GR8 ", "GR9 ", "GR10", "GR11",
271 "GR12", "GR13", "GR14", "GR15",
272 "GR16", "GR17", "GR18", "GR19",
273 "GR20", "GR21", "GR22", "GR23",
274 "GR24", "GR25", "GR26", "GR27",
275 "EFRM", "CURR", "GR30", "BFRM"
278 void show_regs(struct pt_regs
*regs
)
285 printk("Frame: @%08x [%s]\n",
287 regs
->psr
& PSR_S
? "kernel" : "user");
289 reg
= (uint32_t *) regs
;
290 for (loop
= 0; loop
< REG__END
; loop
++) {
291 printk("%s %08x", regnames
[loop
+ 0], reg
[loop
+ 0]);
293 if (loop
== REG__END
- 1 || loop
% 5 == 4)
299 printk("Process %s (pid: %d)\n", current
->comm
, current
->pid
);
302 void die_if_kernel(const char *str
, ...)
307 if (user_mode(__frame
))
311 vsprintf(buffer
, str
, va
);
315 printk("\n===================================\n");
316 printk("%s\n", buffer
);
317 show_backtrace(__frame
, 0);
319 __break_hijack_kernel_event();
323 /*****************************************************************************/
325 * dump the contents of an exception frame
327 static void show_backtrace_regs(struct pt_regs
*frame
)
332 /* print the registers for this frame */
333 printk("<-- %s Frame: @%p -->\n",
334 frame
->psr
& PSR_S
? "Kernel Mode" : "User Mode",
337 reg
= (uint32_t *) frame
;
338 for (loop
= 0; loop
< REG__END
; loop
++) {
339 printk("%s %08x", regnames
[loop
+ 0], reg
[loop
+ 0]);
341 if (loop
== REG__END
- 1 || loop
% 5 == 4)
347 printk("--------\n");
348 } /* end show_backtrace_regs() */
350 /*****************************************************************************/
352 * generate a backtrace of the kernel stack
354 void show_backtrace(struct pt_regs
*frame
, unsigned long sp
)
356 struct pt_regs
*frame0
;
357 unsigned long tos
= 0, stop
= 0, base
;
360 base
= ((((unsigned long) frame
) + 8191) & ~8191) - sizeof(struct user_context
);
361 frame0
= (struct pt_regs
*) base
;
365 stop
= (unsigned long) frame
;
368 printk("\nProcess %s (pid: %d)\n\n", current
->comm
, current
->pid
);
371 /* dump stack segment between frames */
372 //printk("%08lx -> %08lx\n", tos, stop);
376 printk(" %04lx :", tos
& 0xffff);
378 printk(" %08lx", *(unsigned long *) tos
);
391 /* dump frame 0 outside of the loop */
396 if (((unsigned long) frame
) + sizeof(*frame
) != tos
) {
397 printk("-- TOS %08lx does not follow frame %p --\n",
402 show_backtrace_regs(frame
);
404 /* dump the stack between this frame and the next */
405 stop
= (unsigned long) frame
->next_frame
;
409 (stop
< base
&& stop
+ sizeof(*frame
) > base
) ||
411 printk("-- next_frame %08lx is invalid (range %08lx-%08lx) --\n",
416 /* move to next frame */
417 frame
= frame
->next_frame
;
420 /* we can always dump frame 0, even if the rest of the stack is corrupt */
421 show_backtrace_regs(frame0
);
423 } /* end show_backtrace() */
425 /*****************************************************************************/
429 void __init
trap_init (void)
431 } /* end trap_init() */