diff options
Diffstat (limited to 'arch/x86/kvm/x86.c')
-rw-r--r-- | arch/x86/kvm/x86.c | 50 |
1 files changed, 50 insertions, 0 deletions
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 3c4ca98ad27f..73d854c36e39 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 |
@@ -3743,6 +3744,51 @@ static void kvm_timer_init(void) | |||
3743 | } | 3744 | } |
3744 | } | 3745 | } |
3745 | 3746 | ||
3747 | static DEFINE_PER_CPU(struct kvm_vcpu *, current_vcpu); | ||
3748 | |||
3749 | static int kvm_is_in_guest(void) | ||
3750 | { | ||
3751 | return percpu_read(current_vcpu) != NULL; | ||
3752 | } | ||
3753 | |||
3754 | static int kvm_is_user_mode(void) | ||
3755 | { | ||
3756 | int user_mode = 3; | ||
3757 | |||
3758 | if (percpu_read(current_vcpu)) | ||
3759 | user_mode = kvm_x86_ops->get_cpl(percpu_read(current_vcpu)); | ||
3760 | |||
3761 | return user_mode != 0; | ||
3762 | } | ||
3763 | |||
3764 | static unsigned long kvm_get_guest_ip(void) | ||
3765 | { | ||
3766 | unsigned long ip = 0; | ||
3767 | |||
3768 | if (percpu_read(current_vcpu)) | ||
3769 | ip = kvm_rip_read(percpu_read(current_vcpu)); | ||
3770 | |||
3771 | return ip; | ||
3772 | } | ||
3773 | |||
3774 | static struct perf_guest_info_callbacks kvm_guest_cbs = { | ||
3775 | .is_in_guest = kvm_is_in_guest, | ||
3776 | .is_user_mode = kvm_is_user_mode, | ||
3777 | .get_guest_ip = kvm_get_guest_ip, | ||
3778 | }; | ||
3779 | |||
3780 | void kvm_before_handle_nmi(struct kvm_vcpu *vcpu) | ||
3781 | { | ||
3782 | percpu_write(current_vcpu, vcpu); | ||
3783 | } | ||
3784 | EXPORT_SYMBOL_GPL(kvm_before_handle_nmi); | ||
3785 | |||
3786 | void kvm_after_handle_nmi(struct kvm_vcpu *vcpu) | ||
3787 | { | ||
3788 | percpu_write(current_vcpu, NULL); | ||
3789 | } | ||
3790 | EXPORT_SYMBOL_GPL(kvm_after_handle_nmi); | ||
3791 | |||
3746 | int kvm_arch_init(void *opaque) | 3792 | int kvm_arch_init(void *opaque) |
3747 | { | 3793 | { |
3748 | int r; | 3794 | int r; |
@@ -3779,6 +3825,8 @@ int kvm_arch_init(void *opaque) | |||
3779 | 3825 | ||
3780 | kvm_timer_init(); | 3826 | kvm_timer_init(); |
3781 | 3827 | ||
3828 | perf_register_guest_info_callbacks(&kvm_guest_cbs); | ||
3829 | |||
3782 | return 0; | 3830 | return 0; |
3783 | 3831 | ||
3784 | out: | 3832 | out: |
@@ -3787,6 +3835,8 @@ out: | |||
3787 | 3835 | ||
3788 | void kvm_arch_exit(void) | 3836 | void kvm_arch_exit(void) |
3789 | { | 3837 | { |
3838 | perf_unregister_guest_info_callbacks(&kvm_guest_cbs); | ||
3839 | |||
3790 | if (!boot_cpu_has(X86_FEATURE_CONSTANT_TSC)) | 3840 | if (!boot_cpu_has(X86_FEATURE_CONSTANT_TSC)) |
3791 | cpufreq_unregister_notifier(&kvmclock_cpufreq_notifier_block, | 3841 | cpufreq_unregister_notifier(&kvmclock_cpufreq_notifier_block, |
3792 | CPUFREQ_TRANSITION_NOTIFIER); | 3842 | CPUFREQ_TRANSITION_NOTIFIER); |