Merge tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm
[linux-2.6-microblaze.git] / virt / kvm / kvm_main.c
index 2755ba4..58d31da 100644 (file)
@@ -5600,6 +5600,50 @@ struct kvm_vcpu * __percpu *kvm_get_running_vcpus(void)
         return &kvm_running_vcpu;
 }
 
+#ifdef CONFIG_GUEST_PERF_EVENTS
+static unsigned int kvm_guest_state(void)
+{
+       struct kvm_vcpu *vcpu = kvm_get_running_vcpu();
+       unsigned int state;
+
+       if (!kvm_arch_pmi_in_guest(vcpu))
+               return 0;
+
+       state = PERF_GUEST_ACTIVE;
+       if (!kvm_arch_vcpu_in_kernel(vcpu))
+               state |= PERF_GUEST_USER;
+
+       return state;
+}
+
+static unsigned long kvm_guest_get_ip(void)
+{
+       struct kvm_vcpu *vcpu = kvm_get_running_vcpu();
+
+       /* Retrieving the IP must be guarded by a call to kvm_guest_state(). */
+       if (WARN_ON_ONCE(!kvm_arch_pmi_in_guest(vcpu)))
+               return 0;
+
+       return kvm_arch_vcpu_get_ip(vcpu);
+}
+
+static struct perf_guest_info_callbacks kvm_guest_cbs = {
+       .state                  = kvm_guest_state,
+       .get_ip                 = kvm_guest_get_ip,
+       .handle_intel_pt_intr   = NULL,
+};
+
+void kvm_register_perf_callbacks(unsigned int (*pt_intr_handler)(void))
+{
+       kvm_guest_cbs.handle_intel_pt_intr = pt_intr_handler;
+       perf_register_guest_info_callbacks(&kvm_guest_cbs);
+}
+void kvm_unregister_perf_callbacks(void)
+{
+       perf_unregister_guest_info_callbacks(&kvm_guest_cbs);
+}
+#endif
+
 struct kvm_cpu_compat_check {
        void *opaque;
        int *ret;