aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvi Kivity <avi@redhat.com>2009-12-07 11:11:03 +0200
committerAvi Kivity <avi@redhat.com>2009-12-07 11:11:03 +0200
commitc859bf47e565062b7801a18966913142cf59eda8 (patch)
tree45b0d133200af9e62d052d7145a604e7d3d23cc0 /target-i386
parentMerge commit '40ff6d7e8dceca227e7f8a3e8e0d58b2c66d19b4' into upstream-merge (diff)
parentkvm: x86: Add support for VCPU event states (diff)
downloadqemu-kvm-c859bf47e565062b7801a18966913142cf59eda8.tar.gz
qemu-kvm-c859bf47e565062b7801a18966913142cf59eda8.tar.bz2
qemu-kvm-c859bf47e565062b7801a18966913142cf59eda8.zip
Merge commit 'a0fb002c6462d21ceb9eac8c5772e469ec189374' into upstream-merge
* commit 'a0fb002c6462d21ceb9eac8c5772e469ec189374': kvm: x86: Add support for VCPU event states kvm: x86: Fix merge artifact of f8d926e9 about mp_state targe-ppc: Sync CPU state for KVM target-ppc: Get MMU state on register sync qemu: cleanup unused macros in cirrus qemu: make cirrus init value pci spec compliant Conflicts: kvm-all.c target-i386/kvm.c Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'target-i386')
-rw-r--r--target-i386/cpu.h5
-rw-r--r--target-i386/kvm.c81
-rw-r--r--target-i386/machine.c6
3 files changed, 92 insertions, 0 deletions
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index a638e702b..31412a803 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -711,6 +711,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 552866563..568e2117b 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -226,6 +226,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)
@@ -700,6 +702,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;
@@ -724,6 +793,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;
}
@@ -747,6 +820,14 @@ int kvm_arch_get_registers(CPUState *env)
if (ret < 0)
return ret;
+ ret = kvm_get_mp_state(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 9ac477b35..402eddc7e 100644
--- a/target-i386/machine.c
+++ b/target-i386/machine.c
@@ -460,6 +460,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),
@@ -471,6 +476,7 @@ static const VMStateDescription vmstate_cpu = {
VMSTATE_UINT64_V(system_time_msr, CPUState, 12),
VMSTATE_UINT64_V(wall_clock_msr, CPUState, 12),
VMSTATE_END_OF_LIST()
+ /* The above list is not sorted /wrt version numbers, watch out! */
}
};