aboutsummaryrefslogtreecommitdiff
path: root/hw/intc
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/intc
parent4f9924c4d4cf9c039e247c5cdbbf71bce4e573c3 (diff)
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/intc')
-rw-r--r--hw/intc/xics.c14
1 files changed, 13 insertions, 1 deletions
diff --git a/hw/intc/xics.c b/hw/intc/xics.c
index 785b607528..c5d507e707 100644
--- a/hw/intc/xics.c
+++ b/hw/intc/xics.c
@@ -217,7 +217,7 @@ void icp_eoi(ICPState *icp, uint32_t xirr)
}
}
-static void icp_irq(ICSState *ics, int server, int nr, uint8_t priority)
+void icp_irq(ICSState *ics, int server, int nr, uint8_t priority)
{
ICPState *icp = xics_icp_get(ics->xics, server);
@@ -512,8 +512,14 @@ void ics_write_xive(ICSState *ics, int srcno, int server,
static void ics_reject(ICSState *ics, uint32_t nr)
{
+ ICSStateClass *isc = ICS_GET_CLASS(ics);
ICSIRQState *irq = ics->irqs + nr - ics->offset;
+ if (isc->reject) {
+ isc->reject(ics, nr);
+ return;
+ }
+
trace_xics_ics_reject(nr, nr - ics->offset);
if (irq->flags & XICS_FLAGS_IRQ_MSI) {
irq->status |= XICS_STATUS_REJECTED;
@@ -524,8 +530,14 @@ static void ics_reject(ICSState *ics, uint32_t nr)
void ics_resend(ICSState *ics)
{
+ ICSStateClass *isc = ICS_GET_CLASS(ics);
int i;
+ if (isc->resend) {
+ isc->resend(ics);
+ return;
+ }
+
for (i = 0; i < ics->nr_irqs; i++) {
/* FIXME: filter by server#? */
if (ics->irqs[i].flags & XICS_FLAGS_IRQ_LSI) {