KVM: VMX: Consolidate userspace and kernel interrupt injection for VMX
[deliverable/linux.git] / arch / x86 / kvm / vmx.c
index a69ba6ba42117db2b0a2819ee2b1def2f5ef0df0..06252f7465d6e07856f1ae9c35cfc0107755fdc3 100644 (file)
 MODULE_AUTHOR("Qumranet");
 MODULE_LICENSE("GPL");
 
-static int bypass_guest_pf = 1;
+static int __read_mostly bypass_guest_pf = 1;
 module_param(bypass_guest_pf, bool, S_IRUGO);
 
-static int enable_vpid = 1;
+static int __read_mostly enable_vpid = 1;
 module_param_named(vpid, enable_vpid, bool, 0444);
 
-static int flexpriority_enabled = 1;
+static int __read_mostly flexpriority_enabled = 1;
 module_param_named(flexpriority, flexpriority_enabled, bool, S_IRUGO);
 
-static int enable_ept = 1;
+static int __read_mostly enable_ept = 1;
 module_param_named(ept, enable_ept, bool, S_IRUGO);
 
-static int emulate_invalid_guest_state = 0;
+static int __read_mostly emulate_invalid_guest_state = 0;
 module_param(emulate_invalid_guest_state, bool, S_IRUGO);
 
 struct vmcs {
@@ -216,68 +216,69 @@ static inline int is_external_interrupt(u32 intr_info)
 
 static inline int cpu_has_vmx_msr_bitmap(void)
 {
-       return (vmcs_config.cpu_based_exec_ctrl & CPU_BASED_USE_MSR_BITMAPS);
+       return vmcs_config.cpu_based_exec_ctrl & CPU_BASED_USE_MSR_BITMAPS;
 }
 
 static inline int cpu_has_vmx_tpr_shadow(void)
 {
-       return (vmcs_config.cpu_based_exec_ctrl & CPU_BASED_TPR_SHADOW);
+       return vmcs_config.cpu_based_exec_ctrl & CPU_BASED_TPR_SHADOW;
 }
 
 static inline int vm_need_tpr_shadow(struct kvm *kvm)
 {
-       return ((cpu_has_vmx_tpr_shadow()) && (irqchip_in_kernel(kvm)));
+       return (cpu_has_vmx_tpr_shadow()) && (irqchip_in_kernel(kvm));
 }
 
 static inline int cpu_has_secondary_exec_ctrls(void)
 {
-       return (vmcs_config.cpu_based_exec_ctrl &
-               CPU_BASED_ACTIVATE_SECONDARY_CONTROLS);
+       return vmcs_config.cpu_based_exec_ctrl &
+               CPU_BASED_ACTIVATE_SECONDARY_CONTROLS;
 }
 
 static inline bool cpu_has_vmx_virtualize_apic_accesses(void)
 {
-       return flexpriority_enabled
-               && (vmcs_config.cpu_based_2nd_exec_ctrl &
-                   SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES);
+       return vmcs_config.cpu_based_2nd_exec_ctrl &
+               SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES;
+}
+
+static inline bool cpu_has_vmx_flexpriority(void)
+{
+       return cpu_has_vmx_tpr_shadow() &&
+               cpu_has_vmx_virtualize_apic_accesses();
 }
 
 static inline int cpu_has_vmx_invept_individual_addr(void)
 {
-       return (!!(vmx_capability.ept & VMX_EPT_EXTENT_INDIVIDUAL_BIT));
+       return !!(vmx_capability.ept & VMX_EPT_EXTENT_INDIVIDUAL_BIT);
 }
 
 static inline int cpu_has_vmx_invept_context(void)
 {
-       return (!!(vmx_capability.ept & VMX_EPT_EXTENT_CONTEXT_BIT));
+       return !!(vmx_capability.ept & VMX_EPT_EXTENT_CONTEXT_BIT);
 }
 
 static inline int cpu_has_vmx_invept_global(void)
 {
-       return (!!(vmx_capability.ept & VMX_EPT_EXTENT_GLOBAL_BIT));
+       return !!(vmx_capability.ept & VMX_EPT_EXTENT_GLOBAL_BIT);
 }
 
 static inline int cpu_has_vmx_ept(void)
 {
-       return (vmcs_config.cpu_based_2nd_exec_ctrl &
-               SECONDARY_EXEC_ENABLE_EPT);
-}
-
-static inline int vm_need_ept(void)
-{
-       return (cpu_has_vmx_ept() && enable_ept);
+       return vmcs_config.cpu_based_2nd_exec_ctrl &
+               SECONDARY_EXEC_ENABLE_EPT;
 }
 
 static inline int vm_need_virtualize_apic_accesses(struct kvm *kvm)
 {
-       return ((cpu_has_vmx_virtualize_apic_accesses()) &&
-               (irqchip_in_kernel(kvm)));
+       return flexpriority_enabled &&
+               (cpu_has_vmx_virtualize_apic_accesses()) &&
+               (irqchip_in_kernel(kvm));
 }
 
 static inline int cpu_has_vmx_vpid(void)
 {
-       return (vmcs_config.cpu_based_2nd_exec_ctrl &
-               SECONDARY_EXEC_ENABLE_VPID);
+       return vmcs_config.cpu_based_2nd_exec_ctrl &
+               SECONDARY_EXEC_ENABLE_VPID;
 }
 
 static inline int cpu_has_virtual_nmis(void)
@@ -285,6 +286,11 @@ static inline int cpu_has_virtual_nmis(void)
        return vmcs_config.pin_based_exec_ctrl & PIN_BASED_VIRTUAL_NMIS;
 }
 
+static inline bool report_flexpriority(void)
+{
+       return flexpriority_enabled;
+}
+
 static int __find_msr_index(struct vcpu_vmx *vmx, u32 msr)
 {
        int i;
@@ -382,7 +388,7 @@ static inline void ept_sync_global(void)
 
 static inline void ept_sync_context(u64 eptp)
 {
-       if (vm_need_ept()) {
+       if (enable_ept) {
                if (cpu_has_vmx_invept_context())
                        __invept(VMX_EPT_EXTENT_CONTEXT, eptp, 0);
                else
@@ -392,7 +398,7 @@ static inline void ept_sync_context(u64 eptp)
 
 static inline void ept_sync_individual_addr(u64 eptp, gpa_t gpa)
 {
-       if (vm_need_ept()) {
+       if (enable_ept) {
                if (cpu_has_vmx_invept_individual_addr())
                        __invept(VMX_EPT_EXTENT_INDIVIDUAL_ADDR,
                                        eptp, gpa);
@@ -491,7 +497,7 @@ static void update_exception_bitmap(struct kvm_vcpu *vcpu)
        }
        if (vcpu->arch.rmode.active)
                eb = ~0;
-       if (vm_need_ept())
+       if (enable_ept)
                eb &= ~(1u << PF_VECTOR); /* bypass_guest_pf = 0 */
        vmcs_write32(EXCEPTION_BITMAP, eb);
 }
@@ -1305,6 +1311,15 @@ static __init int hardware_setup(void)
        if (boot_cpu_has(X86_FEATURE_NX))
                kvm_enable_efer_bits(EFER_NX);
 
+       if (!cpu_has_vmx_vpid())
+               enable_vpid = 0;
+
+       if (!cpu_has_vmx_ept())
+               enable_ept = 0;
+
+       if (!cpu_has_vmx_flexpriority())
+               flexpriority_enabled = 0;
+
        return alloc_kvm_area();
 }
 
@@ -1496,7 +1511,7 @@ static void exit_lmode(struct kvm_vcpu *vcpu)
 static void vmx_flush_tlb(struct kvm_vcpu *vcpu)
 {
        vpid_sync_vcpu_all(to_vmx(vcpu));
-       if (vm_need_ept())
+       if (enable_ept)
                ept_sync_context(construct_eptp(vcpu->arch.mmu.root_hpa));
 }
 
@@ -1581,7 +1596,7 @@ static void vmx_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
        }
 #endif
 
-       if (vm_need_ept())
+       if (enable_ept)
                ept_update_paging_mode_cr0(&hw_cr0, cr0, vcpu);
 
        vmcs_writel(CR0_READ_SHADOW, cr0);
@@ -1610,7 +1625,7 @@ static void vmx_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3)
        u64 eptp;
 
        guest_cr3 = cr3;
-       if (vm_need_ept()) {
+       if (enable_ept) {
                eptp = construct_eptp(cr3);
                vmcs_write64(EPT_POINTER, eptp);
                ept_sync_context(eptp);
@@ -1631,7 +1646,7 @@ static void vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
                    KVM_RMODE_VM_CR4_ALWAYS_ON : KVM_PMODE_VM_CR4_ALWAYS_ON);
 
        vcpu->arch.cr4 = cr4;
-       if (vm_need_ept())
+       if (enable_ept)
                ept_update_paging_mode_cr4(&hw_cr4, vcpu);
 
        vmcs_writel(CR4_READ_SHADOW, cr4);
@@ -1993,7 +2008,7 @@ static int init_rmode_identity_map(struct kvm *kvm)
        pfn_t identity_map_pfn;
        u32 tmp;
 
-       if (!vm_need_ept())
+       if (!enable_ept)
                return 1;
        if (unlikely(!kvm->arch.ept_identity_pagetable)) {
                printk(KERN_ERR "EPT: identity-mapping pagetable "
@@ -2082,7 +2097,7 @@ static void allocate_vpid(struct vcpu_vmx *vmx)
        int vpid;
 
        vmx->vpid = 0;
-       if (!enable_vpid || !cpu_has_vmx_vpid())
+       if (!enable_vpid)
                return;
        spin_lock(&vmx_vpid_lock);
        vpid = find_first_zero_bit(vmx_vpid_bitmap, VMX_NR_VPIDS);
@@ -2157,7 +2172,7 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx)
                                CPU_BASED_CR8_LOAD_EXITING;
 #endif
        }
-       if (!vm_need_ept())
+       if (!enable_ept)
                exec_control |= CPU_BASED_CR3_STORE_EXITING |
                                CPU_BASED_CR3_LOAD_EXITING  |
                                CPU_BASED_INVLPG_EXITING;
@@ -2170,7 +2185,7 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx)
                                ~SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES;
                if (vmx->vpid == 0)
                        exec_control &= ~SECONDARY_EXEC_ENABLE_VPID;
-               if (!vm_need_ept())
+               if (!enable_ept)
                        exec_control &= ~SECONDARY_EXEC_ENABLE_EPT;
                vmcs_write32(SECONDARY_VM_EXEC_CONTROL, exec_control);
        }
@@ -2489,47 +2504,10 @@ static void vmx_update_window_states(struct kvm_vcpu *vcpu)
                                 GUEST_INTR_STATE_MOV_SS)));
 }
 
-static void do_interrupt_requests(struct kvm_vcpu *vcpu,
-                                      struct kvm_run *kvm_run)
+static int vmx_interrupt_allowed(struct kvm_vcpu *vcpu)
 {
        vmx_update_window_states(vcpu);
-
-       if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP)
-               vmcs_clear_bits(GUEST_INTERRUPTIBILITY_INFO,
-                               GUEST_INTR_STATE_STI |
-                               GUEST_INTR_STATE_MOV_SS);
-
-       if (vcpu->arch.nmi_pending && !vcpu->arch.nmi_injected) {
-               if (vcpu->arch.interrupt.pending) {
-                       enable_nmi_window(vcpu);
-               } else if (vcpu->arch.nmi_window_open) {
-                       vcpu->arch.nmi_pending = false;
-                       vcpu->arch.nmi_injected = true;
-               } else {
-                       enable_nmi_window(vcpu);
-                       return;
-               }
-       }
-       if (vcpu->arch.nmi_injected) {
-               vmx_inject_nmi(vcpu);
-               if (vcpu->arch.nmi_pending)
-                       enable_nmi_window(vcpu);
-               else if (vcpu->arch.irq_summary
-                        || kvm_run->request_interrupt_window)
-                       enable_irq_window(vcpu);
-               return;
-       }
-
-       if (vcpu->arch.interrupt_window_open) {
-               if (vcpu->arch.irq_summary && !vcpu->arch.interrupt.pending)
-                       kvm_queue_interrupt(vcpu, kvm_pop_irq(vcpu));
-
-               if (vcpu->arch.interrupt.pending)
-                       vmx_inject_irq(vcpu, vcpu->arch.interrupt.nr);
-       }
-       if (!vcpu->arch.interrupt_window_open &&
-           (vcpu->arch.irq_summary || kvm_run->request_interrupt_window))
-               enable_irq_window(vcpu);
+       return vcpu->arch.interrupt_window_open;
 }
 
 static int vmx_set_tss_addr(struct kvm *kvm, unsigned int addr)
@@ -2605,11 +2583,6 @@ static int handle_exception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
                printk(KERN_ERR "%s: unexpected, vectoring info 0x%x "
                       "intr info 0x%x\n", __func__, vect_info, intr_info);
 
-       if (!irqchip_in_kernel(vcpu->kvm) && is_external_interrupt(vect_info)) {
-               int irq = vect_info & VECTORING_INFO_VECTOR_MASK;
-               kvm_push_irq(vcpu, irq);
-       }
-
        if ((intr_info & INTR_INFO_INTR_TYPE_MASK) == INTR_TYPE_NMI_INTR)
                return 1;  /* already handled by vmx_vcpu_run() */
 
@@ -2631,7 +2604,7 @@ static int handle_exception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
                error_code = vmcs_read32(VM_EXIT_INTR_ERROR_CODE);
        if (is_page_fault(intr_info)) {
                /* EPT won't cause page fault directly */
-               if (vm_need_ept())
+               if (enable_ept)
                        BUG();
                cr2 = vmcs_readl(EXIT_QUALIFICATION);
                KVMTRACE_3D(PAGE_FAULT, vcpu, error_code, (u32)cr2,
@@ -2960,8 +2933,9 @@ static int handle_interrupt_window(struct kvm_vcpu *vcpu,
         * If the user space waits to inject interrupts, exit as soon as
         * possible
         */
-       if (kvm_run->request_interrupt_window &&
-           !vcpu->arch.irq_summary) {
+       if (!irqchip_in_kernel(vcpu->kvm) &&
+           kvm_run->request_interrupt_window &&
+           !kvm_cpu_has_interrupt(vcpu)) {
                kvm_run->exit_reason = KVM_EXIT_IRQ_WINDOW_OPEN;
                return 0;
        }
@@ -2983,7 +2957,7 @@ static int handle_vmcall(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 
 static int handle_invlpg(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 {
-       u64 exit_qualification = vmcs_read64(EXIT_QUALIFICATION);
+       unsigned long exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
 
        kvm_mmu_invlpg(vcpu, exit_qualification);
        skip_emulated_instruction(vcpu);
@@ -2999,11 +2973,11 @@ static int handle_wbinvd(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 
 static int handle_apic_access(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 {
-       u64 exit_qualification;
+       unsigned long exit_qualification;
        enum emulation_result er;
        unsigned long offset;
 
-       exit_qualification = vmcs_read64(EXIT_QUALIFICATION);
+       exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
        offset = exit_qualification & 0xffful;
 
        er = emulate_instruction(vcpu, kvm_run, 0, 0, 0);
@@ -3022,22 +2996,40 @@ static int handle_task_switch(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
        struct vcpu_vmx *vmx = to_vmx(vcpu);
        unsigned long exit_qualification;
        u16 tss_selector;
-       int reason;
+       int reason, type, idt_v;
+
+       idt_v = (vmx->idt_vectoring_info & VECTORING_INFO_VALID_MASK);
+       type = (vmx->idt_vectoring_info & VECTORING_INFO_TYPE_MASK);
 
        exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
 
        reason = (u32)exit_qualification >> 30;
-       if (reason == TASK_SWITCH_GATE && vmx->vcpu.arch.nmi_injected &&
-           (vmx->idt_vectoring_info & VECTORING_INFO_VALID_MASK) &&
-           (vmx->idt_vectoring_info & VECTORING_INFO_TYPE_MASK)
-           == INTR_TYPE_NMI_INTR) {
-               vcpu->arch.nmi_injected = false;
-               if (cpu_has_virtual_nmis())
-                       vmcs_set_bits(GUEST_INTERRUPTIBILITY_INFO,
-                                     GUEST_INTR_STATE_NMI);
+       if (reason == TASK_SWITCH_GATE && idt_v) {
+               switch (type) {
+               case INTR_TYPE_NMI_INTR:
+                       vcpu->arch.nmi_injected = false;
+                       if (cpu_has_virtual_nmis())
+                               vmcs_set_bits(GUEST_INTERRUPTIBILITY_INFO,
+                                             GUEST_INTR_STATE_NMI);
+                       break;
+               case INTR_TYPE_EXT_INTR:
+                       kvm_clear_interrupt_queue(vcpu);
+                       break;
+               case INTR_TYPE_HARD_EXCEPTION:
+               case INTR_TYPE_SOFT_EXCEPTION:
+                       kvm_clear_exception_queue(vcpu);
+                       break;
+               default:
+                       break;
+               }
        }
        tss_selector = exit_qualification;
 
+       if (!idt_v || (type != INTR_TYPE_HARD_EXCEPTION &&
+                      type != INTR_TYPE_EXT_INTR &&
+                      type != INTR_TYPE_NMI_INTR))
+               skip_emulated_instruction(vcpu);
+
        if (!kvm_task_switch(vcpu, tss_selector, reason))
                return 0;
 
@@ -3054,11 +3046,11 @@ static int handle_task_switch(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 
 static int handle_ept_violation(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 {
-       u64 exit_qualification;
+       unsigned long exit_qualification;
        gpa_t gpa;
        int gla_validity;
 
-       exit_qualification = vmcs_read64(EXIT_QUALIFICATION);
+       exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
 
        if (exit_qualification & (1 << 6)) {
                printk(KERN_ERR "EPT: GPA exceeds GAW!\n");
@@ -3070,7 +3062,7 @@ static int handle_ept_violation(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
                printk(KERN_ERR "EPT: Handling EPT violation failed!\n");
                printk(KERN_ERR "EPT: GPA: 0x%lx, GVA: 0x%lx\n",
                        (long unsigned int)vmcs_read64(GUEST_PHYSICAL_ADDRESS),
-                       (long unsigned int)vmcs_read64(GUEST_LINEAR_ADDRESS));
+                       vmcs_readl(GUEST_LINEAR_ADDRESS));
                printk(KERN_ERR "EPT: Exit qualification is 0x%lx\n",
                        (long unsigned int)exit_qualification);
                kvm_run->exit_reason = KVM_EXIT_UNKNOWN;
@@ -3181,7 +3173,7 @@ static int vmx_handle_exit(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
 
        /* Access CR3 don't cause VMExit in paging mode, so we need
         * to sync with guest real CR3. */
-       if (vm_need_ept() && is_paging(vcpu)) {
+       if (enable_ept && is_paging(vcpu)) {
                vcpu->arch.cr3 = vmcs_readl(GUEST_CR3);
                ept_load_pdptrs(vcpu);
        }
@@ -3251,64 +3243,77 @@ static void update_tpr_threshold(struct kvm_vcpu *vcpu)
 static void vmx_complete_interrupts(struct vcpu_vmx *vmx)
 {
        u32 exit_intr_info;
-       u32 idt_vectoring_info;
+       u32 idt_vectoring_info = vmx->idt_vectoring_info;
        bool unblock_nmi;
        u8 vector;
        int type;
        bool idtv_info_valid;
-       u32 error;
 
+       idtv_info_valid = idt_vectoring_info & VECTORING_INFO_VALID_MASK;
        exit_intr_info = vmcs_read32(VM_EXIT_INTR_INFO);
        if (cpu_has_virtual_nmis()) {
                unblock_nmi = (exit_intr_info & INTR_INFO_UNBLOCK_NMI) != 0;
                vector = exit_intr_info & INTR_INFO_VECTOR_MASK;
                /*
-                * SDM 3: 25.7.1.2
+                * 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 (unblock_nmi && vector != DF_VECTOR)
+               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 if (unlikely(vmx->soft_vnmi_blocked))
                vmx->vnmi_blocked_time +=
                        ktime_to_ns(ktime_sub(ktime_get(), vmx->entry_time));
 
-       idt_vectoring_info = vmx->idt_vectoring_info;
-       idtv_info_valid = idt_vectoring_info & VECTORING_INFO_VALID_MASK;
+       vmx->vcpu.arch.nmi_injected = false;
+       kvm_clear_exception_queue(&vmx->vcpu);
+       kvm_clear_interrupt_queue(&vmx->vcpu);
+
+       if (!idtv_info_valid)
+               return;
+
        vector = idt_vectoring_info & VECTORING_INFO_VECTOR_MASK;
        type = idt_vectoring_info & VECTORING_INFO_TYPE_MASK;
-       if (vmx->vcpu.arch.nmi_injected) {
+
+       switch (type) {
+       case INTR_TYPE_NMI_INTR:
+               vmx->vcpu.arch.nmi_injected = true;
                /*
-                * SDM 3: 25.7.1.2
-                * Clear bit "block by NMI" before VM entry if a NMI delivery
-                * faulted.
+                * SDM 3: 27.7.1.2 (September 2008)
+                * Clear bit "block by NMI" before VM entry if a NMI
+                * delivery faulted.
                 */
-               if (idtv_info_valid && type == INTR_TYPE_NMI_INTR)
-                       vmcs_clear_bits(GUEST_INTERRUPTIBILITY_INFO,
-                                       GUEST_INTR_STATE_NMI);
-               else
-                       vmx->vcpu.arch.nmi_injected = false;
-       }
-       kvm_clear_exception_queue(&vmx->vcpu);
-       if (idtv_info_valid && (type == INTR_TYPE_HARD_EXCEPTION ||
-                               type == INTR_TYPE_SOFT_EXCEPTION)) {
+               vmcs_clear_bits(GUEST_INTERRUPTIBILITY_INFO,
+                               GUEST_INTR_STATE_NMI);
+               break;
+       case INTR_TYPE_HARD_EXCEPTION:
+       case INTR_TYPE_SOFT_EXCEPTION:
                if (idt_vectoring_info & VECTORING_INFO_DELIVER_CODE_MASK) {
-                       error = vmcs_read32(IDT_VECTORING_ERROR_CODE);
-                       kvm_queue_exception_e(&vmx->vcpu, vector, error);
+                       u32 err = vmcs_read32(IDT_VECTORING_ERROR_CODE);
+                       kvm_queue_exception_e(&vmx->vcpu, vector, err);
                } else
                        kvm_queue_exception(&vmx->vcpu, vector);
-               vmx->idt_vectoring_info = 0;
-       }
-       kvm_clear_interrupt_queue(&vmx->vcpu);
-       if (idtv_info_valid && type == INTR_TYPE_EXT_INTR) {
+               break;
+       case INTR_TYPE_EXT_INTR:
                kvm_queue_interrupt(&vmx->vcpu, vector);
-               vmx->idt_vectoring_info = 0;
+               break;
+       default:
+               break;
        }
 }
 
-static void vmx_intr_assist(struct kvm_vcpu *vcpu)
+static void vmx_intr_assist(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 {
+       bool req_int_win = !irqchip_in_kernel(vcpu->kvm) &&
+               kvm_run->request_interrupt_window;
+
        update_tpr_threshold(vcpu);
 
        vmx_update_window_states(vcpu);
@@ -3329,25 +3334,25 @@ static void vmx_intr_assist(struct kvm_vcpu *vcpu)
                        return;
                }
        }
+
        if (vcpu->arch.nmi_injected) {
                vmx_inject_nmi(vcpu);
-               if (vcpu->arch.nmi_pending)
-                       enable_nmi_window(vcpu);
-               else if (kvm_cpu_has_interrupt(vcpu))
-                       enable_irq_window(vcpu);
-               return;
+               goto out;
        }
+
        if (!vcpu->arch.interrupt.pending && kvm_cpu_has_interrupt(vcpu)) {
                if (vcpu->arch.interrupt_window_open)
                        kvm_queue_interrupt(vcpu, kvm_cpu_get_interrupt(vcpu));
-               else
-                       enable_irq_window(vcpu);
        }
-       if (vcpu->arch.interrupt.pending) {
+
+       if (vcpu->arch.interrupt.pending)
                vmx_inject_irq(vcpu, vcpu->arch.interrupt.nr);
-               if (kvm_cpu_has_interrupt(vcpu))
-                       enable_irq_window(vcpu);
-       }
+
+out:
+       if (vcpu->arch.nmi_pending)
+               enable_nmi_window(vcpu);
+       else if (kvm_cpu_has_interrupt(vcpu) || req_int_win)
+               enable_irq_window(vcpu);
 }
 
 /*
@@ -3596,7 +3601,7 @@ static struct kvm_vcpu *vmx_create_vcpu(struct kvm *kvm, unsigned int id)
                if (alloc_apic_access_page(kvm) != 0)
                        goto free_vmcs;
 
-       if (vm_need_ept())
+       if (enable_ept)
                if (alloc_identity_pagetable(kvm) != 0)
                        goto free_vmcs;
 
@@ -3647,7 +3652,7 @@ static struct kvm_x86_ops vmx_x86_ops = {
        .check_processor_compatibility = vmx_check_processor_compat,
        .hardware_enable = hardware_enable,
        .hardware_disable = hardware_disable,
-       .cpu_has_accelerated_tpr = cpu_has_vmx_virtualize_apic_accesses,
+       .cpu_has_accelerated_tpr = report_flexpriority,
 
        .vcpu_create = vmx_create_vcpu,
        .vcpu_free = vmx_free_vcpu,
@@ -3689,8 +3694,8 @@ static struct kvm_x86_ops vmx_x86_ops = {
        .queue_exception = vmx_queue_exception,
        .exception_injected = vmx_exception_injected,
        .inject_pending_irq = vmx_intr_assist,
-       .inject_pending_vectors = do_interrupt_requests,
-
+       .inject_pending_vectors = vmx_intr_assist,
+       .interrupt_allowed = vmx_interrupt_allowed,
        .set_tss_addr = vmx_set_tss_addr,
        .get_tdp_level = get_ept_level,
        .get_mt_mask_shift = vmx_get_mt_mask_shift,
@@ -3747,7 +3752,7 @@ static int __init vmx_init(void)
        vmx_disable_intercept_for_msr(MSR_IA32_SYSENTER_ESP, false);
        vmx_disable_intercept_for_msr(MSR_IA32_SYSENTER_EIP, false);
 
-       if (vm_need_ept()) {
+       if (enable_ept) {
                bypass_guest_pf = 0;
                kvm_mmu_set_base_ptes(VMX_EPT_READABLE_MASK |
                        VMX_EPT_WRITABLE_MASK);
This page took 0.033433 seconds and 5 git commands to generate.