diff options
author | Zhang, Yanmin <yanmin_zhang@linux.intel.com> | 2010-04-19 01:32:45 -0400 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2010-04-19 05:36:50 -0400 |
commit | ff9d07a0e7ce756a183e7c2e483aec452ee6b574 (patch) | |
tree | c355079734dc14700228f78fdd8ad824c0f80db0 /arch/x86/kvm/x86.c | |
parent | 39447b386c846bbf1c56f6403c5282837486200f (diff) |
KVM: Implement perf callbacks for guest sampling
Below patch implements the perf_guest_info_callbacks on kvm.
Signed-off-by: Zhang Yanmin <yanmin_zhang@linux.intel.com>
Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch/x86/kvm/x86.c')
-rw-r--r-- | arch/x86/kvm/x86.c | 46 |
1 files changed, 46 insertions, 0 deletions
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 24cd0ee896e9..c3a33b2bb169 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c | |||
@@ -40,6 +40,7 @@ | |||
40 | #include <linux/user-return-notifier.h> | 40 | #include <linux/user-return-notifier.h> |
41 | #include <linux/srcu.h> | 41 | #include <linux/srcu.h> |
42 | #include <linux/slab.h> | 42 | #include <linux/slab.h> |
43 | #include <linux/perf_event.h> | ||
43 | #include <trace/events/kvm.h> | 44 | #include <trace/events/kvm.h> |
44 | #undef TRACE_INCLUDE_FILE | 45 | #undef TRACE_INCLUDE_FILE |
45 | #define CREATE_TRACE_POINTS | 46 | #define CREATE_TRACE_POINTS |
@@ -3765,6 +3766,47 @@ static void kvm_timer_init(void) | |||
3765 | } | 3766 | } |
3766 | } | 3767 | } |
3767 | 3768 | ||
3769 | static DEFINE_PER_CPU(struct kvm_vcpu *, current_vcpu); | ||
3770 | |||
3771 | static int kvm_is_in_guest(void) | ||
3772 | { | ||
3773 | return percpu_read(current_vcpu) != NULL; | ||
3774 | } | ||
3775 | |||
3776 | static int kvm_is_user_mode(void) | ||
3777 | { | ||
3778 | int user_mode = 3; | ||
3779 | if (percpu_read(current_vcpu)) | ||
3780 | user_mode = kvm_x86_ops->get_cpl(percpu_read(current_vcpu)); | ||
3781 | return user_mode != 0; | ||
3782 | } | ||
3783 | |||
3784 | static unsigned long kvm_get_guest_ip(void) | ||
3785 | { | ||
3786 | unsigned long ip = 0; | ||
3787 | if (percpu_read(current_vcpu)) | ||
3788 | ip = kvm_rip_read(percpu_read(current_vcpu)); | ||
3789 | return ip; | ||
3790 | } | ||
3791 | |||
3792 | static struct perf_guest_info_callbacks kvm_guest_cbs = { | ||
3793 | .is_in_guest = kvm_is_in_guest, | ||
3794 | .is_user_mode = kvm_is_user_mode, | ||
3795 | .get_guest_ip = kvm_get_guest_ip, | ||
3796 | }; | ||
3797 | |||
3798 | void kvm_before_handle_nmi(struct kvm_vcpu *vcpu) | ||
3799 | { | ||
3800 | percpu_write(current_vcpu, vcpu); | ||
3801 | } | ||
3802 | EXPORT_SYMBOL_GPL(kvm_before_handle_nmi); | ||
3803 | |||
3804 | void kvm_after_handle_nmi(struct kvm_vcpu *vcpu) | ||
3805 | { | ||
3806 | percpu_write(current_vcpu, NULL); | ||
3807 | } | ||
3808 | EXPORT_SYMBOL_GPL(kvm_after_handle_nmi); | ||
3809 | |||
3768 | int kvm_arch_init(void *opaque) | 3810 | int kvm_arch_init(void *opaque) |
3769 | { | 3811 | { |
3770 | int r; | 3812 | int r; |
@@ -3801,6 +3843,8 @@ int kvm_arch_init(void *opaque) | |||
3801 | 3843 | ||
3802 | kvm_timer_init(); | 3844 | kvm_timer_init(); |
3803 | 3845 | ||
3846 | perf_register_guest_info_callbacks(&kvm_guest_cbs); | ||
3847 | |||
3804 | return 0; | 3848 | return 0; |
3805 | 3849 | ||
3806 | out: | 3850 | out: |
@@ -3809,6 +3853,8 @@ out: | |||
3809 | 3853 | ||
3810 | void kvm_arch_exit(void) | 3854 | void kvm_arch_exit(void) |
3811 | { | 3855 | { |
3856 | perf_unregister_guest_info_callbacks(&kvm_guest_cbs); | ||
3857 | |||
3812 | if (!boot_cpu_has(X86_FEATURE_CONSTANT_TSC)) | 3858 | if (!boot_cpu_has(X86_FEATURE_CONSTANT_TSC)) |
3813 | cpufreq_unregister_notifier(&kvmclock_cpufreq_notifier_block, | 3859 | cpufreq_unregister_notifier(&kvmclock_cpufreq_notifier_block, |
3814 | CPUFREQ_TRANSITION_NOTIFIER); | 3860 | CPUFREQ_TRANSITION_NOTIFIER); |