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 show_regs_print_info(KERN_DEFAULT
);
122 printk("r0 : %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
123 regs
->regs
[0], regs
->regs
[1], regs
->regs
[2], regs
->regs
[3],
124 regs
->regs
[4], regs
->regs
[5], regs
->regs
[6], regs
->regs
[7]);
125 printk("r8 : %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
126 regs
->regs
[8], regs
->regs
[9], regs
->regs
[10], regs
->regs
[11],
127 regs
->regs
[12], regs
->regs
[13], regs
->regs
[14], regs
->regs
[15]);
128 printk("r16: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
129 regs
->regs
[16], regs
->regs
[17], regs
->regs
[18], regs
->regs
[19],
130 regs
->regs
[20], regs
->regs
[21], regs
->regs
[22], regs
->regs
[23]);
131 printk("r24: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
132 regs
->regs
[24], regs
->regs
[25], regs
->regs
[26], regs
->regs
[27],
133 regs
->regs
[28], regs
->regs
[29], regs
->regs
[30], regs
->regs
[31]);
135 printk("CEH : %08lx\n", regs
->ceh
);
136 printk("CEL : %08lx\n", regs
->cel
);
138 printk("EMA:%08lx, epc:%08lx %s\nPSR: %08lx\nECR:%08lx\nCondition : %08lx\n",
139 regs
->cp0_ema
, regs
->cp0_epc
, print_tainted(), regs
->cp0_psr
,
140 regs
->cp0_ecr
, regs
->cp0_condition
);
143 static void show_registers(struct pt_regs
*regs
)
146 printk(KERN_NOTICE
"Process %s (pid: %d, stackpage=%08lx)\n",
147 current
->comm
, current
->pid
, (unsigned long) current
);
148 show_stack(current_thread_info()->task
, (long *) regs
->regs
[0]);
149 show_trace((long *) regs
->regs
[0]);
150 show_code((unsigned int *) regs
->cp0_epc
);
151 printk(KERN_NOTICE
"\n");
154 void __die(const char *str
, struct pt_regs
*regs
, const char *file
,
155 const char *func
, unsigned long line
)
160 printk(" in %s:%s, line %ld", file
, func
, line
);
162 show_registers(regs
);
166 void __die_if_kernel(const char *str
, struct pt_regs
*regs
,
167 const char *file
, const char *func
, unsigned long line
)
169 if (!user_mode(regs
))
170 __die(str
, regs
, file
, func
, line
);
173 asmlinkage
void do_adelinsn(struct pt_regs
*regs
)
175 printk("do_ADE-linsn:ema:0x%08lx:epc:0x%08lx\n",
176 regs
->cp0_ema
, regs
->cp0_epc
);
177 die_if_kernel("do_ade execution Exception\n", regs
);
178 force_sig(SIGBUS
, current
);
181 asmlinkage
void do_adedata(struct pt_regs
*regs
)
183 const struct exception_table_entry
*fixup
;
184 fixup
= search_exception_tables(regs
->cp0_epc
);
186 regs
->cp0_epc
= fixup
->fixup
;
189 printk("do_ADE-data:ema:0x%08lx:epc:0x%08lx\n",
190 regs
->cp0_ema
, regs
->cp0_epc
);
191 die_if_kernel("do_ade execution Exception\n", regs
);
192 force_sig(SIGBUS
, current
);
195 asmlinkage
void do_pel(struct pt_regs
*regs
)
197 die_if_kernel("do_pel execution Exception", regs
);
198 force_sig(SIGFPE
, current
);
201 asmlinkage
void do_cee(struct pt_regs
*regs
)
203 die_if_kernel("do_cee execution Exception", regs
);
204 force_sig(SIGFPE
, current
);
207 asmlinkage
void do_cpe(struct pt_regs
*regs
)
209 die_if_kernel("do_cpe execution Exception", regs
);
210 force_sig(SIGFPE
, current
);
213 asmlinkage
void do_be(struct pt_regs
*regs
)
215 die_if_kernel("do_be execution Exception", regs
);
216 force_sig(SIGBUS
, current
);
219 asmlinkage
void do_ov(struct pt_regs
*regs
)
223 die_if_kernel("do_ov execution Exception", regs
);
225 info
.si_code
= FPE_INTOVF
;
226 info
.si_signo
= SIGFPE
;
228 info
.si_addr
= (void *)regs
->cp0_epc
;
229 force_sig_info(SIGFPE
, &info
, current
);
232 asmlinkage
void do_tr(struct pt_regs
*regs
)
234 die_if_kernel("do_tr execution Exception", regs
);
235 force_sig(SIGTRAP
, current
);
238 asmlinkage
void do_ri(struct pt_regs
*regs
)
240 unsigned long epc_insn
;
241 unsigned long epc
= regs
->cp0_epc
;
243 read_tsk_long(current
, epc
, &epc_insn
);
244 if (current
->thread
.single_step
== 1) {
245 if ((epc
== current
->thread
.addr1
) ||
246 (epc
== current
->thread
.addr2
)) {
247 user_disable_single_step(current
);
248 force_sig(SIGTRAP
, current
);
252 } else if ((epc_insn
== BREAKPOINT32_INSN
) ||
253 ((epc_insn
& 0x0000FFFF) == 0x7002) ||
254 ((epc_insn
& 0xFFFF0000) == 0x70020000)) {
255 force_sig(SIGTRAP
, current
);
258 die_if_kernel("do_ri execution Exception", regs
);
259 force_sig(SIGILL
, current
);
263 asmlinkage
void do_ccu(struct pt_regs
*regs
)
265 die_if_kernel("do_ccu execution Exception", regs
);
266 force_sig(SIGILL
, current
);
269 asmlinkage
void do_reserved(struct pt_regs
*regs
)
272 * Game over - no way to handle this if it ever occurs. Most probably
273 * caused by a new unknown cpu type or after another deadly
274 * hard/software error.
276 die_if_kernel("do_reserved execution Exception", regs
);
278 panic("Caught reserved exception - should not happen.");
282 * NMI exception handler.
284 void nmi_exception_handler(struct pt_regs
*regs
)
286 die_if_kernel("nmi_exception_handler execution Exception", regs
);
290 /* Install CPU exception handler */
291 void *set_except_vector(int n
, void *addr
)
293 unsigned long handler
= (unsigned long) addr
;
294 unsigned long old_handler
= exception_handlers
[n
];
296 exception_handlers
[n
] = handler
;
297 return (void *)old_handler
;
300 void __init
trap_init(void)
304 pgd_current
= (unsigned long)init_mm
.pgd
;
305 /* DEBUG EXCEPTION */
306 memcpy((void *)DEBUG_VECTOR_BASE_ADDR
,
307 &debug_exception_vector
, DEBUG_VECTOR_SIZE
);
309 memcpy((void *)GENERAL_VECTOR_BASE_ADDR
,
310 &general_exception_vector
, GENERAL_VECTOR_SIZE
);
313 * Initialise exception handlers
315 for (i
= 0; i
<= 31; i
++)
316 set_except_vector(i
, handle_reserved
);
318 set_except_vector(1, handle_nmi
);
319 set_except_vector(2, handle_adelinsn
);
320 set_except_vector(3, handle_tlb_refill
);
321 set_except_vector(4, handle_tlb_invaild
);
322 set_except_vector(5, handle_ibe
);
323 set_except_vector(6, handle_pel
);
324 set_except_vector(7, handle_sys
);
325 set_except_vector(8, handle_ccu
);
326 set_except_vector(9, handle_ri
);
327 set_except_vector(10, handle_tr
);
328 set_except_vector(11, handle_adedata
);
329 set_except_vector(12, handle_adedata
);
330 set_except_vector(13, handle_tlb_refill
);
331 set_except_vector(14, handle_tlb_invaild
);
332 set_except_vector(15, handle_mod
);
333 set_except_vector(16, handle_cee
);
334 set_except_vector(17, handle_cpe
);
335 set_except_vector(18, handle_dbe
);
336 flush_icache_range(DEBUG_VECTOR_BASE_ADDR
, IRQ_VECTOR_BASE_ADDR
);
338 atomic_inc(&init_mm
.mm_count
);
339 current
->active_mm
= &init_mm
;