aboutsummaryrefslogtreecommitdiff
path: root/target-i386/machine.c
diff options
context:
space:
mode:
authorOrit Wasserman <owasserm@redhat.com>2013-07-22 20:29:42 +0300
committerJuan Quintela <quintela@redhat.com>2013-07-23 14:36:10 +0200
commit3e47c249b93d5cc1e0f9404dbe243682598ba8fb (patch)
treeb720e5ce3f612c46228a9c258b8efde271d72c72 /target-i386/machine.c
parent444ba6797ef6ef331fe9fd34309b1ec59caaede3 (diff)
Fix real mode guest segments dpl value in savevm
Older KVM version put invalid value in the segments registers dpl field for real mode guests (0x3). This breaks migration from those hosts to hosts with unrestricted guest support. We detect it by checking CS dpl value for real mode guest and fix the dpl values of all the segment registers. Signed-off-by: Orit Wasserman <owasserm@redhat.com> Reviewed-by: Juan Quintela <quintela@redhat.com> Signed-off-by: Juan Quintela <quintela@redhat.com>
Diffstat (limited to 'target-i386/machine.c')
-rw-r--r--target-i386/machine.c18
1 files changed, 18 insertions, 0 deletions
diff --git a/target-i386/machine.c b/target-i386/machine.c
index af4c167f84..f9ec581faa 100644
--- a/target-i386/machine.c
+++ b/target-i386/machine.c
@@ -252,6 +252,24 @@ static void cpu_pre_save(void *opaque)
}
env->fpregs_format_vmstate = 0;
+
+ /*
+ * Real mode guest segments register DPL should be zero.
+ * Older KVM version were setting it wrongly.
+ * Fixing it will allow live migration to host with unrestricted guest
+ * support (otherwise the migration will fail with invalid guest state
+ * error).
+ */
+ if (!(env->cr[0] & CR0_PE_MASK) &&
+ (env->segs[R_CS].flags >> DESC_DPL_SHIFT & 3) != 0) {
+ env->segs[R_CS].flags &= ~(env->segs[R_CS].flags & DESC_DPL_MASK);
+ env->segs[R_DS].flags &= ~(env->segs[R_DS].flags & DESC_DPL_MASK);
+ env->segs[R_ES].flags &= ~(env->segs[R_ES].flags & DESC_DPL_MASK);
+ env->segs[R_FS].flags &= ~(env->segs[R_FS].flags & DESC_DPL_MASK);
+ env->segs[R_GS].flags &= ~(env->segs[R_GS].flags & DESC_DPL_MASK);
+ env->segs[R_SS].flags &= ~(env->segs[R_SS].flags & DESC_DPL_MASK);
+ }
+
}
static int cpu_post_load(void *opaque, int version_id)