1 /* 2 * Kernel traps/events for Hexagon processor 3 * 4 * Copyright (c) 2010-2013, The Linux Foundation. All rights reserved. 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 2 and 8 * only version 2 as published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 18 * 02110-1301, USA. 19 */ 20 21 #include <linux/init.h> 22 #include <linux/sched.h> 23 #include <linux/module.h> 24 #include <linux/kallsyms.h> 25 #include <linux/kdebug.h> 26 #include <linux/syscalls.h> 27 #include <linux/signal.h> 28 #include <linux/tracehook.h> 29 #include <asm/traps.h> 30 #include <asm/vm_fault.h> 31 #include <asm/syscall.h> 32 #include <asm/registers.h> 33 #include <asm/unistd.h> 34 #include <asm/sections.h> 35 #ifdef CONFIG_KGDB 36 # include <linux/kgdb.h> 37 #endif 38 39 #define TRAP_SYSCALL 1 40 #define TRAP_DEBUG 0xdb 41 42 void __init trap_init(void) 43 { 44 } 45 46 #ifdef CONFIG_GENERIC_BUG 47 /* Maybe should resemble arch/sh/kernel/traps.c ?? */ 48 int is_valid_bugaddr(unsigned long addr) 49 { 50 return 1; 51 } 52 #endif /* CONFIG_GENERIC_BUG */ 53 54 static const char *ex_name(int ex) 55 { 56 switch (ex) { 57 case HVM_GE_C_XPROT: 58 case HVM_GE_C_XUSER: 59 return "Execute protection fault"; 60 case HVM_GE_C_RPROT: 61 case HVM_GE_C_RUSER: 62 return "Read protection fault"; 63 case HVM_GE_C_WPROT: 64 case HVM_GE_C_WUSER: 65 return "Write protection fault"; 66 case HVM_GE_C_XMAL: 67 return "Misaligned instruction"; 68 case HVM_GE_C_WREG: 69 return "Multiple writes to same register in packet"; 70 case HVM_GE_C_PCAL: 71 return "Program counter values that are not properly aligned"; 72 case HVM_GE_C_RMAL: 73 return "Misaligned data load"; 74 case HVM_GE_C_WMAL: 75 return "Misaligned data store"; 76 case HVM_GE_C_INVI: 77 case HVM_GE_C_PRIVI: 78 return "Illegal instruction"; 79 case HVM_GE_C_BUS: 80 return "Precise bus error"; 81 case HVM_GE_C_CACHE: 82 return "Cache error"; 83 84 case 0xdb: 85 return "Debugger trap"; 86 87 default: 88 return "Unrecognized exception"; 89 } 90 } 91 92 static void do_show_stack(struct task_struct *task, unsigned long *fp, 93 unsigned long ip) 94 { 95 int kstack_depth_to_print = 24; 96 unsigned long offset, size; 97 const char *name = NULL; 98 unsigned long *newfp; 99 unsigned long low, high; 100 char tmpstr[128]; 101 char *modname; 102 int i; 103 104 if (task == NULL) 105 task = current; 106 107 printk(KERN_INFO "CPU#%d, %s/%d, Call Trace:\n", 108 raw_smp_processor_id(), task->comm, 109 task_pid_nr(task)); 110 111 if (fp == NULL) { 112 if (task == current) { 113 asm("%0 = r30" : "=r" (fp)); 114 } else { 115 fp = (unsigned long *) 116 ((struct hexagon_switch_stack *) 117 task->thread.switch_sp)->fp; 118 } 119 } 120 121 if ((((unsigned long) fp) & 0x3) || ((unsigned long) fp < 0x1000)) { 122 printk(KERN_INFO "-- Corrupt frame pointer %p\n", fp); 123 return; 124 } 125 126 /* Saved link reg is one word above FP */ 127 if (!ip) 128 ip = *(fp+1); 129 130 /* Expect kernel stack to be in-bounds */ 131 low = (unsigned long)task_stack_page(task); 132 high = low + THREAD_SIZE - 8; 133 low += sizeof(struct thread_info); 134 135 for (i = 0; i < kstack_depth_to_print; i++) { 136 137 name = kallsyms_lookup(ip, &size, &offset, &modname, tmpstr); 138 139 printk(KERN_INFO "[%p] 0x%lx: %s + 0x%lx", fp, ip, name, 140 offset); 141 if (((unsigned long) fp < low) || (high < (unsigned long) fp)) 142 printk(KERN_CONT " (FP out of bounds!)"); 143 if (modname) 144 printk(KERN_CONT " [%s] ", modname); 145 printk(KERN_CONT "\n"); 146 147 newfp = (unsigned long *) *fp; 148 149 if (((unsigned long) newfp) & 0x3) { 150 printk(KERN_INFO "-- Corrupt frame pointer %p\n", 151 newfp); 152 break; 153 } 154 155 /* Attempt to continue past exception. */ 156 if (0 == newfp) { 157 struct pt_regs *regs = (struct pt_regs *) (((void *)fp) 158 + 8); 159 160 if (regs->syscall_nr != -1) { 161 printk(KERN_INFO "-- trap0 -- syscall_nr: %ld", 162 regs->syscall_nr); 163 printk(KERN_CONT " psp: %lx elr: %lx\n", 164 pt_psp(regs), pt_elr(regs)); 165 break; 166 } else { 167 /* really want to see more ... */ 168 kstack_depth_to_print += 6; 169 printk(KERN_INFO "-- %s (0x%lx) badva: %lx\n", 170 ex_name(pt_cause(regs)), pt_cause(regs), 171 pt_badva(regs)); 172 } 173 174 newfp = (unsigned long *) regs->r30; 175 ip = pt_elr(regs); 176 } else { 177 ip = *(newfp + 1); 178 } 179 180 /* If link reg is null, we are done. */ 181 if (ip == 0x0) 182 break; 183 184 /* If newfp isn't larger, we're tracing garbage. */ 185 if (newfp > fp) 186 fp = newfp; 187 else 188 break; 189 } 190 } 191 192 void show_stack(struct task_struct *task, unsigned long *fp) 193 { 194 /* Saved link reg is one word above FP */ 195 do_show_stack(task, fp, 0); 196 } 197 198 void dump_stack(void) 199 { 200 unsigned long *fp; 201 asm("%0 = r30" : "=r" (fp)); 202 show_stack(current, fp); 203 } 204 EXPORT_SYMBOL(dump_stack); 205 206 int die(const char *str, struct pt_regs *regs, long err) 207 { 208 static struct { 209 spinlock_t lock; 210 int counter; 211 } die = { 212 .lock = __SPIN_LOCK_UNLOCKED(die.lock), 213 .counter = 0 214 }; 215 216 console_verbose(); 217 oops_enter(); 218 219 spin_lock_irq(&die.lock); 220 bust_spinlocks(1); 221 printk(KERN_EMERG "Oops: %s[#%d]:\n", str, ++die.counter); 222 223 if (notify_die(DIE_OOPS, str, regs, err, pt_cause(regs), SIGSEGV) == 224 NOTIFY_STOP) 225 return 1; 226 227 print_modules(); 228 show_regs(regs); 229 do_show_stack(current, ®s->r30, pt_elr(regs)); 230 231 bust_spinlocks(0); 232 add_taint(TAINT_DIE, LOCKDEP_NOW_UNRELIABLE); 233 234 spin_unlock_irq(&die.lock); 235 236 if (in_interrupt()) 237 panic("Fatal exception in interrupt"); 238 239 if (panic_on_oops) 240 panic("Fatal exception"); 241 242 oops_exit(); 243 do_exit(err); 244 return 0; 245 } 246 247 int die_if_kernel(char *str, struct pt_regs *regs, long err) 248 { 249 if (!user_mode(regs)) 250 return die(str, regs, err); 251 else 252 return 0; 253 } 254 255 /* 256 * It's not clear that misaligned fetches are ever recoverable. 257 */ 258 static void misaligned_instruction(struct pt_regs *regs) 259 { 260 die_if_kernel("Misaligned Instruction", regs, 0); 261 force_sig(SIGBUS, current); 262 } 263 264 /* 265 * Misaligned loads and stores, on the other hand, can be 266 * emulated, and probably should be, some day. But for now 267 * they will be considered fatal. 268 */ 269 static void misaligned_data_load(struct pt_regs *regs) 270 { 271 die_if_kernel("Misaligned Data Load", regs, 0); 272 force_sig(SIGBUS, current); 273 } 274 275 static void misaligned_data_store(struct pt_regs *regs) 276 { 277 die_if_kernel("Misaligned Data Store", regs, 0); 278 force_sig(SIGBUS, current); 279 } 280 281 static void illegal_instruction(struct pt_regs *regs) 282 { 283 die_if_kernel("Illegal Instruction", regs, 0); 284 force_sig(SIGILL, current); 285 } 286 287 /* 288 * Precise bus errors may be recoverable with a a retry, 289 * but for now, treat them as irrecoverable. 290 */ 291 static void precise_bus_error(struct pt_regs *regs) 292 { 293 die_if_kernel("Precise Bus Error", regs, 0); 294 force_sig(SIGBUS, current); 295 } 296 297 /* 298 * If anything is to be done here other than panic, 299 * it will probably be complex and migrate to another 300 * source module. For now, just die. 301 */ 302 static void cache_error(struct pt_regs *regs) 303 { 304 die("Cache Error", regs, 0); 305 } 306 307 /* 308 * General exception handler 309 */ 310 void do_genex(struct pt_regs *regs) 311 { 312 /* 313 * Decode Cause and Dispatch 314 */ 315 switch (pt_cause(regs)) { 316 case HVM_GE_C_XPROT: 317 case HVM_GE_C_XUSER: 318 execute_protection_fault(regs); 319 break; 320 case HVM_GE_C_RPROT: 321 case HVM_GE_C_RUSER: 322 read_protection_fault(regs); 323 break; 324 case HVM_GE_C_WPROT: 325 case HVM_GE_C_WUSER: 326 write_protection_fault(regs); 327 break; 328 case HVM_GE_C_XMAL: 329 misaligned_instruction(regs); 330 break; 331 case HVM_GE_C_WREG: 332 illegal_instruction(regs); 333 break; 334 case HVM_GE_C_PCAL: 335 misaligned_instruction(regs); 336 break; 337 case HVM_GE_C_RMAL: 338 misaligned_data_load(regs); 339 break; 340 case HVM_GE_C_WMAL: 341 misaligned_data_store(regs); 342 break; 343 case HVM_GE_C_INVI: 344 case HVM_GE_C_PRIVI: 345 illegal_instruction(regs); 346 break; 347 case HVM_GE_C_BUS: 348 precise_bus_error(regs); 349 break; 350 case HVM_GE_C_CACHE: 351 cache_error(regs); 352 break; 353 default: 354 /* Halt and catch fire */ 355 panic("Unrecognized exception 0x%lx\n", pt_cause(regs)); 356 break; 357 } 358 } 359 360 /* Indirect system call dispatch */ 361 long sys_syscall(void) 362 { 363 printk(KERN_ERR "sys_syscall invoked!\n"); 364 return -ENOSYS; 365 } 366 367 void do_trap0(struct pt_regs *regs) 368 { 369 syscall_fn syscall; 370 371 switch (pt_cause(regs)) { 372 case TRAP_SYSCALL: 373 /* System call is trap0 #1 */ 374 375 /* allow strace to catch syscall args */ 376 if (unlikely(test_thread_flag(TIF_SYSCALL_TRACE) && 377 tracehook_report_syscall_entry(regs))) 378 return; /* return -ENOSYS somewhere? */ 379 380 /* Interrupts should be re-enabled for syscall processing */ 381 __vmsetie(VM_INT_ENABLE); 382 383 /* 384 * System call number is in r6, arguments in r0..r5. 385 * Fortunately, no Linux syscall has more than 6 arguments, 386 * and Hexagon ABI passes first 6 arguments in registers. 387 * 64-bit arguments are passed in odd/even register pairs. 388 * Fortunately, we have no system calls that take more 389 * than three arguments with more than one 64-bit value. 390 * Should that change, we'd need to redesign to copy 391 * between user and kernel stacks. 392 */ 393 regs->syscall_nr = regs->r06; 394 395 /* 396 * GPR R0 carries the first parameter, and is also used 397 * to report the return value. We need a backup of 398 * the user's value in case we need to do a late restart 399 * of the system call. 400 */ 401 regs->restart_r0 = regs->r00; 402 403 if ((unsigned long) regs->syscall_nr >= __NR_syscalls) { 404 regs->r00 = -1; 405 } else { 406 syscall = (syscall_fn) 407 (sys_call_table[regs->syscall_nr]); 408 regs->r00 = syscall(regs->r00, regs->r01, 409 regs->r02, regs->r03, 410 regs->r04, regs->r05); 411 } 412 413 /* allow strace to get the syscall return state */ 414 if (unlikely(test_thread_flag(TIF_SYSCALL_TRACE))) 415 tracehook_report_syscall_exit(regs, 0); 416 417 break; 418 case TRAP_DEBUG: 419 /* Trap0 0xdb is debug breakpoint */ 420 if (user_mode(regs)) { 421 struct siginfo info; 422 423 info.si_signo = SIGTRAP; 424 info.si_errno = 0; 425 /* 426 * Some architecures add some per-thread state 427 * to distinguish between breakpoint traps and 428 * trace traps. We may want to do that, and 429 * set the si_code value appropriately, or we 430 * may want to use a different trap0 flavor. 431 */ 432 info.si_code = TRAP_BRKPT; 433 info.si_addr = (void __user *) pt_elr(regs); 434 send_sig_info(SIGTRAP, &info, current); 435 } else { 436 #ifdef CONFIG_KGDB 437 kgdb_handle_exception(pt_cause(regs), SIGTRAP, 438 TRAP_BRKPT, regs); 439 #endif 440 } 441 break; 442 } 443 /* Ignore other trap0 codes for now, especially 0 (Angel calls) */ 444 } 445 446 /* 447 * Machine check exception handler 448 */ 449 void do_machcheck(struct pt_regs *regs) 450 { 451 /* Halt and catch fire */ 452 __vmstop(); 453 } 454 455 /* 456 * Treat this like the old 0xdb trap. 457 */ 458 459 void do_debug_exception(struct pt_regs *regs) 460 { 461 regs->hvmer.vmest &= ~HVM_VMEST_CAUSE_MSK; 462 regs->hvmer.vmest |= (TRAP_DEBUG << HVM_VMEST_CAUSE_SFT); 463 do_trap0(regs); 464 } 465