]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
KVM: x86: Fix perf timer mode IP reporting
authorAndi Kleen <ak@linux.intel.com>
Wed, 26 Jul 2017 00:20:32 +0000 (17:20 -0700)
committerRadim Krčmář <rkrcmar@redhat.com>
Wed, 28 Mar 2018 14:12:59 +0000 (16:12 +0200)
KVM and perf have a special backdoor mechanism to report the IP for interrupts
re-executed after vm exit. This works for the NMIs that perf normally uses.

However when perf is in timer mode it doesn't work because the timer interrupt
doesn't get this special treatment. This is common when KVM is running
nested in another hypervisor which may not implement the PMU, so only
timer mode is available.

Call the functions to set up the backdoor IP also for non NMI interrupts.

I renamed the functions to set up the backdoor IP reporting to be more
appropiate for their new use.  The SVM change is only compile tested.

v2: Moved the functions inline.
For the normal interrupt case the before/after functions are now
called from x86.c, not arch specific code.
For the NMI case we still need to call it in the architecture
specific code, because it's already needed in the low level *_run
functions.

Signed-off-by: Andi Kleen <ak@linux.intel.com>
[Removed unnecessary calls from arch handle_external_intr. - Radim]
Signed-off-by: Radim Krčmář <rkrcmar@redhat.com>
arch/x86/kvm/svm.c
arch/x86/kvm/vmx.c
arch/x86/kvm/x86.c
arch/x86/kvm/x86.h

index cb46e985e29a2eb42746fb50d94efc551851314e..2d175c36ffa26b1527866bcf56696315addbbdd1 100644 (file)
@@ -5599,14 +5599,14 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu)
        vcpu->arch.regs[VCPU_REGS_RIP] = svm->vmcb->save.rip;
 
        if (unlikely(svm->vmcb->control.exit_code == SVM_EXIT_NMI))
-               kvm_before_handle_nmi(&svm->vcpu);
+               kvm_before_interrupt(&svm->vcpu);
 
        stgi();
 
        /* Any pending NMI will happen here */
 
        if (unlikely(svm->vmcb->control.exit_code == SVM_EXIT_NMI))
-               kvm_after_handle_nmi(&svm->vcpu);
+               kvm_after_interrupt(&svm->vcpu);
 
        sync_cr8_to_lapic(vcpu);
 
index 9bc05f5349c8d10e2804e7b0f39e3e39fb7c0c6f..0e5510ebd3f25325fddb92b3272533d8aef3e632 100644 (file)
@@ -9292,9 +9292,9 @@ static void vmx_complete_atomic_exit(struct vcpu_vmx *vmx)
 
        /* We need to handle NMIs before interrupts are enabled */
        if (is_nmi(exit_intr_info)) {
-               kvm_before_handle_nmi(&vmx->vcpu);
+               kvm_before_interrupt(&vmx->vcpu);
                asm("int $2");
-               kvm_after_handle_nmi(&vmx->vcpu);
+               kvm_after_interrupt(&vmx->vcpu);
        }
 }
 
index 1583bdce0e5bcc081c4b30572c7af5d3e2f9c3e8..bf89876e620b63d2a531d258933a9dbb4bb91e6f 100644 (file)
@@ -6370,7 +6370,8 @@ static void kvm_timer_init(void)
                          kvmclock_cpu_online, kvmclock_cpu_down_prep);
 }
 
-static DEFINE_PER_CPU(struct kvm_vcpu *, current_vcpu);
+DEFINE_PER_CPU(struct kvm_vcpu *, current_vcpu);
+EXPORT_PER_CPU_SYMBOL_GPL(current_vcpu);
 
 int kvm_is_in_guest(void)
 {
@@ -6403,18 +6404,6 @@ static struct perf_guest_info_callbacks kvm_guest_cbs = {
        .get_guest_ip           = kvm_get_guest_ip,
 };
 
-void kvm_before_handle_nmi(struct kvm_vcpu *vcpu)
-{
-       __this_cpu_write(current_vcpu, vcpu);
-}
-EXPORT_SYMBOL_GPL(kvm_before_handle_nmi);
-
-void kvm_after_handle_nmi(struct kvm_vcpu *vcpu)
-{
-       __this_cpu_write(current_vcpu, NULL);
-}
-EXPORT_SYMBOL_GPL(kvm_after_handle_nmi);
-
 static void kvm_set_mmio_spte_mask(void)
 {
        u64 mask;
@@ -7429,7 +7418,9 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
 
        kvm_put_guest_xcr0(vcpu);
 
+       kvm_before_interrupt(vcpu);
        kvm_x86_ops->handle_external_intr(vcpu);
+       kvm_after_interrupt(vcpu);
 
        ++vcpu->stat.exits;
 
index b620cfa8e8d5ccdaf57c4e3cdc96d6b2c088f8e7..35efd567a6765f6079ee06f9f9083460381a5b01 100644 (file)
@@ -203,8 +203,6 @@ static inline bool kvm_check_has_quirk(struct kvm *kvm, u64 quirk)
        return !(kvm->arch.disabled_quirks & quirk);
 }
 
-void kvm_before_handle_nmi(struct kvm_vcpu *vcpu);
-void kvm_after_handle_nmi(struct kvm_vcpu *vcpu);
 void kvm_set_pending_timer(struct kvm_vcpu *vcpu);
 int kvm_inject_realmode_interrupt(struct kvm_vcpu *vcpu, int irq, int inc_eip);
 
@@ -286,4 +284,16 @@ static inline bool kvm_pause_in_guest(struct kvm *kvm)
        return kvm->arch.pause_in_guest;
 }
 
+DECLARE_PER_CPU(struct kvm_vcpu *, current_vcpu);
+
+static inline void kvm_before_interrupt(struct kvm_vcpu *vcpu)
+{
+       __this_cpu_write(current_vcpu, vcpu);
+}
+
+static inline void kvm_after_interrupt(struct kvm_vcpu *vcpu)
+{
+       __this_cpu_write(current_vcpu, NULL);
+}
+
 #endif