11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * Handle unaligned accesses by emulation. 31da177e4SLinus Torvalds * 41da177e4SLinus Torvalds * This file is subject to the terms and conditions of the GNU General Public 51da177e4SLinus Torvalds * License. See the file "COPYING" in the main directory of this archive 61da177e4SLinus Torvalds * for more details. 71da177e4SLinus Torvalds * 81da177e4SLinus Torvalds * Copyright (C) 1996, 1998, 1999, 2002 by Ralf Baechle 91da177e4SLinus Torvalds * Copyright (C) 1999 Silicon Graphics, Inc. 101da177e4SLinus Torvalds * 111da177e4SLinus Torvalds * This file contains exception handler for address error exception with the 121da177e4SLinus Torvalds * special capability to execute faulting instructions in software. The 131da177e4SLinus Torvalds * handler does not try to handle the case when the program counter points 141da177e4SLinus Torvalds * to an address not aligned to a word boundary. 151da177e4SLinus Torvalds * 161da177e4SLinus Torvalds * Putting data to unaligned addresses is a bad practice even on Intel where 171da177e4SLinus Torvalds * only the performance is affected. Much worse is that such code is non- 181da177e4SLinus Torvalds * portable. Due to several programs that die on MIPS due to alignment 191da177e4SLinus Torvalds * problems I decided to implement this handler anyway though I originally 201da177e4SLinus Torvalds * didn't intend to do this at all for user code. 211da177e4SLinus Torvalds * 221da177e4SLinus Torvalds * For now I enable fixing of address errors by default to make life easier. 231da177e4SLinus Torvalds * I however intend to disable this somewhen in the future when the alignment 241da177e4SLinus Torvalds * problems with user programs have been fixed. For programmers this is the 251da177e4SLinus Torvalds * right way to go. 261da177e4SLinus Torvalds * 271da177e4SLinus Torvalds * Fixing address errors is a per process option. The option is inherited 281da177e4SLinus Torvalds * across fork(2) and execve(2) calls. If you really want to use the 291da177e4SLinus Torvalds * option in your user programs - I discourage the use of the software 301da177e4SLinus Torvalds * emulation strongly - use the following code in your userland stuff: 311da177e4SLinus Torvalds * 321da177e4SLinus Torvalds * #include <sys/sysmips.h> 331da177e4SLinus Torvalds * 341da177e4SLinus Torvalds * ... 351da177e4SLinus Torvalds * sysmips(MIPS_FIXADE, x); 361da177e4SLinus Torvalds * ... 371da177e4SLinus Torvalds * 381da177e4SLinus Torvalds * The argument x is 0 for disabling software emulation, enabled otherwise. 391da177e4SLinus Torvalds * 401da177e4SLinus Torvalds * Below a little program to play around with this feature. 411da177e4SLinus Torvalds * 421da177e4SLinus Torvalds * #include <stdio.h> 431da177e4SLinus Torvalds * #include <sys/sysmips.h> 441da177e4SLinus Torvalds * 451da177e4SLinus Torvalds * struct foo { 461da177e4SLinus Torvalds * unsigned char bar[8]; 471da177e4SLinus Torvalds * }; 481da177e4SLinus Torvalds * 491da177e4SLinus Torvalds * main(int argc, char *argv[]) 501da177e4SLinus Torvalds * { 511da177e4SLinus Torvalds * struct foo x = {0, 1, 2, 3, 4, 5, 6, 7}; 521da177e4SLinus Torvalds * unsigned int *p = (unsigned int *) (x.bar + 3); 531da177e4SLinus Torvalds * int i; 541da177e4SLinus Torvalds * 551da177e4SLinus Torvalds * if (argc > 1) 561da177e4SLinus Torvalds * sysmips(MIPS_FIXADE, atoi(argv[1])); 571da177e4SLinus Torvalds * 581da177e4SLinus Torvalds * printf("*p = %08lx\n", *p); 591da177e4SLinus Torvalds * 601da177e4SLinus Torvalds * *p = 0xdeadface; 611da177e4SLinus Torvalds * 621da177e4SLinus Torvalds * for(i = 0; i <= 7; i++) 631da177e4SLinus Torvalds * printf("%02x ", x.bar[i]); 641da177e4SLinus Torvalds * printf("\n"); 651da177e4SLinus Torvalds * } 661da177e4SLinus Torvalds * 671da177e4SLinus Torvalds * Coprocessor loads are not supported; I think this case is unimportant 681da177e4SLinus Torvalds * in the practice. 691da177e4SLinus Torvalds * 701da177e4SLinus Torvalds * TODO: Handle ndc (attempted store to doubleword in uncached memory) 711da177e4SLinus Torvalds * exception for the R6000. 721da177e4SLinus Torvalds * A store crossing a page boundary might be executed only partially. 731da177e4SLinus Torvalds * Undo the partial store in this case. 741da177e4SLinus Torvalds */ 751da177e4SLinus Torvalds #include <linux/mm.h> 761da177e4SLinus Torvalds #include <linux/module.h> 771da177e4SLinus Torvalds #include <linux/signal.h> 781da177e4SLinus Torvalds #include <linux/smp.h> 79e8edc6e0SAlexey Dobriyan #include <linux/sched.h> 806312e0eeSAtsushi Nemoto #include <linux/debugfs.h> 817f788d2dSDeng-Cheng Zhu #include <linux/perf_event.h> 827f788d2dSDeng-Cheng Zhu 831da177e4SLinus Torvalds #include <asm/asm.h> 841da177e4SLinus Torvalds #include <asm/branch.h> 851da177e4SLinus Torvalds #include <asm/byteorder.h> 8669f3a7deSRalf Baechle #include <asm/cop2.h> 871da177e4SLinus Torvalds #include <asm/inst.h> 881da177e4SLinus Torvalds #include <asm/uaccess.h> 891da177e4SLinus Torvalds #include <asm/system.h> 901da177e4SLinus Torvalds 911da177e4SLinus Torvalds #define STR(x) __STR(x) 921da177e4SLinus Torvalds #define __STR(x) #x 931da177e4SLinus Torvalds 946312e0eeSAtsushi Nemoto enum { 956312e0eeSAtsushi Nemoto UNALIGNED_ACTION_QUIET, 966312e0eeSAtsushi Nemoto UNALIGNED_ACTION_SIGNAL, 976312e0eeSAtsushi Nemoto UNALIGNED_ACTION_SHOW, 986312e0eeSAtsushi Nemoto }; 996312e0eeSAtsushi Nemoto #ifdef CONFIG_DEBUG_FS 1006312e0eeSAtsushi Nemoto static u32 unaligned_instructions; 1016312e0eeSAtsushi Nemoto static u32 unaligned_action; 1026312e0eeSAtsushi Nemoto #else 1036312e0eeSAtsushi Nemoto #define unaligned_action UNALIGNED_ACTION_QUIET 1041da177e4SLinus Torvalds #endif 1056312e0eeSAtsushi Nemoto extern void show_registers(struct pt_regs *regs); 1061da177e4SLinus Torvalds 1077f18f151SRalf Baechle static void emulate_load_store_insn(struct pt_regs *regs, 1087f18f151SRalf Baechle void __user *addr, unsigned int __user *pc) 1091da177e4SLinus Torvalds { 1101da177e4SLinus Torvalds union mips_instruction insn; 1111da177e4SLinus Torvalds unsigned long value; 1121da177e4SLinus Torvalds unsigned int res; 1131da177e4SLinus Torvalds 114*a8b0ca17SPeter Zijlstra perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, 0); 1157f788d2dSDeng-Cheng Zhu 1161da177e4SLinus Torvalds /* 1171da177e4SLinus Torvalds * This load never faults. 1181da177e4SLinus Torvalds */ 119fe00f943SRalf Baechle __get_user(insn.word, pc); 1201da177e4SLinus Torvalds 1211da177e4SLinus Torvalds switch (insn.i_format.opcode) { 1221da177e4SLinus Torvalds /* 1231da177e4SLinus Torvalds * These are instructions that a compiler doesn't generate. We 1241da177e4SLinus Torvalds * can assume therefore that the code is MIPS-aware and 1251da177e4SLinus Torvalds * really buggy. Emulating these instructions would break the 1261da177e4SLinus Torvalds * semantics anyway. 1271da177e4SLinus Torvalds */ 1281da177e4SLinus Torvalds case ll_op: 1291da177e4SLinus Torvalds case lld_op: 1301da177e4SLinus Torvalds case sc_op: 1311da177e4SLinus Torvalds case scd_op: 1321da177e4SLinus Torvalds 1331da177e4SLinus Torvalds /* 1341da177e4SLinus Torvalds * For these instructions the only way to create an address 1351da177e4SLinus Torvalds * error is an attempted access to kernel/supervisor address 1361da177e4SLinus Torvalds * space. 1371da177e4SLinus Torvalds */ 1381da177e4SLinus Torvalds case ldl_op: 1391da177e4SLinus Torvalds case ldr_op: 1401da177e4SLinus Torvalds case lwl_op: 1411da177e4SLinus Torvalds case lwr_op: 1421da177e4SLinus Torvalds case sdl_op: 1431da177e4SLinus Torvalds case sdr_op: 1441da177e4SLinus Torvalds case swl_op: 1451da177e4SLinus Torvalds case swr_op: 1461da177e4SLinus Torvalds case lb_op: 1471da177e4SLinus Torvalds case lbu_op: 1481da177e4SLinus Torvalds case sb_op: 1491da177e4SLinus Torvalds goto sigbus; 1501da177e4SLinus Torvalds 1511da177e4SLinus Torvalds /* 1521da177e4SLinus Torvalds * The remaining opcodes are the ones that are really of interest. 1531da177e4SLinus Torvalds */ 1541da177e4SLinus Torvalds case lh_op: 1551da177e4SLinus Torvalds if (!access_ok(VERIFY_READ, addr, 2)) 1561da177e4SLinus Torvalds goto sigbus; 1571da177e4SLinus Torvalds 1581da177e4SLinus Torvalds __asm__ __volatile__ (".set\tnoat\n" 1591da177e4SLinus Torvalds #ifdef __BIG_ENDIAN 1601da177e4SLinus Torvalds "1:\tlb\t%0, 0(%2)\n" 1611da177e4SLinus Torvalds "2:\tlbu\t$1, 1(%2)\n\t" 1621da177e4SLinus Torvalds #endif 1631da177e4SLinus Torvalds #ifdef __LITTLE_ENDIAN 1641da177e4SLinus Torvalds "1:\tlb\t%0, 1(%2)\n" 1651da177e4SLinus Torvalds "2:\tlbu\t$1, 0(%2)\n\t" 1661da177e4SLinus Torvalds #endif 1671da177e4SLinus Torvalds "sll\t%0, 0x8\n\t" 1681da177e4SLinus Torvalds "or\t%0, $1\n\t" 1691da177e4SLinus Torvalds "li\t%1, 0\n" 1701da177e4SLinus Torvalds "3:\t.set\tat\n\t" 1711da177e4SLinus Torvalds ".section\t.fixup,\"ax\"\n\t" 1721da177e4SLinus Torvalds "4:\tli\t%1, %3\n\t" 1731da177e4SLinus Torvalds "j\t3b\n\t" 1741da177e4SLinus Torvalds ".previous\n\t" 1751da177e4SLinus Torvalds ".section\t__ex_table,\"a\"\n\t" 1761da177e4SLinus Torvalds STR(PTR)"\t1b, 4b\n\t" 1771da177e4SLinus Torvalds STR(PTR)"\t2b, 4b\n\t" 1781da177e4SLinus Torvalds ".previous" 1791da177e4SLinus Torvalds : "=&r" (value), "=r" (res) 1801da177e4SLinus Torvalds : "r" (addr), "i" (-EFAULT)); 1811da177e4SLinus Torvalds if (res) 1821da177e4SLinus Torvalds goto fault; 1837f18f151SRalf Baechle compute_return_epc(regs); 1847f18f151SRalf Baechle regs->regs[insn.i_format.rt] = value; 1851da177e4SLinus Torvalds break; 1861da177e4SLinus Torvalds 1871da177e4SLinus Torvalds case lw_op: 1881da177e4SLinus Torvalds if (!access_ok(VERIFY_READ, addr, 4)) 1891da177e4SLinus Torvalds goto sigbus; 1901da177e4SLinus Torvalds 1911da177e4SLinus Torvalds __asm__ __volatile__ ( 1921da177e4SLinus Torvalds #ifdef __BIG_ENDIAN 1931da177e4SLinus Torvalds "1:\tlwl\t%0, (%2)\n" 1941da177e4SLinus Torvalds "2:\tlwr\t%0, 3(%2)\n\t" 1951da177e4SLinus Torvalds #endif 1961da177e4SLinus Torvalds #ifdef __LITTLE_ENDIAN 1971da177e4SLinus Torvalds "1:\tlwl\t%0, 3(%2)\n" 1981da177e4SLinus Torvalds "2:\tlwr\t%0, (%2)\n\t" 1991da177e4SLinus Torvalds #endif 2001da177e4SLinus Torvalds "li\t%1, 0\n" 2011da177e4SLinus Torvalds "3:\t.section\t.fixup,\"ax\"\n\t" 2021da177e4SLinus Torvalds "4:\tli\t%1, %3\n\t" 2031da177e4SLinus Torvalds "j\t3b\n\t" 2041da177e4SLinus Torvalds ".previous\n\t" 2051da177e4SLinus Torvalds ".section\t__ex_table,\"a\"\n\t" 2061da177e4SLinus Torvalds STR(PTR)"\t1b, 4b\n\t" 2071da177e4SLinus Torvalds STR(PTR)"\t2b, 4b\n\t" 2081da177e4SLinus Torvalds ".previous" 2091da177e4SLinus Torvalds : "=&r" (value), "=r" (res) 2101da177e4SLinus Torvalds : "r" (addr), "i" (-EFAULT)); 2111da177e4SLinus Torvalds if (res) 2121da177e4SLinus Torvalds goto fault; 2137f18f151SRalf Baechle compute_return_epc(regs); 2147f18f151SRalf Baechle regs->regs[insn.i_format.rt] = value; 2151da177e4SLinus Torvalds break; 2161da177e4SLinus Torvalds 2171da177e4SLinus Torvalds case lhu_op: 2181da177e4SLinus Torvalds if (!access_ok(VERIFY_READ, addr, 2)) 2191da177e4SLinus Torvalds goto sigbus; 2201da177e4SLinus Torvalds 2211da177e4SLinus Torvalds __asm__ __volatile__ ( 2221da177e4SLinus Torvalds ".set\tnoat\n" 2231da177e4SLinus Torvalds #ifdef __BIG_ENDIAN 2241da177e4SLinus Torvalds "1:\tlbu\t%0, 0(%2)\n" 2251da177e4SLinus Torvalds "2:\tlbu\t$1, 1(%2)\n\t" 2261da177e4SLinus Torvalds #endif 2271da177e4SLinus Torvalds #ifdef __LITTLE_ENDIAN 2281da177e4SLinus Torvalds "1:\tlbu\t%0, 1(%2)\n" 2291da177e4SLinus Torvalds "2:\tlbu\t$1, 0(%2)\n\t" 2301da177e4SLinus Torvalds #endif 2311da177e4SLinus Torvalds "sll\t%0, 0x8\n\t" 2321da177e4SLinus Torvalds "or\t%0, $1\n\t" 2331da177e4SLinus Torvalds "li\t%1, 0\n" 2341da177e4SLinus Torvalds "3:\t.set\tat\n\t" 2351da177e4SLinus Torvalds ".section\t.fixup,\"ax\"\n\t" 2361da177e4SLinus Torvalds "4:\tli\t%1, %3\n\t" 2371da177e4SLinus Torvalds "j\t3b\n\t" 2381da177e4SLinus Torvalds ".previous\n\t" 2391da177e4SLinus Torvalds ".section\t__ex_table,\"a\"\n\t" 2401da177e4SLinus Torvalds STR(PTR)"\t1b, 4b\n\t" 2411da177e4SLinus Torvalds STR(PTR)"\t2b, 4b\n\t" 2421da177e4SLinus Torvalds ".previous" 2431da177e4SLinus Torvalds : "=&r" (value), "=r" (res) 2441da177e4SLinus Torvalds : "r" (addr), "i" (-EFAULT)); 2451da177e4SLinus Torvalds if (res) 2461da177e4SLinus Torvalds goto fault; 2477f18f151SRalf Baechle compute_return_epc(regs); 2487f18f151SRalf Baechle regs->regs[insn.i_format.rt] = value; 2491da177e4SLinus Torvalds break; 2501da177e4SLinus Torvalds 2511da177e4SLinus Torvalds case lwu_op: 252875d43e7SRalf Baechle #ifdef CONFIG_64BIT 2531da177e4SLinus Torvalds /* 2541da177e4SLinus Torvalds * A 32-bit kernel might be running on a 64-bit processor. But 2551da177e4SLinus Torvalds * if we're on a 32-bit processor and an i-cache incoherency 2561da177e4SLinus Torvalds * or race makes us see a 64-bit instruction here the sdl/sdr 2571da177e4SLinus Torvalds * would blow up, so for now we don't handle unaligned 64-bit 2581da177e4SLinus Torvalds * instructions on 32-bit kernels. 2591da177e4SLinus Torvalds */ 2601da177e4SLinus Torvalds if (!access_ok(VERIFY_READ, addr, 4)) 2611da177e4SLinus Torvalds goto sigbus; 2621da177e4SLinus Torvalds 2631da177e4SLinus Torvalds __asm__ __volatile__ ( 2641da177e4SLinus Torvalds #ifdef __BIG_ENDIAN 2651da177e4SLinus Torvalds "1:\tlwl\t%0, (%2)\n" 2661da177e4SLinus Torvalds "2:\tlwr\t%0, 3(%2)\n\t" 2671da177e4SLinus Torvalds #endif 2681da177e4SLinus Torvalds #ifdef __LITTLE_ENDIAN 2691da177e4SLinus Torvalds "1:\tlwl\t%0, 3(%2)\n" 2701da177e4SLinus Torvalds "2:\tlwr\t%0, (%2)\n\t" 2711da177e4SLinus Torvalds #endif 2721da177e4SLinus Torvalds "dsll\t%0, %0, 32\n\t" 2731da177e4SLinus Torvalds "dsrl\t%0, %0, 32\n\t" 2741da177e4SLinus Torvalds "li\t%1, 0\n" 2751da177e4SLinus Torvalds "3:\t.section\t.fixup,\"ax\"\n\t" 2761da177e4SLinus Torvalds "4:\tli\t%1, %3\n\t" 2771da177e4SLinus Torvalds "j\t3b\n\t" 2781da177e4SLinus Torvalds ".previous\n\t" 2791da177e4SLinus Torvalds ".section\t__ex_table,\"a\"\n\t" 2801da177e4SLinus Torvalds STR(PTR)"\t1b, 4b\n\t" 2811da177e4SLinus Torvalds STR(PTR)"\t2b, 4b\n\t" 2821da177e4SLinus Torvalds ".previous" 2831da177e4SLinus Torvalds : "=&r" (value), "=r" (res) 2841da177e4SLinus Torvalds : "r" (addr), "i" (-EFAULT)); 2851da177e4SLinus Torvalds if (res) 2861da177e4SLinus Torvalds goto fault; 2877f18f151SRalf Baechle compute_return_epc(regs); 2887f18f151SRalf Baechle regs->regs[insn.i_format.rt] = value; 2891da177e4SLinus Torvalds break; 290875d43e7SRalf Baechle #endif /* CONFIG_64BIT */ 2911da177e4SLinus Torvalds 2921da177e4SLinus Torvalds /* Cannot handle 64-bit instructions in 32-bit kernel */ 2931da177e4SLinus Torvalds goto sigill; 2941da177e4SLinus Torvalds 2951da177e4SLinus Torvalds case ld_op: 296875d43e7SRalf Baechle #ifdef CONFIG_64BIT 2971da177e4SLinus Torvalds /* 2981da177e4SLinus Torvalds * A 32-bit kernel might be running on a 64-bit processor. But 2991da177e4SLinus Torvalds * if we're on a 32-bit processor and an i-cache incoherency 3001da177e4SLinus Torvalds * or race makes us see a 64-bit instruction here the sdl/sdr 3011da177e4SLinus Torvalds * would blow up, so for now we don't handle unaligned 64-bit 3021da177e4SLinus Torvalds * instructions on 32-bit kernels. 3031da177e4SLinus Torvalds */ 3041da177e4SLinus Torvalds if (!access_ok(VERIFY_READ, addr, 8)) 3051da177e4SLinus Torvalds goto sigbus; 3061da177e4SLinus Torvalds 3071da177e4SLinus Torvalds __asm__ __volatile__ ( 3081da177e4SLinus Torvalds #ifdef __BIG_ENDIAN 3091da177e4SLinus Torvalds "1:\tldl\t%0, (%2)\n" 3101da177e4SLinus Torvalds "2:\tldr\t%0, 7(%2)\n\t" 3111da177e4SLinus Torvalds #endif 3121da177e4SLinus Torvalds #ifdef __LITTLE_ENDIAN 3131da177e4SLinus Torvalds "1:\tldl\t%0, 7(%2)\n" 3141da177e4SLinus Torvalds "2:\tldr\t%0, (%2)\n\t" 3151da177e4SLinus Torvalds #endif 3161da177e4SLinus Torvalds "li\t%1, 0\n" 3171da177e4SLinus Torvalds "3:\t.section\t.fixup,\"ax\"\n\t" 3181da177e4SLinus Torvalds "4:\tli\t%1, %3\n\t" 3191da177e4SLinus Torvalds "j\t3b\n\t" 3201da177e4SLinus Torvalds ".previous\n\t" 3211da177e4SLinus Torvalds ".section\t__ex_table,\"a\"\n\t" 3221da177e4SLinus Torvalds STR(PTR)"\t1b, 4b\n\t" 3231da177e4SLinus Torvalds STR(PTR)"\t2b, 4b\n\t" 3241da177e4SLinus Torvalds ".previous" 3251da177e4SLinus Torvalds : "=&r" (value), "=r" (res) 3261da177e4SLinus Torvalds : "r" (addr), "i" (-EFAULT)); 3271da177e4SLinus Torvalds if (res) 3281da177e4SLinus Torvalds goto fault; 3297f18f151SRalf Baechle compute_return_epc(regs); 3307f18f151SRalf Baechle regs->regs[insn.i_format.rt] = value; 3311da177e4SLinus Torvalds break; 332875d43e7SRalf Baechle #endif /* CONFIG_64BIT */ 3331da177e4SLinus Torvalds 3341da177e4SLinus Torvalds /* Cannot handle 64-bit instructions in 32-bit kernel */ 3351da177e4SLinus Torvalds goto sigill; 3361da177e4SLinus Torvalds 3371da177e4SLinus Torvalds case sh_op: 3381da177e4SLinus Torvalds if (!access_ok(VERIFY_WRITE, addr, 2)) 3391da177e4SLinus Torvalds goto sigbus; 3401da177e4SLinus Torvalds 3411da177e4SLinus Torvalds value = regs->regs[insn.i_format.rt]; 3421da177e4SLinus Torvalds __asm__ __volatile__ ( 3431da177e4SLinus Torvalds #ifdef __BIG_ENDIAN 3441da177e4SLinus Torvalds ".set\tnoat\n" 3451da177e4SLinus Torvalds "1:\tsb\t%1, 1(%2)\n\t" 3461da177e4SLinus Torvalds "srl\t$1, %1, 0x8\n" 3471da177e4SLinus Torvalds "2:\tsb\t$1, 0(%2)\n\t" 3481da177e4SLinus Torvalds ".set\tat\n\t" 3491da177e4SLinus Torvalds #endif 3501da177e4SLinus Torvalds #ifdef __LITTLE_ENDIAN 3511da177e4SLinus Torvalds ".set\tnoat\n" 3521da177e4SLinus Torvalds "1:\tsb\t%1, 0(%2)\n\t" 3531da177e4SLinus Torvalds "srl\t$1,%1, 0x8\n" 3541da177e4SLinus Torvalds "2:\tsb\t$1, 1(%2)\n\t" 3551da177e4SLinus Torvalds ".set\tat\n\t" 3561da177e4SLinus Torvalds #endif 3571da177e4SLinus Torvalds "li\t%0, 0\n" 3581da177e4SLinus Torvalds "3:\n\t" 3591da177e4SLinus Torvalds ".section\t.fixup,\"ax\"\n\t" 3601da177e4SLinus Torvalds "4:\tli\t%0, %3\n\t" 3611da177e4SLinus Torvalds "j\t3b\n\t" 3621da177e4SLinus Torvalds ".previous\n\t" 3631da177e4SLinus Torvalds ".section\t__ex_table,\"a\"\n\t" 3641da177e4SLinus Torvalds STR(PTR)"\t1b, 4b\n\t" 3651da177e4SLinus Torvalds STR(PTR)"\t2b, 4b\n\t" 3661da177e4SLinus Torvalds ".previous" 3671da177e4SLinus Torvalds : "=r" (res) 3681da177e4SLinus Torvalds : "r" (value), "r" (addr), "i" (-EFAULT)); 3691da177e4SLinus Torvalds if (res) 3701da177e4SLinus Torvalds goto fault; 3717f18f151SRalf Baechle compute_return_epc(regs); 3721da177e4SLinus Torvalds break; 3731da177e4SLinus Torvalds 3741da177e4SLinus Torvalds case sw_op: 3751da177e4SLinus Torvalds if (!access_ok(VERIFY_WRITE, addr, 4)) 3761da177e4SLinus Torvalds goto sigbus; 3771da177e4SLinus Torvalds 3781da177e4SLinus Torvalds value = regs->regs[insn.i_format.rt]; 3791da177e4SLinus Torvalds __asm__ __volatile__ ( 3801da177e4SLinus Torvalds #ifdef __BIG_ENDIAN 3811da177e4SLinus Torvalds "1:\tswl\t%1,(%2)\n" 3821da177e4SLinus Torvalds "2:\tswr\t%1, 3(%2)\n\t" 3831da177e4SLinus Torvalds #endif 3841da177e4SLinus Torvalds #ifdef __LITTLE_ENDIAN 3851da177e4SLinus Torvalds "1:\tswl\t%1, 3(%2)\n" 3861da177e4SLinus Torvalds "2:\tswr\t%1, (%2)\n\t" 3871da177e4SLinus Torvalds #endif 3881da177e4SLinus Torvalds "li\t%0, 0\n" 3891da177e4SLinus Torvalds "3:\n\t" 3901da177e4SLinus Torvalds ".section\t.fixup,\"ax\"\n\t" 3911da177e4SLinus Torvalds "4:\tli\t%0, %3\n\t" 3921da177e4SLinus Torvalds "j\t3b\n\t" 3931da177e4SLinus Torvalds ".previous\n\t" 3941da177e4SLinus Torvalds ".section\t__ex_table,\"a\"\n\t" 3951da177e4SLinus Torvalds STR(PTR)"\t1b, 4b\n\t" 3961da177e4SLinus Torvalds STR(PTR)"\t2b, 4b\n\t" 3971da177e4SLinus Torvalds ".previous" 3981da177e4SLinus Torvalds : "=r" (res) 3991da177e4SLinus Torvalds : "r" (value), "r" (addr), "i" (-EFAULT)); 4001da177e4SLinus Torvalds if (res) 4011da177e4SLinus Torvalds goto fault; 4027f18f151SRalf Baechle compute_return_epc(regs); 4031da177e4SLinus Torvalds break; 4041da177e4SLinus Torvalds 4051da177e4SLinus Torvalds case sd_op: 406875d43e7SRalf Baechle #ifdef CONFIG_64BIT 4071da177e4SLinus Torvalds /* 4081da177e4SLinus Torvalds * A 32-bit kernel might be running on a 64-bit processor. But 4091da177e4SLinus Torvalds * if we're on a 32-bit processor and an i-cache incoherency 4101da177e4SLinus Torvalds * or race makes us see a 64-bit instruction here the sdl/sdr 4111da177e4SLinus Torvalds * would blow up, so for now we don't handle unaligned 64-bit 4121da177e4SLinus Torvalds * instructions on 32-bit kernels. 4131da177e4SLinus Torvalds */ 4141da177e4SLinus Torvalds if (!access_ok(VERIFY_WRITE, addr, 8)) 4151da177e4SLinus Torvalds goto sigbus; 4161da177e4SLinus Torvalds 4171da177e4SLinus Torvalds value = regs->regs[insn.i_format.rt]; 4181da177e4SLinus Torvalds __asm__ __volatile__ ( 4191da177e4SLinus Torvalds #ifdef __BIG_ENDIAN 4201da177e4SLinus Torvalds "1:\tsdl\t%1,(%2)\n" 4211da177e4SLinus Torvalds "2:\tsdr\t%1, 7(%2)\n\t" 4221da177e4SLinus Torvalds #endif 4231da177e4SLinus Torvalds #ifdef __LITTLE_ENDIAN 4241da177e4SLinus Torvalds "1:\tsdl\t%1, 7(%2)\n" 4251da177e4SLinus Torvalds "2:\tsdr\t%1, (%2)\n\t" 4261da177e4SLinus Torvalds #endif 4271da177e4SLinus Torvalds "li\t%0, 0\n" 4281da177e4SLinus Torvalds "3:\n\t" 4291da177e4SLinus Torvalds ".section\t.fixup,\"ax\"\n\t" 4301da177e4SLinus Torvalds "4:\tli\t%0, %3\n\t" 4311da177e4SLinus Torvalds "j\t3b\n\t" 4321da177e4SLinus Torvalds ".previous\n\t" 4331da177e4SLinus Torvalds ".section\t__ex_table,\"a\"\n\t" 4341da177e4SLinus Torvalds STR(PTR)"\t1b, 4b\n\t" 4351da177e4SLinus Torvalds STR(PTR)"\t2b, 4b\n\t" 4361da177e4SLinus Torvalds ".previous" 4371da177e4SLinus Torvalds : "=r" (res) 4381da177e4SLinus Torvalds : "r" (value), "r" (addr), "i" (-EFAULT)); 4391da177e4SLinus Torvalds if (res) 4401da177e4SLinus Torvalds goto fault; 4417f18f151SRalf Baechle compute_return_epc(regs); 4421da177e4SLinus Torvalds break; 443875d43e7SRalf Baechle #endif /* CONFIG_64BIT */ 4441da177e4SLinus Torvalds 4451da177e4SLinus Torvalds /* Cannot handle 64-bit instructions in 32-bit kernel */ 4461da177e4SLinus Torvalds goto sigill; 4471da177e4SLinus Torvalds 4481da177e4SLinus Torvalds case lwc1_op: 4491da177e4SLinus Torvalds case ldc1_op: 4501da177e4SLinus Torvalds case swc1_op: 4511da177e4SLinus Torvalds case sdc1_op: 4521da177e4SLinus Torvalds /* 4531da177e4SLinus Torvalds * I herewith declare: this does not happen. So send SIGBUS. 4541da177e4SLinus Torvalds */ 4551da177e4SLinus Torvalds goto sigbus; 4561da177e4SLinus Torvalds 4571da177e4SLinus Torvalds /* 45869f3a7deSRalf Baechle * COP2 is available to implementor for application specific use. 45969f3a7deSRalf Baechle * It's up to applications to register a notifier chain and do 46069f3a7deSRalf Baechle * whatever they have to do, including possible sending of signals. 4611da177e4SLinus Torvalds */ 46269f3a7deSRalf Baechle case lwc2_op: 46369f3a7deSRalf Baechle cu2_notifier_call_chain(CU2_LWC2_OP, regs); 46469f3a7deSRalf Baechle break; 46569f3a7deSRalf Baechle 46669f3a7deSRalf Baechle case ldc2_op: 46769f3a7deSRalf Baechle cu2_notifier_call_chain(CU2_LDC2_OP, regs); 46869f3a7deSRalf Baechle break; 46969f3a7deSRalf Baechle 47069f3a7deSRalf Baechle case swc2_op: 47169f3a7deSRalf Baechle cu2_notifier_call_chain(CU2_SWC2_OP, regs); 47269f3a7deSRalf Baechle break; 47369f3a7deSRalf Baechle 47469f3a7deSRalf Baechle case sdc2_op: 47569f3a7deSRalf Baechle cu2_notifier_call_chain(CU2_SDC2_OP, regs); 47669f3a7deSRalf Baechle break; 47769f3a7deSRalf Baechle 4781da177e4SLinus Torvalds default: 4791da177e4SLinus Torvalds /* 4801da177e4SLinus Torvalds * Pheeee... We encountered an yet unknown instruction or 4811da177e4SLinus Torvalds * cache coherence problem. Die sucker, die ... 4821da177e4SLinus Torvalds */ 4831da177e4SLinus Torvalds goto sigill; 4841da177e4SLinus Torvalds } 4851da177e4SLinus Torvalds 4866312e0eeSAtsushi Nemoto #ifdef CONFIG_DEBUG_FS 4871da177e4SLinus Torvalds unaligned_instructions++; 4881da177e4SLinus Torvalds #endif 4891da177e4SLinus Torvalds 4907f18f151SRalf Baechle return; 4911da177e4SLinus Torvalds 4921da177e4SLinus Torvalds fault: 4931da177e4SLinus Torvalds /* Did we have an exception handler installed? */ 4941da177e4SLinus Torvalds if (fixup_exception(regs)) 4957f18f151SRalf Baechle return; 4961da177e4SLinus Torvalds 4971da177e4SLinus Torvalds die_if_kernel("Unhandled kernel unaligned access", regs); 498a6d5ff04SDavid Daney force_sig(SIGSEGV, current); 4991da177e4SLinus Torvalds 5007f18f151SRalf Baechle return; 5011da177e4SLinus Torvalds 5021da177e4SLinus Torvalds sigbus: 5031da177e4SLinus Torvalds die_if_kernel("Unhandled kernel unaligned access", regs); 504a6d5ff04SDavid Daney force_sig(SIGBUS, current); 5051da177e4SLinus Torvalds 5067f18f151SRalf Baechle return; 5071da177e4SLinus Torvalds 5081da177e4SLinus Torvalds sigill: 5091da177e4SLinus Torvalds die_if_kernel("Unhandled kernel unaligned access or invalid instruction", regs); 510a6d5ff04SDavid Daney force_sig(SIGILL, current); 5111da177e4SLinus Torvalds } 5121da177e4SLinus Torvalds 5131da177e4SLinus Torvalds asmlinkage void do_ade(struct pt_regs *regs) 5141da177e4SLinus Torvalds { 515fe00f943SRalf Baechle unsigned int __user *pc; 5161da177e4SLinus Torvalds mm_segment_t seg; 5171da177e4SLinus Torvalds 5187f788d2dSDeng-Cheng Zhu perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 519*a8b0ca17SPeter Zijlstra 1, regs, regs->cp0_badvaddr); 5201da177e4SLinus Torvalds /* 5211da177e4SLinus Torvalds * Did we catch a fault trying to load an instruction? 5221da177e4SLinus Torvalds * Or are we running in MIPS16 mode? 5231da177e4SLinus Torvalds */ 5241da177e4SLinus Torvalds if ((regs->cp0_badvaddr == regs->cp0_epc) || (regs->cp0_epc & 0x1)) 5251da177e4SLinus Torvalds goto sigbus; 5261da177e4SLinus Torvalds 527fe00f943SRalf Baechle pc = (unsigned int __user *) exception_epc(regs); 528293c5bd1SRalf Baechle if (user_mode(regs) && !test_thread_flag(TIF_FIXADE)) 5291da177e4SLinus Torvalds goto sigbus; 5306312e0eeSAtsushi Nemoto if (unaligned_action == UNALIGNED_ACTION_SIGNAL) 5316312e0eeSAtsushi Nemoto goto sigbus; 5326312e0eeSAtsushi Nemoto else if (unaligned_action == UNALIGNED_ACTION_SHOW) 5336312e0eeSAtsushi Nemoto show_registers(regs); 5341da177e4SLinus Torvalds 5351da177e4SLinus Torvalds /* 5361da177e4SLinus Torvalds * Do branch emulation only if we didn't forward the exception. 5371da177e4SLinus Torvalds * This is all so but ugly ... 5381da177e4SLinus Torvalds */ 5391da177e4SLinus Torvalds seg = get_fs(); 5401da177e4SLinus Torvalds if (!user_mode(regs)) 5411da177e4SLinus Torvalds set_fs(KERNEL_DS); 5427f18f151SRalf Baechle emulate_load_store_insn(regs, (void __user *)regs->cp0_badvaddr, pc); 5431da177e4SLinus Torvalds set_fs(seg); 5441da177e4SLinus Torvalds 5451da177e4SLinus Torvalds return; 5461da177e4SLinus Torvalds 5471da177e4SLinus Torvalds sigbus: 5481da177e4SLinus Torvalds die_if_kernel("Kernel unaligned instruction access", regs); 5491da177e4SLinus Torvalds force_sig(SIGBUS, current); 5501da177e4SLinus Torvalds 5511da177e4SLinus Torvalds /* 5521da177e4SLinus Torvalds * XXX On return from the signal handler we should advance the epc 5531da177e4SLinus Torvalds */ 5541da177e4SLinus Torvalds } 5556312e0eeSAtsushi Nemoto 5566312e0eeSAtsushi Nemoto #ifdef CONFIG_DEBUG_FS 5576312e0eeSAtsushi Nemoto extern struct dentry *mips_debugfs_dir; 5586312e0eeSAtsushi Nemoto static int __init debugfs_unaligned(void) 5596312e0eeSAtsushi Nemoto { 5606312e0eeSAtsushi Nemoto struct dentry *d; 5616312e0eeSAtsushi Nemoto 5626312e0eeSAtsushi Nemoto if (!mips_debugfs_dir) 5636312e0eeSAtsushi Nemoto return -ENODEV; 5646312e0eeSAtsushi Nemoto d = debugfs_create_u32("unaligned_instructions", S_IRUGO, 5656312e0eeSAtsushi Nemoto mips_debugfs_dir, &unaligned_instructions); 566b517531cSZhaolei if (!d) 567b517531cSZhaolei return -ENOMEM; 5686312e0eeSAtsushi Nemoto d = debugfs_create_u32("unaligned_action", S_IRUGO | S_IWUSR, 5696312e0eeSAtsushi Nemoto mips_debugfs_dir, &unaligned_action); 570b517531cSZhaolei if (!d) 571b517531cSZhaolei return -ENOMEM; 5726312e0eeSAtsushi Nemoto return 0; 5736312e0eeSAtsushi Nemoto } 5746312e0eeSAtsushi Nemoto __initcall(debugfs_unaligned); 5756312e0eeSAtsushi Nemoto #endif 576