0001
0002
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
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
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
0062 VEC_INIT(VEC_TRAP0, csky_systemcall);
0063 VEC_INIT(VEC_TRAP2, csky_cmpxchg);
0064 VEC_INIT(VEC_TRAP3, csky_get_tls);
0065
0066
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 }