Merge branch 'kvm-amd-fixes' into HEAD
[linux-block.git] / arch / x86 / kvm / svm / svm.c
index a862c768fd542695614d335b033dd18d1c3f86f9..b627564e41f9e6595c68592d9311b2d59bb116f3 100644 (file)
@@ -33,6 +33,7 @@
 #include <asm/debugreg.h>
 #include <asm/kvm_para.h>
 #include <asm/irq_remapping.h>
+#include <asm/mce.h>
 #include <asm/spec-ctrl.h>
 #include <asm/cpu_device_id.h>
 
@@ -1603,7 +1604,7 @@ int svm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
                return 1;
 
        if (npt_enabled && ((old_cr4 ^ cr4) & X86_CR4_PGE))
-               svm_flush_tlb(vcpu, true);
+               svm_flush_tlb(vcpu);
 
        vcpu->arch.cr4 = cr4;
        if (!npt_enabled)
@@ -1842,6 +1843,25 @@ static bool is_erratum_383(void)
        return true;
 }
 
+/*
+ * Trigger machine check on the host. We assume all the MSRs are already set up
+ * by the CPU and that we still run on the same CPU as the MCE occurred on.
+ * We pass a fake environment to the machine check handler because we want
+ * the guest to be always treated like user space, no matter what context
+ * it used internally.
+ */
+static void kvm_machine_check(void)
+{
+#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,
+       };
+
+       do_machine_check(&regs, 0);
+#endif
+}
+
 static void svm_handle_mce(struct vcpu_svm *svm)
 {
        if (is_erratum_383()) {
@@ -1860,11 +1880,7 @@ static void svm_handle_mce(struct vcpu_svm *svm)
         * On an #MC intercept the MCE handler is not called automatically in
         * the host. So do it by hand here.
         */
-       asm volatile (
-               "int $0x12\n");
-       /* not sure if we ever come back to this point */
-
-       return;
+       kvm_machine_check();
 }
 
 static int mc_interception(struct vcpu_svm *svm)
@@ -3156,10 +3172,17 @@ static int svm_set_identity_map_addr(struct kvm *kvm, u64 ident_addr)
        return 0;
 }
 
-void svm_flush_tlb(struct kvm_vcpu *vcpu, bool invalidate_gpa)
+void svm_flush_tlb(struct kvm_vcpu *vcpu)
 {
        struct vcpu_svm *svm = to_svm(vcpu);
 
+       /*
+        * Flush only the current ASID even if the TLB flush was invoked via
+        * kvm_flush_remote_tlbs().  Although flushing remote TLBs requires all
+        * ASIDs to be flushed, KVM uses a single ASID for L1 and L2, and
+        * unconditionally does a TLB flush on both nested VM-Enter and nested
+        * VM-Exit (via kvm_mmu_reset_context()).
+        */
        if (static_cpu_has(X86_FEATURE_FLUSHBYASID))
                svm->vmcb->control.tlb_ctl = TLB_CONTROL_FLUSH_ASID;
        else
@@ -3279,10 +3302,21 @@ static void svm_cancel_injection(struct kvm_vcpu *vcpu)
        svm_complete_interrupts(svm);
 }
 
+static enum exit_fastpath_completion svm_exit_handlers_fastpath(struct kvm_vcpu *vcpu)
+{
+       if (!is_guest_mode(vcpu) &&
+           to_svm(vcpu)->vmcb->control.exit_code == SVM_EXIT_MSR &&
+           to_svm(vcpu)->vmcb->control.exit_info_1)
+               return handle_fastpath_set_msr_irqoff(vcpu);
+
+       return EXIT_FASTPATH_NONE;
+}
+
 void __svm_vcpu_run(unsigned long vmcb_pa, unsigned long *regs);
 
-static void svm_vcpu_run(struct kvm_vcpu *vcpu)
+static enum exit_fastpath_completion svm_vcpu_run(struct kvm_vcpu *vcpu)
 {
+       enum exit_fastpath_completion exit_fastpath;
        struct vcpu_svm *svm = to_svm(vcpu);
 
        svm->vmcb->save.rax = vcpu->arch.regs[VCPU_REGS_RAX];
@@ -3294,7 +3328,7 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu)
         * again.
         */
        if (unlikely(svm->nested.exit_required))
-               return;
+               return EXIT_FASTPATH_NONE;
 
        /*
         * Disable singlestep if we're injecting an interrupt/exception.
@@ -3387,6 +3421,7 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu)
        stgi();
 
        /* Any pending NMI will happen here */
+       exit_fastpath = svm_exit_handlers_fastpath(vcpu);
 
        if (unlikely(svm->vmcb->control.exit_code == SVM_EXIT_NMI))
                kvm_after_interrupt(&svm->vcpu);
@@ -3415,6 +3450,7 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu)
                svm_handle_mce(svm);
 
        mark_all_clean(svm->vmcb);
+       return exit_fastpath;
 }
 
 static void svm_load_mmu_pgd(struct kvm_vcpu *vcpu, unsigned long root)
@@ -3716,13 +3752,8 @@ out:
        return ret;
 }
 
-static void svm_handle_exit_irqoff(struct kvm_vcpu *vcpu,
-       enum exit_fastpath_completion *exit_fastpath)
+static void svm_handle_exit_irqoff(struct kvm_vcpu *vcpu)
 {
-       if (!is_guest_mode(vcpu) &&
-           to_svm(vcpu)->vmcb->control.exit_code == SVM_EXIT_MSR &&
-           to_svm(vcpu)->vmcb->control.exit_info_1)
-               *exit_fastpath = handle_fastpath_set_msr_irqoff(vcpu);
 }
 
 static void svm_sched_in(struct kvm_vcpu *vcpu, int cpu)
@@ -3818,6 +3849,13 @@ static bool svm_need_emulation_on_page_fault(struct kvm_vcpu *vcpu)
        bool smap = cr4 & X86_CR4_SMAP;
        bool is_user = svm_get_cpl(vcpu) == 3;
 
+       /*
+        * If RIP is invalid, go ahead with emulation which will cause an
+        * internal error exit.
+        */
+       if (!kvm_vcpu_gfn_to_memslot(vcpu, kvm_rip_read(vcpu) >> PAGE_SHIFT))
+               return true;
+
        /*
         * Detect and workaround Errata 1096 Fam_17h_00_0Fh.
         *
@@ -3876,9 +3914,9 @@ static bool svm_apic_init_signal_blocked(struct kvm_vcpu *vcpu)
        /*
         * TODO: Last condition latch INIT signals on vCPU when
         * vCPU is in guest-mode and vmcb12 defines intercept on INIT.
-        * To properly emulate the INIT intercept, SVM should implement
-        * kvm_x86_ops.check_nested_events() and call nested_svm_vmexit()
-        * there if an INIT signal is pending.
+        * To properly emulate the INIT intercept,
+        * svm_check_nested_events() should call nested_svm_vmexit()
+        * if an INIT signal is pending.
         */
        return !gif_set(svm) ||
                   (svm->vmcb->control.intercept & (1ULL << INTERCEPT_INIT));
@@ -3947,8 +3985,10 @@ static struct kvm_x86_ops svm_x86_ops __initdata = {
        .get_rflags = svm_get_rflags,
        .set_rflags = svm_set_rflags,
 
-       .tlb_flush = svm_flush_tlb,
+       .tlb_flush_all = svm_flush_tlb,
+       .tlb_flush_current = svm_flush_tlb,
        .tlb_flush_gva = svm_flush_tlb_gva,
+       .tlb_flush_guest = svm_flush_tlb,
 
        .run = svm_vcpu_run,
        .handle_exit = handle_exit,
@@ -4002,6 +4042,8 @@ static struct kvm_x86_ops svm_x86_ops __initdata = {
        .sched_in = svm_sched_in,
 
        .pmu_ops = &amd_pmu_ops,
+       .nested_ops = &svm_nested_ops,
+
        .deliver_posted_interrupt = svm_deliver_avic_intr,
        .dy_apicv_has_pending_interrupt = svm_dy_apicv_has_pending_interrupt,
        .update_pi_irte = svm_update_pi_irte,
@@ -4016,14 +4058,9 @@ static struct kvm_x86_ops svm_x86_ops __initdata = {
        .mem_enc_reg_region = svm_register_enc_region,
        .mem_enc_unreg_region = svm_unregister_enc_region,
 
-       .nested_enable_evmcs = NULL,
-       .nested_get_evmcs_version = NULL,
-
        .need_emulation_on_page_fault = svm_need_emulation_on_page_fault,
 
        .apic_init_signal_blocked = svm_apic_init_signal_blocked,
-
-       .check_nested_events = svm_check_nested_events,
 };
 
 static struct kvm_x86_init_ops svm_init_ops __initdata = {