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 c4f35b545c1d..dd9bc8fb81ab 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 |
@@ -3747,6 +3748,51 @@ static void kvm_timer_init(void) | |||
3747 | } | 3748 | } |
3748 | } | 3749 | } |
3749 | 3750 | ||
3751 | static DEFINE_PER_CPU(struct kvm_vcpu *, current_vcpu); | ||
3752 | |||
3753 | static int kvm_is_in_guest(void) | ||
3754 | { | ||
3755 | return percpu_read(current_vcpu) != NULL; | ||
3756 | } | ||
3757 | |||
3758 | static int kvm_is_user_mode(void) | ||
3759 | { | ||
3760 | int user_mode = 3; | ||
3761 | |||
3762 | if (percpu_read(current_vcpu)) | ||
3763 | user_mode = kvm_x86_ops->get_cpl(percpu_read(current_vcpu)); | ||
3764 | |||
3765 | return user_mode != 0; | ||
3766 | } | ||
3767 | |||
3768 | static unsigned long kvm_get_guest_ip(void) | ||
3769 | { | ||
3770 | unsigned long ip = 0; | ||
3771 | |||
3772 | if (percpu_read(current_vcpu)) | ||
3773 | ip = kvm_rip_read(percpu_read(current_vcpu)); | ||
3774 | |||
3775 | return ip; | ||
3776 | } | ||
3777 | |||
3778 | static struct perf_guest_info_callbacks kvm_guest_cbs = { | ||
3779 | .is_in_guest = kvm_is_in_guest, | ||
3780 | .is_user_mode = kvm_is_user_mode, | ||
3781 | .get_guest_ip = kvm_get_guest_ip, | ||
3782 | }; | ||
3783 | |||
3784 | void kvm_before_handle_nmi(struct kvm_vcpu *vcpu) | ||
3785 | { | ||
3786 | percpu_write(current_vcpu, vcpu); | ||
3787 | } | ||
3788 | EXPORT_SYMBOL_GPL(kvm_before_handle_nmi); | ||
3789 | |||
3790 | void kvm_after_handle_nmi(struct kvm_vcpu *vcpu) | ||
3791 | { | ||
3792 | percpu_write(current_vcpu, NULL); | ||
3793 | } | ||
3794 | EXPORT_SYMBOL_GPL(kvm_after_handle_nmi); | ||
3795 | |||
3750 | int kvm_arch_init(void *opaque) | 3796 | int kvm_arch_init(void *opaque) |
3751 | { | 3797 | { |
3752 | int r; | 3798 | int r; |
@@ -3783,6 +3829,8 @@ int kvm_arch_init(void *opaque) | |||
3783 | 3829 | ||
3784 | kvm_timer_init(); | 3830 | kvm_timer_init(); |
3785 | 3831 | ||
3832 | perf_register_guest_info_callbacks(&kvm_guest_cbs); | ||
3833 | |||
3786 | return 0; | 3834 | return 0; |
3787 | 3835 | ||
3788 | out: | 3836 | out: |
@@ -3791,6 +3839,8 @@ out: | |||
3791 | 3839 | ||
3792 | void kvm_arch_exit(void) | 3840 | void kvm_arch_exit(void) |
3793 | { | 3841 | { |
3842 | perf_unregister_guest_info_callbacks(&kvm_guest_cbs); | ||
3843 | |||
3794 | if (!boot_cpu_has(X86_FEATURE_CONSTANT_TSC)) | 3844 | if (!boot_cpu_has(X86_FEATURE_CONSTANT_TSC)) |
3795 | cpufreq_unregister_notifier(&kvmclock_cpufreq_notifier_block, | 3845 | cpufreq_unregister_notifier(&kvmclock_cpufreq_notifier_block, |
3796 | CPUFREQ_TRANSITION_NOTIFIER); | 3846 | CPUFREQ_TRANSITION_NOTIFIER); |