diff --git a/hw/alpha_typhoon.c b/hw/alpha_typhoon.c
index d5193bb..1056b50 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 57ead09..270a785 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 9a2b4a3..8878a11 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -320,10 +320,12 @@ PCIBus *pci_bus_new(DeviceState *parent, const char *name,
 
 void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq,
                   pci_route_pin_fn route_intx_pin,
+                  pci_route_irq_fn route_intx_to_irq,
                   void *irq_opaque, int nirq)
 {
     bus->set_irq = set_irq;
     bus->route_intx_pin = route_intx_pin;
+    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]));
@@ -340,6 +342,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_route_pin_fn route_intx_pin,
+                         pci_route_irq_fn route_intx_to_irq,
                          void *irq_opaque,
                          MemoryRegion *address_space_mem,
                          MemoryRegion *address_space_io,
@@ -349,7 +352,8 @@ 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, route_intx_pin, irq_opaque, nirq);
+    pci_bus_irqs(bus, set_irq, route_intx_pin, route_intx_to_irq, irq_opaque,
+                 nirq);
     return bus;
 }
 
@@ -1089,6 +1093,14 @@ 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 = dev->host_bus;
+
+    assert(bus->route_intx_to_irq);
+    return bus->route_intx_to_irq(bus->irq_opaque, dev->host_intx_pin[pin]);
+}
+
 /***********************************************************/
 /* monitor info on PCI */
 
diff --git a/hw/pci.h b/hw/pci.h
index 5b54e2d..bbba01e 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;
 
@@ -280,6 +289,7 @@ MemoryRegion *pci_address_space_io(PCIDevice *dev);
 
 typedef void (*pci_set_irq_fn)(void *opaque, int irq_num, int level);
 typedef int (*pci_route_pin_fn)(PCIDevice *pci_dev, int pin);
+typedef PCIINTxRoute (*pci_route_irq_fn)(void *opaque, int pin);
 
 typedef enum {
     PCI_HOTPLUG_DISABLED,
@@ -295,16 +305,19 @@ PCIBus *pci_bus_new(DeviceState *parent, const char *name,
                     uint8_t devfn_min);
 void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq,
                   pci_route_pin_fn route_intx_pin,
+                  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_route_pin_fn route_intx_pin,
+                         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 be5594b..6639232 100644
--- a/hw/pci_internals.h
+++ b/hw/pci_internals.h
@@ -19,6 +19,7 @@ struct PCIBus {
     uint8_t devfn_min;
     pci_set_irq_fn set_irq;
     pci_route_pin_fn route_intx_pin;
+    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 25b400a..4a43062 100644
--- a/hw/spapr_pci.c
+++ b/hw/spapr_pci.c
@@ -306,7 +306,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);
 
