aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/include/asm/kvm_host.h2
-rw-r--r--arch/x86/kvm/x86.c46
-rw-r--r--include/linux/kvm.h11
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
411struct descriptor_table { 413struct 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
1323static 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
1321static int vcpu_ioctl_tpr_access_reporting(struct kvm_vcpu *vcpu, 1332static 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 */
2839static 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
2815static void post_kvm_run_save(struct kvm_vcpu *vcpu, 2847static 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
2829static void vapic_enter(struct kvm_vcpu *vcpu) 2866static 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) */
88struct kvm_run { 90struct 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)