1081860b9SGuo Ren // SPDX-License-Identifier: GPL-2.0 2081860b9SGuo Ren // Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. 3081860b9SGuo Ren 4081860b9SGuo Ren #include <linux/sched.h> 5081860b9SGuo Ren #include <linux/signal.h> 6081860b9SGuo Ren #include <linux/kernel.h> 7081860b9SGuo Ren #include <linux/mm.h> 8081860b9SGuo Ren #include <linux/module.h> 9081860b9SGuo Ren #include <linux/user.h> 10081860b9SGuo Ren #include <linux/string.h> 11081860b9SGuo Ren #include <linux/linkage.h> 12081860b9SGuo Ren #include <linux/init.h> 13081860b9SGuo Ren #include <linux/ptrace.h> 14081860b9SGuo Ren #include <linux/kallsyms.h> 15081860b9SGuo Ren #include <linux/rtc.h> 16081860b9SGuo Ren #include <linux/uaccess.h> 1733e53ae1SGuo Ren #include <linux/kprobes.h> 185bc46ce2SGuo Ren #include <linux/kdebug.h> 195bc46ce2SGuo Ren #include <linux/sched/debug.h> 20081860b9SGuo Ren 21081860b9SGuo Ren #include <asm/setup.h> 22081860b9SGuo Ren #include <asm/traps.h> 23081860b9SGuo Ren #include <asm/pgalloc.h> 24081860b9SGuo Ren #include <asm/siginfo.h> 25081860b9SGuo Ren 26081860b9SGuo Ren #include <asm/mmu_context.h> 27081860b9SGuo Ren 28081860b9SGuo Ren #ifdef CONFIG_CPU_HAS_FPU 29081860b9SGuo Ren #include <abi/fpu.h> 30081860b9SGuo Ren #endif 31081860b9SGuo Ren 325bc46ce2SGuo Ren int show_unhandled_signals = 1; 335bc46ce2SGuo Ren 34081860b9SGuo Ren /* Defined in entry.S */ 35081860b9SGuo Ren asmlinkage void csky_trap(void); 36081860b9SGuo Ren 37081860b9SGuo Ren asmlinkage void csky_systemcall(void); 38081860b9SGuo Ren asmlinkage void csky_cmpxchg(void); 39081860b9SGuo Ren asmlinkage void csky_get_tls(void); 40081860b9SGuo Ren asmlinkage void csky_irq(void); 41081860b9SGuo Ren 42*b0ae5e26SGuo Ren asmlinkage void csky_pagefault(void); 43081860b9SGuo Ren 44081860b9SGuo Ren /* Defined in head.S */ 45081860b9SGuo Ren asmlinkage void _start_smp_secondary(void); 46081860b9SGuo Ren 47081860b9SGuo Ren void __init pre_trap_init(void) 48081860b9SGuo Ren { 49081860b9SGuo Ren int i; 50081860b9SGuo Ren 51081860b9SGuo Ren mtcr("vbr", vec_base); 52081860b9SGuo Ren 53081860b9SGuo Ren for (i = 1; i < 128; i++) 54081860b9SGuo Ren VEC_INIT(i, csky_trap); 55081860b9SGuo Ren } 56081860b9SGuo Ren 57081860b9SGuo Ren void __init trap_init(void) 58081860b9SGuo Ren { 59081860b9SGuo Ren VEC_INIT(VEC_AUTOVEC, csky_irq); 60081860b9SGuo Ren 61081860b9SGuo Ren /* setup trap0 trap2 trap3 */ 62081860b9SGuo Ren VEC_INIT(VEC_TRAP0, csky_systemcall); 63081860b9SGuo Ren VEC_INIT(VEC_TRAP2, csky_cmpxchg); 64081860b9SGuo Ren VEC_INIT(VEC_TRAP3, csky_get_tls); 65081860b9SGuo Ren 66081860b9SGuo Ren /* setup MMU TLB exception */ 67*b0ae5e26SGuo Ren VEC_INIT(VEC_TLBINVALIDL, csky_pagefault); 68*b0ae5e26SGuo Ren VEC_INIT(VEC_TLBINVALIDS, csky_pagefault); 69*b0ae5e26SGuo Ren VEC_INIT(VEC_TLBMODIFIED, csky_pagefault); 70081860b9SGuo Ren 71081860b9SGuo Ren #ifdef CONFIG_CPU_HAS_FPU 72081860b9SGuo Ren init_fpu(); 73081860b9SGuo Ren #endif 74081860b9SGuo Ren 75081860b9SGuo Ren #ifdef CONFIG_SMP 76081860b9SGuo Ren mtcr("cr<28, 0>", virt_to_phys(vec_base)); 77081860b9SGuo Ren 78081860b9SGuo Ren VEC_INIT(VEC_RESET, (void *)virt_to_phys(_start_smp_secondary)); 79081860b9SGuo Ren #endif 80081860b9SGuo Ren } 81081860b9SGuo Ren 825bc46ce2SGuo Ren static DEFINE_SPINLOCK(die_lock); 83081860b9SGuo Ren 845bc46ce2SGuo Ren void die(struct pt_regs *regs, const char *str) 855bc46ce2SGuo Ren { 865bc46ce2SGuo Ren static int die_counter; 875bc46ce2SGuo Ren int ret; 885bc46ce2SGuo Ren 895bc46ce2SGuo Ren oops_enter(); 905bc46ce2SGuo Ren 915bc46ce2SGuo Ren spin_lock_irq(&die_lock); 92081860b9SGuo Ren console_verbose(); 935bc46ce2SGuo Ren bust_spinlocks(1); 945bc46ce2SGuo Ren 955bc46ce2SGuo Ren pr_emerg("%s [#%d]\n", str, ++die_counter); 965bc46ce2SGuo Ren print_modules(); 97081860b9SGuo Ren show_regs(regs); 985bc46ce2SGuo Ren show_stack(current, (unsigned long *)regs->regs[4], KERN_INFO); 995bc46ce2SGuo Ren 1005bc46ce2SGuo Ren ret = notify_die(DIE_OOPS, str, regs, 0, trap_no(regs), SIGSEGV); 1015bc46ce2SGuo Ren 1025bc46ce2SGuo Ren bust_spinlocks(0); 103081860b9SGuo Ren add_taint(TAINT_DIE, LOCKDEP_NOW_UNRELIABLE); 1045bc46ce2SGuo Ren spin_unlock_irq(&die_lock); 1055bc46ce2SGuo Ren oops_exit(); 1065bc46ce2SGuo Ren 1075bc46ce2SGuo Ren if (in_interrupt()) 1085bc46ce2SGuo Ren panic("Fatal exception in interrupt"); 1095bc46ce2SGuo Ren if (panic_on_oops) 1105bc46ce2SGuo Ren panic("Fatal exception"); 1115bc46ce2SGuo Ren if (ret != NOTIFY_STOP) 112081860b9SGuo Ren do_exit(SIGSEGV); 113081860b9SGuo Ren } 114081860b9SGuo Ren 1155bc46ce2SGuo Ren void do_trap(struct pt_regs *regs, int signo, int code, unsigned long addr) 116081860b9SGuo Ren { 1179c0e343dSGuo Ren struct task_struct *tsk = current; 118081860b9SGuo Ren 1195bc46ce2SGuo Ren if (show_unhandled_signals && unhandled_signal(tsk, signo) 1205bc46ce2SGuo Ren && printk_ratelimit()) { 1215bc46ce2SGuo Ren pr_info("%s[%d]: unhandled signal %d code 0x%x at 0x%08lx", 1225bc46ce2SGuo Ren tsk->comm, task_pid_nr(tsk), signo, code, addr); 1235bc46ce2SGuo Ren print_vma_addr(KERN_CONT " in ", instruction_pointer(regs)); 1245bc46ce2SGuo Ren pr_cont("\n"); 1255bc46ce2SGuo Ren show_regs(regs); 1265bc46ce2SGuo Ren } 127081860b9SGuo Ren 1285bc46ce2SGuo Ren force_sig_fault(signo, code, (void __user *)addr); 1295bc46ce2SGuo Ren } 1305bc46ce2SGuo Ren 1315bc46ce2SGuo Ren static void do_trap_error(struct pt_regs *regs, int signo, int code, 1325bc46ce2SGuo Ren unsigned long addr, const char *str) 1335bc46ce2SGuo Ren { 1345bc46ce2SGuo Ren current->thread.trap_no = trap_no(regs); 1355bc46ce2SGuo Ren 1365bc46ce2SGuo Ren if (user_mode(regs)) { 1375bc46ce2SGuo Ren do_trap(regs, signo, code, addr); 1385bc46ce2SGuo Ren } else { 1395bc46ce2SGuo Ren if (!fixup_exception(regs)) 1405bc46ce2SGuo Ren die(regs, str); 1415bc46ce2SGuo Ren } 1425bc46ce2SGuo Ren } 1435bc46ce2SGuo Ren 1445bc46ce2SGuo Ren #define DO_ERROR_INFO(name, signo, code, str) \ 1455bc46ce2SGuo Ren asmlinkage __visible void name(struct pt_regs *regs) \ 1465bc46ce2SGuo Ren { \ 1475bc46ce2SGuo Ren do_trap_error(regs, signo, code, regs->pc, "Oops - " str); \ 1485bc46ce2SGuo Ren } 1495bc46ce2SGuo Ren 1505bc46ce2SGuo Ren DO_ERROR_INFO(do_trap_unknown, 1515bc46ce2SGuo Ren SIGILL, ILL_ILLTRP, "unknown exception"); 1525bc46ce2SGuo Ren DO_ERROR_INFO(do_trap_zdiv, 1535bc46ce2SGuo Ren SIGFPE, FPE_INTDIV, "error zero div exception"); 1545bc46ce2SGuo Ren DO_ERROR_INFO(do_trap_buserr, 1555bc46ce2SGuo Ren SIGSEGV, ILL_ILLADR, "error bus error exception"); 1565bc46ce2SGuo Ren 1575bc46ce2SGuo Ren asmlinkage void do_trap_misaligned(struct pt_regs *regs) 1585bc46ce2SGuo Ren { 1595bc46ce2SGuo Ren #ifdef CONFIG_CPU_NEED_SOFTALIGN 1605bc46ce2SGuo Ren csky_alignment(regs); 1615bc46ce2SGuo Ren #else 1625bc46ce2SGuo Ren current->thread.trap_no = trap_no(regs); 1635bc46ce2SGuo Ren do_trap_error(regs, SIGBUS, BUS_ADRALN, regs->pc, 1645bc46ce2SGuo Ren "Oops - load/store address misaligned"); 1655bc46ce2SGuo Ren #endif 1665bc46ce2SGuo Ren } 1675bc46ce2SGuo Ren 1685bc46ce2SGuo Ren asmlinkage void do_trap_bkpt(struct pt_regs *regs) 1695bc46ce2SGuo Ren { 17033e53ae1SGuo Ren #ifdef CONFIG_KPROBES 17133e53ae1SGuo Ren if (kprobe_single_step_handler(regs)) 17233e53ae1SGuo Ren return; 17333e53ae1SGuo Ren #endif 1748f6bb793SGuo Ren #ifdef CONFIG_UPROBES 1758f6bb793SGuo Ren if (uprobe_single_step_handler(regs)) 1768f6bb793SGuo Ren return; 1778f6bb793SGuo Ren #endif 1785bc46ce2SGuo Ren if (user_mode(regs)) { 1795bc46ce2SGuo Ren send_sig(SIGTRAP, current, 0); 1805bc46ce2SGuo Ren return; 1815bc46ce2SGuo Ren } 1825bc46ce2SGuo Ren 1835bc46ce2SGuo Ren do_trap_error(regs, SIGILL, ILL_ILLTRP, regs->pc, 1845bc46ce2SGuo Ren "Oops - illegal trap exception"); 1855bc46ce2SGuo Ren } 1865bc46ce2SGuo Ren 1875bc46ce2SGuo Ren asmlinkage void do_trap_illinsn(struct pt_regs *regs) 1885bc46ce2SGuo Ren { 1895bc46ce2SGuo Ren current->thread.trap_no = trap_no(regs); 1905bc46ce2SGuo Ren 19133e53ae1SGuo Ren #ifdef CONFIG_KPROBES 19233e53ae1SGuo Ren if (kprobe_breakpoint_handler(regs)) 19333e53ae1SGuo Ren return; 19433e53ae1SGuo Ren #endif 1958f6bb793SGuo Ren #ifdef CONFIG_UPROBES 1968f6bb793SGuo Ren if (uprobe_breakpoint_handler(regs)) 1978f6bb793SGuo Ren return; 1988f6bb793SGuo Ren #endif 199081860b9SGuo Ren #ifndef CONFIG_CPU_NO_USER_BKPT 2005bc46ce2SGuo Ren if (*(uint16_t *)instruction_pointer(regs) != USR_BKPT) { 2015bc46ce2SGuo Ren send_sig(SIGTRAP, current, 0); 2025bc46ce2SGuo Ren return; 203081860b9SGuo Ren } 204081860b9SGuo Ren #endif 2055bc46ce2SGuo Ren 2065bc46ce2SGuo Ren do_trap_error(regs, SIGILL, ILL_ILLOPC, regs->pc, 2075bc46ce2SGuo Ren "Oops - illegal instruction exception"); 2085bc46ce2SGuo Ren } 2095bc46ce2SGuo Ren 2105bc46ce2SGuo Ren asmlinkage void do_trap_fpe(struct pt_regs *regs) 2115bc46ce2SGuo Ren { 2125bc46ce2SGuo Ren #ifdef CONFIG_CPU_HAS_FP 213081860b9SGuo Ren return fpu_fpe(regs); 2145bc46ce2SGuo Ren #else 2155bc46ce2SGuo Ren do_trap_error(regs, SIGILL, ILL_ILLOPC, regs->pc, 2165bc46ce2SGuo Ren "Oops - fpu instruction exception"); 2175bc46ce2SGuo Ren #endif 2185bc46ce2SGuo Ren } 2195bc46ce2SGuo Ren 2205bc46ce2SGuo Ren asmlinkage void do_trap_priv(struct pt_regs *regs) 2215bc46ce2SGuo Ren { 2225bc46ce2SGuo Ren #ifdef CONFIG_CPU_HAS_FP 2235bc46ce2SGuo Ren if (user_mode(regs) && fpu_libc_helper(regs)) 224081860b9SGuo Ren return; 225081860b9SGuo Ren #endif 2265bc46ce2SGuo Ren do_trap_error(regs, SIGILL, ILL_PRVOPC, regs->pc, 2275bc46ce2SGuo Ren "Oops - illegal privileged exception"); 228081860b9SGuo Ren } 2299c0e343dSGuo Ren 2305bc46ce2SGuo Ren asmlinkage void trap_c(struct pt_regs *regs) 2315bc46ce2SGuo Ren { 2325bc46ce2SGuo Ren switch (trap_no(regs)) { 2335bc46ce2SGuo Ren case VEC_ZERODIV: 2345bc46ce2SGuo Ren do_trap_zdiv(regs); 2355bc46ce2SGuo Ren break; 2365bc46ce2SGuo Ren case VEC_TRACE: 2375bc46ce2SGuo Ren do_trap_bkpt(regs); 2385bc46ce2SGuo Ren break; 2395bc46ce2SGuo Ren case VEC_ILLEGAL: 2405bc46ce2SGuo Ren do_trap_illinsn(regs); 2415bc46ce2SGuo Ren break; 2425bc46ce2SGuo Ren case VEC_TRAP1: 2435bc46ce2SGuo Ren case VEC_BREAKPOINT: 2445bc46ce2SGuo Ren do_trap_bkpt(regs); 2455bc46ce2SGuo Ren break; 2465bc46ce2SGuo Ren case VEC_ACCESS: 2475bc46ce2SGuo Ren do_trap_buserr(regs); 2485bc46ce2SGuo Ren break; 2495bc46ce2SGuo Ren case VEC_ALIGN: 2505bc46ce2SGuo Ren do_trap_misaligned(regs); 2515bc46ce2SGuo Ren break; 2525bc46ce2SGuo Ren case VEC_FPE: 2535bc46ce2SGuo Ren do_trap_fpe(regs); 2545bc46ce2SGuo Ren break; 2555bc46ce2SGuo Ren case VEC_PRIV: 2565bc46ce2SGuo Ren do_trap_priv(regs); 2575bc46ce2SGuo Ren break; 2585bc46ce2SGuo Ren default: 2595bc46ce2SGuo Ren do_trap_unknown(regs); 2605bc46ce2SGuo Ren break; 2615bc46ce2SGuo Ren } 262081860b9SGuo Ren } 263