Merge branches 'release', 'button-sysfs', 'misc', 'mismatch', 'randconfig' and 'toshi...
[sfrench/cifs-2.6.git] / arch / x86 / kernel / signal_64.c
index 7347bb14e306bb3ff66385beee9cc1e5c6a15113..1c83e5124c65813f7c966a9ed0e882627b2a84a9 100644 (file)
@@ -295,7 +295,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
           see include/asm-x86_64/uaccess.h for details. */
        set_fs(USER_DS);
 
-       regs->flags &= ~X86_EFLAGS_TF;
+       regs->flags &= ~(X86_EFLAGS_TF | X86_EFLAGS_DF);
        if (test_thread_flag(TIF_SINGLESTEP))
                ptrace_notify(SIGTRAP);
 #ifdef DEBUG_SIG
@@ -310,6 +310,35 @@ give_sigsegv:
        return -EFAULT;
 }
 
+/*
+ * Return -1L or the syscall number that @regs is executing.
+ */
+static long current_syscall(struct pt_regs *regs)
+{
+       /*
+        * We always sign-extend a -1 value being set here,
+        * so this is always either -1L or a syscall number.
+        */
+       return regs->orig_ax;
+}
+
+/*
+ * Return a value that is -EFOO if the system call in @regs->orig_ax
+ * returned an error.  This only works for @regs from @current.
+ */
+static long current_syscall_ret(struct pt_regs *regs)
+{
+#ifdef CONFIG_IA32_EMULATION
+       if (test_thread_flag(TIF_IA32))
+               /*
+                * Sign-extend the value so (int)-EFOO becomes (long)-EFOO
+                * and will match correctly in comparisons.
+                */
+               return (int) regs->ax;
+#endif
+       return regs->ax;
+}
+
 /*
  * OK, we're invoking a handler
  */    
@@ -327,9 +356,9 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
 #endif
 
        /* Are we from a system call? */
-       if ((long)regs->orig_ax >= 0) {
+       if (current_syscall(regs) >= 0) {
                /* If so, check system call restarting.. */
-               switch (regs->ax) {
+               switch (current_syscall_ret(regs)) {
                        case -ERESTART_RESTARTBLOCK:
                        case -ERESTARTNOHAND:
                                regs->ax = -EINTR;
@@ -426,10 +455,9 @@ static void do_signal(struct pt_regs *regs)
        }
 
        /* Did we come from a system call? */
-       if ((long)regs->orig_ax >= 0) {
+       if (current_syscall(regs) >= 0) {
                /* Restart the system call - no handlers present */
-               long res = regs->ax;
-               switch (res) {
+               switch (current_syscall_ret(regs)) {
                case -ERESTARTNOHAND:
                case -ERESTARTSYS:
                case -ERESTARTNOINTR: