diff options
-rw-r--r-- | arch/x86/kvm/vmx.c | 5 | ||||
-rw-r--r-- | arch/x86/kvm/x86.c | 46 | ||||
-rw-r--r-- | arch/x86/kvm/x86.h | 3 |
3 files changed, 53 insertions, 1 deletions
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 686492ed3079..82be6dac3d25 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c | |||
@@ -3654,8 +3654,11 @@ static void vmx_complete_interrupts(struct vcpu_vmx *vmx) | |||
3654 | 3654 | ||
3655 | /* We need to handle NMIs before interrupts are enabled */ | 3655 | /* We need to handle NMIs before interrupts are enabled */ |
3656 | if ((exit_intr_info & INTR_INFO_INTR_TYPE_MASK) == INTR_TYPE_NMI_INTR && | 3656 | if ((exit_intr_info & INTR_INFO_INTR_TYPE_MASK) == INTR_TYPE_NMI_INTR && |
3657 | (exit_intr_info & INTR_INFO_VALID_MASK)) | 3657 | (exit_intr_info & INTR_INFO_VALID_MASK)) { |
3658 | kvm_before_handle_nmi(&vmx->vcpu); | ||
3658 | asm("int $2"); | 3659 | asm("int $2"); |
3660 | kvm_after_handle_nmi(&vmx->vcpu); | ||
3661 | } | ||
3659 | 3662 | ||
3660 | idtv_info_valid = idt_vectoring_info & VECTORING_INFO_VALID_MASK; | 3663 | idtv_info_valid = idt_vectoring_info & VECTORING_INFO_VALID_MASK; |
3661 | 3664 | ||
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); |
diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h index 2d101639bd8d..b7a404722d2b 100644 --- a/arch/x86/kvm/x86.h +++ b/arch/x86/kvm/x86.h | |||
@@ -65,4 +65,7 @@ static inline int is_paging(struct kvm_vcpu *vcpu) | |||
65 | return kvm_read_cr0_bits(vcpu, X86_CR0_PG); | 65 | return kvm_read_cr0_bits(vcpu, X86_CR0_PG); |
66 | } | 66 | } |
67 | 67 | ||
68 | void kvm_before_handle_nmi(struct kvm_vcpu *vcpu); | ||
69 | void kvm_after_handle_nmi(struct kvm_vcpu *vcpu); | ||
70 | |||
68 | #endif | 71 | #endif |