diff mbox series

[v3,26/35] spapr/xive: add a XIVE KVM device to the machine

Message ID 20180419124331.3915-27-clg@kaod.org
State New
Headers show
Series ppc: support for the XIVE interrupt controller (POWER9) | expand

Commit Message

Cédric Le Goater April 19, 2018, 12:43 p.m. UTC
As the VM is connected to the KVM interrupt device at the init of the
machine, KVM support is added for XICS or for XIVE but not both at the
same time. This should change later on when KVM resets are supported.

Signed-off-by: Cédric Le Goater <clg@kaod.org>
---
 hw/intc/xics_kvm.c | 22 +++++++++++++++++++++-
 hw/ppc/spapr.c     | 34 +++++++++++++++++++++++-----------
 2 files changed, 44 insertions(+), 12 deletions(-)
diff mbox series

Patch

diff --git a/hw/intc/xics_kvm.c b/hw/intc/xics_kvm.c
index 89fb20e2c55c..e727397c4a4d 100644
--- a/hw/intc/xics_kvm.c
+++ b/hw/intc/xics_kvm.c
@@ -62,6 +62,11 @@  static void icp_get_kvm_state(ICPState *icp)
     };
     int ret;
 
+    /* A change of the interrupt mode can disable XICS */
+    if (kernel_xics_fd == -1) {
+        return;
+    }
+
     /* ICP for this CPU thread is not in use, exiting */
     if (!icp->cs) {
         return;
@@ -102,6 +107,11 @@  static int icp_set_kvm_state(ICPState *icp, int version_id)
     };
     int ret;
 
+    /* Protect resets. A change of the interrupt mode can disable XICS */
+    if (kernel_xics_fd == -1) {
+        return 0;
+    }
+
     /* ICP for this CPU thread is not in use, exiting */
     if (!icp->cs) {
         return 0;
@@ -135,7 +145,7 @@  static void icp_kvm_realize(ICPState *icp, Error **errp)
     int ret;
 
     if (kernel_xics_fd == -1) {
-        abort();
+        return;
     }
 
     /*
@@ -192,6 +202,11 @@  static void ics_get_kvm_state(ICSState *ics)
     };
     int i;
 
+    /* A change of the interrupt mode can disable XICS */
+    if (kernel_xics_fd == -1) {
+        return;
+    }
+
     for (i = 0; i < ics->nr_irqs; i++) {
         ICSIRQState *irq = &ics->irqs[i];
         int ret;
@@ -262,6 +277,11 @@  static int ics_set_kvm_state(ICSState *ics, int version_id)
     };
     int i;
 
+    /* Protect resets. A change of the interrupt mode can disable XICS */
+    if (kernel_xics_fd == -1) {
+        return 0;
+    }
+
     for (i = 0; i < ics->nr_irqs; i++) {
         ICSIRQState *irq = &ics->irqs[i];
         int ret;
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index d05c83cdb322..c98ceeed9d6f 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -189,8 +189,7 @@  static void xics_system_init(MachineState *machine, int nr_irqs, Error **errp)
     sPAPRMachineState *spapr = SPAPR_MACHINE(machine);
 
     if (kvm_enabled()) {
-        if (machine_kernel_irqchip_allowed(machine) &&
-            !xics_kvm_init(spapr, errp)) {
+        if (machine_kernel_irqchip_allowed(machine)) {
             spapr->icp_type = TYPE_KVM_ICP;
             spapr->ics = spapr_ics_create(spapr, TYPE_ICS_KVM, nr_irqs, errp);
         }
@@ -239,10 +238,16 @@  static void xive_system_init(MachineState *machine, int nr_irqs, Error **errp)
 {
     sPAPRMachineState *spapr = SPAPR_MACHINE(machine);
 
-    /* We don't have KVM support yet, so check for irqchip=on */
-    if (kvm_enabled() && machine_kernel_irqchip_required(machine)) {
-        error_report("kernel_irqchip requested. no XIVE support");
-        exit(1);
+    if (kvm_enabled()) {
+        if (machine_kernel_irqchip_allowed(machine)) {
+            spapr->nvt_type = TYPE_XIVE_NVT_KVM;
+            spapr->xive = spapr_xive_create(spapr, TYPE_SPAPR_XIVE_KVM,
+                                            nr_irqs, errp);
+        }
+        if (machine_kernel_irqchip_required(machine) && !spapr->xive) {
+            error_prepend(errp, "kernel_irqchip requested but unavailable: ");
+            return;
+        }
     }
 
     if (spapr->xive) {
@@ -1043,11 +1048,9 @@  static void spapr_dt_ov5_platform_support(sPAPRMachineState *spapr, void *fdt,
         } else {
             val[3] = 0x00; /* Hash */
         }
-        /* TODO: introduce a kvmppc_has_cap_xive() ? Works with
-         * irqchip=off for now
-         */
-        if (spapr->xive_exploitation) {
-            val[1] = 0x80; /* OV5_XIVE_BOTH */
+        /* TODO: when under KVM, only advertise XIVE but not both mode */
+        if (spapr->xive_exploitation && kvmppc_has_cap_xive()) {
+            val[1] = 0x40; /* OV5_XIVE_EXPLOIT */
         }
     } else {
         if (spapr->xive_exploitation) {
@@ -2580,6 +2583,15 @@  static void spapr_machine_init(MachineState *machine)
         /* XIVE uses the full range of IRQ numbers. */
         xive_system_init(machine, XICS_IRQ_BASE + XICS_IRQS_SPAPR,
                          &error_fatal);
+
+        /* TODO: initialize KVM for XIVE or for XICS but not for both */
+        if (kvm_enabled() && machine_kernel_irqchip_allowed(machine)) {
+            xive_kvm_init(spapr->xive, &error_fatal);
+        }
+    } else {
+        if (kvm_enabled() && machine_kernel_irqchip_allowed(machine)) {
+            xics_kvm_init(spapr, &error_fatal);
+        }
     }
 
     /* Set up containers for ibm,client-architecture-support negotiated options