]> Git Repo - J-linux.git/commitdiff
Merge branch 'x86-fpu-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorLinus Torvalds <[email protected]>
Tue, 7 May 2019 17:24:10 +0000 (10:24 -0700)
committerLinus Torvalds <[email protected]>
Tue, 7 May 2019 17:24:10 +0000 (10:24 -0700)
Pull x86 FPU state handling updates from Borislav Petkov:
 "This contains work started by Rik van Riel and brought to fruition by
  Sebastian Andrzej Siewior with the main goal to optimize when to load
  FPU registers: only when returning to userspace and not on every
  context switch (while the task remains in the kernel).

  In addition, this optimization makes kernel_fpu_begin() cheaper by
  requiring registers saving only on the first invocation and skipping
  that in following ones.

  What is more, this series cleans up and streamlines many aspects of
  the already complex FPU code, hopefully making it more palatable for
  future improvements and simplifications.

  Finally, there's a __user annotations fix from Jann Horn"

* 'x86-fpu-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (29 commits)
  x86/fpu: Fault-in user stack if copy_fpstate_to_sigframe() fails
  x86/pkeys: Add PKRU value to init_fpstate
  x86/fpu: Restore regs in copy_fpstate_to_sigframe() in order to use the fastpath
  x86/fpu: Add a fastpath to copy_fpstate_to_sigframe()
  x86/fpu: Add a fastpath to __fpu__restore_sig()
  x86/fpu: Defer FPU state load until return to userspace
  x86/fpu: Merge the two code paths in __fpu__restore_sig()
  x86/fpu: Restore from kernel memory on the 64-bit path too
  x86/fpu: Inline copy_user_to_fpregs_zeroing()
  x86/fpu: Update xstate's PKRU value on write_pkru()
  x86/fpu: Prepare copy_fpstate_to_sigframe() for TIF_NEED_FPU_LOAD
  x86/fpu: Always store the registers in copy_fpstate_to_sigframe()
  x86/entry: Add TIF_NEED_FPU_LOAD
  x86/fpu: Eager switch PKRU state
  x86/pkeys: Don't check if PKRU is zero before writing it
  x86/fpu: Only write PKRU if it is different from current
  x86/pkeys: Provide *pkru() helpers
  x86/fpu: Use a feature number instead of mask in two more helpers
  x86/fpu: Make __raw_xsave_addr() use a feature number instead of mask
  x86/fpu: Add an __fpregs_load_activate() internal helper
  ...

1  2 
arch/x86/ia32/ia32_signal.c
arch/x86/include/asm/fpu/internal.h
arch/x86/include/asm/pgtable.h
arch/x86/kernel/cpu/common.c
arch/x86/kernel/process.c
arch/x86/kernel/process_32.c
arch/x86/kernel/process_64.c
arch/x86/kernel/signal.c
arch/x86/kvm/vmx/vmx.c
arch/x86/kvm/x86.c

index 4d5fcd47ab75a4e2815f2ed381b9356b3c18e7d1,6eeb3249f22fff9fdbcf4d161ccb62816d90f0c5..629d1ee05599f75083d9e22a69ff9237e6421da8
@@@ -61,8 -61,9 +61,8 @@@
  } while (0)
  
  #define RELOAD_SEG(seg)               {               \
 -      unsigned int pre = GET_SEG(seg);        \
 +      unsigned int pre = (seg) | 3;           \
        unsigned int cur = get_user_seg(seg);   \
 -      pre |= 3;                               \
        if (pre != cur)                         \
                set_user_seg(seg, pre);         \
  }
@@@ -71,7 -72,6 +71,7 @@@ static int ia32_restore_sigcontext(stru
                                   struct sigcontext_32 __user *sc)
  {
        unsigned int tmpflags, err = 0;
 +      u16 gs, fs, es, ds;
        void __user *buf;
        u32 tmp;
  
        current->restart_block.fn = do_no_restart_syscall;
  
        get_user_try {
 -              /*
 -               * Reload fs and gs if they have changed in the signal
 -               * handler.  This does not handle long fs/gs base changes in
 -               * the handler, but does not clobber them at least in the
 -               * normal case.
 -               */
 -              RELOAD_SEG(gs);
 -              RELOAD_SEG(fs);
 -              RELOAD_SEG(ds);
 -              RELOAD_SEG(es);
 +              gs = GET_SEG(gs);
 +              fs = GET_SEG(fs);
 +              ds = GET_SEG(ds);
 +              es = GET_SEG(es);
  
                COPY(di); COPY(si); COPY(bp); COPY(sp); COPY(bx);
                COPY(dx); COPY(cx); COPY(ip); COPY(ax);
                buf = compat_ptr(tmp);
        } get_user_catch(err);
  
 +      /*
 +       * Reload fs and gs if they have changed in the signal
 +       * handler.  This does not handle long fs/gs base changes in
 +       * the handler, but does not clobber them at least in the
 +       * normal case.
 +       */
 +      RELOAD_SEG(gs);
 +      RELOAD_SEG(fs);
 +      RELOAD_SEG(ds);
 +      RELOAD_SEG(es);
 +
        err |= fpu__restore_sig(buf, 1);
  
        force_iret();
@@@ -221,8 -216,7 +221,7 @@@ static void __user *get_sigframe(struc
                                 size_t frame_size,
                                 void __user **fpstate)
  {
-       struct fpu *fpu = &current->thread.fpu;
-       unsigned long sp;
+       unsigned long sp, fx_aligned, math_size;
  
        /* Default to using normal stack */
        sp = regs->sp;
                 ksig->ka.sa.sa_restorer)
                sp = (unsigned long) ksig->ka.sa.sa_restorer;
  
-       if (fpu->initialized) {
-               unsigned long fx_aligned, math_size;
-               sp = fpu__alloc_mathframe(sp, 1, &fx_aligned, &math_size);
-               *fpstate = (struct _fpstate_32 __user *) sp;
-               if (copy_fpstate_to_sigframe(*fpstate, (void __user *)fx_aligned,
-                                   math_size) < 0)
-                       return (void __user *) -1L;
-       }
+       sp = fpu__alloc_mathframe(sp, 1, &fx_aligned, &math_size);
+       *fpstate = (struct _fpstate_32 __user *) sp;
+       if (copy_fpstate_to_sigframe(*fpstate, (void __user *)fx_aligned,
+                                    math_size) < 0)
+               return (void __user *) -1L;
  
        sp -= frame_size;
        /* Align the stack pointer according to the i386 ABI,
index 745a19d34f23f245d17fc50e13786d4a6ca6d34a,0c8a5093647a75236ede1a6acfa246408f7d21f2..9e27fa05a7ae6fca6503fd2eb15928db93355c8d
@@@ -14,6 -14,7 +14,7 @@@
  #include <linux/compat.h>
  #include <linux/sched.h>
  #include <linux/slab.h>
+ #include <linux/mm.h>
  
  #include <asm/user.h>
  #include <asm/fpu/api.h>
  /*
   * High level FPU state handling functions:
   */
- extern void fpu__initialize(struct fpu *fpu);
  extern void fpu__prepare_read(struct fpu *fpu);
  extern void fpu__prepare_write(struct fpu *fpu);
  extern void fpu__save(struct fpu *fpu);
- extern void fpu__restore(struct fpu *fpu);
  extern int  fpu__restore_sig(void __user *buf, int ia32_frame);
  extern void fpu__drop(struct fpu *fpu);
- extern int  fpu__copy(struct fpu *dst_fpu, struct fpu *src_fpu);
+ extern int  fpu__copy(struct task_struct *dst, struct task_struct *src);
  extern void fpu__clear(struct fpu *fpu);
  extern int  fpu__exception_code(struct fpu *fpu, int trap_nr);
  extern int  dump_fpu(struct pt_regs *ptregs, struct user_i387_struct *fpstate);
@@@ -122,6 -121,21 +121,21 @@@ extern void fpstate_sanitize_xstate(str
        err;                                                            \
  })
  
+ #define kernel_insn_err(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;                                                            \
+ })
  #define kernel_insn(insn, output, input...)                           \
        asm volatile("1:" #insn "\n\t"                                  \
                     "2:\n"                                             \
@@@ -150,6 -164,14 +164,14 @@@ static inline void copy_kernel_to_fxreg
                kernel_insn(fxrstorq %[fx], "=m" (*fx), [fx] "m" (*fx));
  }
  
+ static inline int copy_kernel_to_fxregs_err(struct fxregs_state *fx)
+ {
+       if (IS_ENABLED(CONFIG_X86_32))
+               return kernel_insn_err(fxrstor %[fx], "=m" (*fx), [fx] "m" (*fx));
+       else
+               return kernel_insn_err(fxrstorq %[fx], "=m" (*fx), [fx] "m" (*fx));
+ }
  static inline int copy_user_to_fxregs(struct fxregs_state __user *fx)
  {
        if (IS_ENABLED(CONFIG_X86_32))
@@@ -163,6 -185,11 +185,11 @@@ static inline void copy_kernel_to_fregs
        kernel_insn(frstor %[fx], "=m" (*fx), [fx] "m" (*fx));
  }
  
+ static inline int copy_kernel_to_fregs_err(struct fregs_state *fx)
+ {
+       return kernel_insn_err(frstor %[fx], "=m" (*fx), [fx] "m" (*fx));
+ }
  static inline int copy_user_to_fregs(struct fregs_state __user *fx)
  {
        return user_insn(frstor %[fx], "=m" (*fx), [fx] "m" (*fx));
@@@ -253,7 -280,7 +280,7 @@@ static inline void copy_xregs_to_kernel
  
        WARN_ON(system_state != SYSTEM_BOOTING);
  
 -      if (static_cpu_has(X86_FEATURE_XSAVES))
 +      if (boot_cpu_has(X86_FEATURE_XSAVES))
                XSTATE_OP(XSAVES, xstate, lmask, hmask, err);
        else
                XSTATE_OP(XSAVE, xstate, lmask, hmask, err);
@@@ -275,7 -302,7 +302,7 @@@ static inline void copy_kernel_to_xregs
  
        WARN_ON(system_state != SYSTEM_BOOTING);
  
 -      if (static_cpu_has(X86_FEATURE_XSAVES))
 +      if (boot_cpu_has(X86_FEATURE_XSAVES))
                XSTATE_OP(XRSTORS, xstate, lmask, hmask, err);
        else
                XSTATE_OP(XRSTOR, xstate, lmask, hmask, err);
@@@ -362,6 -389,21 +389,21 @@@ static inline int copy_user_to_xregs(st
        return err;
  }
  
+ /*
+  * Restore xstate from kernel space xsave area, return an error code instead of
+  * an exception.
+  */
+ static inline int copy_kernel_to_xregs_err(struct xregs_state *xstate, u64 mask)
+ {
+       u32 lmask = mask;
+       u32 hmask = mask >> 32;
+       int err;
+       XSTATE_OP(XRSTOR, xstate, lmask, hmask, err);
+       return err;
+ }
  /*
   * These must be called with preempt disabled. Returns
   * 'true' if the FPU state is still intact and we can
@@@ -486,6 -528,25 +528,25 @@@ static inline void fpregs_activate(stru
        trace_x86_fpu_regs_activated(fpu);
  }
  
+ /*
+  * Internal helper, do not use directly. Use switch_fpu_return() instead.
+  */
+ static inline void __fpregs_load_activate(void)
+ {
+       struct fpu *fpu = &current->thread.fpu;
+       int cpu = smp_processor_id();
+       if (WARN_ON_ONCE(current->mm == NULL))
+               return;
+       if (!fpregs_state_valid(fpu, cpu)) {
+               copy_kernel_to_fpregs(&fpu->state);
+               fpregs_activate(fpu);
+               fpu->last_cpu = cpu;
+       }
+       clear_thread_flag(TIF_NEED_FPU_LOAD);
+ }
  /*
   * FPU state switching for scheduling.
   *
   *  - switch_fpu_prepare() saves the old state.
   *    This is done within the context of the old process.
   *
-  *  - switch_fpu_finish() restores the new state as
-  *    necessary.
+  *  - switch_fpu_finish() sets TIF_NEED_FPU_LOAD; the floating point state
+  *    will get loaded on return to userspace, or when the kernel needs it.
+  *
+  * If TIF_NEED_FPU_LOAD is cleared then the CPU's FPU registers
+  * are saved in the current thread's FPU register state.
+  *
+  * If TIF_NEED_FPU_LOAD is set then CPU's FPU registers may not
+  * hold current()'s FPU registers. It is required to load the
+  * registers before returning to userland or using the content
+  * otherwise.
+  *
+  * The FPU context is only stored/restored for a user task and
+  * ->mm is used to distinguish between kernel and user threads.
   */
 -static inline void
 -switch_fpu_prepare(struct fpu *old_fpu, int cpu)
 +static inline void switch_fpu_prepare(struct fpu *old_fpu, int cpu)
  {
-       if (static_cpu_has(X86_FEATURE_FPU) && old_fpu->initialized) {
+       if (static_cpu_has(X86_FEATURE_FPU) && current->mm) {
                if (!copy_fpregs_to_fpstate(old_fpu))
                        old_fpu->last_cpu = -1;
                else
  
                /* But leave fpu_fpregs_owner_ctx! */
                trace_x86_fpu_regs_deactivated(old_fpu);
-       } else
-               old_fpu->last_cpu = -1;
+       }
  }
  
  /*
   */
  
  /*
-  * Set up the userspace FPU context for the new task, if the task
-  * has used the FPU.
+  * Load PKRU from the FPU context if available. Delay loading of the
+  * complete FPU state until the return to userland.
   */
- static inline void switch_fpu_finish(struct fpu *new_fpu, int cpu)
+ static inline void switch_fpu_finish(struct fpu *new_fpu)
  {
-       bool preload = static_cpu_has(X86_FEATURE_FPU) &&
-                      new_fpu->initialized;
+       u32 pkru_val = init_pkru_value;
+       struct pkru_state *pk;
  
-       if (preload) {
-               if (!fpregs_state_valid(new_fpu, cpu))
-                       copy_kernel_to_fpregs(&new_fpu->state);
-               fpregs_activate(new_fpu);
-       }
- }
+       if (!static_cpu_has(X86_FEATURE_FPU))
+               return;
  
- /*
-  * Needs to be preemption-safe.
-  *
-  * NOTE! user_fpu_begin() must be used only immediately before restoring
-  * the save state. It does not do any saving/restoring on its own. In
-  * lazy FPU mode, it is just an optimization to avoid a #NM exception,
-  * the task can lose the FPU right after preempt_enable().
-  */
- static inline void user_fpu_begin(void)
- {
-       struct fpu *fpu = &current->thread.fpu;
+       set_thread_flag(TIF_NEED_FPU_LOAD);
+       if (!cpu_feature_enabled(X86_FEATURE_OSPKE))
+               return;
  
-       preempt_disable();
-       fpregs_activate(fpu);
-       preempt_enable();
+       /*
+        * PKRU state is switched eagerly because it needs to be valid before we
+        * return to userland e.g. for a copy_to_user() operation.
+        */
+       if (current->mm) {
+               pk = get_xsave_addr(&new_fpu->state.xsave, XFEATURE_PKRU);
+               if (pk)
+                       pkru_val = pk->pkru;
+       }
+       __write_pkru(pkru_val);
  }
  
  /*
index 3a221942f80587faa960c90b0992f553f127c4a7,5cfbbb6d458d15bf832503895fc357f9aed735ed..5e0509b4198619d364e3e6ee26fcea63bb354f4f
@@@ -23,6 -23,8 +23,8 @@@
  
  #ifndef __ASSEMBLY__
  #include <asm/x86_init.h>
+ #include <asm/fpu/xstate.h>
+ #include <asm/fpu/api.h>
  
  extern pgd_t early_top_pgt[PTRS_PER_PGD];
  int __init __early_make_pgtable(unsigned long address, pmdval_t pmd);
@@@ -46,7 -48,7 +48,7 @@@ void ptdump_walk_user_pgd_level_checkwx
   */
  extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)]
        __visible;
 -#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
 +#define ZERO_PAGE(vaddr) ((void)(vaddr),virt_to_page(empty_zero_page))
  
  extern spinlock_t pgd_lock;
  extern struct list_head pgd_list;
@@@ -127,14 -129,29 +129,29 @@@ static inline int pte_dirty(pte_t pte
  static inline u32 read_pkru(void)
  {
        if (boot_cpu_has(X86_FEATURE_OSPKE))
-               return __read_pkru();
+               return rdpkru();
        return 0;
  }
  
  static inline void write_pkru(u32 pkru)
  {
-       if (boot_cpu_has(X86_FEATURE_OSPKE))
-               __write_pkru(pkru);
+       struct pkru_state *pk;
+       if (!boot_cpu_has(X86_FEATURE_OSPKE))
+               return;
+       pk = get_xsave_addr(&current->thread.fpu.state.xsave, XFEATURE_PKRU);
+       /*
+        * The PKRU value in xstate needs to be in sync with the value that is
+        * written to the CPU. The FPU restore on return to userland would
+        * otherwise load the previous value again.
+        */
+       fpregs_lock();
+       if (pk)
+               pk->pkru = pkru;
+       __write_pkru(pkru);
+       fpregs_unlock();
  }
  
  static inline int pte_young(pte_t pte)
@@@ -1021,9 -1038,6 +1038,9 @@@ static inline void __meminit init_tramp
        /* Default trampoline pgd value */
        trampoline_pgd_entry = init_top_pgt[pgd_index(__PAGE_OFFSET)];
  }
 +
 +void __init poking_init(void);
 +
  # ifdef CONFIG_RANDOMIZE_MEMORY
  void __meminit init_trampoline(void);
  # else
@@@ -1358,6 -1372,12 +1375,12 @@@ static inline pmd_t pmd_swp_clear_soft_
  #define PKRU_WD_BIT 0x2
  #define PKRU_BITS_PER_PKEY 2
  
+ #ifdef CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS
+ extern u32 init_pkru_value;
+ #else
+ #define init_pkru_value       0
+ #endif
  static inline bool __pkru_allows_read(u32 pkru, u16 pkey)
  {
        int pkru_pkey_bits = pkey * PKRU_BITS_PER_PKEY;
index 37640544e12fd1e874b6c6fa6725a9c25084c7ca,352fa19e631105d6934b7dd9fd2d4a8f27323a14..8739bdfe9bdf8b98980a9eca5e4a8def2b57f613
@@@ -372,6 -372,8 +372,8 @@@ static bool pku_disabled
  
  static __always_inline void setup_pku(struct cpuinfo_x86 *c)
  {
+       struct pkru_state *pk;
        /* check the boot processor, plus compile options for PKU: */
        if (!cpu_feature_enabled(X86_FEATURE_PKU))
                return;
                return;
  
        cr4_set_bits(X86_CR4_PKE);
+       pk = get_xsave_addr(&init_fpstate.xsave, XFEATURE_PKRU);
+       if (pk)
+               pk->pkru = init_pkru_value;
        /*
         * Seting X86_CR4_PKE will cause the X86_FEATURE_OSPKE
         * cpuid bit to be set.  We need to ensure that we
@@@ -507,6 -512,19 +512,6 @@@ void load_percpu_segment(int cpu
  DEFINE_PER_CPU(struct cpu_entry_area *, cpu_entry_area);
  #endif
  
 -#ifdef CONFIG_X86_64
 -/*
 - * Special IST stacks which the CPU switches to when it calls
 - * an IST-marked descriptor entry. Up to 7 stacks (hardware
 - * limit), all of them are 4K, except the debug stack which
 - * is 8K.
 - */
 -static const unsigned int exception_stack_sizes[N_EXCEPTION_STACKS] = {
 -        [0 ... N_EXCEPTION_STACKS - 1]        = EXCEPTION_STKSZ,
 -        [DEBUG_STACK - 1]                     = DEBUG_STKSZ
 -};
 -#endif
 -
  /* Load the original GDT from the per-cpu structure */
  void load_direct_gdt(int cpu)
  {
@@@ -1498,9 -1516,9 +1503,9 @@@ static __init int setup_clearcpuid(cha
  __setup("clearcpuid=", setup_clearcpuid);
  
  #ifdef CONFIG_X86_64
 -DEFINE_PER_CPU_FIRST(union irq_stack_union,
 -                   irq_stack_union) __aligned(PAGE_SIZE) __visible;
 -EXPORT_PER_CPU_SYMBOL_GPL(irq_stack_union);
 +DEFINE_PER_CPU_FIRST(struct fixed_percpu_data,
 +                   fixed_percpu_data) __aligned(PAGE_SIZE) __visible;
 +EXPORT_PER_CPU_SYMBOL_GPL(fixed_percpu_data);
  
  /*
   * The following percpu variables are hot.  Align current_task to
@@@ -1510,7 -1528,9 +1515,7 @@@ DEFINE_PER_CPU(struct task_struct *, cu
        &init_task;
  EXPORT_PER_CPU_SYMBOL(current_task);
  
 -DEFINE_PER_CPU(char *, irq_stack_ptr) =
 -      init_per_cpu_var(irq_stack_union.irq_stack) + IRQ_STACK_SIZE;
 -
 +DEFINE_PER_CPU(struct irq_stack *, hardirq_stack_ptr);
  DEFINE_PER_CPU(unsigned int, irq_count) __visible = -1;
  
  DEFINE_PER_CPU(int, __preempt_count) = INIT_PREEMPT_COUNT;
@@@ -1547,7 -1567,23 +1552,7 @@@ void syscall_init(void
               X86_EFLAGS_IOPL|X86_EFLAGS_AC|X86_EFLAGS_NT);
  }
  
 -/*
 - * Copies of the original ist values from the tss are only accessed during
 - * debugging, no special alignment required.
 - */
 -DEFINE_PER_CPU(struct orig_ist, orig_ist);
 -
 -static DEFINE_PER_CPU(unsigned long, debug_stack_addr);
  DEFINE_PER_CPU(int, debug_stack_usage);
 -
 -int is_debug_stack(unsigned long addr)
 -{
 -      return __this_cpu_read(debug_stack_usage) ||
 -              (addr <= __this_cpu_read(debug_stack_addr) &&
 -               addr > (__this_cpu_read(debug_stack_addr) - DEBUG_STKSZ));
 -}
 -NOKPROBE_SYMBOL(is_debug_stack);
 -
  DEFINE_PER_CPU(u32, debug_idt_ctr);
  
  void debug_stack_set_zero(void)
@@@ -1637,7 -1673,7 +1642,7 @@@ static void setup_getcpu(int cpu
        unsigned long cpudata = vdso_encode_cpunode(cpu, early_cpu_to_node(cpu));
        struct desc_struct d = { };
  
 -      if (static_cpu_has(X86_FEATURE_RDTSCP))
 +      if (boot_cpu_has(X86_FEATURE_RDTSCP))
                write_rdtscp_aux(cpudata);
  
        /* Store CPU and node number in limit. */
   * initialized (naturally) in the bootstrap process, such as the GDT
   * and IDT. We reload them nevertheless, this function acts as a
   * 'CPU state barrier', nothing should get across.
 - * A lot of state is already set up in PDA init for 64 bit
   */
  #ifdef CONFIG_X86_64
  
  void cpu_init(void)
  {
 -      struct orig_ist *oist;
 +      int cpu = raw_smp_processor_id();
        struct task_struct *me;
        struct tss_struct *t;
 -      unsigned long v;
 -      int cpu = raw_smp_processor_id();
        int i;
  
        wait_for_master_cpu(cpu);
                load_ucode_ap();
  
        t = &per_cpu(cpu_tss_rw, cpu);
 -      oist = &per_cpu(orig_ist, cpu);
  
  #ifdef CONFIG_NUMA
        if (this_cpu_read(numa_node) == 0 &&
        /*
         * set up and load the per-CPU TSS
         */
 -      if (!oist->ist[0]) {
 -              char *estacks = get_cpu_entry_area(cpu)->exception_stacks;
 -
 -              for (v = 0; v < N_EXCEPTION_STACKS; v++) {
 -                      estacks += exception_stack_sizes[v];
 -                      oist->ist[v] = t->x86_tss.ist[v] =
 -                                      (unsigned long)estacks;
 -                      if (v == DEBUG_STACK-1)
 -                              per_cpu(debug_stack_addr, cpu) = (unsigned long)estacks;
 -              }
 +      if (!t->x86_tss.ist[0]) {
 +              t->x86_tss.ist[IST_INDEX_DF] = __this_cpu_ist_top_va(DF);
 +              t->x86_tss.ist[IST_INDEX_NMI] = __this_cpu_ist_top_va(NMI);
 +              t->x86_tss.ist[IST_INDEX_DB] = __this_cpu_ist_top_va(DB);
 +              t->x86_tss.ist[IST_INDEX_MCE] = __this_cpu_ist_top_va(MCE);
        }
  
        t->x86_tss.io_bitmap_base = IO_BITMAP_OFFSET;
@@@ -1824,6 -1869,23 +1829,6 @@@ void cpu_init(void
  }
  #endif
  
 -static void bsp_resume(void)
 -{
 -      if (this_cpu->c_bsp_resume)
 -              this_cpu->c_bsp_resume(&boot_cpu_data);
 -}
 -
 -static struct syscore_ops cpu_syscore_ops = {
 -      .resume         = bsp_resume,
 -};
 -
 -static int __init init_cpu_syscore(void)
 -{
 -      register_syscore_ops(&cpu_syscore_ops);
 -      return 0;
 -}
 -core_initcall(init_cpu_syscore);
 -
  /*
   * The microcode loader calls this upon late microcode load to recheck features,
   * only when microcode has been updated. Caller holds microcode_mutex and CPU
index d1d312d012a616ea346ad6e4e917de60bc26bcfd,b9b8e6eb74f279927b1dc9f7eccfae2ede22a0c0..75fea0d48c0efc09e068082f7d65ded2c2fbbcff
@@@ -101,7 -101,7 +101,7 @@@ int arch_dup_task_struct(struct task_st
        dst->thread.vm86 = NULL;
  #endif
  
-       return fpu__copy(&dst->thread.fpu, &src->thread.fpu);
+       return fpu__copy(dst, src);
  }
  
  /*
@@@ -236,7 -236,7 +236,7 @@@ static int get_cpuid_mode(void
  
  static int set_cpuid_mode(struct task_struct *task, unsigned long cpuid_enabled)
  {
 -      if (!static_cpu_has(X86_FEATURE_CPUID_FAULT))
 +      if (!boot_cpu_has(X86_FEATURE_CPUID_FAULT))
                return -ENODEV;
  
        if (cpuid_enabled)
@@@ -426,8 -426,6 +426,8 @@@ static __always_inline void __speculati
        u64 msr = x86_spec_ctrl_base;
        bool updmsr = false;
  
 +      lockdep_assert_irqs_disabled();
 +
        /*
         * If TIF_SSBD is different, select the proper mitigation
         * method. Note that if SSBD mitigation is disabled or permanentely
@@@ -479,12 -477,10 +479,12 @@@ static unsigned long speculation_ctrl_u
  
  void speculation_ctrl_update(unsigned long tif)
  {
 +      unsigned long flags;
 +
        /* Forced update. Make sure all relevant TIF flags are different */
 -      preempt_disable();
 +      local_irq_save(flags);
        __speculation_ctrl_update(~tif, tif);
 -      preempt_enable();
 +      local_irq_restore(flags);
  }
  
  /* Called from seccomp/prctl update */
@@@ -670,7 -666,7 +670,7 @@@ static int prefer_mwait_c1_over_halt(co
        if (c->x86_vendor != X86_VENDOR_INTEL)
                return 0;
  
 -      if (!cpu_has(c, X86_FEATURE_MWAIT) || static_cpu_has_bug(X86_BUG_MONITOR))
 +      if (!cpu_has(c, X86_FEATURE_MWAIT) || boot_cpu_has_bug(X86_BUG_MONITOR))
                return 0;
  
        return 1;
index 70933193878caafa4a6414dd7313aa3b7a840d84,1bc47f3a48854d136809fa7e5ad1a2e2e6e37a9a..2399e910d10901f0fccacad4950e73afc3fa261e
@@@ -127,13 -127,6 +127,13 @@@ int copy_thread_tls(unsigned long clone
        struct task_struct *tsk;
        int err;
  
 +      /*
 +       * For a new task use the RESET flags value since there is no before.
 +       * All the status flags are zero; DF and all the system flags must also
 +       * be 0, specifically IF must be 0 because we context switch to the new
 +       * task with interrupts disabled.
 +       */
 +      frame->flags = X86_EFLAGS_FIXED;
        frame->bp = 0;
        frame->ret_addr = (unsigned long) ret_from_fork;
        p->thread.sp = (unsigned long) fork_frame;
@@@ -241,7 -234,8 +241,8 @@@ __switch_to(struct task_struct *prev_p
  
        /* never put a printk in __switch_to... printk() calls wake_up*() indirectly */
  
-       switch_fpu_prepare(prev_fpu, cpu);
+       if (!test_thread_flag(TIF_NEED_FPU_LOAD))
+               switch_fpu_prepare(prev_fpu, cpu);
  
        /*
         * Save away %gs. No need to save %fs, as it was saved on the
        /*
         * Leave lazy mode, flushing any hypercalls made here.
         * This must be done before restoring TLS segments so
-        * the GDT and LDT are properly updated, and must be
-        * done before fpu__restore(), so the TS bit is up
-        * to date.
+        * the GDT and LDT are properly updated.
         */
        arch_end_context_switch(next_p);
  
        if (prev->gs | next->gs)
                lazy_load_gs(next->gs);
  
-       switch_fpu_finish(next_fpu, cpu);
        this_cpu_write(current_task, next_p);
  
+       switch_fpu_finish(next_fpu);
        /* Load the Intel cache allocation PQR MSR. */
        resctrl_sched_in();
  
index 844a28b29967ded4b78e3e69ffda3a6d6a2097d1,37b2ecef041e697125f463e30855771864d796a8..f8e1af380cdfceebf241f9ca97b5ddd175e16841
@@@ -392,7 -392,6 +392,7 @@@ int copy_thread_tls(unsigned long clone
        childregs = task_pt_regs(p);
        fork_frame = container_of(childregs, struct fork_frame, regs);
        frame = &fork_frame->frame;
 +
        frame->bp = 0;
        frame->ret_addr = (unsigned long) ret_from_fork;
        p->thread.sp = (unsigned long) fork_frame;
@@@ -521,7 -520,8 +521,8 @@@ __switch_to(struct task_struct *prev_p
        WARN_ON_ONCE(IS_ENABLED(CONFIG_DEBUG_ENTRY) &&
                     this_cpu_read(irq_count) != -1);
  
-       switch_fpu_prepare(prev_fpu, cpu);
+       if (!test_thread_flag(TIF_NEED_FPU_LOAD))
+               switch_fpu_prepare(prev_fpu, cpu);
  
        /* We must save %fs and %gs before load_TLS() because
         * %fs and %gs may be cleared by load_TLS().
        /*
         * Leave lazy mode, flushing any hypercalls made here.  This
         * must be done after loading TLS entries in the GDT but before
-        * loading segments that might reference them, and and it must
-        * be done before fpu__restore(), so the TS bit is up to
-        * date.
+        * loading segments that might reference them.
         */
        arch_end_context_switch(next_p);
  
  
        x86_fsgsbase_load(prev, next);
  
-       switch_fpu_finish(next_fpu, cpu);
        /*
         * Switch the PDA and FPU contexts.
         */
        this_cpu_write(current_task, next_p);
        this_cpu_write(cpu_current_top_of_stack, task_top_of_stack(next_p));
  
+       switch_fpu_finish(next_fpu);
        /* Reload sp0. */
        update_task_stack(next_p);
  
diff --combined arch/x86/kernel/signal.c
index dff90fb6a9af61fae4d842db282a79d3214eb181,87b327c6cb104db8b59f0f1df4f24eb5f82c6df5..364813cea6476113d888ddd8a9ca428c55c3b955
@@@ -132,6 -132,16 +132,6 @@@ static int restore_sigcontext(struct pt
                COPY_SEG_CPL3(cs);
                COPY_SEG_CPL3(ss);
  
 -#ifdef CONFIG_X86_64
 -              /*
 -               * Fix up SS if needed for the benefit of old DOSEMU and
 -               * CRIU.
 -               */
 -              if (unlikely(!(uc_flags & UC_STRICT_RESTORE_SS) &&
 -                           user_64bit_mode(regs)))
 -                      force_valid_ss(regs);
 -#endif
 -
                get_user_ex(tmpflags, &sc->flags);
                regs->flags = (regs->flags & ~FIX_EFLAGS) | (tmpflags & FIX_EFLAGS);
                regs->orig_ax = -1;             /* disable syscall checks */
                buf = (void __user *)buf_val;
        } get_user_catch(err);
  
 +#ifdef CONFIG_X86_64
 +      /*
 +       * Fix up SS if needed for the benefit of old DOSEMU and
 +       * CRIU.
 +       */
 +      if (unlikely(!(uc_flags & UC_STRICT_RESTORE_SS) && user_64bit_mode(regs)))
 +              force_valid_ss(regs);
 +#endif
 +
        err |= fpu__restore_sig(buf, IS_ENABLED(CONFIG_X86_32));
  
        force_iret();
@@@ -205,7 -206,7 +205,7 @@@ int setup_sigcontext(struct sigcontext 
                put_user_ex(regs->ss, &sc->ss);
  #endif /* CONFIG_X86_32 */
  
-               put_user_ex(fpstate, &sc->fpstate);
+               put_user_ex(fpstate, (unsigned long __user *)&sc->fpstate);
  
                /* non-iBCS2 extensions.. */
                put_user_ex(mask, &sc->oldmask);
@@@ -245,7 -246,7 +245,7 @@@ get_sigframe(struct k_sigaction *ka, st
        unsigned long sp = regs->sp;
        unsigned long buf_fx = 0;
        int onsigstack = on_sig_stack(sp);
-       struct fpu *fpu = &current->thread.fpu;
+       int ret;
  
        /* redzone */
        if (IS_ENABLED(CONFIG_X86_64))
                sp = (unsigned long) ka->sa.sa_restorer;
        }
  
-       if (fpu->initialized) {
-               sp = fpu__alloc_mathframe(sp, IS_ENABLED(CONFIG_X86_32),
-                                         &buf_fx, &math_size);
-               *fpstate = (void __user *)sp;
-       }
+       sp = fpu__alloc_mathframe(sp, IS_ENABLED(CONFIG_X86_32),
+                                 &buf_fx, &math_size);
+       *fpstate = (void __user *)sp;
  
        sp = align_sigframe(sp - frame_size);
  
                return (void __user *)-1L;
  
        /* save i387 and extended state */
-       if (fpu->initialized &&
-           copy_fpstate_to_sigframe(*fpstate, (void __user *)buf_fx, math_size) < 0)
+       ret = copy_fpstate_to_sigframe(*fpstate, (void __user *)buf_fx, math_size);
+       if (ret < 0)
                return (void __user *)-1L;
  
        return (void __user *)sp;
@@@ -460,7 -459,6 +458,7 @@@ static int __setup_rt_frame(int sig, st
  {
        struct rt_sigframe __user *frame;
        void __user *fp = NULL;
 +      unsigned long uc_flags;
        int err = 0;
  
        frame = get_sigframe(&ksig->ka, regs, sizeof(struct rt_sigframe), &fp);
                        return -EFAULT;
        }
  
 +      uc_flags = frame_uc_flags(regs);
 +
        put_user_try {
                /* Create the ucontext.  */
 -              put_user_ex(frame_uc_flags(regs), &frame->uc.uc_flags);
 +              put_user_ex(uc_flags, &frame->uc.uc_flags);
                put_user_ex(0, &frame->uc.uc_link);
                save_altstack_ex(&frame->uc.uc_stack, regs->sp);
  
@@@ -543,7 -539,6 +541,7 @@@ static int x32_setup_rt_frame(struct ks
  {
  #ifdef CONFIG_X86_X32_ABI
        struct rt_sigframe_x32 __user *frame;
 +      unsigned long uc_flags;
        void __user *restorer;
        int err = 0;
        void __user *fpstate = NULL;
                        return -EFAULT;
        }
  
 +      uc_flags = frame_uc_flags(regs);
 +
        put_user_try {
                /* Create the ucontext.  */
 -              put_user_ex(frame_uc_flags(regs), &frame->uc.uc_flags);
 +              put_user_ex(uc_flags, &frame->uc.uc_flags);
                put_user_ex(0, &frame->uc.uc_link);
                compat_save_altstack_ex(&frame->uc.uc_stack, regs->sp);
                put_user_ex(0, &frame->uc.uc__pad0);
                        restorer = NULL;
                        err |= -EFAULT;
                }
-               put_user_ex(restorer, &frame->pretcode);
+               put_user_ex(restorer, (unsigned long __user *)&frame->pretcode);
        } put_user_catch(err);
  
        err |= setup_sigcontext(&frame->uc.uc_mcontext, fpstate,
@@@ -693,7 -686,10 +691,7 @@@ setup_rt_frame(struct ksignal *ksig, st
        sigset_t *set = sigmask_to_save();
        compat_sigset_t *cset = (compat_sigset_t *) set;
  
 -      /*
 -       * Increment event counter and perform fixup for the pre-signal
 -       * frame.
 -       */
 +      /* Perform fixup for the pre-signal frame. */
        rseq_signal_deliver(ksig, regs);
  
        /* Set up the stack frame */
@@@ -765,8 -761,7 +763,7 @@@ handle_signal(struct ksignal *ksig, str
                /*
                 * Ensure the signal handler starts with the new fpu state.
                 */
-               if (fpu->initialized)
-                       fpu__clear(fpu);
+               fpu__clear(fpu);
        }
        signal_setup_done(failed, ksig, stepping);
  }
diff --combined arch/x86/kvm/vmx/vmx.c
index 0c955bb286fffbdefa168d306341cd7a994946aa,dd1e1eea4f0b671715f700c7a316235ae1071286..9663d41cc2bc7ee3e7e17c227880a9ea7992d89f
@@@ -5603,7 -5603,7 +5603,7 @@@ static void vmx_dump_dtsel(char *name, 
               vmcs_readl(limit + GUEST_GDTR_BASE - GUEST_GDTR_LIMIT));
  }
  
 -static void dump_vmcs(void)
 +void dump_vmcs(void)
  {
        u32 vmentry_ctl = vmcs_read32(VM_ENTRY_CONTROLS);
        u32 vmexit_ctl = vmcs_read32(VM_EXIT_CONTROLS);
@@@ -6410,8 -6410,6 +6410,8 @@@ static void vmx_vcpu_run(struct kvm_vcp
        if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP)
                vmx_set_interrupt_shadow(vcpu, 0);
  
 +      kvm_load_guest_xcr0(vcpu);
 +
        if (static_cpu_has(X86_FEATURE_PKU) &&
            kvm_read_cr4_bits(vcpu, X86_CR4_PKE) &&
            vcpu->arch.pkru != vmx->host_pkru)
  
        x86_spec_ctrl_restore_host(vmx->spec_ctrl, 0);
  
 -      /* Eliminate branch target predictions from guest mode */
 -      vmexit_fill_RSB();
 -
        /* All fields are clean at this point */
        if (static_branch_unlikely(&enable_evmcs))
                current_evmcs->hv_clean_fields |=
         */
        if (static_cpu_has(X86_FEATURE_PKU) &&
            kvm_read_cr4_bits(vcpu, X86_CR4_PKE)) {
-               vcpu->arch.pkru = __read_pkru();
+               vcpu->arch.pkru = rdpkru();
                if (vcpu->arch.pkru != vmx->host_pkru)
                        __write_pkru(vmx->host_pkru);
        }
  
 +      kvm_put_guest_xcr0(vcpu);
 +
        vmx->nested.nested_run_pending = 0;
        vmx->idt_vectoring_info = 0;
  
@@@ -6853,30 -6852,6 +6853,30 @@@ static void nested_vmx_entry_exit_ctls_
        }
  }
  
 +static bool guest_cpuid_has_pmu(struct kvm_vcpu *vcpu)
 +{
 +      struct kvm_cpuid_entry2 *entry;
 +      union cpuid10_eax eax;
 +
 +      entry = kvm_find_cpuid_entry(vcpu, 0xa, 0);
 +      if (!entry)
 +              return false;
 +
 +      eax.full = entry->eax;
 +      return (eax.split.version_id > 0);
 +}
 +
 +static void nested_vmx_procbased_ctls_update(struct kvm_vcpu *vcpu)
 +{
 +      struct vcpu_vmx *vmx = to_vmx(vcpu);
 +      bool pmu_enabled = guest_cpuid_has_pmu(vcpu);
 +
 +      if (pmu_enabled)
 +              vmx->nested.msrs.procbased_ctls_high |= CPU_BASED_RDPMC_EXITING;
 +      else
 +              vmx->nested.msrs.procbased_ctls_high &= ~CPU_BASED_RDPMC_EXITING;
 +}
 +
  static void update_intel_pt_cfg(struct kvm_vcpu *vcpu)
  {
        struct vcpu_vmx *vmx = to_vmx(vcpu);
@@@ -6965,7 -6940,6 +6965,7 @@@ static void vmx_cpuid_update(struct kvm
        if (nested_vmx_allowed(vcpu)) {
                nested_vmx_cr_fixed1_bits_update(vcpu);
                nested_vmx_entry_exit_ctls_update(vcpu);
 +              nested_vmx_procbased_ctls_update(vcpu);
        }
  
        if (boot_cpu_has(X86_FEATURE_INTEL_PT) &&
@@@ -7029,7 -7003,6 +7029,7 @@@ static int vmx_set_hv_timer(struct kvm_
  {
        struct vcpu_vmx *vmx;
        u64 tscl, guest_tscl, delta_tsc, lapic_timer_advance_cycles;
 +      struct kvm_timer *ktimer = &vcpu->arch.apic->lapic_timer;
  
        if (kvm_mwait_in_guest(vcpu->kvm))
                return -EOPNOTSUPP;
        tscl = rdtsc();
        guest_tscl = kvm_read_l1_tsc(vcpu, tscl);
        delta_tsc = max(guest_deadline_tsc, guest_tscl) - guest_tscl;
 -      lapic_timer_advance_cycles = nsec_to_cycles(vcpu, lapic_timer_advance_ns);
 +      lapic_timer_advance_cycles = nsec_to_cycles(vcpu,
 +                                                  ktimer->timer_advance_ns);
  
        if (delta_tsc > lapic_timer_advance_cycles)
                delta_tsc -= lapic_timer_advance_cycles;
@@@ -7397,7 -7369,7 +7397,7 @@@ static int vmx_pre_enter_smm(struct kvm
        return 0;
  }
  
 -static int vmx_pre_leave_smm(struct kvm_vcpu *vcpu, u64 smbase)
 +static int vmx_pre_leave_smm(struct kvm_vcpu *vcpu, const char *smstate)
  {
        struct vcpu_vmx *vmx = to_vmx(vcpu);
        int ret;
        }
  
        if (vmx->nested.smm.guest_mode) {
 -              vcpu->arch.hflags &= ~HF_SMM_MASK;
                ret = nested_vmx_enter_non_root_mode(vcpu, false);
 -              vcpu->arch.hflags |= HF_SMM_MASK;
                if (ret)
                        return ret;
  
diff --combined arch/x86/kvm/x86.c
index b5edc8e3ce1dffbd9edeb8b0025bf6277dcc8703,e340c3c0cba325f2bdece816b68f55efa11c51a6..d75bb97b983cbc9edce0fc7baa3712aaa5199182
@@@ -136,14 -136,10 +136,14 @@@ EXPORT_SYMBOL_GPL(kvm_default_tsc_scali
  static u32 __read_mostly tsc_tolerance_ppm = 250;
  module_param(tsc_tolerance_ppm, uint, S_IRUGO | S_IWUSR);
  
 -/* lapic timer advance (tscdeadline mode only) in nanoseconds */
 -unsigned int __read_mostly lapic_timer_advance_ns = 1000;
 +/*
 + * lapic timer advance (tscdeadline mode only) in nanoseconds.  '-1' enables
 + * adaptive tuning starting from default advancment of 1000ns.  '0' disables
 + * advancement entirely.  Any other value is used as-is and disables adaptive
 + * tuning, i.e. allows priveleged userspace to set an exact advancement time.
 + */
 +static int __read_mostly lapic_timer_advance_ns = -1;
  module_param(lapic_timer_advance_ns, uint, S_IRUGO | S_IWUSR);
 -EXPORT_SYMBOL_GPL(lapic_timer_advance_ns);
  
  static bool __read_mostly vector_hashing = true;
  module_param(vector_hashing, bool, S_IRUGO);
@@@ -804,7 -800,7 +804,7 @@@ void kvm_lmsw(struct kvm_vcpu *vcpu, un
  }
  EXPORT_SYMBOL_GPL(kvm_lmsw);
  
 -static void kvm_load_guest_xcr0(struct kvm_vcpu *vcpu)
 +void kvm_load_guest_xcr0(struct kvm_vcpu *vcpu)
  {
        if (kvm_read_cr4_bits(vcpu, X86_CR4_OSXSAVE) &&
                        !vcpu->guest_xcr0_loaded) {
                vcpu->guest_xcr0_loaded = 1;
        }
  }
 +EXPORT_SYMBOL_GPL(kvm_load_guest_xcr0);
  
 -static void kvm_put_guest_xcr0(struct kvm_vcpu *vcpu)
 +void kvm_put_guest_xcr0(struct kvm_vcpu *vcpu)
  {
        if (vcpu->guest_xcr0_loaded) {
                if (vcpu->arch.xcr0 != host_xcr0)
                vcpu->guest_xcr0_loaded = 0;
        }
  }
 +EXPORT_SYMBOL_GPL(kvm_put_guest_xcr0);
  
  static int __kvm_set_xcr(struct kvm_vcpu *vcpu, u32 index, u64 xcr)
  {
@@@ -3099,7 -3093,7 +3099,7 @@@ int kvm_vm_ioctl_check_extension(struc
                break;
        case KVM_CAP_NESTED_STATE:
                r = kvm_x86_ops->get_nested_state ?
 -                      kvm_x86_ops->get_nested_state(NULL, 0, 0) : 0;
 +                      kvm_x86_ops->get_nested_state(NULL, NULL, 0) : 0;
                break;
        default:
                break;
@@@ -3534,7 -3528,7 +3534,7 @@@ static void kvm_vcpu_ioctl_x86_get_vcpu
        memset(&events->reserved, 0, sizeof(events->reserved));
  }
  
 -static void kvm_set_hflags(struct kvm_vcpu *vcpu, unsigned emul_flags);
 +static void kvm_smm_changed(struct kvm_vcpu *vcpu);
  
  static int kvm_vcpu_ioctl_x86_set_vcpu_events(struct kvm_vcpu *vcpu,
                                              struct kvm_vcpu_events *events)
                vcpu->arch.apic->sipi_vector = events->sipi_vector;
  
        if (events->flags & KVM_VCPUEVENT_VALID_SMM) {
 -              u32 hflags = vcpu->arch.hflags;
 -              if (events->smi.smm)
 -                      hflags |= HF_SMM_MASK;
 -              else
 -                      hflags &= ~HF_SMM_MASK;
 -              kvm_set_hflags(vcpu, hflags);
 +              if (!!(vcpu->arch.hflags & HF_SMM_MASK) != events->smi.smm) {
 +                      if (events->smi.smm)
 +                              vcpu->arch.hflags |= HF_SMM_MASK;
 +                      else
 +                              vcpu->arch.hflags &= ~HF_SMM_MASK;
 +                      kvm_smm_changed(vcpu);
 +              }
  
                vcpu->arch.smi_pending = events->smi.pending;
  
@@@ -3681,15 -3674,15 +3681,15 @@@ static void fill_xsave(u8 *dest, struc
         */
        valid = xstate_bv & ~XFEATURE_MASK_FPSSE;
        while (valid) {
-               u64 feature = valid & -valid;
-               int index = fls64(feature) - 1;
-               void *src = get_xsave_addr(xsave, feature);
+               u64 xfeature_mask = valid & -valid;
+               int xfeature_nr = fls64(xfeature_mask) - 1;
+               void *src = get_xsave_addr(xsave, xfeature_nr);
  
                if (src) {
                        u32 size, offset, ecx, edx;
-                       cpuid_count(XSTATE_CPUID, index,
+                       cpuid_count(XSTATE_CPUID, xfeature_nr,
                                    &size, &offset, &ecx, &edx);
-                       if (feature == XFEATURE_MASK_PKRU)
+                       if (xfeature_nr == XFEATURE_PKRU)
                                memcpy(dest + offset, &vcpu->arch.pkru,
                                       sizeof(vcpu->arch.pkru));
                        else
  
                }
  
-               valid -= feature;
+               valid -= xfeature_mask;
        }
  }
  
@@@ -3724,22 -3717,22 +3724,22 @@@ static void load_xsave(struct kvm_vcpu 
         */
        valid = xstate_bv & ~XFEATURE_MASK_FPSSE;
        while (valid) {
-               u64 feature = valid & -valid;
-               int index = fls64(feature) - 1;
-               void *dest = get_xsave_addr(xsave, feature);
+               u64 xfeature_mask = valid & -valid;
+               int xfeature_nr = fls64(xfeature_mask) - 1;
+               void *dest = get_xsave_addr(xsave, xfeature_nr);
  
                if (dest) {
                        u32 size, offset, ecx, edx;
-                       cpuid_count(XSTATE_CPUID, index,
+                       cpuid_count(XSTATE_CPUID, xfeature_nr,
                                    &size, &offset, &ecx, &edx);
-                       if (feature == XFEATURE_MASK_PKRU)
+                       if (xfeature_nr == XFEATURE_PKRU)
                                memcpy(&vcpu->arch.pkru, src + offset,
                                       sizeof(vcpu->arch.pkru));
                        else
                                memcpy(dest, src + offset, size);
                }
  
-               valid -= feature;
+               valid -= xfeature_mask;
        }
  }
  
@@@ -4277,7 -4270,7 +4277,7 @@@ static int kvm_vm_ioctl_set_identity_ma
  }
  
  static int kvm_vm_ioctl_set_nr_mmu_pages(struct kvm *kvm,
 -                                        u32 kvm_nr_mmu_pages)
 +                                       unsigned long kvm_nr_mmu_pages)
  {
        if (kvm_nr_mmu_pages < KVM_MIN_ALLOC_MMU_PAGES)
                return -EINVAL;
        return 0;
  }
  
 -static int kvm_vm_ioctl_get_nr_mmu_pages(struct kvm *kvm)
 +static unsigned long kvm_vm_ioctl_get_nr_mmu_pages(struct kvm *kvm)
  {
        return kvm->arch.n_max_mmu_pages;
  }
@@@ -5965,18 -5958,12 +5965,18 @@@ static unsigned emulator_get_hflags(str
  
  static void emulator_set_hflags(struct x86_emulate_ctxt *ctxt, unsigned emul_flags)
  {
 -      kvm_set_hflags(emul_to_vcpu(ctxt), emul_flags);
 +      emul_to_vcpu(ctxt)->arch.hflags = emul_flags;
  }
  
 -static int emulator_pre_leave_smm(struct x86_emulate_ctxt *ctxt, u64 smbase)
 +static int emulator_pre_leave_smm(struct x86_emulate_ctxt *ctxt,
 +                                const char *smstate)
  {
 -      return kvm_x86_ops->pre_leave_smm(emul_to_vcpu(ctxt), smbase);
 +      return kvm_x86_ops->pre_leave_smm(emul_to_vcpu(ctxt), smstate);
 +}
 +
 +static void emulator_post_leave_smm(struct x86_emulate_ctxt *ctxt)
 +{
 +      kvm_smm_changed(emul_to_vcpu(ctxt));
  }
  
  static const struct x86_emulate_ops emulate_ops = {
        .get_hflags          = emulator_get_hflags,
        .set_hflags          = emulator_set_hflags,
        .pre_leave_smm       = emulator_pre_leave_smm,
 +      .post_leave_smm      = emulator_post_leave_smm,
  };
  
  static void toggle_interruptibility(struct kvm_vcpu *vcpu, u32 mask)
@@@ -6261,6 -6247,16 +6261,6 @@@ static void kvm_smm_changed(struct kvm_
        kvm_mmu_reset_context(vcpu);
  }
  
 -static void kvm_set_hflags(struct kvm_vcpu *vcpu, unsigned emul_flags)
 -{
 -      unsigned changed = vcpu->arch.hflags ^ emul_flags;
 -
 -      vcpu->arch.hflags = emul_flags;
 -
 -      if (changed & HF_SMM_MASK)
 -              kvm_smm_changed(vcpu);
 -}
 -
  static int kvm_vcpu_check_hw_bp(unsigned long addr, u32 type, u32 dr7,
                                unsigned long *db)
  {
@@@ -6539,12 -6535,6 +6539,12 @@@ int kvm_emulate_instruction_from_buffer
  }
  EXPORT_SYMBOL_GPL(kvm_emulate_instruction_from_buffer);
  
 +static int complete_fast_pio_out_port_0x7e(struct kvm_vcpu *vcpu)
 +{
 +      vcpu->arch.pio.count = 0;
 +      return 1;
 +}
 +
  static int complete_fast_pio_out(struct kvm_vcpu *vcpu)
  {
        vcpu->arch.pio.count = 0;
@@@ -6561,23 -6551,12 +6561,23 @@@ static int kvm_fast_pio_out(struct kvm_
        unsigned long val = kvm_register_read(vcpu, VCPU_REGS_RAX);
        int ret = emulator_pio_out_emulated(&vcpu->arch.emulate_ctxt,
                                            size, port, &val, 1);
 +      if (ret)
 +              return ret;
  
 -      if (!ret) {
 +      /*
 +       * Workaround userspace that relies on old KVM behavior of %rip being
 +       * incremented prior to exiting to userspace to handle "OUT 0x7e".
 +       */
 +      if (port == 0x7e &&
 +          kvm_check_has_quirk(vcpu->kvm, KVM_X86_QUIRK_OUT_7E_INC_RIP)) {
 +              vcpu->arch.complete_userspace_io =
 +                      complete_fast_pio_out_port_0x7e;
 +              kvm_skip_emulated_instruction(vcpu);
 +      } else {
                vcpu->arch.pio.linear_rip = kvm_get_linear_rip(vcpu);
                vcpu->arch.complete_userspace_io = complete_fast_pio_out;
        }
 -      return ret;
 +      return 0;
  }
  
  static int complete_fast_pio_in(struct kvm_vcpu *vcpu)
@@@ -7462,9 -7441,9 +7462,9 @@@ static void enter_smm_save_state_32(str
        put_smstate(u32, buf, 0x7ef8, vcpu->arch.smbase);
  }
  
 +#ifdef CONFIG_X86_64
  static void enter_smm_save_state_64(struct kvm_vcpu *vcpu, char *buf)
  {
 -#ifdef CONFIG_X86_64
        struct desc_ptr dt;
        struct kvm_segment seg;
        unsigned long val;
  
        for (i = 0; i < 6; i++)
                enter_smm_save_seg_64(vcpu, buf, i);
 -#else
 -      WARN_ON_ONCE(1);
 -#endif
  }
 +#endif
  
  static void enter_smm(struct kvm_vcpu *vcpu)
  {
  
        trace_kvm_enter_smm(vcpu->vcpu_id, vcpu->arch.smbase, true);
        memset(buf, 0, 512);
 +#ifdef CONFIG_X86_64
        if (guest_cpuid_has(vcpu, X86_FEATURE_LM))
                enter_smm_save_state_64(vcpu, buf);
        else
 +#endif
                enter_smm_save_state_32(vcpu, buf);
  
        /*
        kvm_set_segment(vcpu, &ds, VCPU_SREG_GS);
        kvm_set_segment(vcpu, &ds, VCPU_SREG_SS);
  
 +#ifdef CONFIG_X86_64
        if (guest_cpuid_has(vcpu, X86_FEATURE_LM))
                kvm_x86_ops->set_efer(vcpu, 0);
 +#endif
  
        kvm_update_cpuid(vcpu);
        kvm_mmu_reset_context(vcpu);
@@@ -7888,17 -7865,22 +7888,21 @@@ static int vcpu_enter_guest(struct kvm_
                goto cancel_injection;
        }
  
 -      kvm_load_guest_xcr0(vcpu);
 -
        if (req_immediate_exit) {
                kvm_make_request(KVM_REQ_EVENT, vcpu);
                kvm_x86_ops->request_immediate_exit(vcpu);
        }
  
        trace_kvm_entry(vcpu->vcpu_id);
 -      if (lapic_timer_advance_ns)
 +      if (lapic_in_kernel(vcpu) &&
 +          vcpu->arch.apic->lapic_timer.timer_advance_ns)
                wait_lapic_expire(vcpu);
        guest_enter_irqoff();
  
+       fpregs_assert_state_consistent();
+       if (test_thread_flag(TIF_NEED_FPU_LOAD))
+               switch_fpu_return();
        if (unlikely(vcpu->arch.switch_db_regs)) {
                set_debugreg(0, 7);
                set_debugreg(vcpu->arch.eff_db[0], 0);
        vcpu->mode = OUTSIDE_GUEST_MODE;
        smp_wmb();
  
 -      kvm_put_guest_xcr0(vcpu);
 -
        kvm_before_interrupt(vcpu);
        kvm_x86_ops->handle_external_intr(vcpu);
        kvm_after_interrupt(vcpu);
@@@ -8157,22 -8141,30 +8161,30 @@@ static int complete_emulated_mmio(struc
  /* Swap (qemu) user FPU context for the guest FPU context. */
  static void kvm_load_guest_fpu(struct kvm_vcpu *vcpu)
  {
-       preempt_disable();
+       fpregs_lock();
        copy_fpregs_to_fpstate(&current->thread.fpu);
        /* PKRU is separately restored in kvm_x86_ops->run.  */
        __copy_kernel_to_fpregs(&vcpu->arch.guest_fpu->state,
                                ~XFEATURE_MASK_PKRU);
-       preempt_enable();
+       fpregs_mark_activate();
+       fpregs_unlock();
        trace_kvm_fpu(1);
  }
  
  /* When vcpu_run ends, restore user space FPU context. */
  static void kvm_put_guest_fpu(struct kvm_vcpu *vcpu)
  {
-       preempt_disable();
+       fpregs_lock();
        copy_fpregs_to_fpstate(vcpu->arch.guest_fpu);
        copy_kernel_to_fpregs(&current->thread.fpu.state);
-       preempt_enable();
+       fpregs_mark_activate();
+       fpregs_unlock();
        ++vcpu->stat.fpu_reload;
        trace_kvm_fpu(0);
  }
@@@ -8870,11 -8862,11 +8882,11 @@@ void kvm_vcpu_reset(struct kvm_vcpu *vc
                if (init_event)
                        kvm_put_guest_fpu(vcpu);
                mpx_state_buffer = get_xsave_addr(&vcpu->arch.guest_fpu->state.xsave,
-                                       XFEATURE_MASK_BNDREGS);
+                                       XFEATURE_BNDREGS);
                if (mpx_state_buffer)
                        memset(mpx_state_buffer, 0, sizeof(struct mpx_bndreg_state));
                mpx_state_buffer = get_xsave_addr(&vcpu->arch.guest_fpu->state.xsave,
-                                       XFEATURE_MASK_BNDCSR);
+                                       XFEATURE_BNDCSR);
                if (mpx_state_buffer)
                        memset(mpx_state_buffer, 0, sizeof(struct mpx_bndcsr));
                if (init_event)
@@@ -9083,7 -9075,7 +9095,7 @@@ int kvm_arch_vcpu_init(struct kvm_vcpu 
  
        if (irqchip_in_kernel(vcpu->kvm)) {
                vcpu->arch.apicv_active = kvm_x86_ops->get_enable_apicv(vcpu);
 -              r = kvm_create_lapic(vcpu);
 +              r = kvm_create_lapic(vcpu, lapic_timer_advance_ns);
                if (r < 0)
                        goto fail_mmu_destroy;
        } else
This page took 0.12508 seconds and 4 git commands to generate.