diff mbox series

[v2,21/33] spapr, xics, xive: Move cpu_intc_create from SpaprIrq to SpaprInterruptController

Message ID 20190927055028.11493-22-david@gibson.dropbear.id.au
State New
Headers show
Series spapr: IRQ subsystem cleanup | expand

Commit Message

David Gibson Sept. 27, 2019, 5:50 a.m. UTC
This method essentially represents code which belongs to the interrupt
controller, but needs to be called on all possible intcs, rather than
just the currently active one.  The "dual" version therefore calls
into the xics and xive versions confusingly.

Handle this more directly, by making it instead a method on the intc
backend, and always calling it on every backend that exists.

While we're there, streamline the error reporting a bit.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
 hw/intc/spapr_xive.c       | 25 ++++++++++++
 hw/intc/xics_spapr.c       | 18 +++++++++
 hw/ppc/spapr_cpu_core.c    |  3 +-
 hw/ppc/spapr_irq.c         | 81 +++++++++++---------------------------
 include/hw/ppc/spapr_irq.h | 16 +++++++-
 5 files changed, 82 insertions(+), 61 deletions(-)

Comments

Greg Kurz Sept. 27, 2019, 10:16 a.m. UTC | #1
On Fri, 27 Sep 2019 15:50:16 +1000
David Gibson <david@gibson.dropbear.id.au> wrote:

> This method essentially represents code which belongs to the interrupt
> controller, but needs to be called on all possible intcs, rather than
> just the currently active one.  The "dual" version therefore calls
> into the xics and xive versions confusingly.
> 
> Handle this more directly, by making it instead a method on the intc
> backend, and always calling it on every backend that exists.
> 
> While we're there, streamline the error reporting a bit.
> 
> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> ---
>  hw/intc/spapr_xive.c       | 25 ++++++++++++
>  hw/intc/xics_spapr.c       | 18 +++++++++
>  hw/ppc/spapr_cpu_core.c    |  3 +-
>  hw/ppc/spapr_irq.c         | 81 +++++++++++---------------------------
>  include/hw/ppc/spapr_irq.h | 16 +++++++-
>  5 files changed, 82 insertions(+), 61 deletions(-)
> 
> diff --git a/hw/intc/spapr_xive.c b/hw/intc/spapr_xive.c
> index b67e9c3245..9338daba3d 100644
> --- a/hw/intc/spapr_xive.c
> +++ b/hw/intc/spapr_xive.c
> @@ -495,10 +495,33 @@ static Property spapr_xive_properties[] = {
>      DEFINE_PROP_END_OF_LIST(),
>  };
>  
> +static int spapr_xive_cpu_intc_create(SpaprInterruptController *intc,
> +                                      PowerPCCPU *cpu, Error **errp)
> +{
> +    SpaprXive *xive = SPAPR_XIVE(intc);
> +    Object *obj;
> +    SpaprCpuState *spapr_cpu = spapr_cpu_state(cpu);
> +
> +    obj = xive_tctx_create(OBJECT(cpu), XIVE_ROUTER(xive), errp);
> +    if (!obj) {
> +        return -1;
> +    }
> +
> +    spapr_cpu->tctx = XIVE_TCTX(obj);
> +
> +    /*
> +     * (TCG) Early setting the OS CAM line for hotplugged CPUs as they
> +     * don't beneficiate from the reset of the XIVE IRQ backend
> +     */
> +    spapr_xive_set_tctx_os_cam(spapr_cpu->tctx);
> +    return 0;
> +}
> +
>  static void spapr_xive_class_init(ObjectClass *klass, void *data)
>  {
>      DeviceClass *dc = DEVICE_CLASS(klass);
>      XiveRouterClass *xrc = XIVE_ROUTER_CLASS(klass);
> +    SpaprInterruptControllerClass *sicc = SPAPR_INTC_CLASS(klass);
>  
>      dc->desc    = "sPAPR XIVE Interrupt Controller";
>      dc->props   = spapr_xive_properties;
> @@ -511,6 +534,8 @@ static void spapr_xive_class_init(ObjectClass *klass, void *data)
>      xrc->get_nvt = spapr_xive_get_nvt;
>      xrc->write_nvt = spapr_xive_write_nvt;
>      xrc->get_tctx = spapr_xive_get_tctx;
> +
> +    sicc->cpu_intc_create = spapr_xive_cpu_intc_create;
>  }
>  
>  static const TypeInfo spapr_xive_info = {
> diff --git a/hw/intc/xics_spapr.c b/hw/intc/xics_spapr.c
> index 4874e6be55..946311b858 100644
> --- a/hw/intc/xics_spapr.c
> +++ b/hw/intc/xics_spapr.c
> @@ -330,13 +330,31 @@ void spapr_dt_xics(SpaprMachineState *spapr, uint32_t nr_servers, void *fdt,
>      _FDT(fdt_setprop_cell(fdt, node, "phandle", phandle));
>  }
>  
> +static int xics_spapr_cpu_intc_create(SpaprInterruptController *intc,
> +                                       PowerPCCPU *cpu, Error **errp)
> +{
> +    ICSState *ics = ICS_SPAPR(intc);
> +    Object *obj;
> +    SpaprCpuState *spapr_cpu = spapr_cpu_state(cpu);
> +
> +    obj = icp_create(OBJECT(cpu), TYPE_ICP, ics->xics, errp);
> +    if (!obj) {
> +        return -1;
> +    }
> +
> +    spapr_cpu->icp = ICP(obj);
> +    return 0;
> +}
> +
>  static void ics_spapr_class_init(ObjectClass *klass, void *data)
>  {
>      DeviceClass *dc = DEVICE_CLASS(klass);
>      ICSStateClass *isc = ICS_CLASS(klass);
> +    SpaprInterruptControllerClass *sicc = SPAPR_INTC_CLASS(klass);
>  
>      device_class_set_parent_realize(dc, ics_spapr_realize,
>                                      &isc->parent_realize);
> +    sicc->cpu_intc_create = xics_spapr_cpu_intc_create;
>  }
>  
>  static const TypeInfo ics_spapr_info = {
> diff --git a/hw/ppc/spapr_cpu_core.c b/hw/ppc/spapr_cpu_core.c
> index 1d93de8161..3e4302c7d5 100644
> --- a/hw/ppc/spapr_cpu_core.c
> +++ b/hw/ppc/spapr_cpu_core.c
> @@ -237,8 +237,7 @@ static void spapr_realize_vcpu(PowerPCCPU *cpu, SpaprMachineState *spapr,
>      qemu_register_reset(spapr_cpu_reset, cpu);
>      spapr_cpu_reset(cpu);
>  
> -    spapr->irq->cpu_intc_create(spapr, cpu, &local_err);
> -    if (local_err) {
> +    if (spapr_irq_cpu_intc_create(spapr, cpu, &local_err) < 0) {
>          goto error_unregister;
>      }
>  
> diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c
> index 0603c82fe8..a855dfe4e9 100644
> --- a/hw/ppc/spapr_irq.c
> +++ b/hw/ppc/spapr_irq.c
> @@ -138,23 +138,6 @@ static void spapr_irq_print_info_xics(SpaprMachineState *spapr, Monitor *mon)
>      ics_pic_print_info(spapr->ics, mon);
>  }
>  
> -static void spapr_irq_cpu_intc_create_xics(SpaprMachineState *spapr,
> -                                           PowerPCCPU *cpu, Error **errp)
> -{
> -    Error *local_err = NULL;
> -    Object *obj;
> -    SpaprCpuState *spapr_cpu = spapr_cpu_state(cpu);
> -
> -    obj = icp_create(OBJECT(cpu), TYPE_ICP, XICS_FABRIC(spapr),
> -                     &local_err);
> -    if (local_err) {
> -        error_propagate(errp, local_err);
> -        return;
> -    }
> -
> -    spapr_cpu->icp = ICP(obj);
> -}
> -
>  static int spapr_irq_post_load_xics(SpaprMachineState *spapr, int version_id)
>  {
>      if (!kvm_irqchip_in_kernel()) {
> @@ -203,7 +186,6 @@ SpaprIrq spapr_irq_xics = {
>      .free        = spapr_irq_free_xics,
>      .print_info  = spapr_irq_print_info_xics,
>      .dt_populate = spapr_dt_xics,
> -    .cpu_intc_create = spapr_irq_cpu_intc_create_xics,
>      .post_load   = spapr_irq_post_load_xics,
>      .reset       = spapr_irq_reset_xics,
>      .set_irq     = spapr_irq_set_irq_xics,
> @@ -239,28 +221,6 @@ static void spapr_irq_print_info_xive(SpaprMachineState *spapr,
>      spapr_xive_pic_print_info(spapr->xive, mon);
>  }
>  
> -static void spapr_irq_cpu_intc_create_xive(SpaprMachineState *spapr,
> -                                           PowerPCCPU *cpu, Error **errp)
> -{
> -    Error *local_err = NULL;
> -    Object *obj;
> -    SpaprCpuState *spapr_cpu = spapr_cpu_state(cpu);
> -
> -    obj = xive_tctx_create(OBJECT(cpu), XIVE_ROUTER(spapr->xive), &local_err);
> -    if (local_err) {
> -        error_propagate(errp, local_err);
> -        return;
> -    }
> -
> -    spapr_cpu->tctx = XIVE_TCTX(obj);
> -
> -    /*
> -     * (TCG) Early setting the OS CAM line for hotplugged CPUs as they
> -     * don't beneficiate from the reset of the XIVE IRQ backend
> -     */
> -    spapr_xive_set_tctx_os_cam(spapr_cpu->tctx);
> -}
> -
>  static int spapr_irq_post_load_xive(SpaprMachineState *spapr, int version_id)
>  {
>      return spapr_xive_post_load(spapr->xive, version_id);
> @@ -316,7 +276,6 @@ SpaprIrq spapr_irq_xive = {
>      .free        = spapr_irq_free_xive,
>      .print_info  = spapr_irq_print_info_xive,
>      .dt_populate = spapr_dt_xive,
> -    .cpu_intc_create = spapr_irq_cpu_intc_create_xive,
>      .post_load   = spapr_irq_post_load_xive,
>      .reset       = spapr_irq_reset_xive,
>      .set_irq     = spapr_irq_set_irq_xive,
> @@ -381,20 +340,6 @@ static void spapr_irq_dt_populate_dual(SpaprMachineState *spapr,
>      spapr_irq_current(spapr)->dt_populate(spapr, nr_servers, fdt, phandle);
>  }
>  
> -static void spapr_irq_cpu_intc_create_dual(SpaprMachineState *spapr,
> -                                           PowerPCCPU *cpu, Error **errp)
> -{
> -    Error *local_err = NULL;
> -
> -    spapr_irq_xive.cpu_intc_create(spapr, cpu, &local_err);
> -    if (local_err) {
> -        error_propagate(errp, local_err);
> -        return;
> -    }
> -
> -    spapr_irq_xics.cpu_intc_create(spapr, cpu, errp);
> -}
> -
>  static int spapr_irq_post_load_dual(SpaprMachineState *spapr, int version_id)
>  {
>      /*
> @@ -460,7 +405,6 @@ SpaprIrq spapr_irq_dual = {
>      .free        = spapr_irq_free_dual,
>      .print_info  = spapr_irq_print_info_dual,
>      .dt_populate = spapr_irq_dt_populate_dual,
> -    .cpu_intc_create = spapr_irq_cpu_intc_create_dual,
>      .post_load   = spapr_irq_post_load_dual,
>      .reset       = spapr_irq_reset_dual,
>      .set_irq     = spapr_irq_set_irq_dual,
> @@ -525,6 +469,30 @@ static void spapr_irq_check(SpaprMachineState *spapr, Error **errp)
>  /*
>   * sPAPR IRQ frontend routines for devices
>   */
> +int spapr_irq_cpu_intc_create(SpaprMachineState *spapr,
> +                              PowerPCCPU *cpu, Error **errp)
> +{
> +    if (spapr->xive) {
> +        SpaprInterruptController *intc = SPAPR_INTC(spapr->xive);
> +        SpaprInterruptControllerClass *sicc = SPAPR_INTC_GET_CLASS(intc);
> +
> +        if (sicc->cpu_intc_create(intc, cpu, errp) < 0) {
> +            return -1;
> +        }
> +    }
> +
> +    if (spapr->ics) {
> +        SpaprInterruptController *intc = SPAPR_INTC(spapr->ics);
> +        SpaprInterruptControllerClass *sicc = SPAPR_INTC_GET_CLASS(intc);
> +
> +        if (sicc->cpu_intc_create(intc, cpu, errp) < 0) {
> +            return -1;
> +        }
> +    }
> +

Instead of these hooks, what about open-coding spapr_xive_cpu_intc_create()
and xics_spapr_cpu_intc_create() directly here, like you already did for the
ICS and the XIVE objects in spapr_irq_init() ?

> +    return 0;
> +}
> +
>  void spapr_irq_init(SpaprMachineState *spapr, Error **errp)
>  {
>      MachineState *machine = MACHINE(spapr);
> @@ -763,7 +731,6 @@ SpaprIrq spapr_irq_xics_legacy = {
>      .free        = spapr_irq_free_xics,
>      .print_info  = spapr_irq_print_info_xics,
>      .dt_populate = spapr_dt_xics,
> -    .cpu_intc_create = spapr_irq_cpu_intc_create_xics,
>      .post_load   = spapr_irq_post_load_xics,
>      .reset       = spapr_irq_reset_xics,
>      .set_irq     = spapr_irq_set_irq_xics,
> diff --git a/include/hw/ppc/spapr_irq.h b/include/hw/ppc/spapr_irq.h
> index b9398e0be3..30d660ff1e 100644
> --- a/include/hw/ppc/spapr_irq.h
> +++ b/include/hw/ppc/spapr_irq.h
> @@ -43,8 +43,22 @@ typedef struct SpaprInterruptController SpaprInterruptController;
>  
>  typedef struct SpaprInterruptControllerClass {
>      InterfaceClass parent;
> +
> +    /*
> +     * These methods will typically be called on all intcs, active and
> +     * inactive
> +     */
> +    int (*cpu_intc_create)(SpaprInterruptController *intc,
> +                            PowerPCCPU *cpu, Error **errp);
>  } SpaprInterruptControllerClass;
>  
> +void spapr_irq_print_info(SpaprMachineState *spapr, Monitor *mon);
> +void spapr_irq_dt(SpaprMachineState *spapr, uint32_t nr_servers,
> +                  void *fdt, uint32_t phandle);

These two ^^ seem to belong to later patches.

> +int spapr_irq_cpu_intc_create(SpaprMachineState *spapr,
> +                              PowerPCCPU *cpu, Error **errp);
> +
> +
>  void spapr_irq_msi_init(SpaprMachineState *spapr, uint32_t nr_msis);
>  int spapr_irq_msi_alloc(SpaprMachineState *spapr, uint32_t num, bool align,
>                          Error **errp);
> @@ -61,8 +75,6 @@ typedef struct SpaprIrq {
>      void (*print_info)(SpaprMachineState *spapr, Monitor *mon);
>      void (*dt_populate)(SpaprMachineState *spapr, uint32_t nr_servers,
>                          void *fdt, uint32_t phandle);
> -    void (*cpu_intc_create)(SpaprMachineState *spapr, PowerPCCPU *cpu,
> -                            Error **errp);
>      int (*post_load)(SpaprMachineState *spapr, int version_id);
>      void (*reset)(SpaprMachineState *spapr, Error **errp);
>      void (*set_irq)(void *opaque, int srcno, int val);
David Gibson Sept. 30, 2019, 1:49 a.m. UTC | #2
On Fri, Sep 27, 2019 at 12:16:49PM +0200, Greg Kurz wrote:
> On Fri, 27 Sep 2019 15:50:16 +1000
> David Gibson <david@gibson.dropbear.id.au> wrote:
> 
> > This method essentially represents code which belongs to the interrupt
> > controller, but needs to be called on all possible intcs, rather than
> > just the currently active one.  The "dual" version therefore calls
> > into the xics and xive versions confusingly.
> > 
> > Handle this more directly, by making it instead a method on the intc
> > backend, and always calling it on every backend that exists.
> > 
> > While we're there, streamline the error reporting a bit.
> > 
> > Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
[snip]
> > @@ -525,6 +469,30 @@ static void spapr_irq_check(SpaprMachineState *spapr, Error **errp)
> >  /*
> >   * sPAPR IRQ frontend routines for devices
> >   */
> > +int spapr_irq_cpu_intc_create(SpaprMachineState *spapr,
> > +                              PowerPCCPU *cpu, Error **errp)
> > +{
> > +    if (spapr->xive) {
> > +        SpaprInterruptController *intc = SPAPR_INTC(spapr->xive);
> > +        SpaprInterruptControllerClass *sicc = SPAPR_INTC_GET_CLASS(intc);
> > +
> > +        if (sicc->cpu_intc_create(intc, cpu, errp) < 0) {
> > +            return -1;
> > +        }
> > +    }
> > +
> > +    if (spapr->ics) {
> > +        SpaprInterruptController *intc = SPAPR_INTC(spapr->ics);
> > +        SpaprInterruptControllerClass *sicc = SPAPR_INTC_GET_CLASS(intc);
> > +
> > +        if (sicc->cpu_intc_create(intc, cpu, errp) < 0) {
> > +            return -1;
> > +        }
> > +    }
> > +
> 
> Instead of these hooks, what about open-coding spapr_xive_cpu_intc_create()
> and xics_spapr_cpu_intc_create() directly here, like you already did for the
> ICS and the XIVE objects in spapr_irq_init() ?

I'd prefer not to.  The idea is I want to treat this as basically:

	foreach_possible_intc(intc)
		intc::cpu_intc_create(...)

If I find time I might indeed replace the explicit ics and xive
pointers with just an array of SpaprInterruptController *.

init is fundamentally different though, because it needs to *create*
that list (implicit or explicit) of possible intcs, so it can't be
based on an existing one.

> 
> > +    return 0;
> > +}
> > +
> >  void spapr_irq_init(SpaprMachineState *spapr, Error **errp)
> >  {
> >      MachineState *machine = MACHINE(spapr);
> > @@ -763,7 +731,6 @@ SpaprIrq spapr_irq_xics_legacy = {
> >      .free        = spapr_irq_free_xics,
> >      .print_info  = spapr_irq_print_info_xics,
> >      .dt_populate = spapr_dt_xics,
> > -    .cpu_intc_create = spapr_irq_cpu_intc_create_xics,
> >      .post_load   = spapr_irq_post_load_xics,
> >      .reset       = spapr_irq_reset_xics,
> >      .set_irq     = spapr_irq_set_irq_xics,
> > diff --git a/include/hw/ppc/spapr_irq.h b/include/hw/ppc/spapr_irq.h
> > index b9398e0be3..30d660ff1e 100644
> > --- a/include/hw/ppc/spapr_irq.h
> > +++ b/include/hw/ppc/spapr_irq.h
> > @@ -43,8 +43,22 @@ typedef struct SpaprInterruptController SpaprInterruptController;
> >  
> >  typedef struct SpaprInterruptControllerClass {
> >      InterfaceClass parent;
> > +
> > +    /*
> > +     * These methods will typically be called on all intcs, active and
> > +     * inactive
> > +     */
> > +    int (*cpu_intc_create)(SpaprInterruptController *intc,
> > +                            PowerPCCPU *cpu, Error **errp);
> >  } SpaprInterruptControllerClass;
> >  
> > +void spapr_irq_print_info(SpaprMachineState *spapr, Monitor *mon);
> > +void spapr_irq_dt(SpaprMachineState *spapr, uint32_t nr_servers,
> > +                  void *fdt, uint32_t phandle);
> 
> These two ^^ seem to belong to later patches.
> 
> > +int spapr_irq_cpu_intc_create(SpaprMachineState *spapr,
> > +                              PowerPCCPU *cpu, Error **errp);
> > +
> > +
> >  void spapr_irq_msi_init(SpaprMachineState *spapr, uint32_t nr_msis);
> >  int spapr_irq_msi_alloc(SpaprMachineState *spapr, uint32_t num, bool align,
> >                          Error **errp);
> > @@ -61,8 +75,6 @@ typedef struct SpaprIrq {
> >      void (*print_info)(SpaprMachineState *spapr, Monitor *mon);
> >      void (*dt_populate)(SpaprMachineState *spapr, uint32_t nr_servers,
> >                          void *fdt, uint32_t phandle);
> > -    void (*cpu_intc_create)(SpaprMachineState *spapr, PowerPCCPU *cpu,
> > -                            Error **errp);
> >      int (*post_load)(SpaprMachineState *spapr, int version_id);
> >      void (*reset)(SpaprMachineState *spapr, Error **errp);
> >      void (*set_irq)(void *opaque, int srcno, int val);
>
David Gibson Sept. 30, 2019, 2:37 a.m. UTC | #3
On Fri, Sep 27, 2019 at 12:16:49PM +0200, Greg Kurz wrote:
> On Fri, 27 Sep 2019 15:50:16 +1000
> David Gibson <david@gibson.dropbear.id.au> wrote:
> 
> > This method essentially represents code which belongs to the interrupt
> > controller, but needs to be called on all possible intcs, rather than
> > just the currently active one.  The "dual" version therefore calls
> > into the xics and xive versions confusingly.
> > 
> > Handle this more directly, by making it instead a method on the intc
> > backend, and always calling it on every backend that exists.
> > 
> > While we're there, streamline the error reporting a bit.
> > 
> > Signed-off-by: David Gibson <david@gibson.dropbear.id.au>

[snip]
> > +void spapr_irq_print_info(SpaprMachineState *spapr, Monitor *mon);
> > +void spapr_irq_dt(SpaprMachineState *spapr, uint32_t nr_servers,
> > +                  void *fdt, uint32_t phandle);
> 
> These two ^^ seem to belong to later patches.

Oops, yes.  I've moved those to where they belong.

> 
> > +int spapr_irq_cpu_intc_create(SpaprMachineState *spapr,
> > +                              PowerPCCPU *cpu, Error **errp);
> > +
> > +
> >  void spapr_irq_msi_init(SpaprMachineState *spapr, uint32_t nr_msis);
> >  int spapr_irq_msi_alloc(SpaprMachineState *spapr, uint32_t num, bool align,
> >                          Error **errp);
> > @@ -61,8 +75,6 @@ typedef struct SpaprIrq {
> >      void (*print_info)(SpaprMachineState *spapr, Monitor *mon);
> >      void (*dt_populate)(SpaprMachineState *spapr, uint32_t nr_servers,
> >                          void *fdt, uint32_t phandle);
> > -    void (*cpu_intc_create)(SpaprMachineState *spapr, PowerPCCPU *cpu,
> > -                            Error **errp);
> >      int (*post_load)(SpaprMachineState *spapr, int version_id);
> >      void (*reset)(SpaprMachineState *spapr, Error **errp);
> >      void (*set_irq)(void *opaque, int srcno, int val);
>
Cédric Le Goater Sept. 30, 2019, 5:28 a.m. UTC | #4
On 30/09/2019 03:49, David Gibson wrote:
> On Fri, Sep 27, 2019 at 12:16:49PM +0200, Greg Kurz wrote:
>> On Fri, 27 Sep 2019 15:50:16 +1000
>> David Gibson <david@gibson.dropbear.id.au> wrote:
>>
>>> This method essentially represents code which belongs to the interrupt
>>> controller, but needs to be called on all possible intcs, rather than
>>> just the currently active one.  The "dual" version therefore calls
>>> into the xics and xive versions confusingly.
>>>
>>> Handle this more directly, by making it instead a method on the intc
>>> backend, and always calling it on every backend that exists.
>>>
>>> While we're there, streamline the error reporting a bit.
>>>
>>> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> [snip]
>>> @@ -525,6 +469,30 @@ static void spapr_irq_check(SpaprMachineState *spapr, Error **errp)
>>>  /*
>>>   * sPAPR IRQ frontend routines for devices
>>>   */
>>> +int spapr_irq_cpu_intc_create(SpaprMachineState *spapr,
>>> +                              PowerPCCPU *cpu, Error **errp)
>>> +{
>>> +    if (spapr->xive) {
>>> +        SpaprInterruptController *intc = SPAPR_INTC(spapr->xive);
>>> +        SpaprInterruptControllerClass *sicc = SPAPR_INTC_GET_CLASS(intc);
>>> +
>>> +        if (sicc->cpu_intc_create(intc, cpu, errp) < 0) {
>>> +            return -1;
>>> +        }
>>> +    }
>>> +
>>> +    if (spapr->ics) {
>>> +        SpaprInterruptController *intc = SPAPR_INTC(spapr->ics);
>>> +        SpaprInterruptControllerClass *sicc = SPAPR_INTC_GET_CLASS(intc);
>>> +
>>> +        if (sicc->cpu_intc_create(intc, cpu, errp) < 0) {
>>> +            return -1;
>>> +        }
>>> +    }
>>> +
>>
>> Instead of these hooks, what about open-coding spapr_xive_cpu_intc_create()
>> and xics_spapr_cpu_intc_create() directly here, like you already did for the
>> ICS and the XIVE objects in spapr_irq_init() ?
> 
> I'd prefer not to.  The idea is I want to treat this as basically:
> 
> 	foreach_possible_intc(intc)
> 		intc::cpu_intc_create(...)
> 
> If I find time I might indeed replace the explicit ics and xive
> pointers with just an array of SpaprInterruptController *.

Or you could use object_child_foreach() and check for the type. If we had
a helper object_child_foreach_type(), we could use it elsewhere.

 
> init is fundamentally different though, because it needs to *create*
> that list (implicit or explicit) of possible intcs, so it can't be
> based on an existing one.
> 
>>
>>> +    return 0;
>>> +}
>>> +
>>>  void spapr_irq_init(SpaprMachineState *spapr, Error **errp)
>>>  {
>>>      MachineState *machine = MACHINE(spapr);
>>> @@ -763,7 +731,6 @@ SpaprIrq spapr_irq_xics_legacy = {
>>>      .free        = spapr_irq_free_xics,
>>>      .print_info  = spapr_irq_print_info_xics,
>>>      .dt_populate = spapr_dt_xics,
>>> -    .cpu_intc_create = spapr_irq_cpu_intc_create_xics,
>>>      .post_load   = spapr_irq_post_load_xics,
>>>      .reset       = spapr_irq_reset_xics,
>>>      .set_irq     = spapr_irq_set_irq_xics,
>>> diff --git a/include/hw/ppc/spapr_irq.h b/include/hw/ppc/spapr_irq.h
>>> index b9398e0be3..30d660ff1e 100644
>>> --- a/include/hw/ppc/spapr_irq.h
>>> +++ b/include/hw/ppc/spapr_irq.h
>>> @@ -43,8 +43,22 @@ typedef struct SpaprInterruptController SpaprInterruptController;
>>>  
>>>  typedef struct SpaprInterruptControllerClass {
>>>      InterfaceClass parent;
>>> +
>>> +    /*
>>> +     * These methods will typically be called on all intcs, active and
>>> +     * inactive
>>> +     */
>>> +    int (*cpu_intc_create)(SpaprInterruptController *intc,
>>> +                            PowerPCCPU *cpu, Error **errp);
>>>  } SpaprInterruptControllerClass;
>>>  
>>> +void spapr_irq_print_info(SpaprMachineState *spapr, Monitor *mon);
>>> +void spapr_irq_dt(SpaprMachineState *spapr, uint32_t nr_servers,
>>> +                  void *fdt, uint32_t phandle);
>>
>> These two ^^ seem to belong to later patches.
>>
>>> +int spapr_irq_cpu_intc_create(SpaprMachineState *spapr,
>>> +                              PowerPCCPU *cpu, Error **errp);
>>> +
>>> +
>>>  void spapr_irq_msi_init(SpaprMachineState *spapr, uint32_t nr_msis);
>>>  int spapr_irq_msi_alloc(SpaprMachineState *spapr, uint32_t num, bool align,
>>>                          Error **errp);
>>> @@ -61,8 +75,6 @@ typedef struct SpaprIrq {
>>>      void (*print_info)(SpaprMachineState *spapr, Monitor *mon);
>>>      void (*dt_populate)(SpaprMachineState *spapr, uint32_t nr_servers,
>>>                          void *fdt, uint32_t phandle);
>>> -    void (*cpu_intc_create)(SpaprMachineState *spapr, PowerPCCPU *cpu,
>>> -                            Error **errp);
>>>      int (*post_load)(SpaprMachineState *spapr, int version_id);
>>>      void (*reset)(SpaprMachineState *spapr, Error **errp);
>>>      void (*set_irq)(void *opaque, int srcno, int val);
>>
>
Cédric Le Goater Sept. 30, 2019, 5:30 a.m. UTC | #5
On 27/09/2019 07:50, David Gibson wrote:
> This method essentially represents code which belongs to the interrupt
> controller, but needs to be called on all possible intcs, rather than
> just the currently active one.  The "dual" version therefore calls
> into the xics and xive versions confusingly.
> 
> Handle this more directly, by making it instead a method on the intc
> backend, and always calling it on every backend that exists.
> 
> While we're there, streamline the error reporting a bit.
> 
> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>

With the function declarations removed from spapr_irq.h,

Reviewed-by: Cédric Le Goater <clg@kaod.org>

> ---
>  hw/intc/spapr_xive.c       | 25 ++++++++++++
>  hw/intc/xics_spapr.c       | 18 +++++++++
>  hw/ppc/spapr_cpu_core.c    |  3 +-
>  hw/ppc/spapr_irq.c         | 81 +++++++++++---------------------------
>  include/hw/ppc/spapr_irq.h | 16 +++++++-
>  5 files changed, 82 insertions(+), 61 deletions(-)
> 
> diff --git a/hw/intc/spapr_xive.c b/hw/intc/spapr_xive.c
> index b67e9c3245..9338daba3d 100644
> --- a/hw/intc/spapr_xive.c
> +++ b/hw/intc/spapr_xive.c
> @@ -495,10 +495,33 @@ static Property spapr_xive_properties[] = {
>      DEFINE_PROP_END_OF_LIST(),
>  };
>  
> +static int spapr_xive_cpu_intc_create(SpaprInterruptController *intc,
> +                                      PowerPCCPU *cpu, Error **errp)
> +{
> +    SpaprXive *xive = SPAPR_XIVE(intc);
> +    Object *obj;
> +    SpaprCpuState *spapr_cpu = spapr_cpu_state(cpu);
> +
> +    obj = xive_tctx_create(OBJECT(cpu), XIVE_ROUTER(xive), errp);
> +    if (!obj) {
> +        return -1;
> +    }
> +
> +    spapr_cpu->tctx = XIVE_TCTX(obj);
> +
> +    /*
> +     * (TCG) Early setting the OS CAM line for hotplugged CPUs as they
> +     * don't beneficiate from the reset of the XIVE IRQ backend
> +     */
> +    spapr_xive_set_tctx_os_cam(spapr_cpu->tctx);
> +    return 0;
> +}
> +
>  static void spapr_xive_class_init(ObjectClass *klass, void *data)
>  {
>      DeviceClass *dc = DEVICE_CLASS(klass);
>      XiveRouterClass *xrc = XIVE_ROUTER_CLASS(klass);
> +    SpaprInterruptControllerClass *sicc = SPAPR_INTC_CLASS(klass);
>  
>      dc->desc    = "sPAPR XIVE Interrupt Controller";
>      dc->props   = spapr_xive_properties;
> @@ -511,6 +534,8 @@ static void spapr_xive_class_init(ObjectClass *klass, void *data)
>      xrc->get_nvt = spapr_xive_get_nvt;
>      xrc->write_nvt = spapr_xive_write_nvt;
>      xrc->get_tctx = spapr_xive_get_tctx;
> +
> +    sicc->cpu_intc_create = spapr_xive_cpu_intc_create;
>  }
>  
>  static const TypeInfo spapr_xive_info = {
> diff --git a/hw/intc/xics_spapr.c b/hw/intc/xics_spapr.c
> index 4874e6be55..946311b858 100644
> --- a/hw/intc/xics_spapr.c
> +++ b/hw/intc/xics_spapr.c
> @@ -330,13 +330,31 @@ void spapr_dt_xics(SpaprMachineState *spapr, uint32_t nr_servers, void *fdt,
>      _FDT(fdt_setprop_cell(fdt, node, "phandle", phandle));
>  }
>  
> +static int xics_spapr_cpu_intc_create(SpaprInterruptController *intc,
> +                                       PowerPCCPU *cpu, Error **errp)
> +{
> +    ICSState *ics = ICS_SPAPR(intc);
> +    Object *obj;
> +    SpaprCpuState *spapr_cpu = spapr_cpu_state(cpu);
> +
> +    obj = icp_create(OBJECT(cpu), TYPE_ICP, ics->xics, errp);
> +    if (!obj) {
> +        return -1;
> +    }
> +
> +    spapr_cpu->icp = ICP(obj);
> +    return 0;
> +}
> +
>  static void ics_spapr_class_init(ObjectClass *klass, void *data)
>  {
>      DeviceClass *dc = DEVICE_CLASS(klass);
>      ICSStateClass *isc = ICS_CLASS(klass);
> +    SpaprInterruptControllerClass *sicc = SPAPR_INTC_CLASS(klass);
>  
>      device_class_set_parent_realize(dc, ics_spapr_realize,
>                                      &isc->parent_realize);
> +    sicc->cpu_intc_create = xics_spapr_cpu_intc_create;
>  }
>  
>  static const TypeInfo ics_spapr_info = {
> diff --git a/hw/ppc/spapr_cpu_core.c b/hw/ppc/spapr_cpu_core.c
> index 1d93de8161..3e4302c7d5 100644
> --- a/hw/ppc/spapr_cpu_core.c
> +++ b/hw/ppc/spapr_cpu_core.c
> @@ -237,8 +237,7 @@ static void spapr_realize_vcpu(PowerPCCPU *cpu, SpaprMachineState *spapr,
>      qemu_register_reset(spapr_cpu_reset, cpu);
>      spapr_cpu_reset(cpu);
>  
> -    spapr->irq->cpu_intc_create(spapr, cpu, &local_err);
> -    if (local_err) {
> +    if (spapr_irq_cpu_intc_create(spapr, cpu, &local_err) < 0) {
>          goto error_unregister;
>      }
>  
> diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c
> index 0603c82fe8..a855dfe4e9 100644
> --- a/hw/ppc/spapr_irq.c
> +++ b/hw/ppc/spapr_irq.c
> @@ -138,23 +138,6 @@ static void spapr_irq_print_info_xics(SpaprMachineState *spapr, Monitor *mon)
>      ics_pic_print_info(spapr->ics, mon);
>  }
>  
> -static void spapr_irq_cpu_intc_create_xics(SpaprMachineState *spapr,
> -                                           PowerPCCPU *cpu, Error **errp)
> -{
> -    Error *local_err = NULL;
> -    Object *obj;
> -    SpaprCpuState *spapr_cpu = spapr_cpu_state(cpu);
> -
> -    obj = icp_create(OBJECT(cpu), TYPE_ICP, XICS_FABRIC(spapr),
> -                     &local_err);
> -    if (local_err) {
> -        error_propagate(errp, local_err);
> -        return;
> -    }
> -
> -    spapr_cpu->icp = ICP(obj);
> -}
> -
>  static int spapr_irq_post_load_xics(SpaprMachineState *spapr, int version_id)
>  {
>      if (!kvm_irqchip_in_kernel()) {
> @@ -203,7 +186,6 @@ SpaprIrq spapr_irq_xics = {
>      .free        = spapr_irq_free_xics,
>      .print_info  = spapr_irq_print_info_xics,
>      .dt_populate = spapr_dt_xics,
> -    .cpu_intc_create = spapr_irq_cpu_intc_create_xics,
>      .post_load   = spapr_irq_post_load_xics,
>      .reset       = spapr_irq_reset_xics,
>      .set_irq     = spapr_irq_set_irq_xics,
> @@ -239,28 +221,6 @@ static void spapr_irq_print_info_xive(SpaprMachineState *spapr,
>      spapr_xive_pic_print_info(spapr->xive, mon);
>  }
>  
> -static void spapr_irq_cpu_intc_create_xive(SpaprMachineState *spapr,
> -                                           PowerPCCPU *cpu, Error **errp)
> -{
> -    Error *local_err = NULL;
> -    Object *obj;
> -    SpaprCpuState *spapr_cpu = spapr_cpu_state(cpu);
> -
> -    obj = xive_tctx_create(OBJECT(cpu), XIVE_ROUTER(spapr->xive), &local_err);
> -    if (local_err) {
> -        error_propagate(errp, local_err);
> -        return;
> -    }
> -
> -    spapr_cpu->tctx = XIVE_TCTX(obj);
> -
> -    /*
> -     * (TCG) Early setting the OS CAM line for hotplugged CPUs as they
> -     * don't beneficiate from the reset of the XIVE IRQ backend
> -     */
> -    spapr_xive_set_tctx_os_cam(spapr_cpu->tctx);
> -}
> -
>  static int spapr_irq_post_load_xive(SpaprMachineState *spapr, int version_id)
>  {
>      return spapr_xive_post_load(spapr->xive, version_id);
> @@ -316,7 +276,6 @@ SpaprIrq spapr_irq_xive = {
>      .free        = spapr_irq_free_xive,
>      .print_info  = spapr_irq_print_info_xive,
>      .dt_populate = spapr_dt_xive,
> -    .cpu_intc_create = spapr_irq_cpu_intc_create_xive,
>      .post_load   = spapr_irq_post_load_xive,
>      .reset       = spapr_irq_reset_xive,
>      .set_irq     = spapr_irq_set_irq_xive,
> @@ -381,20 +340,6 @@ static void spapr_irq_dt_populate_dual(SpaprMachineState *spapr,
>      spapr_irq_current(spapr)->dt_populate(spapr, nr_servers, fdt, phandle);
>  }
>  
> -static void spapr_irq_cpu_intc_create_dual(SpaprMachineState *spapr,
> -                                           PowerPCCPU *cpu, Error **errp)
> -{
> -    Error *local_err = NULL;
> -
> -    spapr_irq_xive.cpu_intc_create(spapr, cpu, &local_err);
> -    if (local_err) {
> -        error_propagate(errp, local_err);
> -        return;
> -    }
> -
> -    spapr_irq_xics.cpu_intc_create(spapr, cpu, errp);
> -}
> -
>  static int spapr_irq_post_load_dual(SpaprMachineState *spapr, int version_id)
>  {
>      /*
> @@ -460,7 +405,6 @@ SpaprIrq spapr_irq_dual = {
>      .free        = spapr_irq_free_dual,
>      .print_info  = spapr_irq_print_info_dual,
>      .dt_populate = spapr_irq_dt_populate_dual,
> -    .cpu_intc_create = spapr_irq_cpu_intc_create_dual,
>      .post_load   = spapr_irq_post_load_dual,
>      .reset       = spapr_irq_reset_dual,
>      .set_irq     = spapr_irq_set_irq_dual,
> @@ -525,6 +469,30 @@ static void spapr_irq_check(SpaprMachineState *spapr, Error **errp)
>  /*
>   * sPAPR IRQ frontend routines for devices
>   */
> +int spapr_irq_cpu_intc_create(SpaprMachineState *spapr,
> +                              PowerPCCPU *cpu, Error **errp)
> +{
> +    if (spapr->xive) {
> +        SpaprInterruptController *intc = SPAPR_INTC(spapr->xive);
> +        SpaprInterruptControllerClass *sicc = SPAPR_INTC_GET_CLASS(intc);
> +
> +        if (sicc->cpu_intc_create(intc, cpu, errp) < 0) {
> +            return -1;
> +        }
> +    }
> +
> +    if (spapr->ics) {
> +        SpaprInterruptController *intc = SPAPR_INTC(spapr->ics);
> +        SpaprInterruptControllerClass *sicc = SPAPR_INTC_GET_CLASS(intc);
> +
> +        if (sicc->cpu_intc_create(intc, cpu, errp) < 0) {
> +            return -1;
> +        }
> +    }
> +
> +    return 0;
> +}
> +
>  void spapr_irq_init(SpaprMachineState *spapr, Error **errp)
>  {
>      MachineState *machine = MACHINE(spapr);
> @@ -763,7 +731,6 @@ SpaprIrq spapr_irq_xics_legacy = {
>      .free        = spapr_irq_free_xics,
>      .print_info  = spapr_irq_print_info_xics,
>      .dt_populate = spapr_dt_xics,
> -    .cpu_intc_create = spapr_irq_cpu_intc_create_xics,
>      .post_load   = spapr_irq_post_load_xics,
>      .reset       = spapr_irq_reset_xics,
>      .set_irq     = spapr_irq_set_irq_xics,
> diff --git a/include/hw/ppc/spapr_irq.h b/include/hw/ppc/spapr_irq.h
> index b9398e0be3..30d660ff1e 100644
> --- a/include/hw/ppc/spapr_irq.h
> +++ b/include/hw/ppc/spapr_irq.h
> @@ -43,8 +43,22 @@ typedef struct SpaprInterruptController SpaprInterruptController;
>  
>  typedef struct SpaprInterruptControllerClass {
>      InterfaceClass parent;
> +
> +    /*
> +     * These methods will typically be called on all intcs, active and
> +     * inactive
> +     */
> +    int (*cpu_intc_create)(SpaprInterruptController *intc,
> +                            PowerPCCPU *cpu, Error **errp);
>  } SpaprInterruptControllerClass;
>  
> +void spapr_irq_print_info(SpaprMachineState *spapr, Monitor *mon);
> +void spapr_irq_dt(SpaprMachineState *spapr, uint32_t nr_servers,
> +                  void *fdt, uint32_t phandle);
> +int spapr_irq_cpu_intc_create(SpaprMachineState *spapr,
> +                              PowerPCCPU *cpu, Error **errp);
> +
> +
>  void spapr_irq_msi_init(SpaprMachineState *spapr, uint32_t nr_msis);
>  int spapr_irq_msi_alloc(SpaprMachineState *spapr, uint32_t num, bool align,
>                          Error **errp);
> @@ -61,8 +75,6 @@ typedef struct SpaprIrq {
>      void (*print_info)(SpaprMachineState *spapr, Monitor *mon);
>      void (*dt_populate)(SpaprMachineState *spapr, uint32_t nr_servers,
>                          void *fdt, uint32_t phandle);
> -    void (*cpu_intc_create)(SpaprMachineState *spapr, PowerPCCPU *cpu,
> -                            Error **errp);
>      int (*post_load)(SpaprMachineState *spapr, int version_id);
>      void (*reset)(SpaprMachineState *spapr, Error **errp);
>      void (*set_irq)(void *opaque, int srcno, int val);
>
David Gibson Sept. 30, 2019, 6:14 a.m. UTC | #6
On Mon, Sep 30, 2019 at 07:28:45AM +0200, Cédric Le Goater wrote:
> On 30/09/2019 03:49, David Gibson wrote:
> > On Fri, Sep 27, 2019 at 12:16:49PM +0200, Greg Kurz wrote:
> >> On Fri, 27 Sep 2019 15:50:16 +1000
> >> David Gibson <david@gibson.dropbear.id.au> wrote:
> >>
> >>> This method essentially represents code which belongs to the interrupt
> >>> controller, but needs to be called on all possible intcs, rather than
> >>> just the currently active one.  The "dual" version therefore calls
> >>> into the xics and xive versions confusingly.
> >>>
> >>> Handle this more directly, by making it instead a method on the intc
> >>> backend, and always calling it on every backend that exists.
> >>>
> >>> While we're there, streamline the error reporting a bit.
> >>>
> >>> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> > [snip]
> >>> @@ -525,6 +469,30 @@ static void spapr_irq_check(SpaprMachineState *spapr, Error **errp)
> >>>  /*
> >>>   * sPAPR IRQ frontend routines for devices
> >>>   */
> >>> +int spapr_irq_cpu_intc_create(SpaprMachineState *spapr,
> >>> +                              PowerPCCPU *cpu, Error **errp)
> >>> +{
> >>> +    if (spapr->xive) {
> >>> +        SpaprInterruptController *intc = SPAPR_INTC(spapr->xive);
> >>> +        SpaprInterruptControllerClass *sicc = SPAPR_INTC_GET_CLASS(intc);
> >>> +
> >>> +        if (sicc->cpu_intc_create(intc, cpu, errp) < 0) {
> >>> +            return -1;
> >>> +        }
> >>> +    }
> >>> +
> >>> +    if (spapr->ics) {
> >>> +        SpaprInterruptController *intc = SPAPR_INTC(spapr->ics);
> >>> +        SpaprInterruptControllerClass *sicc = SPAPR_INTC_GET_CLASS(intc);
> >>> +
> >>> +        if (sicc->cpu_intc_create(intc, cpu, errp) < 0) {
> >>> +            return -1;
> >>> +        }
> >>> +    }
> >>> +
> >>
> >> Instead of these hooks, what about open-coding spapr_xive_cpu_intc_create()
> >> and xics_spapr_cpu_intc_create() directly here, like you already did for the
> >> ICS and the XIVE objects in spapr_irq_init() ?
> > 
> > I'd prefer not to.  The idea is I want to treat this as basically:
> > 
> > 	foreach_possible_intc(intc)
> > 		intc::cpu_intc_create(...)
> > 
> > If I find time I might indeed replace the explicit ics and xive
> > pointers with just an array of SpaprInterruptController *.
> 
> Or you could use object_child_foreach() and check for the type. If we had
> a helper object_child_foreach_type(), we could use it elsewhere.

I thought about that, but I don't think it quite works.  The
complication is that the xics device is made explicitly a child of the
machine, but the xive device has mmio, so it's a SusBusDevice sitting
on the root bus instead.
Cédric Le Goater Sept. 30, 2019, 10:13 a.m. UTC | #7
On 30/09/2019 08:14, David Gibson wrote:
> On Mon, Sep 30, 2019 at 07:28:45AM +0200, Cédric Le Goater wrote:
>> On 30/09/2019 03:49, David Gibson wrote:
>>> On Fri, Sep 27, 2019 at 12:16:49PM +0200, Greg Kurz wrote:
>>>> On Fri, 27 Sep 2019 15:50:16 +1000
>>>> David Gibson <david@gibson.dropbear.id.au> wrote:
>>>>
>>>>> This method essentially represents code which belongs to the interrupt
>>>>> controller, but needs to be called on all possible intcs, rather than
>>>>> just the currently active one.  The "dual" version therefore calls
>>>>> into the xics and xive versions confusingly.
>>>>>
>>>>> Handle this more directly, by making it instead a method on the intc
>>>>> backend, and always calling it on every backend that exists.
>>>>>
>>>>> While we're there, streamline the error reporting a bit.
>>>>>
>>>>> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
>>> [snip]
>>>>> @@ -525,6 +469,30 @@ static void spapr_irq_check(SpaprMachineState *spapr, Error **errp)
>>>>>  /*
>>>>>   * sPAPR IRQ frontend routines for devices
>>>>>   */
>>>>> +int spapr_irq_cpu_intc_create(SpaprMachineState *spapr,
>>>>> +                              PowerPCCPU *cpu, Error **errp)
>>>>> +{
>>>>> +    if (spapr->xive) {
>>>>> +        SpaprInterruptController *intc = SPAPR_INTC(spapr->xive);
>>>>> +        SpaprInterruptControllerClass *sicc = SPAPR_INTC_GET_CLASS(intc);
>>>>> +
>>>>> +        if (sicc->cpu_intc_create(intc, cpu, errp) < 0) {
>>>>> +            return -1;
>>>>> +        }
>>>>> +    }
>>>>> +
>>>>> +    if (spapr->ics) {
>>>>> +        SpaprInterruptController *intc = SPAPR_INTC(spapr->ics);
>>>>> +        SpaprInterruptControllerClass *sicc = SPAPR_INTC_GET_CLASS(intc);
>>>>> +
>>>>> +        if (sicc->cpu_intc_create(intc, cpu, errp) < 0) {
>>>>> +            return -1;
>>>>> +        }
>>>>> +    }
>>>>> +
>>>>
>>>> Instead of these hooks, what about open-coding spapr_xive_cpu_intc_create()
>>>> and xics_spapr_cpu_intc_create() directly here, like you already did for the
>>>> ICS and the XIVE objects in spapr_irq_init() ?
>>>
>>> I'd prefer not to.  The idea is I want to treat this as basically:
>>>
>>> 	foreach_possible_intc(intc)
>>> 		intc::cpu_intc_create(...)
>>>
>>> If I find time I might indeed replace the explicit ics and xive
>>> pointers with just an array of SpaprInterruptController *.
>>
>> Or you could use object_child_foreach() and check for the type. If we had
>> a helper object_child_foreach_type(), we could use it elsewhere.
> 
> I thought about that, but I don't think it quite works.  The
> complication is that the xics device is made explicitly a child of the
> machine, but the xive device has mmio, so it's a SusBusDevice sitting
> on the root bus instead.

PnvXscom works fine with Devices and SysBusDevices.

C.
David Gibson Oct. 1, 2019, 2:31 a.m. UTC | #8
On Mon, Sep 30, 2019 at 12:13:14PM +0200, Cédric Le Goater wrote:
> On 30/09/2019 08:14, David Gibson wrote:
> > On Mon, Sep 30, 2019 at 07:28:45AM +0200, Cédric Le Goater wrote:
> >> On 30/09/2019 03:49, David Gibson wrote:
> >>> On Fri, Sep 27, 2019 at 12:16:49PM +0200, Greg Kurz wrote:
> >>>> On Fri, 27 Sep 2019 15:50:16 +1000
> >>>> David Gibson <david@gibson.dropbear.id.au> wrote:
> >>>>
> >>>>> This method essentially represents code which belongs to the interrupt
> >>>>> controller, but needs to be called on all possible intcs, rather than
> >>>>> just the currently active one.  The "dual" version therefore calls
> >>>>> into the xics and xive versions confusingly.
> >>>>>
> >>>>> Handle this more directly, by making it instead a method on the intc
> >>>>> backend, and always calling it on every backend that exists.
> >>>>>
> >>>>> While we're there, streamline the error reporting a bit.
> >>>>>
> >>>>> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> >>> [snip]
> >>>>> @@ -525,6 +469,30 @@ static void spapr_irq_check(SpaprMachineState *spapr, Error **errp)
> >>>>>  /*
> >>>>>   * sPAPR IRQ frontend routines for devices
> >>>>>   */
> >>>>> +int spapr_irq_cpu_intc_create(SpaprMachineState *spapr,
> >>>>> +                              PowerPCCPU *cpu, Error **errp)
> >>>>> +{
> >>>>> +    if (spapr->xive) {
> >>>>> +        SpaprInterruptController *intc = SPAPR_INTC(spapr->xive);
> >>>>> +        SpaprInterruptControllerClass *sicc = SPAPR_INTC_GET_CLASS(intc);
> >>>>> +
> >>>>> +        if (sicc->cpu_intc_create(intc, cpu, errp) < 0) {
> >>>>> +            return -1;
> >>>>> +        }
> >>>>> +    }
> >>>>> +
> >>>>> +    if (spapr->ics) {
> >>>>> +        SpaprInterruptController *intc = SPAPR_INTC(spapr->ics);
> >>>>> +        SpaprInterruptControllerClass *sicc = SPAPR_INTC_GET_CLASS(intc);
> >>>>> +
> >>>>> +        if (sicc->cpu_intc_create(intc, cpu, errp) < 0) {
> >>>>> +            return -1;
> >>>>> +        }
> >>>>> +    }
> >>>>> +
> >>>>
> >>>> Instead of these hooks, what about open-coding spapr_xive_cpu_intc_create()
> >>>> and xics_spapr_cpu_intc_create() directly here, like you already did for the
> >>>> ICS and the XIVE objects in spapr_irq_init() ?
> >>>
> >>> I'd prefer not to.  The idea is I want to treat this as basically:
> >>>
> >>> 	foreach_possible_intc(intc)
> >>> 		intc::cpu_intc_create(...)
> >>>
> >>> If I find time I might indeed replace the explicit ics and xive
> >>> pointers with just an array of SpaprInterruptController *.
> >>
> >> Or you could use object_child_foreach() and check for the type. If we had
> >> a helper object_child_foreach_type(), we could use it elsewhere.
> > 
> > I thought about that, but I don't think it quite works.  The
> > complication is that the xics device is made explicitly a child of the
> > machine, but the xive device has mmio, so it's a SusBusDevice sitting
> > on the root bus instead.
> 
> PnvXscom works fine with Devices and SysBusDevices.

Uh... what's an example of it working with a SysBusDevice?  All the
implementors of PNV_XSCOM_INTERFACE I could find were instantiated
with object_initialize_child() making them explicitly children of the
chip.  The SPAPR_XIVE is instantiated with qdev_create(NULL,
TYPE_SPAPR_XIVE), making it a child of the root bus, not the machine,
I believe.
Cédric Le Goater Oct. 1, 2019, 5:43 a.m. UTC | #9
On 01/10/2019 04:31, David Gibson wrote:
> On Mon, Sep 30, 2019 at 12:13:14PM +0200, Cédric Le Goater wrote:
>> On 30/09/2019 08:14, David Gibson wrote:
>>> On Mon, Sep 30, 2019 at 07:28:45AM +0200, Cédric Le Goater wrote:
>>>> On 30/09/2019 03:49, David Gibson wrote:
>>>>> On Fri, Sep 27, 2019 at 12:16:49PM +0200, Greg Kurz wrote:
>>>>>> On Fri, 27 Sep 2019 15:50:16 +1000
>>>>>> David Gibson <david@gibson.dropbear.id.au> wrote:
>>>>>>
>>>>>>> This method essentially represents code which belongs to the interrupt
>>>>>>> controller, but needs to be called on all possible intcs, rather than
>>>>>>> just the currently active one.  The "dual" version therefore calls
>>>>>>> into the xics and xive versions confusingly.
>>>>>>>
>>>>>>> Handle this more directly, by making it instead a method on the intc
>>>>>>> backend, and always calling it on every backend that exists.
>>>>>>>
>>>>>>> While we're there, streamline the error reporting a bit.
>>>>>>>
>>>>>>> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
>>>>> [snip]
>>>>>>> @@ -525,6 +469,30 @@ static void spapr_irq_check(SpaprMachineState *spapr, Error **errp)
>>>>>>>  /*
>>>>>>>   * sPAPR IRQ frontend routines for devices
>>>>>>>   */
>>>>>>> +int spapr_irq_cpu_intc_create(SpaprMachineState *spapr,
>>>>>>> +                              PowerPCCPU *cpu, Error **errp)
>>>>>>> +{
>>>>>>> +    if (spapr->xive) {
>>>>>>> +        SpaprInterruptController *intc = SPAPR_INTC(spapr->xive);
>>>>>>> +        SpaprInterruptControllerClass *sicc = SPAPR_INTC_GET_CLASS(intc);
>>>>>>> +
>>>>>>> +        if (sicc->cpu_intc_create(intc, cpu, errp) < 0) {
>>>>>>> +            return -1;
>>>>>>> +        }
>>>>>>> +    }
>>>>>>> +
>>>>>>> +    if (spapr->ics) {
>>>>>>> +        SpaprInterruptController *intc = SPAPR_INTC(spapr->ics);
>>>>>>> +        SpaprInterruptControllerClass *sicc = SPAPR_INTC_GET_CLASS(intc);
>>>>>>> +
>>>>>>> +        if (sicc->cpu_intc_create(intc, cpu, errp) < 0) {
>>>>>>> +            return -1;
>>>>>>> +        }
>>>>>>> +    }
>>>>>>> +
>>>>>>
>>>>>> Instead of these hooks, what about open-coding spapr_xive_cpu_intc_create()
>>>>>> and xics_spapr_cpu_intc_create() directly here, like you already did for the
>>>>>> ICS and the XIVE objects in spapr_irq_init() ?
>>>>>
>>>>> I'd prefer not to.  The idea is I want to treat this as basically:
>>>>>
>>>>> 	foreach_possible_intc(intc)
>>>>> 		intc::cpu_intc_create(...)
>>>>>
>>>>> If I find time I might indeed replace the explicit ics and xive
>>>>> pointers with just an array of SpaprInterruptController *.
>>>>
>>>> Or you could use object_child_foreach() and check for the type. If we had
>>>> a helper object_child_foreach_type(), we could use it elsewhere.
>>>
>>> I thought about that, but I don't think it quite works.  The
>>> complication is that the xics device is made explicitly a child of the
>>> machine, but the xive device has mmio, so it's a SusBusDevice sitting
>>> on the root bus instead.
>>
>> PnvXscom works fine with Devices and SysBusDevices.
> 
> Uh... what's an example of it working with a SysBusDevice?  All the
> implementors of PNV_XSCOM_INTERFACE I could find were instantiated
> with object_initialize_child() making them explicitly children of the
> chip.  The SPAPR_XIVE is instantiated with qdev_create(NULL,
> TYPE_SPAPR_XIVE), making it a child of the root bus, not the machine,
> I believe.

I see. We should reparent the interrupt controller then, Could we rework 
the code to instantiate and realize the XICS and XIVE model objects ? 
We have the handlers spapr_instance_init() and spapr_machine_init(). 

That always has been a problem IMO.


C.
David Gibson Oct. 1, 2019, 6:47 a.m. UTC | #10
On Tue, Oct 01, 2019 at 07:43:51AM +0200, Cédric Le Goater wrote:
> On 01/10/2019 04:31, David Gibson wrote:
> > On Mon, Sep 30, 2019 at 12:13:14PM +0200, Cédric Le Goater wrote:
> >> On 30/09/2019 08:14, David Gibson wrote:
> >>> On Mon, Sep 30, 2019 at 07:28:45AM +0200, Cédric Le Goater wrote:
> >>>> On 30/09/2019 03:49, David Gibson wrote:
> >>>>> On Fri, Sep 27, 2019 at 12:16:49PM +0200, Greg Kurz wrote:
> >>>>>> On Fri, 27 Sep 2019 15:50:16 +1000
> >>>>>> David Gibson <david@gibson.dropbear.id.au> wrote:
> >>>>>>
> >>>>>>> This method essentially represents code which belongs to the interrupt
> >>>>>>> controller, but needs to be called on all possible intcs, rather than
> >>>>>>> just the currently active one.  The "dual" version therefore calls
> >>>>>>> into the xics and xive versions confusingly.
> >>>>>>>
> >>>>>>> Handle this more directly, by making it instead a method on the intc
> >>>>>>> backend, and always calling it on every backend that exists.
> >>>>>>>
> >>>>>>> While we're there, streamline the error reporting a bit.
> >>>>>>>
> >>>>>>> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> >>>>> [snip]
> >>>>>>> @@ -525,6 +469,30 @@ static void spapr_irq_check(SpaprMachineState *spapr, Error **errp)
> >>>>>>>  /*
> >>>>>>>   * sPAPR IRQ frontend routines for devices
> >>>>>>>   */
> >>>>>>> +int spapr_irq_cpu_intc_create(SpaprMachineState *spapr,
> >>>>>>> +                              PowerPCCPU *cpu, Error **errp)
> >>>>>>> +{
> >>>>>>> +    if (spapr->xive) {
> >>>>>>> +        SpaprInterruptController *intc = SPAPR_INTC(spapr->xive);
> >>>>>>> +        SpaprInterruptControllerClass *sicc = SPAPR_INTC_GET_CLASS(intc);
> >>>>>>> +
> >>>>>>> +        if (sicc->cpu_intc_create(intc, cpu, errp) < 0) {
> >>>>>>> +            return -1;
> >>>>>>> +        }
> >>>>>>> +    }
> >>>>>>> +
> >>>>>>> +    if (spapr->ics) {
> >>>>>>> +        SpaprInterruptController *intc = SPAPR_INTC(spapr->ics);
> >>>>>>> +        SpaprInterruptControllerClass *sicc = SPAPR_INTC_GET_CLASS(intc);
> >>>>>>> +
> >>>>>>> +        if (sicc->cpu_intc_create(intc, cpu, errp) < 0) {
> >>>>>>> +            return -1;
> >>>>>>> +        }
> >>>>>>> +    }
> >>>>>>> +
> >>>>>>
> >>>>>> Instead of these hooks, what about open-coding spapr_xive_cpu_intc_create()
> >>>>>> and xics_spapr_cpu_intc_create() directly here, like you already did for the
> >>>>>> ICS and the XIVE objects in spapr_irq_init() ?
> >>>>>
> >>>>> I'd prefer not to.  The idea is I want to treat this as basically:
> >>>>>
> >>>>> 	foreach_possible_intc(intc)
> >>>>> 		intc::cpu_intc_create(...)
> >>>>>
> >>>>> If I find time I might indeed replace the explicit ics and xive
> >>>>> pointers with just an array of SpaprInterruptController *.
> >>>>
> >>>> Or you could use object_child_foreach() and check for the type. If we had
> >>>> a helper object_child_foreach_type(), we could use it elsewhere.
> >>>
> >>> I thought about that, but I don't think it quite works.  The
> >>> complication is that the xics device is made explicitly a child of the
> >>> machine, but the xive device has mmio, so it's a SusBusDevice sitting
> >>> on the root bus instead.
> >>
> >> PnvXscom works fine with Devices and SysBusDevices.
> > 
> > Uh... what's an example of it working with a SysBusDevice?  All the
> > implementors of PNV_XSCOM_INTERFACE I could find were instantiated
> > with object_initialize_child() making them explicitly children of the
> > chip.  The SPAPR_XIVE is instantiated with qdev_create(NULL,
> > TYPE_SPAPR_XIVE), making it a child of the root bus, not the machine,
> > I believe.
> 
> I see. We should reparent the interrupt controller then.

Well, maybe.  It's not obvious to me that that's the right approach
just because of this.


> Could we rework 
> the code to instantiate and realize the XICS and XIVE model objects ? 
> We have the handlers spapr_instance_init() and spapr_machine_init(). 

I'm not really sure what you're suggesting here.

> That always has been a problem IMO.
> 
> 
> C. 
>  
> 
>
Cédric Le Goater Oct. 1, 2019, 7:41 a.m. UTC | #11
On 01/10/2019 08:47, David Gibson wrote:
> On Tue, Oct 01, 2019 at 07:43:51AM +0200, Cédric Le Goater wrote:
>> On 01/10/2019 04:31, David Gibson wrote:
>>> On Mon, Sep 30, 2019 at 12:13:14PM +0200, Cédric Le Goater wrote:
>>>> On 30/09/2019 08:14, David Gibson wrote:
>>>>> On Mon, Sep 30, 2019 at 07:28:45AM +0200, Cédric Le Goater wrote:
>>>>>> On 30/09/2019 03:49, David Gibson wrote:
>>>>>>> On Fri, Sep 27, 2019 at 12:16:49PM +0200, Greg Kurz wrote:
>>>>>>>> On Fri, 27 Sep 2019 15:50:16 +1000
>>>>>>>> David Gibson <david@gibson.dropbear.id.au> wrote:
>>>>>>>>
>>>>>>>>> This method essentially represents code which belongs to the interrupt
>>>>>>>>> controller, but needs to be called on all possible intcs, rather than
>>>>>>>>> just the currently active one.  The "dual" version therefore calls
>>>>>>>>> into the xics and xive versions confusingly.
>>>>>>>>>
>>>>>>>>> Handle this more directly, by making it instead a method on the intc
>>>>>>>>> backend, and always calling it on every backend that exists.
>>>>>>>>>
>>>>>>>>> While we're there, streamline the error reporting a bit.
>>>>>>>>>
>>>>>>>>> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
>>>>>>> [snip]
>>>>>>>>> @@ -525,6 +469,30 @@ static void spapr_irq_check(SpaprMachineState *spapr, Error **errp)
>>>>>>>>>  /*
>>>>>>>>>   * sPAPR IRQ frontend routines for devices
>>>>>>>>>   */
>>>>>>>>> +int spapr_irq_cpu_intc_create(SpaprMachineState *spapr,
>>>>>>>>> +                              PowerPCCPU *cpu, Error **errp)
>>>>>>>>> +{
>>>>>>>>> +    if (spapr->xive) {
>>>>>>>>> +        SpaprInterruptController *intc = SPAPR_INTC(spapr->xive);
>>>>>>>>> +        SpaprInterruptControllerClass *sicc = SPAPR_INTC_GET_CLASS(intc);
>>>>>>>>> +
>>>>>>>>> +        if (sicc->cpu_intc_create(intc, cpu, errp) < 0) {
>>>>>>>>> +            return -1;
>>>>>>>>> +        }
>>>>>>>>> +    }
>>>>>>>>> +
>>>>>>>>> +    if (spapr->ics) {
>>>>>>>>> +        SpaprInterruptController *intc = SPAPR_INTC(spapr->ics);
>>>>>>>>> +        SpaprInterruptControllerClass *sicc = SPAPR_INTC_GET_CLASS(intc);
>>>>>>>>> +
>>>>>>>>> +        if (sicc->cpu_intc_create(intc, cpu, errp) < 0) {
>>>>>>>>> +            return -1;
>>>>>>>>> +        }
>>>>>>>>> +    }
>>>>>>>>> +
>>>>>>>>
>>>>>>>> Instead of these hooks, what about open-coding spapr_xive_cpu_intc_create()
>>>>>>>> and xics_spapr_cpu_intc_create() directly here, like you already did for the
>>>>>>>> ICS and the XIVE objects in spapr_irq_init() ?
>>>>>>>
>>>>>>> I'd prefer not to.  The idea is I want to treat this as basically:
>>>>>>>
>>>>>>> 	foreach_possible_intc(intc)
>>>>>>> 		intc::cpu_intc_create(...)
>>>>>>>
>>>>>>> If I find time I might indeed replace the explicit ics and xive
>>>>>>> pointers with just an array of SpaprInterruptController *.
>>>>>>
>>>>>> Or you could use object_child_foreach() and check for the type. If we had
>>>>>> a helper object_child_foreach_type(), we could use it elsewhere.
>>>>>
>>>>> I thought about that, but I don't think it quite works.  The
>>>>> complication is that the xics device is made explicitly a child of the
>>>>> machine, but the xive device has mmio, so it's a SusBusDevice sitting
>>>>> on the root bus instead.
>>>>
>>>> PnvXscom works fine with Devices and SysBusDevices.
>>>
>>> Uh... what's an example of it working with a SysBusDevice?  All the
>>> implementors of PNV_XSCOM_INTERFACE I could find were instantiated
>>> with object_initialize_child() making them explicitly children of the
>>> chip.  The SPAPR_XIVE is instantiated with qdev_create(NULL,
>>> TYPE_SPAPR_XIVE), making it a child of the root bus, not the machine,
>>> I believe.
>>
>> I see. We should reparent the interrupt controller then.
> 
> Well, maybe.  It's not obvious to me that that's the right approach
> just because of this.
> 
> 
>> Could we rework 
>> the code to instantiate and realize the XICS and XIVE model objects ? 
>> We have the handlers spapr_instance_init() and spapr_machine_init(). 
> 
> I'm not really sure what you're suggesting here.

Define the device model objects under the machine and not pointers :

	struct SpaprMachineState {
		...
		ICSState ics;
		SpaprXive  xive;
		...
	};

in spapr_instance_init() :

	object_initialize_child(obj, "ics",  &spapr->ics, sizeof(spapr->ics),
                            TYPE_ICS, &error_abort, NULL);
	object_property_add_const_link(OBJECT(&spapr->ics), "xics", obj,
                                   &error_abort);

	object_initialize_child(obj, "xive",  &spapr->xive, sizeof(spapr->xive),
                            TYPE_SPAPR_XIVE, &error_abort, NULL);


in spapr_machine_init(), call the realize handler depending on the chosen 
'ic-mode'. 


C.


>> That always has been a problem IMO.
>>
>>
>> C. 
>>  
>>
>>
>
David Gibson Oct. 1, 2019, 8:11 a.m. UTC | #12
On Tue, Oct 01, 2019 at 09:41:27AM +0200, Cédric Le Goater wrote:
> On 01/10/2019 08:47, David Gibson wrote:
> > On Tue, Oct 01, 2019 at 07:43:51AM +0200, Cédric Le Goater wrote:
> >> On 01/10/2019 04:31, David Gibson wrote:
> >>> On Mon, Sep 30, 2019 at 12:13:14PM +0200, Cédric Le Goater wrote:
> >>>> On 30/09/2019 08:14, David Gibson wrote:
> >>>>> On Mon, Sep 30, 2019 at 07:28:45AM +0200, Cédric Le Goater wrote:
> >>>>>> On 30/09/2019 03:49, David Gibson wrote:
> >>>>>>> On Fri, Sep 27, 2019 at 12:16:49PM +0200, Greg Kurz wrote:
> >>>>>>>> On Fri, 27 Sep 2019 15:50:16 +1000
> >>>>>>>> David Gibson <david@gibson.dropbear.id.au> wrote:
> >>>>>>>>
> >>>>>>>>> This method essentially represents code which belongs to the interrupt
> >>>>>>>>> controller, but needs to be called on all possible intcs, rather than
> >>>>>>>>> just the currently active one.  The "dual" version therefore calls
> >>>>>>>>> into the xics and xive versions confusingly.
> >>>>>>>>>
> >>>>>>>>> Handle this more directly, by making it instead a method on the intc
> >>>>>>>>> backend, and always calling it on every backend that exists.
> >>>>>>>>>
> >>>>>>>>> While we're there, streamline the error reporting a bit.
> >>>>>>>>>
> >>>>>>>>> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> >>>>>>> [snip]
> >>>>>>>>> @@ -525,6 +469,30 @@ static void spapr_irq_check(SpaprMachineState *spapr, Error **errp)
> >>>>>>>>>  /*
> >>>>>>>>>   * sPAPR IRQ frontend routines for devices
> >>>>>>>>>   */
> >>>>>>>>> +int spapr_irq_cpu_intc_create(SpaprMachineState *spapr,
> >>>>>>>>> +                              PowerPCCPU *cpu, Error **errp)
> >>>>>>>>> +{
> >>>>>>>>> +    if (spapr->xive) {
> >>>>>>>>> +        SpaprInterruptController *intc = SPAPR_INTC(spapr->xive);
> >>>>>>>>> +        SpaprInterruptControllerClass *sicc = SPAPR_INTC_GET_CLASS(intc);
> >>>>>>>>> +
> >>>>>>>>> +        if (sicc->cpu_intc_create(intc, cpu, errp) < 0) {
> >>>>>>>>> +            return -1;
> >>>>>>>>> +        }
> >>>>>>>>> +    }
> >>>>>>>>> +
> >>>>>>>>> +    if (spapr->ics) {
> >>>>>>>>> +        SpaprInterruptController *intc = SPAPR_INTC(spapr->ics);
> >>>>>>>>> +        SpaprInterruptControllerClass *sicc = SPAPR_INTC_GET_CLASS(intc);
> >>>>>>>>> +
> >>>>>>>>> +        if (sicc->cpu_intc_create(intc, cpu, errp) < 0) {
> >>>>>>>>> +            return -1;
> >>>>>>>>> +        }
> >>>>>>>>> +    }
> >>>>>>>>> +
> >>>>>>>>
> >>>>>>>> Instead of these hooks, what about open-coding spapr_xive_cpu_intc_create()
> >>>>>>>> and xics_spapr_cpu_intc_create() directly here, like you already did for the
> >>>>>>>> ICS and the XIVE objects in spapr_irq_init() ?
> >>>>>>>
> >>>>>>> I'd prefer not to.  The idea is I want to treat this as basically:
> >>>>>>>
> >>>>>>> 	foreach_possible_intc(intc)
> >>>>>>> 		intc::cpu_intc_create(...)
> >>>>>>>
> >>>>>>> If I find time I might indeed replace the explicit ics and xive
> >>>>>>> pointers with just an array of SpaprInterruptController *.
> >>>>>>
> >>>>>> Or you could use object_child_foreach() and check for the type. If we had
> >>>>>> a helper object_child_foreach_type(), we could use it elsewhere.
> >>>>>
> >>>>> I thought about that, but I don't think it quite works.  The
> >>>>> complication is that the xics device is made explicitly a child of the
> >>>>> machine, but the xive device has mmio, so it's a SusBusDevice sitting
> >>>>> on the root bus instead.
> >>>>
> >>>> PnvXscom works fine with Devices and SysBusDevices.
> >>>
> >>> Uh... what's an example of it working with a SysBusDevice?  All the
> >>> implementors of PNV_XSCOM_INTERFACE I could find were instantiated
> >>> with object_initialize_child() making them explicitly children of the
> >>> chip.  The SPAPR_XIVE is instantiated with qdev_create(NULL,
> >>> TYPE_SPAPR_XIVE), making it a child of the root bus, not the machine,
> >>> I believe.
> >>
> >> I see. We should reparent the interrupt controller then.
> > 
> > Well, maybe.  It's not obvious to me that that's the right approach
> > just because of this.
> > 
> > 
> >> Could we rework 
> >> the code to instantiate and realize the XICS and XIVE model objects ? 
> >> We have the handlers spapr_instance_init() and spapr_machine_init(). 
> > 
> > I'm not really sure what you're suggesting here.
> 
> Define the device model objects under the machine and not pointers :
> 
> 	struct SpaprMachineState {
> 		...
> 		ICSState ics;
> 		SpaprXive  xive;
> 		...
> 	};
> 
> in spapr_instance_init() :
> 
> 	object_initialize_child(obj, "ics",  &spapr->ics, sizeof(spapr->ics),
>                             TYPE_ICS, &error_abort, NULL);
> 	object_property_add_const_link(OBJECT(&spapr->ics), "xics", obj,
>                                    &error_abort);
> 
> 	object_initialize_child(obj, "xive",  &spapr->xive, sizeof(spapr->xive),
>                             TYPE_SPAPR_XIVE, &error_abort, NULL);
> 
> 
> in spapr_machine_init(), call the realize handler depending on the chosen 
> 'ic-mode'.

Hm, yeah, maybe.  I don't love having a whole structure in there
that's unused when ic-mode != dual.
Cédric Le Goater Oct. 1, 2019, 11:43 a.m. UTC | #13
On 01/10/2019 10:11, David Gibson wrote:
> On Tue, Oct 01, 2019 at 09:41:27AM +0200, Cédric Le Goater wrote:
>> On 01/10/2019 08:47, David Gibson wrote:
>>> On Tue, Oct 01, 2019 at 07:43:51AM +0200, Cédric Le Goater wrote:
>>>> On 01/10/2019 04:31, David Gibson wrote:
>>>>> On Mon, Sep 30, 2019 at 12:13:14PM +0200, Cédric Le Goater wrote:
>>>>>> On 30/09/2019 08:14, David Gibson wrote:
>>>>>>> On Mon, Sep 30, 2019 at 07:28:45AM +0200, Cédric Le Goater wrote:
>>>>>>>> On 30/09/2019 03:49, David Gibson wrote:
>>>>>>>>> On Fri, Sep 27, 2019 at 12:16:49PM +0200, Greg Kurz wrote:
>>>>>>>>>> On Fri, 27 Sep 2019 15:50:16 +1000
>>>>>>>>>> David Gibson <david@gibson.dropbear.id.au> wrote:
>>>>>>>>>>
>>>>>>>>>>> This method essentially represents code which belongs to the interrupt
>>>>>>>>>>> controller, but needs to be called on all possible intcs, rather than
>>>>>>>>>>> just the currently active one.  The "dual" version therefore calls
>>>>>>>>>>> into the xics and xive versions confusingly.
>>>>>>>>>>>
>>>>>>>>>>> Handle this more directly, by making it instead a method on the intc
>>>>>>>>>>> backend, and always calling it on every backend that exists.
>>>>>>>>>>>
>>>>>>>>>>> While we're there, streamline the error reporting a bit.
>>>>>>>>>>>
>>>>>>>>>>> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
>>>>>>>>> [snip]
>>>>>>>>>>> @@ -525,6 +469,30 @@ static void spapr_irq_check(SpaprMachineState *spapr, Error **errp)
>>>>>>>>>>>  /*
>>>>>>>>>>>   * sPAPR IRQ frontend routines for devices
>>>>>>>>>>>   */
>>>>>>>>>>> +int spapr_irq_cpu_intc_create(SpaprMachineState *spapr,
>>>>>>>>>>> +                              PowerPCCPU *cpu, Error **errp)
>>>>>>>>>>> +{
>>>>>>>>>>> +    if (spapr->xive) {
>>>>>>>>>>> +        SpaprInterruptController *intc = SPAPR_INTC(spapr->xive);
>>>>>>>>>>> +        SpaprInterruptControllerClass *sicc = SPAPR_INTC_GET_CLASS(intc);
>>>>>>>>>>> +
>>>>>>>>>>> +        if (sicc->cpu_intc_create(intc, cpu, errp) < 0) {
>>>>>>>>>>> +            return -1;
>>>>>>>>>>> +        }
>>>>>>>>>>> +    }
>>>>>>>>>>> +
>>>>>>>>>>> +    if (spapr->ics) {
>>>>>>>>>>> +        SpaprInterruptController *intc = SPAPR_INTC(spapr->ics);
>>>>>>>>>>> +        SpaprInterruptControllerClass *sicc = SPAPR_INTC_GET_CLASS(intc);
>>>>>>>>>>> +
>>>>>>>>>>> +        if (sicc->cpu_intc_create(intc, cpu, errp) < 0) {
>>>>>>>>>>> +            return -1;
>>>>>>>>>>> +        }
>>>>>>>>>>> +    }
>>>>>>>>>>> +
>>>>>>>>>>
>>>>>>>>>> Instead of these hooks, what about open-coding spapr_xive_cpu_intc_create()
>>>>>>>>>> and xics_spapr_cpu_intc_create() directly here, like you already did for the
>>>>>>>>>> ICS and the XIVE objects in spapr_irq_init() ?
>>>>>>>>>
>>>>>>>>> I'd prefer not to.  The idea is I want to treat this as basically:
>>>>>>>>>
>>>>>>>>> 	foreach_possible_intc(intc)
>>>>>>>>> 		intc::cpu_intc_create(...)
>>>>>>>>>
>>>>>>>>> If I find time I might indeed replace the explicit ics and xive
>>>>>>>>> pointers with just an array of SpaprInterruptController *.
>>>>>>>>
>>>>>>>> Or you could use object_child_foreach() and check for the type. If we had
>>>>>>>> a helper object_child_foreach_type(), we could use it elsewhere.
>>>>>>>
>>>>>>> I thought about that, but I don't think it quite works.  The
>>>>>>> complication is that the xics device is made explicitly a child of the
>>>>>>> machine, but the xive device has mmio, so it's a SusBusDevice sitting
>>>>>>> on the root bus instead.
>>>>>>
>>>>>> PnvXscom works fine with Devices and SysBusDevices.
>>>>>
>>>>> Uh... what's an example of it working with a SysBusDevice?  All the
>>>>> implementors of PNV_XSCOM_INTERFACE I could find were instantiated
>>>>> with object_initialize_child() making them explicitly children of the
>>>>> chip.  The SPAPR_XIVE is instantiated with qdev_create(NULL,
>>>>> TYPE_SPAPR_XIVE), making it a child of the root bus, not the machine,
>>>>> I believe.
>>>>
>>>> I see. We should reparent the interrupt controller then.
>>>
>>> Well, maybe.  It's not obvious to me that that's the right approach
>>> just because of this.
>>>
>>>
>>>> Could we rework 
>>>> the code to instantiate and realize the XICS and XIVE model objects ? 
>>>> We have the handlers spapr_instance_init() and spapr_machine_init(). 
>>>
>>> I'm not really sure what you're suggesting here.
>>
>> Define the device model objects under the machine and not pointers :
>>
>> 	struct SpaprMachineState {
>> 		...
>> 		ICSState ics;
>> 		SpaprXive  xive;
>> 		...
>> 	};
>>
>> in spapr_instance_init() :
>>
>> 	object_initialize_child(obj, "ics",  &spapr->ics, sizeof(spapr->ics),
>>                             TYPE_ICS, &error_abort, NULL);
>> 	object_property_add_const_link(OBJECT(&spapr->ics), "xics", obj,
>>                                    &error_abort);
>>
>> 	object_initialize_child(obj, "xive",  &spapr->xive, sizeof(spapr->xive),
>>                             TYPE_SPAPR_XIVE, &error_abort, NULL);
>>
>>
>> in spapr_machine_init(), call the realize handler depending on the chosen 
>> 'ic-mode'.
> 
> Hm, yeah, maybe.  I don't love having a whole structure in there
> that's unused when ic-mode != dual.
> 

This is the pattern followed in the ARM SoC models. Enough room is 
provisioned for the maximum controllers and depending on the SoC
configuration only some are realized.

C.
David Gibson Oct. 2, 2019, 1:11 a.m. UTC | #14
On Tue, Oct 01, 2019 at 01:43:12PM +0200, Cédric Le Goater wrote:
> On 01/10/2019 10:11, David Gibson wrote:
> > On Tue, Oct 01, 2019 at 09:41:27AM +0200, Cédric Le Goater wrote:
> >> On 01/10/2019 08:47, David Gibson wrote:
> >>> On Tue, Oct 01, 2019 at 07:43:51AM +0200, Cédric Le Goater wrote:
> >>>> On 01/10/2019 04:31, David Gibson wrote:
> >>>>> On Mon, Sep 30, 2019 at 12:13:14PM +0200, Cédric Le Goater wrote:
> >>>>>> On 30/09/2019 08:14, David Gibson wrote:
> >>>>>>> On Mon, Sep 30, 2019 at 07:28:45AM +0200, Cédric Le Goater wrote:
> >>>>>>>> On 30/09/2019 03:49, David Gibson wrote:
> >>>>>>>>> On Fri, Sep 27, 2019 at 12:16:49PM +0200, Greg Kurz wrote:
> >>>>>>>>>> On Fri, 27 Sep 2019 15:50:16 +1000
> >>>>>>>>>> David Gibson <david@gibson.dropbear.id.au> wrote:
> >>>>>>>>>>
> >>>>>>>>>>> This method essentially represents code which belongs to the interrupt
> >>>>>>>>>>> controller, but needs to be called on all possible intcs, rather than
> >>>>>>>>>>> just the currently active one.  The "dual" version therefore calls
> >>>>>>>>>>> into the xics and xive versions confusingly.
> >>>>>>>>>>>
> >>>>>>>>>>> Handle this more directly, by making it instead a method on the intc
> >>>>>>>>>>> backend, and always calling it on every backend that exists.
> >>>>>>>>>>>
> >>>>>>>>>>> While we're there, streamline the error reporting a bit.
> >>>>>>>>>>>
> >>>>>>>>>>> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> >>>>>>>>> [snip]
> >>>>>>>>>>> @@ -525,6 +469,30 @@ static void spapr_irq_check(SpaprMachineState *spapr, Error **errp)
> >>>>>>>>>>>  /*
> >>>>>>>>>>>   * sPAPR IRQ frontend routines for devices
> >>>>>>>>>>>   */
> >>>>>>>>>>> +int spapr_irq_cpu_intc_create(SpaprMachineState *spapr,
> >>>>>>>>>>> +                              PowerPCCPU *cpu, Error **errp)
> >>>>>>>>>>> +{
> >>>>>>>>>>> +    if (spapr->xive) {
> >>>>>>>>>>> +        SpaprInterruptController *intc = SPAPR_INTC(spapr->xive);
> >>>>>>>>>>> +        SpaprInterruptControllerClass *sicc = SPAPR_INTC_GET_CLASS(intc);
> >>>>>>>>>>> +
> >>>>>>>>>>> +        if (sicc->cpu_intc_create(intc, cpu, errp) < 0) {
> >>>>>>>>>>> +            return -1;
> >>>>>>>>>>> +        }
> >>>>>>>>>>> +    }
> >>>>>>>>>>> +
> >>>>>>>>>>> +    if (spapr->ics) {
> >>>>>>>>>>> +        SpaprInterruptController *intc = SPAPR_INTC(spapr->ics);
> >>>>>>>>>>> +        SpaprInterruptControllerClass *sicc = SPAPR_INTC_GET_CLASS(intc);
> >>>>>>>>>>> +
> >>>>>>>>>>> +        if (sicc->cpu_intc_create(intc, cpu, errp) < 0) {
> >>>>>>>>>>> +            return -1;
> >>>>>>>>>>> +        }
> >>>>>>>>>>> +    }
> >>>>>>>>>>> +
> >>>>>>>>>>
> >>>>>>>>>> Instead of these hooks, what about open-coding spapr_xive_cpu_intc_create()
> >>>>>>>>>> and xics_spapr_cpu_intc_create() directly here, like you already did for the
> >>>>>>>>>> ICS and the XIVE objects in spapr_irq_init() ?
> >>>>>>>>>
> >>>>>>>>> I'd prefer not to.  The idea is I want to treat this as basically:
> >>>>>>>>>
> >>>>>>>>> 	foreach_possible_intc(intc)
> >>>>>>>>> 		intc::cpu_intc_create(...)
> >>>>>>>>>
> >>>>>>>>> If I find time I might indeed replace the explicit ics and xive
> >>>>>>>>> pointers with just an array of SpaprInterruptController *.
> >>>>>>>>
> >>>>>>>> Or you could use object_child_foreach() and check for the type. If we had
> >>>>>>>> a helper object_child_foreach_type(), we could use it elsewhere.
> >>>>>>>
> >>>>>>> I thought about that, but I don't think it quite works.  The
> >>>>>>> complication is that the xics device is made explicitly a child of the
> >>>>>>> machine, but the xive device has mmio, so it's a SusBusDevice sitting
> >>>>>>> on the root bus instead.
> >>>>>>
> >>>>>> PnvXscom works fine with Devices and SysBusDevices.
> >>>>>
> >>>>> Uh... what's an example of it working with a SysBusDevice?  All the
> >>>>> implementors of PNV_XSCOM_INTERFACE I could find were instantiated
> >>>>> with object_initialize_child() making them explicitly children of the
> >>>>> chip.  The SPAPR_XIVE is instantiated with qdev_create(NULL,
> >>>>> TYPE_SPAPR_XIVE), making it a child of the root bus, not the machine,
> >>>>> I believe.
> >>>>
> >>>> I see. We should reparent the interrupt controller then.
> >>>
> >>> Well, maybe.  It's not obvious to me that that's the right approach
> >>> just because of this.
> >>>
> >>>
> >>>> Could we rework 
> >>>> the code to instantiate and realize the XICS and XIVE model objects ? 
> >>>> We have the handlers spapr_instance_init() and spapr_machine_init(). 
> >>>
> >>> I'm not really sure what you're suggesting here.
> >>
> >> Define the device model objects under the machine and not pointers :
> >>
> >> 	struct SpaprMachineState {
> >> 		...
> >> 		ICSState ics;
> >> 		SpaprXive  xive;
> >> 		...
> >> 	};
> >>
> >> in spapr_instance_init() :
> >>
> >> 	object_initialize_child(obj, "ics",  &spapr->ics, sizeof(spapr->ics),
> >>                             TYPE_ICS, &error_abort, NULL);
> >> 	object_property_add_const_link(OBJECT(&spapr->ics), "xics", obj,
> >>                                    &error_abort);
> >>
> >> 	object_initialize_child(obj, "xive",  &spapr->xive, sizeof(spapr->xive),
> >>                             TYPE_SPAPR_XIVE, &error_abort, NULL);
> >>
> >>
> >> in spapr_machine_init(), call the realize handler depending on the chosen 
> >> 'ic-mode'.
> > 
> > Hm, yeah, maybe.  I don't love having a whole structure in there
> > that's unused when ic-mode != dual.
> > 
> 
> This is the pattern followed in the ARM SoC models. Enough room is 
> provisioned for the maximum controllers and depending on the SoC
> configuration only some are realized.

Hm, ok, I guess that makes it a pretty promising approach.  Maybe for
another day though.  In the meantime I've come up with an approach
that's not totally elegant, but it does remove the duplication of the
paths for xics vs. xive, keep the individual pointers in the structure
for now, and isn't *too* verbose.

I've stripped your R-b due to the change, so please have a look in the
next spin.
diff mbox series

Patch

diff --git a/hw/intc/spapr_xive.c b/hw/intc/spapr_xive.c
index b67e9c3245..9338daba3d 100644
--- a/hw/intc/spapr_xive.c
+++ b/hw/intc/spapr_xive.c
@@ -495,10 +495,33 @@  static Property spapr_xive_properties[] = {
     DEFINE_PROP_END_OF_LIST(),
 };
 
+static int spapr_xive_cpu_intc_create(SpaprInterruptController *intc,
+                                      PowerPCCPU *cpu, Error **errp)
+{
+    SpaprXive *xive = SPAPR_XIVE(intc);
+    Object *obj;
+    SpaprCpuState *spapr_cpu = spapr_cpu_state(cpu);
+
+    obj = xive_tctx_create(OBJECT(cpu), XIVE_ROUTER(xive), errp);
+    if (!obj) {
+        return -1;
+    }
+
+    spapr_cpu->tctx = XIVE_TCTX(obj);
+
+    /*
+     * (TCG) Early setting the OS CAM line for hotplugged CPUs as they
+     * don't beneficiate from the reset of the XIVE IRQ backend
+     */
+    spapr_xive_set_tctx_os_cam(spapr_cpu->tctx);
+    return 0;
+}
+
 static void spapr_xive_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
     XiveRouterClass *xrc = XIVE_ROUTER_CLASS(klass);
+    SpaprInterruptControllerClass *sicc = SPAPR_INTC_CLASS(klass);
 
     dc->desc    = "sPAPR XIVE Interrupt Controller";
     dc->props   = spapr_xive_properties;
@@ -511,6 +534,8 @@  static void spapr_xive_class_init(ObjectClass *klass, void *data)
     xrc->get_nvt = spapr_xive_get_nvt;
     xrc->write_nvt = spapr_xive_write_nvt;
     xrc->get_tctx = spapr_xive_get_tctx;
+
+    sicc->cpu_intc_create = spapr_xive_cpu_intc_create;
 }
 
 static const TypeInfo spapr_xive_info = {
diff --git a/hw/intc/xics_spapr.c b/hw/intc/xics_spapr.c
index 4874e6be55..946311b858 100644
--- a/hw/intc/xics_spapr.c
+++ b/hw/intc/xics_spapr.c
@@ -330,13 +330,31 @@  void spapr_dt_xics(SpaprMachineState *spapr, uint32_t nr_servers, void *fdt,
     _FDT(fdt_setprop_cell(fdt, node, "phandle", phandle));
 }
 
+static int xics_spapr_cpu_intc_create(SpaprInterruptController *intc,
+                                       PowerPCCPU *cpu, Error **errp)
+{
+    ICSState *ics = ICS_SPAPR(intc);
+    Object *obj;
+    SpaprCpuState *spapr_cpu = spapr_cpu_state(cpu);
+
+    obj = icp_create(OBJECT(cpu), TYPE_ICP, ics->xics, errp);
+    if (!obj) {
+        return -1;
+    }
+
+    spapr_cpu->icp = ICP(obj);
+    return 0;
+}
+
 static void ics_spapr_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
     ICSStateClass *isc = ICS_CLASS(klass);
+    SpaprInterruptControllerClass *sicc = SPAPR_INTC_CLASS(klass);
 
     device_class_set_parent_realize(dc, ics_spapr_realize,
                                     &isc->parent_realize);
+    sicc->cpu_intc_create = xics_spapr_cpu_intc_create;
 }
 
 static const TypeInfo ics_spapr_info = {
diff --git a/hw/ppc/spapr_cpu_core.c b/hw/ppc/spapr_cpu_core.c
index 1d93de8161..3e4302c7d5 100644
--- a/hw/ppc/spapr_cpu_core.c
+++ b/hw/ppc/spapr_cpu_core.c
@@ -237,8 +237,7 @@  static void spapr_realize_vcpu(PowerPCCPU *cpu, SpaprMachineState *spapr,
     qemu_register_reset(spapr_cpu_reset, cpu);
     spapr_cpu_reset(cpu);
 
-    spapr->irq->cpu_intc_create(spapr, cpu, &local_err);
-    if (local_err) {
+    if (spapr_irq_cpu_intc_create(spapr, cpu, &local_err) < 0) {
         goto error_unregister;
     }
 
diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c
index 0603c82fe8..a855dfe4e9 100644
--- a/hw/ppc/spapr_irq.c
+++ b/hw/ppc/spapr_irq.c
@@ -138,23 +138,6 @@  static void spapr_irq_print_info_xics(SpaprMachineState *spapr, Monitor *mon)
     ics_pic_print_info(spapr->ics, mon);
 }
 
-static void spapr_irq_cpu_intc_create_xics(SpaprMachineState *spapr,
-                                           PowerPCCPU *cpu, Error **errp)
-{
-    Error *local_err = NULL;
-    Object *obj;
-    SpaprCpuState *spapr_cpu = spapr_cpu_state(cpu);
-
-    obj = icp_create(OBJECT(cpu), TYPE_ICP, XICS_FABRIC(spapr),
-                     &local_err);
-    if (local_err) {
-        error_propagate(errp, local_err);
-        return;
-    }
-
-    spapr_cpu->icp = ICP(obj);
-}
-
 static int spapr_irq_post_load_xics(SpaprMachineState *spapr, int version_id)
 {
     if (!kvm_irqchip_in_kernel()) {
@@ -203,7 +186,6 @@  SpaprIrq spapr_irq_xics = {
     .free        = spapr_irq_free_xics,
     .print_info  = spapr_irq_print_info_xics,
     .dt_populate = spapr_dt_xics,
-    .cpu_intc_create = spapr_irq_cpu_intc_create_xics,
     .post_load   = spapr_irq_post_load_xics,
     .reset       = spapr_irq_reset_xics,
     .set_irq     = spapr_irq_set_irq_xics,
@@ -239,28 +221,6 @@  static void spapr_irq_print_info_xive(SpaprMachineState *spapr,
     spapr_xive_pic_print_info(spapr->xive, mon);
 }
 
-static void spapr_irq_cpu_intc_create_xive(SpaprMachineState *spapr,
-                                           PowerPCCPU *cpu, Error **errp)
-{
-    Error *local_err = NULL;
-    Object *obj;
-    SpaprCpuState *spapr_cpu = spapr_cpu_state(cpu);
-
-    obj = xive_tctx_create(OBJECT(cpu), XIVE_ROUTER(spapr->xive), &local_err);
-    if (local_err) {
-        error_propagate(errp, local_err);
-        return;
-    }
-
-    spapr_cpu->tctx = XIVE_TCTX(obj);
-
-    /*
-     * (TCG) Early setting the OS CAM line for hotplugged CPUs as they
-     * don't beneficiate from the reset of the XIVE IRQ backend
-     */
-    spapr_xive_set_tctx_os_cam(spapr_cpu->tctx);
-}
-
 static int spapr_irq_post_load_xive(SpaprMachineState *spapr, int version_id)
 {
     return spapr_xive_post_load(spapr->xive, version_id);
@@ -316,7 +276,6 @@  SpaprIrq spapr_irq_xive = {
     .free        = spapr_irq_free_xive,
     .print_info  = spapr_irq_print_info_xive,
     .dt_populate = spapr_dt_xive,
-    .cpu_intc_create = spapr_irq_cpu_intc_create_xive,
     .post_load   = spapr_irq_post_load_xive,
     .reset       = spapr_irq_reset_xive,
     .set_irq     = spapr_irq_set_irq_xive,
@@ -381,20 +340,6 @@  static void spapr_irq_dt_populate_dual(SpaprMachineState *spapr,
     spapr_irq_current(spapr)->dt_populate(spapr, nr_servers, fdt, phandle);
 }
 
-static void spapr_irq_cpu_intc_create_dual(SpaprMachineState *spapr,
-                                           PowerPCCPU *cpu, Error **errp)
-{
-    Error *local_err = NULL;
-
-    spapr_irq_xive.cpu_intc_create(spapr, cpu, &local_err);
-    if (local_err) {
-        error_propagate(errp, local_err);
-        return;
-    }
-
-    spapr_irq_xics.cpu_intc_create(spapr, cpu, errp);
-}
-
 static int spapr_irq_post_load_dual(SpaprMachineState *spapr, int version_id)
 {
     /*
@@ -460,7 +405,6 @@  SpaprIrq spapr_irq_dual = {
     .free        = spapr_irq_free_dual,
     .print_info  = spapr_irq_print_info_dual,
     .dt_populate = spapr_irq_dt_populate_dual,
-    .cpu_intc_create = spapr_irq_cpu_intc_create_dual,
     .post_load   = spapr_irq_post_load_dual,
     .reset       = spapr_irq_reset_dual,
     .set_irq     = spapr_irq_set_irq_dual,
@@ -525,6 +469,30 @@  static void spapr_irq_check(SpaprMachineState *spapr, Error **errp)
 /*
  * sPAPR IRQ frontend routines for devices
  */
+int spapr_irq_cpu_intc_create(SpaprMachineState *spapr,
+                              PowerPCCPU *cpu, Error **errp)
+{
+    if (spapr->xive) {
+        SpaprInterruptController *intc = SPAPR_INTC(spapr->xive);
+        SpaprInterruptControllerClass *sicc = SPAPR_INTC_GET_CLASS(intc);
+
+        if (sicc->cpu_intc_create(intc, cpu, errp) < 0) {
+            return -1;
+        }
+    }
+
+    if (spapr->ics) {
+        SpaprInterruptController *intc = SPAPR_INTC(spapr->ics);
+        SpaprInterruptControllerClass *sicc = SPAPR_INTC_GET_CLASS(intc);
+
+        if (sicc->cpu_intc_create(intc, cpu, errp) < 0) {
+            return -1;
+        }
+    }
+
+    return 0;
+}
+
 void spapr_irq_init(SpaprMachineState *spapr, Error **errp)
 {
     MachineState *machine = MACHINE(spapr);
@@ -763,7 +731,6 @@  SpaprIrq spapr_irq_xics_legacy = {
     .free        = spapr_irq_free_xics,
     .print_info  = spapr_irq_print_info_xics,
     .dt_populate = spapr_dt_xics,
-    .cpu_intc_create = spapr_irq_cpu_intc_create_xics,
     .post_load   = spapr_irq_post_load_xics,
     .reset       = spapr_irq_reset_xics,
     .set_irq     = spapr_irq_set_irq_xics,
diff --git a/include/hw/ppc/spapr_irq.h b/include/hw/ppc/spapr_irq.h
index b9398e0be3..30d660ff1e 100644
--- a/include/hw/ppc/spapr_irq.h
+++ b/include/hw/ppc/spapr_irq.h
@@ -43,8 +43,22 @@  typedef struct SpaprInterruptController SpaprInterruptController;
 
 typedef struct SpaprInterruptControllerClass {
     InterfaceClass parent;
+
+    /*
+     * These methods will typically be called on all intcs, active and
+     * inactive
+     */
+    int (*cpu_intc_create)(SpaprInterruptController *intc,
+                            PowerPCCPU *cpu, Error **errp);
 } SpaprInterruptControllerClass;
 
+void spapr_irq_print_info(SpaprMachineState *spapr, Monitor *mon);
+void spapr_irq_dt(SpaprMachineState *spapr, uint32_t nr_servers,
+                  void *fdt, uint32_t phandle);
+int spapr_irq_cpu_intc_create(SpaprMachineState *spapr,
+                              PowerPCCPU *cpu, Error **errp);
+
+
 void spapr_irq_msi_init(SpaprMachineState *spapr, uint32_t nr_msis);
 int spapr_irq_msi_alloc(SpaprMachineState *spapr, uint32_t num, bool align,
                         Error **errp);
@@ -61,8 +75,6 @@  typedef struct SpaprIrq {
     void (*print_info)(SpaprMachineState *spapr, Monitor *mon);
     void (*dt_populate)(SpaprMachineState *spapr, uint32_t nr_servers,
                         void *fdt, uint32_t phandle);
-    void (*cpu_intc_create)(SpaprMachineState *spapr, PowerPCCPU *cpu,
-                            Error **errp);
     int (*post_load)(SpaprMachineState *spapr, int version_id);
     void (*reset)(SpaprMachineState *spapr, Error **errp);
     void (*set_irq)(void *opaque, int srcno, int val);