diff options
Diffstat (limited to 'arch/x86/kvm/x86.c')
-rw-r--r-- | arch/x86/kvm/x86.c | 46 |
1 files changed, 44 insertions, 2 deletions
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 1fa9a6db633d..07971451b947 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c | |||
@@ -86,6 +86,7 @@ struct kvm_stats_debugfs_item debugfs_entries[] = { | |||
86 | { "halt_wakeup", VCPU_STAT(halt_wakeup) }, | 86 | { "halt_wakeup", VCPU_STAT(halt_wakeup) }, |
87 | { "hypercalls", VCPU_STAT(hypercalls) }, | 87 | { "hypercalls", VCPU_STAT(hypercalls) }, |
88 | { "request_irq", VCPU_STAT(request_irq_exits) }, | 88 | { "request_irq", VCPU_STAT(request_irq_exits) }, |
89 | { "request_nmi", VCPU_STAT(request_nmi_exits) }, | ||
89 | { "irq_exits", VCPU_STAT(irq_exits) }, | 90 | { "irq_exits", VCPU_STAT(irq_exits) }, |
90 | { "host_state_reload", VCPU_STAT(host_state_reload) }, | 91 | { "host_state_reload", VCPU_STAT(host_state_reload) }, |
91 | { "efer_reload", VCPU_STAT(efer_reload) }, | 92 | { "efer_reload", VCPU_STAT(efer_reload) }, |
@@ -93,6 +94,7 @@ struct kvm_stats_debugfs_item debugfs_entries[] = { | |||
93 | { "insn_emulation", VCPU_STAT(insn_emulation) }, | 94 | { "insn_emulation", VCPU_STAT(insn_emulation) }, |
94 | { "insn_emulation_fail", VCPU_STAT(insn_emulation_fail) }, | 95 | { "insn_emulation_fail", VCPU_STAT(insn_emulation_fail) }, |
95 | { "irq_injections", VCPU_STAT(irq_injections) }, | 96 | { "irq_injections", VCPU_STAT(irq_injections) }, |
97 | { "nmi_injections", VCPU_STAT(nmi_injections) }, | ||
96 | { "mmu_shadow_zapped", VM_STAT(mmu_shadow_zapped) }, | 98 | { "mmu_shadow_zapped", VM_STAT(mmu_shadow_zapped) }, |
97 | { "mmu_pte_write", VM_STAT(mmu_pte_write) }, | 99 | { "mmu_pte_write", VM_STAT(mmu_pte_write) }, |
98 | { "mmu_pte_updated", VM_STAT(mmu_pte_updated) }, | 100 | { "mmu_pte_updated", VM_STAT(mmu_pte_updated) }, |
@@ -1318,6 +1320,15 @@ static int kvm_vcpu_ioctl_interrupt(struct kvm_vcpu *vcpu, | |||
1318 | return 0; | 1320 | return 0; |
1319 | } | 1321 | } |
1320 | 1322 | ||
1323 | static int kvm_vcpu_ioctl_nmi(struct kvm_vcpu *vcpu) | ||
1324 | { | ||
1325 | vcpu_load(vcpu); | ||
1326 | kvm_inject_nmi(vcpu); | ||
1327 | vcpu_put(vcpu); | ||
1328 | |||
1329 | return 0; | ||
1330 | } | ||
1331 | |||
1321 | static int vcpu_ioctl_tpr_access_reporting(struct kvm_vcpu *vcpu, | 1332 | static int vcpu_ioctl_tpr_access_reporting(struct kvm_vcpu *vcpu, |
1322 | struct kvm_tpr_access_ctl *tac) | 1333 | struct kvm_tpr_access_ctl *tac) |
1323 | { | 1334 | { |
@@ -1377,6 +1388,13 @@ long kvm_arch_vcpu_ioctl(struct file *filp, | |||
1377 | r = 0; | 1388 | r = 0; |
1378 | break; | 1389 | break; |
1379 | } | 1390 | } |
1391 | case KVM_NMI: { | ||
1392 | r = kvm_vcpu_ioctl_nmi(vcpu); | ||
1393 | if (r) | ||
1394 | goto out; | ||
1395 | r = 0; | ||
1396 | break; | ||
1397 | } | ||
1380 | case KVM_SET_CPUID: { | 1398 | case KVM_SET_CPUID: { |
1381 | struct kvm_cpuid __user *cpuid_arg = argp; | 1399 | struct kvm_cpuid __user *cpuid_arg = argp; |
1382 | struct kvm_cpuid cpuid; | 1400 | struct kvm_cpuid cpuid; |
@@ -2812,18 +2830,37 @@ static int dm_request_for_irq_injection(struct kvm_vcpu *vcpu, | |||
2812 | (kvm_x86_ops->get_rflags(vcpu) & X86_EFLAGS_IF)); | 2830 | (kvm_x86_ops->get_rflags(vcpu) & X86_EFLAGS_IF)); |
2813 | } | 2831 | } |
2814 | 2832 | ||
2833 | /* | ||
2834 | * Check if userspace requested a NMI window, and that the NMI window | ||
2835 | * is open. | ||
2836 | * | ||
2837 | * No need to exit to userspace if we already have a NMI queued. | ||
2838 | */ | ||
2839 | static int dm_request_for_nmi_injection(struct kvm_vcpu *vcpu, | ||
2840 | struct kvm_run *kvm_run) | ||
2841 | { | ||
2842 | return (!vcpu->arch.nmi_pending && | ||
2843 | kvm_run->request_nmi_window && | ||
2844 | vcpu->arch.nmi_window_open); | ||
2845 | } | ||
2846 | |||
2815 | static void post_kvm_run_save(struct kvm_vcpu *vcpu, | 2847 | static void post_kvm_run_save(struct kvm_vcpu *vcpu, |
2816 | struct kvm_run *kvm_run) | 2848 | struct kvm_run *kvm_run) |
2817 | { | 2849 | { |
2818 | kvm_run->if_flag = (kvm_x86_ops->get_rflags(vcpu) & X86_EFLAGS_IF) != 0; | 2850 | kvm_run->if_flag = (kvm_x86_ops->get_rflags(vcpu) & X86_EFLAGS_IF) != 0; |
2819 | kvm_run->cr8 = kvm_get_cr8(vcpu); | 2851 | kvm_run->cr8 = kvm_get_cr8(vcpu); |
2820 | kvm_run->apic_base = kvm_get_apic_base(vcpu); | 2852 | kvm_run->apic_base = kvm_get_apic_base(vcpu); |
2821 | if (irqchip_in_kernel(vcpu->kvm)) | 2853 | if (irqchip_in_kernel(vcpu->kvm)) { |
2822 | kvm_run->ready_for_interrupt_injection = 1; | 2854 | kvm_run->ready_for_interrupt_injection = 1; |
2823 | else | 2855 | kvm_run->ready_for_nmi_injection = 1; |
2856 | } else { | ||
2824 | kvm_run->ready_for_interrupt_injection = | 2857 | kvm_run->ready_for_interrupt_injection = |
2825 | (vcpu->arch.interrupt_window_open && | 2858 | (vcpu->arch.interrupt_window_open && |
2826 | vcpu->arch.irq_summary == 0); | 2859 | vcpu->arch.irq_summary == 0); |
2860 | kvm_run->ready_for_nmi_injection = | ||
2861 | (vcpu->arch.nmi_window_open && | ||
2862 | vcpu->arch.nmi_pending == 0); | ||
2863 | } | ||
2827 | } | 2864 | } |
2828 | 2865 | ||
2829 | static void vapic_enter(struct kvm_vcpu *vcpu) | 2866 | static void vapic_enter(struct kvm_vcpu *vcpu) |
@@ -2999,6 +3036,11 @@ static int __vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | |||
2999 | } | 3036 | } |
3000 | 3037 | ||
3001 | if (r > 0) { | 3038 | if (r > 0) { |
3039 | if (dm_request_for_nmi_injection(vcpu, kvm_run)) { | ||
3040 | r = -EINTR; | ||
3041 | kvm_run->exit_reason = KVM_EXIT_NMI; | ||
3042 | ++vcpu->stat.request_nmi_exits; | ||
3043 | } | ||
3002 | if (dm_request_for_irq_injection(vcpu, kvm_run)) { | 3044 | if (dm_request_for_irq_injection(vcpu, kvm_run)) { |
3003 | r = -EINTR; | 3045 | r = -EINTR; |
3004 | kvm_run->exit_reason = KVM_EXIT_INTR; | 3046 | kvm_run->exit_reason = KVM_EXIT_INTR; |