blob: 7659da224fcdd18fe96c87c6b3e7d1f2cc4a241c [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * Handle unaligned accesses by emulation.
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 *
8 * Copyright (C) 1996, 1998, 1999, 2002 by Ralf Baechle
9 * Copyright (C) 1999 Silicon Graphics, Inc.
Markos Chandras9d8e5732013-12-19 16:41:05 +000010 * Copyright (C) 2014 Imagination Technologies Ltd.
Linus Torvalds1da177e2005-04-16 15:20:36 -070011 *
12 * This file contains exception handler for address error exception with the
13 * special capability to execute faulting instructions in software. The
14 * handler does not try to handle the case when the program counter points
15 * to an address not aligned to a word boundary.
16 *
17 * Putting data to unaligned addresses is a bad practice even on Intel where
18 * only the performance is affected. Much worse is that such code is non-
19 * portable. Due to several programs that die on MIPS due to alignment
20 * problems I decided to implement this handler anyway though I originally
21 * didn't intend to do this at all for user code.
22 *
23 * For now I enable fixing of address errors by default to make life easier.
24 * I however intend to disable this somewhen in the future when the alignment
Ralf Baechle70342282013-01-22 12:59:30 +010025 * problems with user programs have been fixed. For programmers this is the
Linus Torvalds1da177e2005-04-16 15:20:36 -070026 * right way to go.
27 *
28 * Fixing address errors is a per process option. The option is inherited
Ralf Baechle70342282013-01-22 12:59:30 +010029 * across fork(2) and execve(2) calls. If you really want to use the
Linus Torvalds1da177e2005-04-16 15:20:36 -070030 * option in your user programs - I discourage the use of the software
31 * emulation strongly - use the following code in your userland stuff:
32 *
33 * #include <sys/sysmips.h>
34 *
35 * ...
36 * sysmips(MIPS_FIXADE, x);
37 * ...
38 *
39 * The argument x is 0 for disabling software emulation, enabled otherwise.
40 *
41 * Below a little program to play around with this feature.
42 *
43 * #include <stdio.h>
44 * #include <sys/sysmips.h>
45 *
46 * struct foo {
Ralf Baechle70342282013-01-22 12:59:30 +010047 * unsigned char bar[8];
Linus Torvalds1da177e2005-04-16 15:20:36 -070048 * };
49 *
50 * main(int argc, char *argv[])
51 * {
Ralf Baechle70342282013-01-22 12:59:30 +010052 * struct foo x = {0, 1, 2, 3, 4, 5, 6, 7};
53 * unsigned int *p = (unsigned int *) (x.bar + 3);
54 * int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -070055 *
Ralf Baechle70342282013-01-22 12:59:30 +010056 * if (argc > 1)
57 * sysmips(MIPS_FIXADE, atoi(argv[1]));
Linus Torvalds1da177e2005-04-16 15:20:36 -070058 *
Ralf Baechle70342282013-01-22 12:59:30 +010059 * printf("*p = %08lx\n", *p);
Linus Torvalds1da177e2005-04-16 15:20:36 -070060 *
Ralf Baechle70342282013-01-22 12:59:30 +010061 * *p = 0xdeadface;
Linus Torvalds1da177e2005-04-16 15:20:36 -070062 *
Ralf Baechle70342282013-01-22 12:59:30 +010063 * for(i = 0; i <= 7; i++)
64 * printf("%02x ", x.bar[i]);
65 * printf("\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -070066 * }
67 *
68 * Coprocessor loads are not supported; I think this case is unimportant
69 * in the practice.
70 *
71 * TODO: Handle ndc (attempted store to doubleword in uncached memory)
Ralf Baechle70342282013-01-22 12:59:30 +010072 * exception for the R6000.
73 * A store crossing a page boundary might be executed only partially.
74 * Undo the partial store in this case.
Linus Torvalds1da177e2005-04-16 15:20:36 -070075 */
Ralf Baechlec3fc5cd2013-05-29 01:07:19 +020076#include <linux/context_tracking.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070077#include <linux/mm.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070078#include <linux/signal.h>
79#include <linux/smp.h>
Alexey Dobriyane8edc6e2007-05-21 01:22:52 +040080#include <linux/sched.h>
Atsushi Nemoto6312e0e2007-06-30 00:55:48 +090081#include <linux/debugfs.h>
Deng-Cheng Zhu7f788d22010-10-12 19:37:21 +080082#include <linux/perf_event.h>
83
Linus Torvalds1da177e2005-04-16 15:20:36 -070084#include <asm/asm.h>
85#include <asm/branch.h>
86#include <asm/byteorder.h>
Ralf Baechle69f3a7d2009-11-24 01:24:58 +000087#include <asm/cop2.h>
Leonid Yegoshin102cedc2013-03-25 12:09:02 -050088#include <asm/fpu.h>
89#include <asm/fpu_emulator.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070090#include <asm/inst.h>
91#include <asm/uaccess.h>
Leonid Yegoshin34c2f662013-03-25 13:18:07 -050092#include <asm/fpu.h>
93#include <asm/fpu_emulator.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070094
Ralf Baechle70342282013-01-22 12:59:30 +010095#define STR(x) __STR(x)
Linus Torvalds1da177e2005-04-16 15:20:36 -070096#define __STR(x) #x
97
Atsushi Nemoto6312e0e2007-06-30 00:55:48 +090098enum {
99 UNALIGNED_ACTION_QUIET,
100 UNALIGNED_ACTION_SIGNAL,
101 UNALIGNED_ACTION_SHOW,
102};
103#ifdef CONFIG_DEBUG_FS
104static u32 unaligned_instructions;
105static u32 unaligned_action;
106#else
107#define unaligned_action UNALIGNED_ACTION_QUIET
Linus Torvalds1da177e2005-04-16 15:20:36 -0700108#endif
Atsushi Nemoto6312e0e2007-06-30 00:55:48 +0900109extern void show_registers(struct pt_regs *regs);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700110
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500111#ifdef __BIG_ENDIAN
Markos Chandraseeb53892015-03-09 14:54:50 +0000112#define _LoadHW(addr, value, res, type) \
Markos Chandras3563c322015-03-09 14:54:51 +0000113do { \
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500114 __asm__ __volatile__ (".set\tnoat\n" \
Markos Chandraseeb53892015-03-09 14:54:50 +0000115 "1:\t"type##_lb("%0", "0(%2)")"\n" \
116 "2:\t"type##_lbu("$1", "1(%2)")"\n\t"\
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500117 "sll\t%0, 0x8\n\t" \
118 "or\t%0, $1\n\t" \
119 "li\t%1, 0\n" \
120 "3:\t.set\tat\n\t" \
121 ".insn\n\t" \
122 ".section\t.fixup,\"ax\"\n\t" \
123 "4:\tli\t%1, %3\n\t" \
124 "j\t3b\n\t" \
125 ".previous\n\t" \
126 ".section\t__ex_table,\"a\"\n\t" \
127 STR(PTR)"\t1b, 4b\n\t" \
128 STR(PTR)"\t2b, 4b\n\t" \
129 ".previous" \
130 : "=&r" (value), "=r" (res) \
Markos Chandras3563c322015-03-09 14:54:51 +0000131 : "r" (addr), "i" (-EFAULT)); \
132} while(0)
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500133
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000134#ifndef CONFIG_CPU_MIPSR6
Markos Chandraseeb53892015-03-09 14:54:50 +0000135#define _LoadW(addr, value, res, type) \
Markos Chandras3563c322015-03-09 14:54:51 +0000136do { \
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500137 __asm__ __volatile__ ( \
Markos Chandraseeb53892015-03-09 14:54:50 +0000138 "1:\t"type##_lwl("%0", "(%2)")"\n" \
139 "2:\t"type##_lwr("%0", "3(%2)")"\n\t"\
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500140 "li\t%1, 0\n" \
141 "3:\n\t" \
142 ".insn\n\t" \
143 ".section\t.fixup,\"ax\"\n\t" \
144 "4:\tli\t%1, %3\n\t" \
145 "j\t3b\n\t" \
146 ".previous\n\t" \
147 ".section\t__ex_table,\"a\"\n\t" \
148 STR(PTR)"\t1b, 4b\n\t" \
149 STR(PTR)"\t2b, 4b\n\t" \
150 ".previous" \
151 : "=&r" (value), "=r" (res) \
Markos Chandras3563c322015-03-09 14:54:51 +0000152 : "r" (addr), "i" (-EFAULT)); \
153} while(0)
154
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000155#else
156/* MIPSR6 has no lwl instruction */
Markos Chandraseeb53892015-03-09 14:54:50 +0000157#define _LoadW(addr, value, res, type) \
Markos Chandras3563c322015-03-09 14:54:51 +0000158do { \
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000159 __asm__ __volatile__ ( \
160 ".set\tpush\n" \
161 ".set\tnoat\n\t" \
Markos Chandraseeb53892015-03-09 14:54:50 +0000162 "1:"type##_lb("%0", "0(%2)")"\n\t" \
163 "2:"type##_lbu("$1", "1(%2)")"\n\t" \
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000164 "sll\t%0, 0x8\n\t" \
165 "or\t%0, $1\n\t" \
Markos Chandraseeb53892015-03-09 14:54:50 +0000166 "3:"type##_lbu("$1", "2(%2)")"\n\t" \
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000167 "sll\t%0, 0x8\n\t" \
168 "or\t%0, $1\n\t" \
Markos Chandraseeb53892015-03-09 14:54:50 +0000169 "4:"type##_lbu("$1", "3(%2)")"\n\t" \
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000170 "sll\t%0, 0x8\n\t" \
171 "or\t%0, $1\n\t" \
172 "li\t%1, 0\n" \
173 ".set\tpop\n" \
174 "10:\n\t" \
175 ".insn\n\t" \
176 ".section\t.fixup,\"ax\"\n\t" \
177 "11:\tli\t%1, %3\n\t" \
178 "j\t10b\n\t" \
179 ".previous\n\t" \
180 ".section\t__ex_table,\"a\"\n\t" \
181 STR(PTR)"\t1b, 11b\n\t" \
182 STR(PTR)"\t2b, 11b\n\t" \
183 STR(PTR)"\t3b, 11b\n\t" \
184 STR(PTR)"\t4b, 11b\n\t" \
185 ".previous" \
186 : "=&r" (value), "=r" (res) \
Markos Chandras3563c322015-03-09 14:54:51 +0000187 : "r" (addr), "i" (-EFAULT)); \
188} while(0)
189
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000190#endif /* CONFIG_CPU_MIPSR6 */
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500191
Markos Chandraseeb53892015-03-09 14:54:50 +0000192#define _LoadHWU(addr, value, res, type) \
Markos Chandras3563c322015-03-09 14:54:51 +0000193do { \
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500194 __asm__ __volatile__ ( \
195 ".set\tnoat\n" \
Markos Chandraseeb53892015-03-09 14:54:50 +0000196 "1:\t"type##_lbu("%0", "0(%2)")"\n" \
197 "2:\t"type##_lbu("$1", "1(%2)")"\n\t"\
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500198 "sll\t%0, 0x8\n\t" \
199 "or\t%0, $1\n\t" \
200 "li\t%1, 0\n" \
201 "3:\n\t" \
202 ".insn\n\t" \
203 ".set\tat\n\t" \
204 ".section\t.fixup,\"ax\"\n\t" \
205 "4:\tli\t%1, %3\n\t" \
206 "j\t3b\n\t" \
207 ".previous\n\t" \
208 ".section\t__ex_table,\"a\"\n\t" \
209 STR(PTR)"\t1b, 4b\n\t" \
210 STR(PTR)"\t2b, 4b\n\t" \
211 ".previous" \
212 : "=&r" (value), "=r" (res) \
Markos Chandras3563c322015-03-09 14:54:51 +0000213 : "r" (addr), "i" (-EFAULT)); \
214} while(0)
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500215
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000216#ifndef CONFIG_CPU_MIPSR6
Markos Chandraseeb53892015-03-09 14:54:50 +0000217#define _LoadWU(addr, value, res, type) \
Markos Chandras3563c322015-03-09 14:54:51 +0000218do { \
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500219 __asm__ __volatile__ ( \
Markos Chandraseeb53892015-03-09 14:54:50 +0000220 "1:\t"type##_lwl("%0", "(%2)")"\n" \
221 "2:\t"type##_lwr("%0", "3(%2)")"\n\t"\
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500222 "dsll\t%0, %0, 32\n\t" \
223 "dsrl\t%0, %0, 32\n\t" \
224 "li\t%1, 0\n" \
225 "3:\n\t" \
226 ".insn\n\t" \
227 "\t.section\t.fixup,\"ax\"\n\t" \
228 "4:\tli\t%1, %3\n\t" \
229 "j\t3b\n\t" \
230 ".previous\n\t" \
231 ".section\t__ex_table,\"a\"\n\t" \
232 STR(PTR)"\t1b, 4b\n\t" \
233 STR(PTR)"\t2b, 4b\n\t" \
234 ".previous" \
235 : "=&r" (value), "=r" (res) \
Markos Chandras3563c322015-03-09 14:54:51 +0000236 : "r" (addr), "i" (-EFAULT)); \
237} while(0)
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500238
Markos Chandraseeb53892015-03-09 14:54:50 +0000239#define _LoadDW(addr, value, res) \
Markos Chandras3563c322015-03-09 14:54:51 +0000240do { \
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500241 __asm__ __volatile__ ( \
242 "1:\tldl\t%0, (%2)\n" \
243 "2:\tldr\t%0, 7(%2)\n\t" \
244 "li\t%1, 0\n" \
245 "3:\n\t" \
246 ".insn\n\t" \
247 "\t.section\t.fixup,\"ax\"\n\t" \
248 "4:\tli\t%1, %3\n\t" \
249 "j\t3b\n\t" \
250 ".previous\n\t" \
251 ".section\t__ex_table,\"a\"\n\t" \
252 STR(PTR)"\t1b, 4b\n\t" \
253 STR(PTR)"\t2b, 4b\n\t" \
254 ".previous" \
255 : "=&r" (value), "=r" (res) \
Markos Chandras3563c322015-03-09 14:54:51 +0000256 : "r" (addr), "i" (-EFAULT)); \
257} while(0)
258
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000259#else
260/* MIPSR6 has not lwl and ldl instructions */
Markos Chandraseeb53892015-03-09 14:54:50 +0000261#define _LoadWU(addr, value, res, type) \
Markos Chandras3563c322015-03-09 14:54:51 +0000262do { \
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000263 __asm__ __volatile__ ( \
264 ".set\tpush\n\t" \
265 ".set\tnoat\n\t" \
Markos Chandraseeb53892015-03-09 14:54:50 +0000266 "1:"type##_lbu("%0", "0(%2)")"\n\t" \
267 "2:"type##_lbu("$1", "1(%2)")"\n\t" \
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000268 "sll\t%0, 0x8\n\t" \
269 "or\t%0, $1\n\t" \
Markos Chandraseeb53892015-03-09 14:54:50 +0000270 "3:"type##_lbu("$1", "2(%2)")"\n\t" \
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000271 "sll\t%0, 0x8\n\t" \
272 "or\t%0, $1\n\t" \
Markos Chandraseeb53892015-03-09 14:54:50 +0000273 "4:"type##_lbu("$1", "3(%2)")"\n\t" \
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000274 "sll\t%0, 0x8\n\t" \
275 "or\t%0, $1\n\t" \
276 "li\t%1, 0\n" \
277 ".set\tpop\n" \
278 "10:\n\t" \
279 ".insn\n\t" \
280 ".section\t.fixup,\"ax\"\n\t" \
281 "11:\tli\t%1, %3\n\t" \
282 "j\t10b\n\t" \
283 ".previous\n\t" \
284 ".section\t__ex_table,\"a\"\n\t" \
285 STR(PTR)"\t1b, 11b\n\t" \
286 STR(PTR)"\t2b, 11b\n\t" \
287 STR(PTR)"\t3b, 11b\n\t" \
288 STR(PTR)"\t4b, 11b\n\t" \
289 ".previous" \
290 : "=&r" (value), "=r" (res) \
Markos Chandras3563c322015-03-09 14:54:51 +0000291 : "r" (addr), "i" (-EFAULT)); \
292} while(0)
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000293
Markos Chandraseeb53892015-03-09 14:54:50 +0000294#define _LoadDW(addr, value, res) \
Markos Chandras3563c322015-03-09 14:54:51 +0000295do { \
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000296 __asm__ __volatile__ ( \
297 ".set\tpush\n\t" \
298 ".set\tnoat\n\t" \
299 "1:lb\t%0, 0(%2)\n\t" \
300 "2:lbu\t $1, 1(%2)\n\t" \
301 "dsll\t%0, 0x8\n\t" \
302 "or\t%0, $1\n\t" \
303 "3:lbu\t$1, 2(%2)\n\t" \
304 "dsll\t%0, 0x8\n\t" \
305 "or\t%0, $1\n\t" \
306 "4:lbu\t$1, 3(%2)\n\t" \
307 "dsll\t%0, 0x8\n\t" \
308 "or\t%0, $1\n\t" \
309 "5:lbu\t$1, 4(%2)\n\t" \
310 "dsll\t%0, 0x8\n\t" \
311 "or\t%0, $1\n\t" \
312 "6:lbu\t$1, 5(%2)\n\t" \
313 "dsll\t%0, 0x8\n\t" \
314 "or\t%0, $1\n\t" \
315 "7:lbu\t$1, 6(%2)\n\t" \
316 "dsll\t%0, 0x8\n\t" \
317 "or\t%0, $1\n\t" \
318 "8:lbu\t$1, 7(%2)\n\t" \
319 "dsll\t%0, 0x8\n\t" \
320 "or\t%0, $1\n\t" \
321 "li\t%1, 0\n" \
322 ".set\tpop\n\t" \
323 "10:\n\t" \
324 ".insn\n\t" \
325 ".section\t.fixup,\"ax\"\n\t" \
326 "11:\tli\t%1, %3\n\t" \
327 "j\t10b\n\t" \
328 ".previous\n\t" \
329 ".section\t__ex_table,\"a\"\n\t" \
330 STR(PTR)"\t1b, 11b\n\t" \
331 STR(PTR)"\t2b, 11b\n\t" \
332 STR(PTR)"\t3b, 11b\n\t" \
333 STR(PTR)"\t4b, 11b\n\t" \
334 STR(PTR)"\t5b, 11b\n\t" \
335 STR(PTR)"\t6b, 11b\n\t" \
336 STR(PTR)"\t7b, 11b\n\t" \
337 STR(PTR)"\t8b, 11b\n\t" \
338 ".previous" \
339 : "=&r" (value), "=r" (res) \
Markos Chandras3563c322015-03-09 14:54:51 +0000340 : "r" (addr), "i" (-EFAULT)); \
341} while(0)
342
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000343#endif /* CONFIG_CPU_MIPSR6 */
344
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500345
Markos Chandraseeb53892015-03-09 14:54:50 +0000346#define _StoreHW(addr, value, res, type) \
Markos Chandras3563c322015-03-09 14:54:51 +0000347do { \
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500348 __asm__ __volatile__ ( \
349 ".set\tnoat\n" \
Markos Chandraseeb53892015-03-09 14:54:50 +0000350 "1:\t"type##_sb("%1", "1(%2)")"\n" \
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500351 "srl\t$1, %1, 0x8\n" \
Markos Chandraseeb53892015-03-09 14:54:50 +0000352 "2:\t"type##_sb("$1", "0(%2)")"\n" \
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500353 ".set\tat\n\t" \
354 "li\t%0, 0\n" \
355 "3:\n\t" \
356 ".insn\n\t" \
357 ".section\t.fixup,\"ax\"\n\t" \
358 "4:\tli\t%0, %3\n\t" \
359 "j\t3b\n\t" \
360 ".previous\n\t" \
361 ".section\t__ex_table,\"a\"\n\t" \
362 STR(PTR)"\t1b, 4b\n\t" \
363 STR(PTR)"\t2b, 4b\n\t" \
364 ".previous" \
365 : "=r" (res) \
Markos Chandras3563c322015-03-09 14:54:51 +0000366 : "r" (value), "r" (addr), "i" (-EFAULT));\
367} while(0)
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500368
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000369#ifndef CONFIG_CPU_MIPSR6
Markos Chandraseeb53892015-03-09 14:54:50 +0000370#define _StoreW(addr, value, res, type) \
Markos Chandras3563c322015-03-09 14:54:51 +0000371do { \
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500372 __asm__ __volatile__ ( \
Markos Chandraseeb53892015-03-09 14:54:50 +0000373 "1:\t"type##_swl("%1", "(%2)")"\n" \
374 "2:\t"type##_swr("%1", "3(%2)")"\n\t"\
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500375 "li\t%0, 0\n" \
376 "3:\n\t" \
377 ".insn\n\t" \
378 ".section\t.fixup,\"ax\"\n\t" \
379 "4:\tli\t%0, %3\n\t" \
380 "j\t3b\n\t" \
381 ".previous\n\t" \
382 ".section\t__ex_table,\"a\"\n\t" \
383 STR(PTR)"\t1b, 4b\n\t" \
384 STR(PTR)"\t2b, 4b\n\t" \
385 ".previous" \
386 : "=r" (res) \
Markos Chandras3563c322015-03-09 14:54:51 +0000387 : "r" (value), "r" (addr), "i" (-EFAULT)); \
388} while(0)
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500389
Markos Chandraseeb53892015-03-09 14:54:50 +0000390#define _StoreDW(addr, value, res) \
Markos Chandras3563c322015-03-09 14:54:51 +0000391do { \
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500392 __asm__ __volatile__ ( \
393 "1:\tsdl\t%1,(%2)\n" \
394 "2:\tsdr\t%1, 7(%2)\n\t" \
395 "li\t%0, 0\n" \
396 "3:\n\t" \
397 ".insn\n\t" \
398 ".section\t.fixup,\"ax\"\n\t" \
399 "4:\tli\t%0, %3\n\t" \
400 "j\t3b\n\t" \
401 ".previous\n\t" \
402 ".section\t__ex_table,\"a\"\n\t" \
403 STR(PTR)"\t1b, 4b\n\t" \
404 STR(PTR)"\t2b, 4b\n\t" \
405 ".previous" \
406 : "=r" (res) \
Markos Chandras3563c322015-03-09 14:54:51 +0000407 : "r" (value), "r" (addr), "i" (-EFAULT)); \
408} while(0)
409
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000410#else
411/* MIPSR6 has no swl and sdl instructions */
Markos Chandraseeb53892015-03-09 14:54:50 +0000412#define _StoreW(addr, value, res, type) \
Markos Chandras3563c322015-03-09 14:54:51 +0000413do { \
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000414 __asm__ __volatile__ ( \
415 ".set\tpush\n\t" \
416 ".set\tnoat\n\t" \
Markos Chandraseeb53892015-03-09 14:54:50 +0000417 "1:"type##_sb("%1", "3(%2)")"\n\t" \
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000418 "srl\t$1, %1, 0x8\n\t" \
Markos Chandraseeb53892015-03-09 14:54:50 +0000419 "2:"type##_sb("$1", "2(%2)")"\n\t" \
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000420 "srl\t$1, $1, 0x8\n\t" \
Markos Chandraseeb53892015-03-09 14:54:50 +0000421 "3:"type##_sb("$1", "1(%2)")"\n\t" \
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000422 "srl\t$1, $1, 0x8\n\t" \
Markos Chandraseeb53892015-03-09 14:54:50 +0000423 "4:"type##_sb("$1", "0(%2)")"\n\t" \
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000424 ".set\tpop\n\t" \
425 "li\t%0, 0\n" \
426 "10:\n\t" \
427 ".insn\n\t" \
428 ".section\t.fixup,\"ax\"\n\t" \
429 "11:\tli\t%0, %3\n\t" \
430 "j\t10b\n\t" \
431 ".previous\n\t" \
432 ".section\t__ex_table,\"a\"\n\t" \
433 STR(PTR)"\t1b, 11b\n\t" \
434 STR(PTR)"\t2b, 11b\n\t" \
435 STR(PTR)"\t3b, 11b\n\t" \
436 STR(PTR)"\t4b, 11b\n\t" \
437 ".previous" \
438 : "=&r" (res) \
439 : "r" (value), "r" (addr), "i" (-EFAULT) \
Markos Chandras3563c322015-03-09 14:54:51 +0000440 : "memory"); \
441} while(0)
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500442
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000443#define StoreDW(addr, value, res) \
Markos Chandras3563c322015-03-09 14:54:51 +0000444do { \
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000445 __asm__ __volatile__ ( \
446 ".set\tpush\n\t" \
447 ".set\tnoat\n\t" \
448 "1:sb\t%1, 7(%2)\n\t" \
449 "dsrl\t$1, %1, 0x8\n\t" \
450 "2:sb\t$1, 6(%2)\n\t" \
451 "dsrl\t$1, $1, 0x8\n\t" \
452 "3:sb\t$1, 5(%2)\n\t" \
453 "dsrl\t$1, $1, 0x8\n\t" \
454 "4:sb\t$1, 4(%2)\n\t" \
455 "dsrl\t$1, $1, 0x8\n\t" \
456 "5:sb\t$1, 3(%2)\n\t" \
457 "dsrl\t$1, $1, 0x8\n\t" \
458 "6:sb\t$1, 2(%2)\n\t" \
459 "dsrl\t$1, $1, 0x8\n\t" \
460 "7:sb\t$1, 1(%2)\n\t" \
461 "dsrl\t$1, $1, 0x8\n\t" \
462 "8:sb\t$1, 0(%2)\n\t" \
463 "dsrl\t$1, $1, 0x8\n\t" \
464 ".set\tpop\n\t" \
465 "li\t%0, 0\n" \
466 "10:\n\t" \
467 ".insn\n\t" \
468 ".section\t.fixup,\"ax\"\n\t" \
469 "11:\tli\t%0, %3\n\t" \
470 "j\t10b\n\t" \
471 ".previous\n\t" \
472 ".section\t__ex_table,\"a\"\n\t" \
473 STR(PTR)"\t1b, 11b\n\t" \
474 STR(PTR)"\t2b, 11b\n\t" \
475 STR(PTR)"\t3b, 11b\n\t" \
476 STR(PTR)"\t4b, 11b\n\t" \
477 STR(PTR)"\t5b, 11b\n\t" \
478 STR(PTR)"\t6b, 11b\n\t" \
479 STR(PTR)"\t7b, 11b\n\t" \
480 STR(PTR)"\t8b, 11b\n\t" \
481 ".previous" \
482 : "=&r" (res) \
483 : "r" (value), "r" (addr), "i" (-EFAULT) \
Markos Chandras3563c322015-03-09 14:54:51 +0000484 : "memory"); \
485} while(0)
486
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000487#endif /* CONFIG_CPU_MIPSR6 */
488
489#else /* __BIG_ENDIAN */
490
Markos Chandraseeb53892015-03-09 14:54:50 +0000491#define _LoadHW(addr, value, res, type) \
Markos Chandras3563c322015-03-09 14:54:51 +0000492do { \
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500493 __asm__ __volatile__ (".set\tnoat\n" \
Markos Chandraseeb53892015-03-09 14:54:50 +0000494 "1:\t"type##_lb("%0", "1(%2)")"\n" \
495 "2:\t"type##_lbu("$1", "0(%2)")"\n\t"\
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500496 "sll\t%0, 0x8\n\t" \
497 "or\t%0, $1\n\t" \
498 "li\t%1, 0\n" \
499 "3:\t.set\tat\n\t" \
500 ".insn\n\t" \
501 ".section\t.fixup,\"ax\"\n\t" \
502 "4:\tli\t%1, %3\n\t" \
503 "j\t3b\n\t" \
504 ".previous\n\t" \
505 ".section\t__ex_table,\"a\"\n\t" \
506 STR(PTR)"\t1b, 4b\n\t" \
507 STR(PTR)"\t2b, 4b\n\t" \
508 ".previous" \
509 : "=&r" (value), "=r" (res) \
Markos Chandras3563c322015-03-09 14:54:51 +0000510 : "r" (addr), "i" (-EFAULT)); \
511} while(0)
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500512
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000513#ifndef CONFIG_CPU_MIPSR6
Markos Chandraseeb53892015-03-09 14:54:50 +0000514#define _LoadW(addr, value, res, type) \
Markos Chandras3563c322015-03-09 14:54:51 +0000515do { \
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500516 __asm__ __volatile__ ( \
Markos Chandraseeb53892015-03-09 14:54:50 +0000517 "1:\t"type##_lwl("%0", "3(%2)")"\n" \
518 "2:\t"type##_lwr("%0", "(%2)")"\n\t"\
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500519 "li\t%1, 0\n" \
520 "3:\n\t" \
521 ".insn\n\t" \
522 ".section\t.fixup,\"ax\"\n\t" \
523 "4:\tli\t%1, %3\n\t" \
524 "j\t3b\n\t" \
525 ".previous\n\t" \
526 ".section\t__ex_table,\"a\"\n\t" \
527 STR(PTR)"\t1b, 4b\n\t" \
528 STR(PTR)"\t2b, 4b\n\t" \
529 ".previous" \
530 : "=&r" (value), "=r" (res) \
Markos Chandras3563c322015-03-09 14:54:51 +0000531 : "r" (addr), "i" (-EFAULT)); \
532} while(0)
533
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000534#else
535/* MIPSR6 has no lwl instruction */
Markos Chandraseeb53892015-03-09 14:54:50 +0000536#define _LoadW(addr, value, res, type) \
Markos Chandras3563c322015-03-09 14:54:51 +0000537do { \
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000538 __asm__ __volatile__ ( \
539 ".set\tpush\n" \
540 ".set\tnoat\n\t" \
Markos Chandraseeb53892015-03-09 14:54:50 +0000541 "1:"type##_lb("%0", "3(%2)")"\n\t" \
542 "2:"type##_lbu("$1", "2(%2)")"\n\t" \
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000543 "sll\t%0, 0x8\n\t" \
544 "or\t%0, $1\n\t" \
Markos Chandraseeb53892015-03-09 14:54:50 +0000545 "3:"type##_lbu("$1", "1(%2)")"\n\t" \
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000546 "sll\t%0, 0x8\n\t" \
547 "or\t%0, $1\n\t" \
Markos Chandraseeb53892015-03-09 14:54:50 +0000548 "4:"type##_lbu("$1", "0(%2)")"\n\t" \
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000549 "sll\t%0, 0x8\n\t" \
550 "or\t%0, $1\n\t" \
551 "li\t%1, 0\n" \
552 ".set\tpop\n" \
553 "10:\n\t" \
554 ".insn\n\t" \
555 ".section\t.fixup,\"ax\"\n\t" \
556 "11:\tli\t%1, %3\n\t" \
557 "j\t10b\n\t" \
558 ".previous\n\t" \
559 ".section\t__ex_table,\"a\"\n\t" \
560 STR(PTR)"\t1b, 11b\n\t" \
561 STR(PTR)"\t2b, 11b\n\t" \
562 STR(PTR)"\t3b, 11b\n\t" \
563 STR(PTR)"\t4b, 11b\n\t" \
564 ".previous" \
565 : "=&r" (value), "=r" (res) \
Markos Chandras3563c322015-03-09 14:54:51 +0000566 : "r" (addr), "i" (-EFAULT)); \
567} while(0)
568
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000569#endif /* CONFIG_CPU_MIPSR6 */
570
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500571
Markos Chandraseeb53892015-03-09 14:54:50 +0000572#define _LoadHWU(addr, value, res, type) \
Markos Chandras3563c322015-03-09 14:54:51 +0000573do { \
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500574 __asm__ __volatile__ ( \
575 ".set\tnoat\n" \
Markos Chandraseeb53892015-03-09 14:54:50 +0000576 "1:\t"type##_lbu("%0", "1(%2)")"\n" \
577 "2:\t"type##_lbu("$1", "0(%2)")"\n\t"\
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500578 "sll\t%0, 0x8\n\t" \
579 "or\t%0, $1\n\t" \
580 "li\t%1, 0\n" \
581 "3:\n\t" \
582 ".insn\n\t" \
583 ".set\tat\n\t" \
584 ".section\t.fixup,\"ax\"\n\t" \
585 "4:\tli\t%1, %3\n\t" \
586 "j\t3b\n\t" \
587 ".previous\n\t" \
588 ".section\t__ex_table,\"a\"\n\t" \
589 STR(PTR)"\t1b, 4b\n\t" \
590 STR(PTR)"\t2b, 4b\n\t" \
591 ".previous" \
592 : "=&r" (value), "=r" (res) \
Markos Chandras3563c322015-03-09 14:54:51 +0000593 : "r" (addr), "i" (-EFAULT)); \
594} while(0)
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500595
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000596#ifndef CONFIG_CPU_MIPSR6
Markos Chandraseeb53892015-03-09 14:54:50 +0000597#define _LoadWU(addr, value, res, type) \
Markos Chandras3563c322015-03-09 14:54:51 +0000598do { \
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500599 __asm__ __volatile__ ( \
Markos Chandraseeb53892015-03-09 14:54:50 +0000600 "1:\t"type##_lwl("%0", "3(%2)")"\n" \
601 "2:\t"type##_lwr("%0", "(%2)")"\n\t"\
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500602 "dsll\t%0, %0, 32\n\t" \
603 "dsrl\t%0, %0, 32\n\t" \
604 "li\t%1, 0\n" \
605 "3:\n\t" \
606 ".insn\n\t" \
607 "\t.section\t.fixup,\"ax\"\n\t" \
608 "4:\tli\t%1, %3\n\t" \
609 "j\t3b\n\t" \
610 ".previous\n\t" \
611 ".section\t__ex_table,\"a\"\n\t" \
612 STR(PTR)"\t1b, 4b\n\t" \
613 STR(PTR)"\t2b, 4b\n\t" \
614 ".previous" \
615 : "=&r" (value), "=r" (res) \
Markos Chandras3563c322015-03-09 14:54:51 +0000616 : "r" (addr), "i" (-EFAULT)); \
617} while(0)
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500618
Markos Chandraseeb53892015-03-09 14:54:50 +0000619#define _LoadDW(addr, value, res) \
Markos Chandras3563c322015-03-09 14:54:51 +0000620do { \
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500621 __asm__ __volatile__ ( \
622 "1:\tldl\t%0, 7(%2)\n" \
623 "2:\tldr\t%0, (%2)\n\t" \
624 "li\t%1, 0\n" \
625 "3:\n\t" \
626 ".insn\n\t" \
627 "\t.section\t.fixup,\"ax\"\n\t" \
628 "4:\tli\t%1, %3\n\t" \
629 "j\t3b\n\t" \
630 ".previous\n\t" \
631 ".section\t__ex_table,\"a\"\n\t" \
632 STR(PTR)"\t1b, 4b\n\t" \
633 STR(PTR)"\t2b, 4b\n\t" \
634 ".previous" \
635 : "=&r" (value), "=r" (res) \
Markos Chandras3563c322015-03-09 14:54:51 +0000636 : "r" (addr), "i" (-EFAULT)); \
637} while(0)
638
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000639#else
640/* MIPSR6 has not lwl and ldl instructions */
Markos Chandraseeb53892015-03-09 14:54:50 +0000641#define _LoadWU(addr, value, res, type) \
Markos Chandras3563c322015-03-09 14:54:51 +0000642do { \
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000643 __asm__ __volatile__ ( \
644 ".set\tpush\n\t" \
645 ".set\tnoat\n\t" \
Markos Chandraseeb53892015-03-09 14:54:50 +0000646 "1:"type##_lbu("%0", "3(%2)")"\n\t" \
647 "2:"type##_lbu("$1", "2(%2)")"\n\t" \
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000648 "sll\t%0, 0x8\n\t" \
649 "or\t%0, $1\n\t" \
Markos Chandraseeb53892015-03-09 14:54:50 +0000650 "3:"type##_lbu("$1", "1(%2)")"\n\t" \
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000651 "sll\t%0, 0x8\n\t" \
652 "or\t%0, $1\n\t" \
Markos Chandraseeb53892015-03-09 14:54:50 +0000653 "4:"type##_lbu("$1", "0(%2)")"\n\t" \
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000654 "sll\t%0, 0x8\n\t" \
655 "or\t%0, $1\n\t" \
656 "li\t%1, 0\n" \
657 ".set\tpop\n" \
658 "10:\n\t" \
659 ".insn\n\t" \
660 ".section\t.fixup,\"ax\"\n\t" \
661 "11:\tli\t%1, %3\n\t" \
662 "j\t10b\n\t" \
663 ".previous\n\t" \
664 ".section\t__ex_table,\"a\"\n\t" \
665 STR(PTR)"\t1b, 11b\n\t" \
666 STR(PTR)"\t2b, 11b\n\t" \
667 STR(PTR)"\t3b, 11b\n\t" \
668 STR(PTR)"\t4b, 11b\n\t" \
669 ".previous" \
670 : "=&r" (value), "=r" (res) \
Markos Chandras3563c322015-03-09 14:54:51 +0000671 : "r" (addr), "i" (-EFAULT)); \
672} while(0)
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000673
Markos Chandraseeb53892015-03-09 14:54:50 +0000674#define _LoadDW(addr, value, res) \
Markos Chandras3563c322015-03-09 14:54:51 +0000675do { \
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000676 __asm__ __volatile__ ( \
677 ".set\tpush\n\t" \
678 ".set\tnoat\n\t" \
679 "1:lb\t%0, 7(%2)\n\t" \
680 "2:lbu\t$1, 6(%2)\n\t" \
681 "dsll\t%0, 0x8\n\t" \
682 "or\t%0, $1\n\t" \
683 "3:lbu\t$1, 5(%2)\n\t" \
684 "dsll\t%0, 0x8\n\t" \
685 "or\t%0, $1\n\t" \
686 "4:lbu\t$1, 4(%2)\n\t" \
687 "dsll\t%0, 0x8\n\t" \
688 "or\t%0, $1\n\t" \
689 "5:lbu\t$1, 3(%2)\n\t" \
690 "dsll\t%0, 0x8\n\t" \
691 "or\t%0, $1\n\t" \
692 "6:lbu\t$1, 2(%2)\n\t" \
693 "dsll\t%0, 0x8\n\t" \
694 "or\t%0, $1\n\t" \
695 "7:lbu\t$1, 1(%2)\n\t" \
696 "dsll\t%0, 0x8\n\t" \
697 "or\t%0, $1\n\t" \
698 "8:lbu\t$1, 0(%2)\n\t" \
699 "dsll\t%0, 0x8\n\t" \
700 "or\t%0, $1\n\t" \
701 "li\t%1, 0\n" \
702 ".set\tpop\n\t" \
703 "10:\n\t" \
704 ".insn\n\t" \
705 ".section\t.fixup,\"ax\"\n\t" \
706 "11:\tli\t%1, %3\n\t" \
707 "j\t10b\n\t" \
708 ".previous\n\t" \
709 ".section\t__ex_table,\"a\"\n\t" \
710 STR(PTR)"\t1b, 11b\n\t" \
711 STR(PTR)"\t2b, 11b\n\t" \
712 STR(PTR)"\t3b, 11b\n\t" \
713 STR(PTR)"\t4b, 11b\n\t" \
714 STR(PTR)"\t5b, 11b\n\t" \
715 STR(PTR)"\t6b, 11b\n\t" \
716 STR(PTR)"\t7b, 11b\n\t" \
717 STR(PTR)"\t8b, 11b\n\t" \
718 ".previous" \
719 : "=&r" (value), "=r" (res) \
Markos Chandras3563c322015-03-09 14:54:51 +0000720 : "r" (addr), "i" (-EFAULT)); \
721} while(0)
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000722#endif /* CONFIG_CPU_MIPSR6 */
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500723
Markos Chandraseeb53892015-03-09 14:54:50 +0000724#define _StoreHW(addr, value, res, type) \
Markos Chandras3563c322015-03-09 14:54:51 +0000725do { \
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500726 __asm__ __volatile__ ( \
727 ".set\tnoat\n" \
Markos Chandraseeb53892015-03-09 14:54:50 +0000728 "1:\t"type##_sb("%1", "0(%2)")"\n" \
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500729 "srl\t$1,%1, 0x8\n" \
Markos Chandraseeb53892015-03-09 14:54:50 +0000730 "2:\t"type##_sb("$1", "1(%2)")"\n" \
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500731 ".set\tat\n\t" \
732 "li\t%0, 0\n" \
733 "3:\n\t" \
734 ".insn\n\t" \
735 ".section\t.fixup,\"ax\"\n\t" \
736 "4:\tli\t%0, %3\n\t" \
737 "j\t3b\n\t" \
738 ".previous\n\t" \
739 ".section\t__ex_table,\"a\"\n\t" \
740 STR(PTR)"\t1b, 4b\n\t" \
741 STR(PTR)"\t2b, 4b\n\t" \
742 ".previous" \
743 : "=r" (res) \
Markos Chandras3563c322015-03-09 14:54:51 +0000744 : "r" (value), "r" (addr), "i" (-EFAULT));\
745} while(0)
746
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000747#ifndef CONFIG_CPU_MIPSR6
Markos Chandraseeb53892015-03-09 14:54:50 +0000748#define _StoreW(addr, value, res, type) \
Markos Chandras3563c322015-03-09 14:54:51 +0000749do { \
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500750 __asm__ __volatile__ ( \
Markos Chandraseeb53892015-03-09 14:54:50 +0000751 "1:\t"type##_swl("%1", "3(%2)")"\n" \
752 "2:\t"type##_swr("%1", "(%2)")"\n\t"\
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500753 "li\t%0, 0\n" \
754 "3:\n\t" \
755 ".insn\n\t" \
756 ".section\t.fixup,\"ax\"\n\t" \
757 "4:\tli\t%0, %3\n\t" \
758 "j\t3b\n\t" \
759 ".previous\n\t" \
760 ".section\t__ex_table,\"a\"\n\t" \
761 STR(PTR)"\t1b, 4b\n\t" \
762 STR(PTR)"\t2b, 4b\n\t" \
763 ".previous" \
764 : "=r" (res) \
Markos Chandras3563c322015-03-09 14:54:51 +0000765 : "r" (value), "r" (addr), "i" (-EFAULT)); \
766} while(0)
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500767
Markos Chandraseeb53892015-03-09 14:54:50 +0000768#define _StoreDW(addr, value, res) \
Markos Chandras3563c322015-03-09 14:54:51 +0000769do { \
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500770 __asm__ __volatile__ ( \
771 "1:\tsdl\t%1, 7(%2)\n" \
772 "2:\tsdr\t%1, (%2)\n\t" \
773 "li\t%0, 0\n" \
774 "3:\n\t" \
775 ".insn\n\t" \
776 ".section\t.fixup,\"ax\"\n\t" \
777 "4:\tli\t%0, %3\n\t" \
778 "j\t3b\n\t" \
779 ".previous\n\t" \
780 ".section\t__ex_table,\"a\"\n\t" \
781 STR(PTR)"\t1b, 4b\n\t" \
782 STR(PTR)"\t2b, 4b\n\t" \
783 ".previous" \
784 : "=r" (res) \
Markos Chandras3563c322015-03-09 14:54:51 +0000785 : "r" (value), "r" (addr), "i" (-EFAULT)); \
786} while(0)
787
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000788#else
789/* MIPSR6 has no swl and sdl instructions */
Markos Chandraseeb53892015-03-09 14:54:50 +0000790#define _StoreW(addr, value, res, type) \
Markos Chandras3563c322015-03-09 14:54:51 +0000791do { \
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000792 __asm__ __volatile__ ( \
793 ".set\tpush\n\t" \
794 ".set\tnoat\n\t" \
Markos Chandraseeb53892015-03-09 14:54:50 +0000795 "1:"type##_sb("%1", "0(%2)")"\n\t" \
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000796 "srl\t$1, %1, 0x8\n\t" \
Markos Chandraseeb53892015-03-09 14:54:50 +0000797 "2:"type##_sb("$1", "1(%2)")"\n\t" \
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000798 "srl\t$1, $1, 0x8\n\t" \
Markos Chandraseeb53892015-03-09 14:54:50 +0000799 "3:"type##_sb("$1", "2(%2)")"\n\t" \
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000800 "srl\t$1, $1, 0x8\n\t" \
Markos Chandraseeb53892015-03-09 14:54:50 +0000801 "4:"type##_sb("$1", "3(%2)")"\n\t" \
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000802 ".set\tpop\n\t" \
803 "li\t%0, 0\n" \
804 "10:\n\t" \
805 ".insn\n\t" \
806 ".section\t.fixup,\"ax\"\n\t" \
807 "11:\tli\t%0, %3\n\t" \
808 "j\t10b\n\t" \
809 ".previous\n\t" \
810 ".section\t__ex_table,\"a\"\n\t" \
811 STR(PTR)"\t1b, 11b\n\t" \
812 STR(PTR)"\t2b, 11b\n\t" \
813 STR(PTR)"\t3b, 11b\n\t" \
814 STR(PTR)"\t4b, 11b\n\t" \
815 ".previous" \
816 : "=&r" (res) \
817 : "r" (value), "r" (addr), "i" (-EFAULT) \
Markos Chandras3563c322015-03-09 14:54:51 +0000818 : "memory"); \
819} while(0)
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000820
Markos Chandraseeb53892015-03-09 14:54:50 +0000821#define _StoreDW(addr, value, res) \
Markos Chandras3563c322015-03-09 14:54:51 +0000822do { \
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000823 __asm__ __volatile__ ( \
824 ".set\tpush\n\t" \
825 ".set\tnoat\n\t" \
826 "1:sb\t%1, 0(%2)\n\t" \
827 "dsrl\t$1, %1, 0x8\n\t" \
828 "2:sb\t$1, 1(%2)\n\t" \
829 "dsrl\t$1, $1, 0x8\n\t" \
830 "3:sb\t$1, 2(%2)\n\t" \
831 "dsrl\t$1, $1, 0x8\n\t" \
832 "4:sb\t$1, 3(%2)\n\t" \
833 "dsrl\t$1, $1, 0x8\n\t" \
834 "5:sb\t$1, 4(%2)\n\t" \
835 "dsrl\t$1, $1, 0x8\n\t" \
836 "6:sb\t$1, 5(%2)\n\t" \
837 "dsrl\t$1, $1, 0x8\n\t" \
838 "7:sb\t$1, 6(%2)\n\t" \
839 "dsrl\t$1, $1, 0x8\n\t" \
840 "8:sb\t$1, 7(%2)\n\t" \
841 "dsrl\t$1, $1, 0x8\n\t" \
842 ".set\tpop\n\t" \
843 "li\t%0, 0\n" \
844 "10:\n\t" \
845 ".insn\n\t" \
846 ".section\t.fixup,\"ax\"\n\t" \
847 "11:\tli\t%0, %3\n\t" \
848 "j\t10b\n\t" \
849 ".previous\n\t" \
850 ".section\t__ex_table,\"a\"\n\t" \
851 STR(PTR)"\t1b, 11b\n\t" \
852 STR(PTR)"\t2b, 11b\n\t" \
853 STR(PTR)"\t3b, 11b\n\t" \
854 STR(PTR)"\t4b, 11b\n\t" \
855 STR(PTR)"\t5b, 11b\n\t" \
856 STR(PTR)"\t6b, 11b\n\t" \
857 STR(PTR)"\t7b, 11b\n\t" \
858 STR(PTR)"\t8b, 11b\n\t" \
859 ".previous" \
860 : "=&r" (res) \
861 : "r" (value), "r" (addr), "i" (-EFAULT) \
Markos Chandras3563c322015-03-09 14:54:51 +0000862 : "memory"); \
863} while(0)
864
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000865#endif /* CONFIG_CPU_MIPSR6 */
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500866#endif
867
Markos Chandraseeb53892015-03-09 14:54:50 +0000868#define LoadHWU(addr, value, res) _LoadHWU(addr, value, res, kernel)
869#define LoadHWUE(addr, value, res) _LoadHWU(addr, value, res, user)
870#define LoadWU(addr, value, res) _LoadWU(addr, value, res, kernel)
871#define LoadWUE(addr, value, res) _LoadWU(addr, value, res, user)
872#define LoadHW(addr, value, res) _LoadHW(addr, value, res, kernel)
873#define LoadHWE(addr, value, res) _LoadHW(addr, value, res, user)
874#define LoadW(addr, value, res) _LoadW(addr, value, res, kernel)
875#define LoadWE(addr, value, res) _LoadW(addr, value, res, user)
876#define LoadDW(addr, value, res) _LoadDW(addr, value, res)
877
878#define StoreHW(addr, value, res) _StoreHW(addr, value, res, kernel)
879#define StoreHWE(addr, value, res) _StoreHW(addr, value, res, user)
880#define StoreW(addr, value, res) _StoreW(addr, value, res, kernel)
881#define StoreWE(addr, value, res) _StoreW(addr, value, res, user)
882#define StoreDW(addr, value, res) _StoreDW(addr, value, res)
883
Ralf Baechle7f18f152007-07-29 09:16:19 +0100884static void emulate_load_store_insn(struct pt_regs *regs,
885 void __user *addr, unsigned int __user *pc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700886{
887 union mips_instruction insn;
888 unsigned long value;
889 unsigned int res;
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500890 unsigned long origpc;
891 unsigned long orig31;
Leonid Yegoshin102cedc2013-03-25 12:09:02 -0500892 void __user *fault_addr = NULL;
Leonid Yegoshinc1771212013-12-12 16:15:15 +0000893#ifdef CONFIG_EVA
894 mm_segment_t seg;
895#endif
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500896 origpc = (unsigned long)pc;
897 orig31 = regs->regs[31];
898
Peter Zijlstraa8b0ca12011-06-27 14:41:57 +0200899 perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, 0);
Deng-Cheng Zhu7f788d22010-10-12 19:37:21 +0800900
Linus Torvalds1da177e2005-04-16 15:20:36 -0700901 /*
902 * This load never faults.
903 */
Ralf Baechlefe00f942005-03-01 19:22:29 +0000904 __get_user(insn.word, pc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700905
906 switch (insn.i_format.opcode) {
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500907 /*
908 * These are instructions that a compiler doesn't generate. We
909 * can assume therefore that the code is MIPS-aware and
910 * really buggy. Emulating these instructions would break the
911 * semantics anyway.
912 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700913 case ll_op:
914 case lld_op:
915 case sc_op:
916 case scd_op:
917
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500918 /*
919 * For these instructions the only way to create an address
920 * error is an attempted access to kernel/supervisor address
921 * space.
922 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700923 case ldl_op:
924 case ldr_op:
925 case lwl_op:
926 case lwr_op:
927 case sdl_op:
928 case sdr_op:
929 case swl_op:
930 case swr_op:
931 case lb_op:
932 case lbu_op:
933 case sb_op:
934 goto sigbus;
935
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500936 /*
937 * The remaining opcodes are the ones that are really of
938 * interest.
939 */
Leonid Yegoshinc1771212013-12-12 16:15:15 +0000940#ifdef CONFIG_EVA
941 case spec3_op:
942 /*
943 * we can land here only from kernel accessing user memory,
944 * so we need to "switch" the address limit to user space, so
945 * address check can work properly.
946 */
947 seg = get_fs();
948 set_fs(USER_DS);
949 switch (insn.spec3_format.func) {
950 case lhe_op:
951 if (!access_ok(VERIFY_READ, addr, 2)) {
952 set_fs(seg);
953 goto sigbus;
954 }
Markos Chandraseeb53892015-03-09 14:54:50 +0000955 LoadHWE(addr, value, res);
Leonid Yegoshinc1771212013-12-12 16:15:15 +0000956 if (res) {
957 set_fs(seg);
958 goto fault;
959 }
960 compute_return_epc(regs);
961 regs->regs[insn.spec3_format.rt] = value;
962 break;
963 case lwe_op:
964 if (!access_ok(VERIFY_READ, addr, 4)) {
965 set_fs(seg);
966 goto sigbus;
967 }
Markos Chandraseeb53892015-03-09 14:54:50 +0000968 LoadWE(addr, value, res);
Leonid Yegoshinc1771212013-12-12 16:15:15 +0000969 if (res) {
970 set_fs(seg);
971 goto fault;
972 }
973 compute_return_epc(regs);
974 regs->regs[insn.spec3_format.rt] = value;
975 break;
976 case lhue_op:
977 if (!access_ok(VERIFY_READ, addr, 2)) {
978 set_fs(seg);
979 goto sigbus;
980 }
Markos Chandraseeb53892015-03-09 14:54:50 +0000981 LoadHWUE(addr, value, res);
Leonid Yegoshinc1771212013-12-12 16:15:15 +0000982 if (res) {
983 set_fs(seg);
984 goto fault;
985 }
986 compute_return_epc(regs);
987 regs->regs[insn.spec3_format.rt] = value;
988 break;
989 case she_op:
990 if (!access_ok(VERIFY_WRITE, addr, 2)) {
991 set_fs(seg);
992 goto sigbus;
993 }
994 compute_return_epc(regs);
995 value = regs->regs[insn.spec3_format.rt];
Markos Chandraseeb53892015-03-09 14:54:50 +0000996 StoreHWE(addr, value, res);
Leonid Yegoshinc1771212013-12-12 16:15:15 +0000997 if (res) {
998 set_fs(seg);
999 goto fault;
1000 }
1001 break;
1002 case swe_op:
1003 if (!access_ok(VERIFY_WRITE, addr, 4)) {
1004 set_fs(seg);
1005 goto sigbus;
1006 }
1007 compute_return_epc(regs);
1008 value = regs->regs[insn.spec3_format.rt];
Markos Chandraseeb53892015-03-09 14:54:50 +00001009 StoreWE(addr, value, res);
Leonid Yegoshinc1771212013-12-12 16:15:15 +00001010 if (res) {
1011 set_fs(seg);
1012 goto fault;
1013 }
1014 break;
1015 default:
1016 set_fs(seg);
1017 goto sigill;
1018 }
1019 set_fs(seg);
1020 break;
1021#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001022 case lh_op:
1023 if (!access_ok(VERIFY_READ, addr, 2))
1024 goto sigbus;
1025
Markos Chandras6eae3542015-03-09 14:54:52 +00001026 if (config_enabled(CONFIG_EVA)) {
1027 if (segment_eq(get_fs(), get_ds()))
1028 LoadHW(addr, value, res);
1029 else
1030 LoadHWE(addr, value, res);
1031 } else {
1032 LoadHW(addr, value, res);
1033 }
1034
Linus Torvalds1da177e2005-04-16 15:20:36 -07001035 if (res)
1036 goto fault;
Ralf Baechle7f18f152007-07-29 09:16:19 +01001037 compute_return_epc(regs);
1038 regs->regs[insn.i_format.rt] = value;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001039 break;
1040
1041 case lw_op:
1042 if (!access_ok(VERIFY_READ, addr, 4))
1043 goto sigbus;
1044
Markos Chandras6eae3542015-03-09 14:54:52 +00001045 if (config_enabled(CONFIG_EVA)) {
1046 if (segment_eq(get_fs(), get_ds()))
1047 LoadW(addr, value, res);
1048 else
1049 LoadWE(addr, value, res);
1050 } else {
1051 LoadW(addr, value, res);
1052 }
1053
Linus Torvalds1da177e2005-04-16 15:20:36 -07001054 if (res)
1055 goto fault;
Ralf Baechle7f18f152007-07-29 09:16:19 +01001056 compute_return_epc(regs);
1057 regs->regs[insn.i_format.rt] = value;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001058 break;
1059
1060 case lhu_op:
1061 if (!access_ok(VERIFY_READ, addr, 2))
1062 goto sigbus;
1063
Markos Chandras6eae3542015-03-09 14:54:52 +00001064 if (config_enabled(CONFIG_EVA)) {
1065 if (segment_eq(get_fs(), get_ds()))
1066 LoadHWU(addr, value, res);
1067 else
1068 LoadHWUE(addr, value, res);
1069 } else {
1070 LoadHWU(addr, value, res);
1071 }
1072
Linus Torvalds1da177e2005-04-16 15:20:36 -07001073 if (res)
1074 goto fault;
Ralf Baechle7f18f152007-07-29 09:16:19 +01001075 compute_return_epc(regs);
1076 regs->regs[insn.i_format.rt] = value;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001077 break;
1078
1079 case lwu_op:
Ralf Baechle875d43e2005-09-03 15:56:16 -07001080#ifdef CONFIG_64BIT
Linus Torvalds1da177e2005-04-16 15:20:36 -07001081 /*
1082 * A 32-bit kernel might be running on a 64-bit processor. But
1083 * if we're on a 32-bit processor and an i-cache incoherency
1084 * or race makes us see a 64-bit instruction here the sdl/sdr
1085 * would blow up, so for now we don't handle unaligned 64-bit
1086 * instructions on 32-bit kernels.
1087 */
1088 if (!access_ok(VERIFY_READ, addr, 4))
1089 goto sigbus;
1090
Leonid Yegoshin34c2f662013-03-25 13:18:07 -05001091 LoadWU(addr, value, res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001092 if (res)
1093 goto fault;
Ralf Baechle7f18f152007-07-29 09:16:19 +01001094 compute_return_epc(regs);
1095 regs->regs[insn.i_format.rt] = value;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001096 break;
Ralf Baechle875d43e2005-09-03 15:56:16 -07001097#endif /* CONFIG_64BIT */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001098
1099 /* Cannot handle 64-bit instructions in 32-bit kernel */
1100 goto sigill;
1101
1102 case ld_op:
Ralf Baechle875d43e2005-09-03 15:56:16 -07001103#ifdef CONFIG_64BIT
Linus Torvalds1da177e2005-04-16 15:20:36 -07001104 /*
1105 * A 32-bit kernel might be running on a 64-bit processor. But
1106 * if we're on a 32-bit processor and an i-cache incoherency
1107 * or race makes us see a 64-bit instruction here the sdl/sdr
1108 * would blow up, so for now we don't handle unaligned 64-bit
1109 * instructions on 32-bit kernels.
1110 */
1111 if (!access_ok(VERIFY_READ, addr, 8))
1112 goto sigbus;
1113
Leonid Yegoshin34c2f662013-03-25 13:18:07 -05001114 LoadDW(addr, value, res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001115 if (res)
1116 goto fault;
Ralf Baechle7f18f152007-07-29 09:16:19 +01001117 compute_return_epc(regs);
1118 regs->regs[insn.i_format.rt] = value;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001119 break;
Ralf Baechle875d43e2005-09-03 15:56:16 -07001120#endif /* CONFIG_64BIT */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001121
1122 /* Cannot handle 64-bit instructions in 32-bit kernel */
1123 goto sigill;
1124
1125 case sh_op:
1126 if (!access_ok(VERIFY_WRITE, addr, 2))
1127 goto sigbus;
1128
Leonid Yegoshin34c2f662013-03-25 13:18:07 -05001129 compute_return_epc(regs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001130 value = regs->regs[insn.i_format.rt];
Markos Chandras6eae3542015-03-09 14:54:52 +00001131
1132 if (config_enabled(CONFIG_EVA)) {
1133 if (segment_eq(get_fs(), get_ds()))
1134 StoreHW(addr, value, res);
1135 else
1136 StoreHWE(addr, value, res);
1137 } else {
1138 StoreHW(addr, value, res);
1139 }
1140
Linus Torvalds1da177e2005-04-16 15:20:36 -07001141 if (res)
1142 goto fault;
1143 break;
1144
1145 case sw_op:
1146 if (!access_ok(VERIFY_WRITE, addr, 4))
1147 goto sigbus;
1148
Leonid Yegoshin34c2f662013-03-25 13:18:07 -05001149 compute_return_epc(regs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001150 value = regs->regs[insn.i_format.rt];
Markos Chandras6eae3542015-03-09 14:54:52 +00001151
1152 if (config_enabled(CONFIG_EVA)) {
1153 if (segment_eq(get_fs(), get_ds()))
1154 StoreW(addr, value, res);
1155 else
1156 StoreWE(addr, value, res);
1157 } else {
1158 StoreW(addr, value, res);
1159 }
1160
Linus Torvalds1da177e2005-04-16 15:20:36 -07001161 if (res)
1162 goto fault;
1163 break;
1164
1165 case sd_op:
Ralf Baechle875d43e2005-09-03 15:56:16 -07001166#ifdef CONFIG_64BIT
Linus Torvalds1da177e2005-04-16 15:20:36 -07001167 /*
1168 * A 32-bit kernel might be running on a 64-bit processor. But
1169 * if we're on a 32-bit processor and an i-cache incoherency
1170 * or race makes us see a 64-bit instruction here the sdl/sdr
1171 * would blow up, so for now we don't handle unaligned 64-bit
1172 * instructions on 32-bit kernels.
1173 */
1174 if (!access_ok(VERIFY_WRITE, addr, 8))
1175 goto sigbus;
1176
Leonid Yegoshin34c2f662013-03-25 13:18:07 -05001177 compute_return_epc(regs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001178 value = regs->regs[insn.i_format.rt];
Leonid Yegoshin34c2f662013-03-25 13:18:07 -05001179 StoreDW(addr, value, res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001180 if (res)
1181 goto fault;
1182 break;
Ralf Baechle875d43e2005-09-03 15:56:16 -07001183#endif /* CONFIG_64BIT */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001184
1185 /* Cannot handle 64-bit instructions in 32-bit kernel */
1186 goto sigill;
1187
1188 case lwc1_op:
1189 case ldc1_op:
1190 case swc1_op:
1191 case sdc1_op:
Leonid Yegoshin102cedc2013-03-25 12:09:02 -05001192 die_if_kernel("Unaligned FP access in kernel code", regs);
1193 BUG_ON(!used_math());
Leonid Yegoshin102cedc2013-03-25 12:09:02 -05001194
1195 lose_fpu(1); /* Save FPU state for the emulator. */
1196 res = fpu_emulator_cop1Handler(regs, &current->thread.fpu, 1,
1197 &fault_addr);
1198 own_fpu(1); /* Restore FPU state. */
1199
1200 /* Signal if something went wrong. */
1201 process_fpemu_return(res, fault_addr);
1202
1203 if (res == 0)
1204 break;
1205 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001206
Leonid Yegoshin0593a442014-10-28 10:42:23 +00001207#ifndef CONFIG_CPU_MIPSR6
Ralf Baechle69f3a7d2009-11-24 01:24:58 +00001208 /*
1209 * COP2 is available to implementor for application specific use.
1210 * It's up to applications to register a notifier chain and do
1211 * whatever they have to do, including possible sending of signals.
Leonid Yegoshin0593a442014-10-28 10:42:23 +00001212 *
1213 * This instruction has been reallocated in Release 6
Ralf Baechle69f3a7d2009-11-24 01:24:58 +00001214 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001215 case lwc2_op:
Ralf Baechle69f3a7d2009-11-24 01:24:58 +00001216 cu2_notifier_call_chain(CU2_LWC2_OP, regs);
1217 break;
1218
Linus Torvalds1da177e2005-04-16 15:20:36 -07001219 case ldc2_op:
Ralf Baechle69f3a7d2009-11-24 01:24:58 +00001220 cu2_notifier_call_chain(CU2_LDC2_OP, regs);
1221 break;
1222
Linus Torvalds1da177e2005-04-16 15:20:36 -07001223 case swc2_op:
Ralf Baechle69f3a7d2009-11-24 01:24:58 +00001224 cu2_notifier_call_chain(CU2_SWC2_OP, regs);
1225 break;
1226
Linus Torvalds1da177e2005-04-16 15:20:36 -07001227 case sdc2_op:
Ralf Baechle69f3a7d2009-11-24 01:24:58 +00001228 cu2_notifier_call_chain(CU2_SDC2_OP, regs);
1229 break;
Leonid Yegoshin0593a442014-10-28 10:42:23 +00001230#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001231 default:
1232 /*
1233 * Pheeee... We encountered an yet unknown instruction or
1234 * cache coherence problem. Die sucker, die ...
1235 */
1236 goto sigill;
1237 }
1238
Atsushi Nemoto6312e0e2007-06-30 00:55:48 +09001239#ifdef CONFIG_DEBUG_FS
Linus Torvalds1da177e2005-04-16 15:20:36 -07001240 unaligned_instructions++;
1241#endif
1242
Ralf Baechle7f18f152007-07-29 09:16:19 +01001243 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001244
1245fault:
Leonid Yegoshin34c2f662013-03-25 13:18:07 -05001246 /* roll back jump/branch */
1247 regs->cp0_epc = origpc;
1248 regs->regs[31] = orig31;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001249 /* Did we have an exception handler installed? */
1250 if (fixup_exception(regs))
Ralf Baechle7f18f152007-07-29 09:16:19 +01001251 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001252
Ralf Baechle49a89ef2007-10-11 23:46:15 +01001253 die_if_kernel("Unhandled kernel unaligned access", regs);
David Daneya6d5ff02009-05-05 12:49:47 -07001254 force_sig(SIGSEGV, current);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001255
Ralf Baechle7f18f152007-07-29 09:16:19 +01001256 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001257
1258sigbus:
1259 die_if_kernel("Unhandled kernel unaligned access", regs);
David Daneya6d5ff02009-05-05 12:49:47 -07001260 force_sig(SIGBUS, current);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001261
Ralf Baechle7f18f152007-07-29 09:16:19 +01001262 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001263
1264sigill:
Leonid Yegoshin34c2f662013-03-25 13:18:07 -05001265 die_if_kernel
1266 ("Unhandled kernel unaligned access or invalid instruction", regs);
1267 force_sig(SIGILL, current);
1268}
1269
1270/* Recode table from 16-bit register notation to 32-bit GPR. */
1271const int reg16to32[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
1272
1273/* Recode table from 16-bit STORE register notation to 32-bit GPR. */
1274const int reg16to32st[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
1275
David Daney74338802013-05-24 20:54:08 +00001276static void emulate_load_store_microMIPS(struct pt_regs *regs,
1277 void __user *addr)
Leonid Yegoshin34c2f662013-03-25 13:18:07 -05001278{
1279 unsigned long value;
1280 unsigned int res;
1281 int i;
1282 unsigned int reg = 0, rvar;
1283 unsigned long orig31;
1284 u16 __user *pc16;
1285 u16 halfword;
1286 unsigned int word;
1287 unsigned long origpc, contpc;
1288 union mips_instruction insn;
1289 struct mm_decoded_insn mminsn;
1290 void __user *fault_addr = NULL;
1291
1292 origpc = regs->cp0_epc;
1293 orig31 = regs->regs[31];
1294
1295 mminsn.micro_mips_mode = 1;
1296
1297 /*
1298 * This load never faults.
1299 */
1300 pc16 = (unsigned short __user *)msk_isa16_mode(regs->cp0_epc);
1301 __get_user(halfword, pc16);
1302 pc16++;
1303 contpc = regs->cp0_epc + 2;
1304 word = ((unsigned int)halfword << 16);
1305 mminsn.pc_inc = 2;
1306
1307 if (!mm_insn_16bit(halfword)) {
1308 __get_user(halfword, pc16);
1309 pc16++;
1310 contpc = regs->cp0_epc + 4;
1311 mminsn.pc_inc = 4;
1312 word |= halfword;
1313 }
1314 mminsn.insn = word;
1315
1316 if (get_user(halfword, pc16))
1317 goto fault;
1318 mminsn.next_pc_inc = 2;
1319 word = ((unsigned int)halfword << 16);
1320
1321 if (!mm_insn_16bit(halfword)) {
1322 pc16++;
1323 if (get_user(halfword, pc16))
1324 goto fault;
1325 mminsn.next_pc_inc = 4;
1326 word |= halfword;
1327 }
1328 mminsn.next_insn = word;
1329
1330 insn = (union mips_instruction)(mminsn.insn);
1331 if (mm_isBranchInstr(regs, mminsn, &contpc))
1332 insn = (union mips_instruction)(mminsn.next_insn);
1333
1334 /* Parse instruction to find what to do */
1335
1336 switch (insn.mm_i_format.opcode) {
1337
1338 case mm_pool32a_op:
1339 switch (insn.mm_x_format.func) {
1340 case mm_lwxs_op:
1341 reg = insn.mm_x_format.rd;
1342 goto loadW;
1343 }
1344
1345 goto sigbus;
1346
1347 case mm_pool32b_op:
1348 switch (insn.mm_m_format.func) {
1349 case mm_lwp_func:
1350 reg = insn.mm_m_format.rd;
1351 if (reg == 31)
1352 goto sigbus;
1353
1354 if (!access_ok(VERIFY_READ, addr, 8))
1355 goto sigbus;
1356
1357 LoadW(addr, value, res);
1358 if (res)
1359 goto fault;
1360 regs->regs[reg] = value;
1361 addr += 4;
1362 LoadW(addr, value, res);
1363 if (res)
1364 goto fault;
1365 regs->regs[reg + 1] = value;
1366 goto success;
1367
1368 case mm_swp_func:
1369 reg = insn.mm_m_format.rd;
1370 if (reg == 31)
1371 goto sigbus;
1372
1373 if (!access_ok(VERIFY_WRITE, addr, 8))
1374 goto sigbus;
1375
1376 value = regs->regs[reg];
1377 StoreW(addr, value, res);
1378 if (res)
1379 goto fault;
1380 addr += 4;
1381 value = regs->regs[reg + 1];
1382 StoreW(addr, value, res);
1383 if (res)
1384 goto fault;
1385 goto success;
1386
1387 case mm_ldp_func:
1388#ifdef CONFIG_64BIT
1389 reg = insn.mm_m_format.rd;
1390 if (reg == 31)
1391 goto sigbus;
1392
1393 if (!access_ok(VERIFY_READ, addr, 16))
1394 goto sigbus;
1395
1396 LoadDW(addr, value, res);
1397 if (res)
1398 goto fault;
1399 regs->regs[reg] = value;
1400 addr += 8;
1401 LoadDW(addr, value, res);
1402 if (res)
1403 goto fault;
1404 regs->regs[reg + 1] = value;
1405 goto success;
1406#endif /* CONFIG_64BIT */
1407
1408 goto sigill;
1409
1410 case mm_sdp_func:
1411#ifdef CONFIG_64BIT
1412 reg = insn.mm_m_format.rd;
1413 if (reg == 31)
1414 goto sigbus;
1415
1416 if (!access_ok(VERIFY_WRITE, addr, 16))
1417 goto sigbus;
1418
1419 value = regs->regs[reg];
1420 StoreDW(addr, value, res);
1421 if (res)
1422 goto fault;
1423 addr += 8;
1424 value = regs->regs[reg + 1];
1425 StoreDW(addr, value, res);
1426 if (res)
1427 goto fault;
1428 goto success;
1429#endif /* CONFIG_64BIT */
1430
1431 goto sigill;
1432
1433 case mm_lwm32_func:
1434 reg = insn.mm_m_format.rd;
1435 rvar = reg & 0xf;
1436 if ((rvar > 9) || !reg)
1437 goto sigill;
1438 if (reg & 0x10) {
1439 if (!access_ok
1440 (VERIFY_READ, addr, 4 * (rvar + 1)))
1441 goto sigbus;
1442 } else {
1443 if (!access_ok(VERIFY_READ, addr, 4 * rvar))
1444 goto sigbus;
1445 }
1446 if (rvar == 9)
1447 rvar = 8;
1448 for (i = 16; rvar; rvar--, i++) {
1449 LoadW(addr, value, res);
1450 if (res)
1451 goto fault;
1452 addr += 4;
1453 regs->regs[i] = value;
1454 }
1455 if ((reg & 0xf) == 9) {
1456 LoadW(addr, value, res);
1457 if (res)
1458 goto fault;
1459 addr += 4;
1460 regs->regs[30] = value;
1461 }
1462 if (reg & 0x10) {
1463 LoadW(addr, value, res);
1464 if (res)
1465 goto fault;
1466 regs->regs[31] = value;
1467 }
1468 goto success;
1469
1470 case mm_swm32_func:
1471 reg = insn.mm_m_format.rd;
1472 rvar = reg & 0xf;
1473 if ((rvar > 9) || !reg)
1474 goto sigill;
1475 if (reg & 0x10) {
1476 if (!access_ok
1477 (VERIFY_WRITE, addr, 4 * (rvar + 1)))
1478 goto sigbus;
1479 } else {
1480 if (!access_ok(VERIFY_WRITE, addr, 4 * rvar))
1481 goto sigbus;
1482 }
1483 if (rvar == 9)
1484 rvar = 8;
1485 for (i = 16; rvar; rvar--, i++) {
1486 value = regs->regs[i];
1487 StoreW(addr, value, res);
1488 if (res)
1489 goto fault;
1490 addr += 4;
1491 }
1492 if ((reg & 0xf) == 9) {
1493 value = regs->regs[30];
1494 StoreW(addr, value, res);
1495 if (res)
1496 goto fault;
1497 addr += 4;
1498 }
1499 if (reg & 0x10) {
1500 value = regs->regs[31];
1501 StoreW(addr, value, res);
1502 if (res)
1503 goto fault;
1504 }
1505 goto success;
1506
1507 case mm_ldm_func:
1508#ifdef CONFIG_64BIT
1509 reg = insn.mm_m_format.rd;
1510 rvar = reg & 0xf;
1511 if ((rvar > 9) || !reg)
1512 goto sigill;
1513 if (reg & 0x10) {
1514 if (!access_ok
1515 (VERIFY_READ, addr, 8 * (rvar + 1)))
1516 goto sigbus;
1517 } else {
1518 if (!access_ok(VERIFY_READ, addr, 8 * rvar))
1519 goto sigbus;
1520 }
1521 if (rvar == 9)
1522 rvar = 8;
1523
1524 for (i = 16; rvar; rvar--, i++) {
1525 LoadDW(addr, value, res);
1526 if (res)
1527 goto fault;
1528 addr += 4;
1529 regs->regs[i] = value;
1530 }
1531 if ((reg & 0xf) == 9) {
1532 LoadDW(addr, value, res);
1533 if (res)
1534 goto fault;
1535 addr += 8;
1536 regs->regs[30] = value;
1537 }
1538 if (reg & 0x10) {
1539 LoadDW(addr, value, res);
1540 if (res)
1541 goto fault;
1542 regs->regs[31] = value;
1543 }
1544 goto success;
1545#endif /* CONFIG_64BIT */
1546
1547 goto sigill;
1548
1549 case mm_sdm_func:
1550#ifdef CONFIG_64BIT
1551 reg = insn.mm_m_format.rd;
1552 rvar = reg & 0xf;
1553 if ((rvar > 9) || !reg)
1554 goto sigill;
1555 if (reg & 0x10) {
1556 if (!access_ok
1557 (VERIFY_WRITE, addr, 8 * (rvar + 1)))
1558 goto sigbus;
1559 } else {
1560 if (!access_ok(VERIFY_WRITE, addr, 8 * rvar))
1561 goto sigbus;
1562 }
1563 if (rvar == 9)
1564 rvar = 8;
1565
1566 for (i = 16; rvar; rvar--, i++) {
1567 value = regs->regs[i];
1568 StoreDW(addr, value, res);
1569 if (res)
1570 goto fault;
1571 addr += 8;
1572 }
1573 if ((reg & 0xf) == 9) {
1574 value = regs->regs[30];
1575 StoreDW(addr, value, res);
1576 if (res)
1577 goto fault;
1578 addr += 8;
1579 }
1580 if (reg & 0x10) {
1581 value = regs->regs[31];
1582 StoreDW(addr, value, res);
1583 if (res)
1584 goto fault;
1585 }
1586 goto success;
1587#endif /* CONFIG_64BIT */
1588
1589 goto sigill;
1590
1591 /* LWC2, SWC2, LDC2, SDC2 are not serviced */
1592 }
1593
1594 goto sigbus;
1595
1596 case mm_pool32c_op:
1597 switch (insn.mm_m_format.func) {
1598 case mm_lwu_func:
1599 reg = insn.mm_m_format.rd;
1600 goto loadWU;
1601 }
1602
1603 /* LL,SC,LLD,SCD are not serviced */
1604 goto sigbus;
1605
1606 case mm_pool32f_op:
1607 switch (insn.mm_x_format.func) {
1608 case mm_lwxc1_func:
1609 case mm_swxc1_func:
1610 case mm_ldxc1_func:
1611 case mm_sdxc1_func:
1612 goto fpu_emul;
1613 }
1614
1615 goto sigbus;
1616
1617 case mm_ldc132_op:
1618 case mm_sdc132_op:
1619 case mm_lwc132_op:
1620 case mm_swc132_op:
1621fpu_emul:
1622 /* roll back jump/branch */
1623 regs->cp0_epc = origpc;
1624 regs->regs[31] = orig31;
1625
1626 die_if_kernel("Unaligned FP access in kernel code", regs);
1627 BUG_ON(!used_math());
1628 BUG_ON(!is_fpu_owner());
1629
1630 lose_fpu(1); /* save the FPU state for the emulator */
1631 res = fpu_emulator_cop1Handler(regs, &current->thread.fpu, 1,
1632 &fault_addr);
1633 own_fpu(1); /* restore FPU state */
1634
1635 /* If something went wrong, signal */
1636 process_fpemu_return(res, fault_addr);
1637
1638 if (res == 0)
1639 goto success;
1640 return;
1641
1642 case mm_lh32_op:
1643 reg = insn.mm_i_format.rt;
1644 goto loadHW;
1645
1646 case mm_lhu32_op:
1647 reg = insn.mm_i_format.rt;
1648 goto loadHWU;
1649
1650 case mm_lw32_op:
1651 reg = insn.mm_i_format.rt;
1652 goto loadW;
1653
1654 case mm_sh32_op:
1655 reg = insn.mm_i_format.rt;
1656 goto storeHW;
1657
1658 case mm_sw32_op:
1659 reg = insn.mm_i_format.rt;
1660 goto storeW;
1661
1662 case mm_ld32_op:
1663 reg = insn.mm_i_format.rt;
1664 goto loadDW;
1665
1666 case mm_sd32_op:
1667 reg = insn.mm_i_format.rt;
1668 goto storeDW;
1669
1670 case mm_pool16c_op:
1671 switch (insn.mm16_m_format.func) {
1672 case mm_lwm16_op:
1673 reg = insn.mm16_m_format.rlist;
1674 rvar = reg + 1;
1675 if (!access_ok(VERIFY_READ, addr, 4 * rvar))
1676 goto sigbus;
1677
1678 for (i = 16; rvar; rvar--, i++) {
1679 LoadW(addr, value, res);
1680 if (res)
1681 goto fault;
1682 addr += 4;
1683 regs->regs[i] = value;
1684 }
1685 LoadW(addr, value, res);
1686 if (res)
1687 goto fault;
1688 regs->regs[31] = value;
1689
1690 goto success;
1691
1692 case mm_swm16_op:
1693 reg = insn.mm16_m_format.rlist;
1694 rvar = reg + 1;
1695 if (!access_ok(VERIFY_WRITE, addr, 4 * rvar))
1696 goto sigbus;
1697
1698 for (i = 16; rvar; rvar--, i++) {
1699 value = regs->regs[i];
1700 StoreW(addr, value, res);
1701 if (res)
1702 goto fault;
1703 addr += 4;
1704 }
1705 value = regs->regs[31];
1706 StoreW(addr, value, res);
1707 if (res)
1708 goto fault;
1709
1710 goto success;
1711
1712 }
1713
1714 goto sigbus;
1715
1716 case mm_lhu16_op:
1717 reg = reg16to32[insn.mm16_rb_format.rt];
1718 goto loadHWU;
1719
1720 case mm_lw16_op:
1721 reg = reg16to32[insn.mm16_rb_format.rt];
1722 goto loadW;
1723
1724 case mm_sh16_op:
1725 reg = reg16to32st[insn.mm16_rb_format.rt];
1726 goto storeHW;
1727
1728 case mm_sw16_op:
1729 reg = reg16to32st[insn.mm16_rb_format.rt];
1730 goto storeW;
1731
1732 case mm_lwsp16_op:
1733 reg = insn.mm16_r5_format.rt;
1734 goto loadW;
1735
1736 case mm_swsp16_op:
1737 reg = insn.mm16_r5_format.rt;
1738 goto storeW;
1739
1740 case mm_lwgp16_op:
1741 reg = reg16to32[insn.mm16_r3_format.rt];
1742 goto loadW;
1743
1744 default:
1745 goto sigill;
1746 }
1747
1748loadHW:
1749 if (!access_ok(VERIFY_READ, addr, 2))
1750 goto sigbus;
1751
1752 LoadHW(addr, value, res);
1753 if (res)
1754 goto fault;
1755 regs->regs[reg] = value;
1756 goto success;
1757
1758loadHWU:
1759 if (!access_ok(VERIFY_READ, addr, 2))
1760 goto sigbus;
1761
1762 LoadHWU(addr, value, res);
1763 if (res)
1764 goto fault;
1765 regs->regs[reg] = value;
1766 goto success;
1767
1768loadW:
1769 if (!access_ok(VERIFY_READ, addr, 4))
1770 goto sigbus;
1771
1772 LoadW(addr, value, res);
1773 if (res)
1774 goto fault;
1775 regs->regs[reg] = value;
1776 goto success;
1777
1778loadWU:
1779#ifdef CONFIG_64BIT
1780 /*
1781 * A 32-bit kernel might be running on a 64-bit processor. But
1782 * if we're on a 32-bit processor and an i-cache incoherency
1783 * or race makes us see a 64-bit instruction here the sdl/sdr
1784 * would blow up, so for now we don't handle unaligned 64-bit
1785 * instructions on 32-bit kernels.
1786 */
1787 if (!access_ok(VERIFY_READ, addr, 4))
1788 goto sigbus;
1789
1790 LoadWU(addr, value, res);
1791 if (res)
1792 goto fault;
1793 regs->regs[reg] = value;
1794 goto success;
1795#endif /* CONFIG_64BIT */
1796
1797 /* Cannot handle 64-bit instructions in 32-bit kernel */
1798 goto sigill;
1799
1800loadDW:
1801#ifdef CONFIG_64BIT
1802 /*
1803 * A 32-bit kernel might be running on a 64-bit processor. But
1804 * if we're on a 32-bit processor and an i-cache incoherency
1805 * or race makes us see a 64-bit instruction here the sdl/sdr
1806 * would blow up, so for now we don't handle unaligned 64-bit
1807 * instructions on 32-bit kernels.
1808 */
1809 if (!access_ok(VERIFY_READ, addr, 8))
1810 goto sigbus;
1811
1812 LoadDW(addr, value, res);
1813 if (res)
1814 goto fault;
1815 regs->regs[reg] = value;
1816 goto success;
1817#endif /* CONFIG_64BIT */
1818
1819 /* Cannot handle 64-bit instructions in 32-bit kernel */
1820 goto sigill;
1821
1822storeHW:
1823 if (!access_ok(VERIFY_WRITE, addr, 2))
1824 goto sigbus;
1825
1826 value = regs->regs[reg];
1827 StoreHW(addr, value, res);
1828 if (res)
1829 goto fault;
1830 goto success;
1831
1832storeW:
1833 if (!access_ok(VERIFY_WRITE, addr, 4))
1834 goto sigbus;
1835
1836 value = regs->regs[reg];
1837 StoreW(addr, value, res);
1838 if (res)
1839 goto fault;
1840 goto success;
1841
1842storeDW:
1843#ifdef CONFIG_64BIT
1844 /*
1845 * A 32-bit kernel might be running on a 64-bit processor. But
1846 * if we're on a 32-bit processor and an i-cache incoherency
1847 * or race makes us see a 64-bit instruction here the sdl/sdr
1848 * would blow up, so for now we don't handle unaligned 64-bit
1849 * instructions on 32-bit kernels.
1850 */
1851 if (!access_ok(VERIFY_WRITE, addr, 8))
1852 goto sigbus;
1853
1854 value = regs->regs[reg];
1855 StoreDW(addr, value, res);
1856 if (res)
1857 goto fault;
1858 goto success;
1859#endif /* CONFIG_64BIT */
1860
1861 /* Cannot handle 64-bit instructions in 32-bit kernel */
1862 goto sigill;
1863
1864success:
1865 regs->cp0_epc = contpc; /* advance or branch */
1866
1867#ifdef CONFIG_DEBUG_FS
1868 unaligned_instructions++;
1869#endif
1870 return;
1871
1872fault:
1873 /* roll back jump/branch */
1874 regs->cp0_epc = origpc;
1875 regs->regs[31] = orig31;
1876 /* Did we have an exception handler installed? */
1877 if (fixup_exception(regs))
1878 return;
1879
1880 die_if_kernel("Unhandled kernel unaligned access", regs);
1881 force_sig(SIGSEGV, current);
1882
1883 return;
1884
1885sigbus:
1886 die_if_kernel("Unhandled kernel unaligned access", regs);
1887 force_sig(SIGBUS, current);
1888
1889 return;
1890
1891sigill:
1892 die_if_kernel
1893 ("Unhandled kernel unaligned access or invalid instruction", regs);
David Daneya6d5ff02009-05-05 12:49:47 -07001894 force_sig(SIGILL, current);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001895}
1896
Steven J. Hill451b0012013-03-25 13:46:15 -05001897static void emulate_load_store_MIPS16e(struct pt_regs *regs, void __user * addr)
1898{
1899 unsigned long value;
1900 unsigned int res;
1901 int reg;
1902 unsigned long orig31;
1903 u16 __user *pc16;
1904 unsigned long origpc;
1905 union mips16e_instruction mips16inst, oldinst;
1906
1907 origpc = regs->cp0_epc;
1908 orig31 = regs->regs[31];
1909 pc16 = (unsigned short __user *)msk_isa16_mode(origpc);
1910 /*
1911 * This load never faults.
1912 */
1913 __get_user(mips16inst.full, pc16);
1914 oldinst = mips16inst;
1915
1916 /* skip EXTEND instruction */
1917 if (mips16inst.ri.opcode == MIPS16e_extend_op) {
1918 pc16++;
1919 __get_user(mips16inst.full, pc16);
1920 } else if (delay_slot(regs)) {
1921 /* skip jump instructions */
1922 /* JAL/JALX are 32 bits but have OPCODE in first short int */
1923 if (mips16inst.ri.opcode == MIPS16e_jal_op)
1924 pc16++;
1925 pc16++;
1926 if (get_user(mips16inst.full, pc16))
1927 goto sigbus;
1928 }
1929
1930 switch (mips16inst.ri.opcode) {
1931 case MIPS16e_i64_op: /* I64 or RI64 instruction */
1932 switch (mips16inst.i64.func) { /* I64/RI64 func field check */
1933 case MIPS16e_ldpc_func:
1934 case MIPS16e_ldsp_func:
1935 reg = reg16to32[mips16inst.ri64.ry];
1936 goto loadDW;
1937
1938 case MIPS16e_sdsp_func:
1939 reg = reg16to32[mips16inst.ri64.ry];
1940 goto writeDW;
1941
1942 case MIPS16e_sdrasp_func:
1943 reg = 29; /* GPRSP */
1944 goto writeDW;
1945 }
1946
1947 goto sigbus;
1948
1949 case MIPS16e_swsp_op:
1950 case MIPS16e_lwpc_op:
1951 case MIPS16e_lwsp_op:
1952 reg = reg16to32[mips16inst.ri.rx];
1953 break;
1954
1955 case MIPS16e_i8_op:
1956 if (mips16inst.i8.func != MIPS16e_swrasp_func)
1957 goto sigbus;
1958 reg = 29; /* GPRSP */
1959 break;
1960
1961 default:
1962 reg = reg16to32[mips16inst.rri.ry];
1963 break;
1964 }
1965
1966 switch (mips16inst.ri.opcode) {
1967
1968 case MIPS16e_lb_op:
1969 case MIPS16e_lbu_op:
1970 case MIPS16e_sb_op:
1971 goto sigbus;
1972
1973 case MIPS16e_lh_op:
1974 if (!access_ok(VERIFY_READ, addr, 2))
1975 goto sigbus;
1976
1977 LoadHW(addr, value, res);
1978 if (res)
1979 goto fault;
1980 MIPS16e_compute_return_epc(regs, &oldinst);
1981 regs->regs[reg] = value;
1982 break;
1983
1984 case MIPS16e_lhu_op:
1985 if (!access_ok(VERIFY_READ, addr, 2))
1986 goto sigbus;
1987
1988 LoadHWU(addr, value, res);
1989 if (res)
1990 goto fault;
1991 MIPS16e_compute_return_epc(regs, &oldinst);
1992 regs->regs[reg] = value;
1993 break;
1994
1995 case MIPS16e_lw_op:
1996 case MIPS16e_lwpc_op:
1997 case MIPS16e_lwsp_op:
1998 if (!access_ok(VERIFY_READ, addr, 4))
1999 goto sigbus;
2000
2001 LoadW(addr, value, res);
2002 if (res)
2003 goto fault;
2004 MIPS16e_compute_return_epc(regs, &oldinst);
2005 regs->regs[reg] = value;
2006 break;
2007
2008 case MIPS16e_lwu_op:
2009#ifdef CONFIG_64BIT
2010 /*
2011 * A 32-bit kernel might be running on a 64-bit processor. But
2012 * if we're on a 32-bit processor and an i-cache incoherency
2013 * or race makes us see a 64-bit instruction here the sdl/sdr
2014 * would blow up, so for now we don't handle unaligned 64-bit
2015 * instructions on 32-bit kernels.
2016 */
2017 if (!access_ok(VERIFY_READ, addr, 4))
2018 goto sigbus;
2019
2020 LoadWU(addr, value, res);
2021 if (res)
2022 goto fault;
2023 MIPS16e_compute_return_epc(regs, &oldinst);
2024 regs->regs[reg] = value;
2025 break;
2026#endif /* CONFIG_64BIT */
2027
2028 /* Cannot handle 64-bit instructions in 32-bit kernel */
2029 goto sigill;
2030
2031 case MIPS16e_ld_op:
2032loadDW:
2033#ifdef CONFIG_64BIT
2034 /*
2035 * A 32-bit kernel might be running on a 64-bit processor. But
2036 * if we're on a 32-bit processor and an i-cache incoherency
2037 * or race makes us see a 64-bit instruction here the sdl/sdr
2038 * would blow up, so for now we don't handle unaligned 64-bit
2039 * instructions on 32-bit kernels.
2040 */
2041 if (!access_ok(VERIFY_READ, addr, 8))
2042 goto sigbus;
2043
2044 LoadDW(addr, value, res);
2045 if (res)
2046 goto fault;
2047 MIPS16e_compute_return_epc(regs, &oldinst);
2048 regs->regs[reg] = value;
2049 break;
2050#endif /* CONFIG_64BIT */
2051
2052 /* Cannot handle 64-bit instructions in 32-bit kernel */
2053 goto sigill;
2054
2055 case MIPS16e_sh_op:
2056 if (!access_ok(VERIFY_WRITE, addr, 2))
2057 goto sigbus;
2058
2059 MIPS16e_compute_return_epc(regs, &oldinst);
2060 value = regs->regs[reg];
2061 StoreHW(addr, value, res);
2062 if (res)
2063 goto fault;
2064 break;
2065
2066 case MIPS16e_sw_op:
2067 case MIPS16e_swsp_op:
2068 case MIPS16e_i8_op: /* actually - MIPS16e_swrasp_func */
2069 if (!access_ok(VERIFY_WRITE, addr, 4))
2070 goto sigbus;
2071
2072 MIPS16e_compute_return_epc(regs, &oldinst);
2073 value = regs->regs[reg];
2074 StoreW(addr, value, res);
2075 if (res)
2076 goto fault;
2077 break;
2078
2079 case MIPS16e_sd_op:
2080writeDW:
2081#ifdef CONFIG_64BIT
2082 /*
2083 * A 32-bit kernel might be running on a 64-bit processor. But
2084 * if we're on a 32-bit processor and an i-cache incoherency
2085 * or race makes us see a 64-bit instruction here the sdl/sdr
2086 * would blow up, so for now we don't handle unaligned 64-bit
2087 * instructions on 32-bit kernels.
2088 */
2089 if (!access_ok(VERIFY_WRITE, addr, 8))
2090 goto sigbus;
2091
2092 MIPS16e_compute_return_epc(regs, &oldinst);
2093 value = regs->regs[reg];
2094 StoreDW(addr, value, res);
2095 if (res)
2096 goto fault;
2097 break;
2098#endif /* CONFIG_64BIT */
2099
2100 /* Cannot handle 64-bit instructions in 32-bit kernel */
2101 goto sigill;
2102
2103 default:
2104 /*
2105 * Pheeee... We encountered an yet unknown instruction or
2106 * cache coherence problem. Die sucker, die ...
2107 */
2108 goto sigill;
2109 }
2110
2111#ifdef CONFIG_DEBUG_FS
2112 unaligned_instructions++;
2113#endif
2114
2115 return;
2116
2117fault:
2118 /* roll back jump/branch */
2119 regs->cp0_epc = origpc;
2120 regs->regs[31] = orig31;
2121 /* Did we have an exception handler installed? */
2122 if (fixup_exception(regs))
2123 return;
2124
2125 die_if_kernel("Unhandled kernel unaligned access", regs);
2126 force_sig(SIGSEGV, current);
2127
2128 return;
2129
2130sigbus:
2131 die_if_kernel("Unhandled kernel unaligned access", regs);
2132 force_sig(SIGBUS, current);
2133
2134 return;
2135
2136sigill:
2137 die_if_kernel
2138 ("Unhandled kernel unaligned access or invalid instruction", regs);
2139 force_sig(SIGILL, current);
2140}
Tony Wufc192e52013-06-21 10:10:46 +00002141
Linus Torvalds1da177e2005-04-16 15:20:36 -07002142asmlinkage void do_ade(struct pt_regs *regs)
2143{
Ralf Baechlec3fc5cd2013-05-29 01:07:19 +02002144 enum ctx_state prev_state;
Ralf Baechlefe00f942005-03-01 19:22:29 +00002145 unsigned int __user *pc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002146 mm_segment_t seg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002147
Ralf Baechlec3fc5cd2013-05-29 01:07:19 +02002148 prev_state = exception_enter();
Deng-Cheng Zhu7f788d22010-10-12 19:37:21 +08002149 perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS,
Peter Zijlstraa8b0ca12011-06-27 14:41:57 +02002150 1, regs, regs->cp0_badvaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002151 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002152 * Did we catch a fault trying to load an instruction?
Linus Torvalds1da177e2005-04-16 15:20:36 -07002153 */
Leonid Yegoshin34c2f662013-03-25 13:18:07 -05002154 if (regs->cp0_badvaddr == regs->cp0_epc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002155 goto sigbus;
2156
Ralf Baechle293c5bd2007-07-25 16:19:33 +01002157 if (user_mode(regs) && !test_thread_flag(TIF_FIXADE))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002158 goto sigbus;
Atsushi Nemoto6312e0e2007-06-30 00:55:48 +09002159 if (unaligned_action == UNALIGNED_ACTION_SIGNAL)
2160 goto sigbus;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002161
2162 /*
2163 * Do branch emulation only if we didn't forward the exception.
2164 * This is all so but ugly ...
2165 */
Leonid Yegoshin34c2f662013-03-25 13:18:07 -05002166
2167 /*
2168 * Are we running in microMIPS mode?
2169 */
2170 if (get_isa16_mode(regs->cp0_epc)) {
2171 /*
2172 * Did we catch a fault trying to load an instruction in
2173 * 16-bit mode?
2174 */
2175 if (regs->cp0_badvaddr == msk_isa16_mode(regs->cp0_epc))
2176 goto sigbus;
2177 if (unaligned_action == UNALIGNED_ACTION_SHOW)
2178 show_registers(regs);
2179
2180 if (cpu_has_mmips) {
2181 seg = get_fs();
2182 if (!user_mode(regs))
2183 set_fs(KERNEL_DS);
2184 emulate_load_store_microMIPS(regs,
2185 (void __user *)regs->cp0_badvaddr);
2186 set_fs(seg);
2187
2188 return;
2189 }
2190
Steven J. Hill451b0012013-03-25 13:46:15 -05002191 if (cpu_has_mips16) {
2192 seg = get_fs();
2193 if (!user_mode(regs))
2194 set_fs(KERNEL_DS);
2195 emulate_load_store_MIPS16e(regs,
2196 (void __user *)regs->cp0_badvaddr);
2197 set_fs(seg);
2198
2199 return;
2200 }
2201
Leonid Yegoshin34c2f662013-03-25 13:18:07 -05002202 goto sigbus;
2203 }
2204
2205 if (unaligned_action == UNALIGNED_ACTION_SHOW)
2206 show_registers(regs);
2207 pc = (unsigned int __user *)exception_epc(regs);
2208
Linus Torvalds1da177e2005-04-16 15:20:36 -07002209 seg = get_fs();
2210 if (!user_mode(regs))
2211 set_fs(KERNEL_DS);
Ralf Baechle7f18f152007-07-29 09:16:19 +01002212 emulate_load_store_insn(regs, (void __user *)regs->cp0_badvaddr, pc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002213 set_fs(seg);
2214
2215 return;
2216
2217sigbus:
2218 die_if_kernel("Kernel unaligned instruction access", regs);
2219 force_sig(SIGBUS, current);
2220
2221 /*
2222 * XXX On return from the signal handler we should advance the epc
2223 */
Ralf Baechlec3fc5cd2013-05-29 01:07:19 +02002224 exception_exit(prev_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002225}
Atsushi Nemoto6312e0e2007-06-30 00:55:48 +09002226
2227#ifdef CONFIG_DEBUG_FS
2228extern struct dentry *mips_debugfs_dir;
2229static int __init debugfs_unaligned(void)
2230{
2231 struct dentry *d;
2232
2233 if (!mips_debugfs_dir)
2234 return -ENODEV;
2235 d = debugfs_create_u32("unaligned_instructions", S_IRUGO,
2236 mips_debugfs_dir, &unaligned_instructions);
Zhaoleib517531c2008-10-17 19:12:35 +08002237 if (!d)
2238 return -ENOMEM;
Atsushi Nemoto6312e0e2007-06-30 00:55:48 +09002239 d = debugfs_create_u32("unaligned_action", S_IRUGO | S_IWUSR,
2240 mips_debugfs_dir, &unaligned_action);
Zhaoleib517531c2008-10-17 19:12:35 +08002241 if (!d)
2242 return -ENOMEM;
Atsushi Nemoto6312e0e2007-06-30 00:55:48 +09002243 return 0;
2244}
2245__initcall(debugfs_unaligned);
2246#endif