[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PATCH v2 8/8] ppc/pnv: add memory regions for the ICP
From: |
David Gibson |
Subject: |
Re: [Qemu-devel] [PATCH v2 8/8] ppc/pnv: add memory regions for the ICP registers |
Date: |
Thu, 23 Mar 2017 15:20:15 +1100 |
User-agent: |
Mutt/1.8.0 (2017-02-23) |
On Thu, Mar 16, 2017 at 03:35:12PM +0100, Cédric Le Goater wrote:
> This provides to a PowerNV chip (POWER8) access to the Interrupt
> Management area, which contains the registers of the Interrupt Control
> Presenters of each thread. These are used to accept, return, forward
> interrupts in the system.
>
> This area is modeled with a per-chip container memory region holding
> all the ICP registers. Each thread of a chip is then associated with
> its ICP registers using a memory subregion indexed by its PIR number
> in the overall region.
>
> The device tree is populated accordingly.
>
> Signed-off-by: Cédric Le Goater <address@hidden>
Reviewed-by: David Gibson <address@hidden>
> ---
>
> Changes since v1:
>
> - added multichip support
> - adapted to use PnvICPState object
>
> hw/ppc/pnv.c | 81
> ++++++++++++++++++++++++++++++++++++++++++++++++++++
> include/hw/ppc/pnv.h | 19 ++++++++++++
> 2 files changed, 100 insertions(+)
>
> diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
> index 9c239932fb3a..f91e16955fa8 100644
> --- a/hw/ppc/pnv.c
> +++ b/hw/ppc/pnv.c
> @@ -218,6 +218,43 @@ 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, uint32_t pir,
> + uint32_t nr_threads)
> +{
> + uint64_t addr = PNV_ICP_BASE(chip) | (pir << 12);
> + char *name;
> + const char compat[] = "IBM,power8-icp\0IBM,ppc-xicp";
> + uint32_t irange[2], i, rsize;
> + uint64_t *reg;
> + int offset;
> +
> + irange[0] = cpu_to_be32(pir);
> + irange[1] = cpu_to_be32(nr_threads);
> +
> + rsize = sizeof(uint64_t) * 2 * nr_threads;
> + reg = g_malloc(rsize);
> + for (i = 0; i < nr_threads; 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, 0, 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);
> @@ -231,6 +268,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 core. */
> + powernv_populate_icp(chip, fdt, pnv_core->pir,
> + CPU_CORE(pnv_core)->nr_threads);
> }
>
> if (chip->ram_size) {
> @@ -663,6 +704,38 @@ static void pnv_chip_init(Object *obj)
> object_property_add_child(obj, "lpc", OBJECT(&chip->lpc), NULL);
> }
>
> +static void pnv_chip_icp_realize(PnvChip *chip, Error **errp)
> +{
> + PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
> + char *typename = pnv_core_typename(pcc->cpu_model);
> + size_t typesize = object_type_get_instance_size(typename);
> + int i, j;
> + char *name;
> + XICSFabric *xi = XICS_FABRIC(qdev_get_machine());
> +
> + name = g_strdup_printf("icp-%x", chip->chip_id);
> + memory_region_init(&chip->icp_mmio, OBJECT(chip), name, PNV_ICP_SIZE);
> + sysbus_init_mmio(SYS_BUS_DEVICE(chip), &chip->icp_mmio);
> + g_free(name);
> +
> + sysbus_mmio_map(SYS_BUS_DEVICE(chip), 1, PNV_ICP_BASE(chip));
> +
> + /* Map the ICP registers for each thread */
> + for (i = 0; i < chip->nr_cores; i++) {
> + PnvCore *pnv_core = PNV_CORE(chip->cores + i * typesize);
> + int core_hwid = CPU_CORE(pnv_core)->core_id;
> +
> + for (j = 0; j < CPU_CORE(pnv_core)->nr_threads; j++) {
> + uint32_t pir = pcc->core_pir(chip, core_hwid) + j;
> + PnvICPState *icp = PNV_ICP(xics_icp_get(xi, pir));
> +
> + memory_region_add_subregion(&chip->icp_mmio, pir << 12,
> &icp->mmio);
> + }
> + }
> +
> + g_free(typename);
> +}
> +
> static void pnv_chip_realize(DeviceState *dev, Error **errp)
> {
> PnvChip *chip = PNV_CHIP(dev);
> @@ -729,6 +802,14 @@ static void pnv_chip_realize(DeviceState *dev, Error
> **errp)
> }
> g_free(typename);
>
> + /* Interrupt Management Area. This is the memory region holding
> + * all the Interrupt Control Presenter (ICP) registers */
> + pnv_chip_icp_realize(chip, &error);
> + if (error) {
> + error_propagate(errp, error);
> + return;
> + }
> +
> /* Create LPC controller */
> object_property_set_bool(OBJECT(&chip->lpc), true, "realized",
> &error_fatal);
> diff --git a/include/hw/ppc/pnv.h b/include/hw/ppc/pnv.h
> index cfd059fc49db..8e8ca548967d 100644
> --- a/include/hw/ppc/pnv.h
> +++ b/include/hw/ppc/pnv.h
> @@ -55,6 +55,7 @@ typedef struct PnvChip {
> MemoryRegion xscom_mmio;
> MemoryRegion xscom;
> AddressSpace xscom_as;
> + MemoryRegion icp_mmio;
>
> PnvLpcController lpc;
> } PnvChip;
> @@ -140,4 +141,22 @@ typedef struct PnvMachineState {
> #define PNV_XSCOM_BASE(chip) \
> (chip->xscom_base + ((uint64_t)(chip)->chip_id) * PNV_XSCOM_SIZE)
>
> +/*
> + * XSCOM 0x20109CA defines the ICP BAR:
> + *
> + * 0:29 : bits 14 to 43 of address to define 1 MB region.
> + * 30 : 1 to enable ICP to receive loads/stores against its BAR region
> + * 31:63 : Constant 0
> + *
> + * Usually defined as :
> + *
> + * 0xffffe00200000000 -> 0x0003ffff80000000
> + * 0xffffe00600000000 -> 0x0003ffff80100000
> + * 0xffffe02200000000 -> 0x0003ffff80800000
> + * 0xffffe02600000000 -> 0x0003ffff80900000
> + */
> +#define PNV_ICP_SIZE 0x0000000000100000ull
> +#define PNV_ICP_BASE(chip) \
> + (0x0003ffff80000000ull + (uint64_t) PNV_CHIP_INDEX(chip) * PNV_ICP_SIZE)
> +
> #endif /* _PPC_PNV_H */
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
signature.asc
Description: PGP signature
- [Qemu-devel] [PATCH v2 4/8] ppc/pnv: add a PnvICPState object, (continued)
- [Qemu-devel] [PATCH v2 4/8] ppc/pnv: add a PnvICPState object, Cédric Le Goater, 2017/03/16
- [Qemu-devel] [PATCH v2 5/8] ppc/pnv: create the ICP and ICS objects under the machine, Cédric Le Goater, 2017/03/16
- [Qemu-devel] [PATCH v2 6/8] ppc/pnv: add a helper to calculate MMIO addresses registers, Cédric Le Goater, 2017/03/16
- [Qemu-devel] [PATCH v2 7/8] ppc/pnv: link the CPUs to the machine XICSFabric, Cédric Le Goater, 2017/03/16
- [Qemu-devel] [PATCH v2 8/8] ppc/pnv: add memory regions for the ICP registers, Cédric Le Goater, 2017/03/16
- Re: [Qemu-devel] [PATCH v2 8/8] ppc/pnv: add memory regions for the ICP registers,
David Gibson <=