]> Git Repo - linux.git/commitdiff
Merge branch 'kvm-insert-lfence'
authorPaolo Bonzini <[email protected]>
Tue, 16 Jan 2018 15:38:52 +0000 (16:38 +0100)
committerRadim Krčmář <[email protected]>
Tue, 16 Jan 2018 15:39:30 +0000 (16:39 +0100)
Topic branch for CVE-2017-5753, avoiding conflicts in the next merge window.

1  2 
arch/x86/kvm/vmx.c

diff --combined arch/x86/kvm/vmx.c
index c1791759f1e6447feac882c87b7b81d88c126c2a,7f8fcc5ce664debcfe640066143e2158c7098abc..7b1d71665bc2fb4191234f58cef7c1211aba7902
@@@ -70,9 -70,6 +70,9 @@@ MODULE_DEVICE_TABLE(x86cpu, vmx_cpu_id)
  static bool __read_mostly enable_vpid = 1;
  module_param_named(vpid, enable_vpid, bool, 0444);
  
 +static bool __read_mostly enable_vnmi = 1;
 +module_param_named(vnmi, enable_vnmi, bool, S_IRUGO);
 +
  static bool __read_mostly flexpriority_enabled = 1;
  module_param_named(flexpriority, flexpriority_enabled, bool, S_IRUGO);
  
@@@ -184,6 -181,7 +184,6 @@@ module_param(ple_window_max, int, S_IRU
  extern const ulong vmx_return;
  
  #define NR_AUTOLOAD_MSRS 8
 -#define VMCS02_POOL_SIZE 1
  
  struct vmcs {
        u32 revision_id;
@@@ -204,10 -202,6 +204,10 @@@ struct loaded_vmcs 
        bool nmi_known_unmasked;
        unsigned long vmcs_host_cr3;    /* May not match real cr3 */
        unsigned long vmcs_host_cr4;    /* May not match real cr4 */
 +      /* Support for vnmi-less CPUs */
 +      int soft_vnmi_blocked;
 +      ktime_t entry_time;
 +      s64 vnmi_blocked_time;
        struct list_head loaded_vmcss_on_cpu_link;
  };
  
@@@ -224,7 -218,7 +224,7 @@@ struct shared_msr_entry 
   * stored in guest memory specified by VMPTRLD, but is opaque to the guest,
   * which must access it using VMREAD/VMWRITE/VMCLEAR instructions.
   * More than one of these structures may exist, if L1 runs multiple L2 guests.
 - * nested_vmx_run() will use the data here to build a vmcs02: a VMCS for the
 + * nested_vmx_run() will use the data here to build the vmcs02: a VMCS for the
   * underlying hardware which will be used to run L2.
   * This structure is packed to ensure that its layout is identical across
   * machines (necessary for live migration).
@@@ -407,6 -401,13 +407,6 @@@ struct __packed vmcs12 
   */
  #define VMCS12_SIZE 0x1000
  
 -/* Used to remember the last vmcs02 used for some recently used vmcs12s */
 -struct vmcs02_list {
 -      struct list_head list;
 -      gpa_t vmptr;
 -      struct loaded_vmcs vmcs02;
 -};
 -
  /*
   * The nested_vmx structure is part of vcpu_vmx, and holds information we need
   * for correct emulation of VMX (i.e., nested VMX) on this vcpu.
@@@ -431,15 -432,15 +431,15 @@@ struct nested_vmx 
         */
        bool sync_shadow_vmcs;
  
 -      /* vmcs02_list cache of VMCSs recently used to run L2 guests */
 -      struct list_head vmcs02_pool;
 -      int vmcs02_num;
        bool change_vmcs01_virtual_x2apic_mode;
        /* L2 must run next, and mustn't decide to exit to L1. */
        bool nested_run_pending;
 +
 +      struct loaded_vmcs vmcs02;
 +
        /*
 -       * Guest pages referred to in vmcs02 with host-physical pointers, so
 -       * we must keep them pinned while L2 runs.
 +       * Guest pages referred to in the vmcs02 with host-physical
 +       * pointers, so we must keep them pinned while L2 runs.
         */
        struct page *apic_access_page;
        struct page *virtual_apic_page;
        u64 nested_vmx_cr4_fixed1;
        u64 nested_vmx_vmcs_enum;
        u64 nested_vmx_vmfunc_controls;
 +
 +      /* SMM related state */
 +      struct {
 +              /* in VMX operation on SMM entry? */
 +              bool vmxon;
 +              /* in guest mode on SMM entry? */
 +              bool guest_mode;
 +      } smm;
  };
  
  #define POSTED_INTR_ON  0
@@@ -650,8 -643,6 +650,8 @@@ struct vcpu_vmx 
  
        u32 host_pkru;
  
 +      unsigned long host_debugctlmsr;
 +
        /*
         * Only bits masked by msr_ia32_feature_control_valid_bits can be set in
         * msr_ia32_feature_control. FEATURE_CONTROL_LOCKED is always included
@@@ -893,8 -884,16 +893,16 @@@ static inline short vmcs_field_to_offse
  {
        BUILD_BUG_ON(ARRAY_SIZE(vmcs_field_to_offset_table) > SHRT_MAX);
  
-       if (field >= ARRAY_SIZE(vmcs_field_to_offset_table) ||
-           vmcs_field_to_offset_table[field] == 0)
+       if (field >= ARRAY_SIZE(vmcs_field_to_offset_table))
+               return -ENOENT;
+       /*
+        * FIXME: Mitigation for CVE-2017-5753.  To be replaced with a
+        * generic mechanism.
+        */
+       asm("lfence");
+       if (vmcs_field_to_offset_table[field] == 0)
                return -ENOENT;
  
        return vmcs_field_to_offset_table[field];
@@@ -909,13 -908,16 +917,13 @@@ static bool nested_ept_ad_enabled(struc
  static unsigned long nested_ept_get_cr3(struct kvm_vcpu *vcpu);
  static u64 construct_eptp(struct kvm_vcpu *vcpu, unsigned long root_hpa);
  static bool vmx_xsaves_supported(void);
 -static int vmx_set_tss_addr(struct kvm *kvm, unsigned int addr);
  static void vmx_set_segment(struct kvm_vcpu *vcpu,
                            struct kvm_segment *var, int seg);
  static void vmx_get_segment(struct kvm_vcpu *vcpu,
                            struct kvm_segment *var, int seg);
  static bool guest_state_valid(struct kvm_vcpu *vcpu);
  static u32 vmx_segment_access_rights(struct kvm_segment *var);
 -static void copy_vmcs12_to_shadow(struct vcpu_vmx *vmx);
  static void copy_shadow_to_vmcs12(struct vcpu_vmx *vmx);
 -static int alloc_identity_pagetable(struct kvm *kvm);
  static bool vmx_get_nmi_mask(struct kvm_vcpu *vcpu);
  static void vmx_set_nmi_mask(struct kvm_vcpu *vcpu, bool masked);
  static bool nested_vmx_is_page_fault_vmexit(struct vmcs12 *vmcs12,
@@@ -937,6 -939,8 +945,6 @@@ static DEFINE_PER_CPU(struct list_head
  static DEFINE_PER_CPU(spinlock_t, blocked_vcpu_on_cpu_lock);
  
  enum {
 -      VMX_IO_BITMAP_A,
 -      VMX_IO_BITMAP_B,
        VMX_MSR_BITMAP_LEGACY,
        VMX_MSR_BITMAP_LONGMODE,
        VMX_MSR_BITMAP_LEGACY_X2APIC_APICV,
  
  static unsigned long *vmx_bitmap[VMX_BITMAP_NR];
  
 -#define vmx_io_bitmap_a                      (vmx_bitmap[VMX_IO_BITMAP_A])
 -#define vmx_io_bitmap_b                      (vmx_bitmap[VMX_IO_BITMAP_B])
  #define vmx_msr_bitmap_legacy                (vmx_bitmap[VMX_MSR_BITMAP_LEGACY])
  #define vmx_msr_bitmap_longmode              (vmx_bitmap[VMX_MSR_BITMAP_LONGMODE])
  #define vmx_msr_bitmap_legacy_x2apic_apicv   (vmx_bitmap[VMX_MSR_BITMAP_LEGACY_X2APIC_APICV])
@@@ -1288,11 -1294,6 +1296,11 @@@ static inline bool cpu_has_vmx_invpcid(
                SECONDARY_EXEC_ENABLE_INVPCID;
  }
  
 +static inline bool cpu_has_virtual_nmis(void)
 +{
 +      return vmcs_config.pin_based_exec_ctrl & PIN_BASED_VIRTUAL_NMIS;
 +}
 +
  static inline bool cpu_has_vmx_wbinvd_exit(void)
  {
        return vmcs_config.cpu_based_2nd_exec_ctrl &
@@@ -1350,6 -1351,11 +1358,6 @@@ static inline bool nested_cpu_has2(stru
                (vmcs12->secondary_vm_exec_control & bit);
  }
  
 -static inline bool nested_cpu_has_virtual_nmis(struct vmcs12 *vmcs12)
 -{
 -      return vmcs12->pin_based_vm_exec_control & PIN_BASED_VIRTUAL_NMIS;
 -}
 -
  static inline bool nested_cpu_has_preemption_timer(struct vmcs12 *vmcs12)
  {
        return vmcs12->pin_based_vm_exec_control &
@@@ -1600,15 -1606,18 +1608,15 @@@ static inline void vpid_sync_context(in
  
  static inline void ept_sync_global(void)
  {
 -      if (cpu_has_vmx_invept_global())
 -              __invept(VMX_EPT_EXTENT_GLOBAL, 0, 0);
 +      __invept(VMX_EPT_EXTENT_GLOBAL, 0, 0);
  }
  
  static inline void ept_sync_context(u64 eptp)
  {
 -      if (enable_ept) {
 -              if (cpu_has_vmx_invept_context())
 -                      __invept(VMX_EPT_EXTENT_CONTEXT, eptp, 0);
 -              else
 -                      ept_sync_global();
 -      }
 +      if (cpu_has_vmx_invept_context())
 +              __invept(VMX_EPT_EXTENT_CONTEXT, eptp, 0);
 +      else
 +              ept_sync_global();
  }
  
  static __always_inline void vmcs_check16(unsigned long field)
@@@ -1877,7 -1886,7 +1885,7 @@@ static void update_exception_bitmap(str
  {
        u32 eb;
  
 -      eb = (1u << PF_VECTOR) | (1u << UD_VECTOR) | (1u << MC_VECTOR) |
 +      eb = (1u << PF_VECTOR) | (1u << MC_VECTOR) |
             (1u << DB_VECTOR) | (1u << AC_VECTOR);
        if ((vcpu->guest_debug &
             (KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP)) ==
         */
        if (is_guest_mode(vcpu))
                eb |= get_vmcs12(vcpu)->exception_bitmap;
 +      else
 +              eb |= 1u << UD_VECTOR;
  
        vmcs_write32(EXCEPTION_BITMAP, eb);
  }
@@@ -2316,7 -2323,6 +2324,7 @@@ static void vmx_vcpu_load(struct kvm_vc
  
        vmx_vcpu_pi_load(vcpu, cpu);
        vmx->host_pkru = read_pkru();
 +      vmx->host_debugctlmsr = get_debugctlmsr();
  }
  
  static void vmx_vcpu_pi_put(struct kvm_vcpu *vcpu)
@@@ -2833,7 -2839,8 +2841,7 @@@ static void nested_vmx_setup_ctls_msrs(
                                SECONDARY_EXEC_ENABLE_PML;
                        vmx->nested.nested_vmx_ept_caps |= VMX_EPT_AD_BIT;
                }
 -      } else
 -              vmx->nested.nested_vmx_ept_caps = 0;
 +      }
  
        if (cpu_has_vmx_vmfunc()) {
                vmx->nested.nested_vmx_secondary_ctls_high |=
                 * Advertise EPTP switching unconditionally
                 * since we emulate it
                 */
 -              vmx->nested.nested_vmx_vmfunc_controls =
 -                      VMX_VMFUNC_EPTP_SWITCHING;
 +              if (enable_ept)
 +                      vmx->nested.nested_vmx_vmfunc_controls =
 +                              VMX_VMFUNC_EPTP_SWITCHING;
        }
  
        /*
                        SECONDARY_EXEC_ENABLE_VPID;
                vmx->nested.nested_vmx_vpid_caps = VMX_VPID_INVVPID_BIT |
                        VMX_VPID_EXTENT_SUPPORTED_MASK;
 -      } else
 -              vmx->nested.nested_vmx_vpid_caps = 0;
 +      }
  
        if (enable_unrestricted_guest)
                vmx->nested.nested_vmx_secondary_ctls_high |=
@@@ -3545,8 -3552,7 +3553,8 @@@ static int hardware_enable(void
                wrmsrl(MSR_IA32_FEATURE_CONTROL, old | test_bits);
        }
        kvm_cpu_vmxon(phys_addr);
 -      ept_sync_global();
 +      if (enable_ept)
 +              ept_sync_global();
  
        return 0;
  }
@@@ -3623,7 -3629,7 +3631,7 @@@ static __init int setup_vmcs_config(str
  #endif
              CPU_BASED_CR3_LOAD_EXITING |
              CPU_BASED_CR3_STORE_EXITING |
 -            CPU_BASED_USE_IO_BITMAPS |
 +            CPU_BASED_UNCOND_IO_EXITING |
              CPU_BASED_MOV_DR_EXITING |
              CPU_BASED_USE_TSC_OFFSETING |
              CPU_BASED_INVLPG_EXITING |
                        SECONDARY_EXEC_ENABLE_EPT |
                        SECONDARY_EXEC_UNRESTRICTED_GUEST |
                        SECONDARY_EXEC_PAUSE_LOOP_EXITING |
 +                      SECONDARY_EXEC_DESC |
                        SECONDARY_EXEC_RDTSCP |
                        SECONDARY_EXEC_ENABLE_INVPCID |
                        SECONDARY_EXEC_APIC_REGISTER_VIRT |
                        SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY |
                        SECONDARY_EXEC_SHADOW_VMCS |
                        SECONDARY_EXEC_XSAVES |
 -                      SECONDARY_EXEC_RDSEED |
 -                      SECONDARY_EXEC_RDRAND |
 +                      SECONDARY_EXEC_RDSEED_EXITING |
 +                      SECONDARY_EXEC_RDRAND_EXITING |
                        SECONDARY_EXEC_ENABLE_PML |
                        SECONDARY_EXEC_TSC_SCALING |
                        SECONDARY_EXEC_ENABLE_VMFUNC;
                                SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE |
                                SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY);
  
 +      rdmsr_safe(MSR_IA32_VMX_EPT_VPID_CAP,
 +              &vmx_capability.ept, &vmx_capability.vpid);
 +
        if (_cpu_based_2nd_exec_control & SECONDARY_EXEC_ENABLE_EPT) {
                /* CR3 accesses and invlpg don't need to cause VM Exits when EPT
                   enabled */
                _cpu_based_exec_control &= ~(CPU_BASED_CR3_LOAD_EXITING |
                                             CPU_BASED_CR3_STORE_EXITING |
                                             CPU_BASED_INVLPG_EXITING);
 -              rdmsr(MSR_IA32_VMX_EPT_VPID_CAP,
 -                    vmx_capability.ept, vmx_capability.vpid);
 +      } else if (vmx_capability.ept) {
 +              vmx_capability.ept = 0;
 +              pr_warn_once("EPT CAP should not exist if not support "
 +                              "1-setting enable EPT VM-execution control\n");
 +      }
 +      if (!(_cpu_based_2nd_exec_control & SECONDARY_EXEC_ENABLE_VPID) &&
 +              vmx_capability.vpid) {
 +              vmx_capability.vpid = 0;
 +              pr_warn_once("VPID CAP should not exist if not support "
 +                              "1-setting enable VPID VM-execution control\n");
        }
  
        min = VM_EXIT_SAVE_DEBUG_CONTROLS | VM_EXIT_ACK_INTR_ON_EXIT;
                                &_vmexit_control) < 0)
                return -EIO;
  
 -      min = PIN_BASED_EXT_INTR_MASK | PIN_BASED_NMI_EXITING |
 -              PIN_BASED_VIRTUAL_NMIS;
 -      opt = PIN_BASED_POSTED_INTR | PIN_BASED_VMX_PREEMPTION_TIMER;
 +      min = PIN_BASED_EXT_INTR_MASK | PIN_BASED_NMI_EXITING;
 +      opt = PIN_BASED_VIRTUAL_NMIS | PIN_BASED_POSTED_INTR |
 +               PIN_BASED_VMX_PREEMPTION_TIMER;
        if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_PINBASED_CTLS,
                                &_pin_based_exec_control) < 0)
                return -EIO;
@@@ -3845,19 -3839,6 +3853,19 @@@ static void free_loaded_vmcs(struct loa
        WARN_ON(loaded_vmcs->shadow_vmcs != NULL);
  }
  
 +static void vmx_nested_free_vmcs02(struct vcpu_vmx *vmx)
 +{
 +      struct loaded_vmcs *loaded_vmcs = &vmx->nested.vmcs02;
 +
 +      /*
 +       * Just leak the VMCS02 if the WARN triggers. Better than
 +       * a use-after-free.
 +       */
 +      if (WARN_ON(vmx->loaded_vmcs == loaded_vmcs))
 +              return;
 +      free_loaded_vmcs(loaded_vmcs);
 +}
 +
  static void free_kvm_area(void)
  {
        int cpu;
@@@ -4140,10 -4121,9 +4148,10 @@@ static void exit_lmode(struct kvm_vcpu 
  
  #endif
  
 -static inline void __vmx_flush_tlb(struct kvm_vcpu *vcpu, int vpid)
 +static inline void __vmx_flush_tlb(struct kvm_vcpu *vcpu, int vpid,
 +                              bool invalidate_gpa)
  {
 -      if (enable_ept) {
 +      if (enable_ept && (invalidate_gpa || !enable_vpid)) {
                if (!VALID_PAGE(vcpu->arch.mmu.root_hpa))
                        return;
                ept_sync_context(construct_eptp(vcpu, vcpu->arch.mmu.root_hpa));
        }
  }
  
 -static void vmx_flush_tlb(struct kvm_vcpu *vcpu)
 +static void vmx_flush_tlb(struct kvm_vcpu *vcpu, bool invalidate_gpa)
  {
 -      __vmx_flush_tlb(vcpu, to_vmx(vcpu)->vpid);
 +      __vmx_flush_tlb(vcpu, to_vmx(vcpu)->vpid, invalidate_gpa);
  }
  
  static void vmx_flush_tlb_ept_only(struct kvm_vcpu *vcpu)
  {
        if (enable_ept)
 -              vmx_flush_tlb(vcpu);
 +              vmx_flush_tlb(vcpu, true);
  }
  
  static void vmx_decache_cr0_guest_bits(struct kvm_vcpu *vcpu)
@@@ -4358,7 -4338,7 +4366,7 @@@ static void vmx_set_cr3(struct kvm_vcp
                ept_load_pdptrs(vcpu);
        }
  
 -      vmx_flush_tlb(vcpu);
 +      vmx_flush_tlb(vcpu, true);
        vmcs_writel(GUEST_CR3, guest_cr3);
  }
  
@@@ -4375,14 -4355,6 +4383,14 @@@ static int vmx_set_cr4(struct kvm_vcpu 
                (to_vmx(vcpu)->rmode.vm86_active ?
                 KVM_RMODE_VM_CR4_ALWAYS_ON : KVM_PMODE_VM_CR4_ALWAYS_ON);
  
 +      if ((cr4 & X86_CR4_UMIP) && !boot_cpu_has(X86_FEATURE_UMIP)) {
 +              vmcs_set_bits(SECONDARY_VM_EXEC_CONTROL,
 +                            SECONDARY_EXEC_DESC);
 +              hw_cr4 &= ~X86_CR4_UMIP;
 +      } else
 +              vmcs_clear_bits(SECONDARY_VM_EXEC_CONTROL,
 +                              SECONDARY_EXEC_DESC);
 +
        if (cr4 & X86_CR4_VMXE) {
                /*
                 * To use VMXON (and later other VMX instructions), a guest
@@@ -4817,18 -4789,18 +4825,18 @@@ static int init_rmode_identity_map(stru
        kvm_pfn_t identity_map_pfn;
        u32 tmp;
  
 -      if (!enable_ept)
 -              return 0;
 -
        /* Protect kvm->arch.ept_identity_pagetable_done. */
        mutex_lock(&kvm->slots_lock);
  
        if (likely(kvm->arch.ept_identity_pagetable_done))
                goto out2;
  
 +      if (!kvm->arch.ept_identity_map_addr)
 +              kvm->arch.ept_identity_map_addr = VMX_EPT_IDENTITY_PAGETABLE_ADDR;
        identity_map_pfn = kvm->arch.ept_identity_map_addr >> PAGE_SHIFT;
  
 -      r = alloc_identity_pagetable(kvm);
 +      r = __x86_set_memory_region(kvm, IDENTITY_PAGETABLE_PRIVATE_MEMSLOT,
 +                                  kvm->arch.ept_identity_map_addr, PAGE_SIZE);
        if (r < 0)
                goto out2;
  
@@@ -4900,6 -4872,20 +4908,6 @@@ out
        return r;
  }
  
 -static int alloc_identity_pagetable(struct kvm *kvm)
 -{
 -      /* Called with kvm->slots_lock held. */
 -
 -      int r = 0;
 -
 -      BUG_ON(kvm->arch.ept_identity_pagetable_done);
 -
 -      r = __x86_set_memory_region(kvm, IDENTITY_PAGETABLE_PRIVATE_MEMSLOT,
 -                                  kvm->arch.ept_identity_map_addr, PAGE_SIZE);
 -
 -      return r;
 -}
 -
  static int allocate_vpid(void)
  {
        int vpid;
@@@ -5255,10 -5241,6 +5263,10 @@@ static u32 vmx_pin_based_exec_ctrl(stru
  
        if (!kvm_vcpu_apicv_active(&vmx->vcpu))
                pin_based_exec_ctrl &= ~PIN_BASED_POSTED_INTR;
 +
 +      if (!enable_vnmi)
 +              pin_based_exec_ctrl &= ~PIN_BASED_VIRTUAL_NMIS;
 +
        /* Enable the preemption timer dynamically */
        pin_based_exec_ctrl &= ~PIN_BASED_VMX_PREEMPTION_TIMER;
        return pin_based_exec_ctrl;
@@@ -5308,13 -5290,13 +5316,13 @@@ static u32 vmx_exec_control(struct vcpu
  static bool vmx_rdrand_supported(void)
  {
        return vmcs_config.cpu_based_2nd_exec_ctrl &
 -              SECONDARY_EXEC_RDRAND;
 +              SECONDARY_EXEC_RDRAND_EXITING;
  }
  
  static bool vmx_rdseed_supported(void)
  {
        return vmcs_config.cpu_based_2nd_exec_ctrl &
 -              SECONDARY_EXEC_RDSEED;
 +              SECONDARY_EXEC_RDSEED_EXITING;
  }
  
  static void vmx_compute_secondary_exec_control(struct vcpu_vmx *vmx)
        struct kvm_vcpu *vcpu = &vmx->vcpu;
  
        u32 exec_control = vmcs_config.cpu_based_2nd_exec_ctrl;
 +
        if (!cpu_need_virtualize_apic_accesses(vcpu))
                exec_control &= ~SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES;
        if (vmx->vpid == 0)
                exec_control &= ~(SECONDARY_EXEC_APIC_REGISTER_VIRT |
                                  SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY);
        exec_control &= ~SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE;
 +
 +      /* SECONDARY_EXEC_DESC is enabled/disabled on writes to CR4.UMIP,
 +       * in vmx_set_cr4.  */
 +      exec_control &= ~SECONDARY_EXEC_DESC;
 +
        /* SECONDARY_EXEC_SHADOW_VMCS is enabled when L1 executes VMPTRLD
           (handle_vmptrld).
           We can NOT enable shadow_vmcs here because we don't have yet
        if (vmx_rdrand_supported()) {
                bool rdrand_enabled = guest_cpuid_has(vcpu, X86_FEATURE_RDRAND);
                if (rdrand_enabled)
 -                      exec_control &= ~SECONDARY_EXEC_RDRAND;
 +                      exec_control &= ~SECONDARY_EXEC_RDRAND_EXITING;
  
                if (nested) {
                        if (rdrand_enabled)
                                vmx->nested.nested_vmx_secondary_ctls_high |=
 -                                      SECONDARY_EXEC_RDRAND;
 +                                      SECONDARY_EXEC_RDRAND_EXITING;
                        else
                                vmx->nested.nested_vmx_secondary_ctls_high &=
 -                                      ~SECONDARY_EXEC_RDRAND;
 +                                      ~SECONDARY_EXEC_RDRAND_EXITING;
                }
        }
  
        if (vmx_rdseed_supported()) {
                bool rdseed_enabled = guest_cpuid_has(vcpu, X86_FEATURE_RDSEED);
                if (rdseed_enabled)
 -                      exec_control &= ~SECONDARY_EXEC_RDSEED;
 +                      exec_control &= ~SECONDARY_EXEC_RDSEED_EXITING;
  
                if (nested) {
                        if (rdseed_enabled)
                                vmx->nested.nested_vmx_secondary_ctls_high |=
 -                                      SECONDARY_EXEC_RDSEED;
 +                                      SECONDARY_EXEC_RDSEED_EXITING;
                        else
                                vmx->nested.nested_vmx_secondary_ctls_high &=
 -                                      ~SECONDARY_EXEC_RDSEED;
 +                                      ~SECONDARY_EXEC_RDSEED_EXITING;
                }
        }
  
@@@ -5458,13 -5434,17 +5466,13 @@@ static void ept_set_mmio_spte_mask(void
  /*
   * Sets up the vmcs for emulated real mode.
   */
 -static int vmx_vcpu_setup(struct vcpu_vmx *vmx)
 +static void vmx_vcpu_setup(struct vcpu_vmx *vmx)
  {
  #ifdef CONFIG_X86_64
        unsigned long a;
  #endif
        int i;
  
 -      /* I/O */
 -      vmcs_write64(IO_BITMAP_A, __pa(vmx_io_bitmap_a));
 -      vmcs_write64(IO_BITMAP_B, __pa(vmx_io_bitmap_b));
 -
        if (enable_shadow_vmcs) {
                vmcs_write64(VMREAD_BITMAP, __pa(vmx_vmread_bitmap));
                vmcs_write64(VMWRITE_BITMAP, __pa(vmx_vmwrite_bitmap));
                vmcs_write64(PML_ADDRESS, page_to_phys(vmx->pml_pg));
                vmcs_write16(GUEST_PML_INDEX, PML_ENTITY_NUM - 1);
        }
 -
 -      return 0;
  }
  
  static void vmx_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event)
                vmcs_write64(GUEST_IA32_DEBUGCTL, 0);
        }
  
 -      vmcs_writel(GUEST_RFLAGS, 0x02);
 +      kvm_set_rflags(vcpu, X86_EFLAGS_FIXED);
        kvm_rip_write(vcpu, 0xfff0);
  
        vmcs_writel(GUEST_GDTR_BASE, 0);
        vmcs_write32(GUEST_ACTIVITY_STATE, GUEST_ACTIVITY_ACTIVE);
        vmcs_write32(GUEST_INTERRUPTIBILITY_INFO, 0);
        vmcs_writel(GUEST_PENDING_DBG_EXCEPTIONS, 0);
 +      if (kvm_mpx_supported())
 +              vmcs_write64(GUEST_BNDCFGS, 0);
  
        setup_msrs(vmx);
  
@@@ -5695,8 -5675,7 +5703,8 @@@ static void enable_irq_window(struct kv
  
  static void enable_nmi_window(struct kvm_vcpu *vcpu)
  {
 -      if (vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) & GUEST_INTR_STATE_STI) {
 +      if (!enable_vnmi ||
 +          vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) & GUEST_INTR_STATE_STI) {
                enable_irq_window(vcpu);
                return;
        }
@@@ -5736,19 -5715,6 +5744,19 @@@ static void vmx_inject_nmi(struct kvm_v
  {
        struct vcpu_vmx *vmx = to_vmx(vcpu);
  
 +      if (!enable_vnmi) {
 +              /*
 +               * Tracking the NMI-blocked state in software is built upon
 +               * finding the next open IRQ window. This, in turn, depends on
 +               * well-behaving guests: They have to keep IRQs disabled at
 +               * least as long as the NMI handler runs. Otherwise we may
 +               * cause NMI nesting, maybe breaking the guest. But as this is
 +               * highly unlikely, we can live with the residual risk.
 +               */
 +              vmx->loaded_vmcs->soft_vnmi_blocked = 1;
 +              vmx->loaded_vmcs->vnmi_blocked_time = 0;
 +      }
 +
        ++vcpu->stat.nmi_injections;
        vmx->loaded_vmcs->nmi_known_unmasked = false;
  
@@@ -5767,8 -5733,6 +5775,8 @@@ static bool vmx_get_nmi_mask(struct kvm
        struct vcpu_vmx *vmx = to_vmx(vcpu);
        bool masked;
  
 +      if (!enable_vnmi)
 +              return vmx->loaded_vmcs->soft_vnmi_blocked;
        if (vmx->loaded_vmcs->nmi_known_unmasked)
                return false;
        masked = vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) & GUEST_INTR_STATE_NMI;
@@@ -5780,20 -5744,13 +5788,20 @@@ static void vmx_set_nmi_mask(struct kvm
  {
        struct vcpu_vmx *vmx = to_vmx(vcpu);
  
 -      vmx->loaded_vmcs->nmi_known_unmasked = !masked;
 -      if (masked)
 -              vmcs_set_bits(GUEST_INTERRUPTIBILITY_INFO,
 -                            GUEST_INTR_STATE_NMI);
 -      else
 -              vmcs_clear_bits(GUEST_INTERRUPTIBILITY_INFO,
 -                              GUEST_INTR_STATE_NMI);
 +      if (!enable_vnmi) {
 +              if (vmx->loaded_vmcs->soft_vnmi_blocked != masked) {
 +                      vmx->loaded_vmcs->soft_vnmi_blocked = masked;
 +                      vmx->loaded_vmcs->vnmi_blocked_time = 0;
 +              }
 +      } else {
 +              vmx->loaded_vmcs->nmi_known_unmasked = !masked;
 +              if (masked)
 +                      vmcs_set_bits(GUEST_INTERRUPTIBILITY_INFO,
 +                                    GUEST_INTR_STATE_NMI);
 +              else
 +                      vmcs_clear_bits(GUEST_INTERRUPTIBILITY_INFO,
 +                                      GUEST_INTR_STATE_NMI);
 +      }
  }
  
  static int vmx_nmi_allowed(struct kvm_vcpu *vcpu)
        if (to_vmx(vcpu)->nested.nested_run_pending)
                return 0;
  
 +      if (!enable_vnmi &&
 +          to_vmx(vcpu)->loaded_vmcs->soft_vnmi_blocked)
 +              return 0;
 +
        return  !(vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) &
                  (GUEST_INTR_STATE_MOV_SS | GUEST_INTR_STATE_STI
                   | GUEST_INTR_STATE_NMI));
@@@ -5933,10 -5886,11 +5941,10 @@@ static int handle_exception(struct kvm_
                return 1;  /* already handled by vmx_vcpu_run() */
  
        if (is_invalid_opcode(intr_info)) {
 -              if (is_guest_mode(vcpu)) {
 -                      kvm_queue_exception(vcpu, UD_VECTOR);
 -                      return 1;
 -              }
 +              WARN_ON_ONCE(is_guest_mode(vcpu));
                er = emulate_instruction(vcpu, EMULTYPE_TRAP_UD);
 +              if (er == EMULATE_USER_EXIT)
 +                      return 0;
                if (er != EMULATE_DONE)
                        kvm_queue_exception(vcpu, UD_VECTOR);
                return 1;
                cr2 = vmcs_readl(EXIT_QUALIFICATION);
                /* EPT won't cause page fault directly */
                WARN_ON_ONCE(!vcpu->arch.apf.host_apf_reason && enable_ept);
 -              return kvm_handle_page_fault(vcpu, error_code, cr2, NULL, 0,
 -                              true);
 +              return kvm_handle_page_fault(vcpu, error_code, cr2, NULL, 0);
        }
  
        ex_no = intr_info & INTR_INFO_VECTOR_MASK;
@@@ -6117,12 -6072,6 +6125,12 @@@ static int handle_set_cr4(struct kvm_vc
                return kvm_set_cr4(vcpu, val);
  }
  
 +static int handle_desc(struct kvm_vcpu *vcpu)
 +{
 +      WARN_ON(!(vcpu->arch.cr4 & X86_CR4_UMIP));
 +      return emulate_instruction(vcpu, 0) == EMULATE_DONE;
 +}
 +
  static int handle_cr(struct kvm_vcpu *vcpu)
  {
        unsigned long exit_qualification, val;
@@@ -6537,7 -6486,6 +6545,7 @@@ static int handle_ept_violation(struct 
         * AAK134, BY25.
         */
        if (!(to_vmx(vcpu)->idt_vectoring_info & VECTORING_INFO_VALID_MASK) &&
 +                      enable_vnmi &&
                        (exit_qualification & INTR_INFO_UNBLOCK_NMI))
                vmcs_set_bits(GUEST_INTERRUPTIBILITY_INFO, GUEST_INTR_STATE_NMI);
  
@@@ -6597,7 -6545,6 +6605,7 @@@ static int handle_ept_misconfig(struct 
  
  static int handle_nmi_window(struct kvm_vcpu *vcpu)
  {
 +      WARN_ON_ONCE(!enable_vnmi);
        vmcs_clear_bits(CPU_BASED_VM_EXEC_CONTROL,
                        CPU_BASED_VIRTUAL_NMI_PENDING);
        ++vcpu->stat.nmi_window_exits;
@@@ -6625,7 -6572,7 +6633,7 @@@ static int handle_invalid_guest_state(s
                if (kvm_test_request(KVM_REQ_EVENT, vcpu))
                        return 1;
  
 -              err = emulate_instruction(vcpu, EMULTYPE_NO_REEXECUTE);
 +              err = emulate_instruction(vcpu, 0);
  
                if (err == EMULATE_USER_EXIT) {
                        ++vcpu->stat.mmio_exits;
@@@ -6773,9 -6720,19 +6781,9 @@@ static __init int hardware_setup(void
                        goto out;
        }
  
 -      vmx_io_bitmap_b = (unsigned long *)__get_free_page(GFP_KERNEL);
        memset(vmx_vmread_bitmap, 0xff, PAGE_SIZE);
        memset(vmx_vmwrite_bitmap, 0xff, PAGE_SIZE);
  
 -      /*
 -       * Allow direct access to the PC debug port (it is often used for I/O
 -       * delays, but the vmexits simply slow things down).
 -       */
 -      memset(vmx_io_bitmap_a, 0xff, PAGE_SIZE);
 -      clear_bit(0x80, vmx_io_bitmap_a);
 -
 -      memset(vmx_io_bitmap_b, 0xff, PAGE_SIZE);
 -
        memset(vmx_msr_bitmap_legacy, 0xff, PAGE_SIZE);
        memset(vmx_msr_bitmap_longmode, 0xff, PAGE_SIZE);
  
  
        if (!cpu_has_vmx_ept() ||
            !cpu_has_vmx_ept_4levels() ||
 -          !cpu_has_vmx_ept_mt_wb()) {
 +          !cpu_has_vmx_ept_mt_wb() ||
 +          !cpu_has_vmx_invept_global())
                enable_ept = 0;
 -              enable_unrestricted_guest = 0;
 -              enable_ept_ad_bits = 0;
 -      }
  
        if (!cpu_has_vmx_ept_ad_bits() || !enable_ept)
                enable_ept_ad_bits = 0;
  
 -      if (!cpu_has_vmx_unrestricted_guest())
 +      if (!cpu_has_vmx_unrestricted_guest() || !enable_ept)
                enable_unrestricted_guest = 0;
  
        if (!cpu_has_vmx_flexpriority())
                flexpriority_enabled = 0;
  
 +      if (!cpu_has_virtual_nmis())
 +              enable_vnmi = 0;
 +
        /*
         * set_apic_access_page_addr() is used to reload apic access
         * page upon invalidation.  No need to do anything if not
        if (enable_ept && !cpu_has_vmx_ept_2m_page())
                kvm_disable_largepages();
  
 -      if (!cpu_has_vmx_ple())
 +      if (!cpu_has_vmx_ple()) {
                ple_gap = 0;
 +              ple_window = 0;
 +              ple_window_grow = 0;
 +              ple_window_max = 0;
 +              ple_window_shrink = 0;
 +      }
  
        if (!cpu_has_vmx_apicv()) {
                enable_apicv = 0;
@@@ -6985,6 -6936,94 +6993,6 @@@ static int handle_monitor(struct kvm_vc
        return handle_nop(vcpu);
  }
  
 -/*
 - * To run an L2 guest, we need a vmcs02 based on the L1-specified vmcs12.
 - * We could reuse a single VMCS for all the L2 guests, but we also want the
 - * option to allocate a separate vmcs02 for each separate loaded vmcs12 - this
 - * allows keeping them loaded on the processor, and in the future will allow
 - * optimizations where prepare_vmcs02 doesn't need to set all the fields on
 - * every entry if they never change.
 - * So we keep, in vmx->nested.vmcs02_pool, a cache of size VMCS02_POOL_SIZE
 - * (>=0) with a vmcs02 for each recently loaded vmcs12s, most recent first.
 - *
 - * The following functions allocate and free a vmcs02 in this pool.
 - */
 -
 -/* Get a VMCS from the pool to use as vmcs02 for the current vmcs12. */
 -static struct loaded_vmcs *nested_get_current_vmcs02(struct vcpu_vmx *vmx)
 -{
 -      struct vmcs02_list *item;
 -      list_for_each_entry(item, &vmx->nested.vmcs02_pool, list)
 -              if (item->vmptr == vmx->nested.current_vmptr) {
 -                      list_move(&item->list, &vmx->nested.vmcs02_pool);
 -                      return &item->vmcs02;
 -              }
 -
 -      if (vmx->nested.vmcs02_num >= max(VMCS02_POOL_SIZE, 1)) {
 -              /* Recycle the least recently used VMCS. */
 -              item = list_last_entry(&vmx->nested.vmcs02_pool,
 -                                     struct vmcs02_list, list);
 -              item->vmptr = vmx->nested.current_vmptr;
 -              list_move(&item->list, &vmx->nested.vmcs02_pool);
 -              return &item->vmcs02;
 -      }
 -
 -      /* Create a new VMCS */
 -      item = kmalloc(sizeof(struct vmcs02_list), GFP_KERNEL);
 -      if (!item)
 -              return NULL;
 -      item->vmcs02.vmcs = alloc_vmcs();
 -      item->vmcs02.shadow_vmcs = NULL;
 -      if (!item->vmcs02.vmcs) {
 -              kfree(item);
 -              return NULL;
 -      }
 -      loaded_vmcs_init(&item->vmcs02);
 -      item->vmptr = vmx->nested.current_vmptr;
 -      list_add(&(item->list), &(vmx->nested.vmcs02_pool));
 -      vmx->nested.vmcs02_num++;
 -      return &item->vmcs02;
 -}
 -
 -/* Free and remove from pool a vmcs02 saved for a vmcs12 (if there is one) */
 -static void nested_free_vmcs02(struct vcpu_vmx *vmx, gpa_t vmptr)
 -{
 -      struct vmcs02_list *item;
 -      list_for_each_entry(item, &vmx->nested.vmcs02_pool, list)
 -              if (item->vmptr == vmptr) {
 -                      free_loaded_vmcs(&item->vmcs02);
 -                      list_del(&item->list);
 -                      kfree(item);
 -                      vmx->nested.vmcs02_num--;
 -                      return;
 -              }
 -}
 -
 -/*
 - * Free all VMCSs saved for this vcpu, except the one pointed by
 - * vmx->loaded_vmcs. We must be running L1, so vmx->loaded_vmcs
 - * must be &vmx->vmcs01.
 - */
 -static void nested_free_all_saved_vmcss(struct vcpu_vmx *vmx)
 -{
 -      struct vmcs02_list *item, *n;
 -
 -      WARN_ON(vmx->loaded_vmcs != &vmx->vmcs01);
 -      list_for_each_entry_safe(item, n, &vmx->nested.vmcs02_pool, list) {
 -              /*
 -               * Something will leak if the above WARN triggers.  Better than
 -               * a use-after-free.
 -               */
 -              if (vmx->loaded_vmcs == &item->vmcs02)
 -                      continue;
 -
 -              free_loaded_vmcs(&item->vmcs02);
 -              list_del(&item->list);
 -              kfree(item);
 -              vmx->nested.vmcs02_num--;
 -      }
 -}
 -
  /*
   * The following 3 functions, nested_vmx_succeed()/failValid()/failInvalid(),
   * set the success or error code of an emulated VMX instruction, as specified
@@@ -7166,12 -7205,6 +7174,12 @@@ static int enter_vmx_operation(struct k
        struct vcpu_vmx *vmx = to_vmx(vcpu);
        struct vmcs *shadow_vmcs;
  
 +      vmx->nested.vmcs02.vmcs = alloc_vmcs();
 +      vmx->nested.vmcs02.shadow_vmcs = NULL;
 +      if (!vmx->nested.vmcs02.vmcs)
 +              goto out_vmcs02;
 +      loaded_vmcs_init(&vmx->nested.vmcs02);
 +
        if (cpu_has_vmx_msr_bitmap()) {
                vmx->nested.msr_bitmap =
                                (unsigned long *)__get_free_page(GFP_KERNEL);
                vmx->vmcs01.shadow_vmcs = shadow_vmcs;
        }
  
 -      INIT_LIST_HEAD(&(vmx->nested.vmcs02_pool));
 -      vmx->nested.vmcs02_num = 0;
 -
        hrtimer_init(&vmx->nested.preemption_timer, CLOCK_MONOTONIC,
                     HRTIMER_MODE_REL_PINNED);
        vmx->nested.preemption_timer.function = vmx_preemption_timer_fn;
@@@ -7208,9 -7244,6 +7216,9 @@@ out_cached_vmcs12
        free_page((unsigned long)vmx->nested.msr_bitmap);
  
  out_msr_bitmap:
 +      vmx_nested_free_vmcs02(vmx);
 +
 +out_vmcs02:
        return -ENOMEM;
  }
  
@@@ -7345,11 -7378,10 +7353,11 @@@ static inline void nested_release_vmcs1
   */
  static void free_nested(struct vcpu_vmx *vmx)
  {
 -      if (!vmx->nested.vmxon)
 +      if (!vmx->nested.vmxon && !vmx->nested.smm.vmxon)
                return;
  
        vmx->nested.vmxon = false;
 +      vmx->nested.smm.vmxon = false;
        free_vpid(vmx->nested.vpid02);
        vmx->nested.posted_intr_nv = -1;
        vmx->nested.current_vmptr = -1ull;
                vmx->vmcs01.shadow_vmcs = NULL;
        }
        kfree(vmx->nested.cached_vmcs12);
 -      /* Unpin physical memory we referred to in current vmcs02 */
 +      /* Unpin physical memory we referred to in the vmcs02 */
        if (vmx->nested.apic_access_page) {
                kvm_release_page_dirty(vmx->nested.apic_access_page);
                vmx->nested.apic_access_page = NULL;
                vmx->nested.pi_desc = NULL;
        }
  
 -      nested_free_all_saved_vmcss(vmx);
 +      vmx_nested_free_vmcs02(vmx);
  }
  
  /* Emulate the VMXOFF instruction */
@@@ -7423,6 -7455,8 +7431,6 @@@ static int handle_vmclear(struct kvm_vc
                        vmptr + offsetof(struct vmcs12, launch_state),
                        &zero, sizeof(zero));
  
 -      nested_free_vmcs02(vmx, vmptr);
 -
        nested_vmx_succeed(vcpu);
        return kvm_skip_emulated_instruction(vcpu);
  }
@@@ -7933,7 -7967,7 +7941,7 @@@ static int handle_invvpid(struct kvm_vc
                return kvm_skip_emulated_instruction(vcpu);
        }
  
 -      __vmx_flush_tlb(vcpu, vmx->nested.vpid02);
 +      __vmx_flush_tlb(vcpu, vmx->nested.vpid02, true);
        nested_vmx_succeed(vcpu);
  
        return kvm_skip_emulated_instruction(vcpu);
@@@ -7952,7 -7986,6 +7960,7 @@@ static int handle_pml_full(struct kvm_v
         * "blocked by NMI" bit has to be set before next VM entry.
         */
        if (!(to_vmx(vcpu)->idt_vectoring_info & VECTORING_INFO_VALID_MASK) &&
 +                      enable_vnmi &&
                        (exit_qualification & INTR_INFO_UNBLOCK_NMI))
                vmcs_set_bits(GUEST_INTERRUPTIBILITY_INFO,
                                GUEST_INTR_STATE_NMI);
@@@ -8127,8 -8160,6 +8135,8 @@@ static int (*const kvm_vmx_exit_handler
        [EXIT_REASON_XSETBV]                  = handle_xsetbv,
        [EXIT_REASON_TASK_SWITCH]             = handle_task_switch,
        [EXIT_REASON_MCE_DURING_VMENTRY]      = handle_machine_check,
 +      [EXIT_REASON_GDTR_IDTR]               = handle_desc,
 +      [EXIT_REASON_LDTR_TR]                 = handle_desc,
        [EXIT_REASON_EPT_VIOLATION]           = handle_ept_violation,
        [EXIT_REASON_EPT_MISCONFIG]           = handle_ept_misconfig,
        [EXIT_REASON_PAUSE_INSTRUCTION]       = handle_pause,
@@@ -8336,11 -8367,10 +8344,11 @@@ static bool nested_vmx_exit_reflected(s
  
        /*
         * The host physical addresses of some pages of guest memory
 -       * are loaded into VMCS02 (e.g. L1's Virtual APIC Page). The CPU
 -       * may write to these pages via their host physical address while
 -       * L2 is running, bypassing any address-translation-based dirty
 -       * tracking (e.g. EPT write protection).
 +       * are loaded into the vmcs02 (e.g. vmcs12's Virtual APIC
 +       * Page). The CPU may write to these pages via their host
 +       * physical address while L2 is running, bypassing any
 +       * address-translation-based dirty tracking (e.g. EPT write
 +       * protection).
         *
         * Mark them dirty on every exit from L2 to prevent them from
         * getting out of sync with dirty tracking.
        case EXIT_REASON_RDPMC:
                return nested_cpu_has(vmcs12, CPU_BASED_RDPMC_EXITING);
        case EXIT_REASON_RDRAND:
 -              return nested_cpu_has2(vmcs12, SECONDARY_EXEC_RDRAND);
 +              return nested_cpu_has2(vmcs12, SECONDARY_EXEC_RDRAND_EXITING);
        case EXIT_REASON_RDSEED:
 -              return nested_cpu_has2(vmcs12, SECONDARY_EXEC_RDSEED);
 +              return nested_cpu_has2(vmcs12, SECONDARY_EXEC_RDSEED_EXITING);
        case EXIT_REASON_RDTSC: case EXIT_REASON_RDTSCP:
                return nested_cpu_has(vmcs12, CPU_BASED_RDTSC_EXITING);
        case EXIT_REASON_VMCALL: case EXIT_REASON_VMCLEAR:
@@@ -8800,25 -8830,6 +8808,25 @@@ static int vmx_handle_exit(struct kvm_v
                return 0;
        }
  
 +      if (unlikely(!enable_vnmi &&
 +                   vmx->loaded_vmcs->soft_vnmi_blocked)) {
 +              if (vmx_interrupt_allowed(vcpu)) {
 +                      vmx->loaded_vmcs->soft_vnmi_blocked = 0;
 +              } else if (vmx->loaded_vmcs->vnmi_blocked_time > 1000000000LL &&
 +                         vcpu->arch.nmi_pending) {
 +                      /*
 +                       * This CPU don't support us in finding the end of an
 +                       * NMI-blocked window if the guest runs with IRQs
 +                       * disabled. So we pull the trigger after 1 s of
 +                       * futile waiting, but inform the user about this.
 +                       */
 +                      printk(KERN_WARNING "%s: Breaking out of NMI-blocked "
 +                             "state on VCPU %d after 1 s timeout\n",
 +                             __func__, vcpu->vcpu_id);
 +                      vmx->loaded_vmcs->soft_vnmi_blocked = 0;
 +              }
 +      }
 +
        if (exit_reason < kvm_vmx_max_exit_handlers
            && kvm_vmx_exit_handlers[exit_reason])
                return kvm_vmx_exit_handlers[exit_reason](vcpu);
@@@ -9092,12 -9103,6 +9100,12 @@@ static bool vmx_xsaves_supported(void
                SECONDARY_EXEC_XSAVES;
  }
  
 +static bool vmx_umip_emulated(void)
 +{
 +      return vmcs_config.cpu_based_2nd_exec_ctrl &
 +              SECONDARY_EXEC_DESC;
 +}
 +
  static void vmx_recover_nmi_blocking(struct vcpu_vmx *vmx)
  {
        u32 exit_intr_info;
  
        idtv_info_valid = vmx->idt_vectoring_info & VECTORING_INFO_VALID_MASK;
  
 -      if (vmx->loaded_vmcs->nmi_known_unmasked)
 -              return;
 -      /*
 -       * Can't use vmx->exit_intr_info since we're not sure what
 -       * the exit reason is.
 -       */
 -      exit_intr_info = vmcs_read32(VM_EXIT_INTR_INFO);
 -      unblock_nmi = (exit_intr_info & INTR_INFO_UNBLOCK_NMI) != 0;
 -      vector = exit_intr_info & INTR_INFO_VECTOR_MASK;
 -      /*
 -       * SDM 3: 27.7.1.2 (September 2008)
 -       * Re-set bit "block by NMI" before VM entry if vmexit caused by
 -       * a guest IRET fault.
 -       * SDM 3: 23.2.2 (September 2008)
 -       * Bit 12 is undefined in any of the following cases:
 -       *  If the VM exit sets the valid bit in the IDT-vectoring
 -       *   information field.
 -       *  If the VM exit is due to a double fault.
 -       */
 -      if ((exit_intr_info & INTR_INFO_VALID_MASK) && unblock_nmi &&
 -          vector != DF_VECTOR && !idtv_info_valid)
 -              vmcs_set_bits(GUEST_INTERRUPTIBILITY_INFO,
 -                            GUEST_INTR_STATE_NMI);
 -      else
 -              vmx->loaded_vmcs->nmi_known_unmasked =
 -                      !(vmcs_read32(GUEST_INTERRUPTIBILITY_INFO)
 -                        & GUEST_INTR_STATE_NMI);
 +      if (enable_vnmi) {
 +              if (vmx->loaded_vmcs->nmi_known_unmasked)
 +                      return;
 +              /*
 +               * Can't use vmx->exit_intr_info since we're not sure what
 +               * the exit reason is.
 +               */
 +              exit_intr_info = vmcs_read32(VM_EXIT_INTR_INFO);
 +              unblock_nmi = (exit_intr_info & INTR_INFO_UNBLOCK_NMI) != 0;
 +              vector = exit_intr_info & INTR_INFO_VECTOR_MASK;
 +              /*
 +               * SDM 3: 27.7.1.2 (September 2008)
 +               * Re-set bit "block by NMI" before VM entry if vmexit caused by
 +               * a guest IRET fault.
 +               * SDM 3: 23.2.2 (September 2008)
 +               * Bit 12 is undefined in any of the following cases:
 +               *  If the VM exit sets the valid bit in the IDT-vectoring
 +               *   information field.
 +               *  If the VM exit is due to a double fault.
 +               */
 +              if ((exit_intr_info & INTR_INFO_VALID_MASK) && unblock_nmi &&
 +                  vector != DF_VECTOR && !idtv_info_valid)
 +                      vmcs_set_bits(GUEST_INTERRUPTIBILITY_INFO,
 +                                    GUEST_INTR_STATE_NMI);
 +              else
 +                      vmx->loaded_vmcs->nmi_known_unmasked =
 +                              !(vmcs_read32(GUEST_INTERRUPTIBILITY_INFO)
 +                                & GUEST_INTR_STATE_NMI);
 +      } else if (unlikely(vmx->loaded_vmcs->soft_vnmi_blocked))
 +              vmx->loaded_vmcs->vnmi_blocked_time +=
 +                      ktime_to_ns(ktime_sub(ktime_get(),
 +                                            vmx->loaded_vmcs->entry_time));
  }
  
  static void __vmx_complete_interrupts(struct kvm_vcpu *vcpu,
@@@ -9253,12 -9253,7 +9261,12 @@@ static void vmx_arm_hv_timer(struct kvm
  static void __noclone vmx_vcpu_run(struct kvm_vcpu *vcpu)
  {
        struct vcpu_vmx *vmx = to_vmx(vcpu);
 -      unsigned long debugctlmsr, cr3, cr4;
 +      unsigned long cr3, cr4;
 +
 +      /* Record the guest's net vcpu time for enforced NMI injections. */
 +      if (unlikely(!enable_vnmi &&
 +                   vmx->loaded_vmcs->soft_vnmi_blocked))
 +              vmx->loaded_vmcs->entry_time = ktime_get();
  
        /* Don't enter VMX if guest state is invalid, let the exit handler
           start emulation until we arrive back to a valid state */
                __write_pkru(vcpu->arch.pkru);
  
        atomic_switch_perf_msrs(vmx);
 -      debugctlmsr = get_debugctlmsr();
  
        vmx_arm_hv_timer(vcpu);
  
              );
  
        /* MSR_IA32_DEBUGCTLMSR is zeroed on vmexit. Restore it if needed */
 -      if (debugctlmsr)
 -              update_debugctlmsr(debugctlmsr);
 +      if (vmx->host_debugctlmsr)
 +              update_debugctlmsr(vmx->host_debugctlmsr);
  
  #ifndef CONFIG_X86_64
        /*
@@@ -9487,6 -9483,7 +9495,6 @@@ static void vmx_switch_vmcs(struct kvm_
        vmx->loaded_vmcs = vmcs;
        vmx_vcpu_put(vcpu);
        vmx_vcpu_load(vcpu, cpu);
 -      vcpu->cpu = cpu;
        put_cpu();
  }
  
  static void vmx_free_vcpu_nested(struct kvm_vcpu *vcpu)
  {
         struct vcpu_vmx *vmx = to_vmx(vcpu);
 -       int r;
  
 -       r = vcpu_load(vcpu);
 -       BUG_ON(r);
 +       vcpu_load(vcpu);
         vmx_switch_vmcs(vcpu, &vmx->vmcs01);
         free_nested(vmx);
         vcpu_put(vcpu);
@@@ -9565,9 -9564,11 +9573,9 @@@ static struct kvm_vcpu *vmx_create_vcpu
        cpu = get_cpu();
        vmx_vcpu_load(&vmx->vcpu, cpu);
        vmx->vcpu.cpu = cpu;
 -      err = vmx_vcpu_setup(vmx);
 +      vmx_vcpu_setup(vmx);
        vmx_vcpu_put(&vmx->vcpu);
        put_cpu();
 -      if (err)
 -              goto free_vmcs;
        if (cpu_need_virtualize_apic_accesses(&vmx->vcpu)) {
                err = alloc_apic_access_page(kvm);
                if (err)
        }
  
        if (enable_ept) {
 -              if (!kvm->arch.ept_identity_map_addr)
 -                      kvm->arch.ept_identity_map_addr =
 -                              VMX_EPT_IDENTITY_PAGETABLE_ADDR;
                err = init_rmode_identity_map(kvm);
                if (err)
                        goto free_vmcs;
@@@ -9690,8 -9694,7 +9698,8 @@@ static void vmcs_set_secondary_exec_con
        u32 mask =
                SECONDARY_EXEC_SHADOW_VMCS |
                SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE |
 -              SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES;
 +              SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES |
 +              SECONDARY_EXEC_DESC;
  
        u32 cur_ctl = vmcs_read32(SECONDARY_VM_EXEC_CONTROL);
  
@@@ -9737,7 -9740,8 +9745,7 @@@ static void nested_vmx_cr_fixed1_bits_u
        cr4_fixed1_update(X86_CR4_SMEP,       ebx, bit(X86_FEATURE_SMEP));
        cr4_fixed1_update(X86_CR4_SMAP,       ebx, bit(X86_FEATURE_SMAP));
        cr4_fixed1_update(X86_CR4_PKE,        ecx, bit(X86_FEATURE_PKU));
 -      /* TODO: Use X86_CR4_UMIP and X86_FEATURE_UMIP macros */
 -      cr4_fixed1_update(bit(11),            ecx, bit(2));
 +      cr4_fixed1_update(X86_CR4_UMIP,       ecx, bit(X86_FEATURE_UMIP));
  
  #undef cr4_fixed1_update
  }
@@@ -10550,8 -10554,8 +10558,8 @@@ static int prepare_vmcs02(struct kvm_vc
        }
  
        /*
 -       * Merging of IO bitmap not currently supported.
 -       * Rather, exit every time.
 +       * A vmexit (to either L1 hypervisor or L0 userspace) is always needed
 +       * for I/O port accesses.
         */
        exec_control &= ~CPU_BASED_USE_IO_BITMAPS;
        exec_control |= CPU_BASED_UNCOND_IO_EXITING;
                        vmcs_write16(VIRTUAL_PROCESSOR_ID, vmx->nested.vpid02);
                        if (vmcs12->virtual_processor_id != vmx->nested.last_vpid) {
                                vmx->nested.last_vpid = vmcs12->virtual_processor_id;
 -                              __vmx_flush_tlb(vcpu, to_vmx(vcpu)->nested.vpid02);
 +                              __vmx_flush_tlb(vcpu, to_vmx(vcpu)->nested.vpid02, true);
                        }
                } else {
                        vmcs_write16(VIRTUAL_PROCESSOR_ID, vmx->vpid);
 -                      vmx_flush_tlb(vcpu);
 +                      vmx_flush_tlb(vcpu, true);
                }
  
        }
@@@ -10811,11 -10815,6 +10819,11 @@@ static int check_vmentry_postreqs(struc
                        return 1;
        }
  
 +      if ((vmcs12->vm_entry_controls & VM_ENTRY_LOAD_BNDCFGS) &&
 +              (is_noncanonical_address(vmcs12->guest_bndcfgs & PAGE_MASK, vcpu) ||
 +              (vmcs12->guest_bndcfgs & MSR_IA32_BNDCFGS_RSVD)))
 +                      return 1;
 +
        return 0;
  }
  
@@@ -10823,15 -10822,20 +10831,15 @@@ static int enter_vmx_non_root_mode(stru
  {
        struct vcpu_vmx *vmx = to_vmx(vcpu);
        struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
 -      struct loaded_vmcs *vmcs02;
        u32 msr_entry_idx;
        u32 exit_qual;
  
 -      vmcs02 = nested_get_current_vmcs02(vmx);
 -      if (!vmcs02)
 -              return -ENOMEM;
 -
        enter_guest_mode(vcpu);
  
        if (!(vmcs12->vm_entry_controls & VM_ENTRY_LOAD_DEBUG_CONTROLS))
                vmx->nested.vmcs01_debugctl = vmcs_read64(GUEST_IA32_DEBUGCTL);
  
 -      vmx_switch_vmcs(vcpu, vmcs02);
 +      vmx_switch_vmcs(vcpu, &vmx->nested.vmcs02);
        vmx_segment_cache_clear(vmx);
  
        if (prepare_vmcs02(vcpu, vmcs12, from_vmentry, &exit_qual)) {
@@@ -11035,12 -11039,13 +11043,12 @@@ static int vmx_check_nested_events(stru
  {
        struct vcpu_vmx *vmx = to_vmx(vcpu);
        unsigned long exit_qual;
 -
 -      if (kvm_event_needs_reinjection(vcpu))
 -              return -EBUSY;
 +      bool block_nested_events =
 +          vmx->nested.nested_run_pending || kvm_event_needs_reinjection(vcpu);
  
        if (vcpu->arch.exception.pending &&
                nested_vmx_check_exception(vcpu, &exit_qual)) {
 -              if (vmx->nested.nested_run_pending)
 +              if (block_nested_events)
                        return -EBUSY;
                nested_vmx_inject_exception_vmexit(vcpu, exit_qual);
                vcpu->arch.exception.pending = false;
  
        if (nested_cpu_has_preemption_timer(get_vmcs12(vcpu)) &&
            vmx->nested.preemption_timer_expired) {
 -              if (vmx->nested.nested_run_pending)
 +              if (block_nested_events)
                        return -EBUSY;
                nested_vmx_vmexit(vcpu, EXIT_REASON_PREEMPTION_TIMER, 0, 0);
                return 0;
        }
  
        if (vcpu->arch.nmi_pending && nested_exit_on_nmi(vcpu)) {
 -              if (vmx->nested.nested_run_pending)
 +              if (block_nested_events)
                        return -EBUSY;
                nested_vmx_vmexit(vcpu, EXIT_REASON_EXCEPTION_NMI,
                                  NMI_VECTOR | INTR_TYPE_NMI_INTR |
  
        if ((kvm_cpu_has_interrupt(vcpu) || external_intr) &&
            nested_exit_on_intr(vcpu)) {
 -              if (vmx->nested.nested_run_pending)
 +              if (block_nested_events)
                        return -EBUSY;
                nested_vmx_vmexit(vcpu, EXIT_REASON_EXTERNAL_INTERRUPT, 0, 0);
                return 0;
@@@ -11259,24 -11264,6 +11267,24 @@@ static void prepare_vmcs12(struct kvm_v
        kvm_clear_interrupt_queue(vcpu);
  }
  
 +static void load_vmcs12_mmu_host_state(struct kvm_vcpu *vcpu,
 +                      struct vmcs12 *vmcs12)
 +{
 +      u32 entry_failure_code;
 +
 +      nested_ept_uninit_mmu_context(vcpu);
 +
 +      /*
 +       * Only PDPTE load can fail as the value of cr3 was checked on entry and
 +       * couldn't have changed.
 +       */
 +      if (nested_vmx_load_cr3(vcpu, vmcs12->host_cr3, false, &entry_failure_code))
 +              nested_vmx_abort(vcpu, VMX_ABORT_LOAD_HOST_PDPTE_FAIL);
 +
 +      if (!enable_ept)
 +              vcpu->arch.walk_mmu->inject_page_fault = kvm_inject_page_fault;
 +}
 +
  /*
   * A part of what we need to when the nested L2 guest exits and we want to
   * run its L1 parent, is to reset L1's guest state to the host state specified
@@@ -11290,6 -11277,7 +11298,6 @@@ static void load_vmcs12_host_state(stru
                                   struct vmcs12 *vmcs12)
  {
        struct kvm_segment seg;
 -      u32 entry_failure_code;
  
        if (vmcs12->vm_exit_controls & VM_EXIT_LOAD_IA32_EFER)
                vcpu->arch.efer = vmcs12->host_ia32_efer;
        vcpu->arch.cr4_guest_owned_bits = ~vmcs_readl(CR4_GUEST_HOST_MASK);
        vmx_set_cr4(vcpu, vmcs12->host_cr4);
  
 -      nested_ept_uninit_mmu_context(vcpu);
 -
 -      /*
 -       * Only PDPTE load can fail as the value of cr3 was checked on entry and
 -       * couldn't have changed.
 -       */
 -      if (nested_vmx_load_cr3(vcpu, vmcs12->host_cr3, false, &entry_failure_code))
 -              nested_vmx_abort(vcpu, VMX_ABORT_LOAD_HOST_PDPTE_FAIL);
 -
 -      if (!enable_ept)
 -              vcpu->arch.walk_mmu->inject_page_fault = kvm_inject_page_fault;
 +      load_vmcs12_mmu_host_state(vcpu, vmcs12);
  
        if (enable_vpid) {
                /*
                 * L1's vpid. TODO: move to a more elaborate solution, giving
                 * each L2 its own vpid and exposing the vpid feature to L1.
                 */
 -              vmx_flush_tlb(vcpu);
 +              vmx_flush_tlb(vcpu, true);
        }
        /* Restore posted intr vector. */
        if (nested_cpu_has_posted_intr(vmcs12))
        vmcs_writel(GUEST_SYSENTER_EIP, vmcs12->host_ia32_sysenter_eip);
        vmcs_writel(GUEST_IDTR_BASE, vmcs12->host_idtr_base);
        vmcs_writel(GUEST_GDTR_BASE, vmcs12->host_gdtr_base);
 +      vmcs_write32(GUEST_IDTR_LIMIT, 0xFFFF);
 +      vmcs_write32(GUEST_GDTR_LIMIT, 0xFFFF);
  
        /* If not VM_EXIT_CLEAR_BNDCFGS, the L2 value propagates to L1.  */
        if (vmcs12->vm_exit_controls & VM_EXIT_CLEAR_BNDCFGS)
@@@ -11433,11 -11429,8 +11441,11 @@@ static void nested_vmx_vmexit(struct kv
        leave_guest_mode(vcpu);
  
        if (likely(!vmx->fail)) {
 -              prepare_vmcs12(vcpu, vmcs12, exit_reason, exit_intr_info,
 -                             exit_qualification);
 +              if (exit_reason == -1)
 +                      sync_vmcs12(vcpu, vmcs12);
 +              else
 +                      prepare_vmcs12(vcpu, vmcs12, exit_reason, exit_intr_info,
 +                                     exit_qualification);
  
                if (nested_vmx_store_msr(vcpu, vmcs12->vm_exit_msr_store_addr,
                                         vmcs12->vm_exit_msr_store_count))
        vm_exit_controls_reset_shadow(vmx);
        vmx_segment_cache_clear(vmx);
  
 -      /* if no vmcs02 cache requested, remove the one we used */
 -      if (VMCS02_POOL_SIZE == 0)
 -              nested_free_vmcs02(vmx, vmx->nested.current_vmptr);
 -
        /* Update any VMCS fields that might have changed while L2 ran */
        vmcs_write32(VM_EXIT_MSR_LOAD_COUNT, vmx->msr_autoload.nr);
        vmcs_write32(VM_ENTRY_MSR_LOAD_COUNT, vmx->msr_autoload.nr);
         */
        kvm_make_request(KVM_REQ_APIC_PAGE_RELOAD, vcpu);
  
 -      if (enable_shadow_vmcs)
 +      if (enable_shadow_vmcs && exit_reason != -1)
                vmx->nested.sync_shadow_vmcs = true;
  
        /* in case we halted in L2 */
                                INTR_INFO_VALID_MASK | INTR_TYPE_EXT_INTR;
                }
  
 -              trace_kvm_nested_vmexit_inject(vmcs12->vm_exit_reason,
 -                                             vmcs12->exit_qualification,
 -                                             vmcs12->idt_vectoring_info_field,
 -                                             vmcs12->vm_exit_intr_info,
 -                                             vmcs12->vm_exit_intr_error_code,
 -                                             KVM_ISA_VMX);
 +              if (exit_reason != -1)
 +                      trace_kvm_nested_vmexit_inject(vmcs12->vm_exit_reason,
 +                                                     vmcs12->exit_qualification,
 +                                                     vmcs12->idt_vectoring_info_field,
 +                                                     vmcs12->vm_exit_intr_info,
 +                                                     vmcs12->vm_exit_intr_error_code,
 +                                                     KVM_ISA_VMX);
  
                load_vmcs12_host_state(vcpu, vmcs12);
  
         * accordingly.
         */
        nested_vmx_failValid(vcpu, VMXERR_ENTRY_INVALID_CONTROL_FIELD);
 +
 +      load_vmcs12_mmu_host_state(vcpu, vmcs12);
 +
        /*
         * The emulated instruction was already skipped in
         * nested_vmx_run, but the updated RIP was never
@@@ -11589,21 -11582,6 +11597,21 @@@ static int vmx_check_intercept(struct k
                               struct x86_instruction_info *info,
                               enum x86_intercept_stage stage)
  {
 +      struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
 +      struct x86_emulate_ctxt *ctxt = &vcpu->arch.emulate_ctxt;
 +
 +      /*
 +       * RDPID causes #UD if disabled through secondary execution controls.
 +       * Because it is marked as EmulateOnUD, we need to intercept it here.
 +       */
 +      if (info->intercept == x86_intercept_rdtscp &&
 +          !nested_cpu_has2(vmcs12, SECONDARY_EXEC_RDTSCP)) {
 +              ctxt->exception.vector = UD_VECTOR;
 +              ctxt->exception.error_code_valid = false;
 +              return X86EMUL_PROPAGATE_FAULT;
 +      }
 +
 +      /* TODO: check more intercepts... */
        return X86EMUL_CONTINUE;
  }
  
@@@ -11968,54 -11946,6 +11976,54 @@@ static void vmx_setup_mce(struct kvm_vc
                        ~FEATURE_CONTROL_LMCE;
  }
  
 +static int vmx_smi_allowed(struct kvm_vcpu *vcpu)
 +{
 +      /* we need a nested vmexit to enter SMM, postpone if run is pending */
 +      if (to_vmx(vcpu)->nested.nested_run_pending)
 +              return 0;
 +      return 1;
 +}
 +
 +static int vmx_pre_enter_smm(struct kvm_vcpu *vcpu, char *smstate)
 +{
 +      struct vcpu_vmx *vmx = to_vmx(vcpu);
 +
 +      vmx->nested.smm.guest_mode = is_guest_mode(vcpu);
 +      if (vmx->nested.smm.guest_mode)
 +              nested_vmx_vmexit(vcpu, -1, 0, 0);
 +
 +      vmx->nested.smm.vmxon = vmx->nested.vmxon;
 +      vmx->nested.vmxon = false;
 +      return 0;
 +}
 +
 +static int vmx_pre_leave_smm(struct kvm_vcpu *vcpu, u64 smbase)
 +{
 +      struct vcpu_vmx *vmx = to_vmx(vcpu);
 +      int ret;
 +
 +      if (vmx->nested.smm.vmxon) {
 +              vmx->nested.vmxon = true;
 +              vmx->nested.smm.vmxon = false;
 +      }
 +
 +      if (vmx->nested.smm.guest_mode) {
 +              vcpu->arch.hflags &= ~HF_SMM_MASK;
 +              ret = enter_vmx_non_root_mode(vcpu, false);
 +              vcpu->arch.hflags |= HF_SMM_MASK;
 +              if (ret)
 +                      return ret;
 +
 +              vmx->nested.smm.guest_mode = false;
 +      }
 +      return 0;
 +}
 +
 +static int enable_smi_window(struct kvm_vcpu *vcpu)
 +{
 +      return 0;
 +}
 +
  static struct kvm_x86_ops vmx_x86_ops __ro_after_init = {
        .cpu_has_kvm_support = cpu_has_kvm_support,
        .disabled_by_bios = vmx_disabled_by_bios,
        .handle_external_intr = vmx_handle_external_intr,
        .mpx_supported = vmx_mpx_supported,
        .xsaves_supported = vmx_xsaves_supported,
 +      .umip_emulated = vmx_umip_emulated,
  
        .check_nested_events = vmx_check_nested_events,
  
  #endif
  
        .setup_mce = vmx_setup_mce,
 +
 +      .smi_allowed = vmx_smi_allowed,
 +      .pre_enter_smm = vmx_pre_enter_smm,
 +      .pre_leave_smm = vmx_pre_leave_smm,
 +      .enable_smi_window = enable_smi_window,
  };
  
  static int __init vmx_init(void)
This page took 0.187735 seconds and 4 git commands to generate.