blob: eb3efd137fd17cdb6e1defa163744a480ad16185 [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>
Linus Torvalds1da177e2005-04-16 15:20:36 -070092
Ralf Baechle70342282013-01-22 12:59:30 +010093#define STR(x) __STR(x)
Linus Torvalds1da177e2005-04-16 15:20:36 -070094#define __STR(x) #x
95
Atsushi Nemoto6312e0e2007-06-30 00:55:48 +090096enum {
97 UNALIGNED_ACTION_QUIET,
98 UNALIGNED_ACTION_SIGNAL,
99 UNALIGNED_ACTION_SHOW,
100};
101#ifdef CONFIG_DEBUG_FS
102static u32 unaligned_instructions;
103static u32 unaligned_action;
104#else
105#define unaligned_action UNALIGNED_ACTION_QUIET
Linus Torvalds1da177e2005-04-16 15:20:36 -0700106#endif
Atsushi Nemoto6312e0e2007-06-30 00:55:48 +0900107extern void show_registers(struct pt_regs *regs);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700108
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500109#ifdef __BIG_ENDIAN
Markos Chandraseeb53892015-03-09 14:54:50 +0000110#define _LoadHW(addr, value, res, type) \
Markos Chandras3563c322015-03-09 14:54:51 +0000111do { \
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500112 __asm__ __volatile__ (".set\tnoat\n" \
Markos Chandraseeb53892015-03-09 14:54:50 +0000113 "1:\t"type##_lb("%0", "0(%2)")"\n" \
114 "2:\t"type##_lbu("$1", "1(%2)")"\n\t"\
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500115 "sll\t%0, 0x8\n\t" \
116 "or\t%0, $1\n\t" \
117 "li\t%1, 0\n" \
118 "3:\t.set\tat\n\t" \
119 ".insn\n\t" \
120 ".section\t.fixup,\"ax\"\n\t" \
121 "4:\tli\t%1, %3\n\t" \
122 "j\t3b\n\t" \
123 ".previous\n\t" \
124 ".section\t__ex_table,\"a\"\n\t" \
125 STR(PTR)"\t1b, 4b\n\t" \
126 STR(PTR)"\t2b, 4b\n\t" \
127 ".previous" \
128 : "=&r" (value), "=r" (res) \
Markos Chandras3563c322015-03-09 14:54:51 +0000129 : "r" (addr), "i" (-EFAULT)); \
130} while(0)
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500131
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000132#ifndef CONFIG_CPU_MIPSR6
Markos Chandraseeb53892015-03-09 14:54:50 +0000133#define _LoadW(addr, value, res, type) \
Markos Chandras3563c322015-03-09 14:54:51 +0000134do { \
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500135 __asm__ __volatile__ ( \
Markos Chandraseeb53892015-03-09 14:54:50 +0000136 "1:\t"type##_lwl("%0", "(%2)")"\n" \
137 "2:\t"type##_lwr("%0", "3(%2)")"\n\t"\
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500138 "li\t%1, 0\n" \
139 "3:\n\t" \
140 ".insn\n\t" \
141 ".section\t.fixup,\"ax\"\n\t" \
142 "4:\tli\t%1, %3\n\t" \
143 "j\t3b\n\t" \
144 ".previous\n\t" \
145 ".section\t__ex_table,\"a\"\n\t" \
146 STR(PTR)"\t1b, 4b\n\t" \
147 STR(PTR)"\t2b, 4b\n\t" \
148 ".previous" \
149 : "=&r" (value), "=r" (res) \
Markos Chandras3563c322015-03-09 14:54:51 +0000150 : "r" (addr), "i" (-EFAULT)); \
151} while(0)
152
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000153#else
154/* MIPSR6 has no lwl instruction */
Markos Chandraseeb53892015-03-09 14:54:50 +0000155#define _LoadW(addr, value, res, type) \
Markos Chandras3563c322015-03-09 14:54:51 +0000156do { \
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000157 __asm__ __volatile__ ( \
158 ".set\tpush\n" \
159 ".set\tnoat\n\t" \
Markos Chandraseeb53892015-03-09 14:54:50 +0000160 "1:"type##_lb("%0", "0(%2)")"\n\t" \
161 "2:"type##_lbu("$1", "1(%2)")"\n\t" \
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000162 "sll\t%0, 0x8\n\t" \
163 "or\t%0, $1\n\t" \
Markos Chandraseeb53892015-03-09 14:54:50 +0000164 "3:"type##_lbu("$1", "2(%2)")"\n\t" \
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000165 "sll\t%0, 0x8\n\t" \
166 "or\t%0, $1\n\t" \
Markos Chandraseeb53892015-03-09 14:54:50 +0000167 "4:"type##_lbu("$1", "3(%2)")"\n\t" \
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000168 "sll\t%0, 0x8\n\t" \
169 "or\t%0, $1\n\t" \
170 "li\t%1, 0\n" \
171 ".set\tpop\n" \
172 "10:\n\t" \
173 ".insn\n\t" \
174 ".section\t.fixup,\"ax\"\n\t" \
175 "11:\tli\t%1, %3\n\t" \
176 "j\t10b\n\t" \
177 ".previous\n\t" \
178 ".section\t__ex_table,\"a\"\n\t" \
179 STR(PTR)"\t1b, 11b\n\t" \
180 STR(PTR)"\t2b, 11b\n\t" \
181 STR(PTR)"\t3b, 11b\n\t" \
182 STR(PTR)"\t4b, 11b\n\t" \
183 ".previous" \
184 : "=&r" (value), "=r" (res) \
Markos Chandras3563c322015-03-09 14:54:51 +0000185 : "r" (addr), "i" (-EFAULT)); \
186} while(0)
187
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000188#endif /* CONFIG_CPU_MIPSR6 */
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500189
Markos Chandraseeb53892015-03-09 14:54:50 +0000190#define _LoadHWU(addr, value, res, type) \
Markos Chandras3563c322015-03-09 14:54:51 +0000191do { \
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500192 __asm__ __volatile__ ( \
193 ".set\tnoat\n" \
Markos Chandraseeb53892015-03-09 14:54:50 +0000194 "1:\t"type##_lbu("%0", "0(%2)")"\n" \
195 "2:\t"type##_lbu("$1", "1(%2)")"\n\t"\
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500196 "sll\t%0, 0x8\n\t" \
197 "or\t%0, $1\n\t" \
198 "li\t%1, 0\n" \
199 "3:\n\t" \
200 ".insn\n\t" \
201 ".set\tat\n\t" \
202 ".section\t.fixup,\"ax\"\n\t" \
203 "4:\tli\t%1, %3\n\t" \
204 "j\t3b\n\t" \
205 ".previous\n\t" \
206 ".section\t__ex_table,\"a\"\n\t" \
207 STR(PTR)"\t1b, 4b\n\t" \
208 STR(PTR)"\t2b, 4b\n\t" \
209 ".previous" \
210 : "=&r" (value), "=r" (res) \
Markos Chandras3563c322015-03-09 14:54:51 +0000211 : "r" (addr), "i" (-EFAULT)); \
212} while(0)
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500213
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000214#ifndef CONFIG_CPU_MIPSR6
Markos Chandraseeb53892015-03-09 14:54:50 +0000215#define _LoadWU(addr, value, res, type) \
Markos Chandras3563c322015-03-09 14:54:51 +0000216do { \
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500217 __asm__ __volatile__ ( \
Markos Chandraseeb53892015-03-09 14:54:50 +0000218 "1:\t"type##_lwl("%0", "(%2)")"\n" \
219 "2:\t"type##_lwr("%0", "3(%2)")"\n\t"\
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500220 "dsll\t%0, %0, 32\n\t" \
221 "dsrl\t%0, %0, 32\n\t" \
222 "li\t%1, 0\n" \
223 "3:\n\t" \
224 ".insn\n\t" \
225 "\t.section\t.fixup,\"ax\"\n\t" \
226 "4:\tli\t%1, %3\n\t" \
227 "j\t3b\n\t" \
228 ".previous\n\t" \
229 ".section\t__ex_table,\"a\"\n\t" \
230 STR(PTR)"\t1b, 4b\n\t" \
231 STR(PTR)"\t2b, 4b\n\t" \
232 ".previous" \
233 : "=&r" (value), "=r" (res) \
Markos Chandras3563c322015-03-09 14:54:51 +0000234 : "r" (addr), "i" (-EFAULT)); \
235} while(0)
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500236
Markos Chandraseeb53892015-03-09 14:54:50 +0000237#define _LoadDW(addr, value, res) \
Markos Chandras3563c322015-03-09 14:54:51 +0000238do { \
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500239 __asm__ __volatile__ ( \
240 "1:\tldl\t%0, (%2)\n" \
241 "2:\tldr\t%0, 7(%2)\n\t" \
242 "li\t%1, 0\n" \
243 "3:\n\t" \
244 ".insn\n\t" \
245 "\t.section\t.fixup,\"ax\"\n\t" \
246 "4:\tli\t%1, %3\n\t" \
247 "j\t3b\n\t" \
248 ".previous\n\t" \
249 ".section\t__ex_table,\"a\"\n\t" \
250 STR(PTR)"\t1b, 4b\n\t" \
251 STR(PTR)"\t2b, 4b\n\t" \
252 ".previous" \
253 : "=&r" (value), "=r" (res) \
Markos Chandras3563c322015-03-09 14:54:51 +0000254 : "r" (addr), "i" (-EFAULT)); \
255} while(0)
256
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000257#else
258/* MIPSR6 has not lwl and ldl instructions */
Markos Chandraseeb53892015-03-09 14:54:50 +0000259#define _LoadWU(addr, value, res, type) \
Markos Chandras3563c322015-03-09 14:54:51 +0000260do { \
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000261 __asm__ __volatile__ ( \
262 ".set\tpush\n\t" \
263 ".set\tnoat\n\t" \
Markos Chandraseeb53892015-03-09 14:54:50 +0000264 "1:"type##_lbu("%0", "0(%2)")"\n\t" \
265 "2:"type##_lbu("$1", "1(%2)")"\n\t" \
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000266 "sll\t%0, 0x8\n\t" \
267 "or\t%0, $1\n\t" \
Markos Chandraseeb53892015-03-09 14:54:50 +0000268 "3:"type##_lbu("$1", "2(%2)")"\n\t" \
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000269 "sll\t%0, 0x8\n\t" \
270 "or\t%0, $1\n\t" \
Markos Chandraseeb53892015-03-09 14:54:50 +0000271 "4:"type##_lbu("$1", "3(%2)")"\n\t" \
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000272 "sll\t%0, 0x8\n\t" \
273 "or\t%0, $1\n\t" \
274 "li\t%1, 0\n" \
275 ".set\tpop\n" \
276 "10:\n\t" \
277 ".insn\n\t" \
278 ".section\t.fixup,\"ax\"\n\t" \
279 "11:\tli\t%1, %3\n\t" \
280 "j\t10b\n\t" \
281 ".previous\n\t" \
282 ".section\t__ex_table,\"a\"\n\t" \
283 STR(PTR)"\t1b, 11b\n\t" \
284 STR(PTR)"\t2b, 11b\n\t" \
285 STR(PTR)"\t3b, 11b\n\t" \
286 STR(PTR)"\t4b, 11b\n\t" \
287 ".previous" \
288 : "=&r" (value), "=r" (res) \
Markos Chandras3563c322015-03-09 14:54:51 +0000289 : "r" (addr), "i" (-EFAULT)); \
290} while(0)
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000291
Markos Chandraseeb53892015-03-09 14:54:50 +0000292#define _LoadDW(addr, value, res) \
Markos Chandras3563c322015-03-09 14:54:51 +0000293do { \
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000294 __asm__ __volatile__ ( \
295 ".set\tpush\n\t" \
296 ".set\tnoat\n\t" \
297 "1:lb\t%0, 0(%2)\n\t" \
298 "2:lbu\t $1, 1(%2)\n\t" \
299 "dsll\t%0, 0x8\n\t" \
300 "or\t%0, $1\n\t" \
301 "3:lbu\t$1, 2(%2)\n\t" \
302 "dsll\t%0, 0x8\n\t" \
303 "or\t%0, $1\n\t" \
304 "4:lbu\t$1, 3(%2)\n\t" \
305 "dsll\t%0, 0x8\n\t" \
306 "or\t%0, $1\n\t" \
307 "5:lbu\t$1, 4(%2)\n\t" \
308 "dsll\t%0, 0x8\n\t" \
309 "or\t%0, $1\n\t" \
310 "6:lbu\t$1, 5(%2)\n\t" \
311 "dsll\t%0, 0x8\n\t" \
312 "or\t%0, $1\n\t" \
313 "7:lbu\t$1, 6(%2)\n\t" \
314 "dsll\t%0, 0x8\n\t" \
315 "or\t%0, $1\n\t" \
316 "8:lbu\t$1, 7(%2)\n\t" \
317 "dsll\t%0, 0x8\n\t" \
318 "or\t%0, $1\n\t" \
319 "li\t%1, 0\n" \
320 ".set\tpop\n\t" \
321 "10:\n\t" \
322 ".insn\n\t" \
323 ".section\t.fixup,\"ax\"\n\t" \
324 "11:\tli\t%1, %3\n\t" \
325 "j\t10b\n\t" \
326 ".previous\n\t" \
327 ".section\t__ex_table,\"a\"\n\t" \
328 STR(PTR)"\t1b, 11b\n\t" \
329 STR(PTR)"\t2b, 11b\n\t" \
330 STR(PTR)"\t3b, 11b\n\t" \
331 STR(PTR)"\t4b, 11b\n\t" \
332 STR(PTR)"\t5b, 11b\n\t" \
333 STR(PTR)"\t6b, 11b\n\t" \
334 STR(PTR)"\t7b, 11b\n\t" \
335 STR(PTR)"\t8b, 11b\n\t" \
336 ".previous" \
337 : "=&r" (value), "=r" (res) \
Markos Chandras3563c322015-03-09 14:54:51 +0000338 : "r" (addr), "i" (-EFAULT)); \
339} while(0)
340
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000341#endif /* CONFIG_CPU_MIPSR6 */
342
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500343
Markos Chandraseeb53892015-03-09 14:54:50 +0000344#define _StoreHW(addr, value, res, type) \
Markos Chandras3563c322015-03-09 14:54:51 +0000345do { \
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500346 __asm__ __volatile__ ( \
347 ".set\tnoat\n" \
Markos Chandraseeb53892015-03-09 14:54:50 +0000348 "1:\t"type##_sb("%1", "1(%2)")"\n" \
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500349 "srl\t$1, %1, 0x8\n" \
Markos Chandraseeb53892015-03-09 14:54:50 +0000350 "2:\t"type##_sb("$1", "0(%2)")"\n" \
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500351 ".set\tat\n\t" \
352 "li\t%0, 0\n" \
353 "3:\n\t" \
354 ".insn\n\t" \
355 ".section\t.fixup,\"ax\"\n\t" \
356 "4:\tli\t%0, %3\n\t" \
357 "j\t3b\n\t" \
358 ".previous\n\t" \
359 ".section\t__ex_table,\"a\"\n\t" \
360 STR(PTR)"\t1b, 4b\n\t" \
361 STR(PTR)"\t2b, 4b\n\t" \
362 ".previous" \
363 : "=r" (res) \
Markos Chandras3563c322015-03-09 14:54:51 +0000364 : "r" (value), "r" (addr), "i" (-EFAULT));\
365} while(0)
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500366
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000367#ifndef CONFIG_CPU_MIPSR6
Markos Chandraseeb53892015-03-09 14:54:50 +0000368#define _StoreW(addr, value, res, type) \
Markos Chandras3563c322015-03-09 14:54:51 +0000369do { \
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500370 __asm__ __volatile__ ( \
Markos Chandraseeb53892015-03-09 14:54:50 +0000371 "1:\t"type##_swl("%1", "(%2)")"\n" \
372 "2:\t"type##_swr("%1", "3(%2)")"\n\t"\
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500373 "li\t%0, 0\n" \
374 "3:\n\t" \
375 ".insn\n\t" \
376 ".section\t.fixup,\"ax\"\n\t" \
377 "4:\tli\t%0, %3\n\t" \
378 "j\t3b\n\t" \
379 ".previous\n\t" \
380 ".section\t__ex_table,\"a\"\n\t" \
381 STR(PTR)"\t1b, 4b\n\t" \
382 STR(PTR)"\t2b, 4b\n\t" \
383 ".previous" \
384 : "=r" (res) \
Markos Chandras3563c322015-03-09 14:54:51 +0000385 : "r" (value), "r" (addr), "i" (-EFAULT)); \
386} while(0)
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500387
Markos Chandraseeb53892015-03-09 14:54:50 +0000388#define _StoreDW(addr, value, res) \
Markos Chandras3563c322015-03-09 14:54:51 +0000389do { \
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500390 __asm__ __volatile__ ( \
391 "1:\tsdl\t%1,(%2)\n" \
392 "2:\tsdr\t%1, 7(%2)\n\t" \
393 "li\t%0, 0\n" \
394 "3:\n\t" \
395 ".insn\n\t" \
396 ".section\t.fixup,\"ax\"\n\t" \
397 "4:\tli\t%0, %3\n\t" \
398 "j\t3b\n\t" \
399 ".previous\n\t" \
400 ".section\t__ex_table,\"a\"\n\t" \
401 STR(PTR)"\t1b, 4b\n\t" \
402 STR(PTR)"\t2b, 4b\n\t" \
403 ".previous" \
404 : "=r" (res) \
Markos Chandras3563c322015-03-09 14:54:51 +0000405 : "r" (value), "r" (addr), "i" (-EFAULT)); \
406} while(0)
407
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000408#else
409/* MIPSR6 has no swl and sdl instructions */
Markos Chandraseeb53892015-03-09 14:54:50 +0000410#define _StoreW(addr, value, res, type) \
Markos Chandras3563c322015-03-09 14:54:51 +0000411do { \
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000412 __asm__ __volatile__ ( \
413 ".set\tpush\n\t" \
414 ".set\tnoat\n\t" \
Markos Chandraseeb53892015-03-09 14:54:50 +0000415 "1:"type##_sb("%1", "3(%2)")"\n\t" \
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000416 "srl\t$1, %1, 0x8\n\t" \
Markos Chandraseeb53892015-03-09 14:54:50 +0000417 "2:"type##_sb("$1", "2(%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 "3:"type##_sb("$1", "1(%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 "4:"type##_sb("$1", "0(%2)")"\n\t" \
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000422 ".set\tpop\n\t" \
423 "li\t%0, 0\n" \
424 "10:\n\t" \
425 ".insn\n\t" \
426 ".section\t.fixup,\"ax\"\n\t" \
427 "11:\tli\t%0, %3\n\t" \
428 "j\t10b\n\t" \
429 ".previous\n\t" \
430 ".section\t__ex_table,\"a\"\n\t" \
431 STR(PTR)"\t1b, 11b\n\t" \
432 STR(PTR)"\t2b, 11b\n\t" \
433 STR(PTR)"\t3b, 11b\n\t" \
434 STR(PTR)"\t4b, 11b\n\t" \
435 ".previous" \
436 : "=&r" (res) \
437 : "r" (value), "r" (addr), "i" (-EFAULT) \
Markos Chandras3563c322015-03-09 14:54:51 +0000438 : "memory"); \
439} while(0)
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500440
James Cowgill531a6d52015-06-23 12:02:00 +0100441#define _StoreDW(addr, value, res) \
Markos Chandras3563c322015-03-09 14:54:51 +0000442do { \
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000443 __asm__ __volatile__ ( \
444 ".set\tpush\n\t" \
445 ".set\tnoat\n\t" \
446 "1:sb\t%1, 7(%2)\n\t" \
447 "dsrl\t$1, %1, 0x8\n\t" \
448 "2:sb\t$1, 6(%2)\n\t" \
449 "dsrl\t$1, $1, 0x8\n\t" \
450 "3:sb\t$1, 5(%2)\n\t" \
451 "dsrl\t$1, $1, 0x8\n\t" \
452 "4:sb\t$1, 4(%2)\n\t" \
453 "dsrl\t$1, $1, 0x8\n\t" \
454 "5:sb\t$1, 3(%2)\n\t" \
455 "dsrl\t$1, $1, 0x8\n\t" \
456 "6:sb\t$1, 2(%2)\n\t" \
457 "dsrl\t$1, $1, 0x8\n\t" \
458 "7:sb\t$1, 1(%2)\n\t" \
459 "dsrl\t$1, $1, 0x8\n\t" \
460 "8:sb\t$1, 0(%2)\n\t" \
461 "dsrl\t$1, $1, 0x8\n\t" \
462 ".set\tpop\n\t" \
463 "li\t%0, 0\n" \
464 "10:\n\t" \
465 ".insn\n\t" \
466 ".section\t.fixup,\"ax\"\n\t" \
467 "11:\tli\t%0, %3\n\t" \
468 "j\t10b\n\t" \
469 ".previous\n\t" \
470 ".section\t__ex_table,\"a\"\n\t" \
471 STR(PTR)"\t1b, 11b\n\t" \
472 STR(PTR)"\t2b, 11b\n\t" \
473 STR(PTR)"\t3b, 11b\n\t" \
474 STR(PTR)"\t4b, 11b\n\t" \
475 STR(PTR)"\t5b, 11b\n\t" \
476 STR(PTR)"\t6b, 11b\n\t" \
477 STR(PTR)"\t7b, 11b\n\t" \
478 STR(PTR)"\t8b, 11b\n\t" \
479 ".previous" \
480 : "=&r" (res) \
481 : "r" (value), "r" (addr), "i" (-EFAULT) \
Markos Chandras3563c322015-03-09 14:54:51 +0000482 : "memory"); \
483} while(0)
484
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000485#endif /* CONFIG_CPU_MIPSR6 */
486
487#else /* __BIG_ENDIAN */
488
Markos Chandraseeb53892015-03-09 14:54:50 +0000489#define _LoadHW(addr, value, res, type) \
Markos Chandras3563c322015-03-09 14:54:51 +0000490do { \
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500491 __asm__ __volatile__ (".set\tnoat\n" \
Markos Chandraseeb53892015-03-09 14:54:50 +0000492 "1:\t"type##_lb("%0", "1(%2)")"\n" \
493 "2:\t"type##_lbu("$1", "0(%2)")"\n\t"\
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500494 "sll\t%0, 0x8\n\t" \
495 "or\t%0, $1\n\t" \
496 "li\t%1, 0\n" \
497 "3:\t.set\tat\n\t" \
498 ".insn\n\t" \
499 ".section\t.fixup,\"ax\"\n\t" \
500 "4:\tli\t%1, %3\n\t" \
501 "j\t3b\n\t" \
502 ".previous\n\t" \
503 ".section\t__ex_table,\"a\"\n\t" \
504 STR(PTR)"\t1b, 4b\n\t" \
505 STR(PTR)"\t2b, 4b\n\t" \
506 ".previous" \
507 : "=&r" (value), "=r" (res) \
Markos Chandras3563c322015-03-09 14:54:51 +0000508 : "r" (addr), "i" (-EFAULT)); \
509} while(0)
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500510
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000511#ifndef CONFIG_CPU_MIPSR6
Markos Chandraseeb53892015-03-09 14:54:50 +0000512#define _LoadW(addr, value, res, type) \
Markos Chandras3563c322015-03-09 14:54:51 +0000513do { \
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500514 __asm__ __volatile__ ( \
Markos Chandraseeb53892015-03-09 14:54:50 +0000515 "1:\t"type##_lwl("%0", "3(%2)")"\n" \
516 "2:\t"type##_lwr("%0", "(%2)")"\n\t"\
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500517 "li\t%1, 0\n" \
518 "3:\n\t" \
519 ".insn\n\t" \
520 ".section\t.fixup,\"ax\"\n\t" \
521 "4:\tli\t%1, %3\n\t" \
522 "j\t3b\n\t" \
523 ".previous\n\t" \
524 ".section\t__ex_table,\"a\"\n\t" \
525 STR(PTR)"\t1b, 4b\n\t" \
526 STR(PTR)"\t2b, 4b\n\t" \
527 ".previous" \
528 : "=&r" (value), "=r" (res) \
Markos Chandras3563c322015-03-09 14:54:51 +0000529 : "r" (addr), "i" (-EFAULT)); \
530} while(0)
531
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000532#else
533/* MIPSR6 has no lwl instruction */
Markos Chandraseeb53892015-03-09 14:54:50 +0000534#define _LoadW(addr, value, res, type) \
Markos Chandras3563c322015-03-09 14:54:51 +0000535do { \
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000536 __asm__ __volatile__ ( \
537 ".set\tpush\n" \
538 ".set\tnoat\n\t" \
Markos Chandraseeb53892015-03-09 14:54:50 +0000539 "1:"type##_lb("%0", "3(%2)")"\n\t" \
540 "2:"type##_lbu("$1", "2(%2)")"\n\t" \
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000541 "sll\t%0, 0x8\n\t" \
542 "or\t%0, $1\n\t" \
Markos Chandraseeb53892015-03-09 14:54:50 +0000543 "3:"type##_lbu("$1", "1(%2)")"\n\t" \
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000544 "sll\t%0, 0x8\n\t" \
545 "or\t%0, $1\n\t" \
Markos Chandraseeb53892015-03-09 14:54:50 +0000546 "4:"type##_lbu("$1", "0(%2)")"\n\t" \
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000547 "sll\t%0, 0x8\n\t" \
548 "or\t%0, $1\n\t" \
549 "li\t%1, 0\n" \
550 ".set\tpop\n" \
551 "10:\n\t" \
552 ".insn\n\t" \
553 ".section\t.fixup,\"ax\"\n\t" \
554 "11:\tli\t%1, %3\n\t" \
555 "j\t10b\n\t" \
556 ".previous\n\t" \
557 ".section\t__ex_table,\"a\"\n\t" \
558 STR(PTR)"\t1b, 11b\n\t" \
559 STR(PTR)"\t2b, 11b\n\t" \
560 STR(PTR)"\t3b, 11b\n\t" \
561 STR(PTR)"\t4b, 11b\n\t" \
562 ".previous" \
563 : "=&r" (value), "=r" (res) \
Markos Chandras3563c322015-03-09 14:54:51 +0000564 : "r" (addr), "i" (-EFAULT)); \
565} while(0)
566
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000567#endif /* CONFIG_CPU_MIPSR6 */
568
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500569
Markos Chandraseeb53892015-03-09 14:54:50 +0000570#define _LoadHWU(addr, value, res, type) \
Markos Chandras3563c322015-03-09 14:54:51 +0000571do { \
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500572 __asm__ __volatile__ ( \
573 ".set\tnoat\n" \
Markos Chandraseeb53892015-03-09 14:54:50 +0000574 "1:\t"type##_lbu("%0", "1(%2)")"\n" \
575 "2:\t"type##_lbu("$1", "0(%2)")"\n\t"\
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500576 "sll\t%0, 0x8\n\t" \
577 "or\t%0, $1\n\t" \
578 "li\t%1, 0\n" \
579 "3:\n\t" \
580 ".insn\n\t" \
581 ".set\tat\n\t" \
582 ".section\t.fixup,\"ax\"\n\t" \
583 "4:\tli\t%1, %3\n\t" \
584 "j\t3b\n\t" \
585 ".previous\n\t" \
586 ".section\t__ex_table,\"a\"\n\t" \
587 STR(PTR)"\t1b, 4b\n\t" \
588 STR(PTR)"\t2b, 4b\n\t" \
589 ".previous" \
590 : "=&r" (value), "=r" (res) \
Markos Chandras3563c322015-03-09 14:54:51 +0000591 : "r" (addr), "i" (-EFAULT)); \
592} while(0)
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500593
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000594#ifndef CONFIG_CPU_MIPSR6
Markos Chandraseeb53892015-03-09 14:54:50 +0000595#define _LoadWU(addr, value, res, type) \
Markos Chandras3563c322015-03-09 14:54:51 +0000596do { \
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500597 __asm__ __volatile__ ( \
Markos Chandraseeb53892015-03-09 14:54:50 +0000598 "1:\t"type##_lwl("%0", "3(%2)")"\n" \
599 "2:\t"type##_lwr("%0", "(%2)")"\n\t"\
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500600 "dsll\t%0, %0, 32\n\t" \
601 "dsrl\t%0, %0, 32\n\t" \
602 "li\t%1, 0\n" \
603 "3:\n\t" \
604 ".insn\n\t" \
605 "\t.section\t.fixup,\"ax\"\n\t" \
606 "4:\tli\t%1, %3\n\t" \
607 "j\t3b\n\t" \
608 ".previous\n\t" \
609 ".section\t__ex_table,\"a\"\n\t" \
610 STR(PTR)"\t1b, 4b\n\t" \
611 STR(PTR)"\t2b, 4b\n\t" \
612 ".previous" \
613 : "=&r" (value), "=r" (res) \
Markos Chandras3563c322015-03-09 14:54:51 +0000614 : "r" (addr), "i" (-EFAULT)); \
615} while(0)
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500616
Markos Chandraseeb53892015-03-09 14:54:50 +0000617#define _LoadDW(addr, value, res) \
Markos Chandras3563c322015-03-09 14:54:51 +0000618do { \
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500619 __asm__ __volatile__ ( \
620 "1:\tldl\t%0, 7(%2)\n" \
621 "2:\tldr\t%0, (%2)\n\t" \
622 "li\t%1, 0\n" \
623 "3:\n\t" \
624 ".insn\n\t" \
625 "\t.section\t.fixup,\"ax\"\n\t" \
626 "4:\tli\t%1, %3\n\t" \
627 "j\t3b\n\t" \
628 ".previous\n\t" \
629 ".section\t__ex_table,\"a\"\n\t" \
630 STR(PTR)"\t1b, 4b\n\t" \
631 STR(PTR)"\t2b, 4b\n\t" \
632 ".previous" \
633 : "=&r" (value), "=r" (res) \
Markos Chandras3563c322015-03-09 14:54:51 +0000634 : "r" (addr), "i" (-EFAULT)); \
635} while(0)
636
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000637#else
638/* MIPSR6 has not lwl and ldl instructions */
Markos Chandraseeb53892015-03-09 14:54:50 +0000639#define _LoadWU(addr, value, res, type) \
Markos Chandras3563c322015-03-09 14:54:51 +0000640do { \
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000641 __asm__ __volatile__ ( \
642 ".set\tpush\n\t" \
643 ".set\tnoat\n\t" \
Markos Chandraseeb53892015-03-09 14:54:50 +0000644 "1:"type##_lbu("%0", "3(%2)")"\n\t" \
645 "2:"type##_lbu("$1", "2(%2)")"\n\t" \
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000646 "sll\t%0, 0x8\n\t" \
647 "or\t%0, $1\n\t" \
Markos Chandraseeb53892015-03-09 14:54:50 +0000648 "3:"type##_lbu("$1", "1(%2)")"\n\t" \
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000649 "sll\t%0, 0x8\n\t" \
650 "or\t%0, $1\n\t" \
Markos Chandraseeb53892015-03-09 14:54:50 +0000651 "4:"type##_lbu("$1", "0(%2)")"\n\t" \
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000652 "sll\t%0, 0x8\n\t" \
653 "or\t%0, $1\n\t" \
654 "li\t%1, 0\n" \
655 ".set\tpop\n" \
656 "10:\n\t" \
657 ".insn\n\t" \
658 ".section\t.fixup,\"ax\"\n\t" \
659 "11:\tli\t%1, %3\n\t" \
660 "j\t10b\n\t" \
661 ".previous\n\t" \
662 ".section\t__ex_table,\"a\"\n\t" \
663 STR(PTR)"\t1b, 11b\n\t" \
664 STR(PTR)"\t2b, 11b\n\t" \
665 STR(PTR)"\t3b, 11b\n\t" \
666 STR(PTR)"\t4b, 11b\n\t" \
667 ".previous" \
668 : "=&r" (value), "=r" (res) \
Markos Chandras3563c322015-03-09 14:54:51 +0000669 : "r" (addr), "i" (-EFAULT)); \
670} while(0)
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000671
Markos Chandraseeb53892015-03-09 14:54:50 +0000672#define _LoadDW(addr, value, res) \
Markos Chandras3563c322015-03-09 14:54:51 +0000673do { \
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000674 __asm__ __volatile__ ( \
675 ".set\tpush\n\t" \
676 ".set\tnoat\n\t" \
677 "1:lb\t%0, 7(%2)\n\t" \
678 "2:lbu\t$1, 6(%2)\n\t" \
679 "dsll\t%0, 0x8\n\t" \
680 "or\t%0, $1\n\t" \
681 "3:lbu\t$1, 5(%2)\n\t" \
682 "dsll\t%0, 0x8\n\t" \
683 "or\t%0, $1\n\t" \
684 "4:lbu\t$1, 4(%2)\n\t" \
685 "dsll\t%0, 0x8\n\t" \
686 "or\t%0, $1\n\t" \
687 "5:lbu\t$1, 3(%2)\n\t" \
688 "dsll\t%0, 0x8\n\t" \
689 "or\t%0, $1\n\t" \
690 "6:lbu\t$1, 2(%2)\n\t" \
691 "dsll\t%0, 0x8\n\t" \
692 "or\t%0, $1\n\t" \
693 "7:lbu\t$1, 1(%2)\n\t" \
694 "dsll\t%0, 0x8\n\t" \
695 "or\t%0, $1\n\t" \
696 "8:lbu\t$1, 0(%2)\n\t" \
697 "dsll\t%0, 0x8\n\t" \
698 "or\t%0, $1\n\t" \
699 "li\t%1, 0\n" \
700 ".set\tpop\n\t" \
701 "10:\n\t" \
702 ".insn\n\t" \
703 ".section\t.fixup,\"ax\"\n\t" \
704 "11:\tli\t%1, %3\n\t" \
705 "j\t10b\n\t" \
706 ".previous\n\t" \
707 ".section\t__ex_table,\"a\"\n\t" \
708 STR(PTR)"\t1b, 11b\n\t" \
709 STR(PTR)"\t2b, 11b\n\t" \
710 STR(PTR)"\t3b, 11b\n\t" \
711 STR(PTR)"\t4b, 11b\n\t" \
712 STR(PTR)"\t5b, 11b\n\t" \
713 STR(PTR)"\t6b, 11b\n\t" \
714 STR(PTR)"\t7b, 11b\n\t" \
715 STR(PTR)"\t8b, 11b\n\t" \
716 ".previous" \
717 : "=&r" (value), "=r" (res) \
Markos Chandras3563c322015-03-09 14:54:51 +0000718 : "r" (addr), "i" (-EFAULT)); \
719} while(0)
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000720#endif /* CONFIG_CPU_MIPSR6 */
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500721
Markos Chandraseeb53892015-03-09 14:54:50 +0000722#define _StoreHW(addr, value, res, type) \
Markos Chandras3563c322015-03-09 14:54:51 +0000723do { \
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500724 __asm__ __volatile__ ( \
725 ".set\tnoat\n" \
Markos Chandraseeb53892015-03-09 14:54:50 +0000726 "1:\t"type##_sb("%1", "0(%2)")"\n" \
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500727 "srl\t$1,%1, 0x8\n" \
Markos Chandraseeb53892015-03-09 14:54:50 +0000728 "2:\t"type##_sb("$1", "1(%2)")"\n" \
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500729 ".set\tat\n\t" \
730 "li\t%0, 0\n" \
731 "3:\n\t" \
732 ".insn\n\t" \
733 ".section\t.fixup,\"ax\"\n\t" \
734 "4:\tli\t%0, %3\n\t" \
735 "j\t3b\n\t" \
736 ".previous\n\t" \
737 ".section\t__ex_table,\"a\"\n\t" \
738 STR(PTR)"\t1b, 4b\n\t" \
739 STR(PTR)"\t2b, 4b\n\t" \
740 ".previous" \
741 : "=r" (res) \
Markos Chandras3563c322015-03-09 14:54:51 +0000742 : "r" (value), "r" (addr), "i" (-EFAULT));\
743} while(0)
744
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000745#ifndef CONFIG_CPU_MIPSR6
Markos Chandraseeb53892015-03-09 14:54:50 +0000746#define _StoreW(addr, value, res, type) \
Markos Chandras3563c322015-03-09 14:54:51 +0000747do { \
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500748 __asm__ __volatile__ ( \
Markos Chandraseeb53892015-03-09 14:54:50 +0000749 "1:\t"type##_swl("%1", "3(%2)")"\n" \
750 "2:\t"type##_swr("%1", "(%2)")"\n\t"\
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500751 "li\t%0, 0\n" \
752 "3:\n\t" \
753 ".insn\n\t" \
754 ".section\t.fixup,\"ax\"\n\t" \
755 "4:\tli\t%0, %3\n\t" \
756 "j\t3b\n\t" \
757 ".previous\n\t" \
758 ".section\t__ex_table,\"a\"\n\t" \
759 STR(PTR)"\t1b, 4b\n\t" \
760 STR(PTR)"\t2b, 4b\n\t" \
761 ".previous" \
762 : "=r" (res) \
Markos Chandras3563c322015-03-09 14:54:51 +0000763 : "r" (value), "r" (addr), "i" (-EFAULT)); \
764} while(0)
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500765
Markos Chandraseeb53892015-03-09 14:54:50 +0000766#define _StoreDW(addr, value, res) \
Markos Chandras3563c322015-03-09 14:54:51 +0000767do { \
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500768 __asm__ __volatile__ ( \
769 "1:\tsdl\t%1, 7(%2)\n" \
770 "2:\tsdr\t%1, (%2)\n\t" \
771 "li\t%0, 0\n" \
772 "3:\n\t" \
773 ".insn\n\t" \
774 ".section\t.fixup,\"ax\"\n\t" \
775 "4:\tli\t%0, %3\n\t" \
776 "j\t3b\n\t" \
777 ".previous\n\t" \
778 ".section\t__ex_table,\"a\"\n\t" \
779 STR(PTR)"\t1b, 4b\n\t" \
780 STR(PTR)"\t2b, 4b\n\t" \
781 ".previous" \
782 : "=r" (res) \
Markos Chandras3563c322015-03-09 14:54:51 +0000783 : "r" (value), "r" (addr), "i" (-EFAULT)); \
784} while(0)
785
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000786#else
787/* MIPSR6 has no swl and sdl instructions */
Markos Chandraseeb53892015-03-09 14:54:50 +0000788#define _StoreW(addr, value, res, type) \
Markos Chandras3563c322015-03-09 14:54:51 +0000789do { \
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000790 __asm__ __volatile__ ( \
791 ".set\tpush\n\t" \
792 ".set\tnoat\n\t" \
Markos Chandraseeb53892015-03-09 14:54:50 +0000793 "1:"type##_sb("%1", "0(%2)")"\n\t" \
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000794 "srl\t$1, %1, 0x8\n\t" \
Markos Chandraseeb53892015-03-09 14:54:50 +0000795 "2:"type##_sb("$1", "1(%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 "3:"type##_sb("$1", "2(%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 "4:"type##_sb("$1", "3(%2)")"\n\t" \
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000800 ".set\tpop\n\t" \
801 "li\t%0, 0\n" \
802 "10:\n\t" \
803 ".insn\n\t" \
804 ".section\t.fixup,\"ax\"\n\t" \
805 "11:\tli\t%0, %3\n\t" \
806 "j\t10b\n\t" \
807 ".previous\n\t" \
808 ".section\t__ex_table,\"a\"\n\t" \
809 STR(PTR)"\t1b, 11b\n\t" \
810 STR(PTR)"\t2b, 11b\n\t" \
811 STR(PTR)"\t3b, 11b\n\t" \
812 STR(PTR)"\t4b, 11b\n\t" \
813 ".previous" \
814 : "=&r" (res) \
815 : "r" (value), "r" (addr), "i" (-EFAULT) \
Markos Chandras3563c322015-03-09 14:54:51 +0000816 : "memory"); \
817} while(0)
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000818
Markos Chandraseeb53892015-03-09 14:54:50 +0000819#define _StoreDW(addr, value, res) \
Markos Chandras3563c322015-03-09 14:54:51 +0000820do { \
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000821 __asm__ __volatile__ ( \
822 ".set\tpush\n\t" \
823 ".set\tnoat\n\t" \
824 "1:sb\t%1, 0(%2)\n\t" \
825 "dsrl\t$1, %1, 0x8\n\t" \
826 "2:sb\t$1, 1(%2)\n\t" \
827 "dsrl\t$1, $1, 0x8\n\t" \
828 "3:sb\t$1, 2(%2)\n\t" \
829 "dsrl\t$1, $1, 0x8\n\t" \
830 "4:sb\t$1, 3(%2)\n\t" \
831 "dsrl\t$1, $1, 0x8\n\t" \
832 "5:sb\t$1, 4(%2)\n\t" \
833 "dsrl\t$1, $1, 0x8\n\t" \
834 "6:sb\t$1, 5(%2)\n\t" \
835 "dsrl\t$1, $1, 0x8\n\t" \
836 "7:sb\t$1, 6(%2)\n\t" \
837 "dsrl\t$1, $1, 0x8\n\t" \
838 "8:sb\t$1, 7(%2)\n\t" \
839 "dsrl\t$1, $1, 0x8\n\t" \
840 ".set\tpop\n\t" \
841 "li\t%0, 0\n" \
842 "10:\n\t" \
843 ".insn\n\t" \
844 ".section\t.fixup,\"ax\"\n\t" \
845 "11:\tli\t%0, %3\n\t" \
846 "j\t10b\n\t" \
847 ".previous\n\t" \
848 ".section\t__ex_table,\"a\"\n\t" \
849 STR(PTR)"\t1b, 11b\n\t" \
850 STR(PTR)"\t2b, 11b\n\t" \
851 STR(PTR)"\t3b, 11b\n\t" \
852 STR(PTR)"\t4b, 11b\n\t" \
853 STR(PTR)"\t5b, 11b\n\t" \
854 STR(PTR)"\t6b, 11b\n\t" \
855 STR(PTR)"\t7b, 11b\n\t" \
856 STR(PTR)"\t8b, 11b\n\t" \
857 ".previous" \
858 : "=&r" (res) \
859 : "r" (value), "r" (addr), "i" (-EFAULT) \
Markos Chandras3563c322015-03-09 14:54:51 +0000860 : "memory"); \
861} while(0)
862
Leonid Yegoshin0593a442014-10-28 10:42:23 +0000863#endif /* CONFIG_CPU_MIPSR6 */
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500864#endif
865
Markos Chandraseeb53892015-03-09 14:54:50 +0000866#define LoadHWU(addr, value, res) _LoadHWU(addr, value, res, kernel)
867#define LoadHWUE(addr, value, res) _LoadHWU(addr, value, res, user)
868#define LoadWU(addr, value, res) _LoadWU(addr, value, res, kernel)
869#define LoadWUE(addr, value, res) _LoadWU(addr, value, res, user)
870#define LoadHW(addr, value, res) _LoadHW(addr, value, res, kernel)
871#define LoadHWE(addr, value, res) _LoadHW(addr, value, res, user)
872#define LoadW(addr, value, res) _LoadW(addr, value, res, kernel)
873#define LoadWE(addr, value, res) _LoadW(addr, value, res, user)
874#define LoadDW(addr, value, res) _LoadDW(addr, value, res)
875
876#define StoreHW(addr, value, res) _StoreHW(addr, value, res, kernel)
877#define StoreHWE(addr, value, res) _StoreHW(addr, value, res, user)
878#define StoreW(addr, value, res) _StoreW(addr, value, res, kernel)
879#define StoreWE(addr, value, res) _StoreW(addr, value, res, user)
880#define StoreDW(addr, value, res) _StoreDW(addr, value, res)
881
Ralf Baechle7f18f152007-07-29 09:16:19 +0100882static void emulate_load_store_insn(struct pt_regs *regs,
883 void __user *addr, unsigned int __user *pc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700884{
885 union mips_instruction insn;
886 unsigned long value;
887 unsigned int res;
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500888 unsigned long origpc;
889 unsigned long orig31;
Leonid Yegoshin102cedc2013-03-25 12:09:02 -0500890 void __user *fault_addr = NULL;
Leonid Yegoshinc1771212013-12-12 16:15:15 +0000891#ifdef CONFIG_EVA
892 mm_segment_t seg;
893#endif
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500894 origpc = (unsigned long)pc;
895 orig31 = regs->regs[31];
896
Peter Zijlstraa8b0ca12011-06-27 14:41:57 +0200897 perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, 0);
Deng-Cheng Zhu7f788d22010-10-12 19:37:21 +0800898
Linus Torvalds1da177e2005-04-16 15:20:36 -0700899 /*
900 * This load never faults.
901 */
Ralf Baechlefe00f942005-03-01 19:22:29 +0000902 __get_user(insn.word, pc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700903
904 switch (insn.i_format.opcode) {
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500905 /*
906 * These are instructions that a compiler doesn't generate. We
907 * can assume therefore that the code is MIPS-aware and
908 * really buggy. Emulating these instructions would break the
909 * semantics anyway.
910 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700911 case ll_op:
912 case lld_op:
913 case sc_op:
914 case scd_op:
915
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500916 /*
917 * For these instructions the only way to create an address
918 * error is an attempted access to kernel/supervisor address
919 * space.
920 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700921 case ldl_op:
922 case ldr_op:
923 case lwl_op:
924 case lwr_op:
925 case sdl_op:
926 case sdr_op:
927 case swl_op:
928 case swr_op:
929 case lb_op:
930 case lbu_op:
931 case sb_op:
932 goto sigbus;
933
Leonid Yegoshin34c2f662013-03-25 13:18:07 -0500934 /*
935 * The remaining opcodes are the ones that are really of
936 * interest.
937 */
Leonid Yegoshinc1771212013-12-12 16:15:15 +0000938#ifdef CONFIG_EVA
939 case spec3_op:
940 /*
941 * we can land here only from kernel accessing user memory,
942 * so we need to "switch" the address limit to user space, so
943 * address check can work properly.
944 */
945 seg = get_fs();
946 set_fs(USER_DS);
947 switch (insn.spec3_format.func) {
948 case lhe_op:
949 if (!access_ok(VERIFY_READ, addr, 2)) {
950 set_fs(seg);
951 goto sigbus;
952 }
Markos Chandraseeb53892015-03-09 14:54:50 +0000953 LoadHWE(addr, value, res);
Leonid Yegoshinc1771212013-12-12 16:15:15 +0000954 if (res) {
955 set_fs(seg);
956 goto fault;
957 }
958 compute_return_epc(regs);
959 regs->regs[insn.spec3_format.rt] = value;
960 break;
961 case lwe_op:
962 if (!access_ok(VERIFY_READ, addr, 4)) {
963 set_fs(seg);
964 goto sigbus;
965 }
Markos Chandraseeb53892015-03-09 14:54:50 +0000966 LoadWE(addr, value, res);
Leonid Yegoshinc1771212013-12-12 16:15:15 +0000967 if (res) {
968 set_fs(seg);
969 goto fault;
970 }
971 compute_return_epc(regs);
972 regs->regs[insn.spec3_format.rt] = value;
973 break;
974 case lhue_op:
975 if (!access_ok(VERIFY_READ, addr, 2)) {
976 set_fs(seg);
977 goto sigbus;
978 }
Markos Chandraseeb53892015-03-09 14:54:50 +0000979 LoadHWUE(addr, value, res);
Leonid Yegoshinc1771212013-12-12 16:15:15 +0000980 if (res) {
981 set_fs(seg);
982 goto fault;
983 }
984 compute_return_epc(regs);
985 regs->regs[insn.spec3_format.rt] = value;
986 break;
987 case she_op:
988 if (!access_ok(VERIFY_WRITE, addr, 2)) {
989 set_fs(seg);
990 goto sigbus;
991 }
992 compute_return_epc(regs);
993 value = regs->regs[insn.spec3_format.rt];
Markos Chandraseeb53892015-03-09 14:54:50 +0000994 StoreHWE(addr, value, res);
Leonid Yegoshinc1771212013-12-12 16:15:15 +0000995 if (res) {
996 set_fs(seg);
997 goto fault;
998 }
999 break;
1000 case swe_op:
1001 if (!access_ok(VERIFY_WRITE, addr, 4)) {
1002 set_fs(seg);
1003 goto sigbus;
1004 }
1005 compute_return_epc(regs);
1006 value = regs->regs[insn.spec3_format.rt];
Markos Chandraseeb53892015-03-09 14:54:50 +00001007 StoreWE(addr, value, res);
Leonid Yegoshinc1771212013-12-12 16:15:15 +00001008 if (res) {
1009 set_fs(seg);
1010 goto fault;
1011 }
1012 break;
1013 default:
1014 set_fs(seg);
1015 goto sigill;
1016 }
1017 set_fs(seg);
1018 break;
1019#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001020 case lh_op:
1021 if (!access_ok(VERIFY_READ, addr, 2))
1022 goto sigbus;
1023
Markos Chandras6eae3542015-03-09 14:54:52 +00001024 if (config_enabled(CONFIG_EVA)) {
1025 if (segment_eq(get_fs(), get_ds()))
1026 LoadHW(addr, value, res);
1027 else
1028 LoadHWE(addr, value, res);
1029 } else {
1030 LoadHW(addr, value, res);
1031 }
1032
Linus Torvalds1da177e2005-04-16 15:20:36 -07001033 if (res)
1034 goto fault;
Ralf Baechle7f18f152007-07-29 09:16:19 +01001035 compute_return_epc(regs);
1036 regs->regs[insn.i_format.rt] = value;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001037 break;
1038
1039 case lw_op:
1040 if (!access_ok(VERIFY_READ, addr, 4))
1041 goto sigbus;
1042
Markos Chandras6eae3542015-03-09 14:54:52 +00001043 if (config_enabled(CONFIG_EVA)) {
1044 if (segment_eq(get_fs(), get_ds()))
1045 LoadW(addr, value, res);
1046 else
1047 LoadWE(addr, value, res);
1048 } else {
1049 LoadW(addr, value, res);
1050 }
1051
Linus Torvalds1da177e2005-04-16 15:20:36 -07001052 if (res)
1053 goto fault;
Ralf Baechle7f18f152007-07-29 09:16:19 +01001054 compute_return_epc(regs);
1055 regs->regs[insn.i_format.rt] = value;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001056 break;
1057
1058 case lhu_op:
1059 if (!access_ok(VERIFY_READ, addr, 2))
1060 goto sigbus;
1061
Markos Chandras6eae3542015-03-09 14:54:52 +00001062 if (config_enabled(CONFIG_EVA)) {
1063 if (segment_eq(get_fs(), get_ds()))
1064 LoadHWU(addr, value, res);
1065 else
1066 LoadHWUE(addr, value, res);
1067 } else {
1068 LoadHWU(addr, value, res);
1069 }
1070
Linus Torvalds1da177e2005-04-16 15:20:36 -07001071 if (res)
1072 goto fault;
Ralf Baechle7f18f152007-07-29 09:16:19 +01001073 compute_return_epc(regs);
1074 regs->regs[insn.i_format.rt] = value;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001075 break;
1076
1077 case lwu_op:
Ralf Baechle875d43e2005-09-03 15:56:16 -07001078#ifdef CONFIG_64BIT
Linus Torvalds1da177e2005-04-16 15:20:36 -07001079 /*
1080 * A 32-bit kernel might be running on a 64-bit processor. But
1081 * if we're on a 32-bit processor and an i-cache incoherency
1082 * or race makes us see a 64-bit instruction here the sdl/sdr
1083 * would blow up, so for now we don't handle unaligned 64-bit
1084 * instructions on 32-bit kernels.
1085 */
1086 if (!access_ok(VERIFY_READ, addr, 4))
1087 goto sigbus;
1088
Leonid Yegoshin34c2f662013-03-25 13:18:07 -05001089 LoadWU(addr, value, res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001090 if (res)
1091 goto fault;
Ralf Baechle7f18f152007-07-29 09:16:19 +01001092 compute_return_epc(regs);
1093 regs->regs[insn.i_format.rt] = value;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001094 break;
Ralf Baechle875d43e2005-09-03 15:56:16 -07001095#endif /* CONFIG_64BIT */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001096
1097 /* Cannot handle 64-bit instructions in 32-bit kernel */
1098 goto sigill;
1099
1100 case ld_op:
Ralf Baechle875d43e2005-09-03 15:56:16 -07001101#ifdef CONFIG_64BIT
Linus Torvalds1da177e2005-04-16 15:20:36 -07001102 /*
1103 * A 32-bit kernel might be running on a 64-bit processor. But
1104 * if we're on a 32-bit processor and an i-cache incoherency
1105 * or race makes us see a 64-bit instruction here the sdl/sdr
1106 * would blow up, so for now we don't handle unaligned 64-bit
1107 * instructions on 32-bit kernels.
1108 */
1109 if (!access_ok(VERIFY_READ, addr, 8))
1110 goto sigbus;
1111
Leonid Yegoshin34c2f662013-03-25 13:18:07 -05001112 LoadDW(addr, value, res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001113 if (res)
1114 goto fault;
Ralf Baechle7f18f152007-07-29 09:16:19 +01001115 compute_return_epc(regs);
1116 regs->regs[insn.i_format.rt] = value;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001117 break;
Ralf Baechle875d43e2005-09-03 15:56:16 -07001118#endif /* CONFIG_64BIT */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001119
1120 /* Cannot handle 64-bit instructions in 32-bit kernel */
1121 goto sigill;
1122
1123 case sh_op:
1124 if (!access_ok(VERIFY_WRITE, addr, 2))
1125 goto sigbus;
1126
Leonid Yegoshin34c2f662013-03-25 13:18:07 -05001127 compute_return_epc(regs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001128 value = regs->regs[insn.i_format.rt];
Markos Chandras6eae3542015-03-09 14:54:52 +00001129
1130 if (config_enabled(CONFIG_EVA)) {
1131 if (segment_eq(get_fs(), get_ds()))
1132 StoreHW(addr, value, res);
1133 else
1134 StoreHWE(addr, value, res);
1135 } else {
1136 StoreHW(addr, value, res);
1137 }
1138
Linus Torvalds1da177e2005-04-16 15:20:36 -07001139 if (res)
1140 goto fault;
1141 break;
1142
1143 case sw_op:
1144 if (!access_ok(VERIFY_WRITE, addr, 4))
1145 goto sigbus;
1146
Leonid Yegoshin34c2f662013-03-25 13:18:07 -05001147 compute_return_epc(regs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001148 value = regs->regs[insn.i_format.rt];
Markos Chandras6eae3542015-03-09 14:54:52 +00001149
1150 if (config_enabled(CONFIG_EVA)) {
1151 if (segment_eq(get_fs(), get_ds()))
1152 StoreW(addr, value, res);
1153 else
1154 StoreWE(addr, value, res);
1155 } else {
1156 StoreW(addr, value, res);
1157 }
1158
Linus Torvalds1da177e2005-04-16 15:20:36 -07001159 if (res)
1160 goto fault;
1161 break;
1162
1163 case sd_op:
Ralf Baechle875d43e2005-09-03 15:56:16 -07001164#ifdef CONFIG_64BIT
Linus Torvalds1da177e2005-04-16 15:20:36 -07001165 /*
1166 * A 32-bit kernel might be running on a 64-bit processor. But
1167 * if we're on a 32-bit processor and an i-cache incoherency
1168 * or race makes us see a 64-bit instruction here the sdl/sdr
1169 * would blow up, so for now we don't handle unaligned 64-bit
1170 * instructions on 32-bit kernels.
1171 */
1172 if (!access_ok(VERIFY_WRITE, addr, 8))
1173 goto sigbus;
1174
Leonid Yegoshin34c2f662013-03-25 13:18:07 -05001175 compute_return_epc(regs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001176 value = regs->regs[insn.i_format.rt];
Leonid Yegoshin34c2f662013-03-25 13:18:07 -05001177 StoreDW(addr, value, res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001178 if (res)
1179 goto fault;
1180 break;
Ralf Baechle875d43e2005-09-03 15:56:16 -07001181#endif /* CONFIG_64BIT */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001182
1183 /* Cannot handle 64-bit instructions in 32-bit kernel */
1184 goto sigill;
1185
1186 case lwc1_op:
1187 case ldc1_op:
1188 case swc1_op:
1189 case sdc1_op:
Leonid Yegoshin102cedc2013-03-25 12:09:02 -05001190 die_if_kernel("Unaligned FP access in kernel code", regs);
1191 BUG_ON(!used_math());
Leonid Yegoshin102cedc2013-03-25 12:09:02 -05001192
1193 lose_fpu(1); /* Save FPU state for the emulator. */
1194 res = fpu_emulator_cop1Handler(regs, &current->thread.fpu, 1,
1195 &fault_addr);
1196 own_fpu(1); /* Restore FPU state. */
1197
1198 /* Signal if something went wrong. */
Maciej W. Rozycki304acb72015-04-03 23:27:15 +01001199 process_fpemu_return(res, fault_addr, 0);
Leonid Yegoshin102cedc2013-03-25 12:09:02 -05001200
1201 if (res == 0)
1202 break;
1203 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001204
Leonid Yegoshin0593a442014-10-28 10:42:23 +00001205#ifndef CONFIG_CPU_MIPSR6
Ralf Baechle69f3a7d2009-11-24 01:24:58 +00001206 /*
1207 * COP2 is available to implementor for application specific use.
1208 * It's up to applications to register a notifier chain and do
1209 * whatever they have to do, including possible sending of signals.
Leonid Yegoshin0593a442014-10-28 10:42:23 +00001210 *
1211 * This instruction has been reallocated in Release 6
Ralf Baechle69f3a7d2009-11-24 01:24:58 +00001212 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001213 case lwc2_op:
Ralf Baechle69f3a7d2009-11-24 01:24:58 +00001214 cu2_notifier_call_chain(CU2_LWC2_OP, regs);
1215 break;
1216
Linus Torvalds1da177e2005-04-16 15:20:36 -07001217 case ldc2_op:
Ralf Baechle69f3a7d2009-11-24 01:24:58 +00001218 cu2_notifier_call_chain(CU2_LDC2_OP, regs);
1219 break;
1220
Linus Torvalds1da177e2005-04-16 15:20:36 -07001221 case swc2_op:
Ralf Baechle69f3a7d2009-11-24 01:24:58 +00001222 cu2_notifier_call_chain(CU2_SWC2_OP, regs);
1223 break;
1224
Linus Torvalds1da177e2005-04-16 15:20:36 -07001225 case sdc2_op:
Ralf Baechle69f3a7d2009-11-24 01:24:58 +00001226 cu2_notifier_call_chain(CU2_SDC2_OP, regs);
1227 break;
Leonid Yegoshin0593a442014-10-28 10:42:23 +00001228#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001229 default:
1230 /*
1231 * Pheeee... We encountered an yet unknown instruction or
1232 * cache coherence problem. Die sucker, die ...
1233 */
1234 goto sigill;
1235 }
1236
Atsushi Nemoto6312e0e2007-06-30 00:55:48 +09001237#ifdef CONFIG_DEBUG_FS
Linus Torvalds1da177e2005-04-16 15:20:36 -07001238 unaligned_instructions++;
1239#endif
1240
Ralf Baechle7f18f152007-07-29 09:16:19 +01001241 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001242
1243fault:
Leonid Yegoshin34c2f662013-03-25 13:18:07 -05001244 /* roll back jump/branch */
1245 regs->cp0_epc = origpc;
1246 regs->regs[31] = orig31;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001247 /* Did we have an exception handler installed? */
1248 if (fixup_exception(regs))
Ralf Baechle7f18f152007-07-29 09:16:19 +01001249 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001250
Ralf Baechle49a89ef2007-10-11 23:46:15 +01001251 die_if_kernel("Unhandled kernel unaligned access", regs);
David Daneya6d5ff02009-05-05 12:49:47 -07001252 force_sig(SIGSEGV, current);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001253
Ralf Baechle7f18f152007-07-29 09:16:19 +01001254 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001255
1256sigbus:
1257 die_if_kernel("Unhandled kernel unaligned access", regs);
David Daneya6d5ff02009-05-05 12:49:47 -07001258 force_sig(SIGBUS, current);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001259
Ralf Baechle7f18f152007-07-29 09:16:19 +01001260 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001261
1262sigill:
Leonid Yegoshin34c2f662013-03-25 13:18:07 -05001263 die_if_kernel
1264 ("Unhandled kernel unaligned access or invalid instruction", regs);
1265 force_sig(SIGILL, current);
1266}
1267
1268/* Recode table from 16-bit register notation to 32-bit GPR. */
1269const int reg16to32[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
1270
1271/* Recode table from 16-bit STORE register notation to 32-bit GPR. */
1272const int reg16to32st[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
1273
David Daney74338802013-05-24 20:54:08 +00001274static void emulate_load_store_microMIPS(struct pt_regs *regs,
1275 void __user *addr)
Leonid Yegoshin34c2f662013-03-25 13:18:07 -05001276{
1277 unsigned long value;
1278 unsigned int res;
1279 int i;
1280 unsigned int reg = 0, rvar;
1281 unsigned long orig31;
1282 u16 __user *pc16;
1283 u16 halfword;
1284 unsigned int word;
1285 unsigned long origpc, contpc;
1286 union mips_instruction insn;
1287 struct mm_decoded_insn mminsn;
1288 void __user *fault_addr = NULL;
1289
1290 origpc = regs->cp0_epc;
1291 orig31 = regs->regs[31];
1292
1293 mminsn.micro_mips_mode = 1;
1294
1295 /*
1296 * This load never faults.
1297 */
1298 pc16 = (unsigned short __user *)msk_isa16_mode(regs->cp0_epc);
1299 __get_user(halfword, pc16);
1300 pc16++;
1301 contpc = regs->cp0_epc + 2;
1302 word = ((unsigned int)halfword << 16);
1303 mminsn.pc_inc = 2;
1304
1305 if (!mm_insn_16bit(halfword)) {
1306 __get_user(halfword, pc16);
1307 pc16++;
1308 contpc = regs->cp0_epc + 4;
1309 mminsn.pc_inc = 4;
1310 word |= halfword;
1311 }
1312 mminsn.insn = word;
1313
1314 if (get_user(halfword, pc16))
1315 goto fault;
1316 mminsn.next_pc_inc = 2;
1317 word = ((unsigned int)halfword << 16);
1318
1319 if (!mm_insn_16bit(halfword)) {
1320 pc16++;
1321 if (get_user(halfword, pc16))
1322 goto fault;
1323 mminsn.next_pc_inc = 4;
1324 word |= halfword;
1325 }
1326 mminsn.next_insn = word;
1327
1328 insn = (union mips_instruction)(mminsn.insn);
1329 if (mm_isBranchInstr(regs, mminsn, &contpc))
1330 insn = (union mips_instruction)(mminsn.next_insn);
1331
1332 /* Parse instruction to find what to do */
1333
1334 switch (insn.mm_i_format.opcode) {
1335
1336 case mm_pool32a_op:
1337 switch (insn.mm_x_format.func) {
1338 case mm_lwxs_op:
1339 reg = insn.mm_x_format.rd;
1340 goto loadW;
1341 }
1342
1343 goto sigbus;
1344
1345 case mm_pool32b_op:
1346 switch (insn.mm_m_format.func) {
1347 case mm_lwp_func:
1348 reg = insn.mm_m_format.rd;
1349 if (reg == 31)
1350 goto sigbus;
1351
1352 if (!access_ok(VERIFY_READ, addr, 8))
1353 goto sigbus;
1354
1355 LoadW(addr, value, res);
1356 if (res)
1357 goto fault;
1358 regs->regs[reg] = value;
1359 addr += 4;
1360 LoadW(addr, value, res);
1361 if (res)
1362 goto fault;
1363 regs->regs[reg + 1] = value;
1364 goto success;
1365
1366 case mm_swp_func:
1367 reg = insn.mm_m_format.rd;
1368 if (reg == 31)
1369 goto sigbus;
1370
1371 if (!access_ok(VERIFY_WRITE, addr, 8))
1372 goto sigbus;
1373
1374 value = regs->regs[reg];
1375 StoreW(addr, value, res);
1376 if (res)
1377 goto fault;
1378 addr += 4;
1379 value = regs->regs[reg + 1];
1380 StoreW(addr, value, res);
1381 if (res)
1382 goto fault;
1383 goto success;
1384
1385 case mm_ldp_func:
1386#ifdef CONFIG_64BIT
1387 reg = insn.mm_m_format.rd;
1388 if (reg == 31)
1389 goto sigbus;
1390
1391 if (!access_ok(VERIFY_READ, addr, 16))
1392 goto sigbus;
1393
1394 LoadDW(addr, value, res);
1395 if (res)
1396 goto fault;
1397 regs->regs[reg] = value;
1398 addr += 8;
1399 LoadDW(addr, value, res);
1400 if (res)
1401 goto fault;
1402 regs->regs[reg + 1] = value;
1403 goto success;
1404#endif /* CONFIG_64BIT */
1405
1406 goto sigill;
1407
1408 case mm_sdp_func:
1409#ifdef CONFIG_64BIT
1410 reg = insn.mm_m_format.rd;
1411 if (reg == 31)
1412 goto sigbus;
1413
1414 if (!access_ok(VERIFY_WRITE, addr, 16))
1415 goto sigbus;
1416
1417 value = regs->regs[reg];
1418 StoreDW(addr, value, res);
1419 if (res)
1420 goto fault;
1421 addr += 8;
1422 value = regs->regs[reg + 1];
1423 StoreDW(addr, value, res);
1424 if (res)
1425 goto fault;
1426 goto success;
1427#endif /* CONFIG_64BIT */
1428
1429 goto sigill;
1430
1431 case mm_lwm32_func:
1432 reg = insn.mm_m_format.rd;
1433 rvar = reg & 0xf;
1434 if ((rvar > 9) || !reg)
1435 goto sigill;
1436 if (reg & 0x10) {
1437 if (!access_ok
1438 (VERIFY_READ, addr, 4 * (rvar + 1)))
1439 goto sigbus;
1440 } else {
1441 if (!access_ok(VERIFY_READ, addr, 4 * rvar))
1442 goto sigbus;
1443 }
1444 if (rvar == 9)
1445 rvar = 8;
1446 for (i = 16; rvar; rvar--, i++) {
1447 LoadW(addr, value, res);
1448 if (res)
1449 goto fault;
1450 addr += 4;
1451 regs->regs[i] = value;
1452 }
1453 if ((reg & 0xf) == 9) {
1454 LoadW(addr, value, res);
1455 if (res)
1456 goto fault;
1457 addr += 4;
1458 regs->regs[30] = value;
1459 }
1460 if (reg & 0x10) {
1461 LoadW(addr, value, res);
1462 if (res)
1463 goto fault;
1464 regs->regs[31] = value;
1465 }
1466 goto success;
1467
1468 case mm_swm32_func:
1469 reg = insn.mm_m_format.rd;
1470 rvar = reg & 0xf;
1471 if ((rvar > 9) || !reg)
1472 goto sigill;
1473 if (reg & 0x10) {
1474 if (!access_ok
1475 (VERIFY_WRITE, addr, 4 * (rvar + 1)))
1476 goto sigbus;
1477 } else {
1478 if (!access_ok(VERIFY_WRITE, addr, 4 * rvar))
1479 goto sigbus;
1480 }
1481 if (rvar == 9)
1482 rvar = 8;
1483 for (i = 16; rvar; rvar--, i++) {
1484 value = regs->regs[i];
1485 StoreW(addr, value, res);
1486 if (res)
1487 goto fault;
1488 addr += 4;
1489 }
1490 if ((reg & 0xf) == 9) {
1491 value = regs->regs[30];
1492 StoreW(addr, value, res);
1493 if (res)
1494 goto fault;
1495 addr += 4;
1496 }
1497 if (reg & 0x10) {
1498 value = regs->regs[31];
1499 StoreW(addr, value, res);
1500 if (res)
1501 goto fault;
1502 }
1503 goto success;
1504
1505 case mm_ldm_func:
1506#ifdef CONFIG_64BIT
1507 reg = insn.mm_m_format.rd;
1508 rvar = reg & 0xf;
1509 if ((rvar > 9) || !reg)
1510 goto sigill;
1511 if (reg & 0x10) {
1512 if (!access_ok
1513 (VERIFY_READ, addr, 8 * (rvar + 1)))
1514 goto sigbus;
1515 } else {
1516 if (!access_ok(VERIFY_READ, addr, 8 * rvar))
1517 goto sigbus;
1518 }
1519 if (rvar == 9)
1520 rvar = 8;
1521
1522 for (i = 16; rvar; rvar--, i++) {
1523 LoadDW(addr, value, res);
1524 if (res)
1525 goto fault;
1526 addr += 4;
1527 regs->regs[i] = value;
1528 }
1529 if ((reg & 0xf) == 9) {
1530 LoadDW(addr, value, res);
1531 if (res)
1532 goto fault;
1533 addr += 8;
1534 regs->regs[30] = value;
1535 }
1536 if (reg & 0x10) {
1537 LoadDW(addr, value, res);
1538 if (res)
1539 goto fault;
1540 regs->regs[31] = value;
1541 }
1542 goto success;
1543#endif /* CONFIG_64BIT */
1544
1545 goto sigill;
1546
1547 case mm_sdm_func:
1548#ifdef CONFIG_64BIT
1549 reg = insn.mm_m_format.rd;
1550 rvar = reg & 0xf;
1551 if ((rvar > 9) || !reg)
1552 goto sigill;
1553 if (reg & 0x10) {
1554 if (!access_ok
1555 (VERIFY_WRITE, addr, 8 * (rvar + 1)))
1556 goto sigbus;
1557 } else {
1558 if (!access_ok(VERIFY_WRITE, addr, 8 * rvar))
1559 goto sigbus;
1560 }
1561 if (rvar == 9)
1562 rvar = 8;
1563
1564 for (i = 16; rvar; rvar--, i++) {
1565 value = regs->regs[i];
1566 StoreDW(addr, value, res);
1567 if (res)
1568 goto fault;
1569 addr += 8;
1570 }
1571 if ((reg & 0xf) == 9) {
1572 value = regs->regs[30];
1573 StoreDW(addr, value, res);
1574 if (res)
1575 goto fault;
1576 addr += 8;
1577 }
1578 if (reg & 0x10) {
1579 value = regs->regs[31];
1580 StoreDW(addr, value, res);
1581 if (res)
1582 goto fault;
1583 }
1584 goto success;
1585#endif /* CONFIG_64BIT */
1586
1587 goto sigill;
1588
1589 /* LWC2, SWC2, LDC2, SDC2 are not serviced */
1590 }
1591
1592 goto sigbus;
1593
1594 case mm_pool32c_op:
1595 switch (insn.mm_m_format.func) {
1596 case mm_lwu_func:
1597 reg = insn.mm_m_format.rd;
1598 goto loadWU;
1599 }
1600
1601 /* LL,SC,LLD,SCD are not serviced */
1602 goto sigbus;
1603
1604 case mm_pool32f_op:
1605 switch (insn.mm_x_format.func) {
1606 case mm_lwxc1_func:
1607 case mm_swxc1_func:
1608 case mm_ldxc1_func:
1609 case mm_sdxc1_func:
1610 goto fpu_emul;
1611 }
1612
1613 goto sigbus;
1614
1615 case mm_ldc132_op:
1616 case mm_sdc132_op:
1617 case mm_lwc132_op:
1618 case mm_swc132_op:
1619fpu_emul:
1620 /* roll back jump/branch */
1621 regs->cp0_epc = origpc;
1622 regs->regs[31] = orig31;
1623
1624 die_if_kernel("Unaligned FP access in kernel code", regs);
1625 BUG_ON(!used_math());
1626 BUG_ON(!is_fpu_owner());
1627
1628 lose_fpu(1); /* save the FPU state for the emulator */
1629 res = fpu_emulator_cop1Handler(regs, &current->thread.fpu, 1,
1630 &fault_addr);
1631 own_fpu(1); /* restore FPU state */
1632
1633 /* If something went wrong, signal */
Maciej W. Rozycki304acb72015-04-03 23:27:15 +01001634 process_fpemu_return(res, fault_addr, 0);
Leonid Yegoshin34c2f662013-03-25 13:18:07 -05001635
1636 if (res == 0)
1637 goto success;
1638 return;
1639
1640 case mm_lh32_op:
1641 reg = insn.mm_i_format.rt;
1642 goto loadHW;
1643
1644 case mm_lhu32_op:
1645 reg = insn.mm_i_format.rt;
1646 goto loadHWU;
1647
1648 case mm_lw32_op:
1649 reg = insn.mm_i_format.rt;
1650 goto loadW;
1651
1652 case mm_sh32_op:
1653 reg = insn.mm_i_format.rt;
1654 goto storeHW;
1655
1656 case mm_sw32_op:
1657 reg = insn.mm_i_format.rt;
1658 goto storeW;
1659
1660 case mm_ld32_op:
1661 reg = insn.mm_i_format.rt;
1662 goto loadDW;
1663
1664 case mm_sd32_op:
1665 reg = insn.mm_i_format.rt;
1666 goto storeDW;
1667
1668 case mm_pool16c_op:
1669 switch (insn.mm16_m_format.func) {
1670 case mm_lwm16_op:
1671 reg = insn.mm16_m_format.rlist;
1672 rvar = reg + 1;
1673 if (!access_ok(VERIFY_READ, addr, 4 * rvar))
1674 goto sigbus;
1675
1676 for (i = 16; rvar; rvar--, i++) {
1677 LoadW(addr, value, res);
1678 if (res)
1679 goto fault;
1680 addr += 4;
1681 regs->regs[i] = value;
1682 }
1683 LoadW(addr, value, res);
1684 if (res)
1685 goto fault;
1686 regs->regs[31] = value;
1687
1688 goto success;
1689
1690 case mm_swm16_op:
1691 reg = insn.mm16_m_format.rlist;
1692 rvar = reg + 1;
1693 if (!access_ok(VERIFY_WRITE, addr, 4 * rvar))
1694 goto sigbus;
1695
1696 for (i = 16; rvar; rvar--, i++) {
1697 value = regs->regs[i];
1698 StoreW(addr, value, res);
1699 if (res)
1700 goto fault;
1701 addr += 4;
1702 }
1703 value = regs->regs[31];
1704 StoreW(addr, value, res);
1705 if (res)
1706 goto fault;
1707
1708 goto success;
1709
1710 }
1711
1712 goto sigbus;
1713
1714 case mm_lhu16_op:
1715 reg = reg16to32[insn.mm16_rb_format.rt];
1716 goto loadHWU;
1717
1718 case mm_lw16_op:
1719 reg = reg16to32[insn.mm16_rb_format.rt];
1720 goto loadW;
1721
1722 case mm_sh16_op:
1723 reg = reg16to32st[insn.mm16_rb_format.rt];
1724 goto storeHW;
1725
1726 case mm_sw16_op:
1727 reg = reg16to32st[insn.mm16_rb_format.rt];
1728 goto storeW;
1729
1730 case mm_lwsp16_op:
1731 reg = insn.mm16_r5_format.rt;
1732 goto loadW;
1733
1734 case mm_swsp16_op:
1735 reg = insn.mm16_r5_format.rt;
1736 goto storeW;
1737
1738 case mm_lwgp16_op:
1739 reg = reg16to32[insn.mm16_r3_format.rt];
1740 goto loadW;
1741
1742 default:
1743 goto sigill;
1744 }
1745
1746loadHW:
1747 if (!access_ok(VERIFY_READ, addr, 2))
1748 goto sigbus;
1749
1750 LoadHW(addr, value, res);
1751 if (res)
1752 goto fault;
1753 regs->regs[reg] = value;
1754 goto success;
1755
1756loadHWU:
1757 if (!access_ok(VERIFY_READ, addr, 2))
1758 goto sigbus;
1759
1760 LoadHWU(addr, value, res);
1761 if (res)
1762 goto fault;
1763 regs->regs[reg] = value;
1764 goto success;
1765
1766loadW:
1767 if (!access_ok(VERIFY_READ, addr, 4))
1768 goto sigbus;
1769
1770 LoadW(addr, value, res);
1771 if (res)
1772 goto fault;
1773 regs->regs[reg] = value;
1774 goto success;
1775
1776loadWU:
1777#ifdef CONFIG_64BIT
1778 /*
1779 * A 32-bit kernel might be running on a 64-bit processor. But
1780 * if we're on a 32-bit processor and an i-cache incoherency
1781 * or race makes us see a 64-bit instruction here the sdl/sdr
1782 * would blow up, so for now we don't handle unaligned 64-bit
1783 * instructions on 32-bit kernels.
1784 */
1785 if (!access_ok(VERIFY_READ, addr, 4))
1786 goto sigbus;
1787
1788 LoadWU(addr, value, res);
1789 if (res)
1790 goto fault;
1791 regs->regs[reg] = value;
1792 goto success;
1793#endif /* CONFIG_64BIT */
1794
1795 /* Cannot handle 64-bit instructions in 32-bit kernel */
1796 goto sigill;
1797
1798loadDW:
1799#ifdef CONFIG_64BIT
1800 /*
1801 * A 32-bit kernel might be running on a 64-bit processor. But
1802 * if we're on a 32-bit processor and an i-cache incoherency
1803 * or race makes us see a 64-bit instruction here the sdl/sdr
1804 * would blow up, so for now we don't handle unaligned 64-bit
1805 * instructions on 32-bit kernels.
1806 */
1807 if (!access_ok(VERIFY_READ, addr, 8))
1808 goto sigbus;
1809
1810 LoadDW(addr, value, res);
1811 if (res)
1812 goto fault;
1813 regs->regs[reg] = value;
1814 goto success;
1815#endif /* CONFIG_64BIT */
1816
1817 /* Cannot handle 64-bit instructions in 32-bit kernel */
1818 goto sigill;
1819
1820storeHW:
1821 if (!access_ok(VERIFY_WRITE, addr, 2))
1822 goto sigbus;
1823
1824 value = regs->regs[reg];
1825 StoreHW(addr, value, res);
1826 if (res)
1827 goto fault;
1828 goto success;
1829
1830storeW:
1831 if (!access_ok(VERIFY_WRITE, addr, 4))
1832 goto sigbus;
1833
1834 value = regs->regs[reg];
1835 StoreW(addr, value, res);
1836 if (res)
1837 goto fault;
1838 goto success;
1839
1840storeDW:
1841#ifdef CONFIG_64BIT
1842 /*
1843 * A 32-bit kernel might be running on a 64-bit processor. But
1844 * if we're on a 32-bit processor and an i-cache incoherency
1845 * or race makes us see a 64-bit instruction here the sdl/sdr
1846 * would blow up, so for now we don't handle unaligned 64-bit
1847 * instructions on 32-bit kernels.
1848 */
1849 if (!access_ok(VERIFY_WRITE, addr, 8))
1850 goto sigbus;
1851
1852 value = regs->regs[reg];
1853 StoreDW(addr, value, res);
1854 if (res)
1855 goto fault;
1856 goto success;
1857#endif /* CONFIG_64BIT */
1858
1859 /* Cannot handle 64-bit instructions in 32-bit kernel */
1860 goto sigill;
1861
1862success:
1863 regs->cp0_epc = contpc; /* advance or branch */
1864
1865#ifdef CONFIG_DEBUG_FS
1866 unaligned_instructions++;
1867#endif
1868 return;
1869
1870fault:
1871 /* roll back jump/branch */
1872 regs->cp0_epc = origpc;
1873 regs->regs[31] = orig31;
1874 /* Did we have an exception handler installed? */
1875 if (fixup_exception(regs))
1876 return;
1877
1878 die_if_kernel("Unhandled kernel unaligned access", regs);
1879 force_sig(SIGSEGV, current);
1880
1881 return;
1882
1883sigbus:
1884 die_if_kernel("Unhandled kernel unaligned access", regs);
1885 force_sig(SIGBUS, current);
1886
1887 return;
1888
1889sigill:
1890 die_if_kernel
1891 ("Unhandled kernel unaligned access or invalid instruction", regs);
David Daneya6d5ff02009-05-05 12:49:47 -07001892 force_sig(SIGILL, current);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001893}
1894
Steven J. Hill451b0012013-03-25 13:46:15 -05001895static void emulate_load_store_MIPS16e(struct pt_regs *regs, void __user * addr)
1896{
1897 unsigned long value;
1898 unsigned int res;
1899 int reg;
1900 unsigned long orig31;
1901 u16 __user *pc16;
1902 unsigned long origpc;
1903 union mips16e_instruction mips16inst, oldinst;
1904
1905 origpc = regs->cp0_epc;
1906 orig31 = regs->regs[31];
1907 pc16 = (unsigned short __user *)msk_isa16_mode(origpc);
1908 /*
1909 * This load never faults.
1910 */
1911 __get_user(mips16inst.full, pc16);
1912 oldinst = mips16inst;
1913
1914 /* skip EXTEND instruction */
1915 if (mips16inst.ri.opcode == MIPS16e_extend_op) {
1916 pc16++;
1917 __get_user(mips16inst.full, pc16);
1918 } else if (delay_slot(regs)) {
1919 /* skip jump instructions */
1920 /* JAL/JALX are 32 bits but have OPCODE in first short int */
1921 if (mips16inst.ri.opcode == MIPS16e_jal_op)
1922 pc16++;
1923 pc16++;
1924 if (get_user(mips16inst.full, pc16))
1925 goto sigbus;
1926 }
1927
1928 switch (mips16inst.ri.opcode) {
1929 case MIPS16e_i64_op: /* I64 or RI64 instruction */
1930 switch (mips16inst.i64.func) { /* I64/RI64 func field check */
1931 case MIPS16e_ldpc_func:
1932 case MIPS16e_ldsp_func:
1933 reg = reg16to32[mips16inst.ri64.ry];
1934 goto loadDW;
1935
1936 case MIPS16e_sdsp_func:
1937 reg = reg16to32[mips16inst.ri64.ry];
1938 goto writeDW;
1939
1940 case MIPS16e_sdrasp_func:
1941 reg = 29; /* GPRSP */
1942 goto writeDW;
1943 }
1944
1945 goto sigbus;
1946
1947 case MIPS16e_swsp_op:
1948 case MIPS16e_lwpc_op:
1949 case MIPS16e_lwsp_op:
1950 reg = reg16to32[mips16inst.ri.rx];
1951 break;
1952
1953 case MIPS16e_i8_op:
1954 if (mips16inst.i8.func != MIPS16e_swrasp_func)
1955 goto sigbus;
1956 reg = 29; /* GPRSP */
1957 break;
1958
1959 default:
1960 reg = reg16to32[mips16inst.rri.ry];
1961 break;
1962 }
1963
1964 switch (mips16inst.ri.opcode) {
1965
1966 case MIPS16e_lb_op:
1967 case MIPS16e_lbu_op:
1968 case MIPS16e_sb_op:
1969 goto sigbus;
1970
1971 case MIPS16e_lh_op:
1972 if (!access_ok(VERIFY_READ, addr, 2))
1973 goto sigbus;
1974
1975 LoadHW(addr, value, res);
1976 if (res)
1977 goto fault;
1978 MIPS16e_compute_return_epc(regs, &oldinst);
1979 regs->regs[reg] = value;
1980 break;
1981
1982 case MIPS16e_lhu_op:
1983 if (!access_ok(VERIFY_READ, addr, 2))
1984 goto sigbus;
1985
1986 LoadHWU(addr, value, res);
1987 if (res)
1988 goto fault;
1989 MIPS16e_compute_return_epc(regs, &oldinst);
1990 regs->regs[reg] = value;
1991 break;
1992
1993 case MIPS16e_lw_op:
1994 case MIPS16e_lwpc_op:
1995 case MIPS16e_lwsp_op:
1996 if (!access_ok(VERIFY_READ, addr, 4))
1997 goto sigbus;
1998
1999 LoadW(addr, value, res);
2000 if (res)
2001 goto fault;
2002 MIPS16e_compute_return_epc(regs, &oldinst);
2003 regs->regs[reg] = value;
2004 break;
2005
2006 case MIPS16e_lwu_op:
2007#ifdef CONFIG_64BIT
2008 /*
2009 * A 32-bit kernel might be running on a 64-bit processor. But
2010 * if we're on a 32-bit processor and an i-cache incoherency
2011 * or race makes us see a 64-bit instruction here the sdl/sdr
2012 * would blow up, so for now we don't handle unaligned 64-bit
2013 * instructions on 32-bit kernels.
2014 */
2015 if (!access_ok(VERIFY_READ, addr, 4))
2016 goto sigbus;
2017
2018 LoadWU(addr, value, res);
2019 if (res)
2020 goto fault;
2021 MIPS16e_compute_return_epc(regs, &oldinst);
2022 regs->regs[reg] = value;
2023 break;
2024#endif /* CONFIG_64BIT */
2025
2026 /* Cannot handle 64-bit instructions in 32-bit kernel */
2027 goto sigill;
2028
2029 case MIPS16e_ld_op:
2030loadDW:
2031#ifdef CONFIG_64BIT
2032 /*
2033 * A 32-bit kernel might be running on a 64-bit processor. But
2034 * if we're on a 32-bit processor and an i-cache incoherency
2035 * or race makes us see a 64-bit instruction here the sdl/sdr
2036 * would blow up, so for now we don't handle unaligned 64-bit
2037 * instructions on 32-bit kernels.
2038 */
2039 if (!access_ok(VERIFY_READ, addr, 8))
2040 goto sigbus;
2041
2042 LoadDW(addr, value, res);
2043 if (res)
2044 goto fault;
2045 MIPS16e_compute_return_epc(regs, &oldinst);
2046 regs->regs[reg] = value;
2047 break;
2048#endif /* CONFIG_64BIT */
2049
2050 /* Cannot handle 64-bit instructions in 32-bit kernel */
2051 goto sigill;
2052
2053 case MIPS16e_sh_op:
2054 if (!access_ok(VERIFY_WRITE, addr, 2))
2055 goto sigbus;
2056
2057 MIPS16e_compute_return_epc(regs, &oldinst);
2058 value = regs->regs[reg];
2059 StoreHW(addr, value, res);
2060 if (res)
2061 goto fault;
2062 break;
2063
2064 case MIPS16e_sw_op:
2065 case MIPS16e_swsp_op:
2066 case MIPS16e_i8_op: /* actually - MIPS16e_swrasp_func */
2067 if (!access_ok(VERIFY_WRITE, addr, 4))
2068 goto sigbus;
2069
2070 MIPS16e_compute_return_epc(regs, &oldinst);
2071 value = regs->regs[reg];
2072 StoreW(addr, value, res);
2073 if (res)
2074 goto fault;
2075 break;
2076
2077 case MIPS16e_sd_op:
2078writeDW:
2079#ifdef CONFIG_64BIT
2080 /*
2081 * A 32-bit kernel might be running on a 64-bit processor. But
2082 * if we're on a 32-bit processor and an i-cache incoherency
2083 * or race makes us see a 64-bit instruction here the sdl/sdr
2084 * would blow up, so for now we don't handle unaligned 64-bit
2085 * instructions on 32-bit kernels.
2086 */
2087 if (!access_ok(VERIFY_WRITE, addr, 8))
2088 goto sigbus;
2089
2090 MIPS16e_compute_return_epc(regs, &oldinst);
2091 value = regs->regs[reg];
2092 StoreDW(addr, value, res);
2093 if (res)
2094 goto fault;
2095 break;
2096#endif /* CONFIG_64BIT */
2097
2098 /* Cannot handle 64-bit instructions in 32-bit kernel */
2099 goto sigill;
2100
2101 default:
2102 /*
2103 * Pheeee... We encountered an yet unknown instruction or
2104 * cache coherence problem. Die sucker, die ...
2105 */
2106 goto sigill;
2107 }
2108
2109#ifdef CONFIG_DEBUG_FS
2110 unaligned_instructions++;
2111#endif
2112
2113 return;
2114
2115fault:
2116 /* roll back jump/branch */
2117 regs->cp0_epc = origpc;
2118 regs->regs[31] = orig31;
2119 /* Did we have an exception handler installed? */
2120 if (fixup_exception(regs))
2121 return;
2122
2123 die_if_kernel("Unhandled kernel unaligned access", regs);
2124 force_sig(SIGSEGV, current);
2125
2126 return;
2127
2128sigbus:
2129 die_if_kernel("Unhandled kernel unaligned access", regs);
2130 force_sig(SIGBUS, current);
2131
2132 return;
2133
2134sigill:
2135 die_if_kernel
2136 ("Unhandled kernel unaligned access or invalid instruction", regs);
2137 force_sig(SIGILL, current);
2138}
Tony Wufc192e52013-06-21 10:10:46 +00002139
Linus Torvalds1da177e2005-04-16 15:20:36 -07002140asmlinkage void do_ade(struct pt_regs *regs)
2141{
Ralf Baechlec3fc5cd2013-05-29 01:07:19 +02002142 enum ctx_state prev_state;
Ralf Baechlefe00f942005-03-01 19:22:29 +00002143 unsigned int __user *pc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002144 mm_segment_t seg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002145
Ralf Baechlec3fc5cd2013-05-29 01:07:19 +02002146 prev_state = exception_enter();
Deng-Cheng Zhu7f788d22010-10-12 19:37:21 +08002147 perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS,
Peter Zijlstraa8b0ca12011-06-27 14:41:57 +02002148 1, regs, regs->cp0_badvaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002149 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002150 * Did we catch a fault trying to load an instruction?
Linus Torvalds1da177e2005-04-16 15:20:36 -07002151 */
Leonid Yegoshin34c2f662013-03-25 13:18:07 -05002152 if (regs->cp0_badvaddr == regs->cp0_epc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002153 goto sigbus;
2154
Ralf Baechle293c5bd2007-07-25 16:19:33 +01002155 if (user_mode(regs) && !test_thread_flag(TIF_FIXADE))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002156 goto sigbus;
Atsushi Nemoto6312e0e2007-06-30 00:55:48 +09002157 if (unaligned_action == UNALIGNED_ACTION_SIGNAL)
2158 goto sigbus;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002159
2160 /*
2161 * Do branch emulation only if we didn't forward the exception.
2162 * This is all so but ugly ...
2163 */
Leonid Yegoshin34c2f662013-03-25 13:18:07 -05002164
2165 /*
2166 * Are we running in microMIPS mode?
2167 */
2168 if (get_isa16_mode(regs->cp0_epc)) {
2169 /*
2170 * Did we catch a fault trying to load an instruction in
2171 * 16-bit mode?
2172 */
2173 if (regs->cp0_badvaddr == msk_isa16_mode(regs->cp0_epc))
2174 goto sigbus;
2175 if (unaligned_action == UNALIGNED_ACTION_SHOW)
2176 show_registers(regs);
2177
2178 if (cpu_has_mmips) {
2179 seg = get_fs();
2180 if (!user_mode(regs))
2181 set_fs(KERNEL_DS);
2182 emulate_load_store_microMIPS(regs,
2183 (void __user *)regs->cp0_badvaddr);
2184 set_fs(seg);
2185
2186 return;
2187 }
2188
Steven J. Hill451b0012013-03-25 13:46:15 -05002189 if (cpu_has_mips16) {
2190 seg = get_fs();
2191 if (!user_mode(regs))
2192 set_fs(KERNEL_DS);
2193 emulate_load_store_MIPS16e(regs,
2194 (void __user *)regs->cp0_badvaddr);
2195 set_fs(seg);
2196
2197 return;
2198 }
2199
Leonid Yegoshin34c2f662013-03-25 13:18:07 -05002200 goto sigbus;
2201 }
2202
2203 if (unaligned_action == UNALIGNED_ACTION_SHOW)
2204 show_registers(regs);
2205 pc = (unsigned int __user *)exception_epc(regs);
2206
Linus Torvalds1da177e2005-04-16 15:20:36 -07002207 seg = get_fs();
2208 if (!user_mode(regs))
2209 set_fs(KERNEL_DS);
Ralf Baechle7f18f152007-07-29 09:16:19 +01002210 emulate_load_store_insn(regs, (void __user *)regs->cp0_badvaddr, pc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002211 set_fs(seg);
2212
2213 return;
2214
2215sigbus:
2216 die_if_kernel("Kernel unaligned instruction access", regs);
2217 force_sig(SIGBUS, current);
2218
2219 /*
2220 * XXX On return from the signal handler we should advance the epc
2221 */
Ralf Baechlec3fc5cd2013-05-29 01:07:19 +02002222 exception_exit(prev_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002223}
Atsushi Nemoto6312e0e2007-06-30 00:55:48 +09002224
2225#ifdef CONFIG_DEBUG_FS
2226extern struct dentry *mips_debugfs_dir;
2227static int __init debugfs_unaligned(void)
2228{
2229 struct dentry *d;
2230
2231 if (!mips_debugfs_dir)
2232 return -ENODEV;
2233 d = debugfs_create_u32("unaligned_instructions", S_IRUGO,
2234 mips_debugfs_dir, &unaligned_instructions);
Zhaoleib517531c2008-10-17 19:12:35 +08002235 if (!d)
2236 return -ENOMEM;
Atsushi Nemoto6312e0e2007-06-30 00:55:48 +09002237 d = debugfs_create_u32("unaligned_action", S_IRUGO | S_IWUSR,
2238 mips_debugfs_dir, &unaligned_action);
Zhaoleib517531c2008-10-17 19:12:35 +08002239 if (!d)
2240 return -ENOMEM;
Atsushi Nemoto6312e0e2007-06-30 00:55:48 +09002241 return 0;
2242}
2243__initcall(debugfs_unaligned);
2244#endif