diff mbox series

[v5,20/36] spapr: add classes for the XIVE models

Message ID 20181116105729.23240-21-clg@kaod.org (mailing list archive)
State New, archived
Headers show
Series ppc: support for the XIVE interrupt controller (POWER9) | expand

Commit Message

Cédric Le Goater Nov. 16, 2018, 10:57 a.m. UTC
The XIVE models for the QEMU and KVM accelerators will have a lot in
common. Introduce an abstract class for the source, the thread context
and the interrupt controller object to handle the differences in the
object initialization. These classes will also be used to define state
synchronization handlers for the monitor and migration usage.

This is very much like the XICS models.

Signed-off-by: Cédric Le Goater <clg@kaod.org>
---
 include/hw/ppc/spapr_xive.h |  15 +++++
 include/hw/ppc/xive.h       |  30 ++++++++++
 hw/intc/spapr_xive.c        |  86 +++++++++++++++++++---------
 hw/intc/xive.c              | 109 +++++++++++++++++++++++++-----------
 hw/ppc/spapr_irq.c          |   4 +-
 5 files changed, 182 insertions(+), 62 deletions(-)

Comments

David Gibson Nov. 28, 2018, 5:13 a.m. UTC | #1
On Fri, Nov 16, 2018 at 11:57:13AM +0100, Cédric Le Goater wrote:
> The XIVE models for the QEMU and KVM accelerators will have a lot in
> common. Introduce an abstract class for the source, the thread context
> and the interrupt controller object to handle the differences in the
> object initialization. These classes will also be used to define state
> synchronization handlers for the monitor and migration usage.
> 
> This is very much like the XICS models.

Yeah.. so I know it's my code, but in hindsight I think making
separate subclasses for TCG and KVM was a mistake.  The distinction
between emulated and KVM version is supposed to be invisible to both
guest and (almost) to user, whereas a subclass usually indicates a
visibly different device.

> Signed-off-by: Cédric Le Goater <clg@kaod.org>
> ---
>  include/hw/ppc/spapr_xive.h |  15 +++++
>  include/hw/ppc/xive.h       |  30 ++++++++++
>  hw/intc/spapr_xive.c        |  86 +++++++++++++++++++---------
>  hw/intc/xive.c              | 109 +++++++++++++++++++++++++-----------
>  hw/ppc/spapr_irq.c          |   4 +-
>  5 files changed, 182 insertions(+), 62 deletions(-)
> 
> diff --git a/include/hw/ppc/spapr_xive.h b/include/hw/ppc/spapr_xive.h
> index 5b3fab192d41..aca2969a09ab 100644
> --- a/include/hw/ppc/spapr_xive.h
> +++ b/include/hw/ppc/spapr_xive.h
> @@ -13,6 +13,10 @@
>  #include "hw/sysbus.h"
>  #include "hw/ppc/xive.h"
>  
> +#define TYPE_SPAPR_XIVE_BASE "spapr-xive-base"
> +#define SPAPR_XIVE_BASE(obj) \
> +    OBJECT_CHECK(sPAPRXive, (obj), TYPE_SPAPR_XIVE_BASE)
> +
>  #define TYPE_SPAPR_XIVE "spapr-xive"
>  #define SPAPR_XIVE(obj) OBJECT_CHECK(sPAPRXive, (obj), TYPE_SPAPR_XIVE)
>  
> @@ -38,6 +42,17 @@ typedef struct sPAPRXive {
>      MemoryRegion  tm_mmio;
>  } sPAPRXive;
>  
> +#define SPAPR_XIVE_BASE_CLASS(klass) \
> +     OBJECT_CLASS_CHECK(sPAPRXiveClass, (klass), TYPE_SPAPR_XIVE_BASE)
> +#define SPAPR_XIVE_BASE_GET_CLASS(obj) \
> +     OBJECT_GET_CLASS(sPAPRXiveClass, (obj), TYPE_SPAPR_XIVE_BASE)
> +
> +typedef struct sPAPRXiveClass {
> +    XiveRouterClass parent_class;
> +
> +    DeviceRealize   parent_realize;
> +} sPAPRXiveClass;
> +
>  bool spapr_xive_irq_enable(sPAPRXive *xive, uint32_t lisn, bool lsi);
>  bool spapr_xive_irq_disable(sPAPRXive *xive, uint32_t lisn);
>  void spapr_xive_pic_print_info(sPAPRXive *xive, Monitor *mon);
> diff --git a/include/hw/ppc/xive.h b/include/hw/ppc/xive.h
> index b74eb326dcd1..281ed370121c 100644
> --- a/include/hw/ppc/xive.h
> +++ b/include/hw/ppc/xive.h
> @@ -38,6 +38,10 @@ typedef struct XiveFabricClass {
>   * XIVE Interrupt Source
>   */
>  
> +#define TYPE_XIVE_SOURCE_BASE "xive-source-base"
> +#define XIVE_SOURCE_BASE(obj) \
> +    OBJECT_CHECK(XiveSource, (obj), TYPE_XIVE_SOURCE_BASE)
> +
>  #define TYPE_XIVE_SOURCE "xive-source"
>  #define XIVE_SOURCE(obj) OBJECT_CHECK(XiveSource, (obj), TYPE_XIVE_SOURCE)
>  
> @@ -68,6 +72,18 @@ typedef struct XiveSource {
>      XiveFabric      *xive;
>  } XiveSource;
>  
> +#define XIVE_SOURCE_BASE_CLASS(klass) \
> +     OBJECT_CLASS_CHECK(XiveSourceClass, (klass), TYPE_XIVE_SOURCE_BASE)
> +#define XIVE_SOURCE_BASE_GET_CLASS(obj) \
> +     OBJECT_GET_CLASS(XiveSourceClass, (obj), TYPE_XIVE_SOURCE_BASE)
> +
> +typedef struct XiveSourceClass {
> +    SysBusDeviceClass parent_class;
> +
> +    DeviceRealize     parent_realize;
> +    DeviceReset       parent_reset;
> +} XiveSourceClass;
> +
>  /*
>   * ESB MMIO setting. Can be one page, for both source triggering and
>   * source management, or two different pages. See below for magic
> @@ -253,6 +269,9 @@ void xive_end_pic_print_info(XiveEND *end, uint32_t end_idx, Monitor *mon);
>   * XIVE Thread interrupt Management (TM) context
>   */
>  
> +#define TYPE_XIVE_TCTX_BASE "xive-tctx-base"
> +#define XIVE_TCTX_BASE(obj) OBJECT_CHECK(XiveTCTX, (obj), TYPE_XIVE_TCTX_BASE)
> +
>  #define TYPE_XIVE_TCTX "xive-tctx"
>  #define XIVE_TCTX(obj) OBJECT_CHECK(XiveTCTX, (obj), TYPE_XIVE_TCTX)
>  
> @@ -278,6 +297,17 @@ typedef struct XiveTCTX {
>      XiveRouter  *xrtr;
>  } XiveTCTX;
>  
> +#define XIVE_TCTX_BASE_CLASS(klass) \
> +     OBJECT_CLASS_CHECK(XiveTCTXClass, (klass), TYPE_XIVE_TCTX_BASE)
> +#define XIVE_TCTX_BASE_GET_CLASS(obj) \
> +     OBJECT_GET_CLASS(XiveTCTXClass, (obj), TYPE_XIVE_TCTX_BASE)
> +
> +typedef struct XiveTCTXClass {
> +    DeviceClass       parent_class;
> +
> +    DeviceRealize     parent_realize;
> +} XiveTCTXClass;
> +
>  /*
>   * XIVE Thread Interrupt Management Aera (TIMA)
>   */
> diff --git a/hw/intc/spapr_xive.c b/hw/intc/spapr_xive.c
> index 3bf77ace11a2..ec85f7e4f88d 100644
> --- a/hw/intc/spapr_xive.c
> +++ b/hw/intc/spapr_xive.c
> @@ -53,9 +53,9 @@ static void spapr_xive_mmio_map(sPAPRXive *xive)
>      sysbus_mmio_map(SYS_BUS_DEVICE(xive), 0, xive->tm_base);
>  }
>  
> -static void spapr_xive_reset(DeviceState *dev)
> +static void spapr_xive_base_reset(DeviceState *dev)
>  {
> -    sPAPRXive *xive = SPAPR_XIVE(dev);
> +    sPAPRXive *xive = SPAPR_XIVE_BASE(dev);
>      int i;
>  
>      /* Xive Source reset is done through SysBus, it should put all
> @@ -76,9 +76,9 @@ static void spapr_xive_reset(DeviceState *dev)
>      spapr_xive_mmio_map(xive);
>  }
>  
> -static void spapr_xive_instance_init(Object *obj)
> +static void spapr_xive_base_instance_init(Object *obj)
>  {
> -    sPAPRXive *xive = SPAPR_XIVE(obj);
> +    sPAPRXive *xive = SPAPR_XIVE_BASE(obj);
>  
>      object_initialize(&xive->source, sizeof(xive->source), TYPE_XIVE_SOURCE);
>      object_property_add_child(obj, "source", OBJECT(&xive->source), NULL);
> @@ -89,9 +89,9 @@ static void spapr_xive_instance_init(Object *obj)
>                                NULL);
>  }
>  
> -static void spapr_xive_realize(DeviceState *dev, Error **errp)
> +static void spapr_xive_base_realize(DeviceState *dev, Error **errp)
>  {
> -    sPAPRXive *xive = SPAPR_XIVE(dev);
> +    sPAPRXive *xive = SPAPR_XIVE_BASE(dev);
>      XiveSource *xsrc = &xive->source;
>      XiveENDSource *end_xsrc = &xive->end_source;
>      Error *local_err = NULL;
> @@ -142,16 +142,11 @@ static void spapr_xive_realize(DeviceState *dev, Error **errp)
>       */
>      xive->eat = g_new0(XiveEAS, xive->nr_irqs);
>      xive->endt = g_new0(XiveEND, xive->nr_ends);
> -
> -    /* TIMA initialization */
> -    memory_region_init_io(&xive->tm_mmio, OBJECT(xive), &xive_tm_ops, xive,
> -                          "xive.tima", 4ull << TM_SHIFT);
> -    sysbus_init_mmio(SYS_BUS_DEVICE(dev), &xive->tm_mmio);
>  }
>  
>  static int spapr_xive_get_eas(XiveRouter *xrtr, uint32_t lisn, XiveEAS *eas)
>  {
> -    sPAPRXive *xive = SPAPR_XIVE(xrtr);
> +    sPAPRXive *xive = SPAPR_XIVE_BASE(xrtr);
>  
>      if (lisn >= xive->nr_irqs) {
>          return -1;
> @@ -163,7 +158,7 @@ static int spapr_xive_get_eas(XiveRouter *xrtr, uint32_t lisn, XiveEAS *eas)
>  
>  static int spapr_xive_set_eas(XiveRouter *xrtr, uint32_t lisn, XiveEAS *eas)
>  {
> -    sPAPRXive *xive = SPAPR_XIVE(xrtr);
> +    sPAPRXive *xive = SPAPR_XIVE_BASE(xrtr);
>  
>      if (lisn >= xive->nr_irqs) {
>          return -1;
> @@ -176,7 +171,7 @@ static int spapr_xive_set_eas(XiveRouter *xrtr, uint32_t lisn, XiveEAS *eas)
>  static int spapr_xive_get_end(XiveRouter *xrtr,
>                                uint8_t end_blk, uint32_t end_idx, XiveEND *end)
>  {
> -    sPAPRXive *xive = SPAPR_XIVE(xrtr);
> +    sPAPRXive *xive = SPAPR_XIVE_BASE(xrtr);
>  
>      if (end_idx >= xive->nr_ends) {
>          return -1;
> @@ -189,7 +184,7 @@ static int spapr_xive_get_end(XiveRouter *xrtr,
>  static int spapr_xive_set_end(XiveRouter *xrtr,
>                                uint8_t end_blk, uint32_t end_idx, XiveEND *end)
>  {
> -    sPAPRXive *xive = SPAPR_XIVE(xrtr);
> +    sPAPRXive *xive = SPAPR_XIVE_BASE(xrtr);
>  
>      if (end_idx >= xive->nr_ends) {
>          return -1;
> @@ -202,7 +197,7 @@ static int spapr_xive_set_end(XiveRouter *xrtr,
>  static int spapr_xive_get_nvt(XiveRouter *xrtr,
>                                uint8_t nvt_blk, uint32_t nvt_idx, XiveNVT *nvt)
>  {
> -    sPAPRXive *xive = SPAPR_XIVE(xrtr);
> +    sPAPRXive *xive = SPAPR_XIVE_BASE(xrtr);
>      uint32_t vcpu_id = spapr_xive_nvt_to_target(xive, nvt_blk, nvt_idx);
>      PowerPCCPU *cpu = spapr_find_cpu(vcpu_id);
>  
> @@ -236,7 +231,7 @@ static void spapr_xive_reset_tctx(XiveRouter *xrtr, XiveTCTX *tctx)
>      uint32_t nvt_idx;
>      uint32_t nvt_cam;
>  
> -    spapr_xive_cpu_to_nvt(SPAPR_XIVE(xrtr), POWERPC_CPU(tctx->cs),
> +    spapr_xive_cpu_to_nvt(SPAPR_XIVE_BASE(xrtr), POWERPC_CPU(tctx->cs),
>                            &nvt_blk, &nvt_idx);
>  
>      nvt_cam = cpu_to_be32(TM_QW1W2_VO | xive_tctx_cam_line(nvt_blk, nvt_idx));
> @@ -359,7 +354,7 @@ static const VMStateDescription vmstate_spapr_xive_eas = {
>      },
>  };
>  
> -static const VMStateDescription vmstate_spapr_xive = {
> +static const VMStateDescription vmstate_spapr_xive_base = {
>      .name = TYPE_SPAPR_XIVE,
>      .version_id = 1,
>      .minimum_version_id = 1,
> @@ -373,7 +368,7 @@ static const VMStateDescription vmstate_spapr_xive = {
>      },
>  };
>  
> -static Property spapr_xive_properties[] = {
> +static Property spapr_xive_base_properties[] = {
>      DEFINE_PROP_UINT32("nr-irqs", sPAPRXive, nr_irqs, 0),
>      DEFINE_PROP_UINT32("nr-ends", sPAPRXive, nr_ends, 0),
>      DEFINE_PROP_UINT64("vc-base", sPAPRXive, vc_base, SPAPR_XIVE_VC_BASE),
> @@ -381,16 +376,16 @@ static Property spapr_xive_properties[] = {
>      DEFINE_PROP_END_OF_LIST(),
>  };
>  
> -static void spapr_xive_class_init(ObjectClass *klass, void *data)
> +static void spapr_xive_base_class_init(ObjectClass *klass, void *data)
>  {
>      DeviceClass *dc = DEVICE_CLASS(klass);
>      XiveRouterClass *xrc = XIVE_ROUTER_CLASS(klass);
>  
>      dc->desc    = "sPAPR XIVE Interrupt Controller";
> -    dc->props   = spapr_xive_properties;
> -    dc->realize = spapr_xive_realize;
> -    dc->reset   = spapr_xive_reset;
> -    dc->vmsd    = &vmstate_spapr_xive;
> +    dc->props   = spapr_xive_base_properties;
> +    dc->realize = spapr_xive_base_realize;
> +    dc->reset   = spapr_xive_base_reset;
> +    dc->vmsd    = &vmstate_spapr_xive_base;
>  
>      xrc->get_eas = spapr_xive_get_eas;
>      xrc->set_eas = spapr_xive_set_eas;
> @@ -401,16 +396,55 @@ static void spapr_xive_class_init(ObjectClass *klass, void *data)
>      xrc->reset_tctx = spapr_xive_reset_tctx;
>  }
>  
> +static const TypeInfo spapr_xive_base_info = {
> +    .name = TYPE_SPAPR_XIVE_BASE,
> +    .parent = TYPE_XIVE_ROUTER,
> +    .abstract = true,
> +    .instance_init = spapr_xive_base_instance_init,
> +    .instance_size = sizeof(sPAPRXive),
> +    .class_init = spapr_xive_base_class_init,
> +    .class_size = sizeof(sPAPRXiveClass),
> +};
> +
> +static void spapr_xive_realize(DeviceState *dev, Error **errp)
> +{
> +    sPAPRXive *xive = SPAPR_XIVE(dev);
> +    sPAPRXiveClass *sxc = SPAPR_XIVE_BASE_GET_CLASS(dev);
> +    Error *local_err = NULL;
> +
> +    sxc->parent_realize(dev, &local_err);
> +    if (local_err) {
> +        error_propagate(errp, local_err);
> +        return;
> +    }
> +
> +    /* TIMA */
> +    memory_region_init_io(&xive->tm_mmio, OBJECT(xive), &xive_tm_ops, xive,
> +                          "xive.tima", 4ull << TM_SHIFT);
> +    sysbus_init_mmio(SYS_BUS_DEVICE(dev), &xive->tm_mmio);
> +}
> +
> +static void spapr_xive_class_init(ObjectClass *klass, void *data)
> +{
> +    DeviceClass *dc = DEVICE_CLASS(klass);
> +    sPAPRXiveClass *sxc = SPAPR_XIVE_BASE_CLASS(klass);
> +
> +    device_class_set_parent_realize(dc, spapr_xive_realize,
> +                                    &sxc->parent_realize);
> +}
> +
>  static const TypeInfo spapr_xive_info = {
>      .name = TYPE_SPAPR_XIVE,
> -    .parent = TYPE_XIVE_ROUTER,
> -    .instance_init = spapr_xive_instance_init,
> +    .parent = TYPE_SPAPR_XIVE_BASE,
> +    .instance_init = spapr_xive_base_instance_init,
>      .instance_size = sizeof(sPAPRXive),
>      .class_init = spapr_xive_class_init,
> +    .class_size = sizeof(sPAPRXiveClass),
>  };
>  
>  static void spapr_xive_register_types(void)
>  {
> +    type_register_static(&spapr_xive_base_info);
>      type_register_static(&spapr_xive_info);
>  }
>  
> diff --git a/hw/intc/xive.c b/hw/intc/xive.c
> index 7d921023e2ee..9bb37553c9ec 100644
> --- a/hw/intc/xive.c
> +++ b/hw/intc/xive.c
> @@ -478,9 +478,9 @@ static uint32_t xive_tctx_hw_cam_line(XiveTCTX *tctx, bool block_group)
>      return tctx_hw_cam_line(block_group, (pir >> 8) & 0xf, pir & 0x7f);
>  }
>  
> -static void xive_tctx_reset(void *dev)
> +static void xive_tctx_base_reset(void *dev)
>  {
> -    XiveTCTX *tctx = XIVE_TCTX(dev);
> +    XiveTCTX *tctx = XIVE_TCTX_BASE(dev);
>      XiveRouterClass *xrc = XIVE_ROUTER_GET_CLASS(tctx->xrtr);
>  
>      memset(tctx->regs, 0, sizeof(tctx->regs));
> @@ -506,9 +506,9 @@ static void xive_tctx_reset(void *dev)
>      }
>  }
>  
> -static void xive_tctx_realize(DeviceState *dev, Error **errp)
> +static void xive_tctx_base_realize(DeviceState *dev, Error **errp)
>  {
> -    XiveTCTX *tctx = XIVE_TCTX(dev);
> +    XiveTCTX *tctx = XIVE_TCTX_BASE(dev);
>      PowerPCCPU *cpu;
>      CPUPPCState *env;
>      Object *obj;
> @@ -544,15 +544,15 @@ static void xive_tctx_realize(DeviceState *dev, Error **errp)
>          return;
>      }
>  
> -    qemu_register_reset(xive_tctx_reset, dev);
> +    qemu_register_reset(xive_tctx_base_reset, dev);
>  }
>  
> -static void xive_tctx_unrealize(DeviceState *dev, Error **errp)
> +static void xive_tctx_base_unrealize(DeviceState *dev, Error **errp)
>  {
> -    qemu_unregister_reset(xive_tctx_reset, dev);
> +    qemu_unregister_reset(xive_tctx_base_reset, dev);
>  }
>  
> -static const VMStateDescription vmstate_xive_tctx = {
> +static const VMStateDescription vmstate_xive_tctx_base = {
>      .name = TYPE_XIVE_TCTX,
>      .version_id = 1,
>      .minimum_version_id = 1,
> @@ -562,21 +562,28 @@ static const VMStateDescription vmstate_xive_tctx = {
>      },
>  };
>  
> -static void xive_tctx_class_init(ObjectClass *klass, void *data)
> +static void xive_tctx_base_class_init(ObjectClass *klass, void *data)
>  {
>      DeviceClass *dc = DEVICE_CLASS(klass);
>  
> -    dc->realize = xive_tctx_realize;
> -    dc->unrealize = xive_tctx_unrealize;
> +    dc->realize = xive_tctx_base_realize;
> +    dc->unrealize = xive_tctx_base_unrealize;
>      dc->desc = "XIVE Interrupt Thread Context";
> -    dc->vmsd = &vmstate_xive_tctx;
> +    dc->vmsd = &vmstate_xive_tctx_base;
>  }
>  
> -static const TypeInfo xive_tctx_info = {
> -    .name          = TYPE_XIVE_TCTX,
> +static const TypeInfo xive_tctx_base_info = {
> +    .name          = TYPE_XIVE_TCTX_BASE,
>      .parent        = TYPE_DEVICE,
> +    .abstract      = true,
>      .instance_size = sizeof(XiveTCTX),
> -    .class_init    = xive_tctx_class_init,
> +    .class_init    = xive_tctx_base_class_init,
> +    .class_size    = sizeof(XiveTCTXClass),
> +};
> +
> +static const TypeInfo xive_tctx_info = {
> +    .name          = TYPE_XIVE_TCTX,
> +    .parent        = TYPE_XIVE_TCTX_BASE,
>  };
>  
>  Object *xive_tctx_create(Object *cpu, const char *type, XiveRouter *xrtr,
> @@ -933,9 +940,9 @@ void xive_source_pic_print_info(XiveSource *xsrc, uint32_t offset, Monitor *mon)
>      }
>  }
>  
> -static void xive_source_reset(DeviceState *dev)
> +static void xive_source_base_reset(DeviceState *dev)
>  {
> -    XiveSource *xsrc = XIVE_SOURCE(dev);
> +    XiveSource *xsrc = XIVE_SOURCE_BASE(dev);
>  
>      /* Do not clear the LSI bitmap */
>  
> @@ -943,9 +950,9 @@ static void xive_source_reset(DeviceState *dev)
>      memset(xsrc->status, 0x1, xsrc->nr_irqs);
>  }
>  
> -static void xive_source_realize(DeviceState *dev, Error **errp)
> +static void xive_source_base_realize(DeviceState *dev,  Error **errp)
>  {
> -    XiveSource *xsrc = XIVE_SOURCE(dev);
> +    XiveSource *xsrc = XIVE_SOURCE_BASE(dev);
>      Object *obj;
>      Error *local_err = NULL;
>  
> @@ -971,21 +978,14 @@ static void xive_source_realize(DeviceState *dev, Error **errp)
>          return;
>      }
>  
> -    xsrc->qirqs = qemu_allocate_irqs(xive_source_set_irq, xsrc,
> -                                     xsrc->nr_irqs);
> -
>      xsrc->status = g_malloc0(xsrc->nr_irqs);
>  
>      xsrc->lsi_map = bitmap_new(xsrc->nr_irqs);
>      xsrc->lsi_map_size = xsrc->nr_irqs;
>  
> -    memory_region_init_io(&xsrc->esb_mmio, OBJECT(xsrc),
> -                          &xive_source_esb_ops, xsrc, "xive.esb",
> -                          (1ull << xsrc->esb_shift) * xsrc->nr_irqs);
> -    sysbus_init_mmio(SYS_BUS_DEVICE(dev), &xsrc->esb_mmio);
>  }
>  
> -static const VMStateDescription vmstate_xive_source = {
> +static const VMStateDescription vmstate_xive_source_base = {
>      .name = TYPE_XIVE_SOURCE,
>      .version_id = 1,
>      .minimum_version_id = 1,
> @@ -1001,29 +1001,68 @@ static const VMStateDescription vmstate_xive_source = {
>   * The default XIVE interrupt source setting for the ESB MMIOs is two
>   * 64k pages without Store EOI, to be in sync with KVM.
>   */
> -static Property xive_source_properties[] = {
> +static Property xive_source_base_properties[] = {
>      DEFINE_PROP_UINT64("flags", XiveSource, esb_flags, 0),
>      DEFINE_PROP_UINT32("nr-irqs", XiveSource, nr_irqs, 0),
>      DEFINE_PROP_UINT32("shift", XiveSource, esb_shift, XIVE_ESB_64K_2PAGE),
>      DEFINE_PROP_END_OF_LIST(),
>  };
>  
> -static void xive_source_class_init(ObjectClass *klass, void *data)
> +static void xive_source_base_class_init(ObjectClass *klass, void *data)
>  {
>      DeviceClass *dc = DEVICE_CLASS(klass);
>  
>      dc->desc    = "XIVE Interrupt Source";
> -    dc->props   = xive_source_properties;
> -    dc->realize = xive_source_realize;
> -    dc->reset   = xive_source_reset;
> -    dc->vmsd    = &vmstate_xive_source;
> +    dc->props   = xive_source_base_properties;
> +    dc->realize = xive_source_base_realize;
> +    dc->reset   = xive_source_base_reset;
> +    dc->vmsd    = &vmstate_xive_source_base;
> +}
> +
> +static const TypeInfo xive_source_base_info = {
> +    .name          = TYPE_XIVE_SOURCE_BASE,
> +    .parent        = TYPE_SYS_BUS_DEVICE,
> +    .abstract      = true,
> +    .instance_size = sizeof(XiveSource),
> +    .class_init    = xive_source_base_class_init,
> +    .class_size    = sizeof(XiveSourceClass),
> +};
> +
> +static void xive_source_realize(DeviceState *dev, Error **errp)
> +{
> +    XiveSource *xsrc = XIVE_SOURCE(dev);
> +    XiveSourceClass *xsc = XIVE_SOURCE_BASE_GET_CLASS(dev);
> +    Error *local_err = NULL;
> +
> +    xsc->parent_realize(dev, &local_err);
> +    if (local_err) {
> +        error_propagate(errp, local_err);
> +        return;
> +    }
> +
> +    xsrc->qirqs = qemu_allocate_irqs(xive_source_set_irq, xsrc, xsrc->nr_irqs);
> +
> +    memory_region_init_io(&xsrc->esb_mmio, OBJECT(xsrc),
> +                          &xive_source_esb_ops, xsrc, "xive.esb",
> +                          (1ull << xsrc->esb_shift) * xsrc->nr_irqs);
> +    sysbus_init_mmio(SYS_BUS_DEVICE(dev), &xsrc->esb_mmio);
> +}
> +
> +static void xive_source_class_init(ObjectClass *klass, void *data)
> +{
> +    DeviceClass *dc = DEVICE_CLASS(klass);
> +    XiveSourceClass *xsc = XIVE_SOURCE_BASE_CLASS(klass);
> +
> +    device_class_set_parent_realize(dc, xive_source_realize,
> +                                    &xsc->parent_realize);
>  }
>  
>  static const TypeInfo xive_source_info = {
>      .name          = TYPE_XIVE_SOURCE,
> -    .parent        = TYPE_SYS_BUS_DEVICE,
> +    .parent        = TYPE_XIVE_SOURCE_BASE,
>      .instance_size = sizeof(XiveSource),
>      .class_init    = xive_source_class_init,
> +    .class_size    = sizeof(XiveSourceClass),
>  };
>  
>  /*
> @@ -1659,10 +1698,12 @@ static const TypeInfo xive_fabric_info = {
>  
>  static void xive_register_types(void)
>  {
> +    type_register_static(&xive_source_base_info);
>      type_register_static(&xive_source_info);
>      type_register_static(&xive_fabric_info);
>      type_register_static(&xive_router_info);
>      type_register_static(&xive_end_source_info);
> +    type_register_static(&xive_tctx_base_info);
>      type_register_static(&xive_tctx_info);
>  }
>  
> diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c
> index 42e73851b174..f6e9e44d4cf9 100644
> --- a/hw/ppc/spapr_irq.c
> +++ b/hw/ppc/spapr_irq.c
> @@ -243,7 +243,7 @@ static sPAPRXive *spapr_xive_create(sPAPRMachineState *spapr,
>          return NULL;
>      }
>      qdev_set_parent_bus(DEVICE(obj), sysbus_get_default());
> -    xive = SPAPR_XIVE(obj);
> +    xive = SPAPR_XIVE_BASE(obj);
>  
>      /* Enable the CPU IPIs */
>      for (i = 0; i < nr_servers; ++i) {
> @@ -311,7 +311,7 @@ static void spapr_irq_print_info_xive(sPAPRMachineState *spapr,
>      CPU_FOREACH(cs) {
>          PowerPCCPU *cpu = POWERPC_CPU(cs);
>  
> -        xive_tctx_pic_print_info(XIVE_TCTX(cpu->intc), mon);
> +        xive_tctx_pic_print_info(XIVE_TCTX_BASE(cpu->intc), mon);
>      }
>  
>      spapr_xive_pic_print_info(spapr->xive, mon);
Cédric Le Goater Nov. 28, 2018, 10:38 p.m. UTC | #2
On 11/28/18 6:13 AM, David Gibson wrote:
> On Fri, Nov 16, 2018 at 11:57:13AM +0100, Cédric Le Goater wrote:
>> The XIVE models for the QEMU and KVM accelerators will have a lot in
>> common. Introduce an abstract class for the source, the thread context
>> and the interrupt controller object to handle the differences in the
>> object initialization. These classes will also be used to define state
>> synchronization handlers for the monitor and migration usage.
>>
>> This is very much like the XICS models.
> 
> Yeah.. so I know it's my code, but in hindsight I think making
> separate subclasses for TCG and KVM was a mistake.  The distinction
> between emulated and KVM version is supposed to be invisible to both
> guest and (almost) to user, whereas a subclass usually indicates a
> visibly different device.

so how do you want to model the KVM part ? with a single object and
kvm_enabled() sections ? 

> 
>> Signed-off-by: Cédric Le Goater <clg@kaod.org>
>> ---
>>  include/hw/ppc/spapr_xive.h |  15 +++++
>>  include/hw/ppc/xive.h       |  30 ++++++++++
>>  hw/intc/spapr_xive.c        |  86 +++++++++++++++++++---------
>>  hw/intc/xive.c              | 109 +++++++++++++++++++++++++-----------
>>  hw/ppc/spapr_irq.c          |   4 +-
>>  5 files changed, 182 insertions(+), 62 deletions(-)
>>
>> diff --git a/include/hw/ppc/spapr_xive.h b/include/hw/ppc/spapr_xive.h
>> index 5b3fab192d41..aca2969a09ab 100644
>> --- a/include/hw/ppc/spapr_xive.h
>> +++ b/include/hw/ppc/spapr_xive.h
>> @@ -13,6 +13,10 @@
>>  #include "hw/sysbus.h"
>>  #include "hw/ppc/xive.h"
>>  
>> +#define TYPE_SPAPR_XIVE_BASE "spapr-xive-base"
>> +#define SPAPR_XIVE_BASE(obj) \
>> +    OBJECT_CHECK(sPAPRXive, (obj), TYPE_SPAPR_XIVE_BASE)
>> +
>>  #define TYPE_SPAPR_XIVE "spapr-xive"
>>  #define SPAPR_XIVE(obj) OBJECT_CHECK(sPAPRXive, (obj), TYPE_SPAPR_XIVE)
>>  
>> @@ -38,6 +42,17 @@ typedef struct sPAPRXive {
>>      MemoryRegion  tm_mmio;
>>  } sPAPRXive;
>>  
>> +#define SPAPR_XIVE_BASE_CLASS(klass) \
>> +     OBJECT_CLASS_CHECK(sPAPRXiveClass, (klass), TYPE_SPAPR_XIVE_BASE)
>> +#define SPAPR_XIVE_BASE_GET_CLASS(obj) \
>> +     OBJECT_GET_CLASS(sPAPRXiveClass, (obj), TYPE_SPAPR_XIVE_BASE)
>> +
>> +typedef struct sPAPRXiveClass {
>> +    XiveRouterClass parent_class;
>> +
>> +    DeviceRealize   parent_realize;
>> +} sPAPRXiveClass;
>> +
>>  bool spapr_xive_irq_enable(sPAPRXive *xive, uint32_t lisn, bool lsi);
>>  bool spapr_xive_irq_disable(sPAPRXive *xive, uint32_t lisn);
>>  void spapr_xive_pic_print_info(sPAPRXive *xive, Monitor *mon);
>> diff --git a/include/hw/ppc/xive.h b/include/hw/ppc/xive.h
>> index b74eb326dcd1..281ed370121c 100644
>> --- a/include/hw/ppc/xive.h
>> +++ b/include/hw/ppc/xive.h
>> @@ -38,6 +38,10 @@ typedef struct XiveFabricClass {
>>   * XIVE Interrupt Source
>>   */
>>  
>> +#define TYPE_XIVE_SOURCE_BASE "xive-source-base"
>> +#define XIVE_SOURCE_BASE(obj) \
>> +    OBJECT_CHECK(XiveSource, (obj), TYPE_XIVE_SOURCE_BASE)
>> +
>>  #define TYPE_XIVE_SOURCE "xive-source"
>>  #define XIVE_SOURCE(obj) OBJECT_CHECK(XiveSource, (obj), TYPE_XIVE_SOURCE)
>>  
>> @@ -68,6 +72,18 @@ typedef struct XiveSource {
>>      XiveFabric      *xive;
>>  } XiveSource;
>>  
>> +#define XIVE_SOURCE_BASE_CLASS(klass) \
>> +     OBJECT_CLASS_CHECK(XiveSourceClass, (klass), TYPE_XIVE_SOURCE_BASE)
>> +#define XIVE_SOURCE_BASE_GET_CLASS(obj) \
>> +     OBJECT_GET_CLASS(XiveSourceClass, (obj), TYPE_XIVE_SOURCE_BASE)
>> +
>> +typedef struct XiveSourceClass {
>> +    SysBusDeviceClass parent_class;
>> +
>> +    DeviceRealize     parent_realize;
>> +    DeviceReset       parent_reset;
>> +} XiveSourceClass;
>> +
>>  /*
>>   * ESB MMIO setting. Can be one page, for both source triggering and
>>   * source management, or two different pages. See below for magic
>> @@ -253,6 +269,9 @@ void xive_end_pic_print_info(XiveEND *end, uint32_t end_idx, Monitor *mon);
>>   * XIVE Thread interrupt Management (TM) context
>>   */
>>  
>> +#define TYPE_XIVE_TCTX_BASE "xive-tctx-base"
>> +#define XIVE_TCTX_BASE(obj) OBJECT_CHECK(XiveTCTX, (obj), TYPE_XIVE_TCTX_BASE)
>> +
>>  #define TYPE_XIVE_TCTX "xive-tctx"
>>  #define XIVE_TCTX(obj) OBJECT_CHECK(XiveTCTX, (obj), TYPE_XIVE_TCTX)
>>  
>> @@ -278,6 +297,17 @@ typedef struct XiveTCTX {
>>      XiveRouter  *xrtr;
>>  } XiveTCTX;
>>  
>> +#define XIVE_TCTX_BASE_CLASS(klass) \
>> +     OBJECT_CLASS_CHECK(XiveTCTXClass, (klass), TYPE_XIVE_TCTX_BASE)
>> +#define XIVE_TCTX_BASE_GET_CLASS(obj) \
>> +     OBJECT_GET_CLASS(XiveTCTXClass, (obj), TYPE_XIVE_TCTX_BASE)
>> +
>> +typedef struct XiveTCTXClass {
>> +    DeviceClass       parent_class;
>> +
>> +    DeviceRealize     parent_realize;
>> +} XiveTCTXClass;
>> +
>>  /*
>>   * XIVE Thread Interrupt Management Aera (TIMA)
>>   */
>> diff --git a/hw/intc/spapr_xive.c b/hw/intc/spapr_xive.c
>> index 3bf77ace11a2..ec85f7e4f88d 100644
>> --- a/hw/intc/spapr_xive.c
>> +++ b/hw/intc/spapr_xive.c
>> @@ -53,9 +53,9 @@ static void spapr_xive_mmio_map(sPAPRXive *xive)
>>      sysbus_mmio_map(SYS_BUS_DEVICE(xive), 0, xive->tm_base);
>>  }
>>  
>> -static void spapr_xive_reset(DeviceState *dev)
>> +static void spapr_xive_base_reset(DeviceState *dev)
>>  {
>> -    sPAPRXive *xive = SPAPR_XIVE(dev);
>> +    sPAPRXive *xive = SPAPR_XIVE_BASE(dev);
>>      int i;
>>  
>>      /* Xive Source reset is done through SysBus, it should put all
>> @@ -76,9 +76,9 @@ static void spapr_xive_reset(DeviceState *dev)
>>      spapr_xive_mmio_map(xive);
>>  }
>>  
>> -static void spapr_xive_instance_init(Object *obj)
>> +static void spapr_xive_base_instance_init(Object *obj)
>>  {
>> -    sPAPRXive *xive = SPAPR_XIVE(obj);
>> +    sPAPRXive *xive = SPAPR_XIVE_BASE(obj);
>>  
>>      object_initialize(&xive->source, sizeof(xive->source), TYPE_XIVE_SOURCE);
>>      object_property_add_child(obj, "source", OBJECT(&xive->source), NULL);
>> @@ -89,9 +89,9 @@ static void spapr_xive_instance_init(Object *obj)
>>                                NULL);
>>  }
>>  
>> -static void spapr_xive_realize(DeviceState *dev, Error **errp)
>> +static void spapr_xive_base_realize(DeviceState *dev, Error **errp)
>>  {
>> -    sPAPRXive *xive = SPAPR_XIVE(dev);
>> +    sPAPRXive *xive = SPAPR_XIVE_BASE(dev);
>>      XiveSource *xsrc = &xive->source;
>>      XiveENDSource *end_xsrc = &xive->end_source;
>>      Error *local_err = NULL;
>> @@ -142,16 +142,11 @@ static void spapr_xive_realize(DeviceState *dev, Error **errp)
>>       */
>>      xive->eat = g_new0(XiveEAS, xive->nr_irqs);
>>      xive->endt = g_new0(XiveEND, xive->nr_ends);
>> -
>> -    /* TIMA initialization */
>> -    memory_region_init_io(&xive->tm_mmio, OBJECT(xive), &xive_tm_ops, xive,
>> -                          "xive.tima", 4ull << TM_SHIFT);
>> -    sysbus_init_mmio(SYS_BUS_DEVICE(dev), &xive->tm_mmio);
>>  }
>>  
>>  static int spapr_xive_get_eas(XiveRouter *xrtr, uint32_t lisn, XiveEAS *eas)
>>  {
>> -    sPAPRXive *xive = SPAPR_XIVE(xrtr);
>> +    sPAPRXive *xive = SPAPR_XIVE_BASE(xrtr);
>>  
>>      if (lisn >= xive->nr_irqs) {
>>          return -1;
>> @@ -163,7 +158,7 @@ static int spapr_xive_get_eas(XiveRouter *xrtr, uint32_t lisn, XiveEAS *eas)
>>  
>>  static int spapr_xive_set_eas(XiveRouter *xrtr, uint32_t lisn, XiveEAS *eas)
>>  {
>> -    sPAPRXive *xive = SPAPR_XIVE(xrtr);
>> +    sPAPRXive *xive = SPAPR_XIVE_BASE(xrtr);
>>  
>>      if (lisn >= xive->nr_irqs) {
>>          return -1;
>> @@ -176,7 +171,7 @@ static int spapr_xive_set_eas(XiveRouter *xrtr, uint32_t lisn, XiveEAS *eas)
>>  static int spapr_xive_get_end(XiveRouter *xrtr,
>>                                uint8_t end_blk, uint32_t end_idx, XiveEND *end)
>>  {
>> -    sPAPRXive *xive = SPAPR_XIVE(xrtr);
>> +    sPAPRXive *xive = SPAPR_XIVE_BASE(xrtr);
>>  
>>      if (end_idx >= xive->nr_ends) {
>>          return -1;
>> @@ -189,7 +184,7 @@ static int spapr_xive_get_end(XiveRouter *xrtr,
>>  static int spapr_xive_set_end(XiveRouter *xrtr,
>>                                uint8_t end_blk, uint32_t end_idx, XiveEND *end)
>>  {
>> -    sPAPRXive *xive = SPAPR_XIVE(xrtr);
>> +    sPAPRXive *xive = SPAPR_XIVE_BASE(xrtr);
>>  
>>      if (end_idx >= xive->nr_ends) {
>>          return -1;
>> @@ -202,7 +197,7 @@ static int spapr_xive_set_end(XiveRouter *xrtr,
>>  static int spapr_xive_get_nvt(XiveRouter *xrtr,
>>                                uint8_t nvt_blk, uint32_t nvt_idx, XiveNVT *nvt)
>>  {
>> -    sPAPRXive *xive = SPAPR_XIVE(xrtr);
>> +    sPAPRXive *xive = SPAPR_XIVE_BASE(xrtr);
>>      uint32_t vcpu_id = spapr_xive_nvt_to_target(xive, nvt_blk, nvt_idx);
>>      PowerPCCPU *cpu = spapr_find_cpu(vcpu_id);
>>  
>> @@ -236,7 +231,7 @@ static void spapr_xive_reset_tctx(XiveRouter *xrtr, XiveTCTX *tctx)
>>      uint32_t nvt_idx;
>>      uint32_t nvt_cam;
>>  
>> -    spapr_xive_cpu_to_nvt(SPAPR_XIVE(xrtr), POWERPC_CPU(tctx->cs),
>> +    spapr_xive_cpu_to_nvt(SPAPR_XIVE_BASE(xrtr), POWERPC_CPU(tctx->cs),
>>                            &nvt_blk, &nvt_idx);
>>  
>>      nvt_cam = cpu_to_be32(TM_QW1W2_VO | xive_tctx_cam_line(nvt_blk, nvt_idx));
>> @@ -359,7 +354,7 @@ static const VMStateDescription vmstate_spapr_xive_eas = {
>>      },
>>  };
>>  
>> -static const VMStateDescription vmstate_spapr_xive = {
>> +static const VMStateDescription vmstate_spapr_xive_base = {
>>      .name = TYPE_SPAPR_XIVE,
>>      .version_id = 1,
>>      .minimum_version_id = 1,
>> @@ -373,7 +368,7 @@ static const VMStateDescription vmstate_spapr_xive = {
>>      },
>>  };
>>  
>> -static Property spapr_xive_properties[] = {
>> +static Property spapr_xive_base_properties[] = {
>>      DEFINE_PROP_UINT32("nr-irqs", sPAPRXive, nr_irqs, 0),
>>      DEFINE_PROP_UINT32("nr-ends", sPAPRXive, nr_ends, 0),
>>      DEFINE_PROP_UINT64("vc-base", sPAPRXive, vc_base, SPAPR_XIVE_VC_BASE),
>> @@ -381,16 +376,16 @@ static Property spapr_xive_properties[] = {
>>      DEFINE_PROP_END_OF_LIST(),
>>  };
>>  
>> -static void spapr_xive_class_init(ObjectClass *klass, void *data)
>> +static void spapr_xive_base_class_init(ObjectClass *klass, void *data)
>>  {
>>      DeviceClass *dc = DEVICE_CLASS(klass);
>>      XiveRouterClass *xrc = XIVE_ROUTER_CLASS(klass);
>>  
>>      dc->desc    = "sPAPR XIVE Interrupt Controller";
>> -    dc->props   = spapr_xive_properties;
>> -    dc->realize = spapr_xive_realize;
>> -    dc->reset   = spapr_xive_reset;
>> -    dc->vmsd    = &vmstate_spapr_xive;
>> +    dc->props   = spapr_xive_base_properties;
>> +    dc->realize = spapr_xive_base_realize;
>> +    dc->reset   = spapr_xive_base_reset;
>> +    dc->vmsd    = &vmstate_spapr_xive_base;
>>  
>>      xrc->get_eas = spapr_xive_get_eas;
>>      xrc->set_eas = spapr_xive_set_eas;
>> @@ -401,16 +396,55 @@ static void spapr_xive_class_init(ObjectClass *klass, void *data)
>>      xrc->reset_tctx = spapr_xive_reset_tctx;
>>  }
>>  
>> +static const TypeInfo spapr_xive_base_info = {
>> +    .name = TYPE_SPAPR_XIVE_BASE,
>> +    .parent = TYPE_XIVE_ROUTER,
>> +    .abstract = true,
>> +    .instance_init = spapr_xive_base_instance_init,
>> +    .instance_size = sizeof(sPAPRXive),
>> +    .class_init = spapr_xive_base_class_init,
>> +    .class_size = sizeof(sPAPRXiveClass),
>> +};
>> +
>> +static void spapr_xive_realize(DeviceState *dev, Error **errp)
>> +{
>> +    sPAPRXive *xive = SPAPR_XIVE(dev);
>> +    sPAPRXiveClass *sxc = SPAPR_XIVE_BASE_GET_CLASS(dev);
>> +    Error *local_err = NULL;
>> +
>> +    sxc->parent_realize(dev, &local_err);
>> +    if (local_err) {
>> +        error_propagate(errp, local_err);
>> +        return;
>> +    }
>> +
>> +    /* TIMA */
>> +    memory_region_init_io(&xive->tm_mmio, OBJECT(xive), &xive_tm_ops, xive,
>> +                          "xive.tima", 4ull << TM_SHIFT);
>> +    sysbus_init_mmio(SYS_BUS_DEVICE(dev), &xive->tm_mmio);
>> +}
>> +
>> +static void spapr_xive_class_init(ObjectClass *klass, void *data)
>> +{
>> +    DeviceClass *dc = DEVICE_CLASS(klass);
>> +    sPAPRXiveClass *sxc = SPAPR_XIVE_BASE_CLASS(klass);
>> +
>> +    device_class_set_parent_realize(dc, spapr_xive_realize,
>> +                                    &sxc->parent_realize);
>> +}
>> +
>>  static const TypeInfo spapr_xive_info = {
>>      .name = TYPE_SPAPR_XIVE,
>> -    .parent = TYPE_XIVE_ROUTER,
>> -    .instance_init = spapr_xive_instance_init,
>> +    .parent = TYPE_SPAPR_XIVE_BASE,
>> +    .instance_init = spapr_xive_base_instance_init,
>>      .instance_size = sizeof(sPAPRXive),
>>      .class_init = spapr_xive_class_init,
>> +    .class_size = sizeof(sPAPRXiveClass),
>>  };
>>  
>>  static void spapr_xive_register_types(void)
>>  {
>> +    type_register_static(&spapr_xive_base_info);
>>      type_register_static(&spapr_xive_info);
>>  }
>>  
>> diff --git a/hw/intc/xive.c b/hw/intc/xive.c
>> index 7d921023e2ee..9bb37553c9ec 100644
>> --- a/hw/intc/xive.c
>> +++ b/hw/intc/xive.c
>> @@ -478,9 +478,9 @@ static uint32_t xive_tctx_hw_cam_line(XiveTCTX *tctx, bool block_group)
>>      return tctx_hw_cam_line(block_group, (pir >> 8) & 0xf, pir & 0x7f);
>>  }
>>  
>> -static void xive_tctx_reset(void *dev)
>> +static void xive_tctx_base_reset(void *dev)
>>  {
>> -    XiveTCTX *tctx = XIVE_TCTX(dev);
>> +    XiveTCTX *tctx = XIVE_TCTX_BASE(dev);
>>      XiveRouterClass *xrc = XIVE_ROUTER_GET_CLASS(tctx->xrtr);
>>  
>>      memset(tctx->regs, 0, sizeof(tctx->regs));
>> @@ -506,9 +506,9 @@ static void xive_tctx_reset(void *dev)
>>      }
>>  }
>>  
>> -static void xive_tctx_realize(DeviceState *dev, Error **errp)
>> +static void xive_tctx_base_realize(DeviceState *dev, Error **errp)
>>  {
>> -    XiveTCTX *tctx = XIVE_TCTX(dev);
>> +    XiveTCTX *tctx = XIVE_TCTX_BASE(dev);
>>      PowerPCCPU *cpu;
>>      CPUPPCState *env;
>>      Object *obj;
>> @@ -544,15 +544,15 @@ static void xive_tctx_realize(DeviceState *dev, Error **errp)
>>          return;
>>      }
>>  
>> -    qemu_register_reset(xive_tctx_reset, dev);
>> +    qemu_register_reset(xive_tctx_base_reset, dev);
>>  }
>>  
>> -static void xive_tctx_unrealize(DeviceState *dev, Error **errp)
>> +static void xive_tctx_base_unrealize(DeviceState *dev, Error **errp)
>>  {
>> -    qemu_unregister_reset(xive_tctx_reset, dev);
>> +    qemu_unregister_reset(xive_tctx_base_reset, dev);
>>  }
>>  
>> -static const VMStateDescription vmstate_xive_tctx = {
>> +static const VMStateDescription vmstate_xive_tctx_base = {
>>      .name = TYPE_XIVE_TCTX,
>>      .version_id = 1,
>>      .minimum_version_id = 1,
>> @@ -562,21 +562,28 @@ static const VMStateDescription vmstate_xive_tctx = {
>>      },
>>  };
>>  
>> -static void xive_tctx_class_init(ObjectClass *klass, void *data)
>> +static void xive_tctx_base_class_init(ObjectClass *klass, void *data)
>>  {
>>      DeviceClass *dc = DEVICE_CLASS(klass);
>>  
>> -    dc->realize = xive_tctx_realize;
>> -    dc->unrealize = xive_tctx_unrealize;
>> +    dc->realize = xive_tctx_base_realize;
>> +    dc->unrealize = xive_tctx_base_unrealize;
>>      dc->desc = "XIVE Interrupt Thread Context";
>> -    dc->vmsd = &vmstate_xive_tctx;
>> +    dc->vmsd = &vmstate_xive_tctx_base;
>>  }
>>  
>> -static const TypeInfo xive_tctx_info = {
>> -    .name          = TYPE_XIVE_TCTX,
>> +static const TypeInfo xive_tctx_base_info = {
>> +    .name          = TYPE_XIVE_TCTX_BASE,
>>      .parent        = TYPE_DEVICE,
>> +    .abstract      = true,
>>      .instance_size = sizeof(XiveTCTX),
>> -    .class_init    = xive_tctx_class_init,
>> +    .class_init    = xive_tctx_base_class_init,
>> +    .class_size    = sizeof(XiveTCTXClass),
>> +};
>> +
>> +static const TypeInfo xive_tctx_info = {
>> +    .name          = TYPE_XIVE_TCTX,
>> +    .parent        = TYPE_XIVE_TCTX_BASE,
>>  };
>>  
>>  Object *xive_tctx_create(Object *cpu, const char *type, XiveRouter *xrtr,
>> @@ -933,9 +940,9 @@ void xive_source_pic_print_info(XiveSource *xsrc, uint32_t offset, Monitor *mon)
>>      }
>>  }
>>  
>> -static void xive_source_reset(DeviceState *dev)
>> +static void xive_source_base_reset(DeviceState *dev)
>>  {
>> -    XiveSource *xsrc = XIVE_SOURCE(dev);
>> +    XiveSource *xsrc = XIVE_SOURCE_BASE(dev);
>>  
>>      /* Do not clear the LSI bitmap */
>>  
>> @@ -943,9 +950,9 @@ static void xive_source_reset(DeviceState *dev)
>>      memset(xsrc->status, 0x1, xsrc->nr_irqs);
>>  }
>>  
>> -static void xive_source_realize(DeviceState *dev, Error **errp)
>> +static void xive_source_base_realize(DeviceState *dev,  Error **errp)
>>  {
>> -    XiveSource *xsrc = XIVE_SOURCE(dev);
>> +    XiveSource *xsrc = XIVE_SOURCE_BASE(dev);
>>      Object *obj;
>>      Error *local_err = NULL;
>>  
>> @@ -971,21 +978,14 @@ static void xive_source_realize(DeviceState *dev, Error **errp)
>>          return;
>>      }
>>  
>> -    xsrc->qirqs = qemu_allocate_irqs(xive_source_set_irq, xsrc,
>> -                                     xsrc->nr_irqs);
>> -
>>      xsrc->status = g_malloc0(xsrc->nr_irqs);
>>  
>>      xsrc->lsi_map = bitmap_new(xsrc->nr_irqs);
>>      xsrc->lsi_map_size = xsrc->nr_irqs;
>>  
>> -    memory_region_init_io(&xsrc->esb_mmio, OBJECT(xsrc),
>> -                          &xive_source_esb_ops, xsrc, "xive.esb",
>> -                          (1ull << xsrc->esb_shift) * xsrc->nr_irqs);
>> -    sysbus_init_mmio(SYS_BUS_DEVICE(dev), &xsrc->esb_mmio);
>>  }
>>  
>> -static const VMStateDescription vmstate_xive_source = {
>> +static const VMStateDescription vmstate_xive_source_base = {
>>      .name = TYPE_XIVE_SOURCE,
>>      .version_id = 1,
>>      .minimum_version_id = 1,
>> @@ -1001,29 +1001,68 @@ static const VMStateDescription vmstate_xive_source = {
>>   * The default XIVE interrupt source setting for the ESB MMIOs is two
>>   * 64k pages without Store EOI, to be in sync with KVM.
>>   */
>> -static Property xive_source_properties[] = {
>> +static Property xive_source_base_properties[] = {
>>      DEFINE_PROP_UINT64("flags", XiveSource, esb_flags, 0),
>>      DEFINE_PROP_UINT32("nr-irqs", XiveSource, nr_irqs, 0),
>>      DEFINE_PROP_UINT32("shift", XiveSource, esb_shift, XIVE_ESB_64K_2PAGE),
>>      DEFINE_PROP_END_OF_LIST(),
>>  };
>>  
>> -static void xive_source_class_init(ObjectClass *klass, void *data)
>> +static void xive_source_base_class_init(ObjectClass *klass, void *data)
>>  {
>>      DeviceClass *dc = DEVICE_CLASS(klass);
>>  
>>      dc->desc    = "XIVE Interrupt Source";
>> -    dc->props   = xive_source_properties;
>> -    dc->realize = xive_source_realize;
>> -    dc->reset   = xive_source_reset;
>> -    dc->vmsd    = &vmstate_xive_source;
>> +    dc->props   = xive_source_base_properties;
>> +    dc->realize = xive_source_base_realize;
>> +    dc->reset   = xive_source_base_reset;
>> +    dc->vmsd    = &vmstate_xive_source_base;
>> +}
>> +
>> +static const TypeInfo xive_source_base_info = {
>> +    .name          = TYPE_XIVE_SOURCE_BASE,
>> +    .parent        = TYPE_SYS_BUS_DEVICE,
>> +    .abstract      = true,
>> +    .instance_size = sizeof(XiveSource),
>> +    .class_init    = xive_source_base_class_init,
>> +    .class_size    = sizeof(XiveSourceClass),
>> +};
>> +
>> +static void xive_source_realize(DeviceState *dev, Error **errp)
>> +{
>> +    XiveSource *xsrc = XIVE_SOURCE(dev);
>> +    XiveSourceClass *xsc = XIVE_SOURCE_BASE_GET_CLASS(dev);
>> +    Error *local_err = NULL;
>> +
>> +    xsc->parent_realize(dev, &local_err);
>> +    if (local_err) {
>> +        error_propagate(errp, local_err);
>> +        return;
>> +    }
>> +
>> +    xsrc->qirqs = qemu_allocate_irqs(xive_source_set_irq, xsrc, xsrc->nr_irqs);
>> +
>> +    memory_region_init_io(&xsrc->esb_mmio, OBJECT(xsrc),
>> +                          &xive_source_esb_ops, xsrc, "xive.esb",
>> +                          (1ull << xsrc->esb_shift) * xsrc->nr_irqs);
>> +    sysbus_init_mmio(SYS_BUS_DEVICE(dev), &xsrc->esb_mmio);
>> +}
>> +
>> +static void xive_source_class_init(ObjectClass *klass, void *data)
>> +{
>> +    DeviceClass *dc = DEVICE_CLASS(klass);
>> +    XiveSourceClass *xsc = XIVE_SOURCE_BASE_CLASS(klass);
>> +
>> +    device_class_set_parent_realize(dc, xive_source_realize,
>> +                                    &xsc->parent_realize);
>>  }
>>  
>>  static const TypeInfo xive_source_info = {
>>      .name          = TYPE_XIVE_SOURCE,
>> -    .parent        = TYPE_SYS_BUS_DEVICE,
>> +    .parent        = TYPE_XIVE_SOURCE_BASE,
>>      .instance_size = sizeof(XiveSource),
>>      .class_init    = xive_source_class_init,
>> +    .class_size    = sizeof(XiveSourceClass),
>>  };
>>  
>>  /*
>> @@ -1659,10 +1698,12 @@ static const TypeInfo xive_fabric_info = {
>>  
>>  static void xive_register_types(void)
>>  {
>> +    type_register_static(&xive_source_base_info);
>>      type_register_static(&xive_source_info);
>>      type_register_static(&xive_fabric_info);
>>      type_register_static(&xive_router_info);
>>      type_register_static(&xive_end_source_info);
>> +    type_register_static(&xive_tctx_base_info);
>>      type_register_static(&xive_tctx_info);
>>  }
>>  
>> diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c
>> index 42e73851b174..f6e9e44d4cf9 100644
>> --- a/hw/ppc/spapr_irq.c
>> +++ b/hw/ppc/spapr_irq.c
>> @@ -243,7 +243,7 @@ static sPAPRXive *spapr_xive_create(sPAPRMachineState *spapr,
>>          return NULL;
>>      }
>>      qdev_set_parent_bus(DEVICE(obj), sysbus_get_default());
>> -    xive = SPAPR_XIVE(obj);
>> +    xive = SPAPR_XIVE_BASE(obj);
>>  
>>      /* Enable the CPU IPIs */
>>      for (i = 0; i < nr_servers; ++i) {
>> @@ -311,7 +311,7 @@ static void spapr_irq_print_info_xive(sPAPRMachineState *spapr,
>>      CPU_FOREACH(cs) {
>>          PowerPCCPU *cpu = POWERPC_CPU(cs);
>>  
>> -        xive_tctx_pic_print_info(XIVE_TCTX(cpu->intc), mon);
>> +        xive_tctx_pic_print_info(XIVE_TCTX_BASE(cpu->intc), mon);
>>      }
>>  
>>      spapr_xive_pic_print_info(spapr->xive, mon);
>
David Gibson Nov. 29, 2018, 2:59 a.m. UTC | #3
On Wed, Nov 28, 2018 at 11:38:50PM +0100, Cédric Le Goater wrote:
> On 11/28/18 6:13 AM, David Gibson wrote:
> > On Fri, Nov 16, 2018 at 11:57:13AM +0100, Cédric Le Goater wrote:
> >> The XIVE models for the QEMU and KVM accelerators will have a lot in
> >> common. Introduce an abstract class for the source, the thread context
> >> and the interrupt controller object to handle the differences in the
> >> object initialization. These classes will also be used to define state
> >> synchronization handlers for the monitor and migration usage.
> >>
> >> This is very much like the XICS models.
> > 
> > Yeah.. so I know it's my code, but in hindsight I think making
> > separate subclasses for TCG and KVM was a mistake.  The distinction
> > between emulated and KVM version is supposed to be invisible to both
> > guest and (almost) to user, whereas a subclass usually indicates a
> > visibly different device.
> 
> so how do you want to model the KVM part ? with a single object and
> kvm_enabled() sections ?

Basically, yes.  In practice I think you probably want a helper called
xive_is_kvm() or something, which would evaluate to (kvm_enabled() &&
kvm_irqchip_in_kernel()).

> >> Signed-off-by: Cédric Le Goater <clg@kaod.org>
> >> ---
> >>  include/hw/ppc/spapr_xive.h |  15 +++++
> >>  include/hw/ppc/xive.h       |  30 ++++++++++
> >>  hw/intc/spapr_xive.c        |  86 +++++++++++++++++++---------
> >>  hw/intc/xive.c              | 109 +++++++++++++++++++++++++-----------
> >>  hw/ppc/spapr_irq.c          |   4 +-
> >>  5 files changed, 182 insertions(+), 62 deletions(-)
> >>
> >> diff --git a/include/hw/ppc/spapr_xive.h b/include/hw/ppc/spapr_xive.h
> >> index 5b3fab192d41..aca2969a09ab 100644
> >> --- a/include/hw/ppc/spapr_xive.h
> >> +++ b/include/hw/ppc/spapr_xive.h
> >> @@ -13,6 +13,10 @@
> >>  #include "hw/sysbus.h"
> >>  #include "hw/ppc/xive.h"
> >>  
> >> +#define TYPE_SPAPR_XIVE_BASE "spapr-xive-base"
> >> +#define SPAPR_XIVE_BASE(obj) \
> >> +    OBJECT_CHECK(sPAPRXive, (obj), TYPE_SPAPR_XIVE_BASE)
> >> +
> >>  #define TYPE_SPAPR_XIVE "spapr-xive"
> >>  #define SPAPR_XIVE(obj) OBJECT_CHECK(sPAPRXive, (obj), TYPE_SPAPR_XIVE)
> >>  
> >> @@ -38,6 +42,17 @@ typedef struct sPAPRXive {
> >>      MemoryRegion  tm_mmio;
> >>  } sPAPRXive;
> >>  
> >> +#define SPAPR_XIVE_BASE_CLASS(klass) \
> >> +     OBJECT_CLASS_CHECK(sPAPRXiveClass, (klass), TYPE_SPAPR_XIVE_BASE)
> >> +#define SPAPR_XIVE_BASE_GET_CLASS(obj) \
> >> +     OBJECT_GET_CLASS(sPAPRXiveClass, (obj), TYPE_SPAPR_XIVE_BASE)
> >> +
> >> +typedef struct sPAPRXiveClass {
> >> +    XiveRouterClass parent_class;
> >> +
> >> +    DeviceRealize   parent_realize;
> >> +} sPAPRXiveClass;
> >> +
> >>  bool spapr_xive_irq_enable(sPAPRXive *xive, uint32_t lisn, bool lsi);
> >>  bool spapr_xive_irq_disable(sPAPRXive *xive, uint32_t lisn);
> >>  void spapr_xive_pic_print_info(sPAPRXive *xive, Monitor *mon);
> >> diff --git a/include/hw/ppc/xive.h b/include/hw/ppc/xive.h
> >> index b74eb326dcd1..281ed370121c 100644
> >> --- a/include/hw/ppc/xive.h
> >> +++ b/include/hw/ppc/xive.h
> >> @@ -38,6 +38,10 @@ typedef struct XiveFabricClass {
> >>   * XIVE Interrupt Source
> >>   */
> >>  
> >> +#define TYPE_XIVE_SOURCE_BASE "xive-source-base"
> >> +#define XIVE_SOURCE_BASE(obj) \
> >> +    OBJECT_CHECK(XiveSource, (obj), TYPE_XIVE_SOURCE_BASE)
> >> +
> >>  #define TYPE_XIVE_SOURCE "xive-source"
> >>  #define XIVE_SOURCE(obj) OBJECT_CHECK(XiveSource, (obj), TYPE_XIVE_SOURCE)
> >>  
> >> @@ -68,6 +72,18 @@ typedef struct XiveSource {
> >>      XiveFabric      *xive;
> >>  } XiveSource;
> >>  
> >> +#define XIVE_SOURCE_BASE_CLASS(klass) \
> >> +     OBJECT_CLASS_CHECK(XiveSourceClass, (klass), TYPE_XIVE_SOURCE_BASE)
> >> +#define XIVE_SOURCE_BASE_GET_CLASS(obj) \
> >> +     OBJECT_GET_CLASS(XiveSourceClass, (obj), TYPE_XIVE_SOURCE_BASE)
> >> +
> >> +typedef struct XiveSourceClass {
> >> +    SysBusDeviceClass parent_class;
> >> +
> >> +    DeviceRealize     parent_realize;
> >> +    DeviceReset       parent_reset;
> >> +} XiveSourceClass;
> >> +
> >>  /*
> >>   * ESB MMIO setting. Can be one page, for both source triggering and
> >>   * source management, or two different pages. See below for magic
> >> @@ -253,6 +269,9 @@ void xive_end_pic_print_info(XiveEND *end, uint32_t end_idx, Monitor *mon);
> >>   * XIVE Thread interrupt Management (TM) context
> >>   */
> >>  
> >> +#define TYPE_XIVE_TCTX_BASE "xive-tctx-base"
> >> +#define XIVE_TCTX_BASE(obj) OBJECT_CHECK(XiveTCTX, (obj), TYPE_XIVE_TCTX_BASE)
> >> +
> >>  #define TYPE_XIVE_TCTX "xive-tctx"
> >>  #define XIVE_TCTX(obj) OBJECT_CHECK(XiveTCTX, (obj), TYPE_XIVE_TCTX)
> >>  
> >> @@ -278,6 +297,17 @@ typedef struct XiveTCTX {
> >>      XiveRouter  *xrtr;
> >>  } XiveTCTX;
> >>  
> >> +#define XIVE_TCTX_BASE_CLASS(klass) \
> >> +     OBJECT_CLASS_CHECK(XiveTCTXClass, (klass), TYPE_XIVE_TCTX_BASE)
> >> +#define XIVE_TCTX_BASE_GET_CLASS(obj) \
> >> +     OBJECT_GET_CLASS(XiveTCTXClass, (obj), TYPE_XIVE_TCTX_BASE)
> >> +
> >> +typedef struct XiveTCTXClass {
> >> +    DeviceClass       parent_class;
> >> +
> >> +    DeviceRealize     parent_realize;
> >> +} XiveTCTXClass;
> >> +
> >>  /*
> >>   * XIVE Thread Interrupt Management Aera (TIMA)
> >>   */
> >> diff --git a/hw/intc/spapr_xive.c b/hw/intc/spapr_xive.c
> >> index 3bf77ace11a2..ec85f7e4f88d 100644
> >> --- a/hw/intc/spapr_xive.c
> >> +++ b/hw/intc/spapr_xive.c
> >> @@ -53,9 +53,9 @@ static void spapr_xive_mmio_map(sPAPRXive *xive)
> >>      sysbus_mmio_map(SYS_BUS_DEVICE(xive), 0, xive->tm_base);
> >>  }
> >>  
> >> -static void spapr_xive_reset(DeviceState *dev)
> >> +static void spapr_xive_base_reset(DeviceState *dev)
> >>  {
> >> -    sPAPRXive *xive = SPAPR_XIVE(dev);
> >> +    sPAPRXive *xive = SPAPR_XIVE_BASE(dev);
> >>      int i;
> >>  
> >>      /* Xive Source reset is done through SysBus, it should put all
> >> @@ -76,9 +76,9 @@ static void spapr_xive_reset(DeviceState *dev)
> >>      spapr_xive_mmio_map(xive);
> >>  }
> >>  
> >> -static void spapr_xive_instance_init(Object *obj)
> >> +static void spapr_xive_base_instance_init(Object *obj)
> >>  {
> >> -    sPAPRXive *xive = SPAPR_XIVE(obj);
> >> +    sPAPRXive *xive = SPAPR_XIVE_BASE(obj);
> >>  
> >>      object_initialize(&xive->source, sizeof(xive->source), TYPE_XIVE_SOURCE);
> >>      object_property_add_child(obj, "source", OBJECT(&xive->source), NULL);
> >> @@ -89,9 +89,9 @@ static void spapr_xive_instance_init(Object *obj)
> >>                                NULL);
> >>  }
> >>  
> >> -static void spapr_xive_realize(DeviceState *dev, Error **errp)
> >> +static void spapr_xive_base_realize(DeviceState *dev, Error **errp)
> >>  {
> >> -    sPAPRXive *xive = SPAPR_XIVE(dev);
> >> +    sPAPRXive *xive = SPAPR_XIVE_BASE(dev);
> >>      XiveSource *xsrc = &xive->source;
> >>      XiveENDSource *end_xsrc = &xive->end_source;
> >>      Error *local_err = NULL;
> >> @@ -142,16 +142,11 @@ static void spapr_xive_realize(DeviceState *dev, Error **errp)
> >>       */
> >>      xive->eat = g_new0(XiveEAS, xive->nr_irqs);
> >>      xive->endt = g_new0(XiveEND, xive->nr_ends);
> >> -
> >> -    /* TIMA initialization */
> >> -    memory_region_init_io(&xive->tm_mmio, OBJECT(xive), &xive_tm_ops, xive,
> >> -                          "xive.tima", 4ull << TM_SHIFT);
> >> -    sysbus_init_mmio(SYS_BUS_DEVICE(dev), &xive->tm_mmio);
> >>  }
> >>  
> >>  static int spapr_xive_get_eas(XiveRouter *xrtr, uint32_t lisn, XiveEAS *eas)
> >>  {
> >> -    sPAPRXive *xive = SPAPR_XIVE(xrtr);
> >> +    sPAPRXive *xive = SPAPR_XIVE_BASE(xrtr);
> >>  
> >>      if (lisn >= xive->nr_irqs) {
> >>          return -1;
> >> @@ -163,7 +158,7 @@ static int spapr_xive_get_eas(XiveRouter *xrtr, uint32_t lisn, XiveEAS *eas)
> >>  
> >>  static int spapr_xive_set_eas(XiveRouter *xrtr, uint32_t lisn, XiveEAS *eas)
> >>  {
> >> -    sPAPRXive *xive = SPAPR_XIVE(xrtr);
> >> +    sPAPRXive *xive = SPAPR_XIVE_BASE(xrtr);
> >>  
> >>      if (lisn >= xive->nr_irqs) {
> >>          return -1;
> >> @@ -176,7 +171,7 @@ static int spapr_xive_set_eas(XiveRouter *xrtr, uint32_t lisn, XiveEAS *eas)
> >>  static int spapr_xive_get_end(XiveRouter *xrtr,
> >>                                uint8_t end_blk, uint32_t end_idx, XiveEND *end)
> >>  {
> >> -    sPAPRXive *xive = SPAPR_XIVE(xrtr);
> >> +    sPAPRXive *xive = SPAPR_XIVE_BASE(xrtr);
> >>  
> >>      if (end_idx >= xive->nr_ends) {
> >>          return -1;
> >> @@ -189,7 +184,7 @@ static int spapr_xive_get_end(XiveRouter *xrtr,
> >>  static int spapr_xive_set_end(XiveRouter *xrtr,
> >>                                uint8_t end_blk, uint32_t end_idx, XiveEND *end)
> >>  {
> >> -    sPAPRXive *xive = SPAPR_XIVE(xrtr);
> >> +    sPAPRXive *xive = SPAPR_XIVE_BASE(xrtr);
> >>  
> >>      if (end_idx >= xive->nr_ends) {
> >>          return -1;
> >> @@ -202,7 +197,7 @@ static int spapr_xive_set_end(XiveRouter *xrtr,
> >>  static int spapr_xive_get_nvt(XiveRouter *xrtr,
> >>                                uint8_t nvt_blk, uint32_t nvt_idx, XiveNVT *nvt)
> >>  {
> >> -    sPAPRXive *xive = SPAPR_XIVE(xrtr);
> >> +    sPAPRXive *xive = SPAPR_XIVE_BASE(xrtr);
> >>      uint32_t vcpu_id = spapr_xive_nvt_to_target(xive, nvt_blk, nvt_idx);
> >>      PowerPCCPU *cpu = spapr_find_cpu(vcpu_id);
> >>  
> >> @@ -236,7 +231,7 @@ static void spapr_xive_reset_tctx(XiveRouter *xrtr, XiveTCTX *tctx)
> >>      uint32_t nvt_idx;
> >>      uint32_t nvt_cam;
> >>  
> >> -    spapr_xive_cpu_to_nvt(SPAPR_XIVE(xrtr), POWERPC_CPU(tctx->cs),
> >> +    spapr_xive_cpu_to_nvt(SPAPR_XIVE_BASE(xrtr), POWERPC_CPU(tctx->cs),
> >>                            &nvt_blk, &nvt_idx);
> >>  
> >>      nvt_cam = cpu_to_be32(TM_QW1W2_VO | xive_tctx_cam_line(nvt_blk, nvt_idx));
> >> @@ -359,7 +354,7 @@ static const VMStateDescription vmstate_spapr_xive_eas = {
> >>      },
> >>  };
> >>  
> >> -static const VMStateDescription vmstate_spapr_xive = {
> >> +static const VMStateDescription vmstate_spapr_xive_base = {
> >>      .name = TYPE_SPAPR_XIVE,
> >>      .version_id = 1,
> >>      .minimum_version_id = 1,
> >> @@ -373,7 +368,7 @@ static const VMStateDescription vmstate_spapr_xive = {
> >>      },
> >>  };
> >>  
> >> -static Property spapr_xive_properties[] = {
> >> +static Property spapr_xive_base_properties[] = {
> >>      DEFINE_PROP_UINT32("nr-irqs", sPAPRXive, nr_irqs, 0),
> >>      DEFINE_PROP_UINT32("nr-ends", sPAPRXive, nr_ends, 0),
> >>      DEFINE_PROP_UINT64("vc-base", sPAPRXive, vc_base, SPAPR_XIVE_VC_BASE),
> >> @@ -381,16 +376,16 @@ static Property spapr_xive_properties[] = {
> >>      DEFINE_PROP_END_OF_LIST(),
> >>  };
> >>  
> >> -static void spapr_xive_class_init(ObjectClass *klass, void *data)
> >> +static void spapr_xive_base_class_init(ObjectClass *klass, void *data)
> >>  {
> >>      DeviceClass *dc = DEVICE_CLASS(klass);
> >>      XiveRouterClass *xrc = XIVE_ROUTER_CLASS(klass);
> >>  
> >>      dc->desc    = "sPAPR XIVE Interrupt Controller";
> >> -    dc->props   = spapr_xive_properties;
> >> -    dc->realize = spapr_xive_realize;
> >> -    dc->reset   = spapr_xive_reset;
> >> -    dc->vmsd    = &vmstate_spapr_xive;
> >> +    dc->props   = spapr_xive_base_properties;
> >> +    dc->realize = spapr_xive_base_realize;
> >> +    dc->reset   = spapr_xive_base_reset;
> >> +    dc->vmsd    = &vmstate_spapr_xive_base;
> >>  
> >>      xrc->get_eas = spapr_xive_get_eas;
> >>      xrc->set_eas = spapr_xive_set_eas;
> >> @@ -401,16 +396,55 @@ static void spapr_xive_class_init(ObjectClass *klass, void *data)
> >>      xrc->reset_tctx = spapr_xive_reset_tctx;
> >>  }
> >>  
> >> +static const TypeInfo spapr_xive_base_info = {
> >> +    .name = TYPE_SPAPR_XIVE_BASE,
> >> +    .parent = TYPE_XIVE_ROUTER,
> >> +    .abstract = true,
> >> +    .instance_init = spapr_xive_base_instance_init,
> >> +    .instance_size = sizeof(sPAPRXive),
> >> +    .class_init = spapr_xive_base_class_init,
> >> +    .class_size = sizeof(sPAPRXiveClass),
> >> +};
> >> +
> >> +static void spapr_xive_realize(DeviceState *dev, Error **errp)
> >> +{
> >> +    sPAPRXive *xive = SPAPR_XIVE(dev);
> >> +    sPAPRXiveClass *sxc = SPAPR_XIVE_BASE_GET_CLASS(dev);
> >> +    Error *local_err = NULL;
> >> +
> >> +    sxc->parent_realize(dev, &local_err);
> >> +    if (local_err) {
> >> +        error_propagate(errp, local_err);
> >> +        return;
> >> +    }
> >> +
> >> +    /* TIMA */
> >> +    memory_region_init_io(&xive->tm_mmio, OBJECT(xive), &xive_tm_ops, xive,
> >> +                          "xive.tima", 4ull << TM_SHIFT);
> >> +    sysbus_init_mmio(SYS_BUS_DEVICE(dev), &xive->tm_mmio);
> >> +}
> >> +
> >> +static void spapr_xive_class_init(ObjectClass *klass, void *data)
> >> +{
> >> +    DeviceClass *dc = DEVICE_CLASS(klass);
> >> +    sPAPRXiveClass *sxc = SPAPR_XIVE_BASE_CLASS(klass);
> >> +
> >> +    device_class_set_parent_realize(dc, spapr_xive_realize,
> >> +                                    &sxc->parent_realize);
> >> +}
> >> +
> >>  static const TypeInfo spapr_xive_info = {
> >>      .name = TYPE_SPAPR_XIVE,
> >> -    .parent = TYPE_XIVE_ROUTER,
> >> -    .instance_init = spapr_xive_instance_init,
> >> +    .parent = TYPE_SPAPR_XIVE_BASE,
> >> +    .instance_init = spapr_xive_base_instance_init,
> >>      .instance_size = sizeof(sPAPRXive),
> >>      .class_init = spapr_xive_class_init,
> >> +    .class_size = sizeof(sPAPRXiveClass),
> >>  };
> >>  
> >>  static void spapr_xive_register_types(void)
> >>  {
> >> +    type_register_static(&spapr_xive_base_info);
> >>      type_register_static(&spapr_xive_info);
> >>  }
> >>  
> >> diff --git a/hw/intc/xive.c b/hw/intc/xive.c
> >> index 7d921023e2ee..9bb37553c9ec 100644
> >> --- a/hw/intc/xive.c
> >> +++ b/hw/intc/xive.c
> >> @@ -478,9 +478,9 @@ static uint32_t xive_tctx_hw_cam_line(XiveTCTX *tctx, bool block_group)
> >>      return tctx_hw_cam_line(block_group, (pir >> 8) & 0xf, pir & 0x7f);
> >>  }
> >>  
> >> -static void xive_tctx_reset(void *dev)
> >> +static void xive_tctx_base_reset(void *dev)
> >>  {
> >> -    XiveTCTX *tctx = XIVE_TCTX(dev);
> >> +    XiveTCTX *tctx = XIVE_TCTX_BASE(dev);
> >>      XiveRouterClass *xrc = XIVE_ROUTER_GET_CLASS(tctx->xrtr);
> >>  
> >>      memset(tctx->regs, 0, sizeof(tctx->regs));
> >> @@ -506,9 +506,9 @@ static void xive_tctx_reset(void *dev)
> >>      }
> >>  }
> >>  
> >> -static void xive_tctx_realize(DeviceState *dev, Error **errp)
> >> +static void xive_tctx_base_realize(DeviceState *dev, Error **errp)
> >>  {
> >> -    XiveTCTX *tctx = XIVE_TCTX(dev);
> >> +    XiveTCTX *tctx = XIVE_TCTX_BASE(dev);
> >>      PowerPCCPU *cpu;
> >>      CPUPPCState *env;
> >>      Object *obj;
> >> @@ -544,15 +544,15 @@ static void xive_tctx_realize(DeviceState *dev, Error **errp)
> >>          return;
> >>      }
> >>  
> >> -    qemu_register_reset(xive_tctx_reset, dev);
> >> +    qemu_register_reset(xive_tctx_base_reset, dev);
> >>  }
> >>  
> >> -static void xive_tctx_unrealize(DeviceState *dev, Error **errp)
> >> +static void xive_tctx_base_unrealize(DeviceState *dev, Error **errp)
> >>  {
> >> -    qemu_unregister_reset(xive_tctx_reset, dev);
> >> +    qemu_unregister_reset(xive_tctx_base_reset, dev);
> >>  }
> >>  
> >> -static const VMStateDescription vmstate_xive_tctx = {
> >> +static const VMStateDescription vmstate_xive_tctx_base = {
> >>      .name = TYPE_XIVE_TCTX,
> >>      .version_id = 1,
> >>      .minimum_version_id = 1,
> >> @@ -562,21 +562,28 @@ static const VMStateDescription vmstate_xive_tctx = {
> >>      },
> >>  };
> >>  
> >> -static void xive_tctx_class_init(ObjectClass *klass, void *data)
> >> +static void xive_tctx_base_class_init(ObjectClass *klass, void *data)
> >>  {
> >>      DeviceClass *dc = DEVICE_CLASS(klass);
> >>  
> >> -    dc->realize = xive_tctx_realize;
> >> -    dc->unrealize = xive_tctx_unrealize;
> >> +    dc->realize = xive_tctx_base_realize;
> >> +    dc->unrealize = xive_tctx_base_unrealize;
> >>      dc->desc = "XIVE Interrupt Thread Context";
> >> -    dc->vmsd = &vmstate_xive_tctx;
> >> +    dc->vmsd = &vmstate_xive_tctx_base;
> >>  }
> >>  
> >> -static const TypeInfo xive_tctx_info = {
> >> -    .name          = TYPE_XIVE_TCTX,
> >> +static const TypeInfo xive_tctx_base_info = {
> >> +    .name          = TYPE_XIVE_TCTX_BASE,
> >>      .parent        = TYPE_DEVICE,
> >> +    .abstract      = true,
> >>      .instance_size = sizeof(XiveTCTX),
> >> -    .class_init    = xive_tctx_class_init,
> >> +    .class_init    = xive_tctx_base_class_init,
> >> +    .class_size    = sizeof(XiveTCTXClass),
> >> +};
> >> +
> >> +static const TypeInfo xive_tctx_info = {
> >> +    .name          = TYPE_XIVE_TCTX,
> >> +    .parent        = TYPE_XIVE_TCTX_BASE,
> >>  };
> >>  
> >>  Object *xive_tctx_create(Object *cpu, const char *type, XiveRouter *xrtr,
> >> @@ -933,9 +940,9 @@ void xive_source_pic_print_info(XiveSource *xsrc, uint32_t offset, Monitor *mon)
> >>      }
> >>  }
> >>  
> >> -static void xive_source_reset(DeviceState *dev)
> >> +static void xive_source_base_reset(DeviceState *dev)
> >>  {
> >> -    XiveSource *xsrc = XIVE_SOURCE(dev);
> >> +    XiveSource *xsrc = XIVE_SOURCE_BASE(dev);
> >>  
> >>      /* Do not clear the LSI bitmap */
> >>  
> >> @@ -943,9 +950,9 @@ static void xive_source_reset(DeviceState *dev)
> >>      memset(xsrc->status, 0x1, xsrc->nr_irqs);
> >>  }
> >>  
> >> -static void xive_source_realize(DeviceState *dev, Error **errp)
> >> +static void xive_source_base_realize(DeviceState *dev,  Error **errp)
> >>  {
> >> -    XiveSource *xsrc = XIVE_SOURCE(dev);
> >> +    XiveSource *xsrc = XIVE_SOURCE_BASE(dev);
> >>      Object *obj;
> >>      Error *local_err = NULL;
> >>  
> >> @@ -971,21 +978,14 @@ static void xive_source_realize(DeviceState *dev, Error **errp)
> >>          return;
> >>      }
> >>  
> >> -    xsrc->qirqs = qemu_allocate_irqs(xive_source_set_irq, xsrc,
> >> -                                     xsrc->nr_irqs);
> >> -
> >>      xsrc->status = g_malloc0(xsrc->nr_irqs);
> >>  
> >>      xsrc->lsi_map = bitmap_new(xsrc->nr_irqs);
> >>      xsrc->lsi_map_size = xsrc->nr_irqs;
> >>  
> >> -    memory_region_init_io(&xsrc->esb_mmio, OBJECT(xsrc),
> >> -                          &xive_source_esb_ops, xsrc, "xive.esb",
> >> -                          (1ull << xsrc->esb_shift) * xsrc->nr_irqs);
> >> -    sysbus_init_mmio(SYS_BUS_DEVICE(dev), &xsrc->esb_mmio);
> >>  }
> >>  
> >> -static const VMStateDescription vmstate_xive_source = {
> >> +static const VMStateDescription vmstate_xive_source_base = {
> >>      .name = TYPE_XIVE_SOURCE,
> >>      .version_id = 1,
> >>      .minimum_version_id = 1,
> >> @@ -1001,29 +1001,68 @@ static const VMStateDescription vmstate_xive_source = {
> >>   * The default XIVE interrupt source setting for the ESB MMIOs is two
> >>   * 64k pages without Store EOI, to be in sync with KVM.
> >>   */
> >> -static Property xive_source_properties[] = {
> >> +static Property xive_source_base_properties[] = {
> >>      DEFINE_PROP_UINT64("flags", XiveSource, esb_flags, 0),
> >>      DEFINE_PROP_UINT32("nr-irqs", XiveSource, nr_irqs, 0),
> >>      DEFINE_PROP_UINT32("shift", XiveSource, esb_shift, XIVE_ESB_64K_2PAGE),
> >>      DEFINE_PROP_END_OF_LIST(),
> >>  };
> >>  
> >> -static void xive_source_class_init(ObjectClass *klass, void *data)
> >> +static void xive_source_base_class_init(ObjectClass *klass, void *data)
> >>  {
> >>      DeviceClass *dc = DEVICE_CLASS(klass);
> >>  
> >>      dc->desc    = "XIVE Interrupt Source";
> >> -    dc->props   = xive_source_properties;
> >> -    dc->realize = xive_source_realize;
> >> -    dc->reset   = xive_source_reset;
> >> -    dc->vmsd    = &vmstate_xive_source;
> >> +    dc->props   = xive_source_base_properties;
> >> +    dc->realize = xive_source_base_realize;
> >> +    dc->reset   = xive_source_base_reset;
> >> +    dc->vmsd    = &vmstate_xive_source_base;
> >> +}
> >> +
> >> +static const TypeInfo xive_source_base_info = {
> >> +    .name          = TYPE_XIVE_SOURCE_BASE,
> >> +    .parent        = TYPE_SYS_BUS_DEVICE,
> >> +    .abstract      = true,
> >> +    .instance_size = sizeof(XiveSource),
> >> +    .class_init    = xive_source_base_class_init,
> >> +    .class_size    = sizeof(XiveSourceClass),
> >> +};
> >> +
> >> +static void xive_source_realize(DeviceState *dev, Error **errp)
> >> +{
> >> +    XiveSource *xsrc = XIVE_SOURCE(dev);
> >> +    XiveSourceClass *xsc = XIVE_SOURCE_BASE_GET_CLASS(dev);
> >> +    Error *local_err = NULL;
> >> +
> >> +    xsc->parent_realize(dev, &local_err);
> >> +    if (local_err) {
> >> +        error_propagate(errp, local_err);
> >> +        return;
> >> +    }
> >> +
> >> +    xsrc->qirqs = qemu_allocate_irqs(xive_source_set_irq, xsrc, xsrc->nr_irqs);
> >> +
> >> +    memory_region_init_io(&xsrc->esb_mmio, OBJECT(xsrc),
> >> +                          &xive_source_esb_ops, xsrc, "xive.esb",
> >> +                          (1ull << xsrc->esb_shift) * xsrc->nr_irqs);
> >> +    sysbus_init_mmio(SYS_BUS_DEVICE(dev), &xsrc->esb_mmio);
> >> +}
> >> +
> >> +static void xive_source_class_init(ObjectClass *klass, void *data)
> >> +{
> >> +    DeviceClass *dc = DEVICE_CLASS(klass);
> >> +    XiveSourceClass *xsc = XIVE_SOURCE_BASE_CLASS(klass);
> >> +
> >> +    device_class_set_parent_realize(dc, xive_source_realize,
> >> +                                    &xsc->parent_realize);
> >>  }
> >>  
> >>  static const TypeInfo xive_source_info = {
> >>      .name          = TYPE_XIVE_SOURCE,
> >> -    .parent        = TYPE_SYS_BUS_DEVICE,
> >> +    .parent        = TYPE_XIVE_SOURCE_BASE,
> >>      .instance_size = sizeof(XiveSource),
> >>      .class_init    = xive_source_class_init,
> >> +    .class_size    = sizeof(XiveSourceClass),
> >>  };
> >>  
> >>  /*
> >> @@ -1659,10 +1698,12 @@ static const TypeInfo xive_fabric_info = {
> >>  
> >>  static void xive_register_types(void)
> >>  {
> >> +    type_register_static(&xive_source_base_info);
> >>      type_register_static(&xive_source_info);
> >>      type_register_static(&xive_fabric_info);
> >>      type_register_static(&xive_router_info);
> >>      type_register_static(&xive_end_source_info);
> >> +    type_register_static(&xive_tctx_base_info);
> >>      type_register_static(&xive_tctx_info);
> >>  }
> >>  
> >> diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c
> >> index 42e73851b174..f6e9e44d4cf9 100644
> >> --- a/hw/ppc/spapr_irq.c
> >> +++ b/hw/ppc/spapr_irq.c
> >> @@ -243,7 +243,7 @@ static sPAPRXive *spapr_xive_create(sPAPRMachineState *spapr,
> >>          return NULL;
> >>      }
> >>      qdev_set_parent_bus(DEVICE(obj), sysbus_get_default());
> >> -    xive = SPAPR_XIVE(obj);
> >> +    xive = SPAPR_XIVE_BASE(obj);
> >>  
> >>      /* Enable the CPU IPIs */
> >>      for (i = 0; i < nr_servers; ++i) {
> >> @@ -311,7 +311,7 @@ static void spapr_irq_print_info_xive(sPAPRMachineState *spapr,
> >>      CPU_FOREACH(cs) {
> >>          PowerPCCPU *cpu = POWERPC_CPU(cs);
> >>  
> >> -        xive_tctx_pic_print_info(XIVE_TCTX(cpu->intc), mon);
> >> +        xive_tctx_pic_print_info(XIVE_TCTX_BASE(cpu->intc), mon);
> >>      }
> >>  
> >>      spapr_xive_pic_print_info(spapr->xive, mon);
> > 
>
Cédric Le Goater Nov. 29, 2018, 4:06 p.m. UTC | #4
On 11/29/18 3:59 AM, David Gibson wrote:
> On Wed, Nov 28, 2018 at 11:38:50PM +0100, Cédric Le Goater wrote:
>> On 11/28/18 6:13 AM, David Gibson wrote:
>>> On Fri, Nov 16, 2018 at 11:57:13AM +0100, Cédric Le Goater wrote:
>>>> The XIVE models for the QEMU and KVM accelerators will have a lot in
>>>> common. Introduce an abstract class for the source, the thread context
>>>> and the interrupt controller object to handle the differences in the
>>>> object initialization. These classes will also be used to define state
>>>> synchronization handlers for the monitor and migration usage.
>>>>
>>>> This is very much like the XICS models.
>>>
>>> Yeah.. so I know it's my code, but in hindsight I think making
>>> separate subclasses for TCG and KVM was a mistake.  The distinction
>>> between emulated and KVM version is supposed to be invisible to both
>>> guest and (almost) to user, whereas a subclass usually indicates a
>>> visibly different device.
>>
>> so how do you want to model the KVM part ? with a single object and
>> kvm_enabled() sections ?
> 
> Basically, yes. 

OK. Let's take that path then. It should improve code readability. 

> In practice I think you probably want a helper called
> xive_is_kvm() or something, which would evaluate to (kvm_enabled() &&
> kvm_irqchip_in_kernel()).

yes.

Thanks,

C.

> 
>>>> Signed-off-by: Cédric Le Goater <clg@kaod.org>
>>>> ---
>>>>  include/hw/ppc/spapr_xive.h |  15 +++++
>>>>  include/hw/ppc/xive.h       |  30 ++++++++++
>>>>  hw/intc/spapr_xive.c        |  86 +++++++++++++++++++---------
>>>>  hw/intc/xive.c              | 109 +++++++++++++++++++++++++-----------
>>>>  hw/ppc/spapr_irq.c          |   4 +-
>>>>  5 files changed, 182 insertions(+), 62 deletions(-)
>>>>
>>>> diff --git a/include/hw/ppc/spapr_xive.h b/include/hw/ppc/spapr_xive.h
>>>> index 5b3fab192d41..aca2969a09ab 100644
>>>> --- a/include/hw/ppc/spapr_xive.h
>>>> +++ b/include/hw/ppc/spapr_xive.h
>>>> @@ -13,6 +13,10 @@
>>>>  #include "hw/sysbus.h"
>>>>  #include "hw/ppc/xive.h"
>>>>  
>>>> +#define TYPE_SPAPR_XIVE_BASE "spapr-xive-base"
>>>> +#define SPAPR_XIVE_BASE(obj) \
>>>> +    OBJECT_CHECK(sPAPRXive, (obj), TYPE_SPAPR_XIVE_BASE)
>>>> +
>>>>  #define TYPE_SPAPR_XIVE "spapr-xive"
>>>>  #define SPAPR_XIVE(obj) OBJECT_CHECK(sPAPRXive, (obj), TYPE_SPAPR_XIVE)
>>>>  
>>>> @@ -38,6 +42,17 @@ typedef struct sPAPRXive {
>>>>      MemoryRegion  tm_mmio;
>>>>  } sPAPRXive;
>>>>  
>>>> +#define SPAPR_XIVE_BASE_CLASS(klass) \
>>>> +     OBJECT_CLASS_CHECK(sPAPRXiveClass, (klass), TYPE_SPAPR_XIVE_BASE)
>>>> +#define SPAPR_XIVE_BASE_GET_CLASS(obj) \
>>>> +     OBJECT_GET_CLASS(sPAPRXiveClass, (obj), TYPE_SPAPR_XIVE_BASE)
>>>> +
>>>> +typedef struct sPAPRXiveClass {
>>>> +    XiveRouterClass parent_class;
>>>> +
>>>> +    DeviceRealize   parent_realize;
>>>> +} sPAPRXiveClass;
>>>> +
>>>>  bool spapr_xive_irq_enable(sPAPRXive *xive, uint32_t lisn, bool lsi);
>>>>  bool spapr_xive_irq_disable(sPAPRXive *xive, uint32_t lisn);
>>>>  void spapr_xive_pic_print_info(sPAPRXive *xive, Monitor *mon);
>>>> diff --git a/include/hw/ppc/xive.h b/include/hw/ppc/xive.h
>>>> index b74eb326dcd1..281ed370121c 100644
>>>> --- a/include/hw/ppc/xive.h
>>>> +++ b/include/hw/ppc/xive.h
>>>> @@ -38,6 +38,10 @@ typedef struct XiveFabricClass {
>>>>   * XIVE Interrupt Source
>>>>   */
>>>>  
>>>> +#define TYPE_XIVE_SOURCE_BASE "xive-source-base"
>>>> +#define XIVE_SOURCE_BASE(obj) \
>>>> +    OBJECT_CHECK(XiveSource, (obj), TYPE_XIVE_SOURCE_BASE)
>>>> +
>>>>  #define TYPE_XIVE_SOURCE "xive-source"
>>>>  #define XIVE_SOURCE(obj) OBJECT_CHECK(XiveSource, (obj), TYPE_XIVE_SOURCE)
>>>>  
>>>> @@ -68,6 +72,18 @@ typedef struct XiveSource {
>>>>      XiveFabric      *xive;
>>>>  } XiveSource;
>>>>  
>>>> +#define XIVE_SOURCE_BASE_CLASS(klass) \
>>>> +     OBJECT_CLASS_CHECK(XiveSourceClass, (klass), TYPE_XIVE_SOURCE_BASE)
>>>> +#define XIVE_SOURCE_BASE_GET_CLASS(obj) \
>>>> +     OBJECT_GET_CLASS(XiveSourceClass, (obj), TYPE_XIVE_SOURCE_BASE)
>>>> +
>>>> +typedef struct XiveSourceClass {
>>>> +    SysBusDeviceClass parent_class;
>>>> +
>>>> +    DeviceRealize     parent_realize;
>>>> +    DeviceReset       parent_reset;
>>>> +} XiveSourceClass;
>>>> +
>>>>  /*
>>>>   * ESB MMIO setting. Can be one page, for both source triggering and
>>>>   * source management, or two different pages. See below for magic
>>>> @@ -253,6 +269,9 @@ void xive_end_pic_print_info(XiveEND *end, uint32_t end_idx, Monitor *mon);
>>>>   * XIVE Thread interrupt Management (TM) context
>>>>   */
>>>>  
>>>> +#define TYPE_XIVE_TCTX_BASE "xive-tctx-base"
>>>> +#define XIVE_TCTX_BASE(obj) OBJECT_CHECK(XiveTCTX, (obj), TYPE_XIVE_TCTX_BASE)
>>>> +
>>>>  #define TYPE_XIVE_TCTX "xive-tctx"
>>>>  #define XIVE_TCTX(obj) OBJECT_CHECK(XiveTCTX, (obj), TYPE_XIVE_TCTX)
>>>>  
>>>> @@ -278,6 +297,17 @@ typedef struct XiveTCTX {
>>>>      XiveRouter  *xrtr;
>>>>  } XiveTCTX;
>>>>  
>>>> +#define XIVE_TCTX_BASE_CLASS(klass) \
>>>> +     OBJECT_CLASS_CHECK(XiveTCTXClass, (klass), TYPE_XIVE_TCTX_BASE)
>>>> +#define XIVE_TCTX_BASE_GET_CLASS(obj) \
>>>> +     OBJECT_GET_CLASS(XiveTCTXClass, (obj), TYPE_XIVE_TCTX_BASE)
>>>> +
>>>> +typedef struct XiveTCTXClass {
>>>> +    DeviceClass       parent_class;
>>>> +
>>>> +    DeviceRealize     parent_realize;
>>>> +} XiveTCTXClass;
>>>> +
>>>>  /*
>>>>   * XIVE Thread Interrupt Management Aera (TIMA)
>>>>   */
>>>> diff --git a/hw/intc/spapr_xive.c b/hw/intc/spapr_xive.c
>>>> index 3bf77ace11a2..ec85f7e4f88d 100644
>>>> --- a/hw/intc/spapr_xive.c
>>>> +++ b/hw/intc/spapr_xive.c
>>>> @@ -53,9 +53,9 @@ static void spapr_xive_mmio_map(sPAPRXive *xive)
>>>>      sysbus_mmio_map(SYS_BUS_DEVICE(xive), 0, xive->tm_base);
>>>>  }
>>>>  
>>>> -static void spapr_xive_reset(DeviceState *dev)
>>>> +static void spapr_xive_base_reset(DeviceState *dev)
>>>>  {
>>>> -    sPAPRXive *xive = SPAPR_XIVE(dev);
>>>> +    sPAPRXive *xive = SPAPR_XIVE_BASE(dev);
>>>>      int i;
>>>>  
>>>>      /* Xive Source reset is done through SysBus, it should put all
>>>> @@ -76,9 +76,9 @@ static void spapr_xive_reset(DeviceState *dev)
>>>>      spapr_xive_mmio_map(xive);
>>>>  }
>>>>  
>>>> -static void spapr_xive_instance_init(Object *obj)
>>>> +static void spapr_xive_base_instance_init(Object *obj)
>>>>  {
>>>> -    sPAPRXive *xive = SPAPR_XIVE(obj);
>>>> +    sPAPRXive *xive = SPAPR_XIVE_BASE(obj);
>>>>  
>>>>      object_initialize(&xive->source, sizeof(xive->source), TYPE_XIVE_SOURCE);
>>>>      object_property_add_child(obj, "source", OBJECT(&xive->source), NULL);
>>>> @@ -89,9 +89,9 @@ static void spapr_xive_instance_init(Object *obj)
>>>>                                NULL);
>>>>  }
>>>>  
>>>> -static void spapr_xive_realize(DeviceState *dev, Error **errp)
>>>> +static void spapr_xive_base_realize(DeviceState *dev, Error **errp)
>>>>  {
>>>> -    sPAPRXive *xive = SPAPR_XIVE(dev);
>>>> +    sPAPRXive *xive = SPAPR_XIVE_BASE(dev);
>>>>      XiveSource *xsrc = &xive->source;
>>>>      XiveENDSource *end_xsrc = &xive->end_source;
>>>>      Error *local_err = NULL;
>>>> @@ -142,16 +142,11 @@ static void spapr_xive_realize(DeviceState *dev, Error **errp)
>>>>       */
>>>>      xive->eat = g_new0(XiveEAS, xive->nr_irqs);
>>>>      xive->endt = g_new0(XiveEND, xive->nr_ends);
>>>> -
>>>> -    /* TIMA initialization */
>>>> -    memory_region_init_io(&xive->tm_mmio, OBJECT(xive), &xive_tm_ops, xive,
>>>> -                          "xive.tima", 4ull << TM_SHIFT);
>>>> -    sysbus_init_mmio(SYS_BUS_DEVICE(dev), &xive->tm_mmio);
>>>>  }
>>>>  
>>>>  static int spapr_xive_get_eas(XiveRouter *xrtr, uint32_t lisn, XiveEAS *eas)
>>>>  {
>>>> -    sPAPRXive *xive = SPAPR_XIVE(xrtr);
>>>> +    sPAPRXive *xive = SPAPR_XIVE_BASE(xrtr);
>>>>  
>>>>      if (lisn >= xive->nr_irqs) {
>>>>          return -1;
>>>> @@ -163,7 +158,7 @@ static int spapr_xive_get_eas(XiveRouter *xrtr, uint32_t lisn, XiveEAS *eas)
>>>>  
>>>>  static int spapr_xive_set_eas(XiveRouter *xrtr, uint32_t lisn, XiveEAS *eas)
>>>>  {
>>>> -    sPAPRXive *xive = SPAPR_XIVE(xrtr);
>>>> +    sPAPRXive *xive = SPAPR_XIVE_BASE(xrtr);
>>>>  
>>>>      if (lisn >= xive->nr_irqs) {
>>>>          return -1;
>>>> @@ -176,7 +171,7 @@ static int spapr_xive_set_eas(XiveRouter *xrtr, uint32_t lisn, XiveEAS *eas)
>>>>  static int spapr_xive_get_end(XiveRouter *xrtr,
>>>>                                uint8_t end_blk, uint32_t end_idx, XiveEND *end)
>>>>  {
>>>> -    sPAPRXive *xive = SPAPR_XIVE(xrtr);
>>>> +    sPAPRXive *xive = SPAPR_XIVE_BASE(xrtr);
>>>>  
>>>>      if (end_idx >= xive->nr_ends) {
>>>>          return -1;
>>>> @@ -189,7 +184,7 @@ static int spapr_xive_get_end(XiveRouter *xrtr,
>>>>  static int spapr_xive_set_end(XiveRouter *xrtr,
>>>>                                uint8_t end_blk, uint32_t end_idx, XiveEND *end)
>>>>  {
>>>> -    sPAPRXive *xive = SPAPR_XIVE(xrtr);
>>>> +    sPAPRXive *xive = SPAPR_XIVE_BASE(xrtr);
>>>>  
>>>>      if (end_idx >= xive->nr_ends) {
>>>>          return -1;
>>>> @@ -202,7 +197,7 @@ static int spapr_xive_set_end(XiveRouter *xrtr,
>>>>  static int spapr_xive_get_nvt(XiveRouter *xrtr,
>>>>                                uint8_t nvt_blk, uint32_t nvt_idx, XiveNVT *nvt)
>>>>  {
>>>> -    sPAPRXive *xive = SPAPR_XIVE(xrtr);
>>>> +    sPAPRXive *xive = SPAPR_XIVE_BASE(xrtr);
>>>>      uint32_t vcpu_id = spapr_xive_nvt_to_target(xive, nvt_blk, nvt_idx);
>>>>      PowerPCCPU *cpu = spapr_find_cpu(vcpu_id);
>>>>  
>>>> @@ -236,7 +231,7 @@ static void spapr_xive_reset_tctx(XiveRouter *xrtr, XiveTCTX *tctx)
>>>>      uint32_t nvt_idx;
>>>>      uint32_t nvt_cam;
>>>>  
>>>> -    spapr_xive_cpu_to_nvt(SPAPR_XIVE(xrtr), POWERPC_CPU(tctx->cs),
>>>> +    spapr_xive_cpu_to_nvt(SPAPR_XIVE_BASE(xrtr), POWERPC_CPU(tctx->cs),
>>>>                            &nvt_blk, &nvt_idx);
>>>>  
>>>>      nvt_cam = cpu_to_be32(TM_QW1W2_VO | xive_tctx_cam_line(nvt_blk, nvt_idx));
>>>> @@ -359,7 +354,7 @@ static const VMStateDescription vmstate_spapr_xive_eas = {
>>>>      },
>>>>  };
>>>>  
>>>> -static const VMStateDescription vmstate_spapr_xive = {
>>>> +static const VMStateDescription vmstate_spapr_xive_base = {
>>>>      .name = TYPE_SPAPR_XIVE,
>>>>      .version_id = 1,
>>>>      .minimum_version_id = 1,
>>>> @@ -373,7 +368,7 @@ static const VMStateDescription vmstate_spapr_xive = {
>>>>      },
>>>>  };
>>>>  
>>>> -static Property spapr_xive_properties[] = {
>>>> +static Property spapr_xive_base_properties[] = {
>>>>      DEFINE_PROP_UINT32("nr-irqs", sPAPRXive, nr_irqs, 0),
>>>>      DEFINE_PROP_UINT32("nr-ends", sPAPRXive, nr_ends, 0),
>>>>      DEFINE_PROP_UINT64("vc-base", sPAPRXive, vc_base, SPAPR_XIVE_VC_BASE),
>>>> @@ -381,16 +376,16 @@ static Property spapr_xive_properties[] = {
>>>>      DEFINE_PROP_END_OF_LIST(),
>>>>  };
>>>>  
>>>> -static void spapr_xive_class_init(ObjectClass *klass, void *data)
>>>> +static void spapr_xive_base_class_init(ObjectClass *klass, void *data)
>>>>  {
>>>>      DeviceClass *dc = DEVICE_CLASS(klass);
>>>>      XiveRouterClass *xrc = XIVE_ROUTER_CLASS(klass);
>>>>  
>>>>      dc->desc    = "sPAPR XIVE Interrupt Controller";
>>>> -    dc->props   = spapr_xive_properties;
>>>> -    dc->realize = spapr_xive_realize;
>>>> -    dc->reset   = spapr_xive_reset;
>>>> -    dc->vmsd    = &vmstate_spapr_xive;
>>>> +    dc->props   = spapr_xive_base_properties;
>>>> +    dc->realize = spapr_xive_base_realize;
>>>> +    dc->reset   = spapr_xive_base_reset;
>>>> +    dc->vmsd    = &vmstate_spapr_xive_base;
>>>>  
>>>>      xrc->get_eas = spapr_xive_get_eas;
>>>>      xrc->set_eas = spapr_xive_set_eas;
>>>> @@ -401,16 +396,55 @@ static void spapr_xive_class_init(ObjectClass *klass, void *data)
>>>>      xrc->reset_tctx = spapr_xive_reset_tctx;
>>>>  }
>>>>  
>>>> +static const TypeInfo spapr_xive_base_info = {
>>>> +    .name = TYPE_SPAPR_XIVE_BASE,
>>>> +    .parent = TYPE_XIVE_ROUTER,
>>>> +    .abstract = true,
>>>> +    .instance_init = spapr_xive_base_instance_init,
>>>> +    .instance_size = sizeof(sPAPRXive),
>>>> +    .class_init = spapr_xive_base_class_init,
>>>> +    .class_size = sizeof(sPAPRXiveClass),
>>>> +};
>>>> +
>>>> +static void spapr_xive_realize(DeviceState *dev, Error **errp)
>>>> +{
>>>> +    sPAPRXive *xive = SPAPR_XIVE(dev);
>>>> +    sPAPRXiveClass *sxc = SPAPR_XIVE_BASE_GET_CLASS(dev);
>>>> +    Error *local_err = NULL;
>>>> +
>>>> +    sxc->parent_realize(dev, &local_err);
>>>> +    if (local_err) {
>>>> +        error_propagate(errp, local_err);
>>>> +        return;
>>>> +    }
>>>> +
>>>> +    /* TIMA */
>>>> +    memory_region_init_io(&xive->tm_mmio, OBJECT(xive), &xive_tm_ops, xive,
>>>> +                          "xive.tima", 4ull << TM_SHIFT);
>>>> +    sysbus_init_mmio(SYS_BUS_DEVICE(dev), &xive->tm_mmio);
>>>> +}
>>>> +
>>>> +static void spapr_xive_class_init(ObjectClass *klass, void *data)
>>>> +{
>>>> +    DeviceClass *dc = DEVICE_CLASS(klass);
>>>> +    sPAPRXiveClass *sxc = SPAPR_XIVE_BASE_CLASS(klass);
>>>> +
>>>> +    device_class_set_parent_realize(dc, spapr_xive_realize,
>>>> +                                    &sxc->parent_realize);
>>>> +}
>>>> +
>>>>  static const TypeInfo spapr_xive_info = {
>>>>      .name = TYPE_SPAPR_XIVE,
>>>> -    .parent = TYPE_XIVE_ROUTER,
>>>> -    .instance_init = spapr_xive_instance_init,
>>>> +    .parent = TYPE_SPAPR_XIVE_BASE,
>>>> +    .instance_init = spapr_xive_base_instance_init,
>>>>      .instance_size = sizeof(sPAPRXive),
>>>>      .class_init = spapr_xive_class_init,
>>>> +    .class_size = sizeof(sPAPRXiveClass),
>>>>  };
>>>>  
>>>>  static void spapr_xive_register_types(void)
>>>>  {
>>>> +    type_register_static(&spapr_xive_base_info);
>>>>      type_register_static(&spapr_xive_info);
>>>>  }
>>>>  
>>>> diff --git a/hw/intc/xive.c b/hw/intc/xive.c
>>>> index 7d921023e2ee..9bb37553c9ec 100644
>>>> --- a/hw/intc/xive.c
>>>> +++ b/hw/intc/xive.c
>>>> @@ -478,9 +478,9 @@ static uint32_t xive_tctx_hw_cam_line(XiveTCTX *tctx, bool block_group)
>>>>      return tctx_hw_cam_line(block_group, (pir >> 8) & 0xf, pir & 0x7f);
>>>>  }
>>>>  
>>>> -static void xive_tctx_reset(void *dev)
>>>> +static void xive_tctx_base_reset(void *dev)
>>>>  {
>>>> -    XiveTCTX *tctx = XIVE_TCTX(dev);
>>>> +    XiveTCTX *tctx = XIVE_TCTX_BASE(dev);
>>>>      XiveRouterClass *xrc = XIVE_ROUTER_GET_CLASS(tctx->xrtr);
>>>>  
>>>>      memset(tctx->regs, 0, sizeof(tctx->regs));
>>>> @@ -506,9 +506,9 @@ static void xive_tctx_reset(void *dev)
>>>>      }
>>>>  }
>>>>  
>>>> -static void xive_tctx_realize(DeviceState *dev, Error **errp)
>>>> +static void xive_tctx_base_realize(DeviceState *dev, Error **errp)
>>>>  {
>>>> -    XiveTCTX *tctx = XIVE_TCTX(dev);
>>>> +    XiveTCTX *tctx = XIVE_TCTX_BASE(dev);
>>>>      PowerPCCPU *cpu;
>>>>      CPUPPCState *env;
>>>>      Object *obj;
>>>> @@ -544,15 +544,15 @@ static void xive_tctx_realize(DeviceState *dev, Error **errp)
>>>>          return;
>>>>      }
>>>>  
>>>> -    qemu_register_reset(xive_tctx_reset, dev);
>>>> +    qemu_register_reset(xive_tctx_base_reset, dev);
>>>>  }
>>>>  
>>>> -static void xive_tctx_unrealize(DeviceState *dev, Error **errp)
>>>> +static void xive_tctx_base_unrealize(DeviceState *dev, Error **errp)
>>>>  {
>>>> -    qemu_unregister_reset(xive_tctx_reset, dev);
>>>> +    qemu_unregister_reset(xive_tctx_base_reset, dev);
>>>>  }
>>>>  
>>>> -static const VMStateDescription vmstate_xive_tctx = {
>>>> +static const VMStateDescription vmstate_xive_tctx_base = {
>>>>      .name = TYPE_XIVE_TCTX,
>>>>      .version_id = 1,
>>>>      .minimum_version_id = 1,
>>>> @@ -562,21 +562,28 @@ static const VMStateDescription vmstate_xive_tctx = {
>>>>      },
>>>>  };
>>>>  
>>>> -static void xive_tctx_class_init(ObjectClass *klass, void *data)
>>>> +static void xive_tctx_base_class_init(ObjectClass *klass, void *data)
>>>>  {
>>>>      DeviceClass *dc = DEVICE_CLASS(klass);
>>>>  
>>>> -    dc->realize = xive_tctx_realize;
>>>> -    dc->unrealize = xive_tctx_unrealize;
>>>> +    dc->realize = xive_tctx_base_realize;
>>>> +    dc->unrealize = xive_tctx_base_unrealize;
>>>>      dc->desc = "XIVE Interrupt Thread Context";
>>>> -    dc->vmsd = &vmstate_xive_tctx;
>>>> +    dc->vmsd = &vmstate_xive_tctx_base;
>>>>  }
>>>>  
>>>> -static const TypeInfo xive_tctx_info = {
>>>> -    .name          = TYPE_XIVE_TCTX,
>>>> +static const TypeInfo xive_tctx_base_info = {
>>>> +    .name          = TYPE_XIVE_TCTX_BASE,
>>>>      .parent        = TYPE_DEVICE,
>>>> +    .abstract      = true,
>>>>      .instance_size = sizeof(XiveTCTX),
>>>> -    .class_init    = xive_tctx_class_init,
>>>> +    .class_init    = xive_tctx_base_class_init,
>>>> +    .class_size    = sizeof(XiveTCTXClass),
>>>> +};
>>>> +
>>>> +static const TypeInfo xive_tctx_info = {
>>>> +    .name          = TYPE_XIVE_TCTX,
>>>> +    .parent        = TYPE_XIVE_TCTX_BASE,
>>>>  };
>>>>  
>>>>  Object *xive_tctx_create(Object *cpu, const char *type, XiveRouter *xrtr,
>>>> @@ -933,9 +940,9 @@ void xive_source_pic_print_info(XiveSource *xsrc, uint32_t offset, Monitor *mon)
>>>>      }
>>>>  }
>>>>  
>>>> -static void xive_source_reset(DeviceState *dev)
>>>> +static void xive_source_base_reset(DeviceState *dev)
>>>>  {
>>>> -    XiveSource *xsrc = XIVE_SOURCE(dev);
>>>> +    XiveSource *xsrc = XIVE_SOURCE_BASE(dev);
>>>>  
>>>>      /* Do not clear the LSI bitmap */
>>>>  
>>>> @@ -943,9 +950,9 @@ static void xive_source_reset(DeviceState *dev)
>>>>      memset(xsrc->status, 0x1, xsrc->nr_irqs);
>>>>  }
>>>>  
>>>> -static void xive_source_realize(DeviceState *dev, Error **errp)
>>>> +static void xive_source_base_realize(DeviceState *dev,  Error **errp)
>>>>  {
>>>> -    XiveSource *xsrc = XIVE_SOURCE(dev);
>>>> +    XiveSource *xsrc = XIVE_SOURCE_BASE(dev);
>>>>      Object *obj;
>>>>      Error *local_err = NULL;
>>>>  
>>>> @@ -971,21 +978,14 @@ static void xive_source_realize(DeviceState *dev, Error **errp)
>>>>          return;
>>>>      }
>>>>  
>>>> -    xsrc->qirqs = qemu_allocate_irqs(xive_source_set_irq, xsrc,
>>>> -                                     xsrc->nr_irqs);
>>>> -
>>>>      xsrc->status = g_malloc0(xsrc->nr_irqs);
>>>>  
>>>>      xsrc->lsi_map = bitmap_new(xsrc->nr_irqs);
>>>>      xsrc->lsi_map_size = xsrc->nr_irqs;
>>>>  
>>>> -    memory_region_init_io(&xsrc->esb_mmio, OBJECT(xsrc),
>>>> -                          &xive_source_esb_ops, xsrc, "xive.esb",
>>>> -                          (1ull << xsrc->esb_shift) * xsrc->nr_irqs);
>>>> -    sysbus_init_mmio(SYS_BUS_DEVICE(dev), &xsrc->esb_mmio);
>>>>  }
>>>>  
>>>> -static const VMStateDescription vmstate_xive_source = {
>>>> +static const VMStateDescription vmstate_xive_source_base = {
>>>>      .name = TYPE_XIVE_SOURCE,
>>>>      .version_id = 1,
>>>>      .minimum_version_id = 1,
>>>> @@ -1001,29 +1001,68 @@ static const VMStateDescription vmstate_xive_source = {
>>>>   * The default XIVE interrupt source setting for the ESB MMIOs is two
>>>>   * 64k pages without Store EOI, to be in sync with KVM.
>>>>   */
>>>> -static Property xive_source_properties[] = {
>>>> +static Property xive_source_base_properties[] = {
>>>>      DEFINE_PROP_UINT64("flags", XiveSource, esb_flags, 0),
>>>>      DEFINE_PROP_UINT32("nr-irqs", XiveSource, nr_irqs, 0),
>>>>      DEFINE_PROP_UINT32("shift", XiveSource, esb_shift, XIVE_ESB_64K_2PAGE),
>>>>      DEFINE_PROP_END_OF_LIST(),
>>>>  };
>>>>  
>>>> -static void xive_source_class_init(ObjectClass *klass, void *data)
>>>> +static void xive_source_base_class_init(ObjectClass *klass, void *data)
>>>>  {
>>>>      DeviceClass *dc = DEVICE_CLASS(klass);
>>>>  
>>>>      dc->desc    = "XIVE Interrupt Source";
>>>> -    dc->props   = xive_source_properties;
>>>> -    dc->realize = xive_source_realize;
>>>> -    dc->reset   = xive_source_reset;
>>>> -    dc->vmsd    = &vmstate_xive_source;
>>>> +    dc->props   = xive_source_base_properties;
>>>> +    dc->realize = xive_source_base_realize;
>>>> +    dc->reset   = xive_source_base_reset;
>>>> +    dc->vmsd    = &vmstate_xive_source_base;
>>>> +}
>>>> +
>>>> +static const TypeInfo xive_source_base_info = {
>>>> +    .name          = TYPE_XIVE_SOURCE_BASE,
>>>> +    .parent        = TYPE_SYS_BUS_DEVICE,
>>>> +    .abstract      = true,
>>>> +    .instance_size = sizeof(XiveSource),
>>>> +    .class_init    = xive_source_base_class_init,
>>>> +    .class_size    = sizeof(XiveSourceClass),
>>>> +};
>>>> +
>>>> +static void xive_source_realize(DeviceState *dev, Error **errp)
>>>> +{
>>>> +    XiveSource *xsrc = XIVE_SOURCE(dev);
>>>> +    XiveSourceClass *xsc = XIVE_SOURCE_BASE_GET_CLASS(dev);
>>>> +    Error *local_err = NULL;
>>>> +
>>>> +    xsc->parent_realize(dev, &local_err);
>>>> +    if (local_err) {
>>>> +        error_propagate(errp, local_err);
>>>> +        return;
>>>> +    }
>>>> +
>>>> +    xsrc->qirqs = qemu_allocate_irqs(xive_source_set_irq, xsrc, xsrc->nr_irqs);
>>>> +
>>>> +    memory_region_init_io(&xsrc->esb_mmio, OBJECT(xsrc),
>>>> +                          &xive_source_esb_ops, xsrc, "xive.esb",
>>>> +                          (1ull << xsrc->esb_shift) * xsrc->nr_irqs);
>>>> +    sysbus_init_mmio(SYS_BUS_DEVICE(dev), &xsrc->esb_mmio);
>>>> +}
>>>> +
>>>> +static void xive_source_class_init(ObjectClass *klass, void *data)
>>>> +{
>>>> +    DeviceClass *dc = DEVICE_CLASS(klass);
>>>> +    XiveSourceClass *xsc = XIVE_SOURCE_BASE_CLASS(klass);
>>>> +
>>>> +    device_class_set_parent_realize(dc, xive_source_realize,
>>>> +                                    &xsc->parent_realize);
>>>>  }
>>>>  
>>>>  static const TypeInfo xive_source_info = {
>>>>      .name          = TYPE_XIVE_SOURCE,
>>>> -    .parent        = TYPE_SYS_BUS_DEVICE,
>>>> +    .parent        = TYPE_XIVE_SOURCE_BASE,
>>>>      .instance_size = sizeof(XiveSource),
>>>>      .class_init    = xive_source_class_init,
>>>> +    .class_size    = sizeof(XiveSourceClass),
>>>>  };
>>>>  
>>>>  /*
>>>> @@ -1659,10 +1698,12 @@ static const TypeInfo xive_fabric_info = {
>>>>  
>>>>  static void xive_register_types(void)
>>>>  {
>>>> +    type_register_static(&xive_source_base_info);
>>>>      type_register_static(&xive_source_info);
>>>>      type_register_static(&xive_fabric_info);
>>>>      type_register_static(&xive_router_info);
>>>>      type_register_static(&xive_end_source_info);
>>>> +    type_register_static(&xive_tctx_base_info);
>>>>      type_register_static(&xive_tctx_info);
>>>>  }
>>>>  
>>>> diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c
>>>> index 42e73851b174..f6e9e44d4cf9 100644
>>>> --- a/hw/ppc/spapr_irq.c
>>>> +++ b/hw/ppc/spapr_irq.c
>>>> @@ -243,7 +243,7 @@ static sPAPRXive *spapr_xive_create(sPAPRMachineState *spapr,
>>>>          return NULL;
>>>>      }
>>>>      qdev_set_parent_bus(DEVICE(obj), sysbus_get_default());
>>>> -    xive = SPAPR_XIVE(obj);
>>>> +    xive = SPAPR_XIVE_BASE(obj);
>>>>  
>>>>      /* Enable the CPU IPIs */
>>>>      for (i = 0; i < nr_servers; ++i) {
>>>> @@ -311,7 +311,7 @@ static void spapr_irq_print_info_xive(sPAPRMachineState *spapr,
>>>>      CPU_FOREACH(cs) {
>>>>          PowerPCCPU *cpu = POWERPC_CPU(cs);
>>>>  
>>>> -        xive_tctx_pic_print_info(XIVE_TCTX(cpu->intc), mon);
>>>> +        xive_tctx_pic_print_info(XIVE_TCTX_BASE(cpu->intc), mon);
>>>>      }
>>>>  
>>>>      spapr_xive_pic_print_info(spapr->xive, mon);
>>>
>>
>
diff mbox series

Patch

diff --git a/include/hw/ppc/spapr_xive.h b/include/hw/ppc/spapr_xive.h
index 5b3fab192d41..aca2969a09ab 100644
--- a/include/hw/ppc/spapr_xive.h
+++ b/include/hw/ppc/spapr_xive.h
@@ -13,6 +13,10 @@ 
 #include "hw/sysbus.h"
 #include "hw/ppc/xive.h"
 
+#define TYPE_SPAPR_XIVE_BASE "spapr-xive-base"
+#define SPAPR_XIVE_BASE(obj) \
+    OBJECT_CHECK(sPAPRXive, (obj), TYPE_SPAPR_XIVE_BASE)
+
 #define TYPE_SPAPR_XIVE "spapr-xive"
 #define SPAPR_XIVE(obj) OBJECT_CHECK(sPAPRXive, (obj), TYPE_SPAPR_XIVE)
 
@@ -38,6 +42,17 @@  typedef struct sPAPRXive {
     MemoryRegion  tm_mmio;
 } sPAPRXive;
 
+#define SPAPR_XIVE_BASE_CLASS(klass) \
+     OBJECT_CLASS_CHECK(sPAPRXiveClass, (klass), TYPE_SPAPR_XIVE_BASE)
+#define SPAPR_XIVE_BASE_GET_CLASS(obj) \
+     OBJECT_GET_CLASS(sPAPRXiveClass, (obj), TYPE_SPAPR_XIVE_BASE)
+
+typedef struct sPAPRXiveClass {
+    XiveRouterClass parent_class;
+
+    DeviceRealize   parent_realize;
+} sPAPRXiveClass;
+
 bool spapr_xive_irq_enable(sPAPRXive *xive, uint32_t lisn, bool lsi);
 bool spapr_xive_irq_disable(sPAPRXive *xive, uint32_t lisn);
 void spapr_xive_pic_print_info(sPAPRXive *xive, Monitor *mon);
diff --git a/include/hw/ppc/xive.h b/include/hw/ppc/xive.h
index b74eb326dcd1..281ed370121c 100644
--- a/include/hw/ppc/xive.h
+++ b/include/hw/ppc/xive.h
@@ -38,6 +38,10 @@  typedef struct XiveFabricClass {
  * XIVE Interrupt Source
  */
 
+#define TYPE_XIVE_SOURCE_BASE "xive-source-base"
+#define XIVE_SOURCE_BASE(obj) \
+    OBJECT_CHECK(XiveSource, (obj), TYPE_XIVE_SOURCE_BASE)
+
 #define TYPE_XIVE_SOURCE "xive-source"
 #define XIVE_SOURCE(obj) OBJECT_CHECK(XiveSource, (obj), TYPE_XIVE_SOURCE)
 
@@ -68,6 +72,18 @@  typedef struct XiveSource {
     XiveFabric      *xive;
 } XiveSource;
 
+#define XIVE_SOURCE_BASE_CLASS(klass) \
+     OBJECT_CLASS_CHECK(XiveSourceClass, (klass), TYPE_XIVE_SOURCE_BASE)
+#define XIVE_SOURCE_BASE_GET_CLASS(obj) \
+     OBJECT_GET_CLASS(XiveSourceClass, (obj), TYPE_XIVE_SOURCE_BASE)
+
+typedef struct XiveSourceClass {
+    SysBusDeviceClass parent_class;
+
+    DeviceRealize     parent_realize;
+    DeviceReset       parent_reset;
+} XiveSourceClass;
+
 /*
  * ESB MMIO setting. Can be one page, for both source triggering and
  * source management, or two different pages. See below for magic
@@ -253,6 +269,9 @@  void xive_end_pic_print_info(XiveEND *end, uint32_t end_idx, Monitor *mon);
  * XIVE Thread interrupt Management (TM) context
  */
 
+#define TYPE_XIVE_TCTX_BASE "xive-tctx-base"
+#define XIVE_TCTX_BASE(obj) OBJECT_CHECK(XiveTCTX, (obj), TYPE_XIVE_TCTX_BASE)
+
 #define TYPE_XIVE_TCTX "xive-tctx"
 #define XIVE_TCTX(obj) OBJECT_CHECK(XiveTCTX, (obj), TYPE_XIVE_TCTX)
 
@@ -278,6 +297,17 @@  typedef struct XiveTCTX {
     XiveRouter  *xrtr;
 } XiveTCTX;
 
+#define XIVE_TCTX_BASE_CLASS(klass) \
+     OBJECT_CLASS_CHECK(XiveTCTXClass, (klass), TYPE_XIVE_TCTX_BASE)
+#define XIVE_TCTX_BASE_GET_CLASS(obj) \
+     OBJECT_GET_CLASS(XiveTCTXClass, (obj), TYPE_XIVE_TCTX_BASE)
+
+typedef struct XiveTCTXClass {
+    DeviceClass       parent_class;
+
+    DeviceRealize     parent_realize;
+} XiveTCTXClass;
+
 /*
  * XIVE Thread Interrupt Management Aera (TIMA)
  */
diff --git a/hw/intc/spapr_xive.c b/hw/intc/spapr_xive.c
index 3bf77ace11a2..ec85f7e4f88d 100644
--- a/hw/intc/spapr_xive.c
+++ b/hw/intc/spapr_xive.c
@@ -53,9 +53,9 @@  static void spapr_xive_mmio_map(sPAPRXive *xive)
     sysbus_mmio_map(SYS_BUS_DEVICE(xive), 0, xive->tm_base);
 }
 
-static void spapr_xive_reset(DeviceState *dev)
+static void spapr_xive_base_reset(DeviceState *dev)
 {
-    sPAPRXive *xive = SPAPR_XIVE(dev);
+    sPAPRXive *xive = SPAPR_XIVE_BASE(dev);
     int i;
 
     /* Xive Source reset is done through SysBus, it should put all
@@ -76,9 +76,9 @@  static void spapr_xive_reset(DeviceState *dev)
     spapr_xive_mmio_map(xive);
 }
 
-static void spapr_xive_instance_init(Object *obj)
+static void spapr_xive_base_instance_init(Object *obj)
 {
-    sPAPRXive *xive = SPAPR_XIVE(obj);
+    sPAPRXive *xive = SPAPR_XIVE_BASE(obj);
 
     object_initialize(&xive->source, sizeof(xive->source), TYPE_XIVE_SOURCE);
     object_property_add_child(obj, "source", OBJECT(&xive->source), NULL);
@@ -89,9 +89,9 @@  static void spapr_xive_instance_init(Object *obj)
                               NULL);
 }
 
-static void spapr_xive_realize(DeviceState *dev, Error **errp)
+static void spapr_xive_base_realize(DeviceState *dev, Error **errp)
 {
-    sPAPRXive *xive = SPAPR_XIVE(dev);
+    sPAPRXive *xive = SPAPR_XIVE_BASE(dev);
     XiveSource *xsrc = &xive->source;
     XiveENDSource *end_xsrc = &xive->end_source;
     Error *local_err = NULL;
@@ -142,16 +142,11 @@  static void spapr_xive_realize(DeviceState *dev, Error **errp)
      */
     xive->eat = g_new0(XiveEAS, xive->nr_irqs);
     xive->endt = g_new0(XiveEND, xive->nr_ends);
-
-    /* TIMA initialization */
-    memory_region_init_io(&xive->tm_mmio, OBJECT(xive), &xive_tm_ops, xive,
-                          "xive.tima", 4ull << TM_SHIFT);
-    sysbus_init_mmio(SYS_BUS_DEVICE(dev), &xive->tm_mmio);
 }
 
 static int spapr_xive_get_eas(XiveRouter *xrtr, uint32_t lisn, XiveEAS *eas)
 {
-    sPAPRXive *xive = SPAPR_XIVE(xrtr);
+    sPAPRXive *xive = SPAPR_XIVE_BASE(xrtr);
 
     if (lisn >= xive->nr_irqs) {
         return -1;
@@ -163,7 +158,7 @@  static int spapr_xive_get_eas(XiveRouter *xrtr, uint32_t lisn, XiveEAS *eas)
 
 static int spapr_xive_set_eas(XiveRouter *xrtr, uint32_t lisn, XiveEAS *eas)
 {
-    sPAPRXive *xive = SPAPR_XIVE(xrtr);
+    sPAPRXive *xive = SPAPR_XIVE_BASE(xrtr);
 
     if (lisn >= xive->nr_irqs) {
         return -1;
@@ -176,7 +171,7 @@  static int spapr_xive_set_eas(XiveRouter *xrtr, uint32_t lisn, XiveEAS *eas)
 static int spapr_xive_get_end(XiveRouter *xrtr,
                               uint8_t end_blk, uint32_t end_idx, XiveEND *end)
 {
-    sPAPRXive *xive = SPAPR_XIVE(xrtr);
+    sPAPRXive *xive = SPAPR_XIVE_BASE(xrtr);
 
     if (end_idx >= xive->nr_ends) {
         return -1;
@@ -189,7 +184,7 @@  static int spapr_xive_get_end(XiveRouter *xrtr,
 static int spapr_xive_set_end(XiveRouter *xrtr,
                               uint8_t end_blk, uint32_t end_idx, XiveEND *end)
 {
-    sPAPRXive *xive = SPAPR_XIVE(xrtr);
+    sPAPRXive *xive = SPAPR_XIVE_BASE(xrtr);
 
     if (end_idx >= xive->nr_ends) {
         return -1;
@@ -202,7 +197,7 @@  static int spapr_xive_set_end(XiveRouter *xrtr,
 static int spapr_xive_get_nvt(XiveRouter *xrtr,
                               uint8_t nvt_blk, uint32_t nvt_idx, XiveNVT *nvt)
 {
-    sPAPRXive *xive = SPAPR_XIVE(xrtr);
+    sPAPRXive *xive = SPAPR_XIVE_BASE(xrtr);
     uint32_t vcpu_id = spapr_xive_nvt_to_target(xive, nvt_blk, nvt_idx);
     PowerPCCPU *cpu = spapr_find_cpu(vcpu_id);
 
@@ -236,7 +231,7 @@  static void spapr_xive_reset_tctx(XiveRouter *xrtr, XiveTCTX *tctx)
     uint32_t nvt_idx;
     uint32_t nvt_cam;
 
-    spapr_xive_cpu_to_nvt(SPAPR_XIVE(xrtr), POWERPC_CPU(tctx->cs),
+    spapr_xive_cpu_to_nvt(SPAPR_XIVE_BASE(xrtr), POWERPC_CPU(tctx->cs),
                           &nvt_blk, &nvt_idx);
 
     nvt_cam = cpu_to_be32(TM_QW1W2_VO | xive_tctx_cam_line(nvt_blk, nvt_idx));
@@ -359,7 +354,7 @@  static const VMStateDescription vmstate_spapr_xive_eas = {
     },
 };
 
-static const VMStateDescription vmstate_spapr_xive = {
+static const VMStateDescription vmstate_spapr_xive_base = {
     .name = TYPE_SPAPR_XIVE,
     .version_id = 1,
     .minimum_version_id = 1,
@@ -373,7 +368,7 @@  static const VMStateDescription vmstate_spapr_xive = {
     },
 };
 
-static Property spapr_xive_properties[] = {
+static Property spapr_xive_base_properties[] = {
     DEFINE_PROP_UINT32("nr-irqs", sPAPRXive, nr_irqs, 0),
     DEFINE_PROP_UINT32("nr-ends", sPAPRXive, nr_ends, 0),
     DEFINE_PROP_UINT64("vc-base", sPAPRXive, vc_base, SPAPR_XIVE_VC_BASE),
@@ -381,16 +376,16 @@  static Property spapr_xive_properties[] = {
     DEFINE_PROP_END_OF_LIST(),
 };
 
-static void spapr_xive_class_init(ObjectClass *klass, void *data)
+static void spapr_xive_base_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
     XiveRouterClass *xrc = XIVE_ROUTER_CLASS(klass);
 
     dc->desc    = "sPAPR XIVE Interrupt Controller";
-    dc->props   = spapr_xive_properties;
-    dc->realize = spapr_xive_realize;
-    dc->reset   = spapr_xive_reset;
-    dc->vmsd    = &vmstate_spapr_xive;
+    dc->props   = spapr_xive_base_properties;
+    dc->realize = spapr_xive_base_realize;
+    dc->reset   = spapr_xive_base_reset;
+    dc->vmsd    = &vmstate_spapr_xive_base;
 
     xrc->get_eas = spapr_xive_get_eas;
     xrc->set_eas = spapr_xive_set_eas;
@@ -401,16 +396,55 @@  static void spapr_xive_class_init(ObjectClass *klass, void *data)
     xrc->reset_tctx = spapr_xive_reset_tctx;
 }
 
+static const TypeInfo spapr_xive_base_info = {
+    .name = TYPE_SPAPR_XIVE_BASE,
+    .parent = TYPE_XIVE_ROUTER,
+    .abstract = true,
+    .instance_init = spapr_xive_base_instance_init,
+    .instance_size = sizeof(sPAPRXive),
+    .class_init = spapr_xive_base_class_init,
+    .class_size = sizeof(sPAPRXiveClass),
+};
+
+static void spapr_xive_realize(DeviceState *dev, Error **errp)
+{
+    sPAPRXive *xive = SPAPR_XIVE(dev);
+    sPAPRXiveClass *sxc = SPAPR_XIVE_BASE_GET_CLASS(dev);
+    Error *local_err = NULL;
+
+    sxc->parent_realize(dev, &local_err);
+    if (local_err) {
+        error_propagate(errp, local_err);
+        return;
+    }
+
+    /* TIMA */
+    memory_region_init_io(&xive->tm_mmio, OBJECT(xive), &xive_tm_ops, xive,
+                          "xive.tima", 4ull << TM_SHIFT);
+    sysbus_init_mmio(SYS_BUS_DEVICE(dev), &xive->tm_mmio);
+}
+
+static void spapr_xive_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    sPAPRXiveClass *sxc = SPAPR_XIVE_BASE_CLASS(klass);
+
+    device_class_set_parent_realize(dc, spapr_xive_realize,
+                                    &sxc->parent_realize);
+}
+
 static const TypeInfo spapr_xive_info = {
     .name = TYPE_SPAPR_XIVE,
-    .parent = TYPE_XIVE_ROUTER,
-    .instance_init = spapr_xive_instance_init,
+    .parent = TYPE_SPAPR_XIVE_BASE,
+    .instance_init = spapr_xive_base_instance_init,
     .instance_size = sizeof(sPAPRXive),
     .class_init = spapr_xive_class_init,
+    .class_size = sizeof(sPAPRXiveClass),
 };
 
 static void spapr_xive_register_types(void)
 {
+    type_register_static(&spapr_xive_base_info);
     type_register_static(&spapr_xive_info);
 }
 
diff --git a/hw/intc/xive.c b/hw/intc/xive.c
index 7d921023e2ee..9bb37553c9ec 100644
--- a/hw/intc/xive.c
+++ b/hw/intc/xive.c
@@ -478,9 +478,9 @@  static uint32_t xive_tctx_hw_cam_line(XiveTCTX *tctx, bool block_group)
     return tctx_hw_cam_line(block_group, (pir >> 8) & 0xf, pir & 0x7f);
 }
 
-static void xive_tctx_reset(void *dev)
+static void xive_tctx_base_reset(void *dev)
 {
-    XiveTCTX *tctx = XIVE_TCTX(dev);
+    XiveTCTX *tctx = XIVE_TCTX_BASE(dev);
     XiveRouterClass *xrc = XIVE_ROUTER_GET_CLASS(tctx->xrtr);
 
     memset(tctx->regs, 0, sizeof(tctx->regs));
@@ -506,9 +506,9 @@  static void xive_tctx_reset(void *dev)
     }
 }
 
-static void xive_tctx_realize(DeviceState *dev, Error **errp)
+static void xive_tctx_base_realize(DeviceState *dev, Error **errp)
 {
-    XiveTCTX *tctx = XIVE_TCTX(dev);
+    XiveTCTX *tctx = XIVE_TCTX_BASE(dev);
     PowerPCCPU *cpu;
     CPUPPCState *env;
     Object *obj;
@@ -544,15 +544,15 @@  static void xive_tctx_realize(DeviceState *dev, Error **errp)
         return;
     }
 
-    qemu_register_reset(xive_tctx_reset, dev);
+    qemu_register_reset(xive_tctx_base_reset, dev);
 }
 
-static void xive_tctx_unrealize(DeviceState *dev, Error **errp)
+static void xive_tctx_base_unrealize(DeviceState *dev, Error **errp)
 {
-    qemu_unregister_reset(xive_tctx_reset, dev);
+    qemu_unregister_reset(xive_tctx_base_reset, dev);
 }
 
-static const VMStateDescription vmstate_xive_tctx = {
+static const VMStateDescription vmstate_xive_tctx_base = {
     .name = TYPE_XIVE_TCTX,
     .version_id = 1,
     .minimum_version_id = 1,
@@ -562,21 +562,28 @@  static const VMStateDescription vmstate_xive_tctx = {
     },
 };
 
-static void xive_tctx_class_init(ObjectClass *klass, void *data)
+static void xive_tctx_base_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
 
-    dc->realize = xive_tctx_realize;
-    dc->unrealize = xive_tctx_unrealize;
+    dc->realize = xive_tctx_base_realize;
+    dc->unrealize = xive_tctx_base_unrealize;
     dc->desc = "XIVE Interrupt Thread Context";
-    dc->vmsd = &vmstate_xive_tctx;
+    dc->vmsd = &vmstate_xive_tctx_base;
 }
 
-static const TypeInfo xive_tctx_info = {
-    .name          = TYPE_XIVE_TCTX,
+static const TypeInfo xive_tctx_base_info = {
+    .name          = TYPE_XIVE_TCTX_BASE,
     .parent        = TYPE_DEVICE,
+    .abstract      = true,
     .instance_size = sizeof(XiveTCTX),
-    .class_init    = xive_tctx_class_init,
+    .class_init    = xive_tctx_base_class_init,
+    .class_size    = sizeof(XiveTCTXClass),
+};
+
+static const TypeInfo xive_tctx_info = {
+    .name          = TYPE_XIVE_TCTX,
+    .parent        = TYPE_XIVE_TCTX_BASE,
 };
 
 Object *xive_tctx_create(Object *cpu, const char *type, XiveRouter *xrtr,
@@ -933,9 +940,9 @@  void xive_source_pic_print_info(XiveSource *xsrc, uint32_t offset, Monitor *mon)
     }
 }
 
-static void xive_source_reset(DeviceState *dev)
+static void xive_source_base_reset(DeviceState *dev)
 {
-    XiveSource *xsrc = XIVE_SOURCE(dev);
+    XiveSource *xsrc = XIVE_SOURCE_BASE(dev);
 
     /* Do not clear the LSI bitmap */
 
@@ -943,9 +950,9 @@  static void xive_source_reset(DeviceState *dev)
     memset(xsrc->status, 0x1, xsrc->nr_irqs);
 }
 
-static void xive_source_realize(DeviceState *dev, Error **errp)
+static void xive_source_base_realize(DeviceState *dev,  Error **errp)
 {
-    XiveSource *xsrc = XIVE_SOURCE(dev);
+    XiveSource *xsrc = XIVE_SOURCE_BASE(dev);
     Object *obj;
     Error *local_err = NULL;
 
@@ -971,21 +978,14 @@  static void xive_source_realize(DeviceState *dev, Error **errp)
         return;
     }
 
-    xsrc->qirqs = qemu_allocate_irqs(xive_source_set_irq, xsrc,
-                                     xsrc->nr_irqs);
-
     xsrc->status = g_malloc0(xsrc->nr_irqs);
 
     xsrc->lsi_map = bitmap_new(xsrc->nr_irqs);
     xsrc->lsi_map_size = xsrc->nr_irqs;
 
-    memory_region_init_io(&xsrc->esb_mmio, OBJECT(xsrc),
-                          &xive_source_esb_ops, xsrc, "xive.esb",
-                          (1ull << xsrc->esb_shift) * xsrc->nr_irqs);
-    sysbus_init_mmio(SYS_BUS_DEVICE(dev), &xsrc->esb_mmio);
 }
 
-static const VMStateDescription vmstate_xive_source = {
+static const VMStateDescription vmstate_xive_source_base = {
     .name = TYPE_XIVE_SOURCE,
     .version_id = 1,
     .minimum_version_id = 1,
@@ -1001,29 +1001,68 @@  static const VMStateDescription vmstate_xive_source = {
  * The default XIVE interrupt source setting for the ESB MMIOs is two
  * 64k pages without Store EOI, to be in sync with KVM.
  */
-static Property xive_source_properties[] = {
+static Property xive_source_base_properties[] = {
     DEFINE_PROP_UINT64("flags", XiveSource, esb_flags, 0),
     DEFINE_PROP_UINT32("nr-irqs", XiveSource, nr_irqs, 0),
     DEFINE_PROP_UINT32("shift", XiveSource, esb_shift, XIVE_ESB_64K_2PAGE),
     DEFINE_PROP_END_OF_LIST(),
 };
 
-static void xive_source_class_init(ObjectClass *klass, void *data)
+static void xive_source_base_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
 
     dc->desc    = "XIVE Interrupt Source";
-    dc->props   = xive_source_properties;
-    dc->realize = xive_source_realize;
-    dc->reset   = xive_source_reset;
-    dc->vmsd    = &vmstate_xive_source;
+    dc->props   = xive_source_base_properties;
+    dc->realize = xive_source_base_realize;
+    dc->reset   = xive_source_base_reset;
+    dc->vmsd    = &vmstate_xive_source_base;
+}
+
+static const TypeInfo xive_source_base_info = {
+    .name          = TYPE_XIVE_SOURCE_BASE,
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .abstract      = true,
+    .instance_size = sizeof(XiveSource),
+    .class_init    = xive_source_base_class_init,
+    .class_size    = sizeof(XiveSourceClass),
+};
+
+static void xive_source_realize(DeviceState *dev, Error **errp)
+{
+    XiveSource *xsrc = XIVE_SOURCE(dev);
+    XiveSourceClass *xsc = XIVE_SOURCE_BASE_GET_CLASS(dev);
+    Error *local_err = NULL;
+
+    xsc->parent_realize(dev, &local_err);
+    if (local_err) {
+        error_propagate(errp, local_err);
+        return;
+    }
+
+    xsrc->qirqs = qemu_allocate_irqs(xive_source_set_irq, xsrc, xsrc->nr_irqs);
+
+    memory_region_init_io(&xsrc->esb_mmio, OBJECT(xsrc),
+                          &xive_source_esb_ops, xsrc, "xive.esb",
+                          (1ull << xsrc->esb_shift) * xsrc->nr_irqs);
+    sysbus_init_mmio(SYS_BUS_DEVICE(dev), &xsrc->esb_mmio);
+}
+
+static void xive_source_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    XiveSourceClass *xsc = XIVE_SOURCE_BASE_CLASS(klass);
+
+    device_class_set_parent_realize(dc, xive_source_realize,
+                                    &xsc->parent_realize);
 }
 
 static const TypeInfo xive_source_info = {
     .name          = TYPE_XIVE_SOURCE,
-    .parent        = TYPE_SYS_BUS_DEVICE,
+    .parent        = TYPE_XIVE_SOURCE_BASE,
     .instance_size = sizeof(XiveSource),
     .class_init    = xive_source_class_init,
+    .class_size    = sizeof(XiveSourceClass),
 };
 
 /*
@@ -1659,10 +1698,12 @@  static const TypeInfo xive_fabric_info = {
 
 static void xive_register_types(void)
 {
+    type_register_static(&xive_source_base_info);
     type_register_static(&xive_source_info);
     type_register_static(&xive_fabric_info);
     type_register_static(&xive_router_info);
     type_register_static(&xive_end_source_info);
+    type_register_static(&xive_tctx_base_info);
     type_register_static(&xive_tctx_info);
 }
 
diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c
index 42e73851b174..f6e9e44d4cf9 100644
--- a/hw/ppc/spapr_irq.c
+++ b/hw/ppc/spapr_irq.c
@@ -243,7 +243,7 @@  static sPAPRXive *spapr_xive_create(sPAPRMachineState *spapr,
         return NULL;
     }
     qdev_set_parent_bus(DEVICE(obj), sysbus_get_default());
-    xive = SPAPR_XIVE(obj);
+    xive = SPAPR_XIVE_BASE(obj);
 
     /* Enable the CPU IPIs */
     for (i = 0; i < nr_servers; ++i) {
@@ -311,7 +311,7 @@  static void spapr_irq_print_info_xive(sPAPRMachineState *spapr,
     CPU_FOREACH(cs) {
         PowerPCCPU *cpu = POWERPC_CPU(cs);
 
-        xive_tctx_pic_print_info(XIVE_TCTX(cpu->intc), mon);
+        xive_tctx_pic_print_info(XIVE_TCTX_BASE(cpu->intc), mon);
     }
 
     spapr_xive_pic_print_info(spapr->xive, mon);