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/extable.h>
27 #include <linux/ptrace.h>
28 #include <linux/sched/mm.h>
29 #include <linux/sched/signal.h>
30 #include <linux/sched/debug.h>
31 #include <linux/mm_types.h>
33 #include <asm/cacheflush.h>
35 #include <asm/irq_regs.h>
36 #include <linux/uaccess.h>
38 unsigned long exception_handlers
[32];
41 * The architecture-independent show_stack generator
43 void show_stack(struct task_struct
*task
, unsigned long *sp
)
48 sp
= sp
? sp
: (unsigned long *)&sp
;
50 printk(KERN_NOTICE
"Stack: ");
52 while ((long) sp
& (PAGE_SIZE
- 1)) {
53 if (i
&& ((i
% 8) == 0))
54 printk(KERN_NOTICE
"\n");
56 printk(KERN_NOTICE
" ...");
60 if (__get_user(stackdata
, sp
++)) {
61 printk(KERN_NOTICE
" (Bad stack address)");
65 printk(KERN_NOTICE
" %08lx", stackdata
);
68 printk(KERN_NOTICE
"\n");
71 static void show_trace(long *sp
)
76 sp
= sp
? sp
: (long *) &sp
;
78 printk(KERN_NOTICE
"Call Trace: ");
80 while ((long) sp
& (PAGE_SIZE
- 1)) {
81 if (__get_user(addr
, sp
++)) {
82 if (i
&& ((i
% 6) == 0))
83 printk(KERN_NOTICE
"\n");
84 printk(KERN_NOTICE
" (Bad stack address)\n");
88 if (kernel_text_address(addr
)) {
89 if (i
&& ((i
% 6) == 0))
90 printk(KERN_NOTICE
"\n");
92 printk(KERN_NOTICE
" ...");
96 printk(KERN_NOTICE
" [<%08lx>]", addr
);
100 printk(KERN_NOTICE
"\n");
103 static void show_code(unsigned int *pc
)
107 printk(KERN_NOTICE
"\nCode:");
109 for (i
= -3; i
< 6; i
++) {
111 if (__get_user(insn
, pc
+ i
)) {
112 printk(KERN_NOTICE
" (Bad address in epc)\n");
115 printk(KERN_NOTICE
"%c%08lx%c", (i
? ' ' : '<'),
116 insn
, (i
? ' ' : '>'));
121 * FIXME: really the generic show_regs should take a const pointer argument.
123 void show_regs(struct pt_regs
*regs
)
125 show_regs_print_info(KERN_DEFAULT
);
127 printk("r0 : %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
128 regs
->regs
[0], regs
->regs
[1], regs
->regs
[2], regs
->regs
[3],
129 regs
->regs
[4], regs
->regs
[5], regs
->regs
[6], regs
->regs
[7]);
130 printk("r8 : %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
131 regs
->regs
[8], regs
->regs
[9], regs
->regs
[10], regs
->regs
[11],
132 regs
->regs
[12], regs
->regs
[13], regs
->regs
[14], regs
->regs
[15]);
133 printk("r16: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
134 regs
->regs
[16], regs
->regs
[17], regs
->regs
[18], regs
->regs
[19],
135 regs
->regs
[20], regs
->regs
[21], regs
->regs
[22], regs
->regs
[23]);
136 printk("r24: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
137 regs
->regs
[24], regs
->regs
[25], regs
->regs
[26], regs
->regs
[27],
138 regs
->regs
[28], regs
->regs
[29], regs
->regs
[30], regs
->regs
[31]);
140 printk("CEH : %08lx\n", regs
->ceh
);
141 printk("CEL : %08lx\n", regs
->cel
);
143 printk("EMA:%08lx, epc:%08lx %s\nPSR: %08lx\nECR:%08lx\nCondition : %08lx\n",
144 regs
->cp0_ema
, regs
->cp0_epc
, print_tainted(), regs
->cp0_psr
,
145 regs
->cp0_ecr
, regs
->cp0_condition
);
148 static void show_registers(struct pt_regs
*regs
)
151 printk(KERN_NOTICE
"Process %s (pid: %d, stackpage=%08lx)\n",
152 current
->comm
, current
->pid
, (unsigned long) current
);
153 show_stack(current_thread_info()->task
, (long *) regs
->regs
[0]);
154 show_trace((long *) regs
->regs
[0]);
155 show_code((unsigned int *) regs
->cp0_epc
);
156 printk(KERN_NOTICE
"\n");
159 void __die(const char *str
, struct pt_regs
*regs
, const char *file
,
160 const char *func
, unsigned long line
)
165 printk(" in %s:%s, line %ld", file
, func
, line
);
167 show_registers(regs
);
171 void __die_if_kernel(const char *str
, struct pt_regs
*regs
,
172 const char *file
, const char *func
, unsigned long line
)
174 if (!user_mode(regs
))
175 __die(str
, regs
, file
, func
, line
);
178 asmlinkage
void do_adelinsn(struct pt_regs
*regs
)
180 printk("do_ADE-linsn:ema:0x%08lx:epc:0x%08lx\n",
181 regs
->cp0_ema
, regs
->cp0_epc
);
182 die_if_kernel("do_ade execution Exception\n", regs
);
183 force_sig(SIGBUS
, current
);
186 asmlinkage
void do_adedata(struct pt_regs
*regs
)
188 const struct exception_table_entry
*fixup
;
189 fixup
= search_exception_tables(regs
->cp0_epc
);
191 regs
->cp0_epc
= fixup
->fixup
;
194 printk("do_ADE-data:ema:0x%08lx:epc:0x%08lx\n",
195 regs
->cp0_ema
, regs
->cp0_epc
);
196 die_if_kernel("do_ade execution Exception\n", regs
);
197 force_sig(SIGBUS
, current
);
200 asmlinkage
void do_pel(struct pt_regs
*regs
)
202 die_if_kernel("do_pel execution Exception", regs
);
203 force_sig(SIGFPE
, current
);
206 asmlinkage
void do_cee(struct pt_regs
*regs
)
208 die_if_kernel("do_cee execution Exception", regs
);
209 force_sig(SIGFPE
, current
);
212 asmlinkage
void do_cpe(struct pt_regs
*regs
)
214 die_if_kernel("do_cpe execution Exception", regs
);
215 force_sig(SIGFPE
, current
);
218 asmlinkage
void do_be(struct pt_regs
*regs
)
220 die_if_kernel("do_be execution Exception", regs
);
221 force_sig(SIGBUS
, current
);
224 asmlinkage
void do_ov(struct pt_regs
*regs
)
228 die_if_kernel("do_ov execution Exception", regs
);
230 info
.si_code
= FPE_INTOVF
;
231 info
.si_signo
= SIGFPE
;
233 info
.si_addr
= (void *)regs
->cp0_epc
;
234 force_sig_info(SIGFPE
, &info
, current
);
237 asmlinkage
void do_tr(struct pt_regs
*regs
)
239 die_if_kernel("do_tr execution Exception", regs
);
240 force_sig(SIGTRAP
, current
);
243 asmlinkage
void do_ri(struct pt_regs
*regs
)
245 unsigned long epc_insn
;
246 unsigned long epc
= regs
->cp0_epc
;
248 read_tsk_long(current
, epc
, &epc_insn
);
249 if (current
->thread
.single_step
== 1) {
250 if ((epc
== current
->thread
.addr1
) ||
251 (epc
== current
->thread
.addr2
)) {
252 user_disable_single_step(current
);
253 force_sig(SIGTRAP
, current
);
257 } else if ((epc_insn
== BREAKPOINT32_INSN
) ||
258 ((epc_insn
& 0x0000FFFF) == 0x7002) ||
259 ((epc_insn
& 0xFFFF0000) == 0x70020000)) {
260 force_sig(SIGTRAP
, current
);
263 die_if_kernel("do_ri execution Exception", regs
);
264 force_sig(SIGILL
, current
);
268 asmlinkage
void do_ccu(struct pt_regs
*regs
)
270 die_if_kernel("do_ccu execution Exception", regs
);
271 force_sig(SIGILL
, current
);
274 asmlinkage
void do_reserved(struct pt_regs
*regs
)
277 * Game over - no way to handle this if it ever occurs. Most probably
278 * caused by a new unknown cpu type or after another deadly
279 * hard/software error.
281 die_if_kernel("do_reserved execution Exception", regs
);
283 panic("Caught reserved exception - should not happen.");
287 * NMI exception handler.
289 void nmi_exception_handler(struct pt_regs
*regs
)
291 die_if_kernel("nmi_exception_handler execution Exception", regs
);
295 /* Install CPU exception handler */
296 void *set_except_vector(int n
, void *addr
)
298 unsigned long handler
= (unsigned long) addr
;
299 unsigned long old_handler
= exception_handlers
[n
];
301 exception_handlers
[n
] = handler
;
302 return (void *)old_handler
;
305 void __init
trap_init(void)
309 pgd_current
= (unsigned long)init_mm
.pgd
;
310 /* DEBUG EXCEPTION */
311 memcpy((void *)DEBUG_VECTOR_BASE_ADDR
,
312 &debug_exception_vector
, DEBUG_VECTOR_SIZE
);
314 memcpy((void *)GENERAL_VECTOR_BASE_ADDR
,
315 &general_exception_vector
, GENERAL_VECTOR_SIZE
);
318 * Initialise exception handlers
320 for (i
= 0; i
<= 31; i
++)
321 set_except_vector(i
, handle_reserved
);
323 set_except_vector(1, handle_nmi
);
324 set_except_vector(2, handle_adelinsn
);
325 set_except_vector(3, handle_tlb_refill
);
326 set_except_vector(4, handle_tlb_invaild
);
327 set_except_vector(5, handle_ibe
);
328 set_except_vector(6, handle_pel
);
329 set_except_vector(7, handle_sys
);
330 set_except_vector(8, handle_ccu
);
331 set_except_vector(9, handle_ri
);
332 set_except_vector(10, handle_tr
);
333 set_except_vector(11, handle_adedata
);
334 set_except_vector(12, handle_adedata
);
335 set_except_vector(13, handle_tlb_refill
);
336 set_except_vector(14, handle_tlb_invaild
);
337 set_except_vector(15, handle_mod
);
338 set_except_vector(16, handle_cee
);
339 set_except_vector(17, handle_cpe
);
340 set_except_vector(18, handle_dbe
);
341 flush_icache_range(DEBUG_VECTOR_BASE_ADDR
, IRQ_VECTOR_BASE_ADDR
);
344 current
->active_mm
= &init_mm
;