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/sched.h>
13 #include <linux/signal.h>
14 #include <linux/kernel.h>
16 #include <linux/types.h>
17 #include <linux/user.h>
18 #include <linux/string.h>
19 #include <linux/linkage.h>
20 #include <linux/init.h>
21 #include <linux/module.h>
23 #include <asm/asm-offsets.h>
24 #include <asm/setup.h>
26 #include <asm/system.h>
27 #include <asm/uaccess.h>
28 #include <asm/pgtable.h>
29 #include <asm/siginfo.h>
30 #include <asm/unaligned.h>
32 void show_backtrace(struct pt_regs
*, unsigned long);
34 extern asmlinkage
void __break_hijack_kernel_event(void);
36 /*****************************************************************************/
38 * instruction access error
40 asmlinkage
void insn_access_error(unsigned long esfr1
, unsigned long epcr0
, unsigned long esr0
)
44 die_if_kernel("-- Insn Access Error --\n"
49 info
.si_signo
= SIGSEGV
;
50 info
.si_code
= SEGV_ACCERR
;
52 info
.si_addr
= (void *) ((epcr0
& EPCR0_V
) ? (epcr0
& EPCR0_PC
) : __frame
->pc
);
54 force_sig_info(info
.si_signo
, &info
, current
);
55 } /* end insn_access_error() */
57 /*****************************************************************************/
60 * - illegal instruction
61 * - privileged instruction
65 asmlinkage
void illegal_instruction(unsigned long esfr1
, unsigned long epcr0
, unsigned long esr0
)
69 die_if_kernel("-- Illegal Instruction --\n"
76 info
.si_addr
= (void *) ((epcr0
& EPCR0_PC
) ? (epcr0
& EPCR0_PC
) : __frame
->pc
);
78 switch (__frame
->tbr
& TBR_TT
) {
79 case TBR_TT_ILLEGAL_INSTR
:
80 info
.si_signo
= SIGILL
;
81 info
.si_code
= ILL_ILLOPC
;
83 case TBR_TT_PRIV_INSTR
:
84 info
.si_signo
= SIGILL
;
85 info
.si_code
= ILL_PRVOPC
;
87 case TBR_TT_TRAP2
... TBR_TT_TRAP126
:
88 info
.si_signo
= SIGILL
;
89 info
.si_code
= ILL_ILLTRP
;
91 /* GDB uses "tira gr0, #1" as a breakpoint instruction. */
94 info
.si_signo
= SIGTRAP
;
96 (__frame
->__status
& REG__STATUS_STEPPED
) ? TRAP_TRACE
: TRAP_BRKPT
;
100 force_sig_info(info
.si_signo
, &info
, current
);
101 } /* end illegal_instruction() */
103 /*****************************************************************************/
107 asmlinkage
void media_exception(unsigned long msr0
, unsigned long msr1
)
111 die_if_kernel("-- Media Exception --\n"
116 info
.si_signo
= SIGFPE
;
117 info
.si_code
= FPE_MDAOVF
;
119 info
.si_addr
= (void *) __frame
->pc
;
121 force_sig_info(info
.si_signo
, &info
, current
);
122 } /* end media_exception() */
124 /*****************************************************************************/
126 * instruction or data access exception
128 asmlinkage
void memory_access_exception(unsigned long esr0
,
137 if ((esr0
& ESRx_EC
) == ESRx_EC_DATA_ACCESS
)
138 if (handle_misalignment(esr0
, ear0
, epcr0
) == 0)
141 if ((fixup
= search_exception_table(__frame
->pc
)) != 0) {
147 die_if_kernel("-- Memory Access Exception --\n"
153 info
.si_signo
= SIGSEGV
;
154 info
.si_code
= SEGV_ACCERR
;
158 if ((esr0
& (ESRx_VALID
| ESR0_EAV
)) == (ESRx_VALID
| ESR0_EAV
))
159 info
.si_addr
= (void *) ear0
;
161 force_sig_info(info
.si_signo
, &info
, current
);
163 } /* end memory_access_exception() */
165 /*****************************************************************************/
168 * - double-word data load from CPU control area (0xFExxxxxx)
169 * - read performed on inactive or self-refreshing SDRAM
170 * - error notification from slave device
171 * - misaligned address
172 * - access to out of bounds memory region
173 * - user mode accessing privileged memory region
174 * - write to R/O memory region
176 asmlinkage
void data_access_error(unsigned long esfr1
, unsigned long esr15
, unsigned long ear15
)
180 die_if_kernel("-- Data Access Error --\n"
185 info
.si_signo
= SIGSEGV
;
186 info
.si_code
= SEGV_ACCERR
;
188 info
.si_addr
= (void *)
189 (((esr15
& (ESRx_VALID
|ESR15_EAV
)) == (ESRx_VALID
|ESR15_EAV
)) ? ear15
: 0);
191 force_sig_info(info
.si_signo
, &info
, current
);
192 } /* end data_access_error() */
194 /*****************************************************************************/
196 * data store error - should only happen if accessing inactive or self-refreshing SDRAM
198 asmlinkage
void data_store_error(unsigned long esfr1
, unsigned long esr15
)
200 die_if_kernel("-- Data Store Error --\n"
204 } /* end data_store_error() */
206 /*****************************************************************************/
210 asmlinkage
void division_exception(unsigned long esfr1
, unsigned long esr0
, unsigned long isr
)
214 die_if_kernel("-- Division Exception --\n"
219 info
.si_signo
= SIGFPE
;
220 info
.si_code
= FPE_INTDIV
;
222 info
.si_addr
= (void *) __frame
->pc
;
224 force_sig_info(info
.si_signo
, &info
, current
);
225 } /* end division_exception() */
227 /*****************************************************************************/
231 asmlinkage
void compound_exception(unsigned long esfr1
,
232 unsigned long esr0
, unsigned long esr14
, unsigned long esr15
,
233 unsigned long msr0
, unsigned long msr1
)
235 die_if_kernel("-- Compound Exception --\n"
241 esr0
, esr14
, esr15
, msr0
, msr1
);
243 } /* end compound_exception() */
245 /*****************************************************************************/
247 * The architecture-independent backtrace generator
249 void dump_stack(void)
251 show_stack(NULL
, NULL
);
254 EXPORT_SYMBOL(dump_stack
);
256 void show_stack(struct task_struct
*task
, unsigned long *sp
)
260 void show_trace_task(struct task_struct
*tsk
)
262 printk("CONTEXT: stack=0x%lx frame=0x%p LR=0x%lx RET=0x%lx\n",
263 tsk
->thread
.sp
, tsk
->thread
.frame
, tsk
->thread
.lr
, tsk
->thread
.sched_lr
);
266 static const char *regnames
[] = {
267 "PSR ", "ISR ", "CCR ", "CCCR",
268 "LR ", "LCR ", "PC ", "_stt",
269 "sys ", "GR8*", "GNE0", "GNE1",
271 "TBR ", "SP ", "FP ", "GR3 ",
272 "GR4 ", "GR5 ", "GR6 ", "GR7 ",
273 "GR8 ", "GR9 ", "GR10", "GR11",
274 "GR12", "GR13", "GR14", "GR15",
275 "GR16", "GR17", "GR18", "GR19",
276 "GR20", "GR21", "GR22", "GR23",
277 "GR24", "GR25", "GR26", "GR27",
278 "EFRM", "CURR", "GR30", "BFRM"
281 void show_regs(struct pt_regs
*regs
)
288 printk("Frame: @%08lx [%s]\n",
289 (unsigned long) regs
,
290 regs
->psr
& PSR_S
? "kernel" : "user");
292 reg
= (unsigned long *) regs
;
293 for (loop
= 0; loop
< NR_PT_REGS
; loop
++) {
294 printk("%s %08lx", regnames
[loop
+ 0], reg
[loop
+ 0]);
296 if (loop
== NR_PT_REGS
- 1 || loop
% 5 == 4)
302 printk("Process %s (pid: %d)\n", current
->comm
, current
->pid
);
305 void die_if_kernel(const char *str
, ...)
310 if (user_mode(__frame
))
314 vsprintf(buffer
, str
, va
);
318 printk("\n===================================\n");
319 printk("%s\n", buffer
);
320 show_backtrace(__frame
, 0);
322 __break_hijack_kernel_event();
326 /*****************************************************************************/
328 * dump the contents of an exception frame
330 static void show_backtrace_regs(struct pt_regs
*frame
)
335 /* print the registers for this frame */
336 printk("<-- %s Frame: @%p -->\n",
337 frame
->psr
& PSR_S
? "Kernel Mode" : "User Mode",
340 reg
= (unsigned long *) frame
;
341 for (loop
= 0; loop
< NR_PT_REGS
; loop
++) {
342 printk("%s %08lx", regnames
[loop
+ 0], reg
[loop
+ 0]);
344 if (loop
== NR_PT_REGS
- 1 || loop
% 5 == 4)
350 printk("--------\n");
351 } /* end show_backtrace_regs() */
353 /*****************************************************************************/
355 * generate a backtrace of the kernel stack
357 void show_backtrace(struct pt_regs
*frame
, unsigned long sp
)
359 struct pt_regs
*frame0
;
360 unsigned long tos
= 0, stop
= 0, base
;
363 base
= ((((unsigned long) frame
) + 8191) & ~8191) - sizeof(struct user_context
);
364 frame0
= (struct pt_regs
*) base
;
368 stop
= (unsigned long) frame
;
371 printk("\nProcess %s (pid: %d)\n\n", current
->comm
, current
->pid
);
374 /* dump stack segment between frames */
375 //printk("%08lx -> %08lx\n", tos, stop);
379 printk(" %04lx :", tos
& 0xffff);
381 printk(" %08lx", *(unsigned long *) tos
);
394 /* dump frame 0 outside of the loop */
399 if (((unsigned long) frame
) + sizeof(*frame
) != tos
) {
400 printk("-- TOS %08lx does not follow frame %p --\n",
405 show_backtrace_regs(frame
);
407 /* dump the stack between this frame and the next */
408 stop
= (unsigned long) frame
->next_frame
;
412 (stop
< base
&& stop
+ sizeof(*frame
) > base
) ||
414 printk("-- next_frame %08lx is invalid (range %08lx-%08lx) --\n",
419 /* move to next frame */
420 frame
= frame
->next_frame
;
423 /* we can always dump frame 0, even if the rest of the stack is corrupt */
424 show_backtrace_regs(frame0
);
426 } /* end show_backtrace() */
428 /*****************************************************************************/
432 void __init
trap_init (void)
434 } /* end trap_init() */