aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarkos Chandras <markos.chandras@imgtec.com>2015-03-09 10:54:50 -0400
committerRalf Baechle <ralf@linux-mips.org>2015-04-10 09:41:44 -0400
commiteeb538950367e3966cbf0237ab1a1dc30e059818 (patch)
treee5d34952dce301ed1095b54997958dede5cec80f
parent60cd7e08e453bc6828ac4b539f949e4acd80f143 (diff)
MIPS: unaligned: Prevent EVA instructions on kernel unaligned accesses
Commit c1771216ab48 ("MIPS: kernel: unaligned: Handle unaligned accesses for EVA") allowed unaligned accesses to be emulated for EVA. However, when emulating regular load/store unaligned accesses, we need to use the appropriate "address space" instructions for that. Previously, an unaligned load/store instruction in kernel space would have used the corresponding EVA instructions to emulate it which led to segmentation faults because of the address translation that happens with EVA instructions. This is now fixed by using the EVA instruction only when emulating EVA unaligned accesses. Signed-off-by: Markos Chandras <markos.chandras@imgtec.com> Fixes: c1771216ab48 ("MIPS: kernel: unaligned: Handle unaligned accesses for EVA") Cc: <stable@vger.kernel.org> # v3.15+ Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/9501/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
-rw-r--r--arch/mips/kernel/unaligned.c172
1 files changed, 94 insertions, 78 deletions
diff --git a/arch/mips/kernel/unaligned.c b/arch/mips/kernel/unaligned.c
index bbb69695a0a1..7a5707eea898 100644
--- a/arch/mips/kernel/unaligned.c
+++ b/arch/mips/kernel/unaligned.c
@@ -109,10 +109,10 @@ static u32 unaligned_action;
109extern void show_registers(struct pt_regs *regs); 109extern void show_registers(struct pt_regs *regs);
110 110
111#ifdef __BIG_ENDIAN 111#ifdef __BIG_ENDIAN
112#define LoadHW(addr, value, res) \ 112#define _LoadHW(addr, value, res, type) \
113 __asm__ __volatile__ (".set\tnoat\n" \ 113 __asm__ __volatile__ (".set\tnoat\n" \
114 "1:\t"user_lb("%0", "0(%2)")"\n" \ 114 "1:\t"type##_lb("%0", "0(%2)")"\n" \
115 "2:\t"user_lbu("$1", "1(%2)")"\n\t" \ 115 "2:\t"type##_lbu("$1", "1(%2)")"\n\t"\
116 "sll\t%0, 0x8\n\t" \ 116 "sll\t%0, 0x8\n\t" \
117 "or\t%0, $1\n\t" \ 117 "or\t%0, $1\n\t" \
118 "li\t%1, 0\n" \ 118 "li\t%1, 0\n" \
@@ -130,10 +130,10 @@ extern void show_registers(struct pt_regs *regs);
130 : "r" (addr), "i" (-EFAULT)); 130 : "r" (addr), "i" (-EFAULT));
131 131
132#ifndef CONFIG_CPU_MIPSR6 132#ifndef CONFIG_CPU_MIPSR6
133#define LoadW(addr, value, res) \ 133#define _LoadW(addr, value, res, type) \
134 __asm__ __volatile__ ( \ 134 __asm__ __volatile__ ( \
135 "1:\t"user_lwl("%0", "(%2)")"\n" \ 135 "1:\t"type##_lwl("%0", "(%2)")"\n" \
136 "2:\t"user_lwr("%0", "3(%2)")"\n\t" \ 136 "2:\t"type##_lwr("%0", "3(%2)")"\n\t"\
137 "li\t%1, 0\n" \ 137 "li\t%1, 0\n" \
138 "3:\n\t" \ 138 "3:\n\t" \
139 ".insn\n\t" \ 139 ".insn\n\t" \
@@ -149,18 +149,18 @@ extern void show_registers(struct pt_regs *regs);
149 : "r" (addr), "i" (-EFAULT)); 149 : "r" (addr), "i" (-EFAULT));
150#else 150#else
151/* MIPSR6 has no lwl instruction */ 151/* MIPSR6 has no lwl instruction */
152#define LoadW(addr, value, res) \ 152#define _LoadW(addr, value, res, type) \
153 __asm__ __volatile__ ( \ 153 __asm__ __volatile__ ( \
154 ".set\tpush\n" \ 154 ".set\tpush\n" \
155 ".set\tnoat\n\t" \ 155 ".set\tnoat\n\t" \
156 "1:"user_lb("%0", "0(%2)")"\n\t" \ 156 "1:"type##_lb("%0", "0(%2)")"\n\t" \
157 "2:"user_lbu("$1", "1(%2)")"\n\t" \ 157 "2:"type##_lbu("$1", "1(%2)")"\n\t" \
158 "sll\t%0, 0x8\n\t" \ 158 "sll\t%0, 0x8\n\t" \
159 "or\t%0, $1\n\t" \ 159 "or\t%0, $1\n\t" \
160 "3:"user_lbu("$1", "2(%2)")"\n\t" \ 160 "3:"type##_lbu("$1", "2(%2)")"\n\t" \
161 "sll\t%0, 0x8\n\t" \ 161 "sll\t%0, 0x8\n\t" \
162 "or\t%0, $1\n\t" \ 162 "or\t%0, $1\n\t" \
163 "4:"user_lbu("$1", "3(%2)")"\n\t" \ 163 "4:"type##_lbu("$1", "3(%2)")"\n\t" \
164 "sll\t%0, 0x8\n\t" \ 164 "sll\t%0, 0x8\n\t" \
165 "or\t%0, $1\n\t" \ 165 "or\t%0, $1\n\t" \
166 "li\t%1, 0\n" \ 166 "li\t%1, 0\n" \
@@ -181,11 +181,11 @@ extern void show_registers(struct pt_regs *regs);
181 : "r" (addr), "i" (-EFAULT)); 181 : "r" (addr), "i" (-EFAULT));
182#endif /* CONFIG_CPU_MIPSR6 */ 182#endif /* CONFIG_CPU_MIPSR6 */
183 183
184#define LoadHWU(addr, value, res) \ 184#define _LoadHWU(addr, value, res, type) \
185 __asm__ __volatile__ ( \ 185 __asm__ __volatile__ ( \
186 ".set\tnoat\n" \ 186 ".set\tnoat\n" \
187 "1:\t"user_lbu("%0", "0(%2)")"\n" \ 187 "1:\t"type##_lbu("%0", "0(%2)")"\n" \
188 "2:\t"user_lbu("$1", "1(%2)")"\n\t" \ 188 "2:\t"type##_lbu("$1", "1(%2)")"\n\t"\
189 "sll\t%0, 0x8\n\t" \ 189 "sll\t%0, 0x8\n\t" \
190 "or\t%0, $1\n\t" \ 190 "or\t%0, $1\n\t" \
191 "li\t%1, 0\n" \ 191 "li\t%1, 0\n" \
@@ -204,10 +204,10 @@ extern void show_registers(struct pt_regs *regs);
204 : "r" (addr), "i" (-EFAULT)); 204 : "r" (addr), "i" (-EFAULT));
205 205
206#ifndef CONFIG_CPU_MIPSR6 206#ifndef CONFIG_CPU_MIPSR6
207#define LoadWU(addr, value, res) \ 207#define _LoadWU(addr, value, res, type) \
208 __asm__ __volatile__ ( \ 208 __asm__ __volatile__ ( \
209 "1:\t"user_lwl("%0", "(%2)")"\n" \ 209 "1:\t"type##_lwl("%0", "(%2)")"\n" \
210 "2:\t"user_lwr("%0", "3(%2)")"\n\t" \ 210 "2:\t"type##_lwr("%0", "3(%2)")"\n\t"\
211 "dsll\t%0, %0, 32\n\t" \ 211 "dsll\t%0, %0, 32\n\t" \
212 "dsrl\t%0, %0, 32\n\t" \ 212 "dsrl\t%0, %0, 32\n\t" \
213 "li\t%1, 0\n" \ 213 "li\t%1, 0\n" \
@@ -224,7 +224,7 @@ extern void show_registers(struct pt_regs *regs);
224 : "=&r" (value), "=r" (res) \ 224 : "=&r" (value), "=r" (res) \
225 : "r" (addr), "i" (-EFAULT)); 225 : "r" (addr), "i" (-EFAULT));
226 226
227#define LoadDW(addr, value, res) \ 227#define _LoadDW(addr, value, res) \
228 __asm__ __volatile__ ( \ 228 __asm__ __volatile__ ( \
229 "1:\tldl\t%0, (%2)\n" \ 229 "1:\tldl\t%0, (%2)\n" \
230 "2:\tldr\t%0, 7(%2)\n\t" \ 230 "2:\tldr\t%0, 7(%2)\n\t" \
@@ -243,18 +243,18 @@ extern void show_registers(struct pt_regs *regs);
243 : "r" (addr), "i" (-EFAULT)); 243 : "r" (addr), "i" (-EFAULT));
244#else 244#else
245/* MIPSR6 has not lwl and ldl instructions */ 245/* MIPSR6 has not lwl and ldl instructions */
246#define LoadWU(addr, value, res) \ 246#define _LoadWU(addr, value, res, type) \
247 __asm__ __volatile__ ( \ 247 __asm__ __volatile__ ( \
248 ".set\tpush\n\t" \ 248 ".set\tpush\n\t" \
249 ".set\tnoat\n\t" \ 249 ".set\tnoat\n\t" \
250 "1:"user_lbu("%0", "0(%2)")"\n\t" \ 250 "1:"type##_lbu("%0", "0(%2)")"\n\t" \
251 "2:"user_lbu("$1", "1(%2)")"\n\t" \ 251 "2:"type##_lbu("$1", "1(%2)")"\n\t" \
252 "sll\t%0, 0x8\n\t" \ 252 "sll\t%0, 0x8\n\t" \
253 "or\t%0, $1\n\t" \ 253 "or\t%0, $1\n\t" \
254 "3:"user_lbu("$1", "2(%2)")"\n\t" \ 254 "3:"type##_lbu("$1", "2(%2)")"\n\t" \
255 "sll\t%0, 0x8\n\t" \ 255 "sll\t%0, 0x8\n\t" \
256 "or\t%0, $1\n\t" \ 256 "or\t%0, $1\n\t" \
257 "4:"user_lbu("$1", "3(%2)")"\n\t" \ 257 "4:"type##_lbu("$1", "3(%2)")"\n\t" \
258 "sll\t%0, 0x8\n\t" \ 258 "sll\t%0, 0x8\n\t" \
259 "or\t%0, $1\n\t" \ 259 "or\t%0, $1\n\t" \
260 "li\t%1, 0\n" \ 260 "li\t%1, 0\n" \
@@ -274,7 +274,7 @@ extern void show_registers(struct pt_regs *regs);
274 : "=&r" (value), "=r" (res) \ 274 : "=&r" (value), "=r" (res) \
275 : "r" (addr), "i" (-EFAULT)); 275 : "r" (addr), "i" (-EFAULT));
276 276
277#define LoadDW(addr, value, res) \ 277#define _LoadDW(addr, value, res) \
278 __asm__ __volatile__ ( \ 278 __asm__ __volatile__ ( \
279 ".set\tpush\n\t" \ 279 ".set\tpush\n\t" \
280 ".set\tnoat\n\t" \ 280 ".set\tnoat\n\t" \
@@ -323,12 +323,12 @@ extern void show_registers(struct pt_regs *regs);
323#endif /* CONFIG_CPU_MIPSR6 */ 323#endif /* CONFIG_CPU_MIPSR6 */
324 324
325 325
326#define StoreHW(addr, value, res) \ 326#define _StoreHW(addr, value, res, type) \
327 __asm__ __volatile__ ( \ 327 __asm__ __volatile__ ( \
328 ".set\tnoat\n" \ 328 ".set\tnoat\n" \
329 "1:\t"user_sb("%1", "1(%2)")"\n" \ 329 "1:\t"type##_sb("%1", "1(%2)")"\n" \
330 "srl\t$1, %1, 0x8\n" \ 330 "srl\t$1, %1, 0x8\n" \
331 "2:\t"user_sb("$1", "0(%2)")"\n" \ 331 "2:\t"type##_sb("$1", "0(%2)")"\n" \
332 ".set\tat\n\t" \ 332 ".set\tat\n\t" \
333 "li\t%0, 0\n" \ 333 "li\t%0, 0\n" \
334 "3:\n\t" \ 334 "3:\n\t" \
@@ -345,10 +345,10 @@ extern void show_registers(struct pt_regs *regs);
345 : "r" (value), "r" (addr), "i" (-EFAULT)); 345 : "r" (value), "r" (addr), "i" (-EFAULT));
346 346
347#ifndef CONFIG_CPU_MIPSR6 347#ifndef CONFIG_CPU_MIPSR6
348#define StoreW(addr, value, res) \ 348#define _StoreW(addr, value, res, type) \
349 __asm__ __volatile__ ( \ 349 __asm__ __volatile__ ( \
350 "1:\t"user_swl("%1", "(%2)")"\n" \ 350 "1:\t"type##_swl("%1", "(%2)")"\n" \
351 "2:\t"user_swr("%1", "3(%2)")"\n\t" \ 351 "2:\t"type##_swr("%1", "3(%2)")"\n\t"\
352 "li\t%0, 0\n" \ 352 "li\t%0, 0\n" \
353 "3:\n\t" \ 353 "3:\n\t" \
354 ".insn\n\t" \ 354 ".insn\n\t" \
@@ -363,7 +363,7 @@ extern void show_registers(struct pt_regs *regs);
363 : "=r" (res) \ 363 : "=r" (res) \
364 : "r" (value), "r" (addr), "i" (-EFAULT)); 364 : "r" (value), "r" (addr), "i" (-EFAULT));
365 365
366#define StoreDW(addr, value, res) \ 366#define _StoreDW(addr, value, res) \
367 __asm__ __volatile__ ( \ 367 __asm__ __volatile__ ( \
368 "1:\tsdl\t%1,(%2)\n" \ 368 "1:\tsdl\t%1,(%2)\n" \
369 "2:\tsdr\t%1, 7(%2)\n\t" \ 369 "2:\tsdr\t%1, 7(%2)\n\t" \
@@ -382,17 +382,17 @@ extern void show_registers(struct pt_regs *regs);
382 : "r" (value), "r" (addr), "i" (-EFAULT)); 382 : "r" (value), "r" (addr), "i" (-EFAULT));
383#else 383#else
384/* MIPSR6 has no swl and sdl instructions */ 384/* MIPSR6 has no swl and sdl instructions */
385#define StoreW(addr, value, res) \ 385#define _StoreW(addr, value, res, type) \
386 __asm__ __volatile__ ( \ 386 __asm__ __volatile__ ( \
387 ".set\tpush\n\t" \ 387 ".set\tpush\n\t" \
388 ".set\tnoat\n\t" \ 388 ".set\tnoat\n\t" \
389 "1:"user_sb("%1", "3(%2)")"\n\t" \ 389 "1:"type##_sb("%1", "3(%2)")"\n\t" \
390 "srl\t$1, %1, 0x8\n\t" \ 390 "srl\t$1, %1, 0x8\n\t" \
391 "2:"user_sb("$1", "2(%2)")"\n\t" \ 391 "2:"type##_sb("$1", "2(%2)")"\n\t" \
392 "srl\t$1, $1, 0x8\n\t" \ 392 "srl\t$1, $1, 0x8\n\t" \
393 "3:"user_sb("$1", "1(%2)")"\n\t" \ 393 "3:"type##_sb("$1", "1(%2)")"\n\t" \
394 "srl\t$1, $1, 0x8\n\t" \ 394 "srl\t$1, $1, 0x8\n\t" \
395 "4:"user_sb("$1", "0(%2)")"\n\t" \ 395 "4:"type##_sb("$1", "0(%2)")"\n\t" \
396 ".set\tpop\n\t" \ 396 ".set\tpop\n\t" \
397 "li\t%0, 0\n" \ 397 "li\t%0, 0\n" \
398 "10:\n\t" \ 398 "10:\n\t" \
@@ -456,10 +456,10 @@ extern void show_registers(struct pt_regs *regs);
456 456
457#else /* __BIG_ENDIAN */ 457#else /* __BIG_ENDIAN */
458 458
459#define LoadHW(addr, value, res) \ 459#define _LoadHW(addr, value, res, type) \
460 __asm__ __volatile__ (".set\tnoat\n" \ 460 __asm__ __volatile__ (".set\tnoat\n" \
461 "1:\t"user_lb("%0", "1(%2)")"\n" \ 461 "1:\t"type##_lb("%0", "1(%2)")"\n" \
462 "2:\t"user_lbu("$1", "0(%2)")"\n\t" \ 462 "2:\t"type##_lbu("$1", "0(%2)")"\n\t"\
463 "sll\t%0, 0x8\n\t" \ 463 "sll\t%0, 0x8\n\t" \
464 "or\t%0, $1\n\t" \ 464 "or\t%0, $1\n\t" \
465 "li\t%1, 0\n" \ 465 "li\t%1, 0\n" \
@@ -477,10 +477,10 @@ extern void show_registers(struct pt_regs *regs);
477 : "r" (addr), "i" (-EFAULT)); 477 : "r" (addr), "i" (-EFAULT));
478 478
479#ifndef CONFIG_CPU_MIPSR6 479#ifndef CONFIG_CPU_MIPSR6
480#define LoadW(addr, value, res) \ 480#define _LoadW(addr, value, res, type) \
481 __asm__ __volatile__ ( \ 481 __asm__ __volatile__ ( \
482 "1:\t"user_lwl("%0", "3(%2)")"\n" \ 482 "1:\t"type##_lwl("%0", "3(%2)")"\n" \
483 "2:\t"user_lwr("%0", "(%2)")"\n\t" \ 483 "2:\t"type##_lwr("%0", "(%2)")"\n\t"\
484 "li\t%1, 0\n" \ 484 "li\t%1, 0\n" \
485 "3:\n\t" \ 485 "3:\n\t" \
486 ".insn\n\t" \ 486 ".insn\n\t" \
@@ -496,18 +496,18 @@ extern void show_registers(struct pt_regs *regs);
496 : "r" (addr), "i" (-EFAULT)); 496 : "r" (addr), "i" (-EFAULT));
497#else 497#else
498/* MIPSR6 has no lwl instruction */ 498/* MIPSR6 has no lwl instruction */
499#define LoadW(addr, value, res) \ 499#define _LoadW(addr, value, res, type) \
500 __asm__ __volatile__ ( \ 500 __asm__ __volatile__ ( \
501 ".set\tpush\n" \ 501 ".set\tpush\n" \
502 ".set\tnoat\n\t" \ 502 ".set\tnoat\n\t" \
503 "1:"user_lb("%0", "3(%2)")"\n\t" \ 503 "1:"type##_lb("%0", "3(%2)")"\n\t" \
504 "2:"user_lbu("$1", "2(%2)")"\n\t" \ 504 "2:"type##_lbu("$1", "2(%2)")"\n\t" \
505 "sll\t%0, 0x8\n\t" \ 505 "sll\t%0, 0x8\n\t" \
506 "or\t%0, $1\n\t" \ 506 "or\t%0, $1\n\t" \
507 "3:"user_lbu("$1", "1(%2)")"\n\t" \ 507 "3:"type##_lbu("$1", "1(%2)")"\n\t" \
508 "sll\t%0, 0x8\n\t" \ 508 "sll\t%0, 0x8\n\t" \
509 "or\t%0, $1\n\t" \ 509 "or\t%0, $1\n\t" \
510 "4:"user_lbu("$1", "0(%2)")"\n\t" \ 510 "4:"type##_lbu("$1", "0(%2)")"\n\t" \
511 "sll\t%0, 0x8\n\t" \ 511 "sll\t%0, 0x8\n\t" \
512 "or\t%0, $1\n\t" \ 512 "or\t%0, $1\n\t" \
513 "li\t%1, 0\n" \ 513 "li\t%1, 0\n" \
@@ -529,11 +529,11 @@ extern void show_registers(struct pt_regs *regs);
529#endif /* CONFIG_CPU_MIPSR6 */ 529#endif /* CONFIG_CPU_MIPSR6 */
530 530
531 531
532#define LoadHWU(addr, value, res) \ 532#define _LoadHWU(addr, value, res, type) \
533 __asm__ __volatile__ ( \ 533 __asm__ __volatile__ ( \
534 ".set\tnoat\n" \ 534 ".set\tnoat\n" \
535 "1:\t"user_lbu("%0", "1(%2)")"\n" \ 535 "1:\t"type##_lbu("%0", "1(%2)")"\n" \
536 "2:\t"user_lbu("$1", "0(%2)")"\n\t" \ 536 "2:\t"type##_lbu("$1", "0(%2)")"\n\t"\
537 "sll\t%0, 0x8\n\t" \ 537 "sll\t%0, 0x8\n\t" \
538 "or\t%0, $1\n\t" \ 538 "or\t%0, $1\n\t" \
539 "li\t%1, 0\n" \ 539 "li\t%1, 0\n" \
@@ -552,10 +552,10 @@ extern void show_registers(struct pt_regs *regs);
552 : "r" (addr), "i" (-EFAULT)); 552 : "r" (addr), "i" (-EFAULT));
553 553
554#ifndef CONFIG_CPU_MIPSR6 554#ifndef CONFIG_CPU_MIPSR6
555#define LoadWU(addr, value, res) \ 555#define _LoadWU(addr, value, res, type) \
556 __asm__ __volatile__ ( \ 556 __asm__ __volatile__ ( \
557 "1:\t"user_lwl("%0", "3(%2)")"\n" \ 557 "1:\t"type##_lwl("%0", "3(%2)")"\n" \
558 "2:\t"user_lwr("%0", "(%2)")"\n\t" \ 558 "2:\t"type##_lwr("%0", "(%2)")"\n\t"\
559 "dsll\t%0, %0, 32\n\t" \ 559 "dsll\t%0, %0, 32\n\t" \
560 "dsrl\t%0, %0, 32\n\t" \ 560 "dsrl\t%0, %0, 32\n\t" \
561 "li\t%1, 0\n" \ 561 "li\t%1, 0\n" \
@@ -572,7 +572,7 @@ extern void show_registers(struct pt_regs *regs);
572 : "=&r" (value), "=r" (res) \ 572 : "=&r" (value), "=r" (res) \
573 : "r" (addr), "i" (-EFAULT)); 573 : "r" (addr), "i" (-EFAULT));
574 574
575#define LoadDW(addr, value, res) \ 575#define _LoadDW(addr, value, res) \
576 __asm__ __volatile__ ( \ 576 __asm__ __volatile__ ( \
577 "1:\tldl\t%0, 7(%2)\n" \ 577 "1:\tldl\t%0, 7(%2)\n" \
578 "2:\tldr\t%0, (%2)\n\t" \ 578 "2:\tldr\t%0, (%2)\n\t" \
@@ -591,18 +591,18 @@ extern void show_registers(struct pt_regs *regs);
591 : "r" (addr), "i" (-EFAULT)); 591 : "r" (addr), "i" (-EFAULT));
592#else 592#else
593/* MIPSR6 has not lwl and ldl instructions */ 593/* MIPSR6 has not lwl and ldl instructions */
594#define LoadWU(addr, value, res) \ 594#define _LoadWU(addr, value, res, type) \
595 __asm__ __volatile__ ( \ 595 __asm__ __volatile__ ( \
596 ".set\tpush\n\t" \ 596 ".set\tpush\n\t" \
597 ".set\tnoat\n\t" \ 597 ".set\tnoat\n\t" \
598 "1:"user_lbu("%0", "3(%2)")"\n\t" \ 598 "1:"type##_lbu("%0", "3(%2)")"\n\t" \
599 "2:"user_lbu("$1", "2(%2)")"\n\t" \ 599 "2:"type##_lbu("$1", "2(%2)")"\n\t" \
600 "sll\t%0, 0x8\n\t" \ 600 "sll\t%0, 0x8\n\t" \
601 "or\t%0, $1\n\t" \ 601 "or\t%0, $1\n\t" \
602 "3:"user_lbu("$1", "1(%2)")"\n\t" \ 602 "3:"type##_lbu("$1", "1(%2)")"\n\t" \
603 "sll\t%0, 0x8\n\t" \ 603 "sll\t%0, 0x8\n\t" \
604 "or\t%0, $1\n\t" \ 604 "or\t%0, $1\n\t" \
605 "4:"user_lbu("$1", "0(%2)")"\n\t" \ 605 "4:"type##_lbu("$1", "0(%2)")"\n\t" \
606 "sll\t%0, 0x8\n\t" \ 606 "sll\t%0, 0x8\n\t" \
607 "or\t%0, $1\n\t" \ 607 "or\t%0, $1\n\t" \
608 "li\t%1, 0\n" \ 608 "li\t%1, 0\n" \
@@ -622,7 +622,7 @@ extern void show_registers(struct pt_regs *regs);
622 : "=&r" (value), "=r" (res) \ 622 : "=&r" (value), "=r" (res) \
623 : "r" (addr), "i" (-EFAULT)); 623 : "r" (addr), "i" (-EFAULT));
624 624
625#define LoadDW(addr, value, res) \ 625#define _LoadDW(addr, value, res) \
626 __asm__ __volatile__ ( \ 626 __asm__ __volatile__ ( \
627 ".set\tpush\n\t" \ 627 ".set\tpush\n\t" \
628 ".set\tnoat\n\t" \ 628 ".set\tnoat\n\t" \
@@ -670,12 +670,12 @@ extern void show_registers(struct pt_regs *regs);
670 : "r" (addr), "i" (-EFAULT)); 670 : "r" (addr), "i" (-EFAULT));
671#endif /* CONFIG_CPU_MIPSR6 */ 671#endif /* CONFIG_CPU_MIPSR6 */
672 672
673#define StoreHW(addr, value, res) \ 673#define _StoreHW(addr, value, res, type) \
674 __asm__ __volatile__ ( \ 674 __asm__ __volatile__ ( \
675 ".set\tnoat\n" \ 675 ".set\tnoat\n" \
676 "1:\t"user_sb("%1", "0(%2)")"\n" \ 676 "1:\t"type##_sb("%1", "0(%2)")"\n" \
677 "srl\t$1,%1, 0x8\n" \ 677 "srl\t$1,%1, 0x8\n" \
678 "2:\t"user_sb("$1", "1(%2)")"\n" \ 678 "2:\t"type##_sb("$1", "1(%2)")"\n" \
679 ".set\tat\n\t" \ 679 ".set\tat\n\t" \
680 "li\t%0, 0\n" \ 680 "li\t%0, 0\n" \
681 "3:\n\t" \ 681 "3:\n\t" \
@@ -691,10 +691,10 @@ extern void show_registers(struct pt_regs *regs);
691 : "=r" (res) \ 691 : "=r" (res) \
692 : "r" (value), "r" (addr), "i" (-EFAULT)); 692 : "r" (value), "r" (addr), "i" (-EFAULT));
693#ifndef CONFIG_CPU_MIPSR6 693#ifndef CONFIG_CPU_MIPSR6
694#define StoreW(addr, value, res) \ 694#define _StoreW(addr, value, res, type) \
695 __asm__ __volatile__ ( \ 695 __asm__ __volatile__ ( \
696 "1:\t"user_swl("%1", "3(%2)")"\n" \ 696 "1:\t"type##_swl("%1", "3(%2)")"\n" \
697 "2:\t"user_swr("%1", "(%2)")"\n\t" \ 697 "2:\t"type##_swr("%1", "(%2)")"\n\t"\
698 "li\t%0, 0\n" \ 698 "li\t%0, 0\n" \
699 "3:\n\t" \ 699 "3:\n\t" \
700 ".insn\n\t" \ 700 ".insn\n\t" \
@@ -709,7 +709,7 @@ extern void show_registers(struct pt_regs *regs);
709 : "=r" (res) \ 709 : "=r" (res) \
710 : "r" (value), "r" (addr), "i" (-EFAULT)); 710 : "r" (value), "r" (addr), "i" (-EFAULT));
711 711
712#define StoreDW(addr, value, res) \ 712#define _StoreDW(addr, value, res) \
713 __asm__ __volatile__ ( \ 713 __asm__ __volatile__ ( \
714 "1:\tsdl\t%1, 7(%2)\n" \ 714 "1:\tsdl\t%1, 7(%2)\n" \
715 "2:\tsdr\t%1, (%2)\n\t" \ 715 "2:\tsdr\t%1, (%2)\n\t" \
@@ -728,17 +728,17 @@ extern void show_registers(struct pt_regs *regs);
728 : "r" (value), "r" (addr), "i" (-EFAULT)); 728 : "r" (value), "r" (addr), "i" (-EFAULT));
729#else 729#else
730/* MIPSR6 has no swl and sdl instructions */ 730/* MIPSR6 has no swl and sdl instructions */
731#define StoreW(addr, value, res) \ 731#define _StoreW(addr, value, res, type) \
732 __asm__ __volatile__ ( \ 732 __asm__ __volatile__ ( \
733 ".set\tpush\n\t" \ 733 ".set\tpush\n\t" \
734 ".set\tnoat\n\t" \ 734 ".set\tnoat\n\t" \
735 "1:"user_sb("%1", "0(%2)")"\n\t" \ 735 "1:"type##_sb("%1", "0(%2)")"\n\t" \
736 "srl\t$1, %1, 0x8\n\t" \ 736 "srl\t$1, %1, 0x8\n\t" \
737 "2:"user_sb("$1", "1(%2)")"\n\t" \ 737 "2:"type##_sb("$1", "1(%2)")"\n\t" \
738 "srl\t$1, $1, 0x8\n\t" \ 738 "srl\t$1, $1, 0x8\n\t" \
739 "3:"user_sb("$1", "2(%2)")"\n\t" \ 739 "3:"type##_sb("$1", "2(%2)")"\n\t" \
740 "srl\t$1, $1, 0x8\n\t" \ 740 "srl\t$1, $1, 0x8\n\t" \
741 "4:"user_sb("$1", "3(%2)")"\n\t" \ 741 "4:"type##_sb("$1", "3(%2)")"\n\t" \
742 ".set\tpop\n\t" \ 742 ".set\tpop\n\t" \
743 "li\t%0, 0\n" \ 743 "li\t%0, 0\n" \
744 "10:\n\t" \ 744 "10:\n\t" \
@@ -757,7 +757,7 @@ extern void show_registers(struct pt_regs *regs);
757 : "r" (value), "r" (addr), "i" (-EFAULT) \ 757 : "r" (value), "r" (addr), "i" (-EFAULT) \
758 : "memory"); 758 : "memory");
759 759
760#define StoreDW(addr, value, res) \ 760#define _StoreDW(addr, value, res) \
761 __asm__ __volatile__ ( \ 761 __asm__ __volatile__ ( \
762 ".set\tpush\n\t" \ 762 ".set\tpush\n\t" \
763 ".set\tnoat\n\t" \ 763 ".set\tnoat\n\t" \
@@ -801,6 +801,22 @@ extern void show_registers(struct pt_regs *regs);
801#endif /* CONFIG_CPU_MIPSR6 */ 801#endif /* CONFIG_CPU_MIPSR6 */
802#endif 802#endif
803 803
804#define LoadHWU(addr, value, res) _LoadHWU(addr, value, res, kernel)
805#define LoadHWUE(addr, value, res) _LoadHWU(addr, value, res, user)
806#define LoadWU(addr, value, res) _LoadWU(addr, value, res, kernel)
807#define LoadWUE(addr, value, res) _LoadWU(addr, value, res, user)
808#define LoadHW(addr, value, res) _LoadHW(addr, value, res, kernel)
809#define LoadHWE(addr, value, res) _LoadHW(addr, value, res, user)
810#define LoadW(addr, value, res) _LoadW(addr, value, res, kernel)
811#define LoadWE(addr, value, res) _LoadW(addr, value, res, user)
812#define LoadDW(addr, value, res) _LoadDW(addr, value, res)
813
814#define StoreHW(addr, value, res) _StoreHW(addr, value, res, kernel)
815#define StoreHWE(addr, value, res) _StoreHW(addr, value, res, user)
816#define StoreW(addr, value, res) _StoreW(addr, value, res, kernel)
817#define StoreWE(addr, value, res) _StoreW(addr, value, res, user)
818#define StoreDW(addr, value, res) _StoreDW(addr, value, res)
819
804static void emulate_load_store_insn(struct pt_regs *regs, 820static void emulate_load_store_insn(struct pt_regs *regs,
805 void __user *addr, unsigned int __user *pc) 821 void __user *addr, unsigned int __user *pc)
806{ 822{
@@ -872,7 +888,7 @@ static void emulate_load_store_insn(struct pt_regs *regs,
872 set_fs(seg); 888 set_fs(seg);
873 goto sigbus; 889 goto sigbus;
874 } 890 }
875 LoadHW(addr, value, res); 891 LoadHWE(addr, value, res);
876 if (res) { 892 if (res) {
877 set_fs(seg); 893 set_fs(seg);
878 goto fault; 894 goto fault;
@@ -885,7 +901,7 @@ static void emulate_load_store_insn(struct pt_regs *regs,
885 set_fs(seg); 901 set_fs(seg);
886 goto sigbus; 902 goto sigbus;
887 } 903 }
888 LoadW(addr, value, res); 904 LoadWE(addr, value, res);
889 if (res) { 905 if (res) {
890 set_fs(seg); 906 set_fs(seg);
891 goto fault; 907 goto fault;
@@ -898,7 +914,7 @@ static void emulate_load_store_insn(struct pt_regs *regs,
898 set_fs(seg); 914 set_fs(seg);
899 goto sigbus; 915 goto sigbus;
900 } 916 }
901 LoadHWU(addr, value, res); 917 LoadHWUE(addr, value, res);
902 if (res) { 918 if (res) {
903 set_fs(seg); 919 set_fs(seg);
904 goto fault; 920 goto fault;
@@ -913,7 +929,7 @@ static void emulate_load_store_insn(struct pt_regs *regs,
913 } 929 }
914 compute_return_epc(regs); 930 compute_return_epc(regs);
915 value = regs->regs[insn.spec3_format.rt]; 931 value = regs->regs[insn.spec3_format.rt];
916 StoreHW(addr, value, res); 932 StoreHWE(addr, value, res);
917 if (res) { 933 if (res) {
918 set_fs(seg); 934 set_fs(seg);
919 goto fault; 935 goto fault;
@@ -926,7 +942,7 @@ static void emulate_load_store_insn(struct pt_regs *regs,
926 } 942 }
927 compute_return_epc(regs); 943 compute_return_epc(regs);
928 value = regs->regs[insn.spec3_format.rt]; 944 value = regs->regs[insn.spec3_format.rt];
929 StoreW(addr, value, res); 945 StoreWE(addr, value, res);
930 if (res) { 946 if (res) {
931 set_fs(seg); 947 set_fs(seg);
932 goto fault; 948 goto fault;