Merge signal handler branch
[sfrench/cifs-2.6.git] / arch / arm / kernel / signal.c
index e5802bfda31df24346ee2aa2e472bf0bf1bd6042..1ce05ec086c6b40366a2d7aa349eef14af1b0410 100644 (file)
@@ -622,17 +622,33 @@ static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall)
        if (syscall) {
                if (regs->ARM_r0 == -ERESTART_RESTARTBLOCK) {
                        if (thumb_mode(regs)) {
-                               regs->ARM_r7 = __NR_restart_syscall;
+                               regs->ARM_r7 = __NR_restart_syscall - __NR_SYSCALL_BASE;
                                regs->ARM_pc -= 2;
                        } else {
+#if defined(CONFIG_AEABI) && !defined(CONFIG_OABI_COMPAT)
+                               regs->ARM_r7 = __NR_restart_syscall;
+                               regs->ARM_pc -= 4;
+#else
                                u32 __user *usp;
+                               u32 swival = __NR_restart_syscall;
 
                                regs->ARM_sp -= 12;
                                usp = (u32 __user *)regs->ARM_sp;
 
+                               /*
+                                * Either we supports OABI only, or we have
+                                * EABI with the OABI compat layer enabled.
+                                * In the later case we don't know if user
+                                * space is EABI or not, and if not we must
+                                * not clobber r7.  Always using the OABI
+                                * syscall solves that issue and works for
+                                * all those cases.
+                                */
+                               swival = swival - __NR_SYSCALL_BASE + __NR_OABI_SYSCALL_BASE;
+
                                put_user(regs->ARM_pc, &usp[0]);
                                /* swi __NR_restart_syscall */
-                               put_user(0xef000000 | __NR_restart_syscall, &usp[1]);
+                               put_user(0xef000000 | swival, &usp[1]);
                                /* ldr  pc, [sp], #12 */
                                put_user(0xe49df00c, &usp[2]);
 
@@ -640,6 +656,7 @@ static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall)
                                                   (unsigned long)(usp + 3));
 
                                regs->ARM_pc = regs->ARM_sp + 4;
+#endif
                        }
                }
                if (regs->ARM_r0 == -ERESTARTNOHAND ||