All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jan Kiszka <jan.kiszka@web.de>
To: Anthony Liguori <aliguori@us.ibm.com>,
	qemu-devel <qemu-devel@nongnu.org>
Cc: Marcelo Tosatti <mtosatti@redhat.com>, Avi Kivity <avi@redhat.com>
Subject: [Qemu-devel] [PATCH] kvm: x86: Add support for VCPU event states
Date: Wed, 25 Nov 2009 00:33:03 +0100	[thread overview]
Message-ID: <4B0C6D2F.6080701@web.de> (raw)

[-- Attachment #1: Type: text/plain, Size: 6090 bytes --]

This patch extends the qemu-kvm state sync logic with support for
KVM_GET/SET_VCPU_EVENTS, giving access to yet missing exception,
interrupt and NMI states.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
 kvm-all.c             |   11 +++++++
 kvm.h                 |    1 +
 target-i386/cpu.h     |    5 +++
 target-i386/kvm.c     |   77 +++++++++++++++++++++++++++++++++++++++++++++++++
 target-i386/machine.c |    6 ++++
 5 files changed, 100 insertions(+), 0 deletions(-)

diff --git a/kvm-all.c b/kvm-all.c
index b605caa..c05e555 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -61,6 +61,7 @@ struct KVMState
     int coalesced_mmio;
     int broken_set_mem_region;
     int migration_log;
+    int vcpu_events;
 #ifdef KVM_CAP_SET_GUEST_DEBUG
     struct kvm_sw_breakpoint_head kvm_sw_breakpoints;
 #endif
@@ -479,6 +480,11 @@ int kvm_init(int smp_cpus)
     }
 #endif
 
+    s->vcpu_events = 0;
+#ifdef KVM_CAP_VCPU_EVENTS
+    s->vcpu_events = kvm_check_extension(s, KVM_CAP_VCPU_EVENTS);
+#endif
+
     ret = kvm_arch_init(s, smp_cpus);
     if (ret < 0)
         goto err;
@@ -868,6 +874,11 @@ int kvm_has_sync_mmu(void)
 #endif
 }
 
+int kvm_has_vcpu_events(void)
+{
+    return kvm_state->vcpu_events;
+}
+
 void kvm_setup_guest_memory(void *start, size_t size)
 {
     if (!kvm_has_sync_mmu()) {
diff --git a/kvm.h b/kvm.h
index e4cbedc..1c93ac5 100644
--- a/kvm.h
+++ b/kvm.h
@@ -47,6 +47,7 @@ int kvm_log_stop(target_phys_addr_t phys_addr, ram_addr_t size);
 int kvm_set_migration_log(int enable);
 
 int kvm_has_sync_mmu(void);
+int kvm_has_vcpu_events(void);
 
 void kvm_setup_guest_memory(void *start, size_t size);
 
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index eb9532a..9c3e905 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -693,6 +693,11 @@ typedef struct CPUX86State {
     /* For KVM */
     uint32_t mp_state;
     int32_t interrupt_injected;
+    uint8_t soft_interrupt;
+    uint8_t nmi_injected;
+    uint8_t nmi_pending;
+    uint8_t has_error_code;
+    uint32_t sipi_vector;
 
     /* in order to simplify APIC support, we leave this pointer to the
        user */
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 89fd7a5..3b61a7f 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -225,6 +225,8 @@ int kvm_arch_init_vcpu(CPUState *env)
 void kvm_arch_reset_vcpu(CPUState *env)
 {
     env->interrupt_injected = -1;
+    env->nmi_injected = 0;
+    env->nmi_pending = 0;
 }
 
 static int kvm_has_msr_star(CPUState *env)
@@ -694,6 +696,73 @@ static int kvm_get_mp_state(CPUState *env)
     return 0;
 }
 
+static int kvm_put_vcpu_events(CPUState *env)
+{
+#ifdef KVM_CAP_VCPU_EVENTS
+    struct kvm_vcpu_events events;
+
+    if (!kvm_has_vcpu_events()) {
+        return 0;
+    }
+
+    events.exception.injected = (env->exception_index >= 0);
+    events.exception.nr = env->exception_index;
+    events.exception.has_error_code = env->has_error_code;
+    events.exception.error_code = env->error_code;
+
+    events.interrupt.injected = (env->interrupt_injected >= 0);
+    events.interrupt.nr = env->interrupt_injected;
+    events.interrupt.soft = env->soft_interrupt;
+
+    events.nmi.injected = env->nmi_injected;
+    events.nmi.pending = env->nmi_pending;
+    events.nmi.masked = !!(env->hflags2 & HF2_NMI_MASK);
+
+    events.sipi_vector = env->sipi_vector;
+
+    return kvm_vcpu_ioctl(env, KVM_SET_VCPU_EVENTS, &events);
+#else
+    return 0;
+#endif
+}
+
+static int kvm_get_vcpu_events(CPUState *env)
+{
+#ifdef KVM_CAP_VCPU_EVENTS
+    struct kvm_vcpu_events events;
+    int ret;
+
+    if (!kvm_has_vcpu_events()) {
+        return 0;
+    }
+
+    ret = kvm_vcpu_ioctl(env, KVM_GET_VCPU_EVENTS, &events);
+    if (ret < 0) {
+       return ret;
+    }
+    env->exception_index =
+       events.exception.injected ? events.exception.nr : -1;
+    env->has_error_code = events.exception.has_error_code;
+    env->error_code = events.exception.error_code;
+
+    env->interrupt_injected =
+        events.interrupt.injected ? events.interrupt.nr : -1;
+    env->soft_interrupt = events.interrupt.soft;
+
+    env->nmi_injected = events.nmi.injected;
+    env->nmi_pending = events.nmi.pending;
+    if (events.nmi.masked) {
+        env->hflags2 |= HF2_NMI_MASK;
+    } else {
+        env->hflags2 &= ~HF2_NMI_MASK;
+    }
+
+    env->sipi_vector = events.sipi_vector;
+#endif
+
+    return 0;
+}
+
 int kvm_arch_put_registers(CPUState *env)
 {
     int ret;
@@ -718,6 +787,10 @@ int kvm_arch_put_registers(CPUState *env)
     if (ret < 0)
         return ret;
 
+    ret = kvm_put_vcpu_events(env);
+    if (ret < 0)
+        return ret;
+
     return 0;
 }
 
@@ -745,6 +818,10 @@ int kvm_arch_get_registers(CPUState *env)
     if (ret < 0)
         return ret;
 
+    ret = kvm_get_vcpu_events(env);
+    if (ret < 0)
+        return ret;
+
     return 0;
 }
 
diff --git a/target-i386/machine.c b/target-i386/machine.c
index c09b049..cdc8898 100644
--- a/target-i386/machine.c
+++ b/target-i386/machine.c
@@ -448,6 +448,11 @@ static const VMStateDescription vmstate_cpu = {
         VMSTATE_INT32_V(interrupt_injected, CPUState, 9),
         VMSTATE_UINT32_V(mp_state, CPUState, 9),
         VMSTATE_UINT64_V(tsc, CPUState, 9),
+        VMSTATE_UINT8_V(soft_interrupt, CPUState, 11),
+        VMSTATE_UINT8_V(nmi_injected, CPUState, 11),
+        VMSTATE_UINT8_V(nmi_pending, CPUState, 11),
+        VMSTATE_UINT8_V(has_error_code, CPUState, 11),
+        VMSTATE_UINT32_V(sipi_vector, CPUState, 11),
         /* MCE */
         VMSTATE_UINT64_V(mcg_cap, CPUState, 10),
         VMSTATE_UINT64_V(mcg_status, CPUState, 10),
@@ -456,6 +461,7 @@ static const VMStateDescription vmstate_cpu = {
         /* rdtscp */
         VMSTATE_UINT64_V(tsc_aux, CPUState, 11),
         VMSTATE_END_OF_LIST()
+        /* The above list is not sorted /wrt version numbers, watch out! */
     }
 };
 


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 257 bytes --]

             reply	other threads:[~2009-11-24 23:33 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-11-24 23:33 Jan Kiszka [this message]
2009-11-25 14:34 ` [Qemu-devel] Re: [PATCH] kvm: x86: Add support for VCPU event states Avi Kivity
2009-12-08 15:26 ` [Qemu-devel] " Marcelo Tosatti
2009-12-08 16:18   ` Jan Kiszka

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=4B0C6D2F.6080701@web.de \
    --to=jan.kiszka@web.de \
    --cc=aliguori@us.ibm.com \
    --cc=avi@redhat.com \
    --cc=mtosatti@redhat.com \
    --cc=qemu-devel@nongnu.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.