OSDN Git Service

KVM: X86: support paravirtualized help for TLB shootdowns
authorWanpeng Li <wanpeng.li@hotmail.com>
Wed, 13 Dec 2017 01:33:04 +0000 (17:33 -0800)
committerRadim Krčmář <rkrcmar@redhat.com>
Tue, 16 Jan 2018 15:34:13 +0000 (16:34 +0100)
When running on a virtual machine, IPIs are expensive when the target
CPU is sleeping.  Thus, it is nice to be able to avoid them for TLB
shootdowns.  KVM can just do the flush via INVVPID on the guest's behalf
the next time the CPU is scheduled.

Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Radim Krčmář <rkrcmar@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Signed-off-by: Wanpeng Li <wanpeng.li@hotmail.com>
[Use "&" to test the bit instead of "==". - Paolo]
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Radim Krčmář <rkrcmar@redhat.com>
arch/x86/kvm/cpuid.c
arch/x86/kvm/x86.c

index 3db9e1c..a0e6c97 100644 (file)
@@ -602,7 +602,8 @@ static inline int __do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
                             (1 << KVM_FEATURE_ASYNC_PF) |
                             (1 << KVM_FEATURE_PV_EOI) |
                             (1 << KVM_FEATURE_CLOCKSOURCE_STABLE_BIT) |
-                            (1 << KVM_FEATURE_PV_UNHALT);
+                            (1 << KVM_FEATURE_PV_UNHALT) |
+                            (1 << KVM_FEATURE_PV_TLB_FLUSH);
 
                if (sched_info_on())
                        entry->eax |= (1 << KVM_FEATURE_STEAL_TIME);
index 1e6d9f2..35d0b3d 100644 (file)
@@ -2122,6 +2122,12 @@ static void kvmclock_reset(struct kvm_vcpu *vcpu)
        vcpu->arch.pv_time_enabled = false;
 }
 
+static void kvm_vcpu_flush_tlb(struct kvm_vcpu *vcpu, bool invalidate_gpa)
+{
+       ++vcpu->stat.tlb_flush;
+       kvm_x86_ops->tlb_flush(vcpu, invalidate_gpa);
+}
+
 static void record_steal_time(struct kvm_vcpu *vcpu)
 {
        if (!(vcpu->arch.st.msr_val & KVM_MSR_ENABLED))
@@ -2131,7 +2137,12 @@ static void record_steal_time(struct kvm_vcpu *vcpu)
                &vcpu->arch.st.steal, sizeof(struct kvm_steal_time))))
                return;
 
-       vcpu->arch.st.steal.preempted = 0;
+       /*
+        * Doing a TLB flush here, on the guest's behalf, can avoid
+        * expensive IPIs.
+        */
+       if (xchg(&vcpu->arch.st.steal.preempted, 0) & KVM_VCPU_FLUSH_TLB)
+               kvm_vcpu_flush_tlb(vcpu, false);
 
        if (vcpu->arch.st.steal.version & 1)
                vcpu->arch.st.steal.version += 1;  /* first time write, random junk */
@@ -6781,12 +6792,6 @@ static void vcpu_scan_ioapic(struct kvm_vcpu *vcpu)
        kvm_x86_ops->load_eoi_exitmap(vcpu, eoi_exit_bitmap);
 }
 
-static void kvm_vcpu_flush_tlb(struct kvm_vcpu *vcpu, bool invalidate_gpa)
-{
-       ++vcpu->stat.tlb_flush;
-       kvm_x86_ops->tlb_flush(vcpu, invalidate_gpa);
-}
-
 void kvm_arch_mmu_notifier_invalidate_range(struct kvm *kvm,
                unsigned long start, unsigned long end)
 {