aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGleb Natapov <gleb@redhat.com>2010-05-10 11:21:34 +0300
committerMarcelo Tosatti <mtosatti@redhat.com>2010-05-11 14:03:44 -0300
commit4513d9232badcc5039d69dae946054ba2682c258 (patch)
tree5eb6a23d01375e7123a0674bc48f48171c5c5fe2
parent0af691d779965663abdd7bc708c2ad7bce2f6da0 (diff)
Do not stop VM if emulation failed in userspace.
Continue vcpu execution in case emulation failure happened while vcpu was in userspace. In this case #UD will be injected into the guest allowing guest OS to kill offending process and continue. Signed-off-by: Gleb Natapov <gleb@redhat.com> Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
-rw-r--r--kvm-all.c2
-rw-r--r--kvm.h2
-rw-r--r--target-i386/kvm.c7
-rw-r--r--target-ppc/kvm.c5
-rw-r--r--target-s390x/kvm.c5
5 files changed, 21 insertions, 0 deletions
diff --git a/kvm-all.c b/kvm-all.c
index d06980c000..c238f5421c 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -764,6 +764,8 @@ static void kvm_handle_internal_error(CPUState *env, struct kvm_run *run)
cpu_dump_state(env, stderr, fprintf, 0);
if (run->internal.suberror == KVM_INTERNAL_ERROR_EMULATION) {
fprintf(stderr, "emulation failure\n");
+ if (!kvm_arch_stop_on_emulation_error(env))
+ return;
}
/* FIXME: Should trigger a qmp message to let management know
* something went wrong.
diff --git a/kvm.h b/kvm.h
index 5071a31dec..a28e7aab53 100644
--- a/kvm.h
+++ b/kvm.h
@@ -140,6 +140,8 @@ void kvm_arch_remove_all_hw_breakpoints(void);
void kvm_arch_update_guest_debug(CPUState *env, struct kvm_guest_debug *dbg);
+bool kvm_arch_stop_on_emulation_error(CPUState *env);
+
int kvm_check_extension(KVMState *s, unsigned int extension);
uint32_t kvm_arch_get_supported_cpuid(CPUState *env, uint32_t function,
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index bd7a190678..676aa60791 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -1289,3 +1289,10 @@ void kvm_arch_update_guest_debug(CPUState *env, struct kvm_guest_debug *dbg)
}
}
#endif /* KVM_CAP_SET_GUEST_DEBUG */
+
+bool kvm_arch_stop_on_emulation_error(CPUState *env)
+{
+ return !(env->cr[0] & CR0_PE_MASK) ||
+ ((env->segs[R_CS].selector & 3) != 3);
+}
+
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index 91c0963f88..2625cb8bd9 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -326,3 +326,8 @@ uint32_t kvmppc_get_tbfreq(void)
retval = atoi(ns);
return retval;
}
+
+bool kvm_arch_stop_on_emulation_error(CPUState *env)
+{
+ return true;
+}
diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c
index a2c00acf0f..a2d77419bd 100644
--- a/target-s390x/kvm.c
+++ b/target-s390x/kvm.c
@@ -485,3 +485,8 @@ int kvm_arch_handle_exit(CPUState *env, struct kvm_run *run)
return ret;
}
+
+bool kvm_arch_stop_on_emulation_error(CPUState *env)
+{
+ return true;
+}