Skip to contentSkip to conversation

pci: Preparations for KVM device assignment

PATCH Applied Jan Kiszka 4 participants 11 messages Jul 2, 2012 – Jul 19, 2012

lore
Share & tools
lore

Jan Kiszka

author
#0 lore raw

v2 cover pci: Preparations for KVM device assignment

Back to the roots: This implements pci_device_route_intx_to_irq and the PCI INTx routing notifier, but only those, without any caching for existing emulated devices. I tried to carry over all other refactorings and comment on the previous version.

Please review/merge.

Jan Kiszka (2):
pci: Add pci_device_route_intx_to_irq
pci: Add INTx routing notifier

 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           |   41 ++++++++++++++++++++++++++++++++++++++++-
 hw/pci.h           |   20 ++++++++++++++++++++
 hw/pci_internals.h |    1 +
 hw/piix_pci.c      |   25 ++++++++++++++++++++++---
 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, 96 insertions(+), 15 deletions(-)
Signature · 1 line
1.7.3.4
author
#1 lore raw

PATCH v2 1/2 pci: Add pci_device_route_intx_to_irq

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.

---
 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(-)
hw/alpha_typhoon.c +1 -1
index 872e112..fc2e4b3 100644
@@ -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;
 
hw/apb_pci.c +1 -1
index c28411a..d36cbb9 100644
@@ -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);
hw/bonito.c +1 -1
index 77786f8..7ce5993 100644
@@ -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;
hw/grackle_pci.c +1 -0
index 81ff3a3..f47d9fe 100644
@@ -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,
hw/gt64xxx.c +1 -0
index a2d0e5a..2418238 100644
@@ -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(),
hw/pci.c +17 -1
index 99a4304..311ba09 100644
@@ -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 */
 
hw/pci.h +13 -0
index 79d38fd..387111b 100644
@@ -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);
 
hw/pci_internals.h +1 -0
index e8bc9f6..c931b64 100644
@@ -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;
hw/piix_pci.c +20 -3
index 09e84f5..347177f 100644
@@ -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)
 {
hw/ppc4xx_pci.c +1 -1
index 203c3cd..224c4a0 100644
@@ -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;
 
hw/ppce500_pci.c +1 -1
index 0f60b24..dd924ae 100644
@@ -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;
 
hw/prep_pci.c +1 -1
index 38dbff4..9d7bec7 100644
@@ -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;
 
hw/sh_pci.c +1 -1
index 0cfac46..1cea12b 100644
@@ -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(),
hw/spapr_pci.c +1 -1
index 47ba5ff..ffede69 100644
@@ -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;
hw/unin_pci.c +2 -2
index 409bcd4..056e3bc 100644
@@ -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);
hw/versatile_pci.c +1 -1
index ae53a8b..90c400e 100644
@@ -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);
 
Signature · 1 line
1.7.3.4
Acked-by on v2 1/2
#2 lore raw

Re: [Qemu-devel] [PATCH v2 1/2] pci: Add pci_device_route_intx_to_irq

Quoted 10 lines · Jan Kiszka

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.

Quoted 347 lines
---
 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(-)
hw/alpha_typhoon.c +1 -1
index 872e112..fc2e4b3 100644
@@ -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;
 
hw/apb_pci.c +1 -1
index c28411a..d36cbb9 100644
@@ -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);
hw/bonito.c +1 -1
index 77786f8..7ce5993 100644
@@ -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;
hw/grackle_pci.c +1 -0
index 81ff3a3..f47d9fe 100644
@@ -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,
hw/gt64xxx.c +1 -0
index a2d0e5a..2418238 100644
@@ -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(),
hw/pci.c +17 -1
index 99a4304..311ba09 100644
@@ -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 */
 
hw/pci.h +13 -0
index 79d38fd..387111b 100644
@@ -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);
 
hw/pci_internals.h +1 -0
index e8bc9f6..c931b64 100644
@@ -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;
hw/piix_pci.c +20 -3
index 09e84f5..347177f 100644
@@ -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)
 {
hw/ppc4xx_pci.c +1 -1
index 203c3cd..224c4a0 100644
@@ -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;
 
hw/ppce500_pci.c +1 -1
index 0f60b24..dd924ae 100644
@@ -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;
 
hw/prep_pci.c +1 -1
index 38dbff4..9d7bec7 100644
@@ -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;
 
hw/sh_pci.c +1 -1
index 0cfac46..1cea12b 100644
@@ -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(),
hw/spapr_pci.c +1 -1
index 47ba5ff..ffede69 100644
@@ -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;
hw/unin_pci.c +2 -2
index 409bcd4..056e3bc 100644
@@ -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);
hw/versatile_pci.c +1 -1
index ae53a8b..90c400e 100644
@@ -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);
 
#3 lore raw

Re: [Qemu-devel] [PATCH v2 1/2] pci: Add pci_device_route_intx_to_irq

In reply to Jan Kiszka
Quoted 10 lines · Jan Kiszka

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.

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.

Quoted 349 lines
---
 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(-)
hw/alpha_typhoon.c +1 -1
index 872e112..fc2e4b3 100644
@@ -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;
 
hw/apb_pci.c +1 -1
index c28411a..d36cbb9 100644
@@ -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);
hw/bonito.c +1 -1
index 77786f8..7ce5993 100644
@@ -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;
hw/grackle_pci.c +1 -0
index 81ff3a3..f47d9fe 100644
@@ -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,
hw/gt64xxx.c +1 -0
index a2d0e5a..2418238 100644
@@ -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(),
hw/pci.c +17 -1
index 99a4304..311ba09 100644
@@ -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 */
 
hw/pci.h +13 -0
index 79d38fd..387111b 100644
@@ -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);
 
hw/pci_internals.h +1 -0
index e8bc9f6..c931b64 100644
@@ -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;
hw/piix_pci.c +20 -3
index 09e84f5..347177f 100644
@@ -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)
 {
hw/ppc4xx_pci.c +1 -1
index 203c3cd..224c4a0 100644
@@ -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;
 
hw/ppce500_pci.c +1 -1
index 0f60b24..dd924ae 100644
@@ -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;
 
hw/prep_pci.c +1 -1
index 38dbff4..9d7bec7 100644
@@ -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;
 
hw/sh_pci.c +1 -1
index 0cfac46..1cea12b 100644
@@ -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(),
hw/spapr_pci.c +1 -1
index 47ba5ff..ffede69 100644
@@ -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;
hw/unin_pci.c +2 -2
index 409bcd4..056e3bc 100644
@@ -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);
hw/versatile_pci.c +1 -1
index ae53a8b..90c400e 100644
@@ -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);
 
Signature · 1 line
1.7.3.4
author
#4 lore raw

PATCH v2 2/2 pci: Add INTx routing notifier

In reply to Jan Kiszka

This per-device notifier shall be triggered by any interrupt router along the path of a device's legacy interrupt signal on routing changes. For simplicity reasons and as this is a slow path anyway, no further details on the routing changes are provided. Instead, the callback is expected to use pci_device_route_intx_to_irq to check the effect of the change.

Will be used by KVM PCI device assignment and VFIO.

---
 hw/pci.c      |   23 +++++++++++++++++++++++
 hw/pci.h      |    7 +++++++
 hw/piix_pci.c |    2 ++
 3 files changed, 32 insertions(+), 0 deletions(-)
hw/pci.c +23 -0
index 311ba09..772141a 100644
@@ -1095,6 +1095,29 @@ PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin)
     return bus->route_intx_to_irq(bus->irq_opaque, pin);
 }
 
+void pci_bus_fire_intx_routing_notifier(PCIBus *bus)
+{
+    PCIDevice *dev;
+    PCIBus *sec;
+    int i;
+
+    for (i = 0; i < ARRAY_SIZE(bus->devices); ++i) {
+        dev = bus->devices[i];
+        if (dev && dev->intx_routing_notifier) {
+            dev->intx_routing_notifier(dev);
+        }
+        QLIST_FOREACH(sec, &bus->child, sibling) {
+            pci_bus_fire_intx_routing_notifier(sec);
+        }
+    }
+}
+
+void pci_device_set_intx_routing_notifier(PCIDevice *dev,
+                                          PCIINTxRoutingNotifier notifier)
+{
+    dev->intx_routing_notifier = notifier;
+}
+
 /***********************************************************/
 /* monitor info on PCI */
 
hw/pci.h +7 -0
index 387111b..c4382a1 100644
@@ -182,6 +182,7 @@ typedef struct PCIDeviceClass {
     const char *romfile;
 } PCIDeviceClass;
 
+typedef void (*PCIINTxRoutingNotifier)(PCIDevice *dev);
 typedef int (*MSIVectorUseNotifier)(PCIDevice *dev, unsigned int vector,
                                       MSIMessage msg);
 typedef void (*MSIVectorReleaseNotifier)(PCIDevice *dev, unsigned int vector);
@@ -259,6 +260,9 @@ struct PCIDevice {
     MemoryRegion rom;
     uint32_t rom_bar;
 
+    /* INTx routing notifier */
+    PCIINTxRoutingNotifier intx_routing_notifier;
+
     /* MSI-X notifiers */
     MSIVectorUseNotifier msix_vector_use_notifier;
     MSIVectorReleaseNotifier msix_vector_release_notifier;
@@ -319,6 +323,9 @@ PCIBus *pci_register_bus(DeviceState *parent, const char *name,
                          MemoryRegion *address_space_io,
                          uint8_t devfn_min, int nirq);
 PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin);
+void pci_bus_fire_intx_routing_notifier(PCIBus *bus);
+void pci_device_set_intx_routing_notifier(PCIDevice *dev,
+                                          PCIINTxRoutingNotifier notifier);
 void pci_device_reset(PCIDevice *dev);
 void pci_bus_reset(PCIBus *bus);
 
hw/piix_pci.c +2 -0
index 347177f..8fd21f3 100644
@@ -422,6 +422,8 @@ static void piix3_write_config(PCIDevice *dev,
     if (ranges_overlap(address, len, PIIX_PIRQC, 4)) {
         PIIX3State *piix3 = DO_UPCAST(PIIX3State, dev, dev);
         int pic_irq;
+
+        pci_bus_fire_intx_routing_notifier(piix3->dev.bus);
         piix3_update_irq_levels(piix3);
         for (pic_irq = 0; pic_irq < PIIX_NUM_PIC_IRQS; pic_irq++) {
             piix3_set_irq_pic(piix3, pic_irq);
Signature · 1 line
1.7.3.4
#5 lore raw

Re: [Qemu-devel] [PATCH v2 2/2] pci: Add INTx routing notifier

Quoted 37 lines · Jan Kiszka

This per-device notifier shall be triggered by any interrupt router along the path of a device's legacy interrupt signal on routing changes. For simplicity reasons and as this is a slow path anyway, no further details on the routing changes are provided. Instead, the callback is expected to use pci_device_route_intx_to_irq to check the effect of the change.

Will be used by KVM PCI device assignment and VFIO.

---
 hw/pci.c      |   23 +++++++++++++++++++++++
 hw/pci.h      |    7 +++++++
 hw/piix_pci.c |    2 ++
 3 files changed, 32 insertions(+), 0 deletions(-)
hw/pci.c +13 -0
index 311ba09..772141a 100644
@@ -1095,6 +1095,29 @@ PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin)
     return bus->route_intx_to_irq(bus->irq_opaque, pin);
 }
 
+void pci_bus_fire_intx_routing_notifier(PCIBus *bus)
+{
+    PCIDevice *dev;
+    PCIBus *sec;
+    int i;
+
+    for (i = 0; i < ARRAY_SIZE(bus->devices); ++i) {
+        dev = bus->devices[i];
+        if (dev && dev->intx_routing_notifier) {
+            dev->intx_routing_notifier(dev);
+        }
+        QLIST_FOREACH(sec, &bus->child, sibling) {
+            pci_bus_fire_intx_routing_notifier(sec);

hw/pci.c PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin) · line 1120

Quoted 10 lines
hw/pci.c +10 -0
+        }
+    }
+}
+
+void pci_device_set_intx_routing_notifier(PCIDevice *dev,
+                                          PCIINTxRoutingNotifier notifier)
+{
+    dev->intx_routing_notifier = notifier;
+}
+

nit, wish there was also an unset here too. If we switch to MSI mode, there's not much point in calling the notifier, so the driver could unset it. Also nice to have a set in the initfn and matching unset in exitfn. There's potentially a race between the driver freeing data and the pci device going away, but I don't know if we can hit it in qemu. Thanks,

Alex

Quoted 48 lines
hw/pci.c +0 -0
 /***********************************************************/
 /* monitor info on PCI */
 
hw/pci.h +7 -0
index 387111b..c4382a1 100644
@@ -182,6 +182,7 @@ typedef struct PCIDeviceClass {
     const char *romfile;
 } PCIDeviceClass;
 
+typedef void (*PCIINTxRoutingNotifier)(PCIDevice *dev);
 typedef int (*MSIVectorUseNotifier)(PCIDevice *dev, unsigned int vector,
                                       MSIMessage msg);
 typedef void (*MSIVectorReleaseNotifier)(PCIDevice *dev, unsigned int vector);
@@ -259,6 +260,9 @@ struct PCIDevice {
     MemoryRegion rom;
     uint32_t rom_bar;
 
+    /* INTx routing notifier */
+    PCIINTxRoutingNotifier intx_routing_notifier;
+
     /* MSI-X notifiers */
     MSIVectorUseNotifier msix_vector_use_notifier;
     MSIVectorReleaseNotifier msix_vector_release_notifier;
@@ -319,6 +323,9 @@ PCIBus *pci_register_bus(DeviceState *parent, const char *name,
                          MemoryRegion *address_space_io,
                          uint8_t devfn_min, int nirq);
 PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin);
+void pci_bus_fire_intx_routing_notifier(PCIBus *bus);
+void pci_device_set_intx_routing_notifier(PCIDevice *dev,
+                                          PCIINTxRoutingNotifier notifier);
 void pci_device_reset(PCIDevice *dev);
 void pci_bus_reset(PCIBus *bus);
 
hw/piix_pci.c +2 -0
index 347177f..8fd21f3 100644
@@ -422,6 +422,8 @@ static void piix3_write_config(PCIDevice *dev,
     if (ranges_overlap(address, len, PIIX_PIRQC, 4)) {
         PIIX3State *piix3 = DO_UPCAST(PIIX3State, dev, dev);
         int pic_irq;
+
+        pci_bus_fire_intx_routing_notifier(piix3->dev.bus);
         piix3_update_irq_levels(piix3);
         for (pic_irq = 0; pic_irq < PIIX_NUM_PIC_IRQS; pic_irq++) {
             piix3_set_irq_pic(piix3, pic_irq);
author
#6 lore raw

Re: [Qemu-devel] [PATCH v2 2/2] pci: Add INTx routing notifier

Quoted 44 lines · Alex Williamson
Quoted 43 lines · Jan Kiszka

This per-device notifier shall be triggered by any interrupt router along the path of a device's legacy interrupt signal on routing changes. For simplicity reasons and as this is a slow path anyway, no further details on the routing changes are provided. Instead, the callback is expected to use pci_device_route_intx_to_irq to check the effect of the change.

Will be used by KVM PCI device assignment and VFIO.

---
 hw/pci.c      |   23 +++++++++++++++++++++++
 hw/pci.h      |    7 +++++++
 hw/piix_pci.c |    2 ++
 3 files changed, 32 insertions(+), 0 deletions(-)
hw/pci.c +19 -0
index 311ba09..772141a 100644
@@ -1095,6 +1095,29 @@ PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin)
     return bus->route_intx_to_irq(bus->irq_opaque, pin);
 }
 
+void pci_bus_fire_intx_routing_notifier(PCIBus *bus)
+{
+    PCIDevice *dev;
+    PCIBus *sec;
+    int i;
+
+    for (i = 0; i < ARRAY_SIZE(bus->devices); ++i) {
+        dev = bus->devices[i];
+        if (dev && dev->intx_routing_notifier) {
+            dev->intx_routing_notifier(dev);
+        }
+        QLIST_FOREACH(sec, &bus->child, sibling) {
+            pci_bus_fire_intx_routing_notifier(sec);
+        }
+    }
+}
+
+void pci_device_set_intx_routing_notifier(PCIDevice *dev,
+                                          PCIINTxRoutingNotifier notifier)
Quoted 8 lines

hw/pci.c PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin) · line 1120

Quoted 4 lines
hw/pci.c +4 -0
+{
+    dev->intx_routing_notifier = notifier;
+}
+

nit, wish there was also an unset here too. If we switch to MSI mode, there's not much point in calling the notifier, so the driver could unset it.

We could add

static inline pci_device_unset_intx_routing_notifier(PCIDevice *dev)

{
    dev->intx_routing_notifier = NULL;
}

- or simply do pci_device_set_intx_routing_notifier(dev, NULL);.

Quoted 3 lines

Also nice to have a set in the initfn and matching unset in
exitfn. There's potentially a race between the driver freeing data and the pci device going away, but I don't know if we can hit it in qemu.

Everything should be synchronized by the BQL, so far. Or not?

Jan

Signature · 2 lines
Siemens AG, Corporate Technology, CT RTC ITP SDP-DE
Corporate Competence Center Embedded Linux
#7 lore raw

Re: [Qemu-devel] [PATCH v2 2/2] pci: Add INTx routing notifier

Quoted 54 lines · Jan Kiszka
Quoted 44 lines · Alex Williamson
Quoted 43 lines · Jan Kiszka

This per-device notifier shall be triggered by any interrupt router along the path of a device's legacy interrupt signal on routing changes. For simplicity reasons and as this is a slow path anyway, no further details on the routing changes are provided. Instead, the callback is expected to use pci_device_route_intx_to_irq to check the effect of the change.

Will be used by KVM PCI device assignment and VFIO.

---
 hw/pci.c      |   23 +++++++++++++++++++++++
 hw/pci.h      |    7 +++++++
 hw/piix_pci.c |    2 ++
 3 files changed, 32 insertions(+), 0 deletions(-)
hw/pci.c +19 -0
index 311ba09..772141a 100644
@@ -1095,6 +1095,29 @@ PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin)
     return bus->route_intx_to_irq(bus->irq_opaque, pin);
 }
 
+void pci_bus_fire_intx_routing_notifier(PCIBus *bus)
+{
+    PCIDevice *dev;
+    PCIBus *sec;
+    int i;
+
+    for (i = 0; i < ARRAY_SIZE(bus->devices); ++i) {
+        dev = bus->devices[i];
+        if (dev && dev->intx_routing_notifier) {
+            dev->intx_routing_notifier(dev);
+        }
+        QLIST_FOREACH(sec, &bus->child, sibling) {
+            pci_bus_fire_intx_routing_notifier(sec);
+        }
+    }
+}
+
+void pci_device_set_intx_routing_notifier(PCIDevice *dev,
+                                          PCIINTxRoutingNotifier notifier)
Quoted 8 lines

hw/pci.c PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin) · line 1120

Quoted 4 lines
hw/pci.c +4 -0
+{
+    dev->intx_routing_notifier = notifier;
+}
+

nit, wish there was also an unset here too. If we switch to MSI mode, there's not much point in calling the notifier, so the driver could unset it.

Quoted 8 lines

We could add

static inline pci_device_unset_intx_routing_notifier(PCIDevice *dev)

{
    dev->intx_routing_notifier = NULL;
}

- or simply do pci_device_set_intx_routing_notifier(dev, NULL);.

Duh... sorry, too early yet for me ;) This is fine.

Quoted 5 lines
Quoted 3 lines

Also nice to have a set in the initfn and matching unset in
exitfn. There's potentially a race between the driver freeing data and the pci device going away, but I don't know if we can hit it in qemu.

Everything should be synchronized by the BQL, so far. Or not?

Yes, I imagine the lock protects getting called in that gap. Thanks,

Alex

#8 lore raw

Re: [Qemu-devel] [PATCH v2 2/2] pci: Add INTx routing notifier

In reply to Jan Kiszka
Quoted 10 lines · Jan Kiszka

This per-device notifier shall be triggered by any interrupt router along the path of a device's legacy interrupt signal on routing changes. For simplicity reasons and as this is a slow path anyway, no further details on the routing changes are provided. Instead, the callback is expected to use pci_device_route_intx_to_irq to check the effect of the change.

Will be used by KVM PCI device assignment and VFIO.

Thanks, applied.

Quoted 87 lines
---
 hw/pci.c      |   23 +++++++++++++++++++++++
 hw/pci.h      |    7 +++++++
 hw/piix_pci.c |    2 ++
 3 files changed, 32 insertions(+), 0 deletions(-)
hw/pci.c +23 -0
index 311ba09..772141a 100644
@@ -1095,6 +1095,29 @@ PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin)
     return bus->route_intx_to_irq(bus->irq_opaque, pin);
 }
 
+void pci_bus_fire_intx_routing_notifier(PCIBus *bus)
+{
+    PCIDevice *dev;
+    PCIBus *sec;
+    int i;
+
+    for (i = 0; i < ARRAY_SIZE(bus->devices); ++i) {
+        dev = bus->devices[i];
+        if (dev && dev->intx_routing_notifier) {
+            dev->intx_routing_notifier(dev);
+        }
+        QLIST_FOREACH(sec, &bus->child, sibling) {
+            pci_bus_fire_intx_routing_notifier(sec);
+        }
+    }
+}
+
+void pci_device_set_intx_routing_notifier(PCIDevice *dev,
+                                          PCIINTxRoutingNotifier notifier)
+{
+    dev->intx_routing_notifier = notifier;
+}
+
 /***********************************************************/
 /* monitor info on PCI */
 
hw/pci.h +7 -0
index 387111b..c4382a1 100644
@@ -182,6 +182,7 @@ typedef struct PCIDeviceClass {
     const char *romfile;
 } PCIDeviceClass;
 
+typedef void (*PCIINTxRoutingNotifier)(PCIDevice *dev);
 typedef int (*MSIVectorUseNotifier)(PCIDevice *dev, unsigned int vector,
                                       MSIMessage msg);
 typedef void (*MSIVectorReleaseNotifier)(PCIDevice *dev, unsigned int vector);
@@ -259,6 +260,9 @@ struct PCIDevice {
     MemoryRegion rom;
     uint32_t rom_bar;
 
+    /* INTx routing notifier */
+    PCIINTxRoutingNotifier intx_routing_notifier;
+
     /* MSI-X notifiers */
     MSIVectorUseNotifier msix_vector_use_notifier;
     MSIVectorReleaseNotifier msix_vector_release_notifier;
@@ -319,6 +323,9 @@ PCIBus *pci_register_bus(DeviceState *parent, const char *name,
                          MemoryRegion *address_space_io,
                          uint8_t devfn_min, int nirq);
 PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin);
+void pci_bus_fire_intx_routing_notifier(PCIBus *bus);
+void pci_device_set_intx_routing_notifier(PCIDevice *dev,
+                                          PCIINTxRoutingNotifier notifier);
 void pci_device_reset(PCIDevice *dev);
 void pci_bus_reset(PCIBus *bus);
 
hw/piix_pci.c +2 -0
index 347177f..8fd21f3 100644
@@ -422,6 +422,8 @@ static void piix3_write_config(PCIDevice *dev,
     if (ranges_overlap(address, len, PIIX_PIRQC, 4)) {
         PIIX3State *piix3 = DO_UPCAST(PIIX3State, dev, dev);
         int pic_irq;
+
+        pci_bus_fire_intx_routing_notifier(piix3->dev.bus);
         piix3_update_irq_levels(piix3);
         for (pic_irq = 0; pic_irq < PIIX_NUM_PIC_IRQS; pic_irq++) {
             piix3_set_irq_pic(piix3, pic_irq);
Signature · 1 line
1.7.3.4
#9 lore raw
In reply to Jan Kiszka
Quoted 20 lines · Jan Kiszka

Back to the roots: This implements pci_device_route_intx_to_irq and the PCI INTx routing notifier, but only those, without any caching for existing emulated devices. I tried to carry over all other refactorings and comment on the previous version.

Please review/merge.

Jan Kiszka (2):
pci: Add pci_device_route_intx_to_irq
pci: Add INTx routing notifier

 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           |   41 ++++++++++++++++++++++++++++++++++++++++-
 hw/pci.h           |   20 ++++++++++++++++++++
 hw/pci_internals.h |    1 +
 hw/piix_pci.c      |   25 ++++++++++++++++++++++---
Quoted 8 lines
 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, 96 insertions(+), 15 deletions(-)

OK this is not very pretty but I can live with this. But - can you rebase to the tip of pci branch please?

Quoted 1 line

1.7.3.4

#10 lore raw
Quoted 30 lines · Michael S. Tsirkin
Quoted 20 lines · Jan Kiszka

Back to the roots: This implements pci_device_route_intx_to_irq and the PCI INTx routing notifier, but only those, without any caching for existing emulated devices. I tried to carry over all other refactorings and comment on the previous version.

Please review/merge.

Jan Kiszka (2):
pci: Add pci_device_route_intx_to_irq
pci: Add INTx routing notifier

 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           |   41 ++++++++++++++++++++++++++++++++++++++++-
 hw/pci.h           |   20 ++++++++++++++++++++
 hw/pci_internals.h |    1 +
 hw/piix_pci.c      |   25 ++++++++++++++++++++++---
Quoted 8 lines
 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, 96 insertions(+), 15 deletions(-)
Quoted 2 lines

OK this is not very pretty but I can live with this. But - can you rebase to the tip of pci branch please?

Hmm, someone asked me to work against master. Luckily, both patches apply cleanly on top of your current tree.

Thanks,
Jan