Merge branch 'x86/fpu' into x86/smap
authorH. Peter Anvin <hpa@linux.intel.com>
Sat, 22 Sep 2012 00:18:44 +0000 (17:18 -0700)
committerH. Peter Anvin <hpa@linux.intel.com>
Sat, 22 Sep 2012 00:18:44 +0000 (17:18 -0700)
Reason for merge:
       x86/fpu changed the structure of some of the code that x86/smap
       changes; mostly fpu-internal.h but also minor changes to the
       signal code.

Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
Resolved Conflicts:
arch/x86/ia32/ia32_signal.c
arch/x86/include/asm/fpu-internal.h
arch/x86/kernel/signal.c

1  2 
Documentation/kernel-parameters.txt
arch/x86/ia32/ia32_signal.c
arch/x86/include/asm/cpufeature.h
arch/x86/include/asm/fpu-internal.h
arch/x86/include/asm/xsave.h
arch/x86/kernel/cpu/common.c
arch/x86/kernel/signal.c

Simple merge
index 05e62a312bd9d371677dd3af2f28dee9d9e7b02d,8c77c64fbd271e5581c7e41a2fc11b8b0e17184b..efc6a958b71d186a25ee4eadd759f886cf8670f7
@@@ -32,6 -32,6 +32,7 @@@
  #include <asm/sigframe.h>
  #include <asm/sighandling.h>
  #include <asm/sys_ia32.h>
++#include <asm/smap.h>
  
  #define FIX_EFLAGS    __FIX_EFLAGS
  
@@@ -254,8 -256,6 +256,8 @@@ static int ia32_restore_sigcontext(stru
                get_user_ex(*pax, &sc->ax);
        } get_user_catch(err);
  
-       err |= restore_i387_xstate_ia32(buf);
++      err |= restore_xstate_sig(buf, 1);
 +
        return err;
  }
  
@@@ -526,14 -533,9 +531,14 @@@ int ia32_setup_rt_frame(int sig, struc
                 * Not actually used anymore, but left because some gdb
                 * versions need it.
                 */
-               put_user_ex(*((u64 *)&code), (u64 *)frame->retcode);
+               put_user_ex(*((u64 *)&code), (u64 __user *)frame->retcode);
        } put_user_catch(err);
  
 +      err |= copy_siginfo_to_user32(&frame->info, info);
 +      err |= ia32_setup_sigcontext(&frame->uc.uc_mcontext, fpstate,
 +                                   regs, set->sig[0]);
 +      err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
 +
        if (err)
                return -EFAULT;
  
Simple merge
index 0fe13583a0288268fb87eb70a852399c3929f90f,92f3c6ed817fbd6d3ea2d110efb1c7d20e822213..409b9ccf551837f2df045a411d584a134bf0e478
  #include <asm/user.h>
  #include <asm/uaccess.h>
  #include <asm/xsave.h>
++#include <asm/smap.h>
  
- extern unsigned int sig_xstate_size;
+ #ifdef CONFIG_X86_64
+ # include <asm/sigcontext32.h>
+ # include <asm/user32.h>
+ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
+                       compat_sigset_t *set, struct pt_regs *regs);
+ int ia32_setup_frame(int sig, struct k_sigaction *ka,
+                    compat_sigset_t *set, struct pt_regs *regs);
+ #else
+ # define user_i387_ia32_struct        user_i387_struct
+ # define user32_fxsr_struct   user_fxsr_struct
+ # define ia32_setup_frame     __setup_frame
+ # define ia32_setup_rt_frame  __setup_rt_frame
+ #endif
+ extern unsigned int mxcsr_feature_mask;
  extern void fpu_init(void);
+ extern void eager_fpu_init(void);
  
  DECLARE_PER_CPU(struct task_struct *, fpu_owner_task);
  
@@@ -81,123 -121,52 +122,68 @@@ static inline void sanitize_i387_state(
        __sanitize_i387_state(tsk);
  }
  
- #ifdef CONFIG_X86_64
- static inline int fxrstor_checking(struct i387_fxsave_struct *fx)
- {
-       int err;
-       /* See comment in fxsave() below. */
- #ifdef CONFIG_AS_FXSAVEQ
-       asm volatile("1:  fxrstorq %[fx]\n\t"
-                    "2:\n"
-                    ".section .fixup,\"ax\"\n"
-                    "3:  movl $-1,%[err]\n"
-                    "    jmp  2b\n"
-                    ".previous\n"
-                    _ASM_EXTABLE(1b, 3b)
-                    : [err] "=r" (err)
-                    : [fx] "m" (*fx), "0" (0));
- #else
-       asm volatile("1:  rex64/fxrstor (%[fx])\n\t"
-                    "2:\n"
-                    ".section .fixup,\"ax\"\n"
-                    "3:  movl $-1,%[err]\n"
-                    "    jmp  2b\n"
-                    ".previous\n"
-                    _ASM_EXTABLE(1b, 3b)
-                    : [err] "=r" (err)
-                    : [fx] "R" (fx), "m" (*fx), "0" (0));
- #endif
-       return err;
++#define user_insn(insn, output, input...)                             \
++({                                                                    \
++      int err;                                                        \
++      asm volatile(ASM_STAC "\n"                                      \
++                   "1:" #insn "\n\t"                                  \
++                   "2: " ASM_CLAC "\n"                                \
++                   ".section .fixup,\"ax\"\n"                         \
++                   "3:  movl $-1,%[err]\n"                            \
++                   "    jmp  2b\n"                                    \
++                   ".previous\n"                                      \
++                   _ASM_EXTABLE(1b, 3b)                               \
++                   : [err] "=r" (err), output                         \
++                   : "0"(0), input);                                  \
++      err;                                                            \
++})
++
+ #define check_insn(insn, output, input...)                            \
+ ({                                                                    \
+       int err;                                                        \
+       asm volatile("1:" #insn "\n\t"                                  \
+                    "2:\n"                                             \
+                    ".section .fixup,\"ax\"\n"                         \
+                    "3:  movl $-1,%[err]\n"                            \
+                    "    jmp  2b\n"                                    \
+                    ".previous\n"                                      \
+                    _ASM_EXTABLE(1b, 3b)                               \
+                    : [err] "=r" (err), output                         \
+                    : "0"(0), input);                                  \
+       err;                                                            \
+ })
+ static inline int fsave_user(struct i387_fsave_struct __user *fx)
+ {
 -      return check_insn(fnsave %[fx]; fwait,  [fx] "=m" (*fx), "m" (*fx));
++      return user_insn(fnsave %[fx]; fwait,  [fx] "=m" (*fx), "m" (*fx));
  }
  
  static inline int fxsave_user(struct i387_fxsave_struct __user *fx)
  {
-       int err;
+       if (config_enabled(CONFIG_X86_32))
 -              return check_insn(fxsave %[fx], [fx] "=m" (*fx), "m" (*fx));
++              return user_insn(fxsave %[fx], [fx] "=m" (*fx), "m" (*fx));
+       else if (config_enabled(CONFIG_AS_FXSAVEQ))
 -              return check_insn(fxsaveq %[fx], [fx] "=m" (*fx), "m" (*fx));
++              return user_insn(fxsaveq %[fx], [fx] "=m" (*fx), "m" (*fx));
  
-       /*
-        * Clear the bytes not touched by the fxsave and reserved
-        * for the SW usage.
-        */
-       err = __clear_user(&fx->sw_reserved,
-                          sizeof(struct _fpx_sw_bytes));
-       if (unlikely(err))
-               return -EFAULT;
-       /* See comment in fxsave() below. */
- #ifdef CONFIG_AS_FXSAVEQ
-       asm volatile(ASM_STAC "\n"
-                    "1:  fxsaveq %[fx]\n\t"
-                    "2: " ASM_CLAC "\n"
-                    ".section .fixup,\"ax\"\n"
-                    "3:  movl $-1,%[err]\n"
-                    "    jmp  2b\n"
-                    ".previous\n"
-                    _ASM_EXTABLE(1b, 3b)
-                    : [err] "=r" (err), [fx] "=m" (*fx)
-                    : "0" (0));
- #else
-       asm volatile(ASM_STAC "\n"
-                    "1:  rex64/fxsave (%[fx])\n\t"
-                    "2: " ASM_CLAC "\n"
-                    ".section .fixup,\"ax\"\n"
-                    "3:  movl $-1,%[err]\n"
-                    "    jmp  2b\n"
-                    ".previous\n"
-                    _ASM_EXTABLE(1b, 3b)
-                    : [err] "=r" (err), "=m" (*fx)
-                    : [fx] "R" (fx), "0" (0));
- #endif
-       if (unlikely(err) &&
-           __clear_user(fx, sizeof(struct i387_fxsave_struct)))
-               err = -EFAULT;
-       /* No need to clear here because the caller clears USED_MATH */
-       return err;
+       /* See comment in fpu_fxsave() below. */
 -      return check_insn(rex64/fxsave (%[fx]), "=m" (*fx), [fx] "R" (fx));
++      return user_insn(rex64/fxsave (%[fx]), "=m" (*fx), [fx] "R" (fx));
  }
  
- static inline void fpu_fxsave(struct fpu *fpu)
+ static inline int fxrstor_checking(struct i387_fxsave_struct *fx)
  {
-       /* Using "rex64; fxsave %0" is broken because, if the memory operand
-          uses any extended registers for addressing, a second REX prefix
-          will be generated (to the assembler, rex64 followed by semicolon
-          is a separate instruction), and hence the 64-bitness is lost. */
+       if (config_enabled(CONFIG_X86_32))
+               return check_insn(fxrstor %[fx], "=m" (*fx), [fx] "m" (*fx));
+       else if (config_enabled(CONFIG_AS_FXSAVEQ))
+               return check_insn(fxrstorq %[fx], "=m" (*fx), [fx] "m" (*fx));
  
- #ifdef CONFIG_AS_FXSAVEQ
-       /* Using "fxsaveq %0" would be the ideal choice, but is only supported
-          starting with gas 2.16. */
-       __asm__ __volatile__("fxsaveq %0"
-                            : "=m" (fpu->state->fxsave));
- #else
-       /* Using, as a workaround, the properly prefixed form below isn't
-          accepted by any binutils version so far released, complaining that
-          the same type of prefix is used twice if an extended register is
-          needed for addressing (fix submitted to mainline 2005-11-21).
-       asm volatile("rex64/fxsave %0"
-                    : "=m" (fpu->state->fxsave));
-          This, however, we can work around by forcing the compiler to select
-          an addressing mode that doesn't require extended registers. */
-       asm volatile("rex64/fxsave (%[fx])"
-                    : "=m" (fpu->state->fxsave)
-                    : [fx] "R" (&fpu->state->fxsave));
- #endif
+       /* See comment in fpu_fxsave() below. */
+       return check_insn(rex64/fxrstor (%[fx]), "=m" (*fx), [fx] "R" (fx),
+                         "m" (*fx));
  }
  
- #else  /* CONFIG_X86_32 */
- /* perform fxrstor iff the processor has extended states, otherwise frstor */
- static inline int fxrstor_checking(struct i387_fxsave_struct *fx)
+ static inline int frstor_checking(struct i387_fsave_struct *fx)
  {
-       /*
-        * The "nop" is needed to make the instructions the same
-        * length.
-        */
-       alternative_input(
-               "nop ; frstor %1",
-               "fxrstor %1",
-               X86_FEATURE_FXSR,
-               "m" (*fx));
-       return 0;
+       return check_insn(frstor %[fx], "=m" (*fx), [fx] "m" (*fx));
  }
  
  static inline void fpu_fxsave(struct fpu *fpu)
Simple merge
Simple merge
index 932612887e92ebb241e2e6e0cdcadf9695960fa6,e10f96a7e047563dc1d8602a750cb3b8ac17484a..036bddb46236c15141bd383f6e41f8c30f6c7e7f
@@@ -118,8 -119,6 +118,8 @@@ int restore_sigcontext(struct pt_regs *
                get_user_ex(*pax, &sc->ax);
        } get_user_catch(err);
  
-       err |= restore_i387_xstate(buf);
++      err |= restore_xstate_sig(buf, config_enabled(CONFIG_X86_32));
 +
        return err;
  }
  
@@@ -385,11 -386,6 +383,11 @@@ static int __setup_rt_frame(int sig, st
                 */
                put_user_ex(*((u64 *)&rt_retcode), (u64 *)frame->retcode);
        } put_user_catch(err);
++      
 +      err |= copy_siginfo_to_user(&frame->info, info);
 +      err |= setup_sigcontext(&frame->uc.uc_mcontext, fpstate,
 +                              regs, set->sig[0]);
 +      err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
  
        if (err)
                return -EFAULT;
@@@ -477,6 -472,74 +475,75 @@@ static int __setup_rt_frame(int sig, st
  }
  #endif /* CONFIG_X86_32 */
  
 -              err |= setup_sigcontext(&frame->uc.uc_mcontext, fpstate,
 -                                      regs, set->sig[0]);
 -              err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
+ static int x32_setup_rt_frame(int sig, struct k_sigaction *ka,
+                             siginfo_t *info, compat_sigset_t *set,
+                             struct pt_regs *regs)
+ {
+ #ifdef CONFIG_X86_X32_ABI
+       struct rt_sigframe_x32 __user *frame;
+       void __user *restorer;
+       int err = 0;
+       void __user *fpstate = NULL;
+       frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate);
+       if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
+               return -EFAULT;
+       if (ka->sa.sa_flags & SA_SIGINFO) {
+               if (copy_siginfo_to_user32(&frame->info, info))
+                       return -EFAULT;
+       }
+       put_user_try {
+               /* Create the ucontext.  */
+               if (cpu_has_xsave)
+                       put_user_ex(UC_FP_XSTATE, &frame->uc.uc_flags);
+               else
+                       put_user_ex(0, &frame->uc.uc_flags);
+               put_user_ex(0, &frame->uc.uc_link);
+               put_user_ex(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
+               put_user_ex(sas_ss_flags(regs->sp),
+                           &frame->uc.uc_stack.ss_flags);
+               put_user_ex(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
+               put_user_ex(0, &frame->uc.uc__pad0);
+               if (ka->sa.sa_flags & SA_RESTORER) {
+                       restorer = ka->sa.sa_restorer;
+               } else {
+                       /* could use a vstub here */
+                       restorer = NULL;
+                       err |= -EFAULT;
+               }
+               put_user_ex(restorer, &frame->pretcode);
+       } put_user_catch(err);
++      err |= setup_sigcontext(&frame->uc.uc_mcontext, fpstate,
++                              regs, set->sig[0]);
++      err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
++
+       if (err)
+               return -EFAULT;
+       /* Set up registers for signal handler */
+       regs->sp = (unsigned long) frame;
+       regs->ip = (unsigned long) ka->sa.sa_handler;
+       /* We use the x32 calling convention here... */
+       regs->di = sig;
+       regs->si = (unsigned long) &frame->info;
+       regs->dx = (unsigned long) &frame->uc;
+       loadsegment(ds, __USER_DS);
+       loadsegment(es, __USER_DS);
+       regs->cs = __USER_CS;
+       regs->ss = __USER_DS;
+ #endif        /* CONFIG_X86_X32_ABI */
+       return 0;
+ }
  #ifdef CONFIG_X86_32
  /*
   * Atomically swap in the new signal mask, and wait for a signal.