Merge branch 'kvm-amd-fixes' into HEAD
[linux-block.git] / arch / x86 / kvm / vmx / vmx.c
index 8959514eaf0fa115614df4facb3d678f6e00fbbc..46aa3ca019290199fdff520650bf91816ed20a4c 100644 (file)
@@ -437,6 +437,11 @@ static const struct kvm_vmx_segment_field {
        VMX_SEGMENT_FIELD(LDTR),
 };
 
+static inline void vmx_segment_cache_clear(struct vcpu_vmx *vmx)
+{
+       vmx->segment_cache.bitmask = 0;
+}
+
 static unsigned long host_idt_base;
 
 /*
@@ -1338,6 +1343,10 @@ void vmx_vcpu_load_vmcs(struct kvm_vcpu *vcpu, int cpu)
                void *gdt = get_current_gdt_ro();
                unsigned long sysenter_esp;
 
+               /*
+                * Flush all EPTP/VPID contexts, the new pCPU may have stale
+                * TLB entries from its previous association with the vCPU.
+                */
                kvm_make_request(KVM_REQ_TLB_FLUSH, vcpu);
 
                /*
@@ -1372,7 +1381,6 @@ void vmx_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
 
        vmx_vcpu_pi_load(vcpu, cpu);
 
-       vmx->host_pkru = read_pkru();
        vmx->host_debugctlmsr = get_debugctlmsr();
 }
 
@@ -2838,18 +2846,64 @@ static void exit_lmode(struct kvm_vcpu *vcpu)
 
 #endif
 
-static void vmx_flush_tlb_gva(struct kvm_vcpu *vcpu, gva_t addr)
+static void vmx_flush_tlb_all(struct kvm_vcpu *vcpu)
 {
-       int vpid = to_vmx(vcpu)->vpid;
+       struct vcpu_vmx *vmx = to_vmx(vcpu);
+
+       /*
+        * INVEPT must be issued when EPT is enabled, irrespective of VPID, as
+        * the CPU is not required to invalidate guest-physical mappings on
+        * VM-Entry, even if VPID is disabled.  Guest-physical mappings are
+        * associated with the root EPT structure and not any particular VPID
+        * (INVVPID also isn't required to invalidate guest-physical mappings).
+        */
+       if (enable_ept) {
+               ept_sync_global();
+       } else if (enable_vpid) {
+               if (cpu_has_vmx_invvpid_global()) {
+                       vpid_sync_vcpu_global();
+               } else {
+                       vpid_sync_vcpu_single(vmx->vpid);
+                       vpid_sync_vcpu_single(vmx->nested.vpid02);
+               }
+       }
+}
+
+static void vmx_flush_tlb_current(struct kvm_vcpu *vcpu)
+{
+       u64 root_hpa = vcpu->arch.mmu->root_hpa;
+
+       /* No flush required if the current context is invalid. */
+       if (!VALID_PAGE(root_hpa))
+               return;
+
+       if (enable_ept)
+               ept_sync_context(construct_eptp(vcpu, root_hpa));
+       else if (!is_guest_mode(vcpu))
+               vpid_sync_context(to_vmx(vcpu)->vpid);
+       else
+               vpid_sync_context(nested_get_vpid02(vcpu));
+}
 
-       if (!vpid_sync_vcpu_addr(vpid, addr))
-               vpid_sync_context(vpid);
+static void vmx_flush_tlb_gva(struct kvm_vcpu *vcpu, gva_t addr)
+{
+       /*
+        * vpid_sync_vcpu_addr() is a nop if vmx->vpid==0, see the comment in
+        * vmx_flush_tlb_guest() for an explanation of why this is ok.
+        */
+       vpid_sync_vcpu_addr(to_vmx(vcpu)->vpid, addr);
+}
 
+static void vmx_flush_tlb_guest(struct kvm_vcpu *vcpu)
+{
        /*
-        * If VPIDs are not supported or enabled, then the above is a no-op.
-        * But we don't really need a TLB flush in that case anyway, because
-        * each VM entry/exit includes an implicit flush when VPID is 0.
+        * vpid_sync_context() is a nop if vmx->vpid==0, e.g. if enable_vpid==0
+        * or a vpid couldn't be allocated for this vCPU.  VM-Enter and VM-Exit
+        * are required to flush GVA->{G,H}PA mappings from the TLB if vpid is
+        * disabled (VM-Enter with vpid enabled and vpid==0 is disallowed),
+        * i.e. no explicit INVVPID is necessary.
         */
+       vpid_sync_context(to_vmx(vcpu)->vpid);
 }
 
 static void vmx_decache_cr0_guest_bits(struct kvm_vcpu *vcpu)
@@ -2887,12 +2941,13 @@ void ept_save_pdptrs(struct kvm_vcpu *vcpu)
 {
        struct kvm_mmu *mmu = vcpu->arch.walk_mmu;
 
-       if (is_pae_paging(vcpu)) {
-               mmu->pdptrs[0] = vmcs_read64(GUEST_PDPTR0);
-               mmu->pdptrs[1] = vmcs_read64(GUEST_PDPTR1);
-               mmu->pdptrs[2] = vmcs_read64(GUEST_PDPTR2);
-               mmu->pdptrs[3] = vmcs_read64(GUEST_PDPTR3);
-       }
+       if (WARN_ON_ONCE(!is_pae_paging(vcpu)))
+               return;
+
+       mmu->pdptrs[0] = vmcs_read64(GUEST_PDPTR0);
+       mmu->pdptrs[1] = vmcs_read64(GUEST_PDPTR1);
+       mmu->pdptrs[2] = vmcs_read64(GUEST_PDPTR2);
+       mmu->pdptrs[3] = vmcs_read64(GUEST_PDPTR3);
 
        kvm_register_mark_dirty(vcpu, VCPU_EXREG_PDPTR);
 }
@@ -2984,16 +3039,15 @@ u64 construct_eptp(struct kvm_vcpu *vcpu, unsigned long root_hpa)
        return eptp;
 }
 
-void vmx_load_mmu_pgd(struct kvm_vcpu *vcpu, unsigned long cr3)
+void vmx_load_mmu_pgd(struct kvm_vcpu *vcpu, unsigned long pgd)
 {
        struct kvm *kvm = vcpu->kvm;
        bool update_guest_cr3 = true;
        unsigned long guest_cr3;
        u64 eptp;
 
-       guest_cr3 = cr3;
        if (enable_ept) {
-               eptp = construct_eptp(vcpu, cr3);
+               eptp = construct_eptp(vcpu, pgd);
                vmcs_write64(EPT_POINTER, eptp);
 
                if (kvm_x86_ops.tlb_remote_flush) {
@@ -3014,6 +3068,8 @@ void vmx_load_mmu_pgd(struct kvm_vcpu *vcpu, unsigned long cr3)
                else /* vmcs01.GUEST_CR3 is already up-to-date. */
                        update_guest_cr3 = false;
                ept_load_pdptrs(vcpu);
+       } else {
+               guest_cr3 = pgd;
        }
 
        if (update_guest_cr3)
@@ -4572,7 +4628,7 @@ static int handle_rmode_exception(struct kvm_vcpu *vcpu,
  */
 static void kvm_machine_check(void)
 {
-#if defined(CONFIG_X86_MCE) && defined(CONFIG_X86_64)
+#if defined(CONFIG_X86_MCE)
        struct pt_regs regs = {
                .cs = 3, /* Fake ring 3 no matter what the guest ran on */
                .flags = X86_EFLAGS_IF,
@@ -4588,6 +4644,26 @@ static int handle_machine_check(struct kvm_vcpu *vcpu)
        return 1;
 }
 
+/*
+ * If the host has split lock detection disabled, then #AC is
+ * unconditionally injected into the guest, which is the pre split lock
+ * detection behaviour.
+ *
+ * If the host has split lock detection enabled then #AC is
+ * only injected into the guest when:
+ *  - Guest CPL == 3 (user mode)
+ *  - Guest has #AC detection enabled in CR0
+ *  - Guest EFLAGS has AC bit set
+ */
+static inline bool guest_inject_ac(struct kvm_vcpu *vcpu)
+{
+       if (!boot_cpu_has(X86_FEATURE_SPLIT_LOCK_DETECT))
+               return true;
+
+       return vmx_get_cpl(vcpu) == 3 && kvm_read_cr0_bits(vcpu, X86_CR0_AM) &&
+              (kvm_get_rflags(vcpu) & X86_EFLAGS_AC);
+}
+
 static int handle_exception_nmi(struct kvm_vcpu *vcpu)
 {
        struct vcpu_vmx *vmx = to_vmx(vcpu);
@@ -4641,7 +4717,7 @@ static int handle_exception_nmi(struct kvm_vcpu *vcpu)
        }
 
        if (is_page_fault(intr_info)) {
-               cr2 = vmcs_readl(EXIT_QUALIFICATION);
+               cr2 = vmx_get_exit_qual(vcpu);
                /* 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);
@@ -4653,22 +4729,17 @@ static int handle_exception_nmi(struct kvm_vcpu *vcpu)
                return handle_rmode_exception(vcpu, ex_no, error_code);
 
        switch (ex_no) {
-       case AC_VECTOR:
-               kvm_queue_exception_e(vcpu, AC_VECTOR, error_code);
-               return 1;
        case DB_VECTOR:
-               dr6 = vmcs_readl(EXIT_QUALIFICATION);
+               dr6 = vmx_get_exit_qual(vcpu);
                if (!(vcpu->guest_debug &
                      (KVM_GUESTDBG_SINGLESTEP | KVM_GUESTDBG_USE_HW_BP))) {
-                       vcpu->arch.dr6 &= ~DR_TRAP_BITS;
-                       vcpu->arch.dr6 |= dr6 | DR6_RTM;
                        if (is_icebp(intr_info))
                                WARN_ON(!skip_emulated_instruction(vcpu));
 
-                       kvm_queue_exception(vcpu, DB_VECTOR);
+                       kvm_queue_exception_p(vcpu, DB_VECTOR, dr6);
                        return 1;
                }
-               kvm_run->debug.arch.dr6 = dr6 | DR6_FIXED_1;
+               kvm_run->debug.arch.dr6 = dr6 | DR6_FIXED_1 | DR6_RTM;
                kvm_run->debug.arch.dr7 = vmcs_readl(GUEST_DR7);
                /* fall through */
        case BP_VECTOR:
@@ -4684,6 +4755,20 @@ static int handle_exception_nmi(struct kvm_vcpu *vcpu)
                kvm_run->debug.arch.pc = vmcs_readl(GUEST_CS_BASE) + rip;
                kvm_run->debug.arch.exception = ex_no;
                break;
+       case AC_VECTOR:
+               if (guest_inject_ac(vcpu)) {
+                       kvm_queue_exception_e(vcpu, AC_VECTOR, error_code);
+                       return 1;
+               }
+
+               /*
+                * Handle split lock. Depending on detection mode this will
+                * either warn and disable split lock detection for this
+                * task or force SIGBUS on it.
+                */
+               if (handle_guest_split_lock(kvm_rip_read(vcpu)))
+                       return 1;
+               fallthrough;
        default:
                kvm_run->exit_reason = KVM_EXIT_EXCEPTION;
                kvm_run->ex.exception = ex_no;
@@ -4712,7 +4797,7 @@ static int handle_io(struct kvm_vcpu *vcpu)
        int size, in, string;
        unsigned port;
 
-       exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
+       exit_qualification = vmx_get_exit_qual(vcpu);
        string = (exit_qualification & 16) != 0;
 
        ++vcpu->stat.io_exits;
@@ -4803,7 +4888,7 @@ static int handle_cr(struct kvm_vcpu *vcpu)
        int err;
        int ret;
 
-       exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
+       exit_qualification = vmx_get_exit_qual(vcpu);
        cr = exit_qualification & 15;
        reg = (exit_qualification >> 8) & 15;
        switch ((exit_qualification >> 4) & 3) {
@@ -4880,7 +4965,7 @@ static int handle_dr(struct kvm_vcpu *vcpu)
        unsigned long exit_qualification;
        int dr, dr7, reg;
 
-       exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
+       exit_qualification = vmx_get_exit_qual(vcpu);
        dr = exit_qualification & DEBUG_REG_ACCESS_NUM;
 
        /* First, if DR does not exist, trigger UD */
@@ -4898,16 +4983,14 @@ static int handle_dr(struct kvm_vcpu *vcpu)
                 * guest debugging itself.
                 */
                if (vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP) {
-                       vcpu->run->debug.arch.dr6 = vcpu->arch.dr6;
+                       vcpu->run->debug.arch.dr6 = DR6_BD | DR6_RTM | DR6_FIXED_1;
                        vcpu->run->debug.arch.dr7 = dr7;
                        vcpu->run->debug.arch.pc = kvm_get_linear_rip(vcpu);
                        vcpu->run->debug.arch.exception = DB_VECTOR;
                        vcpu->run->exit_reason = KVM_EXIT_DEBUG;
                        return 0;
                } else {
-                       vcpu->arch.dr6 &= ~DR_TRAP_BITS;
-                       vcpu->arch.dr6 |= DR6_BD | DR6_RTM;
-                       kvm_queue_exception(vcpu, DB_VECTOR);
+                       kvm_queue_exception_p(vcpu, DB_VECTOR, DR6_BD);
                        return 1;
                }
        }
@@ -4938,15 +5021,6 @@ static int handle_dr(struct kvm_vcpu *vcpu)
        return kvm_skip_emulated_instruction(vcpu);
 }
 
-static u64 vmx_get_dr6(struct kvm_vcpu *vcpu)
-{
-       return vcpu->arch.dr6;
-}
-
-static void vmx_set_dr6(struct kvm_vcpu *vcpu, unsigned long val)
-{
-}
-
 static void vmx_sync_dirty_debug_regs(struct kvm_vcpu *vcpu)
 {
        get_debugreg(vcpu->arch.db[0], 0);
@@ -4993,7 +5067,7 @@ static int handle_invd(struct kvm_vcpu *vcpu)
 
 static int handle_invlpg(struct kvm_vcpu *vcpu)
 {
-       unsigned long exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
+       unsigned long exit_qualification = vmx_get_exit_qual(vcpu);
 
        kvm_mmu_invlpg(vcpu, exit_qualification);
        return kvm_skip_emulated_instruction(vcpu);
@@ -5025,7 +5099,7 @@ static int handle_xsetbv(struct kvm_vcpu *vcpu)
 static int handle_apic_access(struct kvm_vcpu *vcpu)
 {
        if (likely(fasteoi)) {
-               unsigned long exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
+               unsigned long exit_qualification = vmx_get_exit_qual(vcpu);
                int access_type, offset;
 
                access_type = exit_qualification & APIC_ACCESS_TYPE;
@@ -5046,7 +5120,7 @@ static int handle_apic_access(struct kvm_vcpu *vcpu)
 
 static int handle_apic_eoi_induced(struct kvm_vcpu *vcpu)
 {
-       unsigned long exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
+       unsigned long exit_qualification = vmx_get_exit_qual(vcpu);
        int vector = exit_qualification & 0xff;
 
        /* EOI-induced VM exit is trap-like and thus no need to adjust IP */
@@ -5056,7 +5130,7 @@ static int handle_apic_eoi_induced(struct kvm_vcpu *vcpu)
 
 static int handle_apic_write(struct kvm_vcpu *vcpu)
 {
-       unsigned long exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
+       unsigned long exit_qualification = vmx_get_exit_qual(vcpu);
        u32 offset = exit_qualification & 0xfff;
 
        /* APIC-write VM exit is trap-like and thus no need to adjust IP */
@@ -5077,7 +5151,7 @@ static int handle_task_switch(struct kvm_vcpu *vcpu)
        idt_index = (vmx->idt_vectoring_info & VECTORING_INFO_VECTOR_MASK);
        type = (vmx->idt_vectoring_info & VECTORING_INFO_TYPE_MASK);
 
-       exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
+       exit_qualification = vmx_get_exit_qual(vcpu);
 
        reason = (u32)exit_qualification >> 30;
        if (reason == TASK_SWITCH_GATE && idt_v) {
@@ -5127,7 +5201,7 @@ static int handle_ept_violation(struct kvm_vcpu *vcpu)
        gpa_t gpa;
        u64 error_code;
 
-       exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
+       exit_qualification = vmx_get_exit_qual(vcpu);
 
        /*
         * EPT violation happened while executing iret from NMI,
@@ -5387,13 +5461,13 @@ static int handle_invpcid(struct kvm_vcpu *vcpu)
        /* According to the Intel instruction reference, the memory operand
         * is read even if it isn't needed (e.g., for type==all)
         */
-       if (get_vmx_mem_address(vcpu, vmcs_readl(EXIT_QUALIFICATION),
+       if (get_vmx_mem_address(vcpu, vmx_get_exit_qual(vcpu),
                                vmx_instruction_info, false,
                                sizeof(operand), &gva))
                return 1;
 
        if (kvm_read_guest_virt(vcpu, gva, &operand, sizeof(operand), &e)) {
-               kvm_inject_page_fault(vcpu, &e);
+               kvm_inject_emulated_page_fault(vcpu, &e);
                return 1;
        }
 
@@ -5422,11 +5496,11 @@ static int handle_invpcid(struct kvm_vcpu *vcpu)
 
                if (kvm_get_active_pcid(vcpu) == operand.pcid) {
                        kvm_mmu_sync_roots(vcpu);
-                       kvm_make_request(KVM_REQ_TLB_FLUSH, vcpu);
+                       kvm_make_request(KVM_REQ_TLB_FLUSH_CURRENT, vcpu);
                }
 
                for (i = 0; i < KVM_MMU_NUM_PREV_ROOTS; i++)
-                       if (kvm_get_pcid(vcpu, vcpu->arch.mmu->prev_roots[i].cr3)
+                       if (kvm_get_pcid(vcpu, vcpu->arch.mmu->prev_roots[i].pgd)
                            == operand.pcid)
                                roots_to_free |= KVM_MMU_ROOT_PREVIOUS(i);
 
@@ -5463,7 +5537,7 @@ static int handle_pml_full(struct kvm_vcpu *vcpu)
 
        trace_kvm_pml_full(vcpu->vcpu_id);
 
-       exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
+       exit_qualification = vmx_get_exit_qual(vcpu);
 
        /*
         * PML buffer FULL happened while executing iret from NMI,
@@ -5577,8 +5651,8 @@ static const int kvm_vmx_max_exit_handlers =
 
 static void vmx_get_exit_info(struct kvm_vcpu *vcpu, u64 *info1, u64 *info2)
 {
-       *info1 = vmcs_readl(EXIT_QUALIFICATION);
-       *info2 = vmcs_read32(VM_EXIT_INTR_INFO);
+       *info1 = vmx_get_exit_qual(vcpu);
+       *info2 = vmx_get_intr_info(vcpu);
 }
 
 static void vmx_destroy_pml_buffer(struct vcpu_vmx *vmx)
@@ -5660,7 +5734,6 @@ void dump_vmcs(void)
        u32 cpu_based_exec_ctrl, pin_based_exec_ctrl, secondary_exec_control;
        unsigned long cr4;
        u64 efer;
-       int i, n;
 
        if (!dump_invalid_vmcs) {
                pr_warn_ratelimited("set kvm_intel.dump_invalid_vmcs=1 to dump internal KVM state.\n");
@@ -5797,14 +5870,6 @@ void dump_vmcs(void)
                pr_err("PostedIntrVec = 0x%02x\n", vmcs_read16(POSTED_INTR_NV));
        if ((secondary_exec_control & SECONDARY_EXEC_ENABLE_EPT))
                pr_err("EPT pointer = 0x%016llx\n", vmcs_read64(EPT_POINTER));
-       n = vmcs_read32(CR3_TARGET_COUNT);
-       for (i = 0; i + 1 < n; i += 4)
-               pr_err("CR3 target%u=%016lx target%u=%016lx\n",
-                      i, vmcs_readl(CR3_TARGET_VALUE0 + i * 2),
-                      i + 1, vmcs_readl(CR3_TARGET_VALUE0 + i * 2 + 2));
-       if (i < n)
-               pr_err("CR3 target%u=%016lx\n",
-                      i, vmcs_readl(CR3_TARGET_VALUE0 + i * 2));
        if (secondary_exec_control & SECONDARY_EXEC_PAUSE_LOOP_EXITING)
                pr_err("PLE Gap=%08x Window=%08x\n",
                       vmcs_read32(PLE_GAP), vmcs_read32(PLE_WINDOW));
@@ -5854,8 +5919,8 @@ static int vmx_handle_exit(struct kvm_vcpu *vcpu,
                 */
                nested_mark_vmcs12_pages_dirty(vcpu);
 
-               if (nested_vmx_exit_reflected(vcpu, exit_reason))
-                       return nested_vmx_reflect_vmexit(vcpu, exit_reason);
+               if (nested_vmx_reflect_vmexit(vcpu))
+                       return 1;
        }
 
        if (exit_reason & VMX_EXIT_REASONS_FAILED_VMENTRY) {
@@ -6076,7 +6141,15 @@ void vmx_set_virtual_apic_mode(struct kvm_vcpu *vcpu)
                if (flexpriority_enabled) {
                        sec_exec_control |=
                                SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES;
-                       vmx_flush_tlb(vcpu, true);
+                       kvm_make_request(KVM_REQ_APIC_PAGE_RELOAD, vcpu);
+
+                       /*
+                        * Flush the TLB, reloading the APIC access page will
+                        * only do so if its physical address has changed, but
+                        * the guest may have inserted a non-APIC mapping into
+                        * the TLB while the APIC access page was disabled.
+                        */
+                       kvm_make_request(KVM_REQ_TLB_FLUSH_CURRENT, vcpu);
                }
                break;
        case LAPIC_MODE_X2APIC:
@@ -6090,12 +6163,32 @@ void vmx_set_virtual_apic_mode(struct kvm_vcpu *vcpu)
        vmx_update_msr_bitmap(vcpu);
 }
 
-static void vmx_set_apic_access_page_addr(struct kvm_vcpu *vcpu, hpa_t hpa)
+static void vmx_set_apic_access_page_addr(struct kvm_vcpu *vcpu)
 {
-       if (!is_guest_mode(vcpu)) {
-               vmcs_write64(APIC_ACCESS_ADDR, hpa);
-               vmx_flush_tlb(vcpu, true);
+       struct page *page;
+
+       /* Defer reload until vmcs01 is the current VMCS. */
+       if (is_guest_mode(vcpu)) {
+               to_vmx(vcpu)->nested.reload_vmcs01_apic_access_page = true;
+               return;
        }
+
+       if (!(secondary_exec_controls_get(to_vmx(vcpu)) &
+           SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES))
+               return;
+
+       page = gfn_to_page(vcpu->kvm, APIC_DEFAULT_PHYS_BASE >> PAGE_SHIFT);
+       if (is_error_page(page))
+               return;
+
+       vmcs_write64(APIC_ACCESS_ADDR, page_to_phys(page));
+       vmx_flush_tlb_current(vcpu);
+
+       /*
+        * Do not pin apic access page in memory, the MMU notifier
+        * will call us again if it is migrated or swapped out.
+        */
+       put_page(page);
 }
 
 static void vmx_hwapic_isr_update(struct kvm_vcpu *vcpu, int max_isr)
@@ -6213,16 +6306,16 @@ static void vmx_apicv_post_state_restore(struct kvm_vcpu *vcpu)
 
 static void handle_exception_nmi_irqoff(struct vcpu_vmx *vmx)
 {
-       vmx->exit_intr_info = vmcs_read32(VM_EXIT_INTR_INFO);
+       u32 intr_info = vmx_get_intr_info(&vmx->vcpu);
 
        /* if exit due to PF check for async PF */
-       if (is_page_fault(vmx->exit_intr_info)) {
+       if (is_page_fault(intr_info)) {
                vmx->vcpu.arch.apf.host_apf_reason = kvm_read_and_reset_pf_reason();
        /* Handle machine checks before interrupts are enabled */
-       } else if (is_machine_check(vmx->exit_intr_info)) {
+       } else if (is_machine_check(intr_info)) {
                kvm_machine_check();
        /* We need to handle NMIs before interrupts are enabled */
-       } else if (is_nmi(vmx->exit_intr_info)) {
+       } else if (is_nmi(intr_info)) {
                kvm_before_interrupt(&vmx->vcpu);
                asm("int $2");
                kvm_after_interrupt(&vmx->vcpu);
@@ -6237,9 +6330,8 @@ static void handle_external_interrupt_irqoff(struct kvm_vcpu *vcpu)
        unsigned long tmp;
 #endif
        gate_desc *desc;
-       u32 intr_info;
+       u32 intr_info = vmx_get_intr_info(vcpu);
 
-       intr_info = vmcs_read32(VM_EXIT_INTR_INFO);
        if (WARN_ONCE(!is_external_intr(intr_info),
            "KVM: unexpected VM-Exit interrupt info: 0x%x", intr_info))
                return;
@@ -6275,8 +6367,7 @@ static void handle_external_interrupt_irqoff(struct kvm_vcpu *vcpu)
 }
 STACK_FRAME_NON_STANDARD(handle_external_interrupt_irqoff);
 
-static void vmx_handle_exit_irqoff(struct kvm_vcpu *vcpu,
-       enum exit_fastpath_completion *exit_fastpath)
+static void vmx_handle_exit_irqoff(struct kvm_vcpu *vcpu)
 {
        struct vcpu_vmx *vmx = to_vmx(vcpu);
 
@@ -6284,9 +6375,6 @@ static void vmx_handle_exit_irqoff(struct kvm_vcpu *vcpu,
                handle_external_interrupt_irqoff(vcpu);
        else if (vmx->exit_reason == EXIT_REASON_EXCEPTION_NMI)
                handle_exception_nmi_irqoff(vmx);
-       else if (!is_guest_mode(vcpu) &&
-               vmx->exit_reason == EXIT_REASON_MSR_WRITE)
-               *exit_fastpath = handle_fastpath_set_msr_irqoff(vcpu);
 }
 
 static bool vmx_has_emulated_msr(int index)
@@ -6320,11 +6408,8 @@ static void vmx_recover_nmi_blocking(struct vcpu_vmx *vmx)
        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);
+
+               exit_intr_info = vmx_get_intr_info(&vmx->vcpu);
                unblock_nmi = (exit_intr_info & INTR_INFO_UNBLOCK_NMI) != 0;
                vector = exit_intr_info & INTR_INFO_VECTOR_MASK;
                /*
@@ -6493,8 +6578,9 @@ void vmx_update_host_rsp(struct vcpu_vmx *vmx, unsigned long host_rsp)
 
 bool __vmx_vcpu_run(struct vcpu_vmx *vmx, unsigned long *regs, bool launched);
 
-static void vmx_vcpu_run(struct kvm_vcpu *vcpu)
+static enum exit_fastpath_completion vmx_vcpu_run(struct kvm_vcpu *vcpu)
 {
+       enum exit_fastpath_completion exit_fastpath;
        struct vcpu_vmx *vmx = to_vmx(vcpu);
        unsigned long cr3, cr4;
 
@@ -6506,7 +6592,7 @@ static void vmx_vcpu_run(struct kvm_vcpu *vcpu)
        /* Don't enter VMX if guest state is invalid, let the exit handler
           start emulation until we arrive back to a valid state */
        if (vmx->emulation_required)
-               return;
+               return EXIT_FASTPATH_NONE;
 
        if (vmx->ple_window_dirty) {
                vmx->ple_window_dirty = false;
@@ -6546,11 +6632,6 @@ static void vmx_vcpu_run(struct kvm_vcpu *vcpu)
 
        kvm_load_guest_xsave_state(vcpu);
 
-       if (static_cpu_has(X86_FEATURE_PKU) &&
-           kvm_read_cr4_bits(vcpu, X86_CR4_PKE) &&
-           vcpu->arch.pkru != vmx->host_pkru)
-               __write_pkru(vcpu->arch.pkru);
-
        pt_guest_enter(vmx);
 
        if (vcpu_to_pmu(vcpu)->version)
@@ -6631,44 +6712,39 @@ static void vmx_vcpu_run(struct kvm_vcpu *vcpu)
        loadsegment(es, __USER_DS);
 #endif
 
-       vcpu->arch.regs_avail = ~((1 << VCPU_REGS_RIP) | (1 << VCPU_REGS_RSP)
-                                 | (1 << VCPU_EXREG_RFLAGS)
-                                 | (1 << VCPU_EXREG_PDPTR)
-                                 | (1 << VCPU_EXREG_SEGMENTS)
-                                 | (1 << VCPU_EXREG_CR3));
-       vcpu->arch.regs_dirty = 0;
+       vmx_register_cache_reset(vcpu);
 
        pt_guest_exit(vmx);
 
-       /*
-        * eager fpu is enabled if PKEY is supported and CR4 is switched
-        * back on host, so it is safe to read guest PKRU from current
-        * XSAVE.
-        */
-       if (static_cpu_has(X86_FEATURE_PKU) &&
-           kvm_read_cr4_bits(vcpu, X86_CR4_PKE)) {
-               vcpu->arch.pkru = rdpkru();
-               if (vcpu->arch.pkru != vmx->host_pkru)
-                       __write_pkru(vmx->host_pkru);
-       }
-
        kvm_load_host_xsave_state(vcpu);
 
        vmx->nested.nested_run_pending = 0;
        vmx->idt_vectoring_info = 0;
 
-       vmx->exit_reason = vmx->fail ? 0xdead : vmcs_read32(VM_EXIT_REASON);
-       if ((u16)vmx->exit_reason == EXIT_REASON_MCE_DURING_VMENTRY)
+       if (unlikely(vmx->fail)) {
+               vmx->exit_reason = 0xdead;
+               return EXIT_FASTPATH_NONE;
+       }
+
+       vmx->exit_reason = vmcs_read32(VM_EXIT_REASON);
+       if (unlikely((u16)vmx->exit_reason == EXIT_REASON_MCE_DURING_VMENTRY))
                kvm_machine_check();
 
-       if (vmx->fail || (vmx->exit_reason & VMX_EXIT_REASONS_FAILED_VMENTRY))
-               return;
+       if (unlikely(vmx->exit_reason & VMX_EXIT_REASONS_FAILED_VMENTRY))
+               return EXIT_FASTPATH_NONE;
+
+       if (!is_guest_mode(vcpu) && vmx->exit_reason == EXIT_REASON_MSR_WRITE)
+               exit_fastpath = handle_fastpath_set_msr_irqoff(vcpu);
+       else
+               exit_fastpath = EXIT_FASTPATH_NONE;
 
        vmx->loaded_vmcs->launched = 1;
        vmx->idt_vectoring_info = vmcs_read32(IDT_VECTORING_INFO_FIELD);
 
        vmx_recover_nmi_blocking(vmx);
        vmx_complete_interrupts(vmx);
+
+       return exit_fastpath;
 }
 
 static void vmx_free_vcpu(struct kvm_vcpu *vcpu)
@@ -7709,16 +7785,16 @@ static struct kvm_x86_ops vmx_x86_ops __initdata = {
        .set_idt = vmx_set_idt,
        .get_gdt = vmx_get_gdt,
        .set_gdt = vmx_set_gdt,
-       .get_dr6 = vmx_get_dr6,
-       .set_dr6 = vmx_set_dr6,
        .set_dr7 = vmx_set_dr7,
        .sync_dirty_debug_regs = vmx_sync_dirty_debug_regs,
        .cache_reg = vmx_cache_reg,
        .get_rflags = vmx_get_rflags,
        .set_rflags = vmx_set_rflags,
 
-       .tlb_flush = vmx_flush_tlb,
+       .tlb_flush_all = vmx_flush_tlb_all,
+       .tlb_flush_current = vmx_flush_tlb_current,
        .tlb_flush_gva = vmx_flush_tlb_gva,
+       .tlb_flush_guest = vmx_flush_tlb_guest,
 
        .run = vmx_vcpu_run,
        .handle_exit = vmx_handle_exit,
@@ -7784,6 +7860,7 @@ static struct kvm_x86_ops vmx_x86_ops __initdata = {
        .post_block = vmx_post_block,
 
        .pmu_ops = &intel_pmu_ops,
+       .nested_ops = &vmx_nested_ops,
 
        .update_pi_irte = vmx_update_pi_irte,
 
@@ -7799,12 +7876,6 @@ static struct kvm_x86_ops vmx_x86_ops __initdata = {
        .pre_leave_smm = vmx_pre_leave_smm,
        .enable_smi_window = enable_smi_window,
 
-       .check_nested_events = NULL,
-       .get_nested_state = NULL,
-       .set_nested_state = NULL,
-       .get_vmcs12_pages = NULL,
-       .nested_enable_evmcs = NULL,
-       .nested_get_evmcs_version = NULL,
        .need_emulation_on_page_fault = vmx_need_emulation_on_page_fault,
        .apic_init_signal_blocked = vmx_apic_init_signal_blocked,
 };