Message ID | 0e5a08009a064472e957d0bfff2b63513da538b2.1341232709.git.jan.kiszka@siemens.com |
---|---|
State | New |
Headers | show |
On Mon, 2012-07-02 at 14:38 +0200, Jan Kiszka wrote: > Add a PCI IRQ path discovery function that walks from a given device to > the host bridge, returning the mode (enabled/inverted/disabled) and the > IRQ number that is reported to the attached interrupt controller. For > this purpose, another host bridge callback function is introduced: > route_intx_to_irq. It is so far only implemented by the PIIX3, other > host bridges can be added later on as required. > > Will be used for KVM PCI device assignment and VFIO. > > Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com> Acked-by: Alex Williamson <alex.williamson@redhat.com> > --- > hw/alpha_typhoon.c | 2 +- > hw/apb_pci.c | 2 +- > hw/bonito.c | 2 +- > hw/grackle_pci.c | 1 + > hw/gt64xxx.c | 1 + > hw/pci.c | 18 +++++++++++++++++- > hw/pci.h | 13 +++++++++++++ > hw/pci_internals.h | 1 + > hw/piix_pci.c | 23 ++++++++++++++++++++--- > hw/ppc4xx_pci.c | 2 +- > hw/ppce500_pci.c | 2 +- > hw/prep_pci.c | 2 +- > hw/sh_pci.c | 2 +- > hw/spapr_pci.c | 2 +- > hw/unin_pci.c | 4 ++-- > hw/versatile_pci.c | 2 +- > 16 files changed, 64 insertions(+), 15 deletions(-) > > diff --git a/hw/alpha_typhoon.c b/hw/alpha_typhoon.c > index 872e112..fc2e4b3 100644 > --- a/hw/alpha_typhoon.c > +++ b/hw/alpha_typhoon.c > @@ -764,7 +764,7 @@ PCIBus *typhoon_init(ram_addr_t ram_size, ISABus **isa_bus, > &s->pchip.reg_io); > > b = pci_register_bus(&s->host.busdev.qdev, "pci", > - typhoon_set_irq, sys_map_irq, s, > + typhoon_set_irq, sys_map_irq, NULL, s, > &s->pchip.reg_mem, addr_space_io, 0, 64); > s->host.bus = b; > > diff --git a/hw/apb_pci.c b/hw/apb_pci.c > index c28411a..d36cbb9 100644 > --- a/hw/apb_pci.c > +++ b/hw/apb_pci.c > @@ -378,7 +378,7 @@ PCIBus *pci_apb_init(target_phys_addr_t special_base, > memory_region_add_subregion(get_system_memory(), mem_base, &d->pci_mmio); > > d->bus = pci_register_bus(&d->busdev.qdev, "pci", > - pci_apb_set_irq, pci_pbm_map_irq, d, > + pci_apb_set_irq, pci_pbm_map_irq, NULL, d, > &d->pci_mmio, > get_system_io(), > 0, 32); > diff --git a/hw/bonito.c b/hw/bonito.c > index 77786f8..7ce5993 100644 > --- a/hw/bonito.c > +++ b/hw/bonito.c > @@ -750,7 +750,7 @@ PCIBus *bonito_init(qemu_irq *pic) > dev = qdev_create(NULL, "Bonito-pcihost"); > pcihost = FROM_SYSBUS(BonitoState, sysbus_from_qdev(dev)); > b = pci_register_bus(&pcihost->busdev.qdev, "pci", pci_bonito_set_irq, > - pci_bonito_map_irq, pic, get_system_memory(), > + pci_bonito_map_irq, NULL, pic, get_system_memory(), > get_system_io(), > 0x28, 32); > pcihost->bus = b; > diff --git a/hw/grackle_pci.c b/hw/grackle_pci.c > index 81ff3a3..f47d9fe 100644 > --- a/hw/grackle_pci.c > +++ b/hw/grackle_pci.c > @@ -85,6 +85,7 @@ PCIBus *pci_grackle_init(uint32_t base, qemu_irq *pic, > d->host_state.bus = pci_register_bus(&d->busdev.qdev, "pci", > pci_grackle_set_irq, > pci_grackle_map_irq, > + NULL, > pic, > &d->pci_mmio, > address_space_io, > diff --git a/hw/gt64xxx.c b/hw/gt64xxx.c > index a2d0e5a..2418238 100644 > --- a/hw/gt64xxx.c > +++ b/hw/gt64xxx.c > @@ -1093,6 +1093,7 @@ PCIBus *gt64120_register(qemu_irq *pic) > d = FROM_SYSBUS(GT64120State, s); > d->pci.bus = pci_register_bus(&d->busdev.qdev, "pci", > gt64120_pci_set_irq, gt64120_pci_map_irq, > + NULL, > pic, > get_system_memory(), > get_system_io(), > diff --git a/hw/pci.c b/hw/pci.c > index 99a4304..311ba09 100644 > --- a/hw/pci.c > +++ b/hw/pci.c > @@ -307,10 +307,12 @@ PCIBus *pci_bus_new(DeviceState *parent, const char *name, > } > > void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq, pci_map_irq_fn map_irq, > + pci_route_irq_fn route_intx_to_irq, > void *irq_opaque, int nirq) > { > bus->set_irq = set_irq; > bus->map_irq = map_irq; > + bus->route_intx_to_irq = route_intx_to_irq; > bus->irq_opaque = irq_opaque; > bus->nirq = nirq; > bus->irq_count = g_malloc0(nirq * sizeof(bus->irq_count[0])); > @@ -325,6 +327,7 @@ void pci_bus_hotplug(PCIBus *bus, pci_hotplug_fn hotplug, DeviceState *qdev) > > PCIBus *pci_register_bus(DeviceState *parent, const char *name, > pci_set_irq_fn set_irq, pci_map_irq_fn map_irq, > + pci_route_irq_fn route_intx_to_irq, > void *irq_opaque, > MemoryRegion *address_space_mem, > MemoryRegion *address_space_io, > @@ -334,7 +337,7 @@ PCIBus *pci_register_bus(DeviceState *parent, const char *name, > > bus = pci_bus_new(parent, name, address_space_mem, > address_space_io, devfn_min); > - pci_bus_irqs(bus, set_irq, map_irq, irq_opaque, nirq); > + pci_bus_irqs(bus, set_irq, map_irq, route_intx_to_irq, irq_opaque, nirq); > return bus; > } > > @@ -1079,6 +1082,19 @@ static void pci_set_irq(void *opaque, int irq_num, int level) > pci_change_irq_level(pci_dev, irq_num, change); > } > > +PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin) > +{ > + PCIBus *bus; > + > + do { > + bus = dev->bus; > + pin = bus->map_irq(dev, pin); > + dev = bus->parent_dev; > + } while (dev); > + assert(bus->route_intx_to_irq); > + return bus->route_intx_to_irq(bus->irq_opaque, pin); > +} > + > /***********************************************************/ > /* monitor info on PCI */ > > diff --git a/hw/pci.h b/hw/pci.h > index 79d38fd..387111b 100644 > --- a/hw/pci.h > +++ b/hw/pci.h > @@ -141,6 +141,15 @@ enum { > #define PCI_DEVICE_GET_CLASS(obj) \ > OBJECT_GET_CLASS(PCIDeviceClass, (obj), TYPE_PCI_DEVICE) > > +typedef struct PCIINTxRoute { > + enum { > + PCI_INTX_ENABLED, > + PCI_INTX_INVERTED, > + PCI_INTX_DISABLED, > + } mode; > + int irq; > +} PCIINTxRoute; > + > typedef struct PCIDeviceClass { > DeviceClass parent_class; > > @@ -278,6 +287,7 @@ MemoryRegion *pci_address_space_io(PCIDevice *dev); > > typedef void (*pci_set_irq_fn)(void *opaque, int irq_num, int level); > typedef int (*pci_map_irq_fn)(PCIDevice *pci_dev, int irq_num); > +typedef PCIINTxRoute (*pci_route_irq_fn)(void *opaque, int pin); > > typedef enum { > PCI_HOTPLUG_DISABLED, > @@ -297,15 +307,18 @@ PCIBus *pci_bus_new(DeviceState *parent, const char *name, > MemoryRegion *address_space_io, > uint8_t devfn_min); > void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq, pci_map_irq_fn map_irq, > + pci_route_irq_fn route_intx_to_irq, > void *irq_opaque, int nirq); > int pci_bus_get_irq_level(PCIBus *bus, int irq_num); > void pci_bus_hotplug(PCIBus *bus, pci_hotplug_fn hotplug, DeviceState *dev); > PCIBus *pci_register_bus(DeviceState *parent, const char *name, > pci_set_irq_fn set_irq, pci_map_irq_fn map_irq, > + pci_route_irq_fn route_intx_to_irq, > void *irq_opaque, > MemoryRegion *address_space_mem, > MemoryRegion *address_space_io, > uint8_t devfn_min, int nirq); > +PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin); > void pci_device_reset(PCIDevice *dev); > void pci_bus_reset(PCIBus *bus); > > diff --git a/hw/pci_internals.h b/hw/pci_internals.h > index e8bc9f6..c931b64 100644 > --- a/hw/pci_internals.h > +++ b/hw/pci_internals.h > @@ -22,6 +22,7 @@ struct PCIBus { > uint8_t devfn_min; > pci_set_irq_fn set_irq; > pci_map_irq_fn map_irq; > + pci_route_irq_fn route_intx_to_irq; > pci_hotplug_fn hotplug; > DeviceState *hotplug_qdev; > void *irq_opaque; > diff --git a/hw/piix_pci.c b/hw/piix_pci.c > index 09e84f5..347177f 100644 > --- a/hw/piix_pci.c > +++ b/hw/piix_pci.c > @@ -89,6 +89,7 @@ struct PCII440FXState { > #define I440FX_SMRAM 0x72 > > static void piix3_set_irq(void *opaque, int pirq, int level); > +static PCIINTxRoute piix3_route_intx_pin_to_irq(void *opaque, int pci_intx); > static void piix3_write_config_xen(PCIDevice *dev, > uint32_t address, uint32_t val, int len); > > @@ -308,13 +309,13 @@ static PCIBus *i440fx_common_init(const char *device_name, > if (xen_enabled()) { > piix3 = DO_UPCAST(PIIX3State, dev, > pci_create_simple_multifunction(b, -1, true, "PIIX3-xen")); > - pci_bus_irqs(b, xen_piix3_set_irq, xen_pci_slot_get_pirq, > + pci_bus_irqs(b, xen_piix3_set_irq, xen_pci_slot_get_pirq, NULL, > piix3, XEN_PIIX_NUM_PIRQS); > } else { > piix3 = DO_UPCAST(PIIX3State, dev, > pci_create_simple_multifunction(b, -1, true, "PIIX3")); > - pci_bus_irqs(b, piix3_set_irq, pci_slot_get_pirq, piix3, > - PIIX_NUM_PIRQS); > + pci_bus_irqs(b, piix3_set_irq, pci_slot_get_pirq, > + piix3_route_intx_pin_to_irq, piix3, PIIX_NUM_PIRQS); > } > piix3->pic = pic; > *isa_bus = DO_UPCAST(ISABus, qbus, > @@ -386,6 +387,22 @@ static void piix3_set_irq(void *opaque, int pirq, int level) > piix3_set_irq_level(piix3, pirq, level); > } > > +static PCIINTxRoute piix3_route_intx_pin_to_irq(void *opaque, int pin) > +{ > + PIIX3State *piix3 = opaque; > + int irq = piix3->dev.config[PIIX_PIRQC + pin]; > + PCIINTxRoute route; > + > + if (irq < PIIX_NUM_PIC_IRQS) { > + route.mode = PCI_INTX_ENABLED; > + route.irq = irq; > + } else { > + route.mode = PCI_INTX_DISABLED; > + route.irq = -1; > + } > + return route; > +} > + > /* irq routing is changed. so rebuild bitmap */ > static void piix3_update_irq_levels(PIIX3State *piix3) > { > diff --git a/hw/ppc4xx_pci.c b/hw/ppc4xx_pci.c > index 203c3cd..224c4a0 100644 > --- a/hw/ppc4xx_pci.c > +++ b/hw/ppc4xx_pci.c > @@ -343,7 +343,7 @@ static int ppc4xx_pcihost_initfn(SysBusDevice *dev) > } > > b = pci_register_bus(&s->pci_state.busdev.qdev, NULL, ppc4xx_pci_set_irq, > - ppc4xx_pci_map_irq, s->irq, get_system_memory(), > + ppc4xx_pci_map_irq, NULL, s->irq, get_system_memory(), > get_system_io(), 0, 4); > s->pci_state.bus = b; > > diff --git a/hw/ppce500_pci.c b/hw/ppce500_pci.c > index 0f60b24..dd924ae 100644 > --- a/hw/ppce500_pci.c > +++ b/hw/ppce500_pci.c > @@ -318,7 +318,7 @@ static int e500_pcihost_initfn(SysBusDevice *dev) > } > > b = pci_register_bus(&s->pci_state.busdev.qdev, NULL, mpc85xx_pci_set_irq, > - mpc85xx_pci_map_irq, s->irq, address_space_mem, > + mpc85xx_pci_map_irq, NULL, s->irq, address_space_mem, > address_space_io, PCI_DEVFN(0x11, 0), 4); > s->pci_state.bus = b; > > diff --git a/hw/prep_pci.c b/hw/prep_pci.c > index 38dbff4..9d7bec7 100644 > --- a/hw/prep_pci.c > +++ b/hw/prep_pci.c > @@ -108,7 +108,7 @@ static int raven_pcihost_init(SysBusDevice *dev) > } > > bus = pci_register_bus(&h->busdev.qdev, NULL, > - prep_set_irq, prep_map_irq, s->irq, > + prep_set_irq, prep_map_irq, NULL, s->irq, > address_space_mem, address_space_io, 0, 4); > h->bus = bus; > > diff --git a/hw/sh_pci.c b/hw/sh_pci.c > index 0cfac46..1cea12b 100644 > --- a/hw/sh_pci.c > +++ b/hw/sh_pci.c > @@ -120,7 +120,7 @@ static int sh_pci_device_init(SysBusDevice *dev) > sysbus_init_irq(dev, &s->irq[i]); > } > s->bus = pci_register_bus(&s->busdev.qdev, "pci", > - sh_pci_set_irq, sh_pci_map_irq, > + sh_pci_set_irq, sh_pci_map_irq, NULL, > s->irq, > get_system_memory(), > get_system_io(), > diff --git a/hw/spapr_pci.c b/hw/spapr_pci.c > index 47ba5ff..ffede69 100644 > --- a/hw/spapr_pci.c > +++ b/hw/spapr_pci.c > @@ -316,7 +316,7 @@ static int spapr_phb_init(SysBusDevice *s) > > bus = pci_register_bus(&phb->busdev.qdev, > phb->busname ? phb->busname : phb->dtbusname, > - pci_spapr_set_irq, pci_spapr_map_irq, phb, > + pci_spapr_set_irq, pci_spapr_map_irq, NULL, phb, > &phb->memspace, &phb->iospace, > PCI_DEVFN(0, 0), PCI_NUM_PINS); > phb->host_state.bus = bus; > diff --git a/hw/unin_pci.c b/hw/unin_pci.c > index 409bcd4..056e3bc 100644 > --- a/hw/unin_pci.c > +++ b/hw/unin_pci.c > @@ -227,7 +227,7 @@ PCIBus *pci_pmac_init(qemu_irq *pic, > > d->host_state.bus = pci_register_bus(dev, "pci", > pci_unin_set_irq, pci_unin_map_irq, > - pic, > + NULL, pic, > &d->pci_mmio, > address_space_io, > PCI_DEVFN(11, 0), 4); > @@ -293,7 +293,7 @@ PCIBus *pci_pmac_u3_init(qemu_irq *pic, > > d->host_state.bus = pci_register_bus(dev, "pci", > pci_unin_set_irq, pci_unin_map_irq, > - pic, > + NULL, pic, > &d->pci_mmio, > address_space_io, > PCI_DEVFN(11, 0), 4); > diff --git a/hw/versatile_pci.c b/hw/versatile_pci.c > index ae53a8b..90c400e 100644 > --- a/hw/versatile_pci.c > +++ b/hw/versatile_pci.c > @@ -68,7 +68,7 @@ static int pci_vpb_init(SysBusDevice *dev) > sysbus_init_irq(dev, &s->irq[i]); > } > bus = pci_register_bus(&dev->qdev, "pci", > - pci_vpb_set_irq, pci_vpb_map_irq, s->irq, > + pci_vpb_set_irq, pci_vpb_map_irq, NULL, s->irq, > get_system_memory(), get_system_io(), > PCI_DEVFN(11, 0), 4); >
On Mon, Jul 02, 2012 at 02:38:46PM +0200, Jan Kiszka wrote: > Add a PCI IRQ path discovery function that walks from a given device to > the host bridge, returning the mode (enabled/inverted/disabled) and the > IRQ number that is reported to the attached interrupt controller. For > this purpose, another host bridge callback function is introduced: > route_intx_to_irq. It is so far only implemented by the PIIX3, other > host bridges can be added later on as required. > > Will be used for KVM PCI device assignment and VFIO. > > Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com> I strongly suspect what we'll end up with is reworking this in some way, so IMO touching all architectures is premature and will just cause churn: this is stubbed out even on piix xen. So I just added an extra API instead, and applied. > --- > hw/alpha_typhoon.c | 2 +- > hw/apb_pci.c | 2 +- > hw/bonito.c | 2 +- > hw/grackle_pci.c | 1 + > hw/gt64xxx.c | 1 + > hw/pci.c | 18 +++++++++++++++++- > hw/pci.h | 13 +++++++++++++ > hw/pci_internals.h | 1 + > hw/piix_pci.c | 23 ++++++++++++++++++++--- > hw/ppc4xx_pci.c | 2 +- > hw/ppce500_pci.c | 2 +- > hw/prep_pci.c | 2 +- > hw/sh_pci.c | 2 +- > hw/spapr_pci.c | 2 +- > hw/unin_pci.c | 4 ++-- > hw/versatile_pci.c | 2 +- > 16 files changed, 64 insertions(+), 15 deletions(-) > > diff --git a/hw/alpha_typhoon.c b/hw/alpha_typhoon.c > index 872e112..fc2e4b3 100644 > --- a/hw/alpha_typhoon.c > +++ b/hw/alpha_typhoon.c > @@ -764,7 +764,7 @@ PCIBus *typhoon_init(ram_addr_t ram_size, ISABus **isa_bus, > &s->pchip.reg_io); > > b = pci_register_bus(&s->host.busdev.qdev, "pci", > - typhoon_set_irq, sys_map_irq, s, > + typhoon_set_irq, sys_map_irq, NULL, s, > &s->pchip.reg_mem, addr_space_io, 0, 64); > s->host.bus = b; > > diff --git a/hw/apb_pci.c b/hw/apb_pci.c > index c28411a..d36cbb9 100644 > --- a/hw/apb_pci.c > +++ b/hw/apb_pci.c > @@ -378,7 +378,7 @@ PCIBus *pci_apb_init(target_phys_addr_t special_base, > memory_region_add_subregion(get_system_memory(), mem_base, &d->pci_mmio); > > d->bus = pci_register_bus(&d->busdev.qdev, "pci", > - pci_apb_set_irq, pci_pbm_map_irq, d, > + pci_apb_set_irq, pci_pbm_map_irq, NULL, d, > &d->pci_mmio, > get_system_io(), > 0, 32); > diff --git a/hw/bonito.c b/hw/bonito.c > index 77786f8..7ce5993 100644 > --- a/hw/bonito.c > +++ b/hw/bonito.c > @@ -750,7 +750,7 @@ PCIBus *bonito_init(qemu_irq *pic) > dev = qdev_create(NULL, "Bonito-pcihost"); > pcihost = FROM_SYSBUS(BonitoState, sysbus_from_qdev(dev)); > b = pci_register_bus(&pcihost->busdev.qdev, "pci", pci_bonito_set_irq, > - pci_bonito_map_irq, pic, get_system_memory(), > + pci_bonito_map_irq, NULL, pic, get_system_memory(), > get_system_io(), > 0x28, 32); > pcihost->bus = b; > diff --git a/hw/grackle_pci.c b/hw/grackle_pci.c > index 81ff3a3..f47d9fe 100644 > --- a/hw/grackle_pci.c > +++ b/hw/grackle_pci.c > @@ -85,6 +85,7 @@ PCIBus *pci_grackle_init(uint32_t base, qemu_irq *pic, > d->host_state.bus = pci_register_bus(&d->busdev.qdev, "pci", > pci_grackle_set_irq, > pci_grackle_map_irq, > + NULL, > pic, > &d->pci_mmio, > address_space_io, > diff --git a/hw/gt64xxx.c b/hw/gt64xxx.c > index a2d0e5a..2418238 100644 > --- a/hw/gt64xxx.c > +++ b/hw/gt64xxx.c > @@ -1093,6 +1093,7 @@ PCIBus *gt64120_register(qemu_irq *pic) > d = FROM_SYSBUS(GT64120State, s); > d->pci.bus = pci_register_bus(&d->busdev.qdev, "pci", > gt64120_pci_set_irq, gt64120_pci_map_irq, > + NULL, > pic, > get_system_memory(), > get_system_io(), > diff --git a/hw/pci.c b/hw/pci.c > index 99a4304..311ba09 100644 > --- a/hw/pci.c > +++ b/hw/pci.c > @@ -307,10 +307,12 @@ PCIBus *pci_bus_new(DeviceState *parent, const char *name, > } > > void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq, pci_map_irq_fn map_irq, > + pci_route_irq_fn route_intx_to_irq, > void *irq_opaque, int nirq) > { > bus->set_irq = set_irq; > bus->map_irq = map_irq; > + bus->route_intx_to_irq = route_intx_to_irq; > bus->irq_opaque = irq_opaque; > bus->nirq = nirq; > bus->irq_count = g_malloc0(nirq * sizeof(bus->irq_count[0])); > @@ -325,6 +327,7 @@ void pci_bus_hotplug(PCIBus *bus, pci_hotplug_fn hotplug, DeviceState *qdev) > > PCIBus *pci_register_bus(DeviceState *parent, const char *name, > pci_set_irq_fn set_irq, pci_map_irq_fn map_irq, > + pci_route_irq_fn route_intx_to_irq, > void *irq_opaque, > MemoryRegion *address_space_mem, > MemoryRegion *address_space_io, > @@ -334,7 +337,7 @@ PCIBus *pci_register_bus(DeviceState *parent, const char *name, > > bus = pci_bus_new(parent, name, address_space_mem, > address_space_io, devfn_min); > - pci_bus_irqs(bus, set_irq, map_irq, irq_opaque, nirq); > + pci_bus_irqs(bus, set_irq, map_irq, route_intx_to_irq, irq_opaque, nirq); > return bus; > } > > @@ -1079,6 +1082,19 @@ static void pci_set_irq(void *opaque, int irq_num, int level) > pci_change_irq_level(pci_dev, irq_num, change); > } > > +PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin) > +{ > + PCIBus *bus; > + > + do { > + bus = dev->bus; > + pin = bus->map_irq(dev, pin); > + dev = bus->parent_dev; > + } while (dev); > + assert(bus->route_intx_to_irq); > + return bus->route_intx_to_irq(bus->irq_opaque, pin); > +} > + > /***********************************************************/ > /* monitor info on PCI */ > > diff --git a/hw/pci.h b/hw/pci.h > index 79d38fd..387111b 100644 > --- a/hw/pci.h > +++ b/hw/pci.h > @@ -141,6 +141,15 @@ enum { > #define PCI_DEVICE_GET_CLASS(obj) \ > OBJECT_GET_CLASS(PCIDeviceClass, (obj), TYPE_PCI_DEVICE) > > +typedef struct PCIINTxRoute { > + enum { > + PCI_INTX_ENABLED, > + PCI_INTX_INVERTED, > + PCI_INTX_DISABLED, > + } mode; > + int irq; > +} PCIINTxRoute; > + > typedef struct PCIDeviceClass { > DeviceClass parent_class; > > @@ -278,6 +287,7 @@ MemoryRegion *pci_address_space_io(PCIDevice *dev); > > typedef void (*pci_set_irq_fn)(void *opaque, int irq_num, int level); > typedef int (*pci_map_irq_fn)(PCIDevice *pci_dev, int irq_num); > +typedef PCIINTxRoute (*pci_route_irq_fn)(void *opaque, int pin); > > typedef enum { > PCI_HOTPLUG_DISABLED, > @@ -297,15 +307,18 @@ PCIBus *pci_bus_new(DeviceState *parent, const char *name, > MemoryRegion *address_space_io, > uint8_t devfn_min); > void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq, pci_map_irq_fn map_irq, > + pci_route_irq_fn route_intx_to_irq, > void *irq_opaque, int nirq); > int pci_bus_get_irq_level(PCIBus *bus, int irq_num); > void pci_bus_hotplug(PCIBus *bus, pci_hotplug_fn hotplug, DeviceState *dev); > PCIBus *pci_register_bus(DeviceState *parent, const char *name, > pci_set_irq_fn set_irq, pci_map_irq_fn map_irq, > + pci_route_irq_fn route_intx_to_irq, > void *irq_opaque, > MemoryRegion *address_space_mem, > MemoryRegion *address_space_io, > uint8_t devfn_min, int nirq); > +PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin); > void pci_device_reset(PCIDevice *dev); > void pci_bus_reset(PCIBus *bus); > > diff --git a/hw/pci_internals.h b/hw/pci_internals.h > index e8bc9f6..c931b64 100644 > --- a/hw/pci_internals.h > +++ b/hw/pci_internals.h > @@ -22,6 +22,7 @@ struct PCIBus { > uint8_t devfn_min; > pci_set_irq_fn set_irq; > pci_map_irq_fn map_irq; > + pci_route_irq_fn route_intx_to_irq; > pci_hotplug_fn hotplug; > DeviceState *hotplug_qdev; > void *irq_opaque; > diff --git a/hw/piix_pci.c b/hw/piix_pci.c > index 09e84f5..347177f 100644 > --- a/hw/piix_pci.c > +++ b/hw/piix_pci.c > @@ -89,6 +89,7 @@ struct PCII440FXState { > #define I440FX_SMRAM 0x72 > > static void piix3_set_irq(void *opaque, int pirq, int level); > +static PCIINTxRoute piix3_route_intx_pin_to_irq(void *opaque, int pci_intx); > static void piix3_write_config_xen(PCIDevice *dev, > uint32_t address, uint32_t val, int len); > > @@ -308,13 +309,13 @@ static PCIBus *i440fx_common_init(const char *device_name, > if (xen_enabled()) { > piix3 = DO_UPCAST(PIIX3State, dev, > pci_create_simple_multifunction(b, -1, true, "PIIX3-xen")); > - pci_bus_irqs(b, xen_piix3_set_irq, xen_pci_slot_get_pirq, > + pci_bus_irqs(b, xen_piix3_set_irq, xen_pci_slot_get_pirq, NULL, > piix3, XEN_PIIX_NUM_PIRQS); > } else { > piix3 = DO_UPCAST(PIIX3State, dev, > pci_create_simple_multifunction(b, -1, true, "PIIX3")); > - pci_bus_irqs(b, piix3_set_irq, pci_slot_get_pirq, piix3, > - PIIX_NUM_PIRQS); > + pci_bus_irqs(b, piix3_set_irq, pci_slot_get_pirq, > + piix3_route_intx_pin_to_irq, piix3, PIIX_NUM_PIRQS); > } > piix3->pic = pic; > *isa_bus = DO_UPCAST(ISABus, qbus, > @@ -386,6 +387,22 @@ static void piix3_set_irq(void *opaque, int pirq, int level) > piix3_set_irq_level(piix3, pirq, level); > } > > +static PCIINTxRoute piix3_route_intx_pin_to_irq(void *opaque, int pin) > +{ > + PIIX3State *piix3 = opaque; > + int irq = piix3->dev.config[PIIX_PIRQC + pin]; > + PCIINTxRoute route; > + > + if (irq < PIIX_NUM_PIC_IRQS) { > + route.mode = PCI_INTX_ENABLED; > + route.irq = irq; > + } else { > + route.mode = PCI_INTX_DISABLED; > + route.irq = -1; > + } > + return route; > +} > + > /* irq routing is changed. so rebuild bitmap */ > static void piix3_update_irq_levels(PIIX3State *piix3) > { > diff --git a/hw/ppc4xx_pci.c b/hw/ppc4xx_pci.c > index 203c3cd..224c4a0 100644 > --- a/hw/ppc4xx_pci.c > +++ b/hw/ppc4xx_pci.c > @@ -343,7 +343,7 @@ static int ppc4xx_pcihost_initfn(SysBusDevice *dev) > } > > b = pci_register_bus(&s->pci_state.busdev.qdev, NULL, ppc4xx_pci_set_irq, > - ppc4xx_pci_map_irq, s->irq, get_system_memory(), > + ppc4xx_pci_map_irq, NULL, s->irq, get_system_memory(), > get_system_io(), 0, 4); > s->pci_state.bus = b; > > diff --git a/hw/ppce500_pci.c b/hw/ppce500_pci.c > index 0f60b24..dd924ae 100644 > --- a/hw/ppce500_pci.c > +++ b/hw/ppce500_pci.c > @@ -318,7 +318,7 @@ static int e500_pcihost_initfn(SysBusDevice *dev) > } > > b = pci_register_bus(&s->pci_state.busdev.qdev, NULL, mpc85xx_pci_set_irq, > - mpc85xx_pci_map_irq, s->irq, address_space_mem, > + mpc85xx_pci_map_irq, NULL, s->irq, address_space_mem, > address_space_io, PCI_DEVFN(0x11, 0), 4); > s->pci_state.bus = b; > > diff --git a/hw/prep_pci.c b/hw/prep_pci.c > index 38dbff4..9d7bec7 100644 > --- a/hw/prep_pci.c > +++ b/hw/prep_pci.c > @@ -108,7 +108,7 @@ static int raven_pcihost_init(SysBusDevice *dev) > } > > bus = pci_register_bus(&h->busdev.qdev, NULL, > - prep_set_irq, prep_map_irq, s->irq, > + prep_set_irq, prep_map_irq, NULL, s->irq, > address_space_mem, address_space_io, 0, 4); > h->bus = bus; > > diff --git a/hw/sh_pci.c b/hw/sh_pci.c > index 0cfac46..1cea12b 100644 > --- a/hw/sh_pci.c > +++ b/hw/sh_pci.c > @@ -120,7 +120,7 @@ static int sh_pci_device_init(SysBusDevice *dev) > sysbus_init_irq(dev, &s->irq[i]); > } > s->bus = pci_register_bus(&s->busdev.qdev, "pci", > - sh_pci_set_irq, sh_pci_map_irq, > + sh_pci_set_irq, sh_pci_map_irq, NULL, > s->irq, > get_system_memory(), > get_system_io(), > diff --git a/hw/spapr_pci.c b/hw/spapr_pci.c > index 47ba5ff..ffede69 100644 > --- a/hw/spapr_pci.c > +++ b/hw/spapr_pci.c > @@ -316,7 +316,7 @@ static int spapr_phb_init(SysBusDevice *s) > > bus = pci_register_bus(&phb->busdev.qdev, > phb->busname ? phb->busname : phb->dtbusname, > - pci_spapr_set_irq, pci_spapr_map_irq, phb, > + pci_spapr_set_irq, pci_spapr_map_irq, NULL, phb, > &phb->memspace, &phb->iospace, > PCI_DEVFN(0, 0), PCI_NUM_PINS); > phb->host_state.bus = bus; > diff --git a/hw/unin_pci.c b/hw/unin_pci.c > index 409bcd4..056e3bc 100644 > --- a/hw/unin_pci.c > +++ b/hw/unin_pci.c > @@ -227,7 +227,7 @@ PCIBus *pci_pmac_init(qemu_irq *pic, > > d->host_state.bus = pci_register_bus(dev, "pci", > pci_unin_set_irq, pci_unin_map_irq, > - pic, > + NULL, pic, > &d->pci_mmio, > address_space_io, > PCI_DEVFN(11, 0), 4); > @@ -293,7 +293,7 @@ PCIBus *pci_pmac_u3_init(qemu_irq *pic, > > d->host_state.bus = pci_register_bus(dev, "pci", > pci_unin_set_irq, pci_unin_map_irq, > - pic, > + NULL, pic, > &d->pci_mmio, > address_space_io, > PCI_DEVFN(11, 0), 4); > diff --git a/hw/versatile_pci.c b/hw/versatile_pci.c > index ae53a8b..90c400e 100644 > --- a/hw/versatile_pci.c > +++ b/hw/versatile_pci.c > @@ -68,7 +68,7 @@ static int pci_vpb_init(SysBusDevice *dev) > sysbus_init_irq(dev, &s->irq[i]); > } > bus = pci_register_bus(&dev->qdev, "pci", > - pci_vpb_set_irq, pci_vpb_map_irq, s->irq, > + pci_vpb_set_irq, pci_vpb_map_irq, NULL, s->irq, > get_system_memory(), get_system_io(), > PCI_DEVFN(11, 0), 4); > > -- > 1.7.3.4
diff --git a/hw/alpha_typhoon.c b/hw/alpha_typhoon.c index 872e112..fc2e4b3 100644 --- a/hw/alpha_typhoon.c +++ b/hw/alpha_typhoon.c @@ -764,7 +764,7 @@ PCIBus *typhoon_init(ram_addr_t ram_size, ISABus **isa_bus, &s->pchip.reg_io); b = pci_register_bus(&s->host.busdev.qdev, "pci", - typhoon_set_irq, sys_map_irq, s, + typhoon_set_irq, sys_map_irq, NULL, s, &s->pchip.reg_mem, addr_space_io, 0, 64); s->host.bus = b; diff --git a/hw/apb_pci.c b/hw/apb_pci.c index c28411a..d36cbb9 100644 --- a/hw/apb_pci.c +++ b/hw/apb_pci.c @@ -378,7 +378,7 @@ PCIBus *pci_apb_init(target_phys_addr_t special_base, memory_region_add_subregion(get_system_memory(), mem_base, &d->pci_mmio); d->bus = pci_register_bus(&d->busdev.qdev, "pci", - pci_apb_set_irq, pci_pbm_map_irq, d, + pci_apb_set_irq, pci_pbm_map_irq, NULL, d, &d->pci_mmio, get_system_io(), 0, 32); diff --git a/hw/bonito.c b/hw/bonito.c index 77786f8..7ce5993 100644 --- a/hw/bonito.c +++ b/hw/bonito.c @@ -750,7 +750,7 @@ PCIBus *bonito_init(qemu_irq *pic) dev = qdev_create(NULL, "Bonito-pcihost"); pcihost = FROM_SYSBUS(BonitoState, sysbus_from_qdev(dev)); b = pci_register_bus(&pcihost->busdev.qdev, "pci", pci_bonito_set_irq, - pci_bonito_map_irq, pic, get_system_memory(), + pci_bonito_map_irq, NULL, pic, get_system_memory(), get_system_io(), 0x28, 32); pcihost->bus = b; diff --git a/hw/grackle_pci.c b/hw/grackle_pci.c index 81ff3a3..f47d9fe 100644 --- a/hw/grackle_pci.c +++ b/hw/grackle_pci.c @@ -85,6 +85,7 @@ PCIBus *pci_grackle_init(uint32_t base, qemu_irq *pic, d->host_state.bus = pci_register_bus(&d->busdev.qdev, "pci", pci_grackle_set_irq, pci_grackle_map_irq, + NULL, pic, &d->pci_mmio, address_space_io, diff --git a/hw/gt64xxx.c b/hw/gt64xxx.c index a2d0e5a..2418238 100644 --- a/hw/gt64xxx.c +++ b/hw/gt64xxx.c @@ -1093,6 +1093,7 @@ PCIBus *gt64120_register(qemu_irq *pic) d = FROM_SYSBUS(GT64120State, s); d->pci.bus = pci_register_bus(&d->busdev.qdev, "pci", gt64120_pci_set_irq, gt64120_pci_map_irq, + NULL, pic, get_system_memory(), get_system_io(), diff --git a/hw/pci.c b/hw/pci.c index 99a4304..311ba09 100644 --- a/hw/pci.c +++ b/hw/pci.c @@ -307,10 +307,12 @@ PCIBus *pci_bus_new(DeviceState *parent, const char *name, } void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq, pci_map_irq_fn map_irq, + pci_route_irq_fn route_intx_to_irq, void *irq_opaque, int nirq) { bus->set_irq = set_irq; bus->map_irq = map_irq; + bus->route_intx_to_irq = route_intx_to_irq; bus->irq_opaque = irq_opaque; bus->nirq = nirq; bus->irq_count = g_malloc0(nirq * sizeof(bus->irq_count[0])); @@ -325,6 +327,7 @@ void pci_bus_hotplug(PCIBus *bus, pci_hotplug_fn hotplug, DeviceState *qdev) PCIBus *pci_register_bus(DeviceState *parent, const char *name, pci_set_irq_fn set_irq, pci_map_irq_fn map_irq, + pci_route_irq_fn route_intx_to_irq, void *irq_opaque, MemoryRegion *address_space_mem, MemoryRegion *address_space_io, @@ -334,7 +337,7 @@ PCIBus *pci_register_bus(DeviceState *parent, const char *name, bus = pci_bus_new(parent, name, address_space_mem, address_space_io, devfn_min); - pci_bus_irqs(bus, set_irq, map_irq, irq_opaque, nirq); + pci_bus_irqs(bus, set_irq, map_irq, route_intx_to_irq, irq_opaque, nirq); return bus; } @@ -1079,6 +1082,19 @@ static void pci_set_irq(void *opaque, int irq_num, int level) pci_change_irq_level(pci_dev, irq_num, change); } +PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin) +{ + PCIBus *bus; + + do { + bus = dev->bus; + pin = bus->map_irq(dev, pin); + dev = bus->parent_dev; + } while (dev); + assert(bus->route_intx_to_irq); + return bus->route_intx_to_irq(bus->irq_opaque, pin); +} + /***********************************************************/ /* monitor info on PCI */ diff --git a/hw/pci.h b/hw/pci.h index 79d38fd..387111b 100644 --- a/hw/pci.h +++ b/hw/pci.h @@ -141,6 +141,15 @@ enum { #define PCI_DEVICE_GET_CLASS(obj) \ OBJECT_GET_CLASS(PCIDeviceClass, (obj), TYPE_PCI_DEVICE) +typedef struct PCIINTxRoute { + enum { + PCI_INTX_ENABLED, + PCI_INTX_INVERTED, + PCI_INTX_DISABLED, + } mode; + int irq; +} PCIINTxRoute; + typedef struct PCIDeviceClass { DeviceClass parent_class; @@ -278,6 +287,7 @@ MemoryRegion *pci_address_space_io(PCIDevice *dev); typedef void (*pci_set_irq_fn)(void *opaque, int irq_num, int level); typedef int (*pci_map_irq_fn)(PCIDevice *pci_dev, int irq_num); +typedef PCIINTxRoute (*pci_route_irq_fn)(void *opaque, int pin); typedef enum { PCI_HOTPLUG_DISABLED, @@ -297,15 +307,18 @@ PCIBus *pci_bus_new(DeviceState *parent, const char *name, MemoryRegion *address_space_io, uint8_t devfn_min); void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq, pci_map_irq_fn map_irq, + pci_route_irq_fn route_intx_to_irq, void *irq_opaque, int nirq); int pci_bus_get_irq_level(PCIBus *bus, int irq_num); void pci_bus_hotplug(PCIBus *bus, pci_hotplug_fn hotplug, DeviceState *dev); PCIBus *pci_register_bus(DeviceState *parent, const char *name, pci_set_irq_fn set_irq, pci_map_irq_fn map_irq, + pci_route_irq_fn route_intx_to_irq, void *irq_opaque, MemoryRegion *address_space_mem, MemoryRegion *address_space_io, uint8_t devfn_min, int nirq); +PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin); void pci_device_reset(PCIDevice *dev); void pci_bus_reset(PCIBus *bus); diff --git a/hw/pci_internals.h b/hw/pci_internals.h index e8bc9f6..c931b64 100644 --- a/hw/pci_internals.h +++ b/hw/pci_internals.h @@ -22,6 +22,7 @@ struct PCIBus { uint8_t devfn_min; pci_set_irq_fn set_irq; pci_map_irq_fn map_irq; + pci_route_irq_fn route_intx_to_irq; pci_hotplug_fn hotplug; DeviceState *hotplug_qdev; void *irq_opaque; diff --git a/hw/piix_pci.c b/hw/piix_pci.c index 09e84f5..347177f 100644 --- a/hw/piix_pci.c +++ b/hw/piix_pci.c @@ -89,6 +89,7 @@ struct PCII440FXState { #define I440FX_SMRAM 0x72 static void piix3_set_irq(void *opaque, int pirq, int level); +static PCIINTxRoute piix3_route_intx_pin_to_irq(void *opaque, int pci_intx); static void piix3_write_config_xen(PCIDevice *dev, uint32_t address, uint32_t val, int len); @@ -308,13 +309,13 @@ static PCIBus *i440fx_common_init(const char *device_name, if (xen_enabled()) { piix3 = DO_UPCAST(PIIX3State, dev, pci_create_simple_multifunction(b, -1, true, "PIIX3-xen")); - pci_bus_irqs(b, xen_piix3_set_irq, xen_pci_slot_get_pirq, + pci_bus_irqs(b, xen_piix3_set_irq, xen_pci_slot_get_pirq, NULL, piix3, XEN_PIIX_NUM_PIRQS); } else { piix3 = DO_UPCAST(PIIX3State, dev, pci_create_simple_multifunction(b, -1, true, "PIIX3")); - pci_bus_irqs(b, piix3_set_irq, pci_slot_get_pirq, piix3, - PIIX_NUM_PIRQS); + pci_bus_irqs(b, piix3_set_irq, pci_slot_get_pirq, + piix3_route_intx_pin_to_irq, piix3, PIIX_NUM_PIRQS); } piix3->pic = pic; *isa_bus = DO_UPCAST(ISABus, qbus, @@ -386,6 +387,22 @@ static void piix3_set_irq(void *opaque, int pirq, int level) piix3_set_irq_level(piix3, pirq, level); } +static PCIINTxRoute piix3_route_intx_pin_to_irq(void *opaque, int pin) +{ + PIIX3State *piix3 = opaque; + int irq = piix3->dev.config[PIIX_PIRQC + pin]; + PCIINTxRoute route; + + if (irq < PIIX_NUM_PIC_IRQS) { + route.mode = PCI_INTX_ENABLED; + route.irq = irq; + } else { + route.mode = PCI_INTX_DISABLED; + route.irq = -1; + } + return route; +} + /* irq routing is changed. so rebuild bitmap */ static void piix3_update_irq_levels(PIIX3State *piix3) { diff --git a/hw/ppc4xx_pci.c b/hw/ppc4xx_pci.c index 203c3cd..224c4a0 100644 --- a/hw/ppc4xx_pci.c +++ b/hw/ppc4xx_pci.c @@ -343,7 +343,7 @@ static int ppc4xx_pcihost_initfn(SysBusDevice *dev) } b = pci_register_bus(&s->pci_state.busdev.qdev, NULL, ppc4xx_pci_set_irq, - ppc4xx_pci_map_irq, s->irq, get_system_memory(), + ppc4xx_pci_map_irq, NULL, s->irq, get_system_memory(), get_system_io(), 0, 4); s->pci_state.bus = b; diff --git a/hw/ppce500_pci.c b/hw/ppce500_pci.c index 0f60b24..dd924ae 100644 --- a/hw/ppce500_pci.c +++ b/hw/ppce500_pci.c @@ -318,7 +318,7 @@ static int e500_pcihost_initfn(SysBusDevice *dev) } b = pci_register_bus(&s->pci_state.busdev.qdev, NULL, mpc85xx_pci_set_irq, - mpc85xx_pci_map_irq, s->irq, address_space_mem, + mpc85xx_pci_map_irq, NULL, s->irq, address_space_mem, address_space_io, PCI_DEVFN(0x11, 0), 4); s->pci_state.bus = b; diff --git a/hw/prep_pci.c b/hw/prep_pci.c index 38dbff4..9d7bec7 100644 --- a/hw/prep_pci.c +++ b/hw/prep_pci.c @@ -108,7 +108,7 @@ static int raven_pcihost_init(SysBusDevice *dev) } bus = pci_register_bus(&h->busdev.qdev, NULL, - prep_set_irq, prep_map_irq, s->irq, + prep_set_irq, prep_map_irq, NULL, s->irq, address_space_mem, address_space_io, 0, 4); h->bus = bus; diff --git a/hw/sh_pci.c b/hw/sh_pci.c index 0cfac46..1cea12b 100644 --- a/hw/sh_pci.c +++ b/hw/sh_pci.c @@ -120,7 +120,7 @@ static int sh_pci_device_init(SysBusDevice *dev) sysbus_init_irq(dev, &s->irq[i]); } s->bus = pci_register_bus(&s->busdev.qdev, "pci", - sh_pci_set_irq, sh_pci_map_irq, + sh_pci_set_irq, sh_pci_map_irq, NULL, s->irq, get_system_memory(), get_system_io(), diff --git a/hw/spapr_pci.c b/hw/spapr_pci.c index 47ba5ff..ffede69 100644 --- a/hw/spapr_pci.c +++ b/hw/spapr_pci.c @@ -316,7 +316,7 @@ static int spapr_phb_init(SysBusDevice *s) bus = pci_register_bus(&phb->busdev.qdev, phb->busname ? phb->busname : phb->dtbusname, - pci_spapr_set_irq, pci_spapr_map_irq, phb, + pci_spapr_set_irq, pci_spapr_map_irq, NULL, phb, &phb->memspace, &phb->iospace, PCI_DEVFN(0, 0), PCI_NUM_PINS); phb->host_state.bus = bus; diff --git a/hw/unin_pci.c b/hw/unin_pci.c index 409bcd4..056e3bc 100644 --- a/hw/unin_pci.c +++ b/hw/unin_pci.c @@ -227,7 +227,7 @@ PCIBus *pci_pmac_init(qemu_irq *pic, d->host_state.bus = pci_register_bus(dev, "pci", pci_unin_set_irq, pci_unin_map_irq, - pic, + NULL, pic, &d->pci_mmio, address_space_io, PCI_DEVFN(11, 0), 4); @@ -293,7 +293,7 @@ PCIBus *pci_pmac_u3_init(qemu_irq *pic, d->host_state.bus = pci_register_bus(dev, "pci", pci_unin_set_irq, pci_unin_map_irq, - pic, + NULL, pic, &d->pci_mmio, address_space_io, PCI_DEVFN(11, 0), 4); diff --git a/hw/versatile_pci.c b/hw/versatile_pci.c index ae53a8b..90c400e 100644 --- a/hw/versatile_pci.c +++ b/hw/versatile_pci.c @@ -68,7 +68,7 @@ static int pci_vpb_init(SysBusDevice *dev) sysbus_init_irq(dev, &s->irq[i]); } bus = pci_register_bus(&dev->qdev, "pci", - pci_vpb_set_irq, pci_vpb_map_irq, s->irq, + pci_vpb_set_irq, pci_vpb_map_irq, NULL, s->irq, get_system_memory(), get_system_io(), PCI_DEVFN(11, 0), 4);
Add a PCI IRQ path discovery function that walks from a given device to the host bridge, returning the mode (enabled/inverted/disabled) and the IRQ number that is reported to the attached interrupt controller. For this purpose, another host bridge callback function is introduced: route_intx_to_irq. It is so far only implemented by the PIIX3, other host bridges can be added later on as required. Will be used for KVM PCI device assignment and VFIO. Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com> --- hw/alpha_typhoon.c | 2 +- hw/apb_pci.c | 2 +- hw/bonito.c | 2 +- hw/grackle_pci.c | 1 + hw/gt64xxx.c | 1 + hw/pci.c | 18 +++++++++++++++++- hw/pci.h | 13 +++++++++++++ hw/pci_internals.h | 1 + hw/piix_pci.c | 23 ++++++++++++++++++++--- hw/ppc4xx_pci.c | 2 +- hw/ppce500_pci.c | 2 +- hw/prep_pci.c | 2 +- hw/sh_pci.c | 2 +- hw/spapr_pci.c | 2 +- hw/unin_pci.c | 4 ++-- hw/versatile_pci.c | 2 +- 16 files changed, 64 insertions(+), 15 deletions(-)