aboutsummaryrefslogtreecommitdiff
path: root/hw/ppc/pnv.c
diff options
context:
space:
mode:
authorCédric Le Goater <clg@kaod.org>2020-01-27 15:45:06 +0100
committerDavid Gibson <david@gibson.dropbear.id.au>2020-02-02 14:07:57 +1100
commit9ae1329ee2fee95f201ca219090d7c742eaf6a90 (patch)
treefea34e2d2ac683817d1affb4c46537051b96431f /hw/ppc/pnv.c
parent4f9924c4d4cf9c039e247c5cdbbf71bce4e573c3 (diff)
downloadqemu-9ae1329ee2fee95f201ca219090d7c742eaf6a90.zip
qemu-9ae1329ee2fee95f201ca219090d7c742eaf6a90.tar.gz
qemu-9ae1329ee2fee95f201ca219090d7c742eaf6a90.tar.bz2
ppc/pnv: Add models for POWER8 PHB3 PCIe Host bridge
This is a model of the PCIe Host Bridge (PHB3) found on a POWER8 processor. It includes the PowerBus logic interface (PBCQ), IOMMU support, a single PCIe Gen.3 Root Complex, and support for MSI and LSI interrupt sources as found on a POWER8 system using the XICS interrupt controller. The POWER8 processor comes in different flavors: Venice, Murano, Naple, each having a different number of PHBs. To make things simpler, the models provides 3 PHB3 per chip. Some platforms, like the Firestone, can also couple PHBs on the first chip to provide more bandwidth but this is too specific to model in QEMU. XICS requires some adjustment to support the PHB3 MSI. The changes are provided here but they could be decoupled in prereq patches. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Cédric Le Goater <clg@kaod.org> Message-Id: <20200127144506.11132-3-clg@kaod.org> [dwg: Use device_class_set_props()] Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Diffstat (limited to 'hw/ppc/pnv.c')
-rw-r--r--hw/ppc/pnv.c69
1 files changed, 67 insertions, 2 deletions
diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
index d5ecec6..139c857 100644
--- a/hw/ppc/pnv.c
+++ b/hw/ppc/pnv.c
@@ -616,8 +616,13 @@ static ISABus *pnv_isa_create(PnvChip *chip, Error **errp)
static void pnv_chip_power8_pic_print_info(PnvChip *chip, Monitor *mon)
{
Pnv8Chip *chip8 = PNV8_CHIP(chip);
+ int i;
ics_pic_print_info(&chip8->psi.ics, mon);
+ for (i = 0; i < chip->num_phbs; i++) {
+ pnv_phb3_msi_pic_print_info(&chip8->phbs[i].msis, mon);
+ ics_pic_print_info(&chip8->phbs[i].lsis, mon);
+ }
}
static void pnv_chip_power9_pic_print_info(PnvChip *chip, Monitor *mon)
@@ -1026,7 +1031,10 @@ static void pnv_chip_power10_intc_print_info(PnvChip *chip, PowerPCCPU *cpu,
static void pnv_chip_power8_instance_init(Object *obj)
{
+ PnvChip *chip = PNV_CHIP(obj);
Pnv8Chip *chip8 = PNV8_CHIP(obj);
+ PnvChipClass *pcc = PNV_CHIP_GET_CLASS(obj);
+ int i;
object_property_add_link(obj, "xics", TYPE_XICS_FABRIC,
(Object **)&chip8->xics,
@@ -1045,6 +1053,17 @@ static void pnv_chip_power8_instance_init(Object *obj)
object_initialize_child(obj, "homer", &chip8->homer, sizeof(chip8->homer),
TYPE_PNV8_HOMER, &error_abort, NULL);
+
+ for (i = 0; i < pcc->num_phbs; i++) {
+ object_initialize_child(obj, "phb[*]", &chip8->phbs[i],
+ sizeof(chip8->phbs[i]), TYPE_PNV_PHB3,
+ &error_abort, NULL);
+ }
+
+ /*
+ * Number of PHBs is the chip default
+ */
+ chip->num_phbs = pcc->num_phbs;
}
static void pnv_chip_icp_realize(Pnv8Chip *chip8, Error **errp)
@@ -1083,6 +1102,7 @@ static void pnv_chip_power8_realize(DeviceState *dev, Error **errp)
Pnv8Chip *chip8 = PNV8_CHIP(dev);
Pnv8Psi *psi8 = &chip8->psi;
Error *local_err = NULL;
+ int i;
assert(chip8->xics);
@@ -1163,6 +1183,33 @@ static void pnv_chip_power8_realize(DeviceState *dev, Error **errp)
/* Homer mmio region */
memory_region_add_subregion(get_system_memory(), PNV_HOMER_BASE(chip),
&chip8->homer.regs);
+
+ /* PHB3 controllers */
+ for (i = 0; i < chip->num_phbs; i++) {
+ PnvPHB3 *phb = &chip8->phbs[i];
+ PnvPBCQState *pbcq = &phb->pbcq;
+
+ 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);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ 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);
+ }
}
static uint32_t pnv_chip_power8_xscom_pcba(PnvChip *chip, uint64_t addr)
@@ -1178,6 +1225,7 @@ static void pnv_chip_power8e_class_init(ObjectClass *klass, void *data)
k->chip_cfam_id = 0x221ef04980000000ull; /* P8 Murano DD2.1 */
k->cores_mask = POWER8E_CORE_MASK;
+ k->num_phbs = 3;
k->core_pir = pnv_chip_core_pir_p8;
k->intc_create = pnv_chip_power8_intc_create;
k->intc_reset = pnv_chip_power8_intc_reset;
@@ -1201,6 +1249,7 @@ static void pnv_chip_power8_class_init(ObjectClass *klass, void *data)
k->chip_cfam_id = 0x220ea04980000000ull; /* P8 Venice DD2.0 */
k->cores_mask = POWER8_CORE_MASK;
+ k->num_phbs = 3;
k->core_pir = pnv_chip_core_pir_p8;
k->intc_create = pnv_chip_power8_intc_create;
k->intc_reset = pnv_chip_power8_intc_reset;
@@ -1224,6 +1273,7 @@ static void pnv_chip_power8nvl_class_init(ObjectClass *klass, void *data)
k->chip_cfam_id = 0x120d304980000000ull; /* P8 Naples DD1.0 */
k->cores_mask = POWER8_CORE_MASK;
+ k->num_phbs = 3;
k->core_pir = pnv_chip_core_pir_p8;
k->intc_create = pnv_chip_power8_intc_create;
k->intc_reset = pnv_chip_power8_intc_reset;
@@ -1748,14 +1798,23 @@ PowerPCCPU *pnv_chip_find_cpu(PnvChip *chip, uint32_t pir)
static ICSState *pnv_ics_get(XICSFabric *xi, int irq)
{
PnvMachineState *pnv = PNV_MACHINE(xi);
- int i;
+ int i, j;
for (i = 0; i < pnv->num_chips; i++) {
+ PnvChip *chip = pnv->chips[i];
Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]);
if (ics_valid_irq(&chip8->psi.ics, irq)) {
return &chip8->psi.ics;
}
+ for (j = 0; j < chip->num_phbs; j++) {
+ if (ics_valid_irq(&chip8->phbs[j].lsis, irq)) {
+ return &chip8->phbs[j].lsis;
+ }
+ if (ics_valid_irq(ICS(&chip8->phbs[j].msis), irq)) {
+ return ICS(&chip8->phbs[j].msis);
+ }
+ }
}
return NULL;
}
@@ -1763,11 +1822,17 @@ static ICSState *pnv_ics_get(XICSFabric *xi, int irq)
static void pnv_ics_resend(XICSFabric *xi)
{
PnvMachineState *pnv = PNV_MACHINE(xi);
- int i;
+ int i, j;
for (i = 0; i < pnv->num_chips; i++) {
+ PnvChip *chip = pnv->chips[i];
Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]);
+
ics_resend(&chip8->psi.ics);
+ for (j = 0; j < chip->num_phbs; j++) {
+ ics_resend(&chip8->phbs[j].lsis);
+ ics_resend(ICS(&chip8->phbs[j].msis));
+ }
}
}