diff mbox

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

Message ID 1488970371-8865-6-git-send-email-clg@kaod.org
State New
Headers show

Commit Message

Cédric Le Goater March 8, 2017, 10:52 a.m. UTC
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 <clg@kaod.org>
---
 hw/ppc/pnv.c      | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 hw/ppc/pnv_core.c | 12 ++++++++----
 2 files changed, 63 insertions(+), 4 deletions(-)

Comments

David Gibson March 14, 2017, 5:52 a.m. UTC | #1
On Wed, Mar 08, 2017 at 11:52:48AM +0100, Cédric Le Goater wrote:
> 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 <clg@kaod.org>
> ---
>  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("interrupt-controller@%"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,

All the xicp nodes under the root bus, is that correct?

> +                             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;
>          }
Cédric Le Goater March 14, 2017, 10:02 a.m. UTC | #2
On 03/14/2017 06:52 AM, David Gibson wrote:
> On Wed, Mar 08, 2017 at 11:52:48AM +0100, Cédric Le Goater wrote:
>> 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 <clg@kaod.org>
>> ---
>>  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("interrupt-controller@%"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,
> 
> All the xicp nodes under the root bus, is that correct?

yes. The '0' parameter feels useless there.

C. 


> 
>> +                             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;
>>          }
>
diff mbox

Patch

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("interrupt-controller@%"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;
         }