pci: Preparations for KVM device assignment
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
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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -89,6 +89,7 @@ struct PCII440FXState {#define I440FX_SMRAM 0x72static 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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
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.
Signed-off-by Jan Kiszka <[email protected]>
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@@ -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@@ -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@@ -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@@ -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@@ -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@@ -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@@ -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@@ -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@@ -89,6 +89,7 @@ struct PCII440FXState {#define I440FX_SMRAM 0x72static 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@@ -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@@ -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@@ -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@@ -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@@ -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@@ -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@@ -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 );
Re: [Qemu-devel] [PATCH v2 1/2] pci: Add pci_device_route_intx_to_irq
In reply to Jan KiszkaQuoted 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.
Signed-off-by Jan Kiszka <[email protected]>
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@@ -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@@ -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@@ -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@@ -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@@ -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@@ -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@@ -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@@ -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@@ -89,6 +89,7 @@ struct PCII440FXState {#define I440FX_SMRAM 0x72static 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@@ -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@@ -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@@ -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@@ -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@@ -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@@ -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@@ -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
PATCH v2 2/2 pci: Add INTx routing notifier
In reply to Jan KiszkaThis 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
@@ -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
@@ -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
@@ -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
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_irqto check the effect of the change.Will be used by KVM PCI device assignment and VFIO.
Signed-off-by Jan Kiszka <[email protected]>--- 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@@ -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@@ -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@@ -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);
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_irqto check the effect of the change.Will be used by KVM PCI device assignment and VFIO.
Signed-off-by Jan Kiszka <[email protected]>--- 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@@ -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
Alex Williamson
Acked-byRe: [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_irqto check the effect of the change.Will be used by KVM PCI device assignment and VFIO.
Signed-off-by Jan Kiszka <[email protected]>--- 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@@ -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
Michael S. Tsirkin
AppliedRe: [Qemu-devel] [PATCH v2 2/2] pci: Add INTx routing notifier
In reply to Jan KiszkaQuoted 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_irqto check the effect of the change.Will be used by KVM PCI device assignment and VFIO.
Signed-off-by Jan Kiszka <[email protected]>
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@@ -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@@ -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@@ -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
Quoted 20 lines · Jan Kiszka
Back to the roots: This implements
pci_device_route_intx_to_irqand 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: Addpci_device_route_intx_to_irq
pci: Add INTx routing notifierhw/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
Quoted 30 lines · Michael S. Tsirkin
Quoted 20 lines · Jan Kiszka
Back to the roots: This implements
pci_device_route_intx_to_irqand 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: Addpci_device_route_intx_to_irq
pci: Add INTx routing notifierhw/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