aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
Diffstat (limited to 'hw')
-rw-r--r--hw/intc/xics_kvm.c30
-rw-r--r--hw/ppc/spapr_irq.c13
2 files changed, 43 insertions, 0 deletions
diff --git a/hw/intc/xics_kvm.c b/hw/intc/xics_kvm.c
index 5c4208f..c7f8f5e 100644
--- a/hw/intc/xics_kvm.c
+++ b/hw/intc/xics_kvm.c
@@ -452,3 +452,33 @@ void xics_kvm_disconnect(SpaprMachineState *spapr, Error **errp)
/* Clear the presenter from the VCPUs */
kvm_disable_icps();
}
+
+/*
+ * This is a heuristic to detect older KVMs on POWER9 hosts that don't
+ * support destruction of a KVM XICS device while the VM is running.
+ * Required to start a spapr machine with ic-mode=dual,kernel-irqchip=on.
+ */
+bool xics_kvm_has_broken_disconnect(SpaprMachineState *spapr)
+{
+ int rc;
+
+ rc = kvm_create_device(kvm_state, KVM_DEV_TYPE_XICS, false);
+ if (rc < 0) {
+ /*
+ * The error is ignored on purpose. The KVM XICS setup code
+ * will catch it again anyway. The goal here is to see if
+ * close() actually destroys the device or not.
+ */
+ return false;
+ }
+
+ close(rc);
+
+ rc = kvm_create_device(kvm_state, KVM_DEV_TYPE_XICS, false);
+ if (rc >= 0) {
+ close(rc);
+ return false;
+ }
+
+ return errno == EEXIST;
+}
diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c
index dfb99f3..75654fc 100644
--- a/hw/ppc/spapr_irq.c
+++ b/hw/ppc/spapr_irq.c
@@ -669,6 +669,19 @@ static void spapr_irq_check(SpaprMachineState *spapr, Error **errp)
return;
}
}
+
+ /*
+ * On a POWER9 host, some older KVM XICS devices cannot be destroyed and
+ * re-created. Detect that early to avoid QEMU to exit later when the
+ * guest reboots.
+ */
+ if (kvm_enabled() &&
+ spapr->irq == &spapr_irq_dual &&
+ machine_kernel_irqchip_required(machine) &&
+ xics_kvm_has_broken_disconnect(spapr)) {
+ error_setg(errp, "KVM is too old to support ic-mode=dual,kernel-irqchip=on");
+ return;
+ }
}
/*