OSDN Git Service

Merge tag 'v4.0-rc5' into x86/fpu, to prevent conflicts
authorIngo Molnar <mingo@kernel.org>
Mon, 23 Mar 2015 09:13:36 +0000 (10:13 +0100)
committerIngo Molnar <mingo@kernel.org>
Mon, 23 Mar 2015 09:13:36 +0000 (10:13 +0100)
Signed-off-by: Ingo Molnar <mingo@kernel.org>
1  2 
arch/x86/include/asm/fpu-internal.h
arch/x86/kernel/i387.c
arch/x86/kernel/process.c
arch/x86/kernel/traps.c
arch/x86/kernel/xsave.c

@@@ -67,34 -67,6 +67,34 @@@ extern void finit_soft_fpu(struct i387_
  static inline void finit_soft_fpu(struct i387_soft_struct *soft) {}
  #endif
  
 +/*
 + * Must be run with preemption disabled: this clears the fpu_owner_task,
 + * on this CPU.
 + *
 + * This will disable any lazy FPU state restore of the current FPU state,
 + * but if the current thread owns the FPU, it will still be saved by.
 + */
 +static inline void __cpu_disable_lazy_restore(unsigned int cpu)
 +{
 +      per_cpu(fpu_owner_task, cpu) = NULL;
 +}
 +
 +/*
 + * Used to indicate that the FPU state in memory is newer than the FPU
 + * state in registers, and the FPU state should be reloaded next time the
 + * task is run. Only safe on the current task, or non-running tasks.
 + */
 +static inline void task_disable_lazy_fpu_restore(struct task_struct *tsk)
 +{
 +      tsk->thread.fpu.last_cpu = ~0;
 +}
 +
 +static inline int fpu_lazy_restore(struct task_struct *new, unsigned int cpu)
 +{
 +      return new == this_cpu_read_stable(fpu_owner_task) &&
 +              cpu == new->thread.fpu.last_cpu;
 +}
 +
  static inline int is_ia32_compat_frame(void)
  {
        return config_enabled(CONFIG_IA32_EMULATION) &&
@@@ -135,6 -107,7 +135,6 @@@ static __always_inline __pure bool use_
  
  static inline void fx_finit(struct i387_fxsave_struct *fx)
  {
 -      memset(fx, 0, xstate_size);
        fx->cwd = 0x37f;
        fx->mxcsr = MXCSR_DEFAULT;
  }
@@@ -397,7 -370,7 +397,7 @@@ static inline void drop_fpu(struct task
        preempt_disable();
        tsk->thread.fpu_counter = 0;
        __drop_fpu(tsk);
-       clear_used_math();
+       clear_stopped_child_used_math(tsk);
        preempt_enable();
  }
  
@@@ -427,6 -400,24 +427,6 @@@ static inline void drop_init_fpu(struc
   */
  typedef struct { int preload; } fpu_switch_t;
  
 -/*
 - * Must be run with preemption disabled: this clears the fpu_owner_task,
 - * on this CPU.
 - *
 - * This will disable any lazy FPU state restore of the current FPU state,
 - * but if the current thread owns the FPU, it will still be saved by.
 - */
 -static inline void __cpu_disable_lazy_restore(unsigned int cpu)
 -{
 -      per_cpu(fpu_owner_task, cpu) = NULL;
 -}
 -
 -static inline int fpu_lazy_restore(struct task_struct *new, unsigned int cpu)
 -{
 -      return new == this_cpu_read_stable(fpu_owner_task) &&
 -              cpu == new->thread.fpu.last_cpu;
 -}
 -
  static inline fpu_switch_t switch_fpu_prepare(struct task_struct *old, struct task_struct *new, int cpu)
  {
        fpu_switch_t fpu;
         * If the task has used the math, pre-load the FPU on xsave processors
         * or if the past 5 consecutive context-switches used math.
         */
 -      fpu.preload = tsk_used_math(new) && (use_eager_fpu() ||
 -                                           new->thread.fpu_counter > 5);
 +      fpu.preload = tsk_used_math(new) &&
 +                    (use_eager_fpu() || new->thread.fpu_counter > 5);
 +
        if (__thread_has_fpu(old)) {
                if (!__save_init_fpu(old))
 -                      cpu = ~0;
 -              old->thread.fpu.last_cpu = cpu;
 -              old->thread.fpu.has_fpu = 0;    /* But leave fpu_owner_task! */
 +                      task_disable_lazy_fpu_restore(old);
 +              else
 +                      old->thread.fpu.last_cpu = cpu;
 +
 +              /* But leave fpu_owner_task! */
 +              old->thread.fpu.has_fpu = 0;
  
                /* Don't change CR0.TS if we just switch! */
                if (fpu.preload) {
                        stts();
        } else {
                old->thread.fpu_counter = 0;
 -              old->thread.fpu.last_cpu = ~0;
 +              task_disable_lazy_fpu_restore(old);
                if (fpu.preload) {
                        new->thread.fpu_counter++;
 -                      if (!use_eager_fpu() && fpu_lazy_restore(new, cpu))
 +                      if (fpu_lazy_restore(new, cpu))
                                fpu.preload = 0;
                        else
                                prefetch(new->thread.fpu.state);
@@@ -533,6 -520,24 +533,6 @@@ static inline void __save_fpu(struct ta
  }
  
  /*
 - * These disable preemption on their own and are safe
 - */
 -static inline void save_init_fpu(struct task_struct *tsk)
 -{
 -      WARN_ON_ONCE(!__thread_has_fpu(tsk));
 -
 -      if (use_eager_fpu()) {
 -              __save_fpu(tsk);
 -              return;
 -      }
 -
 -      preempt_disable();
 -      __save_init_fpu(tsk);
 -      __thread_fpu_end(tsk);
 -      preempt_enable();
 -}
 -
 -/*
   * i387 state interaction
   */
  static inline unsigned short get_fpu_cwd(struct task_struct *tsk)
diff --combined arch/x86/kernel/i387.c
@@@ -13,6 -13,7 +13,7 @@@
  #include <asm/sigcontext.h>
  #include <asm/processor.h>
  #include <asm/math_emu.h>
+ #include <asm/tlbflush.h>
  #include <asm/uaccess.h>
  #include <asm/ptrace.h>
  #include <asm/i387.h>
@@@ -41,8 -42,8 +42,8 @@@ void kernel_fpu_enable(void
   * be set (so that the clts/stts pair does nothing that is
   * visible in the interrupted kernel thread).
   *
 - * Except for the eagerfpu case when we return 1 unless we've already
 - * been eager and saved the state in kernel_fpu_begin().
 + * Except for the eagerfpu case when we return true; in the likely case
 + * the thread has FPU but we are not going to set/clear TS.
   */
  static inline bool interrupted_kernel_fpu_idle(void)
  {
@@@ -50,7 -51,7 +51,7 @@@
                return false;
  
        if (use_eager_fpu())
 -              return __thread_has_fpu(current);
 +              return true;
  
        return !__thread_has_fpu(current) &&
                (read_cr0() & X86_CR0_TS);
@@@ -93,10 -94,9 +94,10 @@@ void __kernel_fpu_begin(void
  
        if (__thread_has_fpu(me)) {
                __save_init_fpu(me);
 -      } else if (!use_eager_fpu()) {
 +      } else {
                this_cpu_write(fpu_owner_task, NULL);
 -              clts();
 +              if (!use_eager_fpu())
 +                      clts();
        }
  }
  EXPORT_SYMBOL(__kernel_fpu_begin);
@@@ -120,13 -120,10 +121,13 @@@ void unlazy_fpu(struct task_struct *tsk
  {
        preempt_disable();
        if (__thread_has_fpu(tsk)) {
 -              __save_init_fpu(tsk);
 -              __thread_fpu_end(tsk);
 -      } else
 -              tsk->thread.fpu_counter = 0;
 +              if (use_eager_fpu()) {
 +                      __save_fpu(tsk);
 +              } else {
 +                      __save_init_fpu(tsk);
 +                      __thread_fpu_end(tsk);
 +              }
 +      }
        preempt_enable();
  }
  EXPORT_SYMBOL(unlazy_fpu);
@@@ -197,7 -194,7 +198,7 @@@ void fpu_init(void
        if (cpu_has_xmm)
                cr4_mask |= X86_CR4_OSXMMEXCPT;
        if (cr4_mask)
-               set_in_cr4(cr4_mask);
+               cr4_set_bits(cr4_mask);
  
        cr0 = read_cr0();
        cr0 &= ~(X86_CR0_TS|X86_CR0_EM); /* clear TS and EM */
@@@ -224,12 -221,11 +225,12 @@@ void fpu_finit(struct fpu *fpu
                return;
        }
  
 +      memset(fpu->state, 0, xstate_size);
 +
        if (cpu_has_fxsr) {
                fx_finit(&fpu->state->fxsave);
        } else {
                struct i387_fsave_struct *fp = &fpu->state->fsave;
 -              memset(fp, 0, xstate_size);
                fp->cwd = 0xffff037fu;
                fp->swd = 0xffff0000u;
                fp->twd = 0xffffffffu;
@@@ -251,7 -247,7 +252,7 @@@ int init_fpu(struct task_struct *tsk
        if (tsk_used_math(tsk)) {
                if (cpu_has_fpu && tsk == current)
                        unlazy_fpu(tsk);
 -              tsk->thread.fpu.last_cpu = ~0;
 +              task_disable_lazy_fpu_restore(tsk);
                return 0;
        }
  
@@@ -340,7 -336,6 +341,7 @@@ int xstateregs_get(struct task_struct *
                unsigned int pos, unsigned int count,
                void *kbuf, void __user *ubuf)
  {
 +      struct xsave_struct *xsave = &target->thread.fpu.state->xsave;
        int ret;
  
        if (!cpu_has_xsave)
         * memory layout in the thread struct, so that we can copy the entire
         * xstateregs to the user using one user_regset_copyout().
         */
 -      memcpy(&target->thread.fpu.state->fxsave.sw_reserved,
 -             xstate_fx_sw_bytes, sizeof(xstate_fx_sw_bytes));
 -
 +      memcpy(&xsave->i387.sw_reserved,
 +              xstate_fx_sw_bytes, sizeof(xstate_fx_sw_bytes));
        /*
         * Copy the xstate memory layout.
         */
 -      ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
 -                                &target->thread.fpu.state->xsave, 0, -1);
 +      ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, xsave, 0, -1);
        return ret;
  }
  
@@@ -368,8 -365,8 +369,8 @@@ int xstateregs_set(struct task_struct *
                  unsigned int pos, unsigned int count,
                  const void *kbuf, const void __user *ubuf)
  {
 +      struct xsave_struct *xsave = &target->thread.fpu.state->xsave;
        int ret;
 -      struct xsave_hdr_struct *xsave_hdr;
  
        if (!cpu_has_xsave)
                return -ENODEV;
        if (ret)
                return ret;
  
 -      ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
 -                               &target->thread.fpu.state->xsave, 0, -1);
 -
 +      ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, xsave, 0, -1);
        /*
         * mxcsr reserved bits must be masked to zero for security reasons.
         */
 -      target->thread.fpu.state->fxsave.mxcsr &= mxcsr_feature_mask;
 -
 -      xsave_hdr = &target->thread.fpu.state->xsave.xsave_hdr;
 -
 -      xsave_hdr->xstate_bv &= pcntxt_mask;
 +      xsave->i387.mxcsr &= mxcsr_feature_mask;
 +      xsave->xsave_hdr.xstate_bv &= pcntxt_mask;
        /*
         * These bits must be zero.
         */
 -      memset(xsave_hdr->reserved, 0, 48);
 -
 +      memset(&xsave->xsave_hdr.reserved, 0, 48);
        return ret;
  }
  
@@@ -28,6 -28,7 +28,7 @@@
  #include <asm/fpu-internal.h>
  #include <asm/debugreg.h>
  #include <asm/nmi.h>
+ #include <asm/tlbflush.h>
  
  /*
   * per-CPU TSS segments. Threads are completely 'soft' on Linux,
@@@ -68,8 -69,8 +69,8 @@@ int arch_dup_task_struct(struct task_st
  
        dst->thread.fpu_counter = 0;
        dst->thread.fpu.has_fpu = 0;
 -      dst->thread.fpu.last_cpu = ~0;
        dst->thread.fpu.state = NULL;
 +      task_disable_lazy_fpu_restore(dst);
        if (tsk_used_math(src)) {
                int err = fpu_alloc(&dst->thread.fpu);
                if (err)
@@@ -130,7 -131,6 +131,7 @@@ void flush_thread(void
  
        flush_ptrace_hw_breakpoint(tsk);
        memset(tsk->thread.tls_array, 0, sizeof(tsk->thread.tls_array));
 +
        drop_init_fpu(tsk);
        /*
         * Free the FPU state for non xsave platforms. They get reallocated
         */
        if (!use_eager_fpu())
                free_thread_xstate(tsk);
 +      else if (!used_math()) {
 +              /* kthread execs. TODO: cleanup this horror. */
 +              if (WARN_ON(init_fpu(current)))
 +                      force_sig(SIGKILL, current);
 +              math_state_restore();
 +      }
  }
  
  static void hard_disable_TSC(void)
  {
-       write_cr4(read_cr4() | X86_CR4_TSD);
+       cr4_set_bits(X86_CR4_TSD);
  }
  
  void disable_TSC(void)
  
  static void hard_enable_TSC(void)
  {
-       write_cr4(read_cr4() & ~X86_CR4_TSD);
+       cr4_clear_bits(X86_CR4_TSD);
  }
  
  static void enable_TSC(void)
diff --combined arch/x86/kernel/traps.c
@@@ -384,7 -384,7 +384,7 @@@ dotraplinkage void do_bounds(struct pt_
                goto exit;
        conditional_sti(regs);
  
-       if (!user_mode(regs))
+       if (!user_mode_vm(regs))
                die("bounds", regs, error_code);
  
        if (!cpu_feature_enabled(X86_FEATURE_MPX)) {
@@@ -637,7 -637,7 +637,7 @@@ dotraplinkage void do_debug(struct pt_r
         * then it's very likely the result of an icebp/int01 trap.
         * User wants a sigtrap for that.
         */
-       if (!dr6 && user_mode(regs))
+       if (!dr6 && user_mode_vm(regs))
                user_icebp = 1;
  
        /* Catch kmemcheck conditions first of all! */
@@@ -734,7 -734,7 +734,7 @@@ static void math_error(struct pt_regs *
        /*
         * Save the info for the exception handler and clear the error.
         */
 -      save_init_fpu(task);
 +      unlazy_fpu(task);
        task->thread.trap_nr = trapnr;
        task->thread.error_code = error_code;
        info.si_signo = SIGFPE;
diff --combined arch/x86/kernel/xsave.c
@@@ -12,6 -12,7 +12,7 @@@
  #include <asm/i387.h>
  #include <asm/fpu-internal.h>
  #include <asm/sigframe.h>
+ #include <asm/tlbflush.h>
  #include <asm/xcr.h>
  
  /*
@@@ -378,7 -379,7 +379,7 @@@ int __restore_xstate_sig(void __user *b
                 * thread's fpu state, reconstruct fxstate from the fsave
                 * header. Sanitize the copied state etc.
                 */
-               struct xsave_struct *xsave = &tsk->thread.fpu.state->xsave;
+               struct fpu *fpu = &tsk->thread.fpu;
                struct user_i387_ia32_struct env;
                int err = 0;
  
                 */
                drop_fpu(tsk);
  
-               if (__copy_from_user(xsave, buf_fx, state_size) ||
+               if (__copy_from_user(&fpu->state->xsave, buf_fx, state_size) ||
                    __copy_from_user(&env, buf, sizeof(env))) {
+                       fpu_finit(fpu);
                        err = -1;
                } else {
                        sanitize_restored_xstate(tsk, &env, xstate_bv, fx_only);
-                       set_used_math();
                }
  
+               set_used_math();
                if (use_eager_fpu()) {
                        preempt_disable();
                        math_state_restore();
@@@ -453,7 -455,7 +455,7 @@@ static void prepare_fx_sw_frame(void
   */
  static inline void xstate_enable(void)
  {
-       set_in_cr4(X86_CR4_OSXSAVE);
+       cr4_set_bits(X86_CR4_OSXSAVE);
        xsetbv(XCR_XFEATURE_ENABLED_MASK, pcntxt_mask);
  }
  
@@@ -688,7 -690,7 +690,7 @@@ void eager_fpu_init(void
  {
        static __refdata void (*boot_func)(void) = eager_fpu_init_bp;
  
 -      clear_used_math();
 +      WARN_ON(used_math());
        current_thread_info()->status = 0;
  
        if (eagerfpu == ENABLE)
                boot_func();
                boot_func = NULL;
        }
 -
 -      /*
 -       * This is same as math_state_restore(). But use_xsave() is
 -       * not yet patched to use math_state_restore().
 -       */
 -      init_fpu(current);
 -      __thread_fpu_begin(current);
 -      if (cpu_has_xsave)
 -              xrstor_state(init_xstate_buf, -1);
 -      else
 -              fxrstor_checking(&init_xstate_buf->i387);
  }
  
  /*