[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-ppc] [PATCH 05/23] ppc/pnv: introduce Pnv8Chip and Pnv9Chip models
From: |
David Gibson |
Subject: |
[Qemu-ppc] [PATCH 05/23] ppc/pnv: introduce Pnv8Chip and Pnv9Chip models |
Date: |
Fri, 22 Jun 2018 14:24:19 +1000 |
From: Cédric Le Goater <address@hidden>
It introduces a base PnvChip class from which the specific processor
chip classes, Pnv8Chip and Pnv9Chip, inherit. Each of them needs to
define an init and a realize routine which will create the controllers
of the target processor. For the moment, the base PnvChip class
handles the XSCOM bus and the cores.
Signed-off-by: Cédric Le Goater <address@hidden>
Signed-off-by: David Gibson <address@hidden>
---
hw/ppc/pnv.c | 281 +++++++++++++++++++++++++++----------------
include/hw/ppc/pnv.h | 24 +++-
2 files changed, 202 insertions(+), 103 deletions(-)
diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
index ac828d1331..a29ea996b4 100644
--- a/hw/ppc/pnv.c
+++ b/hw/ppc/pnv.c
@@ -531,12 +531,14 @@ static void pnv_reset(void)
static ISABus *pnv_chip_power8_isa_create(PnvChip *chip, Error **errp)
{
- return pnv_lpc_isa_create(&chip->lpc, true, errp);
+ Pnv8Chip *chip8 = PNV8_CHIP(chip);
+ return pnv_lpc_isa_create(&chip8->lpc, true, errp);
}
static ISABus *pnv_chip_power8nvl_isa_create(PnvChip *chip, Error **errp)
{
- return pnv_lpc_isa_create(&chip->lpc, false, errp);
+ Pnv8Chip *chip8 = PNV8_CHIP(chip);
+ return pnv_lpc_isa_create(&chip8->lpc, false, errp);
}
static ISABus *pnv_chip_power9_isa_create(PnvChip *chip, Error **errp)
@@ -725,6 +727,103 @@ static Object *pnv_chip_power9_intc_create(PnvChip *chip,
Object *child,
*/
#define POWER9_CORE_MASK (0xffffffffffffffull)
+static void pnv_chip_power8_instance_init(Object *obj)
+{
+ Pnv8Chip *chip8 = PNV8_CHIP(obj);
+
+ object_initialize(&chip8->psi, sizeof(chip8->psi), TYPE_PNV_PSI);
+ object_property_add_child(obj, "psi", OBJECT(&chip8->psi), NULL);
+ object_property_add_const_link(OBJECT(&chip8->psi), "xics",
+ OBJECT(qdev_get_machine()), &error_abort);
+
+ object_initialize(&chip8->lpc, sizeof(chip8->lpc), TYPE_PNV_LPC);
+ object_property_add_child(obj, "lpc", OBJECT(&chip8->lpc), NULL);
+ object_property_add_const_link(OBJECT(&chip8->lpc), "psi",
+ OBJECT(&chip8->psi), &error_abort);
+
+ object_initialize(&chip8->occ, sizeof(chip8->occ), TYPE_PNV_OCC);
+ object_property_add_child(obj, "occ", OBJECT(&chip8->occ), NULL);
+ object_property_add_const_link(OBJECT(&chip8->occ), "psi",
+ OBJECT(&chip8->psi), &error_abort);
+}
+
+static void pnv_chip_icp_realize(Pnv8Chip *chip8, Error **errp)
+ {
+ PnvChip *chip = PNV_CHIP(chip8);
+ PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
+ const char *typename = pnv_chip_core_typename(chip);
+ 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(&chip8->icp_mmio, OBJECT(chip), name, PNV_ICP_SIZE);
+ sysbus_init_mmio(SYS_BUS_DEVICE(chip), &chip8->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(&chip8->icp_mmio, pir << 12,
+ &icp->mmio);
+ }
+ }
+}
+
+static void pnv_chip_power8_realize(DeviceState *dev, Error **errp)
+{
+ PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev);
+ PnvChip *chip = PNV_CHIP(dev);
+ Pnv8Chip *chip8 = PNV8_CHIP(dev);
+ Error *local_err = NULL;
+
+ pcc->parent_realize(dev, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ return;
+ }
+
+ /* Processor Service Interface (PSI) Host Bridge */
+ object_property_set_int(OBJECT(&chip8->psi), PNV_PSIHB_BASE(chip),
+ "bar", &error_fatal);
+ object_property_set_bool(OBJECT(&chip8->psi), true, "realized",
&local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ return;
+ }
+ pnv_xscom_add_subregion(chip, PNV_XSCOM_PSIHB_BASE,
&chip8->psi.xscom_regs);
+
+ /* Create LPC controller */
+ object_property_set_bool(OBJECT(&chip8->lpc), true, "realized",
+ &error_fatal);
+ pnv_xscom_add_subregion(chip, PNV_XSCOM_LPC_BASE, &chip8->lpc.xscom_regs);
+
+ /* Interrupt Management Area. This is the memory region holding
+ * all the Interrupt Control Presenter (ICP) registers */
+ pnv_chip_icp_realize(chip8, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ return;
+ }
+
+ /* Create the simplified OCC model */
+ object_property_set_bool(OBJECT(&chip8->occ), true, "realized",
&local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ return;
+ }
+ pnv_xscom_add_subregion(chip, PNV_XSCOM_OCC_BASE, &chip8->occ.xscom_regs);
+}
+
static void pnv_chip_power8e_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
@@ -738,6 +837,9 @@ static void pnv_chip_power8e_class_init(ObjectClass *klass,
void *data)
k->isa_create = pnv_chip_power8_isa_create;
k->xscom_base = 0x003fc0000000000ull;
dc->desc = "PowerNV Chip POWER8E";
+
+ device_class_set_parent_realize(dc, pnv_chip_power8_realize,
+ &k->parent_realize);
}
static void pnv_chip_power8_class_init(ObjectClass *klass, void *data)
@@ -753,6 +855,9 @@ static void pnv_chip_power8_class_init(ObjectClass *klass,
void *data)
k->isa_create = pnv_chip_power8_isa_create;
k->xscom_base = 0x003fc0000000000ull;
dc->desc = "PowerNV Chip POWER8";
+
+ device_class_set_parent_realize(dc, pnv_chip_power8_realize,
+ &k->parent_realize);
}
static void pnv_chip_power8nvl_class_init(ObjectClass *klass, void *data)
@@ -768,6 +873,25 @@ static void pnv_chip_power8nvl_class_init(ObjectClass
*klass, void *data)
k->isa_create = pnv_chip_power8nvl_isa_create;
k->xscom_base = 0x003fc0000000000ull;
dc->desc = "PowerNV Chip POWER8NVL";
+
+ device_class_set_parent_realize(dc, pnv_chip_power8_realize,
+ &k->parent_realize);
+}
+
+static void pnv_chip_power9_instance_init(Object *obj)
+{
+}
+
+static void pnv_chip_power9_realize(DeviceState *dev, Error **errp)
+{
+ PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev);
+ Error *local_err = NULL;
+
+ pcc->parent_realize(dev, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ return;
+ }
}
static void pnv_chip_power9_class_init(ObjectClass *klass, void *data)
@@ -783,6 +907,9 @@ static void pnv_chip_power9_class_init(ObjectClass *klass,
void *data)
k->isa_create = pnv_chip_power9_isa_create;
k->xscom_base = 0x00603fc00000000ull;
dc->desc = "PowerNV Chip POWER9";
+
+ device_class_set_parent_realize(dc, pnv_chip_power9_realize,
+ &k->parent_realize);
}
static void pnv_chip_core_sanitize(PnvChip *chip, Error **errp)
@@ -815,59 +942,9 @@ static void pnv_chip_core_sanitize(PnvChip *chip, Error
**errp)
}
}
-static void pnv_chip_init(Object *obj)
+static void pnv_chip_instance_init(Object *obj)
{
- PnvChip *chip = PNV_CHIP(obj);
- PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
-
- chip->xscom_base = pcc->xscom_base;
-
- object_initialize(&chip->lpc, sizeof(chip->lpc), TYPE_PNV_LPC);
- object_property_add_child(obj, "lpc", OBJECT(&chip->lpc), NULL);
-
- object_initialize(&chip->psi, sizeof(chip->psi), TYPE_PNV_PSI);
- object_property_add_child(obj, "psi", OBJECT(&chip->psi), NULL);
- object_property_add_const_link(OBJECT(&chip->psi), "xics",
- OBJECT(qdev_get_machine()), &error_abort);
-
- object_initialize(&chip->occ, sizeof(chip->occ), TYPE_PNV_OCC);
- object_property_add_child(obj, "occ", OBJECT(&chip->occ), NULL);
- object_property_add_const_link(OBJECT(&chip->occ), "psi",
- OBJECT(&chip->psi), &error_abort);
-
- /* The LPC controller needs PSI to generate interrupts */
- object_property_add_const_link(OBJECT(&chip->lpc), "psi",
- OBJECT(&chip->psi), &error_abort);
-}
-
-static void pnv_chip_icp_realize(PnvChip *chip, Error **errp)
-{
- PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
- const char *typename = pnv_chip_core_typename(chip);
- 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);
- }
- }
+ PNV_CHIP(obj)->xscom_base = PNV_CHIP_GET_CLASS(obj)->xscom_base;
}
static void pnv_chip_core_realize(PnvChip *chip, Error **errp)
@@ -951,37 +1028,6 @@ static void pnv_chip_realize(DeviceState *dev, Error
**errp)
error_propagate(errp, error);
return;
}
-
- /* Create LPC controller */
- 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;
- }
-
- /* Processor Service Interface (PSI) Host Bridge */
- object_property_set_int(OBJECT(&chip->psi), PNV_PSIHB_BASE(chip),
- "bar", &error_fatal);
- object_property_set_bool(OBJECT(&chip->psi), true, "realized", &error);
- if (error) {
- error_propagate(errp, error);
- return;
- }
- pnv_xscom_add_subregion(chip, PNV_XSCOM_PSIHB_BASE, &chip->psi.xscom_regs);
-
- /* Create the simplified OCC model */
- object_property_set_bool(OBJECT(&chip->occ), true, "realized", &error);
- if (error) {
- error_propagate(errp, error);
- return;
- }
- pnv_xscom_add_subregion(chip, PNV_XSCOM_OCC_BASE, &chip->occ.xscom_regs);
}
static Property pnv_chip_properties[] = {
@@ -1009,8 +1055,10 @@ static ICSState *pnv_ics_get(XICSFabric *xi, int irq)
int i;
for (i = 0; i < pnv->num_chips; i++) {
- if (ics_valid_irq(&pnv->chips[i]->psi.ics, irq)) {
- return &pnv->chips[i]->psi.ics;
+ Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]);
+
+ if (ics_valid_irq(&chip8->psi.ics, irq)) {
+ return &chip8->psi.ics;
}
}
return NULL;
@@ -1022,7 +1070,8 @@ static void pnv_ics_resend(XICSFabric *xi)
int i;
for (i = 0; i < pnv->num_chips; i++) {
- ics_resend(&pnv->chips[i]->psi.ics);
+ Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]);
+ ics_resend(&chip8->psi.ics);
}
}
@@ -1063,7 +1112,8 @@ static void pnv_pic_print_info(InterruptStatsProvider
*obj,
}
for (i = 0; i < pnv->num_chips; i++) {
- ics_pic_print_info(&pnv->chips[i]->psi.ics, mon);
+ Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]);
+ ics_pic_print_info(&chip8->psi.ics, mon);
}
}
@@ -1098,7 +1148,7 @@ static void pnv_set_num_chips(Object *obj, Visitor *v,
const char *name,
pnv->num_chips = num_chips;
}
-static void pnv_machine_initfn(Object *obj)
+static void pnv_machine_instance_init(Object *obj)
{
PnvMachineState *pnv = PNV_MACHINE(obj);
pnv->num_chips = 1;
@@ -1138,11 +1188,18 @@ static void pnv_machine_class_init(ObjectClass *oc,
void *data)
pnv_machine_class_props_init(oc);
}
-#define DEFINE_PNV_CHIP_TYPE(type, class_initfn) \
- { \
- .name = type, \
- .class_init = class_initfn, \
- .parent = TYPE_PNV_CHIP, \
+#define DEFINE_PNV8_CHIP_TYPE(type, class_initfn) \
+ { \
+ .name = type, \
+ .class_init = class_initfn, \
+ .parent = TYPE_PNV8_CHIP, \
+ }
+
+#define DEFINE_PNV9_CHIP_TYPE(type, class_initfn) \
+ { \
+ .name = type, \
+ .class_init = class_initfn, \
+ .parent = TYPE_PNV9_CHIP, \
}
static const TypeInfo types[] = {
@@ -1150,7 +1207,7 @@ static const TypeInfo types[] = {
.name = TYPE_PNV_MACHINE,
.parent = TYPE_MACHINE,
.instance_size = sizeof(PnvMachineState),
- .instance_init = pnv_machine_initfn,
+ .instance_init = pnv_machine_instance_init,
.class_init = pnv_machine_class_init,
.interfaces = (InterfaceInfo[]) {
{ TYPE_XICS_FABRIC },
@@ -1162,16 +1219,36 @@ static const TypeInfo types[] = {
.name = TYPE_PNV_CHIP,
.parent = TYPE_SYS_BUS_DEVICE,
.class_init = pnv_chip_class_init,
- .instance_init = pnv_chip_init,
+ .instance_init = pnv_chip_instance_init,
.instance_size = sizeof(PnvChip),
.class_size = sizeof(PnvChipClass),
.abstract = true,
},
- DEFINE_PNV_CHIP_TYPE(TYPE_PNV_CHIP_POWER9, pnv_chip_power9_class_init),
- DEFINE_PNV_CHIP_TYPE(TYPE_PNV_CHIP_POWER8, pnv_chip_power8_class_init),
- DEFINE_PNV_CHIP_TYPE(TYPE_PNV_CHIP_POWER8E, pnv_chip_power8e_class_init),
- DEFINE_PNV_CHIP_TYPE(TYPE_PNV_CHIP_POWER8NVL,
- pnv_chip_power8nvl_class_init),
+
+ /*
+ * P9 chip and variants
+ */
+ {
+ .name = TYPE_PNV9_CHIP,
+ .parent = TYPE_PNV_CHIP,
+ .instance_init = pnv_chip_power9_instance_init,
+ .instance_size = sizeof(Pnv9Chip),
+ },
+ DEFINE_PNV9_CHIP_TYPE(TYPE_PNV_CHIP_POWER9, pnv_chip_power9_class_init),
+
+ /*
+ * P8 chip and variants
+ */
+ {
+ .name = TYPE_PNV8_CHIP,
+ .parent = TYPE_PNV_CHIP,
+ .instance_init = pnv_chip_power8_instance_init,
+ .instance_size = sizeof(Pnv8Chip),
+ },
+ DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8, pnv_chip_power8_class_init),
+ DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8E, pnv_chip_power8e_class_init),
+ DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8NVL,
+ pnv_chip_power8nvl_class_init),
};
DEFINE_TYPES(types)
diff --git a/include/hw/ppc/pnv.h b/include/hw/ppc/pnv.h
index 563279f3e0..86d5f54e54 100644
--- a/include/hw/ppc/pnv.h
+++ b/include/hw/ppc/pnv.h
@@ -57,12 +57,32 @@ typedef struct PnvChip {
MemoryRegion xscom_mmio;
MemoryRegion xscom;
AddressSpace xscom_as;
+} PnvChip;
+
+#define TYPE_PNV8_CHIP "pnv8-chip"
+#define PNV8_CHIP(obj) OBJECT_CHECK(Pnv8Chip, (obj), TYPE_PNV8_CHIP)
+
+typedef struct Pnv8Chip {
+ /*< private >*/
+ PnvChip parent_obj;
+
+ /*< public >*/
MemoryRegion icp_mmio;
PnvLpcController lpc;
PnvPsi psi;
PnvOCC occ;
-} PnvChip;
+} Pnv8Chip;
+
+#define TYPE_PNV9_CHIP "pnv9-chip"
+#define PNV9_CHIP(obj) OBJECT_CHECK(Pnv9Chip, (obj), TYPE_PNV9_CHIP)
+
+typedef struct Pnv9Chip {
+ /*< private >*/
+ PnvChip parent_obj;
+
+ /*< public >*/
+} Pnv9Chip;
typedef struct PnvChipClass {
/*< private >*/
@@ -75,6 +95,8 @@ typedef struct PnvChipClass {
hwaddr xscom_base;
+ DeviceRealize parent_realize;
+
uint32_t (*core_pir)(PnvChip *chip, uint32_t core_id);
Object *(*intc_create)(PnvChip *chip, Object *child, Error **errp);
ISABus *(*isa_create)(PnvChip *chip, Error **errp);
--
2.17.1
- [Qemu-ppc] [PATCH 06/23] ppc/pnv: consolidate the creation of the ISA bus device tree, (continued)
- [Qemu-ppc] [PATCH 06/23] ppc/pnv: consolidate the creation of the ISA bus device tree, David Gibson, 2018/06/22
- [Qemu-ppc] [PATCH 03/23] spapr_cpu_core: migrate per-CPU data, David Gibson, 2018/06/22
- [Qemu-ppc] [PATCH 02/23] ppc/pnv: introduce a new isa_create() operation to the chip model, David Gibson, 2018/06/22
- [Qemu-ppc] [PATCH 22/23] spapr: Limit available pagesizes to provide a consistent guest environment, David Gibson, 2018/06/22
- [Qemu-ppc] [PATCH 17/23] target/ppc: Add missing opcode for icbt on PPC440, David Gibson, 2018/06/22
- [Qemu-ppc] [PATCH 14/23] sm501: Fix hardware cursor color conversion, David Gibson, 2018/06/22
- [Qemu-ppc] [PATCH 04/23] spapr_cpu_core: migrate VPA related state, David Gibson, 2018/06/22
- [Qemu-ppc] [PATCH 08/23] spapr: Compute effective capability values earlier, David Gibson, 2018/06/22
- [Qemu-ppc] [PATCH 20/23] spapr: Use maximum page size capability to simplify memory backend checking, David Gibson, 2018/06/22
- [Qemu-ppc] [PATCH 16/23] ppc4xx_i2c: Implement directcntl register, David Gibson, 2018/06/22
- [Qemu-ppc] [PATCH 05/23] ppc/pnv: introduce Pnv8Chip and Pnv9Chip models,
David Gibson <=
- [Qemu-ppc] [PATCH 09/23] spapr: Add cpu_apply hook to capabilities, David Gibson, 2018/06/22
- [Qemu-ppc] [PATCH 10/23] target/ppc: Add kvmppc_hpt_needs_host_contiguous_pages() helper, David Gibson, 2018/06/22
- [Qemu-ppc] [PATCH 21/23] target/ppc: Add ppc_hash64_filter_pagesizes(), David Gibson, 2018/06/22
- [Qemu-ppc] [PATCH 12/23] spapr: remove unused spapr_irq routines, David Gibson, 2018/06/22
- [Qemu-ppc] [PATCH 07/23] target/ppc: Allow cpu compatiblity checks based on type, not instance, David Gibson, 2018/06/22
- [Qemu-ppc] [PATCH 19/23] spapr: Maximum (HPT) pagesize property, David Gibson, 2018/06/22
- [Qemu-ppc] [PATCH 23/23] spapr: Don't rewrite mmu capabilities in KVM mode, David Gibson, 2018/06/22
- [Qemu-ppc] [PATCH 15/23] ppc4xx_i2c: Remove unimplemented sdata and intr registers, David Gibson, 2018/06/22
- [Qemu-ppc] [PATCH 13/23] fpu_helper.c: fix helper_fpscr_clrbit() function, David Gibson, 2018/06/22
- [Qemu-ppc] [PATCH 11/23] spapr: split the IRQ allocation sequence, David Gibson, 2018/06/22