16bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin/* 26bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin * arch/score/kernel/traps.c 36bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin * 46bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin * Score Processor version. 56bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin * 66bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin * Copyright (C) 2009 Sunplus Core Technology Co., Ltd. 76bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin * Chen Liqin <liqin.chen@sunplusct.com> 86bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin * Lennox Wu <lennox.wu@sunplusct.com> 96bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin * 106bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin * This program is free software; you can redistribute it and/or modify 116bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin * it under the terms of the GNU General Public License as published by 126bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin * the Free Software Foundation; either version 2 of the License, or 136bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin * (at your option) any later version. 146bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin * 156bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin * This program is distributed in the hope that it will be useful, 166bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin * but WITHOUT ANY WARRANTY; without even the implied warranty of 176bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 186bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin * GNU General Public License for more details. 196bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin * 206bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin * You should have received a copy of the GNU General Public License 216bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin * along with this program; if not, see the file COPYING, or write 226bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin * to the Free Software Foundation, Inc., 236bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 246bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin */ 256bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin 266bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin#include <linux/module.h> 276bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin#include <linux/sched.h> 286bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin 296bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin#include <asm/cacheflush.h> 306bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin#include <asm/irq.h> 316bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin#include <asm/irq_regs.h> 326bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin 336bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqinunsigned long exception_handlers[32]; 346bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin 356bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin/* 366bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin * The architecture-independent show_stack generator 376bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin */ 386bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqinvoid show_stack(struct task_struct *task, unsigned long *sp) 396bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin{ 406bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin int i; 416bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin long stackdata; 426bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin 436bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin sp = sp ? sp : (unsigned long *)&sp; 446bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin 456bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin printk(KERN_NOTICE "Stack: "); 466bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin i = 1; 476bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin while ((long) sp & (PAGE_SIZE - 1)) { 486bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin if (i && ((i % 8) == 0)) 496bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin printk(KERN_NOTICE "\n"); 506bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin if (i > 40) { 516bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin printk(KERN_NOTICE " ..."); 526bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin break; 536bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin } 546bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin 556bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin if (__get_user(stackdata, sp++)) { 566bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin printk(KERN_NOTICE " (Bad stack address)"); 576bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin break; 586bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin } 596bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin 606bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin printk(KERN_NOTICE " %08lx", stackdata); 616bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin i++; 626bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin } 636bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin printk(KERN_NOTICE "\n"); 646bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin} 656bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin 666bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqinstatic void show_trace(long *sp) 676bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin{ 686bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin int i; 696bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin long addr; 706bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin 716bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin sp = sp ? sp : (long *) &sp; 726bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin 736bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin printk(KERN_NOTICE "Call Trace: "); 746bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin i = 1; 756bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin while ((long) sp & (PAGE_SIZE - 1)) { 766bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin if (__get_user(addr, sp++)) { 776bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin if (i && ((i % 6) == 0)) 786bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin printk(KERN_NOTICE "\n"); 796bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin printk(KERN_NOTICE " (Bad stack address)\n"); 806bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin break; 816bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin } 826bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin 836bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin if (kernel_text_address(addr)) { 846bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin if (i && ((i % 6) == 0)) 856bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin printk(KERN_NOTICE "\n"); 866bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin if (i > 40) { 876bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin printk(KERN_NOTICE " ..."); 886bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin break; 896bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin } 906bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin 916bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin printk(KERN_NOTICE " [<%08lx>]", addr); 926bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin i++; 936bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin } 946bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin } 956bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin printk(KERN_NOTICE "\n"); 966bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin} 976bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin 986bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqinstatic void show_code(unsigned int *pc) 996bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin{ 1006bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin long i; 1016bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin 1026bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin printk(KERN_NOTICE "\nCode:"); 1036bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin 1046bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin for (i = -3; i < 6; i++) { 1056bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin unsigned long insn; 1066bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin if (__get_user(insn, pc + i)) { 1076bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin printk(KERN_NOTICE " (Bad address in epc)\n"); 1086bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin break; 1096bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin } 1106bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin printk(KERN_NOTICE "%c%08lx%c", (i ? ' ' : '<'), 1116bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin insn, (i ? ' ' : '>')); 1126bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin } 1136bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin} 1146bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin 1156bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin/* 1166bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin * FIXME: really the generic show_regs should take a const pointer argument. 1176bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin */ 1186bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqinvoid show_regs(struct pt_regs *regs) 1196bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin{ 120a43cb95d547a061ed5bf1acb28e0f5fd575e26c1Tejun Heo show_regs_print_info(KERN_DEFAULT); 121a43cb95d547a061ed5bf1acb28e0f5fd575e26c1Tejun Heo 1226bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin printk("r0 : %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", 1236bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin regs->regs[0], regs->regs[1], regs->regs[2], regs->regs[3], 1246bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin regs->regs[4], regs->regs[5], regs->regs[6], regs->regs[7]); 1256bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin printk("r8 : %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", 1266bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin regs->regs[8], regs->regs[9], regs->regs[10], regs->regs[11], 1276bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin regs->regs[12], regs->regs[13], regs->regs[14], regs->regs[15]); 1286bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin printk("r16: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", 1296bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin regs->regs[16], regs->regs[17], regs->regs[18], regs->regs[19], 1306bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin regs->regs[20], regs->regs[21], regs->regs[22], regs->regs[23]); 1316bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin printk("r24: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", 1326bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin regs->regs[24], regs->regs[25], regs->regs[26], regs->regs[27], 1336bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin regs->regs[28], regs->regs[29], regs->regs[30], regs->regs[31]); 1346bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin 1356bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin printk("CEH : %08lx\n", regs->ceh); 1366bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin printk("CEL : %08lx\n", regs->cel); 1376bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin 1386bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin printk("EMA:%08lx, epc:%08lx %s\nPSR: %08lx\nECR:%08lx\nCondition : %08lx\n", 1396bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin regs->cp0_ema, regs->cp0_epc, print_tainted(), regs->cp0_psr, 1406bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin regs->cp0_ecr, regs->cp0_condition); 1416bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin} 1426bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin 1436bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqinstatic void show_registers(struct pt_regs *regs) 1446bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin{ 1456bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin show_regs(regs); 1466bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin printk(KERN_NOTICE "Process %s (pid: %d, stackpage=%08lx)\n", 1476bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin current->comm, current->pid, (unsigned long) current); 1486bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin show_stack(current_thread_info()->task, (long *) regs->regs[0]); 1496bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin show_trace((long *) regs->regs[0]); 1506bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin show_code((unsigned int *) regs->cp0_epc); 1516bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin printk(KERN_NOTICE "\n"); 1526bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin} 1536bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin 1546bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqinvoid __die(const char *str, struct pt_regs *regs, const char *file, 1556bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin const char *func, unsigned long line) 1566bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin{ 1576bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin console_verbose(); 1586bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin printk("%s", str); 1596bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin if (file && func) 1606bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin printk(" in %s:%s, line %ld", file, func, line); 1616bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin printk(":\n"); 1626bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin show_registers(regs); 1636bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin do_exit(SIGSEGV); 1646bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin} 1656bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin 1666bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqinvoid __die_if_kernel(const char *str, struct pt_regs *regs, 1676bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin const char *file, const char *func, unsigned long line) 1686bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin{ 1696bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin if (!user_mode(regs)) 1706bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin __die(str, regs, file, func, line); 1716bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin} 1726bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin 1736bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqinasmlinkage void do_adelinsn(struct pt_regs *regs) 1746bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin{ 1756bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin printk("do_ADE-linsn:ema:0x%08lx:epc:0x%08lx\n", 1766bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin regs->cp0_ema, regs->cp0_epc); 1776bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin die_if_kernel("do_ade execution Exception\n", regs); 1786bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin force_sig(SIGBUS, current); 1796bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin} 1806bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin 1816bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqinasmlinkage void do_adedata(struct pt_regs *regs) 1826bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin{ 1836bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin const struct exception_table_entry *fixup; 1846bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin fixup = search_exception_tables(regs->cp0_epc); 1856bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin if (fixup) { 1866bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin regs->cp0_epc = fixup->fixup; 1876bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin return; 1886bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin } 1896bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin printk("do_ADE-data:ema:0x%08lx:epc:0x%08lx\n", 1906bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin regs->cp0_ema, regs->cp0_epc); 1916bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin die_if_kernel("do_ade execution Exception\n", regs); 1926bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin force_sig(SIGBUS, current); 1936bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin} 1946bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin 1956bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqinasmlinkage void do_pel(struct pt_regs *regs) 1966bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin{ 1976bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin die_if_kernel("do_pel execution Exception", regs); 1986bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin force_sig(SIGFPE, current); 1996bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin} 2006bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin 2016bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqinasmlinkage void do_cee(struct pt_regs *regs) 2026bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin{ 2036bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin die_if_kernel("do_cee execution Exception", regs); 2046bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin force_sig(SIGFPE, current); 2056bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin} 2066bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin 2076bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqinasmlinkage void do_cpe(struct pt_regs *regs) 2086bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin{ 2096bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin die_if_kernel("do_cpe execution Exception", regs); 2106bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin force_sig(SIGFPE, current); 2116bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin} 2126bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin 2136bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqinasmlinkage void do_be(struct pt_regs *regs) 2146bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin{ 2156bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin die_if_kernel("do_be execution Exception", regs); 2166bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin force_sig(SIGBUS, current); 2176bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin} 2186bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin 2196bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqinasmlinkage void do_ov(struct pt_regs *regs) 2206bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin{ 2216bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin siginfo_t info; 2226bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin 2236bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin die_if_kernel("do_ov execution Exception", regs); 2246bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin 2256bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin info.si_code = FPE_INTOVF; 2266bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin info.si_signo = SIGFPE; 2276bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin info.si_errno = 0; 2286bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin info.si_addr = (void *)regs->cp0_epc; 2296bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin force_sig_info(SIGFPE, &info, current); 2306bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin} 2316bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin 2326bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqinasmlinkage void do_tr(struct pt_regs *regs) 2336bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin{ 2346bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin die_if_kernel("do_tr execution Exception", regs); 2356bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin force_sig(SIGTRAP, current); 2366bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin} 2376bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin 2386bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqinasmlinkage void do_ri(struct pt_regs *regs) 2396bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin{ 2406bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin unsigned long epc_insn; 2416bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin unsigned long epc = regs->cp0_epc; 2426bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin 2436bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin read_tsk_long(current, epc, &epc_insn); 2446bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin if (current->thread.single_step == 1) { 2456bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin if ((epc == current->thread.addr1) || 2466bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin (epc == current->thread.addr2)) { 2470402c91af944c61bf788370f03326959a35cb8beChen Liqin user_disable_single_step(current); 2486bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin force_sig(SIGTRAP, current); 2496bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin return; 2506bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin } else 2516bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin BUG(); 2526bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin } else if ((epc_insn == BREAKPOINT32_INSN) || 2536bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin ((epc_insn & 0x0000FFFF) == 0x7002) || 2546bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin ((epc_insn & 0xFFFF0000) == 0x70020000)) { 2556bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin force_sig(SIGTRAP, current); 2566bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin return; 2576bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin } else { 2586bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin die_if_kernel("do_ri execution Exception", regs); 2596bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin force_sig(SIGILL, current); 2606bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin } 2616bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin} 2626bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin 2636bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqinasmlinkage void do_ccu(struct pt_regs *regs) 2646bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin{ 2656bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin die_if_kernel("do_ccu execution Exception", regs); 2666bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin force_sig(SIGILL, current); 2676bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin} 2686bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin 2696bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqinasmlinkage void do_reserved(struct pt_regs *regs) 2706bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin{ 2716bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin /* 2726bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin * Game over - no way to handle this if it ever occurs. Most probably 2736bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin * caused by a new unknown cpu type or after another deadly 2746bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin * hard/software error. 2756bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin */ 2766bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin die_if_kernel("do_reserved execution Exception", regs); 2776bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin show_regs(regs); 2786bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin panic("Caught reserved exception - should not happen."); 2796bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin} 2806bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin 2816bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin/* 2826bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin * NMI exception handler. 2836bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin */ 2846bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqinvoid nmi_exception_handler(struct pt_regs *regs) 2856bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin{ 2866bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin die_if_kernel("nmi_exception_handler execution Exception", regs); 2876bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin die("NMI", regs); 2886bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin} 2896bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin 2906bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin/* Install CPU exception handler */ 2916bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqinvoid *set_except_vector(int n, void *addr) 2926bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin{ 2936bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin unsigned long handler = (unsigned long) addr; 2946bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin unsigned long old_handler = exception_handlers[n]; 2956bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin 2966bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin exception_handlers[n] = handler; 2976bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin return (void *)old_handler; 2986bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin} 2996bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin 3006bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqinvoid __init trap_init(void) 3016bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin{ 3026bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin int i; 3036bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin 3046bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin pgd_current = (unsigned long)init_mm.pgd; 3056bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin /* DEBUG EXCEPTION */ 3066bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin memcpy((void *)DEBUG_VECTOR_BASE_ADDR, 3076bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin &debug_exception_vector, DEBUG_VECTOR_SIZE); 3086bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin /* NMI EXCEPTION */ 3096bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin memcpy((void *)GENERAL_VECTOR_BASE_ADDR, 3106bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin &general_exception_vector, GENERAL_VECTOR_SIZE); 3116bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin 3126bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin /* 3136bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin * Initialise exception handlers 3146bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin */ 3156bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin for (i = 0; i <= 31; i++) 3166bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin set_except_vector(i, handle_reserved); 3176bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin 3186bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin set_except_vector(1, handle_nmi); 3196bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin set_except_vector(2, handle_adelinsn); 3206bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin set_except_vector(3, handle_tlb_refill); 3216bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin set_except_vector(4, handle_tlb_invaild); 3226bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin set_except_vector(5, handle_ibe); 3236bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin set_except_vector(6, handle_pel); 3246bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin set_except_vector(7, handle_sys); 3256bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin set_except_vector(8, handle_ccu); 3266bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin set_except_vector(9, handle_ri); 3276bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin set_except_vector(10, handle_tr); 3286bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin set_except_vector(11, handle_adedata); 3296bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin set_except_vector(12, handle_adedata); 3306bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin set_except_vector(13, handle_tlb_refill); 3316bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin set_except_vector(14, handle_tlb_invaild); 3326bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin set_except_vector(15, handle_mod); 3336bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin set_except_vector(16, handle_cee); 3346bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin set_except_vector(17, handle_cpe); 3356bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin set_except_vector(18, handle_dbe); 3366bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin flush_icache_range(DEBUG_VECTOR_BASE_ADDR, IRQ_VECTOR_BASE_ADDR); 3376bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin 3386bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin atomic_inc(&init_mm.mm_count); 3396bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin current->active_mm = &init_mm; 3406bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin cpu_cache_init(); 3416bc9a3966f0395419b09b2ec90f89f7f00341b37Chen Liqin} 342