Signed-off-by: Sasha Levin <[email protected]>
---
 tools/kvm/virtio/blk.c |  263 ++++++++++++++++--------------------------------
 1 files changed, 88 insertions(+), 175 deletions(-)

diff --git a/tools/kvm/virtio/blk.c b/tools/kvm/virtio/blk.c
index 2ccf585..2e047d7 100644
--- a/tools/kvm/virtio/blk.c
+++ b/tools/kvm/virtio/blk.c
@@ -1,10 +1,8 @@
 #include "kvm/virtio-blk.h"
 
 #include "kvm/virtio-pci-dev.h"
-#include "kvm/irq.h"
 #include "kvm/disk-image.h"
 #include "kvm/virtio.h"
-#include "kvm/ioport.h"
 #include "kvm/mutex.h"
 #include "kvm/util.h"
 #include "kvm/kvm.h"
@@ -12,10 +10,12 @@
 #include "kvm/threadpool.h"
 #include "kvm/ioeventfd.h"
 #include "kvm/guest_compat.h"
+#include "kvm/virtio-pci.h"
 
 #include <linux/virtio_ring.h>
 #include <linux/virtio_blk.h>
 
+#include <linux/kernel.h>
 #include <linux/list.h>
 #include <linux/types.h>
 #include <pthread.h>
@@ -41,88 +41,19 @@ struct blk_dev {
        pthread_mutex_t                 mutex;
        struct list_head                list;
 
+       struct virtio_pci               vpci;
        struct virtio_blk_config        blk_config;
        struct disk_image               *disk;
-       u64                             base_addr;
-       u32                             host_features;
-       u32                             guest_features;
-       u16                             config_vector;
-       u8                              status;
-       u8                              isr;
        int                             compat_id;
-
-       /* virtio queue */
-       u16                             queue_selector;
+       u32                             features;
 
        struct virt_queue               vqs[NUM_VIRT_QUEUES];
        struct blk_dev_job              jobs[VIRTIO_BLK_QUEUE_SIZE];
        u16                             job_idx;
-       struct pci_device_header        pci_hdr;
 };
 
 static LIST_HEAD(bdevs);
 
-static bool virtio_blk_dev_in(struct blk_dev *bdev, void *data, unsigned long 
offset, int size)
-{
-       u8 *config_space = (u8 *) &bdev->blk_config;
-
-       if (size != 1)
-               return false;
-
-       ioport__write8(data, config_space[offset - VIRTIO_MSI_CONFIG_VECTOR]);
-
-       return true;
-}
-
-static bool virtio_blk_pci_io_in(struct ioport *ioport, struct kvm *kvm, u16 
port, void *data, int size)
-{
-       struct blk_dev *bdev;
-       u16 offset;
-       bool ret = true;
-
-       bdev    = ioport->priv;
-       offset  = port - bdev->base_addr;
-
-       mutex_lock(&bdev->mutex);
-
-       switch (offset) {
-       case VIRTIO_PCI_HOST_FEATURES:
-               ioport__write32(data, bdev->host_features);
-               break;
-       case VIRTIO_PCI_GUEST_FEATURES:
-               ret             = false;
-               break;
-       case VIRTIO_PCI_QUEUE_PFN:
-               ioport__write32(data, bdev->vqs[bdev->queue_selector].pfn);
-               break;
-       case VIRTIO_PCI_QUEUE_NUM:
-               ioport__write16(data, VIRTIO_BLK_QUEUE_SIZE);
-               break;
-       case VIRTIO_PCI_QUEUE_SEL:
-       case VIRTIO_PCI_QUEUE_NOTIFY:
-               ret             = false;
-               break;
-       case VIRTIO_PCI_STATUS:
-               ioport__write8(data, bdev->status);
-               break;
-       case VIRTIO_PCI_ISR:
-               ioport__write8(data, bdev->isr);
-               kvm__irq_line(kvm, bdev->pci_hdr.irq_line, VIRTIO_IRQ_LOW);
-               bdev->isr = VIRTIO_IRQ_LOW;
-               break;
-       case VIRTIO_MSI_CONFIG_VECTOR:
-               ioport__write16(data, bdev->config_vector);
-               break;
-       default:
-               ret = virtio_blk_dev_in(bdev, data, offset, size);
-               break;
-       };
-
-       mutex_unlock(&bdev->mutex);
-
-       return ret;
-}
-
 static void virtio_blk_do_io_request(struct kvm *kvm, void *param)
 {
        struct virtio_blk_outhdr *req;
@@ -172,7 +103,7 @@ static void virtio_blk_do_io_request(struct kvm *kvm, void 
*param)
        virt_queue__set_used_elem(queue, head, block_cnt);
        mutex_unlock(&bdev->mutex);
 
-       virt_queue__trigger_irq(queue, bdev->pci_hdr.irq_line, &bdev->isr, kvm);
+       virtio_pci__signal_vq(kvm, &bdev->vpci, queue - bdev->vqs);
 }
 
 static void virtio_blk_do_io(struct kvm *kvm, struct virt_queue *vq, struct 
blk_dev *bdev)
@@ -191,82 +122,93 @@ static void virtio_blk_do_io(struct kvm *kvm, struct 
virt_queue *vq, struct blk_
        }
 }
 
-static bool virtio_blk_pci_io_out(struct ioport *ioport, struct kvm *kvm, u16 
port, void *data, int size)
+static void ioevent_callback(struct kvm *kvm, void *param)
 {
-       struct blk_dev *bdev;
-       u16 offset;
-       bool ret = true;
+       struct blk_dev *bdev = param;
 
-       bdev    = ioport->priv;
-       offset  = port - bdev->base_addr;
+       virtio_blk_do_io(kvm, &bdev->vqs[0], bdev);
+}
 
-       mutex_lock(&bdev->mutex);
+static void set_config(struct kvm *kvm, void *dev, u8 data, u32 offset)
+{
+       struct blk_dev *bdev = dev;
 
-       switch (offset) {
-       case VIRTIO_PCI_GUEST_FEATURES:
-               bdev->guest_features    = ioport__read32(data);
-               break;
-       case VIRTIO_PCI_QUEUE_PFN: {
-               struct virt_queue *queue;
-               void *p;
+       ((u8 *)(&bdev->blk_config))[offset] = data;
+}
 
-               compat__remove_message(bdev->compat_id);
+static u8 get_config(struct kvm *kvm, void *dev, u32 offset)
+{
+       struct blk_dev *bdev = dev;
 
-               queue                   = &bdev->vqs[bdev->queue_selector];
-               queue->pfn              = ioport__read32(data);
-               p                       = guest_pfn_to_host(kvm, queue->pfn);
+       return ((u8 *)(&bdev->blk_config))[offset];
+}
 
-               vring_init(&queue->vring, VIRTIO_BLK_QUEUE_SIZE, p, 
VIRTIO_PCI_VRING_ALIGN);
+static u32 get_host_features(struct kvm *kvm, void *dev)
+{
+       return 1UL << VIRTIO_BLK_F_SEG_MAX | 1UL << VIRTIO_BLK_F_FLUSH;
+}
 
-               break;
-       }
-       case VIRTIO_PCI_QUEUE_SEL:
-               bdev->queue_selector    = ioport__read16(data);
-               break;
-       case VIRTIO_PCI_QUEUE_NOTIFY: {
-               u16 queue_index;
+static void set_guest_features(struct kvm *kvm, void *dev, u32 features)
+{
+       struct blk_dev *bdev = dev;
 
-               queue_index             = ioport__read16(data);
-               virtio_blk_do_io(kvm, &bdev->vqs[queue_index], bdev);
+       bdev->features = features;
+}
 
-               break;
-       }
-       case VIRTIO_PCI_STATUS:
-               bdev->status            = ioport__read8(data);
-               break;
-       case VIRTIO_MSI_CONFIG_VECTOR:
-               bdev->config_vector     = VIRTIO_MSI_NO_VECTOR;
-               break;
-       case VIRTIO_MSI_QUEUE_VECTOR:
-               break;
-       default:
-               ret                     = false;
-               break;
+static int init_vq(struct kvm *kvm, void *dev, u32 vq, u32 pfn)
+{
+       struct blk_dev *bdev = dev;
+       struct virt_queue *queue;
+       void *p;
+       struct ioevent ioevent;
+
+       compat__remove_message(bdev->compat_id);
+
+       queue                   = &bdev->vqs[vq];
+       queue->pfn              = pfn;
+       p                       = guest_pfn_to_host(kvm, queue->pfn);
+
+       vring_init(&queue->vring, VIRTIO_BLK_QUEUE_SIZE, p, 
VIRTIO_PCI_VRING_ALIGN);
+
+       ioevent = (struct ioevent) {
+               .io_addr        = bdev->vpci.base_addr + 
VIRTIO_PCI_QUEUE_NOTIFY,
+               .io_len         = sizeof(u16),
+               .fn             = ioevent_callback,
+               .fn_ptr         = bdev,
+               .datamatch      = vq,
+               .fn_kvm         = kvm,
+               .fd             = eventfd(0, 0),
        };
 
-       mutex_unlock(&bdev->mutex);
+       ioeventfd__add_event(&ioevent);
 
-       return ret;
+       return 0;
 }
 
-static struct ioport_operations virtio_blk_io_ops = {
-       .io_in  = virtio_blk_pci_io_in,
-       .io_out = virtio_blk_pci_io_out,
-};
+static int notify_vq(struct kvm *kvm, void *dev, u32 vq)
+{
+       struct blk_dev *bdev = dev;
 
-static void ioevent_callback(struct kvm *kvm, void *param)
+       virtio_blk_do_io(kvm, &bdev->vqs[vq], bdev);
+
+       return 0;
+}
+
+static int get_pfn_vq(struct kvm *kvm, void *dev, u32 vq)
 {
-       struct blk_dev *bdev = param;
+       struct blk_dev *bdev = dev;
 
-       virtio_blk_do_io(kvm, &bdev->vqs[0], bdev);
+       return bdev->vqs[vq].pfn;
+}
+
+static int get_size_vq(struct kvm *kvm, void *dev, u32 vq)
+{
+       return VIRTIO_BLK_QUEUE_SIZE;
 }
 
 void virtio_blk__init(struct kvm *kvm, struct disk_image *disk)
 {
-       u16 blk_dev_base_addr;
-       u8 dev, pin, line, i;
        struct blk_dev *bdev;
-       struct ioevent ioevent;
 
        if (!disk)
                return;
@@ -275,57 +217,28 @@ void virtio_blk__init(struct kvm *kvm, struct disk_image 
*disk)
        if (bdev == NULL)
                die("Failed allocating bdev");
 
-       blk_dev_base_addr       = ioport__register(IOPORT_EMPTY, 
&virtio_blk_io_ops, IOPORT_SIZE, bdev);
-
-       *bdev                   = (struct blk_dev) {
-               .mutex                          = PTHREAD_MUTEX_INITIALIZER,
-               .disk                           = disk,
-               .base_addr                      = blk_dev_base_addr,
-               .blk_config                     = (struct virtio_blk_config) {
-                       .capacity               = disk->size / SECTOR_SIZE,
-                       .seg_max                = DISK_SEG_MAX,
-               },
-               .pci_hdr = (struct pci_device_header) {
-                       .vendor_id              = PCI_VENDOR_ID_REDHAT_QUMRANET,
-                       .device_id              = PCI_DEVICE_ID_VIRTIO_BLK,
-                       .header_type            = PCI_HEADER_TYPE_NORMAL,
-                       .revision_id            = 0,
-                       .class                  = 0x010000,
-                       .subsys_vendor_id       = 
PCI_SUBSYSTEM_VENDOR_ID_REDHAT_QUMRANET,
-                       .subsys_id              = VIRTIO_ID_BLOCK,
-                       .bar[0]                 = blk_dev_base_addr | 
PCI_BASE_ADDRESS_SPACE_IO,
+       *bdev = (struct blk_dev) {
+               .mutex                  = PTHREAD_MUTEX_INITIALIZER,
+               .disk                   = disk,
+               .blk_config             = (struct virtio_blk_config) {
+                       .capacity       = disk->size / SECTOR_SIZE,
+                       .seg_max        = DISK_SEG_MAX,
                },
-               /*
-                * Note we don't set VIRTIO_BLK_F_GEOMETRY here so the
-                * guest kernel will compute disk geometry by own, the
-                * same applies to VIRTIO_BLK_F_BLK_SIZE
-                */
-               .host_features                  = (1UL << VIRTIO_BLK_F_SEG_MAX 
| 1UL << VIRTIO_BLK_F_FLUSH),
        };
 
-       list_add_tail(&bdev->list, &bdevs);
-
-       if (irq__register_device(VIRTIO_ID_BLOCK, &dev, &pin, &line) < 0)
-               return;
-
-       bdev->pci_hdr.irq_pin   = pin;
-       bdev->pci_hdr.irq_line  = line;
-
-       pci__register(&bdev->pci_hdr, dev);
-
-       for (i = 0; i < NUM_VIRT_QUEUES; i++) {
-               ioevent = (struct ioevent) {
-                       .io_addr                = blk_dev_base_addr + 
VIRTIO_PCI_QUEUE_NOTIFY,
-                       .io_len                 = sizeof(u16),
-                       .fn                     = ioevent_callback,
-                       .datamatch              = i,
-                       .fn_ptr                 = bdev,
-                       .fn_kvm                 = kvm,
-                       .fd                     = eventfd(0, 0),
-               };
+       virtio_pci__init(kvm, &bdev->vpci, bdev, PCI_DEVICE_ID_VIRTIO_BLK, 
VIRTIO_ID_BLOCK);
+       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,
+       };
 
-               ioeventfd__add_event(&ioevent);
-       }
+       list_add_tail(&bdev->list, &bdevs);
 
        bdev->compat_id = compat__add_message("virtio-blk device was not 
detected",
                                                "While you have requested a 
virtio-blk device, "
@@ -348,7 +261,7 @@ void virtio_blk__delete_all(struct kvm *kvm)
                struct blk_dev *bdev;
 
                bdev = list_first_entry(&bdevs, struct blk_dev, list);
-               ioeventfd__del_event(bdev->base_addr + VIRTIO_PCI_QUEUE_NOTIFY, 
0);
+               ioeventfd__del_event(bdev->vpci.base_addr + 
VIRTIO_PCI_QUEUE_NOTIFY, 0);
                list_del(&bdev->list);
                free(bdev);
        }
-- 
1.7.6

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

Reply via email to