16b0022305f80cf249de69e746f6f5ccf7ffc5b7cPaul Mundt/* 26b0022305f80cf249de69e746f6f5ccf7ffc5b7cPaul Mundt * 'traps.c' handles hardware traps and faults after we have saved some 36b0022305f80cf249de69e746f6f5ccf7ffc5b7cPaul Mundt * state in 'entry.S'. 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * SuperH version: Copyright (C) 1999 Niibe Yutaka 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 2000 Philipp Rumpf 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 2000 David Howells 8ace2dc7d12693545b67f15ab8cdb3d255c937713Paul Mundt * Copyright (C) 2002 - 2010 Paul Mundt 96b0022305f80cf249de69e746f6f5ccf7ffc5b7cPaul Mundt * 106b0022305f80cf249de69e746f6f5ccf7ffc5b7cPaul Mundt * This file is subject to the terms and conditions of the GNU General Public 116b0022305f80cf249de69e746f6f5ccf7ffc5b7cPaul Mundt * License. See the file "COPYING" in the main directory of this archive 126b0022305f80cf249de69e746f6f5ccf7ffc5b7cPaul Mundt * for more details. 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h> 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ptrace.h> 16ba84be2338d3a2b6020d39279335bb06fcd332e1Russell King#include <linux/hardirq.h> 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/spinlock.h> 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kallsyms.h> 211f666587dbf6bc660b23d8dd8abb6c572ce3eae5Paul Mundt#include <linux/io.h> 22fa69151173b1fc6fa3ced0edd5c2ea83b5d32bc1Paul Mundt#include <linux/bug.h> 239b8c90eb0d916f6802f8bbac79f61aca6ac533e8Paul Mundt#include <linux/debug_locks.h> 24b118ca572db5af832c6fc1af7b301105378d1a08Paul Mundt#include <linux/kdebug.h> 25e113276624104d9c3b25f333d8dd999b804d980aPaul Mundt#include <linux/kexec.h> 26dc34d312c7b25d5d0f54c16d143a9526936e5d38Paul Mundt#include <linux/limits.h> 27af67c3a9e68ee0a9e30ee8582577408adba0e299Paul Mundt#include <linux/sysfs.h> 28a99eae5417a09e0be66bf574a9a79a2a7388c967Paul Mundt#include <linux/uaccess.h> 29ace2dc7d12693545b67f15ab8cdb3d255c937713Paul Mundt#include <linux/perf_event.h> 30a99eae5417a09e0be66bf574a9a79a2a7388c967Paul Mundt#include <asm/alignment.h> 31fad0f90134197259b5a935c69d7556ee847f242cAndrew Morton#include <asm/fpu.h> 32d39f5450146ff39f66cfde9d5184420627d0ac51Chris Smith#include <asm/kprobes.h> 33e839ca528718e68cad32a307dc9aabf01ef3eb05David Howells#include <asm/traps.h> 34e839ca528718e68cad32a307dc9aabf01ef3eb05David Howells#include <asm/bl_bit.h> 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_CPU_SH2 370983b31849bbe1fe82520947acc1bec97c457d4bYoshinori Sato# define TRAP_RESERVED_INST 4 380983b31849bbe1fe82520947acc1bec97c457d4bYoshinori Sato# define TRAP_ILLEGAL_SLOT_INST 6 390983b31849bbe1fe82520947acc1bec97c457d4bYoshinori Sato# define TRAP_ADDRESS_ERROR 9 400983b31849bbe1fe82520947acc1bec97c457d4bYoshinori Sato# ifdef CONFIG_CPU_SH2A 41cd89436e54b29a07a383ee82f2f718d8c9d24cc4Peter Griffin# define TRAP_UBC 12 426e80f5e8c4c685eb7bc34c3916e3d986b03f9981Yoshinori Sato# define TRAP_FPU_ERROR 13 430983b31849bbe1fe82520947acc1bec97c457d4bYoshinori Sato# define TRAP_DIVZERO_ERROR 17 440983b31849bbe1fe82520947acc1bec97c457d4bYoshinori Sato# define TRAP_DIVOVF_ERROR 18 450983b31849bbe1fe82520947acc1bec97c457d4bYoshinori Sato# endif 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TRAP_RESERVED_INST 12 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TRAP_ILLEGAL_SLOT_INST 13 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 516b0022305f80cf249de69e746f6f5ccf7ffc5b7cPaul Mundtstatic void dump_mem(const char *str, unsigned long bottom, unsigned long top) 526b0022305f80cf249de69e746f6f5ccf7ffc5b7cPaul Mundt{ 536b0022305f80cf249de69e746f6f5ccf7ffc5b7cPaul Mundt unsigned long p; 546b0022305f80cf249de69e746f6f5ccf7ffc5b7cPaul Mundt int i; 556b0022305f80cf249de69e746f6f5ccf7ffc5b7cPaul Mundt 566b0022305f80cf249de69e746f6f5ccf7ffc5b7cPaul Mundt printk("%s(0x%08lx to 0x%08lx)\n", str, bottom, top); 576b0022305f80cf249de69e746f6f5ccf7ffc5b7cPaul Mundt 586b0022305f80cf249de69e746f6f5ccf7ffc5b7cPaul Mundt for (p = bottom & ~31; p < top; ) { 596b0022305f80cf249de69e746f6f5ccf7ffc5b7cPaul Mundt printk("%04lx: ", p & 0xffff); 606b0022305f80cf249de69e746f6f5ccf7ffc5b7cPaul Mundt 616b0022305f80cf249de69e746f6f5ccf7ffc5b7cPaul Mundt for (i = 0; i < 8; i++, p += 4) { 626b0022305f80cf249de69e746f6f5ccf7ffc5b7cPaul Mundt unsigned int val; 636b0022305f80cf249de69e746f6f5ccf7ffc5b7cPaul Mundt 646b0022305f80cf249de69e746f6f5ccf7ffc5b7cPaul Mundt if (p < bottom || p >= top) 656b0022305f80cf249de69e746f6f5ccf7ffc5b7cPaul Mundt printk(" "); 666b0022305f80cf249de69e746f6f5ccf7ffc5b7cPaul Mundt else { 676b0022305f80cf249de69e746f6f5ccf7ffc5b7cPaul Mundt if (__get_user(val, (unsigned int __user *)p)) { 686b0022305f80cf249de69e746f6f5ccf7ffc5b7cPaul Mundt printk("\n"); 696b0022305f80cf249de69e746f6f5ccf7ffc5b7cPaul Mundt return; 706b0022305f80cf249de69e746f6f5ccf7ffc5b7cPaul Mundt } 716b0022305f80cf249de69e746f6f5ccf7ffc5b7cPaul Mundt printk("%08x ", val); 726b0022305f80cf249de69e746f6f5ccf7ffc5b7cPaul Mundt } 736b0022305f80cf249de69e746f6f5ccf7ffc5b7cPaul Mundt } 746b0022305f80cf249de69e746f6f5ccf7ffc5b7cPaul Mundt printk("\n"); 756b0022305f80cf249de69e746f6f5ccf7ffc5b7cPaul Mundt } 766b0022305f80cf249de69e746f6f5ccf7ffc5b7cPaul Mundt} 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 783a2e117e220f000f95187ea1e1bbe83b0ed5fdfbPaul Mundtstatic DEFINE_SPINLOCK(die_lock); 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid die(const char * str, struct pt_regs * regs, long err) 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds static int die_counter; 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 845527398218aae85f37552a69fad163fa500c39e4Paul Mundt oops_enter(); 855527398218aae85f37552a69fad163fa500c39e4Paul Mundt 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irq(&die_lock); 87af67c3a9e68ee0a9e30ee8582577408adba0e299Paul Mundt console_verbose(); 886b0022305f80cf249de69e746f6f5ccf7ffc5b7cPaul Mundt bust_spinlocks(1); 896b0022305f80cf249de69e746f6f5ccf7ffc5b7cPaul Mundt 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter); 916b0022305f80cf249de69e746f6f5ccf7ffc5b7cPaul Mundt print_modules(); 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds show_regs(regs); 936b0022305f80cf249de69e746f6f5ccf7ffc5b7cPaul Mundt 9419c5870c0eefd27c6d09d867465e0571262e05d0Alexey Dobriyan printk("Process: %s (pid: %d, stack limit = %p)\n", current->comm, 9519c5870c0eefd27c6d09d867465e0571262e05d0Alexey Dobriyan task_pid_nr(current), task_stack_page(current) + 1); 966b0022305f80cf249de69e746f6f5ccf7ffc5b7cPaul Mundt 976b0022305f80cf249de69e746f6f5ccf7ffc5b7cPaul Mundt if (!user_mode(regs) || in_interrupt()) 986b0022305f80cf249de69e746f6f5ccf7ffc5b7cPaul Mundt dump_mem("Stack: ", regs->regs[15], THREAD_SIZE + 99b5a1bcbee434b843c8850a968d9a6c7541f1be9dStuart Menefy (unsigned long)task_stack_page(current)); 1006b0022305f80cf249de69e746f6f5ccf7ffc5b7cPaul Mundt 101c9306f0efbfbe65a6e9212082f1d1fc19fdc3094Paul Mundt notify_die(DIE_OOPS, str, regs, err, 255, SIGSEGV); 102c9306f0efbfbe65a6e9212082f1d1fc19fdc3094Paul Mundt 1036b0022305f80cf249de69e746f6f5ccf7ffc5b7cPaul Mundt bust_spinlocks(0); 104bcdcd8e725b923ad7c0de809680d5d5658a7bf8cPavel Emelianov add_taint(TAINT_DIE); 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irq(&die_lock); 106af67c3a9e68ee0a9e30ee8582577408adba0e299Paul Mundt oops_exit(); 107e113276624104d9c3b25f333d8dd999b804d980aPaul Mundt 108e113276624104d9c3b25f333d8dd999b804d980aPaul Mundt if (kexec_should_crash(current)) 109e113276624104d9c3b25f333d8dd999b804d980aPaul Mundt crash_kexec(regs); 110e113276624104d9c3b25f333d8dd999b804d980aPaul Mundt 111e113276624104d9c3b25f333d8dd999b804d980aPaul Mundt if (in_interrupt()) 112e113276624104d9c3b25f333d8dd999b804d980aPaul Mundt panic("Fatal exception in interrupt"); 113e113276624104d9c3b25f333d8dd999b804d980aPaul Mundt 114e113276624104d9c3b25f333d8dd999b804d980aPaul Mundt if (panic_on_oops) 115e113276624104d9c3b25f333d8dd999b804d980aPaul Mundt panic("Fatal exception"); 116e113276624104d9c3b25f333d8dd999b804d980aPaul Mundt 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do_exit(SIGSEGV); 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1206b0022305f80cf249de69e746f6f5ccf7ffc5b7cPaul Mundtstatic inline void die_if_kernel(const char *str, struct pt_regs *regs, 1216b0022305f80cf249de69e746f6f5ccf7ffc5b7cPaul Mundt long err) 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!user_mode(regs)) 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds die(str, regs, err); 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * try and fix up kernelspace address errors 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - userspace errors just cause EFAULT to be returned, resulting in SEGV 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - kernel/userspace interfaces cause a jump to an appropriate handler 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - other kernel errors are bad 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1332afb447f33c29cb000a494396559f8005d3e33c1SUGIOKA Toshinobustatic void die_if_no_fixup(const char * str, struct pt_regs * regs, long err) 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1356b0022305f80cf249de69e746f6f5ccf7ffc5b7cPaul Mundt if (!user_mode(regs)) { 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds const struct exception_table_entry *fixup; 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fixup = search_exception_tables(regs->pc); 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fixup) { 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds regs->pc = fixup->fixup; 1402afb447f33c29cb000a494396559f8005d3e33c1SUGIOKA Toshinobu return; 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 142b344e24a8e8ceda83d1285d22e3e5baf4f5e42d3Matt Fleming 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds die(str, regs, err); 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14786c0179c9307bd600a96a44d623814c33bdbe0f0Magnus Dammstatic inline void sign_extend(unsigned int count, unsigned char *dst) 14886c0179c9307bd600a96a44d623814c33bdbe0f0Magnus Damm{ 14986c0179c9307bd600a96a44d623814c33bdbe0f0Magnus Damm#ifdef __LITTLE_ENDIAN__ 1504252c659a4e7f4260e4bdc87538578236c51ab2dMagnus Damm if ((count == 1) && dst[0] & 0x80) { 1514252c659a4e7f4260e4bdc87538578236c51ab2dMagnus Damm dst[1] = 0xff; 1524252c659a4e7f4260e4bdc87538578236c51ab2dMagnus Damm dst[2] = 0xff; 1534252c659a4e7f4260e4bdc87538578236c51ab2dMagnus Damm dst[3] = 0xff; 1544252c659a4e7f4260e4bdc87538578236c51ab2dMagnus Damm } 15586c0179c9307bd600a96a44d623814c33bdbe0f0Magnus Damm if ((count == 2) && dst[1] & 0x80) { 15686c0179c9307bd600a96a44d623814c33bdbe0f0Magnus Damm dst[2] = 0xff; 15786c0179c9307bd600a96a44d623814c33bdbe0f0Magnus Damm dst[3] = 0xff; 15886c0179c9307bd600a96a44d623814c33bdbe0f0Magnus Damm } 15986c0179c9307bd600a96a44d623814c33bdbe0f0Magnus Damm#else 1604252c659a4e7f4260e4bdc87538578236c51ab2dMagnus Damm if ((count == 1) && dst[3] & 0x80) { 1614252c659a4e7f4260e4bdc87538578236c51ab2dMagnus Damm dst[2] = 0xff; 1624252c659a4e7f4260e4bdc87538578236c51ab2dMagnus Damm dst[1] = 0xff; 16386c0179c9307bd600a96a44d623814c33bdbe0f0Magnus Damm dst[0] = 0xff; 1644252c659a4e7f4260e4bdc87538578236c51ab2dMagnus Damm } 1654252c659a4e7f4260e4bdc87538578236c51ab2dMagnus Damm if ((count == 2) && dst[2] & 0x80) { 16686c0179c9307bd600a96a44d623814c33bdbe0f0Magnus Damm dst[1] = 0xff; 1674252c659a4e7f4260e4bdc87538578236c51ab2dMagnus Damm dst[0] = 0xff; 16886c0179c9307bd600a96a44d623814c33bdbe0f0Magnus Damm } 16986c0179c9307bd600a96a44d623814c33bdbe0f0Magnus Damm#endif 17086c0179c9307bd600a96a44d623814c33bdbe0f0Magnus Damm} 17186c0179c9307bd600a96a44d623814c33bdbe0f0Magnus Damm 172e7cc9a7340b8ec018caa9eb1d035fdaef1f2fc51Magnus Dammstatic struct mem_access user_mem_access = { 173e7cc9a7340b8ec018caa9eb1d035fdaef1f2fc51Magnus Damm copy_from_user, 174e7cc9a7340b8ec018caa9eb1d035fdaef1f2fc51Magnus Damm copy_to_user, 175e7cc9a7340b8ec018caa9eb1d035fdaef1f2fc51Magnus Damm}; 176e7cc9a7340b8ec018caa9eb1d035fdaef1f2fc51Magnus Damm 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * handle an instruction that does an unaligned memory access by emulating the 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * desired behaviour 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - note that PC _may not_ point to the faulting instruction 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (if that instruction is in a branch delay slot) 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - return 0 if emulation okay, -EFAULT on existential error 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1842bcfffa42309b6f73042c62459bf5207762a271dPaul Mundtstatic int handle_unaligned_ins(insn_size_t instruction, struct pt_regs *regs, 185e7cc9a7340b8ec018caa9eb1d035fdaef1f2fc51Magnus Damm struct mem_access *ma) 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret, index, count; 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long *rm, *rn; 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned char *src, *dst; 190fa43972fab24a3c050e880a7831f9378c6cebc0bPaul Mundt unsigned char __user *srcu, *dstu; 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds index = (instruction>>8)&15; /* 0x0F00 */ 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rn = ®s->regs[index]; 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds index = (instruction>>4)&15; /* 0x00F0 */ 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rm = ®s->regs[index]; 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds count = 1<<(instruction&3); 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2007436cde6b2ca71049051620c68c26522bb3403bfAndre Draszik switch (count) { 201a99eae5417a09e0be66bf574a9a79a2a7388c967Paul Mundt case 1: inc_unaligned_byte_access(); break; 202a99eae5417a09e0be66bf574a9a79a2a7388c967Paul Mundt case 2: inc_unaligned_word_access(); break; 203a99eae5417a09e0be66bf574a9a79a2a7388c967Paul Mundt case 4: inc_unaligned_dword_access(); break; 204a99eae5417a09e0be66bf574a9a79a2a7388c967Paul Mundt case 8: inc_unaligned_multi_access(); break; 2057436cde6b2ca71049051620c68c26522bb3403bfAndre Draszik } 2067436cde6b2ca71049051620c68c26522bb3403bfAndre Draszik 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -EFAULT; 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (instruction>>12) { 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0: /* mov.[bwl] to/from memory via r0+rn */ 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (instruction & 8) { 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* from memory */ 212fa43972fab24a3c050e880a7831f9378c6cebc0bPaul Mundt srcu = (unsigned char __user *)*rm; 213fa43972fab24a3c050e880a7831f9378c6cebc0bPaul Mundt srcu += regs->regs[0]; 214fa43972fab24a3c050e880a7831f9378c6cebc0bPaul Mundt dst = (unsigned char *)rn; 215fa43972fab24a3c050e880a7831f9378c6cebc0bPaul Mundt *(unsigned long *)dst = 0; 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21786c0179c9307bd600a96a44d623814c33bdbe0f0Magnus Damm#if !defined(__LITTLE_ENDIAN__) 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dst += 4-count; 21986c0179c9307bd600a96a44d623814c33bdbe0f0Magnus Damm#endif 220fa43972fab24a3c050e880a7831f9378c6cebc0bPaul Mundt if (ma->from(dst, srcu, count)) 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fetch_fault; 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 22386c0179c9307bd600a96a44d623814c33bdbe0f0Magnus Damm sign_extend(count, dst); 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* to memory */ 226fa43972fab24a3c050e880a7831f9378c6cebc0bPaul Mundt src = (unsigned char *)rm; 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if !defined(__LITTLE_ENDIAN__) 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds src += 4-count; 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 230fa43972fab24a3c050e880a7831f9378c6cebc0bPaul Mundt dstu = (unsigned char __user *)*rn; 231fa43972fab24a3c050e880a7831f9378c6cebc0bPaul Mundt dstu += regs->regs[0]; 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 233fa43972fab24a3c050e880a7831f9378c6cebc0bPaul Mundt if (ma->to(dstu, src, count)) 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fetch_fault; 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = 0; 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 1: /* mov.l Rm,@(disp,Rn) */ 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds src = (unsigned char*) rm; 241fa43972fab24a3c050e880a7831f9378c6cebc0bPaul Mundt dstu = (unsigned char __user *)*rn; 242fa43972fab24a3c050e880a7831f9378c6cebc0bPaul Mundt dstu += (instruction&0x000F)<<2; 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 244fa43972fab24a3c050e880a7831f9378c6cebc0bPaul Mundt if (ma->to(dstu, src, 4)) 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fetch_fault; 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = 0; 247b5a1bcbee434b843c8850a968d9a6c7541f1be9dStuart Menefy break; 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 2: /* mov.[bwl] to memory, possibly with pre-decrement */ 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (instruction & 4) 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *rn -= count; 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds src = (unsigned char*) rm; 253fa43972fab24a3c050e880a7831f9378c6cebc0bPaul Mundt dstu = (unsigned char __user *)*rn; 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if !defined(__LITTLE_ENDIAN__) 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds src += 4-count; 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 257fa43972fab24a3c050e880a7831f9378c6cebc0bPaul Mundt if (ma->to(dstu, src, count)) 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fetch_fault; 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = 0; 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 5: /* mov.l @(disp,Rm),Rn */ 263fa43972fab24a3c050e880a7831f9378c6cebc0bPaul Mundt srcu = (unsigned char __user *)*rm; 264fa43972fab24a3c050e880a7831f9378c6cebc0bPaul Mundt srcu += (instruction & 0x000F) << 2; 265fa43972fab24a3c050e880a7831f9378c6cebc0bPaul Mundt dst = (unsigned char *)rn; 266fa43972fab24a3c050e880a7831f9378c6cebc0bPaul Mundt *(unsigned long *)dst = 0; 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 268fa43972fab24a3c050e880a7831f9378c6cebc0bPaul Mundt if (ma->from(dst, srcu, 4)) 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fetch_fault; 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = 0; 271b5a1bcbee434b843c8850a968d9a6c7541f1be9dStuart Menefy break; 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 6: /* mov.[bwl] from memory, possibly with post-increment */ 274fa43972fab24a3c050e880a7831f9378c6cebc0bPaul Mundt srcu = (unsigned char __user *)*rm; 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (instruction & 4) 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *rm += count; 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dst = (unsigned char*) rn; 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *(unsigned long*)dst = 0; 279b5a1bcbee434b843c8850a968d9a6c7541f1be9dStuart Menefy 28086c0179c9307bd600a96a44d623814c33bdbe0f0Magnus Damm#if !defined(__LITTLE_ENDIAN__) 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dst += 4-count; 28286c0179c9307bd600a96a44d623814c33bdbe0f0Magnus Damm#endif 283fa43972fab24a3c050e880a7831f9378c6cebc0bPaul Mundt if (ma->from(dst, srcu, count)) 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fetch_fault; 28586c0179c9307bd600a96a44d623814c33bdbe0f0Magnus Damm sign_extend(count, dst); 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = 0; 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 8: 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch ((instruction&0xFF00)>>8) { 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x81: /* mov.w R0,@(disp,Rn) */ 292fa43972fab24a3c050e880a7831f9378c6cebc0bPaul Mundt src = (unsigned char *) ®s->regs[0]; 2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if !defined(__LITTLE_ENDIAN__) 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds src += 2; 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 296fa43972fab24a3c050e880a7831f9378c6cebc0bPaul Mundt dstu = (unsigned char __user *)*rm; /* called Rn in the spec */ 297fa43972fab24a3c050e880a7831f9378c6cebc0bPaul Mundt dstu += (instruction & 0x000F) << 1; 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 299fa43972fab24a3c050e880a7831f9378c6cebc0bPaul Mundt if (ma->to(dstu, src, 2)) 3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fetch_fault; 3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = 0; 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x85: /* mov.w @(disp,Rm),R0 */ 305fa43972fab24a3c050e880a7831f9378c6cebc0bPaul Mundt srcu = (unsigned char __user *)*rm; 306fa43972fab24a3c050e880a7831f9378c6cebc0bPaul Mundt srcu += (instruction & 0x000F) << 1; 307fa43972fab24a3c050e880a7831f9378c6cebc0bPaul Mundt dst = (unsigned char *) ®s->regs[0]; 308fa43972fab24a3c050e880a7831f9378c6cebc0bPaul Mundt *(unsigned long *)dst = 0; 3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if !defined(__LITTLE_ENDIAN__) 3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dst += 2; 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 313fa43972fab24a3c050e880a7831f9378c6cebc0bPaul Mundt if (ma->from(dst, srcu, 2)) 3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fetch_fault; 31586c0179c9307bd600a96a44d623814c33bdbe0f0Magnus Damm sign_extend(2, dst); 3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = 0; 3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 32034f7145a63211eb7ecfcafa6c2a8db5646baf953Phil Edworthy 32134f7145a63211eb7ecfcafa6c2a8db5646baf953Phil Edworthy case 9: /* mov.w @(disp,PC),Rn */ 32234f7145a63211eb7ecfcafa6c2a8db5646baf953Phil Edworthy srcu = (unsigned char __user *)regs->pc; 32334f7145a63211eb7ecfcafa6c2a8db5646baf953Phil Edworthy srcu += 4; 32434f7145a63211eb7ecfcafa6c2a8db5646baf953Phil Edworthy srcu += (instruction & 0x00FF) << 1; 32534f7145a63211eb7ecfcafa6c2a8db5646baf953Phil Edworthy dst = (unsigned char *)rn; 32634f7145a63211eb7ecfcafa6c2a8db5646baf953Phil Edworthy *(unsigned long *)dst = 0; 32734f7145a63211eb7ecfcafa6c2a8db5646baf953Phil Edworthy 32834f7145a63211eb7ecfcafa6c2a8db5646baf953Phil Edworthy#if !defined(__LITTLE_ENDIAN__) 32934f7145a63211eb7ecfcafa6c2a8db5646baf953Phil Edworthy dst += 2; 33034f7145a63211eb7ecfcafa6c2a8db5646baf953Phil Edworthy#endif 33134f7145a63211eb7ecfcafa6c2a8db5646baf953Phil Edworthy 33234f7145a63211eb7ecfcafa6c2a8db5646baf953Phil Edworthy if (ma->from(dst, srcu, 2)) 33334f7145a63211eb7ecfcafa6c2a8db5646baf953Phil Edworthy goto fetch_fault; 33434f7145a63211eb7ecfcafa6c2a8db5646baf953Phil Edworthy sign_extend(2, dst); 33534f7145a63211eb7ecfcafa6c2a8db5646baf953Phil Edworthy ret = 0; 33634f7145a63211eb7ecfcafa6c2a8db5646baf953Phil Edworthy break; 33734f7145a63211eb7ecfcafa6c2a8db5646baf953Phil Edworthy 33834f7145a63211eb7ecfcafa6c2a8db5646baf953Phil Edworthy case 0xd: /* mov.l @(disp,PC),Rn */ 33934f7145a63211eb7ecfcafa6c2a8db5646baf953Phil Edworthy srcu = (unsigned char __user *)(regs->pc & ~0x3); 34034f7145a63211eb7ecfcafa6c2a8db5646baf953Phil Edworthy srcu += 4; 34134f7145a63211eb7ecfcafa6c2a8db5646baf953Phil Edworthy srcu += (instruction & 0x00FF) << 2; 34234f7145a63211eb7ecfcafa6c2a8db5646baf953Phil Edworthy dst = (unsigned char *)rn; 34334f7145a63211eb7ecfcafa6c2a8db5646baf953Phil Edworthy *(unsigned long *)dst = 0; 34434f7145a63211eb7ecfcafa6c2a8db5646baf953Phil Edworthy 34534f7145a63211eb7ecfcafa6c2a8db5646baf953Phil Edworthy if (ma->from(dst, srcu, 4)) 34634f7145a63211eb7ecfcafa6c2a8db5646baf953Phil Edworthy goto fetch_fault; 34734f7145a63211eb7ecfcafa6c2a8db5646baf953Phil Edworthy ret = 0; 34834f7145a63211eb7ecfcafa6c2a8db5646baf953Phil Edworthy break; 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fetch_fault: 3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Argh. Address not only misaligned but also non-existent. 3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Raise an EFAULT and see if it's trapped 3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3562afb447f33c29cb000a494396559f8005d3e33c1SUGIOKA Toshinobu die_if_no_fixup("Fault in unaligned fixup", regs, 0); 3572afb447f33c29cb000a494396559f8005d3e33c1SUGIOKA Toshinobu return -EFAULT; 3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * emulate the instruction in the delay slot 3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - fetches the instruction from PC+2 3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 364e7cc9a7340b8ec018caa9eb1d035fdaef1f2fc51Magnus Dammstatic inline int handle_delayslot(struct pt_regs *regs, 3652bcfffa42309b6f73042c62459bf5207762a271dPaul Mundt insn_size_t old_instruction, 366e7cc9a7340b8ec018caa9eb1d035fdaef1f2fc51Magnus Damm struct mem_access *ma) 3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3682bcfffa42309b6f73042c62459bf5207762a271dPaul Mundt insn_size_t instruction; 369fa43972fab24a3c050e880a7831f9378c6cebc0bPaul Mundt void __user *addr = (void __user *)(regs->pc + 370fa43972fab24a3c050e880a7831f9378c6cebc0bPaul Mundt instruction_size(old_instruction)); 3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3724b5a9ef5279aed2c34d92fee62cf6d0c6ffacbaaMagnus Damm if (copy_from_user(&instruction, addr, sizeof(instruction))) { 3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* the instruction-fetch faulted */ 3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (user_mode(regs)) 3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* kernel */ 378b5a1bcbee434b843c8850a968d9a6c7541f1be9dStuart Menefy die("delay-slot-insn faulting in handle_unaligned_delayslot", 379b5a1bcbee434b843c8850a968d9a6c7541f1be9dStuart Menefy regs, 0); 3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 382e7cc9a7340b8ec018caa9eb1d035fdaef1f2fc51Magnus Damm return handle_unaligned_ins(instruction, regs, ma); 3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * handle an instruction that does an unaligned memory access 3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - have to be careful of branch delay-slot instructions that fault 3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * SH3: 3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - if the branch would be taken PC points to the branch 3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - if the branch would not be taken, PC points to delay-slot 3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * SH4: 3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - PC always points to delayed branch 3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - return 0 if handled, -EFAULT if failed (may not return if in kernel) 3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Macros to determine offset from current PC for branch instructions */ 3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Explicit type coercion is used to force sign extension where needed */ 3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SH_PC_8BIT_OFFSET(instr) ((((signed char)(instr))*2) + 4) 3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SH_PC_12BIT_OFFSET(instr) ((((signed short)(instr<<4))>>3) + 4) 4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4012bcfffa42309b6f73042c62459bf5207762a271dPaul Mundtint handle_unaligned_access(insn_size_t instruction, struct pt_regs *regs, 402ace2dc7d12693545b67f15ab8cdb3d255c937713Paul Mundt struct mem_access *ma, int expected, 403ace2dc7d12693545b67f15ab8cdb3d255c937713Paul Mundt unsigned long address) 4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_int rm; 4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret, index; 4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 40823c4c82171008c8b18d8627c9741cdd577631ceaPaul Mundt /* 40923c4c82171008c8b18d8627c9741cdd577631ceaPaul Mundt * XXX: We can't handle mixed 16/32-bit instructions yet 41023c4c82171008c8b18d8627c9741cdd577631ceaPaul Mundt */ 41123c4c82171008c8b18d8627c9741cdd577631ceaPaul Mundt if (instruction_size(instruction) != 2) 41223c4c82171008c8b18d8627c9741cdd577631ceaPaul Mundt return -EINVAL; 41323c4c82171008c8b18d8627c9741cdd577631ceaPaul Mundt 4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds index = (instruction>>8)&15; /* 0x0F00 */ 4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rm = regs->regs[index]; 4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 417ace2dc7d12693545b67f15ab8cdb3d255c937713Paul Mundt /* 418ace2dc7d12693545b67f15ab8cdb3d255c937713Paul Mundt * Log the unexpected fixups, and then pass them on to perf. 419ace2dc7d12693545b67f15ab8cdb3d255c937713Paul Mundt * 420ace2dc7d12693545b67f15ab8cdb3d255c937713Paul Mundt * We intentionally don't report the expected cases to perf as 421ace2dc7d12693545b67f15ab8cdb3d255c937713Paul Mundt * otherwise the trapped I/O case will skew the results too much 422ace2dc7d12693545b67f15ab8cdb3d255c937713Paul Mundt * to be useful. 423ace2dc7d12693545b67f15ab8cdb3d255c937713Paul Mundt */ 424ace2dc7d12693545b67f15ab8cdb3d255c937713Paul Mundt if (!expected) { 425a99eae5417a09e0be66bf574a9a79a2a7388c967Paul Mundt unaligned_fixups_notify(current, instruction, regs); 426a8b0ca17b80e92faab46ee7179ba9e99ccb61233Peter Zijlstra perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, 427ace2dc7d12693545b67f15ab8cdb3d255c937713Paul Mundt regs, address); 428ace2dc7d12693545b67f15ab8cdb3d255c937713Paul Mundt } 4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -EFAULT; 4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (instruction&0xF000) { 4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x0000: 4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (instruction==0x000B) { 4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* rts */ 435e7cc9a7340b8ec018caa9eb1d035fdaef1f2fc51Magnus Damm ret = handle_delayslot(regs, instruction, ma); 4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret==0) 4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds regs->pc = regs->pr; 4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if ((instruction&0x00FF)==0x0023) { 4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* braf @Rm */ 441e7cc9a7340b8ec018caa9eb1d035fdaef1f2fc51Magnus Damm ret = handle_delayslot(regs, instruction, ma); 4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret==0) 4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds regs->pc += rm + 4; 4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if ((instruction&0x00FF)==0x0003) { 4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* bsrf @Rm */ 447e7cc9a7340b8ec018caa9eb1d035fdaef1f2fc51Magnus Damm ret = handle_delayslot(regs, instruction, ma); 4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret==0) { 4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds regs->pr = regs->pc + 4; 4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds regs->pc += rm + 4; 4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else { 4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* mov.[bwl] to/from memory via r0+rn */ 4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto simple; 4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x1000: /* mov.l Rm,@(disp,Rn) */ 4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto simple; 4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x2000: /* mov.[bwl] to memory, possibly with pre-decrement */ 4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto simple; 4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x4000: 4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((instruction&0x00FF)==0x002B) { 4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* jmp @Rm */ 468e7cc9a7340b8ec018caa9eb1d035fdaef1f2fc51Magnus Damm ret = handle_delayslot(regs, instruction, ma); 4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret==0) 4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds regs->pc = rm; 4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if ((instruction&0x00FF)==0x000B) { 4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* jsr @Rm */ 474e7cc9a7340b8ec018caa9eb1d035fdaef1f2fc51Magnus Damm ret = handle_delayslot(regs, instruction, ma); 4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret==0) { 4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds regs->pr = regs->pc + 4; 4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds regs->pc = rm; 4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else { 4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* mov.[bwl] to/from memory via r0+rn */ 4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto simple; 4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x5000: /* mov.l @(disp,Rm),Rn */ 4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto simple; 4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x6000: /* mov.[bwl] from memory, possibly with post-increment */ 4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto simple; 4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x8000: /* bf lab, bf/s lab, bt lab, bt/s lab */ 4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (instruction&0x0F00) { 4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x0100: /* mov.w R0,@(disp,Rm) */ 4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto simple; 4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x0500: /* mov.w @(disp,Rm),R0 */ 4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto simple; 4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x0B00: /* bf lab - no delayslot*/ 4990710b91c516ffd448db6e80e9026f11778a80d45Phil Edworthy ret = 0; 5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x0F00: /* bf/s lab */ 502e7cc9a7340b8ec018caa9eb1d035fdaef1f2fc51Magnus Damm ret = handle_delayslot(regs, instruction, ma); 5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret==0) { 5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if defined(CONFIG_CPU_SH4) || defined(CONFIG_SH7705_CACHE_32KB) 5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((regs->sr & 0x00000001) != 0) 5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds regs->pc += 4; /* next after slot */ 5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds regs->pc += SH_PC_8BIT_OFFSET(instruction); 5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x0900: /* bt lab - no delayslot */ 5130710b91c516ffd448db6e80e9026f11778a80d45Phil Edworthy ret = 0; 5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x0D00: /* bt/s lab */ 516e7cc9a7340b8ec018caa9eb1d035fdaef1f2fc51Magnus Damm ret = handle_delayslot(regs, instruction, ma); 5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret==0) { 5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if defined(CONFIG_CPU_SH4) || defined(CONFIG_SH7705_CACHE_32KB) 5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((regs->sr & 0x00000001) == 0) 5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds regs->pc += 4; /* next after slot */ 5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds regs->pc += SH_PC_8BIT_OFFSET(instruction); 5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 52934f7145a63211eb7ecfcafa6c2a8db5646baf953Phil Edworthy case 0x9000: /* mov.w @(disp,Rm),Rn */ 53034f7145a63211eb7ecfcafa6c2a8db5646baf953Phil Edworthy goto simple; 53134f7145a63211eb7ecfcafa6c2a8db5646baf953Phil Edworthy 5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0xA000: /* bra label */ 533e7cc9a7340b8ec018caa9eb1d035fdaef1f2fc51Magnus Damm ret = handle_delayslot(regs, instruction, ma); 5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret==0) 5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds regs->pc += SH_PC_12BIT_OFFSET(instruction); 5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0xB000: /* bsr label */ 539e7cc9a7340b8ec018caa9eb1d035fdaef1f2fc51Magnus Damm ret = handle_delayslot(regs, instruction, ma); 5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret==0) { 5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds regs->pr = regs->pc + 4; 5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds regs->pc += SH_PC_12BIT_OFFSET(instruction); 5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 54534f7145a63211eb7ecfcafa6c2a8db5646baf953Phil Edworthy 54634f7145a63211eb7ecfcafa6c2a8db5646baf953Phil Edworthy case 0xD000: /* mov.l @(disp,Rm),Rn */ 54734f7145a63211eb7ecfcafa6c2a8db5646baf953Phil Edworthy goto simple; 5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* handle non-delay-slot instruction */ 5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds simple: 553e7cc9a7340b8ec018caa9eb1d035fdaef1f2fc51Magnus Damm ret = handle_unaligned_ins(instruction, regs, ma); 5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret==0) 55553f983a90d7908bcece51f86180c7c9b575a1e4dPaul Mundt regs->pc += instruction_size(instruction); 5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 560b5a1bcbee434b843c8850a968d9a6c7541f1be9dStuart Menefy * Handle various address error exceptions: 561b5a1bcbee434b843c8850a968d9a6c7541f1be9dStuart Menefy * - instruction address error: 562b5a1bcbee434b843c8850a968d9a6c7541f1be9dStuart Menefy * misaligned PC 563b5a1bcbee434b843c8850a968d9a6c7541f1be9dStuart Menefy * PC >= 0x80000000 in user mode 564b5a1bcbee434b843c8850a968d9a6c7541f1be9dStuart Menefy * - data address error (read and write) 565b5a1bcbee434b843c8850a968d9a6c7541f1be9dStuart Menefy * misaligned data access 566b5a1bcbee434b843c8850a968d9a6c7541f1be9dStuart Menefy * access to >= 0x80000000 is user mode 567b5a1bcbee434b843c8850a968d9a6c7541f1be9dStuart Menefy * Unfortuntaly we can't distinguish between instruction address error 568e868d61272caa648214046a096e5a6bfc068dc8cSimon Arlott * and data address errors caused by read accesses. 5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 570f0bc814cfbc212683c882e58b3d1afec6b3e3aa3Stuart Menefyasmlinkage void do_address_error(struct pt_regs *regs, 5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long writeaccess, 5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long address) 5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5740983b31849bbe1fe82520947acc1bec97c457d4bYoshinori Sato unsigned long error_code = 0; 5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mm_segment_t oldfs; 576b5a1bcbee434b843c8850a968d9a6c7541f1be9dStuart Menefy siginfo_t info; 5772bcfffa42309b6f73042c62459bf5207762a271dPaul Mundt insn_size_t instruction; 5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int tmp; 5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5800983b31849bbe1fe82520947acc1bec97c457d4bYoshinori Sato /* Intentional ifdef */ 5810983b31849bbe1fe82520947acc1bec97c457d4bYoshinori Sato#ifdef CONFIG_CPU_HAS_SR_RB 5824c59e2942e92d2d776bcd038604a5c3c1d56d3acPaul Mundt error_code = lookup_exception_vector(); 5830983b31849bbe1fe82520947acc1bec97c457d4bYoshinori Sato#endif 5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds oldfs = get_fs(); 5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (user_mode(regs)) { 588b5a1bcbee434b843c8850a968d9a6c7541f1be9dStuart Menefy int si_code = BUS_ADRERR; 589a99eae5417a09e0be66bf574a9a79a2a7388c967Paul Mundt unsigned int user_action; 590b5a1bcbee434b843c8850a968d9a6c7541f1be9dStuart Menefy 5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds local_irq_enable(); 592a99eae5417a09e0be66bf574a9a79a2a7388c967Paul Mundt inc_unaligned_user_access(); 5937436cde6b2ca71049051620c68c26522bb3403bfAndre Draszik 5945a0ab35e43a6e3c69893c0091fe6a78ea8b3e443Andre Draszik set_fs(USER_DS); 59523c4c82171008c8b18d8627c9741cdd577631ceaPaul Mundt if (copy_from_user(&instruction, (insn_size_t *)(regs->pc & ~1), 59623c4c82171008c8b18d8627c9741cdd577631ceaPaul Mundt sizeof(instruction))) { 5975a0ab35e43a6e3c69893c0091fe6a78ea8b3e443Andre Draszik set_fs(oldfs); 5985a0ab35e43a6e3c69893c0091fe6a78ea8b3e443Andre Draszik goto uspace_segv; 5995a0ab35e43a6e3c69893c0091fe6a78ea8b3e443Andre Draszik } 6005a0ab35e43a6e3c69893c0091fe6a78ea8b3e443Andre Draszik set_fs(oldfs); 6015a0ab35e43a6e3c69893c0091fe6a78ea8b3e443Andre Draszik 6027436cde6b2ca71049051620c68c26522bb3403bfAndre Draszik /* shout about userspace fixups */ 603a99eae5417a09e0be66bf574a9a79a2a7388c967Paul Mundt unaligned_fixups_notify(current, instruction, regs); 6047436cde6b2ca71049051620c68c26522bb3403bfAndre Draszik 605a99eae5417a09e0be66bf574a9a79a2a7388c967Paul Mundt user_action = unaligned_user_action(); 606a99eae5417a09e0be66bf574a9a79a2a7388c967Paul Mundt if (user_action & UM_FIXUP) 6077436cde6b2ca71049051620c68c26522bb3403bfAndre Draszik goto fixup; 608a99eae5417a09e0be66bf574a9a79a2a7388c967Paul Mundt if (user_action & UM_SIGNAL) 6097436cde6b2ca71049051620c68c26522bb3403bfAndre Draszik goto uspace_segv; 6107436cde6b2ca71049051620c68c26522bb3403bfAndre Draszik else { 6117436cde6b2ca71049051620c68c26522bb3403bfAndre Draszik /* ignore */ 6125a0ab35e43a6e3c69893c0091fe6a78ea8b3e443Andre Draszik regs->pc += instruction_size(instruction); 6137436cde6b2ca71049051620c68c26522bb3403bfAndre Draszik return; 6147436cde6b2ca71049051620c68c26522bb3403bfAndre Draszik } 6157436cde6b2ca71049051620c68c26522bb3403bfAndre Draszik 6167436cde6b2ca71049051620c68c26522bb3403bfAndre Draszikfixup: 6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* bad PC is not something we can fix */ 618b5a1bcbee434b843c8850a968d9a6c7541f1be9dStuart Menefy if (regs->pc & 1) { 619b5a1bcbee434b843c8850a968d9a6c7541f1be9dStuart Menefy si_code = BUS_ADRALN; 6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto uspace_segv; 621b5a1bcbee434b843c8850a968d9a6c7541f1be9dStuart Menefy } 6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_fs(USER_DS); 624e7cc9a7340b8ec018caa9eb1d035fdaef1f2fc51Magnus Damm tmp = handle_unaligned_access(instruction, regs, 625ace2dc7d12693545b67f15ab8cdb3d255c937713Paul Mundt &user_mem_access, 0, 626ace2dc7d12693545b67f15ab8cdb3d255c937713Paul Mundt address); 6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_fs(oldfs); 6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 629a99eae5417a09e0be66bf574a9a79a2a7388c967Paul Mundt if (tmp == 0) 6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; /* sorted */ 631b5a1bcbee434b843c8850a968d9a6c7541f1be9dStuart Menefyuspace_segv: 632b5a1bcbee434b843c8850a968d9a6c7541f1be9dStuart Menefy printk(KERN_NOTICE "Sending SIGBUS to \"%s\" due to unaligned " 633b5a1bcbee434b843c8850a968d9a6c7541f1be9dStuart Menefy "access (PC %lx PR %lx)\n", current->comm, regs->pc, 634b5a1bcbee434b843c8850a968d9a6c7541f1be9dStuart Menefy regs->pr); 635b5a1bcbee434b843c8850a968d9a6c7541f1be9dStuart Menefy 636b5a1bcbee434b843c8850a968d9a6c7541f1be9dStuart Menefy info.si_signo = SIGBUS; 637b5a1bcbee434b843c8850a968d9a6c7541f1be9dStuart Menefy info.si_errno = 0; 638b5a1bcbee434b843c8850a968d9a6c7541f1be9dStuart Menefy info.si_code = si_code; 639e08f457c7c0cc7720f28349f8780ea752c063441Paul Mundt info.si_addr = (void __user *)address; 640b5a1bcbee434b843c8850a968d9a6c7541f1be9dStuart Menefy force_sig_info(SIGBUS, &info, current); 6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 642a99eae5417a09e0be66bf574a9a79a2a7388c967Paul Mundt inc_unaligned_kernel_access(); 6437436cde6b2ca71049051620c68c26522bb3403bfAndre Draszik 6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (regs->pc & 1) 6451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds die("unaligned program counter", regs, error_code); 6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_fs(KERNEL_DS); 648fa43972fab24a3c050e880a7831f9378c6cebc0bPaul Mundt if (copy_from_user(&instruction, (void __user *)(regs->pc), 6494b5a9ef5279aed2c34d92fee62cf6d0c6ffacbaaMagnus Damm sizeof(instruction))) { 6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Argh. Fault on the instruction itself. 6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds This should never happen non-SMP 6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_fs(oldfs); 6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds die("insn faulting in do_address_error", regs, 0); 6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 657a99eae5417a09e0be66bf574a9a79a2a7388c967Paul Mundt unaligned_fixups_notify(current, instruction, regs); 65840258ee97d0d5e5c30a3d4b7acaf294fe82cd23fPaul Mundt 659ace2dc7d12693545b67f15ab8cdb3d255c937713Paul Mundt handle_unaligned_access(instruction, regs, &user_mem_access, 660ace2dc7d12693545b67f15ab8cdb3d255c937713Paul Mundt 0, address); 6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_fs(oldfs); 6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_SH_DSP 6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * SH-DSP support gerg@snapgear.com. 6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint is_dsp_inst(struct pt_regs *regs) 6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 671882c12c4e1a95e55227f06dbb99eca90f237c018Paul Mundt unsigned short inst = 0; 6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 673f0bc814cfbc212683c882e58b3d1afec6b3e3aa3Stuart Menefy /* 6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Safe guard if DSP mode is already enabled or we're lacking 6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the DSP altogether. 6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 67711c1965687b0a472add948d4240dfe65a2fcb298Paul Mundt if (!(current_cpu_data.flags & CPU_HAS_DSP) || (regs->sr & SR_DSP)) 6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds get_user(inst, ((unsigned short *) regs->pc)); 6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds inst &= 0xf000; 6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Check for any type of DSP or support instruction */ 6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((inst == 0xf000) || (inst == 0x4000)) 6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define is_dsp_inst(regs) (0) 6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif /* CONFIG_SH_DSP */ 6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6940983b31849bbe1fe82520947acc1bec97c457d4bYoshinori Sato#ifdef CONFIG_CPU_SH2A 6950983b31849bbe1fe82520947acc1bec97c457d4bYoshinori Satoasmlinkage void do_divide_error(unsigned long r4, unsigned long r5, 6960983b31849bbe1fe82520947acc1bec97c457d4bYoshinori Sato unsigned long r6, unsigned long r7, 697f0bc814cfbc212683c882e58b3d1afec6b3e3aa3Stuart Menefy struct pt_regs __regs) 6980983b31849bbe1fe82520947acc1bec97c457d4bYoshinori Sato{ 6990983b31849bbe1fe82520947acc1bec97c457d4bYoshinori Sato siginfo_t info; 7000983b31849bbe1fe82520947acc1bec97c457d4bYoshinori Sato 7010983b31849bbe1fe82520947acc1bec97c457d4bYoshinori Sato switch (r4) { 7020983b31849bbe1fe82520947acc1bec97c457d4bYoshinori Sato case TRAP_DIVZERO_ERROR: 7030983b31849bbe1fe82520947acc1bec97c457d4bYoshinori Sato info.si_code = FPE_INTDIV; 7040983b31849bbe1fe82520947acc1bec97c457d4bYoshinori Sato break; 7050983b31849bbe1fe82520947acc1bec97c457d4bYoshinori Sato case TRAP_DIVOVF_ERROR: 7060983b31849bbe1fe82520947acc1bec97c457d4bYoshinori Sato info.si_code = FPE_INTOVF; 7070983b31849bbe1fe82520947acc1bec97c457d4bYoshinori Sato break; 7080983b31849bbe1fe82520947acc1bec97c457d4bYoshinori Sato } 7090983b31849bbe1fe82520947acc1bec97c457d4bYoshinori Sato 7100983b31849bbe1fe82520947acc1bec97c457d4bYoshinori Sato force_sig_info(SIGFPE, &info, current); 7110983b31849bbe1fe82520947acc1bec97c457d4bYoshinori Sato} 7120983b31849bbe1fe82520947acc1bec97c457d4bYoshinori Sato#endif 7130983b31849bbe1fe82520947acc1bec97c457d4bYoshinori Sato 7144b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHIIasmlinkage void do_reserved_inst(unsigned long r4, unsigned long r5, 7154b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII unsigned long r6, unsigned long r7, 716f0bc814cfbc212683c882e58b3d1afec6b3e3aa3Stuart Menefy struct pt_regs __regs) 7174b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII{ 718f0bc814cfbc212683c882e58b3d1afec6b3e3aa3Stuart Menefy struct pt_regs *regs = RELOC_HIDE(&__regs, 0); 7194b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII unsigned long error_code; 7204b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII struct task_struct *tsk = current; 7214b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII 7224b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII#ifdef CONFIG_SH_FPU_EMU 7230983b31849bbe1fe82520947acc1bec97c457d4bYoshinori Sato unsigned short inst = 0; 7244b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII int err; 7254b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII 726f0bc814cfbc212683c882e58b3d1afec6b3e3aa3Stuart Menefy get_user(inst, (unsigned short*)regs->pc); 7274b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII 728f0bc814cfbc212683c882e58b3d1afec6b3e3aa3Stuart Menefy err = do_fpu_inst(inst, regs); 7294b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII if (!err) { 73053f983a90d7908bcece51f86180c7c9b575a1e4dPaul Mundt regs->pc += instruction_size(inst); 7314b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII return; 7324b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII } 7334b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII /* not a FPU inst. */ 7344b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII#endif 7354b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII 7364b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII#ifdef CONFIG_SH_DSP 7374b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII /* Check if it's a DSP instruction */ 738b5a1bcbee434b843c8850a968d9a6c7541f1be9dStuart Menefy if (is_dsp_inst(regs)) { 7394b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII /* Enable DSP mode, and restart instruction. */ 740f0bc814cfbc212683c882e58b3d1afec6b3e3aa3Stuart Menefy regs->sr |= SR_DSP; 74101ab10393c510342ec4ce85df11ccfa3df06bbb2Michael Trimarchi /* Save DSP mode */ 74201ab10393c510342ec4ce85df11ccfa3df06bbb2Michael Trimarchi tsk->thread.dsp_status.status |= SR_DSP; 7434b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII return; 7444b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII } 7454b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII#endif 7464b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII 7474c59e2942e92d2d776bcd038604a5c3c1d56d3acPaul Mundt error_code = lookup_exception_vector(); 7480983b31849bbe1fe82520947acc1bec97c457d4bYoshinori Sato 7494b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII local_irq_enable(); 7504b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII force_sig(SIGILL, tsk); 751f0bc814cfbc212683c882e58b3d1afec6b3e3aa3Stuart Menefy die_if_no_fixup("reserved instruction", regs, error_code); 7524b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII} 7534b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII 7544b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII#ifdef CONFIG_SH_FPU_EMU 755edfd6da0405520b147ab1473ad183a5b32be7082Paul Mundtstatic int emulate_branch(unsigned short inst, struct pt_regs *regs) 7564b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII{ 7574b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII /* 7584b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII * bfs: 8fxx: PC+=d*2+4; 7594b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII * bts: 8dxx: PC+=d*2+4; 7604b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII * bra: axxx: PC+=D*2+4; 7614b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII * bsr: bxxx: PC+=D*2+4 after PR=PC+4; 7624b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII * braf:0x23: PC+=Rn*2+4; 7634b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII * bsrf:0x03: PC+=Rn*2+4 after PR=PC+4; 7644b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII * jmp: 4x2b: PC=Rn; 7654b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII * jsr: 4x0b: PC=Rn after PR=PC+4; 7664b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII * rts: 000b: PC=PR; 7674b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII */ 768edfd6da0405520b147ab1473ad183a5b32be7082Paul Mundt if (((inst & 0xf000) == 0xb000) || /* bsr */ 769edfd6da0405520b147ab1473ad183a5b32be7082Paul Mundt ((inst & 0xf0ff) == 0x0003) || /* bsrf */ 770edfd6da0405520b147ab1473ad183a5b32be7082Paul Mundt ((inst & 0xf0ff) == 0x400b)) /* jsr */ 771edfd6da0405520b147ab1473ad183a5b32be7082Paul Mundt regs->pr = regs->pc + 4; 772edfd6da0405520b147ab1473ad183a5b32be7082Paul Mundt 773edfd6da0405520b147ab1473ad183a5b32be7082Paul Mundt if ((inst & 0xfd00) == 0x8d00) { /* bfs, bts */ 7744b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII regs->pc += SH_PC_8BIT_OFFSET(inst); 7754b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII return 0; 7764b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII } 7774b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII 778edfd6da0405520b147ab1473ad183a5b32be7082Paul Mundt if ((inst & 0xe000) == 0xa000) { /* bra, bsr */ 7794b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII regs->pc += SH_PC_12BIT_OFFSET(inst); 7804b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII return 0; 7814b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII } 7824b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII 783edfd6da0405520b147ab1473ad183a5b32be7082Paul Mundt if ((inst & 0xf0df) == 0x0003) { /* braf, bsrf */ 7844b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII regs->pc += regs->regs[(inst & 0x0f00) >> 8] + 4; 7854b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII return 0; 7864b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII } 7874b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII 788edfd6da0405520b147ab1473ad183a5b32be7082Paul Mundt if ((inst & 0xf0df) == 0x400b) { /* jmp, jsr */ 7894b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII regs->pc = regs->regs[(inst & 0x0f00) >> 8]; 7904b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII return 0; 7914b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII } 7924b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII 793edfd6da0405520b147ab1473ad183a5b32be7082Paul Mundt if ((inst & 0xffff) == 0x000b) { /* rts */ 7944b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII regs->pc = regs->pr; 7954b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII return 0; 7964b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII } 7974b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII 7984b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII return 1; 7994b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII} 8004b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII#endif 8014b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII 8024b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHIIasmlinkage void do_illegal_slot_inst(unsigned long r4, unsigned long r5, 8034b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII unsigned long r6, unsigned long r7, 804f0bc814cfbc212683c882e58b3d1afec6b3e3aa3Stuart Menefy struct pt_regs __regs) 8054b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII{ 806f0bc814cfbc212683c882e58b3d1afec6b3e3aa3Stuart Menefy struct pt_regs *regs = RELOC_HIDE(&__regs, 0); 807b3d765f5df5707e2b3676768b6877db5d8db76a2Paul Mundt unsigned long inst; 8084b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII struct task_struct *tsk = current; 809d39f5450146ff39f66cfde9d5184420627d0ac51Chris Smith 810d39f5450146ff39f66cfde9d5184420627d0ac51Chris Smith if (kprobe_handle_illslot(regs->pc) == 0) 811d39f5450146ff39f66cfde9d5184420627d0ac51Chris Smith return; 812d39f5450146ff39f66cfde9d5184420627d0ac51Chris Smith 8134b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII#ifdef CONFIG_SH_FPU_EMU 814f0bc814cfbc212683c882e58b3d1afec6b3e3aa3Stuart Menefy get_user(inst, (unsigned short *)regs->pc + 1); 815f0bc814cfbc212683c882e58b3d1afec6b3e3aa3Stuart Menefy if (!do_fpu_inst(inst, regs)) { 816f0bc814cfbc212683c882e58b3d1afec6b3e3aa3Stuart Menefy get_user(inst, (unsigned short *)regs->pc); 817f0bc814cfbc212683c882e58b3d1afec6b3e3aa3Stuart Menefy if (!emulate_branch(inst, regs)) 8184b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII return; 8194b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII /* fault in branch.*/ 8204b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII } 8214b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII /* not a FPU inst. */ 8224b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII#endif 8234b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII 8244c59e2942e92d2d776bcd038604a5c3c1d56d3acPaul Mundt inst = lookup_exception_vector(); 8250983b31849bbe1fe82520947acc1bec97c457d4bYoshinori Sato 8264b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII local_irq_enable(); 8274b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII force_sig(SIGILL, tsk); 828b3d765f5df5707e2b3676768b6877db5d8db76a2Paul Mundt die_if_no_fixup("illegal slot instruction", regs, inst); 8294b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII} 8301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsasmlinkage void do_exception_error(unsigned long r4, unsigned long r5, 8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long r6, unsigned long r7, 833f0bc814cfbc212683c882e58b3d1afec6b3e3aa3Stuart Menefy struct pt_regs __regs) 8341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 835f0bc814cfbc212683c882e58b3d1afec6b3e3aa3Stuart Menefy struct pt_regs *regs = RELOC_HIDE(&__regs, 0); 8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds long ex; 8370983b31849bbe1fe82520947acc1bec97c457d4bYoshinori Sato 8384c59e2942e92d2d776bcd038604a5c3c1d56d3acPaul Mundt ex = lookup_exception_vector(); 839f0bc814cfbc212683c882e58b3d1afec6b3e3aa3Stuart Menefy die_if_kernel("exception", regs, ex); 8401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 842aba1030a7e529ec9fe47a8cfc06d12a39180fa71Paul Mundtvoid __cpuinit per_cpu_trap_init(void) 8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds extern void *vbr_base; 8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* NOTE: The VBR value should be at P1 8471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (or P2, virtural "fixed" address space). 8481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds It's definitely should not in physical address. */ 8491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds asm volatile("ldc %0, vbr" 8511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds : /* no output */ 8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds : "r" (&vbr_base) 8531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds : "memory"); 85468a1aed7039e5a94a8e60e23fdf676738c36086aMagnus Damm 85568a1aed7039e5a94a8e60e23fdf676738c36086aMagnus Damm /* disable exception blocking now when the vbr has been setup */ 85668a1aed7039e5a94a8e60e23fdf676738c36086aMagnus Damm clear_bl_bit(); 8571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8591f666587dbf6bc660b23d8dd8abb6c572ce3eae5Paul Mundtvoid *set_exception_table_vec(unsigned int vec, void *handler) 8601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds extern void *exception_handling_table[]; 8621f666587dbf6bc660b23d8dd8abb6c572ce3eae5Paul Mundt void *old_handler; 863b5a1bcbee434b843c8850a968d9a6c7541f1be9dStuart Menefy 8641f666587dbf6bc660b23d8dd8abb6c572ce3eae5Paul Mundt old_handler = exception_handling_table[vec]; 8651f666587dbf6bc660b23d8dd8abb6c572ce3eae5Paul Mundt exception_handling_table[vec] = handler; 8661f666587dbf6bc660b23d8dd8abb6c572ce3eae5Paul Mundt return old_handler; 8671f666587dbf6bc660b23d8dd8abb6c572ce3eae5Paul Mundt} 8681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8691f666587dbf6bc660b23d8dd8abb6c572ce3eae5Paul Mundtvoid __init trap_init(void) 8701f666587dbf6bc660b23d8dd8abb6c572ce3eae5Paul Mundt{ 8711f666587dbf6bc660b23d8dd8abb6c572ce3eae5Paul Mundt set_exception_table_vec(TRAP_RESERVED_INST, do_reserved_inst); 8721f666587dbf6bc660b23d8dd8abb6c572ce3eae5Paul Mundt set_exception_table_vec(TRAP_ILLEGAL_SLOT_INST, do_illegal_slot_inst); 8731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8744b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII#if defined(CONFIG_CPU_SH4) && !defined(CONFIG_SH_FPU) || \ 8754b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII defined(CONFIG_SH_FPU_EMU) 8764b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII /* 8774b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII * For SH-4 lacking an FPU, treat floating point instructions as 8784b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII * reserved. They'll be handled in the math-emu case, or faulted on 8794b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII * otherwise. 8804b565680d16300acab0ff167e24f0ea289a6bd5dTakashi YOSHII */ 8811f666587dbf6bc660b23d8dd8abb6c572ce3eae5Paul Mundt set_exception_table_evt(0x800, do_reserved_inst); 8821f666587dbf6bc660b23d8dd8abb6c572ce3eae5Paul Mundt set_exception_table_evt(0x820, do_illegal_slot_inst); 8831f666587dbf6bc660b23d8dd8abb6c572ce3eae5Paul Mundt#elif defined(CONFIG_SH_FPU) 88474d99a5e262229ee865f6f68528d10b82471ead6Paul Mundt set_exception_table_evt(0x800, fpu_state_restore_trap_handler); 88574d99a5e262229ee865f6f68528d10b82471ead6Paul Mundt set_exception_table_evt(0x820, fpu_state_restore_trap_handler); 8861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 8870983b31849bbe1fe82520947acc1bec97c457d4bYoshinori Sato 8880983b31849bbe1fe82520947acc1bec97c457d4bYoshinori Sato#ifdef CONFIG_CPU_SH2 8895a4f7c66be981c6b5f44a4d66a14ea6ac9b7b6b0Paul Mundt set_exception_table_vec(TRAP_ADDRESS_ERROR, address_error_trap_handler); 8900983b31849bbe1fe82520947acc1bec97c457d4bYoshinori Sato#endif 8910983b31849bbe1fe82520947acc1bec97c457d4bYoshinori Sato#ifdef CONFIG_CPU_SH2A 8920983b31849bbe1fe82520947acc1bec97c457d4bYoshinori Sato set_exception_table_vec(TRAP_DIVZERO_ERROR, do_divide_error); 8930983b31849bbe1fe82520947acc1bec97c457d4bYoshinori Sato set_exception_table_vec(TRAP_DIVOVF_ERROR, do_divide_error); 8946e80f5e8c4c685eb7bc34c3916e3d986b03f9981Yoshinori Sato#ifdef CONFIG_SH_FPU 8956e80f5e8c4c685eb7bc34c3916e3d986b03f9981Yoshinori Sato set_exception_table_vec(TRAP_FPU_ERROR, fpu_error_trap_handler); 8966e80f5e8c4c685eb7bc34c3916e3d986b03f9981Yoshinori Sato#endif 8970983b31849bbe1fe82520947acc1bec97c457d4bYoshinori Sato#endif 898b5a1bcbee434b843c8850a968d9a6c7541f1be9dStuart Menefy 899cd89436e54b29a07a383ee82f2f718d8c9d24cc4Peter Griffin#ifdef TRAP_UBC 900c4761815ab49feca904776dec464046bc7138d3aPaul Mundt set_exception_table_vec(TRAP_UBC, breakpoint_trap_handler); 901cd89436e54b29a07a383ee82f2f718d8c9d24cc4Peter Griffin#endif 9021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9046b0022305f80cf249de69e746f6f5ccf7ffc5b7cPaul Mundtvoid show_stack(struct task_struct *tsk, unsigned long *sp) 9051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 9066b0022305f80cf249de69e746f6f5ccf7ffc5b7cPaul Mundt unsigned long stack; 9076b0022305f80cf249de69e746f6f5ccf7ffc5b7cPaul Mundt 9086b0022305f80cf249de69e746f6f5ccf7ffc5b7cPaul Mundt if (!tsk) 9096b0022305f80cf249de69e746f6f5ccf7ffc5b7cPaul Mundt tsk = current; 9106b0022305f80cf249de69e746f6f5ccf7ffc5b7cPaul Mundt if (tsk == current) 9116b0022305f80cf249de69e746f6f5ccf7ffc5b7cPaul Mundt sp = (unsigned long *)current_stack_pointer; 9126b0022305f80cf249de69e746f6f5ccf7ffc5b7cPaul Mundt else 9136b0022305f80cf249de69e746f6f5ccf7ffc5b7cPaul Mundt sp = (unsigned long *)tsk->thread.sp; 9146b0022305f80cf249de69e746f6f5ccf7ffc5b7cPaul Mundt 9156b0022305f80cf249de69e746f6f5ccf7ffc5b7cPaul Mundt stack = (unsigned long)sp; 9166b0022305f80cf249de69e746f6f5ccf7ffc5b7cPaul Mundt dump_mem("Stack: ", stack, THREAD_SIZE + 9176b0022305f80cf249de69e746f6f5ccf7ffc5b7cPaul Mundt (unsigned long)task_stack_page(tsk)); 9186b0022305f80cf249de69e746f6f5ccf7ffc5b7cPaul Mundt show_trace(tsk, sp, NULL); 9191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid dump_stack(void) 9221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 9231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds show_stack(NULL, NULL); 9241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(dump_stack); 926