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
#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>
struct p9_dev {
struct list_head list;
- struct virtio_pci vpci;
+ struct virtio_trans vtrans;
struct virtio_9p_config *config;
u32 features;
#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;
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
--- /dev/null
+#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
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);
}
}
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;
#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>
struct bln_dev {
struct list_head list;
- struct virtio_pci vpci;
+ struct virtio_trans vtrans;
u32 features;
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);
}
}
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;
}
/* 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)
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);
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",
#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>
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;
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);
}
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;
},
};
- 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);
#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>
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;
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);
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",
#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>
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];
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);
}
}
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);
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;
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);
#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,
};
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);
} 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;
}
{
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;
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);
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;
}
{
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;
};
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)) {
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)) {
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);
#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>
struct rng_dev {
struct list_head list;
- struct virtio_pci vpci;
+ struct virtio_trans vtrans;
int fd;
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)
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;
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);
--- /dev/null
+#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