aboutsummaryrefslogtreecommitdiff
path: root/target/ppc/kvm.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/kvm.c
parentb96919d765a65f5e0f140479f7da0b94521263c6 (diff)
downloadqemu-c363a37a450f925df76b88a87dc733bad75cc452.zip
qemu-c363a37a450f925df76b88a87dc733bad75cc452.tar.gz
qemu-c363a37a450f925df76b88a87dc733bad75cc452.tar.bz2
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/kvm.c')
-rw-r--r--target/ppc/kvm.c38
1 files changed, 38 insertions, 0 deletions
diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c
index 8571379..f31c67e 100644
--- a/target/ppc/kvm.c
+++ b/target/ppc/kvm.c
@@ -90,6 +90,7 @@ static int cap_htm; /* Hardware transactional memory support */
static int cap_mmu_radix;
static int cap_mmu_hash_v3;
static int cap_resize_hpt;
+static int cap_ppc_pvr_compat;
static uint32_t debug_inst_opcode;
@@ -147,6 +148,13 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
cap_mmu_radix = kvm_vm_check_extension(s, KVM_CAP_PPC_MMU_RADIX);
cap_mmu_hash_v3 = kvm_vm_check_extension(s, KVM_CAP_PPC_MMU_HASH_V3);
cap_resize_hpt = kvm_vm_check_extension(s, KVM_CAP_SPAPR_RESIZE_HPT);
+ /*
+ * Note: setting it to false because there is not such capability
+ * in KVM at this moment.
+ *
+ * TODO: call kvm_vm_check_extension() with the right capability
+ * after the kernel starts implementing it.*/
+ cap_ppc_pvr_compat = false;
if (!cap_interrupt_level) {
fprintf(stderr, "KVM: Couldn't find level irq capability. Expect the "
@@ -2785,3 +2793,33 @@ void kvmppc_update_sdr1(target_ulong sdr1)
run_on_cpu(cs, kvmppc_pivot_hpt_cpu, RUN_ON_CPU_TARGET_PTR(sdr1));
}
}
+
+/*
+ * This is a helper function to detect a post migration scenario
+ * in which a guest, running as KVM-HV, freezes in cpu_post_load because
+ * the guest kernel can't handle a PVR value other than the actual host
+ * PVR in KVM_SET_SREGS, even if pvr_match() returns true.
+ *
+ * If we don't have cap_ppc_pvr_compat and we're not running in PR
+ * (so, we're HV), return true. The workaround itself is done in
+ * cpu_post_load.
+ *
+ * The order here is important: we'll only check for KVM PR as a
+ * fallback if the guest kernel can't handle the situation itself.
+ * We need to avoid as much as possible querying the running KVM type
+ * in QEMU level.
+ */
+bool kvmppc_pvr_workaround_required(PowerPCCPU *cpu)
+{
+ CPUState *cs = CPU(cpu);
+
+ if (!kvm_enabled()) {
+ return false;
+ }
+
+ if (cap_ppc_pvr_compat) {
+ return false;
+ }
+
+ return !kvmppc_is_pr(cs->kvm_state);
+}