public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Avi Kivity <avi@redhat.com>
To: kvm@vger.kernel.org
Cc: linux-kernel@vger.kernel.org, Jan Kiszka <jan.kiszka@siemens.com>
Subject: [PATCH 12/45] KVM: x86: Support for user space injected NMIs
Date: Mon,  8 Dec 2008 13:36:23 +0200	[thread overview]
Message-ID: <1228736216-15787-13-git-send-email-avi@redhat.com> (raw)
In-Reply-To: <1228736216-15787-1-git-send-email-avi@redhat.com>

From: Jan Kiszka <jan.kiszka@siemens.com>

Introduces the KVM_NMI IOCTL to the generic x86 part of KVM for
injecting NMIs from user space and also extends the statistic report
accordingly.

Based on the original patch by Sheng Yang.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Sheng Yang <sheng.yang@intel.com>
Signed-off-by: Avi Kivity <avi@redhat.com>
---
 arch/x86/include/asm/kvm_host.h |    2 +
 arch/x86/kvm/x86.c              |   46 +++++++++++++++++++++++++++++++++++++-
 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 bfbbdea..a40fa84 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 {
 	u32 halt_exits;
 	u32 halt_wakeup;
 	u32 request_irq_exits;
+	u32 request_nmi_exits;
 	u32 irq_exits;
 	u32 host_state_reload;
 	u32 efer_reload;
@@ -406,6 +407,7 @@ struct kvm_vcpu_stat {
 	u32 insn_emulation_fail;
 	u32 hypercalls;
 	u32 irq_injections;
+	u32 nmi_injections;
 };
 
 struct descriptor_table {
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 1fa9a6d..0797145 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -86,6 +86,7 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
 	{ "halt_wakeup", VCPU_STAT(halt_wakeup) },
 	{ "hypercalls", VCPU_STAT(hypercalls) },
 	{ "request_irq", VCPU_STAT(request_irq_exits) },
+	{ "request_nmi", VCPU_STAT(request_nmi_exits) },
 	{ "irq_exits", VCPU_STAT(irq_exits) },
 	{ "host_state_reload", VCPU_STAT(host_state_reload) },
 	{ "efer_reload", VCPU_STAT(efer_reload) },
@@ -93,6 +94,7 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
 	{ "insn_emulation", VCPU_STAT(insn_emulation) },
 	{ "insn_emulation_fail", VCPU_STAT(insn_emulation_fail) },
 	{ "irq_injections", VCPU_STAT(irq_injections) },
+	{ "nmi_injections", VCPU_STAT(nmi_injections) },
 	{ "mmu_shadow_zapped", VM_STAT(mmu_shadow_zapped) },
 	{ "mmu_pte_write", VM_STAT(mmu_pte_write) },
 	{ "mmu_pte_updated", VM_STAT(mmu_pte_updated) },
@@ -1318,6 +1320,15 @@ static int kvm_vcpu_ioctl_interrupt(struct kvm_vcpu *vcpu,
 	return 0;
 }
 
+static int kvm_vcpu_ioctl_nmi(struct kvm_vcpu *vcpu)
+{
+	vcpu_load(vcpu);
+	kvm_inject_nmi(vcpu);
+	vcpu_put(vcpu);
+
+	return 0;
+}
+
 static int vcpu_ioctl_tpr_access_reporting(struct kvm_vcpu *vcpu,
 					   struct kvm_tpr_access_ctl *tac)
 {
@@ -1377,6 +1388,13 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
 		r = 0;
 		break;
 	}
+	case KVM_NMI: {
+		r = kvm_vcpu_ioctl_nmi(vcpu);
+		if (r)
+			goto out;
+		r = 0;
+		break;
+	}
 	case KVM_SET_CPUID: {
 		struct kvm_cpuid __user *cpuid_arg = argp;
 		struct kvm_cpuid cpuid;
@@ -2812,18 +2830,37 @@ static int dm_request_for_irq_injection(struct kvm_vcpu *vcpu,
 		(kvm_x86_ops->get_rflags(vcpu) & X86_EFLAGS_IF));
 }
 
+/*
+ * Check if userspace requested a NMI window, and that the NMI window
+ * is open.
+ *
+ * No need to exit to userspace if we already have a NMI queued.
+ */
+static int dm_request_for_nmi_injection(struct kvm_vcpu *vcpu,
+					struct kvm_run *kvm_run)
+{
+	return (!vcpu->arch.nmi_pending &&
+		kvm_run->request_nmi_window &&
+		vcpu->arch.nmi_window_open);
+}
+
 static void post_kvm_run_save(struct kvm_vcpu *vcpu,
 			      struct kvm_run *kvm_run)
 {
 	kvm_run->if_flag = (kvm_x86_ops->get_rflags(vcpu) & X86_EFLAGS_IF) != 0;
 	kvm_run->cr8 = kvm_get_cr8(vcpu);
 	kvm_run->apic_base = kvm_get_apic_base(vcpu);
-	if (irqchip_in_kernel(vcpu->kvm))
+	if (irqchip_in_kernel(vcpu->kvm)) {
 		kvm_run->ready_for_interrupt_injection = 1;
-	else
+		kvm_run->ready_for_nmi_injection = 1;
+	} else {
 		kvm_run->ready_for_interrupt_injection =
 					(vcpu->arch.interrupt_window_open &&
 					 vcpu->arch.irq_summary == 0);
+		kvm_run->ready_for_nmi_injection =
+					(vcpu->arch.nmi_window_open &&
+					 vcpu->arch.nmi_pending == 0);
+	}
 }
 
 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)
 		}
 
 		if (r > 0) {
+			if (dm_request_for_nmi_injection(vcpu, kvm_run)) {
+				r = -EINTR;
+				kvm_run->exit_reason = KVM_EXIT_NMI;
+				++vcpu->stat.request_nmi_exits;
+			}
 			if (dm_request_for_irq_injection(vcpu, kvm_run)) {
 				r = -EINTR;
 				kvm_run->exit_reason = KVM_EXIT_INTR;
diff --git a/include/linux/kvm.h b/include/linux/kvm.h
index f18b86f..44fd7fa 100644
--- a/include/linux/kvm.h
+++ b/include/linux/kvm.h
@@ -83,18 +83,22 @@ struct kvm_irqchip {
 #define KVM_EXIT_S390_SIEIC       13
 #define KVM_EXIT_S390_RESET       14
 #define KVM_EXIT_DCR              15
+#define KVM_EXIT_NMI              16
+#define KVM_EXIT_NMI_WINDOW_OPEN  17
 
 /* for KVM_RUN, returned by mmap(vcpu_fd, offset=0) */
 struct kvm_run {
 	/* in */
 	__u8 request_interrupt_window;
-	__u8 padding1[7];
+	__u8 request_nmi_window;
+	__u8 padding1[6];
 
 	/* out */
 	__u32 exit_reason;
 	__u8 ready_for_interrupt_injection;
 	__u8 if_flag;
-	__u8 padding2[2];
+	__u8 ready_for_nmi_injection;
+	__u8 padding2;
 
 	/* in (pre_kvm_run), out (post_kvm_run) */
 	__u64 cr8;
@@ -387,6 +391,7 @@ struct kvm_trace_rec {
 #define KVM_CAP_DEVICE_ASSIGNMENT 17
 #endif
 #define KVM_CAP_IOMMU 18
+#define KVM_CAP_NMI 19
 
 /*
  * ioctls for VM fds
@@ -458,6 +463,8 @@ struct kvm_trace_rec {
 #define KVM_S390_INITIAL_RESET    _IO(KVMIO,  0x97)
 #define KVM_GET_MP_STATE          _IOR(KVMIO,  0x98, struct kvm_mp_state)
 #define KVM_SET_MP_STATE          _IOW(KVMIO,  0x99, struct kvm_mp_state)
+/* Available with KVM_CAP_NMI */
+#define KVM_NMI                   _IO(KVMIO,  0x9a)
 
 #define KVM_TRC_INJ_VIRQ         (KVM_TRC_HANDLER + 0x02)
 #define KVM_TRC_REDELIVER_EVT    (KVM_TRC_HANDLER + 0x03)
-- 
1.6.0.3


  parent reply	other threads:[~2008-12-08 11:50 UTC|newest]

Thread overview: 49+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-12-08 11:36 [PATCH 00/45] KVM Updates for 2.6.29 (Part 1 of 3) Avi Kivity
2008-12-08 11:36 ` [PATCH 01/45] KVM: x86 emulator: consolidate push reg Avi Kivity
2008-12-08 11:36 ` [PATCH 02/45] KVM: VMX: include all IRQ window exits in statistics Avi Kivity
2008-12-08 11:36 ` [PATCH 03/45] KVM: VMX: Use INTR_TYPE_NMI_INTR instead of magic value Avi Kivity
2008-12-08 11:36 ` [PATCH 04/45] KVM: VMX: Support for NMI task gates Avi Kivity
2008-12-08 11:36 ` [PATCH 05/45] KVM: x86: Reset pending/inject NMI state on CPU reset Avi Kivity
2008-12-08 11:36 ` [PATCH 06/45] KVM: VMX: refactor/fix IRQ and NMI injectability determination Avi Kivity
2008-12-08 11:36 ` [PATCH 07/45] KVM: VMX: refactor IRQ and NMI window enabling Avi Kivity
2008-12-08 11:36 ` [PATCH 08/45] KVM: VMX: fix real-mode NMI support Avi Kivity
2008-12-08 11:36 ` [PATCH 09/45] KVM: x86: Enable NMI Watchdog via in-kernel PIT source Avi Kivity
2008-12-08 11:36 ` [PATCH 10/45] KVM: x86: VCPU with pending NMI is runnabled Avi Kivity
2008-12-08 11:36 ` [PATCH 11/45] KVM: Kick NMI receiving VCPU Avi Kivity
2008-12-08 11:36 ` Avi Kivity [this message]
2008-12-08 12:07   ` [PATCH 12/45] KVM: x86: Support for user space injected NMIs Jan Kiszka
2008-12-10  8:46     ` Avi Kivity
2008-12-10  9:16       ` Jan Kiszka
2008-12-08 11:36 ` [PATCH 13/45] KVM: VMX: Provide support " Avi Kivity
2008-12-08 11:36 ` [PATCH 14/45] KVM: VMX: work around lacking VNMI support Avi Kivity
2008-12-08 11:36 ` [PATCH 15/45] KVM: call kvm_arch_vcpu_reset() instead of the kvm_x86_ops callback Avi Kivity
2008-12-08 11:36 ` [PATCH 16/45] x86: Rename mtrr_state struct and macro names Avi Kivity
2008-12-08 11:36 ` [PATCH 17/45] x86: Export some definition of MTRR Avi Kivity
2008-12-08 11:36 ` [PATCH 18/45] KVM: Improve MTRR structure Avi Kivity
2008-12-08 11:36 ` [PATCH 19/45] KVM: VMX: Add PAT support for EPT Avi Kivity
2008-12-08 11:36 ` [PATCH 20/45] KVM: Add local get_mtrr_type() to support MTRR Avi Kivity
2008-12-08 11:36 ` [PATCH 21/45] KVM: Enable MTRR for EPT Avi Kivity
2008-12-08 11:36 ` [PATCH 22/45] KVM: Clean up kvm_x86_emulate.h Avi Kivity
2008-12-08 11:36 ` [PATCH 23/45] KVM: MMU: Extend kvm_mmu_page->slot_bitmap size Avi Kivity
2008-12-08 11:36 ` [PATCH 24/45] KVM: VMX: Move private memory slot position Avi Kivity
2008-12-08 11:36 ` [PATCH 25/45] KVM: x86 emulator: Add decode entries for 0x04 and 0x05 opcodes (add acc, imm) Avi Kivity
2008-12-08 11:36 ` [PATCH 26/45] KVM: x86: Fix and refactor NMI watchdog emulation Avi Kivity
2008-12-08 11:36 ` [PATCH 27/45] KVM: x86: Optimize NMI watchdog delivery Avi Kivity
2008-12-08 11:36 ` [PATCH 28/45] KVM: IRQ ACK notifier should be used with in-kernel irqchip Avi Kivity
2008-12-08 11:36 ` [PATCH 29/45] KVM: x86: Fix typo in function name Avi Kivity
2008-12-08 11:36 ` [PATCH 30/45] KVM: SVM: Set the 'g' bit of the cs selector for cross-vendor migration Avi Kivity
2008-12-08 11:36 ` [PATCH 31/45] KVM: SVM: Set the 'busy' flag of the TR selector Avi Kivity
2008-12-08 11:36 ` [PATCH 32/45] KVM: allow emulator to adjust rip for emulated pio instructions Avi Kivity
2008-12-08 11:36 ` [PATCH 33/45] KVM: VMX: Handle mmio emulation when guest state is invalid Avi Kivity
2008-12-08 11:36 ` [PATCH 34/45] KVM: ia64: Re-organize data sturure of guests' data area Avi Kivity
2008-12-08 11:36 ` [PATCH 35/45] KVM: ia64: Remove lock held by halted vcpu Avi Kivity
2008-12-08 11:36 ` [PATCH 36/45] KVM: Enable Function Level Reset for assigned device Avi Kivity
2008-12-08 11:36 ` [PATCH 37/45] KVM: MMU: Fix aliased gfns treated as unaliased Avi Kivity
2008-12-08 11:36 ` [PATCH 38/45] KVM: ppc: Move 440-specific TLB code into 44x_tlb.c Avi Kivity
2008-12-08 11:36 ` [PATCH 39/45] KVM: ppc: Rename "struct tlbe" to "struct kvmppc_44x_tlbe" Avi Kivity
2008-12-08 11:36 ` [PATCH 40/45] KVM: ppc: combine booke_guest.c and booke_host.c Avi Kivity
2008-12-08 11:36 ` [PATCH 41/45] KVM: ppc: Refactor powerpc.c to relocate 440-specific code Avi Kivity
2008-12-08 11:36 ` [PATCH 42/45] ppc: Create disassemble.h to extract instruction fields Avi Kivity
2008-12-08 11:36 ` [PATCH 43/45] KVM: ppc: refactor instruction emulation into generic and core-specific pieces Avi Kivity
2008-12-08 11:36 ` [PATCH 44/45] KVM: ppc: Move the last bits of 44x code out of booke.c Avi Kivity
2008-12-08 11:36 ` [PATCH 45/45] KVM: ppc: create struct kvm_vcpu_44x and introduce container_of() accessor Avi Kivity

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1228736216-15787-13-git-send-email-avi@redhat.com \
    --to=avi@redhat.com \
    --cc=jan.kiszka@siemens.com \
    --cc=kvm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox