cp1emu.c (8990c1bc4be46473ad19bf2fa612ca57286f3df4) | cp1emu.c (515b029d005b5694cf612a0a5ca6f861a7e45362) |
---|---|
1/* 2 * cp1emu.c: a MIPS coprocessor 1 (fpu) instruction emulator 3 * 4 * MIPS floating point support 5 * Copyright (C) 1994-2000 Algorithmics Ltd. 6 * 7 * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com 8 * Copyright (C) 2000 MIPS Technologies, Inc. --- 50 unchanged lines hidden (view full) --- 59 60/* Function which emulates a floating point instruction. */ 61 62static int fpu_emu(struct pt_regs *, struct mips_fpu_struct *, 63 mips_instruction); 64 65#if __mips >= 4 && __mips != 32 66static int fpux_emu(struct pt_regs *, | 1/* 2 * cp1emu.c: a MIPS coprocessor 1 (fpu) instruction emulator 3 * 4 * MIPS floating point support 5 * Copyright (C) 1994-2000 Algorithmics Ltd. 6 * 7 * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com 8 * Copyright (C) 2000 MIPS Technologies, Inc. --- 50 unchanged lines hidden (view full) --- 59 60/* Function which emulates a floating point instruction. */ 61 62static int fpu_emu(struct pt_regs *, struct mips_fpu_struct *, 63 mips_instruction); 64 65#if __mips >= 4 && __mips != 32 66static int fpux_emu(struct pt_regs *, |
67 struct mips_fpu_struct *, mips_instruction); | 67 struct mips_fpu_struct *, mips_instruction, void *__user *); |
68#endif 69 70/* Further private data for which no space exists in mips_fpu_struct */ 71 72#ifdef CONFIG_DEBUG_FS 73DEFINE_PER_CPU(struct mips_fpu_emulator_stats, fpuemustats); 74#endif 75 --- 127 unchanged lines hidden (view full) --- 203#define DPFROMREG(dp, x) DIFROMREG((dp).bits, x) 204#define DPTOREG(dp, x) DITOREG((dp).bits, x) 205 206/* 207 * Emulate the single floating point instruction pointed at by EPC. 208 * Two instructions if the instruction is in a branch delay slot. 209 */ 210 | 68#endif 69 70/* Further private data for which no space exists in mips_fpu_struct */ 71 72#ifdef CONFIG_DEBUG_FS 73DEFINE_PER_CPU(struct mips_fpu_emulator_stats, fpuemustats); 74#endif 75 --- 127 unchanged lines hidden (view full) --- 203#define DPFROMREG(dp, x) DIFROMREG((dp).bits, x) 204#define DPTOREG(dp, x) DITOREG((dp).bits, x) 205 206/* 207 * Emulate the single floating point instruction pointed at by EPC. 208 * Two instructions if the instruction is in a branch delay slot. 209 */ 210 |
211static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx) | 211static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx, 212 void *__user *fault_addr) |
212{ 213 mips_instruction ir; 214 unsigned long emulpc, contpc; 215 unsigned int cond; 216 | 213{ 214 mips_instruction ir; 215 unsigned long emulpc, contpc; 216 unsigned int cond; 217 |
217 if (get_user(ir, (mips_instruction __user *) xcp->cp0_epc)) { | 218 if (!access_ok(VERIFY_READ, xcp->cp0_epc, sizeof(mips_instruction))) { |
218 MIPS_FPU_EMU_INC_STATS(errors); | 219 MIPS_FPU_EMU_INC_STATS(errors); |
220 *fault_addr = (mips_instruction __user *)xcp->cp0_epc; |
|
219 return SIGBUS; 220 } | 221 return SIGBUS; 222 } |
223 if (__get_user(ir, (mips_instruction __user *) xcp->cp0_epc)) { 224 MIPS_FPU_EMU_INC_STATS(errors); 225 *fault_addr = (mips_instruction __user *)xcp->cp0_epc; 226 return SIGSEGV; 227 } |
|
221 222 /* XXX NEC Vr54xx bug workaround */ 223 if ((xcp->cp0_cause & CAUSEF_BD) && !isBranchInstr(&ir)) 224 xcp->cp0_cause &= ~CAUSEF_BD; 225 226 if (xcp->cp0_cause & CAUSEF_BD) { 227 /* 228 * The instruction to be emulated is in a branch delay slot --- 11 unchanged lines hidden (view full) --- 240 241 if (__compute_return_epc(xcp)) { 242#ifdef CP1DBG 243 printk("failed to emulate branch at %p\n", 244 (void *) (xcp->cp0_epc)); 245#endif 246 return SIGILL; 247 } | 228 229 /* XXX NEC Vr54xx bug workaround */ 230 if ((xcp->cp0_cause & CAUSEF_BD) && !isBranchInstr(&ir)) 231 xcp->cp0_cause &= ~CAUSEF_BD; 232 233 if (xcp->cp0_cause & CAUSEF_BD) { 234 /* 235 * The instruction to be emulated is in a branch delay slot --- 11 unchanged lines hidden (view full) --- 247 248 if (__compute_return_epc(xcp)) { 249#ifdef CP1DBG 250 printk("failed to emulate branch at %p\n", 251 (void *) (xcp->cp0_epc)); 252#endif 253 return SIGILL; 254 } |
248 if (get_user(ir, (mips_instruction __user *) emulpc)) { | 255 if (!access_ok(VERIFY_READ, emulpc, sizeof(mips_instruction))) { |
249 MIPS_FPU_EMU_INC_STATS(errors); | 256 MIPS_FPU_EMU_INC_STATS(errors); |
257 *fault_addr = (mips_instruction __user *)emulpc; |
|
250 return SIGBUS; 251 } | 258 return SIGBUS; 259 } |
260 if (__get_user(ir, (mips_instruction __user *) emulpc)) { 261 MIPS_FPU_EMU_INC_STATS(errors); 262 *fault_addr = (mips_instruction __user *)emulpc; 263 return SIGSEGV; 264 } |
|
252 /* __compute_return_epc() will have updated cp0_epc */ 253 contpc = xcp->cp0_epc; 254 /* In order not to confuse ptrace() et al, tweak context */ 255 xcp->cp0_epc = emulpc - 4; 256 } else { 257 emulpc = xcp->cp0_epc; 258 contpc = xcp->cp0_epc + 4; 259 } --- 4 unchanged lines hidden (view full) --- 264 MIPS_FPU_EMU_INC_STATS(emulated); 265 switch (MIPSInst_OPCODE(ir)) { 266 case ldc1_op:{ 267 u64 __user *va = (u64 __user *) (xcp->regs[MIPSInst_RS(ir)] + 268 MIPSInst_SIMM(ir)); 269 u64 val; 270 271 MIPS_FPU_EMU_INC_STATS(loads); | 265 /* __compute_return_epc() will have updated cp0_epc */ 266 contpc = xcp->cp0_epc; 267 /* In order not to confuse ptrace() et al, tweak context */ 268 xcp->cp0_epc = emulpc - 4; 269 } else { 270 emulpc = xcp->cp0_epc; 271 contpc = xcp->cp0_epc + 4; 272 } --- 4 unchanged lines hidden (view full) --- 277 MIPS_FPU_EMU_INC_STATS(emulated); 278 switch (MIPSInst_OPCODE(ir)) { 279 case ldc1_op:{ 280 u64 __user *va = (u64 __user *) (xcp->regs[MIPSInst_RS(ir)] + 281 MIPSInst_SIMM(ir)); 282 u64 val; 283 284 MIPS_FPU_EMU_INC_STATS(loads); |
272 if (get_user(val, va)) { | 285 286 if (!access_ok(VERIFY_READ, va, sizeof(u64))) { |
273 MIPS_FPU_EMU_INC_STATS(errors); | 287 MIPS_FPU_EMU_INC_STATS(errors); |
288 *fault_addr = va; |
|
274 return SIGBUS; 275 } | 289 return SIGBUS; 290 } |
291 if (__get_user(val, va)) { 292 MIPS_FPU_EMU_INC_STATS(errors); 293 *fault_addr = va; 294 return SIGSEGV; 295 } |
|
276 DITOREG(val, MIPSInst_RT(ir)); 277 break; 278 } 279 280 case sdc1_op:{ 281 u64 __user *va = (u64 __user *) (xcp->regs[MIPSInst_RS(ir)] + 282 MIPSInst_SIMM(ir)); 283 u64 val; 284 285 MIPS_FPU_EMU_INC_STATS(stores); 286 DIFROMREG(val, MIPSInst_RT(ir)); | 296 DITOREG(val, MIPSInst_RT(ir)); 297 break; 298 } 299 300 case sdc1_op:{ 301 u64 __user *va = (u64 __user *) (xcp->regs[MIPSInst_RS(ir)] + 302 MIPSInst_SIMM(ir)); 303 u64 val; 304 305 MIPS_FPU_EMU_INC_STATS(stores); 306 DIFROMREG(val, MIPSInst_RT(ir)); |
287 if (put_user(val, va)) { | 307 if (!access_ok(VERIFY_WRITE, va, sizeof(u64))) { |
288 MIPS_FPU_EMU_INC_STATS(errors); | 308 MIPS_FPU_EMU_INC_STATS(errors); |
309 *fault_addr = va; |
|
289 return SIGBUS; 290 } | 310 return SIGBUS; 311 } |
312 if (__put_user(val, va)) { 313 MIPS_FPU_EMU_INC_STATS(errors); 314 *fault_addr = va; 315 return SIGSEGV; 316 } |
|
291 break; 292 } 293 294 case lwc1_op:{ 295 u32 __user *va = (u32 __user *) (xcp->regs[MIPSInst_RS(ir)] + 296 MIPSInst_SIMM(ir)); 297 u32 val; 298 299 MIPS_FPU_EMU_INC_STATS(loads); | 317 break; 318 } 319 320 case lwc1_op:{ 321 u32 __user *va = (u32 __user *) (xcp->regs[MIPSInst_RS(ir)] + 322 MIPSInst_SIMM(ir)); 323 u32 val; 324 325 MIPS_FPU_EMU_INC_STATS(loads); |
300 if (get_user(val, va)) { | 326 if (!access_ok(VERIFY_READ, va, sizeof(u32))) { |
301 MIPS_FPU_EMU_INC_STATS(errors); | 327 MIPS_FPU_EMU_INC_STATS(errors); |
328 *fault_addr = va; |
|
302 return SIGBUS; 303 } | 329 return SIGBUS; 330 } |
331 if (__get_user(val, va)) { 332 MIPS_FPU_EMU_INC_STATS(errors); 333 *fault_addr = va; 334 return SIGSEGV; 335 } |
|
304 SITOREG(val, MIPSInst_RT(ir)); 305 break; 306 } 307 308 case swc1_op:{ 309 u32 __user *va = (u32 __user *) (xcp->regs[MIPSInst_RS(ir)] + 310 MIPSInst_SIMM(ir)); 311 u32 val; 312 313 MIPS_FPU_EMU_INC_STATS(stores); 314 SIFROMREG(val, MIPSInst_RT(ir)); | 336 SITOREG(val, MIPSInst_RT(ir)); 337 break; 338 } 339 340 case swc1_op:{ 341 u32 __user *va = (u32 __user *) (xcp->regs[MIPSInst_RS(ir)] + 342 MIPSInst_SIMM(ir)); 343 u32 val; 344 345 MIPS_FPU_EMU_INC_STATS(stores); 346 SIFROMREG(val, MIPSInst_RT(ir)); |
315 if (put_user(val, va)) { | 347 if (!access_ok(VERIFY_WRITE, va, sizeof(u32))) { |
316 MIPS_FPU_EMU_INC_STATS(errors); | 348 MIPS_FPU_EMU_INC_STATS(errors); |
349 *fault_addr = va; |
|
317 return SIGBUS; 318 } | 350 return SIGBUS; 351 } |
352 if (__put_user(val, va)) { 353 MIPS_FPU_EMU_INC_STATS(errors); 354 *fault_addr = va; 355 return SIGSEGV; 356 } |
|
319 break; 320 } 321 322 case cop1_op: 323 switch (MIPSInst_RS(ir)) { 324 325#if defined(__mips64) 326 case dmfc_op: --- 108 unchanged lines hidden (view full) --- 435 if (cond) { 436 /* branch taken: emulate dslot 437 * instruction 438 */ 439 xcp->cp0_epc += 4; 440 contpc = (xcp->cp0_epc + 441 (MIPSInst_SIMM(ir) << 2)); 442 | 357 break; 358 } 359 360 case cop1_op: 361 switch (MIPSInst_RS(ir)) { 362 363#if defined(__mips64) 364 case dmfc_op: --- 108 unchanged lines hidden (view full) --- 473 if (cond) { 474 /* branch taken: emulate dslot 475 * instruction 476 */ 477 xcp->cp0_epc += 4; 478 contpc = (xcp->cp0_epc + 479 (MIPSInst_SIMM(ir) << 2)); 480 |
443 if (get_user(ir, 444 (mips_instruction __user *) xcp->cp0_epc)) { | 481 if (!access_ok(VERIFY_READ, xcp->cp0_epc, 482 sizeof(mips_instruction))) { |
445 MIPS_FPU_EMU_INC_STATS(errors); | 483 MIPS_FPU_EMU_INC_STATS(errors); |
484 *fault_addr = (mips_instruction __user *)xcp->cp0_epc; |
|
446 return SIGBUS; 447 } | 485 return SIGBUS; 486 } |
487 if (__get_user(ir, 488 (mips_instruction __user *) xcp->cp0_epc)) { 489 MIPS_FPU_EMU_INC_STATS(errors); 490 *fault_addr = (mips_instruction __user *)xcp->cp0_epc; 491 return SIGSEGV; 492 } |
|
448 449 switch (MIPSInst_OPCODE(ir)) { 450 case lwc1_op: 451 case swc1_op: 452#if (__mips >= 2 || defined(__mips64)) 453 case ldc1_op: 454 case sdc1_op: 455#endif --- 45 unchanged lines hidden (view full) --- 501 if ((sig = fpu_emu(xcp, ctx, ir))) 502 return sig; 503 } 504 } 505 break; 506 507#if __mips >= 4 && __mips != 32 508 case cop1x_op:{ | 493 494 switch (MIPSInst_OPCODE(ir)) { 495 case lwc1_op: 496 case swc1_op: 497#if (__mips >= 2 || defined(__mips64)) 498 case ldc1_op: 499 case sdc1_op: 500#endif --- 45 unchanged lines hidden (view full) --- 546 if ((sig = fpu_emu(xcp, ctx, ir))) 547 return sig; 548 } 549 } 550 break; 551 552#if __mips >= 4 && __mips != 32 553 case cop1x_op:{ |
509 int sig; 510 511 if ((sig = fpux_emu(xcp, ctx, ir))) | 554 int sig = fpux_emu(xcp, ctx, ir, fault_addr); 555 if (sig) |
512 return sig; 513 break; 514 } 515#endif 516 517#if __mips >= 4 518 case spec_op: 519 if (MIPSInst_FUNC(ir) != movc_op) --- 79 unchanged lines hidden (view full) --- 599DEF3OP(nmadd, sp, ieee754sp_mul, ieee754sp_add, ieee754sp_neg); 600DEF3OP(nmsub, sp, ieee754sp_mul, ieee754sp_sub, ieee754sp_neg); 601DEF3OP(madd, dp, ieee754dp_mul, ieee754dp_add, ); 602DEF3OP(msub, dp, ieee754dp_mul, ieee754dp_sub, ); 603DEF3OP(nmadd, dp, ieee754dp_mul, ieee754dp_add, ieee754dp_neg); 604DEF3OP(nmsub, dp, ieee754dp_mul, ieee754dp_sub, ieee754dp_neg); 605 606static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, | 556 return sig; 557 break; 558 } 559#endif 560 561#if __mips >= 4 562 case spec_op: 563 if (MIPSInst_FUNC(ir) != movc_op) --- 79 unchanged lines hidden (view full) --- 643DEF3OP(nmadd, sp, ieee754sp_mul, ieee754sp_add, ieee754sp_neg); 644DEF3OP(nmsub, sp, ieee754sp_mul, ieee754sp_sub, ieee754sp_neg); 645DEF3OP(madd, dp, ieee754dp_mul, ieee754dp_add, ); 646DEF3OP(msub, dp, ieee754dp_mul, ieee754dp_sub, ); 647DEF3OP(nmadd, dp, ieee754dp_mul, ieee754dp_add, ieee754dp_neg); 648DEF3OP(nmsub, dp, ieee754dp_mul, ieee754dp_sub, ieee754dp_neg); 649 650static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, |
607 mips_instruction ir) | 651 mips_instruction ir, void *__user *fault_addr) |
608{ 609 unsigned rcsr = 0; /* resulting csr */ 610 611 MIPS_FPU_EMU_INC_STATS(cp1xops); 612 613 switch (MIPSInst_FMA_FFMT(ir)) { 614 case s_fmt:{ /* 0 */ 615 616 ieee754sp(*handler) (ieee754sp, ieee754sp, ieee754sp); 617 ieee754sp fd, fr, fs, ft; 618 u32 __user *va; 619 u32 val; 620 621 switch (MIPSInst_FUNC(ir)) { 622 case lwxc1_op: 623 va = (void __user *) (xcp->regs[MIPSInst_FR(ir)] + 624 xcp->regs[MIPSInst_FT(ir)]); 625 626 MIPS_FPU_EMU_INC_STATS(loads); | 652{ 653 unsigned rcsr = 0; /* resulting csr */ 654 655 MIPS_FPU_EMU_INC_STATS(cp1xops); 656 657 switch (MIPSInst_FMA_FFMT(ir)) { 658 case s_fmt:{ /* 0 */ 659 660 ieee754sp(*handler) (ieee754sp, ieee754sp, ieee754sp); 661 ieee754sp fd, fr, fs, ft; 662 u32 __user *va; 663 u32 val; 664 665 switch (MIPSInst_FUNC(ir)) { 666 case lwxc1_op: 667 va = (void __user *) (xcp->regs[MIPSInst_FR(ir)] + 668 xcp->regs[MIPSInst_FT(ir)]); 669 670 MIPS_FPU_EMU_INC_STATS(loads); |
627 if (get_user(val, va)) { | 671 if (!access_ok(VERIFY_READ, va, sizeof(u32))) { |
628 MIPS_FPU_EMU_INC_STATS(errors); | 672 MIPS_FPU_EMU_INC_STATS(errors); |
673 *fault_addr = va; |
|
629 return SIGBUS; 630 } | 674 return SIGBUS; 675 } |
676 if (__get_user(val, va)) { 677 MIPS_FPU_EMU_INC_STATS(errors); 678 *fault_addr = va; 679 return SIGSEGV; 680 } |
|
631 SITOREG(val, MIPSInst_FD(ir)); 632 break; 633 634 case swxc1_op: 635 va = (void __user *) (xcp->regs[MIPSInst_FR(ir)] + 636 xcp->regs[MIPSInst_FT(ir)]); 637 638 MIPS_FPU_EMU_INC_STATS(stores); 639 640 SIFROMREG(val, MIPSInst_FS(ir)); | 681 SITOREG(val, MIPSInst_FD(ir)); 682 break; 683 684 case swxc1_op: 685 va = (void __user *) (xcp->regs[MIPSInst_FR(ir)] + 686 xcp->regs[MIPSInst_FT(ir)]); 687 688 MIPS_FPU_EMU_INC_STATS(stores); 689 690 SIFROMREG(val, MIPSInst_FS(ir)); |
641 if (put_user(val, va)) { | 691 if (!access_ok(VERIFY_WRITE, va, sizeof(u32))) { |
642 MIPS_FPU_EMU_INC_STATS(errors); | 692 MIPS_FPU_EMU_INC_STATS(errors); |
693 *fault_addr = va; |
|
643 return SIGBUS; 644 } | 694 return SIGBUS; 695 } |
696 if (put_user(val, va)) { 697 MIPS_FPU_EMU_INC_STATS(errors); 698 *fault_addr = va; 699 return SIGSEGV; 700 } |
|
645 break; 646 647 case madd_s_op: 648 handler = fpemu_sp_madd; 649 goto scoptop; 650 case msub_s_op: 651 handler = fpemu_sp_msub; 652 goto scoptop; --- 43 unchanged lines hidden (view full) --- 696 u64 val; 697 698 switch (MIPSInst_FUNC(ir)) { 699 case ldxc1_op: 700 va = (void __user *) (xcp->regs[MIPSInst_FR(ir)] + 701 xcp->regs[MIPSInst_FT(ir)]); 702 703 MIPS_FPU_EMU_INC_STATS(loads); | 701 break; 702 703 case madd_s_op: 704 handler = fpemu_sp_madd; 705 goto scoptop; 706 case msub_s_op: 707 handler = fpemu_sp_msub; 708 goto scoptop; --- 43 unchanged lines hidden (view full) --- 752 u64 val; 753 754 switch (MIPSInst_FUNC(ir)) { 755 case ldxc1_op: 756 va = (void __user *) (xcp->regs[MIPSInst_FR(ir)] + 757 xcp->regs[MIPSInst_FT(ir)]); 758 759 MIPS_FPU_EMU_INC_STATS(loads); |
704 if (get_user(val, va)) { | 760 if (!access_ok(VERIFY_READ, va, sizeof(u64))) { |
705 MIPS_FPU_EMU_INC_STATS(errors); | 761 MIPS_FPU_EMU_INC_STATS(errors); |
762 *fault_addr = va; |
|
706 return SIGBUS; 707 } | 763 return SIGBUS; 764 } |
765 if (__get_user(val, va)) { 766 MIPS_FPU_EMU_INC_STATS(errors); 767 *fault_addr = va; 768 return SIGSEGV; 769 } |
|
708 DITOREG(val, MIPSInst_FD(ir)); 709 break; 710 711 case sdxc1_op: 712 va = (void __user *) (xcp->regs[MIPSInst_FR(ir)] + 713 xcp->regs[MIPSInst_FT(ir)]); 714 715 MIPS_FPU_EMU_INC_STATS(stores); 716 DIFROMREG(val, MIPSInst_FS(ir)); | 770 DITOREG(val, MIPSInst_FD(ir)); 771 break; 772 773 case sdxc1_op: 774 va = (void __user *) (xcp->regs[MIPSInst_FR(ir)] + 775 xcp->regs[MIPSInst_FT(ir)]); 776 777 MIPS_FPU_EMU_INC_STATS(stores); 778 DIFROMREG(val, MIPSInst_FS(ir)); |
717 if (put_user(val, va)) { | 779 if (!access_ok(VERIFY_WRITE, va, sizeof(u64))) { |
718 MIPS_FPU_EMU_INC_STATS(errors); | 780 MIPS_FPU_EMU_INC_STATS(errors); |
781 *fault_addr = va; |
|
719 return SIGBUS; 720 } | 782 return SIGBUS; 783 } |
784 if (__put_user(val, va)) { 785 MIPS_FPU_EMU_INC_STATS(errors); 786 *fault_addr = va; 787 return SIGSEGV; 788 } |
|
721 break; 722 723 case madd_d_op: 724 handler = fpemu_dp_madd; 725 goto dcoptop; 726 case msub_d_op: 727 handler = fpemu_dp_msub; 728 goto dcoptop; --- 508 unchanged lines hidden (view full) --- 1237 default: 1238 return SIGILL; 1239 } 1240 1241 return 0; 1242} 1243 1244int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx, | 789 break; 790 791 case madd_d_op: 792 handler = fpemu_dp_madd; 793 goto dcoptop; 794 case msub_d_op: 795 handler = fpemu_dp_msub; 796 goto dcoptop; --- 508 unchanged lines hidden (view full) --- 1305 default: 1306 return SIGILL; 1307 } 1308 1309 return 0; 1310} 1311 1312int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx, |
1245 int has_fpu) | 1313 int has_fpu, void *__user *fault_addr) |
1246{ 1247 unsigned long oldepc, prevepc; 1248 mips_instruction insn; 1249 int sig = 0; 1250 1251 oldepc = xcp->cp0_epc; 1252 do { 1253 prevepc = xcp->cp0_epc; 1254 | 1314{ 1315 unsigned long oldepc, prevepc; 1316 mips_instruction insn; 1317 int sig = 0; 1318 1319 oldepc = xcp->cp0_epc; 1320 do { 1321 prevepc = xcp->cp0_epc; 1322 |
1255 if (get_user(insn, (mips_instruction __user *) xcp->cp0_epc)) { | 1323 if (!access_ok(VERIFY_READ, xcp->cp0_epc, sizeof(mips_instruction))) { |
1256 MIPS_FPU_EMU_INC_STATS(errors); | 1324 MIPS_FPU_EMU_INC_STATS(errors); |
1325 *fault_addr = (mips_instruction __user *)xcp->cp0_epc; |
|
1257 return SIGBUS; 1258 } | 1326 return SIGBUS; 1327 } |
1328 if (__get_user(insn, (mips_instruction __user *) xcp->cp0_epc)) { 1329 MIPS_FPU_EMU_INC_STATS(errors); 1330 *fault_addr = (mips_instruction __user *)xcp->cp0_epc; 1331 return SIGSEGV; 1332 } |
|
1259 if (insn == 0) 1260 xcp->cp0_epc += 4; /* skip nops */ 1261 else { 1262 /* 1263 * The 'ieee754_csr' is an alias of 1264 * ctx->fcr31. No need to copy ctx->fcr31 to 1265 * ieee754_csr. But ieee754_csr.rm is ieee 1266 * library modes. (not mips rounding mode) 1267 */ 1268 /* convert to ieee library modes */ 1269 ieee754_csr.rm = ieee_rm[ieee754_csr.rm]; | 1333 if (insn == 0) 1334 xcp->cp0_epc += 4; /* skip nops */ 1335 else { 1336 /* 1337 * The 'ieee754_csr' is an alias of 1338 * ctx->fcr31. No need to copy ctx->fcr31 to 1339 * ieee754_csr. But ieee754_csr.rm is ieee 1340 * library modes. (not mips rounding mode) 1341 */ 1342 /* convert to ieee library modes */ 1343 ieee754_csr.rm = ieee_rm[ieee754_csr.rm]; |
1270 sig = cop1Emulate(xcp, ctx); | 1344 sig = cop1Emulate(xcp, ctx, fault_addr); |
1271 /* revert to mips rounding mode */ 1272 ieee754_csr.rm = mips_rm[ieee754_csr.rm]; 1273 } 1274 1275 if (has_fpu) 1276 break; 1277 if (sig) 1278 break; --- 61 unchanged lines hidden --- | 1345 /* revert to mips rounding mode */ 1346 ieee754_csr.rm = mips_rm[ieee754_csr.rm]; 1347 } 1348 1349 if (has_fpu) 1350 break; 1351 if (sig) 1352 break; --- 61 unchanged lines hidden --- |