aboutsummaryrefslogtreecommitdiff
path: root/target/ppc/machine.c
diff options
context:
space:
mode:
Diffstat (limited to 'target/ppc/machine.c')
-rw-r--r--target/ppc/machine.c22
1 files changed, 22 insertions, 0 deletions
diff --git a/target/ppc/machine.c b/target/ppc/machine.c
index abe0a1cdf0..e36b7100cb 100644
--- a/target/ppc/machine.c
+++ b/target/ppc/machine.c
@@ -9,6 +9,7 @@
#include "mmu-hash64.h"
#include "migration/cpu.h"
#include "qapi/error.h"
+#include "kvm_ppc.h"
static int cpu_load_old(QEMUFile *f, void *opaque, int version_id)
{
@@ -249,6 +250,27 @@ static int cpu_post_load(void *opaque, int version_id)
}
}
+ /*
+ * If we're running with KVM HV, there is a chance that the guest
+ * is running with KVM HV and its kernel does not have the
+ * capability of dealing with a different PVR other than this
+ * exact host PVR in KVM_SET_SREGS. If that happens, the
+ * guest freezes after migration.
+ *
+ * The function kvmppc_pvr_workaround_required does this verification
+ * by first checking if the kernel has the cap, returning true immediately
+ * if that is the case. Otherwise, it checks if we're running in KVM PR.
+ * If the guest kernel does not have the cap and we're not running KVM-PR
+ * (so, it is running KVM-HV), we need to ensure that KVM_SET_SREGS will
+ * receive the PVR it expects as a workaround.
+ *
+ */
+#if defined(CONFIG_KVM)
+ if (kvmppc_pvr_workaround_required(cpu)) {
+ env->spr[SPR_PVR] = env->spr_cb[SPR_PVR].default_value;
+ }
+#endif
+
env->lr = env->spr[SPR_LR];
env->ctr = env->spr[SPR_CTR];
cpu_write_xer(env, env->spr[SPR_XER]);