@@ -1,5 +1,7 @@
#include "kvm/devices.h"
#include "kvm/kvm.h"
+#include "kvm/pci.h"
+#include "kvm/virtio-mmio.h"
#include <linux/err.h>
#include <linux/rbtree.h>
@@ -27,6 +29,17 @@ int device__register(struct device_header *dev)
bus = &device_trees[dev->bus_type];
dev->dev_num = bus->dev_num++;
+ switch (dev->bus_type) {
+ case DEVICE_BUS_PCI:
+ pci__assign_irq(dev);
+ break;
+ case DEVICE_BUS_MMIO:
+ virtio_mmio_assign_irq(dev);
+ break;
+ default:
+ break;
+ }
+
node = &bus->root.rb_node;
while (*node) {
int num = rb_entry(*node, struct device_header, node)->dev_num;
@@ -358,10 +358,6 @@ int pci_shmem__init(struct kvm *kvm)
if (shmem_region == NULL)
return 0;
- /* Register good old INTx */
- pci_shmem_pci_device.irq_pin = 1;
- pci_shmem_pci_device.irq_line = irq__alloc_line();
-
/* Register MMIO space for MSI-X */
r = ioport__register(kvm, IOPORT_EMPTY, &shmem_pci__io_ops, IOPORT_SIZE, NULL);
if (r < 0)
@@ -65,8 +65,6 @@ struct framebuffer *vesa__init(struct kvm *kvm)
if (r < 0)
return ERR_PTR(r);
- vesa_pci_device.irq_pin = 1;
- vesa_pci_device.irq_line = irq__alloc_line();
vesa_base_addr = (u16)r;
vesa_pci_device.bar[0] = cpu_to_le32(vesa_base_addr | PCI_BASE_ADDRESS_SPACE_IO);
device__register(&vesa_device);
@@ -6,6 +6,7 @@
#include <linux/pci_regs.h>
#include <endian.h>
+#include "kvm/devices.h"
#include "kvm/kvm.h"
#include "kvm/msi.h"
@@ -88,6 +89,7 @@ int pci__init(struct kvm *kvm);
int pci__exit(struct kvm *kvm);
struct pci_device_header *pci__find_dev(u8 dev_num);
u32 pci_get_io_space_block(u32 size);
+void pci__assign_irq(struct device_header *dev_hdr);
void pci__config_wr(struct kvm *kvm, union pci_config_address addr, void *data, int size);
void pci__config_rd(struct kvm *kvm, union pci_config_address addr, void *data, int size);
@@ -56,4 +56,5 @@ int virtio_mmio_signal_config(struct kvm *kvm, struct virtio_device *vdev);
int virtio_mmio_exit(struct kvm *kvm, struct virtio_device *vdev);
int virtio_mmio_init(struct kvm *kvm, void *dev, struct virtio_device *vdev,
int device_id, int subsys_id, int class);
+void virtio_mmio_assign_irq(struct device_header *dev_hdr);
#endif
@@ -1,6 +1,7 @@
#include "kvm/devices.h"
#include "kvm/pci.h"
#include "kvm/ioport.h"
+#include "kvm/irq.h"
#include "kvm/util.h"
#include "kvm/kvm.h"
@@ -28,6 +29,20 @@ u32 pci_get_io_space_block(u32 size)
return block;
}
+void pci__assign_irq(struct device_header *dev_hdr)
+{
+ struct pci_device_header *pci_hdr = dev_hdr->data;
+
+ /*
+ * PCI supports only INTA#,B#,C#,D# per device.
+ *
+ * A#,B#,C#,D# are allowed for multifunctional devices so stick
+ * with A# for our single function devices.
+ */
+ pci_hdr->irq_pin = 1;
+ pci_hdr->irq_line = irq__alloc_line();
+}
+
static void *pci_config_address_ptr(u16 port)
{
unsigned long offset;
@@ -256,6 +256,14 @@ static void generate_virtio_mmio_fdt_node(void *fdt,
}
#endif
+void virtio_mmio_assign_irq(struct device_header *dev_hdr)
+{
+ struct virtio_mmio *vmmio = container_of(dev_hdr,
+ struct virtio_mmio,
+ dev_hdr);
+ vmmio->irq = irq__alloc_line();
+}
+
int virtio_mmio_init(struct kvm *kvm, void *dev, struct virtio_device *vdev,
int device_id, int subsys_id, int class)
{
@@ -276,7 +284,6 @@ int virtio_mmio_init(struct kvm *kvm, void *dev, struct virtio_device *vdev,
.queue_num_max = 256,
};
- vmmio->irq = irq__alloc_line();
vmmio->dev_hdr = (struct device_header) {
.bus_type = DEVICE_BUS_MMIO,
.data = generate_virtio_mmio_fdt_node,
@@ -408,8 +408,6 @@ int virtio_pci__init(struct kvm *kvm, void *dev, struct virtio_device *vdev,
if (kvm__supports_extension(kvm, KVM_CAP_SIGNAL_MSI))
vpci->features |= VIRTIO_PCI_F_SIGNAL_MSI;
- vpci->pci_hdr.irq_pin = 1;
- vpci->pci_hdr.irq_line = irq__alloc_line();
r = device__register(&vpci->dev_hdr);
if (r < 0)
goto free_msix_mmio;
For the MMIO and PCI buses, drivers typically allocate an IRQ line for their device before registering the device with the device tree for the relevant bus. This patch moves the IRQ allocation into the bus code, which is then called directly by the device tree when a new device is registered. IOPORT devices, however, tend to use hardcoded IRQs for legacy reasons, so they are still required to deal with their interrupts (which also require remapping for non-x86 architectures). Signed-off-by: Will Deacon <will.deacon@arm.com> --- tools/kvm/devices.c | 13 +++++++++++++ tools/kvm/hw/pci-shmem.c | 4 ---- tools/kvm/hw/vesa.c | 2 -- tools/kvm/include/kvm/pci.h | 2 ++ tools/kvm/include/kvm/virtio-mmio.h | 1 + tools/kvm/pci.c | 15 +++++++++++++++ tools/kvm/virtio/mmio.c | 9 ++++++++- tools/kvm/virtio/pci.c | 2 -- 8 files changed, 39 insertions(+), 9 deletions(-)