aboutsummaryrefslogtreecommitdiff
path: root/target-i386/kvm.c
diff options
context:
space:
mode:
Diffstat (limited to 'target-i386/kvm.c')
-rw-r--r--target-i386/kvm.c77
1 files changed, 77 insertions, 0 deletions
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 89fd7a52b5..3b61a7fc5d 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;
}