@@ -146,6 +146,8 @@ struct PnvPHB3 {
PnvPBCQState pbcq;
QLIST_HEAD(, PnvPhb3DMASpace) dma_spaces;
+
+ PnvChip *chip;
};
#define TYPE_PNV_PHB3_RC "pnv-phb3-rc"
@@ -970,6 +970,16 @@ static void pnv_phb3_pci_create(PnvPHB3 *phb, Error **errp)
qdev_init_nofail(DEVICE(brdev));
}
+static void pnv_phb3_parent_fixup(Object *obj, Object *parent, Error **errp)
+{
+ if (obj->parent != parent) {
+ object_ref(obj);
+ object_unparent(obj);
+ object_property_add_child(parent, DEVICE(obj)->id, obj, errp);
+ object_unref(obj);
+ }
+}
+
static void pnv_phb3_realize(DeviceState *dev, Error **errp)
{
PnvPHB3 *phb = PNV_PHB3(dev);
@@ -978,6 +988,17 @@ static void pnv_phb3_realize(DeviceState *dev, Error **errp)
Error *local_err = NULL;
int i;
+ /*
+ * PHB3 devices created on the command line are not parented to
+ * the chip. Make sure they are because this is necessary to build
+ * correctly the device tree.
+ */
+ pnv_phb3_parent_fixup(OBJECT(phb), OBJECT(phb->chip), &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ return;
+ }
+
memory_region_init(&phb->pci_mmio, OBJECT(phb), "pci-mmio",
PCI_MMIO_TOTAL_SIZE);
@@ -1138,6 +1159,7 @@ static void pnv_phb3_set_chip_id(Object *obj, Visitor *v, const char *name,
return;
}
+ phb->chip = chip;
phb->chip_id = chip_id;
}
@@ -1148,7 +1170,7 @@ static const PropertyInfo pnv_phb3_chip_id_propinfo = {
};
static Property pnv_phb3_properties[] = {
- DEFINE_PROP("phb-id", PnvPHB3, phb_id, pnv_phb3_phb_id_propinfo,
+ DEFINE_PROP("index", PnvPHB3, phb_id, pnv_phb3_phb_id_propinfo,
uint32_t),
DEFINE_PROP("chip-id", PnvPHB3, chip_id, pnv_phb3_chip_id_propinfo,
uint32_t),
@@ -1164,6 +1186,7 @@ static void pnv_phb3_class_init(ObjectClass *klass, void *data)
dc->realize = pnv_phb3_realize;
dc->props = pnv_phb3_properties;
set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
+ dc->user_creatable = true;
}
static const TypeInfo pnv_phb3_type_info = {
@@ -285,6 +285,17 @@ static void pnv_pbcq_realize(DeviceState *dev, Error **errp)
pnv_xscom_region_init(&pbcq->xscom_spci_regs, OBJECT(dev),
&pnv_pbcq_spci_xscom_ops, pbcq, name,
PNV_XSCOM_PBCQ_SPCI_SIZE);
+
+ /* Populate the XSCOM address space. */
+ pnv_xscom_add_subregion(phb->chip,
+ PNV_XSCOM_PBCQ_NEST_BASE + 0x400 * phb->phb_id,
+ &pbcq->xscom_nest_regs);
+ pnv_xscom_add_subregion(phb->chip,
+ PNV_XSCOM_PBCQ_PCI_BASE + 0x400 * phb->phb_id,
+ &pbcq->xscom_pci_regs);
+ pnv_xscom_add_subregion(phb->chip,
+ PNV_XSCOM_PBCQ_SPCI_BASE + 0x040 * phb->phb_id,
+ &pbcq->xscom_spci_regs);
}
static int pnv_pbcq_dt_xscom(PnvXScomInterface *dev, void *fdt,
@@ -834,9 +834,8 @@ static void pnv_chip_power8_realize(DeviceState *dev, Error **errp)
/* Create the PHB3 controllers */
for (i = 0; i < pcc->num_phbs; i++) {
PnvPHB3 *phb = &chip8->phbs[i];
- PnvPBCQState *pbcq = &phb->pbcq;
- object_property_set_int(OBJECT(phb), i, "phb-id", &error_fatal);
+ object_property_set_int(OBJECT(phb), i, "index", &error_fatal);
object_property_set_int(OBJECT(phb), chip->chip_id, "chip-id",
&error_fatal);
object_property_set_bool(OBJECT(phb), true, "realized", &local_err);
@@ -845,17 +844,6 @@ static void pnv_chip_power8_realize(DeviceState *dev, Error **errp)
return;
}
qdev_set_parent_bus(DEVICE(phb), sysbus_get_default());
-
- /* Populate the XSCOM address space. */
- pnv_xscom_add_subregion(chip,
- PNV_XSCOM_PBCQ_NEST_BASE + 0x400 * phb->phb_id,
- &pbcq->xscom_nest_regs);
- pnv_xscom_add_subregion(chip,
- PNV_XSCOM_PBCQ_PCI_BASE + 0x400 * phb->phb_id,
- &pbcq->xscom_pci_regs);
- pnv_xscom_add_subregion(chip,
- PNV_XSCOM_PBCQ_SPCI_BASE + 0x040 * phb->phb_id,
- &pbcq->xscom_spci_regs);
}
}
@@ -886,7 +874,7 @@ static void pnv_chip_power8_class_init(ObjectClass *klass, void *data)
k->chip_type = PNV_CHIP_POWER8;
k->chip_cfam_id = 0x220ea04980000000ull; /* P8 Venice DD2.0 */
k->cores_mask = POWER8_CORE_MASK;
- k->num_phbs = 3;
+ k->num_phbs = 1;
k->core_pir = pnv_chip_core_pir_p8;
k->intc_create = pnv_chip_power8_intc_create;
k->isa_create = pnv_chip_power8_isa_create;
@@ -1248,6 +1236,7 @@ static void pnv_machine_class_init(ObjectClass *oc, void *data)
xic->ics_get = pnv_ics_get;
xic->ics_resend = pnv_ics_resend;
ispc->print_info = pnv_pic_print_info;
+ machine_class_allow_dynamic_sysbus_dev(mc, TYPE_PNV_PHB3);
pnv_machine_class_props_init(oc);
}
Extra PHB3 devices and PCI devices can now be added to the powernv machine using such a command: -device pnv-phb3,chip-id=0,index=1,id=phb-0.1 \ -device nec-usb-xhci,bus=pci.1,addr=0x7 The 'index' property identifies the PHB3 in the chip and 'chip-id' the chip it belongs to. The PHB3 identifier property name is changed to 'index' to match the attribute name of the pci-root device used by libvirt for sPAPR machines. One problem we have to solve when devices are created on the command line is the object parenthood. The powernv machine uses the object hierarchy to populate the device tree and each device should be parented to the chip it belongs to. This is not the case for user created device which are parented to the container "/unattached". The changes below make sure PHB3 device is parented to its chip by reparenting the object if necessary. Signed-off-by: Cédric Le Goater <clg@kaod.org> --- include/hw/pci-host/pnv_phb3.h | 2 ++ hw/pci-host/pnv_phb3.c | 25 ++++++++++++++++++++++++- hw/pci-host/pnv_phb3_pbcq.c | 11 +++++++++++ hw/ppc/pnv.c | 17 +++-------------- 4 files changed, 40 insertions(+), 15 deletions(-)