kvm.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Jan Kiszka <jan.kiszka@siemens.com>
To: Avi Kivity <avi@redhat.com>, Marcelo Tosatti <mtosatti@redhat.com>
Cc: kvm@vger.kernel.org
Subject: [PATCH] qemu-kvm: x86: Add support for NMI states
Date: Wed, 14 Oct 2009 10:52:37 +0200	[thread overview]
Message-ID: <4AD59155.5050706@siemens.com> (raw)
In-Reply-To: <20091013160647.27006.58598.stgit@mchn012c.ww002.siemens.net>

This adds the required bit to retrieve and set the so far hidden NMI
pending and NMI masked states of the KVM kernel side. It also extends
CPU VMState for proper saving/restoring. We can now savely reset a VM
while NMIs are on the fly, and we can live migrate etc. too.

Fortunately, the probability that this deficit bit normal VMs in
practice was very low.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 qemu-kvm-x86.c        |   52 +++++++++++++++++++++++++++++++++++++++++++++++++
 target-i386/cpu.h     |    1 +
 target-i386/machine.c |    1 +
 3 files changed, 54 insertions(+), 0 deletions(-)

diff --git a/qemu-kvm-x86.c b/qemu-kvm-x86.c
index acb1b91..86fd341 100644
--- a/qemu-kvm-x86.c
+++ b/qemu-kvm-x86.c
@@ -901,6 +901,53 @@ static void get_seg(SegmentCache *lhs, const struct kvm_segment *rhs)
 	| (rhs->avl * DESC_AVL_MASK);
 }
 
+static void kvm_get_nmi_state(CPUState *env)
+{
+#ifdef KVM_CAP_VCPU_STATE
+    kvm_vcpu_context_t vcpu = env->kvm_cpu_state.vcpu_ctx;
+    struct {
+        struct kvm_vcpu_state header;
+        struct kvm_vcpu_substate substates[1];
+    } request;
+    struct kvm_nmi_state nmi_state;
+    int r;
+
+    request.header.nsubstates = 1;
+    request.header.substates[0].type = KVM_X86_VCPU_NMI;
+    request.header.substates[0].offset = (size_t)&nmi_state - (size_t)&request;
+    r = ioctl(vcpu->fd, KVM_GET_VCPU_STATE, &request);
+    if (r == 0) {
+        env->nmi_pending = nmi_state.pending;
+        if (nmi_state.masked) {
+            env->hflags2 |= HF2_NMI_MASK;
+        } else {
+            env->hflags2 &= ~HF2_NMI_MASK;
+        }
+    }
+#endif
+    env->nmi_pending = 0;
+    env->hflags2 &= ~HF2_NMI_MASK;
+}
+
+static void kvm_set_nmi_state(CPUState *env)
+{
+#ifdef KVM_CAP_VCPU_STATE
+    kvm_vcpu_context_t vcpu = env->kvm_cpu_state.vcpu_ctx;
+    struct {
+        struct kvm_vcpu_state header;
+        struct kvm_vcpu_substate substates[1];
+    } request;
+    struct kvm_nmi_state nmi_state;
+
+    request.header.nsubstates = 1;
+    request.header.substates[0].type = KVM_X86_VCPU_NMI;
+    request.header.substates[0].offset = (size_t)&nmi_state - (size_t)&request;
+    nmi_state.pending = env->nmi_pending;
+    nmi_state.masked = !!(env->hflags2 & HF2_NMI_MASK);
+    ioctl(vcpu->fd, KVM_SET_VCPU_STATE, &request);
+#endif
+}
+
 void kvm_arch_load_regs(CPUState *env)
 {
     struct kvm_regs regs;
@@ -1010,6 +1057,8 @@ void kvm_arch_load_regs(CPUState *env)
     rc = kvm_set_msrs(env->kvm_cpu_state.vcpu_ctx, msrs, n);
     if (rc == -1)
         perror("kvm_set_msrs FAILED");
+
+    kvm_set_nmi_state(env);
 }
 
 void kvm_load_tsc(CPUState *env)
@@ -1195,6 +1244,8 @@ void kvm_arch_save_regs(CPUState *env)
                 return;
         }
     }
+
+    kvm_get_nmi_state(env);
 }
 
 static void do_cpuid_ent(struct kvm_cpuid_entry2 *e, uint32_t function,
@@ -1438,6 +1489,7 @@ void kvm_arch_push_nmi(void *opaque)
 
 void kvm_arch_cpu_reset(CPUState *env)
 {
+    env->nmi_pending = 0;
     kvm_arch_load_regs(env);
     if (!cpu_is_bsp(env)) {
 	if (kvm_irqchip_in_kernel(kvm_context)) {
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index 278d3e3..620822a 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -709,6 +709,7 @@ typedef struct CPUX86State {
     /* For KVM */
     uint64_t interrupt_bitmap[256 / 64];
     uint32_t mp_state;
+    uint32_t nmi_pending;
 
     /* in order to simplify APIC support, we leave this pointer to the
        user */
diff --git a/target-i386/machine.c b/target-i386/machine.c
index e640dad..5c290f3 100644
--- a/target-i386/machine.c
+++ b/target-i386/machine.c
@@ -469,6 +469,7 @@ const VMStateDescription vmstate_cpu = {
         VMSTATE_INT32_V(pending_irq_vmstate, CPUState, 9),
         VMSTATE_UINT32_V(mp_state, CPUState, 9),
         VMSTATE_UINT64_V(tsc, CPUState, 9),
+        VMSTATE_UINT32_V(nmi_pending, CPUState, 11),
         /* MCE */
         VMSTATE_UINT64_V(mcg_cap, CPUState, 10),
         VMSTATE_UINT64_V(mcg_status, CPUState, 10),

      parent reply	other threads:[~2009-10-14  8:53 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-10-13 16:06 [PATCH 0/4] Extensible VCPU state IOCTL Jan Kiszka
2009-10-13 16:06 ` [PATCH 2/4] KVM: Add unified KVM_GET/SET_VCPU_STATE IOCTL Jan Kiszka
2009-10-15  8:00   ` Avi Kivity
2009-10-15  9:22     ` Jan Kiszka
2009-10-15  9:33       ` Avi Kivity
2009-10-15  8:07   ` Avi Kivity
2009-10-15  9:22     ` Jan Kiszka
2009-10-15  8:11   ` Avi Kivity
2009-10-15  9:22     ` Jan Kiszka
2009-10-15 14:54     ` Glauber Costa
2009-10-15 15:57     ` Glauber Costa
2009-10-15 16:06       ` Jan Kiszka
2009-10-15 16:23         ` Glauber Costa
2009-10-13 16:06 ` [PATCH 1/4] KVM: Reorder IOCTLs in main kvm.h Jan Kiszka
2009-10-13 16:06 ` [PATCH 3/4] KVM: x86: Add support for KVM_GET/SET_VCPU_STATE Jan Kiszka
2009-10-13 16:06 ` [PATCH 4/4] KVM: x86: Add VCPU substate for NMI states Jan Kiszka
2009-10-15  8:09   ` Avi Kivity
2009-10-15  9:22     ` Jan Kiszka
2009-10-15  9:29       ` Avi Kivity
2009-10-15 11:27         ` Jan Kiszka
2009-10-25 13:11           ` Avi Kivity
2009-10-26  7:40             ` Jan Kiszka
2009-10-13 16:18 ` [RFC][PATCH] kvm: x86: Add support for KVM_GET/PUT_VCPU_STATE Jan Kiszka
2009-10-14  8:52 ` Jan Kiszka [this message]

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=4AD59155.5050706@siemens.com \
    --to=jan.kiszka@siemens.com \
    --cc=avi@redhat.com \
    --cc=kvm@vger.kernel.org \
    --cc=mtosatti@redhat.com \
    /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;
as well as URLs for NNTP newsgroup(s).