aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/kernel/traps.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/kernel/traps.c')
-rw-r--r--arch/mips/kernel/traps.c43
1 files changed, 22 insertions, 21 deletions
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 6eccfb49ae68..0ae19e1fa867 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -399,19 +399,6 @@ asmlinkage void do_be(struct pt_regs *regs)
399 force_sig(SIGBUS, current); 399 force_sig(SIGBUS, current);
400} 400}
401 401
402static inline int get_insn_opcode(struct pt_regs *regs, unsigned int *opcode)
403{
404 unsigned int __user *epc;
405
406 epc = (unsigned int __user *) regs->cp0_epc +
407 ((regs->cp0_cause & CAUSEF_BD) != 0);
408 if (!get_user(*opcode, epc))
409 return 0;
410
411 force_sig(SIGSEGV, current);
412 return 1;
413}
414
415/* 402/*
416 * ll/sc emulation 403 * ll/sc emulation
417 */ 404 */
@@ -546,8 +533,8 @@ static inline int simulate_llsc(struct pt_regs *regs)
546{ 533{
547 unsigned int opcode; 534 unsigned int opcode;
548 535
549 if (unlikely(get_insn_opcode(regs, &opcode))) 536 if (get_user(opcode, (unsigned int __user *) exception_epc(regs)))
550 return -EFAULT; 537 goto out_sigsegv;
551 538
552 if ((opcode & OPCODE) == LL) { 539 if ((opcode & OPCODE) == LL) {
553 simulate_ll(regs, opcode); 540 simulate_ll(regs, opcode);
@@ -559,6 +546,10 @@ static inline int simulate_llsc(struct pt_regs *regs)
559 } 546 }
560 547
561 return -EFAULT; /* Strange things going on ... */ 548 return -EFAULT; /* Strange things going on ... */
549
550out_sigsegv:
551 force_sig(SIGSEGV, current);
552 return -EFAULT;
562} 553}
563 554
564/* 555/*
@@ -571,8 +562,8 @@ static inline int simulate_rdhwr(struct pt_regs *regs)
571 struct thread_info *ti = task_thread_info(current); 562 struct thread_info *ti = task_thread_info(current);
572 unsigned int opcode; 563 unsigned int opcode;
573 564
574 if (unlikely(get_insn_opcode(regs, &opcode))) 565 if (get_user(opcode, (unsigned int __user *) exception_epc(regs)))
575 return -EFAULT; 566 goto out_sigsegv;
576 567
577 if (unlikely(compute_return_epc(regs))) 568 if (unlikely(compute_return_epc(regs)))
578 return -EFAULT; 569 return -EFAULT;
@@ -591,6 +582,10 @@ static inline int simulate_rdhwr(struct pt_regs *regs)
591 582
592 /* Not ours. */ 583 /* Not ours. */
593 return -EFAULT; 584 return -EFAULT;
585
586out_sigsegv:
587 force_sig(SIGSEGV, current);
588 return -EFAULT;
594} 589}
595 590
596asmlinkage void do_ov(struct pt_regs *regs) 591asmlinkage void do_ov(struct pt_regs *regs)
@@ -676,8 +671,8 @@ asmlinkage void do_bp(struct pt_regs *regs)
676 671
677 die_if_kernel("Break instruction in kernel code", regs); 672 die_if_kernel("Break instruction in kernel code", regs);
678 673
679 if (get_insn_opcode(regs, &opcode)) 674 if (get_user(opcode, (unsigned int __user *) exception_epc(regs)))
680 return; 675 goto out_sigsegv;
681 676
682 /* 677 /*
683 * There is the ancient bug in the MIPS assemblers that the break 678 * There is the ancient bug in the MIPS assemblers that the break
@@ -710,6 +705,9 @@ asmlinkage void do_bp(struct pt_regs *regs)
710 default: 705 default:
711 force_sig(SIGTRAP, current); 706 force_sig(SIGTRAP, current);
712 } 707 }
708
709out_sigsegv:
710 force_sig(SIGSEGV, current);
713} 711}
714 712
715asmlinkage void do_tr(struct pt_regs *regs) 713asmlinkage void do_tr(struct pt_regs *regs)
@@ -719,8 +717,8 @@ asmlinkage void do_tr(struct pt_regs *regs)
719 717
720 die_if_kernel("Trap instruction in kernel code", regs); 718 die_if_kernel("Trap instruction in kernel code", regs);
721 719
722 if (get_insn_opcode(regs, &opcode)) 720 if (get_user(opcode, (unsigned int __user *) exception_epc(regs)))
723 return; 721 goto out_sigsegv;
724 722
725 /* Immediate versions don't provide a code. */ 723 /* Immediate versions don't provide a code. */
726 if (!(opcode & OPCODE)) 724 if (!(opcode & OPCODE))
@@ -747,6 +745,9 @@ asmlinkage void do_tr(struct pt_regs *regs)
747 default: 745 default:
748 force_sig(SIGTRAP, current); 746 force_sig(SIGTRAP, current);
749 } 747 }
748
749out_sigsegv:
750 force_sig(SIGSEGV, current);
750} 751}
751 752
752asmlinkage void do_ri(struct pt_regs *regs) 753asmlinkage void do_ri(struct pt_regs *regs)