Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 340e01248478ba8b78a6d4d1809b1eff > files > 812

kvm-83-270.el5_11.src.rpm

From 60fbe0cbe9e0f769a4db560eca1e145cbd3a0065 Mon Sep 17 00:00:00 2001
From: Juan Quintela <quintela@redhat.com>
Date: Wed, 16 Dec 2009 16:33:24 -0200
Subject: [PATCH 1/6] kvm: x86: Add support for VCPU event states

RH-Author: Juan Quintela <quintela@redhat.com>
Message-id: <m3tyvqc20b.fsf@neno.neno>
Patchwork-id: 5740
O-Subject: [RHEL 5.5 v2 PATCH] kvm: x86: Add support for VCPU event states
Bugzilla: 541084
RH-Acked-by: Marcelo Tosatti <mtosatti@redhat.com>
RH-Acked-by: Michael S. Tsirkin <mst@redhat.com>
RH-Acked-by: Gleb Natapov <gleb@redhat.com>

( quintela changes:
 new version, in top of -M 5.4.0 changes.
 Once there simplify it to use same version_id == 8).

(new version fixing the "unused variable r" warning)

commit a0fb002c6462d21ceb9eac8c5772e469ec189374
Author: Jan Kiszka <jan.kiszka@web.de>
Date:   Wed Nov 25 00:33:03 2009 +0100

kvm: x86: Add support for VCPU event states

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>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Bugzilla: 541084
Signed-off-by: Juan Quintela <quintela@redhat.com>
---
 libkvm/libkvm-x86.c        |   35 ++++++++++++++++++++++++++
 libkvm/libkvm.h            |    6 ++++
 qemu/qemu-kvm-x86.c        |   59 ++++++++++++++++++++++++++++++++++++++++++++
 qemu/qemu-kvm.h            |    3 ++
 qemu/target-i386/cpu.h     |    6 ++++
 qemu/target-i386/machine.c |   16 +++++++++++-
 6 files changed, 124 insertions(+), 1 deletions(-)

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
 libkvm/libkvm-x86.c        |   35 ++++++++++++++++++++++++++
 libkvm/libkvm.h            |    6 ++++
 qemu/qemu-kvm-x86.c        |   59 ++++++++++++++++++++++++++++++++++++++++++++
 qemu/qemu-kvm.h            |    3 ++
 qemu/target-i386/cpu.h     |    6 ++++
 qemu/target-i386/machine.c |   14 ++++++++++
 6 files changed, 123 insertions(+), 0 deletions(-)

diff --git a/libkvm/libkvm-x86.c b/libkvm/libkvm-x86.c
index c10c7e5..3918f49 100644
--- a/libkvm/libkvm-x86.c
+++ b/libkvm/libkvm-x86.c
@@ -585,3 +585,38 @@ int kvm_set_clock(kvm_context_t kvm, struct kvm_clock_data *cl)
 }
 #endif
 
+#ifdef KVM_CAP_VCPU_EVENTS
+int kvm_has_vcpu_events(kvm_context_t kvm)
+{
+	int r;
+	r = ioctl(kvm->fd, KVM_CHECK_EXTENSION, KVM_CAP_VCPU_EVENTS);
+	if (r == -1 || r == 0)
+		return 0;
+	return 1;
+}
+
+int kvm_get_vcpu_events(kvm_context_t kvm, int vcpu, struct kvm_vcpu_events *ev)
+{
+	int r;
+	
+	r = ioctl(kvm->vcpu_fd[vcpu], KVM_GET_VCPU_EVENTS, ev);
+	if (r == -1) {
+		r = -errno;
+		perror("kvm_get_vcpu_events");
+	}
+	return r;
+}
+
+int kvm_set_vcpu_events(kvm_context_t kvm, int vcpu, struct kvm_vcpu_events *ev)
+{
+	int r;
+	
+	r = ioctl(kvm->vcpu_fd[vcpu], KVM_SET_VCPU_EVENTS, ev);
+	if (r == -1) {
+		r = -errno;
+		perror("kvm_set_vcpu_events");
+	}
+	return r;
+}
+#endif
+
diff --git a/libkvm/libkvm.h b/libkvm/libkvm.h
index be163e8..185285a 100644
--- a/libkvm/libkvm.h
+++ b/libkvm/libkvm.h
@@ -864,4 +864,10 @@ int kvm_assign_set_msix_entry(kvm_context_t kvm,
 int kvm_get_clock(kvm_context_t kvm, struct kvm_clock_data *cl);
 int kvm_set_clock(kvm_context_t kvm, struct kvm_clock_data *cl);
 int kvm_can_adjust_clock(kvm_context_t kvm);
+
+int kvm_has_vcpu_events(kvm_context_t kvm);
+int kvm_get_vcpu_events(kvm_context_t kvm, int vcpu,
+                        struct kvm_vcpu_events *ev);
+int kvm_set_vcpu_events(kvm_context_t kvm, int vcpu,
+                        struct kvm_vcpu_events *ev);
 #endif
diff --git a/qemu/qemu-kvm-x86.c b/qemu/qemu-kvm-x86.c
index fcf5a21..899f0ad 100644
--- a/qemu/qemu-kvm-x86.c
+++ b/qemu/qemu-kvm-x86.c
@@ -358,6 +358,61 @@ void kvm_load_mpstate(CPUState *env)
 #endif
 }
 
+void kvm_save_vcpu_events(CPUState *env)
+{
+#ifdef KVM_CAP_VCPU_EVENTS
+    struct kvm_vcpu_events events;
+
+    if (!kvm_has_vcpu_events(kvm_context))
+        return;
+
+    if (kvm_get_vcpu_events(kvm_context, env->cpu_index, &events))
+        exit(0);
+
+    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
+}
+
+void kvm_load_vcpu_events(CPUState *env)
+{
+#ifdef KVM_CAP_VCPU_EVENTS
+    struct kvm_vcpu_events events;
+
+    if (!kvm_has_vcpu_events(kvm_context))
+        return;
+
+    events.flags = 0;
+
+    /* Exceptions are regenerated */
+    events.exception.injected = 0;
+    events.exception.nr = 0;
+    events.exception.has_error_code = 0;
+    events.exception.error_code = 0;
+
+    /* Pending interrupts are restored through interrupt_bitmap */
+    events.interrupt.injected = 0;
+    events.interrupt.nr = 0;
+    events.interrupt.soft = 0;
+
+    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;
+
+    if (kvm_set_vcpu_events(kvm_context, env->cpu_index, &events))
+        exit(0);
+#endif
+}
+
 void kvm_arch_save_regs(CPUState *env)
 {
     struct kvm_regs regs;
@@ -714,6 +769,10 @@ int handle_tpr_access(void *opaque, int vcpu,
 
 void kvm_arch_cpu_reset(CPUState *env)
 {
+    env->nmi_injected = 0;
+    env->nmi_pending = 0;
+    kvm_load_vcpu_events(env);
+
     kvm_arch_load_regs(env);
     if (env->cpu_index != 0) {
 	if (kvm_irqchip_in_kernel(kvm_context)) {
diff --git a/qemu/qemu-kvm.h b/qemu/qemu-kvm.h
index f2063ce..37d8727 100644
--- a/qemu/qemu-kvm.h
+++ b/qemu/qemu-kvm.h
@@ -22,6 +22,9 @@ void kvm_load_registers(CPUState *env);
 void kvm_save_registers(CPUState *env);
 void kvm_load_mpstate(CPUState *env);
 void kvm_save_mpstate(CPUState *env);
+void kvm_save_vcpu_events(CPUState *env);
+void kvm_load_vcpu_events(CPUState *env);
+
 int kvm_cpu_exec(CPUState *env);
 int kvm_insert_breakpoint(CPUState *current_env, target_ulong addr,
                           target_ulong len, int type);
diff --git a/qemu/target-i386/cpu.h b/qemu/target-i386/cpu.h
index b4c0bec..e1a7fc4 100644
--- a/qemu/target-i386/cpu.h
+++ b/qemu/target-i386/cpu.h
@@ -644,6 +644,12 @@ typedef struct CPUX86State {
        user */
     struct APICState *apic_state;
     uint32_t mp_state;
+    uint8_t soft_interrupt;
+    uint8_t nmi_injected;
+    uint8_t nmi_pending;
+    uint8_t has_error_code;
+    uint32_t sipi_vector;
+
 } CPUX86State;
 
 CPUX86State *cpu_x86_init(const char *cpu_model);
diff --git a/qemu/target-i386/machine.c b/qemu/target-i386/machine.c
index d77ed04..db344c3 100644
--- a/qemu/target-i386/machine.c
+++ b/qemu/target-i386/machine.c
@@ -43,6 +43,7 @@ void cpu_save(QEMUFile *f, void *opaque, int version_id)
     if (kvm_enabled()) {
         kvm_save_registers(env);
         kvm_save_mpstate(env);
+        kvm_save_vcpu_events(env);
     }
 
     for(i = 0; i < CPU_NB_REGS; i++)
@@ -154,6 +155,12 @@ void cpu_save(QEMUFile *f, void *opaque, int version_id)
     if (version_id >= 8) {
         qemu_put_be64s(f, &env->system_time_msr);
         qemu_put_be64s(f, &env->wall_clock_msr);
+
+        qemu_put_8s(f, &env->soft_interrupt);
+        qemu_put_8s(f, &env->nmi_injected);
+        qemu_put_8s(f, &env->nmi_pending);
+        qemu_put_8s(f, &env->has_error_code);
+        qemu_put_be32s(f, &env->sipi_vector);
     }
 }
 
@@ -346,6 +353,13 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
     if (version_id >= 8) {
         qemu_get_be64s(f, &env->system_time_msr);
         qemu_get_be64s(f, &env->wall_clock_msr);
+
+        qemu_get_8s(f, &env->soft_interrupt);
+        qemu_get_8s(f, &env->nmi_injected);
+        qemu_get_8s(f, &env->nmi_pending);
+        qemu_get_8s(f, &env->has_error_code);
+        qemu_get_be32s(f, &env->sipi_vector);
+        kvm_load_vcpu_events(env);
     }
     return 0;
 }
-- 
1.6.3.rc4.29.g8146