]> err.no Git - linux-2.6/blobdiff - arch/x86/kernel/signal_64.c
Merge branches 'x86/urgent', 'x86/amd-iommu', 'x86/apic', 'x86/cleanups', 'x86/core...
[linux-2.6] / arch / x86 / kernel / signal_64.c
index f3247d71edbcb7e01bf57cb19b1da1ec578ea0ae..bf87684474f18497e2326d497217ae45b4888df5 100644 (file)
@@ -28,8 +28,6 @@
 #include <asm/mce.h>
 #include "sigframe.h"
 
-/* #define DEBUG_SIG 1 */
-
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 
 #define __FIX_EFLAGS   (X86_EFLAGS_AC | X86_EFLAGS_OF | \
@@ -142,10 +140,6 @@ asmlinkage long sys_rt_sigreturn(struct pt_regs *regs)
        if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &ax))
                goto badframe;
 
-#ifdef DEBUG_SIG
-       printk("%d sigreturn ip:%lx sp:%lx frame:%p ax:%lx\n",current->pid,regs->ip,regs->sp,frame,ax);
-#endif
-
        if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->sp) == -EFAULT)
                goto badframe;
 
@@ -274,10 +268,6 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
        if (err)
                goto give_sigsegv;
 
-#ifdef DEBUG_SIG
-       printk("%d old ip %lx old sp %lx old ax %lx\n", current->pid,regs->ip,regs->sp,regs->ax);
-#endif
-
        /* Set up registers for signal handler */
        regs->di = sig;
        /* In case the signal handler was declared without prototypes */ 
@@ -295,18 +285,6 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
           even if the handler happens to be interrupting 32-bit code. */
        regs->cs = __USER_CS;
 
-       /* This, by contrast, has nothing to do with segment registers -
-          see include/asm-x86_64/uaccess.h for details. */
-       set_fs(USER_DS);
-
-       regs->flags &= ~(X86_EFLAGS_TF | X86_EFLAGS_DF);
-       if (test_thread_flag(TIF_SINGLESTEP))
-               ptrace_notify(SIGTRAP);
-#ifdef DEBUG_SIG
-       printk("SIG deliver (%s:%d): sp=%p pc=%lx ra=%p\n",
-               current->comm, current->pid, frame, regs->ip, frame->pretcode);
-#endif
-
        return 0;
 
 give_sigsegv:
@@ -353,12 +331,6 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
 {
        int ret;
 
-#ifdef DEBUG_SIG
-       printk("handle_signal pid:%d sig:%lu ip:%lx sp:%lx regs=%p\n",
-               current->pid, sig,
-               regs->ip, regs->sp, regs);
-#endif
-
        /* Are we from a system call? */
        if (current_syscall(regs) >= 0) {
                /* If so, check system call restarting.. */
@@ -400,6 +372,28 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
        ret = setup_rt_frame(sig, ka, info, oldset, regs);
 
        if (ret == 0) {
+               /*
+                * This has nothing to do with segment registers,
+                * despite the name.  This magic affects uaccess.h
+                * macros' behavior.  Reset it to the normal setting.
+                */
+               set_fs(USER_DS);
+
+               /*
+                * Clear the direction flag as per the ABI for function entry.
+                */
+               regs->flags &= ~X86_EFLAGS_DF;
+
+               /*
+                * Clear TF when entering the signal handler, but
+                * notify any tracer that was single-stepping it.
+                * The tracer may want to single-step inside the
+                * handler too.
+                */
+               regs->flags &= ~X86_EFLAGS_TF;
+               if (test_thread_flag(TIF_SINGLESTEP))
+                       ptrace_notify(SIGTRAP);
+
                spin_lock_irq(&current->sighand->siglock);
                sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
                if (!(ka->sa.sa_flags & SA_NODEFER))
@@ -433,7 +427,7 @@ static void do_signal(struct pt_regs *regs)
        if (!user_mode(regs))
                return;
 
-       if (test_thread_flag(TIF_RESTORE_SIGMASK))
+       if (current_thread_info()->status & TS_RESTORE_SIGMASK)
                oldset = &current->saved_sigmask;
        else
                oldset = &current->blocked;
@@ -450,11 +444,13 @@ static void do_signal(struct pt_regs *regs)
 
                /* Whee!  Actually deliver the signal.  */
                if (handle_signal(signr, &info, &ka, oldset, regs) == 0) {
-                       /* a signal was successfully delivered; the saved
+                       /*
+                        * A signal was successfully delivered; the saved
                         * sigmask will have been stored in the signal frame,
                         * and will be restored by sigreturn, so we can simply
-                        * clear the TIF_RESTORE_SIGMASK flag */
-                       clear_thread_flag(TIF_RESTORE_SIGMASK);
+                        * clear the TS_RESTORE_SIGMASK flag.
+                        */
+                       current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
                }
                return;
        }
@@ -482,8 +478,8 @@ static void do_signal(struct pt_regs *regs)
         * If there's no signal to deliver, we just put the saved sigmask
         * back.
         */
-       if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
-               clear_thread_flag(TIF_RESTORE_SIGMASK);
+       if (current_thread_info()->status & TS_RESTORE_SIGMASK) {
+               current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
                sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
        }
 }
@@ -491,17 +487,6 @@ static void do_signal(struct pt_regs *regs)
 void do_notify_resume(struct pt_regs *regs, void *unused,
                      __u32 thread_info_flags)
 {
-#ifdef DEBUG_SIG
-       printk("do_notify_resume flags:%x ip:%lx sp:%lx caller:%p pending:%x\n",
-              thread_info_flags, regs->ip, regs->sp, __builtin_return_address(0),signal_pending(current));
-#endif
-              
-       /* Pending single-step? */
-       if (thread_info_flags & _TIF_SINGLESTEP) {
-               regs->flags |= X86_EFLAGS_TF;
-               clear_thread_flag(TIF_SINGLESTEP);
-       }
-
 #ifdef CONFIG_X86_MCE
        /* notify userspace of pending MCEs */
        if (thread_info_flags & _TIF_MCE_NOTIFY)
@@ -509,7 +494,7 @@ void do_notify_resume(struct pt_regs *regs, void *unused,
 #endif /* CONFIG_X86_MCE */
 
        /* deal with pending signal delivery */
-       if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
+       if (thread_info_flags & _TIF_SIGPENDING)
                do_signal(regs);
 
        if (thread_info_flags & _TIF_HRTICK_RESCHED)