diff options
-rw-r--r-- | arch/x86/include/asm/kvm_host.h | 2 | ||||
-rw-r--r-- | arch/x86/kvm/x86.c | 46 | ||||
-rw-r--r-- | include/linux/kvm.h | 11 |
3 files changed, 55 insertions, 4 deletions
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index bfbbdea869bf..a40fa8478920 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h | |||
@@ -398,6 +398,7 @@ struct kvm_vcpu_stat { | |||
398 | u32 halt_exits; | 398 | u32 halt_exits; |
399 | u32 halt_wakeup; | 399 | u32 halt_wakeup; |
400 | u32 request_irq_exits; | 400 | u32 request_irq_exits; |
401 | u32 request_nmi_exits; | ||
401 | u32 irq_exits; | 402 | u32 irq_exits; |
402 | u32 host_state_reload; | 403 | u32 host_state_reload; |
403 | u32 efer_reload; | 404 | u32 efer_reload; |
@@ -406,6 +407,7 @@ struct kvm_vcpu_stat { | |||
406 | u32 insn_emulation_fail; | 407 | u32 insn_emulation_fail; |
407 | u32 hypercalls; | 408 | u32 hypercalls; |
408 | u32 irq_injections; | 409 | u32 irq_injections; |
410 | u32 nmi_injections; | ||
409 | }; | 411 | }; |
410 | 412 | ||
411 | struct descriptor_table { | 413 | struct descriptor_table { |
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; |
diff --git a/include/linux/kvm.h b/include/linux/kvm.h index f18b86fa8655..44fd7fa0af2b 100644 --- a/include/linux/kvm.h +++ b/include/linux/kvm.h | |||
@@ -83,18 +83,22 @@ struct kvm_irqchip { | |||
83 | #define KVM_EXIT_S390_SIEIC 13 | 83 | #define KVM_EXIT_S390_SIEIC 13 |
84 | #define KVM_EXIT_S390_RESET 14 | 84 | #define KVM_EXIT_S390_RESET 14 |
85 | #define KVM_EXIT_DCR 15 | 85 | #define KVM_EXIT_DCR 15 |
86 | #define KVM_EXIT_NMI 16 | ||
87 | #define KVM_EXIT_NMI_WINDOW_OPEN 17 | ||
86 | 88 | ||
87 | /* for KVM_RUN, returned by mmap(vcpu_fd, offset=0) */ | 89 | /* for KVM_RUN, returned by mmap(vcpu_fd, offset=0) */ |
88 | struct kvm_run { | 90 | struct kvm_run { |
89 | /* in */ | 91 | /* in */ |
90 | __u8 request_interrupt_window; | 92 | __u8 request_interrupt_window; |
91 | __u8 padding1[7]; | 93 | __u8 request_nmi_window; |
94 | __u8 padding1[6]; | ||
92 | 95 | ||
93 | /* out */ | 96 | /* out */ |
94 | __u32 exit_reason; | 97 | __u32 exit_reason; |
95 | __u8 ready_for_interrupt_injection; | 98 | __u8 ready_for_interrupt_injection; |
96 | __u8 if_flag; | 99 | __u8 if_flag; |
97 | __u8 padding2[2]; | 100 | __u8 ready_for_nmi_injection; |
101 | __u8 padding2; | ||
98 | 102 | ||
99 | /* in (pre_kvm_run), out (post_kvm_run) */ | 103 | /* in (pre_kvm_run), out (post_kvm_run) */ |
100 | __u64 cr8; | 104 | __u64 cr8; |
@@ -387,6 +391,7 @@ struct kvm_trace_rec { | |||
387 | #define KVM_CAP_DEVICE_ASSIGNMENT 17 | 391 | #define KVM_CAP_DEVICE_ASSIGNMENT 17 |
388 | #endif | 392 | #endif |
389 | #define KVM_CAP_IOMMU 18 | 393 | #define KVM_CAP_IOMMU 18 |
394 | #define KVM_CAP_NMI 19 | ||
390 | 395 | ||
391 | /* | 396 | /* |
392 | * ioctls for VM fds | 397 | * ioctls for VM fds |
@@ -458,6 +463,8 @@ struct kvm_trace_rec { | |||
458 | #define KVM_S390_INITIAL_RESET _IO(KVMIO, 0x97) | 463 | #define KVM_S390_INITIAL_RESET _IO(KVMIO, 0x97) |
459 | #define KVM_GET_MP_STATE _IOR(KVMIO, 0x98, struct kvm_mp_state) | 464 | #define KVM_GET_MP_STATE _IOR(KVMIO, 0x98, struct kvm_mp_state) |
460 | #define KVM_SET_MP_STATE _IOW(KVMIO, 0x99, struct kvm_mp_state) | 465 | #define KVM_SET_MP_STATE _IOW(KVMIO, 0x99, struct kvm_mp_state) |
466 | /* Available with KVM_CAP_NMI */ | ||
467 | #define KVM_NMI _IO(KVMIO, 0x9a) | ||
461 | 468 | ||
462 | #define KVM_TRC_INJ_VIRQ (KVM_TRC_HANDLER + 0x02) | 469 | #define KVM_TRC_INJ_VIRQ (KVM_TRC_HANDLER + 0x02) |
463 | #define KVM_TRC_REDELIVER_EVT (KVM_TRC_HANDLER + 0x03) | 470 | #define KVM_TRC_REDELIVER_EVT (KVM_TRC_HANDLER + 0x03) |