1/* 2 * linux/arch/m68knommu/kernel/traps.c 3 * 4 * Copyright (C) 1993, 1994 by Hamish Macdonald 5 * 6 * 68040 fixes by Michael Rausch 7 * 68040 fixes by Martin Apel 8 * 68060 fixes by Roman Hodek 9 * 68060 fixes by Jesper Skov 10 * 11 * This file is subject to the terms and conditions of the GNU General Public 12 * License. See the file COPYING in the main directory of this archive 13 * for more details. 14 */ 15 16/* 17 * Sets up all exception vectors 18 */ 19#include <linux/sched.h> 20#include <linux/signal.h> 21#include <linux/kernel.h> 22#include <linux/mm.h> 23#include <linux/module.h> 24#include <linux/types.h> 25#include <linux/a.out.h> 26#include <linux/user.h> 27#include <linux/string.h> 28#include <linux/linkage.h> 29#include <linux/init.h> 30#include <linux/ptrace.h> 31 32#include <asm/setup.h> 33#include <asm/fpu.h> 34#include <asm/system.h> 35#include <asm/uaccess.h> 36#include <asm/traps.h> 37#include <asm/pgtable.h> 38#include <asm/machdep.h> 39#include <asm/siginfo.h> 40 41static char const * const vec_names[] = { 42 "RESET SP", "RESET PC", "BUS ERROR", "ADDRESS ERROR", 43 "ILLEGAL INSTRUCTION", "ZERO DIVIDE", "CHK", "TRAPcc", 44 "PRIVILEGE VIOLATION", "TRACE", "LINE 1010", "LINE 1111", 45 "UNASSIGNED RESERVED 12", "COPROCESSOR PROTOCOL VIOLATION", 46 "FORMAT ERROR", "UNINITIALIZED INTERRUPT", 47 "UNASSIGNED RESERVED 16", "UNASSIGNED RESERVED 17", 48 "UNASSIGNED RESERVED 18", "UNASSIGNED RESERVED 19", 49 "UNASSIGNED RESERVED 20", "UNASSIGNED RESERVED 21", 50 "UNASSIGNED RESERVED 22", "UNASSIGNED RESERVED 23", 51 "SPURIOUS INTERRUPT", "LEVEL 1 INT", "LEVEL 2 INT", "LEVEL 3 INT", 52 "LEVEL 4 INT", "LEVEL 5 INT", "LEVEL 6 INT", "LEVEL 7 INT", 53 "SYSCALL", "TRAP #1", "TRAP #2", "TRAP #3", 54 "TRAP #4", "TRAP #5", "TRAP #6", "TRAP #7", 55 "TRAP #8", "TRAP #9", "TRAP #10", "TRAP #11", 56 "TRAP #12", "TRAP #13", "TRAP #14", "TRAP #15", 57 "FPCP BSUN", "FPCP INEXACT", "FPCP DIV BY 0", "FPCP UNDERFLOW", 58 "FPCP OPERAND ERROR", "FPCP OVERFLOW", "FPCP SNAN", 59 "FPCP UNSUPPORTED OPERATION", 60 "MMU CONFIGURATION ERROR" 61}; 62 63void __init trap_init(void) 64{ 65 if (mach_trap_init) 66 mach_trap_init(); 67} 68 69void die_if_kernel(char *str, struct pt_regs *fp, int nr) 70{ 71 if (!(fp->sr & PS_S)) 72 return; 73 74 console_verbose(); 75 printk(KERN_EMERG "%s: %08x\n",str,nr); 76 printk(KERN_EMERG "PC: [<%08lx>]\nSR: %04x SP: %p a2: %08lx\n", 77 fp->pc, fp->sr, fp, fp->a2); 78 printk(KERN_EMERG "d0: %08lx d1: %08lx d2: %08lx d3: %08lx\n", 79 fp->d0, fp->d1, fp->d2, fp->d3); 80 printk(KERN_EMERG "d4: %08lx d5: %08lx a0: %08lx a1: %08lx\n", 81 fp->d4, fp->d5, fp->a0, fp->a1); 82 83 printk(KERN_EMERG "Process %s (pid: %d, stackpage=%08lx)\n", 84 current->comm, current->pid, PAGE_SIZE+(unsigned long)current); 85 show_stack(NULL, (unsigned long *)fp); 86 do_exit(SIGSEGV); 87} 88 89asmlinkage void buserr_c(struct frame *fp) 90{ 91 /* Only set esp0 if coming from user mode */ 92 if (user_mode(&fp->ptregs)) 93 current->thread.esp0 = (unsigned long) fp; 94 95#if defined(DEBUG) 96 printk (KERN_DEBUG "*** Bus Error *** Format is %x\n", fp->ptregs.format); 97#endif 98 99 die_if_kernel("bad frame format",&fp->ptregs,0); 100#if defined(DEBUG) 101 printk(KERN_DEBUG "Unknown SIGSEGV - 4\n"); 102#endif 103 force_sig(SIGSEGV, current); 104} 105 106 107int kstack_depth_to_print = 48; 108 109void show_stack(struct task_struct *task, unsigned long *stack) 110{ 111 unsigned long *endstack, addr; 112 extern char _start, _etext; 113 int i; 114 115 if (!stack) { 116 if (task) 117 stack = (unsigned long *)task->thread.ksp; 118 else 119 stack = (unsigned long *)&stack; 120 } 121 122 addr = (unsigned long) stack; 123 endstack = (unsigned long *) PAGE_ALIGN(addr); 124 125 printk(KERN_EMERG "Stack from %08lx:", (unsigned long)stack); 126 for (i = 0; i < kstack_depth_to_print; i++) { 127 if (stack + 1 > endstack) 128 break; 129 if (i % 8 == 0) 130 printk("\n" KERN_EMERG " "); 131 printk(" %08lx", *stack++); 132 } 133 printk("\n"); 134 135 printk(KERN_EMERG "Call Trace:"); 136 i = 0; 137 while (stack + 1 <= endstack) { 138 addr = *stack++; 139 /* 140 * If the address is either in the text segment of the 141 * kernel, or in the region which contains vmalloc'ed 142 * memory, it *may* be the address of a calling 143 * routine; if so, print it so that someone tracing 144 * down the cause of the crash will be able to figure 145 * out the call path that was taken. 146 */ 147 if (((addr >= (unsigned long) &_start) && 148 (addr <= (unsigned long) &_etext))) { 149 if (i % 4 == 0) 150 printk("\n" KERN_EMERG " "); 151 printk(" [<%08lx>]", addr); 152 i++; 153 } 154 } 155 printk("\n"); 156} 157 158void bad_super_trap(struct frame *fp) 159{ 160 console_verbose(); 161 if (fp->ptregs.vector < 4 * ARRAY_SIZE(vec_names)) 162 printk (KERN_WARNING "*** %s *** FORMAT=%X\n", 163 vec_names[(fp->ptregs.vector) >> 2], 164 fp->ptregs.format); 165 else 166 printk (KERN_WARNING "*** Exception %d *** FORMAT=%X\n", 167 (fp->ptregs.vector) >> 2, 168 fp->ptregs.format); 169 printk (KERN_WARNING "Current process id is %d\n", current->pid); 170 die_if_kernel("BAD KERNEL TRAP", &fp->ptregs, 0); 171} 172 173asmlinkage void trap_c(struct frame *fp) 174{ 175 int sig; 176 siginfo_t info; 177 178 if (fp->ptregs.sr & PS_S) { 179 if ((fp->ptregs.vector >> 2) == VEC_TRACE) { 180 /* traced a trapping instruction */ 181 current->ptrace |= PT_DTRACE; 182 } else 183 bad_super_trap(fp); 184 return; 185 } 186 187 /* send the appropriate signal to the user program */ 188 switch ((fp->ptregs.vector) >> 2) { 189 case VEC_ADDRERR: 190 info.si_code = BUS_ADRALN; 191 sig = SIGBUS; 192 break; 193 case VEC_ILLEGAL: 194 case VEC_LINE10: 195 case VEC_LINE11: 196 info.si_code = ILL_ILLOPC; 197 sig = SIGILL; 198 break; 199 case VEC_PRIV: 200 info.si_code = ILL_PRVOPC; 201 sig = SIGILL; 202 break; 203 case VEC_COPROC: 204 info.si_code = ILL_COPROC; 205 sig = SIGILL; 206 break; 207 case VEC_TRAP1: /* gdbserver breakpoint */ 208 fp->ptregs.pc -= 2; 209 info.si_code = TRAP_TRACE; 210 sig = SIGTRAP; 211 break; 212 case VEC_TRAP2: 213 case VEC_TRAP3: 214 case VEC_TRAP4: 215 case VEC_TRAP5: 216 case VEC_TRAP6: 217 case VEC_TRAP7: 218 case VEC_TRAP8: 219 case VEC_TRAP9: 220 case VEC_TRAP10: 221 case VEC_TRAP11: 222 case VEC_TRAP12: 223 case VEC_TRAP13: 224 case VEC_TRAP14: 225 info.si_code = ILL_ILLTRP; 226 sig = SIGILL; 227 break; 228 case VEC_FPBRUC: 229 case VEC_FPOE: 230 case VEC_FPNAN: 231 info.si_code = FPE_FLTINV; 232 sig = SIGFPE; 233 break; 234 case VEC_FPIR: 235 info.si_code = FPE_FLTRES; 236 sig = SIGFPE; 237 break; 238 case VEC_FPDIVZ: 239 info.si_code = FPE_FLTDIV; 240 sig = SIGFPE; 241 break; 242 case VEC_FPUNDER: 243 info.si_code = FPE_FLTUND; 244 sig = SIGFPE; 245 break; 246 case VEC_FPOVER: 247 info.si_code = FPE_FLTOVF; 248 sig = SIGFPE; 249 break; 250 case VEC_ZERODIV: 251 info.si_code = FPE_INTDIV; 252 sig = SIGFPE; 253 break; 254 case VEC_CHK: 255 case VEC_TRAP: 256 info.si_code = FPE_INTOVF; 257 sig = SIGFPE; 258 break; 259 case VEC_TRACE: /* ptrace single step */ 260 info.si_code = TRAP_TRACE; 261 sig = SIGTRAP; 262 break; 263 case VEC_TRAP15: /* breakpoint */ 264 info.si_code = TRAP_BRKPT; 265 sig = SIGTRAP; 266 break; 267 default: 268 info.si_code = ILL_ILLOPC; 269 sig = SIGILL; 270 break; 271 } 272 info.si_signo = sig; 273 info.si_errno = 0; 274 switch (fp->ptregs.format) { 275 default: 276 info.si_addr = (void *) fp->ptregs.pc; 277 break; 278 case 2: 279 info.si_addr = (void *) fp->un.fmt2.iaddr; 280 break; 281 case 7: 282 info.si_addr = (void *) fp->un.fmt7.effaddr; 283 break; 284 case 9: 285 info.si_addr = (void *) fp->un.fmt9.iaddr; 286 break; 287 case 10: 288 info.si_addr = (void *) fp->un.fmta.daddr; 289 break; 290 case 11: 291 info.si_addr = (void *) fp->un.fmtb.daddr; 292 break; 293 } 294 force_sig_info (sig, &info, current); 295} 296 297asmlinkage void set_esp0(unsigned long ssp) 298{ 299 current->thread.esp0 = ssp; 300} 301 302 303/* 304 * The architecture-independent backtrace generator 305 */ 306void dump_stack(void) 307{ 308 unsigned long stack; 309 310 show_stack(current, &stack); 311} 312 313EXPORT_SYMBOL(dump_stack); 314 315#ifdef CONFIG_M68KFPU_EMU 316asmlinkage void fpemu_signal(int signal, int code, void *addr) 317{ 318 siginfo_t info; 319 320 info.si_signo = signal; 321 info.si_errno = 0; 322 info.si_code = code; 323 info.si_addr = addr; 324 force_sig_info(signal, &info, current); 325} 326#endif 327