aboutsummaryrefslogtreecommitdiff
path: root/target/ppc/machine.c
diff options
context:
space:
mode:
authorDaniel Henrique Barboza <danielhb@linux.vnet.ibm.com>2017-08-09 17:43:46 -0300
committerDavid Gibson <david@gibson.dropbear.id.au>2017-08-22 21:26:19 +1000
commitc363a37a450f925df76b88a87dc733bad75cc452 (patch)
tree61bf56699e90c41ad8786bbe9d884c7822dcf082 /target/ppc/machine.c
parentb96919d765a65f5e0f140479f7da0b94521263c6 (diff)
target/ppc: 'PVR != host PVR' in KVM_SET_SREGS workaround
Commit d5fc133eed ("ppc: Rework CPU compatibility testing across migration") changed the way cpu_post_load behaves with the PVR setting, causing an unexpected bug in KVM-HV migrations between hosts that are compatible (POWER8 and POWER8E, for example). Even with pvr_match() returning true, the guest freezes right after cpu_post_load. The reason is that the guest kernel can't handle a different PVR value other that the running host in KVM_SET_SREGS. In [1] it was discussed the possibility of a new KVM capability that would indicate that the guest kernel can handle a different PVR in KVM_SET_SREGS. Even if such feature is implemented, there is still the problem with older kernels that will not have this capability and will fail to migrate. This patch implements a workaround for that scenario. If running with KVM, check if the guest kernel does not have the capability (named here as 'cap_ppc_pvr_compat'). If it doesn't, calls kvmppc_is_pr() to see if the guest is running in KVM-HV. If all this happens, set env->spr[SPR_PVR] to the same value as the current host PVR. This ensures that we allow migrations with 'close enough' PVRs to still work in KVM-HV but also makes the code ready for this new KVM capability when it is done. A new function called 'kvmppc_pvr_workaround_required' was created to encapsulate the conditions said above and to avoid calling too many kvm.c internals inside cpu_post_load. [1] https://lists.gnu.org/archive/html/qemu-ppc/2017-06/msg00503.html Signed-off-by: Daniel Henrique Barboza <danielhb@linux.vnet.ibm.com> [dwg: Fix for the case of using TCG on a PPC host] Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
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]);