diff options
Diffstat (limited to 'arch/mips/kernel/signal.c')
-rw-r--r-- | arch/mips/kernel/signal.c | 37 |
1 files changed, 18 insertions, 19 deletions
diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c index b3273aeaeedc..604f077bb5bf 100644 --- a/arch/mips/kernel/signal.c +++ b/arch/mips/kernel/signal.c | |||
@@ -550,23 +550,26 @@ static int handle_signal(unsigned long sig, siginfo_t *info, | |||
550 | struct mips_abi *abi = current->thread.abi; | 550 | struct mips_abi *abi = current->thread.abi; |
551 | void *vdso = current->mm->context.vdso; | 551 | void *vdso = current->mm->context.vdso; |
552 | 552 | ||
553 | switch(regs->regs[0]) { | 553 | if (regs->regs[0]) { |
554 | case ERESTART_RESTARTBLOCK: | 554 | switch(regs->regs[2]) { |
555 | case ERESTARTNOHAND: | 555 | case ERESTART_RESTARTBLOCK: |
556 | regs->regs[2] = EINTR; | 556 | case ERESTARTNOHAND: |
557 | break; | ||
558 | case ERESTARTSYS: | ||
559 | if (!(ka->sa.sa_flags & SA_RESTART)) { | ||
560 | regs->regs[2] = EINTR; | 557 | regs->regs[2] = EINTR; |
561 | break; | 558 | break; |
559 | case ERESTARTSYS: | ||
560 | if (!(ka->sa.sa_flags & SA_RESTART)) { | ||
561 | regs->regs[2] = EINTR; | ||
562 | break; | ||
563 | } | ||
564 | /* fallthrough */ | ||
565 | case ERESTARTNOINTR: | ||
566 | regs->regs[7] = regs->regs[26]; | ||
567 | regs->regs[2] = regs->regs[0]; | ||
568 | regs->cp0_epc -= 4; | ||
562 | } | 569 | } |
563 | /* fallthrough */ | ||
564 | case ERESTARTNOINTR: /* Userland will reload $v0. */ | ||
565 | regs->regs[7] = regs->regs[26]; | ||
566 | regs->cp0_epc -= 8; | ||
567 | } | ||
568 | 570 | ||
569 | regs->regs[0] = 0; /* Don't deal with this again. */ | 571 | regs->regs[0] = 0; /* Don't deal with this again. */ |
572 | } | ||
570 | 573 | ||
571 | if (sig_uses_siginfo(ka)) | 574 | if (sig_uses_siginfo(ka)) |
572 | ret = abi->setup_rt_frame(vdso + abi->rt_signal_return_offset, | 575 | ret = abi->setup_rt_frame(vdso + abi->rt_signal_return_offset, |
@@ -625,17 +628,13 @@ static void do_signal(struct pt_regs *regs) | |||
625 | return; | 628 | return; |
626 | } | 629 | } |
627 | 630 | ||
628 | /* | ||
629 | * Who's code doesn't conform to the restartable syscall convention | ||
630 | * dies here!!! The li instruction, a single machine instruction, | ||
631 | * must directly be followed by the syscall instruction. | ||
632 | */ | ||
633 | if (regs->regs[0]) { | 631 | if (regs->regs[0]) { |
634 | if (regs->regs[2] == ERESTARTNOHAND || | 632 | if (regs->regs[2] == ERESTARTNOHAND || |
635 | regs->regs[2] == ERESTARTSYS || | 633 | regs->regs[2] == ERESTARTSYS || |
636 | regs->regs[2] == ERESTARTNOINTR) { | 634 | regs->regs[2] == ERESTARTNOINTR) { |
635 | regs->regs[2] = regs->regs[0]; | ||
637 | regs->regs[7] = regs->regs[26]; | 636 | regs->regs[7] = regs->regs[26]; |
638 | regs->cp0_epc -= 8; | 637 | regs->cp0_epc -= 4; |
639 | } | 638 | } |
640 | if (regs->regs[2] == ERESTART_RESTARTBLOCK) { | 639 | if (regs->regs[2] == ERESTART_RESTARTBLOCK) { |
641 | regs->regs[2] = current->thread.abi->restart; | 640 | regs->regs[2] = current->thread.abi->restart; |