提交 3afa9bb4 编写于 作者: M Michael S. Tsirkin

pci: Add pci_device_route_intx_to_irq

Device assigned on KVM needs to know the mode
(enabled/inverted/disabled) and the IRQ number that a given device
triggers in the attached interrupt controller.

Add a PCI IRQ path discovery function that walks from a given device to
the host bridge, and gets this information.  For
this purpose, a 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.

Based on patch by Jan Kiszka, with minor tweaks.
Signed-off-by: NJan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: NMichael S. Tsirkin <mst@redhat.com>
上级 7cf1b0fd
...@@ -1066,6 +1066,26 @@ static void pci_set_irq(void *opaque, int irq_num, int level) ...@@ -1066,6 +1066,26 @@ static void pci_set_irq(void *opaque, int irq_num, int level)
pci_change_irq_level(pci_dev, irq_num, change); pci_change_irq_level(pci_dev, irq_num, change);
} }
/* Special hooks used by device assignment */
void pci_bus_set_route_irq_fn(PCIBus *bus, pci_route_irq_fn route_intx_to_irq)
{
assert(!bus->parent_dev);
bus->route_intx_to_irq = route_intx_to_irq;
}
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 */ /* monitor info on PCI */
......
...@@ -141,6 +141,15 @@ enum { ...@@ -141,6 +141,15 @@ enum {
#define PCI_DEVICE_GET_CLASS(obj) \ #define PCI_DEVICE_GET_CLASS(obj) \
OBJECT_GET_CLASS(PCIDeviceClass, (obj), TYPE_PCI_DEVICE) 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 { typedef struct PCIDeviceClass {
DeviceClass parent_class; DeviceClass parent_class;
...@@ -278,6 +287,7 @@ MemoryRegion *pci_address_space_io(PCIDevice *dev); ...@@ -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 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 int (*pci_map_irq_fn)(PCIDevice *pci_dev, int irq_num);
typedef PCIINTxRoute (*pci_route_irq_fn)(void *opaque, int pin);
typedef enum { typedef enum {
PCI_HOTPLUG_DISABLED, PCI_HOTPLUG_DISABLED,
...@@ -306,6 +316,8 @@ PCIBus *pci_register_bus(DeviceState *parent, const char *name, ...@@ -306,6 +316,8 @@ PCIBus *pci_register_bus(DeviceState *parent, const char *name,
MemoryRegion *address_space_mem, MemoryRegion *address_space_mem,
MemoryRegion *address_space_io, MemoryRegion *address_space_io,
uint8_t devfn_min, int nirq); uint8_t devfn_min, int nirq);
void pci_bus_set_route_irq_fn(PCIBus *, pci_route_irq_fn);
PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin);
void pci_device_reset(PCIDevice *dev); void pci_device_reset(PCIDevice *dev);
void pci_bus_reset(PCIBus *bus); void pci_bus_reset(PCIBus *bus);
......
...@@ -19,6 +19,7 @@ struct PCIBus { ...@@ -19,6 +19,7 @@ struct PCIBus {
uint8_t devfn_min; uint8_t devfn_min;
pci_set_irq_fn set_irq; pci_set_irq_fn set_irq;
pci_map_irq_fn map_irq; pci_map_irq_fn map_irq;
pci_route_irq_fn route_intx_to_irq;
pci_hotplug_fn hotplug; pci_hotplug_fn hotplug;
DeviceState *hotplug_qdev; DeviceState *hotplug_qdev;
void *irq_opaque; void *irq_opaque;
......
...@@ -89,6 +89,7 @@ struct PCII440FXState { ...@@ -89,6 +89,7 @@ struct PCII440FXState {
#define I440FX_SMRAM 0x72 #define I440FX_SMRAM 0x72
static void piix3_set_irq(void *opaque, int pirq, int level); 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, static void piix3_write_config_xen(PCIDevice *dev,
uint32_t address, uint32_t val, int len); uint32_t address, uint32_t val, int len);
...@@ -315,6 +316,7 @@ static PCIBus *i440fx_common_init(const char *device_name, ...@@ -315,6 +316,7 @@ static PCIBus *i440fx_common_init(const char *device_name,
pci_create_simple_multifunction(b, -1, true, "PIIX3")); pci_create_simple_multifunction(b, -1, true, "PIIX3"));
pci_bus_irqs(b, piix3_set_irq, pci_slot_get_pirq, piix3, pci_bus_irqs(b, piix3_set_irq, pci_slot_get_pirq, piix3,
PIIX_NUM_PIRQS); PIIX_NUM_PIRQS);
pci_bus_set_route_irq_fn(b, piix3_route_intx_pin_to_irq);
} }
piix3->pic = pic; piix3->pic = pic;
*isa_bus = DO_UPCAST(ISABus, qbus, *isa_bus = DO_UPCAST(ISABus, qbus,
...@@ -386,6 +388,22 @@ static void piix3_set_irq(void *opaque, int pirq, int level) ...@@ -386,6 +388,22 @@ static void piix3_set_irq(void *opaque, int pirq, int level)
piix3_set_irq_level(piix3, pirq, 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 */ /* irq routing is changed. so rebuild bitmap */
static void piix3_update_irq_levels(PIIX3State *piix3) static void piix3_update_irq_levels(PIIX3State *piix3)
{ {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册