KVM: x86: Inject PMI for KVM guest
authorLuwei Kang <luwei.kang@intel.com>
Tue, 19 Feb 2019 00:26:07 +0000 (19:26 -0500)
committerPaolo Bonzini <pbonzini@redhat.com>
Tue, 30 Apr 2019 19:32:13 +0000 (21:32 +0200)
Inject a PMI for KVM guest when Intel PT working
in Host-Guest mode and Guest ToPA entry memory buffer
was completely filled.

Signed-off-by: Luwei Kang <luwei.kang@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
arch/x86/events/intel/core.c
arch/x86/include/asm/msr-index.h
arch/x86/kvm/x86.c
include/linux/perf_event.h

index 8baa441..386151b 100644 (file)
@@ -2307,7 +2307,11 @@ static int handle_pmi_common(struct pt_regs *regs, u64 status)
         */
        if (__test_and_clear_bit(55, (unsigned long *)&status)) {
                handled++;
-               intel_pt_interrupt();
+               if (unlikely(perf_guest_cbs && perf_guest_cbs->is_in_guest() &&
+                       perf_guest_cbs->handle_intel_pt_intr))
+                       perf_guest_cbs->handle_intel_pt_intr();
+               else
+                       intel_pt_interrupt();
        }
 
        /*
index ca5bc0e..be40c09 100644 (file)
 #define MSR_CORE_PERF_GLOBAL_CTRL      0x0000038f
 #define MSR_CORE_PERF_GLOBAL_OVF_CTRL  0x00000390
 
+/* PERF_GLOBAL_OVF_CTL bits */
+#define MSR_CORE_PERF_GLOBAL_OVF_CTRL_TRACE_TOPA_PMI_BIT       55
+#define MSR_CORE_PERF_GLOBAL_OVF_CTRL_TRACE_TOPA_PMI           (1ULL << MSR_CORE_PERF_GLOBAL_OVF_CTRL_TRACE_TOPA_PMI_BIT)
+
 /* Geode defined MSRs */
 #define MSR_GEODE_BUSCONT_CONF0                0x00001900
 
index 6c27d22..cedd396 100644 (file)
@@ -6839,10 +6839,20 @@ static unsigned long kvm_get_guest_ip(void)
        return ip;
 }
 
+static void kvm_handle_intel_pt_intr(void)
+{
+       struct kvm_vcpu *vcpu = __this_cpu_read(current_vcpu);
+
+       kvm_make_request(KVM_REQ_PMI, vcpu);
+       __set_bit(MSR_CORE_PERF_GLOBAL_OVF_CTRL_TRACE_TOPA_PMI_BIT,
+                       (unsigned long *)&vcpu->arch.pmu.global_status);
+}
+
 static struct perf_guest_info_callbacks kvm_guest_cbs = {
        .is_in_guest            = kvm_is_in_guest,
        .is_user_mode           = kvm_is_user_mode,
        .get_guest_ip           = kvm_get_guest_ip,
+       .handle_intel_pt_intr   = kvm_handle_intel_pt_intr,
 };
 
 static void kvm_set_mmio_spte_mask(void)
index e47ef76..820c4ff 100644 (file)
@@ -30,6 +30,7 @@ struct perf_guest_info_callbacks {
        int                             (*is_in_guest)(void);
        int                             (*is_user_mode)(void);
        unsigned long                   (*get_guest_ip)(void);
+       void                            (*handle_intel_pt_intr)(void);
 };
 
 #ifdef CONFIG_HAVE_HW_BREAKPOINT