]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
kvm tools: Add abstract virtio transport layer
authorSasha Levin <levinsasha928@gmail.com>
Wed, 9 Nov 2011 20:01:52 +0000 (22:01 +0200)
committerPekka Enberg <penberg@kernel.org>
Thu, 10 Nov 2011 06:49:43 +0000 (08:49 +0200)
Since virtio-mmio was introduced in 3.2, virtio-pci isn't the only transport
layer between the kernel and virtio devices.

This patch adds an abstract virtio-transport layer which allows to easily
use different transports while making it transparent to the device.

This is the first step in adding virtio-mmio support.

Cc: Pawel Moll <pawel.moll@arm.com>
Cc: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Sasha Levin <levinsasha928@gmail.com>
Signed-off-by: Pekka Enberg <penberg@kernel.org>
12 files changed:
tools/kvm/Makefile
tools/kvm/include/kvm/virtio-9p.h
tools/kvm/include/kvm/virtio-pci.h
tools/kvm/include/kvm/virtio-trans.h [new file with mode: 0644]
tools/kvm/virtio/9p.c
tools/kvm/virtio/balloon.c
tools/kvm/virtio/blk.c
tools/kvm/virtio/console.c
tools/kvm/virtio/net.c
tools/kvm/virtio/pci.c
tools/kvm/virtio/rng.c
tools/kvm/virtio/trans.c [new file with mode: 0644]

index 20389f9c7b24198500bc9d90fa3f1ba389c152ce..f4741f2c378fbc6b0a94714c3b7bb591a6fc7b7c 100644 (file)
@@ -56,6 +56,7 @@ OBJS  += virtio/net.o
 OBJS   += virtio/rng.o
 OBJS    += virtio/balloon.o
 OBJS   += virtio/pci.o
+OBJS   += virtio/trans.o
 OBJS   += disk/blk.o
 OBJS   += disk/qcow.o
 OBJS   += disk/raw.o
index 3096df27c6466411b9015b848a88a617612e5221..ac3dc45976b421d3cc53a480e3a59e663f7038ac 100644 (file)
@@ -3,7 +3,7 @@
 #include "kvm/virtio.h"
 #include "kvm/pci.h"
 #include "kvm/threadpool.h"
-#include "kvm/virtio-pci.h"
+#include "kvm/virtio-trans.h"
 
 #include <sys/types.h>
 #include <dirent.h>
@@ -42,7 +42,7 @@ struct p9_dev_job {
 
 struct p9_dev {
        struct list_head        list;
-       struct virtio_pci       vpci;
+       struct virtio_trans     vtrans;
 
        struct virtio_9p_config *config;
        u32                     features;
index 81196e53b89d756302902b3eeba07ec5d4cd6431..2bbb27108be57736a988a20b3f770c6917a60138 100644 (file)
@@ -2,6 +2,7 @@
 #define KVM__VIRTIO_PCI_H
 
 #include "kvm/pci.h"
+#include "kvm/virtio-trans.h"
 
 #include <linux/types.h>
 
 
 struct kvm;
 
-struct virtio_pci_ops {
-       void (*set_config)(struct kvm *kvm, void *dev, u8 data, u32 offset);
-       u8 (*get_config)(struct kvm *kvm, void *dev, u32 offset);
-
-       u32 (*get_host_features)(struct kvm *kvm, void *dev);
-       void (*set_guest_features)(struct kvm *kvm, void *dev, u32 features);
-
-       int (*init_vq)(struct kvm *kvm, void *dev, u32 vq, u32 pfn);
-       int (*notify_vq)(struct kvm *kvm, void *dev, u32 vq);
-       int (*get_pfn_vq)(struct kvm *kvm, void *dev, u32 vq);
-       int (*get_size_vq)(struct kvm *kvm, void *dev, u32 vq);
-};
-
 struct virtio_pci_ioevent_param {
-       struct virtio_pci       *vpci;
+       struct virtio_trans     *vtrans;
        u32                     vq;
 };
 
 struct virtio_pci {
        struct pci_device_header pci_hdr;
-       struct virtio_pci_ops   ops;
        void                    *dev;
 
        u16                     base_addr;
@@ -52,9 +39,11 @@ struct virtio_pci {
        struct virtio_pci_ioevent_param ioeventfds[VIRTIO_PCI_MAX_VQ];
 };
 
-int virtio_pci__init(struct kvm *kvm, struct virtio_pci *vpci, void *dev,
+int virtio_pci__init(struct kvm *kvm, struct virtio_trans *vtrans, void *dev,
                        int device_id, int subsys_id, int class);
-int virtio_pci__signal_vq(struct kvm *kvm, struct virtio_pci *vpci, u32 vq);
-int virtio_pci__signal_config(struct kvm *kvm, struct virtio_pci *vpci);
+int virtio_pci__signal_vq(struct kvm *kvm, struct virtio_trans *vtrans, u32 vq);
+int virtio_pci__signal_config(struct kvm *kvm, struct virtio_trans *vtrans);
+
+struct virtio_trans_ops *virtio_pci__get_trans_ops(void);
 
 #endif
diff --git a/tools/kvm/include/kvm/virtio-trans.h b/tools/kvm/include/kvm/virtio-trans.h
new file mode 100644 (file)
index 0000000..d9f4b95
--- /dev/null
@@ -0,0 +1,41 @@
+#ifndef KVM__VIRTIO_TRANS_H
+#define KVM__VIRTIO_TRANS_H
+
+#include "kvm/kvm.h"
+
+enum virtio_trans_type {
+       VIRTIO_PCI,
+};
+
+struct virtio_trans;
+
+struct virtio_ops {
+       void (*set_config)(struct kvm *kvm, void *dev, u8 data, u32 offset);
+       u8 (*get_config)(struct kvm *kvm, void *dev, u32 offset);
+
+       u32 (*get_host_features)(struct kvm *kvm, void *dev);
+       void (*set_guest_features)(struct kvm *kvm, void *dev, u32 features);
+
+       int (*init_vq)(struct kvm *kvm, void *dev, u32 vq, u32 pfn);
+       int (*notify_vq)(struct kvm *kvm, void *dev, u32 vq);
+       int (*get_pfn_vq)(struct kvm *kvm, void *dev, u32 vq);
+       int (*get_size_vq)(struct kvm *kvm, void *dev, u32 vq);
+};
+
+struct virtio_trans_ops {
+       int (*init)(struct kvm *kvm, struct virtio_trans *vtrans, void *dev, int device_id,
+                       int subsys_id, int class);
+       int (*signal_vq)(struct kvm *kvm, struct virtio_trans *virtio_trans, u32 queueid);
+       int (*signal_config)(struct kvm *kvm, struct virtio_trans *virtio_trans);
+};
+
+struct virtio_trans {
+       void                    *virtio;
+       enum virtio_trans_type  type;
+       struct virtio_trans_ops *trans_ops;
+       struct virtio_ops       *virtio_ops;
+};
+
+int virtio_trans_init(struct virtio_trans *vtrans, enum virtio_trans_type type);
+
+#endif
\ No newline at end of file
index 8104ac41ce6b5b9feebfc0ff29d319de8c597023..8e37925d07d8e932d6afbf39fbffd4214b88c19d 100644 (file)
@@ -1162,7 +1162,7 @@ static void virtio_p9_do_io(struct kvm *kvm, void *param)
 
        while (virt_queue__available(vq)) {
                virtio_p9_do_io_request(kvm, job);
-               virtio_pci__signal_vq(kvm, &p9dev->vpci, vq - p9dev->vqs);
+               p9dev->vtrans.trans_ops->signal_vq(kvm, &p9dev->vtrans, vq - p9dev->vqs);
        }
 }
 
@@ -1238,22 +1238,26 @@ static int get_size_vq(struct kvm *kvm, void *dev, u32 vq)
        return VIRTQUEUE_NUM;
 }
 
+struct virtio_ops p9_dev_virtio_ops = (struct virtio_ops) {
+       .set_config             = set_config,
+       .get_config             = get_config,
+       .get_host_features      = get_host_features,
+       .set_guest_features     = set_guest_features,
+       .init_vq                = init_vq,
+       .notify_vq              = notify_vq,
+       .get_pfn_vq             = get_pfn_vq,
+       .get_size_vq            = get_size_vq,
+};
+
 int virtio_9p__init(struct kvm *kvm)
 {
        struct p9_dev *p9dev;
 
        list_for_each_entry(p9dev, &devs, list) {
-               virtio_pci__init(kvm, &p9dev->vpci, p9dev, PCI_DEVICE_ID_VIRTIO_P9, VIRTIO_ID_9P, PCI_CLASS_P9);
-               p9dev->vpci.ops = (struct virtio_pci_ops) {
-                       .set_config             = set_config,
-                       .get_config             = get_config,
-                       .get_host_features      = get_host_features,
-                       .set_guest_features     = set_guest_features,
-                       .init_vq                = init_vq,
-                       .notify_vq              = notify_vq,
-                       .get_pfn_vq             = get_pfn_vq,
-                       .get_size_vq            = get_size_vq,
-               };
+               virtio_trans_init(&p9dev->vtrans, VIRTIO_PCI);
+               p9dev->vtrans.trans_ops->init(kvm, &p9dev->vtrans, p9dev,
+                                       PCI_DEVICE_ID_VIRTIO_P9, VIRTIO_ID_9P, PCI_CLASS_P9);
+               p9dev->vtrans.virtio_ops = &p9_dev_virtio_ops;
        }
 
        return 0;
index 9a52108c1f2b071fdaeb94d3a8f0d658375f3223..07fd97654dda2889c35db9dd98e664dc82db5b93 100644 (file)
@@ -8,7 +8,7 @@
 #include "kvm/pci.h"
 #include "kvm/threadpool.h"
 #include "kvm/guest_compat.h"
-#include "kvm/virtio-pci.h"
+#include "kvm/virtio-trans.h"
 #include "kvm/kvm-ipc.h"
 
 #include <linux/virtio_ring.h>
@@ -31,7 +31,7 @@
 
 struct bln_dev {
        struct list_head        list;
-       struct virtio_pci       vpci;
+       struct virtio_trans     vtrans;
 
        u32                     features;
 
@@ -116,13 +116,13 @@ static void virtio_bln_do_io(struct kvm *kvm, void *param)
 
        if (vq == &bdev.vqs[VIRTIO_BLN_STATS]) {
                virtio_bln_do_stat_request(kvm, &bdev, vq);
-               virtio_pci__signal_vq(kvm, &bdev.vpci, VIRTIO_BLN_STATS);
+               bdev.vtrans.trans_ops->signal_vq(kvm, &bdev.vtrans, VIRTIO_BLN_STATS);
                return;
        }
 
        while (virt_queue__available(vq)) {
                virtio_bln_do_io_request(kvm, &bdev, vq);
-               virtio_pci__signal_vq(kvm, &bdev.vpci, vq - bdev.vqs);
+               bdev.vtrans.trans_ops->signal_vq(kvm, &bdev.vtrans, vq - bdev.vqs);
        }
 }
 
@@ -132,7 +132,7 @@ static int virtio_bln__collect_stats(void)
 
        virt_queue__set_used_elem(&bdev.vqs[VIRTIO_BLN_STATS], bdev.cur_stat_head,
                                  sizeof(struct virtio_balloon_stat));
-       virtio_pci__signal_vq(kvm, &bdev.vpci, VIRTIO_BLN_STATS);
+       bdev.vtrans.trans_ops->signal_vq(kvm, &bdev.vtrans, VIRTIO_BLN_STATS);
 
        if (read(bdev.stat_waitfd, &tmp, sizeof(tmp)) <= 0)
                return -EFAULT;
@@ -166,7 +166,7 @@ static void handle_mem(int fd, u32 type, u32 len, u8 *msg)
        }
 
        /* Notify that the configuration space has changed */
-       virtio_pci__signal_config(kvm, &bdev.vpci);
+       bdev.vtrans.trans_ops->signal_config(kvm, &bdev.vtrans);
 }
 
 static void set_config(struct kvm *kvm, void *dev, u8 data, u32 offset)
@@ -234,6 +234,17 @@ static int get_size_vq(struct kvm *kvm, void *dev, u32 vq)
        return VIRTIO_BLN_QUEUE_SIZE;
 }
 
+struct virtio_ops bln_dev_virtio_ops = (struct virtio_ops) {
+       .set_config             = set_config,
+       .get_config             = get_config,
+       .get_host_features      = get_host_features,
+       .set_guest_features     = set_guest_features,
+       .init_vq                = init_vq,
+       .notify_vq              = notify_vq,
+       .get_pfn_vq             = get_pfn_vq,
+       .get_size_vq            = get_size_vq,
+};
+
 void virtio_bln__init(struct kvm *kvm)
 {
        kvm_ipc__register_handler(KVM_IPC_BALLOON, handle_mem);
@@ -242,17 +253,10 @@ void virtio_bln__init(struct kvm *kvm)
        bdev.stat_waitfd        = eventfd(0, 0);
        memset(&bdev.config, 0, sizeof(struct virtio_balloon_config));
 
-       virtio_pci__init(kvm, &bdev.vpci, &bdev, PCI_DEVICE_ID_VIRTIO_BLN, VIRTIO_ID_BALLOON, PCI_CLASS_BLN);
-       bdev.vpci.ops = (struct virtio_pci_ops) {
-               .set_config             = set_config,
-               .get_config             = get_config,
-               .get_host_features      = get_host_features,
-               .set_guest_features     = set_guest_features,
-               .init_vq                = init_vq,
-               .notify_vq              = notify_vq,
-               .get_pfn_vq             = get_pfn_vq,
-               .get_size_vq            = get_size_vq,
-       };
+       virtio_trans_init(&bdev.vtrans, VIRTIO_PCI);
+       bdev.vtrans.trans_ops->init(kvm, &bdev.vtrans, &bdev, PCI_DEVICE_ID_VIRTIO_BLN,
+                                       VIRTIO_ID_BALLOON, PCI_CLASS_BLN);
+       bdev.vtrans.virtio_ops = &bln_dev_virtio_ops;
 
        if (compat_id != -1)
                compat_id = compat__add_message("virtio-balloon device was not detected",
index 223e79f68bd231495f4e9194b31f1acb2ad1fe1e..ed4e0991dd112aa858d7465bb80ebdf1918f2885 100644 (file)
@@ -11,6 +11,7 @@
 #include "kvm/guest_compat.h"
 #include "kvm/virtio-pci.h"
 #include "kvm/virtio.h"
+#include "kvm/virtio-trans.h"
 
 #include <linux/virtio_ring.h>
 #include <linux/virtio_blk.h>
@@ -44,7 +45,7 @@ struct blk_dev {
        struct list_head                list;
        struct list_head                req_list;
 
-       struct virtio_pci               vpci;
+       struct virtio_trans             vtrans;
        struct virtio_blk_config        blk_config;
        struct disk_image               *disk;
        u32                             features;
@@ -92,7 +93,7 @@ void virtio_blk_complete(void *param, long len)
        virt_queue__set_used_elem(req->vq, req->head, len);
        mutex_unlock(&bdev->mutex);
 
-       virtio_pci__signal_vq(req->kvm, &bdev->vpci, queueid);
+       bdev->vtrans.trans_ops->signal_vq(req->kvm, &bdev->vtrans, queueid);
 
        virtio_blk_req_push(req->bdev, req);
 }
@@ -217,6 +218,17 @@ static int get_size_vq(struct kvm *kvm, void *dev, u32 vq)
        return VIRTIO_BLK_QUEUE_SIZE;
 }
 
+static struct virtio_ops blk_dev_virtio_ops = (struct virtio_ops) {
+       .set_config             = set_config,
+       .get_config             = get_config,
+       .get_host_features      = get_host_features,
+       .set_guest_features     = set_guest_features,
+       .init_vq                = init_vq,
+       .notify_vq              = notify_vq,
+       .get_pfn_vq             = get_pfn_vq,
+       .get_size_vq            = get_size_vq,
+};
+
 void virtio_blk__init(struct kvm *kvm, struct disk_image *disk)
 {
        struct blk_dev *bdev;
@@ -239,17 +251,10 @@ void virtio_blk__init(struct kvm *kvm, struct disk_image *disk)
                },
        };
 
-       virtio_pci__init(kvm, &bdev->vpci, bdev, PCI_DEVICE_ID_VIRTIO_BLK, VIRTIO_ID_BLOCK, PCI_CLASS_BLK);
-       bdev->vpci.ops = (struct virtio_pci_ops) {
-               .set_config             = set_config,
-               .get_config             = get_config,
-               .get_host_features      = get_host_features,
-               .set_guest_features     = set_guest_features,
-               .init_vq                = init_vq,
-               .notify_vq              = notify_vq,
-               .get_pfn_vq             = get_pfn_vq,
-               .get_size_vq            = get_size_vq,
-       };
+       virtio_trans_init(&bdev->vtrans, VIRTIO_PCI);
+       bdev->vtrans.trans_ops->init(kvm, &bdev->vtrans, bdev, PCI_DEVICE_ID_VIRTIO_BLK,
+                                       VIRTIO_ID_BLOCK, PCI_CLASS_BLK);
+       bdev->vtrans.virtio_ops = &blk_dev_virtio_ops;
 
        list_add_tail(&bdev->list, &bdevs);
 
index f0e4bf8b033e3ef4bdb4d143d391bb8d01176475..68c30f519d77b87df489b0137206b0240dc2474b 100644 (file)
@@ -11,7 +11,7 @@
 #include "kvm/threadpool.h"
 #include "kvm/irq.h"
 #include "kvm/guest_compat.h"
-#include "kvm/virtio-pci.h"
+#include "kvm/virtio-trans.h"
 
 #include <linux/virtio_console.h>
 #include <linux/virtio_ring.h>
@@ -33,7 +33,7 @@
 struct con_dev {
        pthread_mutex_t                 mutex;
 
-       struct virtio_pci               vpci;
+       struct virtio_trans             vtrans;
        struct virt_queue               vqs[VIRTIO_CONSOLE_NUM_QUEUES];
        struct virtio_console_config    config;
        u32                             features;
@@ -72,7 +72,7 @@ static void virtio_console__inject_interrupt_callback(struct kvm *kvm, void *par
                head = virt_queue__get_iov(vq, iov, &out, &in, kvm);
                len = term_getc_iov(CONSOLE_VIRTIO, iov, in, 0);
                virt_queue__set_used_elem(vq, head, len);
-               virtio_pci__signal_vq(kvm, &cdev.vpci, vq - cdev.vqs);
+               cdev.vtrans.trans_ops->signal_vq(kvm, &cdev.vtrans, vq - cdev.vqs);
        }
 
        mutex_unlock(&cdev.mutex);
@@ -175,19 +175,24 @@ static int get_size_vq(struct kvm *kvm, void *dev, u32 vq)
        return VIRTIO_CONSOLE_QUEUE_SIZE;
 }
 
+static struct virtio_ops con_dev_virtio_ops = (struct virtio_ops) {
+       .set_config             = set_config,
+       .get_config             = get_config,
+       .get_host_features      = get_host_features,
+       .set_guest_features     = set_guest_features,
+       .init_vq                = init_vq,
+       .notify_vq              = notify_vq,
+       .get_pfn_vq             = get_pfn_vq,
+       .get_size_vq            = get_size_vq,
+};
+
 void virtio_console__init(struct kvm *kvm)
 {
-       virtio_pci__init(kvm, &cdev.vpci, &cdev, PCI_DEVICE_ID_VIRTIO_CONSOLE, VIRTIO_ID_CONSOLE, PCI_CLASS_CONSOLE);
-       cdev.vpci.ops = (struct virtio_pci_ops) {
-               .set_config             = set_config,
-               .get_config             = get_config,
-               .get_host_features      = get_host_features,
-               .set_guest_features     = set_guest_features,
-               .init_vq                = init_vq,
-               .notify_vq              = notify_vq,
-               .get_pfn_vq             = get_pfn_vq,
-               .get_size_vq            = get_size_vq,
-       };
+       virtio_trans_init(&cdev.vtrans, VIRTIO_PCI);
+
+       cdev.vtrans.trans_ops->init(kvm, &cdev.vtrans, &cdev, PCI_DEVICE_ID_VIRTIO_CONSOLE,
+                                       VIRTIO_ID_CONSOLE, PCI_CLASS_CONSOLE);
+       cdev.vtrans.virtio_ops = &con_dev_virtio_ops;
 
        if (compat_id != -1)
                compat_id = compat__add_message("virtio-console device was not detected",
index 7cd6794f941f0813fc6fde1f901f63965cdfa63e..cee2b5bd14f38503b7a7db61cd1be665c81b70cd 100644 (file)
@@ -8,7 +8,7 @@
 #include "kvm/irq.h"
 #include "kvm/uip.h"
 #include "kvm/guest_compat.h"
-#include "kvm/virtio-pci.h"
+#include "kvm/virtio-trans.h"
 
 #include <linux/virtio_net.h>
 #include <linux/if_tun.h>
@@ -42,7 +42,7 @@ struct net_dev_operations {
 
 struct net_dev {
        pthread_mutex_t                 mutex;
-       struct virtio_pci               vpci;
+       struct virtio_trans             vtrans;
        struct list_head                list;
 
        struct virt_queue               vqs[VIRTIO_NET_NUM_QUEUES];
@@ -99,7 +99,7 @@ static void *virtio_net_rx_thread(void *p)
                        virt_queue__set_used_elem(vq, head, len);
 
                        /* We should interrupt guest right now, otherwise latency is huge. */
-                       virtio_pci__signal_vq(kvm, &ndev->vpci, VIRTIO_NET_RX_QUEUE);
+                       ndev->vtrans.trans_ops->signal_vq(kvm, &ndev->vtrans, VIRTIO_NET_RX_QUEUE);
                }
 
        }
@@ -137,7 +137,7 @@ static void *virtio_net_tx_thread(void *p)
                        virt_queue__set_used_elem(vq, head, len);
                }
 
-               virtio_pci__signal_vq(kvm, &ndev->vpci, VIRTIO_NET_TX_QUEUE);
+               ndev->vtrans.trans_ops->signal_vq(kvm, &ndev->vtrans, VIRTIO_NET_TX_QUEUE);
        }
 
        pthread_exit(NULL);
@@ -359,6 +359,17 @@ static int get_size_vq(struct kvm *kvm, void *dev, u32 vq)
        return VIRTIO_NET_QUEUE_SIZE;
 }
 
+static struct virtio_ops net_dev_virtio_ops = (struct virtio_ops) {
+       .set_config             = set_config,
+       .get_config             = get_config,
+       .get_host_features      = get_host_features,
+       .set_guest_features     = set_guest_features,
+       .init_vq                = init_vq,
+       .notify_vq              = notify_vq,
+       .get_pfn_vq             = get_pfn_vq,
+       .get_size_vq            = get_size_vq,
+};
+
 void virtio_net__init(const struct virtio_net_params *params)
 {
        int i;
@@ -399,17 +410,10 @@ void virtio_net__init(const struct virtio_net_params *params)
                ndev->ops = &uip_ops;
        }
 
-       virtio_pci__init(kvm, &ndev->vpci, ndev, PCI_DEVICE_ID_VIRTIO_NET, VIRTIO_ID_NET, PCI_CLASS_NET);
-       ndev->vpci.ops = (struct virtio_pci_ops) {
-               .set_config             = set_config,
-               .get_config             = get_config,
-               .get_host_features      = get_host_features,
-               .set_guest_features     = set_guest_features,
-               .init_vq                = init_vq,
-               .notify_vq              = notify_vq,
-               .get_pfn_vq             = get_pfn_vq,
-               .get_size_vq            = get_size_vq,
-       };
+       virtio_trans_init(&ndev->vtrans, VIRTIO_PCI);
+       ndev->vtrans.trans_ops->init(kvm, &ndev->vtrans, ndev, PCI_DEVICE_ID_VIRTIO_NET,
+                                       VIRTIO_ID_NET, PCI_CLASS_NET);
+       ndev->vtrans.virtio_ops = &net_dev_virtio_ops;
 
        virtio_net__io_thread_init(params->kvm, ndev);
 
index b8d1ec1b33cdbd6cc8af84ee24248f1faf2f4ced..85994f879003ff3e72c43cad7ab50ede3f0c15e0 100644 (file)
@@ -6,23 +6,36 @@
 #include "kvm/irq.h"
 #include "kvm/virtio.h"
 #include "kvm/ioeventfd.h"
+#include "kvm/virtio-trans.h"
 
 #include <linux/virtio_pci.h>
 #include <string.h>
 
+struct virtio_trans_ops *virtio_pci__get_trans_ops(void)
+{
+       static struct virtio_trans_ops virtio_pci_trans = (struct virtio_trans_ops) {
+               .signal_vq      = virtio_pci__signal_vq,
+               .signal_config  = virtio_pci__signal_config,
+               .init           = virtio_pci__init,
+       };
+       return &virtio_pci_trans;
+};
+
 static void virtio_pci__ioevent_callback(struct kvm *kvm, void *param)
 {
        struct virtio_pci_ioevent_param *ioeventfd = param;
+       struct virtio_pci *vpci = ioeventfd->vtrans->virtio;
 
-       ioeventfd->vpci->ops.notify_vq(kvm, ioeventfd->vpci->dev, ioeventfd->vq);
+       ioeventfd->vtrans->virtio_ops->notify_vq(kvm, vpci->dev, ioeventfd->vq);
 }
 
-static int virtio_pci__init_ioeventfd(struct kvm *kvm, struct virtio_pci *vpci, u32 vq)
+static int virtio_pci__init_ioeventfd(struct kvm *kvm, struct virtio_trans *vtrans, u32 vq)
 {
        struct ioevent ioevent;
+       struct virtio_pci *vpci = vtrans->virtio;
 
        vpci->ioeventfds[vq] = (struct virtio_pci_ioevent_param) {
-               .vpci           = vpci,
+               .vtrans         = vtrans,
                .vq             = vq,
        };
 
@@ -46,10 +59,11 @@ static inline bool virtio_pci__msix_enabled(struct virtio_pci *vpci)
        return vpci->pci_hdr.msix.ctrl & PCI_MSIX_FLAGS_ENABLE;
 }
 
-static bool virtio_pci__specific_io_in(struct kvm *kvm, struct virtio_pci *vpci, u16 port,
+static bool virtio_pci__specific_io_in(struct kvm *kvm, struct virtio_trans *vtrans, u16 port,
                                        void *data, int size, int offset)
 {
        u32 config_offset;
+       struct virtio_pci *vpci = vtrans->virtio;
        int type = virtio__get_dev_specific_field(offset - 20,
                                                        virtio_pci__msix_enabled(vpci),
                                                        0, &config_offset);
@@ -67,7 +81,7 @@ static bool virtio_pci__specific_io_in(struct kvm *kvm, struct virtio_pci *vpci,
        } else if (type == VIRTIO_PCI_O_CONFIG) {
                u8 cfg;
 
-               cfg = vpci->ops.get_config(kvm, vpci->dev, config_offset);
+               cfg = vtrans->virtio_ops->get_config(kvm, vpci->dev, config_offset);
                ioport__write8(data, cfg);
                return true;
        }
@@ -79,23 +93,25 @@ static bool virtio_pci__io_in(struct ioport *ioport, struct kvm *kvm, u16 port,
 {
        unsigned long offset;
        bool ret = true;
+       struct virtio_trans *vtrans;
        struct virtio_pci *vpci;
        u32 val;
 
-       vpci = ioport->priv;
+       vtrans = ioport->priv;
+       vpci = vtrans->virtio;
        offset = port - vpci->base_addr;
 
        switch (offset) {
        case VIRTIO_PCI_HOST_FEATURES:
-               val = vpci->ops.get_host_features(kvm, vpci->dev);
+               val = vtrans->virtio_ops->get_host_features(kvm, vpci->dev);
                ioport__write32(data, val);
                break;
        case VIRTIO_PCI_QUEUE_PFN:
-               val = vpci->ops.get_pfn_vq(kvm, vpci->dev, vpci->queue_selector);
+               val = vtrans->virtio_ops->get_pfn_vq(kvm, vpci->dev, vpci->queue_selector);
                ioport__write32(data, val);
                break;
        case VIRTIO_PCI_QUEUE_NUM:
-               val = vpci->ops.get_size_vq(kvm, vpci->dev, vpci->queue_selector);
+               val = vtrans->virtio_ops->get_size_vq(kvm, vpci->dev, vpci->queue_selector);
                ioport__write32(data, val);
                break;
                break;
@@ -108,16 +124,17 @@ static bool virtio_pci__io_in(struct ioport *ioport, struct kvm *kvm, u16 port,
                vpci->isr = VIRTIO_IRQ_LOW;
                break;
        default:
-               ret = virtio_pci__specific_io_in(kvm, vpci, port, data, size, offset);
+               ret = virtio_pci__specific_io_in(kvm, vtrans, port, data, size, offset);
                break;
        };
 
        return ret;
 }
 
-static bool virtio_pci__specific_io_out(struct kvm *kvm, struct virtio_pci *vpci, u16 port,
+static bool virtio_pci__specific_io_out(struct kvm *kvm, struct virtio_trans *vtrans, u16 port,
                                        void *data, int size, int offset)
 {
+       struct virtio_pci *vpci = vtrans->virtio;
        u32 config_offset, gsi, vec;
        int type = virtio__get_dev_specific_field(offset - 20, virtio_pci__msix_enabled(vpci),
                                                        0, &config_offset);
@@ -141,7 +158,7 @@ static bool virtio_pci__specific_io_out(struct kvm *kvm, struct virtio_pci *vpci
 
                return true;
        } else if (type == VIRTIO_PCI_O_CONFIG) {
-               vpci->ops.set_config(kvm, vpci->dev, *(u8 *)data, config_offset);
+               vtrans->virtio_ops->set_config(kvm, vpci->dev, *(u8 *)data, config_offset);
 
                return true;
        }
@@ -153,34 +170,36 @@ static bool virtio_pci__io_out(struct ioport *ioport, struct kvm *kvm, u16 port,
 {
        unsigned long offset;
        bool ret = true;
+       struct virtio_trans *vtrans;
        struct virtio_pci *vpci;
        u32 val;
 
-       vpci = ioport->priv;
+       vtrans = ioport->priv;
+       vpci = vtrans->virtio;
        offset = port - vpci->base_addr;
 
        switch (offset) {
        case VIRTIO_PCI_GUEST_FEATURES:
                val = ioport__read32(data);
-               vpci->ops.set_guest_features(kvm, vpci, val);
+               vtrans->virtio_ops->set_guest_features(kvm, vpci, val);
                break;
        case VIRTIO_PCI_QUEUE_PFN:
                val = ioport__read32(data);
-               virtio_pci__init_ioeventfd(kvm, vpci, vpci->queue_selector);
-               vpci->ops.init_vq(kvm, vpci->dev, vpci->queue_selector, val);
+               virtio_pci__init_ioeventfd(kvm, vtrans, vpci->queue_selector);
+               vtrans->virtio_ops->init_vq(kvm, vpci->dev, vpci->queue_selector, val);
                break;
        case VIRTIO_PCI_QUEUE_SEL:
                vpci->queue_selector    = ioport__read16(data);
                break;
        case VIRTIO_PCI_QUEUE_NOTIFY:
                val                     = ioport__read16(data);
-               vpci->ops.notify_vq(kvm, vpci->dev, val);
+               vtrans->virtio_ops->notify_vq(kvm, vpci->dev, val);
                break;
        case VIRTIO_PCI_STATUS:
                vpci->status            = ioport__read8(data);
                break;
        default:
-               ret = virtio_pci__specific_io_out(kvm, vpci, port, data, size, offset);
+               ret = virtio_pci__specific_io_out(kvm, vtrans, port, data, size, offset);
                break;
        };
 
@@ -214,8 +233,9 @@ static void callback_mmio_pba(u64 addr, u8 *data, u32 len, u8 is_write, void *pt
                memcpy(data, pba + addr - vpci->msix_pba_block, len);
 }
 
-int virtio_pci__signal_vq(struct kvm *kvm, struct virtio_pci *vpci, u32 vq)
+int virtio_pci__signal_vq(struct kvm *kvm, struct virtio_trans *vtrans, u32 vq)
 {
+       struct virtio_pci *vpci = vtrans->virtio;
        int tbl = vpci->vq_vector[vq];
 
        if (virtio_pci__msix_enabled(vpci)) {
@@ -234,8 +254,9 @@ int virtio_pci__signal_vq(struct kvm *kvm, struct virtio_pci *vpci, u32 vq)
        return 0;
 }
 
-int virtio_pci__signal_config(struct kvm *kvm, struct virtio_pci *vpci)
+int virtio_pci__signal_config(struct kvm *kvm, struct virtio_trans *vtrans)
 {
+       struct virtio_pci *vpci = vtrans->virtio;
        int tbl = vpci->config_vector;
 
        if (virtio_pci__msix_enabled(vpci)) {
@@ -255,16 +276,17 @@ int virtio_pci__signal_config(struct kvm *kvm, struct virtio_pci *vpci)
        return 0;
 }
 
-int virtio_pci__init(struct kvm *kvm, struct virtio_pci *vpci, void *dev,
+int virtio_pci__init(struct kvm *kvm, struct virtio_trans *vtrans, void *dev,
                        int device_id, int subsys_id, int class)
 {
+       struct virtio_pci *vpci = vtrans->virtio;
        u8 pin, line, ndev;
 
        vpci->dev = dev;
        vpci->msix_io_block = pci_get_io_space_block(PCI_IO_SIZE);
        vpci->msix_pba_block = pci_get_io_space_block(PCI_IO_SIZE);
 
-       vpci->base_addr = ioport__register(IOPORT_EMPTY, &virtio_pci__io_ops, IOPORT_SIZE, vpci);
+       vpci->base_addr = ioport__register(IOPORT_EMPTY, &virtio_pci__io_ops, IOPORT_SIZE, vtrans);
        kvm__register_mmio(kvm, vpci->msix_io_block, 0x100, callback_mmio_table, vpci);
        kvm__register_mmio(kvm, vpci->msix_pba_block, 0x100, callback_mmio_pba, vpci);
 
index efb94c9284c8530f144bd9b0a02300faf0f6e305..c333e6bd3094962474938d0e0523b328ecb172d1 100644 (file)
@@ -7,7 +7,7 @@
 #include "kvm/kvm.h"
 #include "kvm/threadpool.h"
 #include "kvm/guest_compat.h"
-#include "kvm/virtio-pci.h"
+#include "kvm/virtio-trans.h"
 
 #include <linux/virtio_ring.h>
 #include <linux/virtio_rng.h>
@@ -30,7 +30,7 @@ struct rng_dev_job {
 
 struct rng_dev {
        struct list_head        list;
-       struct virtio_pci       vpci;
+       struct virtio_trans     vtrans;
 
        int                     fd;
 
@@ -87,7 +87,7 @@ static void virtio_rng_do_io(struct kvm *kvm, void *param)
        while (virt_queue__available(vq))
                virtio_rng_do_io_request(kvm, rdev, vq);
 
-       virtio_pci__signal_vq(kvm, &rdev->vpci, vq - rdev->vqs);
+       rdev->vtrans.trans_ops->signal_vq(kvm, &rdev->vtrans, vq - rdev->vqs);
 }
 
 static int init_vq(struct kvm *kvm, void *dev, u32 vq, u32 pfn)
@@ -138,6 +138,17 @@ static int get_size_vq(struct kvm *kvm, void *dev, u32 vq)
        return VIRTIO_RNG_QUEUE_SIZE;
 }
 
+static struct virtio_ops rng_dev_virtio_ops = (struct virtio_ops) {
+       .set_config             = set_config,
+       .get_config             = get_config,
+       .get_host_features      = get_host_features,
+       .set_guest_features     = set_guest_features,
+       .init_vq                = init_vq,
+       .notify_vq              = notify_vq,
+       .get_pfn_vq             = get_pfn_vq,
+       .get_size_vq            = get_size_vq,
+};
+
 void virtio_rng__init(struct kvm *kvm)
 {
        struct rng_dev *rdev;
@@ -150,17 +161,10 @@ void virtio_rng__init(struct kvm *kvm)
        if (rdev->fd < 0)
                die("Failed initializing RNG");
 
-       virtio_pci__init(kvm, &rdev->vpci, rdev, PCI_DEVICE_ID_VIRTIO_RNG, VIRTIO_ID_RNG, PCI_CLASS_RNG);
-       rdev->vpci.ops = (struct virtio_pci_ops) {
-               .set_config             = set_config,
-               .get_config             = get_config,
-               .get_host_features      = get_host_features,
-               .set_guest_features     = set_guest_features,
-               .init_vq                = init_vq,
-               .notify_vq              = notify_vq,
-               .get_pfn_vq             = get_pfn_vq,
-               .get_size_vq            = get_size_vq,
-       };
+       virtio_trans_init(&rdev->vtrans, VIRTIO_PCI);
+       rdev->vtrans.trans_ops->init(kvm, &rdev->vtrans, rdev, PCI_DEVICE_ID_VIRTIO_RNG,
+                                       VIRTIO_ID_RNG, PCI_CLASS_RNG);
+       rdev->vtrans.virtio_ops = &rng_dev_virtio_ops;
 
        list_add_tail(&rdev->list, &rdevs);
 
diff --git a/tools/kvm/virtio/trans.c b/tools/kvm/virtio/trans.c
new file mode 100644 (file)
index 0000000..50c206d
--- /dev/null
@@ -0,0 +1,22 @@
+#include "kvm/virtio-trans.h"
+
+#include "kvm/virtio-pci.h"
+#include "kvm/util.h"
+
+#include <stdlib.h>
+
+int virtio_trans_init(struct virtio_trans *vtrans, enum virtio_trans_type type)
+{
+       void *trans;
+
+       switch (type) {
+       case VIRTIO_PCI:
+               trans = calloc(sizeof(struct virtio_pci), 1);
+               if (!trans)
+                       die("Failed allocating virtio transport");
+               vtrans->virtio = trans;
+               vtrans->trans_ops = virtio_pci__get_trans_ops();
+       default:
+               return -1;
+       };
+}
\ No newline at end of file