qemu-ppc
[Top][All Lists]
Advanced

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

[Qemu-ppc] [PATCH for-2.10 5/8] ppc/pnv: map the ICP memory regions


From: Cédric Le Goater
Subject: [Qemu-ppc] [PATCH for-2.10 5/8] ppc/pnv: map the ICP memory regions
Date: Wed, 8 Mar 2017 11:52:48 +0100

and populate the device tree accordingly for the guest to start using
interrupts. This also links the ICP object to its associated CPUState
(only used by KVM to control the kernel vCPU).

Signed-off-by: Cédric Le Goater <address@hidden>
---
 hw/ppc/pnv.c      | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 hw/ppc/pnv_core.c | 12 ++++++++----
 2 files changed, 63 insertions(+), 4 deletions(-)

diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
index 7b13b08deadf..0ae11cc3a2ca 100644
--- a/hw/ppc/pnv.c
+++ b/hw/ppc/pnv.c
@@ -35,6 +35,7 @@
 #include "monitor/monitor.h"
 #include "hw/intc/intc.h"
 
+#include "hw/ppc/xics.h"
 #include "hw/ppc/pnv_xscom.h"
 
 #include "hw/isa/isa.h"
@@ -216,6 +217,47 @@ static void powernv_create_core_node(PnvChip *chip, 
PnvCore *pc, void *fdt)
                        servers_prop, sizeof(servers_prop))));
 }
 
+static void powernv_populate_icp(PnvChip *chip, void *fdt, int offset,
+                          uint32_t pir, uint32_t count)
+{
+    uint64_t addr;
+    char *name;
+    const char compat[] = "IBM,power8-icp\0IBM,ppc-xicp";
+    uint32_t irange[2], i, rsize;
+    uint64_t *reg;
+
+    /*
+     * TODO: add multichip ICP BAR
+     */
+    addr = PNV_ICP_BASE(chip) | (pir << 12);
+
+    irange[0] = cpu_to_be32(pir);
+    irange[1] = cpu_to_be32(count);
+
+    rsize = sizeof(uint64_t) * 2 * count;
+    reg = g_malloc(rsize);
+    for (i = 0; i < count; i++) {
+        reg[i * 2] = cpu_to_be64(addr | ((pir + i) * 0x1000));
+        reg[i * 2 + 1] = cpu_to_be64(0x1000);
+    }
+
+    name = g_strdup_printf("address@hidden"PRIX64, addr);
+    offset = fdt_add_subnode(fdt, offset, name);
+    _FDT(offset);
+    g_free(name);
+
+    _FDT((fdt_setprop(fdt, offset, "compatible", compat, sizeof(compat))));
+    _FDT((fdt_setprop(fdt, offset, "reg", reg, rsize)));
+    _FDT((fdt_setprop_string(fdt, offset, "device_type",
+                              "PowerPC-External-Interrupt-Presentation")));
+    _FDT((fdt_setprop(fdt, offset, "interrupt-controller", NULL, 0)));
+    _FDT((fdt_setprop(fdt, offset, "ibm,interrupt-server-ranges",
+                       irange, sizeof(irange))));
+    _FDT((fdt_setprop_cell(fdt, offset, "#interrupt-cells", 1)));
+    _FDT((fdt_setprop_cell(fdt, offset, "#address-cells", 0)));
+    g_free(reg);
+}
+
 static void powernv_populate_chip(PnvChip *chip, void *fdt)
 {
     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
@@ -229,6 +271,10 @@ 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 Control Presenters (ICP). One per thread. */
+        powernv_populate_icp(chip, fdt, 0, pnv_core->pir,
+                             CPU_CORE(pnv_core)->nr_threads);
     }
 
     if (chip->ram_size) {
@@ -697,6 +743,7 @@ static void pnv_chip_realize(DeviceState *dev, Error **errp)
         error_propagate(errp, error);
         return;
     }
+    sysbus_mmio_map(SYS_BUS_DEVICE(chip), 1, PNV_ICP_BASE(chip));
 
     /* Cores */
     pnv_chip_core_sanitize(chip, &error);
@@ -711,6 +758,7 @@ static void pnv_chip_realize(DeviceState *dev, Error **errp)
              && (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;
@@ -738,6 +786,13 @@ static void pnv_chip_realize(DeviceState *dev, Error 
**errp)
                                 PNV_XSCOM_EX_CORE_BASE(pcc->xscom_core_base,
                                                        core_hwid),
                                 &PNV_CORE(pnv_core)->xscom_regs);
+
+        /* Map the ICP registers for each thread */
+        for (j = 0; j < CPU_CORE(pnv_core)->nr_threads; j++) {
+            memory_region_add_subregion(&chip->icp_mmio,
+                                 (pcc->core_pir(chip, core_hwid) + j) << 12,
+                                  &PNV_CORE(pnv_core)->icp_mmios[j]);
+        }
         i++;
     }
     g_free(typename);
diff --git a/hw/ppc/pnv_core.c b/hw/ppc/pnv_core.c
index 8633afbff795..d28fa445b11b 100644
--- a/hw/ppc/pnv_core.c
+++ b/hw/ppc/pnv_core.c
@@ -25,6 +25,7 @@
 #include "hw/ppc/pnv.h"
 #include "hw/ppc/pnv_core.h"
 #include "hw/ppc/pnv_xscom.h"
+#include "hw/ppc/xics.h"
 
 static uint64_t pnv_core_icp_read(void *opaque, hwaddr addr, unsigned width)
 {
@@ -165,7 +166,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, XICSFabric *xi, Error **errp)
 {
     CPUPPCState *env = &cpu->env;
     int core_pir;
@@ -185,6 +186,9 @@ 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 ICPState */
+    xics_cpu_setup(xi, cpu);
 }
 
 /*
@@ -232,7 +236,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, XICSFabric *xi, Error **errp)
 {
     Error *local_err = NULL;
     CPUState *cs = CPU(child);
@@ -244,7 +248,7 @@ static void pnv_core_realize_child(Object *child, Error 
**errp)
         return;
     }
 
-    powernv_cpu_init(cpu, &local_err);
+    powernv_cpu_init(cpu, xi, &local_err);
     if (local_err) {
         error_propagate(errp, local_err);
         return;
@@ -298,7 +302,7 @@ static void pnv_core_realize(DeviceState *dev, Error **errp)
     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_FABRIC(xi), &local_err);
         if (local_err) {
             goto err;
         }
-- 
2.7.4




reply via email to

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