Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 // Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
0003 
0004 #include <linux/sched.h>
0005 #include <linux/signal.h>
0006 #include <linux/kernel.h>
0007 #include <linux/mm.h>
0008 #include <linux/module.h>
0009 #include <linux/user.h>
0010 #include <linux/string.h>
0011 #include <linux/linkage.h>
0012 #include <linux/init.h>
0013 #include <linux/ptrace.h>
0014 #include <linux/kallsyms.h>
0015 #include <linux/rtc.h>
0016 #include <linux/uaccess.h>
0017 #include <linux/kprobes.h>
0018 #include <linux/kdebug.h>
0019 #include <linux/sched/debug.h>
0020 
0021 #include <asm/setup.h>
0022 #include <asm/traps.h>
0023 #include <asm/pgalloc.h>
0024 #include <asm/siginfo.h>
0025 
0026 #include <asm/mmu_context.h>
0027 
0028 #ifdef CONFIG_CPU_HAS_FPU
0029 #include <abi/fpu.h>
0030 #endif
0031 
0032 int show_unhandled_signals = 1;
0033 
0034 /* Defined in entry.S */
0035 asmlinkage void csky_trap(void);
0036 
0037 asmlinkage void csky_systemcall(void);
0038 asmlinkage void csky_cmpxchg(void);
0039 asmlinkage void csky_get_tls(void);
0040 asmlinkage void csky_irq(void);
0041 
0042 asmlinkage void csky_pagefault(void);
0043 
0044 /* Defined in head.S */
0045 asmlinkage void _start_smp_secondary(void);
0046 
0047 void __init pre_trap_init(void)
0048 {
0049     int i;
0050 
0051     mtcr("vbr", vec_base);
0052 
0053     for (i = 1; i < 128; i++)
0054         VEC_INIT(i, csky_trap);
0055 }
0056 
0057 void __init trap_init(void)
0058 {
0059     VEC_INIT(VEC_AUTOVEC, csky_irq);
0060 
0061     /* setup trap0 trap2 trap3 */
0062     VEC_INIT(VEC_TRAP0, csky_systemcall);
0063     VEC_INIT(VEC_TRAP2, csky_cmpxchg);
0064     VEC_INIT(VEC_TRAP3, csky_get_tls);
0065 
0066     /* setup MMU TLB exception */
0067     VEC_INIT(VEC_TLBINVALIDL, csky_pagefault);
0068     VEC_INIT(VEC_TLBINVALIDS, csky_pagefault);
0069     VEC_INIT(VEC_TLBMODIFIED, csky_pagefault);
0070 
0071 #ifdef CONFIG_CPU_HAS_FPU
0072     init_fpu();
0073 #endif
0074 
0075 #ifdef CONFIG_SMP
0076     mtcr("cr<28, 0>", virt_to_phys(vec_base));
0077 
0078     VEC_INIT(VEC_RESET, (void *)virt_to_phys(_start_smp_secondary));
0079 #endif
0080 }
0081 
0082 static DEFINE_SPINLOCK(die_lock);
0083 
0084 void die(struct pt_regs *regs, const char *str)
0085 {
0086     static int die_counter;
0087     int ret;
0088 
0089     oops_enter();
0090 
0091     spin_lock_irq(&die_lock);
0092     console_verbose();
0093     bust_spinlocks(1);
0094 
0095     pr_emerg("%s [#%d]\n", str, ++die_counter);
0096     print_modules();
0097     show_regs(regs);
0098     show_stack(current, (unsigned long *)regs->regs[4], KERN_INFO);
0099 
0100     ret = notify_die(DIE_OOPS, str, regs, 0, trap_no(regs), SIGSEGV);
0101 
0102     bust_spinlocks(0);
0103     add_taint(TAINT_DIE, LOCKDEP_NOW_UNRELIABLE);
0104     spin_unlock_irq(&die_lock);
0105     oops_exit();
0106 
0107     if (in_interrupt())
0108         panic("Fatal exception in interrupt");
0109     if (panic_on_oops)
0110         panic("Fatal exception");
0111     if (ret != NOTIFY_STOP)
0112         make_task_dead(SIGSEGV);
0113 }
0114 
0115 void do_trap(struct pt_regs *regs, int signo, int code, unsigned long addr)
0116 {
0117     struct task_struct *tsk = current;
0118 
0119     if (show_unhandled_signals && unhandled_signal(tsk, signo)
0120         && printk_ratelimit()) {
0121         pr_info("%s[%d]: unhandled signal %d code 0x%x at 0x%08lx",
0122             tsk->comm, task_pid_nr(tsk), signo, code, addr);
0123         print_vma_addr(KERN_CONT " in ", instruction_pointer(regs));
0124         pr_cont("\n");
0125         show_regs(regs);
0126     }
0127 
0128     force_sig_fault(signo, code, (void __user *)addr);
0129 }
0130 
0131 static void do_trap_error(struct pt_regs *regs, int signo, int code,
0132     unsigned long addr, const char *str)
0133 {
0134     current->thread.trap_no = trap_no(regs);
0135 
0136     if (user_mode(regs)) {
0137         do_trap(regs, signo, code, addr);
0138     } else {
0139         if (!fixup_exception(regs))
0140             die(regs, str);
0141     }
0142 }
0143 
0144 #define DO_ERROR_INFO(name, signo, code, str)               \
0145 asmlinkage __visible void name(struct pt_regs *regs)            \
0146 {                                   \
0147     do_trap_error(regs, signo, code, regs->pc, "Oops - " str);  \
0148 }
0149 
0150 DO_ERROR_INFO(do_trap_unknown,
0151     SIGILL, ILL_ILLTRP, "unknown exception");
0152 DO_ERROR_INFO(do_trap_zdiv,
0153     SIGFPE, FPE_INTDIV, "error zero div exception");
0154 DO_ERROR_INFO(do_trap_buserr,
0155     SIGSEGV, ILL_ILLADR, "error bus error exception");
0156 
0157 asmlinkage void do_trap_misaligned(struct pt_regs *regs)
0158 {
0159 #ifdef CONFIG_CPU_NEED_SOFTALIGN
0160     csky_alignment(regs);
0161 #else
0162     current->thread.trap_no = trap_no(regs);
0163     do_trap_error(regs, SIGBUS, BUS_ADRALN, regs->pc,
0164               "Oops - load/store address misaligned");
0165 #endif
0166 }
0167 
0168 asmlinkage void do_trap_bkpt(struct pt_regs *regs)
0169 {
0170 #ifdef CONFIG_KPROBES
0171     if (kprobe_single_step_handler(regs))
0172         return;
0173 #endif
0174 #ifdef CONFIG_UPROBES
0175     if (uprobe_single_step_handler(regs))
0176         return;
0177 #endif
0178     if (user_mode(regs)) {
0179         send_sig(SIGTRAP, current, 0);
0180         return;
0181     }
0182 
0183     do_trap_error(regs, SIGILL, ILL_ILLTRP, regs->pc,
0184               "Oops - illegal trap exception");
0185 }
0186 
0187 asmlinkage void do_trap_illinsn(struct pt_regs *regs)
0188 {
0189     current->thread.trap_no = trap_no(regs);
0190 
0191 #ifdef CONFIG_KPROBES
0192     if (kprobe_breakpoint_handler(regs))
0193         return;
0194 #endif
0195 #ifdef CONFIG_UPROBES
0196     if (uprobe_breakpoint_handler(regs))
0197         return;
0198 #endif
0199 #ifndef CONFIG_CPU_NO_USER_BKPT
0200     if (*(uint16_t *)instruction_pointer(regs) != USR_BKPT) {
0201         send_sig(SIGTRAP, current, 0);
0202         return;
0203     }
0204 #endif
0205 
0206     do_trap_error(regs, SIGILL, ILL_ILLOPC, regs->pc,
0207               "Oops - illegal instruction exception");
0208 }
0209 
0210 asmlinkage void do_trap_fpe(struct pt_regs *regs)
0211 {
0212 #ifdef CONFIG_CPU_HAS_FPU
0213     return fpu_fpe(regs);
0214 #else
0215     do_trap_error(regs, SIGILL, ILL_ILLOPC, regs->pc,
0216               "Oops - fpu instruction exception");
0217 #endif
0218 }
0219 
0220 asmlinkage void do_trap_priv(struct pt_regs *regs)
0221 {
0222 #ifdef CONFIG_CPU_HAS_FPU
0223     if (user_mode(regs) && fpu_libc_helper(regs))
0224         return;
0225 #endif
0226     do_trap_error(regs, SIGILL, ILL_PRVOPC, regs->pc,
0227               "Oops - illegal privileged exception");
0228 }
0229 
0230 asmlinkage void trap_c(struct pt_regs *regs)
0231 {
0232     switch (trap_no(regs)) {
0233     case VEC_ZERODIV:
0234         do_trap_zdiv(regs);
0235         break;
0236     case VEC_TRACE:
0237         do_trap_bkpt(regs);
0238         break;
0239     case VEC_ILLEGAL:
0240         do_trap_illinsn(regs);
0241         break;
0242     case VEC_TRAP1:
0243     case VEC_BREAKPOINT:
0244         do_trap_bkpt(regs);
0245         break;
0246     case VEC_ACCESS:
0247         do_trap_buserr(regs);
0248         break;
0249     case VEC_ALIGN:
0250         do_trap_misaligned(regs);
0251         break;
0252     case VEC_FPE:
0253         do_trap_fpe(regs);
0254         break;
0255     case VEC_PRIV:
0256         do_trap_priv(regs);
0257         break;
0258     default:
0259         do_trap_unknown(regs);
0260         break;
0261     }
0262 }