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 |
