All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v4 0/9] sPAPR xics rework/cleanup
@ 2016-09-19  6:29 Nikunj A Dadhania
  2016-09-19  6:29 ` [Qemu-devel] [PATCH v4 1/9] ppc/xics: account correct irq status Nikunj A Dadhania
                   ` (8 more replies)
  0 siblings, 9 replies; 38+ messages in thread
From: Nikunj A Dadhania @ 2016-09-19  6:29 UTC (permalink / raw)
  To: qemu-ppc, david; +Cc: qemu-devel, nikunj, benh, clg

sPAPR xics related changes required for powernv platform. This brings
infrastructure to get the xics native mode for powernv. Tested pseries guests
in KVM and TCG mode. These are the pending patches of the original set.

Changelog v3:
 * Added ICP_Native and XICSNative in "native" implementation
 * Added fix for migration hang when kernel-irqchip=off

Changelog v2:
 * Restore xirr_owner after migration
 * Call icp_resend after restoring all the ICP

Changelog v1:
 * Change XICS to XICS_SPAPR and KVM_XICS to XICS_KVM_SPAPR
 * Added xics_ to function get_cpu_index_by_dt_id as this is a global symbol
 * Dropped server parameter from  icp_check_ipi
 * Send HW_ERROR when ics is NULL
 * Remove redundant parameters in trace routines
 * Use type ICS_SIMPLE, ICS_BASE and ICS_KVM
 * Dropped xics-native and info pic patches for this version

ToDo:
 + xics_spapr_alloc - getting rid of that

Benjamin Herrenschmidt (6):
  ppc/xics: Make the ICSState a list
  ppc/xics: An ICS with offset 0 is assumed to be uninitialized
  ppc/xics: Use a helper to add a new ICS
  ppc/xics: Split ICS into ics-base and ics class
  ppc/xics: Add "native" XICS subclass
  ppc/xics: Add xics to the monitor "info pic" command

Nikunj A Dadhania (3):
  ppc/xics: account correct irq status
  ppc/xics: Fix migration failure with kernel-irqchip=off
  ppc/xics: move set_nr_{irqs,servers} to xics.c

 default-configs/ppc64-softmmu.mak |   3 +-
 hmp-commands-info.hx              |   2 +
 hw/intc/Makefile.objs             |   1 +
 hw/intc/trace-events              |  15 +-
 hw/intc/xics.c                    | 405 ++++++++++++++++++++++++++++----------
 hw/intc/xics_kvm.c                |  55 ++----
 hw/intc/xics_native.c             | 306 ++++++++++++++++++++++++++++
 hw/intc/xics_spapr.c              | 147 +++++++-------
 hw/ppc/ppc.c                      |  14 ++
 hw/ppc/spapr_events.c             |   2 +-
 hw/ppc/spapr_pci.c                |   5 +-
 hw/ppc/spapr_vio.c                |   2 +-
 include/hw/ppc/ppc.h              |   1 +
 include/hw/ppc/xics.h             |  72 +++++--
 monitor.c                         |   4 +
 15 files changed, 787 insertions(+), 247 deletions(-)
 create mode 100644 hw/intc/xics_native.c

-- 
2.7.4

^ permalink raw reply	[flat|nested] 38+ messages in thread

* [Qemu-devel] [PATCH v4 1/9] ppc/xics: account correct irq status
  2016-09-19  6:29 [Qemu-devel] [PATCH v4 0/9] sPAPR xics rework/cleanup Nikunj A Dadhania
@ 2016-09-19  6:29 ` Nikunj A Dadhania
  2016-09-21  6:39   ` David Gibson
  2016-09-19  6:29 ` [Qemu-devel] [PATCH v4 2/9] ppc/xics: Fix migration failure with kernel-irqchip=off Nikunj A Dadhania
                   ` (7 subsequent siblings)
  8 siblings, 1 reply; 38+ messages in thread
From: Nikunj A Dadhania @ 2016-09-19  6:29 UTC (permalink / raw)
  To: qemu-ppc, david; +Cc: qemu-devel, nikunj, benh, clg

Fix inconsistent irq status, because of this in the trace logs, for e.g.
LSI status was 0x7, i.e. XICS_STATUS_ASSERTED, XICS_STATUS_SENT and
XICS_STATUS_REJECTED all set, which did not make sense. So the REJECTED
would have been set in earlier interrupt cycle, and then asserted and
sent in this current one.

Signed-off-by: Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>
---
 hw/intc/xics.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/hw/intc/xics.c b/hw/intc/xics.c
index cd48f42..69162f0 100644
--- a/hw/intc/xics.c
+++ b/hw/intc/xics.c
@@ -505,8 +505,11 @@ static void ics_reject(ICSState *ics, int nr)
     ICSIRQState *irq = ics->irqs + nr - ics->offset;
 
     trace_xics_ics_reject(nr, nr - ics->offset);
-    irq->status |= XICS_STATUS_REJECTED; /* Irrelevant but harmless for LSI */
-    irq->status &= ~XICS_STATUS_SENT; /* Irrelevant but harmless for MSI */
+    if (irq->flags & XICS_FLAGS_IRQ_MSI) {
+        irq->status |= XICS_STATUS_REJECTED;
+    } else if (irq->flags & XICS_FLAGS_IRQ_LSI) {
+        irq->status &= ~XICS_STATUS_SENT;
+    }
 }
 
 static void ics_resend(ICSState *ics)
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [Qemu-devel] [PATCH v4 2/9] ppc/xics: Fix migration failure with kernel-irqchip=off
  2016-09-19  6:29 [Qemu-devel] [PATCH v4 0/9] sPAPR xics rework/cleanup Nikunj A Dadhania
  2016-09-19  6:29 ` [Qemu-devel] [PATCH v4 1/9] ppc/xics: account correct irq status Nikunj A Dadhania
@ 2016-09-19  6:29 ` Nikunj A Dadhania
  2016-09-21  7:21   ` David Gibson
  2016-09-19  6:29 ` [Qemu-devel] [PATCH v4 3/9] ppc/xics: Make the ICSState a list Nikunj A Dadhania
                   ` (6 subsequent siblings)
  8 siblings, 1 reply; 38+ messages in thread
From: Nikunj A Dadhania @ 2016-09-19  6:29 UTC (permalink / raw)
  To: qemu-ppc, david; +Cc: qemu-devel, nikunj, benh, clg

With a single cpu VM running with kernel-irqchip=off and a flood ping
running in the guest. Migration fails once in few times.

Found that whenever there is an interrupt (in this case lsi int 3 from
e1000), we raise an interrupt using qemu_irq_pulse() and also see that
the kvm ioctl is complete.

67351@1468011062.810020:xics_set_irq_lsi set_irq_lsi: srcno 3 [irq 0x1003]
67351@1468011062.810031:xics_icp_irq cpu 0 trying to deliver irq 0x1003 priority 0x5
67351@1468011062.810038:xics_icp_raise raising IRQ new XIRR=0xff001003
new pending priority=0x5

After migration on the target side, interrupts(prio 0x5) are rejected as
there is a interrupt pending (pending_priority 0x5). Moreover, we never
get an icp_accept from the guest, so it hangs and crashes.

Basically, resend the irq pulse(lsi) to the guest.

Signed-off-by: Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>
---
 hw/intc/xics.c | 19 +++++++++++++++----
 1 file changed, 15 insertions(+), 4 deletions(-)

diff --git a/hw/intc/xics.c b/hw/intc/xics.c
index 69162f0..f765b08 100644
--- a/hw/intc/xics.c
+++ b/hw/intc/xics.c
@@ -209,7 +209,7 @@ static const TypeInfo xics_common_info = {
 #define CPPR(ss)   (((ss)->xirr) >> 24)
 
 static void ics_reject(ICSState *ics, int nr);
-static void ics_resend(ICSState *ics);
+static void ics_resend(ICSState *ics, int server);
 static void ics_eoi(ICSState *ics, int nr);
 
 static void icp_check_ipi(XICSState *xics, int server)
@@ -238,7 +238,7 @@ static void icp_resend(XICSState *xics, int server)
     if (ss->mfrr < CPPR(ss)) {
         icp_check_ipi(xics, server);
     }
-    ics_resend(xics->ics);
+    ics_resend(xics->ics, server);
 }
 
 void icp_set_cppr(XICSState *xics, int server, uint8_t cppr)
@@ -512,13 +512,24 @@ static void ics_reject(ICSState *ics, int nr)
     }
 }
 
-static void ics_resend(ICSState *ics)
+static void ics_resend(ICSState *ics, int server)
 {
     int i;
+    ICPState *ss = ics->xics->ss + server;
+    ICSIRQState *irq;
 
     for (i = 0; i < ics->nr_irqs; i++) {
         /* FIXME: filter by server#? */
-        if (ics->irqs[i].flags & XICS_FLAGS_IRQ_LSI) {
+        irq = &ics->irqs[i];
+        if (!(irq->flags & XICS_FLAGS_IRQ_MASK)) {
+            continue;
+        }
+
+        if (irq->flags & XICS_FLAGS_IRQ_LSI) {
+            if (irq->status & XICS_STATUS_SENT) {
+                qemu_irq_raise(ss->output);
+                continue;
+            }
             resend_lsi(ics, i);
         } else {
             resend_msi(ics, i);
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [Qemu-devel] [PATCH v4 3/9] ppc/xics: Make the ICSState a list
  2016-09-19  6:29 [Qemu-devel] [PATCH v4 0/9] sPAPR xics rework/cleanup Nikunj A Dadhania
  2016-09-19  6:29 ` [Qemu-devel] [PATCH v4 1/9] ppc/xics: account correct irq status Nikunj A Dadhania
  2016-09-19  6:29 ` [Qemu-devel] [PATCH v4 2/9] ppc/xics: Fix migration failure with kernel-irqchip=off Nikunj A Dadhania
@ 2016-09-19  6:29 ` Nikunj A Dadhania
  2016-09-19  6:59   ` [Qemu-devel] [Qemu-ppc] " Cédric Le Goater
  2016-09-21  7:48   ` [Qemu-devel] " David Gibson
  2016-09-19  6:29 ` [Qemu-devel] [PATCH v4 4/9] ppc/xics: An ICS with offset 0 is assumed to be uninitialized Nikunj A Dadhania
                   ` (5 subsequent siblings)
  8 siblings, 2 replies; 38+ messages in thread
From: Nikunj A Dadhania @ 2016-09-19  6:29 UTC (permalink / raw)
  To: qemu-ppc, david; +Cc: qemu-devel, nikunj, benh, clg

From: Benjamin Herrenschmidt <benh@kernel.crashing.org>

Instead of an array of fixed sized blocks, use a list, as we will need
to have sources with variable number of interrupts. SPAPR only uses
a single entry. Native will create more. If performance becomes an
issue we can add some hashed lookup but for now this will do fine.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
[ move the initialization of list to xics_common_initfn,
  restore xirr_owner after migration and move restoring to
  icp_post_load]
Signed-off-by: Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>
---
 hw/intc/trace-events  |   5 +-
 hw/intc/xics.c        | 130 ++++++++++++++++++++++++++++++++------------------
 hw/intc/xics_kvm.c    |  27 +++++++----
 hw/intc/xics_spapr.c  |  88 ++++++++++++++++++++++------------
 hw/ppc/spapr_events.c |   2 +-
 hw/ppc/spapr_pci.c    |   5 +-
 hw/ppc/spapr_vio.c    |   2 +-
 include/hw/ppc/xics.h |  13 ++---
 8 files changed, 173 insertions(+), 99 deletions(-)

diff --git a/hw/intc/trace-events b/hw/intc/trace-events
index f12192c..aa342a8 100644
--- a/hw/intc/trace-events
+++ b/hw/intc/trace-events
@@ -56,10 +56,11 @@ xics_set_irq_lsi(int srcno, int nr) "set_irq_lsi: srcno %d [irq %#x]"
 xics_ics_write_xive(int nr, int srcno, int server, uint8_t priority) "ics_write_xive: irq %#x [src %d] server %#x prio %#x"
 xics_ics_reject(int nr, int srcno) "reject irq %#x [src %d]"
 xics_ics_eoi(int nr) "ics_eoi: irq %#x"
-xics_alloc(int src, int irq) "source#%d, irq %d"
-xics_alloc_block(int src, int first, int num, bool lsi, int align) "source#%d, first irq %d, %d irqs, lsi=%d, alignnum %d"
+xics_alloc(int irq) "irq %d"
+xics_alloc_block(int first, int num, bool lsi, int align) "first irq %d, %d irqs, lsi=%d, alignnum %d"
 xics_ics_free(int src, int irq, int num) "Source#%d, first irq %d, %d irqs"
 xics_ics_free_warn(int src, int irq) "Source#%d, irq %d is already free"
+xics_icp_post_load(uint32_t server_no, uint32_t xirr, uint64_t addr, uint8_t pend) "server_no %d, xirr %#x, xirr_owner 0x%" PRIx64 ", pending %d"
 
 # hw/intc/s390_flic_kvm.c
 flic_create_device(int err) "flic: create device failed %d"
diff --git a/hw/intc/xics.c b/hw/intc/xics.c
index f765b08..05e938f 100644
--- a/hw/intc/xics.c
+++ b/hw/intc/xics.c
@@ -32,6 +32,7 @@
 #include "hw/hw.h"
 #include "trace.h"
 #include "qemu/timer.h"
+#include "hw/ppc/spapr.h"
 #include "hw/ppc/xics.h"
 #include "qemu/error-report.h"
 #include "qapi/visitor.h"
@@ -96,13 +97,16 @@ void xics_cpu_setup(XICSState *xics, PowerPCCPU *cpu)
 static void xics_common_reset(DeviceState *d)
 {
     XICSState *xics = XICS_COMMON(d);
+    ICSState *ics;
     int i;
 
     for (i = 0; i < xics->nr_servers; i++) {
         device_reset(DEVICE(&xics->ss[i]));
     }
 
-    device_reset(DEVICE(xics->ics));
+    QLIST_FOREACH(ics, &xics->ics, list) {
+        device_reset(DEVICE(ics));
+    }
 }
 
 static void xics_prop_get_nr_irqs(Object *obj, Visitor *v, const char *name,
@@ -134,7 +138,6 @@ static void xics_prop_set_nr_irqs(Object *obj, Visitor *v, const char *name,
     }
 
     assert(info->set_nr_irqs);
-    assert(xics->ics);
     info->set_nr_irqs(xics, value, errp);
 }
 
@@ -174,6 +177,9 @@ static void xics_prop_set_nr_servers(Object *obj, Visitor *v,
 
 static void xics_common_initfn(Object *obj)
 {
+    XICSState *xics = XICS_COMMON(obj);
+
+    QLIST_INIT(&xics->ics);
     object_property_add(obj, "nr_irqs", "int",
                         xics_prop_get_nr_irqs, xics_prop_set_nr_irqs,
                         NULL, NULL, NULL);
@@ -212,33 +218,35 @@ static void ics_reject(ICSState *ics, int nr);
 static void ics_resend(ICSState *ics, int server);
 static void ics_eoi(ICSState *ics, int nr);
 
-static void icp_check_ipi(XICSState *xics, int server)
+static void icp_check_ipi(ICPState *ss)
 {
-    ICPState *ss = xics->ss + server;
-
     if (XISR(ss) && (ss->pending_priority <= ss->mfrr)) {
         return;
     }
 
-    trace_xics_icp_check_ipi(server, ss->mfrr);
+    trace_xics_icp_check_ipi(ss->cs->cpu_index, ss->mfrr);
 
-    if (XISR(ss)) {
-        ics_reject(xics->ics, XISR(ss));
+    if (XISR(ss) && ss->xirr_owner) {
+        ics_reject(ss->xirr_owner, XISR(ss));
     }
 
     ss->xirr = (ss->xirr & ~XISR_MASK) | XICS_IPI;
     ss->pending_priority = ss->mfrr;
+    ss->xirr_owner = NULL;
     qemu_irq_raise(ss->output);
 }
 
 static void icp_resend(XICSState *xics, int server)
 {
     ICPState *ss = xics->ss + server;
+    ICSState *ics;
 
     if (ss->mfrr < CPPR(ss)) {
-        icp_check_ipi(xics, server);
+        icp_check_ipi(ss);
+    }
+    QLIST_FOREACH(ics, &xics->ics, list) {
+        ics_resend(ics, server);
     }
-    ics_resend(xics->ics, server);
 }
 
 void icp_set_cppr(XICSState *xics, int server, uint8_t cppr)
@@ -256,7 +264,10 @@ void icp_set_cppr(XICSState *xics, int server, uint8_t cppr)
             ss->xirr &= ~XISR_MASK; /* Clear XISR */
             ss->pending_priority = 0xff;
             qemu_irq_lower(ss->output);
-            ics_reject(xics->ics, old_xisr);
+            if (ss->xirr_owner) {
+                ics_reject(ss->xirr_owner, old_xisr);
+                ss->xirr_owner = NULL;
+            }
         }
     } else {
         if (!XISR(ss)) {
@@ -271,7 +282,7 @@ void icp_set_mfrr(XICSState *xics, int server, uint8_t mfrr)
 
     ss->mfrr = mfrr;
     if (mfrr < CPPR(ss)) {
-        icp_check_ipi(xics, server);
+        icp_check_ipi(ss);
     }
 }
 
@@ -282,6 +293,7 @@ uint32_t icp_accept(ICPState *ss)
     qemu_irq_lower(ss->output);
     ss->xirr = ss->pending_priority << 24;
     ss->pending_priority = 0xff;
+    ss->xirr_owner = NULL;
 
     trace_xics_icp_accept(xirr, ss->xirr);
 
@@ -299,30 +311,40 @@ uint32_t icp_ipoll(ICPState *ss, uint32_t *mfrr)
 void icp_eoi(XICSState *xics, int server, uint32_t xirr)
 {
     ICPState *ss = xics->ss + server;
+    ICSState *ics;
+    uint32_t irq;
 
     /* Send EOI -> ICS */
     ss->xirr = (ss->xirr & ~CPPR_MASK) | (xirr & CPPR_MASK);
     trace_xics_icp_eoi(server, xirr, ss->xirr);
-    ics_eoi(xics->ics, xirr & XISR_MASK);
+    irq = xirr & XISR_MASK;
+    QLIST_FOREACH(ics, &xics->ics, list) {
+        if (ics_valid_irq(ics, irq)) {
+            ics_eoi(ics, irq);
+        }
+    }
     if (!XISR(ss)) {
         icp_resend(xics, server);
     }
 }
 
-static void icp_irq(XICSState *xics, int server, int nr, uint8_t priority)
+static void icp_irq(ICSState *ics, int server, int nr, uint8_t priority)
 {
+    XICSState *xics = ics->xics;
     ICPState *ss = xics->ss + server;
 
     trace_xics_icp_irq(server, nr, priority);
 
     if ((priority >= CPPR(ss))
         || (XISR(ss) && (ss->pending_priority <= priority))) {
-        ics_reject(xics->ics, nr);
+        ics_reject(ics, nr);
     } else {
-        if (XISR(ss)) {
-            ics_reject(xics->ics, XISR(ss));
+        if (XISR(ss) && ss->xirr_owner) {
+            ics_reject(ss->xirr_owner, XISR(ss));
+            ss->xirr_owner = NULL;
         }
         ss->xirr = (ss->xirr & ~XISR_MASK) | (nr & XISR_MASK);
+        ss->xirr_owner = ics;
         ss->pending_priority = priority;
         trace_xics_icp_raise(ss->xirr, ss->pending_priority);
         qemu_irq_raise(ss->output);
@@ -378,12 +400,45 @@ static void icp_reset(DeviceState *dev)
     qemu_set_irq(icp->output, 0);
 }
 
+static int icp_post_load(ICPState *ss, int version_id)
+{
+    sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
+    XICSState *xics = spapr->xics;
+    uint32_t irq, i;
+    static uint32_t server_no;
+
+    server_no++;
+    irq = XISR(ss);
+    if (!ss->cs || !irq) {
+        goto icpend;
+    }
+
+    /* Restore the xirr_owner */
+    ss->xirr_owner = xics_find_source(xics, irq);
+
+ icpend:
+    trace_xics_icp_post_load(server_no, ss->xirr, (uint64_t)ss->xirr_owner,
+                             ss->pending_priority);
+    if (xics->nr_servers != server_no) {
+        return 0;
+    }
+
+    /* All the ICPs are processed, now restore all the state */
+    for (i = 0; i < xics->nr_servers; i++) {
+        icp_resend(xics, i);
+    }
+    server_no = 0;
+    return 0;
+}
+
 static void icp_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
+    ICPStateClass *icpc = ICP_CLASS(klass);
 
     dc->reset = icp_reset;
     dc->vmsd = &vmstate_icp_server;
+    icpc->post_load = icp_post_load;
 }
 
 static const TypeInfo icp_info = {
@@ -405,8 +460,7 @@ static void resend_msi(ICSState *ics, int srcno)
     if (irq->status & XICS_STATUS_REJECTED) {
         irq->status &= ~XICS_STATUS_REJECTED;
         if (irq->priority != 0xff) {
-            icp_irq(ics->xics, irq->server, srcno + ics->offset,
-                    irq->priority);
+            icp_irq(ics, irq->server, srcno + ics->offset, irq->priority);
         }
     }
 }
@@ -419,7 +473,7 @@ static void resend_lsi(ICSState *ics, int srcno)
         && (irq->status & XICS_STATUS_ASSERTED)
         && !(irq->status & XICS_STATUS_SENT)) {
         irq->status |= XICS_STATUS_SENT;
-        icp_irq(ics->xics, irq->server, srcno + ics->offset, irq->priority);
+        icp_irq(ics, irq->server, srcno + ics->offset, irq->priority);
     }
 }
 
@@ -434,7 +488,7 @@ static void set_irq_msi(ICSState *ics, int srcno, int val)
             irq->status |= XICS_STATUS_MASKED_PENDING;
             trace_xics_masked_pending();
         } else  {
-            icp_irq(ics->xics, irq->server, srcno + ics->offset, irq->priority);
+            icp_irq(ics, irq->server, srcno + ics->offset, irq->priority);
         }
     }
 }
@@ -473,7 +527,7 @@ static void write_xive_msi(ICSState *ics, int srcno)
     }
 
     irq->status &= ~XICS_STATUS_MASKED_PENDING;
-    icp_irq(ics->xics, irq->server, srcno + ics->offset, irq->priority);
+    icp_irq(ics, irq->server, srcno + ics->offset, irq->priority);
 }
 
 static void write_xive_lsi(ICSState *ics, int srcno)
@@ -568,17 +622,6 @@ static void ics_reset(DeviceState *dev)
     }
 }
 
-static int ics_post_load(ICSState *ics, int version_id)
-{
-    int i;
-
-    for (i = 0; i < ics->xics->nr_servers; i++) {
-        icp_resend(ics->xics, i);
-    }
-
-    return 0;
-}
-
 static void ics_dispatch_pre_save(void *opaque)
 {
     ICSState *ics = opaque;
@@ -653,12 +696,10 @@ static void ics_realize(DeviceState *dev, Error **errp)
 static void ics_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
-    ICSStateClass *isc = ICS_CLASS(klass);
 
     dc->realize = ics_realize;
     dc->vmsd = &vmstate_ics;
     dc->reset = ics_reset;
-    isc->post_load = ics_post_load;
 }
 
 static const TypeInfo ics_info = {
@@ -673,28 +714,23 @@ static const TypeInfo ics_info = {
 /*
  * Exported functions
  */
-int xics_find_source(XICSState *xics, int irq)
+ICSState *xics_find_source(XICSState *xics, int irq)
 {
-    int sources = 1;
-    int src;
+    ICSState *ics;
 
-    /* FIXME: implement multiple sources */
-    for (src = 0; src < sources; ++src) {
-        ICSState *ics = &xics->ics[src];
+    QLIST_FOREACH(ics, &xics->ics, list) {
         if (ics_valid_irq(ics, irq)) {
-            return src;
+            return ics;
         }
     }
-
-    return -1;
+    return NULL;
 }
 
 qemu_irq xics_get_qirq(XICSState *xics, int irq)
 {
-    int src = xics_find_source(xics, irq);
+    ICSState *ics = xics_find_source(xics, irq);
 
-    if (src >= 0) {
-        ICSState *ics = &xics->ics[src];
+    if (ics) {
         return ics->qirqs[irq - ics->offset];
     }
 
diff --git a/hw/intc/xics_kvm.c b/hw/intc/xics_kvm.c
index edbd62f..04fa7cb 100644
--- a/hw/intc/xics_kvm.c
+++ b/hw/intc/xics_kvm.c
@@ -365,7 +365,13 @@ static void xics_kvm_cpu_setup(XICSState *xics, PowerPCCPU *cpu)
 static void xics_kvm_set_nr_irqs(XICSState *xics, uint32_t nr_irqs,
                                  Error **errp)
 {
-    xics->nr_irqs = xics->ics->nr_irqs = nr_irqs;
+    ICSState *ics = QLIST_FIRST(&xics->ics);
+
+    /* This needs to be deprecated ... */
+    xics->nr_irqs = nr_irqs;
+    if (ics) {
+        ics->nr_irqs = nr_irqs;
+    }
 }
 
 static void xics_kvm_set_nr_servers(XICSState *xics, uint32_t nr_servers,
@@ -398,6 +404,7 @@ static void xics_kvm_realize(DeviceState *dev, Error **errp)
 {
     KVMXICSState *xicskvm = XICS_SPAPR_KVM(dev);
     XICSState *xics = XICS_COMMON(dev);
+    ICSState *ics;
     int i, rc;
     Error *error = NULL;
     struct kvm_create_device xics_create_device = {
@@ -449,10 +456,12 @@ static void xics_kvm_realize(DeviceState *dev, Error **errp)
 
     xicskvm->kernel_xics_fd = xics_create_device.fd;
 
-    object_property_set_bool(OBJECT(xics->ics), true, "realized", &error);
-    if (error) {
-        error_propagate(errp, error);
-        goto fail;
+    QLIST_FOREACH(ics, &xics->ics, list) {
+        object_property_set_bool(OBJECT(ics), true, "realized", &error);
+        if (error) {
+            error_propagate(errp, error);
+            goto fail;
+        }
     }
 
     assert(xics->nr_servers);
@@ -481,10 +490,12 @@ fail:
 static void xics_kvm_initfn(Object *obj)
 {
     XICSState *xics = XICS_COMMON(obj);
+    ICSState *ics;
 
-    xics->ics = ICS(object_new(TYPE_KVM_ICS));
-    object_property_add_child(obj, "ics", OBJECT(xics->ics), NULL);
-    xics->ics->xics = xics;
+    ics = ICS(object_new(TYPE_KVM_ICS));
+    object_property_add_child(obj, "ics", OBJECT(ics), NULL);
+    ics->xics = xics;
+    QLIST_INSERT_HEAD(&xics->ics, ics, list);
 }
 
 static void xics_kvm_class_init(ObjectClass *oc, void *data)
diff --git a/hw/intc/xics_spapr.c b/hw/intc/xics_spapr.c
index 618826d..0b0845d 100644
--- a/hw/intc/xics_spapr.c
+++ b/hw/intc/xics_spapr.c
@@ -113,13 +113,17 @@ static void rtas_set_xive(PowerPCCPU *cpu, sPAPRMachineState *spapr,
                           uint32_t nargs, target_ulong args,
                           uint32_t nret, target_ulong rets)
 {
-    ICSState *ics = spapr->xics->ics;
+    ICSState *ics = QLIST_FIRST(&spapr->xics->ics);
     uint32_t nr, server, priority;
 
     if ((nargs != 3) || (nret != 1)) {
         rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
         return;
     }
+    if (!ics) {
+        rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
+        return;
+    }
 
     nr = rtas_ld(args, 0);
     server = xics_get_cpu_index_by_dt_id(rtas_ld(args, 1));
@@ -141,13 +145,17 @@ static void rtas_get_xive(PowerPCCPU *cpu, sPAPRMachineState *spapr,
                           uint32_t nargs, target_ulong args,
                           uint32_t nret, target_ulong rets)
 {
-    ICSState *ics = spapr->xics->ics;
+    ICSState *ics = QLIST_FIRST(&spapr->xics->ics);
     uint32_t nr;
 
     if ((nargs != 1) || (nret != 3)) {
         rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
         return;
     }
+    if (!ics) {
+        rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
+        return;
+    }
 
     nr = rtas_ld(args, 0);
 
@@ -166,13 +174,17 @@ static void rtas_int_off(PowerPCCPU *cpu, sPAPRMachineState *spapr,
                          uint32_t nargs, target_ulong args,
                          uint32_t nret, target_ulong rets)
 {
-    ICSState *ics = spapr->xics->ics;
+    ICSState *ics = QLIST_FIRST(&spapr->xics->ics);
     uint32_t nr;
 
     if ((nargs != 1) || (nret != 1)) {
         rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
         return;
     }
+    if (!ics) {
+        rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
+        return;
+    }
 
     nr = rtas_ld(args, 0);
 
@@ -192,13 +204,17 @@ static void rtas_int_on(PowerPCCPU *cpu, sPAPRMachineState *spapr,
                         uint32_t nargs, target_ulong args,
                         uint32_t nret, target_ulong rets)
 {
-    ICSState *ics = spapr->xics->ics;
+    ICSState *ics = QLIST_FIRST(&spapr->xics->ics);
     uint32_t nr;
 
     if ((nargs != 1) || (nret != 1)) {
         rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
         return;
     }
+    if (!ics) {
+        rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
+        return;
+    }
 
     nr = rtas_ld(args, 0);
 
@@ -217,7 +233,13 @@ static void rtas_int_on(PowerPCCPU *cpu, sPAPRMachineState *spapr,
 static void xics_spapr_set_nr_irqs(XICSState *xics, uint32_t nr_irqs,
                                    Error **errp)
 {
-    xics->nr_irqs = xics->ics->nr_irqs = nr_irqs;
+    ICSState *ics = QLIST_FIRST(&xics->ics);
+
+    /* This needs to be deprecated ... */
+    xics->nr_irqs = nr_irqs;
+    if (ics) {
+        ics->nr_irqs = nr_irqs;
+    }
 }
 
 static void xics_spapr_set_nr_servers(XICSState *xics, uint32_t nr_servers,
@@ -240,6 +262,7 @@ static void xics_spapr_set_nr_servers(XICSState *xics, uint32_t nr_servers,
 static void xics_spapr_realize(DeviceState *dev, Error **errp)
 {
     XICSState *xics = XICS_SPAPR(dev);
+    ICSState *ics;
     Error *error = NULL;
     int i;
 
@@ -261,10 +284,12 @@ static void xics_spapr_realize(DeviceState *dev, Error **errp)
     spapr_register_hypercall(H_EOI, h_eoi);
     spapr_register_hypercall(H_IPOLL, h_ipoll);
 
-    object_property_set_bool(OBJECT(xics->ics), true, "realized", &error);
-    if (error) {
-        error_propagate(errp, error);
-        return;
+    QLIST_FOREACH(ics, &xics->ics, list) {
+        object_property_set_bool(OBJECT(ics), true, "realized", &error);
+        if (error) {
+            error_propagate(errp, error);
+            return;
+        }
     }
 
     for (i = 0; i < xics->nr_servers; i++) {
@@ -280,10 +305,12 @@ static void xics_spapr_realize(DeviceState *dev, Error **errp)
 static void xics_spapr_initfn(Object *obj)
 {
     XICSState *xics = XICS_SPAPR(obj);
+    ICSState *ics;
 
-    xics->ics = ICS(object_new(TYPE_ICS));
-    object_property_add_child(obj, "ics", OBJECT(xics->ics), NULL);
-    xics->ics->xics = xics;
+    ics = ICS(object_new(TYPE_ICS));
+    object_property_add_child(obj, "ics", OBJECT(ics), NULL);
+    ics->xics = xics;
+    QLIST_INSERT_HEAD(&xics->ics, ics, list);
 }
 
 static void xics_spapr_class_init(ObjectClass *oc, void *data)
@@ -329,14 +356,15 @@ static int ics_find_free_block(ICSState *ics, int num, int alignnum)
     return -1;
 }
 
-int xics_spapr_alloc(XICSState *xics, int src, int irq_hint, bool lsi,
-                     Error **errp)
+int xics_spapr_alloc(XICSState *xics, int irq_hint, bool lsi, Error **errp)
 {
-    ICSState *ics = &xics->ics[src];
+    ICSState *ics = QLIST_FIRST(&xics->ics);
     int irq;
 
+    if (!ics) {
+        return -1;
+    }
     if (irq_hint) {
-        assert(src == xics_find_source(xics, irq_hint));
         if (!ICS_IRQ_FREE(ics, irq_hint - ics->offset)) {
             error_setg(errp, "can't allocate IRQ %d: already in use", irq_hint);
             return -1;
@@ -352,7 +380,7 @@ int xics_spapr_alloc(XICSState *xics, int src, int irq_hint, bool lsi,
     }
 
     ics_set_irq_type(ics, irq - ics->offset, lsi);
-    trace_xics_alloc(src, irq);
+    trace_xics_alloc(irq);
 
     return irq;
 }
@@ -361,13 +389,16 @@ int xics_spapr_alloc(XICSState *xics, int src, int irq_hint, bool lsi,
  * Allocate block of consecutive IRQs, and return the number of the first IRQ in
  * the block. If align==true, aligns the first IRQ number to num.
  */
-int xics_spapr_alloc_block(XICSState *xics, int src, int num, bool lsi,
-                           bool align, Error **errp)
+int xics_spapr_alloc_block(XICSState *xics, int num, bool lsi, bool align,
+                           Error **errp)
 {
+    ICSState *ics = QLIST_FIRST(&xics->ics);
     int i, first = -1;
-    ICSState *ics = &xics->ics[src];
 
-    assert(src == 0);
+    if (!ics) {
+        return -1;
+    }
+
     /*
      * MSIMesage::data is used for storing VIRQ so
      * it has to be aligned to num to support multiple
@@ -394,7 +425,7 @@ int xics_spapr_alloc_block(XICSState *xics, int src, int num, bool lsi,
     }
     first += ics->offset;
 
-    trace_xics_alloc_block(src, first, num, lsi, align);
+    trace_xics_alloc_block(first, num, lsi, align);
 
     return first;
 }
@@ -405,7 +436,7 @@ static void ics_free(ICSState *ics, int srcno, int num)
 
     for (i = srcno; i < srcno + num; ++i) {
         if (ICS_IRQ_FREE(ics, i)) {
-            trace_xics_ics_free_warn(ics - ics->xics->ics, i + ics->offset);
+            trace_xics_ics_free_warn(0, i + ics->offset);
         }
         memset(&ics->irqs[i], 0, sizeof(ICSIRQState));
     }
@@ -413,15 +444,10 @@ static void ics_free(ICSState *ics, int srcno, int num)
 
 void xics_spapr_free(XICSState *xics, int irq, int num)
 {
-    int src = xics_find_source(xics, irq);
-
-    if (src >= 0) {
-        ICSState *ics = &xics->ics[src];
-
-        /* FIXME: implement multiple sources */
-        assert(src == 0);
+    ICSState *ics = xics_find_source(xics, irq);
 
-        trace_xics_ics_free(ics - xics->ics, irq, num);
+    if (ics) {
+        trace_xics_ics_free(0, irq, num);
         ics_free(ics, irq - ics->offset, num);
     }
 }
diff --git a/hw/ppc/spapr_events.c b/hw/ppc/spapr_events.c
index b0668b3..adf8da4 100644
--- a/hw/ppc/spapr_events.c
+++ b/hw/ppc/spapr_events.c
@@ -603,7 +603,7 @@ out_no_events:
 void spapr_events_init(sPAPRMachineState *spapr)
 {
     QTAILQ_INIT(&spapr->pending_events);
-    spapr->check_exception_irq = xics_spapr_alloc(spapr->xics, 0, 0, false,
+    spapr->check_exception_irq = xics_spapr_alloc(spapr->xics, 0, false,
                                             &error_fatal);
     spapr->epow_notifier.notify = spapr_powerdown_req;
     qemu_register_powerdown_notifier(&spapr->epow_notifier);
diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
index 949c44f..4d06794 100644
--- a/hw/ppc/spapr_pci.c
+++ b/hw/ppc/spapr_pci.c
@@ -362,7 +362,7 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, sPAPRMachineState *spapr,
     }
 
     /* Allocate MSIs */
-    irq = xics_spapr_alloc_block(spapr->xics, 0, req_num, false,
+    irq = xics_spapr_alloc_block(spapr->xics, req_num, false,
                            ret_intr_type == RTAS_TYPE_MSI, &err);
     if (err) {
         error_reportf_err(err, "Can't allocate MSIs for device %x: ",
@@ -1444,8 +1444,7 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp)
         uint32_t irq;
         Error *local_err = NULL;
 
-        irq = xics_spapr_alloc_block(spapr->xics, 0, 1, true, false,
-                                     &local_err);
+        irq = xics_spapr_alloc_block(spapr->xics, 1, true, false, &local_err);
         if (local_err) {
             error_propagate(errp, local_err);
             error_prepend(errp, "can't allocate LSIs: ");
diff --git a/hw/ppc/spapr_vio.c b/hw/ppc/spapr_vio.c
index f93244d..22360af 100644
--- a/hw/ppc/spapr_vio.c
+++ b/hw/ppc/spapr_vio.c
@@ -463,7 +463,7 @@ static void spapr_vio_busdev_realize(DeviceState *qdev, Error **errp)
         dev->qdev.id = id;
     }
 
-    dev->irq = xics_spapr_alloc(spapr->xics, 0, dev->irq, false, &local_err);
+    dev->irq = xics_spapr_alloc(spapr->xics, dev->irq, false, &local_err);
     if (local_err) {
         error_propagate(errp, local_err);
         return;
diff --git a/include/hw/ppc/xics.h b/include/hw/ppc/xics.h
index 2db9f93..1ea40bd 100644
--- a/include/hw/ppc/xics.h
+++ b/include/hw/ppc/xics.h
@@ -85,7 +85,7 @@ struct XICSState {
     uint32_t nr_servers;
     uint32_t nr_irqs;
     ICPState *ss;
-    ICSState *ics;
+    QLIST_HEAD(, ICSState) ics;
 };
 
 #define TYPE_ICP "icp"
@@ -111,6 +111,7 @@ struct ICPState {
     DeviceState parent_obj;
     /*< public >*/
     CPUState *cs;
+    ICSState *xirr_owner;
     uint32_t xirr;
     uint8_t pending_priority;
     uint8_t mfrr;
@@ -145,6 +146,7 @@ struct ICSState {
     qemu_irq *qirqs;
     ICSIRQState *irqs;
     XICSState *xics;
+    QLIST_ENTRY(ICSState) list;
 };
 
 static inline bool ics_valid_irq(ICSState *ics, uint32_t nr)
@@ -172,10 +174,9 @@ struct ICSIRQState {
 #define XICS_IRQS_SPAPR               1024
 
 qemu_irq xics_get_qirq(XICSState *icp, int irq);
-int xics_spapr_alloc(XICSState *icp, int src, int irq_hint, bool lsi,
-                     Error **errp);
-int xics_spapr_alloc_block(XICSState *icp, int src, int num, bool lsi,
-                           bool align, Error **errp);
+int xics_spapr_alloc(XICSState *icp, int irq_hint, bool lsi, Error **errp);
+int xics_spapr_alloc_block(XICSState *icp, int num, bool lsi, bool align,
+                           Error **errp);
 void xics_spapr_free(XICSState *icp, int irq, int num);
 
 void xics_cpu_setup(XICSState *icp, PowerPCCPU *cpu);
@@ -195,6 +196,6 @@ void ics_write_xive(ICSState *ics, int nr, int server,
 
 void ics_set_irq_type(ICSState *ics, int srcno, bool lsi);
 
-int xics_find_source(XICSState *icp, int irq);
+ICSState *xics_find_source(XICSState *icp, int irq);
 
 #endif /* XICS_H */
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [Qemu-devel] [PATCH v4 4/9] ppc/xics: An ICS with offset 0 is assumed to be uninitialized
  2016-09-19  6:29 [Qemu-devel] [PATCH v4 0/9] sPAPR xics rework/cleanup Nikunj A Dadhania
                   ` (2 preceding siblings ...)
  2016-09-19  6:29 ` [Qemu-devel] [PATCH v4 3/9] ppc/xics: Make the ICSState a list Nikunj A Dadhania
@ 2016-09-19  6:29 ` Nikunj A Dadhania
  2016-09-21  7:50   ` David Gibson
  2016-09-19  6:29 ` [Qemu-devel] [PATCH v4 5/9] ppc/xics: Use a helper to add a new ICS Nikunj A Dadhania
                   ` (4 subsequent siblings)
  8 siblings, 1 reply; 38+ messages in thread
From: Nikunj A Dadhania @ 2016-09-19  6:29 UTC (permalink / raw)
  To: qemu-ppc, david; +Cc: qemu-devel, nikunj, benh, clg

From: Benjamin Herrenschmidt <benh@kernel.crashing.org>

This will make life easier for dealing with dynamically configured
ICSes such as PHB3

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>
---
 include/hw/ppc/xics.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/hw/ppc/xics.h b/include/hw/ppc/xics.h
index 1ea40bd..e49a2da 100644
--- a/include/hw/ppc/xics.h
+++ b/include/hw/ppc/xics.h
@@ -151,7 +151,7 @@ struct ICSState {
 
 static inline bool ics_valid_irq(ICSState *ics, uint32_t nr)
 {
-    return (nr >= ics->offset)
+    return (ics->offset != 0) && (nr >= ics->offset)
         && (nr < (ics->offset + ics->nr_irqs));
 }
 
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [Qemu-devel] [PATCH v4 5/9] ppc/xics: Use a helper to add a new ICS
  2016-09-19  6:29 [Qemu-devel] [PATCH v4 0/9] sPAPR xics rework/cleanup Nikunj A Dadhania
                   ` (3 preceding siblings ...)
  2016-09-19  6:29 ` [Qemu-devel] [PATCH v4 4/9] ppc/xics: An ICS with offset 0 is assumed to be uninitialized Nikunj A Dadhania
@ 2016-09-19  6:29 ` Nikunj A Dadhania
  2016-09-21 23:40   ` David Gibson
  2016-09-19  6:29 ` [Qemu-devel] [PATCH v4 6/9] ppc/xics: Split ICS into ics-base and ics class Nikunj A Dadhania
                   ` (3 subsequent siblings)
  8 siblings, 1 reply; 38+ messages in thread
From: Nikunj A Dadhania @ 2016-09-19  6:29 UTC (permalink / raw)
  To: qemu-ppc, david; +Cc: qemu-devel, nikunj, benh, clg

From: Benjamin Herrenschmidt <benh@kernel.crashing.org>

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
[Move object allocation and adding child to the helper]
Signed-off-by: Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
---
 hw/intc/xics.c        | 10 ++++++++++
 hw/intc/xics_spapr.c  |  6 +-----
 include/hw/ppc/xics.h |  1 +
 3 files changed, 12 insertions(+), 5 deletions(-)

diff --git a/hw/intc/xics.c b/hw/intc/xics.c
index 05e938f..c7901c4 100644
--- a/hw/intc/xics.c
+++ b/hw/intc/xics.c
@@ -109,6 +109,16 @@ static void xics_common_reset(DeviceState *d)
     }
 }
 
+void xics_add_ics(XICSState *xics)
+{
+    ICSState *ics;
+
+    ics = ICS(object_new(TYPE_ICS));
+    object_property_add_child(OBJECT(xics), "ics", OBJECT(ics), NULL);
+    ics->xics = xics;
+    QLIST_INSERT_HEAD(&xics->ics, ics, list);
+}
+
 static void xics_prop_get_nr_irqs(Object *obj, Visitor *v, const char *name,
                                   void *opaque, Error **errp)
 {
diff --git a/hw/intc/xics_spapr.c b/hw/intc/xics_spapr.c
index 0b0845d..270f20e 100644
--- a/hw/intc/xics_spapr.c
+++ b/hw/intc/xics_spapr.c
@@ -305,12 +305,8 @@ static void xics_spapr_realize(DeviceState *dev, Error **errp)
 static void xics_spapr_initfn(Object *obj)
 {
     XICSState *xics = XICS_SPAPR(obj);
-    ICSState *ics;
 
-    ics = ICS(object_new(TYPE_ICS));
-    object_property_add_child(obj, "ics", OBJECT(ics), NULL);
-    ics->xics = xics;
-    QLIST_INSERT_HEAD(&xics->ics, ics, list);
+    xics_add_ics(xics);
 }
 
 static void xics_spapr_class_init(ObjectClass *oc, void *data)
diff --git a/include/hw/ppc/xics.h b/include/hw/ppc/xics.h
index e49a2da..a7a1e54 100644
--- a/include/hw/ppc/xics.h
+++ b/include/hw/ppc/xics.h
@@ -197,5 +197,6 @@ void ics_write_xive(ICSState *ics, int nr, int server,
 void ics_set_irq_type(ICSState *ics, int srcno, bool lsi);
 
 ICSState *xics_find_source(XICSState *icp, int irq);
+void xics_add_ics(XICSState *xics);
 
 #endif /* XICS_H */
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [Qemu-devel] [PATCH v4 6/9] ppc/xics: Split ICS into ics-base and ics class
  2016-09-19  6:29 [Qemu-devel] [PATCH v4 0/9] sPAPR xics rework/cleanup Nikunj A Dadhania
                   ` (4 preceding siblings ...)
  2016-09-19  6:29 ` [Qemu-devel] [PATCH v4 5/9] ppc/xics: Use a helper to add a new ICS Nikunj A Dadhania
@ 2016-09-19  6:29 ` Nikunj A Dadhania
  2016-09-19  7:09   ` [Qemu-devel] [Qemu-ppc] " Cédric Le Goater
  2016-09-19 14:34   ` Cédric Le Goater
  2016-09-19  6:29 ` [Qemu-devel] [PATCH v4 7/9] ppc/xics: Add "native" XICS subclass Nikunj A Dadhania
                   ` (2 subsequent siblings)
  8 siblings, 2 replies; 38+ messages in thread
From: Nikunj A Dadhania @ 2016-09-19  6:29 UTC (permalink / raw)
  To: qemu-ppc, david; +Cc: qemu-devel, nikunj, benh, clg

From: Benjamin Herrenschmidt <benh@kernel.crashing.org>

The existing implementation remains same and ics-base is introduced. The
type name "ics" is retained, and all the related functions renamed as
ics_simple_*

This will allow different implementations for the source controllers
such as the MSI support of PHB3 on Power8 which uses in-memory state
tables for example.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>
---
 hw/intc/trace-events  |  10 ++--
 hw/intc/xics.c        | 143 +++++++++++++++++++++++++++++++-------------------
 hw/intc/xics_kvm.c    |  10 ++--
 hw/intc/xics_spapr.c  |  28 +++++-----
 include/hw/ppc/xics.h |  23 +++++---
 5 files changed, 131 insertions(+), 83 deletions(-)

diff --git a/hw/intc/trace-events b/hw/intc/trace-events
index aa342a8..a367b46 100644
--- a/hw/intc/trace-events
+++ b/hw/intc/trace-events
@@ -50,12 +50,12 @@ xics_icp_accept(uint32_t old_xirr, uint32_t new_xirr) "icp_accept: XIRR %#"PRIx3
 xics_icp_eoi(int server, uint32_t xirr, uint32_t new_xirr) "icp_eoi: server %d given XIRR %#"PRIx32" new XIRR %#"PRIx32
 xics_icp_irq(int server, int nr, uint8_t priority) "cpu %d trying to deliver irq %#"PRIx32" priority %#x"
 xics_icp_raise(uint32_t xirr, uint8_t pending_priority) "raising IRQ new XIRR=%#x new pending priority=%#x"
-xics_set_irq_msi(int srcno, int nr) "set_irq_msi: srcno %d [irq %#x]"
+xics_ics_simple_set_irq_msi(int srcno, int nr) "set_irq_msi: srcno %d [irq %#x]"
 xics_masked_pending(void) "set_irq_msi: masked pending"
-xics_set_irq_lsi(int srcno, int nr) "set_irq_lsi: srcno %d [irq %#x]"
-xics_ics_write_xive(int nr, int srcno, int server, uint8_t priority) "ics_write_xive: irq %#x [src %d] server %#x prio %#x"
-xics_ics_reject(int nr, int srcno) "reject irq %#x [src %d]"
-xics_ics_eoi(int nr) "ics_eoi: irq %#x"
+xics_ics_simple_set_irq_lsi(int srcno, int nr) "set_irq_lsi: srcno %d [irq %#x]"
+xics_ics_simple_write_xive(int nr, int srcno, int server, uint8_t priority) "ics_write_xive: irq %#x [src %d] server %#x prio %#x"
+xics_ics_simple_reject(int nr, int srcno) "reject irq %#x [src %d]"
+xics_ics_simple_eoi(int nr) "ics_eoi: irq %#x"
 xics_alloc(int irq) "irq %d"
 xics_alloc_block(int first, int num, bool lsi, int align) "first irq %d, %d irqs, lsi=%d, alignnum %d"
 xics_ics_free(int src, int irq, int num) "Source#%d, first irq %d, %d irqs"
diff --git a/hw/intc/xics.c b/hw/intc/xics.c
index c7901c4..b15751e 100644
--- a/hw/intc/xics.c
+++ b/hw/intc/xics.c
@@ -113,7 +113,7 @@ void xics_add_ics(XICSState *xics)
 {
     ICSState *ics;
 
-    ics = ICS(object_new(TYPE_ICS));
+    ics = ICS_SIMPLE(object_new(TYPE_ICS_SIMPLE));
     object_property_add_child(OBJECT(xics), "ics", OBJECT(ics), NULL);
     ics->xics = xics;
     QLIST_INSERT_HEAD(&xics->ics, ics, list);
@@ -224,9 +224,32 @@ static const TypeInfo xics_common_info = {
 #define XISR(ss)   (((ss)->xirr) & XISR_MASK)
 #define CPPR(ss)   (((ss)->xirr) >> 24)
 
-static void ics_reject(ICSState *ics, int nr);
-static void ics_resend(ICSState *ics, int server);
-static void ics_eoi(ICSState *ics, int nr);
+static void ics_reject(ICSState *ics, uint32_t nr)
+{
+    ICSStateClass *k = ICS_GET_CLASS(ics);
+
+    if (k->reject) {
+        k->reject(ics, nr);
+    }
+}
+
+static void ics_resend(ICSState *ics, int server)
+{
+    ICSStateClass *k = ICS_GET_CLASS(ics);
+
+    if (k->resend) {
+        k->resend(ics, server);
+    }
+}
+
+static void ics_eoi(ICSState *ics, int nr)
+{
+    ICSStateClass *k = ICS_GET_CLASS(ics);
+
+    if (k->eoi) {
+        k->eoi(ics, nr);
+    }
+}
 
 static void icp_check_ipi(ICPState *ss)
 {
@@ -462,7 +485,7 @@ static const TypeInfo icp_info = {
 /*
  * ICS: Source layer
  */
-static void resend_msi(ICSState *ics, int srcno)
+static void ics_simple_resend_msi(ICSState *ics, int srcno)
 {
     ICSIRQState *irq = ics->irqs + srcno;
 
@@ -475,7 +498,7 @@ static void resend_msi(ICSState *ics, int srcno)
     }
 }
 
-static void resend_lsi(ICSState *ics, int srcno)
+static void ics_simple_resend_lsi(ICSState *ics, int srcno)
 {
     ICSIRQState *irq = ics->irqs + srcno;
 
@@ -487,11 +510,11 @@ static void resend_lsi(ICSState *ics, int srcno)
     }
 }
 
-static void set_irq_msi(ICSState *ics, int srcno, int val)
+static void ics_simple_set_irq_msi(ICSState *ics, int srcno, int val)
 {
     ICSIRQState *irq = ics->irqs + srcno;
 
-    trace_xics_set_irq_msi(srcno, srcno + ics->offset);
+    trace_xics_ics_simple_set_irq_msi(srcno, srcno + ics->offset);
 
     if (val) {
         if (irq->priority == 0xff) {
@@ -503,31 +526,31 @@ static void set_irq_msi(ICSState *ics, int srcno, int val)
     }
 }
 
-static void set_irq_lsi(ICSState *ics, int srcno, int val)
+static void ics_simple_set_irq_lsi(ICSState *ics, int srcno, int val)
 {
     ICSIRQState *irq = ics->irqs + srcno;
 
-    trace_xics_set_irq_lsi(srcno, srcno + ics->offset);
+    trace_xics_ics_simple_set_irq_lsi(srcno, srcno + ics->offset);
     if (val) {
         irq->status |= XICS_STATUS_ASSERTED;
     } else {
         irq->status &= ~XICS_STATUS_ASSERTED;
     }
-    resend_lsi(ics, srcno);
+    ics_simple_resend_lsi(ics, srcno);
 }
 
-static void ics_set_irq(void *opaque, int srcno, int val)
+static void ics_simple_set_irq(void *opaque, int srcno, int val)
 {
     ICSState *ics = (ICSState *)opaque;
 
     if (ics->irqs[srcno].flags & XICS_FLAGS_IRQ_LSI) {
-        set_irq_lsi(ics, srcno, val);
+        ics_simple_set_irq_lsi(ics, srcno, val);
     } else {
-        set_irq_msi(ics, srcno, val);
+        ics_simple_set_irq_msi(ics, srcno, val);
     }
 }
 
-static void write_xive_msi(ICSState *ics, int srcno)
+static void ics_simple_write_xive_msi(ICSState *ics, int srcno)
 {
     ICSIRQState *irq = ics->irqs + srcno;
 
@@ -540,35 +563,35 @@ static void write_xive_msi(ICSState *ics, int srcno)
     icp_irq(ics, irq->server, srcno + ics->offset, irq->priority);
 }
 
-static void write_xive_lsi(ICSState *ics, int srcno)
+static void ics_simple_write_xive_lsi(ICSState *ics, int srcno)
 {
-    resend_lsi(ics, srcno);
+    ics_simple_resend_lsi(ics, srcno);
 }
 
-void ics_write_xive(ICSState *ics, int nr, int server,
-                    uint8_t priority, uint8_t saved_priority)
+void ics_simple_write_xive(ICSState *ics, int srcno, int server,
+                           uint8_t priority, uint8_t saved_priority)
 {
-    int srcno = nr - ics->offset;
     ICSIRQState *irq = ics->irqs + srcno;
 
     irq->server = server;
     irq->priority = priority;
     irq->saved_priority = saved_priority;
 
-    trace_xics_ics_write_xive(nr, srcno, server, priority);
+    trace_xics_ics_simple_write_xive(ics->offset + srcno, srcno, server,
+                                     priority);
 
     if (ics->irqs[srcno].flags & XICS_FLAGS_IRQ_LSI) {
-        write_xive_lsi(ics, srcno);
+        ics_simple_write_xive_lsi(ics, srcno);
     } else {
-        write_xive_msi(ics, srcno);
+        ics_simple_write_xive_msi(ics, srcno);
     }
 }
 
-static void ics_reject(ICSState *ics, int nr)
+static void ics_simple_reject(ICSState *ics, uint32_t nr)
 {
     ICSIRQState *irq = ics->irqs + nr - ics->offset;
 
-    trace_xics_ics_reject(nr, nr - ics->offset);
+    trace_xics_ics_simple_reject(nr, nr - ics->offset);
     if (irq->flags & XICS_FLAGS_IRQ_MSI) {
         irq->status |= XICS_STATUS_REJECTED;
     } else if (irq->flags & XICS_FLAGS_IRQ_LSI) {
@@ -576,7 +599,7 @@ static void ics_reject(ICSState *ics, int nr)
     }
 }
 
-static void ics_resend(ICSState *ics, int server)
+static void ics_simple_resend(ICSState *ics, int server)
 {
     int i;
     ICPState *ss = ics->xics->ss + server;
@@ -594,28 +617,28 @@ static void ics_resend(ICSState *ics, int server)
                 qemu_irq_raise(ss->output);
                 continue;
             }
-            resend_lsi(ics, i);
+            ics_simple_resend_lsi(ics, i);
         } else {
-            resend_msi(ics, i);
+            ics_simple_resend_msi(ics, i);
         }
     }
 }
 
-static void ics_eoi(ICSState *ics, int nr)
+static void ics_simple_eoi(ICSState *ics, uint32_t nr)
 {
     int srcno = nr - ics->offset;
     ICSIRQState *irq = ics->irqs + srcno;
 
-    trace_xics_ics_eoi(nr);
+    trace_xics_ics_simple_eoi(nr);
 
     if (ics->irqs[srcno].flags & XICS_FLAGS_IRQ_LSI) {
         irq->status &= ~XICS_STATUS_SENT;
     }
 }
 
-static void ics_reset(DeviceState *dev)
+static void ics_simple_reset(DeviceState *dev)
 {
-    ICSState *ics = ICS(dev);
+    ICSState *ics = ICS_SIMPLE(dev);
     int i;
     uint8_t flags[ics->nr_irqs];
 
@@ -632,7 +655,7 @@ static void ics_reset(DeviceState *dev)
     }
 }
 
-static void ics_dispatch_pre_save(void *opaque)
+static void ics_simple_dispatch_pre_save(void *opaque)
 {
     ICSState *ics = opaque;
     ICSStateClass *info = ICS_GET_CLASS(ics);
@@ -642,7 +665,7 @@ static void ics_dispatch_pre_save(void *opaque)
     }
 }
 
-static int ics_dispatch_post_load(void *opaque, int version_id)
+static int ics_simple_dispatch_post_load(void *opaque, int version_id)
 {
     ICSState *ics = opaque;
     ICSStateClass *info = ICS_GET_CLASS(ics);
@@ -654,7 +677,7 @@ static int ics_dispatch_post_load(void *opaque, int version_id)
     return 0;
 }
 
-static const VMStateDescription vmstate_ics_irq = {
+static const VMStateDescription vmstate_ics_simple_irq = {
     .name = "ics/irq",
     .version_id = 2,
     .minimum_version_id = 1,
@@ -668,57 +691,70 @@ static const VMStateDescription vmstate_ics_irq = {
     },
 };
 
-static const VMStateDescription vmstate_ics = {
+static const VMStateDescription vmstate_ics_simple = {
     .name = "ics",
     .version_id = 1,
     .minimum_version_id = 1,
-    .pre_save = ics_dispatch_pre_save,
-    .post_load = ics_dispatch_post_load,
+    .pre_save = ics_simple_dispatch_pre_save,
+    .post_load = ics_simple_dispatch_post_load,
     .fields = (VMStateField[]) {
         /* Sanity check */
         VMSTATE_UINT32_EQUAL(nr_irqs, ICSState),
 
         VMSTATE_STRUCT_VARRAY_POINTER_UINT32(irqs, ICSState, nr_irqs,
-                                             vmstate_ics_irq, ICSIRQState),
+                                             vmstate_ics_simple_irq,
+                                             ICSIRQState),
         VMSTATE_END_OF_LIST()
     },
 };
 
-static void ics_initfn(Object *obj)
+static void ics_simple_initfn(Object *obj)
 {
-    ICSState *ics = ICS(obj);
+    ICSState *ics = ICS_SIMPLE(obj);
 
     ics->offset = XICS_IRQ_BASE;
 }
 
-static void ics_realize(DeviceState *dev, Error **errp)
+static void ics_simple_realize(DeviceState *dev, Error **errp)
 {
-    ICSState *ics = ICS(dev);
+    ICSState *ics = ICS_SIMPLE(dev);
 
     if (!ics->nr_irqs) {
         error_setg(errp, "Number of interrupts needs to be greater 0");
         return;
     }
     ics->irqs = g_malloc0(ics->nr_irqs * sizeof(ICSIRQState));
-    ics->qirqs = qemu_allocate_irqs(ics_set_irq, ics, ics->nr_irqs);
+    ics->qirqs = qemu_allocate_irqs(ics_simple_set_irq, ics, ics->nr_irqs);
 }
 
-static void ics_class_init(ObjectClass *klass, void *data)
+static void ics_simple_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
+    ICSStateClass *isc = ICS_CLASS(klass);
 
-    dc->realize = ics_realize;
-    dc->vmsd = &vmstate_ics;
-    dc->reset = ics_reset;
+    dc->realize = ics_simple_realize;
+    dc->vmsd = &vmstate_ics_simple;
+    dc->reset = ics_simple_reset;
+    isc->reject = ics_simple_reject;
+    isc->resend = ics_simple_resend;
+    isc->eoi = ics_simple_eoi;
 }
 
-static const TypeInfo ics_info = {
-    .name = TYPE_ICS,
+static const TypeInfo ics_simple_info = {
+    .name = TYPE_ICS_SIMPLE,
+    .parent = TYPE_ICS_BASE,
+    .instance_size = sizeof(ICSState),
+    .class_init = ics_simple_class_init,
+    .class_size = sizeof(ICSStateClass),
+    .instance_init = ics_simple_initfn,
+};
+
+static const TypeInfo ics_base_info = {
+    .name = TYPE_ICS_BASE,
     .parent = TYPE_DEVICE,
+    .abstract = true,
     .instance_size = sizeof(ICSState),
-    .class_init = ics_class_init,
     .class_size = sizeof(ICSStateClass),
-    .instance_init = ics_initfn,
 };
 
 /*
@@ -758,7 +794,8 @@ void ics_set_irq_type(ICSState *ics, int srcno, bool lsi)
 static void xics_register_types(void)
 {
     type_register_static(&xics_common_info);
-    type_register_static(&ics_info);
+    type_register_static(&ics_simple_info);
+    type_register_static(&ics_base_info);
     type_register_static(&icp_info);
 }
 
diff --git a/hw/intc/xics_kvm.c b/hw/intc/xics_kvm.c
index 04fa7cb..89862df 100644
--- a/hw/intc/xics_kvm.c
+++ b/hw/intc/xics_kvm.c
@@ -272,7 +272,7 @@ static void ics_kvm_set_irq(void *opaque, int srcno, int val)
 
 static void ics_kvm_reset(DeviceState *dev)
 {
-    ICSState *ics = ICS(dev);
+    ICSState *ics = ICS_SIMPLE(dev);
     int i;
     uint8_t flags[ics->nr_irqs];
 
@@ -293,7 +293,7 @@ static void ics_kvm_reset(DeviceState *dev)
 
 static void ics_kvm_realize(DeviceState *dev, Error **errp)
 {
-    ICSState *ics = ICS(dev);
+    ICSState *ics = ICS_SIMPLE(dev);
 
     if (!ics->nr_irqs) {
         error_setg(errp, "Number of interrupts needs to be greater 0");
@@ -315,8 +315,8 @@ static void ics_kvm_class_init(ObjectClass *klass, void *data)
 }
 
 static const TypeInfo ics_kvm_info = {
-    .name = TYPE_KVM_ICS,
-    .parent = TYPE_ICS,
+    .name = TYPE_ICS_KVM,
+    .parent = TYPE_ICS_SIMPLE,
     .instance_size = sizeof(ICSState),
     .class_init = ics_kvm_class_init,
 };
@@ -492,7 +492,7 @@ static void xics_kvm_initfn(Object *obj)
     XICSState *xics = XICS_COMMON(obj);
     ICSState *ics;
 
-    ics = ICS(object_new(TYPE_KVM_ICS));
+    ics = ICS_SIMPLE(object_new(TYPE_ICS_KVM));
     object_property_add_child(obj, "ics", OBJECT(ics), NULL);
     ics->xics = xics;
     QLIST_INSERT_HEAD(&xics->ics, ics, list);
diff --git a/hw/intc/xics_spapr.c b/hw/intc/xics_spapr.c
index 270f20e..4dd1399 100644
--- a/hw/intc/xics_spapr.c
+++ b/hw/intc/xics_spapr.c
@@ -114,7 +114,7 @@ static void rtas_set_xive(PowerPCCPU *cpu, sPAPRMachineState *spapr,
                           uint32_t nret, target_ulong rets)
 {
     ICSState *ics = QLIST_FIRST(&spapr->xics->ics);
-    uint32_t nr, server, priority;
+    uint32_t nr, srcno, server, priority;
 
     if ((nargs != 3) || (nret != 1)) {
         rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
@@ -135,7 +135,8 @@ static void rtas_set_xive(PowerPCCPU *cpu, sPAPRMachineState *spapr,
         return;
     }
 
-    ics_write_xive(ics, nr, server, priority, priority);
+    srcno = nr - ics->offset;
+    ics_simple_write_xive(ics, srcno, server, priority, priority);
 
     rtas_st(rets, 0, RTAS_OUT_SUCCESS);
 }
@@ -146,7 +147,7 @@ static void rtas_get_xive(PowerPCCPU *cpu, sPAPRMachineState *spapr,
                           uint32_t nret, target_ulong rets)
 {
     ICSState *ics = QLIST_FIRST(&spapr->xics->ics);
-    uint32_t nr;
+    uint32_t nr, srcno;
 
     if ((nargs != 1) || (nret != 3)) {
         rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
@@ -165,8 +166,9 @@ static void rtas_get_xive(PowerPCCPU *cpu, sPAPRMachineState *spapr,
     }
 
     rtas_st(rets, 0, RTAS_OUT_SUCCESS);
-    rtas_st(rets, 1, ics->irqs[nr - ics->offset].server);
-    rtas_st(rets, 2, ics->irqs[nr - ics->offset].priority);
+    srcno = nr - ics->offset;
+    rtas_st(rets, 1, ics->irqs[srcno].server);
+    rtas_st(rets, 2, ics->irqs[srcno].priority);
 }
 
 static void rtas_int_off(PowerPCCPU *cpu, sPAPRMachineState *spapr,
@@ -175,7 +177,7 @@ static void rtas_int_off(PowerPCCPU *cpu, sPAPRMachineState *spapr,
                          uint32_t nret, target_ulong rets)
 {
     ICSState *ics = QLIST_FIRST(&spapr->xics->ics);
-    uint32_t nr;
+    uint32_t nr, srcno;
 
     if ((nargs != 1) || (nret != 1)) {
         rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
@@ -193,8 +195,9 @@ static void rtas_int_off(PowerPCCPU *cpu, sPAPRMachineState *spapr,
         return;
     }
 
-    ics_write_xive(ics, nr, ics->irqs[nr - ics->offset].server, 0xff,
-                   ics->irqs[nr - ics->offset].priority);
+    srcno = nr - ics->offset;
+    ics_simple_write_xive(ics, srcno, ics->irqs[srcno].server, 0xff,
+                          ics->irqs[srcno].priority);
 
     rtas_st(rets, 0, RTAS_OUT_SUCCESS);
 }
@@ -205,7 +208,7 @@ static void rtas_int_on(PowerPCCPU *cpu, sPAPRMachineState *spapr,
                         uint32_t nret, target_ulong rets)
 {
     ICSState *ics = QLIST_FIRST(&spapr->xics->ics);
-    uint32_t nr;
+    uint32_t nr, srcno;
 
     if ((nargs != 1) || (nret != 1)) {
         rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
@@ -223,9 +226,10 @@ static void rtas_int_on(PowerPCCPU *cpu, sPAPRMachineState *spapr,
         return;
     }
 
-    ics_write_xive(ics, nr, ics->irqs[nr - ics->offset].server,
-                   ics->irqs[nr - ics->offset].saved_priority,
-                   ics->irqs[nr - ics->offset].saved_priority);
+    srcno = nr - ics->offset;
+    ics_simple_write_xive(ics, srcno, ics->irqs[srcno].server,
+                          ics->irqs[srcno].saved_priority,
+                          ics->irqs[srcno].saved_priority);
 
     rtas_st(rets, 0, RTAS_OUT_SUCCESS);
 }
diff --git a/include/hw/ppc/xics.h b/include/hw/ppc/xics.h
index a7a1e54..2231f2a 100644
--- a/include/hw/ppc/xics.h
+++ b/include/hw/ppc/xics.h
@@ -119,22 +119,29 @@ struct ICPState {
     bool cap_irq_xics_enabled;
 };
 
-#define TYPE_ICS "ics"
-#define ICS(obj) OBJECT_CHECK(ICSState, (obj), TYPE_ICS)
+#define TYPE_ICS_BASE "ics-base"
+#define ICS_BASE(obj) OBJECT_CHECK(ICSState, (obj), TYPE_ICS_SIMPLE)
 
-#define TYPE_KVM_ICS "icskvm"
-#define KVM_ICS(obj) OBJECT_CHECK(ICSState, (obj), TYPE_KVM_ICS)
+/* Retain ics for sPAPR for migration from existing sPAPR guests */
+#define TYPE_ICS_SIMPLE "ics"
+#define ICS_SIMPLE(obj) OBJECT_CHECK(ICSState, (obj), TYPE_ICS_SIMPLE)
+
+#define TYPE_ICS_KVM "icskvm"
+#define ICS_KVM(obj) OBJECT_CHECK(ICSState, (obj), TYPE_ICS_KVM)
 
 #define ICS_CLASS(klass) \
-     OBJECT_CLASS_CHECK(ICSStateClass, (klass), TYPE_ICS)
+     OBJECT_CLASS_CHECK(ICSStateClass, (klass), TYPE_ICS_SIMPLE)
 #define ICS_GET_CLASS(obj) \
-     OBJECT_GET_CLASS(ICSStateClass, (obj), TYPE_ICS)
+     OBJECT_GET_CLASS(ICSStateClass, (obj), TYPE_ICS_SIMPLE)
 
 struct ICSStateClass {
     DeviceClass parent_class;
 
     void (*pre_save)(ICSState *s);
     int (*post_load)(ICSState *s, int version_id);
+    void (*reject)(ICSState *s, uint32_t irq);
+    void (*resend)(ICSState *s, int server);
+    void (*eoi)(ICSState *s, uint32_t irq);
 };
 
 struct ICSState {
@@ -191,8 +198,8 @@ uint32_t icp_accept(ICPState *ss);
 uint32_t icp_ipoll(ICPState *ss, uint32_t *mfrr);
 void icp_eoi(XICSState *icp, int server, uint32_t xirr);
 
-void ics_write_xive(ICSState *ics, int nr, int server,
-                    uint8_t priority, uint8_t saved_priority);
+void ics_simple_write_xive(ICSState *ics, int nr, int server,
+                           uint8_t priority, uint8_t saved_priority);
 
 void ics_set_irq_type(ICSState *ics, int srcno, bool lsi);
 
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [Qemu-devel] [PATCH v4 7/9] ppc/xics: Add "native" XICS subclass
  2016-09-19  6:29 [Qemu-devel] [PATCH v4 0/9] sPAPR xics rework/cleanup Nikunj A Dadhania
                   ` (5 preceding siblings ...)
  2016-09-19  6:29 ` [Qemu-devel] [PATCH v4 6/9] ppc/xics: Split ICS into ics-base and ics class Nikunj A Dadhania
@ 2016-09-19  6:29 ` Nikunj A Dadhania
  2016-09-19  7:03   ` [Qemu-devel] [Qemu-ppc] " Cédric Le Goater
  2016-09-22  0:02   ` [Qemu-devel] " David Gibson
  2016-09-19  6:29 ` [Qemu-devel] [PATCH v4 8/9] ppc/xics: Add xics to the monitor "info pic" command Nikunj A Dadhania
  2016-09-19  6:29 ` [Qemu-devel] [PATCH v4 9/9] ppc/xics: move set_nr_{irqs, servers} to xics.c Nikunj A Dadhania
  8 siblings, 2 replies; 38+ messages in thread
From: Nikunj A Dadhania @ 2016-09-19  6:29 UTC (permalink / raw)
  To: qemu-ppc, david; +Cc: qemu-devel, nikunj, benh, clg

From: Benjamin Herrenschmidt <benh@kernel.crashing.org>

This provides MMIO based ICP access as found on POWER8

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>
---
 default-configs/ppc64-softmmu.mak |   3 +-
 hw/intc/Makefile.objs             |   1 +
 hw/intc/xics_native.c             | 295 ++++++++++++++++++++++++++++++++++++++
 include/hw/ppc/xics.h             |  14 ++
 4 files changed, 312 insertions(+), 1 deletion(-)
 create mode 100644 hw/intc/xics_native.c

diff --git a/default-configs/ppc64-softmmu.mak b/default-configs/ppc64-softmmu.mak
index c4be59f..315e30b 100644
--- a/default-configs/ppc64-softmmu.mak
+++ b/default-configs/ppc64-softmmu.mak
@@ -48,8 +48,9 @@ CONFIG_PLATFORM_BUS=y
 CONFIG_ETSEC=y
 CONFIG_LIBDECNUMBER=y
 # For pSeries
-CONFIG_XICS=$(CONFIG_PSERIES)
+CONFIG_XICS=$(or $(CONFIG_PSERIES),$(CONFIG_POWERNV))
 CONFIG_XICS_SPAPR=$(CONFIG_PSERIES)
+CONFIG_XICS_NATIVE=$(CONFIG_POWERNV)
 CONFIG_XICS_KVM=$(and $(CONFIG_PSERIES),$(CONFIG_KVM))
 # For PReP
 CONFIG_MC146818RTC=y
diff --git a/hw/intc/Makefile.objs b/hw/intc/Makefile.objs
index 05ec21b..7be5dfc 100644
--- a/hw/intc/Makefile.objs
+++ b/hw/intc/Makefile.objs
@@ -31,6 +31,7 @@ obj-$(CONFIG_RASPI) += bcm2835_ic.o bcm2836_control.o
 obj-$(CONFIG_SH4) += sh_intc.o
 obj-$(CONFIG_XICS) += xics.o
 obj-$(CONFIG_XICS_SPAPR) += xics_spapr.o
+obj-$(CONFIG_XICS_NATIVE) += xics_native.o
 obj-$(CONFIG_XICS_KVM) += xics_kvm.o
 obj-$(CONFIG_ALLWINNER_A10_PIC) += allwinner-a10-pic.o
 obj-$(CONFIG_S390_FLIC) += s390_flic.o
diff --git a/hw/intc/xics_native.c b/hw/intc/xics_native.c
new file mode 100644
index 0000000..26e45cc
--- /dev/null
+++ b/hw/intc/xics_native.c
@@ -0,0 +1,295 @@
+/*
+ * QEMU PowerPC hardware System Emulator
+ *
+ * Native version of ICS/ICP
+ *
+ * Copyright (c) 2010,2011 David Gibson, IBM Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "hw/hw.h"
+#include "trace.h"
+#include "qemu/timer.h"
+#include "hw/ppc/xics.h"
+#include "qapi/visitor.h"
+#include "qapi/error.h"
+
+#include <libfdt.h>
+
+/* #define DEBUG_MM(fmt...)      printf(fmt) */
+#define DEBUG_MM(fmt...)        do { } while (0)
+
+static void xics_native_initfn(Object *obj)
+{
+    XICSState *xics = XICS_NATIVE(obj);
+
+    QLIST_INIT(&xics->ics);
+}
+
+static uint64_t icp_mm_read(void *opaque, hwaddr addr, unsigned width)
+{
+    XICSState *s = opaque;
+    int32_t cpu_id, server;
+    uint32_t val;
+    ICPState *ss;
+    bool byte0 = (width == 1 && (addr & 0x3) == 0);
+
+    cpu_id = (addr & (ICP_MM_SIZE - 1)) >> 12;
+    server = get_cpu_index_by_dt_id(cpu_id);
+    if (server < 0) {
+        fprintf(stderr, "XICS: Bad ICP server %d\n", server);
+        goto bad_access;
+    }
+    ss = &s->ss[server];
+
+    switch (addr & 0xffc) {
+    case 0: /* poll */
+        val = icp_ipoll(ss, NULL);
+        if (byte0) {
+            val >>= 24;
+        } else if (width != 4) {
+            goto bad_access;
+        }
+        break;
+    case 4: /* xirr */
+        if (byte0) {
+            val = icp_ipoll(ss, NULL) >> 24;
+        } else if (width == 4) {
+            val = icp_accept(ss);
+        } else {
+            goto bad_access;
+        }
+        break;
+    case 12:
+        if (byte0) {
+            val = ss->mfrr;
+        } else {
+            goto bad_access;
+        }
+        break;
+    case 16:
+        if (width == 4) {
+            val = ss->links[0];
+        } else {
+            goto bad_access;
+        }
+        break;
+    case 20:
+        if (width == 4) {
+            val = ss->links[1];
+        } else {
+            goto bad_access;
+        }
+        break;
+    case 24:
+        if (width == 4) {
+            val = ss->links[2];
+        } else {
+            goto bad_access;
+        }
+        break;
+    default:
+bad_access:
+        fprintf(stderr, "XICS: Bad ICP access %llx/%d\n",
+                (unsigned long long)addr, width);
+        val = 0xffffffff;
+    }
+    DEBUG_MM("icp_mm_read(addr=%016llx,serv=0x%x/%d,off=%d,w=%d,val=0x%08x)\n",
+             (unsigned long long)addr, cpu_id, server, (int)(addr & 0xffc),
+             width, val);
+
+    return val;
+}
+
+static void icp_mm_write(void *opaque, hwaddr addr, uint64_t val,
+                        unsigned width)
+{
+    XICSState *s = opaque;
+    int32_t cpu_id, server;
+    ICPState *ss;
+    bool byte0 = (width == 1 && (addr & 0x3) == 0);
+
+    cpu_id = (addr & (ICP_MM_SIZE - 1)) >> 12;
+    server = get_cpu_index_by_dt_id(cpu_id);
+    if (server < 0) {
+        fprintf(stderr, "XICS: Bad ICP server %d\n", server);
+        goto bad_access;
+    }
+    ss = &s->ss[server];
+
+    DEBUG_MM("icp_mm_write(addr=%016llx,serv=0x%x/%d,off=%d,w=%d,val=0x%08x)\n",
+             (unsigned long long)addr, cpu_id, server,
+             (int)(addr & 0xffc), width, (uint32_t)val);
+
+    switch (addr & 0xffc) {
+    case 4: /* xirr */
+        if (byte0) {
+            icp_set_cppr(s, server, val);
+        } else if (width == 4) {
+            icp_eoi(s, server, val);
+        } else {
+            goto bad_access;
+        }
+        break;
+    case 12:
+        if (byte0) {
+            icp_set_mfrr(s, server, val);
+        } else {
+            goto bad_access;
+        }
+        break;
+    case 16:
+        if (width == 4) {
+            ss->links[0] = val;
+        } else {
+            goto bad_access;
+        }
+        break;
+    case 20:
+        if (width == 4) {
+            ss->links[1] = val;
+        } else {
+            goto bad_access;
+        }
+        break;
+    case 24:
+        if (width == 4) {
+            ss->links[2] = val;
+        } else {
+            goto bad_access;
+        }
+        break;
+    default:
+ bad_access:
+        val = 0xffffffff;
+    }
+}
+
+static const MemoryRegionOps icp_mm_ops = {
+    .read = icp_mm_read,
+    .write = icp_mm_write,
+    .valid.min_access_size = 1,
+    .valid.max_access_size = 4,
+    .impl.min_access_size = 1,
+    .impl.max_access_size = 4,
+    .endianness = DEVICE_BIG_ENDIAN,
+};
+
+#define _FDT(exp) \
+    do { \
+        int ret = (exp);                                           \
+        if (ret < 0) {                                             \
+            fprintf(stderr, "qemu: error creating device tree: %s: %s\n", \
+                    #exp, fdt_strerror(ret));                      \
+            exit(1);                                               \
+        }                                                          \
+    } while (0)
+
+void xics_create_native_icp_node(XICSState *s, void *fdt,
+                                 uint32_t base, uint32_t count)
+{
+    uint64_t addr;
+    char *name;
+    const char compat[] = "IBM,power8-icp\0IBM,ppc-xicp";
+    uint32_t irange[2], i, rsize;
+    uint64_t *reg;
+
+    addr = ICP_MM_BASE | (base << 12);
+
+    irange[0] = cpu_to_be32(base);
+    irange[1] = cpu_to_be32(count);
+
+    rsize = sizeof(uint64_t) * 2 * count;
+    reg = g_malloc(rsize);
+    for (i = 0; i < count; i++) {
+        reg[i * 2] = cpu_to_be64(addr | ((base + i) * 0x1000));
+        reg[i * 2 + 1] = cpu_to_be64(0x1000);
+    }
+
+    name = g_strdup_printf("interrupt-controller@%"PRIX64, addr);
+
+    /* interrupt controller */
+    _FDT((fdt_begin_node(fdt, name)));
+    g_free(name);
+
+    _FDT((fdt_property(fdt, "compatible", compat, sizeof(compat))));
+    _FDT((fdt_property(fdt, "reg", reg, rsize)));
+    _FDT((fdt_property_string(fdt, "device_type",
+                              "PowerPC-External-Interrupt-Presentation")));
+    _FDT((fdt_property(fdt, "interrupt-controller", NULL, 0)));
+    _FDT((fdt_property(fdt, "ibm,interrupt-server-ranges",
+                       irange, sizeof(irange))));
+    _FDT((fdt_property_cell(fdt, "#interrupt-cells", 1)));
+    _FDT((fdt_property_cell(fdt, "#address-cells", 0)));
+    _FDT((fdt_end_node(fdt)));
+}
+
+static void xics_native_realize(DeviceState *dev, Error **errp)
+{
+    XICSState *s = XICS_NATIVE(dev);
+    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+    Error *error = NULL;
+    int i;
+
+    if (!s->nr_servers) {
+        error_setg(errp, "Number of servers needs to be greater 0");
+        return;
+    }
+
+    /* Register MMIO regions */
+    memory_region_init_io(&s->icp_mmio, OBJECT(s), &icp_mm_ops, s, "icp",
+                          ICP_MM_SIZE);
+    sysbus_init_mmio(sbd, &s->icp_mmio);
+    sysbus_mmio_map(sbd, 0, ICP_MM_BASE);
+
+    for (i = 0; i < s->nr_servers; i++) {
+        object_property_set_bool(OBJECT(&s->ss[i]), true, "realized", &error);
+        if (error) {
+            error_propagate(errp, error);
+            return;
+        }
+    }
+}
+
+static void xics_native_class_init(ObjectClass *oc, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(oc);
+    XICSStateClass *xsc = XICS_NATIVE_CLASS(oc);
+
+    dc->realize = xics_native_realize;
+    xsc->set_nr_servers = xics_set_nr_servers;
+}
+
+static const TypeInfo xics_native_info = {
+    .name          = TYPE_XICS_NATIVE,
+    .parent        = TYPE_XICS_COMMON,
+    .instance_size = sizeof(XICSState),
+    .class_size = sizeof(XICSStateClass),
+    .class_init    = xics_native_class_init,
+    .instance_init = xics_native_initfn,
+};
+
+static void xics_native_register_types(void)
+{
+    type_register_static(&xics_native_info);
+}
+type_init(xics_native_register_types)
diff --git a/include/hw/ppc/xics.h b/include/hw/ppc/xics.h
index 2231f2a..f81155c 100644
--- a/include/hw/ppc/xics.h
+++ b/include/hw/ppc/xics.h
@@ -44,6 +44,9 @@
 #define XICS_SPAPR_KVM(obj) \
      OBJECT_CHECK(KVMXICSState, (obj), TYPE_XICS_SPAPR_KVM)
 
+#define TYPE_XICS_NATIVE "xics-native"
+#define XICS_NATIVE(obj) OBJECT_CHECK(XICSState, (obj), TYPE_XICS_NATIVE)
+
 #define XICS_COMMON_CLASS(klass) \
      OBJECT_CLASS_CHECK(XICSStateClass, (klass), TYPE_XICS_COMMON)
 #define XICS_SPAPR_CLASS(klass) \
@@ -52,6 +55,8 @@
      OBJECT_GET_CLASS(XICSStateClass, (obj), TYPE_XICS_COMMON)
 #define XICS_SPAPR_GET_CLASS(obj) \
      OBJECT_GET_CLASS(XICSStateClass, (obj), TYPE_XICS_SPAPR)
+#define XICS_NATIVE_CLASS(klass) \
+     OBJECT_CLASS_CHECK(XICSStateClass, (klass), TYPE_XICS_NATIVE)
 
 #define XICS_IPI        0x2
 #define XICS_BUID       0x1
@@ -86,6 +91,7 @@ struct XICSState {
     uint32_t nr_irqs;
     ICPState *ss;
     QLIST_HEAD(, ICSState) ics;
+    MemoryRegion icp_mmio;
 };
 
 #define TYPE_ICP "icp"
@@ -117,8 +123,13 @@ struct ICPState {
     uint8_t mfrr;
     qemu_irq output;
     bool cap_irq_xics_enabled;
+    uint32_t links[3];
 };
 
+/* This should be an XSCOM BAR ... the size is arbitrary as well */
+#define ICP_MM_BASE     0x0003FFFF80000000
+#define ICP_MM_SIZE     0x0000000010000000
+
 #define TYPE_ICS_BASE "ics-base"
 #define ICS_BASE(obj) OBJECT_CHECK(ICSState, (obj), TYPE_ICS_SIMPLE)
 
@@ -189,6 +200,9 @@ void xics_spapr_free(XICSState *icp, int irq, int num);
 void xics_cpu_setup(XICSState *icp, PowerPCCPU *cpu);
 void xics_cpu_destroy(XICSState *icp, PowerPCCPU *cpu);
 
+void xics_create_native_icp_node(XICSState *s, void *fdt,
+                                 uint32_t base, uint32_t count);
+
 /* Internal XICS interfaces */
 int xics_get_cpu_index_by_dt_id(int cpu_dt_id);
 
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [Qemu-devel] [PATCH v4 8/9] ppc/xics: Add xics to the monitor "info pic" command
  2016-09-19  6:29 [Qemu-devel] [PATCH v4 0/9] sPAPR xics rework/cleanup Nikunj A Dadhania
                   ` (6 preceding siblings ...)
  2016-09-19  6:29 ` [Qemu-devel] [PATCH v4 7/9] ppc/xics: Add "native" XICS subclass Nikunj A Dadhania
@ 2016-09-19  6:29 ` Nikunj A Dadhania
  2016-09-22  0:07   ` David Gibson
  2016-09-19  6:29 ` [Qemu-devel] [PATCH v4 9/9] ppc/xics: move set_nr_{irqs, servers} to xics.c Nikunj A Dadhania
  8 siblings, 1 reply; 38+ messages in thread
From: Nikunj A Dadhania @ 2016-09-19  6:29 UTC (permalink / raw)
  To: qemu-ppc, david; +Cc: qemu-devel, nikunj, benh, clg

From: Benjamin Herrenschmidt <benh@kernel.crashing.org>

Useful to debug interrupt problems.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>
---
 hmp-commands-info.hx  |  2 ++
 hw/intc/xics.c        | 38 ++++++++++++++++++++++++++++++++++++++
 hw/ppc/ppc.c          | 14 ++++++++++++++
 include/hw/ppc/ppc.h  |  1 +
 include/hw/ppc/xics.h |  4 +++-
 monitor.c             |  4 ++++
 6 files changed, 62 insertions(+), 1 deletion(-)

diff --git a/hmp-commands-info.hx b/hmp-commands-info.hx
index 74446c6..0929cb7 100644
--- a/hmp-commands-info.hx
+++ b/hmp-commands-info.hx
@@ -203,6 +203,8 @@ ETEXI
         .mhandler.cmd = sun4m_hmp_info_pic,
 #elif defined(TARGET_LM32)
         .mhandler.cmd = lm32_hmp_info_pic,
+#elif defined(TARGET_PPC)
+        .mhandler.cmd = ppc_hmp_info_pic,
 #else
         .mhandler.cmd = hmp_info_pic,
 #endif
diff --git a/hw/intc/xics.c b/hw/intc/xics.c
index b15751e..4ac2d00 100644
--- a/hw/intc/xics.c
+++ b/hw/intc/xics.c
@@ -36,6 +36,9 @@
 #include "hw/ppc/xics.h"
 #include "qemu/error-report.h"
 #include "qapi/visitor.h"
+#include "monitor/monitor.h"
+
+static XICSState *g_xics;
 
 int xics_get_cpu_index_by_dt_id(int cpu_dt_id)
 {
@@ -196,6 +199,9 @@ static void xics_common_initfn(Object *obj)
     object_property_add(obj, "nr_servers", "int",
                         xics_prop_get_nr_servers, xics_prop_set_nr_servers,
                         NULL, NULL, NULL);
+
+    /* For exclusive use of monitor command */
+    g_xics = XICS_COMMON(obj);
 }
 
 static void xics_common_class_init(ObjectClass *oc, void *data)
@@ -677,6 +683,38 @@ static int ics_simple_dispatch_post_load(void *opaque, int version_id)
     return 0;
 }
 
+void xics_hmp_info_pic(Monitor *mon, const QDict *qdict)
+{
+    ICSState *ics;
+    uint32_t i;
+
+    for (i = 0; i < g_xics->nr_servers; i++) {
+        ICPState *icp = &g_xics->ss[i];
+
+        if (!icp->output) {
+            continue;
+        }
+        monitor_printf(mon, "CPU %d XIRR=%08x (%p) PP=%02x MFRR=%02x\n",
+                       i, icp->xirr, icp->xirr_owner,
+                       icp->pending_priority, icp->mfrr);
+    }
+    QLIST_FOREACH(ics, &g_xics->ics, list) {
+        monitor_printf(mon, "ICS %4x..%4x %p\n",
+                       ics->offset, ics->offset + ics->nr_irqs - 1, ics);
+        for (i = 0; i < ics->nr_irqs; i++) {
+            ICSIRQState *irq = ics->irqs + i;
+
+            if (!(irq->flags & XICS_FLAGS_IRQ_MASK)) {
+                continue;
+            }
+            monitor_printf(mon, "  %4x %s %02x %02x\n",
+                           ics->offset + i,
+                           (irq->flags & XICS_FLAGS_IRQ_LSI) ? "LSI" : "MSI",
+                           irq->priority, irq->status);
+        }
+    }
+}
+
 static const VMStateDescription vmstate_ics_simple_irq = {
     .name = "ics/irq",
     .version_id = 2,
diff --git a/hw/ppc/ppc.c b/hw/ppc/ppc.c
index 8945869..bc73428 100644
--- a/hw/ppc/ppc.c
+++ b/hw/ppc/ppc.c
@@ -27,6 +27,7 @@
 #include "hw/hw.h"
 #include "hw/ppc/ppc.h"
 #include "hw/ppc/ppc_e500.h"
+#include "hw/i386/pc.h"
 #include "qemu/timer.h"
 #include "sysemu/sysemu.h"
 #include "sysemu/cpus.h"
@@ -39,6 +40,10 @@
 #include "kvm_ppc.h"
 #include "trace.h"
 
+#if defined(TARGET_PPC64)
+#include "hw/ppc/xics.h"
+#endif
+
 //#define PPC_DEBUG_IRQ
 //#define PPC_DEBUG_TB
 
@@ -1376,3 +1381,12 @@ void ppc_cpu_parse_features(const char *cpu_model)
     cc->parse_features(typename, model_pieces[1], &error_fatal);
     g_strfreev(model_pieces);
 }
+
+void ppc_hmp_info_pic(Monitor *mon, const QDict *qdict)
+{
+    /* Call in turn every PIC around. OpenPIC doesn't have one yet */
+#ifdef TARGET_PPC64
+    xics_hmp_info_pic(mon, qdict);
+#endif
+    hmp_info_pic(mon, qdict);
+}
diff --git a/include/hw/ppc/ppc.h b/include/hw/ppc/ppc.h
index 00c1fb1..69c4b19 100644
--- a/include/hw/ppc/ppc.h
+++ b/include/hw/ppc/ppc.h
@@ -3,6 +3,7 @@
 
 #include "target-ppc/cpu-qom.h"
 
+void ppc_hmp_info_pic(Monitor *mon, const QDict *qdict);
 void ppc_set_irq(PowerPCCPU *cpu, int n_IRQ, int level);
 
 /* PowerPC hardware exceptions management helpers */
diff --git a/include/hw/ppc/xics.h b/include/hw/ppc/xics.h
index f81155c..58bb7c6 100644
--- a/include/hw/ppc/xics.h
+++ b/include/hw/ppc/xics.h
@@ -220,4 +220,6 @@ void ics_set_irq_type(ICSState *ics, int srcno, bool lsi);
 ICSState *xics_find_source(XICSState *icp, int irq);
 void xics_add_ics(XICSState *xics);
 
-#endif /* XICS_H */
+void xics_hmp_info_pic(Monitor *mon, const QDict *qdict);
+
+#endif /* __XICS_H__ */
diff --git a/monitor.c b/monitor.c
index 5c00373..e9009de 100644
--- a/monitor.c
+++ b/monitor.c
@@ -90,6 +90,10 @@
 #include "hw/s390x/storage-keys.h"
 #endif
 
+#if defined(TARGET_PPC)
+#include "hw/ppc/ppc.h"
+#endif
+
 /*
  * Supported types:
  *
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [Qemu-devel] [PATCH v4 9/9] ppc/xics: move set_nr_{irqs, servers} to xics.c
  2016-09-19  6:29 [Qemu-devel] [PATCH v4 0/9] sPAPR xics rework/cleanup Nikunj A Dadhania
                   ` (7 preceding siblings ...)
  2016-09-19  6:29 ` [Qemu-devel] [PATCH v4 8/9] ppc/xics: Add xics to the monitor "info pic" command Nikunj A Dadhania
@ 2016-09-19  6:29 ` Nikunj A Dadhania
  2016-09-22  0:14   ` David Gibson
  8 siblings, 1 reply; 38+ messages in thread
From: Nikunj A Dadhania @ 2016-09-19  6:29 UTC (permalink / raw)
  To: qemu-ppc, david; +Cc: qemu-devel, nikunj, benh, clg

Get this duplicate code in the base implementation.

Signed-off-by: Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>
---
 hw/intc/xics.c        | 74 ++++++++++++++++++++++++++++++++++++++++++++-------
 hw/intc/xics_kvm.c    | 34 +++--------------------
 hw/intc/xics_native.c | 51 +++++++++++++++++++++--------------
 hw/intc/xics_spapr.c  | 49 +++++++++-------------------------
 include/hw/ppc/xics.h | 19 ++++++++++---
 5 files changed, 126 insertions(+), 101 deletions(-)

diff --git a/hw/intc/xics.c b/hw/intc/xics.c
index 4ac2d00..9fbf962 100644
--- a/hw/intc/xics.c
+++ b/hw/intc/xics.c
@@ -54,8 +54,9 @@ int xics_get_cpu_index_by_dt_id(int cpu_dt_id)
 void xics_cpu_destroy(XICSState *xics, PowerPCCPU *cpu)
 {
     CPUState *cs = CPU(cpu);
-    ICPState *ss = &xics->ss[cs->cpu_index];
+    ICPState *ss;
 
+    ss = xics->ss + sizeof(ICPState) * cs->cpu_index;
     assert(cs->cpu_index < xics->nr_servers);
     assert(cs == ss->cs);
 
@@ -67,9 +68,10 @@ void xics_cpu_setup(XICSState *xics, PowerPCCPU *cpu)
 {
     CPUState *cs = CPU(cpu);
     CPUPPCState *env = &cpu->env;
-    ICPState *ss = &xics->ss[cs->cpu_index];
+    ICPState *ss;
     XICSStateClass *info = XICS_COMMON_GET_CLASS(xics);
 
+    ss = xics->ss + sizeof(ICPState) * cs->cpu_index;
     assert(cs->cpu_index < xics->nr_servers);
 
     ss->cs = cs;
@@ -101,10 +103,12 @@ static void xics_common_reset(DeviceState *d)
 {
     XICSState *xics = XICS_COMMON(d);
     ICSState *ics;
+    ICPState *ss;
     int i;
 
     for (i = 0; i < xics->nr_servers; i++) {
-        device_reset(DEVICE(&xics->ss[i]));
+        ss = xics->ss + sizeof(ICPState) * i;
+        device_reset(DEVICE(ss));
     }
 
     QLIST_FOREACH(ics, &xics->ics, list) {
@@ -193,6 +197,7 @@ static void xics_common_initfn(Object *obj)
     XICSState *xics = XICS_COMMON(obj);
 
     QLIST_INIT(&xics->ics);
+    xics->ss_class = object_class_by_name(TYPE_ICP);
     object_property_add(obj, "nr_irqs", "int",
                         xics_prop_get_nr_irqs, xics_prop_set_nr_irqs,
                         NULL, NULL, NULL);
@@ -201,7 +206,15 @@ static void xics_common_initfn(Object *obj)
                         NULL, NULL, NULL);
 
     /* For exclusive use of monitor command */
-    g_xics = XICS_COMMON(obj);
+    g_xics = xics;
+}
+
+static void xics_common_realize(DeviceState *dev, Error **errp)
+{
+    XICSState *xics = XICS_COMMON(dev);
+    XICSStateClass *xsc = XICS_COMMON_GET_CLASS(xics);
+
+    xsc->realize(dev, errp);
 }
 
 static void xics_common_class_init(ObjectClass *oc, void *data)
@@ -209,6 +222,7 @@ static void xics_common_class_init(ObjectClass *oc, void *data)
     DeviceClass *dc = DEVICE_CLASS(oc);
 
     dc->reset = xics_common_reset;
+    dc->realize = xics_common_realize;
 }
 
 static const TypeInfo xics_common_info = {
@@ -277,7 +291,7 @@ static void icp_check_ipi(ICPState *ss)
 
 static void icp_resend(XICSState *xics, int server)
 {
-    ICPState *ss = xics->ss + server;
+    ICPState *ss = xics->ss + server * sizeof(ICPState);
     ICSState *ics;
 
     if (ss->mfrr < CPPR(ss)) {
@@ -290,7 +304,7 @@ static void icp_resend(XICSState *xics, int server)
 
 void icp_set_cppr(XICSState *xics, int server, uint8_t cppr)
 {
-    ICPState *ss = xics->ss + server;
+    ICPState *ss = xics->ss + server * sizeof(ICPState);
     uint8_t old_cppr;
     uint32_t old_xisr;
 
@@ -317,7 +331,7 @@ void icp_set_cppr(XICSState *xics, int server, uint8_t cppr)
 
 void icp_set_mfrr(XICSState *xics, int server, uint8_t mfrr)
 {
-    ICPState *ss = xics->ss + server;
+    ICPState *ss = xics->ss + server * sizeof(ICPState);
 
     ss->mfrr = mfrr;
     if (mfrr < CPPR(ss)) {
@@ -349,7 +363,7 @@ uint32_t icp_ipoll(ICPState *ss, uint32_t *mfrr)
 
 void icp_eoi(XICSState *xics, int server, uint32_t xirr)
 {
-    ICPState *ss = xics->ss + server;
+    ICPState *ss = xics->ss + server * sizeof(ICPState);
     ICSState *ics;
     uint32_t irq;
 
@@ -370,7 +384,7 @@ void icp_eoi(XICSState *xics, int server, uint32_t xirr)
 static void icp_irq(ICSState *ics, int server, int nr, uint8_t priority)
 {
     XICSState *xics = ics->xics;
-    ICPState *ss = xics->ss + server;
+    ICPState *ss = xics->ss + server * sizeof(ICPState);
 
     trace_xics_icp_irq(server, nr, priority);
 
@@ -488,6 +502,14 @@ static const TypeInfo icp_info = {
     .class_size = sizeof(ICPStateClass),
 };
 
+static const TypeInfo icp_native_info = {
+    .name = TYPE_NATIVE_ICP,
+    .parent = TYPE_ICP,
+    .instance_size = sizeof(ICPNative),
+    .class_init = icp_class_init,
+    .class_size = sizeof(ICPStateClass),
+};
+
 /*
  * ICS: Source layer
  */
@@ -689,7 +711,7 @@ void xics_hmp_info_pic(Monitor *mon, const QDict *qdict)
     uint32_t i;
 
     for (i = 0; i < g_xics->nr_servers; i++) {
-        ICPState *icp = &g_xics->ss[i];
+        ICPState *icp = g_xics->ss + i * sizeof(ICPState);
 
         if (!icp->output) {
             continue;
@@ -829,12 +851,44 @@ void ics_set_irq_type(ICSState *ics, int srcno, bool lsi)
         lsi ? XICS_FLAGS_IRQ_LSI : XICS_FLAGS_IRQ_MSI;
 }
 
+void xics_set_nr_irqs(XICSState *xics, uint32_t nr_irqs, Error **errp)
+{
+    ICSState *ics = QLIST_FIRST(&xics->ics);
+
+    /* This needs to be deprecated ... */
+    xics->nr_irqs = nr_irqs;
+    if (ics) {
+        ics->nr_irqs = nr_irqs;
+    }
+}
+
+void xics_set_nr_servers(XICSState *xics, uint32_t nr_servers, Error **errp)
+{
+    int i;
+    const char *typename = object_class_get_name(xics->ss_class);
+    size_t size = object_type_get_instance_size(typename);
+
+    xics->nr_servers = nr_servers;
+
+    xics->ss = g_malloc0(xics->nr_servers * size);
+    for (i = 0; i < xics->nr_servers; i++) {
+        char buffer[32];
+        void *obj;
+
+        obj = xics->ss + size * i;
+        object_initialize(obj, size, typename);
+        snprintf(buffer, sizeof(buffer), "icp[%d]", i);
+        object_property_add_child(OBJECT(xics), buffer, obj, errp);
+    }
+}
+
 static void xics_register_types(void)
 {
     type_register_static(&xics_common_info);
     type_register_static(&ics_simple_info);
     type_register_static(&ics_base_info);
     type_register_static(&icp_info);
+    type_register_static(&icp_native_info);
 }
 
 type_init(xics_register_types)
diff --git a/hw/intc/xics_kvm.c b/hw/intc/xics_kvm.c
index 89862df..b095b9e 100644
--- a/hw/intc/xics_kvm.c
+++ b/hw/intc/xics_kvm.c
@@ -362,35 +362,6 @@ static void xics_kvm_cpu_setup(XICSState *xics, PowerPCCPU *cpu)
     }
 }
 
-static void xics_kvm_set_nr_irqs(XICSState *xics, uint32_t nr_irqs,
-                                 Error **errp)
-{
-    ICSState *ics = QLIST_FIRST(&xics->ics);
-
-    /* This needs to be deprecated ... */
-    xics->nr_irqs = nr_irqs;
-    if (ics) {
-        ics->nr_irqs = nr_irqs;
-    }
-}
-
-static void xics_kvm_set_nr_servers(XICSState *xics, uint32_t nr_servers,
-                                    Error **errp)
-{
-    int i;
-
-    xics->nr_servers = nr_servers;
-
-    xics->ss = g_malloc0(xics->nr_servers * sizeof(ICPState));
-    for (i = 0; i < xics->nr_servers; i++) {
-        char buffer[32];
-        object_initialize(&xics->ss[i], sizeof(xics->ss[i]), TYPE_KVM_ICP);
-        snprintf(buffer, sizeof(buffer), "icp[%d]", i);
-        object_property_add_child(OBJECT(xics), buffer, OBJECT(&xics->ss[i]),
-                                  errp);
-    }
-}
-
 static void rtas_dummy(PowerPCCPU *cpu, sPAPRMachineState *spapr,
                        uint32_t token,
                        uint32_t nargs, target_ulong args,
@@ -492,6 +463,7 @@ static void xics_kvm_initfn(Object *obj)
     XICSState *xics = XICS_COMMON(obj);
     ICSState *ics;
 
+    xics->ss_class = object_class_by_name(TYPE_KVM_ICP);
     ics = ICS_SIMPLE(object_new(TYPE_ICS_KVM));
     object_property_add_child(obj, "ics", OBJECT(ics), NULL);
     ics->xics = xics;
@@ -505,8 +477,8 @@ static void xics_kvm_class_init(ObjectClass *oc, void *data)
 
     dc->realize = xics_kvm_realize;
     xsc->cpu_setup = xics_kvm_cpu_setup;
-    xsc->set_nr_irqs = xics_kvm_set_nr_irqs;
-    xsc->set_nr_servers = xics_kvm_set_nr_servers;
+    xsc->set_nr_irqs = xics_set_nr_irqs;
+    xsc->set_nr_servers = xics_set_nr_servers;
 }
 
 static const TypeInfo xics_spapr_kvm_info = {
diff --git a/hw/intc/xics_native.c b/hw/intc/xics_native.c
index 26e45cc..db2fd4d 100644
--- a/hw/intc/xics_native.c
+++ b/hw/intc/xics_native.c
@@ -38,11 +38,19 @@
 /* #define DEBUG_MM(fmt...)      printf(fmt) */
 #define DEBUG_MM(fmt...)        do { } while (0)
 
+typedef struct XICSNative {
+    /*< private >*/
+    XICSState xics;
+
+    /*< public >*/
+    MemoryRegion icp_mmio;
+} XICSNative;
+
 static void xics_native_initfn(Object *obj)
 {
-    XICSState *xics = XICS_NATIVE(obj);
+    XICSState *xics = XICS_COMMON(obj);
 
-    QLIST_INIT(&xics->ics);
+    xics->ss_class = object_class_by_name(TYPE_NATIVE_ICP);
 }
 
 static uint64_t icp_mm_read(void *opaque, hwaddr addr, unsigned width)
@@ -51,6 +59,7 @@ static uint64_t icp_mm_read(void *opaque, hwaddr addr, unsigned width)
     int32_t cpu_id, server;
     uint32_t val;
     ICPState *ss;
+    ICPNative *icpn;
     bool byte0 = (width == 1 && (addr & 0x3) == 0);
 
     cpu_id = (addr & (ICP_MM_SIZE - 1)) >> 12;
@@ -59,7 +68,8 @@ static uint64_t icp_mm_read(void *opaque, hwaddr addr, unsigned width)
         fprintf(stderr, "XICS: Bad ICP server %d\n", server);
         goto bad_access;
     }
-    ss = &s->ss[server];
+    icpn = s->ss + server * sizeof(ICPNative);
+    ss = &icpn->icp;
 
     switch (addr & 0xffc) {
     case 0: /* poll */
@@ -88,21 +98,21 @@ static uint64_t icp_mm_read(void *opaque, hwaddr addr, unsigned width)
         break;
     case 16:
         if (width == 4) {
-            val = ss->links[0];
+            val = icpn->links[0];
         } else {
             goto bad_access;
         }
         break;
     case 20:
         if (width == 4) {
-            val = ss->links[1];
+            val = icpn->links[1];
         } else {
             goto bad_access;
         }
         break;
     case 24:
         if (width == 4) {
-            val = ss->links[2];
+            val = icpn->links[2];
         } else {
             goto bad_access;
         }
@@ -125,7 +135,7 @@ static void icp_mm_write(void *opaque, hwaddr addr, uint64_t val,
 {
     XICSState *s = opaque;
     int32_t cpu_id, server;
-    ICPState *ss;
+    ICPNative *icpn;
     bool byte0 = (width == 1 && (addr & 0x3) == 0);
 
     cpu_id = (addr & (ICP_MM_SIZE - 1)) >> 12;
@@ -134,7 +144,8 @@ static void icp_mm_write(void *opaque, hwaddr addr, uint64_t val,
         fprintf(stderr, "XICS: Bad ICP server %d\n", server);
         goto bad_access;
     }
-    ss = &s->ss[server];
+    icpn = s->ss + server * sizeof(ICPNative);
+    ss = &icpn->icp;
 
     DEBUG_MM("icp_mm_write(addr=%016llx,serv=0x%x/%d,off=%d,w=%d,val=0x%08x)\n",
              (unsigned long long)addr, cpu_id, server,
@@ -159,21 +170,21 @@ static void icp_mm_write(void *opaque, hwaddr addr, uint64_t val,
         break;
     case 16:
         if (width == 4) {
-            ss->links[0] = val;
+            icpn->links[0] = val;
         } else {
             goto bad_access;
         }
         break;
     case 20:
         if (width == 4) {
-            ss->links[1] = val;
+            icpn->links[1] = val;
         } else {
             goto bad_access;
         }
         break;
     case 24:
         if (width == 4) {
-            ss->links[2] = val;
+            icpn->links[2] = val;
         } else {
             goto bad_access;
         }
@@ -245,8 +256,9 @@ void xics_create_native_icp_node(XICSState *s, void *fdt,
 
 static void xics_native_realize(DeviceState *dev, Error **errp)
 {
-    XICSState *s = XICS_NATIVE(dev);
-    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+    XICSNative *n = XICS_NATIVE(dev);
+    XICSState *s = XICS_COMMON(dev);
+    SysBusDevice *sbd = SYS_BUS_DEVICE(s);
     Error *error = NULL;
     int i;
 
@@ -256,13 +268,14 @@ static void xics_native_realize(DeviceState *dev, Error **errp)
     }
 
     /* Register MMIO regions */
-    memory_region_init_io(&s->icp_mmio, OBJECT(s), &icp_mm_ops, s, "icp",
+    memory_region_init_io(&n->icp_mmio, OBJECT(s), &icp_mm_ops, s, "icp",
                           ICP_MM_SIZE);
-    sysbus_init_mmio(sbd, &s->icp_mmio);
+    sysbus_init_mmio(sbd, &n->icp_mmio);
     sysbus_mmio_map(sbd, 0, ICP_MM_BASE);
 
     for (i = 0; i < s->nr_servers; i++) {
-        object_property_set_bool(OBJECT(&s->ss[i]), true, "realized", &error);
+        ICPNative *icpn = s->ss + i * sizeof(ICPNative);
+        object_property_set_bool(OBJECT(icpn), true, "realized", &error);
         if (error) {
             error_propagate(errp, error);
             return;
@@ -272,20 +285,18 @@ static void xics_native_realize(DeviceState *dev, Error **errp)
 
 static void xics_native_class_init(ObjectClass *oc, void *data)
 {
-    DeviceClass *dc = DEVICE_CLASS(oc);
     XICSStateClass *xsc = XICS_NATIVE_CLASS(oc);
 
-    dc->realize = xics_native_realize;
+    xsc->realize = xics_native_realize;
     xsc->set_nr_servers = xics_set_nr_servers;
 }
 
 static const TypeInfo xics_native_info = {
     .name          = TYPE_XICS_NATIVE,
     .parent        = TYPE_XICS_COMMON,
-    .instance_size = sizeof(XICSState),
+    .instance_size = sizeof(XICSNative),
     .class_size = sizeof(XICSStateClass),
     .class_init    = xics_native_class_init,
-    .instance_init = xics_native_initfn,
 };
 
 static void xics_native_register_types(void)
diff --git a/hw/intc/xics_spapr.c b/hw/intc/xics_spapr.c
index 4dd1399..0644942 100644
--- a/hw/intc/xics_spapr.c
+++ b/hw/intc/xics_spapr.c
@@ -67,7 +67,8 @@ static target_ulong h_xirr(PowerPCCPU *cpu, sPAPRMachineState *spapr,
                            target_ulong opcode, target_ulong *args)
 {
     CPUState *cs = CPU(cpu);
-    uint32_t xirr = icp_accept(spapr->xics->ss + cs->cpu_index);
+    uint32_t xirr = icp_accept(spapr->xics->ss +
+                               cs->cpu_index * sizeof(ICPState));
 
     args[0] = xirr;
     return H_SUCCESS;
@@ -77,9 +78,11 @@ static target_ulong h_xirr_x(PowerPCCPU *cpu, sPAPRMachineState *spapr,
                              target_ulong opcode, target_ulong *args)
 {
     CPUState *cs = CPU(cpu);
-    ICPState *ss = &spapr->xics->ss[cs->cpu_index];
-    uint32_t xirr = icp_accept(ss);
+    ICPState *ss;
+    uint32_t xirr;
 
+    ss = spapr->xics->ss + cs->cpu_index * sizeof(ICPState);
+    xirr = icp_accept(ss);
     args[0] = xirr;
     args[1] = cpu_get_host_ticks();
     return H_SUCCESS;
@@ -100,7 +103,8 @@ static target_ulong h_ipoll(PowerPCCPU *cpu, sPAPRMachineState *spapr,
 {
     CPUState *cs = CPU(cpu);
     uint32_t mfrr;
-    uint32_t xirr = icp_ipoll(spapr->xics->ss + cs->cpu_index, &mfrr);
+    uint32_t xirr = icp_ipoll(spapr->xics->ss +
+                              cs->cpu_index * sizeof(ICPState), &mfrr);
 
     args[0] = xirr;
     args[1] = mfrr;
@@ -234,35 +238,6 @@ static void rtas_int_on(PowerPCCPU *cpu, sPAPRMachineState *spapr,
     rtas_st(rets, 0, RTAS_OUT_SUCCESS);
 }
 
-static void xics_spapr_set_nr_irqs(XICSState *xics, uint32_t nr_irqs,
-                                   Error **errp)
-{
-    ICSState *ics = QLIST_FIRST(&xics->ics);
-
-    /* This needs to be deprecated ... */
-    xics->nr_irqs = nr_irqs;
-    if (ics) {
-        ics->nr_irqs = nr_irqs;
-    }
-}
-
-static void xics_spapr_set_nr_servers(XICSState *xics, uint32_t nr_servers,
-                                      Error **errp)
-{
-    int i;
-
-    xics->nr_servers = nr_servers;
-
-    xics->ss = g_malloc0(xics->nr_servers * sizeof(ICPState));
-    for (i = 0; i < xics->nr_servers; i++) {
-        char buffer[32];
-        object_initialize(&xics->ss[i], sizeof(xics->ss[i]), TYPE_ICP);
-        snprintf(buffer, sizeof(buffer), "icp[%d]", i);
-        object_property_add_child(OBJECT(xics), buffer, OBJECT(&xics->ss[i]),
-                                  errp);
-    }
-}
-
 static void xics_spapr_realize(DeviceState *dev, Error **errp)
 {
     XICSState *xics = XICS_SPAPR(dev);
@@ -297,8 +272,8 @@ static void xics_spapr_realize(DeviceState *dev, Error **errp)
     }
 
     for (i = 0; i < xics->nr_servers; i++) {
-        object_property_set_bool(OBJECT(&xics->ss[i]), true, "realized",
-                                 &error);
+        ICPState *ss = xics->ss + i * sizeof(ICPState);
+        object_property_set_bool(OBJECT(ss), true, "realized", &error);
         if (error) {
             error_propagate(errp, error);
             return;
@@ -319,8 +294,8 @@ static void xics_spapr_class_init(ObjectClass *oc, void *data)
     XICSStateClass *xsc = XICS_SPAPR_CLASS(oc);
 
     dc->realize = xics_spapr_realize;
-    xsc->set_nr_irqs = xics_spapr_set_nr_irqs;
-    xsc->set_nr_servers = xics_spapr_set_nr_servers;
+    xsc->set_nr_irqs = xics_set_nr_irqs;
+    xsc->set_nr_servers = xics_set_nr_servers;
 }
 
 static const TypeInfo xics_spapr_info = {
diff --git a/include/hw/ppc/xics.h b/include/hw/ppc/xics.h
index 58bb7c6..0a427d7 100644
--- a/include/hw/ppc/xics.h
+++ b/include/hw/ppc/xics.h
@@ -45,7 +45,7 @@
      OBJECT_CHECK(KVMXICSState, (obj), TYPE_XICS_SPAPR_KVM)
 
 #define TYPE_XICS_NATIVE "xics-native"
-#define XICS_NATIVE(obj) OBJECT_CHECK(XICSState, (obj), TYPE_XICS_NATIVE)
+#define XICS_NATIVE(obj) OBJECT_CHECK(XICSNative, (obj), TYPE_XICS_NATIVE)
 
 #define XICS_COMMON_CLASS(klass) \
      OBJECT_CLASS_CHECK(XICSStateClass, (klass), TYPE_XICS_COMMON)
@@ -71,6 +71,7 @@ typedef struct XICSStateClass XICSStateClass;
 typedef struct XICSState XICSState;
 typedef struct ICPStateClass ICPStateClass;
 typedef struct ICPState ICPState;
+typedef struct ICPNative ICPNative;
 typedef struct ICSStateClass ICSStateClass;
 typedef struct ICSState ICSState;
 typedef struct ICSIRQState ICSIRQState;
@@ -78,6 +79,7 @@ typedef struct ICSIRQState ICSIRQState;
 struct XICSStateClass {
     DeviceClass parent_class;
 
+    DeviceRealize realize;
     void (*cpu_setup)(XICSState *icp, PowerPCCPU *cpu);
     void (*set_nr_irqs)(XICSState *icp, uint32_t nr_irqs, Error **errp);
     void (*set_nr_servers)(XICSState *icp, uint32_t nr_servers, Error **errp);
@@ -89,9 +91,9 @@ struct XICSState {
     /*< public >*/
     uint32_t nr_servers;
     uint32_t nr_irqs;
-    ICPState *ss;
+    void *ss;
+    ObjectClass *ss_class;
     QLIST_HEAD(, ICSState) ics;
-    MemoryRegion icp_mmio;
 };
 
 #define TYPE_ICP "icp"
@@ -100,6 +102,9 @@ struct XICSState {
 #define TYPE_KVM_ICP "icp-kvm"
 #define KVM_ICP(obj) OBJECT_CHECK(ICPState, (obj), TYPE_KVM_ICP)
 
+#define TYPE_NATIVE_ICP "icp-native"
+#define NATIVE_ICP(obj) OBJECT_CHECK(ICPNative, (obj), TYPE_NATIVE_ICP)
+
 #define ICP_CLASS(klass) \
      OBJECT_CLASS_CHECK(ICPStateClass, (klass), TYPE_ICP)
 #define ICP_GET_CLASS(obj) \
@@ -123,6 +128,12 @@ struct ICPState {
     uint8_t mfrr;
     qemu_irq output;
     bool cap_irq_xics_enabled;
+};
+
+struct ICPNative {
+    /*<private>*/
+    ICPState icp;
+    /*<public>*/
     uint32_t links[3];
 };
 
@@ -199,6 +210,8 @@ void xics_spapr_free(XICSState *icp, int irq, int num);
 
 void xics_cpu_setup(XICSState *icp, PowerPCCPU *cpu);
 void xics_cpu_destroy(XICSState *icp, PowerPCCPU *cpu);
+void xics_set_nr_irqs(XICSState *xics, uint32_t nr_irqs, Error **errp);
+void xics_set_nr_servers(XICSState *xics, uint32_t nr_servers, Error **errp);
 
 void xics_create_native_icp_node(XICSState *s, void *fdt,
                                  uint32_t base, uint32_t count);
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [Qemu-ppc] [PATCH v4 3/9] ppc/xics: Make the ICSState a list
  2016-09-19  6:29 ` [Qemu-devel] [PATCH v4 3/9] ppc/xics: Make the ICSState a list Nikunj A Dadhania
@ 2016-09-19  6:59   ` Cédric Le Goater
  2016-09-19  7:02     ` Nikunj A Dadhania
  2016-09-21  7:48   ` [Qemu-devel] " David Gibson
  1 sibling, 1 reply; 38+ messages in thread
From: Cédric Le Goater @ 2016-09-19  6:59 UTC (permalink / raw)
  To: Nikunj A Dadhania, qemu-ppc, david; +Cc: qemu-devel

On 09/19/2016 08:29 AM, Nikunj A Dadhania wrote:
> From: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> 
> Instead of an array of fixed sized blocks, use a list, as we will need
> to have sources with variable number of interrupts. SPAPR only uses
> a single entry. Native will create more. If performance becomes an
> issue we can add some hashed lookup but for now this will do fine.
> 
> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> [ move the initialization of list to xics_common_initfn,
>   restore xirr_owner after migration and move restoring to
>   icp_post_load]
> Signed-off-by: Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>

This looks good to me apart from the change of icp_post_load(). 

> ---
>  hw/intc/trace-events  |   5 +-
>  hw/intc/xics.c        | 130 ++++++++++++++++++++++++++++++++------------------
>  hw/intc/xics_kvm.c    |  27 +++++++----
>  hw/intc/xics_spapr.c  |  88 ++++++++++++++++++++++------------
>  hw/ppc/spapr_events.c |   2 +-
>  hw/ppc/spapr_pci.c    |   5 +-
>  hw/ppc/spapr_vio.c    |   2 +-
>  include/hw/ppc/xics.h |  13 ++---
>  8 files changed, 173 insertions(+), 99 deletions(-)
> 
> diff --git a/hw/intc/trace-events b/hw/intc/trace-events
> index f12192c..aa342a8 100644
> --- a/hw/intc/trace-events
> +++ b/hw/intc/trace-events
> @@ -56,10 +56,11 @@ xics_set_irq_lsi(int srcno, int nr) "set_irq_lsi: srcno %d [irq %#x]"
>  xics_ics_write_xive(int nr, int srcno, int server, uint8_t priority) "ics_write_xive: irq %#x [src %d] server %#x prio %#x"
>  xics_ics_reject(int nr, int srcno) "reject irq %#x [src %d]"
>  xics_ics_eoi(int nr) "ics_eoi: irq %#x"
> -xics_alloc(int src, int irq) "source#%d, irq %d"
> -xics_alloc_block(int src, int first, int num, bool lsi, int align) "source#%d, first irq %d, %d irqs, lsi=%d, alignnum %d"
> +xics_alloc(int irq) "irq %d"
> +xics_alloc_block(int first, int num, bool lsi, int align) "first irq %d, %d irqs, lsi=%d, alignnum %d"
>  xics_ics_free(int src, int irq, int num) "Source#%d, first irq %d, %d irqs"
>  xics_ics_free_warn(int src, int irq) "Source#%d, irq %d is already free"
> +xics_icp_post_load(uint32_t server_no, uint32_t xirr, uint64_t addr, uint8_t pend) "server_no %d, xirr %#x, xirr_owner 0x%" PRIx64 ", pending %d"
>  
>  # hw/intc/s390_flic_kvm.c
>  flic_create_device(int err) "flic: create device failed %d"
> diff --git a/hw/intc/xics.c b/hw/intc/xics.c
> index f765b08..05e938f 100644
> --- a/hw/intc/xics.c
> +++ b/hw/intc/xics.c
> @@ -32,6 +32,7 @@
>  #include "hw/hw.h"
>  #include "trace.h"
>  #include "qemu/timer.h"
> +#include "hw/ppc/spapr.h"
>  #include "hw/ppc/xics.h"
>  #include "qemu/error-report.h"
>  #include "qapi/visitor.h"
> @@ -96,13 +97,16 @@ void xics_cpu_setup(XICSState *xics, PowerPCCPU *cpu)
>  static void xics_common_reset(DeviceState *d)
>  {
>      XICSState *xics = XICS_COMMON(d);
> +    ICSState *ics;
>      int i;
>  
>      for (i = 0; i < xics->nr_servers; i++) {
>          device_reset(DEVICE(&xics->ss[i]));
>      }
>  
> -    device_reset(DEVICE(xics->ics));
> +    QLIST_FOREACH(ics, &xics->ics, list) {
> +        device_reset(DEVICE(ics));
> +    }
>  }
>  
>  static void xics_prop_get_nr_irqs(Object *obj, Visitor *v, const char *name,
> @@ -134,7 +138,6 @@ static void xics_prop_set_nr_irqs(Object *obj, Visitor *v, const char *name,
>      }
>  
>      assert(info->set_nr_irqs);
> -    assert(xics->ics);
>      info->set_nr_irqs(xics, value, errp);
>  }
>  
> @@ -174,6 +177,9 @@ static void xics_prop_set_nr_servers(Object *obj, Visitor *v,
>  
>  static void xics_common_initfn(Object *obj)
>  {
> +    XICSState *xics = XICS_COMMON(obj);
> +
> +    QLIST_INIT(&xics->ics);
>      object_property_add(obj, "nr_irqs", "int",
>                          xics_prop_get_nr_irqs, xics_prop_set_nr_irqs,
>                          NULL, NULL, NULL);
> @@ -212,33 +218,35 @@ static void ics_reject(ICSState *ics, int nr);
>  static void ics_resend(ICSState *ics, int server);
>  static void ics_eoi(ICSState *ics, int nr);
>  
> -static void icp_check_ipi(XICSState *xics, int server)
> +static void icp_check_ipi(ICPState *ss)
>  {
> -    ICPState *ss = xics->ss + server;
> -
>      if (XISR(ss) && (ss->pending_priority <= ss->mfrr)) {
>          return;
>      }
>  
> -    trace_xics_icp_check_ipi(server, ss->mfrr);
> +    trace_xics_icp_check_ipi(ss->cs->cpu_index, ss->mfrr);
>  
> -    if (XISR(ss)) {
> -        ics_reject(xics->ics, XISR(ss));
> +    if (XISR(ss) && ss->xirr_owner) {
> +        ics_reject(ss->xirr_owner, XISR(ss));
>      }
>  
>      ss->xirr = (ss->xirr & ~XISR_MASK) | XICS_IPI;
>      ss->pending_priority = ss->mfrr;
> +    ss->xirr_owner = NULL;
>      qemu_irq_raise(ss->output);
>  }
>  
>  static void icp_resend(XICSState *xics, int server)
>  {
>      ICPState *ss = xics->ss + server;
> +    ICSState *ics;
>  
>      if (ss->mfrr < CPPR(ss)) {
> -        icp_check_ipi(xics, server);
> +        icp_check_ipi(ss);
> +    }
> +    QLIST_FOREACH(ics, &xics->ics, list) {
> +        ics_resend(ics, server);
>      }
> -    ics_resend(xics->ics, server);
>  }
>  
>  void icp_set_cppr(XICSState *xics, int server, uint8_t cppr)
> @@ -256,7 +264,10 @@ void icp_set_cppr(XICSState *xics, int server, uint8_t cppr)
>              ss->xirr &= ~XISR_MASK; /* Clear XISR */
>              ss->pending_priority = 0xff;
>              qemu_irq_lower(ss->output);
> -            ics_reject(xics->ics, old_xisr);
> +            if (ss->xirr_owner) {
> +                ics_reject(ss->xirr_owner, old_xisr);
> +                ss->xirr_owner = NULL;
> +            }
>          }
>      } else {
>          if (!XISR(ss)) {
> @@ -271,7 +282,7 @@ void icp_set_mfrr(XICSState *xics, int server, uint8_t mfrr)
>  
>      ss->mfrr = mfrr;
>      if (mfrr < CPPR(ss)) {
> -        icp_check_ipi(xics, server);
> +        icp_check_ipi(ss);
>      }
>  }
>  
> @@ -282,6 +293,7 @@ uint32_t icp_accept(ICPState *ss)
>      qemu_irq_lower(ss->output);
>      ss->xirr = ss->pending_priority << 24;
>      ss->pending_priority = 0xff;
> +    ss->xirr_owner = NULL;
>  
>      trace_xics_icp_accept(xirr, ss->xirr);
>  
> @@ -299,30 +311,40 @@ uint32_t icp_ipoll(ICPState *ss, uint32_t *mfrr)
>  void icp_eoi(XICSState *xics, int server, uint32_t xirr)
>  {
>      ICPState *ss = xics->ss + server;
> +    ICSState *ics;
> +    uint32_t irq;
>  
>      /* Send EOI -> ICS */
>      ss->xirr = (ss->xirr & ~CPPR_MASK) | (xirr & CPPR_MASK);
>      trace_xics_icp_eoi(server, xirr, ss->xirr);
> -    ics_eoi(xics->ics, xirr & XISR_MASK);
> +    irq = xirr & XISR_MASK;
> +    QLIST_FOREACH(ics, &xics->ics, list) {
> +        if (ics_valid_irq(ics, irq)) {
> +            ics_eoi(ics, irq);
> +        }
> +    }
>      if (!XISR(ss)) {
>          icp_resend(xics, server);
>      }
>  }
>  
> -static void icp_irq(XICSState *xics, int server, int nr, uint8_t priority)
> +static void icp_irq(ICSState *ics, int server, int nr, uint8_t priority)
>  {
> +    XICSState *xics = ics->xics;
>      ICPState *ss = xics->ss + server;
>  
>      trace_xics_icp_irq(server, nr, priority);
>  
>      if ((priority >= CPPR(ss))
>          || (XISR(ss) && (ss->pending_priority <= priority))) {
> -        ics_reject(xics->ics, nr);
> +        ics_reject(ics, nr);
>      } else {
> -        if (XISR(ss)) {
> -            ics_reject(xics->ics, XISR(ss));
> +        if (XISR(ss) && ss->xirr_owner) {
> +            ics_reject(ss->xirr_owner, XISR(ss));
> +            ss->xirr_owner = NULL;
>          }
>          ss->xirr = (ss->xirr & ~XISR_MASK) | (nr & XISR_MASK);
> +        ss->xirr_owner = ics;
>          ss->pending_priority = priority;
>          trace_xics_icp_raise(ss->xirr, ss->pending_priority);
>          qemu_irq_raise(ss->output);
> @@ -378,12 +400,45 @@ static void icp_reset(DeviceState *dev)
>      qemu_set_irq(icp->output, 0);
>  }
>  
> +static int icp_post_load(ICPState *ss, int version_id)
> +{
> +    sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
> +    XICSState *xics = spapr->xics;
> +    uint32_t irq, i;
> +    static uint32_t server_no;
> +
> +    server_no++;
> +    irq = XISR(ss);
> +    if (!ss->cs || !irq) {
> +        goto icpend;
> +    }
> +
> +    /* Restore the xirr_owner */
> +    ss->xirr_owner = xics_find_source(xics, irq);
> +
> + icpend:
> +    trace_xics_icp_post_load(server_no, ss->xirr, (uint64_t)ss->xirr_owner,
> +                             ss->pending_priority);
> +    if (xics->nr_servers != server_no) {
> +        return 0;
> +    }
> +
> +    /* All the ICPs are processed, now restore all the state */
> +    for (i = 0; i < xics->nr_servers; i++) {
> +        icp_resend(xics, i);
> +    }
> +    server_no = 0;
> +    return 0;
> +}

Is the issue this change is trying to fix related to ICSState becoming 
a list ? If not, It should be in another patch I think.

Thanks,

C. 

>  static void icp_class_init(ObjectClass *klass, void *data)
>  {
>      DeviceClass *dc = DEVICE_CLASS(klass);
> +    ICPStateClass *icpc = ICP_CLASS(klass);
>  
>      dc->reset = icp_reset;
>      dc->vmsd = &vmstate_icp_server;
> +    icpc->post_load = icp_post_load;
>  }
>  
>  static const TypeInfo icp_info = {
> @@ -405,8 +460,7 @@ static void resend_msi(ICSState *ics, int srcno)
>      if (irq->status & XICS_STATUS_REJECTED) {
>          irq->status &= ~XICS_STATUS_REJECTED;
>          if (irq->priority != 0xff) {
> -            icp_irq(ics->xics, irq->server, srcno + ics->offset,
> -                    irq->priority);
> +            icp_irq(ics, irq->server, srcno + ics->offset, irq->priority);
>          }
>      }
>  }
> @@ -419,7 +473,7 @@ static void resend_lsi(ICSState *ics, int srcno)
>          && (irq->status & XICS_STATUS_ASSERTED)
>          && !(irq->status & XICS_STATUS_SENT)) {
>          irq->status |= XICS_STATUS_SENT;
> -        icp_irq(ics->xics, irq->server, srcno + ics->offset, irq->priority);
> +        icp_irq(ics, irq->server, srcno + ics->offset, irq->priority);
>      }
>  }
>  
> @@ -434,7 +488,7 @@ static void set_irq_msi(ICSState *ics, int srcno, int val)
>              irq->status |= XICS_STATUS_MASKED_PENDING;
>              trace_xics_masked_pending();
>          } else  {
> -            icp_irq(ics->xics, irq->server, srcno + ics->offset, irq->priority);
> +            icp_irq(ics, irq->server, srcno + ics->offset, irq->priority);
>          }
>      }
>  }
> @@ -473,7 +527,7 @@ static void write_xive_msi(ICSState *ics, int srcno)
>      }
>  
>      irq->status &= ~XICS_STATUS_MASKED_PENDING;
> -    icp_irq(ics->xics, irq->server, srcno + ics->offset, irq->priority);
> +    icp_irq(ics, irq->server, srcno + ics->offset, irq->priority);
>  }
>  
>  static void write_xive_lsi(ICSState *ics, int srcno)
> @@ -568,17 +622,6 @@ static void ics_reset(DeviceState *dev)
>      }
>  }
>  
> -static int ics_post_load(ICSState *ics, int version_id)
> -{
> -    int i;
> -
> -    for (i = 0; i < ics->xics->nr_servers; i++) {
> -        icp_resend(ics->xics, i);
> -    }
> -
> -    return 0;
> -}
> -
>  static void ics_dispatch_pre_save(void *opaque)
>  {
>      ICSState *ics = opaque;
> @@ -653,12 +696,10 @@ static void ics_realize(DeviceState *dev, Error **errp)
>  static void ics_class_init(ObjectClass *klass, void *data)
>  {
>      DeviceClass *dc = DEVICE_CLASS(klass);
> -    ICSStateClass *isc = ICS_CLASS(klass);
>  
>      dc->realize = ics_realize;
>      dc->vmsd = &vmstate_ics;
>      dc->reset = ics_reset;
> -    isc->post_load = ics_post_load;
>  }
>  
>  static const TypeInfo ics_info = {
> @@ -673,28 +714,23 @@ static const TypeInfo ics_info = {
>  /*
>   * Exported functions
>   */
> -int xics_find_source(XICSState *xics, int irq)
> +ICSState *xics_find_source(XICSState *xics, int irq)
>  {
> -    int sources = 1;
> -    int src;
> +    ICSState *ics;
>  
> -    /* FIXME: implement multiple sources */
> -    for (src = 0; src < sources; ++src) {
> -        ICSState *ics = &xics->ics[src];
> +    QLIST_FOREACH(ics, &xics->ics, list) {
>          if (ics_valid_irq(ics, irq)) {
> -            return src;
> +            return ics;
>          }
>      }
> -
> -    return -1;
> +    return NULL;
>  }
>  
>  qemu_irq xics_get_qirq(XICSState *xics, int irq)
>  {
> -    int src = xics_find_source(xics, irq);
> +    ICSState *ics = xics_find_source(xics, irq);
>  
> -    if (src >= 0) {
> -        ICSState *ics = &xics->ics[src];
> +    if (ics) {
>          return ics->qirqs[irq - ics->offset];
>      }
>  
> diff --git a/hw/intc/xics_kvm.c b/hw/intc/xics_kvm.c
> index edbd62f..04fa7cb 100644
> --- a/hw/intc/xics_kvm.c
> +++ b/hw/intc/xics_kvm.c
> @@ -365,7 +365,13 @@ static void xics_kvm_cpu_setup(XICSState *xics, PowerPCCPU *cpu)
>  static void xics_kvm_set_nr_irqs(XICSState *xics, uint32_t nr_irqs,
>                                   Error **errp)
>  {
> -    xics->nr_irqs = xics->ics->nr_irqs = nr_irqs;
> +    ICSState *ics = QLIST_FIRST(&xics->ics);
> +
> +    /* This needs to be deprecated ... */
> +    xics->nr_irqs = nr_irqs;
> +    if (ics) {
> +        ics->nr_irqs = nr_irqs;
> +    }
>  }
>  
>  static void xics_kvm_set_nr_servers(XICSState *xics, uint32_t nr_servers,
> @@ -398,6 +404,7 @@ static void xics_kvm_realize(DeviceState *dev, Error **errp)
>  {
>      KVMXICSState *xicskvm = XICS_SPAPR_KVM(dev);
>      XICSState *xics = XICS_COMMON(dev);
> +    ICSState *ics;
>      int i, rc;
>      Error *error = NULL;
>      struct kvm_create_device xics_create_device = {
> @@ -449,10 +456,12 @@ static void xics_kvm_realize(DeviceState *dev, Error **errp)
>  
>      xicskvm->kernel_xics_fd = xics_create_device.fd;
>  
> -    object_property_set_bool(OBJECT(xics->ics), true, "realized", &error);
> -    if (error) {
> -        error_propagate(errp, error);
> -        goto fail;
> +    QLIST_FOREACH(ics, &xics->ics, list) {
> +        object_property_set_bool(OBJECT(ics), true, "realized", &error);
> +        if (error) {
> +            error_propagate(errp, error);
> +            goto fail;
> +        }
>      }
>  
>      assert(xics->nr_servers);
> @@ -481,10 +490,12 @@ fail:
>  static void xics_kvm_initfn(Object *obj)
>  {
>      XICSState *xics = XICS_COMMON(obj);
> +    ICSState *ics;
>  
> -    xics->ics = ICS(object_new(TYPE_KVM_ICS));
> -    object_property_add_child(obj, "ics", OBJECT(xics->ics), NULL);
> -    xics->ics->xics = xics;
> +    ics = ICS(object_new(TYPE_KVM_ICS));
> +    object_property_add_child(obj, "ics", OBJECT(ics), NULL);
> +    ics->xics = xics;
> +    QLIST_INSERT_HEAD(&xics->ics, ics, list);
>  }
>  
>  static void xics_kvm_class_init(ObjectClass *oc, void *data)
> diff --git a/hw/intc/xics_spapr.c b/hw/intc/xics_spapr.c
> index 618826d..0b0845d 100644
> --- a/hw/intc/xics_spapr.c
> +++ b/hw/intc/xics_spapr.c
> @@ -113,13 +113,17 @@ static void rtas_set_xive(PowerPCCPU *cpu, sPAPRMachineState *spapr,
>                            uint32_t nargs, target_ulong args,
>                            uint32_t nret, target_ulong rets)
>  {
> -    ICSState *ics = spapr->xics->ics;
> +    ICSState *ics = QLIST_FIRST(&spapr->xics->ics);
>      uint32_t nr, server, priority;
>  
>      if ((nargs != 3) || (nret != 1)) {
>          rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
>          return;
>      }
> +    if (!ics) {
> +        rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
> +        return;
> +    }
>  
>      nr = rtas_ld(args, 0);
>      server = xics_get_cpu_index_by_dt_id(rtas_ld(args, 1));
> @@ -141,13 +145,17 @@ static void rtas_get_xive(PowerPCCPU *cpu, sPAPRMachineState *spapr,
>                            uint32_t nargs, target_ulong args,
>                            uint32_t nret, target_ulong rets)
>  {
> -    ICSState *ics = spapr->xics->ics;
> +    ICSState *ics = QLIST_FIRST(&spapr->xics->ics);
>      uint32_t nr;
>  
>      if ((nargs != 1) || (nret != 3)) {
>          rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
>          return;
>      }
> +    if (!ics) {
> +        rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
> +        return;
> +    }
>  
>      nr = rtas_ld(args, 0);
>  
> @@ -166,13 +174,17 @@ static void rtas_int_off(PowerPCCPU *cpu, sPAPRMachineState *spapr,
>                           uint32_t nargs, target_ulong args,
>                           uint32_t nret, target_ulong rets)
>  {
> -    ICSState *ics = spapr->xics->ics;
> +    ICSState *ics = QLIST_FIRST(&spapr->xics->ics);
>      uint32_t nr;
>  
>      if ((nargs != 1) || (nret != 1)) {
>          rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
>          return;
>      }
> +    if (!ics) {
> +        rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
> +        return;
> +    }
>  
>      nr = rtas_ld(args, 0);
>  
> @@ -192,13 +204,17 @@ static void rtas_int_on(PowerPCCPU *cpu, sPAPRMachineState *spapr,
>                          uint32_t nargs, target_ulong args,
>                          uint32_t nret, target_ulong rets)
>  {
> -    ICSState *ics = spapr->xics->ics;
> +    ICSState *ics = QLIST_FIRST(&spapr->xics->ics);
>      uint32_t nr;
>  
>      if ((nargs != 1) || (nret != 1)) {
>          rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
>          return;
>      }
> +    if (!ics) {
> +        rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
> +        return;
> +    }
>  
>      nr = rtas_ld(args, 0);
>  
> @@ -217,7 +233,13 @@ static void rtas_int_on(PowerPCCPU *cpu, sPAPRMachineState *spapr,
>  static void xics_spapr_set_nr_irqs(XICSState *xics, uint32_t nr_irqs,
>                                     Error **errp)
>  {
> -    xics->nr_irqs = xics->ics->nr_irqs = nr_irqs;
> +    ICSState *ics = QLIST_FIRST(&xics->ics);
> +
> +    /* This needs to be deprecated ... */
> +    xics->nr_irqs = nr_irqs;
> +    if (ics) {
> +        ics->nr_irqs = nr_irqs;
> +    }
>  }
>  
>  static void xics_spapr_set_nr_servers(XICSState *xics, uint32_t nr_servers,
> @@ -240,6 +262,7 @@ static void xics_spapr_set_nr_servers(XICSState *xics, uint32_t nr_servers,
>  static void xics_spapr_realize(DeviceState *dev, Error **errp)
>  {
>      XICSState *xics = XICS_SPAPR(dev);
> +    ICSState *ics;
>      Error *error = NULL;
>      int i;
>  
> @@ -261,10 +284,12 @@ static void xics_spapr_realize(DeviceState *dev, Error **errp)
>      spapr_register_hypercall(H_EOI, h_eoi);
>      spapr_register_hypercall(H_IPOLL, h_ipoll);
>  
> -    object_property_set_bool(OBJECT(xics->ics), true, "realized", &error);
> -    if (error) {
> -        error_propagate(errp, error);
> -        return;
> +    QLIST_FOREACH(ics, &xics->ics, list) {
> +        object_property_set_bool(OBJECT(ics), true, "realized", &error);
> +        if (error) {
> +            error_propagate(errp, error);
> +            return;
> +        }
>      }
>  
>      for (i = 0; i < xics->nr_servers; i++) {
> @@ -280,10 +305,12 @@ static void xics_spapr_realize(DeviceState *dev, Error **errp)
>  static void xics_spapr_initfn(Object *obj)
>  {
>      XICSState *xics = XICS_SPAPR(obj);
> +    ICSState *ics;
>  
> -    xics->ics = ICS(object_new(TYPE_ICS));
> -    object_property_add_child(obj, "ics", OBJECT(xics->ics), NULL);
> -    xics->ics->xics = xics;
> +    ics = ICS(object_new(TYPE_ICS));
> +    object_property_add_child(obj, "ics", OBJECT(ics), NULL);
> +    ics->xics = xics;
> +    QLIST_INSERT_HEAD(&xics->ics, ics, list);
>  }
>  
>  static void xics_spapr_class_init(ObjectClass *oc, void *data)
> @@ -329,14 +356,15 @@ static int ics_find_free_block(ICSState *ics, int num, int alignnum)
>      return -1;
>  }
>  
> -int xics_spapr_alloc(XICSState *xics, int src, int irq_hint, bool lsi,
> -                     Error **errp)
> +int xics_spapr_alloc(XICSState *xics, int irq_hint, bool lsi, Error **errp)
>  {
> -    ICSState *ics = &xics->ics[src];
> +    ICSState *ics = QLIST_FIRST(&xics->ics);
>      int irq;
>  
> +    if (!ics) {
> +        return -1;
> +    }
>      if (irq_hint) {
> -        assert(src == xics_find_source(xics, irq_hint));
>          if (!ICS_IRQ_FREE(ics, irq_hint - ics->offset)) {
>              error_setg(errp, "can't allocate IRQ %d: already in use", irq_hint);
>              return -1;
> @@ -352,7 +380,7 @@ int xics_spapr_alloc(XICSState *xics, int src, int irq_hint, bool lsi,
>      }
>  
>      ics_set_irq_type(ics, irq - ics->offset, lsi);
> -    trace_xics_alloc(src, irq);
> +    trace_xics_alloc(irq);
>  
>      return irq;
>  }
> @@ -361,13 +389,16 @@ int xics_spapr_alloc(XICSState *xics, int src, int irq_hint, bool lsi,
>   * Allocate block of consecutive IRQs, and return the number of the first IRQ in
>   * the block. If align==true, aligns the first IRQ number to num.
>   */
> -int xics_spapr_alloc_block(XICSState *xics, int src, int num, bool lsi,
> -                           bool align, Error **errp)
> +int xics_spapr_alloc_block(XICSState *xics, int num, bool lsi, bool align,
> +                           Error **errp)
>  {
> +    ICSState *ics = QLIST_FIRST(&xics->ics);
>      int i, first = -1;
> -    ICSState *ics = &xics->ics[src];
>  
> -    assert(src == 0);
> +    if (!ics) {
> +        return -1;
> +    }
> +
>      /*
>       * MSIMesage::data is used for storing VIRQ so
>       * it has to be aligned to num to support multiple
> @@ -394,7 +425,7 @@ int xics_spapr_alloc_block(XICSState *xics, int src, int num, bool lsi,
>      }
>      first += ics->offset;
>  
> -    trace_xics_alloc_block(src, first, num, lsi, align);
> +    trace_xics_alloc_block(first, num, lsi, align);
>  
>      return first;
>  }
> @@ -405,7 +436,7 @@ static void ics_free(ICSState *ics, int srcno, int num)
>  
>      for (i = srcno; i < srcno + num; ++i) {
>          if (ICS_IRQ_FREE(ics, i)) {
> -            trace_xics_ics_free_warn(ics - ics->xics->ics, i + ics->offset);
> +            trace_xics_ics_free_warn(0, i + ics->offset);
>          }
>          memset(&ics->irqs[i], 0, sizeof(ICSIRQState));
>      }
> @@ -413,15 +444,10 @@ static void ics_free(ICSState *ics, int srcno, int num)
>  
>  void xics_spapr_free(XICSState *xics, int irq, int num)
>  {
> -    int src = xics_find_source(xics, irq);
> -
> -    if (src >= 0) {
> -        ICSState *ics = &xics->ics[src];
> -
> -        /* FIXME: implement multiple sources */
> -        assert(src == 0);
> +    ICSState *ics = xics_find_source(xics, irq);
>  
> -        trace_xics_ics_free(ics - xics->ics, irq, num);
> +    if (ics) {
> +        trace_xics_ics_free(0, irq, num);
>          ics_free(ics, irq - ics->offset, num);
>      }
>  }
> diff --git a/hw/ppc/spapr_events.c b/hw/ppc/spapr_events.c
> index b0668b3..adf8da4 100644
> --- a/hw/ppc/spapr_events.c
> +++ b/hw/ppc/spapr_events.c
> @@ -603,7 +603,7 @@ out_no_events:
>  void spapr_events_init(sPAPRMachineState *spapr)
>  {
>      QTAILQ_INIT(&spapr->pending_events);
> -    spapr->check_exception_irq = xics_spapr_alloc(spapr->xics, 0, 0, false,
> +    spapr->check_exception_irq = xics_spapr_alloc(spapr->xics, 0, false,
>                                              &error_fatal);
>      spapr->epow_notifier.notify = spapr_powerdown_req;
>      qemu_register_powerdown_notifier(&spapr->epow_notifier);
> diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
> index 949c44f..4d06794 100644
> --- a/hw/ppc/spapr_pci.c
> +++ b/hw/ppc/spapr_pci.c
> @@ -362,7 +362,7 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, sPAPRMachineState *spapr,
>      }
>  
>      /* Allocate MSIs */
> -    irq = xics_spapr_alloc_block(spapr->xics, 0, req_num, false,
> +    irq = xics_spapr_alloc_block(spapr->xics, req_num, false,
>                             ret_intr_type == RTAS_TYPE_MSI, &err);
>      if (err) {
>          error_reportf_err(err, "Can't allocate MSIs for device %x: ",
> @@ -1444,8 +1444,7 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp)
>          uint32_t irq;
>          Error *local_err = NULL;
>  
> -        irq = xics_spapr_alloc_block(spapr->xics, 0, 1, true, false,
> -                                     &local_err);
> +        irq = xics_spapr_alloc_block(spapr->xics, 1, true, false, &local_err);
>          if (local_err) {
>              error_propagate(errp, local_err);
>              error_prepend(errp, "can't allocate LSIs: ");
> diff --git a/hw/ppc/spapr_vio.c b/hw/ppc/spapr_vio.c
> index f93244d..22360af 100644
> --- a/hw/ppc/spapr_vio.c
> +++ b/hw/ppc/spapr_vio.c
> @@ -463,7 +463,7 @@ static void spapr_vio_busdev_realize(DeviceState *qdev, Error **errp)
>          dev->qdev.id = id;
>      }
>  
> -    dev->irq = xics_spapr_alloc(spapr->xics, 0, dev->irq, false, &local_err);
> +    dev->irq = xics_spapr_alloc(spapr->xics, dev->irq, false, &local_err);
>      if (local_err) {
>          error_propagate(errp, local_err);
>          return;
> diff --git a/include/hw/ppc/xics.h b/include/hw/ppc/xics.h
> index 2db9f93..1ea40bd 100644
> --- a/include/hw/ppc/xics.h
> +++ b/include/hw/ppc/xics.h
> @@ -85,7 +85,7 @@ struct XICSState {
>      uint32_t nr_servers;
>      uint32_t nr_irqs;
>      ICPState *ss;
> -    ICSState *ics;
> +    QLIST_HEAD(, ICSState) ics;
>  };
>  
>  #define TYPE_ICP "icp"
> @@ -111,6 +111,7 @@ struct ICPState {
>      DeviceState parent_obj;
>      /*< public >*/
>      CPUState *cs;
> +    ICSState *xirr_owner;
>      uint32_t xirr;
>      uint8_t pending_priority;
>      uint8_t mfrr;
> @@ -145,6 +146,7 @@ struct ICSState {
>      qemu_irq *qirqs;
>      ICSIRQState *irqs;
>      XICSState *xics;
> +    QLIST_ENTRY(ICSState) list;
>  };
>  
>  static inline bool ics_valid_irq(ICSState *ics, uint32_t nr)
> @@ -172,10 +174,9 @@ struct ICSIRQState {
>  #define XICS_IRQS_SPAPR               1024
>  
>  qemu_irq xics_get_qirq(XICSState *icp, int irq);
> -int xics_spapr_alloc(XICSState *icp, int src, int irq_hint, bool lsi,
> -                     Error **errp);
> -int xics_spapr_alloc_block(XICSState *icp, int src, int num, bool lsi,
> -                           bool align, Error **errp);
> +int xics_spapr_alloc(XICSState *icp, int irq_hint, bool lsi, Error **errp);
> +int xics_spapr_alloc_block(XICSState *icp, int num, bool lsi, bool align,
> +                           Error **errp);
>  void xics_spapr_free(XICSState *icp, int irq, int num);
>  
>  void xics_cpu_setup(XICSState *icp, PowerPCCPU *cpu);
> @@ -195,6 +196,6 @@ void ics_write_xive(ICSState *ics, int nr, int server,
>  
>  void ics_set_irq_type(ICSState *ics, int srcno, bool lsi);
>  
> -int xics_find_source(XICSState *icp, int irq);
> +ICSState *xics_find_source(XICSState *icp, int irq);
>  
>  #endif /* XICS_H */
> 

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [Qemu-ppc] [PATCH v4 3/9] ppc/xics: Make the ICSState a list
  2016-09-19  6:59   ` [Qemu-devel] [Qemu-ppc] " Cédric Le Goater
@ 2016-09-19  7:02     ` Nikunj A Dadhania
  2016-09-19  7:24       ` Cédric Le Goater
  0 siblings, 1 reply; 38+ messages in thread
From: Nikunj A Dadhania @ 2016-09-19  7:02 UTC (permalink / raw)
  To: Cédric Le Goater, qemu-ppc, david; +Cc: qemu-devel

Cédric Le Goater <clg@kaod.org> writes:

> On 09/19/2016 08:29 AM, Nikunj A Dadhania wrote:
>> From: Benjamin Herrenschmidt <benh@kernel.crashing.org>
>> 
>> Instead of an array of fixed sized blocks, use a list, as we will need
>> to have sources with variable number of interrupts. SPAPR only uses
>> a single entry. Native will create more. If performance becomes an
>> issue we can add some hashed lookup but for now this will do fine.
>> 
>> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
>> [ move the initialization of list to xics_common_initfn,
>>   restore xirr_owner after migration and move restoring to
>>   icp_post_load]
>> Signed-off-by: Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>
>
> This looks good to me apart from the change of icp_post_load(). 
>
>> ---
>>  hw/intc/trace-events  |   5 +-
>>  hw/intc/xics.c        | 130 ++++++++++++++++++++++++++++++++------------------
>>  hw/intc/xics_kvm.c    |  27 +++++++----
>>  hw/intc/xics_spapr.c  |  88 ++++++++++++++++++++++------------
>>  hw/ppc/spapr_events.c |   2 +-
>>  hw/ppc/spapr_pci.c    |   5 +-
>>  hw/ppc/spapr_vio.c    |   2 +-
>>  include/hw/ppc/xics.h |  13 ++---
>>  8 files changed, 173 insertions(+), 99 deletions(-)
>> 
>> diff --git a/hw/intc/trace-events b/hw/intc/trace-events
>> index f12192c..aa342a8 100644
>> --- a/hw/intc/trace-events
>> +++ b/hw/intc/trace-events
>> @@ -56,10 +56,11 @@ xics_set_irq_lsi(int srcno, int nr) "set_irq_lsi: srcno %d [irq %#x]"
>>  xics_ics_write_xive(int nr, int srcno, int server, uint8_t priority) "ics_write_xive: irq %#x [src %d] server %#x prio %#x"
>>  xics_ics_reject(int nr, int srcno) "reject irq %#x [src %d]"
>>  xics_ics_eoi(int nr) "ics_eoi: irq %#x"
>> -xics_alloc(int src, int irq) "source#%d, irq %d"
>> -xics_alloc_block(int src, int first, int num, bool lsi, int align) "source#%d, first irq %d, %d irqs, lsi=%d, alignnum %d"
>> +xics_alloc(int irq) "irq %d"
>> +xics_alloc_block(int first, int num, bool lsi, int align) "first irq %d, %d irqs, lsi=%d, alignnum %d"
>>  xics_ics_free(int src, int irq, int num) "Source#%d, first irq %d, %d irqs"
>>  xics_ics_free_warn(int src, int irq) "Source#%d, irq %d is already free"
>> +xics_icp_post_load(uint32_t server_no, uint32_t xirr, uint64_t addr, uint8_t pend) "server_no %d, xirr %#x, xirr_owner 0x%" PRIx64 ", pending %d"
>>  
>>  # hw/intc/s390_flic_kvm.c
>>  flic_create_device(int err) "flic: create device failed %d"
>> diff --git a/hw/intc/xics.c b/hw/intc/xics.c
>> index f765b08..05e938f 100644
>> --- a/hw/intc/xics.c
>> +++ b/hw/intc/xics.c
>> @@ -32,6 +32,7 @@
>>  #include "hw/hw.h"
>>  #include "trace.h"
>>  #include "qemu/timer.h"
>> +#include "hw/ppc/spapr.h"
>>  #include "hw/ppc/xics.h"
>>  #include "qemu/error-report.h"
>>  #include "qapi/visitor.h"
>> @@ -96,13 +97,16 @@ void xics_cpu_setup(XICSState *xics, PowerPCCPU *cpu)
>>  static void xics_common_reset(DeviceState *d)
>>  {
>>      XICSState *xics = XICS_COMMON(d);
>> +    ICSState *ics;
>>      int i;
>>  
>>      for (i = 0; i < xics->nr_servers; i++) {
>>          device_reset(DEVICE(&xics->ss[i]));
>>      }
>>  
>> -    device_reset(DEVICE(xics->ics));
>> +    QLIST_FOREACH(ics, &xics->ics, list) {
>> +        device_reset(DEVICE(ics));
>> +    }
>>  }
>>  
>>  static void xics_prop_get_nr_irqs(Object *obj, Visitor *v, const char *name,
>> @@ -134,7 +138,6 @@ static void xics_prop_set_nr_irqs(Object *obj, Visitor *v, const char *name,
>>      }
>>  
>>      assert(info->set_nr_irqs);
>> -    assert(xics->ics);
>>      info->set_nr_irqs(xics, value, errp);
>>  }
>>  
>> @@ -174,6 +177,9 @@ static void xics_prop_set_nr_servers(Object *obj, Visitor *v,
>>  
>>  static void xics_common_initfn(Object *obj)
>>  {
>> +    XICSState *xics = XICS_COMMON(obj);
>> +
>> +    QLIST_INIT(&xics->ics);
>>      object_property_add(obj, "nr_irqs", "int",
>>                          xics_prop_get_nr_irqs, xics_prop_set_nr_irqs,
>>                          NULL, NULL, NULL);
>> @@ -212,33 +218,35 @@ static void ics_reject(ICSState *ics, int nr);
>>  static void ics_resend(ICSState *ics, int server);
>>  static void ics_eoi(ICSState *ics, int nr);
>>  
>> -static void icp_check_ipi(XICSState *xics, int server)
>> +static void icp_check_ipi(ICPState *ss)
>>  {
>> -    ICPState *ss = xics->ss + server;
>> -
>>      if (XISR(ss) && (ss->pending_priority <= ss->mfrr)) {
>>          return;
>>      }
>>  
>> -    trace_xics_icp_check_ipi(server, ss->mfrr);
>> +    trace_xics_icp_check_ipi(ss->cs->cpu_index, ss->mfrr);
>>  
>> -    if (XISR(ss)) {
>> -        ics_reject(xics->ics, XISR(ss));
>> +    if (XISR(ss) && ss->xirr_owner) {
>> +        ics_reject(ss->xirr_owner, XISR(ss));
>>      }
>>  
>>      ss->xirr = (ss->xirr & ~XISR_MASK) | XICS_IPI;
>>      ss->pending_priority = ss->mfrr;
>> +    ss->xirr_owner = NULL;
>>      qemu_irq_raise(ss->output);
>>  }
>>  
>>  static void icp_resend(XICSState *xics, int server)
>>  {
>>      ICPState *ss = xics->ss + server;
>> +    ICSState *ics;
>>  
>>      if (ss->mfrr < CPPR(ss)) {
>> -        icp_check_ipi(xics, server);
>> +        icp_check_ipi(ss);
>> +    }
>> +    QLIST_FOREACH(ics, &xics->ics, list) {
>> +        ics_resend(ics, server);
>>      }
>> -    ics_resend(xics->ics, server);
>>  }
>>  
>>  void icp_set_cppr(XICSState *xics, int server, uint8_t cppr)
>> @@ -256,7 +264,10 @@ void icp_set_cppr(XICSState *xics, int server, uint8_t cppr)
>>              ss->xirr &= ~XISR_MASK; /* Clear XISR */
>>              ss->pending_priority = 0xff;
>>              qemu_irq_lower(ss->output);
>> -            ics_reject(xics->ics, old_xisr);
>> +            if (ss->xirr_owner) {
>> +                ics_reject(ss->xirr_owner, old_xisr);
>> +                ss->xirr_owner = NULL;
>> +            }
>>          }
>>      } else {
>>          if (!XISR(ss)) {
>> @@ -271,7 +282,7 @@ void icp_set_mfrr(XICSState *xics, int server, uint8_t mfrr)
>>  
>>      ss->mfrr = mfrr;
>>      if (mfrr < CPPR(ss)) {
>> -        icp_check_ipi(xics, server);
>> +        icp_check_ipi(ss);
>>      }
>>  }
>>  
>> @@ -282,6 +293,7 @@ uint32_t icp_accept(ICPState *ss)
>>      qemu_irq_lower(ss->output);
>>      ss->xirr = ss->pending_priority << 24;
>>      ss->pending_priority = 0xff;
>> +    ss->xirr_owner = NULL;
>>  
>>      trace_xics_icp_accept(xirr, ss->xirr);
>>  
>> @@ -299,30 +311,40 @@ uint32_t icp_ipoll(ICPState *ss, uint32_t *mfrr)
>>  void icp_eoi(XICSState *xics, int server, uint32_t xirr)
>>  {
>>      ICPState *ss = xics->ss + server;
>> +    ICSState *ics;
>> +    uint32_t irq;
>>  
>>      /* Send EOI -> ICS */
>>      ss->xirr = (ss->xirr & ~CPPR_MASK) | (xirr & CPPR_MASK);
>>      trace_xics_icp_eoi(server, xirr, ss->xirr);
>> -    ics_eoi(xics->ics, xirr & XISR_MASK);
>> +    irq = xirr & XISR_MASK;
>> +    QLIST_FOREACH(ics, &xics->ics, list) {
>> +        if (ics_valid_irq(ics, irq)) {
>> +            ics_eoi(ics, irq);
>> +        }
>> +    }
>>      if (!XISR(ss)) {
>>          icp_resend(xics, server);
>>      }
>>  }
>>  
>> -static void icp_irq(XICSState *xics, int server, int nr, uint8_t priority)
>> +static void icp_irq(ICSState *ics, int server, int nr, uint8_t priority)
>>  {
>> +    XICSState *xics = ics->xics;
>>      ICPState *ss = xics->ss + server;
>>  
>>      trace_xics_icp_irq(server, nr, priority);
>>  
>>      if ((priority >= CPPR(ss))
>>          || (XISR(ss) && (ss->pending_priority <= priority))) {
>> -        ics_reject(xics->ics, nr);
>> +        ics_reject(ics, nr);
>>      } else {
>> -        if (XISR(ss)) {
>> -            ics_reject(xics->ics, XISR(ss));
>> +        if (XISR(ss) && ss->xirr_owner) {
>> +            ics_reject(ss->xirr_owner, XISR(ss));
>> +            ss->xirr_owner = NULL;
>>          }
>>          ss->xirr = (ss->xirr & ~XISR_MASK) | (nr & XISR_MASK);
>> +        ss->xirr_owner = ics;
>>          ss->pending_priority = priority;
>>          trace_xics_icp_raise(ss->xirr, ss->pending_priority);
>>          qemu_irq_raise(ss->output);
>> @@ -378,12 +400,45 @@ static void icp_reset(DeviceState *dev)
>>      qemu_set_irq(icp->output, 0);
>>  }
>>  
>> +static int icp_post_load(ICPState *ss, int version_id)
>> +{
>> +    sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
>> +    XICSState *xics = spapr->xics;
>> +    uint32_t irq, i;
>> +    static uint32_t server_no;
>> +
>> +    server_no++;
>> +    irq = XISR(ss);
>> +    if (!ss->cs || !irq) {
>> +        goto icpend;
>> +    }
>> +
>> +    /* Restore the xirr_owner */
>> +    ss->xirr_owner = xics_find_source(xics, irq);
>> +
>> + icpend:
>> +    trace_xics_icp_post_load(server_no, ss->xirr, (uint64_t)ss->xirr_owner,
>> +                             ss->pending_priority);
>> +    if (xics->nr_servers != server_no) {
>> +        return 0;
>> +    }
>> +
>> +    /* All the ICPs are processed, now restore all the state */
>> +    for (i = 0; i < xics->nr_servers; i++) {
>> +        icp_resend(xics, i);
>> +    }
>> +    server_no = 0;
>> +    return 0;
>> +}
>
> Is the issue this change is trying to fix related to ICSState becoming 
> a list ? If not, It should be in another patch I think.

Yes, and we introduced xirr_owner to optimize. This needs to regenerated
at the destination after migration.

Regards
Nikunj

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [Qemu-ppc] [PATCH v4 7/9] ppc/xics: Add "native" XICS subclass
  2016-09-19  6:29 ` [Qemu-devel] [PATCH v4 7/9] ppc/xics: Add "native" XICS subclass Nikunj A Dadhania
@ 2016-09-19  7:03   ` Cédric Le Goater
  2016-09-22  0:02   ` [Qemu-devel] " David Gibson
  1 sibling, 0 replies; 38+ messages in thread
From: Cédric Le Goater @ 2016-09-19  7:03 UTC (permalink / raw)
  To: Nikunj A Dadhania, qemu-ppc, david; +Cc: qemu-devel

On 09/19/2016 08:29 AM, Nikunj A Dadhania wrote:
> From: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> 
> This provides MMIO based ICP access as found on POWER8
> 
> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> Signed-off-by: Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>

There are further changes to do on this one before merging it.
I think we should wait a bit. Any way, we lack CONFIG_POWERNV
for the moment.

Thanks,

C. 

> ---
>  default-configs/ppc64-softmmu.mak |   3 +-
>  hw/intc/Makefile.objs             |   1 +
>  hw/intc/xics_native.c             | 295 ++++++++++++++++++++++++++++++++++++++
>  include/hw/ppc/xics.h             |  14 ++
>  4 files changed, 312 insertions(+), 1 deletion(-)
>  create mode 100644 hw/intc/xics_native.c
> 
> diff --git a/default-configs/ppc64-softmmu.mak b/default-configs/ppc64-softmmu.mak
> index c4be59f..315e30b 100644
> --- a/default-configs/ppc64-softmmu.mak
> +++ b/default-configs/ppc64-softmmu.mak
> @@ -48,8 +48,9 @@ CONFIG_PLATFORM_BUS=y
>  CONFIG_ETSEC=y
>  CONFIG_LIBDECNUMBER=y
>  # For pSeries
> -CONFIG_XICS=$(CONFIG_PSERIES)
> +CONFIG_XICS=$(or $(CONFIG_PSERIES),$(CONFIG_POWERNV))
>  CONFIG_XICS_SPAPR=$(CONFIG_PSERIES)
> +CONFIG_XICS_NATIVE=$(CONFIG_POWERNV)
>  CONFIG_XICS_KVM=$(and $(CONFIG_PSERIES),$(CONFIG_KVM))
>  # For PReP
>  CONFIG_MC146818RTC=y
> diff --git a/hw/intc/Makefile.objs b/hw/intc/Makefile.objs
> index 05ec21b..7be5dfc 100644
> --- a/hw/intc/Makefile.objs
> +++ b/hw/intc/Makefile.objs
> @@ -31,6 +31,7 @@ obj-$(CONFIG_RASPI) += bcm2835_ic.o bcm2836_control.o
>  obj-$(CONFIG_SH4) += sh_intc.o
>  obj-$(CONFIG_XICS) += xics.o
>  obj-$(CONFIG_XICS_SPAPR) += xics_spapr.o
> +obj-$(CONFIG_XICS_NATIVE) += xics_native.o
>  obj-$(CONFIG_XICS_KVM) += xics_kvm.o
>  obj-$(CONFIG_ALLWINNER_A10_PIC) += allwinner-a10-pic.o
>  obj-$(CONFIG_S390_FLIC) += s390_flic.o
> diff --git a/hw/intc/xics_native.c b/hw/intc/xics_native.c
> new file mode 100644
> index 0000000..26e45cc
> --- /dev/null
> +++ b/hw/intc/xics_native.c
> @@ -0,0 +1,295 @@
> +/*
> + * QEMU PowerPC hardware System Emulator
> + *
> + * Native version of ICS/ICP
> + *
> + * Copyright (c) 2010,2011 David Gibson, IBM Corporation.
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a copy
> + * of this software and associated documentation files (the "Software"), to deal
> + * in the Software without restriction, including without limitation the rights
> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> + * copies of the Software, and to permit persons to whom the Software is
> + * furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> + * THE SOFTWARE.
> + *
> + */
> +
> +#include "qemu/osdep.h"
> +#include "hw/hw.h"
> +#include "trace.h"
> +#include "qemu/timer.h"
> +#include "hw/ppc/xics.h"
> +#include "qapi/visitor.h"
> +#include "qapi/error.h"
> +
> +#include <libfdt.h>
> +
> +/* #define DEBUG_MM(fmt...)      printf(fmt) */
> +#define DEBUG_MM(fmt...)        do { } while (0)
> +
> +static void xics_native_initfn(Object *obj)
> +{
> +    XICSState *xics = XICS_NATIVE(obj);
> +
> +    QLIST_INIT(&xics->ics);
> +}
> +
> +static uint64_t icp_mm_read(void *opaque, hwaddr addr, unsigned width)
> +{
> +    XICSState *s = opaque;
> +    int32_t cpu_id, server;
> +    uint32_t val;
> +    ICPState *ss;
> +    bool byte0 = (width == 1 && (addr & 0x3) == 0);
> +
> +    cpu_id = (addr & (ICP_MM_SIZE - 1)) >> 12;
> +    server = get_cpu_index_by_dt_id(cpu_id);
> +    if (server < 0) {
> +        fprintf(stderr, "XICS: Bad ICP server %d\n", server);
> +        goto bad_access;
> +    }
> +    ss = &s->ss[server];
> +
> +    switch (addr & 0xffc) {
> +    case 0: /* poll */
> +        val = icp_ipoll(ss, NULL);
> +        if (byte0) {
> +            val >>= 24;
> +        } else if (width != 4) {
> +            goto bad_access;
> +        }
> +        break;
> +    case 4: /* xirr */
> +        if (byte0) {
> +            val = icp_ipoll(ss, NULL) >> 24;
> +        } else if (width == 4) {
> +            val = icp_accept(ss);
> +        } else {
> +            goto bad_access;
> +        }
> +        break;
> +    case 12:
> +        if (byte0) {
> +            val = ss->mfrr;
> +        } else {
> +            goto bad_access;
> +        }
> +        break;
> +    case 16:
> +        if (width == 4) {
> +            val = ss->links[0];
> +        } else {
> +            goto bad_access;
> +        }
> +        break;
> +    case 20:
> +        if (width == 4) {
> +            val = ss->links[1];
> +        } else {
> +            goto bad_access;
> +        }
> +        break;
> +    case 24:
> +        if (width == 4) {
> +            val = ss->links[2];
> +        } else {
> +            goto bad_access;
> +        }
> +        break;
> +    default:
> +bad_access:
> +        fprintf(stderr, "XICS: Bad ICP access %llx/%d\n",
> +                (unsigned long long)addr, width);
> +        val = 0xffffffff;
> +    }
> +    DEBUG_MM("icp_mm_read(addr=%016llx,serv=0x%x/%d,off=%d,w=%d,val=0x%08x)\n",
> +             (unsigned long long)addr, cpu_id, server, (int)(addr & 0xffc),
> +             width, val);
> +
> +    return val;
> +}
> +
> +static void icp_mm_write(void *opaque, hwaddr addr, uint64_t val,
> +                        unsigned width)
> +{
> +    XICSState *s = opaque;
> +    int32_t cpu_id, server;
> +    ICPState *ss;
> +    bool byte0 = (width == 1 && (addr & 0x3) == 0);
> +
> +    cpu_id = (addr & (ICP_MM_SIZE - 1)) >> 12;
> +    server = get_cpu_index_by_dt_id(cpu_id);
> +    if (server < 0) {
> +        fprintf(stderr, "XICS: Bad ICP server %d\n", server);
> +        goto bad_access;
> +    }
> +    ss = &s->ss[server];
> +
> +    DEBUG_MM("icp_mm_write(addr=%016llx,serv=0x%x/%d,off=%d,w=%d,val=0x%08x)\n",
> +             (unsigned long long)addr, cpu_id, server,
> +             (int)(addr & 0xffc), width, (uint32_t)val);
> +
> +    switch (addr & 0xffc) {
> +    case 4: /* xirr */
> +        if (byte0) {
> +            icp_set_cppr(s, server, val);
> +        } else if (width == 4) {
> +            icp_eoi(s, server, val);
> +        } else {
> +            goto bad_access;
> +        }
> +        break;
> +    case 12:
> +        if (byte0) {
> +            icp_set_mfrr(s, server, val);
> +        } else {
> +            goto bad_access;
> +        }
> +        break;
> +    case 16:
> +        if (width == 4) {
> +            ss->links[0] = val;
> +        } else {
> +            goto bad_access;
> +        }
> +        break;
> +    case 20:
> +        if (width == 4) {
> +            ss->links[1] = val;
> +        } else {
> +            goto bad_access;
> +        }
> +        break;
> +    case 24:
> +        if (width == 4) {
> +            ss->links[2] = val;
> +        } else {
> +            goto bad_access;
> +        }
> +        break;
> +    default:
> + bad_access:
> +        val = 0xffffffff;
> +    }
> +}
> +
> +static const MemoryRegionOps icp_mm_ops = {
> +    .read = icp_mm_read,
> +    .write = icp_mm_write,
> +    .valid.min_access_size = 1,
> +    .valid.max_access_size = 4,
> +    .impl.min_access_size = 1,
> +    .impl.max_access_size = 4,
> +    .endianness = DEVICE_BIG_ENDIAN,
> +};
> +
> +#define _FDT(exp) \
> +    do { \
> +        int ret = (exp);                                           \
> +        if (ret < 0) {                                             \
> +            fprintf(stderr, "qemu: error creating device tree: %s: %s\n", \
> +                    #exp, fdt_strerror(ret));                      \
> +            exit(1);                                               \
> +        }                                                          \
> +    } while (0)
> +
> +void xics_create_native_icp_node(XICSState *s, void *fdt,
> +                                 uint32_t base, uint32_t count)
> +{
> +    uint64_t addr;
> +    char *name;
> +    const char compat[] = "IBM,power8-icp\0IBM,ppc-xicp";
> +    uint32_t irange[2], i, rsize;
> +    uint64_t *reg;
> +
> +    addr = ICP_MM_BASE | (base << 12);
> +
> +    irange[0] = cpu_to_be32(base);
> +    irange[1] = cpu_to_be32(count);
> +
> +    rsize = sizeof(uint64_t) * 2 * count;
> +    reg = g_malloc(rsize);
> +    for (i = 0; i < count; i++) {
> +        reg[i * 2] = cpu_to_be64(addr | ((base + i) * 0x1000));
> +        reg[i * 2 + 1] = cpu_to_be64(0x1000);
> +    }
> +
> +    name = g_strdup_printf("interrupt-controller@%"PRIX64, addr);
> +
> +    /* interrupt controller */
> +    _FDT((fdt_begin_node(fdt, name)));
> +    g_free(name);
> +
> +    _FDT((fdt_property(fdt, "compatible", compat, sizeof(compat))));
> +    _FDT((fdt_property(fdt, "reg", reg, rsize)));
> +    _FDT((fdt_property_string(fdt, "device_type",
> +                              "PowerPC-External-Interrupt-Presentation")));
> +    _FDT((fdt_property(fdt, "interrupt-controller", NULL, 0)));
> +    _FDT((fdt_property(fdt, "ibm,interrupt-server-ranges",
> +                       irange, sizeof(irange))));
> +    _FDT((fdt_property_cell(fdt, "#interrupt-cells", 1)));
> +    _FDT((fdt_property_cell(fdt, "#address-cells", 0)));
> +    _FDT((fdt_end_node(fdt)));
> +}
> +
> +static void xics_native_realize(DeviceState *dev, Error **errp)
> +{
> +    XICSState *s = XICS_NATIVE(dev);
> +    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
> +    Error *error = NULL;
> +    int i;
> +
> +    if (!s->nr_servers) {
> +        error_setg(errp, "Number of servers needs to be greater 0");
> +        return;
> +    }
> +
> +    /* Register MMIO regions */
> +    memory_region_init_io(&s->icp_mmio, OBJECT(s), &icp_mm_ops, s, "icp",
> +                          ICP_MM_SIZE);
> +    sysbus_init_mmio(sbd, &s->icp_mmio);
> +    sysbus_mmio_map(sbd, 0, ICP_MM_BASE);
> +
> +    for (i = 0; i < s->nr_servers; i++) {
> +        object_property_set_bool(OBJECT(&s->ss[i]), true, "realized", &error);
> +        if (error) {
> +            error_propagate(errp, error);
> +            return;
> +        }
> +    }
> +}
> +
> +static void xics_native_class_init(ObjectClass *oc, void *data)
> +{
> +    DeviceClass *dc = DEVICE_CLASS(oc);
> +    XICSStateClass *xsc = XICS_NATIVE_CLASS(oc);
> +
> +    dc->realize = xics_native_realize;
> +    xsc->set_nr_servers = xics_set_nr_servers;
> +}
> +
> +static const TypeInfo xics_native_info = {
> +    .name          = TYPE_XICS_NATIVE,
> +    .parent        = TYPE_XICS_COMMON,
> +    .instance_size = sizeof(XICSState),
> +    .class_size = sizeof(XICSStateClass),
> +    .class_init    = xics_native_class_init,
> +    .instance_init = xics_native_initfn,
> +};
> +
> +static void xics_native_register_types(void)
> +{
> +    type_register_static(&xics_native_info);
> +}
> +type_init(xics_native_register_types)
> diff --git a/include/hw/ppc/xics.h b/include/hw/ppc/xics.h
> index 2231f2a..f81155c 100644
> --- a/include/hw/ppc/xics.h
> +++ b/include/hw/ppc/xics.h
> @@ -44,6 +44,9 @@
>  #define XICS_SPAPR_KVM(obj) \
>       OBJECT_CHECK(KVMXICSState, (obj), TYPE_XICS_SPAPR_KVM)
>  
> +#define TYPE_XICS_NATIVE "xics-native"
> +#define XICS_NATIVE(obj) OBJECT_CHECK(XICSState, (obj), TYPE_XICS_NATIVE)
> +
>  #define XICS_COMMON_CLASS(klass) \
>       OBJECT_CLASS_CHECK(XICSStateClass, (klass), TYPE_XICS_COMMON)
>  #define XICS_SPAPR_CLASS(klass) \
> @@ -52,6 +55,8 @@
>       OBJECT_GET_CLASS(XICSStateClass, (obj), TYPE_XICS_COMMON)
>  #define XICS_SPAPR_GET_CLASS(obj) \
>       OBJECT_GET_CLASS(XICSStateClass, (obj), TYPE_XICS_SPAPR)
> +#define XICS_NATIVE_CLASS(klass) \
> +     OBJECT_CLASS_CHECK(XICSStateClass, (klass), TYPE_XICS_NATIVE)
>  
>  #define XICS_IPI        0x2
>  #define XICS_BUID       0x1
> @@ -86,6 +91,7 @@ struct XICSState {
>      uint32_t nr_irqs;
>      ICPState *ss;
>      QLIST_HEAD(, ICSState) ics;
> +    MemoryRegion icp_mmio;
>  };
>  
>  #define TYPE_ICP "icp"
> @@ -117,8 +123,13 @@ struct ICPState {
>      uint8_t mfrr;
>      qemu_irq output;
>      bool cap_irq_xics_enabled;
> +    uint32_t links[3];
>  };
>  
> +/* This should be an XSCOM BAR ... the size is arbitrary as well */
> +#define ICP_MM_BASE     0x0003FFFF80000000
> +#define ICP_MM_SIZE     0x0000000010000000
> +
>  #define TYPE_ICS_BASE "ics-base"
>  #define ICS_BASE(obj) OBJECT_CHECK(ICSState, (obj), TYPE_ICS_SIMPLE)
>  
> @@ -189,6 +200,9 @@ void xics_spapr_free(XICSState *icp, int irq, int num);
>  void xics_cpu_setup(XICSState *icp, PowerPCCPU *cpu);
>  void xics_cpu_destroy(XICSState *icp, PowerPCCPU *cpu);
>  
> +void xics_create_native_icp_node(XICSState *s, void *fdt,
> +                                 uint32_t base, uint32_t count);
> +
>  /* Internal XICS interfaces */
>  int xics_get_cpu_index_by_dt_id(int cpu_dt_id);
>  
> 

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [Qemu-ppc] [PATCH v4 6/9] ppc/xics: Split ICS into ics-base and ics class
  2016-09-19  6:29 ` [Qemu-devel] [PATCH v4 6/9] ppc/xics: Split ICS into ics-base and ics class Nikunj A Dadhania
@ 2016-09-19  7:09   ` Cédric Le Goater
  2016-09-20  5:14     ` Nikunj A Dadhania
  2016-09-19 14:34   ` Cédric Le Goater
  1 sibling, 1 reply; 38+ messages in thread
From: Cédric Le Goater @ 2016-09-19  7:09 UTC (permalink / raw)
  To: Nikunj A Dadhania, qemu-ppc, david; +Cc: qemu-devel

On 09/19/2016 08:29 AM, Nikunj A Dadhania wrote:
> From: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> 
> The existing implementation remains same and ics-base is introduced. The
> type name "ics" is retained, and all the related functions renamed as
> ics_simple_*
> 
> This will allow different implementations for the source controllers
> such as the MSI support of PHB3 on Power8 which uses in-memory state
> tables for example.
> 
> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> Signed-off-by: Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>

This patch had a Reviewed-by from David. Did you change anything 
in v4 ? 

Thanks,

C. 


> ---
>  hw/intc/trace-events  |  10 ++--
>  hw/intc/xics.c        | 143 +++++++++++++++++++++++++++++++-------------------
>  hw/intc/xics_kvm.c    |  10 ++--
>  hw/intc/xics_spapr.c  |  28 +++++-----
>  include/hw/ppc/xics.h |  23 +++++---
>  5 files changed, 131 insertions(+), 83 deletions(-)
> 
> diff --git a/hw/intc/trace-events b/hw/intc/trace-events
> index aa342a8..a367b46 100644
> --- a/hw/intc/trace-events
> +++ b/hw/intc/trace-events
> @@ -50,12 +50,12 @@ xics_icp_accept(uint32_t old_xirr, uint32_t new_xirr) "icp_accept: XIRR %#"PRIx3
>  xics_icp_eoi(int server, uint32_t xirr, uint32_t new_xirr) "icp_eoi: server %d given XIRR %#"PRIx32" new XIRR %#"PRIx32
>  xics_icp_irq(int server, int nr, uint8_t priority) "cpu %d trying to deliver irq %#"PRIx32" priority %#x"
>  xics_icp_raise(uint32_t xirr, uint8_t pending_priority) "raising IRQ new XIRR=%#x new pending priority=%#x"
> -xics_set_irq_msi(int srcno, int nr) "set_irq_msi: srcno %d [irq %#x]"
> +xics_ics_simple_set_irq_msi(int srcno, int nr) "set_irq_msi: srcno %d [irq %#x]"
>  xics_masked_pending(void) "set_irq_msi: masked pending"
> -xics_set_irq_lsi(int srcno, int nr) "set_irq_lsi: srcno %d [irq %#x]"
> -xics_ics_write_xive(int nr, int srcno, int server, uint8_t priority) "ics_write_xive: irq %#x [src %d] server %#x prio %#x"
> -xics_ics_reject(int nr, int srcno) "reject irq %#x [src %d]"
> -xics_ics_eoi(int nr) "ics_eoi: irq %#x"
> +xics_ics_simple_set_irq_lsi(int srcno, int nr) "set_irq_lsi: srcno %d [irq %#x]"
> +xics_ics_simple_write_xive(int nr, int srcno, int server, uint8_t priority) "ics_write_xive: irq %#x [src %d] server %#x prio %#x"
> +xics_ics_simple_reject(int nr, int srcno) "reject irq %#x [src %d]"
> +xics_ics_simple_eoi(int nr) "ics_eoi: irq %#x"
>  xics_alloc(int irq) "irq %d"
>  xics_alloc_block(int first, int num, bool lsi, int align) "first irq %d, %d irqs, lsi=%d, alignnum %d"
>  xics_ics_free(int src, int irq, int num) "Source#%d, first irq %d, %d irqs"
> diff --git a/hw/intc/xics.c b/hw/intc/xics.c
> index c7901c4..b15751e 100644
> --- a/hw/intc/xics.c
> +++ b/hw/intc/xics.c
> @@ -113,7 +113,7 @@ void xics_add_ics(XICSState *xics)
>  {
>      ICSState *ics;
>  
> -    ics = ICS(object_new(TYPE_ICS));
> +    ics = ICS_SIMPLE(object_new(TYPE_ICS_SIMPLE));
>      object_property_add_child(OBJECT(xics), "ics", OBJECT(ics), NULL);
>      ics->xics = xics;
>      QLIST_INSERT_HEAD(&xics->ics, ics, list);
> @@ -224,9 +224,32 @@ static const TypeInfo xics_common_info = {
>  #define XISR(ss)   (((ss)->xirr) & XISR_MASK)
>  #define CPPR(ss)   (((ss)->xirr) >> 24)
>  
> -static void ics_reject(ICSState *ics, int nr);
> -static void ics_resend(ICSState *ics, int server);
> -static void ics_eoi(ICSState *ics, int nr);
> +static void ics_reject(ICSState *ics, uint32_t nr)
> +{
> +    ICSStateClass *k = ICS_GET_CLASS(ics);
> +
> +    if (k->reject) {
> +        k->reject(ics, nr);
> +    }
> +}
> +
> +static void ics_resend(ICSState *ics, int server)
> +{
> +    ICSStateClass *k = ICS_GET_CLASS(ics);
> +
> +    if (k->resend) {
> +        k->resend(ics, server);
> +    }
> +}
> +
> +static void ics_eoi(ICSState *ics, int nr)
> +{
> +    ICSStateClass *k = ICS_GET_CLASS(ics);
> +
> +    if (k->eoi) {
> +        k->eoi(ics, nr);
> +    }
> +}
>  
>  static void icp_check_ipi(ICPState *ss)
>  {
> @@ -462,7 +485,7 @@ static const TypeInfo icp_info = {
>  /*
>   * ICS: Source layer
>   */
> -static void resend_msi(ICSState *ics, int srcno)
> +static void ics_simple_resend_msi(ICSState *ics, int srcno)
>  {
>      ICSIRQState *irq = ics->irqs + srcno;
>  
> @@ -475,7 +498,7 @@ static void resend_msi(ICSState *ics, int srcno)
>      }
>  }
>  
> -static void resend_lsi(ICSState *ics, int srcno)
> +static void ics_simple_resend_lsi(ICSState *ics, int srcno)
>  {
>      ICSIRQState *irq = ics->irqs + srcno;
>  
> @@ -487,11 +510,11 @@ static void resend_lsi(ICSState *ics, int srcno)
>      }
>  }
>  
> -static void set_irq_msi(ICSState *ics, int srcno, int val)
> +static void ics_simple_set_irq_msi(ICSState *ics, int srcno, int val)
>  {
>      ICSIRQState *irq = ics->irqs + srcno;
>  
> -    trace_xics_set_irq_msi(srcno, srcno + ics->offset);
> +    trace_xics_ics_simple_set_irq_msi(srcno, srcno + ics->offset);
>  
>      if (val) {
>          if (irq->priority == 0xff) {
> @@ -503,31 +526,31 @@ static void set_irq_msi(ICSState *ics, int srcno, int val)
>      }
>  }
>  
> -static void set_irq_lsi(ICSState *ics, int srcno, int val)
> +static void ics_simple_set_irq_lsi(ICSState *ics, int srcno, int val)
>  {
>      ICSIRQState *irq = ics->irqs + srcno;
>  
> -    trace_xics_set_irq_lsi(srcno, srcno + ics->offset);
> +    trace_xics_ics_simple_set_irq_lsi(srcno, srcno + ics->offset);
>      if (val) {
>          irq->status |= XICS_STATUS_ASSERTED;
>      } else {
>          irq->status &= ~XICS_STATUS_ASSERTED;
>      }
> -    resend_lsi(ics, srcno);
> +    ics_simple_resend_lsi(ics, srcno);
>  }
>  
> -static void ics_set_irq(void *opaque, int srcno, int val)
> +static void ics_simple_set_irq(void *opaque, int srcno, int val)
>  {
>      ICSState *ics = (ICSState *)opaque;
>  
>      if (ics->irqs[srcno].flags & XICS_FLAGS_IRQ_LSI) {
> -        set_irq_lsi(ics, srcno, val);
> +        ics_simple_set_irq_lsi(ics, srcno, val);
>      } else {
> -        set_irq_msi(ics, srcno, val);
> +        ics_simple_set_irq_msi(ics, srcno, val);
>      }
>  }
>  
> -static void write_xive_msi(ICSState *ics, int srcno)
> +static void ics_simple_write_xive_msi(ICSState *ics, int srcno)
>  {
>      ICSIRQState *irq = ics->irqs + srcno;
>  
> @@ -540,35 +563,35 @@ static void write_xive_msi(ICSState *ics, int srcno)
>      icp_irq(ics, irq->server, srcno + ics->offset, irq->priority);
>  }
>  
> -static void write_xive_lsi(ICSState *ics, int srcno)
> +static void ics_simple_write_xive_lsi(ICSState *ics, int srcno)
>  {
> -    resend_lsi(ics, srcno);
> +    ics_simple_resend_lsi(ics, srcno);
>  }
>  
> -void ics_write_xive(ICSState *ics, int nr, int server,
> -                    uint8_t priority, uint8_t saved_priority)
> +void ics_simple_write_xive(ICSState *ics, int srcno, int server,
> +                           uint8_t priority, uint8_t saved_priority)
>  {
> -    int srcno = nr - ics->offset;
>      ICSIRQState *irq = ics->irqs + srcno;
>  
>      irq->server = server;
>      irq->priority = priority;
>      irq->saved_priority = saved_priority;
>  
> -    trace_xics_ics_write_xive(nr, srcno, server, priority);
> +    trace_xics_ics_simple_write_xive(ics->offset + srcno, srcno, server,
> +                                     priority);
>  
>      if (ics->irqs[srcno].flags & XICS_FLAGS_IRQ_LSI) {
> -        write_xive_lsi(ics, srcno);
> +        ics_simple_write_xive_lsi(ics, srcno);
>      } else {
> -        write_xive_msi(ics, srcno);
> +        ics_simple_write_xive_msi(ics, srcno);
>      }
>  }
>  
> -static void ics_reject(ICSState *ics, int nr)
> +static void ics_simple_reject(ICSState *ics, uint32_t nr)
>  {
>      ICSIRQState *irq = ics->irqs + nr - ics->offset;
>  
> -    trace_xics_ics_reject(nr, nr - ics->offset);
> +    trace_xics_ics_simple_reject(nr, nr - ics->offset);
>      if (irq->flags & XICS_FLAGS_IRQ_MSI) {
>          irq->status |= XICS_STATUS_REJECTED;
>      } else if (irq->flags & XICS_FLAGS_IRQ_LSI) {
> @@ -576,7 +599,7 @@ static void ics_reject(ICSState *ics, int nr)
>      }
>  }
>  
> -static void ics_resend(ICSState *ics, int server)
> +static void ics_simple_resend(ICSState *ics, int server)
>  {
>      int i;
>      ICPState *ss = ics->xics->ss + server;
> @@ -594,28 +617,28 @@ static void ics_resend(ICSState *ics, int server)
>                  qemu_irq_raise(ss->output);
>                  continue;
>              }
> -            resend_lsi(ics, i);
> +            ics_simple_resend_lsi(ics, i);
>          } else {
> -            resend_msi(ics, i);
> +            ics_simple_resend_msi(ics, i);
>          }
>      }
>  }
>  
> -static void ics_eoi(ICSState *ics, int nr)
> +static void ics_simple_eoi(ICSState *ics, uint32_t nr)
>  {
>      int srcno = nr - ics->offset;
>      ICSIRQState *irq = ics->irqs + srcno;
>  
> -    trace_xics_ics_eoi(nr);
> +    trace_xics_ics_simple_eoi(nr);
>  
>      if (ics->irqs[srcno].flags & XICS_FLAGS_IRQ_LSI) {
>          irq->status &= ~XICS_STATUS_SENT;
>      }
>  }
>  
> -static void ics_reset(DeviceState *dev)
> +static void ics_simple_reset(DeviceState *dev)
>  {
> -    ICSState *ics = ICS(dev);
> +    ICSState *ics = ICS_SIMPLE(dev);
>      int i;
>      uint8_t flags[ics->nr_irqs];
>  
> @@ -632,7 +655,7 @@ static void ics_reset(DeviceState *dev)
>      }
>  }
>  
> -static void ics_dispatch_pre_save(void *opaque)
> +static void ics_simple_dispatch_pre_save(void *opaque)
>  {
>      ICSState *ics = opaque;
>      ICSStateClass *info = ICS_GET_CLASS(ics);
> @@ -642,7 +665,7 @@ static void ics_dispatch_pre_save(void *opaque)
>      }
>  }
>  
> -static int ics_dispatch_post_load(void *opaque, int version_id)
> +static int ics_simple_dispatch_post_load(void *opaque, int version_id)
>  {
>      ICSState *ics = opaque;
>      ICSStateClass *info = ICS_GET_CLASS(ics);
> @@ -654,7 +677,7 @@ static int ics_dispatch_post_load(void *opaque, int version_id)
>      return 0;
>  }
>  
> -static const VMStateDescription vmstate_ics_irq = {
> +static const VMStateDescription vmstate_ics_simple_irq = {
>      .name = "ics/irq",
>      .version_id = 2,
>      .minimum_version_id = 1,
> @@ -668,57 +691,70 @@ static const VMStateDescription vmstate_ics_irq = {
>      },
>  };
>  
> -static const VMStateDescription vmstate_ics = {
> +static const VMStateDescription vmstate_ics_simple = {
>      .name = "ics",
>      .version_id = 1,
>      .minimum_version_id = 1,
> -    .pre_save = ics_dispatch_pre_save,
> -    .post_load = ics_dispatch_post_load,
> +    .pre_save = ics_simple_dispatch_pre_save,
> +    .post_load = ics_simple_dispatch_post_load,
>      .fields = (VMStateField[]) {
>          /* Sanity check */
>          VMSTATE_UINT32_EQUAL(nr_irqs, ICSState),
>  
>          VMSTATE_STRUCT_VARRAY_POINTER_UINT32(irqs, ICSState, nr_irqs,
> -                                             vmstate_ics_irq, ICSIRQState),
> +                                             vmstate_ics_simple_irq,
> +                                             ICSIRQState),
>          VMSTATE_END_OF_LIST()
>      },
>  };
>  
> -static void ics_initfn(Object *obj)
> +static void ics_simple_initfn(Object *obj)
>  {
> -    ICSState *ics = ICS(obj);
> +    ICSState *ics = ICS_SIMPLE(obj);
>  
>      ics->offset = XICS_IRQ_BASE;
>  }
>  
> -static void ics_realize(DeviceState *dev, Error **errp)
> +static void ics_simple_realize(DeviceState *dev, Error **errp)
>  {
> -    ICSState *ics = ICS(dev);
> +    ICSState *ics = ICS_SIMPLE(dev);
>  
>      if (!ics->nr_irqs) {
>          error_setg(errp, "Number of interrupts needs to be greater 0");
>          return;
>      }
>      ics->irqs = g_malloc0(ics->nr_irqs * sizeof(ICSIRQState));
> -    ics->qirqs = qemu_allocate_irqs(ics_set_irq, ics, ics->nr_irqs);
> +    ics->qirqs = qemu_allocate_irqs(ics_simple_set_irq, ics, ics->nr_irqs);
>  }
>  
> -static void ics_class_init(ObjectClass *klass, void *data)
> +static void ics_simple_class_init(ObjectClass *klass, void *data)
>  {
>      DeviceClass *dc = DEVICE_CLASS(klass);
> +    ICSStateClass *isc = ICS_CLASS(klass);
>  
> -    dc->realize = ics_realize;
> -    dc->vmsd = &vmstate_ics;
> -    dc->reset = ics_reset;
> +    dc->realize = ics_simple_realize;
> +    dc->vmsd = &vmstate_ics_simple;
> +    dc->reset = ics_simple_reset;
> +    isc->reject = ics_simple_reject;
> +    isc->resend = ics_simple_resend;
> +    isc->eoi = ics_simple_eoi;
>  }
>  
> -static const TypeInfo ics_info = {
> -    .name = TYPE_ICS,
> +static const TypeInfo ics_simple_info = {
> +    .name = TYPE_ICS_SIMPLE,
> +    .parent = TYPE_ICS_BASE,
> +    .instance_size = sizeof(ICSState),
> +    .class_init = ics_simple_class_init,
> +    .class_size = sizeof(ICSStateClass),
> +    .instance_init = ics_simple_initfn,
> +};
> +
> +static const TypeInfo ics_base_info = {
> +    .name = TYPE_ICS_BASE,
>      .parent = TYPE_DEVICE,
> +    .abstract = true,
>      .instance_size = sizeof(ICSState),
> -    .class_init = ics_class_init,
>      .class_size = sizeof(ICSStateClass),
> -    .instance_init = ics_initfn,
>  };
>  
>  /*
> @@ -758,7 +794,8 @@ void ics_set_irq_type(ICSState *ics, int srcno, bool lsi)
>  static void xics_register_types(void)
>  {
>      type_register_static(&xics_common_info);
> -    type_register_static(&ics_info);
> +    type_register_static(&ics_simple_info);
> +    type_register_static(&ics_base_info);
>      type_register_static(&icp_info);
>  }
>  
> diff --git a/hw/intc/xics_kvm.c b/hw/intc/xics_kvm.c
> index 04fa7cb..89862df 100644
> --- a/hw/intc/xics_kvm.c
> +++ b/hw/intc/xics_kvm.c
> @@ -272,7 +272,7 @@ static void ics_kvm_set_irq(void *opaque, int srcno, int val)
>  
>  static void ics_kvm_reset(DeviceState *dev)
>  {
> -    ICSState *ics = ICS(dev);
> +    ICSState *ics = ICS_SIMPLE(dev);
>      int i;
>      uint8_t flags[ics->nr_irqs];
>  
> @@ -293,7 +293,7 @@ static void ics_kvm_reset(DeviceState *dev)
>  
>  static void ics_kvm_realize(DeviceState *dev, Error **errp)
>  {
> -    ICSState *ics = ICS(dev);
> +    ICSState *ics = ICS_SIMPLE(dev);
>  
>      if (!ics->nr_irqs) {
>          error_setg(errp, "Number of interrupts needs to be greater 0");
> @@ -315,8 +315,8 @@ static void ics_kvm_class_init(ObjectClass *klass, void *data)
>  }
>  
>  static const TypeInfo ics_kvm_info = {
> -    .name = TYPE_KVM_ICS,
> -    .parent = TYPE_ICS,
> +    .name = TYPE_ICS_KVM,
> +    .parent = TYPE_ICS_SIMPLE,
>      .instance_size = sizeof(ICSState),
>      .class_init = ics_kvm_class_init,
>  };
> @@ -492,7 +492,7 @@ static void xics_kvm_initfn(Object *obj)
>      XICSState *xics = XICS_COMMON(obj);
>      ICSState *ics;
>  
> -    ics = ICS(object_new(TYPE_KVM_ICS));
> +    ics = ICS_SIMPLE(object_new(TYPE_ICS_KVM));
>      object_property_add_child(obj, "ics", OBJECT(ics), NULL);
>      ics->xics = xics;
>      QLIST_INSERT_HEAD(&xics->ics, ics, list);
> diff --git a/hw/intc/xics_spapr.c b/hw/intc/xics_spapr.c
> index 270f20e..4dd1399 100644
> --- a/hw/intc/xics_spapr.c
> +++ b/hw/intc/xics_spapr.c
> @@ -114,7 +114,7 @@ static void rtas_set_xive(PowerPCCPU *cpu, sPAPRMachineState *spapr,
>                            uint32_t nret, target_ulong rets)
>  {
>      ICSState *ics = QLIST_FIRST(&spapr->xics->ics);
> -    uint32_t nr, server, priority;
> +    uint32_t nr, srcno, server, priority;
>  
>      if ((nargs != 3) || (nret != 1)) {
>          rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
> @@ -135,7 +135,8 @@ static void rtas_set_xive(PowerPCCPU *cpu, sPAPRMachineState *spapr,
>          return;
>      }
>  
> -    ics_write_xive(ics, nr, server, priority, priority);
> +    srcno = nr - ics->offset;
> +    ics_simple_write_xive(ics, srcno, server, priority, priority);
>  
>      rtas_st(rets, 0, RTAS_OUT_SUCCESS);
>  }
> @@ -146,7 +147,7 @@ static void rtas_get_xive(PowerPCCPU *cpu, sPAPRMachineState *spapr,
>                            uint32_t nret, target_ulong rets)
>  {
>      ICSState *ics = QLIST_FIRST(&spapr->xics->ics);
> -    uint32_t nr;
> +    uint32_t nr, srcno;
>  
>      if ((nargs != 1) || (nret != 3)) {
>          rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
> @@ -165,8 +166,9 @@ static void rtas_get_xive(PowerPCCPU *cpu, sPAPRMachineState *spapr,
>      }
>  
>      rtas_st(rets, 0, RTAS_OUT_SUCCESS);
> -    rtas_st(rets, 1, ics->irqs[nr - ics->offset].server);
> -    rtas_st(rets, 2, ics->irqs[nr - ics->offset].priority);
> +    srcno = nr - ics->offset;
> +    rtas_st(rets, 1, ics->irqs[srcno].server);
> +    rtas_st(rets, 2, ics->irqs[srcno].priority);
>  }
>  
>  static void rtas_int_off(PowerPCCPU *cpu, sPAPRMachineState *spapr,
> @@ -175,7 +177,7 @@ static void rtas_int_off(PowerPCCPU *cpu, sPAPRMachineState *spapr,
>                           uint32_t nret, target_ulong rets)
>  {
>      ICSState *ics = QLIST_FIRST(&spapr->xics->ics);
> -    uint32_t nr;
> +    uint32_t nr, srcno;
>  
>      if ((nargs != 1) || (nret != 1)) {
>          rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
> @@ -193,8 +195,9 @@ static void rtas_int_off(PowerPCCPU *cpu, sPAPRMachineState *spapr,
>          return;
>      }
>  
> -    ics_write_xive(ics, nr, ics->irqs[nr - ics->offset].server, 0xff,
> -                   ics->irqs[nr - ics->offset].priority);
> +    srcno = nr - ics->offset;
> +    ics_simple_write_xive(ics, srcno, ics->irqs[srcno].server, 0xff,
> +                          ics->irqs[srcno].priority);
>  
>      rtas_st(rets, 0, RTAS_OUT_SUCCESS);
>  }
> @@ -205,7 +208,7 @@ static void rtas_int_on(PowerPCCPU *cpu, sPAPRMachineState *spapr,
>                          uint32_t nret, target_ulong rets)
>  {
>      ICSState *ics = QLIST_FIRST(&spapr->xics->ics);
> -    uint32_t nr;
> +    uint32_t nr, srcno;
>  
>      if ((nargs != 1) || (nret != 1)) {
>          rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
> @@ -223,9 +226,10 @@ static void rtas_int_on(PowerPCCPU *cpu, sPAPRMachineState *spapr,
>          return;
>      }
>  
> -    ics_write_xive(ics, nr, ics->irqs[nr - ics->offset].server,
> -                   ics->irqs[nr - ics->offset].saved_priority,
> -                   ics->irqs[nr - ics->offset].saved_priority);
> +    srcno = nr - ics->offset;
> +    ics_simple_write_xive(ics, srcno, ics->irqs[srcno].server,
> +                          ics->irqs[srcno].saved_priority,
> +                          ics->irqs[srcno].saved_priority);
>  
>      rtas_st(rets, 0, RTAS_OUT_SUCCESS);
>  }
> diff --git a/include/hw/ppc/xics.h b/include/hw/ppc/xics.h
> index a7a1e54..2231f2a 100644
> --- a/include/hw/ppc/xics.h
> +++ b/include/hw/ppc/xics.h
> @@ -119,22 +119,29 @@ struct ICPState {
>      bool cap_irq_xics_enabled;
>  };
>  
> -#define TYPE_ICS "ics"
> -#define ICS(obj) OBJECT_CHECK(ICSState, (obj), TYPE_ICS)
> +#define TYPE_ICS_BASE "ics-base"
> +#define ICS_BASE(obj) OBJECT_CHECK(ICSState, (obj), TYPE_ICS_SIMPLE)
>  
> -#define TYPE_KVM_ICS "icskvm"
> -#define KVM_ICS(obj) OBJECT_CHECK(ICSState, (obj), TYPE_KVM_ICS)
> +/* Retain ics for sPAPR for migration from existing sPAPR guests */
> +#define TYPE_ICS_SIMPLE "ics"
> +#define ICS_SIMPLE(obj) OBJECT_CHECK(ICSState, (obj), TYPE_ICS_SIMPLE)
> +
> +#define TYPE_ICS_KVM "icskvm"
> +#define ICS_KVM(obj) OBJECT_CHECK(ICSState, (obj), TYPE_ICS_KVM)
>  
>  #define ICS_CLASS(klass) \
> -     OBJECT_CLASS_CHECK(ICSStateClass, (klass), TYPE_ICS)
> +     OBJECT_CLASS_CHECK(ICSStateClass, (klass), TYPE_ICS_SIMPLE)
>  #define ICS_GET_CLASS(obj) \
> -     OBJECT_GET_CLASS(ICSStateClass, (obj), TYPE_ICS)
> +     OBJECT_GET_CLASS(ICSStateClass, (obj), TYPE_ICS_SIMPLE)
>  
>  struct ICSStateClass {
>      DeviceClass parent_class;
>  
>      void (*pre_save)(ICSState *s);
>      int (*post_load)(ICSState *s, int version_id);
> +    void (*reject)(ICSState *s, uint32_t irq);
> +    void (*resend)(ICSState *s, int server);
> +    void (*eoi)(ICSState *s, uint32_t irq);
>  };
>  
>  struct ICSState {
> @@ -191,8 +198,8 @@ uint32_t icp_accept(ICPState *ss);
>  uint32_t icp_ipoll(ICPState *ss, uint32_t *mfrr);
>  void icp_eoi(XICSState *icp, int server, uint32_t xirr);
>  
> -void ics_write_xive(ICSState *ics, int nr, int server,
> -                    uint8_t priority, uint8_t saved_priority);
> +void ics_simple_write_xive(ICSState *ics, int nr, int server,
> +                           uint8_t priority, uint8_t saved_priority);
>  
>  void ics_set_irq_type(ICSState *ics, int srcno, bool lsi);
>  
> 

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [Qemu-ppc] [PATCH v4 3/9] ppc/xics: Make the ICSState a list
  2016-09-19  7:02     ` Nikunj A Dadhania
@ 2016-09-19  7:24       ` Cédric Le Goater
  2016-09-20  5:13         ` Nikunj A Dadhania
  0 siblings, 1 reply; 38+ messages in thread
From: Cédric Le Goater @ 2016-09-19  7:24 UTC (permalink / raw)
  To: Nikunj A Dadhania, qemu-ppc, david; +Cc: qemu-devel

On 09/19/2016 09:02 AM, Nikunj A Dadhania wrote:
> Cédric Le Goater <clg@kaod.org> writes:
> 
>> On 09/19/2016 08:29 AM, Nikunj A Dadhania wrote:
>>> From: Benjamin Herrenschmidt <benh@kernel.crashing.org>
>>>
>>> Instead of an array of fixed sized blocks, use a list, as we will need
>>> to have sources with variable number of interrupts. SPAPR only uses
>>> a single entry. Native will create more. If performance becomes an
>>> issue we can add some hashed lookup but for now this will do fine.
>>>
>>> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
>>> [ move the initialization of list to xics_common_initfn,
>>>   restore xirr_owner after migration and move restoring to
>>>   icp_post_load]
>>> Signed-off-by: Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>
>>
>> This looks good to me apart from the change of icp_post_load(). 
>>
>>> ---
>>>  hw/intc/trace-events  |   5 +-
>>>  hw/intc/xics.c        | 130 ++++++++++++++++++++++++++++++++------------------
>>>  hw/intc/xics_kvm.c    |  27 +++++++----
>>>  hw/intc/xics_spapr.c  |  88 ++++++++++++++++++++++------------
>>>  hw/ppc/spapr_events.c |   2 +-
>>>  hw/ppc/spapr_pci.c    |   5 +-
>>>  hw/ppc/spapr_vio.c    |   2 +-
>>>  include/hw/ppc/xics.h |  13 ++---
>>>  8 files changed, 173 insertions(+), 99 deletions(-)
>>>
>>> diff --git a/hw/intc/trace-events b/hw/intc/trace-events
>>> index f12192c..aa342a8 100644
>>> --- a/hw/intc/trace-events
>>> +++ b/hw/intc/trace-events
>>> @@ -56,10 +56,11 @@ xics_set_irq_lsi(int srcno, int nr) "set_irq_lsi: srcno %d [irq %#x]"
>>>  xics_ics_write_xive(int nr, int srcno, int server, uint8_t priority) "ics_write_xive: irq %#x [src %d] server %#x prio %#x"
>>>  xics_ics_reject(int nr, int srcno) "reject irq %#x [src %d]"
>>>  xics_ics_eoi(int nr) "ics_eoi: irq %#x"
>>> -xics_alloc(int src, int irq) "source#%d, irq %d"
>>> -xics_alloc_block(int src, int first, int num, bool lsi, int align) "source#%d, first irq %d, %d irqs, lsi=%d, alignnum %d"
>>> +xics_alloc(int irq) "irq %d"
>>> +xics_alloc_block(int first, int num, bool lsi, int align) "first irq %d, %d irqs, lsi=%d, alignnum %d"
>>>  xics_ics_free(int src, int irq, int num) "Source#%d, first irq %d, %d irqs"
>>>  xics_ics_free_warn(int src, int irq) "Source#%d, irq %d is already free"
>>> +xics_icp_post_load(uint32_t server_no, uint32_t xirr, uint64_t addr, uint8_t pend) "server_no %d, xirr %#x, xirr_owner 0x%" PRIx64 ", pending %d"
>>>  
>>>  # hw/intc/s390_flic_kvm.c
>>>  flic_create_device(int err) "flic: create device failed %d"
>>> diff --git a/hw/intc/xics.c b/hw/intc/xics.c
>>> index f765b08..05e938f 100644
>>> --- a/hw/intc/xics.c
>>> +++ b/hw/intc/xics.c
>>> @@ -32,6 +32,7 @@
>>>  #include "hw/hw.h"
>>>  #include "trace.h"
>>>  #include "qemu/timer.h"
>>> +#include "hw/ppc/spapr.h"
>>>  #include "hw/ppc/xics.h"
>>>  #include "qemu/error-report.h"
>>>  #include "qapi/visitor.h"
>>> @@ -96,13 +97,16 @@ void xics_cpu_setup(XICSState *xics, PowerPCCPU *cpu)
>>>  static void xics_common_reset(DeviceState *d)
>>>  {
>>>      XICSState *xics = XICS_COMMON(d);
>>> +    ICSState *ics;
>>>      int i;
>>>  
>>>      for (i = 0; i < xics->nr_servers; i++) {
>>>          device_reset(DEVICE(&xics->ss[i]));
>>>      }
>>>  
>>> -    device_reset(DEVICE(xics->ics));
>>> +    QLIST_FOREACH(ics, &xics->ics, list) {
>>> +        device_reset(DEVICE(ics));
>>> +    }
>>>  }
>>>  
>>>  static void xics_prop_get_nr_irqs(Object *obj, Visitor *v, const char *name,
>>> @@ -134,7 +138,6 @@ static void xics_prop_set_nr_irqs(Object *obj, Visitor *v, const char *name,
>>>      }
>>>  
>>>      assert(info->set_nr_irqs);
>>> -    assert(xics->ics);
>>>      info->set_nr_irqs(xics, value, errp);
>>>  }
>>>  
>>> @@ -174,6 +177,9 @@ static void xics_prop_set_nr_servers(Object *obj, Visitor *v,
>>>  
>>>  static void xics_common_initfn(Object *obj)
>>>  {
>>> +    XICSState *xics = XICS_COMMON(obj);
>>> +
>>> +    QLIST_INIT(&xics->ics);
>>>      object_property_add(obj, "nr_irqs", "int",
>>>                          xics_prop_get_nr_irqs, xics_prop_set_nr_irqs,
>>>                          NULL, NULL, NULL);
>>> @@ -212,33 +218,35 @@ static void ics_reject(ICSState *ics, int nr);
>>>  static void ics_resend(ICSState *ics, int server);
>>>  static void ics_eoi(ICSState *ics, int nr);
>>>  
>>> -static void icp_check_ipi(XICSState *xics, int server)
>>> +static void icp_check_ipi(ICPState *ss)
>>>  {
>>> -    ICPState *ss = xics->ss + server;
>>> -
>>>      if (XISR(ss) && (ss->pending_priority <= ss->mfrr)) {
>>>          return;
>>>      }
>>>  
>>> -    trace_xics_icp_check_ipi(server, ss->mfrr);
>>> +    trace_xics_icp_check_ipi(ss->cs->cpu_index, ss->mfrr);
>>>  
>>> -    if (XISR(ss)) {
>>> -        ics_reject(xics->ics, XISR(ss));
>>> +    if (XISR(ss) && ss->xirr_owner) {
>>> +        ics_reject(ss->xirr_owner, XISR(ss));
>>>      }
>>>  
>>>      ss->xirr = (ss->xirr & ~XISR_MASK) | XICS_IPI;
>>>      ss->pending_priority = ss->mfrr;
>>> +    ss->xirr_owner = NULL;
>>>      qemu_irq_raise(ss->output);
>>>  }
>>>  
>>>  static void icp_resend(XICSState *xics, int server)
>>>  {
>>>      ICPState *ss = xics->ss + server;
>>> +    ICSState *ics;
>>>  
>>>      if (ss->mfrr < CPPR(ss)) {
>>> -        icp_check_ipi(xics, server);
>>> +        icp_check_ipi(ss);
>>> +    }
>>> +    QLIST_FOREACH(ics, &xics->ics, list) {
>>> +        ics_resend(ics, server);
>>>      }
>>> -    ics_resend(xics->ics, server);
>>>  }
>>>  
>>>  void icp_set_cppr(XICSState *xics, int server, uint8_t cppr)
>>> @@ -256,7 +264,10 @@ void icp_set_cppr(XICSState *xics, int server, uint8_t cppr)
>>>              ss->xirr &= ~XISR_MASK; /* Clear XISR */
>>>              ss->pending_priority = 0xff;
>>>              qemu_irq_lower(ss->output);
>>> -            ics_reject(xics->ics, old_xisr);
>>> +            if (ss->xirr_owner) {
>>> +                ics_reject(ss->xirr_owner, old_xisr);
>>> +                ss->xirr_owner = NULL;
>>> +            }
>>>          }
>>>      } else {
>>>          if (!XISR(ss)) {
>>> @@ -271,7 +282,7 @@ void icp_set_mfrr(XICSState *xics, int server, uint8_t mfrr)
>>>  
>>>      ss->mfrr = mfrr;
>>>      if (mfrr < CPPR(ss)) {
>>> -        icp_check_ipi(xics, server);
>>> +        icp_check_ipi(ss);
>>>      }
>>>  }
>>>  
>>> @@ -282,6 +293,7 @@ uint32_t icp_accept(ICPState *ss)
>>>      qemu_irq_lower(ss->output);
>>>      ss->xirr = ss->pending_priority << 24;
>>>      ss->pending_priority = 0xff;
>>> +    ss->xirr_owner = NULL;
>>>  
>>>      trace_xics_icp_accept(xirr, ss->xirr);
>>>  
>>> @@ -299,30 +311,40 @@ uint32_t icp_ipoll(ICPState *ss, uint32_t *mfrr)
>>>  void icp_eoi(XICSState *xics, int server, uint32_t xirr)
>>>  {
>>>      ICPState *ss = xics->ss + server;
>>> +    ICSState *ics;
>>> +    uint32_t irq;
>>>  
>>>      /* Send EOI -> ICS */
>>>      ss->xirr = (ss->xirr & ~CPPR_MASK) | (xirr & CPPR_MASK);
>>>      trace_xics_icp_eoi(server, xirr, ss->xirr);
>>> -    ics_eoi(xics->ics, xirr & XISR_MASK);
>>> +    irq = xirr & XISR_MASK;
>>> +    QLIST_FOREACH(ics, &xics->ics, list) {
>>> +        if (ics_valid_irq(ics, irq)) {
>>> +            ics_eoi(ics, irq);
>>> +        }
>>> +    }
>>>      if (!XISR(ss)) {
>>>          icp_resend(xics, server);
>>>      }
>>>  }
>>>  
>>> -static void icp_irq(XICSState *xics, int server, int nr, uint8_t priority)
>>> +static void icp_irq(ICSState *ics, int server, int nr, uint8_t priority)
>>>  {
>>> +    XICSState *xics = ics->xics;
>>>      ICPState *ss = xics->ss + server;
>>>  
>>>      trace_xics_icp_irq(server, nr, priority);
>>>  
>>>      if ((priority >= CPPR(ss))
>>>          || (XISR(ss) && (ss->pending_priority <= priority))) {
>>> -        ics_reject(xics->ics, nr);
>>> +        ics_reject(ics, nr);
>>>      } else {
>>> -        if (XISR(ss)) {
>>> -            ics_reject(xics->ics, XISR(ss));
>>> +        if (XISR(ss) && ss->xirr_owner) {
>>> +            ics_reject(ss->xirr_owner, XISR(ss));
>>> +            ss->xirr_owner = NULL;
>>>          }
>>>          ss->xirr = (ss->xirr & ~XISR_MASK) | (nr & XISR_MASK);
>>> +        ss->xirr_owner = ics;
>>>          ss->pending_priority = priority;
>>>          trace_xics_icp_raise(ss->xirr, ss->pending_priority);
>>>          qemu_irq_raise(ss->output);
>>> @@ -378,12 +400,45 @@ static void icp_reset(DeviceState *dev)
>>>      qemu_set_irq(icp->output, 0);
>>>  }
>>>  
>>> +static int icp_post_load(ICPState *ss, int version_id)
>>> +{
>>> +    sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
>>> +    XICSState *xics = spapr->xics;
>>> +    uint32_t irq, i;
>>> +    static uint32_t server_no;
>>> +
>>> +    server_no++;
>>> +    irq = XISR(ss);
>>> +    if (!ss->cs || !irq) {
>>> +        goto icpend;
>>> +    }
>>> +
>>> +    /* Restore the xirr_owner */
>>> +    ss->xirr_owner = xics_find_source(xics, irq);
>>> +
>>> + icpend:
>>> +    trace_xics_icp_post_load(server_no, ss->xirr, (uint64_t)ss->xirr_owner,
>>> +                             ss->pending_priority);
>>> +    if (xics->nr_servers != server_no) {
>>> +        return 0;
>>> +    }
>>> +
>>> +    /* All the ICPs are processed, now restore all the state */
>>> +    for (i = 0; i < xics->nr_servers; i++) {
>>> +        icp_resend(xics, i);
>>> +    }
>>> +    server_no = 0;
>>> +    return 0;
>>> +}
>>
>> Is the issue this change is trying to fix related to ICSState becoming 
>> a list ? If not, It should be in another patch I think.
> 
> Yes, and we introduced xirr_owner to optimize. This needs to regenerated
> at the destination after migration.

Ah. this is because of the previous patch. ok. I am not sure 
I understand the complete issue but it would better if it was 
a bit more isolated. This patch is mixing different things and 
doing in xics.c :

	#include "hw/ppc/spapr.h"

seems wrong. I think David suggested to redesign the xics 
migration state.

As we are shuffling code a bit for pnv, I would add that first
to have a better view of the needs. 

C.

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [Qemu-ppc] [PATCH v4 6/9] ppc/xics: Split ICS into ics-base and ics class
  2016-09-19  6:29 ` [Qemu-devel] [PATCH v4 6/9] ppc/xics: Split ICS into ics-base and ics class Nikunj A Dadhania
  2016-09-19  7:09   ` [Qemu-devel] [Qemu-ppc] " Cédric Le Goater
@ 2016-09-19 14:34   ` Cédric Le Goater
  2016-09-20  6:02     ` Nikunj A Dadhania
  1 sibling, 1 reply; 38+ messages in thread
From: Cédric Le Goater @ 2016-09-19 14:34 UTC (permalink / raw)
  To: Nikunj A Dadhania, qemu-ppc, david; +Cc: qemu-devel

On 09/19/2016 08:29 AM, Nikunj A Dadhania wrote:
> From: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> 
> The existing implementation remains same and ics-base is introduced. The
> type name "ics" is retained, and all the related functions renamed as
> ics_simple_*
> 
> This will allow different implementations for the source controllers
> such as the MSI support of PHB3 on Power8 which uses in-memory state
> tables for example.

A couple of issues below regarding the class helpers,

> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> Signed-off-by: Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>
> ---
>  hw/intc/trace-events  |  10 ++--
>  hw/intc/xics.c        | 143 +++++++++++++++++++++++++++++++-------------------
>  hw/intc/xics_kvm.c    |  10 ++--
>  hw/intc/xics_spapr.c  |  28 +++++-----
>  include/hw/ppc/xics.h |  23 +++++---
>  5 files changed, 131 insertions(+), 83 deletions(-)
> 
> diff --git a/hw/intc/trace-events b/hw/intc/trace-events
> index aa342a8..a367b46 100644
> --- a/hw/intc/trace-events
> +++ b/hw/intc/trace-events
> @@ -50,12 +50,12 @@ xics_icp_accept(uint32_t old_xirr, uint32_t new_xirr) "icp_accept: XIRR %#"PRIx3
>  xics_icp_eoi(int server, uint32_t xirr, uint32_t new_xirr) "icp_eoi: server %d given XIRR %#"PRIx32" new XIRR %#"PRIx32
>  xics_icp_irq(int server, int nr, uint8_t priority) "cpu %d trying to deliver irq %#"PRIx32" priority %#x"
>  xics_icp_raise(uint32_t xirr, uint8_t pending_priority) "raising IRQ new XIRR=%#x new pending priority=%#x"
> -xics_set_irq_msi(int srcno, int nr) "set_irq_msi: srcno %d [irq %#x]"
> +xics_ics_simple_set_irq_msi(int srcno, int nr) "set_irq_msi: srcno %d [irq %#x]"
>  xics_masked_pending(void) "set_irq_msi: masked pending"
> -xics_set_irq_lsi(int srcno, int nr) "set_irq_lsi: srcno %d [irq %#x]"
> -xics_ics_write_xive(int nr, int srcno, int server, uint8_t priority) "ics_write_xive: irq %#x [src %d] server %#x prio %#x"
> -xics_ics_reject(int nr, int srcno) "reject irq %#x [src %d]"
> -xics_ics_eoi(int nr) "ics_eoi: irq %#x"
> +xics_ics_simple_set_irq_lsi(int srcno, int nr) "set_irq_lsi: srcno %d [irq %#x]"
> +xics_ics_simple_write_xive(int nr, int srcno, int server, uint8_t priority) "ics_write_xive: irq %#x [src %d] server %#x prio %#x"
> +xics_ics_simple_reject(int nr, int srcno) "reject irq %#x [src %d]"
> +xics_ics_simple_eoi(int nr) "ics_eoi: irq %#x"
>  xics_alloc(int irq) "irq %d"
>  xics_alloc_block(int first, int num, bool lsi, int align) "first irq %d, %d irqs, lsi=%d, alignnum %d"
>  xics_ics_free(int src, int irq, int num) "Source#%d, first irq %d, %d irqs"
> diff --git a/hw/intc/xics.c b/hw/intc/xics.c
> index c7901c4..b15751e 100644
> --- a/hw/intc/xics.c
> +++ b/hw/intc/xics.c
> @@ -113,7 +113,7 @@ void xics_add_ics(XICSState *xics)
>  {
>      ICSState *ics;
>  
> -    ics = ICS(object_new(TYPE_ICS));
> +    ics = ICS_SIMPLE(object_new(TYPE_ICS_SIMPLE));
>      object_property_add_child(OBJECT(xics), "ics", OBJECT(ics), NULL);
>      ics->xics = xics;
>      QLIST_INSERT_HEAD(&xics->ics, ics, list);
> @@ -224,9 +224,32 @@ static const TypeInfo xics_common_info = {
>  #define XISR(ss)   (((ss)->xirr) & XISR_MASK)
>  #define CPPR(ss)   (((ss)->xirr) >> 24)
>  
> -static void ics_reject(ICSState *ics, int nr);
> -static void ics_resend(ICSState *ics, int server);
> -static void ics_eoi(ICSState *ics, int nr);
> +static void ics_reject(ICSState *ics, uint32_t nr)
> +{
> +    ICSStateClass *k = ICS_GET_CLASS(ics);

Shouldn't that be ICS_BASE_GET_CLASS()

> +    if (k->reject) {
> +        k->reject(ics, nr);
> +    }
> +}
> +
> +static void ics_resend(ICSState *ics, int server)
> +{
> +    ICSStateClass *k = ICS_GET_CLASS(ics);

here also

> +
> +    if (k->resend) {
> +        k->resend(ics, server);
> +    }
> +}
> +
> +static void ics_eoi(ICSState *ics, int nr)
> +{
> +    ICSStateClass *k = ICS_GET_CLASS(ics);

and here. 

> +
> +    if (k->eoi) {
> +        k->eoi(ics, nr);
> +    }
> +}
>  
>  static void icp_check_ipi(ICPState *ss)
>  {
> @@ -462,7 +485,7 @@ static const TypeInfo icp_info = {
>  /*
>   * ICS: Source layer
>   */
> -static void resend_msi(ICSState *ics, int srcno)
> +static void ics_simple_resend_msi(ICSState *ics, int srcno)
>  {
>      ICSIRQState *irq = ics->irqs + srcno;
>  
> @@ -475,7 +498,7 @@ static void resend_msi(ICSState *ics, int srcno)
>      }
>  }
>  
> -static void resend_lsi(ICSState *ics, int srcno)
> +static void ics_simple_resend_lsi(ICSState *ics, int srcno)
>  {
>      ICSIRQState *irq = ics->irqs + srcno;
>  
> @@ -487,11 +510,11 @@ static void resend_lsi(ICSState *ics, int srcno)
>      }
>  }
>  
> -static void set_irq_msi(ICSState *ics, int srcno, int val)
> +static void ics_simple_set_irq_msi(ICSState *ics, int srcno, int val)
>  {
>      ICSIRQState *irq = ics->irqs + srcno;
>  
> -    trace_xics_set_irq_msi(srcno, srcno + ics->offset);
> +    trace_xics_ics_simple_set_irq_msi(srcno, srcno + ics->offset);
>  
>      if (val) {
>          if (irq->priority == 0xff) {
> @@ -503,31 +526,31 @@ static void set_irq_msi(ICSState *ics, int srcno, int val)
>      }
>  }
>  
> -static void set_irq_lsi(ICSState *ics, int srcno, int val)
> +static void ics_simple_set_irq_lsi(ICSState *ics, int srcno, int val)
>  {
>      ICSIRQState *irq = ics->irqs + srcno;
>  
> -    trace_xics_set_irq_lsi(srcno, srcno + ics->offset);
> +    trace_xics_ics_simple_set_irq_lsi(srcno, srcno + ics->offset);
>      if (val) {
>          irq->status |= XICS_STATUS_ASSERTED;
>      } else {
>          irq->status &= ~XICS_STATUS_ASSERTED;
>      }
> -    resend_lsi(ics, srcno);
> +    ics_simple_resend_lsi(ics, srcno);
>  }
>  
> -static void ics_set_irq(void *opaque, int srcno, int val)
> +static void ics_simple_set_irq(void *opaque, int srcno, int val)
>  {
>      ICSState *ics = (ICSState *)opaque;
>  
>      if (ics->irqs[srcno].flags & XICS_FLAGS_IRQ_LSI) {
> -        set_irq_lsi(ics, srcno, val);
> +        ics_simple_set_irq_lsi(ics, srcno, val);
>      } else {
> -        set_irq_msi(ics, srcno, val);
> +        ics_simple_set_irq_msi(ics, srcno, val);
>      }
>  }
>  
> -static void write_xive_msi(ICSState *ics, int srcno)
> +static void ics_simple_write_xive_msi(ICSState *ics, int srcno)
>  {
>      ICSIRQState *irq = ics->irqs + srcno;
>  
> @@ -540,35 +563,35 @@ static void write_xive_msi(ICSState *ics, int srcno)
>      icp_irq(ics, irq->server, srcno + ics->offset, irq->priority);
>  }
>  
> -static void write_xive_lsi(ICSState *ics, int srcno)
> +static void ics_simple_write_xive_lsi(ICSState *ics, int srcno)
>  {
> -    resend_lsi(ics, srcno);
> +    ics_simple_resend_lsi(ics, srcno);
>  }
>  
> -void ics_write_xive(ICSState *ics, int nr, int server,
> -                    uint8_t priority, uint8_t saved_priority)
> +void ics_simple_write_xive(ICSState *ics, int srcno, int server,
> +                           uint8_t priority, uint8_t saved_priority)
>  {
> -    int srcno = nr - ics->offset;
>      ICSIRQState *irq = ics->irqs + srcno;
>  
>      irq->server = server;
>      irq->priority = priority;
>      irq->saved_priority = saved_priority;
>  
> -    trace_xics_ics_write_xive(nr, srcno, server, priority);
> +    trace_xics_ics_simple_write_xive(ics->offset + srcno, srcno, server,
> +                                     priority);
>  
>      if (ics->irqs[srcno].flags & XICS_FLAGS_IRQ_LSI) {
> -        write_xive_lsi(ics, srcno);
> +        ics_simple_write_xive_lsi(ics, srcno);
>      } else {
> -        write_xive_msi(ics, srcno);
> +        ics_simple_write_xive_msi(ics, srcno);
>      }
>  }
>  
> -static void ics_reject(ICSState *ics, int nr)
> +static void ics_simple_reject(ICSState *ics, uint32_t nr)
>  {
>      ICSIRQState *irq = ics->irqs + nr - ics->offset;
>  
> -    trace_xics_ics_reject(nr, nr - ics->offset);
> +    trace_xics_ics_simple_reject(nr, nr - ics->offset);
>      if (irq->flags & XICS_FLAGS_IRQ_MSI) {
>          irq->status |= XICS_STATUS_REJECTED;
>      } else if (irq->flags & XICS_FLAGS_IRQ_LSI) {
> @@ -576,7 +599,7 @@ static void ics_reject(ICSState *ics, int nr)
>      }
>  }
>  
> -static void ics_resend(ICSState *ics, int server)
> +static void ics_simple_resend(ICSState *ics, int server)
>  {
>      int i;
>      ICPState *ss = ics->xics->ss + server;
> @@ -594,28 +617,28 @@ static void ics_resend(ICSState *ics, int server)
>                  qemu_irq_raise(ss->output);
>                  continue;
>              }
> -            resend_lsi(ics, i);
> +            ics_simple_resend_lsi(ics, i);
>          } else {
> -            resend_msi(ics, i);
> +            ics_simple_resend_msi(ics, i);
>          }
>      }
>  }
>  
> -static void ics_eoi(ICSState *ics, int nr)
> +static void ics_simple_eoi(ICSState *ics, uint32_t nr)
>  {
>      int srcno = nr - ics->offset;
>      ICSIRQState *irq = ics->irqs + srcno;
>  
> -    trace_xics_ics_eoi(nr);
> +    trace_xics_ics_simple_eoi(nr);
>  
>      if (ics->irqs[srcno].flags & XICS_FLAGS_IRQ_LSI) {
>          irq->status &= ~XICS_STATUS_SENT;
>      }
>  }
>  
> -static void ics_reset(DeviceState *dev)
> +static void ics_simple_reset(DeviceState *dev)
>  {
> -    ICSState *ics = ICS(dev);
> +    ICSState *ics = ICS_SIMPLE(dev);
>      int i;
>      uint8_t flags[ics->nr_irqs];
>  
> @@ -632,7 +655,7 @@ static void ics_reset(DeviceState *dev)
>      }
>  }
>  
> -static void ics_dispatch_pre_save(void *opaque)
> +static void ics_simple_dispatch_pre_save(void *opaque)
>  {
>      ICSState *ics = opaque;
>      ICSStateClass *info = ICS_GET_CLASS(ics);


and here. 

> @@ -642,7 +665,7 @@ static void ics_dispatch_pre_save(void *opaque)
>      }
>  }
>  
> -static int ics_dispatch_post_load(void *opaque, int version_id)
> +static int ics_simple_dispatch_post_load(void *opaque, int version_id)
>  {
>      ICSState *ics = opaque;
>      ICSStateClass *info = ICS_GET_CLASS(ics);


and here. 

> @@ -654,7 +677,7 @@ static int ics_dispatch_post_load(void *opaque, int version_id)
>      return 0;
>  }
>  
> -static const VMStateDescription vmstate_ics_irq = {
> +static const VMStateDescription vmstate_ics_simple_irq = {
>      .name = "ics/irq",
>      .version_id = 2,
>      .minimum_version_id = 1,
> @@ -668,57 +691,70 @@ static const VMStateDescription vmstate_ics_irq = {
>      },
>  };
>  
> -static const VMStateDescription vmstate_ics = {
> +static const VMStateDescription vmstate_ics_simple = {
>      .name = "ics",
>      .version_id = 1,
>      .minimum_version_id = 1,
> -    .pre_save = ics_dispatch_pre_save,
> -    .post_load = ics_dispatch_post_load,
> +    .pre_save = ics_simple_dispatch_pre_save,
> +    .post_load = ics_simple_dispatch_post_load,
>      .fields = (VMStateField[]) {
>          /* Sanity check */
>          VMSTATE_UINT32_EQUAL(nr_irqs, ICSState),
>  
>          VMSTATE_STRUCT_VARRAY_POINTER_UINT32(irqs, ICSState, nr_irqs,
> -                                             vmstate_ics_irq, ICSIRQState),
> +                                             vmstate_ics_simple_irq,
> +                                             ICSIRQState),
>          VMSTATE_END_OF_LIST()
>      },
>  };
>  
> -static void ics_initfn(Object *obj)
> +static void ics_simple_initfn(Object *obj)
>  {
> -    ICSState *ics = ICS(obj);
> +    ICSState *ics = ICS_SIMPLE(obj);
>  
>      ics->offset = XICS_IRQ_BASE;
>  }
>  
> -static void ics_realize(DeviceState *dev, Error **errp)
> +static void ics_simple_realize(DeviceState *dev, Error **errp)
>  {
> -    ICSState *ics = ICS(dev);
> +    ICSState *ics = ICS_SIMPLE(dev);
>  
>      if (!ics->nr_irqs) {
>          error_setg(errp, "Number of interrupts needs to be greater 0");
>          return;
>      }
>      ics->irqs = g_malloc0(ics->nr_irqs * sizeof(ICSIRQState));
> -    ics->qirqs = qemu_allocate_irqs(ics_set_irq, ics, ics->nr_irqs);
> +    ics->qirqs = qemu_allocate_irqs(ics_simple_set_irq, ics, ics->nr_irqs);
>  }
>  
> -static void ics_class_init(ObjectClass *klass, void *data)
> +static void ics_simple_class_init(ObjectClass *klass, void *data)
>  {
>      DeviceClass *dc = DEVICE_CLASS(klass);
> +    ICSStateClass *isc = ICS_CLASS(klass);
>  
> -    dc->realize = ics_realize;
> -    dc->vmsd = &vmstate_ics;
> -    dc->reset = ics_reset;
> +    dc->realize = ics_simple_realize;
> +    dc->vmsd = &vmstate_ics_simple;
> +    dc->reset = ics_simple_reset;
> +    isc->reject = ics_simple_reject;
> +    isc->resend = ics_simple_resend;
> +    isc->eoi = ics_simple_eoi;
>  }
>  
> -static const TypeInfo ics_info = {
> -    .name = TYPE_ICS,
> +static const TypeInfo ics_simple_info = {
> +    .name = TYPE_ICS_SIMPLE,
> +    .parent = TYPE_ICS_BASE,
> +    .instance_size = sizeof(ICSState),
> +    .class_init = ics_simple_class_init,
> +    .class_size = sizeof(ICSStateClass),
> +    .instance_init = ics_simple_initfn,
> +};
> +
> +static const TypeInfo ics_base_info = {
> +    .name = TYPE_ICS_BASE,
>      .parent = TYPE_DEVICE,
> +    .abstract = true,
>      .instance_size = sizeof(ICSState),
> -    .class_init = ics_class_init,
>      .class_size = sizeof(ICSStateClass),
> -    .instance_init = ics_initfn,
>  };
>  
>  /*
> @@ -758,7 +794,8 @@ void ics_set_irq_type(ICSState *ics, int srcno, bool lsi)
>  static void xics_register_types(void)
>  {
>      type_register_static(&xics_common_info);
> -    type_register_static(&ics_info);
> +    type_register_static(&ics_simple_info);
> +    type_register_static(&ics_base_info);
>      type_register_static(&icp_info);
>  }
>  
> diff --git a/hw/intc/xics_kvm.c b/hw/intc/xics_kvm.c
> index 04fa7cb..89862df 100644
> --- a/hw/intc/xics_kvm.c
> +++ b/hw/intc/xics_kvm.c
> @@ -272,7 +272,7 @@ static void ics_kvm_set_irq(void *opaque, int srcno, int val)
>  
>  static void ics_kvm_reset(DeviceState *dev)
>  {
> -    ICSState *ics = ICS(dev);
> +    ICSState *ics = ICS_SIMPLE(dev);
>      int i;
>      uint8_t flags[ics->nr_irqs];
>  
> @@ -293,7 +293,7 @@ static void ics_kvm_reset(DeviceState *dev)
>  
>  static void ics_kvm_realize(DeviceState *dev, Error **errp)
>  {
> -    ICSState *ics = ICS(dev);
> +    ICSState *ics = ICS_SIMPLE(dev);
>  
>      if (!ics->nr_irqs) {
>          error_setg(errp, "Number of interrupts needs to be greater 0");
> @@ -315,8 +315,8 @@ static void ics_kvm_class_init(ObjectClass *klass, void *data)

and in ics_kvm_class_init  also.

>  }
>  
>  static const TypeInfo ics_kvm_info = {
> -    .name = TYPE_KVM_ICS,
> -    .parent = TYPE_ICS,
> +    .name = TYPE_ICS_KVM,
> +    .parent = TYPE_ICS_SIMPLE,
>      .instance_size = sizeof(ICSState),
>      .class_init = ics_kvm_class_init,
>  };
> @@ -492,7 +492,7 @@ static void xics_kvm_initfn(Object *obj)
>      XICSState *xics = XICS_COMMON(obj);
>      ICSState *ics;
>  
> -    ics = ICS(object_new(TYPE_KVM_ICS));
> +    ics = ICS_SIMPLE(object_new(TYPE_ICS_KVM));
>      object_property_add_child(obj, "ics", OBJECT(ics), NULL);
>      ics->xics = xics;
>      QLIST_INSERT_HEAD(&xics->ics, ics, list);
> diff --git a/hw/intc/xics_spapr.c b/hw/intc/xics_spapr.c
> index 270f20e..4dd1399 100644
> --- a/hw/intc/xics_spapr.c
> +++ b/hw/intc/xics_spapr.c
> @@ -114,7 +114,7 @@ static void rtas_set_xive(PowerPCCPU *cpu, sPAPRMachineState *spapr,
>                            uint32_t nret, target_ulong rets)
>  {
>      ICSState *ics = QLIST_FIRST(&spapr->xics->ics);
> -    uint32_t nr, server, priority;
> +    uint32_t nr, srcno, server, priority;
>  
>      if ((nargs != 3) || (nret != 1)) {
>          rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
> @@ -135,7 +135,8 @@ static void rtas_set_xive(PowerPCCPU *cpu, sPAPRMachineState *spapr,
>          return;
>      }
>  
> -    ics_write_xive(ics, nr, server, priority, priority);
> +    srcno = nr - ics->offset;
> +    ics_simple_write_xive(ics, srcno, server, priority, priority);
>  
>      rtas_st(rets, 0, RTAS_OUT_SUCCESS);
>  }
> @@ -146,7 +147,7 @@ static void rtas_get_xive(PowerPCCPU *cpu, sPAPRMachineState *spapr,
>                            uint32_t nret, target_ulong rets)
>  {
>      ICSState *ics = QLIST_FIRST(&spapr->xics->ics);
> -    uint32_t nr;
> +    uint32_t nr, srcno;
>  
>      if ((nargs != 1) || (nret != 3)) {
>          rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
> @@ -165,8 +166,9 @@ static void rtas_get_xive(PowerPCCPU *cpu, sPAPRMachineState *spapr,
>      }
>  
>      rtas_st(rets, 0, RTAS_OUT_SUCCESS);
> -    rtas_st(rets, 1, ics->irqs[nr - ics->offset].server);
> -    rtas_st(rets, 2, ics->irqs[nr - ics->offset].priority);
> +    srcno = nr - ics->offset;
> +    rtas_st(rets, 1, ics->irqs[srcno].server);
> +    rtas_st(rets, 2, ics->irqs[srcno].priority);
>  }
>  
>  static void rtas_int_off(PowerPCCPU *cpu, sPAPRMachineState *spapr,
> @@ -175,7 +177,7 @@ static void rtas_int_off(PowerPCCPU *cpu, sPAPRMachineState *spapr,
>                           uint32_t nret, target_ulong rets)
>  {
>      ICSState *ics = QLIST_FIRST(&spapr->xics->ics);
> -    uint32_t nr;
> +    uint32_t nr, srcno;
>  
>      if ((nargs != 1) || (nret != 1)) {
>          rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
> @@ -193,8 +195,9 @@ static void rtas_int_off(PowerPCCPU *cpu, sPAPRMachineState *spapr,
>          return;
>      }
>  
> -    ics_write_xive(ics, nr, ics->irqs[nr - ics->offset].server, 0xff,
> -                   ics->irqs[nr - ics->offset].priority);
> +    srcno = nr - ics->offset;
> +    ics_simple_write_xive(ics, srcno, ics->irqs[srcno].server, 0xff,
> +                          ics->irqs[srcno].priority);
>  
>      rtas_st(rets, 0, RTAS_OUT_SUCCESS);
>  }
> @@ -205,7 +208,7 @@ static void rtas_int_on(PowerPCCPU *cpu, sPAPRMachineState *spapr,
>                          uint32_t nret, target_ulong rets)
>  {
>      ICSState *ics = QLIST_FIRST(&spapr->xics->ics);
> -    uint32_t nr;
> +    uint32_t nr, srcno;
>  
>      if ((nargs != 1) || (nret != 1)) {
>          rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
> @@ -223,9 +226,10 @@ static void rtas_int_on(PowerPCCPU *cpu, sPAPRMachineState *spapr,
>          return;
>      }
>  
> -    ics_write_xive(ics, nr, ics->irqs[nr - ics->offset].server,
> -                   ics->irqs[nr - ics->offset].saved_priority,
> -                   ics->irqs[nr - ics->offset].saved_priority);
> +    srcno = nr - ics->offset;
> +    ics_simple_write_xive(ics, srcno, ics->irqs[srcno].server,
> +                          ics->irqs[srcno].saved_priority,
> +                          ics->irqs[srcno].saved_priority);
>  
>      rtas_st(rets, 0, RTAS_OUT_SUCCESS);
>  }
> diff --git a/include/hw/ppc/xics.h b/include/hw/ppc/xics.h
> index a7a1e54..2231f2a 100644
> --- a/include/hw/ppc/xics.h
> +++ b/include/hw/ppc/xics.h
> @@ -119,22 +119,29 @@ struct ICPState {
>      bool cap_irq_xics_enabled;
>  };
>  
> -#define TYPE_ICS "ics"
> -#define ICS(obj) OBJECT_CHECK(ICSState, (obj), TYPE_ICS)
> +#define TYPE_ICS_BASE "ics-base"
> +#define ICS_BASE(obj) OBJECT_CHECK(ICSState, (obj), TYPE_ICS_SIMPLE)

#define ICS_BASE(obj) OBJECT_CHECK(ICSState, (obj), TYPE_ICS_BASE)

> -#define TYPE_KVM_ICS "icskvm"
> -#define KVM_ICS(obj) OBJECT_CHECK(ICSState, (obj), TYPE_KVM_ICS)
> +/* Retain ics for sPAPR for migration from existing sPAPR guests */
> +#define TYPE_ICS_SIMPLE "ics"
> +#define ICS_SIMPLE(obj) OBJECT_CHECK(ICSState, (obj), TYPE_ICS_SIMPLE)
> +
> +#define TYPE_ICS_KVM "icskvm"
> +#define ICS_KVM(obj) OBJECT_CHECK(ICSState, (obj), TYPE_ICS_KVM)
>  
>  #define ICS_CLASS(klass) \
> -     OBJECT_CLASS_CHECK(ICSStateClass, (klass), TYPE_ICS)
> +     OBJECT_CLASS_CHECK(ICSStateClass, (klass), TYPE_ICS_SIMPLE)
>  #define ICS_GET_CLASS(obj) \
> -     OBJECT_GET_CLASS(ICSStateClass, (obj), TYPE_ICS)
> +     OBJECT_GET_CLASS(ICSStateClass, (obj), TYPE_ICS_SIMPLE)

#define ICS_BASE_CLASS(klass) \
     OBJECT_CLASS_CHECK(ICSStateClass, (klass), TYPE_ICS_BASE)
#define ICS_BASE_GET_CLASS(obj) \
     OBJECT_GET_CLASS(ICSStateClass, (obj), TYPE_ICS_BASE)

Cheers,

C.

>  struct ICSStateClass {
>      DeviceClass parent_class;
>  
>      void (*pre_save)(ICSState *s);
>      int (*post_load)(ICSState *s, int version_id);
> +    void (*reject)(ICSState *s, uint32_t irq);
> +    void (*resend)(ICSState *s, int server);
> +    void (*eoi)(ICSState *s, uint32_t irq);
>  };
>  
>  struct ICSState {
> @@ -191,8 +198,8 @@ uint32_t icp_accept(ICPState *ss);
>  uint32_t icp_ipoll(ICPState *ss, uint32_t *mfrr);
>  void icp_eoi(XICSState *icp, int server, uint32_t xirr);
>  
> -void ics_write_xive(ICSState *ics, int nr, int server,
> -                    uint8_t priority, uint8_t saved_priority);
> +void ics_simple_write_xive(ICSState *ics, int nr, int server,
> +                           uint8_t priority, uint8_t saved_priority);
>  
>  void ics_set_irq_type(ICSState *ics, int srcno, bool lsi);
>  
> 

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [Qemu-ppc] [PATCH v4 3/9] ppc/xics: Make the ICSState a list
  2016-09-19  7:24       ` Cédric Le Goater
@ 2016-09-20  5:13         ` Nikunj A Dadhania
  0 siblings, 0 replies; 38+ messages in thread
From: Nikunj A Dadhania @ 2016-09-20  5:13 UTC (permalink / raw)
  To: Cédric Le Goater, qemu-ppc, david; +Cc: qemu-devel

Cédric Le Goater <clg@kaod.org> writes:

> On 09/19/2016 09:02 AM, Nikunj A Dadhania wrote:
>> Cédric Le Goater <clg@kaod.org> writes:
>> 
>>>  
>>>> +static int icp_post_load(ICPState *ss, int version_id)
>>>> +{
>>>> +    sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
>>>> +    XICSState *xics = spapr->xics;
>>>> +    uint32_t irq, i;
>>>> +    static uint32_t server_no;
>>>> +
>>>> +    server_no++;
>>>> +    irq = XISR(ss);
>>>> +    if (!ss->cs || !irq) {
>>>> +        goto icpend;
>>>> +    }
>>>> +
>>>> +    /* Restore the xirr_owner */
>>>> +    ss->xirr_owner = xics_find_source(xics, irq);
>>>> +
>>>> + icpend:
>>>> +    trace_xics_icp_post_load(server_no, ss->xirr, (uint64_t)ss->xirr_owner,
>>>> +                             ss->pending_priority);
>>>> +    if (xics->nr_servers != server_no) {
>>>> +        return 0;
>>>> +    }
>>>> +
>>>> +    /* All the ICPs are processed, now restore all the state */
>>>> +    for (i = 0; i < xics->nr_servers; i++) {
>>>> +        icp_resend(xics, i);
>>>> +    }
>>>> +    server_no = 0;
>>>> +    return 0;
>>>> +}
>>>
>>> Is the issue this change is trying to fix related to ICSState becoming 
>>> a list ? If not, It should be in another patch I think.
>> 
>> Yes, and we introduced xirr_owner to optimize. This needs to regenerated
>> at the destination after migration.
>
> Ah. this is because of the previous patch. ok. I am not sure 
> I understand the complete issue but it would better if it was 
> a bit more isolated. This patch is mixing different things and 
> doing in xics.c :
>
> 	#include "hw/ppc/spapr.h"
>
> seems wrong.

Not sure, Why?

> I think David suggested to redesign the xics migration state.

That is not needed, as I have solved the problem in the previous patch.
The migration changes was needed for the issue that I had reported.

Regards
Nikunj

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [Qemu-ppc] [PATCH v4 6/9] ppc/xics: Split ICS into ics-base and ics class
  2016-09-19  7:09   ` [Qemu-devel] [Qemu-ppc] " Cédric Le Goater
@ 2016-09-20  5:14     ` Nikunj A Dadhania
  0 siblings, 0 replies; 38+ messages in thread
From: Nikunj A Dadhania @ 2016-09-20  5:14 UTC (permalink / raw)
  To: Cédric Le Goater, qemu-ppc, david; +Cc: qemu-devel

Cédric Le Goater <clg@kaod.org> writes:

> On 09/19/2016 08:29 AM, Nikunj A Dadhania wrote:
>> From: Benjamin Herrenschmidt <benh@kernel.crashing.org>
>> 
>> The existing implementation remains same and ics-base is introduced. The
>> type name "ics" is retained, and all the related functions renamed as
>> ics_simple_*
>> 
>> This will allow different implementations for the source controllers
>> such as the MSI support of PHB3 on Power8 which uses in-memory state
>> tables for example.
>> 
>> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
>> Signed-off-by: Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>
>
> This patch had a Reviewed-by from David. Did you change anything 
> in v4 ? 

No changes, I missed adding reviewed-by in v4.

Regards
Nikunj

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [Qemu-ppc] [PATCH v4 6/9] ppc/xics: Split ICS into ics-base and ics class
  2016-09-19 14:34   ` Cédric Le Goater
@ 2016-09-20  6:02     ` Nikunj A Dadhania
  2016-09-20  6:20       ` Cédric Le Goater
  0 siblings, 1 reply; 38+ messages in thread
From: Nikunj A Dadhania @ 2016-09-20  6:02 UTC (permalink / raw)
  To: Cédric Le Goater, qemu-ppc, david; +Cc: qemu-devel

Cédric Le Goater <clg@kaod.org> writes:

> On 09/19/2016 08:29 AM, Nikunj A Dadhania wrote:
>> From: Benjamin Herrenschmidt <benh@kernel.crashing.org>
>> 
>> The existing implementation remains same and ics-base is introduced. The
>> type name "ics" is retained, and all the related functions renamed as
>> ics_simple_*
>> 
>> This will allow different implementations for the source controllers
>> such as the MSI support of PHB3 on Power8 which uses in-memory state
>> tables for example.
>
> A couple of issues below regarding the class helpers,
>
>> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
>> Signed-off-by: Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>
>> ---
>>  hw/intc/trace-events  |  10 ++--
>>  hw/intc/xics.c        | 143 +++++++++++++++++++++++++++++++-------------------
>>  hw/intc/xics_kvm.c    |  10 ++--
>>  hw/intc/xics_spapr.c  |  28 +++++-----
>>  include/hw/ppc/xics.h |  23 +++++---
>>  5 files changed, 131 insertions(+), 83 deletions(-)
>> 
>> diff --git a/hw/intc/trace-events b/hw/intc/trace-events
>> index aa342a8..a367b46 100644
>> --- a/hw/intc/trace-events
>> +++ b/hw/intc/trace-events
>> @@ -50,12 +50,12 @@ xics_icp_accept(uint32_t old_xirr, uint32_t new_xirr) "icp_accept: XIRR %#"PRIx3
>>  xics_icp_eoi(int server, uint32_t xirr, uint32_t new_xirr) "icp_eoi: server %d given XIRR %#"PRIx32" new XIRR %#"PRIx32
>>  xics_icp_irq(int server, int nr, uint8_t priority) "cpu %d trying to deliver irq %#"PRIx32" priority %#x"
>>  xics_icp_raise(uint32_t xirr, uint8_t pending_priority) "raising IRQ new XIRR=%#x new pending priority=%#x"
>> -xics_set_irq_msi(int srcno, int nr) "set_irq_msi: srcno %d [irq %#x]"
>> +xics_ics_simple_set_irq_msi(int srcno, int nr) "set_irq_msi: srcno %d [irq %#x]"
>>  xics_masked_pending(void) "set_irq_msi: masked pending"
>> -xics_set_irq_lsi(int srcno, int nr) "set_irq_lsi: srcno %d [irq %#x]"
>> -xics_ics_write_xive(int nr, int srcno, int server, uint8_t priority) "ics_write_xive: irq %#x [src %d] server %#x prio %#x"
>> -xics_ics_reject(int nr, int srcno) "reject irq %#x [src %d]"
>> -xics_ics_eoi(int nr) "ics_eoi: irq %#x"
>> +xics_ics_simple_set_irq_lsi(int srcno, int nr) "set_irq_lsi: srcno %d [irq %#x]"
>> +xics_ics_simple_write_xive(int nr, int srcno, int server, uint8_t priority) "ics_write_xive: irq %#x [src %d] server %#x prio %#x"
>> +xics_ics_simple_reject(int nr, int srcno) "reject irq %#x [src %d]"
>> +xics_ics_simple_eoi(int nr) "ics_eoi: irq %#x"
>>  xics_alloc(int irq) "irq %d"
>>  xics_alloc_block(int first, int num, bool lsi, int align) "first irq %d, %d irqs, lsi=%d, alignnum %d"
>>  xics_ics_free(int src, int irq, int num) "Source#%d, first irq %d, %d irqs"
>> diff --git a/hw/intc/xics.c b/hw/intc/xics.c
>> index c7901c4..b15751e 100644
>> --- a/hw/intc/xics.c
>> +++ b/hw/intc/xics.c
>> @@ -113,7 +113,7 @@ void xics_add_ics(XICSState *xics)
>>  {
>>      ICSState *ics;
>>  
>> -    ics = ICS(object_new(TYPE_ICS));
>> +    ics = ICS_SIMPLE(object_new(TYPE_ICS_SIMPLE));
>>      object_property_add_child(OBJECT(xics), "ics", OBJECT(ics), NULL);
>>      ics->xics = xics;
>>      QLIST_INSERT_HEAD(&xics->ics, ics, list);
>> @@ -224,9 +224,32 @@ static const TypeInfo xics_common_info = {
>>  #define XISR(ss)   (((ss)->xirr) & XISR_MASK)
>>  #define CPPR(ss)   (((ss)->xirr) >> 24)
>>  
>> -static void ics_reject(ICSState *ics, int nr);
>> -static void ics_resend(ICSState *ics, int server);
>> -static void ics_eoi(ICSState *ics, int nr);
>> +static void ics_reject(ICSState *ics, uint32_t nr)
>> +{
>> +    ICSStateClass *k = ICS_GET_CLASS(ics);
>
> Shouldn't that be ICS_BASE_GET_CLASS()

The class hierarchy is something like this:

ICS_BASE -> ICS_SIMPLE -> ICS_KVM

We have an instance init for ICS_SIMPLE where we set these pointers.

>> diff --git a/include/hw/ppc/xics.h b/include/hw/ppc/xics.h
>> index a7a1e54..2231f2a 100644
>> --- a/include/hw/ppc/xics.h
>> +++ b/include/hw/ppc/xics.h
>> @@ -119,22 +119,29 @@ struct ICPState {
>>      bool cap_irq_xics_enabled;
>>  };
>>  
>> -#define TYPE_ICS "ics"
>> -#define ICS(obj) OBJECT_CHECK(ICSState, (obj), TYPE_ICS)
>> +#define TYPE_ICS_BASE "ics-base"
>> +#define ICS_BASE(obj) OBJECT_CHECK(ICSState, (obj), TYPE_ICS_SIMPLE)
>
> #define ICS_BASE(obj) OBJECT_CHECK(ICSState, (obj), TYPE_ICS_BASE)

Yes, that is a bug. Will correct.

>
>> -#define TYPE_KVM_ICS "icskvm"
>> -#define KVM_ICS(obj) OBJECT_CHECK(ICSState, (obj), TYPE_KVM_ICS)
>> +/* Retain ics for sPAPR for migration from existing sPAPR guests */
>> +#define TYPE_ICS_SIMPLE "ics"
>> +#define ICS_SIMPLE(obj) OBJECT_CHECK(ICSState, (obj), TYPE_ICS_SIMPLE)
>> +
>> +#define TYPE_ICS_KVM "icskvm"
>> +#define ICS_KVM(obj) OBJECT_CHECK(ICSState, (obj), TYPE_ICS_KVM)
>>  
>>  #define ICS_CLASS(klass) \
>> -     OBJECT_CLASS_CHECK(ICSStateClass, (klass), TYPE_ICS)
>> +     OBJECT_CLASS_CHECK(ICSStateClass, (klass), TYPE_ICS_SIMPLE)
>>  #define ICS_GET_CLASS(obj) \
>> -     OBJECT_GET_CLASS(ICSStateClass, (obj), TYPE_ICS)
>> +     OBJECT_GET_CLASS(ICSStateClass, (obj), TYPE_ICS_SIMPLE)
>
> #define ICS_BASE_CLASS(klass) \
>      OBJECT_CLASS_CHECK(ICSStateClass, (klass), TYPE_ICS_BASE)
> #define ICS_BASE_GET_CLASS(obj) \
>      OBJECT_GET_CLASS(ICSStateClass, (obj), TYPE_ICS_BASE)

As explained above, not needed.

Regards
Nikunj

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [Qemu-ppc] [PATCH v4 6/9] ppc/xics: Split ICS into ics-base and ics class
  2016-09-20  6:02     ` Nikunj A Dadhania
@ 2016-09-20  6:20       ` Cédric Le Goater
  2016-09-20  6:29         ` Nikunj A Dadhania
  0 siblings, 1 reply; 38+ messages in thread
From: Cédric Le Goater @ 2016-09-20  6:20 UTC (permalink / raw)
  To: Nikunj A Dadhania, qemu-ppc, david; +Cc: qemu-devel

On 09/20/2016 08:02 AM, Nikunj A Dadhania wrote:
> Cédric Le Goater <clg@kaod.org> writes:
> 
>> On 09/19/2016 08:29 AM, Nikunj A Dadhania wrote:
>>> From: Benjamin Herrenschmidt <benh@kernel.crashing.org>
>>>
>>> The existing implementation remains same and ics-base is introduced. The
>>> type name "ics" is retained, and all the related functions renamed as
>>> ics_simple_*
>>>
>>> This will allow different implementations for the source controllers
>>> such as the MSI support of PHB3 on Power8 which uses in-memory state
>>> tables for example.
>>
>> A couple of issues below regarding the class helpers,
>>
>>> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
>>> Signed-off-by: Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>
>>> ---
>>>  hw/intc/trace-events  |  10 ++--
>>>  hw/intc/xics.c        | 143 +++++++++++++++++++++++++++++++-------------------
>>>  hw/intc/xics_kvm.c    |  10 ++--
>>>  hw/intc/xics_spapr.c  |  28 +++++-----
>>>  include/hw/ppc/xics.h |  23 +++++---
>>>  5 files changed, 131 insertions(+), 83 deletions(-)
>>>
>>> diff --git a/hw/intc/trace-events b/hw/intc/trace-events
>>> index aa342a8..a367b46 100644
>>> --- a/hw/intc/trace-events
>>> +++ b/hw/intc/trace-events
>>> @@ -50,12 +50,12 @@ xics_icp_accept(uint32_t old_xirr, uint32_t new_xirr) "icp_accept: XIRR %#"PRIx3
>>>  xics_icp_eoi(int server, uint32_t xirr, uint32_t new_xirr) "icp_eoi: server %d given XIRR %#"PRIx32" new XIRR %#"PRIx32
>>>  xics_icp_irq(int server, int nr, uint8_t priority) "cpu %d trying to deliver irq %#"PRIx32" priority %#x"
>>>  xics_icp_raise(uint32_t xirr, uint8_t pending_priority) "raising IRQ new XIRR=%#x new pending priority=%#x"
>>> -xics_set_irq_msi(int srcno, int nr) "set_irq_msi: srcno %d [irq %#x]"
>>> +xics_ics_simple_set_irq_msi(int srcno, int nr) "set_irq_msi: srcno %d [irq %#x]"
>>>  xics_masked_pending(void) "set_irq_msi: masked pending"
>>> -xics_set_irq_lsi(int srcno, int nr) "set_irq_lsi: srcno %d [irq %#x]"
>>> -xics_ics_write_xive(int nr, int srcno, int server, uint8_t priority) "ics_write_xive: irq %#x [src %d] server %#x prio %#x"
>>> -xics_ics_reject(int nr, int srcno) "reject irq %#x [src %d]"
>>> -xics_ics_eoi(int nr) "ics_eoi: irq %#x"
>>> +xics_ics_simple_set_irq_lsi(int srcno, int nr) "set_irq_lsi: srcno %d [irq %#x]"
>>> +xics_ics_simple_write_xive(int nr, int srcno, int server, uint8_t priority) "ics_write_xive: irq %#x [src %d] server %#x prio %#x"
>>> +xics_ics_simple_reject(int nr, int srcno) "reject irq %#x [src %d]"
>>> +xics_ics_simple_eoi(int nr) "ics_eoi: irq %#x"
>>>  xics_alloc(int irq) "irq %d"
>>>  xics_alloc_block(int first, int num, bool lsi, int align) "first irq %d, %d irqs, lsi=%d, alignnum %d"
>>>  xics_ics_free(int src, int irq, int num) "Source#%d, first irq %d, %d irqs"
>>> diff --git a/hw/intc/xics.c b/hw/intc/xics.c
>>> index c7901c4..b15751e 100644
>>> --- a/hw/intc/xics.c
>>> +++ b/hw/intc/xics.c
>>> @@ -113,7 +113,7 @@ void xics_add_ics(XICSState *xics)
>>>  {
>>>      ICSState *ics;
>>>  
>>> -    ics = ICS(object_new(TYPE_ICS));
>>> +    ics = ICS_SIMPLE(object_new(TYPE_ICS_SIMPLE));
>>>      object_property_add_child(OBJECT(xics), "ics", OBJECT(ics), NULL);
>>>      ics->xics = xics;
>>>      QLIST_INSERT_HEAD(&xics->ics, ics, list);
>>> @@ -224,9 +224,32 @@ static const TypeInfo xics_common_info = {
>>>  #define XISR(ss)   (((ss)->xirr) & XISR_MASK)
>>>  #define CPPR(ss)   (((ss)->xirr) >> 24)
>>>  
>>> -static void ics_reject(ICSState *ics, int nr);
>>> -static void ics_resend(ICSState *ics, int server);
>>> -static void ics_eoi(ICSState *ics, int nr);
>>> +static void ics_reject(ICSState *ics, uint32_t nr)
>>> +{
>>> +    ICSStateClass *k = ICS_GET_CLASS(ics);
>>
>> Shouldn't that be ICS_BASE_GET_CLASS()
> 
> The class hierarchy is something like this:
> 
> ICS_BASE -> ICS_SIMPLE -> ICS_KVM

yes. but if we called  ics_* with an instance of an ics class which is 
not a ICS_SIMPLE class that will break.

ICSStateClass is the baseclass, whenever we call methods on a ICSState* 
object, we should use the method defines in ICSStateClass.


> We have an instance init for ICS_SIMPLE where we set these pointers.
> 
>>> diff --git a/include/hw/ppc/xics.h b/include/hw/ppc/xics.h
>>> index a7a1e54..2231f2a 100644
>>> --- a/include/hw/ppc/xics.h
>>> +++ b/include/hw/ppc/xics.h
>>> @@ -119,22 +119,29 @@ struct ICPState {
>>>      bool cap_irq_xics_enabled;
>>>  };
>>>  
>>> -#define TYPE_ICS "ics"
>>> -#define ICS(obj) OBJECT_CHECK(ICSState, (obj), TYPE_ICS)
>>> +#define TYPE_ICS_BASE "ics-base"
>>> +#define ICS_BASE(obj) OBJECT_CHECK(ICSState, (obj), TYPE_ICS_SIMPLE)
>>
>> #define ICS_BASE(obj) OBJECT_CHECK(ICSState, (obj), TYPE_ICS_BASE)
> 
> Yes, that is a bug. Will correct.
> 
>>
>>> -#define TYPE_KVM_ICS "icskvm"
>>> -#define KVM_ICS(obj) OBJECT_CHECK(ICSState, (obj), TYPE_KVM_ICS)
>>> +/* Retain ics for sPAPR for migration from existing sPAPR guests */
>>> +#define TYPE_ICS_SIMPLE "ics"
>>> +#define ICS_SIMPLE(obj) OBJECT_CHECK(ICSState, (obj), TYPE_ICS_SIMPLE)
>>> +
>>> +#define TYPE_ICS_KVM "icskvm"
>>> +#define ICS_KVM(obj) OBJECT_CHECK(ICSState, (obj), TYPE_ICS_KVM)
>>>  
>>>  #define ICS_CLASS(klass) \
>>> -     OBJECT_CLASS_CHECK(ICSStateClass, (klass), TYPE_ICS)
>>> +     OBJECT_CLASS_CHECK(ICSStateClass, (klass), TYPE_ICS_SIMPLE)
>>>  #define ICS_GET_CLASS(obj) \
>>> -     OBJECT_GET_CLASS(ICSStateClass, (obj), TYPE_ICS)
>>> +     OBJECT_GET_CLASS(ICSStateClass, (obj), TYPE_ICS_SIMPLE)
>>
>> #define ICS_BASE_CLASS(klass) \
>>      OBJECT_CLASS_CHECK(ICSStateClass, (klass), TYPE_ICS_BASE)
>> #define ICS_BASE_GET_CLASS(obj) \
>>      OBJECT_GET_CLASS(ICSStateClass, (obj), TYPE_ICS_BASE)
> 
> As explained above, not needed.

We will with powernv which defines a new ics type for the phb3 msis.

Thanks,

C.

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [Qemu-ppc] [PATCH v4 6/9] ppc/xics: Split ICS into ics-base and ics class
  2016-09-20  6:20       ` Cédric Le Goater
@ 2016-09-20  6:29         ` Nikunj A Dadhania
  2016-09-20  7:13           ` Cédric Le Goater
  0 siblings, 1 reply; 38+ messages in thread
From: Nikunj A Dadhania @ 2016-09-20  6:29 UTC (permalink / raw)
  To: Cédric Le Goater, qemu-ppc, david; +Cc: qemu-devel

Cédric Le Goater <clg@kaod.org> writes:

> On 09/20/2016 08:02 AM, Nikunj A Dadhania wrote:
>> Cédric Le Goater <clg@kaod.org> writes:
>> 
>>> On 09/19/2016 08:29 AM, Nikunj A Dadhania wrote:
>>>> From: Benjamin Herrenschmidt <benh@kernel.crashing.org>
>>>>
>>>> The existing implementation remains same and ics-base is introduced. The
>>>> type name "ics" is retained, and all the related functions renamed as
>>>> ics_simple_*
>>>>
>>>> This will allow different implementations for the source controllers
>>>> such as the MSI support of PHB3 on Power8 which uses in-memory state
>>>> tables for example.
>>>
>>> A couple of issues below regarding the class helpers,
>>>
>>>> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
>>>> Signed-off-by: Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>
>>>> ---
>>>>  hw/intc/trace-events  |  10 ++--
>>>>  hw/intc/xics.c        | 143 +++++++++++++++++++++++++++++++-------------------
>>>>  hw/intc/xics_kvm.c    |  10 ++--
>>>>  hw/intc/xics_spapr.c  |  28 +++++-----
>>>>  include/hw/ppc/xics.h |  23 +++++---
>>>>  5 files changed, 131 insertions(+), 83 deletions(-)
>>>>
>>>> diff --git a/hw/intc/trace-events b/hw/intc/trace-events
>>>> index aa342a8..a367b46 100644
>>>> --- a/hw/intc/trace-events
>>>> +++ b/hw/intc/trace-events
>>>> @@ -50,12 +50,12 @@ xics_icp_accept(uint32_t old_xirr, uint32_t new_xirr) "icp_accept: XIRR %#"PRIx3
>>>>  xics_icp_eoi(int server, uint32_t xirr, uint32_t new_xirr) "icp_eoi: server %d given XIRR %#"PRIx32" new XIRR %#"PRIx32
>>>>  xics_icp_irq(int server, int nr, uint8_t priority) "cpu %d trying to deliver irq %#"PRIx32" priority %#x"
>>>>  xics_icp_raise(uint32_t xirr, uint8_t pending_priority) "raising IRQ new XIRR=%#x new pending priority=%#x"
>>>> -xics_set_irq_msi(int srcno, int nr) "set_irq_msi: srcno %d [irq %#x]"
>>>> +xics_ics_simple_set_irq_msi(int srcno, int nr) "set_irq_msi: srcno %d [irq %#x]"
>>>>  xics_masked_pending(void) "set_irq_msi: masked pending"
>>>> -xics_set_irq_lsi(int srcno, int nr) "set_irq_lsi: srcno %d [irq %#x]"
>>>> -xics_ics_write_xive(int nr, int srcno, int server, uint8_t priority) "ics_write_xive: irq %#x [src %d] server %#x prio %#x"
>>>> -xics_ics_reject(int nr, int srcno) "reject irq %#x [src %d]"
>>>> -xics_ics_eoi(int nr) "ics_eoi: irq %#x"
>>>> +xics_ics_simple_set_irq_lsi(int srcno, int nr) "set_irq_lsi: srcno %d [irq %#x]"
>>>> +xics_ics_simple_write_xive(int nr, int srcno, int server, uint8_t priority) "ics_write_xive: irq %#x [src %d] server %#x prio %#x"
>>>> +xics_ics_simple_reject(int nr, int srcno) "reject irq %#x [src %d]"
>>>> +xics_ics_simple_eoi(int nr) "ics_eoi: irq %#x"
>>>>  xics_alloc(int irq) "irq %d"
>>>>  xics_alloc_block(int first, int num, bool lsi, int align) "first irq %d, %d irqs, lsi=%d, alignnum %d"
>>>>  xics_ics_free(int src, int irq, int num) "Source#%d, first irq %d, %d irqs"
>>>> diff --git a/hw/intc/xics.c b/hw/intc/xics.c
>>>> index c7901c4..b15751e 100644
>>>> --- a/hw/intc/xics.c
>>>> +++ b/hw/intc/xics.c
>>>> @@ -113,7 +113,7 @@ void xics_add_ics(XICSState *xics)
>>>>  {
>>>>      ICSState *ics;
>>>>  
>>>> -    ics = ICS(object_new(TYPE_ICS));
>>>> +    ics = ICS_SIMPLE(object_new(TYPE_ICS_SIMPLE));
>>>>      object_property_add_child(OBJECT(xics), "ics", OBJECT(ics), NULL);
>>>>      ics->xics = xics;
>>>>      QLIST_INSERT_HEAD(&xics->ics, ics, list);
>>>> @@ -224,9 +224,32 @@ static const TypeInfo xics_common_info = {
>>>>  #define XISR(ss)   (((ss)->xirr) & XISR_MASK)
>>>>  #define CPPR(ss)   (((ss)->xirr) >> 24)
>>>>  
>>>> -static void ics_reject(ICSState *ics, int nr);
>>>> -static void ics_resend(ICSState *ics, int server);
>>>> -static void ics_eoi(ICSState *ics, int nr);
>>>> +static void ics_reject(ICSState *ics, uint32_t nr)
>>>> +{
>>>> +    ICSStateClass *k = ICS_GET_CLASS(ics);
>>>
>>> Shouldn't that be ICS_BASE_GET_CLASS()
>> 
>> The class hierarchy is something like this:
>> 
>> ICS_BASE -> ICS_SIMPLE -> ICS_KVM
>
> yes. but if we called  ics_* with an instance of an ics class which is 
> not a ICS_SIMPLE class that will break.

Correct

> ICSStateClass is the baseclass, whenever we call methods on a ICSState* 
> object, we should use the method defines in ICSStateClass.

Hmm, in that case I need to initialize base class methods in
instance_init of ics_simple

>> We have an instance init for ICS_SIMPLE where we set these pointers.
>> 
>>>> diff --git a/include/hw/ppc/xics.h b/include/hw/ppc/xics.h
>>>> index a7a1e54..2231f2a 100644
>>>> --- a/include/hw/ppc/xics.h
>>>> +++ b/include/hw/ppc/xics.h
>>>> @@ -119,22 +119,29 @@ struct ICPState {
>>>>      bool cap_irq_xics_enabled;
>>>>  };
>>>>  
>>>> -#define TYPE_ICS "ics"
>>>> -#define ICS(obj) OBJECT_CHECK(ICSState, (obj), TYPE_ICS)
>>>> +#define TYPE_ICS_BASE "ics-base"
>>>> +#define ICS_BASE(obj) OBJECT_CHECK(ICSState, (obj), TYPE_ICS_SIMPLE)
>>>
>>> #define ICS_BASE(obj) OBJECT_CHECK(ICSState, (obj), TYPE_ICS_BASE)
>> 
>> Yes, that is a bug. Will correct.
>> 
>>>
>>>> -#define TYPE_KVM_ICS "icskvm"
>>>> -#define KVM_ICS(obj) OBJECT_CHECK(ICSState, (obj), TYPE_KVM_ICS)
>>>> +/* Retain ics for sPAPR for migration from existing sPAPR guests */
>>>> +#define TYPE_ICS_SIMPLE "ics"
>>>> +#define ICS_SIMPLE(obj) OBJECT_CHECK(ICSState, (obj), TYPE_ICS_SIMPLE)
>>>> +
>>>> +#define TYPE_ICS_KVM "icskvm"
>>>> +#define ICS_KVM(obj) OBJECT_CHECK(ICSState, (obj), TYPE_ICS_KVM)
>>>>  
>>>>  #define ICS_CLASS(klass) \
>>>> -     OBJECT_CLASS_CHECK(ICSStateClass, (klass), TYPE_ICS)
>>>> +     OBJECT_CLASS_CHECK(ICSStateClass, (klass), TYPE_ICS_SIMPLE)
>>>>  #define ICS_GET_CLASS(obj) \
>>>> -     OBJECT_GET_CLASS(ICSStateClass, (obj), TYPE_ICS)
>>>> +     OBJECT_GET_CLASS(ICSStateClass, (obj), TYPE_ICS_SIMPLE)
>>>
>>> #define ICS_BASE_CLASS(klass) \
>>>      OBJECT_CLASS_CHECK(ICSStateClass, (klass), TYPE_ICS_BASE)
>>> #define ICS_BASE_GET_CLASS(obj) \
>>>      OBJECT_GET_CLASS(ICSStateClass, (obj), TYPE_ICS_BASE)
>> 
>> As explained above, not needed.
>
> We will with powernv which defines a new ics type for the phb3 msis.

Right, will change it.

Regards
Nikunj

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [Qemu-ppc] [PATCH v4 6/9] ppc/xics: Split ICS into ics-base and ics class
  2016-09-20  6:29         ` Nikunj A Dadhania
@ 2016-09-20  7:13           ` Cédric Le Goater
  2016-09-20  8:10             ` Nikunj A Dadhania
  0 siblings, 1 reply; 38+ messages in thread
From: Cédric Le Goater @ 2016-09-20  7:13 UTC (permalink / raw)
  To: Nikunj A Dadhania, qemu-ppc, david; +Cc: qemu-devel

On 09/20/2016 08:29 AM, Nikunj A Dadhania wrote:
> Cédric Le Goater <clg@kaod.org> writes:
> 
>> On 09/20/2016 08:02 AM, Nikunj A Dadhania wrote:
>>> Cédric Le Goater <clg@kaod.org> writes:
>>>
>>>> On 09/19/2016 08:29 AM, Nikunj A Dadhania wrote:
>>>>> From: Benjamin Herrenschmidt <benh@kernel.crashing.org>
>>>>>
>>>>> The existing implementation remains same and ics-base is introduced. The
>>>>> type name "ics" is retained, and all the related functions renamed as
>>>>> ics_simple_*
>>>>>
>>>>> This will allow different implementations for the source controllers
>>>>> such as the MSI support of PHB3 on Power8 which uses in-memory state
>>>>> tables for example.
>>>>
>>>> A couple of issues below regarding the class helpers,
>>>>
>>>>> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
>>>>> Signed-off-by: Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>
>>>>> ---
>>>>>  hw/intc/trace-events  |  10 ++--
>>>>>  hw/intc/xics.c        | 143 +++++++++++++++++++++++++++++++-------------------
>>>>>  hw/intc/xics_kvm.c    |  10 ++--
>>>>>  hw/intc/xics_spapr.c  |  28 +++++-----
>>>>>  include/hw/ppc/xics.h |  23 +++++---
>>>>>  5 files changed, 131 insertions(+), 83 deletions(-)

>>>>> @@ -224,9 +224,32 @@ static const TypeInfo xics_common_info = {
>>>>>  #define XISR(ss)   (((ss)->xirr) & XISR_MASK)
>>>>>  #define CPPR(ss)   (((ss)->xirr) >> 24)
>>>>>  
>>>>> -static void ics_reject(ICSState *ics, int nr);
>>>>> -static void ics_resend(ICSState *ics, int server);
>>>>> -static void ics_eoi(ICSState *ics, int nr);
>>>>> +static void ics_reject(ICSState *ics, uint32_t nr)
>>>>> +{
>>>>> +    ICSStateClass *k = ICS_GET_CLASS(ics);
>>>>
>>>> Shouldn't that be ICS_BASE_GET_CLASS()
>>>
>>> The class hierarchy is something like this:
>>>
>>> ICS_BASE -> ICS_SIMPLE -> ICS_KVM
>>
>> yes. but if we called  ics_* with an instance of an ics class which is 
>> not a ICS_SIMPLE class that will break.
> 
> Correct
> 
>> ICSStateClass is the baseclass, whenever we call methods on a ICSState* 
>> object, we should use the method defines in ICSStateClass.
> 
> Hmm, in that case I need to initialize base class methods in
> instance_init of ics_simple

yes but this is done, no ? I see : 

static void ics_simple_class_init(ObjectClass *klass, void *data)
{
    DeviceClass *dc = DEVICE_CLASS(klass);
    ICSStateClass *isc = ICS_BASE_CLASS(klass);

    dc->realize = ics_simple_realize;
    dc->vmsd = &vmstate_ics_simple;
    dc->reset = ics_simple_reset;
    isc->post_load = ics_simple_post_load;
    isc->reject = ics_simple_reject;
    isc->resend = ics_simple_resend;
    isc->eoi = ics_simple_eoi;
}

Thanks,

C. 

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [Qemu-ppc] [PATCH v4 6/9] ppc/xics: Split ICS into ics-base and ics class
  2016-09-20  7:13           ` Cédric Le Goater
@ 2016-09-20  8:10             ` Nikunj A Dadhania
  2016-09-20  9:06               ` Cédric Le Goater
  0 siblings, 1 reply; 38+ messages in thread
From: Nikunj A Dadhania @ 2016-09-20  8:10 UTC (permalink / raw)
  To: Cédric Le Goater, qemu-ppc, david; +Cc: qemu-devel

Cédric Le Goater <clg@kaod.org> writes:

> On 09/20/2016 08:29 AM, Nikunj A Dadhania wrote:
>> Cédric Le Goater <clg@kaod.org> writes:
>> 
>>> On 09/20/2016 08:02 AM, Nikunj A Dadhania wrote:
>>>> Cédric Le Goater <clg@kaod.org> writes:
>>>>
>>>>> On 09/19/2016 08:29 AM, Nikunj A Dadhania wrote:
>>>>>> From: Benjamin Herrenschmidt <benh@kernel.crashing.org>
>>>>>>
>>>>>> The existing implementation remains same and ics-base is introduced. The
>>>>>> type name "ics" is retained, and all the related functions renamed as
>>>>>> ics_simple_*
>>>>>>
>>>>>> This will allow different implementations for the source controllers
>>>>>> such as the MSI support of PHB3 on Power8 which uses in-memory state
>>>>>> tables for example.
>>>>>
>>>>> A couple of issues below regarding the class helpers,
>>>>>
>>>>>> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
>>>>>> Signed-off-by: Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>
>>>>>> ---
>>>>>>  hw/intc/trace-events  |  10 ++--
>>>>>>  hw/intc/xics.c        | 143 +++++++++++++++++++++++++++++++-------------------
>>>>>>  hw/intc/xics_kvm.c    |  10 ++--
>>>>>>  hw/intc/xics_spapr.c  |  28 +++++-----
>>>>>>  include/hw/ppc/xics.h |  23 +++++---
>>>>>>  5 files changed, 131 insertions(+), 83 deletions(-)
>
>>>>>> @@ -224,9 +224,32 @@ static const TypeInfo xics_common_info = {
>>>>>>  #define XISR(ss)   (((ss)->xirr) & XISR_MASK)
>>>>>>  #define CPPR(ss)   (((ss)->xirr) >> 24)
>>>>>>  
>>>>>> -static void ics_reject(ICSState *ics, int nr);
>>>>>> -static void ics_resend(ICSState *ics, int server);
>>>>>> -static void ics_eoi(ICSState *ics, int nr);
>>>>>> +static void ics_reject(ICSState *ics, uint32_t nr)
>>>>>> +{
>>>>>> +    ICSStateClass *k = ICS_GET_CLASS(ics);
>>>>>
>>>>> Shouldn't that be ICS_BASE_GET_CLASS()
>>>>
>>>> The class hierarchy is something like this:
>>>>
>>>> ICS_BASE -> ICS_SIMPLE -> ICS_KVM
>>>
>>> yes. but if we called  ics_* with an instance of an ics class which is 
>>> not a ICS_SIMPLE class that will break.
>> 
>> Correct
>> 
>>> ICSStateClass is the baseclass, whenever we call methods on a ICSState* 
>>> object, we should use the method defines in ICSStateClass.
>> 
>> Hmm, in that case I need to initialize base class methods in
>> instance_init of ics_simple
>
> yes but this is done, no ? I see : 
>
> static void ics_simple_class_init(ObjectClass *klass, void *data)
> {
>     DeviceClass *dc = DEVICE_CLASS(klass);
>     ICSStateClass *isc = ICS_BASE_CLASS(klass);

Right.

Currently, we have this:

+    ICSStateClass *isc = ICS_CLASS(klass);

>
>     dc->realize = ics_simple_realize;
>     dc->vmsd = &vmstate_ics_simple;
>     dc->reset = ics_simple_reset;
>     isc->post_load = ics_simple_post_load;
>     isc->reject = ics_simple_reject;
>     isc->resend = ics_simple_resend;
>     isc->eoi = ics_simple_eoi;

Regards
Nikunj

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [Qemu-ppc] [PATCH v4 6/9] ppc/xics: Split ICS into ics-base and ics class
  2016-09-20  8:10             ` Nikunj A Dadhania
@ 2016-09-20  9:06               ` Cédric Le Goater
  2016-09-20  9:41                 ` Nikunj A Dadhania
  0 siblings, 1 reply; 38+ messages in thread
From: Cédric Le Goater @ 2016-09-20  9:06 UTC (permalink / raw)
  To: Nikunj A Dadhania, qemu-ppc, david; +Cc: qemu-devel

On 09/20/2016 10:10 AM, Nikunj A Dadhania wrote:
> Cédric Le Goater <clg@kaod.org> writes:
> 
>> On 09/20/2016 08:29 AM, Nikunj A Dadhania wrote:
>>> Cédric Le Goater <clg@kaod.org> writes:
>>>
>>>> On 09/20/2016 08:02 AM, Nikunj A Dadhania wrote:
>>>>> Cédric Le Goater <clg@kaod.org> writes:
>>>>>
>>>>>> On 09/19/2016 08:29 AM, Nikunj A Dadhania wrote:
>>>>>>> From: Benjamin Herrenschmidt <benh@kernel.crashing.org>
>>>>>>>
>>>>>>> The existing implementation remains same and ics-base is introduced. The
>>>>>>> type name "ics" is retained, and all the related functions renamed as
>>>>>>> ics_simple_*
>>>>>>>
>>>>>>> This will allow different implementations for the source controllers
>>>>>>> such as the MSI support of PHB3 on Power8 which uses in-memory state
>>>>>>> tables for example.
>>>>>>
>>>>>> A couple of issues below regarding the class helpers,
>>>>>>
>>>>>>> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
>>>>>>> Signed-off-by: Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>
>>>>>>> ---
>>>>>>>  hw/intc/trace-events  |  10 ++--
>>>>>>>  hw/intc/xics.c        | 143 +++++++++++++++++++++++++++++++-------------------
>>>>>>>  hw/intc/xics_kvm.c    |  10 ++--
>>>>>>>  hw/intc/xics_spapr.c  |  28 +++++-----
>>>>>>>  include/hw/ppc/xics.h |  23 +++++---
>>>>>>>  5 files changed, 131 insertions(+), 83 deletions(-)
>>
>>>>>>> @@ -224,9 +224,32 @@ static const TypeInfo xics_common_info = {
>>>>>>>  #define XISR(ss)   (((ss)->xirr) & XISR_MASK)
>>>>>>>  #define CPPR(ss)   (((ss)->xirr) >> 24)
>>>>>>>  
>>>>>>> -static void ics_reject(ICSState *ics, int nr);
>>>>>>> -static void ics_resend(ICSState *ics, int server);
>>>>>>> -static void ics_eoi(ICSState *ics, int nr);
>>>>>>> +static void ics_reject(ICSState *ics, uint32_t nr)
>>>>>>> +{
>>>>>>> +    ICSStateClass *k = ICS_GET_CLASS(ics);
>>>>>>
>>>>>> Shouldn't that be ICS_BASE_GET_CLASS()
>>>>>
>>>>> The class hierarchy is something like this:
>>>>>
>>>>> ICS_BASE -> ICS_SIMPLE -> ICS_KVM
>>>>
>>>> yes. but if we called  ics_* with an instance of an ics class which is 
>>>> not a ICS_SIMPLE class that will break.
>>>
>>> Correct
>>>
>>>> ICSStateClass is the baseclass, whenever we call methods on a ICSState* 
>>>> object, we should use the method defines in ICSStateClass.
>>>
>>> Hmm, in that case I need to initialize base class methods in
>>> instance_init of ics_simple
>>
>> yes but this is done, no ? I see : 
>>
>> static void ics_simple_class_init(ObjectClass *klass, void *data)
>> {
>>     DeviceClass *dc = DEVICE_CLASS(klass);
>>     ICSStateClass *isc = ICS_BASE_CLASS(klass);
> 
> Right.
> 
> Currently, we have this:
> 
> +    ICSStateClass *isc = ICS_CLASS(klass);

oh yes and same in the kvm ICS. The name are bit confusing as we are 
introducing SIMPLE but not the associated macros.

You can check on my 2.8 github branch, I got something working there :

	https://github.com/legoater/qemu/commit/d0b492707debc7192f0860e2c5fc2daa9fd453ac

Thanks,

C.

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [Qemu-ppc] [PATCH v4 6/9] ppc/xics: Split ICS into ics-base and ics class
  2016-09-20  9:06               ` Cédric Le Goater
@ 2016-09-20  9:41                 ` Nikunj A Dadhania
  2016-09-20  9:52                   ` Cédric Le Goater
  0 siblings, 1 reply; 38+ messages in thread
From: Nikunj A Dadhania @ 2016-09-20  9:41 UTC (permalink / raw)
  To: Cédric Le Goater, qemu-ppc, david; +Cc: qemu-devel

Cédric Le Goater <clg@kaod.org> writes:
> On 09/20/2016 10:10 AM, Nikunj A Dadhania wrote:
>>>>>>>> -static void ics_reject(ICSState *ics, int nr);
>>>>>>>> -static void ics_resend(ICSState *ics, int server);
>>>>>>>> -static void ics_eoi(ICSState *ics, int nr);
>>>>>>>> +static void ics_reject(ICSState *ics, uint32_t nr)
>>>>>>>> +{
>>>>>>>> +    ICSStateClass *k = ICS_GET_CLASS(ics);
>>>>>>>
>>>>>>> Shouldn't that be ICS_BASE_GET_CLASS()
>>>>>>
>>>>>> The class hierarchy is something like this:
>>>>>>
>>>>>> ICS_BASE -> ICS_SIMPLE -> ICS_KVM
>>>>>
>>>>> yes. but if we called  ics_* with an instance of an ics class which is 
>>>>> not a ICS_SIMPLE class that will break.
>>>>
>>>> Correct
>>>>
>>>>> ICSStateClass is the baseclass, whenever we call methods on a ICSState* 
>>>>> object, we should use the method defines in ICSStateClass.
>>>>
>>>> Hmm, in that case I need to initialize base class methods in
>>>> instance_init of ics_simple
>>>
>>> yes but this is done, no ? I see : 
>>>
>>> static void ics_simple_class_init(ObjectClass *klass, void *data)
>>> {
>>>     DeviceClass *dc = DEVICE_CLASS(klass);
>>>     ICSStateClass *isc = ICS_BASE_CLASS(klass);
>> 
>> Right.
>> 
>> Currently, we have this:
>> 
>> +    ICSStateClass *isc = ICS_CLASS(klass);
>
> oh yes and same in the kvm ICS. The name are bit confusing as we are 
> introducing SIMPLE but not the associated macros.
>
> You can check on my 2.8 github branch, I got something working there :
>
> 	https://github.com/legoater/qemu/commit/d0b492707debc7192f0860e2c5fc2daa9fd453ac

Cool. :-)

Thanks for testing.

Regards,
Nikunj

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [Qemu-ppc] [PATCH v4 6/9] ppc/xics: Split ICS into ics-base and ics class
  2016-09-20  9:41                 ` Nikunj A Dadhania
@ 2016-09-20  9:52                   ` Cédric Le Goater
  2016-09-20 10:03                     ` Nikunj A Dadhania
  0 siblings, 1 reply; 38+ messages in thread
From: Cédric Le Goater @ 2016-09-20  9:52 UTC (permalink / raw)
  To: Nikunj A Dadhania, qemu-ppc, david; +Cc: qemu-devel

On 09/20/2016 11:41 AM, Nikunj A Dadhania wrote:
> Cédric Le Goater <clg@kaod.org> writes:
>> On 09/20/2016 10:10 AM, Nikunj A Dadhania wrote:
>>>>>>>>> -static void ics_reject(ICSState *ics, int nr);
>>>>>>>>> -static void ics_resend(ICSState *ics, int server);
>>>>>>>>> -static void ics_eoi(ICSState *ics, int nr);
>>>>>>>>> +static void ics_reject(ICSState *ics, uint32_t nr)
>>>>>>>>> +{
>>>>>>>>> +    ICSStateClass *k = ICS_GET_CLASS(ics);
>>>>>>>>
>>>>>>>> Shouldn't that be ICS_BASE_GET_CLASS()
>>>>>>>
>>>>>>> The class hierarchy is something like this:
>>>>>>>
>>>>>>> ICS_BASE -> ICS_SIMPLE -> ICS_KVM
>>>>>>
>>>>>> yes. but if we called  ics_* with an instance of an ics class which is 
>>>>>> not a ICS_SIMPLE class that will break.
>>>>>
>>>>> Correct
>>>>>
>>>>>> ICSStateClass is the baseclass, whenever we call methods on a ICSState* 
>>>>>> object, we should use the method defines in ICSStateClass.
>>>>>
>>>>> Hmm, in that case I need to initialize base class methods in
>>>>> instance_init of ics_simple
>>>>
>>>> yes but this is done, no ? I see : 
>>>>
>>>> static void ics_simple_class_init(ObjectClass *klass, void *data)
>>>> {
>>>>     DeviceClass *dc = DEVICE_CLASS(klass);
>>>>     ICSStateClass *isc = ICS_BASE_CLASS(klass);
>>>
>>> Right.
>>>
>>> Currently, we have this:
>>>
>>> +    ICSStateClass *isc = ICS_CLASS(klass);
>>
>> oh yes and same in the kvm ICS. The name are bit confusing as we are 
>> introducing SIMPLE but not the associated macros.
>>
>> You can check on my 2.8 github branch, I got something working there :
>>
>> 	https://github.com/legoater/qemu/commit/d0b492707debc7192f0860e2c5fc2daa9fd453ac
> 
> Cool. :-)
> 
> Thanks for testing.

I did some tests for pnv, pseries tcg and kvm. 

It didn't see any migration issues, yet. Do you have some scenario 
to reproduce the fix you are trying to add ? That's under tcg with
a e1000 ? 

Thanks,

C.   

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [Qemu-ppc] [PATCH v4 6/9] ppc/xics: Split ICS into ics-base and ics class
  2016-09-20  9:52                   ` Cédric Le Goater
@ 2016-09-20 10:03                     ` Nikunj A Dadhania
  0 siblings, 0 replies; 38+ messages in thread
From: Nikunj A Dadhania @ 2016-09-20 10:03 UTC (permalink / raw)
  To: Cédric Le Goater, qemu-ppc, david; +Cc: qemu-devel

Cédric Le Goater <clg@kaod.org> writes:

> On 09/20/2016 11:41 AM, Nikunj A Dadhania wrote:
>> Cédric Le Goater <clg@kaod.org> writes:
>>> On 09/20/2016 10:10 AM, Nikunj A Dadhania wrote:
>>>>>>>>>> -static void ics_reject(ICSState *ics, int nr);
>>>>>>>>>> -static void ics_resend(ICSState *ics, int server);
>>>>>>>>>> -static void ics_eoi(ICSState *ics, int nr);
>>>>>>>>>> +static void ics_reject(ICSState *ics, uint32_t nr)
>>>>>>>>>> +{
>>>>>>>>>> +    ICSStateClass *k = ICS_GET_CLASS(ics);
>>>>>>>>>
>>>>>>>>> Shouldn't that be ICS_BASE_GET_CLASS()
>>>>>>>>
>>>>>>>> The class hierarchy is something like this:
>>>>>>>>
>>>>>>>> ICS_BASE -> ICS_SIMPLE -> ICS_KVM
>>>>>>>
>>>>>>> yes. but if we called  ics_* with an instance of an ics class which is 
>>>>>>> not a ICS_SIMPLE class that will break.
>>>>>>
>>>>>> Correct
>>>>>>
>>>>>>> ICSStateClass is the baseclass, whenever we call methods on a ICSState* 
>>>>>>> object, we should use the method defines in ICSStateClass.
>>>>>>
>>>>>> Hmm, in that case I need to initialize base class methods in
>>>>>> instance_init of ics_simple
>>>>>
>>>>> yes but this is done, no ? I see : 
>>>>>
>>>>> static void ics_simple_class_init(ObjectClass *klass, void *data)
>>>>> {
>>>>>     DeviceClass *dc = DEVICE_CLASS(klass);
>>>>>     ICSStateClass *isc = ICS_BASE_CLASS(klass);
>>>>
>>>> Right.
>>>>
>>>> Currently, we have this:
>>>>
>>>> +    ICSStateClass *isc = ICS_CLASS(klass);
>>>
>>> oh yes and same in the kvm ICS. The name are bit confusing as we are 
>>> introducing SIMPLE but not the associated macros.
>>>
>>> You can check on my 2.8 github branch, I got something working there :
>>>
>>> 	https://github.com/legoater/qemu/commit/d0b492707debc7192f0860e2c5fc2daa9fd453ac
>> 
>> Cool. :-)
>> 
>> Thanks for testing.
>
> I did some tests for pnv, pseries tcg and kvm. 
>
> It didn't see any migration issues, yet. Do you have some scenario 
> to reproduce the fix you are trying to add ? That's under tcg with
> a e1000 ? 

Oh that is pretty complex:

Here is how I was reproducing the issue, it does not reproduce always,
but at least 1 in 3 times, and sometimes when lucky 3 in 3 times as well.

* Start a guest with single cpu, kernel-irqchip=off, e1000 card
* From the guest start a flood ping (ssh to guest)
* From the guest console trigger xmon
* Migrate to the target (localhost)
* Once the vm migrates to the target, exit xmon
* In success case, i get the console, and the flood ping continues
* In case of failure, console does not respond and within few seconds I
  get a crash

Regards,
Nikunj

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [PATCH v4 1/9] ppc/xics: account correct irq status
  2016-09-19  6:29 ` [Qemu-devel] [PATCH v4 1/9] ppc/xics: account correct irq status Nikunj A Dadhania
@ 2016-09-21  6:39   ` David Gibson
  0 siblings, 0 replies; 38+ messages in thread
From: David Gibson @ 2016-09-21  6:39 UTC (permalink / raw)
  To: Nikunj A Dadhania; +Cc: qemu-ppc, qemu-devel, benh, clg

[-- Attachment #1: Type: text/plain, Size: 1570 bytes --]

On Mon, Sep 19, 2016 at 11:59:29AM +0530, Nikunj A Dadhania wrote:
> Fix inconsistent irq status, because of this in the trace logs, for e.g.
> LSI status was 0x7, i.e. XICS_STATUS_ASSERTED, XICS_STATUS_SENT and
> XICS_STATUS_REJECTED all set, which did not make sense. So the REJECTED
> would have been set in earlier interrupt cycle, and then asserted and
> sent in this current one.
> 
> Signed-off-by: Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>

It looks like this patch stands on its own, so I've applied it to ppc-for-2.8.

> ---
>  hw/intc/xics.c | 7 +++++--
>  1 file changed, 5 insertions(+), 2 deletions(-)
> 
> diff --git a/hw/intc/xics.c b/hw/intc/xics.c
> index cd48f42..69162f0 100644
> --- a/hw/intc/xics.c
> +++ b/hw/intc/xics.c
> @@ -505,8 +505,11 @@ static void ics_reject(ICSState *ics, int nr)
>      ICSIRQState *irq = ics->irqs + nr - ics->offset;
>  
>      trace_xics_ics_reject(nr, nr - ics->offset);
> -    irq->status |= XICS_STATUS_REJECTED; /* Irrelevant but harmless for LSI */
> -    irq->status &= ~XICS_STATUS_SENT; /* Irrelevant but harmless for MSI */
> +    if (irq->flags & XICS_FLAGS_IRQ_MSI) {
> +        irq->status |= XICS_STATUS_REJECTED;
> +    } else if (irq->flags & XICS_FLAGS_IRQ_LSI) {
> +        irq->status &= ~XICS_STATUS_SENT;
> +    }
>  }
>  
>  static void ics_resend(ICSState *ics)

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [PATCH v4 2/9] ppc/xics: Fix migration failure with kernel-irqchip=off
  2016-09-19  6:29 ` [Qemu-devel] [PATCH v4 2/9] ppc/xics: Fix migration failure with kernel-irqchip=off Nikunj A Dadhania
@ 2016-09-21  7:21   ` David Gibson
  0 siblings, 0 replies; 38+ messages in thread
From: David Gibson @ 2016-09-21  7:21 UTC (permalink / raw)
  To: Nikunj A Dadhania; +Cc: qemu-ppc, qemu-devel, benh, clg

[-- Attachment #1: Type: text/plain, Size: 3436 bytes --]

On Mon, Sep 19, 2016 at 11:59:30AM +0530, Nikunj A Dadhania wrote:
> With a single cpu VM running with kernel-irqchip=off and a flood ping
> running in the guest. Migration fails once in few times.
> 
> Found that whenever there is an interrupt (in this case lsi int 3 from
> e1000), we raise an interrupt using qemu_irq_pulse() and also see that
> the kvm ioctl is complete.

Uh.. for an lsi qemu_irq_pulse() should not ever be used - that should
only be used for edge or message interrupts.

> 67351@1468011062.810020:xics_set_irq_lsi set_irq_lsi: srcno 3 [irq 0x1003]
> 67351@1468011062.810031:xics_icp_irq cpu 0 trying to deliver irq 0x1003 priority 0x5
> 67351@1468011062.810038:xics_icp_raise raising IRQ new XIRR=0xff001003
> new pending priority=0x5
> 
> After migration on the target side, interrupts(prio 0x5) are rejected as
> there is a interrupt pending (pending_priority 0x5). Moreover, we never
> get an icp_accept from the guest, so it hangs and crashes.

Sorry, I'm still having a lot of trouble following this description of
what's happening.

> Basically, resend the irq pulse(lsi) to the guest.
> 
> Signed-off-by: Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>
> ---
>  hw/intc/xics.c | 19 +++++++++++++++----
>  1 file changed, 15 insertions(+), 4 deletions(-)
> 
> diff --git a/hw/intc/xics.c b/hw/intc/xics.c
> index 69162f0..f765b08 100644
> --- a/hw/intc/xics.c
> +++ b/hw/intc/xics.c
> @@ -209,7 +209,7 @@ static const TypeInfo xics_common_info = {
>  #define CPPR(ss)   (((ss)->xirr) >> 24)
>  
>  static void ics_reject(ICSState *ics, int nr);
> -static void ics_resend(ICSState *ics);
> +static void ics_resend(ICSState *ics, int server);
>  static void ics_eoi(ICSState *ics, int nr);
>  
>  static void icp_check_ipi(XICSState *xics, int server)
> @@ -238,7 +238,7 @@ static void icp_resend(XICSState *xics, int server)
>      if (ss->mfrr < CPPR(ss)) {
>          icp_check_ipi(xics, server);
>      }
> -    ics_resend(xics->ics);
> +    ics_resend(xics->ics, server);
>  }
>  
>  void icp_set_cppr(XICSState *xics, int server, uint8_t cppr)
> @@ -512,13 +512,24 @@ static void ics_reject(ICSState *ics, int nr)
>      }
>  }
>  
> -static void ics_resend(ICSState *ics)
> +static void ics_resend(ICSState *ics, int server)
>  {
>      int i;
> +    ICPState *ss = ics->xics->ss + server;
> +    ICSIRQState *irq;
>  
>      for (i = 0; i < ics->nr_irqs; i++) {
>          /* FIXME: filter by server#? */
> -        if (ics->irqs[i].flags & XICS_FLAGS_IRQ_LSI) {
> +        irq = &ics->irqs[i];
> +        if (!(irq->flags & XICS_FLAGS_IRQ_MASK)) {
> +            continue;
> +        }
> +
> +        if (irq->flags & XICS_FLAGS_IRQ_LSI) {
> +            if (irq->status & XICS_STATUS_SENT) {
> +                qemu_irq_raise(ss->output);
> +                continue;

Directly reraising the CPU irq line from an ics function rather than
an icp function seems very dubious.  It really seems like instead we
need to be recalculating the output line state from the ICP state,
after we've done all the ICS resends.

> +            }
>              resend_lsi(ics, i);
>          } else {
>              resend_msi(ics, i);

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [PATCH v4 3/9] ppc/xics: Make the ICSState a list
  2016-09-19  6:29 ` [Qemu-devel] [PATCH v4 3/9] ppc/xics: Make the ICSState a list Nikunj A Dadhania
  2016-09-19  6:59   ` [Qemu-devel] [Qemu-ppc] " Cédric Le Goater
@ 2016-09-21  7:48   ` David Gibson
  1 sibling, 0 replies; 38+ messages in thread
From: David Gibson @ 2016-09-21  7:48 UTC (permalink / raw)
  To: Nikunj A Dadhania; +Cc: qemu-ppc, qemu-devel, benh, clg

[-- Attachment #1: Type: text/plain, Size: 27991 bytes --]

On Mon, Sep 19, 2016 at 11:59:31AM +0530, Nikunj A Dadhania wrote:
> From: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> 
> Instead of an array of fixed sized blocks, use a list, as we will need
> to have sources with variable number of interrupts. SPAPR only uses
> a single entry. Native will create more. If performance becomes an
> issue we can add some hashed lookup but for now this will do fine.
> 
> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> [ move the initialization of list to xics_common_initfn,
>   restore xirr_owner after migration and move restoring to
>   icp_post_load]
> Signed-off-by: Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>
> ---
>  hw/intc/trace-events  |   5 +-
>  hw/intc/xics.c        | 130 ++++++++++++++++++++++++++++++++------------------
>  hw/intc/xics_kvm.c    |  27 +++++++----
>  hw/intc/xics_spapr.c  |  88 ++++++++++++++++++++++------------
>  hw/ppc/spapr_events.c |   2 +-
>  hw/ppc/spapr_pci.c    |   5 +-
>  hw/ppc/spapr_vio.c    |   2 +-
>  include/hw/ppc/xics.h |  13 ++---
>  8 files changed, 173 insertions(+), 99 deletions(-)
> 
> diff --git a/hw/intc/trace-events b/hw/intc/trace-events
> index f12192c..aa342a8 100644
> --- a/hw/intc/trace-events
> +++ b/hw/intc/trace-events
> @@ -56,10 +56,11 @@ xics_set_irq_lsi(int srcno, int nr) "set_irq_lsi: srcno %d [irq %#x]"
>  xics_ics_write_xive(int nr, int srcno, int server, uint8_t priority) "ics_write_xive: irq %#x [src %d] server %#x prio %#x"
>  xics_ics_reject(int nr, int srcno) "reject irq %#x [src %d]"
>  xics_ics_eoi(int nr) "ics_eoi: irq %#x"
> -xics_alloc(int src, int irq) "source#%d, irq %d"
> -xics_alloc_block(int src, int first, int num, bool lsi, int align) "source#%d, first irq %d, %d irqs, lsi=%d, alignnum %d"
> +xics_alloc(int irq) "irq %d"
> +xics_alloc_block(int first, int num, bool lsi, int align) "first irq %d, %d irqs, lsi=%d, alignnum %d"
>  xics_ics_free(int src, int irq, int num) "Source#%d, first irq %d, %d irqs"
>  xics_ics_free_warn(int src, int irq) "Source#%d, irq %d is already free"
> +xics_icp_post_load(uint32_t server_no, uint32_t xirr, uint64_t addr, uint8_t pend) "server_no %d, xirr %#x, xirr_owner 0x%" PRIx64 ", pending %d"
>  
>  # hw/intc/s390_flic_kvm.c
>  flic_create_device(int err) "flic: create device failed %d"
> diff --git a/hw/intc/xics.c b/hw/intc/xics.c
> index f765b08..05e938f 100644
> --- a/hw/intc/xics.c
> +++ b/hw/intc/xics.c
> @@ -32,6 +32,7 @@
>  #include "hw/hw.h"
>  #include "trace.h"
>  #include "qemu/timer.h"
> +#include "hw/ppc/spapr.h"
>  #include "hw/ppc/xics.h"
>  #include "qemu/error-report.h"
>  #include "qapi/visitor.h"
> @@ -96,13 +97,16 @@ void xics_cpu_setup(XICSState *xics, PowerPCCPU *cpu)
>  static void xics_common_reset(DeviceState *d)
>  {
>      XICSState *xics = XICS_COMMON(d);
> +    ICSState *ics;
>      int i;
>  
>      for (i = 0; i < xics->nr_servers; i++) {
>          device_reset(DEVICE(&xics->ss[i]));
>      }
>  
> -    device_reset(DEVICE(xics->ics));
> +    QLIST_FOREACH(ics, &xics->ics, list) {
> +        device_reset(DEVICE(ics));
> +    }
>  }
>  
>  static void xics_prop_get_nr_irqs(Object *obj, Visitor *v, const char *name,
> @@ -134,7 +138,6 @@ static void xics_prop_set_nr_irqs(Object *obj, Visitor *v, const char *name,
>      }
>  
>      assert(info->set_nr_irqs);
> -    assert(xics->ics);
>      info->set_nr_irqs(xics, value, errp);
>  }
>  
> @@ -174,6 +177,9 @@ static void xics_prop_set_nr_servers(Object *obj, Visitor *v,
>  
>  static void xics_common_initfn(Object *obj)
>  {
> +    XICSState *xics = XICS_COMMON(obj);
> +
> +    QLIST_INIT(&xics->ics);
>      object_property_add(obj, "nr_irqs", "int",
>                          xics_prop_get_nr_irqs, xics_prop_set_nr_irqs,
>                          NULL, NULL, NULL);
> @@ -212,33 +218,35 @@ static void ics_reject(ICSState *ics, int nr);
>  static void ics_resend(ICSState *ics, int server);
>  static void ics_eoi(ICSState *ics, int nr);
>  
> -static void icp_check_ipi(XICSState *xics, int server)
> +static void icp_check_ipi(ICPState *ss)
>  {
> -    ICPState *ss = xics->ss + server;
> -
>      if (XISR(ss) && (ss->pending_priority <= ss->mfrr)) {
>          return;
>      }
>  
> -    trace_xics_icp_check_ipi(server, ss->mfrr);
> +    trace_xics_icp_check_ipi(ss->cs->cpu_index, ss->mfrr);
>  
> -    if (XISR(ss)) {
> -        ics_reject(xics->ics, XISR(ss));
> +    if (XISR(ss) && ss->xirr_owner) {
> +        ics_reject(ss->xirr_owner, XISR(ss));
>      }
>  
>      ss->xirr = (ss->xirr & ~XISR_MASK) | XICS_IPI;
>      ss->pending_priority = ss->mfrr;
> +    ss->xirr_owner = NULL;
>      qemu_irq_raise(ss->output);
>  }
>  
>  static void icp_resend(XICSState *xics, int server)
>  {
>      ICPState *ss = xics->ss + server;
> +    ICSState *ics;
>  
>      if (ss->mfrr < CPPR(ss)) {
> -        icp_check_ipi(xics, server);
> +        icp_check_ipi(ss);
> +    }
> +    QLIST_FOREACH(ics, &xics->ics, list) {
> +        ics_resend(ics, server);
>      }
> -    ics_resend(xics->ics, server);
>  }
>  
>  void icp_set_cppr(XICSState *xics, int server, uint8_t cppr)
> @@ -256,7 +264,10 @@ void icp_set_cppr(XICSState *xics, int server, uint8_t cppr)
>              ss->xirr &= ~XISR_MASK; /* Clear XISR */
>              ss->pending_priority = 0xff;
>              qemu_irq_lower(ss->output);
> -            ics_reject(xics->ics, old_xisr);
> +            if (ss->xirr_owner) {
> +                ics_reject(ss->xirr_owner, old_xisr);
> +                ss->xirr_owner = NULL;
> +            }
>          }
>      } else {
>          if (!XISR(ss)) {
> @@ -271,7 +282,7 @@ void icp_set_mfrr(XICSState *xics, int server, uint8_t mfrr)
>  
>      ss->mfrr = mfrr;
>      if (mfrr < CPPR(ss)) {
> -        icp_check_ipi(xics, server);
> +        icp_check_ipi(ss);
>      }
>  }
>  
> @@ -282,6 +293,7 @@ uint32_t icp_accept(ICPState *ss)
>      qemu_irq_lower(ss->output);
>      ss->xirr = ss->pending_priority << 24;
>      ss->pending_priority = 0xff;
> +    ss->xirr_owner = NULL;
>  
>      trace_xics_icp_accept(xirr, ss->xirr);
>  
> @@ -299,30 +311,40 @@ uint32_t icp_ipoll(ICPState *ss, uint32_t *mfrr)
>  void icp_eoi(XICSState *xics, int server, uint32_t xirr)
>  {
>      ICPState *ss = xics->ss + server;
> +    ICSState *ics;
> +    uint32_t irq;
>  
>      /* Send EOI -> ICS */
>      ss->xirr = (ss->xirr & ~CPPR_MASK) | (xirr & CPPR_MASK);
>      trace_xics_icp_eoi(server, xirr, ss->xirr);
> -    ics_eoi(xics->ics, xirr & XISR_MASK);
> +    irq = xirr & XISR_MASK;
> +    QLIST_FOREACH(ics, &xics->ics, list) {
> +        if (ics_valid_irq(ics, irq)) {
> +            ics_eoi(ics, irq);
> +        }
> +    }
>      if (!XISR(ss)) {
>          icp_resend(xics, server);
>      }
>  }
>  
> -static void icp_irq(XICSState *xics, int server, int nr, uint8_t priority)
> +static void icp_irq(ICSState *ics, int server, int nr, uint8_t priority)
>  {
> +    XICSState *xics = ics->xics;
>      ICPState *ss = xics->ss + server;
>  
>      trace_xics_icp_irq(server, nr, priority);
>  
>      if ((priority >= CPPR(ss))
>          || (XISR(ss) && (ss->pending_priority <= priority))) {
> -        ics_reject(xics->ics, nr);
> +        ics_reject(ics, nr);
>      } else {
> -        if (XISR(ss)) {
> -            ics_reject(xics->ics, XISR(ss));
> +        if (XISR(ss) && ss->xirr_owner) {
> +            ics_reject(ss->xirr_owner, XISR(ss));
> +            ss->xirr_owner = NULL;
>          }
>          ss->xirr = (ss->xirr & ~XISR_MASK) | (nr & XISR_MASK);
> +        ss->xirr_owner = ics;
>          ss->pending_priority = priority;
>          trace_xics_icp_raise(ss->xirr, ss->pending_priority);
>          qemu_irq_raise(ss->output);
> @@ -378,12 +400,45 @@ static void icp_reset(DeviceState *dev)
>      qemu_set_irq(icp->output, 0);
>  }
>  
> +static int icp_post_load(ICPState *ss, int version_id)
> +{
> +    sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
> +    XICSState *xics = spapr->xics;
> +    uint32_t irq, i;
> +    static uint32_t server_no;

Ugh.. this static local stuff looks very fragile to me.  Not to
mention assuming the machine type, when we know ics native is coming.

> +    server_no++;
> +    irq = XISR(ss);
> +    if (!ss->cs || !irq) {
> +        goto icpend;

There's no excuse for this goto, you can accomplish exactly the same
thing more clearly by inverting the sense of the if.

> +    }
> +
> +    /* Restore the xirr_owner */
> +    ss->xirr_owner = xics_find_source(xics, irq);
> +
> + icpend:
> +    trace_xics_icp_post_load(server_no, ss->xirr, (uint64_t)ss->xirr_owner,
> +                             ss->pending_priority);
> +    if (xics->nr_servers != server_no) {
> +        return 0;
> +    }
> +
> +    /* All the ICPs are processed, now restore all the state */

So.. what exactly is the significance of running this after all
ICPs have restored state?

Rather than the static local, I'd instead suggest having a
xics_resync() or similar function, which you could call from the
machine's post_load, when everything should be restored.

> +    for (i = 0; i < xics->nr_servers; i++) {
> +        icp_resend(xics, i);
> +    }
> +    server_no = 0;
> +    return 0;
> +}
> +
>  static void icp_class_init(ObjectClass *klass, void *data)
>  {
>      DeviceClass *dc = DEVICE_CLASS(klass);
> +    ICPStateClass *icpc = ICP_CLASS(klass);
>  
>      dc->reset = icp_reset;
>      dc->vmsd = &vmstate_icp_server;
> +    icpc->post_load = icp_post_load;
>  }
>  
>  static const TypeInfo icp_info = {
> @@ -405,8 +460,7 @@ static void resend_msi(ICSState *ics, int srcno)
>      if (irq->status & XICS_STATUS_REJECTED) {
>          irq->status &= ~XICS_STATUS_REJECTED;
>          if (irq->priority != 0xff) {
> -            icp_irq(ics->xics, irq->server, srcno + ics->offset,
> -                    irq->priority);
> +            icp_irq(ics, irq->server, srcno + ics->offset, irq->priority);
>          }
>      }
>  }
> @@ -419,7 +473,7 @@ static void resend_lsi(ICSState *ics, int srcno)
>          && (irq->status & XICS_STATUS_ASSERTED)
>          && !(irq->status & XICS_STATUS_SENT)) {
>          irq->status |= XICS_STATUS_SENT;
> -        icp_irq(ics->xics, irq->server, srcno + ics->offset, irq->priority);
> +        icp_irq(ics, irq->server, srcno + ics->offset, irq->priority);
>      }
>  }
>  
> @@ -434,7 +488,7 @@ static void set_irq_msi(ICSState *ics, int srcno, int val)
>              irq->status |= XICS_STATUS_MASKED_PENDING;
>              trace_xics_masked_pending();
>          } else  {
> -            icp_irq(ics->xics, irq->server, srcno + ics->offset, irq->priority);
> +            icp_irq(ics, irq->server, srcno + ics->offset, irq->priority);
>          }
>      }
>  }
> @@ -473,7 +527,7 @@ static void write_xive_msi(ICSState *ics, int srcno)
>      }
>  
>      irq->status &= ~XICS_STATUS_MASKED_PENDING;
> -    icp_irq(ics->xics, irq->server, srcno + ics->offset, irq->priority);
> +    icp_irq(ics, irq->server, srcno + ics->offset, irq->priority);
>  }
>  
>  static void write_xive_lsi(ICSState *ics, int srcno)
> @@ -568,17 +622,6 @@ static void ics_reset(DeviceState *dev)
>      }
>  }
>  
> -static int ics_post_load(ICSState *ics, int version_id)
> -{
> -    int i;
> -
> -    for (i = 0; i < ics->xics->nr_servers; i++) {
> -        icp_resend(ics->xics, i);
> -    }
> -
> -    return 0;
> -}
> -
>  static void ics_dispatch_pre_save(void *opaque)
>  {
>      ICSState *ics = opaque;
> @@ -653,12 +696,10 @@ static void ics_realize(DeviceState *dev, Error **errp)
>  static void ics_class_init(ObjectClass *klass, void *data)
>  {
>      DeviceClass *dc = DEVICE_CLASS(klass);
> -    ICSStateClass *isc = ICS_CLASS(klass);
>  
>      dc->realize = ics_realize;
>      dc->vmsd = &vmstate_ics;
>      dc->reset = ics_reset;
> -    isc->post_load = ics_post_load;
>  }
>  
>  static const TypeInfo ics_info = {
> @@ -673,28 +714,23 @@ static const TypeInfo ics_info = {
>  /*
>   * Exported functions
>   */
> -int xics_find_source(XICSState *xics, int irq)
> +ICSState *xics_find_source(XICSState *xics, int irq)
>  {
> -    int sources = 1;
> -    int src;
> +    ICSState *ics;
>  
> -    /* FIXME: implement multiple sources */
> -    for (src = 0; src < sources; ++src) {
> -        ICSState *ics = &xics->ics[src];
> +    QLIST_FOREACH(ics, &xics->ics, list) {
>          if (ics_valid_irq(ics, irq)) {
> -            return src;
> +            return ics;
>          }
>      }
> -
> -    return -1;
> +    return NULL;
>  }
>  
>  qemu_irq xics_get_qirq(XICSState *xics, int irq)
>  {
> -    int src = xics_find_source(xics, irq);
> +    ICSState *ics = xics_find_source(xics, irq);
>  
> -    if (src >= 0) {
> -        ICSState *ics = &xics->ics[src];
> +    if (ics) {
>          return ics->qirqs[irq - ics->offset];
>      }
>  
> diff --git a/hw/intc/xics_kvm.c b/hw/intc/xics_kvm.c
> index edbd62f..04fa7cb 100644
> --- a/hw/intc/xics_kvm.c
> +++ b/hw/intc/xics_kvm.c
> @@ -365,7 +365,13 @@ static void xics_kvm_cpu_setup(XICSState *xics, PowerPCCPU *cpu)
>  static void xics_kvm_set_nr_irqs(XICSState *xics, uint32_t nr_irqs,
>                                   Error **errp)
>  {
> -    xics->nr_irqs = xics->ics->nr_irqs = nr_irqs;
> +    ICSState *ics = QLIST_FIRST(&xics->ics);
> +
> +    /* This needs to be deprecated ... */
> +    xics->nr_irqs = nr_irqs;
> +    if (ics) {
> +        ics->nr_irqs = nr_irqs;
> +    }
>  }
>  
>  static void xics_kvm_set_nr_servers(XICSState *xics, uint32_t nr_servers,
> @@ -398,6 +404,7 @@ static void xics_kvm_realize(DeviceState *dev, Error **errp)
>  {
>      KVMXICSState *xicskvm = XICS_SPAPR_KVM(dev);
>      XICSState *xics = XICS_COMMON(dev);
> +    ICSState *ics;
>      int i, rc;
>      Error *error = NULL;
>      struct kvm_create_device xics_create_device = {
> @@ -449,10 +456,12 @@ static void xics_kvm_realize(DeviceState *dev, Error **errp)
>  
>      xicskvm->kernel_xics_fd = xics_create_device.fd;
>  
> -    object_property_set_bool(OBJECT(xics->ics), true, "realized", &error);
> -    if (error) {
> -        error_propagate(errp, error);
> -        goto fail;
> +    QLIST_FOREACH(ics, &xics->ics, list) {
> +        object_property_set_bool(OBJECT(ics), true, "realized", &error);
> +        if (error) {
> +            error_propagate(errp, error);
> +            goto fail;
> +        }
>      }
>  
>      assert(xics->nr_servers);
> @@ -481,10 +490,12 @@ fail:
>  static void xics_kvm_initfn(Object *obj)
>  {
>      XICSState *xics = XICS_COMMON(obj);
> +    ICSState *ics;
>  
> -    xics->ics = ICS(object_new(TYPE_KVM_ICS));
> -    object_property_add_child(obj, "ics", OBJECT(xics->ics), NULL);
> -    xics->ics->xics = xics;
> +    ics = ICS(object_new(TYPE_KVM_ICS));
> +    object_property_add_child(obj, "ics", OBJECT(ics), NULL);
> +    ics->xics = xics;
> +    QLIST_INSERT_HEAD(&xics->ics, ics, list);
>  }
>  
>  static void xics_kvm_class_init(ObjectClass *oc, void *data)
> diff --git a/hw/intc/xics_spapr.c b/hw/intc/xics_spapr.c
> index 618826d..0b0845d 100644
> --- a/hw/intc/xics_spapr.c
> +++ b/hw/intc/xics_spapr.c
> @@ -113,13 +113,17 @@ static void rtas_set_xive(PowerPCCPU *cpu, sPAPRMachineState *spapr,
>                            uint32_t nargs, target_ulong args,
>                            uint32_t nret, target_ulong rets)
>  {
> -    ICSState *ics = spapr->xics->ics;
> +    ICSState *ics = QLIST_FIRST(&spapr->xics->ics);
>      uint32_t nr, server, priority;
>  
>      if ((nargs != 3) || (nret != 1)) {
>          rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
>          return;
>      }
> +    if (!ics) {
> +        rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
> +        return;
> +    }
>  
>      nr = rtas_ld(args, 0);
>      server = xics_get_cpu_index_by_dt_id(rtas_ld(args, 1));
> @@ -141,13 +145,17 @@ static void rtas_get_xive(PowerPCCPU *cpu, sPAPRMachineState *spapr,
>                            uint32_t nargs, target_ulong args,
>                            uint32_t nret, target_ulong rets)
>  {
> -    ICSState *ics = spapr->xics->ics;
> +    ICSState *ics = QLIST_FIRST(&spapr->xics->ics);
>      uint32_t nr;
>  
>      if ((nargs != 1) || (nret != 3)) {
>          rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
>          return;
>      }
> +    if (!ics) {
> +        rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
> +        return;
> +    }

I'd suggest a helper which retrieves the single ics for an spapr
system, and validates that there is exactly one.  It's a machine setup
error if there isn't exactly 1, so an assert() would make more sense
than an rtas error.

>  
>      nr = rtas_ld(args, 0);
>  
> @@ -166,13 +174,17 @@ static void rtas_int_off(PowerPCCPU *cpu, sPAPRMachineState *spapr,
>                           uint32_t nargs, target_ulong args,
>                           uint32_t nret, target_ulong rets)
>  {
> -    ICSState *ics = spapr->xics->ics;
> +    ICSState *ics = QLIST_FIRST(&spapr->xics->ics);
>      uint32_t nr;
>  
>      if ((nargs != 1) || (nret != 1)) {
>          rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
>          return;
>      }
> +    if (!ics) {
> +        rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
> +        return;
> +    }
>  
>      nr = rtas_ld(args, 0);
>  
> @@ -192,13 +204,17 @@ static void rtas_int_on(PowerPCCPU *cpu, sPAPRMachineState *spapr,
>                          uint32_t nargs, target_ulong args,
>                          uint32_t nret, target_ulong rets)
>  {
> -    ICSState *ics = spapr->xics->ics;
> +    ICSState *ics = QLIST_FIRST(&spapr->xics->ics);
>      uint32_t nr;
>  
>      if ((nargs != 1) || (nret != 1)) {
>          rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
>          return;
>      }
> +    if (!ics) {
> +        rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
> +        return;
> +    }
>  
>      nr = rtas_ld(args, 0);
>  
> @@ -217,7 +233,13 @@ static void rtas_int_on(PowerPCCPU *cpu, sPAPRMachineState *spapr,
>  static void xics_spapr_set_nr_irqs(XICSState *xics, uint32_t nr_irqs,
>                                     Error **errp)
>  {
> -    xics->nr_irqs = xics->ics->nr_irqs = nr_irqs;
> +    ICSState *ics = QLIST_FIRST(&xics->ics);
> +
> +    /* This needs to be deprecated ... */
> +    xics->nr_irqs = nr_irqs;
> +    if (ics) {
> +        ics->nr_irqs = nr_irqs;
> +    }
>  }
>  
>  static void xics_spapr_set_nr_servers(XICSState *xics, uint32_t nr_servers,
> @@ -240,6 +262,7 @@ static void xics_spapr_set_nr_servers(XICSState *xics, uint32_t nr_servers,
>  static void xics_spapr_realize(DeviceState *dev, Error **errp)
>  {
>      XICSState *xics = XICS_SPAPR(dev);
> +    ICSState *ics;
>      Error *error = NULL;
>      int i;
>  
> @@ -261,10 +284,12 @@ static void xics_spapr_realize(DeviceState *dev, Error **errp)
>      spapr_register_hypercall(H_EOI, h_eoi);
>      spapr_register_hypercall(H_IPOLL, h_ipoll);
>  
> -    object_property_set_bool(OBJECT(xics->ics), true, "realized", &error);
> -    if (error) {
> -        error_propagate(errp, error);
> -        return;
> +    QLIST_FOREACH(ics, &xics->ics, list) {
> +        object_property_set_bool(OBJECT(ics), true, "realized", &error);
> +        if (error) {
> +            error_propagate(errp, error);
> +            return;
> +        }

Hrm.. shouldn't this realize loop be in one of the base class
realize() calls anyway?

>      }
>  
>      for (i = 0; i < xics->nr_servers; i++) {
> @@ -280,10 +305,12 @@ static void xics_spapr_realize(DeviceState *dev, Error **errp)
>  static void xics_spapr_initfn(Object *obj)
>  {
>      XICSState *xics = XICS_SPAPR(obj);
> +    ICSState *ics;
>  
> -    xics->ics = ICS(object_new(TYPE_ICS));
> -    object_property_add_child(obj, "ics", OBJECT(xics->ics), NULL);
> -    xics->ics->xics = xics;
> +    ics = ICS(object_new(TYPE_ICS));
> +    object_property_add_child(obj, "ics", OBJECT(ics), NULL);
> +    ics->xics = xics;
> +    QLIST_INSERT_HEAD(&xics->ics, ics, list);
>  }
>  
>  static void xics_spapr_class_init(ObjectClass *oc, void *data)
> @@ -329,14 +356,15 @@ static int ics_find_free_block(ICSState *ics, int num, int alignnum)
>      return -1;
>  }
>  
> -int xics_spapr_alloc(XICSState *xics, int src, int irq_hint, bool lsi,
> -                     Error **errp)
> +int xics_spapr_alloc(XICSState *xics, int irq_hint, bool lsi, Error **errp)
>  {
> -    ICSState *ics = &xics->ics[src];
> +    ICSState *ics = QLIST_FIRST(&xics->ics);
>      int irq;
>  
> +    if (!ics) {
> +        return -1;
> +    }
>      if (irq_hint) {
> -        assert(src == xics_find_source(xics, irq_hint));
>          if (!ICS_IRQ_FREE(ics, irq_hint - ics->offset)) {
>              error_setg(errp, "can't allocate IRQ %d: already in use", irq_hint);
>              return -1;
> @@ -352,7 +380,7 @@ int xics_spapr_alloc(XICSState *xics, int src, int irq_hint, bool lsi,
>      }
>  
>      ics_set_irq_type(ics, irq - ics->offset, lsi);
> -    trace_xics_alloc(src, irq);
> +    trace_xics_alloc(irq);
>  
>      return irq;
>  }
> @@ -361,13 +389,16 @@ int xics_spapr_alloc(XICSState *xics, int src, int irq_hint, bool lsi,
>   * Allocate block of consecutive IRQs, and return the number of the first IRQ in
>   * the block. If align==true, aligns the first IRQ number to num.
>   */
> -int xics_spapr_alloc_block(XICSState *xics, int src, int num, bool lsi,
> -                           bool align, Error **errp)
> +int xics_spapr_alloc_block(XICSState *xics, int num, bool lsi, bool align,
> +                           Error **errp)
>  {
> +    ICSState *ics = QLIST_FIRST(&xics->ics);
>      int i, first = -1;
> -    ICSState *ics = &xics->ics[src];
>  
> -    assert(src == 0);
> +    if (!ics) {
> +        return -1;
> +    }
> +
>      /*
>       * MSIMesage::data is used for storing VIRQ so
>       * it has to be aligned to num to support multiple
> @@ -394,7 +425,7 @@ int xics_spapr_alloc_block(XICSState *xics, int src, int num, bool lsi,
>      }
>      first += ics->offset;
>  
> -    trace_xics_alloc_block(src, first, num, lsi, align);
> +    trace_xics_alloc_block(first, num, lsi, align);
>  
>      return first;
>  }
> @@ -405,7 +436,7 @@ static void ics_free(ICSState *ics, int srcno, int num)
>  
>      for (i = srcno; i < srcno + num; ++i) {
>          if (ICS_IRQ_FREE(ics, i)) {
> -            trace_xics_ics_free_warn(ics - ics->xics->ics, i + ics->offset);
> +            trace_xics_ics_free_warn(0, i + ics->offset);
>          }
>          memset(&ics->irqs[i], 0, sizeof(ICSIRQState));
>      }
> @@ -413,15 +444,10 @@ static void ics_free(ICSState *ics, int srcno, int num)
>  
>  void xics_spapr_free(XICSState *xics, int irq, int num)
>  {
> -    int src = xics_find_source(xics, irq);
> -
> -    if (src >= 0) {
> -        ICSState *ics = &xics->ics[src];
> -
> -        /* FIXME: implement multiple sources */
> -        assert(src == 0);
> +    ICSState *ics = xics_find_source(xics, irq);
>  
> -        trace_xics_ics_free(ics - xics->ics, irq, num);
> +    if (ics) {
> +        trace_xics_ics_free(0, irq, num);
>          ics_free(ics, irq - ics->offset, num);
>      }
>  }
> diff --git a/hw/ppc/spapr_events.c b/hw/ppc/spapr_events.c
> index b0668b3..adf8da4 100644
> --- a/hw/ppc/spapr_events.c
> +++ b/hw/ppc/spapr_events.c
> @@ -603,7 +603,7 @@ out_no_events:
>  void spapr_events_init(sPAPRMachineState *spapr)
>  {
>      QTAILQ_INIT(&spapr->pending_events);
> -    spapr->check_exception_irq = xics_spapr_alloc(spapr->xics, 0, 0, false,
> +    spapr->check_exception_irq = xics_spapr_alloc(spapr->xics, 0, false,
>                                              &error_fatal);
>      spapr->epow_notifier.notify = spapr_powerdown_req;
>      qemu_register_powerdown_notifier(&spapr->epow_notifier);
> diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
> index 949c44f..4d06794 100644
> --- a/hw/ppc/spapr_pci.c
> +++ b/hw/ppc/spapr_pci.c
> @@ -362,7 +362,7 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, sPAPRMachineState *spapr,
>      }
>  
>      /* Allocate MSIs */
> -    irq = xics_spapr_alloc_block(spapr->xics, 0, req_num, false,
> +    irq = xics_spapr_alloc_block(spapr->xics, req_num, false,
>                             ret_intr_type == RTAS_TYPE_MSI, &err);
>      if (err) {
>          error_reportf_err(err, "Can't allocate MSIs for device %x: ",
> @@ -1444,8 +1444,7 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp)
>          uint32_t irq;
>          Error *local_err = NULL;
>  
> -        irq = xics_spapr_alloc_block(spapr->xics, 0, 1, true, false,
> -                                     &local_err);
> +        irq = xics_spapr_alloc_block(spapr->xics, 1, true, false, &local_err);
>          if (local_err) {
>              error_propagate(errp, local_err);
>              error_prepend(errp, "can't allocate LSIs: ");
> diff --git a/hw/ppc/spapr_vio.c b/hw/ppc/spapr_vio.c
> index f93244d..22360af 100644
> --- a/hw/ppc/spapr_vio.c
> +++ b/hw/ppc/spapr_vio.c
> @@ -463,7 +463,7 @@ static void spapr_vio_busdev_realize(DeviceState *qdev, Error **errp)
>          dev->qdev.id = id;
>      }
>  
> -    dev->irq = xics_spapr_alloc(spapr->xics, 0, dev->irq, false, &local_err);
> +    dev->irq = xics_spapr_alloc(spapr->xics, dev->irq, false, &local_err);
>      if (local_err) {
>          error_propagate(errp, local_err);
>          return;
> diff --git a/include/hw/ppc/xics.h b/include/hw/ppc/xics.h
> index 2db9f93..1ea40bd 100644
> --- a/include/hw/ppc/xics.h
> +++ b/include/hw/ppc/xics.h
> @@ -85,7 +85,7 @@ struct XICSState {
>      uint32_t nr_servers;
>      uint32_t nr_irqs;
>      ICPState *ss;
> -    ICSState *ics;
> +    QLIST_HEAD(, ICSState) ics;
>  };
>  
>  #define TYPE_ICP "icp"
> @@ -111,6 +111,7 @@ struct ICPState {
>      DeviceState parent_obj;
>      /*< public >*/
>      CPUState *cs;
> +    ICSState *xirr_owner;
>      uint32_t xirr;
>      uint8_t pending_priority;
>      uint8_t mfrr;
> @@ -145,6 +146,7 @@ struct ICSState {
>      qemu_irq *qirqs;
>      ICSIRQState *irqs;
>      XICSState *xics;
> +    QLIST_ENTRY(ICSState) list;
>  };
>  
>  static inline bool ics_valid_irq(ICSState *ics, uint32_t nr)
> @@ -172,10 +174,9 @@ struct ICSIRQState {
>  #define XICS_IRQS_SPAPR               1024
>  
>  qemu_irq xics_get_qirq(XICSState *icp, int irq);
> -int xics_spapr_alloc(XICSState *icp, int src, int irq_hint, bool lsi,
> -                     Error **errp);
> -int xics_spapr_alloc_block(XICSState *icp, int src, int num, bool lsi,
> -                           bool align, Error **errp);
> +int xics_spapr_alloc(XICSState *icp, int irq_hint, bool lsi, Error **errp);
> +int xics_spapr_alloc_block(XICSState *icp, int num, bool lsi, bool align,
> +                           Error **errp);
>  void xics_spapr_free(XICSState *icp, int irq, int num);
>  
>  void xics_cpu_setup(XICSState *icp, PowerPCCPU *cpu);
> @@ -195,6 +196,6 @@ void ics_write_xive(ICSState *ics, int nr, int server,
>  
>  void ics_set_irq_type(ICSState *ics, int srcno, bool lsi);
>  
> -int xics_find_source(XICSState *icp, int irq);
> +ICSState *xics_find_source(XICSState *icp, int irq);
>  
>  #endif /* XICS_H */

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [PATCH v4 4/9] ppc/xics: An ICS with offset 0 is assumed to be uninitialized
  2016-09-19  6:29 ` [Qemu-devel] [PATCH v4 4/9] ppc/xics: An ICS with offset 0 is assumed to be uninitialized Nikunj A Dadhania
@ 2016-09-21  7:50   ` David Gibson
  0 siblings, 0 replies; 38+ messages in thread
From: David Gibson @ 2016-09-21  7:50 UTC (permalink / raw)
  To: Nikunj A Dadhania; +Cc: qemu-ppc, qemu-devel, benh, clg

[-- Attachment #1: Type: text/plain, Size: 1211 bytes --]

On Mon, Sep 19, 2016 at 11:59:32AM +0530, Nikunj A Dadhania wrote:
> From: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> 
> This will make life easier for dealing with dynamically configured
> ICSes such as PHB3
> 
> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
> Signed-off-by: Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>

This seems reasonable on its own, so I've applied it to ppc-for-2.8.

> ---
>  include/hw/ppc/xics.h | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/include/hw/ppc/xics.h b/include/hw/ppc/xics.h
> index 1ea40bd..e49a2da 100644
> --- a/include/hw/ppc/xics.h
> +++ b/include/hw/ppc/xics.h
> @@ -151,7 +151,7 @@ struct ICSState {
>  
>  static inline bool ics_valid_irq(ICSState *ics, uint32_t nr)
>  {
> -    return (nr >= ics->offset)
> +    return (ics->offset != 0) && (nr >= ics->offset)
>          && (nr < (ics->offset + ics->nr_irqs));
>  }
>  

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [PATCH v4 5/9] ppc/xics: Use a helper to add a new ICS
  2016-09-19  6:29 ` [Qemu-devel] [PATCH v4 5/9] ppc/xics: Use a helper to add a new ICS Nikunj A Dadhania
@ 2016-09-21 23:40   ` David Gibson
  2016-09-22  6:21     ` Cédric Le Goater
  0 siblings, 1 reply; 38+ messages in thread
From: David Gibson @ 2016-09-21 23:40 UTC (permalink / raw)
  To: Nikunj A Dadhania; +Cc: qemu-ppc, qemu-devel, benh, clg

[-- Attachment #1: Type: text/plain, Size: 2602 bytes --]

On Mon, Sep 19, 2016 at 11:59:33AM +0530, Nikunj A Dadhania wrote:
> From: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> 
> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> [Move object allocation and adding child to the helper]
> Signed-off-by: Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>
> Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
> ---
>  hw/intc/xics.c        | 10 ++++++++++
>  hw/intc/xics_spapr.c  |  6 +-----
>  include/hw/ppc/xics.h |  1 +
>  3 files changed, 12 insertions(+), 5 deletions(-)
> 
> diff --git a/hw/intc/xics.c b/hw/intc/xics.c
> index 05e938f..c7901c4 100644
> --- a/hw/intc/xics.c
> +++ b/hw/intc/xics.c
> @@ -109,6 +109,16 @@ static void xics_common_reset(DeviceState *d)
>      }
>  }
>  
> +void xics_add_ics(XICSState *xics)
> +{
> +    ICSState *ics;
> +
> +    ics = ICS(object_new(TYPE_ICS));
> +    object_property_add_child(OBJECT(xics), "ics", OBJECT(ics), NULL);

You'll need to construct a name here so you don't have all the ics
objects called an indistinguishable "ics".

> +    ics->xics = xics;
> +    QLIST_INSERT_HEAD(&xics->ics, ics, list);
> +}
> +
>  static void xics_prop_get_nr_irqs(Object *obj, Visitor *v, const char *name,
>                                    void *opaque, Error **errp)
>  {
> diff --git a/hw/intc/xics_spapr.c b/hw/intc/xics_spapr.c
> index 0b0845d..270f20e 100644
> --- a/hw/intc/xics_spapr.c
> +++ b/hw/intc/xics_spapr.c
> @@ -305,12 +305,8 @@ static void xics_spapr_realize(DeviceState *dev, Error **errp)
>  static void xics_spapr_initfn(Object *obj)
>  {
>      XICSState *xics = XICS_SPAPR(obj);
> -    ICSState *ics;
>  
> -    ics = ICS(object_new(TYPE_ICS));
> -    object_property_add_child(obj, "ics", OBJECT(ics), NULL);
> -    ics->xics = xics;
> -    QLIST_INSERT_HEAD(&xics->ics, ics, list);
> +    xics_add_ics(xics);
>  }
>  
>  static void xics_spapr_class_init(ObjectClass *oc, void *data)
> diff --git a/include/hw/ppc/xics.h b/include/hw/ppc/xics.h
> index e49a2da..a7a1e54 100644
> --- a/include/hw/ppc/xics.h
> +++ b/include/hw/ppc/xics.h
> @@ -197,5 +197,6 @@ void ics_write_xive(ICSState *ics, int nr, int server,
>  void ics_set_irq_type(ICSState *ics, int srcno, bool lsi);
>  
>  ICSState *xics_find_source(XICSState *icp, int irq);
> +void xics_add_ics(XICSState *xics);
>  
>  #endif /* XICS_H */

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [PATCH v4 7/9] ppc/xics: Add "native" XICS subclass
  2016-09-19  6:29 ` [Qemu-devel] [PATCH v4 7/9] ppc/xics: Add "native" XICS subclass Nikunj A Dadhania
  2016-09-19  7:03   ` [Qemu-devel] [Qemu-ppc] " Cédric Le Goater
@ 2016-09-22  0:02   ` David Gibson
  2016-09-22  6:27     ` Cédric Le Goater
  1 sibling, 1 reply; 38+ messages in thread
From: David Gibson @ 2016-09-22  0:02 UTC (permalink / raw)
  To: Nikunj A Dadhania; +Cc: qemu-ppc, qemu-devel, benh, clg

[-- Attachment #1: Type: text/plain, Size: 14075 bytes --]

On Mon, Sep 19, 2016 at 11:59:35AM +0530, Nikunj A Dadhania wrote:
> From: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> 
> This provides MMIO based ICP access as found on POWER8
> 
> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> Signed-off-by: Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>
> ---
>  default-configs/ppc64-softmmu.mak |   3 +-
>  hw/intc/Makefile.objs             |   1 +
>  hw/intc/xics_native.c             | 295 ++++++++++++++++++++++++++++++++++++++
>  include/hw/ppc/xics.h             |  14 ++
>  4 files changed, 312 insertions(+), 1 deletion(-)
>  create mode 100644 hw/intc/xics_native.c
> 
> diff --git a/default-configs/ppc64-softmmu.mak b/default-configs/ppc64-softmmu.mak
> index c4be59f..315e30b 100644
> --- a/default-configs/ppc64-softmmu.mak
> +++ b/default-configs/ppc64-softmmu.mak
> @@ -48,8 +48,9 @@ CONFIG_PLATFORM_BUS=y
>  CONFIG_ETSEC=y
>  CONFIG_LIBDECNUMBER=y
>  # For pSeries
> -CONFIG_XICS=$(CONFIG_PSERIES)
> +CONFIG_XICS=$(or $(CONFIG_PSERIES),$(CONFIG_POWERNV))
>  CONFIG_XICS_SPAPR=$(CONFIG_PSERIES)
> +CONFIG_XICS_NATIVE=$(CONFIG_POWERNV)
>  CONFIG_XICS_KVM=$(and $(CONFIG_PSERIES),$(CONFIG_KVM))
>  # For PReP
>  CONFIG_MC146818RTC=y
> diff --git a/hw/intc/Makefile.objs b/hw/intc/Makefile.objs
> index 05ec21b..7be5dfc 100644
> --- a/hw/intc/Makefile.objs
> +++ b/hw/intc/Makefile.objs
> @@ -31,6 +31,7 @@ obj-$(CONFIG_RASPI) += bcm2835_ic.o bcm2836_control.o
>  obj-$(CONFIG_SH4) += sh_intc.o
>  obj-$(CONFIG_XICS) += xics.o
>  obj-$(CONFIG_XICS_SPAPR) += xics_spapr.o
> +obj-$(CONFIG_XICS_NATIVE) += xics_native.o
>  obj-$(CONFIG_XICS_KVM) += xics_kvm.o
>  obj-$(CONFIG_ALLWINNER_A10_PIC) += allwinner-a10-pic.o
>  obj-$(CONFIG_S390_FLIC) += s390_flic.o
> diff --git a/hw/intc/xics_native.c b/hw/intc/xics_native.c
> new file mode 100644
> index 0000000..26e45cc
> --- /dev/null
> +++ b/hw/intc/xics_native.c
> @@ -0,0 +1,295 @@
> +/*
> + * QEMU PowerPC hardware System Emulator
> + *
> + * Native version of ICS/ICP
> + *
> + * Copyright (c) 2010,2011 David Gibson, IBM Corporation.
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a copy
> + * of this software and associated documentation files (the "Software"), to deal
> + * in the Software without restriction, including without limitation the rights
> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> + * copies of the Software, and to permit persons to whom the Software is
> + * furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> + * THE SOFTWARE.
> + *
> + */
> +
> +#include "qemu/osdep.h"
> +#include "hw/hw.h"
> +#include "trace.h"
> +#include "qemu/timer.h"
> +#include "hw/ppc/xics.h"
> +#include "qapi/visitor.h"
> +#include "qapi/error.h"
> +
> +#include <libfdt.h>
> +
> +/* #define DEBUG_MM(fmt...)      printf(fmt) */
> +#define DEBUG_MM(fmt...)        do { } while (0)
> +
> +static void xics_native_initfn(Object *obj)
> +{
> +    XICSState *xics = XICS_NATIVE(obj);
> +
> +    QLIST_INIT(&xics->ics);

Isn't this redundant with the QLIST_INIT() in the common initfn?

> +}
> +
> +static uint64_t icp_mm_read(void *opaque, hwaddr addr, unsigned width)
> +{
> +    XICSState *s = opaque;
> +    int32_t cpu_id, server;
> +    uint32_t val;
> +    ICPState *ss;
> +    bool byte0 = (width == 1 && (addr & 0x3) == 0);
> +
> +    cpu_id = (addr & (ICP_MM_SIZE - 1)) >> 12;
> +    server = get_cpu_index_by_dt_id(cpu_id);
> +    if (server < 0) {
> +        fprintf(stderr, "XICS: Bad ICP server %d\n", server);

Please use error_report() instead of raw fprintf()s.

> +        goto bad_access;
> +    }
> +    ss = &s->ss[server];
> +
> +    switch (addr & 0xffc) {
> +    case 0: /* poll */
> +        val = icp_ipoll(ss, NULL);
> +        if (byte0) {
> +            val >>= 24;
> +        } else if (width != 4) {
> +            goto bad_access;
> +        }
> +        break;
> +    case 4: /* xirr */
> +        if (byte0) {
> +            val = icp_ipoll(ss, NULL) >> 24;
> +        } else if (width == 4) {
> +            val = icp_accept(ss);
> +        } else {
> +            goto bad_access;
> +        }
> +        break;
> +    case 12:
> +        if (byte0) {
> +            val = ss->mfrr;
> +        } else {
> +            goto bad_access;
> +        }
> +        break;
> +    case 16:
> +        if (width == 4) {
> +            val = ss->links[0];
> +        } else {
> +            goto bad_access;
> +        }
> +        break;
> +    case 20:
> +        if (width == 4) {
> +            val = ss->links[1];
> +        } else {
> +            goto bad_access;
> +        }
> +        break;
> +    case 24:
> +        if (width == 4) {
> +            val = ss->links[2];
> +        } else {
> +            goto bad_access;
> +        }
> +        break;
> +    default:
> +bad_access:
> +        fprintf(stderr, "XICS: Bad ICP access %llx/%d\n",
> +                (unsigned long long)addr, width);
> +        val = 0xffffffff;
> +    }
> +    DEBUG_MM("icp_mm_read(addr=%016llx,serv=0x%x/%d,off=%d,w=%d,val=0x%08x)\n",
> +             (unsigned long long)addr, cpu_id, server, (int)(addr & 0xffc),
> +             width, val);

It's preferred to use trace-events rather than DEBUG macros.

> +
> +    return val;
> +}
> +
> +static void icp_mm_write(void *opaque, hwaddr addr, uint64_t val,
> +                        unsigned width)
> +{
> +    XICSState *s = opaque;
> +    int32_t cpu_id, server;
> +    ICPState *ss;
> +    bool byte0 = (width == 1 && (addr & 0x3) == 0);
> +
> +    cpu_id = (addr & (ICP_MM_SIZE - 1)) >> 12;
> +    server = get_cpu_index_by_dt_id(cpu_id);
> +    if (server < 0) {
> +        fprintf(stderr, "XICS: Bad ICP server %d\n", server);
> +        goto bad_access;
> +    }
> +    ss = &s->ss[server];
> +
> +    DEBUG_MM("icp_mm_write(addr=%016llx,serv=0x%x/%d,off=%d,w=%d,val=0x%08x)\n",
> +             (unsigned long long)addr, cpu_id, server,
> +             (int)(addr & 0xffc), width, (uint32_t)val);
> +
> +    switch (addr & 0xffc) {
> +    case 4: /* xirr */
> +        if (byte0) {
> +            icp_set_cppr(s, server, val);
> +        } else if (width == 4) {
> +            icp_eoi(s, server, val);
> +        } else {
> +            goto bad_access;
> +        }
> +        break;
> +    case 12:
> +        if (byte0) {
> +            icp_set_mfrr(s, server, val);
> +        } else {
> +            goto bad_access;
> +        }
> +        break;
> +    case 16:
> +        if (width == 4) {
> +            ss->links[0] = val;
> +        } else {
> +            goto bad_access;
> +        }
> +        break;
> +    case 20:
> +        if (width == 4) {
> +            ss->links[1] = val;
> +        } else {
> +            goto bad_access;
> +        }
> +        break;
> +    case 24:
> +        if (width == 4) {
> +            ss->links[2] = val;
> +        } else {
> +            goto bad_access;
> +        }
> +        break;
> +    default:
> + bad_access:
> +        val = 0xffffffff;
> +    }
> +}
> +
> +static const MemoryRegionOps icp_mm_ops = {
> +    .read = icp_mm_read,
> +    .write = icp_mm_write,
> +    .valid.min_access_size = 1,
> +    .valid.max_access_size = 4,
> +    .impl.min_access_size = 1,
> +    .impl.max_access_size = 4,
> +    .endianness = DEVICE_BIG_ENDIAN,
> +};
> +
> +#define _FDT(exp) \
> +    do { \
> +        int ret = (exp);                                           \
> +        if (ret < 0) {                                             \
> +            fprintf(stderr, "qemu: error creating device tree: %s: %s\n", \
> +                    #exp, fdt_strerror(ret));                      \
> +            exit(1);                                               \
> +        }                                                          \
> +    } while (0)
> +
> +void xics_create_native_icp_node(XICSState *s, void *fdt,
> +                                 uint32_t base, uint32_t count)
> +{
> +    uint64_t addr;
> +    char *name;
> +    const char compat[] = "IBM,power8-icp\0IBM,ppc-xicp";
> +    uint32_t irange[2], i, rsize;
> +    uint64_t *reg;
> +
> +    addr = ICP_MM_BASE | (base << 12);
> +
> +    irange[0] = cpu_to_be32(base);
> +    irange[1] = cpu_to_be32(count);
> +
> +    rsize = sizeof(uint64_t) * 2 * count;
> +    reg = g_malloc(rsize);
> +    for (i = 0; i < count; i++) {
> +        reg[i * 2] = cpu_to_be64(addr | ((base + i) * 0x1000));
> +        reg[i * 2 + 1] = cpu_to_be64(0x1000);
> +    }
> +
> +    name = g_strdup_printf("interrupt-controller@%"PRIX64, addr);
> +
> +    /* interrupt controller */
> +    _FDT((fdt_begin_node(fdt, name)));
> +    g_free(name);
> +
> +    _FDT((fdt_property(fdt, "compatible", compat, sizeof(compat))));
> +    _FDT((fdt_property(fdt, "reg", reg, rsize)));
> +    _FDT((fdt_property_string(fdt, "device_type",
> +                              "PowerPC-External-Interrupt-Presentation")));
> +    _FDT((fdt_property(fdt, "interrupt-controller", NULL, 0)));
> +    _FDT((fdt_property(fdt, "ibm,interrupt-server-ranges",
> +                       irange, sizeof(irange))));
> +    _FDT((fdt_property_cell(fdt, "#interrupt-cells", 1)));
> +    _FDT((fdt_property_cell(fdt, "#address-cells", 0)));
> +    _FDT((fdt_end_node(fdt)));
> +}
> +
> +static void xics_native_realize(DeviceState *dev, Error **errp)
> +{
> +    XICSState *s = XICS_NATIVE(dev);
> +    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
> +    Error *error = NULL;
> +    int i;
> +
> +    if (!s->nr_servers) {
> +        error_setg(errp, "Number of servers needs to be greater 0");
> +        return;
> +    }
> +
> +    /* Register MMIO regions */
> +    memory_region_init_io(&s->icp_mmio, OBJECT(s), &icp_mm_ops, s, "icp",
> +                          ICP_MM_SIZE);
> +    sysbus_init_mmio(sbd, &s->icp_mmio);
> +    sysbus_mmio_map(sbd, 0, ICP_MM_BASE);
> +
> +    for (i = 0; i < s->nr_servers; i++) {
> +        object_property_set_bool(OBJECT(&s->ss[i]), true, "realized", &error);
> +        if (error) {
> +            error_propagate(errp, error);
> +            return;
> +        }
> +    }
> +}
> +
> +static void xics_native_class_init(ObjectClass *oc, void *data)
> +{
> +    DeviceClass *dc = DEVICE_CLASS(oc);
> +    XICSStateClass *xsc = XICS_NATIVE_CLASS(oc);
> +
> +    dc->realize = xics_native_realize;
> +    xsc->set_nr_servers = xics_set_nr_servers;
> +}
> +
> +static const TypeInfo xics_native_info = {
> +    .name          = TYPE_XICS_NATIVE,
> +    .parent        = TYPE_XICS_COMMON,
> +    .instance_size = sizeof(XICSState),
> +    .class_size = sizeof(XICSStateClass),
> +    .class_init    = xics_native_class_init,
> +    .instance_init = xics_native_initfn,
> +};
> +
> +static void xics_native_register_types(void)
> +{
> +    type_register_static(&xics_native_info);
> +}
> +type_init(xics_native_register_types)
> diff --git a/include/hw/ppc/xics.h b/include/hw/ppc/xics.h
> index 2231f2a..f81155c 100644
> --- a/include/hw/ppc/xics.h
> +++ b/include/hw/ppc/xics.h
> @@ -44,6 +44,9 @@
>  #define XICS_SPAPR_KVM(obj) \
>       OBJECT_CHECK(KVMXICSState, (obj), TYPE_XICS_SPAPR_KVM)
>  
> +#define TYPE_XICS_NATIVE "xics-native"
> +#define XICS_NATIVE(obj) OBJECT_CHECK(XICSState, (obj), TYPE_XICS_NATIVE)
> +
>  #define XICS_COMMON_CLASS(klass) \
>       OBJECT_CLASS_CHECK(XICSStateClass, (klass), TYPE_XICS_COMMON)
>  #define XICS_SPAPR_CLASS(klass) \
> @@ -52,6 +55,8 @@
>       OBJECT_GET_CLASS(XICSStateClass, (obj), TYPE_XICS_COMMON)
>  #define XICS_SPAPR_GET_CLASS(obj) \
>       OBJECT_GET_CLASS(XICSStateClass, (obj), TYPE_XICS_SPAPR)
> +#define XICS_NATIVE_CLASS(klass) \
> +     OBJECT_CLASS_CHECK(XICSStateClass, (klass), TYPE_XICS_NATIVE)
>  
>  #define XICS_IPI        0x2
>  #define XICS_BUID       0x1
> @@ -86,6 +91,7 @@ struct XICSState {
>      uint32_t nr_irqs;
>      ICPState *ss;
>      QLIST_HEAD(, ICSState) ics;
> +    MemoryRegion icp_mmio;

Shouldn't this just be in the native subclass?

>  };
>  
>  #define TYPE_ICP "icp"
> @@ -117,8 +123,13 @@ struct ICPState {
>      uint8_t mfrr;
>      qemu_irq output;
>      bool cap_irq_xics_enabled;
> +    uint32_t links[3];

Likewise here.

>  };
>  
> +/* This should be an XSCOM BAR ... the size is arbitrary as well */
> +#define ICP_MM_BASE     0x0003FFFF80000000
> +#define ICP_MM_SIZE     0x0000000010000000
> +
>  #define TYPE_ICS_BASE "ics-base"
>  #define ICS_BASE(obj) OBJECT_CHECK(ICSState, (obj), TYPE_ICS_SIMPLE)
>  
> @@ -189,6 +200,9 @@ void xics_spapr_free(XICSState *icp, int irq, int num);
>  void xics_cpu_setup(XICSState *icp, PowerPCCPU *cpu);
>  void xics_cpu_destroy(XICSState *icp, PowerPCCPU *cpu);
>  
> +void xics_create_native_icp_node(XICSState *s, void *fdt,
> +                                 uint32_t base, uint32_t count);
> +
>  /* Internal XICS interfaces */
>  int xics_get_cpu_index_by_dt_id(int cpu_dt_id);
>  

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [PATCH v4 8/9] ppc/xics: Add xics to the monitor "info pic" command
  2016-09-19  6:29 ` [Qemu-devel] [PATCH v4 8/9] ppc/xics: Add xics to the monitor "info pic" command Nikunj A Dadhania
@ 2016-09-22  0:07   ` David Gibson
  0 siblings, 0 replies; 38+ messages in thread
From: David Gibson @ 2016-09-22  0:07 UTC (permalink / raw)
  To: Nikunj A Dadhania; +Cc: qemu-ppc, qemu-devel, benh, clg

[-- Attachment #1: Type: text/plain, Size: 6007 bytes --]

On Mon, Sep 19, 2016 at 11:59:36AM +0530, Nikunj A Dadhania wrote:
> From: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> 
> Useful to debug interrupt problems.
> 
> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> Signed-off-by: Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>
> ---
>  hmp-commands-info.hx  |  2 ++
>  hw/intc/xics.c        | 38 ++++++++++++++++++++++++++++++++++++++
>  hw/ppc/ppc.c          | 14 ++++++++++++++
>  include/hw/ppc/ppc.h  |  1 +
>  include/hw/ppc/xics.h |  4 +++-
>  monitor.c             |  4 ++++
>  6 files changed, 62 insertions(+), 1 deletion(-)
> 
> diff --git a/hmp-commands-info.hx b/hmp-commands-info.hx
> index 74446c6..0929cb7 100644
> --- a/hmp-commands-info.hx
> +++ b/hmp-commands-info.hx
> @@ -203,6 +203,8 @@ ETEXI
>          .mhandler.cmd = sun4m_hmp_info_pic,
>  #elif defined(TARGET_LM32)
>          .mhandler.cmd = lm32_hmp_info_pic,
> +#elif defined(TARGET_PPC)
> +        .mhandler.cmd = ppc_hmp_info_pic,

It's bad enough that the existing ones treat what's really a machine
type dependent thing as an arch dependent thing without adding more.

I need to dust off my patches which try to clean up the whole info pic mess.

>  #else
>          .mhandler.cmd = hmp_info_pic,
>  #endif
> diff --git a/hw/intc/xics.c b/hw/intc/xics.c
> index b15751e..4ac2d00 100644
> --- a/hw/intc/xics.c
> +++ b/hw/intc/xics.c
> @@ -36,6 +36,9 @@
>  #include "hw/ppc/xics.h"
>  #include "qemu/error-report.h"
>  #include "qapi/visitor.h"
> +#include "monitor/monitor.h"
> +
> +static XICSState *g_xics;
>  
>  int xics_get_cpu_index_by_dt_id(int cpu_dt_id)
>  {
> @@ -196,6 +199,9 @@ static void xics_common_initfn(Object *obj)
>      object_property_add(obj, "nr_servers", "int",
>                          xics_prop_get_nr_servers, xics_prop_set_nr_servers,
>                          NULL, NULL, NULL);
> +
> +    /* For exclusive use of monitor command */
> +    g_xics = XICS_COMMON(obj);

I don't think you need this, you should be able to get to the xics via
qdev_get_machine().

>  }
>  
>  static void xics_common_class_init(ObjectClass *oc, void *data)
> @@ -677,6 +683,38 @@ static int ics_simple_dispatch_post_load(void *opaque, int version_id)
>      return 0;
>  }
>  
> +void xics_hmp_info_pic(Monitor *mon, const QDict *qdict)
> +{
> +    ICSState *ics;
> +    uint32_t i;
> +
> +    for (i = 0; i < g_xics->nr_servers; i++) {

This will SEGV on machine types which aren't xics based.

> +        ICPState *icp = &g_xics->ss[i];
> +
> +        if (!icp->output) {
> +            continue;
> +        }
> +        monitor_printf(mon, "CPU %d XIRR=%08x (%p) PP=%02x MFRR=%02x\n",
> +                       i, icp->xirr, icp->xirr_owner,
> +                       icp->pending_priority, icp->mfrr);
> +    }
> +    QLIST_FOREACH(ics, &g_xics->ics, list) {
> +        monitor_printf(mon, "ICS %4x..%4x %p\n",
> +                       ics->offset, ics->offset + ics->nr_irqs - 1, ics);
> +        for (i = 0; i < ics->nr_irqs; i++) {
> +            ICSIRQState *irq = ics->irqs + i;
> +
> +            if (!(irq->flags & XICS_FLAGS_IRQ_MASK)) {
> +                continue;
> +            }
> +            monitor_printf(mon, "  %4x %s %02x %02x\n",
> +                           ics->offset + i,
> +                           (irq->flags & XICS_FLAGS_IRQ_LSI) ? "LSI" : "MSI",
> +                           irq->priority, irq->status);
> +        }
> +    }
> +}
> +
>  static const VMStateDescription vmstate_ics_simple_irq = {
>      .name = "ics/irq",
>      .version_id = 2,
> diff --git a/hw/ppc/ppc.c b/hw/ppc/ppc.c
> index 8945869..bc73428 100644
> --- a/hw/ppc/ppc.c
> +++ b/hw/ppc/ppc.c
> @@ -27,6 +27,7 @@
>  #include "hw/hw.h"
>  #include "hw/ppc/ppc.h"
>  #include "hw/ppc/ppc_e500.h"
> +#include "hw/i386/pc.h"
>  #include "qemu/timer.h"
>  #include "sysemu/sysemu.h"
>  #include "sysemu/cpus.h"
> @@ -39,6 +40,10 @@
>  #include "kvm_ppc.h"
>  #include "trace.h"
>  
> +#if defined(TARGET_PPC64)
> +#include "hw/ppc/xics.h"
> +#endif
> +
>  //#define PPC_DEBUG_IRQ
>  //#define PPC_DEBUG_TB
>  
> @@ -1376,3 +1381,12 @@ void ppc_cpu_parse_features(const char *cpu_model)
>      cc->parse_features(typename, model_pieces[1], &error_fatal);
>      g_strfreev(model_pieces);
>  }
> +
> +void ppc_hmp_info_pic(Monitor *mon, const QDict *qdict)
> +{
> +    /* Call in turn every PIC around. OpenPIC doesn't have one yet */
> +#ifdef TARGET_PPC64
> +    xics_hmp_info_pic(mon, qdict);
> +#endif
> +    hmp_info_pic(mon, qdict);
> +}
> diff --git a/include/hw/ppc/ppc.h b/include/hw/ppc/ppc.h
> index 00c1fb1..69c4b19 100644
> --- a/include/hw/ppc/ppc.h
> +++ b/include/hw/ppc/ppc.h
> @@ -3,6 +3,7 @@
>  
>  #include "target-ppc/cpu-qom.h"
>  
> +void ppc_hmp_info_pic(Monitor *mon, const QDict *qdict);
>  void ppc_set_irq(PowerPCCPU *cpu, int n_IRQ, int level);
>  
>  /* PowerPC hardware exceptions management helpers */
> diff --git a/include/hw/ppc/xics.h b/include/hw/ppc/xics.h
> index f81155c..58bb7c6 100644
> --- a/include/hw/ppc/xics.h
> +++ b/include/hw/ppc/xics.h
> @@ -220,4 +220,6 @@ void ics_set_irq_type(ICSState *ics, int srcno, bool lsi);
>  ICSState *xics_find_source(XICSState *icp, int irq);
>  void xics_add_ics(XICSState *xics);
>  
> -#endif /* XICS_H */
> +void xics_hmp_info_pic(Monitor *mon, const QDict *qdict);
> +
> +#endif /* __XICS_H__ */
> diff --git a/monitor.c b/monitor.c
> index 5c00373..e9009de 100644
> --- a/monitor.c
> +++ b/monitor.c
> @@ -90,6 +90,10 @@
>  #include "hw/s390x/storage-keys.h"
>  #endif
>  
> +#if defined(TARGET_PPC)
> +#include "hw/ppc/ppc.h"
> +#endif
> +
>  /*
>   * Supported types:
>   *

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [PATCH v4 9/9] ppc/xics: move set_nr_{irqs, servers} to xics.c
  2016-09-19  6:29 ` [Qemu-devel] [PATCH v4 9/9] ppc/xics: move set_nr_{irqs, servers} to xics.c Nikunj A Dadhania
@ 2016-09-22  0:14   ` David Gibson
  0 siblings, 0 replies; 38+ messages in thread
From: David Gibson @ 2016-09-22  0:14 UTC (permalink / raw)
  To: Nikunj A Dadhania; +Cc: qemu-ppc, qemu-devel, benh, clg

[-- Attachment #1: Type: text/plain, Size: 21850 bytes --]

On Mon, Sep 19, 2016 at 11:59:37AM +0530, Nikunj A Dadhania wrote:
> Get this duplicate code in the base implementation.
> 
> Signed-off-by: Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>
> ---
>  hw/intc/xics.c        | 74 ++++++++++++++++++++++++++++++++++++++++++++-------
>  hw/intc/xics_kvm.c    | 34 +++--------------------
>  hw/intc/xics_native.c | 51 +++++++++++++++++++++--------------
>  hw/intc/xics_spapr.c  | 49 +++++++++-------------------------
>  include/hw/ppc/xics.h | 19 ++++++++++---
>  5 files changed, 126 insertions(+), 101 deletions(-)
> 
> diff --git a/hw/intc/xics.c b/hw/intc/xics.c
> index 4ac2d00..9fbf962 100644
> --- a/hw/intc/xics.c
> +++ b/hw/intc/xics.c
> @@ -54,8 +54,9 @@ int xics_get_cpu_index_by_dt_id(int cpu_dt_id)
>  void xics_cpu_destroy(XICSState *xics, PowerPCCPU *cpu)
>  {
>      CPUState *cs = CPU(cpu);
> -    ICPState *ss = &xics->ss[cs->cpu_index];
> +    ICPState *ss;
>  
> +    ss = xics->ss + sizeof(ICPState) * cs->cpu_index;
>      assert(cs->cpu_index < xics->nr_servers);
>      assert(cs == ss->cs);
>  
> @@ -67,9 +68,10 @@ void xics_cpu_setup(XICSState *xics, PowerPCCPU *cpu)
>  {
>      CPUState *cs = CPU(cpu);
>      CPUPPCState *env = &cpu->env;
> -    ICPState *ss = &xics->ss[cs->cpu_index];
> +    ICPState *ss;
>      XICSStateClass *info = XICS_COMMON_GET_CLASS(xics);
>  
> +    ss = xics->ss + sizeof(ICPState) * cs->cpu_index;
>      assert(cs->cpu_index < xics->nr_servers);
>  
>      ss->cs = cs;
> @@ -101,10 +103,12 @@ static void xics_common_reset(DeviceState *d)
>  {
>      XICSState *xics = XICS_COMMON(d);
>      ICSState *ics;
> +    ICPState *ss;
>      int i;
>  
>      for (i = 0; i < xics->nr_servers; i++) {
> -        device_reset(DEVICE(&xics->ss[i]));
> +        ss = xics->ss + sizeof(ICPState) * i;
> +        device_reset(DEVICE(ss));
>      }
>  
>      QLIST_FOREACH(ics, &xics->ics, list) {
> @@ -193,6 +197,7 @@ static void xics_common_initfn(Object *obj)
>      XICSState *xics = XICS_COMMON(obj);
>  
>      QLIST_INIT(&xics->ics);
> +    xics->ss_class = object_class_by_name(TYPE_ICP);
>      object_property_add(obj, "nr_irqs", "int",
>                          xics_prop_get_nr_irqs, xics_prop_set_nr_irqs,
>                          NULL, NULL, NULL);
> @@ -201,7 +206,15 @@ static void xics_common_initfn(Object *obj)
>                          NULL, NULL, NULL);
>  
>      /* For exclusive use of monitor command */
> -    g_xics = XICS_COMMON(obj);
> +    g_xics = xics;

Looks like this change should be folded into the patch introducing g_xics.

> +}
> +
> +static void xics_common_realize(DeviceState *dev, Error **errp)
> +{
> +    XICSState *xics = XICS_COMMON(dev);
> +    XICSStateClass *xsc = XICS_COMMON_GET_CLASS(xics);
> +
> +    xsc->realize(dev, errp);
>  }
>  
>  static void xics_common_class_init(ObjectClass *oc, void *data)
> @@ -209,6 +222,7 @@ static void xics_common_class_init(ObjectClass *oc, void *data)
>      DeviceClass *dc = DEVICE_CLASS(oc);
>  
>      dc->reset = xics_common_reset;
> +    dc->realize = xics_common_realize;
>  }
>  
>  static const TypeInfo xics_common_info = {
> @@ -277,7 +291,7 @@ static void icp_check_ipi(ICPState *ss)
>  
>  static void icp_resend(XICSState *xics, int server)
>  {
> -    ICPState *ss = xics->ss + server;
> +    ICPState *ss = xics->ss + server * sizeof(ICPState);
>      ICSState *ics;
>  
>      if (ss->mfrr < CPPR(ss)) {
> @@ -290,7 +304,7 @@ static void icp_resend(XICSState *xics, int server)
>  
>  void icp_set_cppr(XICSState *xics, int server, uint8_t cppr)
>  {
> -    ICPState *ss = xics->ss + server;
> +    ICPState *ss = xics->ss + server * sizeof(ICPState);
>      uint8_t old_cppr;
>      uint32_t old_xisr;
>  
> @@ -317,7 +331,7 @@ void icp_set_cppr(XICSState *xics, int server, uint8_t cppr)
>  
>  void icp_set_mfrr(XICSState *xics, int server, uint8_t mfrr)
>  {
> -    ICPState *ss = xics->ss + server;
> +    ICPState *ss = xics->ss + server * sizeof(ICPState);
>  
>      ss->mfrr = mfrr;
>      if (mfrr < CPPR(ss)) {
> @@ -349,7 +363,7 @@ uint32_t icp_ipoll(ICPState *ss, uint32_t *mfrr)
>  
>  void icp_eoi(XICSState *xics, int server, uint32_t xirr)
>  {
> -    ICPState *ss = xics->ss + server;
> +    ICPState *ss = xics->ss + server * sizeof(ICPState);
>      ICSState *ics;
>      uint32_t irq;
>  
> @@ -370,7 +384,7 @@ void icp_eoi(XICSState *xics, int server, uint32_t xirr)
>  static void icp_irq(ICSState *ics, int server, int nr, uint8_t priority)
>  {
>      XICSState *xics = ics->xics;
> -    ICPState *ss = xics->ss + server;
> +    ICPState *ss = xics->ss + server * sizeof(ICPState);
>  
>      trace_xics_icp_irq(server, nr, priority);
>  
> @@ -488,6 +502,14 @@ static const TypeInfo icp_info = {
>      .class_size = sizeof(ICPStateClass),
>  };
>  
> +static const TypeInfo icp_native_info = {
> +    .name = TYPE_NATIVE_ICP,
> +    .parent = TYPE_ICP,
> +    .instance_size = sizeof(ICPNative),
> +    .class_init = icp_class_init,
> +    .class_size = sizeof(ICPStateClass),
> +};
> +

Introducing a whole new subclass doesn't seem to be covered by the
commit message...

>  /*
>   * ICS: Source layer
>   */
> @@ -689,7 +711,7 @@ void xics_hmp_info_pic(Monitor *mon, const QDict *qdict)
>      uint32_t i;
>  
>      for (i = 0; i < g_xics->nr_servers; i++) {
> -        ICPState *icp = &g_xics->ss[i];
> +        ICPState *icp = g_xics->ss + i * sizeof(ICPState);
>  
>          if (!icp->output) {
>              continue;
> @@ -829,12 +851,44 @@ void ics_set_irq_type(ICSState *ics, int srcno, bool lsi)
>          lsi ? XICS_FLAGS_IRQ_LSI : XICS_FLAGS_IRQ_MSI;
>  }
>  
> +void xics_set_nr_irqs(XICSState *xics, uint32_t nr_irqs, Error **errp)
> +{
> +    ICSState *ics = QLIST_FIRST(&xics->ics);
> +
> +    /* This needs to be deprecated ... */

Could you actually deprecate this, instead of moving it around?

> +    xics->nr_irqs = nr_irqs;
> +    if (ics) {
> +        ics->nr_irqs = nr_irqs;
> +    }
> +}
> +
> +void xics_set_nr_servers(XICSState *xics, uint32_t nr_servers, Error **errp)
> +{
> +    int i;
> +    const char *typename = object_class_get_name(xics->ss_class);
> +    size_t size = object_type_get_instance_size(typename);
> +
> +    xics->nr_servers = nr_servers;
> +
> +    xics->ss = g_malloc0(xics->nr_servers * size);
> +    for (i = 0; i < xics->nr_servers; i++) {
> +        char buffer[32];
> +        void *obj;
> +
> +        obj = xics->ss + size * i;
> +        object_initialize(obj, size, typename);
> +        snprintf(buffer, sizeof(buffer), "icp[%d]", i);
> +        object_property_add_child(OBJECT(xics), buffer, obj, errp);
> +    }
> +}
> +
>  static void xics_register_types(void)
>  {
>      type_register_static(&xics_common_info);
>      type_register_static(&ics_simple_info);
>      type_register_static(&ics_base_info);
>      type_register_static(&icp_info);
> +    type_register_static(&icp_native_info);
>  }
>  
>  type_init(xics_register_types)
> diff --git a/hw/intc/xics_kvm.c b/hw/intc/xics_kvm.c
> index 89862df..b095b9e 100644
> --- a/hw/intc/xics_kvm.c
> +++ b/hw/intc/xics_kvm.c
> @@ -362,35 +362,6 @@ static void xics_kvm_cpu_setup(XICSState *xics, PowerPCCPU *cpu)
>      }
>  }
>  
> -static void xics_kvm_set_nr_irqs(XICSState *xics, uint32_t nr_irqs,
> -                                 Error **errp)
> -{
> -    ICSState *ics = QLIST_FIRST(&xics->ics);
> -
> -    /* This needs to be deprecated ... */
> -    xics->nr_irqs = nr_irqs;
> -    if (ics) {
> -        ics->nr_irqs = nr_irqs;
> -    }
> -}
> -
> -static void xics_kvm_set_nr_servers(XICSState *xics, uint32_t nr_servers,
> -                                    Error **errp)
> -{
> -    int i;
> -
> -    xics->nr_servers = nr_servers;
> -
> -    xics->ss = g_malloc0(xics->nr_servers * sizeof(ICPState));
> -    for (i = 0; i < xics->nr_servers; i++) {
> -        char buffer[32];
> -        object_initialize(&xics->ss[i], sizeof(xics->ss[i]), TYPE_KVM_ICP);
> -        snprintf(buffer, sizeof(buffer), "icp[%d]", i);
> -        object_property_add_child(OBJECT(xics), buffer, OBJECT(&xics->ss[i]),
> -                                  errp);
> -    }
> -}
> -
>  static void rtas_dummy(PowerPCCPU *cpu, sPAPRMachineState *spapr,
>                         uint32_t token,
>                         uint32_t nargs, target_ulong args,
> @@ -492,6 +463,7 @@ static void xics_kvm_initfn(Object *obj)
>      XICSState *xics = XICS_COMMON(obj);
>      ICSState *ics;
>  
> +    xics->ss_class = object_class_by_name(TYPE_KVM_ICP);
>      ics = ICS_SIMPLE(object_new(TYPE_ICS_KVM));
>      object_property_add_child(obj, "ics", OBJECT(ics), NULL);
>      ics->xics = xics;
> @@ -505,8 +477,8 @@ static void xics_kvm_class_init(ObjectClass *oc, void *data)
>  
>      dc->realize = xics_kvm_realize;
>      xsc->cpu_setup = xics_kvm_cpu_setup;
> -    xsc->set_nr_irqs = xics_kvm_set_nr_irqs;
> -    xsc->set_nr_servers = xics_kvm_set_nr_servers;
> +    xsc->set_nr_irqs = xics_set_nr_irqs;
> +    xsc->set_nr_servers = xics_set_nr_servers;
>  }
>  
>  static const TypeInfo xics_spapr_kvm_info = {
> diff --git a/hw/intc/xics_native.c b/hw/intc/xics_native.c
> index 26e45cc..db2fd4d 100644
> --- a/hw/intc/xics_native.c
> +++ b/hw/intc/xics_native.c
> @@ -38,11 +38,19 @@
>  /* #define DEBUG_MM(fmt...)      printf(fmt) */
>  #define DEBUG_MM(fmt...)        do { } while (0)
>  
> +typedef struct XICSNative {
> +    /*< private >*/
> +    XICSState xics;
> +
> +    /*< public >*/
> +    MemoryRegion icp_mmio;
> +} XICSNative;
> +
>  static void xics_native_initfn(Object *obj)
>  {
> -    XICSState *xics = XICS_NATIVE(obj);
> +    XICSState *xics = XICS_COMMON(obj);
>  
> -    QLIST_INIT(&xics->ics);
> +    xics->ss_class = object_class_by_name(TYPE_NATIVE_ICP);

ss_class should be a class field, not an instance field.

>  }
>  
>  static uint64_t icp_mm_read(void *opaque, hwaddr addr, unsigned width)
> @@ -51,6 +59,7 @@ static uint64_t icp_mm_read(void *opaque, hwaddr addr, unsigned width)
>      int32_t cpu_id, server;
>      uint32_t val;
>      ICPState *ss;
> +    ICPNative *icpn;
>      bool byte0 = (width == 1 && (addr & 0x3) == 0);
>  
>      cpu_id = (addr & (ICP_MM_SIZE - 1)) >> 12;
> @@ -59,7 +68,8 @@ static uint64_t icp_mm_read(void *opaque, hwaddr addr, unsigned width)
>          fprintf(stderr, "XICS: Bad ICP server %d\n", server);
>          goto bad_access;
>      }
> -    ss = &s->ss[server];
> +    icpn = s->ss + server * sizeof(ICPNative);
> +    ss = &icpn->icp;
>  
>      switch (addr & 0xffc) {
>      case 0: /* poll */
> @@ -88,21 +98,21 @@ static uint64_t icp_mm_read(void *opaque, hwaddr addr, unsigned width)
>          break;
>      case 16:
>          if (width == 4) {
> -            val = ss->links[0];
> +            val = icpn->links[0];
>          } else {
>              goto bad_access;
>          }
>          break;
>      case 20:
>          if (width == 4) {
> -            val = ss->links[1];
> +            val = icpn->links[1];
>          } else {
>              goto bad_access;
>          }
>          break;
>      case 24:
>          if (width == 4) {
> -            val = ss->links[2];
> +            val = icpn->links[2];
>          } else {
>              goto bad_access;
>          }
> @@ -125,7 +135,7 @@ static void icp_mm_write(void *opaque, hwaddr addr, uint64_t val,
>  {
>      XICSState *s = opaque;
>      int32_t cpu_id, server;
> -    ICPState *ss;
> +    ICPNative *icpn;
>      bool byte0 = (width == 1 && (addr & 0x3) == 0);
>  
>      cpu_id = (addr & (ICP_MM_SIZE - 1)) >> 12;
> @@ -134,7 +144,8 @@ static void icp_mm_write(void *opaque, hwaddr addr, uint64_t val,
>          fprintf(stderr, "XICS: Bad ICP server %d\n", server);
>          goto bad_access;
>      }
> -    ss = &s->ss[server];
> +    icpn = s->ss + server * sizeof(ICPNative);
> +    ss = &icpn->icp;
>  
>      DEBUG_MM("icp_mm_write(addr=%016llx,serv=0x%x/%d,off=%d,w=%d,val=0x%08x)\n",
>               (unsigned long long)addr, cpu_id, server,
> @@ -159,21 +170,21 @@ static void icp_mm_write(void *opaque, hwaddr addr, uint64_t val,
>          break;
>      case 16:
>          if (width == 4) {
> -            ss->links[0] = val;
> +            icpn->links[0] = val;
>          } else {
>              goto bad_access;
>          }
>          break;
>      case 20:
>          if (width == 4) {
> -            ss->links[1] = val;
> +            icpn->links[1] = val;
>          } else {
>              goto bad_access;
>          }
>          break;
>      case 24:
>          if (width == 4) {
> -            ss->links[2] = val;
> +            icpn->links[2] = val;
>          } else {
>              goto bad_access;
>          }
> @@ -245,8 +256,9 @@ void xics_create_native_icp_node(XICSState *s, void *fdt,
>  
>  static void xics_native_realize(DeviceState *dev, Error **errp)
>  {
> -    XICSState *s = XICS_NATIVE(dev);
> -    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
> +    XICSNative *n = XICS_NATIVE(dev);
> +    XICSState *s = XICS_COMMON(dev);
> +    SysBusDevice *sbd = SYS_BUS_DEVICE(s);
>      Error *error = NULL;
>      int i;
>  
> @@ -256,13 +268,14 @@ static void xics_native_realize(DeviceState *dev, Error **errp)
>      }
>  
>      /* Register MMIO regions */
> -    memory_region_init_io(&s->icp_mmio, OBJECT(s), &icp_mm_ops, s, "icp",
> +    memory_region_init_io(&n->icp_mmio, OBJECT(s), &icp_mm_ops, s, "icp",
>                            ICP_MM_SIZE);
> -    sysbus_init_mmio(sbd, &s->icp_mmio);
> +    sysbus_init_mmio(sbd, &n->icp_mmio);
>      sysbus_mmio_map(sbd, 0, ICP_MM_BASE);
>  
>      for (i = 0; i < s->nr_servers; i++) {
> -        object_property_set_bool(OBJECT(&s->ss[i]), true, "realized", &error);
> +        ICPNative *icpn = s->ss + i * sizeof(ICPNative);
> +        object_property_set_bool(OBJECT(icpn), true, "realized", &error);
>          if (error) {
>              error_propagate(errp, error);
>              return;
> @@ -272,20 +285,18 @@ static void xics_native_realize(DeviceState *dev, Error **errp)
>  
>  static void xics_native_class_init(ObjectClass *oc, void *data)
>  {
> -    DeviceClass *dc = DEVICE_CLASS(oc);
>      XICSStateClass *xsc = XICS_NATIVE_CLASS(oc);
>  
> -    dc->realize = xics_native_realize;
> +    xsc->realize = xics_native_realize;
>      xsc->set_nr_servers = xics_set_nr_servers;
>  }
>  
>  static const TypeInfo xics_native_info = {
>      .name          = TYPE_XICS_NATIVE,
>      .parent        = TYPE_XICS_COMMON,
> -    .instance_size = sizeof(XICSState),
> +    .instance_size = sizeof(XICSNative),
>      .class_size = sizeof(XICSStateClass),
>      .class_init    = xics_native_class_init,
> -    .instance_init = xics_native_initfn,
>  };
>  
>  static void xics_native_register_types(void)
> diff --git a/hw/intc/xics_spapr.c b/hw/intc/xics_spapr.c
> index 4dd1399..0644942 100644
> --- a/hw/intc/xics_spapr.c
> +++ b/hw/intc/xics_spapr.c
> @@ -67,7 +67,8 @@ static target_ulong h_xirr(PowerPCCPU *cpu, sPAPRMachineState *spapr,
>                             target_ulong opcode, target_ulong *args)
>  {
>      CPUState *cs = CPU(cpu);
> -    uint32_t xirr = icp_accept(spapr->xics->ss + cs->cpu_index);
> +    uint32_t xirr = icp_accept(spapr->xics->ss +
> +                               cs->cpu_index * sizeof(ICPState));
>  
>      args[0] = xirr;
>      return H_SUCCESS;
> @@ -77,9 +78,11 @@ static target_ulong h_xirr_x(PowerPCCPU *cpu, sPAPRMachineState *spapr,
>                               target_ulong opcode, target_ulong *args)
>  {
>      CPUState *cs = CPU(cpu);
> -    ICPState *ss = &spapr->xics->ss[cs->cpu_index];
> -    uint32_t xirr = icp_accept(ss);
> +    ICPState *ss;
> +    uint32_t xirr;
>  
> +    ss = spapr->xics->ss + cs->cpu_index * sizeof(ICPState);
> +    xirr = icp_accept(ss);
>      args[0] = xirr;
>      args[1] = cpu_get_host_ticks();
>      return H_SUCCESS;
> @@ -100,7 +103,8 @@ static target_ulong h_ipoll(PowerPCCPU *cpu, sPAPRMachineState *spapr,
>  {
>      CPUState *cs = CPU(cpu);
>      uint32_t mfrr;
> -    uint32_t xirr = icp_ipoll(spapr->xics->ss + cs->cpu_index, &mfrr);
> +    uint32_t xirr = icp_ipoll(spapr->xics->ss +
> +                              cs->cpu_index * sizeof(ICPState), &mfrr);
>  
>      args[0] = xirr;
>      args[1] = mfrr;
> @@ -234,35 +238,6 @@ static void rtas_int_on(PowerPCCPU *cpu, sPAPRMachineState *spapr,
>      rtas_st(rets, 0, RTAS_OUT_SUCCESS);
>  }
>  
> -static void xics_spapr_set_nr_irqs(XICSState *xics, uint32_t nr_irqs,
> -                                   Error **errp)
> -{
> -    ICSState *ics = QLIST_FIRST(&xics->ics);
> -
> -    /* This needs to be deprecated ... */
> -    xics->nr_irqs = nr_irqs;
> -    if (ics) {
> -        ics->nr_irqs = nr_irqs;
> -    }
> -}
> -
> -static void xics_spapr_set_nr_servers(XICSState *xics, uint32_t nr_servers,
> -                                      Error **errp)
> -{
> -    int i;
> -
> -    xics->nr_servers = nr_servers;
> -
> -    xics->ss = g_malloc0(xics->nr_servers * sizeof(ICPState));
> -    for (i = 0; i < xics->nr_servers; i++) {
> -        char buffer[32];
> -        object_initialize(&xics->ss[i], sizeof(xics->ss[i]), TYPE_ICP);
> -        snprintf(buffer, sizeof(buffer), "icp[%d]", i);
> -        object_property_add_child(OBJECT(xics), buffer, OBJECT(&xics->ss[i]),
> -                                  errp);
> -    }
> -}
> -
>  static void xics_spapr_realize(DeviceState *dev, Error **errp)
>  {
>      XICSState *xics = XICS_SPAPR(dev);
> @@ -297,8 +272,8 @@ static void xics_spapr_realize(DeviceState *dev, Error **errp)
>      }
>  
>      for (i = 0; i < xics->nr_servers; i++) {
> -        object_property_set_bool(OBJECT(&xics->ss[i]), true, "realized",
> -                                 &error);
> +        ICPState *ss = xics->ss + i * sizeof(ICPState);
> +        object_property_set_bool(OBJECT(ss), true, "realized", &error);
>          if (error) {
>              error_propagate(errp, error);
>              return;
> @@ -319,8 +294,8 @@ static void xics_spapr_class_init(ObjectClass *oc, void *data)
>      XICSStateClass *xsc = XICS_SPAPR_CLASS(oc);
>  
>      dc->realize = xics_spapr_realize;
> -    xsc->set_nr_irqs = xics_spapr_set_nr_irqs;
> -    xsc->set_nr_servers = xics_spapr_set_nr_servers;
> +    xsc->set_nr_irqs = xics_set_nr_irqs;
> +    xsc->set_nr_servers = xics_set_nr_servers;
>  }
>  
>  static const TypeInfo xics_spapr_info = {
> diff --git a/include/hw/ppc/xics.h b/include/hw/ppc/xics.h
> index 58bb7c6..0a427d7 100644
> --- a/include/hw/ppc/xics.h
> +++ b/include/hw/ppc/xics.h
> @@ -45,7 +45,7 @@
>       OBJECT_CHECK(KVMXICSState, (obj), TYPE_XICS_SPAPR_KVM)
>  
>  #define TYPE_XICS_NATIVE "xics-native"
> -#define XICS_NATIVE(obj) OBJECT_CHECK(XICSState, (obj), TYPE_XICS_NATIVE)
> +#define XICS_NATIVE(obj) OBJECT_CHECK(XICSNative, (obj), TYPE_XICS_NATIVE)
>  
>  #define XICS_COMMON_CLASS(klass) \
>       OBJECT_CLASS_CHECK(XICSStateClass, (klass), TYPE_XICS_COMMON)
> @@ -71,6 +71,7 @@ typedef struct XICSStateClass XICSStateClass;
>  typedef struct XICSState XICSState;
>  typedef struct ICPStateClass ICPStateClass;
>  typedef struct ICPState ICPState;
> +typedef struct ICPNative ICPNative;
>  typedef struct ICSStateClass ICSStateClass;
>  typedef struct ICSState ICSState;
>  typedef struct ICSIRQState ICSIRQState;
> @@ -78,6 +79,7 @@ typedef struct ICSIRQState ICSIRQState;
>  struct XICSStateClass {
>      DeviceClass parent_class;
>  
> +    DeviceRealize realize;
>      void (*cpu_setup)(XICSState *icp, PowerPCCPU *cpu);
>      void (*set_nr_irqs)(XICSState *icp, uint32_t nr_irqs, Error **errp);
>      void (*set_nr_servers)(XICSState *icp, uint32_t nr_servers, Error **errp);
> @@ -89,9 +91,9 @@ struct XICSState {
>      /*< public >*/
>      uint32_t nr_servers;
>      uint32_t nr_irqs;
> -    ICPState *ss;
> +    void *ss;
> +    ObjectClass *ss_class;
>      QLIST_HEAD(, ICSState) ics;
> -    MemoryRegion icp_mmio;
>  };
>  
>  #define TYPE_ICP "icp"
> @@ -100,6 +102,9 @@ struct XICSState {
>  #define TYPE_KVM_ICP "icp-kvm"
>  #define KVM_ICP(obj) OBJECT_CHECK(ICPState, (obj), TYPE_KVM_ICP)
>  
> +#define TYPE_NATIVE_ICP "icp-native"
> +#define NATIVE_ICP(obj) OBJECT_CHECK(ICPNative, (obj), TYPE_NATIVE_ICP)
> +
>  #define ICP_CLASS(klass) \
>       OBJECT_CLASS_CHECK(ICPStateClass, (klass), TYPE_ICP)
>  #define ICP_GET_CLASS(obj) \
> @@ -123,6 +128,12 @@ struct ICPState {
>      uint8_t mfrr;
>      qemu_irq output;
>      bool cap_irq_xics_enabled;
> +};
> +
> +struct ICPNative {
> +    /*<private>*/
> +    ICPState icp;
> +    /*<public>*/
>      uint32_t links[3];
>  };
>  
> @@ -199,6 +210,8 @@ void xics_spapr_free(XICSState *icp, int irq, int num);
>  
>  void xics_cpu_setup(XICSState *icp, PowerPCCPU *cpu);
>  void xics_cpu_destroy(XICSState *icp, PowerPCCPU *cpu);
> +void xics_set_nr_irqs(XICSState *xics, uint32_t nr_irqs, Error **errp);
> +void xics_set_nr_servers(XICSState *xics, uint32_t nr_servers, Error **errp);
>  
>  void xics_create_native_icp_node(XICSState *s, void *fdt,
>                                   uint32_t base, uint32_t count);

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [PATCH v4 5/9] ppc/xics: Use a helper to add a new ICS
  2016-09-21 23:40   ` David Gibson
@ 2016-09-22  6:21     ` Cédric Le Goater
  2016-09-23  0:37       ` David Gibson
  0 siblings, 1 reply; 38+ messages in thread
From: Cédric Le Goater @ 2016-09-22  6:21 UTC (permalink / raw)
  To: David Gibson, Nikunj A Dadhania; +Cc: qemu-ppc, qemu-devel, benh

On 09/22/2016 01:40 AM, David Gibson wrote:
> On Mon, Sep 19, 2016 at 11:59:33AM +0530, Nikunj A Dadhania wrote:
>> From: Benjamin Herrenschmidt <benh@kernel.crashing.org>
>>
>> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
>> [Move object allocation and adding child to the helper]
>> Signed-off-by: Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>
>> Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
>> ---
>>  hw/intc/xics.c        | 10 ++++++++++
>>  hw/intc/xics_spapr.c  |  6 +-----
>>  include/hw/ppc/xics.h |  1 +
>>  3 files changed, 12 insertions(+), 5 deletions(-)
>>
>> diff --git a/hw/intc/xics.c b/hw/intc/xics.c
>> index 05e938f..c7901c4 100644
>> --- a/hw/intc/xics.c
>> +++ b/hw/intc/xics.c
>> @@ -109,6 +109,16 @@ static void xics_common_reset(DeviceState *d)
>>      }
>>  }
>>  
>> +void xics_add_ics(XICSState *xics)
>> +{
>> +    ICSState *ics;
>> +
>> +    ics = ICS(object_new(TYPE_ICS));
>> +    object_property_add_child(OBJECT(xics), "ics", OBJECT(ics), NULL);
> 
> You'll need to construct a name here so you don't have all the ics
> objects called an indistinguishable "ics".

Yes, exactly, and so PowerNV does not use it because at least three ics 
are needed : 

qemu) info qom-tree 
/machine (powernv-machine)
  /unattached (container)
    /sysbus (System)
    /ipmi-bt[0] (qemu:memory-region)
    /device[0] (pnv-phb3)
      /ics-phb-lsi (ics)
      /ics-phb-msi (phb3-msi)

      ...

      /psi (pnv-psi)
        /xscom-psi[0] (qemu:memory-region)
        /psihb[0] (qemu:memory-region)
        /ics-psi (ics)


I think we can drop that patch. 


However some routine like this one :

+void xics_insert_ics(XICSState *xics, ICSState *ics)
+{
+    ics->xics = xics;
+    QLIST_INSERT_HEAD(&xics->ics, ics, list);
+}
+

would be useful to hide the list details below xics : 


    /* link in the PSI ICS */
    xics_insert_ics(XICS_COMMON(&chip->xics), &chip->psi.ics);

    ....

    /* insert the ICS in XICS */
    xics_insert_ics(xics, phb->lsi_ics);
    xics_insert_ics(xics, ICS_BASE(phb->msis));


Cheers,

C. 

>> +    ics->xics = xics;
>> +    QLIST_INSERT_HEAD(&xics->ics, ics, list);
>> +}
>> +
>>  static void xics_prop_get_nr_irqs(Object *obj, Visitor *v, const char *name,
>>                                    void *opaque, Error **errp)
>>  {
>> diff --git a/hw/intc/xics_spapr.c b/hw/intc/xics_spapr.c
>> index 0b0845d..270f20e 100644
>> --- a/hw/intc/xics_spapr.c
>> +++ b/hw/intc/xics_spapr.c
>> @@ -305,12 +305,8 @@ static void xics_spapr_realize(DeviceState *dev, Error **errp)
>>  static void xics_spapr_initfn(Object *obj)
>>  {
>>      XICSState *xics = XICS_SPAPR(obj);
>> -    ICSState *ics;
>>  
>> -    ics = ICS(object_new(TYPE_ICS));
>> -    object_property_add_child(obj, "ics", OBJECT(ics), NULL);
>> -    ics->xics = xics;
>> -    QLIST_INSERT_HEAD(&xics->ics, ics, list);
>> +    xics_add_ics(xics);
>>  }
>>  
>>  static void xics_spapr_class_init(ObjectClass *oc, void *data)
>> diff --git a/include/hw/ppc/xics.h b/include/hw/ppc/xics.h
>> index e49a2da..a7a1e54 100644
>> --- a/include/hw/ppc/xics.h
>> +++ b/include/hw/ppc/xics.h
>> @@ -197,5 +197,6 @@ void ics_write_xive(ICSState *ics, int nr, int server,
>>  void ics_set_irq_type(ICSState *ics, int srcno, bool lsi);
>>  
>>  ICSState *xics_find_source(XICSState *icp, int irq);
>> +void xics_add_ics(XICSState *xics);
>>  
>>  #endif /* XICS_H */
> 

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [PATCH v4 7/9] ppc/xics: Add "native" XICS subclass
  2016-09-22  0:02   ` [Qemu-devel] " David Gibson
@ 2016-09-22  6:27     ` Cédric Le Goater
  0 siblings, 0 replies; 38+ messages in thread
From: Cédric Le Goater @ 2016-09-22  6:27 UTC (permalink / raw)
  To: David Gibson, Nikunj A Dadhania; +Cc: qemu-ppc, qemu-devel, benh

On 09/22/2016 02:02 AM, David Gibson wrote:
> On Mon, Sep 19, 2016 at 11:59:35AM +0530, Nikunj A Dadhania wrote:
>> From: Benjamin Herrenschmidt <benh@kernel.crashing.org>
>>
>> This provides MMIO based ICP access as found on POWER8
>>
>> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
>> Signed-off-by: Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>
>> ---
>>  default-configs/ppc64-softmmu.mak |   3 +-
>>  hw/intc/Makefile.objs             |   1 +
>>  hw/intc/xics_native.c             | 295 ++++++++++++++++++++++++++++++++++++++
>>  include/hw/ppc/xics.h             |  14 ++
>>  4 files changed, 312 insertions(+), 1 deletion(-)
>>  create mode 100644 hw/intc/xics_native.c
>>
>> diff --git a/default-configs/ppc64-softmmu.mak b/default-configs/ppc64-softmmu.mak
>> index c4be59f..315e30b 100644
>> --- a/default-configs/ppc64-softmmu.mak
>> +++ b/default-configs/ppc64-softmmu.mak
>> @@ -48,8 +48,9 @@ CONFIG_PLATFORM_BUS=y
>>  CONFIG_ETSEC=y
>>  CONFIG_LIBDECNUMBER=y
>>  # For pSeries
>> -CONFIG_XICS=$(CONFIG_PSERIES)
>> +CONFIG_XICS=$(or $(CONFIG_PSERIES),$(CONFIG_POWERNV))
>>  CONFIG_XICS_SPAPR=$(CONFIG_PSERIES)
>> +CONFIG_XICS_NATIVE=$(CONFIG_POWERNV)
>>  CONFIG_XICS_KVM=$(and $(CONFIG_PSERIES),$(CONFIG_KVM))
>>  # For PReP
>>  CONFIG_MC146818RTC=y
>> diff --git a/hw/intc/Makefile.objs b/hw/intc/Makefile.objs
>> index 05ec21b..7be5dfc 100644
>> --- a/hw/intc/Makefile.objs
>> +++ b/hw/intc/Makefile.objs
>> @@ -31,6 +31,7 @@ obj-$(CONFIG_RASPI) += bcm2835_ic.o bcm2836_control.o
>>  obj-$(CONFIG_SH4) += sh_intc.o
>>  obj-$(CONFIG_XICS) += xics.o
>>  obj-$(CONFIG_XICS_SPAPR) += xics_spapr.o
>> +obj-$(CONFIG_XICS_NATIVE) += xics_native.o
>>  obj-$(CONFIG_XICS_KVM) += xics_kvm.o
>>  obj-$(CONFIG_ALLWINNER_A10_PIC) += allwinner-a10-pic.o
>>  obj-$(CONFIG_S390_FLIC) += s390_flic.o
>> diff --git a/hw/intc/xics_native.c b/hw/intc/xics_native.c
>> new file mode 100644
>> index 0000000..26e45cc
>> --- /dev/null
>> +++ b/hw/intc/xics_native.c
>> @@ -0,0 +1,295 @@
>> +/*
>> + * QEMU PowerPC hardware System Emulator
>> + *
>> + * Native version of ICS/ICP
>> + *
>> + * Copyright (c) 2010,2011 David Gibson, IBM Corporation.
>> + *
>> + * Permission is hereby granted, free of charge, to any person obtaining a copy
>> + * of this software and associated documentation files (the "Software"), to deal
>> + * in the Software without restriction, including without limitation the rights
>> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
>> + * copies of the Software, and to permit persons to whom the Software is
>> + * furnished to do so, subject to the following conditions:
>> + *
>> + * The above copyright notice and this permission notice shall be included in
>> + * all copies or substantial portions of the Software.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
>> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
>> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
>> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
>> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
>> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
>> + * THE SOFTWARE.
>> + *
>> + */
>> +
>> +#include "qemu/osdep.h"
>> +#include "hw/hw.h"
>> +#include "trace.h"
>> +#include "qemu/timer.h"
>> +#include "hw/ppc/xics.h"
>> +#include "qapi/visitor.h"
>> +#include "qapi/error.h"
>> +
>> +#include <libfdt.h>
>> +
>> +/* #define DEBUG_MM(fmt...)      printf(fmt) */
>> +#define DEBUG_MM(fmt...)        do { } while (0)
>> +
>> +static void xics_native_initfn(Object *obj)
>> +{
>> +    XICSState *xics = XICS_NATIVE(obj);
>> +
>> +    QLIST_INIT(&xics->ics);
> 
> Isn't this redundant with the QLIST_INIT() in the common initfn?
> 
>> +}
>> +
>> +static uint64_t icp_mm_read(void *opaque, hwaddr addr, unsigned width)
>> +{
>> +    XICSState *s = opaque;
>> +    int32_t cpu_id, server;
>> +    uint32_t val;
>> +    ICPState *ss;
>> +    bool byte0 = (width == 1 && (addr & 0x3) == 0);
>> +
>> +    cpu_id = (addr & (ICP_MM_SIZE - 1)) >> 12;
>> +    server = get_cpu_index_by_dt_id(cpu_id);
>> +    if (server < 0) {
>> +        fprintf(stderr, "XICS: Bad ICP server %d\n", server);
> 
> Please use error_report() instead of raw fprintf()s.
> 
>> +        goto bad_access;
>> +    }
>> +    ss = &s->ss[server];
>> +
>> +    switch (addr & 0xffc) {
>> +    case 0: /* poll */
>> +        val = icp_ipoll(ss, NULL);
>> +        if (byte0) {
>> +            val >>= 24;
>> +        } else if (width != 4) {
>> +            goto bad_access;
>> +        }
>> +        break;
>> +    case 4: /* xirr */
>> +        if (byte0) {
>> +            val = icp_ipoll(ss, NULL) >> 24;
>> +        } else if (width == 4) {
>> +            val = icp_accept(ss);
>> +        } else {
>> +            goto bad_access;
>> +        }
>> +        break;
>> +    case 12:
>> +        if (byte0) {
>> +            val = ss->mfrr;
>> +        } else {
>> +            goto bad_access;
>> +        }
>> +        break;
>> +    case 16:
>> +        if (width == 4) {
>> +            val = ss->links[0];
>> +        } else {
>> +            goto bad_access;
>> +        }
>> +        break;
>> +    case 20:
>> +        if (width == 4) {
>> +            val = ss->links[1];
>> +        } else {
>> +            goto bad_access;
>> +        }
>> +        break;
>> +    case 24:
>> +        if (width == 4) {
>> +            val = ss->links[2];
>> +        } else {
>> +            goto bad_access;
>> +        }
>> +        break;
>> +    default:
>> +bad_access:
>> +        fprintf(stderr, "XICS: Bad ICP access %llx/%d\n",
>> +                (unsigned long long)addr, width);
>> +        val = 0xffffffff;
>> +    }
>> +    DEBUG_MM("icp_mm_read(addr=%016llx,serv=0x%x/%d,off=%d,w=%d,val=0x%08x)\n",
>> +             (unsigned long long)addr, cpu_id, server, (int)(addr & 0xffc),
>> +             width, val);
> 
> It's preferred to use trace-events rather than DEBUG macros.
> 
>> +
>> +    return val;
>> +}
>> +
>> +static void icp_mm_write(void *opaque, hwaddr addr, uint64_t val,
>> +                        unsigned width)
>> +{
>> +    XICSState *s = opaque;
>> +    int32_t cpu_id, server;
>> +    ICPState *ss;
>> +    bool byte0 = (width == 1 && (addr & 0x3) == 0);
>> +
>> +    cpu_id = (addr & (ICP_MM_SIZE - 1)) >> 12;
>> +    server = get_cpu_index_by_dt_id(cpu_id);
>> +    if (server < 0) {
>> +        fprintf(stderr, "XICS: Bad ICP server %d\n", server);
>> +        goto bad_access;
>> +    }
>> +    ss = &s->ss[server];
>> +
>> +    DEBUG_MM("icp_mm_write(addr=%016llx,serv=0x%x/%d,off=%d,w=%d,val=0x%08x)\n",
>> +             (unsigned long long)addr, cpu_id, server,
>> +             (int)(addr & 0xffc), width, (uint32_t)val);
>> +
>> +    switch (addr & 0xffc) {
>> +    case 4: /* xirr */
>> +        if (byte0) {
>> +            icp_set_cppr(s, server, val);
>> +        } else if (width == 4) {
>> +            icp_eoi(s, server, val);
>> +        } else {
>> +            goto bad_access;
>> +        }
>> +        break;
>> +    case 12:
>> +        if (byte0) {
>> +            icp_set_mfrr(s, server, val);
>> +        } else {
>> +            goto bad_access;
>> +        }
>> +        break;
>> +    case 16:
>> +        if (width == 4) {
>> +            ss->links[0] = val;
>> +        } else {
>> +            goto bad_access;
>> +        }
>> +        break;
>> +    case 20:
>> +        if (width == 4) {
>> +            ss->links[1] = val;
>> +        } else {
>> +            goto bad_access;
>> +        }
>> +        break;
>> +    case 24:
>> +        if (width == 4) {
>> +            ss->links[2] = val;
>> +        } else {
>> +            goto bad_access;
>> +        }
>> +        break;
>> +    default:
>> + bad_access:
>> +        val = 0xffffffff;
>> +    }
>> +}
>> +
>> +static const MemoryRegionOps icp_mm_ops = {
>> +    .read = icp_mm_read,
>> +    .write = icp_mm_write,
>> +    .valid.min_access_size = 1,
>> +    .valid.max_access_size = 4,
>> +    .impl.min_access_size = 1,
>> +    .impl.max_access_size = 4,
>> +    .endianness = DEVICE_BIG_ENDIAN,
>> +};
>> +
>> +#define _FDT(exp) \
>> +    do { \
>> +        int ret = (exp);                                           \
>> +        if (ret < 0) {                                             \
>> +            fprintf(stderr, "qemu: error creating device tree: %s: %s\n", \
>> +                    #exp, fdt_strerror(ret));                      \
>> +            exit(1);                                               \
>> +        }                                                          \
>> +    } while (0)
>> +
>> +void xics_create_native_icp_node(XICSState *s, void *fdt,
>> +                                 uint32_t base, uint32_t count)
>> +{
>> +    uint64_t addr;
>> +    char *name;
>> +    const char compat[] = "IBM,power8-icp\0IBM,ppc-xicp";
>> +    uint32_t irange[2], i, rsize;
>> +    uint64_t *reg;
>> +
>> +    addr = ICP_MM_BASE | (base << 12);
>> +
>> +    irange[0] = cpu_to_be32(base);
>> +    irange[1] = cpu_to_be32(count);
>> +
>> +    rsize = sizeof(uint64_t) * 2 * count;
>> +    reg = g_malloc(rsize);
>> +    for (i = 0; i < count; i++) {
>> +        reg[i * 2] = cpu_to_be64(addr | ((base + i) * 0x1000));
>> +        reg[i * 2 + 1] = cpu_to_be64(0x1000);
>> +    }
>> +
>> +    name = g_strdup_printf("interrupt-controller@%"PRIX64, addr);
>> +
>> +    /* interrupt controller */
>> +    _FDT((fdt_begin_node(fdt, name)));
>> +    g_free(name);
>> +
>> +    _FDT((fdt_property(fdt, "compatible", compat, sizeof(compat))));
>> +    _FDT((fdt_property(fdt, "reg", reg, rsize)));
>> +    _FDT((fdt_property_string(fdt, "device_type",
>> +                              "PowerPC-External-Interrupt-Presentation")));
>> +    _FDT((fdt_property(fdt, "interrupt-controller", NULL, 0)));
>> +    _FDT((fdt_property(fdt, "ibm,interrupt-server-ranges",
>> +                       irange, sizeof(irange))));
>> +    _FDT((fdt_property_cell(fdt, "#interrupt-cells", 1)));
>> +    _FDT((fdt_property_cell(fdt, "#address-cells", 0)));
>> +    _FDT((fdt_end_node(fdt)));
>> +}
>> +
>> +static void xics_native_realize(DeviceState *dev, Error **errp)
>> +{
>> +    XICSState *s = XICS_NATIVE(dev);
>> +    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
>> +    Error *error = NULL;
>> +    int i;
>> +
>> +    if (!s->nr_servers) {
>> +        error_setg(errp, "Number of servers needs to be greater 0");
>> +        return;
>> +    }
>> +
>> +    /* Register MMIO regions */
>> +    memory_region_init_io(&s->icp_mmio, OBJECT(s), &icp_mm_ops, s, "icp",
>> +                          ICP_MM_SIZE);
>> +    sysbus_init_mmio(sbd, &s->icp_mmio);
>> +    sysbus_mmio_map(sbd, 0, ICP_MM_BASE);
>> +
>> +    for (i = 0; i < s->nr_servers; i++) {
>> +        object_property_set_bool(OBJECT(&s->ss[i]), true, "realized", &error);
>> +        if (error) {
>> +            error_propagate(errp, error);
>> +            return;
>> +        }
>> +    }
>> +}
>> +
>> +static void xics_native_class_init(ObjectClass *oc, void *data)
>> +{
>> +    DeviceClass *dc = DEVICE_CLASS(oc);
>> +    XICSStateClass *xsc = XICS_NATIVE_CLASS(oc);
>> +
>> +    dc->realize = xics_native_realize;
>> +    xsc->set_nr_servers = xics_set_nr_servers;
>> +}
>> +
>> +static const TypeInfo xics_native_info = {
>> +    .name          = TYPE_XICS_NATIVE,
>> +    .parent        = TYPE_XICS_COMMON,
>> +    .instance_size = sizeof(XICSState),
>> +    .class_size = sizeof(XICSStateClass),
>> +    .class_init    = xics_native_class_init,
>> +    .instance_init = xics_native_initfn,
>> +};
>> +
>> +static void xics_native_register_types(void)
>> +{
>> +    type_register_static(&xics_native_info);
>> +}
>> +type_init(xics_native_register_types)
>> diff --git a/include/hw/ppc/xics.h b/include/hw/ppc/xics.h
>> index 2231f2a..f81155c 100644
>> --- a/include/hw/ppc/xics.h
>> +++ b/include/hw/ppc/xics.h
>> @@ -44,6 +44,9 @@
>>  #define XICS_SPAPR_KVM(obj) \
>>       OBJECT_CHECK(KVMXICSState, (obj), TYPE_XICS_SPAPR_KVM)
>>  
>> +#define TYPE_XICS_NATIVE "xics-native"
>> +#define XICS_NATIVE(obj) OBJECT_CHECK(XICSState, (obj), TYPE_XICS_NATIVE)
>> +
>>  #define XICS_COMMON_CLASS(klass) \
>>       OBJECT_CLASS_CHECK(XICSStateClass, (klass), TYPE_XICS_COMMON)
>>  #define XICS_SPAPR_CLASS(klass) \
>> @@ -52,6 +55,8 @@
>>       OBJECT_GET_CLASS(XICSStateClass, (obj), TYPE_XICS_COMMON)
>>  #define XICS_SPAPR_GET_CLASS(obj) \
>>       OBJECT_GET_CLASS(XICSStateClass, (obj), TYPE_XICS_SPAPR)
>> +#define XICS_NATIVE_CLASS(klass) \
>> +     OBJECT_CLASS_CHECK(XICSStateClass, (klass), TYPE_XICS_NATIVE)
>>  
>>  #define XICS_IPI        0x2
>>  #define XICS_BUID       0x1
>> @@ -86,6 +91,7 @@ struct XICSState {
>>      uint32_t nr_irqs;
>>      ICPState *ss;
>>      QLIST_HEAD(, ICSState) ics;
>> +    MemoryRegion icp_mmio;
> 
> Shouldn't this just be in the native subclass?

yes. 

Nikunj,

I am reworking quite a bit this patch in PowerNV to handle 
the cpu index -> icp index mapping and for an other reasons. 
I will push another version of XICS native in sync with the 
code base. 

Thanks,

C. 


> 
>>  };
>>  
>>  #define TYPE_ICP "icp"
>> @@ -117,8 +123,13 @@ struct ICPState {
>>      uint8_t mfrr;
>>      qemu_irq output;
>>      bool cap_irq_xics_enabled;
>> +    uint32_t links[3];
> 
> Likewise here.
> 
>>  };
>>  
>> +/* This should be an XSCOM BAR ... the size is arbitrary as well */
>> +#define ICP_MM_BASE     0x0003FFFF80000000
>> +#define ICP_MM_SIZE     0x0000000010000000
>> +
>>  #define TYPE_ICS_BASE "ics-base"
>>  #define ICS_BASE(obj) OBJECT_CHECK(ICSState, (obj), TYPE_ICS_SIMPLE)
>>  
>> @@ -189,6 +200,9 @@ void xics_spapr_free(XICSState *icp, int irq, int num);
>>  void xics_cpu_setup(XICSState *icp, PowerPCCPU *cpu);
>>  void xics_cpu_destroy(XICSState *icp, PowerPCCPU *cpu);
>>  
>> +void xics_create_native_icp_node(XICSState *s, void *fdt,
>> +                                 uint32_t base, uint32_t count);
>> +
>>  /* Internal XICS interfaces */
>>  int xics_get_cpu_index_by_dt_id(int cpu_dt_id);
>>  
> 

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [PATCH v4 5/9] ppc/xics: Use a helper to add a new ICS
  2016-09-22  6:21     ` Cédric Le Goater
@ 2016-09-23  0:37       ` David Gibson
  0 siblings, 0 replies; 38+ messages in thread
From: David Gibson @ 2016-09-23  0:37 UTC (permalink / raw)
  To: Cédric Le Goater; +Cc: Nikunj A Dadhania, qemu-ppc, qemu-devel, benh

[-- Attachment #1: Type: text/plain, Size: 2582 bytes --]

On Thu, Sep 22, 2016 at 08:21:00AM +0200, Cédric Le Goater wrote:
> On 09/22/2016 01:40 AM, David Gibson wrote:
> > On Mon, Sep 19, 2016 at 11:59:33AM +0530, Nikunj A Dadhania wrote:
> >> From: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> >>
> >> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> >> [Move object allocation and adding child to the helper]
> >> Signed-off-by: Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>
> >> Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
> >> ---
> >>  hw/intc/xics.c        | 10 ++++++++++
> >>  hw/intc/xics_spapr.c  |  6 +-----
> >>  include/hw/ppc/xics.h |  1 +
> >>  3 files changed, 12 insertions(+), 5 deletions(-)
> >>
> >> diff --git a/hw/intc/xics.c b/hw/intc/xics.c
> >> index 05e938f..c7901c4 100644
> >> --- a/hw/intc/xics.c
> >> +++ b/hw/intc/xics.c
> >> @@ -109,6 +109,16 @@ static void xics_common_reset(DeviceState *d)
> >>      }
> >>  }
> >>  
> >> +void xics_add_ics(XICSState *xics)
> >> +{
> >> +    ICSState *ics;
> >> +
> >> +    ics = ICS(object_new(TYPE_ICS));
> >> +    object_property_add_child(OBJECT(xics), "ics", OBJECT(ics), NULL);
> > 
> > You'll need to construct a name here so you don't have all the ics
> > objects called an indistinguishable "ics".
> 
> Yes, exactly, and so PowerNV does not use it because at least three ics 
> are needed : 
> 
> qemu) info qom-tree 
> /machine (powernv-machine)
>   /unattached (container)
>     /sysbus (System)
>     /ipmi-bt[0] (qemu:memory-region)
>     /device[0] (pnv-phb3)
>       /ics-phb-lsi (ics)
>       /ics-phb-msi (phb3-msi)
> 
>       ...
> 
>       /psi (pnv-psi)
>         /xscom-psi[0] (qemu:memory-region)
>         /psihb[0] (qemu:memory-region)
>         /ics-psi (ics)
> 
> 
> I think we can drop that patch. 
> 
> 
> However some routine like this one :
> 
> +void xics_insert_ics(XICSState *xics, ICSState *ics)
> +{
> +    ics->xics = xics;
> +    QLIST_INSERT_HEAD(&xics->ics, ics, list);
> +}
> +
> 
> would be useful to hide the list details below xics :

Yes, that makes sense.

> 
> 
>     /* link in the PSI ICS */
>     xics_insert_ics(XICS_COMMON(&chip->xics), &chip->psi.ics);
> 
>     ....
> 
>     /* insert the ICS in XICS */
>     xics_insert_ics(xics, phb->lsi_ics);
>     xics_insert_ics(xics, ICS_BASE(phb->msis));
> 
> 

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 38+ messages in thread

end of thread, other threads:[~2016-09-23  2:49 UTC | newest]

Thread overview: 38+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-09-19  6:29 [Qemu-devel] [PATCH v4 0/9] sPAPR xics rework/cleanup Nikunj A Dadhania
2016-09-19  6:29 ` [Qemu-devel] [PATCH v4 1/9] ppc/xics: account correct irq status Nikunj A Dadhania
2016-09-21  6:39   ` David Gibson
2016-09-19  6:29 ` [Qemu-devel] [PATCH v4 2/9] ppc/xics: Fix migration failure with kernel-irqchip=off Nikunj A Dadhania
2016-09-21  7:21   ` David Gibson
2016-09-19  6:29 ` [Qemu-devel] [PATCH v4 3/9] ppc/xics: Make the ICSState a list Nikunj A Dadhania
2016-09-19  6:59   ` [Qemu-devel] [Qemu-ppc] " Cédric Le Goater
2016-09-19  7:02     ` Nikunj A Dadhania
2016-09-19  7:24       ` Cédric Le Goater
2016-09-20  5:13         ` Nikunj A Dadhania
2016-09-21  7:48   ` [Qemu-devel] " David Gibson
2016-09-19  6:29 ` [Qemu-devel] [PATCH v4 4/9] ppc/xics: An ICS with offset 0 is assumed to be uninitialized Nikunj A Dadhania
2016-09-21  7:50   ` David Gibson
2016-09-19  6:29 ` [Qemu-devel] [PATCH v4 5/9] ppc/xics: Use a helper to add a new ICS Nikunj A Dadhania
2016-09-21 23:40   ` David Gibson
2016-09-22  6:21     ` Cédric Le Goater
2016-09-23  0:37       ` David Gibson
2016-09-19  6:29 ` [Qemu-devel] [PATCH v4 6/9] ppc/xics: Split ICS into ics-base and ics class Nikunj A Dadhania
2016-09-19  7:09   ` [Qemu-devel] [Qemu-ppc] " Cédric Le Goater
2016-09-20  5:14     ` Nikunj A Dadhania
2016-09-19 14:34   ` Cédric Le Goater
2016-09-20  6:02     ` Nikunj A Dadhania
2016-09-20  6:20       ` Cédric Le Goater
2016-09-20  6:29         ` Nikunj A Dadhania
2016-09-20  7:13           ` Cédric Le Goater
2016-09-20  8:10             ` Nikunj A Dadhania
2016-09-20  9:06               ` Cédric Le Goater
2016-09-20  9:41                 ` Nikunj A Dadhania
2016-09-20  9:52                   ` Cédric Le Goater
2016-09-20 10:03                     ` Nikunj A Dadhania
2016-09-19  6:29 ` [Qemu-devel] [PATCH v4 7/9] ppc/xics: Add "native" XICS subclass Nikunj A Dadhania
2016-09-19  7:03   ` [Qemu-devel] [Qemu-ppc] " Cédric Le Goater
2016-09-22  0:02   ` [Qemu-devel] " David Gibson
2016-09-22  6:27     ` Cédric Le Goater
2016-09-19  6:29 ` [Qemu-devel] [PATCH v4 8/9] ppc/xics: Add xics to the monitor "info pic" command Nikunj A Dadhania
2016-09-22  0:07   ` David Gibson
2016-09-19  6:29 ` [Qemu-devel] [PATCH v4 9/9] ppc/xics: move set_nr_{irqs, servers} to xics.c Nikunj A Dadhania
2016-09-22  0:14   ` David Gibson

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.