11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* traps.c: high-level exception handler for FR-V 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved. 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Written by David Howells (dhowells@redhat.com) 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is free software; you can redistribute it and/or 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * modify it under the terms of the GNU General Public License 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * as published by the Free Software Foundation; either version 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2 of the License, or (at your option) any later version. 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/sched.h> 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/signal.h> 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h> 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/mm.h> 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/types.h> 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/user.h> 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/string.h> 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/linkage.h> 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 21402344012ebe696d9353bbf056889ddaaec83079David Howells#include <linux/module.h> 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2384e8cd6dbc00b4979e8d1c15c80d91987aeb3417David Howells#include <asm/asm-offsets.h> 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/setup.h> 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/fpu.h> 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/uaccess.h> 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/pgtable.h> 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/siginfo.h> 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/unaligned.h> 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid show_backtrace(struct pt_regs *, unsigned long); 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern asmlinkage void __break_hijack_kernel_event(void); 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*****************************************************************************/ 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * instruction access error 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsasmlinkage void insn_access_error(unsigned long esfr1, unsigned long epcr0, unsigned long esr0) 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds siginfo_t info; 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds die_if_kernel("-- Insn Access Error --\n" 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "EPCR0 : %08lx\n" 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "ESR0 : %08lx\n", 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds epcr0, esr0); 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info.si_signo = SIGSEGV; 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info.si_code = SEGV_ACCERR; 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info.si_errno = 0; 51ff471b2464ca7344eba347d360f23ea415a774dcAl Viro info.si_addr = (void __user *) ((epcr0 & EPCR0_V) ? (epcr0 & EPCR0_PC) : __frame->pc); 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds force_sig_info(info.si_signo, &info, current); 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} /* end insn_access_error() */ 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*****************************************************************************/ 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * handler for: 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - illegal instruction 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - privileged instruction 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - unsupported trap 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - debug exceptions 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsasmlinkage void illegal_instruction(unsigned long esfr1, unsigned long epcr0, unsigned long esr0) 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds siginfo_t info; 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds die_if_kernel("-- Illegal Instruction --\n" 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "EPCR0 : %08lx\n" 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "ESR0 : %08lx\n" 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "ESFR1 : %08lx\n", 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds epcr0, esr0, esfr1); 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info.si_errno = 0; 75ff471b2464ca7344eba347d360f23ea415a774dcAl Viro info.si_addr = (void __user *) ((epcr0 & EPCR0_V) ? (epcr0 & EPCR0_PC) : __frame->pc); 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (__frame->tbr & TBR_TT) { 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case TBR_TT_ILLEGAL_INSTR: 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info.si_signo = SIGILL; 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info.si_code = ILL_ILLOPC; 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case TBR_TT_PRIV_INSTR: 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info.si_signo = SIGILL; 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info.si_code = ILL_PRVOPC; 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case TBR_TT_TRAP2 ... TBR_TT_TRAP126: 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info.si_signo = SIGILL; 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info.si_code = ILL_ILLTRP; 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* GDB uses "tira gr0, #1" as a breakpoint instruction. */ 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case TBR_TT_TRAP1: 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case TBR_TT_BREAK: 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info.si_signo = SIGTRAP; 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info.si_code = 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (__frame->__status & REG__STATUS_STEPPED) ? TRAP_TRACE : TRAP_BRKPT; 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds force_sig_info(info.si_signo, &info, current); 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} /* end illegal_instruction() */ 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*****************************************************************************/ 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 104e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells * handle atomic operations with errors 105e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells * - arguments in gr8, gr9, gr10 106e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells * - original memory value placed in gr5 107e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells * - replacement memory value placed in gr9 108e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells */ 109e31c243f984628d02f045dc4b622f1e2827860dcDavid Howellsasmlinkage void atomic_operation(unsigned long esfr1, unsigned long epcr0, 110e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells unsigned long esr0) 111e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells{ 112e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells static DEFINE_SPINLOCK(atomic_op_lock); 113ff471b2464ca7344eba347d360f23ea415a774dcAl Viro unsigned long x, y, z; 114ff471b2464ca7344eba347d360f23ea415a774dcAl Viro unsigned long __user *p; 115e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells mm_segment_t oldfs; 116e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells siginfo_t info; 117e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells int ret; 118e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells 119e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells y = 0; 120e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells z = 0; 121e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells 122e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells oldfs = get_fs(); 123e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells if (!user_mode(__frame)) 124e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells set_fs(KERNEL_DS); 125e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells 126e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells switch (__frame->tbr & TBR_TT) { 127e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells /* TIRA gr0,#120 128e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells * u32 __atomic_user_cmpxchg32(u32 *ptr, u32 test, u32 new) 129e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells */ 130e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells case TBR_TT_ATOMIC_CMPXCHG32: 131ff471b2464ca7344eba347d360f23ea415a774dcAl Viro p = (unsigned long __user *) __frame->gr8; 132e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells x = __frame->gr9; 133e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells y = __frame->gr10; 134e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells 135e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells for (;;) { 136e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells ret = get_user(z, p); 137e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells if (ret < 0) 138e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells goto error; 139e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells 140e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells if (z != x) 141e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells goto done; 142e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells 143e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells spin_lock_irq(&atomic_op_lock); 144e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells 145e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells if (__get_user(z, p) == 0) { 146e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells if (z != x) 147e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells goto done2; 148e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells 149e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells if (__put_user(y, p) == 0) 150e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells goto done2; 151e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells goto error2; 152e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells } 153e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells 154e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells spin_unlock_irq(&atomic_op_lock); 155e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells } 156e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells 157e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells /* TIRA gr0,#121 158e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells * u32 __atomic_kernel_xchg32(void *v, u32 new) 159e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells */ 160e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells case TBR_TT_ATOMIC_XCHG32: 161ff471b2464ca7344eba347d360f23ea415a774dcAl Viro p = (unsigned long __user *) __frame->gr8; 162e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells y = __frame->gr9; 163e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells 164e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells for (;;) { 165e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells ret = get_user(z, p); 166e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells if (ret < 0) 167e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells goto error; 168e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells 169e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells spin_lock_irq(&atomic_op_lock); 170e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells 171e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells if (__get_user(z, p) == 0) { 172e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells if (__put_user(y, p) == 0) 173e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells goto done2; 174e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells goto error2; 175e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells } 176e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells 177e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells spin_unlock_irq(&atomic_op_lock); 178e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells } 179e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells 180e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells /* TIRA gr0,#122 181e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells * ulong __atomic_kernel_XOR_return(ulong i, ulong *v) 182e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells */ 183e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells case TBR_TT_ATOMIC_XOR: 184ff471b2464ca7344eba347d360f23ea415a774dcAl Viro p = (unsigned long __user *) __frame->gr8; 185e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells x = __frame->gr9; 186e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells 187e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells for (;;) { 188e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells ret = get_user(z, p); 189e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells if (ret < 0) 190e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells goto error; 191e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells 192e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells spin_lock_irq(&atomic_op_lock); 193e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells 194e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells if (__get_user(z, p) == 0) { 195e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells y = x ^ z; 196e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells if (__put_user(y, p) == 0) 197e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells goto done2; 198e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells goto error2; 199e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells } 200e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells 201e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells spin_unlock_irq(&atomic_op_lock); 202e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells } 203e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells 204e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells /* TIRA gr0,#123 205e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells * ulong __atomic_kernel_OR_return(ulong i, ulong *v) 206e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells */ 207e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells case TBR_TT_ATOMIC_OR: 208ff471b2464ca7344eba347d360f23ea415a774dcAl Viro p = (unsigned long __user *) __frame->gr8; 209e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells x = __frame->gr9; 210e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells 211e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells for (;;) { 212e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells ret = get_user(z, p); 213e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells if (ret < 0) 214e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells goto error; 215e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells 216e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells spin_lock_irq(&atomic_op_lock); 217e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells 218e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells if (__get_user(z, p) == 0) { 219e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells y = x ^ z; 220e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells if (__put_user(y, p) == 0) 221e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells goto done2; 222e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells goto error2; 223e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells } 224e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells 225e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells spin_unlock_irq(&atomic_op_lock); 226e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells } 227e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells 228e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells /* TIRA gr0,#124 229e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells * ulong __atomic_kernel_AND_return(ulong i, ulong *v) 230e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells */ 231e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells case TBR_TT_ATOMIC_AND: 232ff471b2464ca7344eba347d360f23ea415a774dcAl Viro p = (unsigned long __user *) __frame->gr8; 233e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells x = __frame->gr9; 234e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells 235e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells for (;;) { 236e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells ret = get_user(z, p); 237e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells if (ret < 0) 238e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells goto error; 239e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells 240e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells spin_lock_irq(&atomic_op_lock); 241e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells 242e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells if (__get_user(z, p) == 0) { 243e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells y = x & z; 244e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells if (__put_user(y, p) == 0) 245e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells goto done2; 246e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells goto error2; 247e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells } 248e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells 249e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells spin_unlock_irq(&atomic_op_lock); 250e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells } 251e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells 252e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells /* TIRA gr0,#125 253e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells * int __atomic_user_sub_return(atomic_t *v, int i) 254e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells */ 255e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells case TBR_TT_ATOMIC_SUB: 256ff471b2464ca7344eba347d360f23ea415a774dcAl Viro p = (unsigned long __user *) __frame->gr8; 257e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells x = __frame->gr9; 258e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells 259e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells for (;;) { 260e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells ret = get_user(z, p); 261e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells if (ret < 0) 262e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells goto error; 263e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells 264e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells spin_lock_irq(&atomic_op_lock); 265e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells 266e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells if (__get_user(z, p) == 0) { 267e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells y = z - x; 268e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells if (__put_user(y, p) == 0) 269e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells goto done2; 270e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells goto error2; 271e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells } 272e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells 273e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells spin_unlock_irq(&atomic_op_lock); 274e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells } 275e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells 276e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells /* TIRA gr0,#126 277e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells * int __atomic_user_add_return(atomic_t *v, int i) 278e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells */ 279e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells case TBR_TT_ATOMIC_ADD: 280ff471b2464ca7344eba347d360f23ea415a774dcAl Viro p = (unsigned long __user *) __frame->gr8; 281e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells x = __frame->gr9; 282e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells 283e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells for (;;) { 284e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells ret = get_user(z, p); 285e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells if (ret < 0) 286e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells goto error; 287e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells 288e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells spin_lock_irq(&atomic_op_lock); 289e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells 290e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells if (__get_user(z, p) == 0) { 291e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells y = z + x; 292e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells if (__put_user(y, p) == 0) 293e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells goto done2; 294e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells goto error2; 295e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells } 296e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells 297e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells spin_unlock_irq(&atomic_op_lock); 298e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells } 299e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells 300e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells default: 301e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells BUG(); 302e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells } 303e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells 304e31c243f984628d02f045dc4b622f1e2827860dcDavid Howellsdone2: 305e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells spin_unlock_irq(&atomic_op_lock); 306e31c243f984628d02f045dc4b622f1e2827860dcDavid Howellsdone: 307e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells if (!user_mode(__frame)) 308e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells set_fs(oldfs); 309e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells __frame->gr5 = z; 310e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells __frame->gr9 = y; 311e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells return; 312e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells 313e31c243f984628d02f045dc4b622f1e2827860dcDavid Howellserror2: 314e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells spin_unlock_irq(&atomic_op_lock); 315e31c243f984628d02f045dc4b622f1e2827860dcDavid Howellserror: 316e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells if (!user_mode(__frame)) 317e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells set_fs(oldfs); 318e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells __frame->pc -= 4; 319e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells 320e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells die_if_kernel("-- Atomic Op Error --\n"); 321e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells 322e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells info.si_signo = SIGSEGV; 323e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells info.si_code = SEGV_ACCERR; 324e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells info.si_errno = 0; 325ff471b2464ca7344eba347d360f23ea415a774dcAl Viro info.si_addr = (void __user *) __frame->pc; 326e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells 327e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells force_sig_info(info.si_signo, &info, current); 328e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells} 329e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells 330e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells/*****************************************************************************/ 331e31c243f984628d02f045dc4b622f1e2827860dcDavid Howells/* 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsasmlinkage void media_exception(unsigned long msr0, unsigned long msr1) 3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds siginfo_t info; 3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds die_if_kernel("-- Media Exception --\n" 3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "MSR0 : %08lx\n" 3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "MSR1 : %08lx\n", 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds msr0, msr1); 3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info.si_signo = SIGFPE; 3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info.si_code = FPE_MDAOVF; 3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info.si_errno = 0; 346ff471b2464ca7344eba347d360f23ea415a774dcAl Viro info.si_addr = (void __user *) __frame->pc; 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds force_sig_info(info.si_signo, &info, current); 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} /* end media_exception() */ 3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*****************************************************************************/ 3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * instruction or data access exception 3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsasmlinkage void memory_access_exception(unsigned long esr0, 3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long ear0, 3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long epcr0) 3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds siginfo_t info; 3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_MMU 3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long fixup; 3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3646510d41954dc6a9c8b1dbca7eaca0f23195ca727Harvey Harrison fixup = search_exception_table(__frame->pc); 3656510d41954dc6a9c8b1dbca7eaca0f23195ca727Harvey Harrison if (fixup) { 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __frame->pc = fixup; 3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds die_if_kernel("-- Memory Access Exception --\n" 3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "ESR0 : %08lx\n" 3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "EAR0 : %08lx\n" 3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "EPCR0 : %08lx\n", 3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds esr0, ear0, epcr0); 3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info.si_signo = SIGSEGV; 3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info.si_code = SEGV_ACCERR; 3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info.si_errno = 0; 3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info.si_addr = NULL; 3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((esr0 & (ESRx_VALID | ESR0_EAV)) == (ESRx_VALID | ESR0_EAV)) 383ff471b2464ca7344eba347d360f23ea415a774dcAl Viro info.si_addr = (void __user *) ear0; 3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds force_sig_info(info.si_signo, &info, current); 3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} /* end memory_access_exception() */ 3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*****************************************************************************/ 3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * data access error 3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - double-word data load from CPU control area (0xFExxxxxx) 3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - read performed on inactive or self-refreshing SDRAM 3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - error notification from slave device 3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - misaligned address 3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - access to out of bounds memory region 3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - user mode accessing privileged memory region 3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - write to R/O memory region 3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsasmlinkage void data_access_error(unsigned long esfr1, unsigned long esr15, unsigned long ear15) 4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds siginfo_t info; 4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds die_if_kernel("-- Data Access Error --\n" 4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "ESR15 : %08lx\n" 4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "EAR15 : %08lx\n", 4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds esr15, ear15); 4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info.si_signo = SIGSEGV; 4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info.si_code = SEGV_ACCERR; 4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info.si_errno = 0; 412ff471b2464ca7344eba347d360f23ea415a774dcAl Viro info.si_addr = (void __user *) 4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (((esr15 & (ESRx_VALID|ESR15_EAV)) == (ESRx_VALID|ESR15_EAV)) ? ear15 : 0); 4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds force_sig_info(info.si_signo, &info, current); 4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} /* end data_access_error() */ 4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*****************************************************************************/ 4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * data store error - should only happen if accessing inactive or self-refreshing SDRAM 4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsasmlinkage void data_store_error(unsigned long esfr1, unsigned long esr15) 4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds die_if_kernel("-- Data Store Error --\n" 4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "ESR15 : %08lx\n", 4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds esr15); 4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BUG(); 4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} /* end data_store_error() */ 4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*****************************************************************************/ 4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsasmlinkage void division_exception(unsigned long esfr1, unsigned long esr0, unsigned long isr) 4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds siginfo_t info; 4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds die_if_kernel("-- Division Exception --\n" 4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "ESR0 : %08lx\n" 4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "ISR : %08lx\n", 4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds esr0, isr); 4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info.si_signo = SIGFPE; 4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info.si_code = FPE_INTDIV; 4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info.si_errno = 0; 446ff471b2464ca7344eba347d360f23ea415a774dcAl Viro info.si_addr = (void __user *) __frame->pc; 4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds force_sig_info(info.si_signo, &info, current); 4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} /* end division_exception() */ 4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*****************************************************************************/ 4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsasmlinkage void compound_exception(unsigned long esfr1, 4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long esr0, unsigned long esr14, unsigned long esr15, 4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long msr0, unsigned long msr1) 4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds die_if_kernel("-- Compound Exception --\n" 4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "ESR0 : %08lx\n" 4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "ESR15 : %08lx\n" 4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "ESR15 : %08lx\n" 4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "MSR0 : %08lx\n" 4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "MSR1 : %08lx\n", 4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds esr0, esr14, esr15, msr0, msr1); 4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BUG(); 4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} /* end compound_exception() */ 4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*****************************************************************************/ 4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The architecture-independent backtrace generator 4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid dump_stack(void) 4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds show_stack(NULL, NULL); 4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 478402344012ebe696d9353bbf056889ddaaec83079David HowellsEXPORT_SYMBOL(dump_stack); 479402344012ebe696d9353bbf056889ddaaec83079David Howells 4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid show_stack(struct task_struct *task, unsigned long *sp) 4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid show_trace_task(struct task_struct *tsk) 4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("CONTEXT: stack=0x%lx frame=0x%p LR=0x%lx RET=0x%lx\n", 4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tsk->thread.sp, tsk->thread.frame, tsk->thread.lr, tsk->thread.sched_lr); 4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const char *regnames[] = { 4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "PSR ", "ISR ", "CCR ", "CCCR", 4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "LR ", "LCR ", "PC ", "_stt", 4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "sys ", "GR8*", "GNE0", "GNE1", 4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "IACH", "IACL", 4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "TBR ", "SP ", "FP ", "GR3 ", 4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "GR4 ", "GR5 ", "GR6 ", "GR7 ", 4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "GR8 ", "GR9 ", "GR10", "GR11", 4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "GR12", "GR13", "GR14", "GR15", 4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "GR16", "GR17", "GR18", "GR19", 5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "GR20", "GR21", "GR22", "GR23", 5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "GR24", "GR25", "GR26", "GR27", 5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "EFRM", "CURR", "GR30", "BFRM" 5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid show_regs(struct pt_regs *regs) 5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 50784e8cd6dbc00b4979e8d1c15c80d91987aeb3417David Howells unsigned long *reg; 5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int loop; 5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("\n"); 5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 51284e8cd6dbc00b4979e8d1c15c80d91987aeb3417David Howells printk("Frame: @%08lx [%s]\n", 51384e8cd6dbc00b4979e8d1c15c80d91987aeb3417David Howells (unsigned long) regs, 5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds regs->psr & PSR_S ? "kernel" : "user"); 5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 51684e8cd6dbc00b4979e8d1c15c80d91987aeb3417David Howells reg = (unsigned long *) regs; 51784e8cd6dbc00b4979e8d1c15c80d91987aeb3417David Howells for (loop = 0; loop < NR_PT_REGS; loop++) { 51884e8cd6dbc00b4979e8d1c15c80d91987aeb3417David Howells printk("%s %08lx", regnames[loop + 0], reg[loop + 0]); 5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 52084e8cd6dbc00b4979e8d1c15c80d91987aeb3417David Howells if (loop == NR_PT_REGS - 1 || loop % 5 == 4) 5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("\n"); 5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(" | "); 5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("Process %s (pid: %d)\n", current->comm, current->pid); 5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid die_if_kernel(const char *str, ...) 5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char buffer[256]; 5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds va_list va; 5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (user_mode(__frame)) 5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds va_start(va, str); 5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vsprintf(buffer, str, va); 5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds va_end(va); 5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds console_verbose(); 5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("\n===================================\n"); 5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("%s\n", buffer); 5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds show_backtrace(__frame, 0); 5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __break_hijack_kernel_event(); 5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do_exit(SIGSEGV); 5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*****************************************************************************/ 5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * dump the contents of an exception frame 5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void show_backtrace_regs(struct pt_regs *frame) 5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 55684e8cd6dbc00b4979e8d1c15c80d91987aeb3417David Howells unsigned long *reg; 5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int loop; 5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* print the registers for this frame */ 5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("<-- %s Frame: @%p -->\n", 5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds frame->psr & PSR_S ? "Kernel Mode" : "User Mode", 5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds frame); 5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 56484e8cd6dbc00b4979e8d1c15c80d91987aeb3417David Howells reg = (unsigned long *) frame; 56584e8cd6dbc00b4979e8d1c15c80d91987aeb3417David Howells for (loop = 0; loop < NR_PT_REGS; loop++) { 56684e8cd6dbc00b4979e8d1c15c80d91987aeb3417David Howells printk("%s %08lx", regnames[loop + 0], reg[loop + 0]); 5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 56884e8cd6dbc00b4979e8d1c15c80d91987aeb3417David Howells if (loop == NR_PT_REGS - 1 || loop % 5 == 4) 5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("\n"); 5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(" | "); 5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("--------\n"); 5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} /* end show_backtrace_regs() */ 5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*****************************************************************************/ 5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * generate a backtrace of the kernel stack 5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid show_backtrace(struct pt_regs *frame, unsigned long sp) 5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pt_regs *frame0; 5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long tos = 0, stop = 0, base; 5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int format; 5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds base = ((((unsigned long) frame) + 8191) & ~8191) - sizeof(struct user_context); 5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds frame0 = (struct pt_regs *) base; 5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sp) { 5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tos = sp; 5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stop = (unsigned long) frame; 5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("\nProcess %s (pid: %d)\n\n", current->comm, current->pid); 5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (;;) { 5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* dump stack segment between frames */ 5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds //printk("%08lx -> %08lx\n", tos, stop); 6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds format = 0; 6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (tos < stop) { 6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (format == 0) 6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(" %04lx :", tos & 0xffff); 6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(" %08lx", *(unsigned long *) tos); 6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tos += 4; 6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds format++; 6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (format == 8) { 6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("\n"); 6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds format = 0; 6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (format > 0) 6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("\n"); 6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* dump frame 0 outside of the loop */ 6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (frame == frame0) 6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tos = frame->sp; 6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (((unsigned long) frame) + sizeof(*frame) != tos) { 6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("-- TOS %08lx does not follow frame %p --\n", 6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tos, frame); 6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds show_backtrace_regs(frame); 6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* dump the stack between this frame and the next */ 6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stop = (unsigned long) frame->next_frame; 6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (stop != base && 6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (stop < tos || 6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stop > base || 6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (stop < base && stop + sizeof(*frame) > base) || 6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stop & 3)) { 6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("-- next_frame %08lx is invalid (range %08lx-%08lx) --\n", 6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stop, tos, base); 6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* move to next frame */ 6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds frame = frame->next_frame; 6451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* we can always dump frame 0, even if the rest of the stack is corrupt */ 6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds show_backtrace_regs(frame0); 6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} /* end show_backtrace() */ 6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*****************************************************************************/ 6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * initialise traps 6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid __init trap_init (void) 6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} /* end trap_init() */ 659