qemu-ppc
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-ppc] [PATCH v3 29/35] spapr/xive, xics: use the CPU_INTC handlers


From: Cédric Le Goater
Subject: [Qemu-ppc] [PATCH v3 29/35] spapr/xive, xics: use the CPU_INTC handlers to reset KVM
Date: Thu, 19 Apr 2018 14:43:25 +0200

The vCPUs are disconnected from the KVM device using a 'disable=1' as
last argument of the KVM_ENABLE_CAP ioctl. This is a bit hacky, we
should probably introduce a KVM_DISABLE_CAP ioctl.

Signed-off-by: Cédric Le Goater <address@hidden>
---
 hw/intc/spapr_xive_kvm.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++--
 hw/intc/xics.c           |  4 ++++
 hw/intc/xics_kvm.c       | 48 ++++++++++++++++++++++++++++++++++++++++--
 hw/intc/xive.c           |  5 +++++
 hw/ppc/spapr_cpu_core.c  |  8 +++++++
 5 files changed, 116 insertions(+), 4 deletions(-)

diff --git a/hw/intc/spapr_xive_kvm.c b/hw/intc/spapr_xive_kvm.c
index ec5613fc2804..e3851991653e 100644
--- a/hw/intc/spapr_xive_kvm.c
+++ b/hw/intc/spapr_xive_kvm.c
@@ -15,6 +15,7 @@
 #include "sysemu/cpus.h"
 #include "sysemu/kvm.h"
 #include "monitor/monitor.h"
+#include "hw/intc/intc.h"
 #include "hw/ppc/spapr.h"
 #include "hw/ppc/spapr_xive.h"
 #include "hw/ppc/xive.h"
@@ -47,6 +48,25 @@ static bool xive_nvt_kvm_cpu_is_enabled(CPUState *cs)
     return false;
 }
 
+static void xive_nvt_kvm_cpu_disable(CPUState *cs, Error **errp)
+{
+    KVMEnabledCPU *enabled_cpu;
+    unsigned long vcpu_id = kvm_arch_vcpu_id(cs);
+
+    QLIST_FOREACH(enabled_cpu, &kvm_enabled_cpus, node) {
+        if (enabled_cpu->vcpu_id == vcpu_id) {
+            break;
+        }
+    }
+
+    if (enabled_cpu->vcpu_id == vcpu_id) {
+        QLIST_REMOVE(enabled_cpu, node);
+        g_free(enabled_cpu);
+    } else {
+        error_setg(errp, "Can not find enabled CPU%ld", vcpu_id);
+    }
+}
+
 static void xive_nvt_kvm_cpu_enable(CPUState *cs)
 {
     KVMEnabledCPU *enabled_cpu;
@@ -183,8 +203,36 @@ static void xive_nvt_kvm_reset(XiveNVT *nvt)
     xive_nvt_kvm_set_state(nvt, 1);
 }
 
-static void xive_nvt_kvm_realize(XiveNVT *nvt, Error **errp)
+static void xive_nvt_kvm_disconnect(CPUIntc *intc, Error **errp)
 {
+    XiveNVT *nvt = XIVE_NVT_KVM(intc);
+    CPUState *cs = nvt->cs;
+    unsigned long vcpu_id = kvm_arch_vcpu_id(cs);
+    int ret;
+
+    if (kernel_xive_fd == -1) {
+        return;
+    }
+
+    /* Disable IRQ capability with a 'disable=1' as last argument.
+     *
+     * This is a bit hacky, we should introduce a KVM_DISABLE_CAP
+     * iotcl
+     */
+    ret = kvm_vcpu_enable_cap(cs, KVM_CAP_PPC_IRQ_XIVE, 0, kernel_xive_fd,
+                              vcpu_id, 1);
+    if (ret < 0) {
+        error_setg(errp, "Unable to disconnect CPU%ld from KVM XIVE device: 
%s",
+                   vcpu_id, strerror(errno));
+        return;
+    }
+
+    xive_nvt_kvm_cpu_disable(cs, errp);
+}
+
+static void xive_nvt_kvm_connect(CPUIntc *intc, Error **errp)
+{
+    XiveNVT *nvt = XIVE_NVT_KVM(intc);
     CPUState *cs = nvt->cs;
     unsigned long vcpu_id = kvm_arch_vcpu_id(cs);
     int ret;
@@ -209,14 +257,17 @@ static void xive_nvt_kvm_class_init(ObjectClass *klass, 
void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
     XiveNVTClass *xnc = XIVE_NVT_CLASS(klass);
+    CPUIntcClass *cic = CPU_INTC_CLASS(klass);
 
     dc->desc = "XIVE KVM Interrupt Presenter";
 
-    xnc->realize = xive_nvt_kvm_realize;
     xnc->synchronize_state = xive_nvt_kvm_synchronize_state;
     xnc->reset = xive_nvt_kvm_reset;
     xnc->pre_save = xive_nvt_kvm_get_state;
     xnc->post_load = xive_nvt_kvm_set_state;
+
+    cic->connect = xive_nvt_kvm_connect;
+    cic->disconnect = xive_nvt_kvm_disconnect;
 }
 
 static const TypeInfo xive_nvt_kvm_info = {
diff --git a/hw/intc/xics.c b/hw/intc/xics.c
index e73e623e3b53..48fed2731fd2 100644
--- a/hw/intc/xics.c
+++ b/hw/intc/xics.c
@@ -381,6 +381,10 @@ static const TypeInfo icp_info = {
     .instance_size = sizeof(ICPState),
     .class_init = icp_class_init,
     .class_size = sizeof(ICPStateClass),
+    .interfaces = (InterfaceInfo[]) {
+        { TYPE_CPU_INTC },
+        { }
+    }
 };
 
 Object *icp_create(Object *cpu, const char *type, XICSFabric *xi, Error **errp)
diff --git a/hw/intc/xics_kvm.c b/hw/intc/xics_kvm.c
index e727397c4a4d..62ea4ea150f2 100644
--- a/hw/intc/xics_kvm.c
+++ b/hw/intc/xics_kvm.c
@@ -32,6 +32,7 @@
 #include "hw/hw.h"
 #include "trace.h"
 #include "sysemu/kvm.h"
+#include "hw/intc/intc.h"
 #include "hw/ppc/spapr.h"
 #include "hw/ppc/xics.h"
 #include "kvm_ppc.h"
@@ -137,8 +138,48 @@ static void icp_kvm_reset(ICPState *icp)
     icp_set_kvm_state(icp, 1);
 }
 
-static void icp_kvm_realize(ICPState *icp, Error **errp)
+static void icp_kvm_disconnect(CPUIntc *intc, Error **errp)
 {
+    ICPState *icp = ICP(intc);
+    CPUState *cs = icp->cs;
+    KVMEnabledICP *enabled_icp;
+    unsigned long vcpu_id = kvm_arch_vcpu_id(cs);
+    int ret;
+
+    if (kernel_xics_fd == -1) {
+        return;
+    }
+
+    /* Disable IRQ capability with a 'disable=1' as last argument.
+     *
+     * This is a bit hacky, we should introduce a KVM_DISABLE_CAP
+     * iotcl
+     */
+    ret = kvm_vcpu_enable_cap(cs, KVM_CAP_IRQ_XICS, 0, kernel_xics_fd,
+                              vcpu_id, 1);
+    if (ret < 0) {
+        error_setg(errp, "Unable to disconnect CPU%ld to kernel XICS: %s",
+                   vcpu_id, strerror(errno));
+        return;
+    }
+
+    QLIST_FOREACH(enabled_icp, &kvm_enabled_icps, node) {
+        if (enabled_icp->vcpu_id == vcpu_id) {
+            break;
+        }
+    }
+
+    if (enabled_icp->vcpu_id == vcpu_id) {
+        QLIST_REMOVE(enabled_icp, node);
+        g_free(enabled_icp);
+    } else {
+        error_setg(errp, "Can not find enabled CPU%ld", vcpu_id);
+    }
+ }
+
+static void icp_kvm_connect(CPUIntc *intc, Error **errp)
+{
+    ICPState *icp = ICP(intc);
     CPUState *cs = icp->cs;
     KVMEnabledICP *enabled_icp;
     unsigned long vcpu_id = kvm_arch_vcpu_id(cs);
@@ -173,12 +214,15 @@ static void icp_kvm_realize(ICPState *icp, Error **errp)
 static void icp_kvm_class_init(ObjectClass *klass, void *data)
 {
     ICPStateClass *icpc = ICP_CLASS(klass);
+    CPUIntcClass *cic = CPU_INTC_CLASS(klass);
 
     icpc->pre_save = icp_get_kvm_state;
     icpc->post_load = icp_set_kvm_state;
-    icpc->realize = icp_kvm_realize;
     icpc->reset = icp_kvm_reset;
     icpc->synchronize_state = icp_synchronize_state;
+
+    cic->connect = icp_kvm_connect;
+    cic->disconnect = icp_kvm_disconnect;
 }
 
 static const TypeInfo icp_kvm_info = {
diff --git a/hw/intc/xive.c b/hw/intc/xive.c
index d96732cfe6be..4a9b09e3d819 100644
--- a/hw/intc/xive.c
+++ b/hw/intc/xive.c
@@ -14,6 +14,7 @@
 #include "sysemu/cpus.h"
 #include "sysemu/dma.h"
 #include "monitor/monitor.h"
+#include "hw/intc/intc.h"
 #include "hw/ppc/xics.h" /* for ICP_PROP_CPU */
 #include "hw/ppc/xive.h"
 #include "hw/ppc/xive_regs.h"
@@ -513,6 +514,10 @@ static const TypeInfo xive_nvt_info = {
     .instance_init = xive_nvt_init,
     .class_init    = xive_nvt_class_init,
     .class_size    = sizeof(XiveNVTClass),
+    .interfaces = (InterfaceInfo[]) {
+        { TYPE_CPU_INTC },
+        { }
+    }
 };
 
 /*
diff --git a/hw/ppc/spapr_cpu_core.c b/hw/ppc/spapr_cpu_core.c
index 3df2bda53f50..aa612cb1c9f6 100644
--- a/hw/ppc/spapr_cpu_core.c
+++ b/hw/ppc/spapr_cpu_core.c
@@ -16,6 +16,7 @@
 #include "sysemu/cpus.h"
 #include "sysemu/kvm.h"
 #include "target/ppc/kvm_ppc.h"
+#include "hw/intc/intc.h"
 #include "hw/ppc/ppc.h"
 #include "target/ppc/mmu-hash64.h"
 #include "sysemu/numa.h"
@@ -105,6 +106,7 @@ static void spapr_cpu_core_unrealizefn(DeviceState *dev, 
Error **errp)
         PowerPCCPU *cpu = POWERPC_CPU(cs);
 
         spapr_cpu_destroy(cpu);
+        cpu_intc_disconnect(CPU_INTC(cpu->intc), NULL);
         object_unparent(cpu->intc);
         cpu_remove_sync(cs);
         object_unparent(obj);
@@ -134,6 +136,10 @@ static void spapr_cpu_core_realize_child(Object *child,
         goto error;
     }
 
+    cpu_intc_connect(CPU_INTC(cpu->intc), &local_err);
+    if (local_err) {
+        goto error;
+    }
     return;
 
 error:
@@ -263,6 +269,7 @@ void spapr_cpu_core_reset_icp(Error **errp)
 
     CPU_FOREACH(cs) {
         PowerPCCPU *cpu = POWERPC_CPU(cs);
+        cpu_intc_disconnect(CPU_INTC(cpu->intc), errp);
         cpu->intc = NULL;
     }
 }
@@ -298,5 +305,6 @@ void spapr_cpu_core_set_icp(const char *icp_type, Error 
**errp)
         }
 
         cpu->intc = args.icp;
+        cpu_intc_connect(CPU_INTC(cpu->intc), errp);
     }
 }
-- 
2.13.6




reply via email to

[Prev in Thread] Current Thread [Next in Thread]