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>
33 unsigned long exception_handlers
[32];
36 * The architecture-independent show_stack generator
38 void show_stack(struct task_struct
*task
, unsigned long *sp
)
43 sp
= sp
? sp
: (unsigned long *)&sp
;
45 printk(KERN_NOTICE
"Stack: ");
47 while ((long) sp
& (PAGE_SIZE
- 1)) {
48 if (i
&& ((i
% 8) == 0))
49 printk(KERN_NOTICE
"\n");
51 printk(KERN_NOTICE
" ...");
55 if (__get_user(stackdata
, sp
++)) {
56 printk(KERN_NOTICE
" (Bad stack address)");
60 printk(KERN_NOTICE
" %08lx", stackdata
);
63 printk(KERN_NOTICE
"\n");
66 static void show_trace(long *sp
)
71 sp
= sp
? sp
: (long *) &sp
;
73 printk(KERN_NOTICE
"Call Trace: ");
75 while ((long) sp
& (PAGE_SIZE
- 1)) {
76 if (__get_user(addr
, sp
++)) {
77 if (i
&& ((i
% 6) == 0))
78 printk(KERN_NOTICE
"\n");
79 printk(KERN_NOTICE
" (Bad stack address)\n");
83 if (kernel_text_address(addr
)) {
84 if (i
&& ((i
% 6) == 0))
85 printk(KERN_NOTICE
"\n");
87 printk(KERN_NOTICE
" ...");
91 printk(KERN_NOTICE
" [<%08lx>]", addr
);
95 printk(KERN_NOTICE
"\n");
98 static void show_code(unsigned int *pc
)
102 printk(KERN_NOTICE
"\nCode:");
104 for (i
= -3; i
< 6; i
++) {
106 if (__get_user(insn
, pc
+ i
)) {
107 printk(KERN_NOTICE
" (Bad address in epc)\n");
110 printk(KERN_NOTICE
"%c%08lx%c", (i
? ' ' : '<'),
111 insn
, (i
? ' ' : '>'));
116 * FIXME: really the generic show_regs should take a const pointer argument.
118 void show_regs(struct pt_regs
*regs
)
120 printk("r0 : %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
121 regs
->regs
[0], regs
->regs
[1], regs
->regs
[2], regs
->regs
[3],
122 regs
->regs
[4], regs
->regs
[5], regs
->regs
[6], regs
->regs
[7]);
123 printk("r8 : %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
124 regs
->regs
[8], regs
->regs
[9], regs
->regs
[10], regs
->regs
[11],
125 regs
->regs
[12], regs
->regs
[13], regs
->regs
[14], regs
->regs
[15]);
126 printk("r16: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
127 regs
->regs
[16], regs
->regs
[17], regs
->regs
[18], regs
->regs
[19],
128 regs
->regs
[20], regs
->regs
[21], regs
->regs
[22], regs
->regs
[23]);
129 printk("r24: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
130 regs
->regs
[24], regs
->regs
[25], regs
->regs
[26], regs
->regs
[27],
131 regs
->regs
[28], regs
->regs
[29], regs
->regs
[30], regs
->regs
[31]);
133 printk("CEH : %08lx\n", regs
->ceh
);
134 printk("CEL : %08lx\n", regs
->cel
);
136 printk("EMA:%08lx, epc:%08lx %s\nPSR: %08lx\nECR:%08lx\nCondition : %08lx\n",
137 regs
->cp0_ema
, regs
->cp0_epc
, print_tainted(), regs
->cp0_psr
,
138 regs
->cp0_ecr
, regs
->cp0_condition
);
141 static void show_registers(struct pt_regs
*regs
)
144 printk(KERN_NOTICE
"Process %s (pid: %d, stackpage=%08lx)\n",
145 current
->comm
, current
->pid
, (unsigned long) current
);
146 show_stack(current_thread_info()->task
, (long *) regs
->regs
[0]);
147 show_trace((long *) regs
->regs
[0]);
148 show_code((unsigned int *) regs
->cp0_epc
);
149 printk(KERN_NOTICE
"\n");
153 * The architecture-independent dump_stack generator
155 void dump_stack(void)
157 show_stack(current_thread_info()->task
,
158 (long *) get_irq_regs()->regs
[0]);
160 EXPORT_SYMBOL(dump_stack
);
162 void __die(const char *str
, struct pt_regs
*regs
, const char *file
,
163 const char *func
, unsigned long line
)
168 printk(" in %s:%s, line %ld", file
, func
, line
);
170 show_registers(regs
);
174 void __die_if_kernel(const char *str
, struct pt_regs
*regs
,
175 const char *file
, const char *func
, unsigned long line
)
177 if (!user_mode(regs
))
178 __die(str
, regs
, file
, func
, line
);
181 asmlinkage
void do_adelinsn(struct pt_regs
*regs
)
183 printk("do_ADE-linsn:ema:0x%08lx:epc:0x%08lx\n",
184 regs
->cp0_ema
, regs
->cp0_epc
);
185 die_if_kernel("do_ade execution Exception\n", regs
);
186 force_sig(SIGBUS
, current
);
189 asmlinkage
void do_adedata(struct pt_regs
*regs
)
191 const struct exception_table_entry
*fixup
;
192 fixup
= search_exception_tables(regs
->cp0_epc
);
194 regs
->cp0_epc
= fixup
->fixup
;
197 printk("do_ADE-data:ema:0x%08lx:epc:0x%08lx\n",
198 regs
->cp0_ema
, regs
->cp0_epc
);
199 die_if_kernel("do_ade execution Exception\n", regs
);
200 force_sig(SIGBUS
, current
);
203 asmlinkage
void do_pel(struct pt_regs
*regs
)
205 die_if_kernel("do_pel execution Exception", regs
);
206 force_sig(SIGFPE
, current
);
209 asmlinkage
void do_cee(struct pt_regs
*regs
)
211 die_if_kernel("do_cee execution Exception", regs
);
212 force_sig(SIGFPE
, current
);
215 asmlinkage
void do_cpe(struct pt_regs
*regs
)
217 die_if_kernel("do_cpe execution Exception", regs
);
218 force_sig(SIGFPE
, current
);
221 asmlinkage
void do_be(struct pt_regs
*regs
)
223 die_if_kernel("do_be execution Exception", regs
);
224 force_sig(SIGBUS
, current
);
227 asmlinkage
void do_ov(struct pt_regs
*regs
)
231 die_if_kernel("do_ov execution Exception", regs
);
233 info
.si_code
= FPE_INTOVF
;
234 info
.si_signo
= SIGFPE
;
236 info
.si_addr
= (void *)regs
->cp0_epc
;
237 force_sig_info(SIGFPE
, &info
, current
);
240 asmlinkage
void do_tr(struct pt_regs
*regs
)
242 die_if_kernel("do_tr execution Exception", regs
);
243 force_sig(SIGTRAP
, current
);
246 asmlinkage
void do_ri(struct pt_regs
*regs
)
248 unsigned long epc_insn
;
249 unsigned long epc
= regs
->cp0_epc
;
251 read_tsk_long(current
, epc
, &epc_insn
);
252 if (current
->thread
.single_step
== 1) {
253 if ((epc
== current
->thread
.addr1
) ||
254 (epc
== current
->thread
.addr2
)) {
255 user_disable_single_step(current
);
256 force_sig(SIGTRAP
, current
);
260 } else if ((epc_insn
== BREAKPOINT32_INSN
) ||
261 ((epc_insn
& 0x0000FFFF) == 0x7002) ||
262 ((epc_insn
& 0xFFFF0000) == 0x70020000)) {
263 force_sig(SIGTRAP
, current
);
266 die_if_kernel("do_ri execution Exception", regs
);
267 force_sig(SIGILL
, current
);
271 asmlinkage
void do_ccu(struct pt_regs
*regs
)
273 die_if_kernel("do_ccu execution Exception", regs
);
274 force_sig(SIGILL
, current
);
277 asmlinkage
void do_reserved(struct pt_regs
*regs
)
280 * Game over - no way to handle this if it ever occurs. Most probably
281 * caused by a new unknown cpu type or after another deadly
282 * hard/software error.
284 die_if_kernel("do_reserved execution Exception", regs
);
286 panic("Caught reserved exception - should not happen.");
290 * NMI exception handler.
292 void nmi_exception_handler(struct pt_regs
*regs
)
294 die_if_kernel("nmi_exception_handler execution Exception", regs
);
298 /* Install CPU exception handler */
299 void *set_except_vector(int n
, void *addr
)
301 unsigned long handler
= (unsigned long) addr
;
302 unsigned long old_handler
= exception_handlers
[n
];
304 exception_handlers
[n
] = handler
;
305 return (void *)old_handler
;
308 void __init
trap_init(void)
312 pgd_current
= (unsigned long)init_mm
.pgd
;
313 /* DEBUG EXCEPTION */
314 memcpy((void *)DEBUG_VECTOR_BASE_ADDR
,
315 &debug_exception_vector
, DEBUG_VECTOR_SIZE
);
317 memcpy((void *)GENERAL_VECTOR_BASE_ADDR
,
318 &general_exception_vector
, GENERAL_VECTOR_SIZE
);
321 * Initialise exception handlers
323 for (i
= 0; i
<= 31; i
++)
324 set_except_vector(i
, handle_reserved
);
326 set_except_vector(1, handle_nmi
);
327 set_except_vector(2, handle_adelinsn
);
328 set_except_vector(3, handle_tlb_refill
);
329 set_except_vector(4, handle_tlb_invaild
);
330 set_except_vector(5, handle_ibe
);
331 set_except_vector(6, handle_pel
);
332 set_except_vector(7, handle_sys
);
333 set_except_vector(8, handle_ccu
);
334 set_except_vector(9, handle_ri
);
335 set_except_vector(10, handle_tr
);
336 set_except_vector(11, handle_adedata
);
337 set_except_vector(12, handle_adedata
);
338 set_except_vector(13, handle_tlb_refill
);
339 set_except_vector(14, handle_tlb_invaild
);
340 set_except_vector(15, handle_mod
);
341 set_except_vector(16, handle_cee
);
342 set_except_vector(17, handle_cpe
);
343 set_except_vector(18, handle_dbe
);
344 flush_icache_range(DEBUG_VECTOR_BASE_ADDR
, IRQ_VECTOR_BASE_ADDR
);
346 atomic_inc(&init_mm
.mm_count
);
347 current
->active_mm
= &init_mm
;