qemu-ppc
[Top][All Lists]
Advanced

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

[Qemu-ppc] [PATCH v5 12/17] ppc/pnv: add a XICS native to each PowerNV c


From: Cédric Le Goater
Subject: [Qemu-ppc] [PATCH v5 12/17] ppc/pnv: add a XICS native to each PowerNV chip
Date: Sat, 22 Oct 2016 11:46:45 +0200

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 <address@hidden>
---

 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,
+                                        &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 {
-- 
2.7.4




reply via email to

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