]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
Merge branch 'x86-fpu-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 1 Oct 2012 18:10:52 +0000 (11:10 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 1 Oct 2012 18:10:52 +0000 (11:10 -0700)
Pull x86/fpu update from Ingo Molnar:
 "The biggest change is the addition of the non-lazy (eager) FPU saving
  support model and enabling it on CPUs with optimized xsaveopt/xrstor
  FPU state saving instructions.

  There are also various Sparse fixes"

Fix up trivial add-add conflict in arch/x86/kernel/traps.c

* 'x86-fpu-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  x86, kvm: fix kvm's usage of kernel_fpu_begin/end()
  x86, fpu: remove cpu_has_xmm check in the fx_finit()
  x86, fpu: make eagerfpu= boot param tri-state
  x86, fpu: enable eagerfpu by default for xsaveopt
  x86, fpu: decouple non-lazy/eager fpu restore from xsave
  x86, fpu: use non-lazy fpu restore for processors supporting xsave
  lguest, x86: handle guest TS bit for lazy/non-lazy fpu host models
  x86, fpu: always use kernel_fpu_begin/end() for in-kernel FPU usage
  x86, kvm: use kernel_fpu_begin/end() in kvm_load/put_guest_fpu()
  x86, fpu: remove unnecessary user_fpu_end() in save_xstate_sig()
  x86, fpu: drop_fpu() before restoring new state from sigframe
  x86, fpu: Unify signal handling code paths for x86 and x86_64 kernels
  x86, fpu: Consolidate inline asm routines for saving/restoring fpu state
  x86, signal: Cleanup ifdefs and is_ia32, is_x32

1  2 
Documentation/kernel-parameters.txt
arch/x86/include/asm/cpufeature.h
arch/x86/kernel/cpu/common.c
arch/x86/kernel/ptrace.c
arch/x86/kernel/signal.c
arch/x86/kernel/traps.c
arch/x86/kvm/vmx.c
arch/x86/kvm/x86.c

index d1cda8d892aafde31b16632087db1507e0db6f09,46a6a8288dec71b80ab6fba839ab12b9984b7b8e..df551dfa8e52ae36819edd7b33d0a381f7b53e16
@@@ -1833,6 -1833,12 +1833,12 @@@ bytes respectively. Such letter suffixe
                        and restore using xsave. The kernel will fallback to
                        enabling legacy floating-point and sse state.
  
+       eagerfpu=       [X86]
+                       on      enable eager fpu restore
+                       off     disable eager fpu restore
+                       auto    selects the default scheme, which automatically
+                               enables eagerfpu restore for xsaveopt.
        nohlt           [BUGS=ARM,SH] Tells the kernel that the sleep(SH) or
                        wfi(ARM) instruction doesn't work correctly and not to
                        use it. This is also useful when using JTAG debugger.
        rcutree.rcu_cpu_stall_timeout= [KNL,BOOT]
                        Set timeout for RCU CPU stall warning messages.
  
 +      rcutree.jiffies_till_first_fqs= [KNL,BOOT]
 +                      Set delay from grace-period initialization to
 +                      first attempt to force quiescent states.
 +                      Units are jiffies, minimum value is zero,
 +                      and maximum value is HZ.
 +
 +      rcutree.jiffies_till_next_fqs= [KNL,BOOT]
 +                      Set delay between subsequent attempts to force
 +                      quiescent states.  Units are jiffies, minimum
 +                      value is one, and maximum value is HZ.
 +
        rcutorture.fqs_duration= [KNL,BOOT]
                        Set duration of force_quiescent_state bursts.
  
        smart2=         [HW]
                        Format: <io1>[,<io2>[,...,<io8>]]
  
 -      smp-alt-once    [X86-32,SMP] On a hotplug CPU system, only
 -                      attempt to substitute SMP alternatives once at boot.
 -
        smsc-ircc2.nopnp        [HW] Don't use PNP to discover SMC devices
        smsc-ircc2.ircc_cfg=    [HW] Device configuration I/O port
        smsc-ircc2.ircc_sir=    [HW] SIR base I/O port
index 633b6176cf6097bd64cde003dbcfadee48c88a34,0debdb5184402f505c6f0df6420250b37fa73774..16cae425d1f80fe40a6b1d6785b0d494a0566b8b
@@@ -97,6 -97,7 +97,7 @@@
  #define X86_FEATURE_EXTD_APICID       (3*32+26) /* has extended APICID (8 bits) */
  #define X86_FEATURE_AMD_DCM     (3*32+27) /* multi-node processor */
  #define X86_FEATURE_APERFMPERF        (3*32+28) /* APERFMPERF */
+ #define X86_FEATURE_EAGER_FPU (3*32+29) /* "eagerfpu" Non lazy FPU restore */
  
  /* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */
  #define X86_FEATURE_XMM3      (4*32+ 0) /* "pni" SSE-3 */
  #define X86_FEATURE_RTM               (9*32+11) /* Restricted Transactional Memory */
  #define X86_FEATURE_RDSEED    (9*32+18) /* The RDSEED instruction */
  #define X86_FEATURE_ADX               (9*32+19) /* The ADCX and ADOX instructions */
 +#define X86_FEATURE_SMAP      (9*32+20) /* Supervisor Mode Access Prevention */
  
  #if defined(__KERNEL__) && !defined(__ASSEMBLY__)
  
@@@ -300,12 -300,14 +301,14 @@@ extern const char * const x86_power_fla
  #define cpu_has_xmm4_2                boot_cpu_has(X86_FEATURE_XMM4_2)
  #define cpu_has_x2apic                boot_cpu_has(X86_FEATURE_X2APIC)
  #define cpu_has_xsave         boot_cpu_has(X86_FEATURE_XSAVE)
+ #define cpu_has_xsaveopt      boot_cpu_has(X86_FEATURE_XSAVEOPT)
  #define cpu_has_osxsave               boot_cpu_has(X86_FEATURE_OSXSAVE)
  #define cpu_has_hypervisor    boot_cpu_has(X86_FEATURE_HYPERVISOR)
  #define cpu_has_pclmulqdq     boot_cpu_has(X86_FEATURE_PCLMULQDQ)
  #define cpu_has_perfctr_core  boot_cpu_has(X86_FEATURE_PERFCTR_CORE)
  #define cpu_has_cx8           boot_cpu_has(X86_FEATURE_CX8)
  #define cpu_has_cx16          boot_cpu_has(X86_FEATURE_CX16)
+ #define cpu_has_eager_fpu     boot_cpu_has(X86_FEATURE_EAGER_FPU)
  
  #if defined(CONFIG_X86_INVLPG) || defined(CONFIG_X86_64)
  # define cpu_has_invlpg               1
index 134505e07b09ec46612a6b2bf6dee4c2c6e5b089,b0fe078614d88713a86e0dff75eb23870e6b7495..761cb354704151041b6820f38749c9e8289ec4f5
@@@ -1023,16 -1023,14 +1023,16 @@@ void __cpuinit print_cpu_info(struct cp
                printk(KERN_CONT "%s ", vendor);
  
        if (c->x86_model_id[0])
 -              printk(KERN_CONT "%s", c->x86_model_id);
 +              printk(KERN_CONT "%s", strim(c->x86_model_id));
        else
                printk(KERN_CONT "%d86", c->x86);
  
 +      printk(KERN_CONT " (fam: %02x, model: %02x", c->x86, c->x86_model);
 +
        if (c->x86_mask || c->cpuid_level >= 0)
 -              printk(KERN_CONT " stepping %02x\n", c->x86_mask);
 +              printk(KERN_CONT ", stepping: %02x)\n", c->x86_mask);
        else
 -              printk(KERN_CONT "\n");
 +              printk(KERN_CONT ")\n");
  
        print_cpu_msr(c);
  }
@@@ -1118,6 -1116,8 +1118,6 @@@ void syscall_init(void
               X86_EFLAGS_TF|X86_EFLAGS_DF|X86_EFLAGS_IF|X86_EFLAGS_IOPL);
  }
  
 -unsigned long kernel_eflags;
 -
  /*
   * Copies of the original ist values from the tss are only accessed during
   * debugging, no special alignment required.
@@@ -1297,8 -1297,9 +1297,7 @@@ void __cpuinit cpu_init(void
        dbg_restore_debug_regs();
  
        fpu_init();
-       xsave_init();
  
 -      raw_local_save_flags(kernel_eflags);
 -
        if (is_uv_system())
                uv_cpu_init();
  }
@@@ -1350,6 -1351,5 +1349,5 @@@ void __cpuinit cpu_init(void
        dbg_restore_debug_regs();
  
        fpu_init();
-       xsave_init();
  }
  #endif
diff --combined arch/x86/kernel/ptrace.c
index 9f94f8ec26e40f60f35e36e3151c6115b876ba73,861a9d1a463dc82dbf24b22c9748b58d111c2859..b00b33a183908bdb201aa38266e40ad87d89754d
@@@ -21,7 -21,6 +21,7 @@@
  #include <linux/signal.h>
  #include <linux/perf_event.h>
  #include <linux/hw_breakpoint.h>
 +#include <linux/rcupdate.h>
  
  #include <asm/uaccess.h>
  #include <asm/pgtable.h>
@@@ -1333,9 -1332,6 +1333,6 @@@ static const struct user_regset_view us
  #define genregs32_get         genregs_get
  #define genregs32_set         genregs_set
  
- #define user_i387_ia32_struct user_i387_struct
- #define user32_fxsr_struct    user_fxsr_struct
  #endif        /* CONFIG_X86_64 */
  
  #if defined CONFIG_X86_32 || defined CONFIG_IA32_EMULATION
@@@ -1464,8 -1460,6 +1461,8 @@@ long syscall_trace_enter(struct pt_reg
  {
        long ret = 0;
  
 +      rcu_user_exit();
 +
        /*
         * If we stepped into a sysenter/syscall insn, it trapped in
         * kernel mode; do_debug() cleared TF and set TIF_SINGLESTEP.
@@@ -1529,6 -1523,4 +1526,6 @@@ void syscall_trace_leave(struct pt_reg
                        !test_thread_flag(TIF_SYSCALL_EMU);
        if (step || test_thread_flag(TIF_SYSCALL_TRACE))
                tracehook_report_syscall_exit(regs, step);
 +
 +      rcu_user_enter();
  }
diff --combined arch/x86/kernel/signal.c
index bca0ab903e577dd96c017cd2b1deeded1e28ea60,e10f96a7e047563dc1d8602a750cb3b8ac17484a..3160c26db5e7cc29f396c08958142ec7cba3e2c3
@@@ -114,7 -114,7 +114,7 @@@ int restore_sigcontext(struct pt_regs *
                regs->orig_ax = -1;             /* disable syscall checks */
  
                get_user_ex(buf, &sc->fpstate);
-               err |= restore_i387_xstate(buf);
+               err |= restore_xstate_sig(buf, config_enabled(CONFIG_X86_32));
  
                get_user_ex(*pax, &sc->ax);
        } get_user_catch(err);
@@@ -206,35 -206,32 +206,32 @@@ get_sigframe(struct k_sigaction *ka, st
             void __user **fpstate)
  {
        /* Default to using normal stack */
+       unsigned long math_size = 0;
        unsigned long sp = regs->sp;
+       unsigned long buf_fx = 0;
        int onsigstack = on_sig_stack(sp);
  
- #ifdef CONFIG_X86_64
        /* redzone */
-       sp -= 128;
- #endif /* CONFIG_X86_64 */
+       if (config_enabled(CONFIG_X86_64))
+               sp -= 128;
  
        if (!onsigstack) {
                /* This is the X/Open sanctioned signal stack switching.  */
                if (ka->sa.sa_flags & SA_ONSTACK) {
                        if (current->sas_ss_size)
                                sp = current->sas_ss_sp + current->sas_ss_size;
-               } else {
- #ifdef CONFIG_X86_32
-                       /* This is the legacy signal stack switching. */
-                       if ((regs->ss & 0xffff) != __USER_DS &&
-                               !(ka->sa.sa_flags & SA_RESTORER) &&
-                                       ka->sa.sa_restorer)
+               } else if (config_enabled(CONFIG_X86_32) &&
+                          (regs->ss & 0xffff) != __USER_DS &&
+                          !(ka->sa.sa_flags & SA_RESTORER) &&
+                          ka->sa.sa_restorer) {
+                               /* This is the legacy signal stack switching. */
                                sp = (unsigned long) ka->sa.sa_restorer;
- #endif /* CONFIG_X86_32 */
                }
        }
  
        if (used_math()) {
-               sp -= sig_xstate_size;
- #ifdef CONFIG_X86_64
-               sp = round_down(sp, 64);
- #endif /* CONFIG_X86_64 */
+               sp = alloc_mathframe(sp, config_enabled(CONFIG_X86_32),
+                                    &buf_fx, &math_size);
                *fpstate = (void __user *)sp;
        }
  
        if (onsigstack && !likely(on_sig_stack(sp)))
                return (void __user *)-1L;
  
-       /* save i387 state */
-       if (used_math() && save_i387_xstate(*fpstate) < 0)
+       /* save i387 and extended state */
+       if (used_math() &&
+           save_xstate_sig(*fpstate, (void __user *)buf_fx, math_size) < 0)
                return (void __user *)-1L;
  
        return (void __user *)sp;
@@@ -474,6 -472,74 +472,74 @@@ static int __setup_rt_frame(int sig, st
  }
  #endif /* CONFIG_X86_32 */
  
+ 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);
+               err |= setup_sigcontext(&frame->uc.uc_mcontext, fpstate,
+                                       regs, set->sig[0]);
+               err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
+               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);
+       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.
@@@ -612,55 -678,22 +678,22 @@@ static int signr_convert(int sig
        return sig;
  }
  
- #ifdef CONFIG_X86_32
- #define is_ia32       1
- #define ia32_setup_frame      __setup_frame
- #define ia32_setup_rt_frame   __setup_rt_frame
- #else /* !CONFIG_X86_32 */
- #ifdef CONFIG_IA32_EMULATION
- #define is_ia32       test_thread_flag(TIF_IA32)
- #else /* !CONFIG_IA32_EMULATION */
- #define is_ia32       0
- #endif /* CONFIG_IA32_EMULATION */
- #ifdef CONFIG_X86_X32_ABI
- #define is_x32        test_thread_flag(TIF_X32)
- static int x32_setup_rt_frame(int sig, struct k_sigaction *ka,
-                             siginfo_t *info, compat_sigset_t *set,
-                             struct pt_regs *regs);
- #else /* !CONFIG_X86_X32_ABI */
- #define is_x32        0
- #endif /* CONFIG_X86_X32_ABI */
- int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
-               sigset_t *set, struct pt_regs *regs);
- int ia32_setup_frame(int sig, struct k_sigaction *ka,
-               sigset_t *set, struct pt_regs *regs);
- #endif /* CONFIG_X86_32 */
  static int
  setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
                struct pt_regs *regs)
  {
        int usig = signr_convert(sig);
        sigset_t *set = sigmask_to_save();
+       compat_sigset_t *cset = (compat_sigset_t *) set;
  
        /* Set up the stack frame */
-       if (is_ia32) {
+       if (is_ia32_frame()) {
                if (ka->sa.sa_flags & SA_SIGINFO)
-                       return ia32_setup_rt_frame(usig, ka, info, set, regs);
+                       return ia32_setup_rt_frame(usig, ka, info, cset, regs);
                else
-                       return ia32_setup_frame(usig, ka, set, regs);
- #ifdef CONFIG_X86_X32_ABI
-       } else if (is_x32) {
-               return x32_setup_rt_frame(usig, ka, info,
-                                        (compat_sigset_t *)set, regs);
- #endif
+                       return ia32_setup_frame(usig, ka, cset, regs);
+       } else if (is_x32_frame()) {
+               return x32_setup_rt_frame(usig, ka, info, cset, regs);
        } else {
                return __setup_rt_frame(sig, ka, info, set, regs);
        }
@@@ -779,8 -812,6 +812,8 @@@ static void do_signal(struct pt_regs *r
  void
  do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags)
  {
 +      rcu_user_exit();
 +
  #ifdef CONFIG_X86_MCE
        /* notify userspace of pending MCEs */
        if (thread_info_flags & _TIF_MCE_NOTIFY)
  #ifdef CONFIG_X86_32
        clear_thread_flag(TIF_IRET);
  #endif /* CONFIG_X86_32 */
 +
 +      rcu_user_enter();
  }
  
  void signal_fault(struct pt_regs *regs, void __user *frame, char *where)
  }
  
  #ifdef CONFIG_X86_X32_ABI
- static int x32_setup_rt_frame(int sig, struct k_sigaction *ka,
-                             siginfo_t *info, compat_sigset_t *set,
-                             struct pt_regs *regs)
- {
-       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);
-               err |= setup_sigcontext(&frame->uc.uc_mcontext, fpstate,
-                                       regs, set->sig[0]);
-               err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
-               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);
-       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;
-       return 0;
- }
  asmlinkage long sys32_x32_rt_sigreturn(struct pt_regs *regs)
  {
        struct rt_sigframe_x32 __user *frame;
diff --combined arch/x86/kernel/traps.c
index cfbe3fc415866c6fe7c257d210bf27391576ffa6,4f4aba0551b0833e0b0155205b4f576f94a6a488..8276dc6794cceec9ffa6a9183eb5707ece9bceeb
@@@ -55,7 -55,6 +55,7 @@@
  #include <asm/i387.h>
  #include <asm/fpu-internal.h>
  #include <asm/mce.h>
 +#include <asm/rcu.h>
  
  #include <asm/mach_traps.h>
  
@@@ -108,45 -107,30 +108,45 @@@ static inline void preempt_conditional_
        dec_preempt_count();
  }
  
 -static void __kprobes
 -do_trap(int trapnr, int signr, char *str, struct pt_regs *regs,
 -      long error_code, siginfo_t *info)
 +static int __kprobes
 +do_trap_no_signal(struct task_struct *tsk, int trapnr, char *str,
 +                struct pt_regs *regs, long error_code)
  {
 -      struct task_struct *tsk = current;
 -
  #ifdef CONFIG_X86_32
        if (regs->flags & X86_VM_MASK) {
                /*
 -               * traps 0, 1, 3, 4, and 5 should be forwarded to vm86.
 +               * Traps 0, 1, 3, 4, and 5 should be forwarded to vm86.
                 * On nmi (interrupt 2), do_trap should not be called.
                 */
 -              if (trapnr < X86_TRAP_UD)
 -                      goto vm86_trap;
 -              goto trap_signal;
 +              if (trapnr < X86_TRAP_UD) {
 +                      if (!handle_vm86_trap((struct kernel_vm86_regs *) regs,
 +                                              error_code, trapnr))
 +                              return 0;
 +              }
 +              return -1;
        }
  #endif
 +      if (!user_mode(regs)) {
 +              if (!fixup_exception(regs)) {
 +                      tsk->thread.error_code = error_code;
 +                      tsk->thread.trap_nr = trapnr;
 +                      die(str, regs, error_code);
 +              }
 +              return 0;
 +      }
  
 -      if (!user_mode(regs))
 -              goto kernel_trap;
 +      return -1;
 +}
  
 -#ifdef CONFIG_X86_32
 -trap_signal:
 -#endif
 +static void __kprobes
 +do_trap(int trapnr, int signr, char *str, struct pt_regs *regs,
 +      long error_code, siginfo_t *info)
 +{
 +      struct task_struct *tsk = current;
 +
 +
 +      if (!do_trap_no_signal(tsk, trapnr, str, regs, error_code))
 +              return;
        /*
         * We want error_code and trap_nr set for userspace faults and
         * kernelspace faults which result in die(), but not
                force_sig_info(signr, info, tsk);
        else
                force_sig(signr, tsk);
 -      return;
 -
 -kernel_trap:
 -      if (!fixup_exception(regs)) {
 -              tsk->thread.error_code = error_code;
 -              tsk->thread.trap_nr = trapnr;
 -              die(str, regs, error_code);
 -      }
 -      return;
 -
 -#ifdef CONFIG_X86_32
 -vm86_trap:
 -      if (handle_vm86_trap((struct kernel_vm86_regs *) regs,
 -                                              error_code, trapnr))
 -              goto trap_signal;
 -      return;
 -#endif
  }
  
  #define DO_ERROR(trapnr, signr, str, name)                            \
  dotraplinkage void do_##name(struct pt_regs *regs, long error_code)   \
  {                                                                     \
 -      if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr)  \
 -                                                      == NOTIFY_STOP) \
 +      exception_enter(regs);                                          \
 +      if (notify_die(DIE_TRAP, str, regs, error_code,                 \
 +                      trapnr, signr) == NOTIFY_STOP) {                \
 +              exception_exit(regs);                                   \
                return;                                                 \
 +      }                                                               \
        conditional_sti(regs);                                          \
        do_trap(trapnr, signr, str, regs, error_code, NULL);            \
 +      exception_exit(regs);                                           \
  }
  
  #define DO_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr)               \
@@@ -198,15 -195,11 +198,15 @@@ dotraplinkage void do_##name(struct pt_
        info.si_errno = 0;                                              \
        info.si_code = sicode;                                          \
        info.si_addr = (void __user *)siaddr;                           \
 -      if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr)  \
 -                                                      == NOTIFY_STOP) \
 +      exception_enter(regs);                                          \
 +      if (notify_die(DIE_TRAP, str, regs, error_code,                 \
 +                      trapnr, signr) == NOTIFY_STOP) {                \
 +              exception_exit(regs);                                   \
                return;                                                 \
 +      }                                                               \
        conditional_sti(regs);                                          \
        do_trap(trapnr, signr, str, regs, error_code, &info);           \
 +      exception_exit(regs);                                           \
  }
  
  DO_ERROR_INFO(X86_TRAP_DE, SIGFPE, "divide error", divide_error, FPE_INTDIV,
@@@ -229,14 -222,12 +229,14 @@@ DO_ERROR_INFO(X86_TRAP_AC, SIGBUS, "ali
  /* Runs on IST stack */
  dotraplinkage void do_stack_segment(struct pt_regs *regs, long error_code)
  {
 +      exception_enter(regs);
        if (notify_die(DIE_TRAP, "stack segment", regs, error_code,
 -                      X86_TRAP_SS, SIGBUS) == NOTIFY_STOP)
 -              return;
 -      preempt_conditional_sti(regs);
 -      do_trap(X86_TRAP_SS, SIGBUS, "stack segment", regs, error_code, NULL);
 -      preempt_conditional_cli(regs);
 +                     X86_TRAP_SS, SIGBUS) != NOTIFY_STOP) {
 +              preempt_conditional_sti(regs);
 +              do_trap(X86_TRAP_SS, SIGBUS, "stack segment", regs, error_code, NULL);
 +              preempt_conditional_cli(regs);
 +      }
 +      exception_exit(regs);
  }
  
  dotraplinkage void do_double_fault(struct pt_regs *regs, long error_code)
        static const char str[] = "double fault";
        struct task_struct *tsk = current;
  
 +      exception_enter(regs);
        /* Return not checked because double check cannot be ignored */
        notify_die(DIE_TRAP, str, regs, error_code, X86_TRAP_DF, SIGSEGV);
  
@@@ -265,29 -255,16 +265,29 @@@ do_general_protection(struct pt_regs *r
  {
        struct task_struct *tsk;
  
 +      exception_enter(regs);
        conditional_sti(regs);
  
  #ifdef CONFIG_X86_32
 -      if (regs->flags & X86_VM_MASK)
 -              goto gp_in_vm86;
 +      if (regs->flags & X86_VM_MASK) {
 +              local_irq_enable();
 +              handle_vm86_fault((struct kernel_vm86_regs *) regs, error_code);
 +              goto exit;
 +      }
  #endif
  
        tsk = current;
 -      if (!user_mode(regs))
 -              goto gp_in_kernel;
 +      if (!user_mode(regs)) {
 +              if (fixup_exception(regs))
 +                      goto exit;
 +
 +              tsk->thread.error_code = error_code;
 +              tsk->thread.trap_nr = X86_TRAP_GP;
 +              if (notify_die(DIE_GPF, "general protection fault", regs, error_code,
 +                             X86_TRAP_GP, SIGSEGV) != NOTIFY_STOP)
 +                      die("general protection fault", regs, error_code);
 +              goto exit;
 +      }
  
        tsk->thread.error_code = error_code;
        tsk->thread.trap_nr = X86_TRAP_GP;
        }
  
        force_sig(SIGSEGV, tsk);
 -      return;
 -
 -#ifdef CONFIG_X86_32
 -gp_in_vm86:
 -      local_irq_enable();
 -      handle_vm86_fault((struct kernel_vm86_regs *) regs, error_code);
 -      return;
 -#endif
 -
 -gp_in_kernel:
 -      if (fixup_exception(regs))
 -              return;
 -
 -      tsk->thread.error_code = error_code;
 -      tsk->thread.trap_nr = X86_TRAP_GP;
 -      if (notify_die(DIE_GPF, "general protection fault", regs, error_code,
 -                      X86_TRAP_GP, SIGSEGV) == NOTIFY_STOP)
 -              return;
 -      die("general protection fault", regs, error_code);
 +exit:
 +      exception_exit(regs);
  }
  
  /* May run on IST stack. */
@@@ -318,16 -312,15 +318,16 @@@ dotraplinkage void __kprobes notrace do
            ftrace_int3_handler(regs))
                return;
  #endif
 +      exception_enter(regs);
  #ifdef CONFIG_KGDB_LOW_LEVEL_TRAP
        if (kgdb_ll_trap(DIE_INT3, "int3", regs, error_code, X86_TRAP_BP,
                                SIGTRAP) == NOTIFY_STOP)
 -              return;
 +              goto exit;
  #endif /* CONFIG_KGDB_LOW_LEVEL_TRAP */
  
        if (notify_die(DIE_INT3, "int3", regs, error_code, X86_TRAP_BP,
                        SIGTRAP) == NOTIFY_STOP)
 -              return;
 +              goto exit;
  
        /*
         * Let others (NMI) know that the debug stack is in use
        do_trap(X86_TRAP_BP, SIGTRAP, "int3", regs, error_code, NULL);
        preempt_conditional_cli(regs);
        debug_stack_usage_dec();
 +exit:
 +      exception_exit(regs);
  }
  
  #ifdef CONFIG_X86_64
@@@ -400,8 -391,6 +400,8 @@@ dotraplinkage void __kprobes do_debug(s
        unsigned long dr6;
        int si_code;
  
 +      exception_enter(regs);
 +
        get_debugreg(dr6, 6);
  
        /* Filter out all the reserved bits which are preset to 1 */
  
        /* Catch kmemcheck conditions first of all! */
        if ((dr6 & DR_STEP) && kmemcheck_trap(regs))
 -              return;
 +              goto exit;
  
        /* DR6 may or may not be cleared by the CPU */
        set_debugreg(0, 6);
  
        if (notify_die(DIE_DEBUG, "debug", regs, PTR_ERR(&dr6), error_code,
                                                        SIGTRAP) == NOTIFY_STOP)
 -              return;
 +              goto exit;
  
        /*
         * Let others (NMI) know that the debug stack is in use
                                        X86_TRAP_DB);
                preempt_conditional_cli(regs);
                debug_stack_usage_dec();
 -              return;
 +              goto exit;
        }
  
        /*
        preempt_conditional_cli(regs);
        debug_stack_usage_dec();
  
 -      return;
 +exit:
 +      exception_exit(regs);
  }
  
  /*
@@@ -567,17 -555,14 +567,17 @@@ dotraplinkage void do_coprocessor_error
  #ifdef CONFIG_X86_32
        ignore_fpu_irq = 1;
  #endif
 -
 +      exception_enter(regs);
        math_error(regs, error_code, X86_TRAP_MF);
 +      exception_exit(regs);
  }
  
  dotraplinkage void
  do_simd_coprocessor_error(struct pt_regs *regs, long error_code)
  {
 +      exception_enter(regs);
        math_error(regs, error_code, X86_TRAP_XF);
 +      exception_exit(regs);
  }
  
  dotraplinkage void
@@@ -628,11 -613,12 +628,12 @@@ void math_state_restore(void
        }
  
        __thread_fpu_begin(tsk);
        /*
         * Paranoid restore. send a SIGSEGV if we fail to restore the state.
         */
        if (unlikely(restore_fpu_checking(tsk))) {
-               __thread_fpu_end(tsk);
+               drop_init_fpu(tsk);
                force_sig(SIGSEGV, tsk);
                return;
        }
@@@ -644,7 -630,8 +645,9 @@@ EXPORT_SYMBOL_GPL(math_state_restore)
  dotraplinkage void __kprobes
  do_device_not_available(struct pt_regs *regs, long error_code)
  {
 +      exception_enter(regs);
+       BUG_ON(use_eager_fpu());
  #ifdef CONFIG_MATH_EMULATION
        if (read_cr0() & X86_CR0_EM) {
                struct math_emu_info info = { };
  
                info.regs = regs;
                math_emulate(&info);
 +              exception_exit(regs);
                return;
        }
  #endif
  #ifdef CONFIG_X86_32
        conditional_sti(regs);
  #endif
 +      exception_exit(regs);
  }
  
  #ifdef CONFIG_X86_32
  dotraplinkage void do_iret_error(struct pt_regs *regs, long error_code)
  {
        siginfo_t info;
 +
 +      exception_enter(regs);
        local_irq_enable();
  
        info.si_signo = SIGILL;
        info.si_code = ILL_BADSTK;
        info.si_addr = NULL;
        if (notify_die(DIE_TRAP, "iret exception", regs, error_code,
 -                      X86_TRAP_IRET, SIGILL) == NOTIFY_STOP)
 -              return;
 -      do_trap(X86_TRAP_IRET, SIGILL, "iret exception", regs, error_code,
 -              &info);
 +                      X86_TRAP_IRET, SIGILL) != NOTIFY_STOP) {
 +              do_trap(X86_TRAP_IRET, SIGILL, "iret exception", regs, error_code,
 +                      &info);
 +      }
 +      exception_exit(regs);
  }
  #endif
  
diff --combined arch/x86/kvm/vmx.c
index b06737d122f4904020957fdc051a4ebde95db937,70dfcec3c46321229addc7021b9255f1a8c8edaa..851aa7c3b890f511fc350f2275a33801f58e8350
@@@ -1493,8 -1493,12 +1493,12 @@@ static void __vmx_load_host_state(struc
  #ifdef CONFIG_X86_64
        wrmsrl(MSR_KERNEL_GS_BASE, vmx->msr_host_kernel_gs_base);
  #endif
-       if (user_has_fpu())
-               clts();
+       /*
+        * If the FPU is not active (through the host task or
+        * the guest vcpu), then restore the cr0.TS bit.
+        */
+       if (!user_has_fpu() && !vmx->vcpu.guest_fpu_loaded)
+               stts();
        load_gdt(&__get_cpu_var(host_gdt));
  }
  
@@@ -3619,7 -3623,6 +3623,7 @@@ static void seg_setup(int seg
  
  static int alloc_apic_access_page(struct kvm *kvm)
  {
 +      struct page *page;
        struct kvm_userspace_memory_region kvm_userspace_mem;
        int r = 0;
  
        if (r)
                goto out;
  
 -      kvm->arch.apic_access_page = gfn_to_page(kvm, 0xfee00);
 +      page = gfn_to_page(kvm, 0xfee00);
 +      if (is_error_page(page)) {
 +              r = -EFAULT;
 +              goto out;
 +      }
 +
 +      kvm->arch.apic_access_page = page;
  out:
        mutex_unlock(&kvm->slots_lock);
        return r;
  
  static int alloc_identity_pagetable(struct kvm *kvm)
  {
 +      struct page *page;
        struct kvm_userspace_memory_region kvm_userspace_mem;
        int r = 0;
  
        if (r)
                goto out;
  
 -      kvm->arch.ept_identity_pagetable = gfn_to_page(kvm,
 -                      kvm->arch.ept_identity_map_addr >> PAGE_SHIFT);
 +      page = gfn_to_page(kvm, kvm->arch.ept_identity_map_addr >> PAGE_SHIFT);
 +      if (is_error_page(page)) {
 +              r = -EFAULT;
 +              goto out;
 +      }
 +
 +      kvm->arch.ept_identity_pagetable = page;
  out:
        mutex_unlock(&kvm->slots_lock);
        return r;
@@@ -3743,7 -3734,7 +3747,7 @@@ static void vmx_set_constant_host_state
        unsigned long tmpl;
        struct desc_ptr dt;
  
-       vmcs_writel(HOST_CR0, read_cr0() X86_CR0_TS);  /* 22.2.3 */
+       vmcs_writel(HOST_CR0, read_cr0() & ~X86_CR0_TS);  /* 22.2.3 */
        vmcs_writel(HOST_CR4, read_cr4());  /* 22.2.3, 22.2.5 */
        vmcs_writel(HOST_CR3, read_cr3());  /* 22.2.3  FIXME: shadow tables */
  
@@@ -4543,7 -4534,7 +4547,7 @@@ static int handle_cr(struct kvm_vcpu *v
                                vcpu->run->exit_reason = KVM_EXIT_SET_TPR;
                                return 0;
                        }
 -              };
 +              }
                break;
        case 2: /* clts */
                handle_clts(vcpu);
@@@ -6588,7 -6579,7 +6592,7 @@@ static void vmx_cpuid_update(struct kvm
        /* Exposing INVPCID only when PCID is exposed */
        best = kvm_find_cpuid_entry(vcpu, 0x7, 0);
        if (vmx_invpcid_supported() &&
 -          best && (best->ecx & bit(X86_FEATURE_INVPCID)) &&
 +          best && (best->ebx & bit(X86_FEATURE_INVPCID)) &&
            guest_cpuid_has_pcid(vcpu)) {
                exec_control |= SECONDARY_EXEC_ENABLE_INVPCID;
                vmcs_write32(SECONDARY_VM_EXEC_CONTROL,
                vmcs_write32(SECONDARY_VM_EXEC_CONTROL,
                             exec_control);
                if (best)
 -                      best->ecx &= ~bit(X86_FEATURE_INVPCID);
 +                      best->ebx &= ~bit(X86_FEATURE_INVPCID);
        }
  }
  
diff --combined arch/x86/kvm/x86.c
index 2966c847d489d84f1f2b3cb8450daf4bcce1d568,02b2cd520693563e62659e1983618785433a47a2..1f09552572fa15709b51022fdbaa8044b3fdb73d
@@@ -5113,20 -5113,17 +5113,20 @@@ static void post_kvm_run_save(struct kv
                        !kvm_event_needs_reinjection(vcpu);
  }
  
 -static void vapic_enter(struct kvm_vcpu *vcpu)
 +static int vapic_enter(struct kvm_vcpu *vcpu)
  {
        struct kvm_lapic *apic = vcpu->arch.apic;
        struct page *page;
  
        if (!apic || !apic->vapic_addr)
 -              return;
 +              return 0;
  
        page = gfn_to_page(vcpu->kvm, apic->vapic_addr >> PAGE_SHIFT);
 +      if (is_error_page(page))
 +              return -EFAULT;
  
        vcpu->arch.apic->vapic_page = page;
 +      return 0;
  }
  
  static void vapic_exit(struct kvm_vcpu *vcpu)
@@@ -5433,11 -5430,7 +5433,11 @@@ static int __vcpu_run(struct kvm_vcpu *
        }
  
        vcpu->srcu_idx = srcu_read_lock(&kvm->srcu);
 -      vapic_enter(vcpu);
 +      r = vapic_enter(vcpu);
 +      if (r) {
 +              srcu_read_unlock(&kvm->srcu, vcpu->srcu_idx);
 +              return r;
 +      }
  
        r = 1;
        while (r > 0) {
@@@ -5979,7 -5972,7 +5979,7 @@@ void kvm_load_guest_fpu(struct kvm_vcp
         */
        kvm_put_guest_xcr0(vcpu);
        vcpu->guest_fpu_loaded = 1;
-       unlazy_fpu(current);
+       __kernel_fpu_begin();
        fpu_restore_checking(&vcpu->arch.guest_fpu);
        trace_kvm_fpu(1);
  }
@@@ -5993,6 -5986,7 +5993,7 @@@ void kvm_put_guest_fpu(struct kvm_vcpu 
  
        vcpu->guest_fpu_loaded = 0;
        fpu_save_init(&vcpu->arch.guest_fpu);
+       __kernel_fpu_end();
        ++vcpu->stat.fpu_reload;
        kvm_make_request(KVM_REQ_DEACTIVATE_FPU, vcpu);
        trace_kvm_fpu(0);