2 * arch/score/kernel/traps.c
4 * Score Processor version.
6 * Copyright (C) 2009 Sunplus Core Technology Co., Ltd.
7 * Chen Liqin <liqin.chen@sunplusct.com>
8 * Lennox Wu <lennox.wu@sunplusct.com>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, see the file COPYING, or write
22 * to the Free Software Foundation, Inc.,
23 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
26 #include <linux/module.h>
27 #include <linux/sched.h>
29 #include <asm/cacheflush.h>
31 #include <asm/irq_regs.h>
32 #include <asm/uaccess.h>
34 unsigned long exception_handlers
[32];
37 * The architecture-independent show_stack generator
39 void show_stack(struct task_struct
*task
, unsigned long *sp
)
44 sp
= sp
? sp
: (unsigned long *)&sp
;
46 printk(KERN_NOTICE
"Stack: ");
48 while ((long) sp
& (PAGE_SIZE
- 1)) {
49 if (i
&& ((i
% 8) == 0))
50 printk(KERN_NOTICE
"\n");
52 printk(KERN_NOTICE
" ...");
56 if (__get_user(stackdata
, sp
++)) {
57 printk(KERN_NOTICE
" (Bad stack address)");
61 printk(KERN_NOTICE
" %08lx", stackdata
);
64 printk(KERN_NOTICE
"\n");
67 static void show_trace(long *sp
)
72 sp
= sp
? sp
: (long *) &sp
;
74 printk(KERN_NOTICE
"Call Trace: ");
76 while ((long) sp
& (PAGE_SIZE
- 1)) {
77 if (__get_user(addr
, sp
++)) {
78 if (i
&& ((i
% 6) == 0))
79 printk(KERN_NOTICE
"\n");
80 printk(KERN_NOTICE
" (Bad stack address)\n");
84 if (kernel_text_address(addr
)) {
85 if (i
&& ((i
% 6) == 0))
86 printk(KERN_NOTICE
"\n");
88 printk(KERN_NOTICE
" ...");
92 printk(KERN_NOTICE
" [<%08lx>]", addr
);
96 printk(KERN_NOTICE
"\n");
99 static void show_code(unsigned int *pc
)
103 printk(KERN_NOTICE
"\nCode:");
105 for (i
= -3; i
< 6; i
++) {
107 if (__get_user(insn
, pc
+ i
)) {
108 printk(KERN_NOTICE
" (Bad address in epc)\n");
111 printk(KERN_NOTICE
"%c%08lx%c", (i
? ' ' : '<'),
112 insn
, (i
? ' ' : '>'));
117 * FIXME: really the generic show_regs should take a const pointer argument.
119 void show_regs(struct pt_regs
*regs
)
121 show_regs_print_info(KERN_DEFAULT
);
123 printk("r0 : %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
124 regs
->regs
[0], regs
->regs
[1], regs
->regs
[2], regs
->regs
[3],
125 regs
->regs
[4], regs
->regs
[5], regs
->regs
[6], regs
->regs
[7]);
126 printk("r8 : %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
127 regs
->regs
[8], regs
->regs
[9], regs
->regs
[10], regs
->regs
[11],
128 regs
->regs
[12], regs
->regs
[13], regs
->regs
[14], regs
->regs
[15]);
129 printk("r16: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
130 regs
->regs
[16], regs
->regs
[17], regs
->regs
[18], regs
->regs
[19],
131 regs
->regs
[20], regs
->regs
[21], regs
->regs
[22], regs
->regs
[23]);
132 printk("r24: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
133 regs
->regs
[24], regs
->regs
[25], regs
->regs
[26], regs
->regs
[27],
134 regs
->regs
[28], regs
->regs
[29], regs
->regs
[30], regs
->regs
[31]);
136 printk("CEH : %08lx\n", regs
->ceh
);
137 printk("CEL : %08lx\n", regs
->cel
);
139 printk("EMA:%08lx, epc:%08lx %s\nPSR: %08lx\nECR:%08lx\nCondition : %08lx\n",
140 regs
->cp0_ema
, regs
->cp0_epc
, print_tainted(), regs
->cp0_psr
,
141 regs
->cp0_ecr
, regs
->cp0_condition
);
144 static void show_registers(struct pt_regs
*regs
)
147 printk(KERN_NOTICE
"Process %s (pid: %d, stackpage=%08lx)\n",
148 current
->comm
, current
->pid
, (unsigned long) current
);
149 show_stack(current_thread_info()->task
, (long *) regs
->regs
[0]);
150 show_trace((long *) regs
->regs
[0]);
151 show_code((unsigned int *) regs
->cp0_epc
);
152 printk(KERN_NOTICE
"\n");
155 void __die(const char *str
, struct pt_regs
*regs
, const char *file
,
156 const char *func
, unsigned long line
)
161 printk(" in %s:%s, line %ld", file
, func
, line
);
163 show_registers(regs
);
167 void __die_if_kernel(const char *str
, struct pt_regs
*regs
,
168 const char *file
, const char *func
, unsigned long line
)
170 if (!user_mode(regs
))
171 __die(str
, regs
, file
, func
, line
);
174 asmlinkage
void do_adelinsn(struct pt_regs
*regs
)
176 printk("do_ADE-linsn:ema:0x%08lx:epc:0x%08lx\n",
177 regs
->cp0_ema
, regs
->cp0_epc
);
178 die_if_kernel("do_ade execution Exception\n", regs
);
179 force_sig(SIGBUS
, current
);
182 asmlinkage
void do_adedata(struct pt_regs
*regs
)
184 const struct exception_table_entry
*fixup
;
185 fixup
= search_exception_tables(regs
->cp0_epc
);
187 regs
->cp0_epc
= fixup
->fixup
;
190 printk("do_ADE-data:ema:0x%08lx:epc:0x%08lx\n",
191 regs
->cp0_ema
, regs
->cp0_epc
);
192 die_if_kernel("do_ade execution Exception\n", regs
);
193 force_sig(SIGBUS
, current
);
196 asmlinkage
void do_pel(struct pt_regs
*regs
)
198 die_if_kernel("do_pel execution Exception", regs
);
199 force_sig(SIGFPE
, current
);
202 asmlinkage
void do_cee(struct pt_regs
*regs
)
204 die_if_kernel("do_cee execution Exception", regs
);
205 force_sig(SIGFPE
, current
);
208 asmlinkage
void do_cpe(struct pt_regs
*regs
)
210 die_if_kernel("do_cpe execution Exception", regs
);
211 force_sig(SIGFPE
, current
);
214 asmlinkage
void do_be(struct pt_regs
*regs
)
216 die_if_kernel("do_be execution Exception", regs
);
217 force_sig(SIGBUS
, current
);
220 asmlinkage
void do_ov(struct pt_regs
*regs
)
224 die_if_kernel("do_ov execution Exception", regs
);
226 info
.si_code
= FPE_INTOVF
;
227 info
.si_signo
= SIGFPE
;
229 info
.si_addr
= (void *)regs
->cp0_epc
;
230 force_sig_info(SIGFPE
, &info
, current
);
233 asmlinkage
void do_tr(struct pt_regs
*regs
)
235 die_if_kernel("do_tr execution Exception", regs
);
236 force_sig(SIGTRAP
, current
);
239 asmlinkage
void do_ri(struct pt_regs
*regs
)
241 unsigned long epc_insn
;
242 unsigned long epc
= regs
->cp0_epc
;
244 read_tsk_long(current
, epc
, &epc_insn
);
245 if (current
->thread
.single_step
== 1) {
246 if ((epc
== current
->thread
.addr1
) ||
247 (epc
== current
->thread
.addr2
)) {
248 user_disable_single_step(current
);
249 force_sig(SIGTRAP
, current
);
253 } else if ((epc_insn
== BREAKPOINT32_INSN
) ||
254 ((epc_insn
& 0x0000FFFF) == 0x7002) ||
255 ((epc_insn
& 0xFFFF0000) == 0x70020000)) {
256 force_sig(SIGTRAP
, current
);
259 die_if_kernel("do_ri execution Exception", regs
);
260 force_sig(SIGILL
, current
);
264 asmlinkage
void do_ccu(struct pt_regs
*regs
)
266 die_if_kernel("do_ccu execution Exception", regs
);
267 force_sig(SIGILL
, current
);
270 asmlinkage
void do_reserved(struct pt_regs
*regs
)
273 * Game over - no way to handle this if it ever occurs. Most probably
274 * caused by a new unknown cpu type or after another deadly
275 * hard/software error.
277 die_if_kernel("do_reserved execution Exception", regs
);
279 panic("Caught reserved exception - should not happen.");
283 * NMI exception handler.
285 void nmi_exception_handler(struct pt_regs
*regs
)
287 die_if_kernel("nmi_exception_handler execution Exception", regs
);
291 /* Install CPU exception handler */
292 void *set_except_vector(int n
, void *addr
)
294 unsigned long handler
= (unsigned long) addr
;
295 unsigned long old_handler
= exception_handlers
[n
];
297 exception_handlers
[n
] = handler
;
298 return (void *)old_handler
;
301 void __init
trap_init(void)
305 pgd_current
= (unsigned long)init_mm
.pgd
;
306 /* DEBUG EXCEPTION */
307 memcpy((void *)DEBUG_VECTOR_BASE_ADDR
,
308 &debug_exception_vector
, DEBUG_VECTOR_SIZE
);
310 memcpy((void *)GENERAL_VECTOR_BASE_ADDR
,
311 &general_exception_vector
, GENERAL_VECTOR_SIZE
);
314 * Initialise exception handlers
316 for (i
= 0; i
<= 31; i
++)
317 set_except_vector(i
, handle_reserved
);
319 set_except_vector(1, handle_nmi
);
320 set_except_vector(2, handle_adelinsn
);
321 set_except_vector(3, handle_tlb_refill
);
322 set_except_vector(4, handle_tlb_invaild
);
323 set_except_vector(5, handle_ibe
);
324 set_except_vector(6, handle_pel
);
325 set_except_vector(7, handle_sys
);
326 set_except_vector(8, handle_ccu
);
327 set_except_vector(9, handle_ri
);
328 set_except_vector(10, handle_tr
);
329 set_except_vector(11, handle_adedata
);
330 set_except_vector(12, handle_adedata
);
331 set_except_vector(13, handle_tlb_refill
);
332 set_except_vector(14, handle_tlb_invaild
);
333 set_except_vector(15, handle_mod
);
334 set_except_vector(16, handle_cee
);
335 set_except_vector(17, handle_cpe
);
336 set_except_vector(18, handle_dbe
);
337 flush_icache_range(DEBUG_VECTOR_BASE_ADDR
, IRQ_VECTOR_BASE_ADDR
);
339 atomic_inc(&init_mm
.mm_count
);
340 current
->active_mm
= &init_mm
;