OSDN Git Service

Merge branch 'for-linus-4.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 28 May 2016 01:54:59 +0000 (18:54 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 28 May 2016 01:54:59 +0000 (18:54 -0700)
Pull UML updates from Richard Weinberger:
 "This contains a nice FPU fixup from Eli Cooper for UML"

* 'for-linus-4.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/uml:
  um: add extended processor state save/restore support
  um: extend fpstate to _xstate to support YMM registers
  um: fix FPU state preservation around signal handlers

arch/um/include/shared/registers.h
arch/um/kernel/process.c
arch/um/os-Linux/signal.c
arch/x86/um/os-Linux/registers.c
arch/x86/um/ptrace_32.c
arch/x86/um/ptrace_64.c
arch/x86/um/shared/sysdep/ptrace_64.h
arch/x86/um/signal.c
arch/x86/um/user-offsets.c

index f5b7635..a74449b 100644 (file)
@@ -9,6 +9,8 @@
 #include <sysdep/ptrace.h>
 #include <sysdep/archsetjmp.h>
 
+extern int save_i387_registers(int pid, unsigned long *fp_regs);
+extern int restore_i387_registers(int pid, unsigned long *fp_regs);
 extern int save_fp_registers(int pid, unsigned long *fp_regs);
 extern int restore_fp_registers(int pid, unsigned long *fp_regs);
 extern int save_fpx_registers(int pid, unsigned long *fp_regs);
index 0b04711..034b42c 100644 (file)
@@ -398,6 +398,6 @@ int elf_core_copy_fpregs(struct task_struct *t, elf_fpregset_t *fpu)
 {
        int cpu = current_thread_info()->cpu;
 
-       return save_fp_registers(userspace_pid[cpu], (unsigned long *) fpu);
+       return save_i387_registers(userspace_pid[cpu], (unsigned long *) fpu);
 }
 
index 7801666..8acaf4e 100644 (file)
@@ -29,23 +29,29 @@ void (*sig_info[NSIG])(int, struct siginfo *, struct uml_pt_regs *) = {
 
 static void sig_handler_common(int sig, struct siginfo *si, mcontext_t *mc)
 {
-       struct uml_pt_regs r;
+       struct uml_pt_regs *r;
        int save_errno = errno;
 
-       r.is_user = 0;
+       r = malloc(sizeof(struct uml_pt_regs));
+       if (!r)
+               panic("out of memory");
+
+       r->is_user = 0;
        if (sig == SIGSEGV) {
                /* For segfaults, we want the data from the sigcontext. */
-               get_regs_from_mc(&r, mc);
-               GET_FAULTINFO_FROM_MC(r.faultinfo, mc);
+               get_regs_from_mc(r, mc);
+               GET_FAULTINFO_FROM_MC(r->faultinfo, mc);
        }
 
        /* enable signals if sig isn't IRQ signal */
        if ((sig != SIGIO) && (sig != SIGWINCH) && (sig != SIGALRM))
                unblock_signals();
 
-       (*sig_info[sig])(sig, si, &r);
+       (*sig_info[sig])(sig, si, r);
 
        errno = save_errno;
+
+       free(r);
 }
 
 /*
@@ -83,11 +89,17 @@ void sig_handler(int sig, struct siginfo *si, mcontext_t *mc)
 
 static void timer_real_alarm_handler(mcontext_t *mc)
 {
-       struct uml_pt_regs regs;
+       struct uml_pt_regs *regs;
+
+       regs = malloc(sizeof(struct uml_pt_regs));
+       if (!regs)
+               panic("out of memory");
 
        if (mc != NULL)
-               get_regs_from_mc(&regs, mc);
-       timer_handler(SIGALRM, NULL, &regs);
+               get_regs_from_mc(regs, mc);
+       timer_handler(SIGALRM, NULL, regs);
+
+       free(regs);
 }
 
 void timer_alarm_handler(int sig, struct siginfo *unused_si, mcontext_t *mc)
index 41bfe84..00f54a9 100644 (file)
 #endif
 #include <longjmp.h>
 #include <sysdep/ptrace_user.h>
+#include <sys/uio.h>
+#include <asm/sigcontext.h>
+#include <linux/elf.h>
 
-int save_fp_registers(int pid, unsigned long *fp_regs)
+int have_xstate_support;
+
+int save_i387_registers(int pid, unsigned long *fp_regs)
 {
        if (ptrace(PTRACE_GETFPREGS, pid, 0, fp_regs) < 0)
                return -errno;
        return 0;
 }
 
-int restore_fp_registers(int pid, unsigned long *fp_regs)
+int save_fp_registers(int pid, unsigned long *fp_regs)
+{
+       struct iovec iov;
+
+       if (have_xstate_support) {
+               iov.iov_base = fp_regs;
+               iov.iov_len = sizeof(struct _xstate);
+               if (ptrace(PTRACE_GETREGSET, pid, NT_X86_XSTATE, &iov) < 0)
+                       return -errno;
+               return 0;
+       } else {
+               return save_i387_registers(pid, fp_regs);
+       }
+}
+
+int restore_i387_registers(int pid, unsigned long *fp_regs)
 {
        if (ptrace(PTRACE_SETFPREGS, pid, 0, fp_regs) < 0)
                return -errno;
        return 0;
 }
 
+int restore_fp_registers(int pid, unsigned long *fp_regs)
+{
+       struct iovec iov;
+
+       if (have_xstate_support) {
+               iov.iov_base = fp_regs;
+               iov.iov_len = sizeof(struct _xstate);
+               if (ptrace(PTRACE_SETREGSET, pid, NT_X86_XSTATE, &iov) < 0)
+                       return -errno;
+               return 0;
+       } else {
+               return restore_i387_registers(pid, fp_regs);
+       }
+}
+
 #ifdef __i386__
 int have_fpx_regs = 1;
 int save_fpx_registers(int pid, unsigned long *fp_regs)
@@ -85,6 +120,16 @@ int put_fp_registers(int pid, unsigned long *regs)
        return restore_fp_registers(pid, regs);
 }
 
+void arch_init_registers(int pid)
+{
+       struct _xstate fp_regs;
+       struct iovec iov;
+
+       iov.iov_base = &fp_regs;
+       iov.iov_len = sizeof(struct _xstate);
+       if (ptrace(PTRACE_GETREGSET, pid, NT_X86_XSTATE, &iov) == 0)
+               have_xstate_support = 1;
+}
 #endif
 
 unsigned long get_thread_reg(int reg, jmp_buf *buf)
index 47c78d5..ebd4dd6 100644 (file)
@@ -194,7 +194,8 @@ static int get_fpregs(struct user_i387_struct __user *buf, struct task_struct *c
        int err, n, cpu = ((struct thread_info *) child->stack)->cpu;
        struct user_i387_struct fpregs;
 
-       err = save_fp_registers(userspace_pid[cpu], (unsigned long *) &fpregs);
+       err = save_i387_registers(userspace_pid[cpu],
+                                 (unsigned long *) &fpregs);
        if (err)
                return err;
 
@@ -214,7 +215,7 @@ static int set_fpregs(struct user_i387_struct __user *buf, struct task_struct *c
        if (n > 0)
                return -EFAULT;
 
-       return restore_fp_registers(userspace_pid[cpu],
+       return restore_i387_registers(userspace_pid[cpu],
                                    (unsigned long *) &fpregs);
 }
 
index a629694..faab418 100644 (file)
@@ -222,14 +222,14 @@ int is_syscall(unsigned long addr)
 static int get_fpregs(struct user_i387_struct __user *buf, struct task_struct *child)
 {
        int err, n, cpu = ((struct thread_info *) child->stack)->cpu;
-       long fpregs[HOST_FP_SIZE];
+       struct user_i387_struct fpregs;
 
-       BUG_ON(sizeof(*buf) != sizeof(fpregs));
-       err = save_fp_registers(userspace_pid[cpu], fpregs);
+       err = save_i387_registers(userspace_pid[cpu],
+                                 (unsigned long *) &fpregs);
        if (err)
                return err;
 
-       n = copy_to_user(buf, fpregs, sizeof(fpregs));
+       n = copy_to_user(buf, &fpregs, sizeof(fpregs));
        if (n > 0)
                return -EFAULT;
 
@@ -239,14 +239,14 @@ static int get_fpregs(struct user_i387_struct __user *buf, struct task_struct *c
 static int set_fpregs(struct user_i387_struct __user *buf, struct task_struct *child)
 {
        int n, cpu = ((struct thread_info *) child->stack)->cpu;
-       long fpregs[HOST_FP_SIZE];
+       struct user_i387_struct fpregs;
 
-       BUG_ON(sizeof(*buf) != sizeof(fpregs));
-       n = copy_from_user(fpregs, buf, sizeof(fpregs));
+       n = copy_from_user(&fpregs, buf, sizeof(fpregs));
        if (n > 0)
                return -EFAULT;
 
-       return restore_fp_registers(userspace_pid[cpu], fpregs);
+       return restore_i387_registers(userspace_pid[cpu],
+                                     (unsigned long *) &fpregs);
 }
 
 long subarch_ptrace(struct task_struct *child, long request,
index 919789f..0dc223a 100644 (file)
@@ -57,8 +57,6 @@
 #define UPT_SYSCALL_ARG5(r) UPT_R8(r)
 #define UPT_SYSCALL_ARG6(r) UPT_R9(r)
 
-static inline void arch_init_registers(int pid)
-{
-}
+extern void arch_init_registers(int pid);
 
 #endif
index 14fcd01..49e5036 100644 (file)
@@ -225,26 +225,16 @@ static int copy_sc_from_user(struct pt_regs *regs,
        } else
 #endif
        {
-               struct user_i387_struct fp;
-
-               err = copy_from_user(&fp, (void *)sc.fpstate,
-                                    sizeof(struct user_i387_struct));
+               err = copy_from_user(regs->regs.fp, (void *)sc.fpstate,
+                                    sizeof(struct _xstate));
                if (err)
                        return 1;
-
-               err = restore_fp_registers(pid, (unsigned long *) &fp);
-               if (err < 0) {
-                       printk(KERN_ERR "copy_sc_from_user - "
-                              "restore_fp_registers failed, errno = %d\n",
-                              -err);
-                       return 1;
-               }
        }
        return 0;
 }
 
 static int copy_sc_to_user(struct sigcontext __user *to,
-                          struct _fpstate __user *to_fp, struct pt_regs *regs,
+                          struct _xstate __user *to_fp, struct pt_regs *regs,
                           unsigned long mask)
 {
        struct sigcontext sc;
@@ -310,25 +300,22 @@ static int copy_sc_to_user(struct sigcontext __user *to,
                        return 1;
                }
 
-               err = convert_fxsr_to_user(to_fp, &fpx);
+               err = convert_fxsr_to_user(&to_fp->fpstate, &fpx);
                if (err)
                        return 1;
 
-               err |= __put_user(fpx.swd, &to_fp->status);
-               err |= __put_user(X86_FXSR_MAGIC, &to_fp->magic);
+               err |= __put_user(fpx.swd, &to_fp->fpstate.status);
+               err |= __put_user(X86_FXSR_MAGIC, &to_fp->fpstate.magic);
                if (err)
                        return 1;
 
-               if (copy_to_user(&to_fp->_fxsr_env[0], &fpx,
+               if (copy_to_user(&to_fp->fpstate._fxsr_env[0], &fpx,
                                 sizeof(struct user_fxsr_struct)))
                        return 1;
        } else
 #endif
        {
-               struct user_i387_struct fp;
-
-               err = save_fp_registers(pid, (unsigned long *) &fp);
-               if (copy_to_user(to_fp, &fp, sizeof(struct user_i387_struct)))
+               if (copy_to_user(to_fp, regs->regs.fp, sizeof(struct _xstate)))
                        return 1;
        }
 
@@ -337,7 +324,7 @@ static int copy_sc_to_user(struct sigcontext __user *to,
 
 #ifdef CONFIG_X86_32
 static int copy_ucontext_to_user(struct ucontext __user *uc,
-                                struct _fpstate __user *fp, sigset_t *set,
+                                struct _xstate __user *fp, sigset_t *set,
                                 unsigned long sp)
 {
        int err = 0;
@@ -353,7 +340,7 @@ struct sigframe
        char __user *pretcode;
        int sig;
        struct sigcontext sc;
-       struct _fpstate fpstate;
+       struct _xstate fpstate;
        unsigned long extramask[_NSIG_WORDS-1];
        char retcode[8];
 };
@@ -366,7 +353,7 @@ struct rt_sigframe
        void __user *puc;
        struct siginfo info;
        struct ucontext uc;
-       struct _fpstate fpstate;
+       struct _xstate fpstate;
        char retcode[8];
 };
 
@@ -495,7 +482,7 @@ struct rt_sigframe
        char __user *pretcode;
        struct ucontext uc;
        struct siginfo info;
-       struct _fpstate fpstate;
+       struct _xstate fpstate;
 };
 
 int setup_signal_stack_si(unsigned long stack_top, struct ksignal *ksig,
index 470564b..cb3c223 100644 (file)
@@ -50,7 +50,7 @@ void foo(void)
        DEFINE(HOST_GS, GS);
        DEFINE(HOST_ORIG_AX, ORIG_EAX);
 #else
-       DEFINE(HOST_FP_SIZE, sizeof(struct _fpstate) / sizeof(unsigned long));
+       DEFINE(HOST_FP_SIZE, sizeof(struct _xstate) / sizeof(unsigned long));
        DEFINE_LONGS(HOST_BX, RBX);
        DEFINE_LONGS(HOST_CX, RCX);
        DEFINE_LONGS(HOST_DI, RDI);