aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/kernel/signal.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/kernel/signal.c')
-rw-r--r--arch/arm/kernel/signal.c21
1 files changed, 19 insertions, 2 deletions
diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
index a0cd0a90a10d..e9fe78033361 100644
--- a/arch/arm/kernel/signal.c
+++ b/arch/arm/kernel/signal.c
@@ -665,17 +665,33 @@ static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall)
665 if (syscall) { 665 if (syscall) {
666 if (regs->ARM_r0 == -ERESTART_RESTARTBLOCK) { 666 if (regs->ARM_r0 == -ERESTART_RESTARTBLOCK) {
667 if (thumb_mode(regs)) { 667 if (thumb_mode(regs)) {
668 regs->ARM_r7 = __NR_restart_syscall; 668 regs->ARM_r7 = __NR_restart_syscall - __NR_SYSCALL_BASE;
669 regs->ARM_pc -= 2; 669 regs->ARM_pc -= 2;
670 } else { 670 } else {
671#if defined(CONFIG_AEABI) && !defined(CONFIG_OABI_COMPAT)
672 regs->ARM_r7 = __NR_restart_syscall;
673 regs->ARM_pc -= 4;
674#else
671 u32 __user *usp; 675 u32 __user *usp;
676 u32 swival = __NR_restart_syscall;
672 677
673 regs->ARM_sp -= 12; 678 regs->ARM_sp -= 12;
674 usp = (u32 __user *)regs->ARM_sp; 679 usp = (u32 __user *)regs->ARM_sp;
675 680
681 /*
682 * Either we supports OABI only, or we have
683 * EABI with the OABI compat layer enabled.
684 * In the later case we don't know if user
685 * space is EABI or not, and if not we must
686 * not clobber r7. Always using the OABI
687 * syscall solves that issue and works for
688 * all those cases.
689 */
690 swival = swival - __NR_SYSCAll_BASE + __NR_OABI_SYSCALL_BASE;
691
676 put_user(regs->ARM_pc, &usp[0]); 692 put_user(regs->ARM_pc, &usp[0]);
677 /* swi __NR_restart_syscall */ 693 /* swi __NR_restart_syscall */
678 put_user(0xef000000 | __NR_restart_syscall, &usp[1]); 694 put_user(0xef000000 | swival, &usp[1]);
679 /* ldr pc, [sp], #12 */ 695 /* ldr pc, [sp], #12 */
680 put_user(0xe49df00c, &usp[2]); 696 put_user(0xe49df00c, &usp[2]);
681 697
@@ -683,6 +699,7 @@ static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall)
683 (unsigned long)(usp + 3)); 699 (unsigned long)(usp + 3));
684 700
685 regs->ARM_pc = regs->ARM_sp + 4; 701 regs->ARM_pc = regs->ARM_sp + 4;
702#endif
686 } 703 }
687 } 704 }
688 if (regs->ARM_r0 == -ERESTARTNOHAND || 705 if (regs->ARM_r0 == -ERESTARTNOHAND ||