PCI devices are currently registered into the pci_devices array via the
pci__register function, which can then be indexed later by architecture
code to construct device tree nodes. For MMIO devices, there is no such
utility.

Rather than invent a similar mechanism for MMIO, this patch creates a
global device registration mechanism, which allows the device type to be
specified when registered or indexing a device. Current users of the pci
registration code are migrated to the new infrastructure and virtio MMIO
devices are registered at init time.

Signed-off-by: Will Deacon <will.dea...@arm.com>
---
 tools/kvm/Makefile                  |    1 +
 tools/kvm/devices.c                 |   24 +++++++++++++++++++++
 tools/kvm/hw/pci-shmem.c            |    8 ++++++-
 tools/kvm/hw/vesa.c                 |    8 ++++++-
 tools/kvm/include/kvm/devices.h     |   21 ++++++++++++++++++
 tools/kvm/include/kvm/pci.h         |    2 -
 tools/kvm/include/kvm/virtio-mmio.h |    1 +
 tools/kvm/include/kvm/virtio-pci.h  |    2 +
 tools/kvm/pci.c                     |   40 ++++++++++++----------------------
 tools/kvm/powerpc/irq.c             |    3 +-
 tools/kvm/powerpc/spapr_pci.c       |    2 +-
 tools/kvm/virtio/mmio.c             |    7 ++++++
 tools/kvm/virtio/pci.c              |    7 +++++-
 13 files changed, 93 insertions(+), 33 deletions(-)
 create mode 100644 tools/kvm/devices.c
 create mode 100644 tools/kvm/include/kvm/devices.h

diff --git a/tools/kvm/Makefile b/tools/kvm/Makefile
index c105de1..5da416f 100644
--- a/tools/kvm/Makefile
+++ b/tools/kvm/Makefile
@@ -50,6 +50,7 @@ OBJS  += builtin-run.o
 OBJS   += builtin-setup.o
 OBJS   += builtin-stop.o
 OBJS   += builtin-version.o
+OBJS   += devices.o
 OBJS   += disk/core.o
 OBJS   += framebuffer.o
 OBJS   += guest_compat.o
diff --git a/tools/kvm/devices.c b/tools/kvm/devices.c
new file mode 100644
index 0000000..f9666b9
--- /dev/null
+++ b/tools/kvm/devices.c
@@ -0,0 +1,24 @@
+#include "kvm/devices.h"
+#include "kvm/kvm.h"
+
+#include <linux/err.h>
+
+static struct device_header *devices[KVM_MAX_DEVICES];
+
+int device__register(struct device_header *dev, u8 dev_num)
+{
+       if (dev_num >= KVM_MAX_DEVICES)
+               return -ENOSPC;
+
+       devices[dev_num] = dev;
+
+       return 0;
+}
+
+struct device_header *device__find_dev(u8 dev_num)
+{
+       if (dev_num >= KVM_MAX_DEVICES)
+               return ERR_PTR(-EOVERFLOW);
+
+       return devices[dev_num];
+}
diff --git a/tools/kvm/hw/pci-shmem.c b/tools/kvm/hw/pci-shmem.c
index 4161335..f06c013 100644
--- a/tools/kvm/hw/pci-shmem.c
+++ b/tools/kvm/hw/pci-shmem.c
@@ -1,3 +1,4 @@
+#include "kvm/devices.h"
 #include "kvm/pci-shmem.h"
 #include "kvm/virtio-pci-dev.h"
 #include "kvm/irq.h"
@@ -30,6 +31,11 @@ static struct pci_device_header pci_shmem_pci_device = {
        .msix.pba_offset = cpu_to_le32(0x1001),         /* Use BAR 1 */
 };
 
+static struct device_header pci_shmem_device = {
+       .bus_type       = DEVICE_BUS_PCI,
+       .data           = &pci_shmem_pci_device,
+};
+
 /* registers for the Inter-VM shared memory device */
 enum ivshmem_registers {
        INTRMASK = 0,
@@ -384,7 +390,7 @@ int pci_shmem__init(struct kvm *kvm)
        pci_shmem_pci_device.bar[2] = cpu_to_le32(shmem_region->phys_addr | 
PCI_BASE_ADDRESS_SPACE_MEMORY);
        pci_shmem_pci_device.bar_size[2] = shmem_region->size;
 
-       pci__register(&pci_shmem_pci_device, dev);
+       device__register(&pci_shmem_device, dev);
 
        /* Open shared memory and plug it into the guest */
        mem = setup_shmem(shmem_region->handle, shmem_region->size,
diff --git a/tools/kvm/hw/vesa.c b/tools/kvm/hw/vesa.c
index a211491..630d8c9 100644
--- a/tools/kvm/hw/vesa.c
+++ b/tools/kvm/hw/vesa.c
@@ -1,5 +1,6 @@
 #include "kvm/vesa.h"
 
+#include "kvm/devices.h"
 #include "kvm/virtio-pci-dev.h"
 #include "kvm/framebuffer.h"
 #include "kvm/kvm-cpu.h"
@@ -44,6 +45,11 @@ static struct pci_device_header vesa_pci_device = {
        .bar_size[1]            = VESA_MEM_SIZE,
 };
 
+static struct device_header vesa_device = {
+       .bus_type       = DEVICE_BUS_PCI,
+       .data           = &vesa_pci_device,
+};
+
 static struct framebuffer vesafb;
 
 struct framebuffer *vesa__init(struct kvm *kvm)
@@ -68,7 +74,7 @@ struct framebuffer *vesa__init(struct kvm *kvm)
        vesa_pci_device.irq_line        = line;
        vesa_base_addr                  = (u16)r;
        vesa_pci_device.bar[0]          = cpu_to_le32(vesa_base_addr | 
PCI_BASE_ADDRESS_SPACE_IO);
-       pci__register(&vesa_pci_device, dev);
+       device__register(&vesa_device, dev);
 
        mem = mmap(NULL, VESA_MEM_SIZE, PROT_RW, MAP_ANON_NORESERVE, -1, 0);
        if (mem == MAP_FAILED)
diff --git a/tools/kvm/include/kvm/devices.h b/tools/kvm/include/kvm/devices.h
new file mode 100644
index 0000000..3546904
--- /dev/null
+++ b/tools/kvm/include/kvm/devices.h
@@ -0,0 +1,21 @@
+#ifndef KVM__DEVICES_H
+#define KVM__DEVICES_H
+
+#include <linux/types.h>
+
+#define KVM_MAX_DEVICES        256
+
+enum device_bus_type {
+       DEVICE_BUS_PCI,
+       DEVICE_BUS_MMIO,
+};
+
+struct device_header {
+       enum device_bus_type    bus_type;
+       void                    *data;
+};
+
+int device__register(struct device_header *dev, u8 dev_num);
+struct device_header *device__find_dev(u8 dev_num);
+
+#endif /* KVM__DEVICES_H */
diff --git a/tools/kvm/include/kvm/pci.h b/tools/kvm/include/kvm/pci.h
index 26639b5..3da3811 100644
--- a/tools/kvm/include/kvm/pci.h
+++ b/tools/kvm/include/kvm/pci.h
@@ -9,7 +9,6 @@
 #include "kvm/kvm.h"
 #include "kvm/msi.h"
 
-#define PCI_MAX_DEVICES                256
 /*
  * PCI Configuration Mechanism #1 I/O ports. See Section 3.7.4.1.
  * ("Configuration Mechanism #1") of the PCI Local Bus Specification 2.1 for
@@ -86,7 +85,6 @@ struct pci_device_header {
 
 int pci__init(struct kvm *kvm);
 int pci__exit(struct kvm *kvm);
-int pci__register(struct pci_device_header *dev, u8 dev_num);
 struct pci_device_header *pci__find_dev(u8 dev_num);
 u32 pci_get_io_space_block(u32 size);
 void pci__config_wr(struct kvm *kvm, union pci_config_address addr, void 
*data, int size);
diff --git a/tools/kvm/include/kvm/virtio-mmio.h 
b/tools/kvm/include/kvm/virtio-mmio.h
index e0ede3c..983c8fc 100644
--- a/tools/kvm/include/kvm/virtio-mmio.h
+++ b/tools/kvm/include/kvm/virtio-mmio.h
@@ -47,6 +47,7 @@ struct virtio_mmio {
        struct kvm              *kvm;
        u8                      irq;
        struct virtio_mmio_hdr  hdr;
+       struct device_header    dev_hdr;
        struct virtio_mmio_ioevent_param ioeventfds[VIRTIO_MMIO_MAX_VQ];
 };
 
diff --git a/tools/kvm/include/kvm/virtio-pci.h 
b/tools/kvm/include/kvm/virtio-pci.h
index 44130e0c..6d9a558 100644
--- a/tools/kvm/include/kvm/virtio-pci.h
+++ b/tools/kvm/include/kvm/virtio-pci.h
@@ -1,6 +1,7 @@
 #ifndef KVM__VIRTIO_PCI_H
 #define KVM__VIRTIO_PCI_H
 
+#include "kvm/devices.h"
 #include "kvm/pci.h"
 
 #include <linux/types.h>
@@ -19,6 +20,7 @@ struct virtio_pci_ioevent_param {
 
 struct virtio_pci {
        struct pci_device_header pci_hdr;
+       struct device_header    dev_hdr;
        void                    *dev;
 
        u16                     base_addr;
diff --git a/tools/kvm/pci.c b/tools/kvm/pci.c
index c77d3cc..0c70343 100644
--- a/tools/kvm/pci.c
+++ b/tools/kvm/pci.c
@@ -1,3 +1,4 @@
+#include "kvm/devices.h"
 #include "kvm/pci.h"
 #include "kvm/ioport.h"
 #include "kvm/util.h"
@@ -8,8 +9,6 @@
 
 #define PCI_BAR_OFFSET(b)              (offsetof(struct pci_device_header, 
bar[b]))
 
-static struct pci_device_header                *pci_devices[PCI_MAX_DEVICES];
-
 static union pci_config_address                pci_config_address;
 
 /* This is within our PCI gap - in an unused area.
@@ -63,7 +62,7 @@ static struct ioport_operations pci_config_address_ops = {
 
 static bool pci_device_exists(u8 bus_number, u8 device_number, u8 
function_number)
 {
-       struct pci_device_header *dev;
+       struct device_header *dev;
 
        if (pci_config_address.bus_number != bus_number)
                return false;
@@ -71,12 +70,8 @@ static bool pci_device_exists(u8 bus_number, u8 
device_number, u8 function_numbe
        if (pci_config_address.function_number != function_number)
                return false;
 
-       if (device_number >= PCI_MAX_DEVICES)
-               return false;
-
-       dev = pci_devices[device_number];
-
-       return dev != NULL;
+       dev = device__find_dev(device_number);
+       return !IS_ERR_OR_NULL(dev) && dev->bus_type == DEVICE_BUS_PCI;
 }
 
 static bool pci_config_data_out(struct ioport *ioport, struct kvm *kvm, u16 
port, void *data, int size)
@@ -121,12 +116,13 @@ void pci__config_wr(struct kvm *kvm, union 
pci_config_address addr, void *data,
 
                offset = addr.w & 0xff;
                if (offset < sizeof(struct pci_device_header)) {
-                       void *p = pci_devices[dev_num];
+                       void *p = device__find_dev(dev_num)->data;
+                       struct pci_device_header *hdr = p;
                        u8 bar = (offset - PCI_BAR_OFFSET(0)) / (sizeof(u32));
                        u32 sz = PCI_IO_SIZE;
 
-                       if (bar < 6 && pci_devices[dev_num]->bar_size[bar])
-                               sz = pci_devices[dev_num]->bar_size[bar];
+                       if (bar < 6 && hdr->bar_size[bar])
+                               sz = hdr->bar_size[bar];
 
                        /*
                         * If the kernel masks the BAR it would expect to find 
the
@@ -158,7 +154,7 @@ void pci__config_rd(struct kvm *kvm, union 
pci_config_address addr, void *data,
 
                offset = addr.w & 0xff;
                if (offset < sizeof(struct pci_device_header)) {
-                       void *p = pci_devices[dev_num];
+                       void *p = device__find_dev(dev_num)->data;
 
                        memcpy(data, p + offset, size);
                } else {
@@ -169,22 +165,14 @@ void pci__config_rd(struct kvm *kvm, union 
pci_config_address addr, void *data,
        }
 }
 
-int pci__register(struct pci_device_header *dev, u8 dev_num)
-{
-       if (dev_num >= PCI_MAX_DEVICES)
-               return -ENOSPC;
-
-       pci_devices[dev_num] = dev;
-
-       return 0;
-}
-
 struct pci_device_header *pci__find_dev(u8 dev_num)
 {
-       if (dev_num >= PCI_MAX_DEVICES)
-               return ERR_PTR(-EOVERFLOW);
+       struct device_header *hdr = device__find_dev(dev_num);
+
+       if (IS_ERR(hdr) || hdr->bus_type != DEVICE_BUS_PCI)
+               return NULL;
 
-       return pci_devices[dev_num];
+       return hdr->data;
 }
 
 int pci__init(struct kvm *kvm)
diff --git a/tools/kvm/powerpc/irq.c b/tools/kvm/powerpc/irq.c
index e89fa3b..af239fb 100644
--- a/tools/kvm/powerpc/irq.c
+++ b/tools/kvm/powerpc/irq.c
@@ -8,6 +8,7 @@
  * by the Free Software Foundation.
  */
 
+#include "kvm/devices.h"
 #include "kvm/irq.h"
 #include "kvm/kvm.h"
 #include "kvm/util.h"
@@ -35,7 +36,7 @@ static int pci_devs = 0;
 
 int irq__register_device(u32 dev, u8 *num, u8 *pin, u8 *line)
 {
-       if (pci_devs >= PCI_MAX_DEVICES)
+       if (pci_devs >= KVM_MAX_DEVICES)
                die("Hit PCI device limit!\n");
 
        *num = pci_devs++;
diff --git a/tools/kvm/powerpc/spapr_pci.c b/tools/kvm/powerpc/spapr_pci.c
index b74790e..5bfcec1 100644
--- a/tools/kvm/powerpc/spapr_pci.c
+++ b/tools/kvm/powerpc/spapr_pci.c
@@ -302,7 +302,7 @@ int spapr_populate_pci_devices(struct kvm *kvm,
        /* Populate PCI devices and allocate IRQs */
        devices = 0;
 
-       for (devid = 0; devid < PCI_MAX_DEVICES; devid++) {
+       for (devid = 0; devid < KVM_MAX_DEVICES; devid++) {
                uint32_t *irqmap = interrupt_map[devices];
                struct pci_device_header *hdr = pci__find_dev(devid);
 
diff --git a/tools/kvm/virtio/mmio.c b/tools/kvm/virtio/mmio.c
index 6ec33ec..2d538b8 100644
--- a/tools/kvm/virtio/mmio.c
+++ b/tools/kvm/virtio/mmio.c
@@ -1,3 +1,4 @@
+#include "kvm/devices.h"
 #include "kvm/virtio-mmio.h"
 #include "kvm/ioeventfd.h"
 #include "kvm/ioport.h"
@@ -238,6 +239,12 @@ int virtio_mmio_init(struct kvm *kvm, void *dev, struct 
virtio_device *vdev,
        if (irq__register_device(subsys_id, &device, &pin, &line) < 0)
                return -1;
        vmmio->irq = line;
+       vmmio->dev_hdr = (struct device_header) {
+               .bus_type       = DEVICE_BUS_MMIO,
+               .data           = vmmio,
+       };
+
+       device__register(&vmmio->dev_hdr, device);
 
        /*
         * Instantiate guest virtio-mmio devices using kernel command line
diff --git a/tools/kvm/virtio/pci.c b/tools/kvm/virtio/pci.c
index adc8efc..e3cfb0a 100644
--- a/tools/kvm/virtio/pci.c
+++ b/tools/kvm/virtio/pci.c
@@ -343,6 +343,11 @@ int virtio_pci__init(struct kvm *kvm, void *dev, struct 
virtio_device *vdev,
                .bar_size[3]            = PCI_IO_SIZE,
        };
 
+       vpci->dev_hdr = (struct device_header) {
+               .bus_type               = DEVICE_BUS_PCI,
+               .data                   = &vpci->pci_hdr,
+       };
+
        vpci->pci_hdr.msix.cap = PCI_CAP_ID_MSIX;
        vpci->pci_hdr.msix.next = 0;
        /*
@@ -375,7 +380,7 @@ int virtio_pci__init(struct kvm *kvm, void *dev, struct 
virtio_device *vdev,
 
        vpci->pci_hdr.irq_pin   = pin;
        vpci->pci_hdr.irq_line  = line;
-       r = pci__register(&vpci->pci_hdr, ndev);
+       r = device__register(&vpci->dev_hdr, ndev);
        if (r < 0)
                goto free_ioport;
 
-- 
1.7.4.1

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to