diff mbox

[v5,12/17] ppc/pnv: add a XICS native to each PowerNV chip

Message ID 1477129610-31353-13-git-send-email-clg@kaod.org
State New
Headers show

Commit Message

Cédric Le Goater Oct. 22, 2016, 9:46 a.m. UTC
It also links the XICS object to each core as it is needed to do the
CPU setup and the ICP MMIO windows are memory mapped for each thread.

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

 Changes since v4:

 - changed the calculation of the number of ICPs to use smp_threads
 - added the mapping of the ICP subregions per thread

 hw/ppc/pnv.c         | 27 +++++++++++++++++++++++++++
 hw/ppc/pnv_core.c    | 24 ++++++++++++++++++++----
 include/hw/ppc/pnv.h |  2 ++
 3 files changed, 49 insertions(+), 4 deletions(-)

Comments

Cédric Le Goater Oct. 24, 2016, 3:42 p.m. UTC | #1
On 10/22/2016 11:46 AM, Cédric Le Goater wrote:
> It also links the XICS object to each core as it is needed to do the
> CPU setup and the ICP MMIO windows are memory mapped for each thread.
> 
> Signed-off-by: Cédric Le Goater <clg@kaod.org>
> ---
> 
>  Changes since v4:
> 
>  - changed the calculation of the number of ICPs to use smp_threads
>  - added the mapping of the ICP subregions per thread
> 
>  hw/ppc/pnv.c         | 27 +++++++++++++++++++++++++++
>  hw/ppc/pnv_core.c    | 24 ++++++++++++++++++++----
>  include/hw/ppc/pnv.h |  2 ++
>  3 files changed, 49 insertions(+), 4 deletions(-)
> 
> diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
> index c6dc7ca895b6..16d7baf0da71 100644
> --- a/hw/ppc/pnv.c
> +++ b/hw/ppc/pnv.c
> @@ -33,6 +33,7 @@
>  #include "qemu/cutils.h"
>  #include "qapi/visitor.h"
>  
> +#include "hw/ppc/xics.h"
>  #include "hw/ppc/pnv_xscom.h"
>  
>  #include "hw/isa/isa.h"
> @@ -231,6 +232,9 @@ static void powernv_populate_chip(PnvChip *chip, void *fdt)
>          PnvCore *pnv_core = PNV_CORE(chip->cores + i * typesize);
>  
>          powernv_create_core_node(chip, pnv_core, fdt);
> +
> +        /* Interrupt presentation controllers (ICP). One per thread. */
> +        xics_native_populate_icp(chip, fdt, 0, pnv_core->pir, smp_threads);
>      }
>  
>      if (chip->ram_size) {
> @@ -637,6 +641,9 @@ static void pnv_chip_init(Object *obj)
>  
>      object_initialize(&chip->lpc, sizeof(chip->lpc), TYPE_PNV_LPC);
>      object_property_add_child(obj, "lpc", OBJECT(&chip->lpc), NULL);
> +
> +    object_initialize(&chip->xics, sizeof(chip->xics), TYPE_XICS_NATIVE);
> +    object_property_add_child(obj, "xics", OBJECT(&chip->xics), NULL);
>  }
>  
>  static void pnv_chip_realize(DeviceState *dev, Error **errp)
> @@ -668,12 +675,23 @@ static void pnv_chip_realize(DeviceState *dev, Error **errp)
>          return;
>      }
>  
> +    /*
> +     * Interrupt Controller. To be created before the cores because
> +     * each thread will fetch its ICP in the XICS
> +     */
> +    object_property_set_int(OBJECT(&chip->xics), chip->nr_cores * smp_threads,
> +                            "nr_servers",  &error_fatal);
> +    object_property_set_bool(OBJECT(&chip->xics), true, "realized",
> +                             &error_fatal);
> +    sysbus_mmio_map(SYS_BUS_DEVICE(&chip->xics), 0, PNV_XICS_BASE);
> +
>      chip->cores = g_malloc0(typesize * chip->nr_cores);
>  
>      for (i = 0, core_hwid = 0; (core_hwid < sizeof(chip->cores_mask) * 8)
>               && (i < chip->nr_cores); core_hwid++) {
>          char core_name[32];
>          void *pnv_core = chip->cores + i * typesize;
> +        int j;
>  
>          if (!(chip->cores_mask & (1ull << core_hwid))) {
>              continue;
> @@ -690,6 +708,8 @@ static void pnv_chip_realize(DeviceState *dev, Error **errp)
>          object_property_set_int(OBJECT(pnv_core),
>                                  pcc->core_pir(chip, core_hwid),
>                                  "pir", &error_fatal);
> +        object_property_add_const_link(OBJECT(pnv_core), "xics",
> +                                       OBJECT(&chip->xics), &error_fatal);
>          object_property_set_bool(OBJECT(pnv_core), true, "realized",
>                                   &error_fatal);
>          object_unref(OBJECT(pnv_core));
> @@ -697,6 +717,13 @@ static void pnv_chip_realize(DeviceState *dev, Error **errp)
>          /* Each core has an XSCOM MMIO region */
>          pnv_xscom_add_subregion(chip, PNV_XSCOM_EX_CORE_BASE(core_hwid),
>                                  &PNV_CORE(pnv_core)->xscom_regs);
> +
> +        /* Each thread as region for its ICP */
> +        for (j = 0; j < smp_threads; j++) {
> +            memory_region_add_subregion(&chip->xics.icp_mmio,
> +                                        pcc->core_pir(chip, core_hwid) << 12,

Pffut ... This should be :

                                          (pcc->core_pir(chip, core_hwid) + j) << 12,

but as smp_threads=1, it has no consequences for the moment. Tell me 
how you would prefer me to fix this.

Thanks,

C.


> +                                        &chip->xics.icp_mmios[i]);
> +        }
>          i++;
>      }
>      g_free(typename);
> diff --git a/hw/ppc/pnv_core.c b/hw/ppc/pnv_core.c
> index 2acda9637db5..e15c76163759 100644
> --- a/hw/ppc/pnv_core.c
> +++ b/hw/ppc/pnv_core.c
> @@ -24,6 +24,7 @@
>  #include "hw/ppc/ppc.h"
>  #include "hw/ppc/pnv.h"
>  #include "hw/ppc/pnv_core.h"
> +#include "hw/ppc/xics.h"
>  
>  static void powernv_cpu_reset(void *opaque)
>  {
> @@ -42,7 +43,7 @@ static void powernv_cpu_reset(void *opaque)
>      env->msr |= MSR_HVB; /* Hypervisor mode */
>  }
>  
> -static void powernv_cpu_init(PowerPCCPU *cpu, Error **errp)
> +static void powernv_cpu_init(PowerPCCPU *cpu, XICSState *xics, Error **errp)
>  {
>      CPUPPCState *env = &cpu->env;
>      int core_pir;
> @@ -62,6 +63,11 @@ static void powernv_cpu_init(PowerPCCPU *cpu, Error **errp)
>      cpu_ppc_tb_init(env, PNV_TIMEBASE_FREQ);
>  
>      qemu_register_reset(powernv_cpu_reset, cpu);
> +
> +    /*
> +     * xics_cpu_setup() assigns the CPU to the ICP in XICS
> +     */
> +    xics_cpu_setup(xics, cpu);
>  }
>  
>  /*
> @@ -109,7 +115,7 @@ static const MemoryRegionOps pnv_core_xscom_ops = {
>      .endianness = DEVICE_BIG_ENDIAN,
>  };
>  
> -static void pnv_core_realize_child(Object *child, Error **errp)
> +static void pnv_core_realize_child(Object *child, XICSState *xics, Error **errp)
>  {
>      Error *local_err = NULL;
>      CPUState *cs = CPU(child);
> @@ -121,7 +127,7 @@ static void pnv_core_realize_child(Object *child, Error **errp)
>          return;
>      }
>  
> -    powernv_cpu_init(cpu, &local_err);
> +    powernv_cpu_init(cpu, xics, &local_err);
>      if (local_err) {
>          error_propagate(errp, local_err);
>          return;
> @@ -139,6 +145,7 @@ static void pnv_core_realize(DeviceState *dev, Error **errp)
>      void *obj;
>      int i, j;
>      char name[32];
> +    XICSState *xics;
>  
>      pc->threads = g_malloc0(size * cc->nr_threads);
>      for (i = 0; i < cc->nr_threads; i++) {
> @@ -156,10 +163,19 @@ static void pnv_core_realize(DeviceState *dev, Error **errp)
>          object_unref(obj);
>      }
>  
> +    /* get XICS object from chip */
> +    obj = object_property_get_link(OBJECT(dev), "xics", &local_err);
> +    if (!obj) {
> +        error_setg(errp, "%s: required link 'xics' not found: %s",
> +                   __func__, error_get_pretty(local_err));
> +        return;
> +    }
> +    xics = XICS_COMMON(obj);
> +
>      for (j = 0; j < cc->nr_threads; j++) {
>          obj = pc->threads + j * size;
>  
> -        pnv_core_realize_child(obj, &local_err);
> +        pnv_core_realize_child(obj, xics, &local_err);
>          if (local_err) {
>              goto err;
>          }
> diff --git a/include/hw/ppc/pnv.h b/include/hw/ppc/pnv.h
> index c08ed1c72b17..e11618b05f1d 100644
> --- a/include/hw/ppc/pnv.h
> +++ b/include/hw/ppc/pnv.h
> @@ -23,6 +23,7 @@
>  #include "hw/sysbus.h"
>  #include "hw/ppc/pnv_xscom.h"
>  #include "hw/ppc/pnv_lpc.h"
> +#include "hw/ppc/xics.h"
>  
>  #define TYPE_PNV_CHIP "powernv-chip"
>  #define PNV_CHIP(obj) OBJECT_CHECK(PnvChip, (obj), TYPE_PNV_CHIP)
> @@ -57,6 +58,7 @@ typedef struct PnvChip {
>      AddressSpace xscom_as;
>  
>      PnvLpcController lpc;
> +    XICSNative   xics;
>  } PnvChip;
>  
>  typedef struct PnvChipClass {
>
David Gibson Oct. 25, 2016, 5:11 a.m. UTC | #2
On Mon, Oct 24, 2016 at 05:42:52PM +0200, Cédric Le Goater wrote:
> On 10/22/2016 11:46 AM, Cédric Le Goater wrote:
> > It also links the XICS object to each core as it is needed to do the
> > CPU setup and the ICP MMIO windows are memory mapped for each thread.
> > 
> > Signed-off-by: Cédric Le Goater <clg@kaod.org>
> > ---
> > 
> >  Changes since v4:
> > 
> >  - changed the calculation of the number of ICPs to use smp_threads
> >  - added the mapping of the ICP subregions per thread
> > 
> >  hw/ppc/pnv.c         | 27 +++++++++++++++++++++++++++
> >  hw/ppc/pnv_core.c    | 24 ++++++++++++++++++++----
> >  include/hw/ppc/pnv.h |  2 ++
> >  3 files changed, 49 insertions(+), 4 deletions(-)
> > 
> > diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
> > index c6dc7ca895b6..16d7baf0da71 100644
> > --- a/hw/ppc/pnv.c
> > +++ b/hw/ppc/pnv.c
> > @@ -33,6 +33,7 @@
> >  #include "qemu/cutils.h"
> >  #include "qapi/visitor.h"
> >  
> > +#include "hw/ppc/xics.h"
> >  #include "hw/ppc/pnv_xscom.h"
> >  
> >  #include "hw/isa/isa.h"
> > @@ -231,6 +232,9 @@ static void powernv_populate_chip(PnvChip *chip, void *fdt)
> >          PnvCore *pnv_core = PNV_CORE(chip->cores + i * typesize);
> >  
> >          powernv_create_core_node(chip, pnv_core, fdt);
> > +
> > +        /* Interrupt presentation controllers (ICP). One per thread. */
> > +        xics_native_populate_icp(chip, fdt, 0, pnv_core->pir, smp_threads);
> >      }
> >  
> >      if (chip->ram_size) {
> > @@ -637,6 +641,9 @@ static void pnv_chip_init(Object *obj)
> >  
> >      object_initialize(&chip->lpc, sizeof(chip->lpc), TYPE_PNV_LPC);
> >      object_property_add_child(obj, "lpc", OBJECT(&chip->lpc), NULL);
> > +
> > +    object_initialize(&chip->xics, sizeof(chip->xics), TYPE_XICS_NATIVE);
> > +    object_property_add_child(obj, "xics", OBJECT(&chip->xics), NULL);
> >  }
> >  
> >  static void pnv_chip_realize(DeviceState *dev, Error **errp)
> > @@ -668,12 +675,23 @@ static void pnv_chip_realize(DeviceState *dev, Error **errp)
> >          return;
> >      }
> >  
> > +    /*
> > +     * Interrupt Controller. To be created before the cores because
> > +     * each thread will fetch its ICP in the XICS
> > +     */
> > +    object_property_set_int(OBJECT(&chip->xics), chip->nr_cores * smp_threads,
> > +                            "nr_servers",  &error_fatal);
> > +    object_property_set_bool(OBJECT(&chip->xics), true, "realized",
> > +                             &error_fatal);
> > +    sysbus_mmio_map(SYS_BUS_DEVICE(&chip->xics), 0, PNV_XICS_BASE);
> > +
> >      chip->cores = g_malloc0(typesize * chip->nr_cores);
> >  
> >      for (i = 0, core_hwid = 0; (core_hwid < sizeof(chip->cores_mask) * 8)
> >               && (i < chip->nr_cores); core_hwid++) {
> >          char core_name[32];
> >          void *pnv_core = chip->cores + i * typesize;
> > +        int j;
> >  
> >          if (!(chip->cores_mask & (1ull << core_hwid))) {
> >              continue;
> > @@ -690,6 +708,8 @@ static void pnv_chip_realize(DeviceState *dev, Error **errp)
> >          object_property_set_int(OBJECT(pnv_core),
> >                                  pcc->core_pir(chip, core_hwid),
> >                                  "pir", &error_fatal);
> > +        object_property_add_const_link(OBJECT(pnv_core), "xics",
> > +                                       OBJECT(&chip->xics), &error_fatal);
> >          object_property_set_bool(OBJECT(pnv_core), true, "realized",
> >                                   &error_fatal);
> >          object_unref(OBJECT(pnv_core));
> > @@ -697,6 +717,13 @@ static void pnv_chip_realize(DeviceState *dev, Error **errp)
> >          /* Each core has an XSCOM MMIO region */
> >          pnv_xscom_add_subregion(chip, PNV_XSCOM_EX_CORE_BASE(core_hwid),
> >                                  &PNV_CORE(pnv_core)->xscom_regs);
> > +
> > +        /* Each thread as region for its ICP */
> > +        for (j = 0; j < smp_threads; j++) {
> > +            memory_region_add_subregion(&chip->xics.icp_mmio,
> > +                                        pcc->core_pir(chip, core_hwid) << 12,
> 
> Pffut ... This should be :
> 
>                                           (pcc->core_pir(chip, core_hwid) + j) << 12,
> 
> but as smp_threads=1, it has no consequences for the moment. Tell me 
> how you would prefer me to fix this.

I think I have enough comments on the previous patch that a respin of
patches 11+ will make sense, so just fix it then.

> 
> Thanks,
> 
> C.
> 
> 
> > +                                        &chip->xics.icp_mmios[i]);
> > +        }
> >          i++;
> >      }
> >      g_free(typename);
> > diff --git a/hw/ppc/pnv_core.c b/hw/ppc/pnv_core.c
> > index 2acda9637db5..e15c76163759 100644
> > --- a/hw/ppc/pnv_core.c
> > +++ b/hw/ppc/pnv_core.c
> > @@ -24,6 +24,7 @@
> >  #include "hw/ppc/ppc.h"
> >  #include "hw/ppc/pnv.h"
> >  #include "hw/ppc/pnv_core.h"
> > +#include "hw/ppc/xics.h"
> >  
> >  static void powernv_cpu_reset(void *opaque)
> >  {
> > @@ -42,7 +43,7 @@ static void powernv_cpu_reset(void *opaque)
> >      env->msr |= MSR_HVB; /* Hypervisor mode */
> >  }
> >  
> > -static void powernv_cpu_init(PowerPCCPU *cpu, Error **errp)
> > +static void powernv_cpu_init(PowerPCCPU *cpu, XICSState *xics, Error **errp)
> >  {
> >      CPUPPCState *env = &cpu->env;
> >      int core_pir;
> > @@ -62,6 +63,11 @@ static void powernv_cpu_init(PowerPCCPU *cpu, Error **errp)
> >      cpu_ppc_tb_init(env, PNV_TIMEBASE_FREQ);
> >  
> >      qemu_register_reset(powernv_cpu_reset, cpu);
> > +
> > +    /*
> > +     * xics_cpu_setup() assigns the CPU to the ICP in XICS
> > +     */
> > +    xics_cpu_setup(xics, cpu);
> >  }
> >  
> >  /*
> > @@ -109,7 +115,7 @@ static const MemoryRegionOps pnv_core_xscom_ops = {
> >      .endianness = DEVICE_BIG_ENDIAN,
> >  };
> >  
> > -static void pnv_core_realize_child(Object *child, Error **errp)
> > +static void pnv_core_realize_child(Object *child, XICSState *xics, Error **errp)
> >  {
> >      Error *local_err = NULL;
> >      CPUState *cs = CPU(child);
> > @@ -121,7 +127,7 @@ static void pnv_core_realize_child(Object *child, Error **errp)
> >          return;
> >      }
> >  
> > -    powernv_cpu_init(cpu, &local_err);
> > +    powernv_cpu_init(cpu, xics, &local_err);
> >      if (local_err) {
> >          error_propagate(errp, local_err);
> >          return;
> > @@ -139,6 +145,7 @@ static void pnv_core_realize(DeviceState *dev, Error **errp)
> >      void *obj;
> >      int i, j;
> >      char name[32];
> > +    XICSState *xics;
> >  
> >      pc->threads = g_malloc0(size * cc->nr_threads);
> >      for (i = 0; i < cc->nr_threads; i++) {
> > @@ -156,10 +163,19 @@ static void pnv_core_realize(DeviceState *dev, Error **errp)
> >          object_unref(obj);
> >      }
> >  
> > +    /* get XICS object from chip */
> > +    obj = object_property_get_link(OBJECT(dev), "xics", &local_err);
> > +    if (!obj) {
> > +        error_setg(errp, "%s: required link 'xics' not found: %s",
> > +                   __func__, error_get_pretty(local_err));
> > +        return;
> > +    }
> > +    xics = XICS_COMMON(obj);
> > +
> >      for (j = 0; j < cc->nr_threads; j++) {
> >          obj = pc->threads + j * size;
> >  
> > -        pnv_core_realize_child(obj, &local_err);
> > +        pnv_core_realize_child(obj, xics, &local_err);
> >          if (local_err) {
> >              goto err;
> >          }
> > diff --git a/include/hw/ppc/pnv.h b/include/hw/ppc/pnv.h
> > index c08ed1c72b17..e11618b05f1d 100644
> > --- a/include/hw/ppc/pnv.h
> > +++ b/include/hw/ppc/pnv.h
> > @@ -23,6 +23,7 @@
> >  #include "hw/sysbus.h"
> >  #include "hw/ppc/pnv_xscom.h"
> >  #include "hw/ppc/pnv_lpc.h"
> > +#include "hw/ppc/xics.h"
> >  
> >  #define TYPE_PNV_CHIP "powernv-chip"
> >  #define PNV_CHIP(obj) OBJECT_CHECK(PnvChip, (obj), TYPE_PNV_CHIP)
> > @@ -57,6 +58,7 @@ typedef struct PnvChip {
> >      AddressSpace xscom_as;
> >  
> >      PnvLpcController lpc;
> > +    XICSNative   xics;
> >  } PnvChip;
> >  
> >  typedef struct PnvChipClass {
> > 
>
diff mbox

Patch

diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
index c6dc7ca895b6..16d7baf0da71 100644
--- a/hw/ppc/pnv.c
+++ b/hw/ppc/pnv.c
@@ -33,6 +33,7 @@ 
 #include "qemu/cutils.h"
 #include "qapi/visitor.h"
 
+#include "hw/ppc/xics.h"
 #include "hw/ppc/pnv_xscom.h"
 
 #include "hw/isa/isa.h"
@@ -231,6 +232,9 @@  static void powernv_populate_chip(PnvChip *chip, void *fdt)
         PnvCore *pnv_core = PNV_CORE(chip->cores + i * typesize);
 
         powernv_create_core_node(chip, pnv_core, fdt);
+
+        /* Interrupt presentation controllers (ICP). One per thread. */
+        xics_native_populate_icp(chip, fdt, 0, pnv_core->pir, smp_threads);
     }
 
     if (chip->ram_size) {
@@ -637,6 +641,9 @@  static void pnv_chip_init(Object *obj)
 
     object_initialize(&chip->lpc, sizeof(chip->lpc), TYPE_PNV_LPC);
     object_property_add_child(obj, "lpc", OBJECT(&chip->lpc), NULL);
+
+    object_initialize(&chip->xics, sizeof(chip->xics), TYPE_XICS_NATIVE);
+    object_property_add_child(obj, "xics", OBJECT(&chip->xics), NULL);
 }
 
 static void pnv_chip_realize(DeviceState *dev, Error **errp)
@@ -668,12 +675,23 @@  static void pnv_chip_realize(DeviceState *dev, Error **errp)
         return;
     }
 
+    /*
+     * Interrupt Controller. To be created before the cores because
+     * each thread will fetch its ICP in the XICS
+     */
+    object_property_set_int(OBJECT(&chip->xics), chip->nr_cores * smp_threads,
+                            "nr_servers",  &error_fatal);
+    object_property_set_bool(OBJECT(&chip->xics), true, "realized",
+                             &error_fatal);
+    sysbus_mmio_map(SYS_BUS_DEVICE(&chip->xics), 0, PNV_XICS_BASE);
+
     chip->cores = g_malloc0(typesize * chip->nr_cores);
 
     for (i = 0, core_hwid = 0; (core_hwid < sizeof(chip->cores_mask) * 8)
              && (i < chip->nr_cores); core_hwid++) {
         char core_name[32];
         void *pnv_core = chip->cores + i * typesize;
+        int j;
 
         if (!(chip->cores_mask & (1ull << core_hwid))) {
             continue;
@@ -690,6 +708,8 @@  static void pnv_chip_realize(DeviceState *dev, Error **errp)
         object_property_set_int(OBJECT(pnv_core),
                                 pcc->core_pir(chip, core_hwid),
                                 "pir", &error_fatal);
+        object_property_add_const_link(OBJECT(pnv_core), "xics",
+                                       OBJECT(&chip->xics), &error_fatal);
         object_property_set_bool(OBJECT(pnv_core), true, "realized",
                                  &error_fatal);
         object_unref(OBJECT(pnv_core));
@@ -697,6 +717,13 @@  static void pnv_chip_realize(DeviceState *dev, Error **errp)
         /* Each core has an XSCOM MMIO region */
         pnv_xscom_add_subregion(chip, PNV_XSCOM_EX_CORE_BASE(core_hwid),
                                 &PNV_CORE(pnv_core)->xscom_regs);
+
+        /* Each thread as region for its ICP */
+        for (j = 0; j < smp_threads; j++) {
+            memory_region_add_subregion(&chip->xics.icp_mmio,
+                                        pcc->core_pir(chip, core_hwid) << 12,
+                                        &chip->xics.icp_mmios[i]);
+        }
         i++;
     }
     g_free(typename);
diff --git a/hw/ppc/pnv_core.c b/hw/ppc/pnv_core.c
index 2acda9637db5..e15c76163759 100644
--- a/hw/ppc/pnv_core.c
+++ b/hw/ppc/pnv_core.c
@@ -24,6 +24,7 @@ 
 #include "hw/ppc/ppc.h"
 #include "hw/ppc/pnv.h"
 #include "hw/ppc/pnv_core.h"
+#include "hw/ppc/xics.h"
 
 static void powernv_cpu_reset(void *opaque)
 {
@@ -42,7 +43,7 @@  static void powernv_cpu_reset(void *opaque)
     env->msr |= MSR_HVB; /* Hypervisor mode */
 }
 
-static void powernv_cpu_init(PowerPCCPU *cpu, Error **errp)
+static void powernv_cpu_init(PowerPCCPU *cpu, XICSState *xics, Error **errp)
 {
     CPUPPCState *env = &cpu->env;
     int core_pir;
@@ -62,6 +63,11 @@  static void powernv_cpu_init(PowerPCCPU *cpu, Error **errp)
     cpu_ppc_tb_init(env, PNV_TIMEBASE_FREQ);
 
     qemu_register_reset(powernv_cpu_reset, cpu);
+
+    /*
+     * xics_cpu_setup() assigns the CPU to the ICP in XICS
+     */
+    xics_cpu_setup(xics, cpu);
 }
 
 /*
@@ -109,7 +115,7 @@  static const MemoryRegionOps pnv_core_xscom_ops = {
     .endianness = DEVICE_BIG_ENDIAN,
 };
 
-static void pnv_core_realize_child(Object *child, Error **errp)
+static void pnv_core_realize_child(Object *child, XICSState *xics, Error **errp)
 {
     Error *local_err = NULL;
     CPUState *cs = CPU(child);
@@ -121,7 +127,7 @@  static void pnv_core_realize_child(Object *child, Error **errp)
         return;
     }
 
-    powernv_cpu_init(cpu, &local_err);
+    powernv_cpu_init(cpu, xics, &local_err);
     if (local_err) {
         error_propagate(errp, local_err);
         return;
@@ -139,6 +145,7 @@  static void pnv_core_realize(DeviceState *dev, Error **errp)
     void *obj;
     int i, j;
     char name[32];
+    XICSState *xics;
 
     pc->threads = g_malloc0(size * cc->nr_threads);
     for (i = 0; i < cc->nr_threads; i++) {
@@ -156,10 +163,19 @@  static void pnv_core_realize(DeviceState *dev, Error **errp)
         object_unref(obj);
     }
 
+    /* get XICS object from chip */
+    obj = object_property_get_link(OBJECT(dev), "xics", &local_err);
+    if (!obj) {
+        error_setg(errp, "%s: required link 'xics' not found: %s",
+                   __func__, error_get_pretty(local_err));
+        return;
+    }
+    xics = XICS_COMMON(obj);
+
     for (j = 0; j < cc->nr_threads; j++) {
         obj = pc->threads + j * size;
 
-        pnv_core_realize_child(obj, &local_err);
+        pnv_core_realize_child(obj, xics, &local_err);
         if (local_err) {
             goto err;
         }
diff --git a/include/hw/ppc/pnv.h b/include/hw/ppc/pnv.h
index c08ed1c72b17..e11618b05f1d 100644
--- a/include/hw/ppc/pnv.h
+++ b/include/hw/ppc/pnv.h
@@ -23,6 +23,7 @@ 
 #include "hw/sysbus.h"
 #include "hw/ppc/pnv_xscom.h"
 #include "hw/ppc/pnv_lpc.h"
+#include "hw/ppc/xics.h"
 
 #define TYPE_PNV_CHIP "powernv-chip"
 #define PNV_CHIP(obj) OBJECT_CHECK(PnvChip, (obj), TYPE_PNV_CHIP)
@@ -57,6 +58,7 @@  typedef struct PnvChip {
     AddressSpace xscom_as;
 
     PnvLpcController lpc;
+    XICSNative   xics;
 } PnvChip;
 
 typedef struct PnvChipClass {