From ef10d0bfc95f72bebd37a2ef7205bf2d1f68d162 Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Wed, 9 Nov 2011 22:01:52 +0200 Subject: [PATCH] kvm tools: Add abstract virtio transport layer 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 Cc: Peter Maydell Signed-off-by: Sasha Levin Signed-off-by: Pekka Enberg --- tools/kvm/Makefile | 1 + tools/kvm/include/kvm/virtio-9p.h | 4 +- tools/kvm/include/kvm/virtio-pci.h | 25 +++-------- tools/kvm/include/kvm/virtio-trans.h | 41 +++++++++++++++++ tools/kvm/virtio/9p.c | 28 +++++++----- tools/kvm/virtio/balloon.c | 38 +++++++++------- tools/kvm/virtio/blk.c | 31 +++++++------ tools/kvm/virtio/console.c | 33 ++++++++------ tools/kvm/virtio/net.c | 34 +++++++------- tools/kvm/virtio/pci.c | 66 ++++++++++++++++++---------- tools/kvm/virtio/rng.c | 32 ++++++++------ tools/kvm/virtio/trans.c | 22 ++++++++++ 12 files changed, 228 insertions(+), 127 deletions(-) create mode 100644 tools/kvm/include/kvm/virtio-trans.h create mode 100644 tools/kvm/virtio/trans.c diff --git a/tools/kvm/Makefile b/tools/kvm/Makefile index 20389f9c7b24..f4741f2c378f 100644 --- a/tools/kvm/Makefile +++ b/tools/kvm/Makefile @@ -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 diff --git a/tools/kvm/include/kvm/virtio-9p.h b/tools/kvm/include/kvm/virtio-9p.h index 3096df27c646..ac3dc45976b4 100644 --- a/tools/kvm/include/kvm/virtio-9p.h +++ b/tools/kvm/include/kvm/virtio-9p.h @@ -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 #include @@ -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; diff --git a/tools/kvm/include/kvm/virtio-pci.h b/tools/kvm/include/kvm/virtio-pci.h index 81196e53b89d..2bbb27108be5 100644 --- a/tools/kvm/include/kvm/virtio-pci.h +++ b/tools/kvm/include/kvm/virtio-pci.h @@ -2,6 +2,7 @@ #define KVM__VIRTIO_PCI_H #include "kvm/pci.h" +#include "kvm/virtio-trans.h" #include @@ -10,27 +11,13 @@ 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 index 000000000000..d9f4b95a0b22 --- /dev/null +++ b/tools/kvm/include/kvm/virtio-trans.h @@ -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 diff --git a/tools/kvm/virtio/9p.c b/tools/kvm/virtio/9p.c index 8104ac41ce6b..8e37925d07d8 100644 --- a/tools/kvm/virtio/9p.c +++ b/tools/kvm/virtio/9p.c @@ -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; diff --git a/tools/kvm/virtio/balloon.c b/tools/kvm/virtio/balloon.c index 9a52108c1f2b..07fd97654dda 100644 --- a/tools/kvm/virtio/balloon.c +++ b/tools/kvm/virtio/balloon.c @@ -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 @@ -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", diff --git a/tools/kvm/virtio/blk.c b/tools/kvm/virtio/blk.c index 223e79f68bd2..ed4e0991dd11 100644 --- a/tools/kvm/virtio/blk.c +++ b/tools/kvm/virtio/blk.c @@ -11,6 +11,7 @@ #include "kvm/guest_compat.h" #include "kvm/virtio-pci.h" #include "kvm/virtio.h" +#include "kvm/virtio-trans.h" #include #include @@ -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); diff --git a/tools/kvm/virtio/console.c b/tools/kvm/virtio/console.c index f0e4bf8b033e..68c30f519d77 100644 --- a/tools/kvm/virtio/console.c +++ b/tools/kvm/virtio/console.c @@ -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 #include @@ -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", diff --git a/tools/kvm/virtio/net.c b/tools/kvm/virtio/net.c index 7cd6794f941f..cee2b5bd14f3 100644 --- a/tools/kvm/virtio/net.c +++ b/tools/kvm/virtio/net.c @@ -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 #include @@ -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); diff --git a/tools/kvm/virtio/pci.c b/tools/kvm/virtio/pci.c index b8d1ec1b33cd..85994f879003 100644 --- a/tools/kvm/virtio/pci.c +++ b/tools/kvm/virtio/pci.c @@ -6,23 +6,36 @@ #include "kvm/irq.h" #include "kvm/virtio.h" #include "kvm/ioeventfd.h" +#include "kvm/virtio-trans.h" #include #include +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); diff --git a/tools/kvm/virtio/rng.c b/tools/kvm/virtio/rng.c index efb94c9284c8..c333e6bd3094 100644 --- a/tools/kvm/virtio/rng.c +++ b/tools/kvm/virtio/rng.c @@ -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 #include @@ -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 index 000000000000..50c206d839c4 --- /dev/null +++ b/tools/kvm/virtio/trans.c @@ -0,0 +1,22 @@ +#include "kvm/virtio-trans.h" + +#include "kvm/virtio-pci.h" +#include "kvm/util.h" + +#include + +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 -- 2.39.5