root/arch/csky/kernel/traps.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. pre_trap_init
  2. trap_init
  3. die_if_kernel
  4. buserr
  5. trap_c

   1 // SPDX-License-Identifier: GPL-2.0
   2 // Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
   3 
   4 #include <linux/sched.h>
   5 #include <linux/signal.h>
   6 #include <linux/kernel.h>
   7 #include <linux/mm.h>
   8 #include <linux/module.h>
   9 #include <linux/user.h>
  10 #include <linux/string.h>
  11 #include <linux/linkage.h>
  12 #include <linux/init.h>
  13 #include <linux/ptrace.h>
  14 #include <linux/kallsyms.h>
  15 #include <linux/rtc.h>
  16 #include <linux/uaccess.h>
  17 
  18 #include <asm/setup.h>
  19 #include <asm/traps.h>
  20 #include <asm/pgalloc.h>
  21 #include <asm/siginfo.h>
  22 
  23 #include <asm/mmu_context.h>
  24 
  25 #ifdef CONFIG_CPU_HAS_FPU
  26 #include <abi/fpu.h>
  27 #endif
  28 
  29 /* Defined in entry.S */
  30 asmlinkage void csky_trap(void);
  31 
  32 asmlinkage void csky_systemcall(void);
  33 asmlinkage void csky_cmpxchg(void);
  34 asmlinkage void csky_get_tls(void);
  35 asmlinkage void csky_irq(void);
  36 
  37 asmlinkage void csky_tlbinvalidl(void);
  38 asmlinkage void csky_tlbinvalids(void);
  39 asmlinkage void csky_tlbmodified(void);
  40 
  41 /* Defined in head.S */
  42 asmlinkage void _start_smp_secondary(void);
  43 
  44 void __init pre_trap_init(void)
  45 {
  46         int i;
  47 
  48         mtcr("vbr", vec_base);
  49 
  50         for (i = 1; i < 128; i++)
  51                 VEC_INIT(i, csky_trap);
  52 }
  53 
  54 void __init trap_init(void)
  55 {
  56         VEC_INIT(VEC_AUTOVEC, csky_irq);
  57 
  58         /* setup trap0 trap2 trap3 */
  59         VEC_INIT(VEC_TRAP0, csky_systemcall);
  60         VEC_INIT(VEC_TRAP2, csky_cmpxchg);
  61         VEC_INIT(VEC_TRAP3, csky_get_tls);
  62 
  63         /* setup MMU TLB exception */
  64         VEC_INIT(VEC_TLBINVALIDL, csky_tlbinvalidl);
  65         VEC_INIT(VEC_TLBINVALIDS, csky_tlbinvalids);
  66         VEC_INIT(VEC_TLBMODIFIED, csky_tlbmodified);
  67 
  68 #ifdef CONFIG_CPU_HAS_FPU
  69         init_fpu();
  70 #endif
  71 
  72 #ifdef CONFIG_SMP
  73         mtcr("cr<28, 0>", virt_to_phys(vec_base));
  74 
  75         VEC_INIT(VEC_RESET, (void *)virt_to_phys(_start_smp_secondary));
  76 #endif
  77 }
  78 
  79 void die_if_kernel(char *str, struct pt_regs *regs, int nr)
  80 {
  81         if (user_mode(regs))
  82                 return;
  83 
  84         console_verbose();
  85         pr_err("%s: %08x\n", str, nr);
  86         show_regs(regs);
  87         add_taint(TAINT_DIE, LOCKDEP_NOW_UNRELIABLE);
  88         do_exit(SIGSEGV);
  89 }
  90 
  91 void buserr(struct pt_regs *regs)
  92 {
  93 #ifdef CONFIG_CPU_CK810
  94         static unsigned long prev_pc;
  95 
  96         if ((regs->pc == prev_pc) && prev_pc != 0) {
  97                 prev_pc = 0;
  98         } else {
  99                 prev_pc = regs->pc;
 100                 return;
 101         }
 102 #endif
 103 
 104         die_if_kernel("Kernel mode BUS error", regs, 0);
 105 
 106         pr_err("User mode Bus Error\n");
 107         show_regs(regs);
 108 
 109         force_sig_fault(SIGSEGV, 0, (void __user *)regs->pc);
 110 }
 111 
 112 #define USR_BKPT 0x1464
 113 asmlinkage void trap_c(struct pt_regs *regs)
 114 {
 115         int sig;
 116         unsigned long vector;
 117         siginfo_t info;
 118         struct task_struct *tsk = current;
 119 
 120         vector = (regs->sr >> 16) & 0xff;
 121 
 122         switch (vector) {
 123         case VEC_ZERODIV:
 124                 die_if_kernel("Kernel mode ZERO DIV", regs, vector);
 125                 sig = SIGFPE;
 126                 break;
 127         /* ptrace */
 128         case VEC_TRACE:
 129                 info.si_code = TRAP_TRACE;
 130                 sig = SIGTRAP;
 131                 break;
 132         case VEC_ILLEGAL:
 133                 tsk->thread.trap_no = vector;
 134                 die_if_kernel("Kernel mode ILLEGAL", regs, vector);
 135 #ifndef CONFIG_CPU_NO_USER_BKPT
 136                 if (*(uint16_t *)instruction_pointer(regs) != USR_BKPT)
 137 #endif
 138                 {
 139                         sig = SIGILL;
 140                         break;
 141                 }
 142         /* gdbserver  breakpoint */
 143         case VEC_TRAP1:
 144         /* jtagserver breakpoint */
 145         case VEC_BREAKPOINT:
 146                 die_if_kernel("Kernel mode BKPT", regs, vector);
 147                 info.si_code = TRAP_BRKPT;
 148                 sig = SIGTRAP;
 149                 break;
 150         case VEC_ACCESS:
 151                 tsk->thread.trap_no = vector;
 152                 return buserr(regs);
 153 #ifdef CONFIG_CPU_NEED_SOFTALIGN
 154         case VEC_ALIGN:
 155                 tsk->thread.trap_no = vector;
 156                 return csky_alignment(regs);
 157 #endif
 158 #ifdef CONFIG_CPU_HAS_FPU
 159         case VEC_FPE:
 160                 tsk->thread.trap_no = vector;
 161                 die_if_kernel("Kernel mode FPE", regs, vector);
 162                 return fpu_fpe(regs);
 163         case VEC_PRIV:
 164                 tsk->thread.trap_no = vector;
 165                 die_if_kernel("Kernel mode PRIV", regs, vector);
 166                 if (fpu_libc_helper(regs))
 167                         return;
 168 #endif
 169         default:
 170                 sig = SIGSEGV;
 171                 break;
 172         }
 173 
 174         tsk->thread.trap_no = vector;
 175 
 176         send_sig(sig, current, 0);
 177 }

/* [<][>][^][v][top][bottom][index][help] */