diff options
Diffstat (limited to 'arch/x86/kvm/x86.c')
-rw-r--r-- | arch/x86/kvm/x86.c | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 3c4ca98ad27f..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 |
@@ -1712,6 +1713,7 @@ static int kvm_vcpu_ioctl_set_cpuid(struct kvm_vcpu *vcpu, | |||
1712 | if (copy_from_user(cpuid_entries, entries, | 1713 | if (copy_from_user(cpuid_entries, entries, |
1713 | cpuid->nent * sizeof(struct kvm_cpuid_entry))) | 1714 | cpuid->nent * sizeof(struct kvm_cpuid_entry))) |
1714 | goto out_free; | 1715 | goto out_free; |
1716 | vcpu_load(vcpu); | ||
1715 | for (i = 0; i < cpuid->nent; i++) { | 1717 | for (i = 0; i < cpuid->nent; i++) { |
1716 | vcpu->arch.cpuid_entries[i].function = cpuid_entries[i].function; | 1718 | vcpu->arch.cpuid_entries[i].function = cpuid_entries[i].function; |
1717 | vcpu->arch.cpuid_entries[i].eax = cpuid_entries[i].eax; | 1719 | vcpu->arch.cpuid_entries[i].eax = cpuid_entries[i].eax; |
@@ -1729,6 +1731,7 @@ static int kvm_vcpu_ioctl_set_cpuid(struct kvm_vcpu *vcpu, | |||
1729 | r = 0; | 1731 | r = 0; |
1730 | kvm_apic_set_version(vcpu); | 1732 | kvm_apic_set_version(vcpu); |
1731 | kvm_x86_ops->cpuid_update(vcpu); | 1733 | kvm_x86_ops->cpuid_update(vcpu); |
1734 | vcpu_put(vcpu); | ||
1732 | 1735 | ||
1733 | out_free: | 1736 | out_free: |
1734 | vfree(cpuid_entries); | 1737 | vfree(cpuid_entries); |
@@ -1749,9 +1752,11 @@ static int kvm_vcpu_ioctl_set_cpuid2(struct kvm_vcpu *vcpu, | |||
1749 | if (copy_from_user(&vcpu->arch.cpuid_entries, entries, | 1752 | if (copy_from_user(&vcpu->arch.cpuid_entries, entries, |
1750 | cpuid->nent * sizeof(struct kvm_cpuid_entry2))) | 1753 | cpuid->nent * sizeof(struct kvm_cpuid_entry2))) |
1751 | goto out; | 1754 | goto out; |
1755 | vcpu_load(vcpu); | ||
1752 | vcpu->arch.cpuid_nent = cpuid->nent; | 1756 | vcpu->arch.cpuid_nent = cpuid->nent; |
1753 | kvm_apic_set_version(vcpu); | 1757 | kvm_apic_set_version(vcpu); |
1754 | kvm_x86_ops->cpuid_update(vcpu); | 1758 | kvm_x86_ops->cpuid_update(vcpu); |
1759 | vcpu_put(vcpu); | ||
1755 | return 0; | 1760 | return 0; |
1756 | 1761 | ||
1757 | out: | 1762 | out: |
@@ -3743,6 +3748,51 @@ static void kvm_timer_init(void) | |||
3743 | } | 3748 | } |
3744 | } | 3749 | } |
3745 | 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 | |||
3746 | int kvm_arch_init(void *opaque) | 3796 | int kvm_arch_init(void *opaque) |
3747 | { | 3797 | { |
3748 | int r; | 3798 | int r; |
@@ -3779,6 +3829,8 @@ int kvm_arch_init(void *opaque) | |||
3779 | 3829 | ||
3780 | kvm_timer_init(); | 3830 | kvm_timer_init(); |
3781 | 3831 | ||
3832 | perf_register_guest_info_callbacks(&kvm_guest_cbs); | ||
3833 | |||
3782 | return 0; | 3834 | return 0; |
3783 | 3835 | ||
3784 | out: | 3836 | out: |
@@ -3787,6 +3839,8 @@ out: | |||
3787 | 3839 | ||
3788 | void kvm_arch_exit(void) | 3840 | void kvm_arch_exit(void) |
3789 | { | 3841 | { |
3842 | perf_unregister_guest_info_callbacks(&kvm_guest_cbs); | ||
3843 | |||
3790 | if (!boot_cpu_has(X86_FEATURE_CONSTANT_TSC)) | 3844 | if (!boot_cpu_has(X86_FEATURE_CONSTANT_TSC)) |
3791 | cpufreq_unregister_notifier(&kvmclock_cpufreq_notifier_block, | 3845 | cpufreq_unregister_notifier(&kvmclock_cpufreq_notifier_block, |
3792 | CPUFREQ_TRANSITION_NOTIFIER); | 3846 | CPUFREQ_TRANSITION_NOTIFIER); |