aboutsummaryrefslogtreecommitdiff
path: root/target/i386/machine.c
diff options
context:
space:
mode:
Diffstat (limited to 'target/i386/machine.c')
-rw-r--r--target/i386/machine.c45
1 files changed, 21 insertions, 24 deletions
diff --git a/target/i386/machine.c b/target/i386/machine.c
index 704ba6d..b114609 100644
--- a/target/i386/machine.c
+++ b/target/i386/machine.c
@@ -7,6 +7,7 @@
#include "hw/isa/isa.h"
#include "migration/cpu.h"
#include "hyperv.h"
+#include "kvm_i386.h"
#include "sysemu/kvm.h"
#include "sysemu/tcg.h"
@@ -232,10 +233,25 @@ static int cpu_pre_save(void *opaque)
}
#ifdef CONFIG_KVM
- /* Verify we have nested virtualization state from kernel if required */
- if (kvm_enabled() && cpu_has_vmx(env) && !env->nested_state) {
- error_report("Guest enabled nested virtualization but kernel "
- "does not support saving of nested state");
+ /*
+ * In case vCPU may have enabled VMX, we need to make sure kernel have
+ * required capabilities in order to perform migration correctly:
+ *
+ * 1) We must be able to extract vCPU nested-state from KVM.
+ *
+ * 2) In case vCPU is running in guest-mode and it has a pending exception,
+ * we must be able to determine if it's in a pending or injected state.
+ * Note that in case KVM don't have required capability to do so,
+ * a pending/injected exception will always appear as an
+ * injected exception.
+ */
+ if (kvm_enabled() && cpu_vmx_maybe_enabled(env) &&
+ (!env->nested_state ||
+ (!kvm_has_exception_payload() && (env->hflags & HF_GUEST_MASK) &&
+ env->exception_injected))) {
+ error_report("Guest maybe enabled nested virtualization but kernel "
+ "does not support required capabilities to save vCPU "
+ "nested state");
return -EINVAL;
}
#endif
@@ -1019,31 +1035,13 @@ static const VMStateDescription vmstate_vmx_nested_state = {
}
};
-static bool svm_nested_state_needed(void *opaque)
-{
- struct kvm_nested_state *nested_state = opaque;
-
- return (nested_state->format == KVM_STATE_NESTED_FORMAT_SVM);
-}
-
-static const VMStateDescription vmstate_svm_nested_state = {
- .name = "cpu/kvm_nested_state/svm",
- .version_id = 1,
- .minimum_version_id = 1,
- .needed = svm_nested_state_needed,
- .fields = (VMStateField[]) {
- VMSTATE_END_OF_LIST()
- }
-};
-
static bool nested_state_needed(void *opaque)
{
X86CPU *cpu = opaque;
CPUX86State *env = &cpu->env;
return (env->nested_state &&
- (vmx_nested_state_needed(env->nested_state) ||
- svm_nested_state_needed(env->nested_state)));
+ vmx_nested_state_needed(env->nested_state));
}
static int nested_state_post_load(void *opaque, int version_id)
@@ -1105,7 +1103,6 @@ static const VMStateDescription vmstate_kvm_nested_state = {
},
.subsections = (const VMStateDescription*[]) {
&vmstate_vmx_nested_state,
- &vmstate_svm_nested_state,
NULL
}
};