[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PULL 26/48] ppc/pnv: add memory regions for the ICP regist
From: |
David Gibson |
Subject: |
[Qemu-devel] [PULL 26/48] ppc/pnv: add memory regions for the ICP registers |
Date: |
Wed, 26 Apr 2017 17:00:12 +1000 |
From: Cédric Le Goater <address@hidden>
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>
Signed-off-by: David Gibson <address@hidden>
---
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 2add2ad..1fa90d6 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) {
@@ -643,6 +684,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);
@@ -713,6 +786,14 @@ static void pnv_chip_realize(DeviceState *dev, Error
**errp)
object_property_set_bool(OBJECT(&chip->lpc), true, "realized",
&error_fatal);
pnv_xscom_add_subregion(chip, PNV_XSCOM_LPC_BASE, &chip->lpc.xscom_regs);
+
+ /* 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;
+ }
}
static Property pnv_chip_properties[] = {
diff --git a/include/hw/ppc/pnv.h b/include/hw/ppc/pnv.h
index 5693ba1..96231c1 100644
--- a/include/hw/ppc/pnv.h
+++ b/include/hw/ppc/pnv.h
@@ -54,6 +54,7 @@ typedef struct PnvChip {
MemoryRegion xscom_mmio;
MemoryRegion xscom;
AddressSpace xscom_as;
+ MemoryRegion icp_mmio;
PnvLpcController lpc;
} PnvChip;
@@ -136,4 +137,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 */
--
2.9.3
- [Qemu-devel] [PULL 23/48] ppc/pnv: extend the machine with a InterruptStatsProvider interface, (continued)
- [Qemu-devel] [PULL 23/48] ppc/pnv: extend the machine with a InterruptStatsProvider interface, David Gibson, 2017/04/26
- [Qemu-devel] [PULL 22/48] ppc/pnv: extend the machine with a XICSFabric interface, David Gibson, 2017/04/26
- [Qemu-devel] [PULL 19/48] spapr: allocate the ICPState object from under sPAPRCPUCore, David Gibson, 2017/04/26
- [Qemu-devel] [PULL 10/48] spapr: move spapr_populate_pa_features(), David Gibson, 2017/04/26
- [Qemu-devel] [PULL 15/48] spapr_pci: Removed unused include, David Gibson, 2017/04/26
- [Qemu-devel] [PULL 25/48] ppc/pnv: add a helper to calculate MMIO addresses registers, David Gibson, 2017/04/26
- [Qemu-devel] [PULL 33/48] ipmi: introduce an ipmi_bmc_gen_event() API, David Gibson, 2017/04/26
- [Qemu-devel] [PULL 12/48] spapr: Workaround for broken radix guests, David Gibson, 2017/04/26
- [Qemu-devel] [PULL 24/48] ppc/pnv: create the ICP object under PnvCore, David Gibson, 2017/04/26
- [Qemu-devel] [PULL 21/48] ppc/pnv: add a PnvICPState object, David Gibson, 2017/04/26
- [Qemu-devel] [PULL 26/48] ppc/pnv: add memory regions for the ICP registers,
David Gibson <=
- [Qemu-devel] [PULL 30/48] ipmi: use a file to load SDRs, David Gibson, 2017/04/26
- [Qemu-devel] [PULL 31/48] ipmi: provide support for FRUs, David Gibson, 2017/04/26
- [Qemu-devel] [PULL 39/48] ppc/pnv: populate device tree for RTC devices, David Gibson, 2017/04/26
- [Qemu-devel] [PULL 28/48] ppc/pnv: Add OCC model stub with interrupt support, David Gibson, 2017/04/26
- [Qemu-devel] [PULL 41/48] ppc/pnv: populate device tree for IPMI BT devices, David Gibson, 2017/04/26
- [Qemu-devel] [PULL 29/48] ppc: add IPMI support, David Gibson, 2017/04/26
- [Qemu-devel] [PULL 35/48] spapr: remove the 'nr_servers' field from the machine, David Gibson, 2017/04/26
- [Qemu-devel] [PULL 36/48] ppc/pnv: Add support for POWER8+ LPC Controller, David Gibson, 2017/04/26
- [Qemu-devel] [PULL 34/48] target/ppc: Fix size of struct PPCElfPrstatus, David Gibson, 2017/04/26
- [Qemu-devel] [PULL 38/48] ppc/pnv: scan ISA bus to populate device tree, David Gibson, 2017/04/26