Signed-off-by: Sasha Levin <levinsasha...@gmail.com>
---
 tools/kvm/virtio/balloon.c |  267 ++++++++++++++++----------------------------
 1 files changed, 97 insertions(+), 170 deletions(-)

diff --git a/tools/kvm/virtio/balloon.c b/tools/kvm/virtio/balloon.c
index 7f3fe65..6b93121 100644
--- a/tools/kvm/virtio/balloon.c
+++ b/tools/kvm/virtio/balloon.c
@@ -2,24 +2,24 @@
 
 #include "kvm/virtio-pci-dev.h"
 
-#include "kvm/disk-image.h"
 #include "kvm/virtio.h"
-#include "kvm/ioport.h"
 #include "kvm/util.h"
 #include "kvm/kvm.h"
 #include "kvm/pci.h"
 #include "kvm/threadpool.h"
-#include "kvm/irq.h"
 #include "kvm/ioeventfd.h"
 #include "kvm/guest_compat.h"
+#include "kvm/virtio-pci.h"
 
 #include <linux/virtio_ring.h>
 #include <linux/virtio_balloon.h>
 
+#include <linux/kernel.h>
 #include <linux/list.h>
 #include <fcntl.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <sys/mman.h>
 #include <pthread.h>
 
 #define NUM_VIRT_QUEUES                3
@@ -29,17 +29,12 @@
 #define VIRTIO_BLN_STATS       2
 
 struct bln_dev {
-       struct pci_device_header pci_hdr;
        struct list_head        list;
+       struct virtio_pci       vpci;
 
-       u16                     base_addr;
-       u8                      status;
-       u8                      isr;
-       u16                     config_vector;
-       u32                     host_features;
+       u32                     features;
 
        /* virtio queue */
-       u16                     queue_selector;
        struct virt_queue       vqs[NUM_VIRT_QUEUES];
        struct thread_pool__job jobs[NUM_VIRT_QUEUES];
 
@@ -56,68 +51,6 @@ struct bln_dev {
 static struct bln_dev bdev;
 extern struct kvm *kvm;
 
-static bool virtio_bln_dev_in(void *data, unsigned long offset, int size)
-{
-       u8 *config_space = (u8 *) &bdev.config;
-
-       if (size != 1)
-               return false;
-
-       ioport__write8(data, config_space[offset - VIRTIO_MSI_CONFIG_VECTOR]);
-
-       return true;
-}
-
-static bool virtio_bln_dev_out(void *data, unsigned long offset, int size)
-{
-       u8 *config_space = (u8 *) &bdev.config;
-
-       if (size != 1)
-               return false;
-
-       config_space[offset - VIRTIO_MSI_CONFIG_VECTOR] = *(u8 *)data;
-
-       return true;
-}
-
-static bool virtio_bln_pci_io_in(struct ioport *ioport, struct kvm *kvm, u16 
port, void *data, int size)
-{
-       unsigned long offset;
-       bool ret = true;
-
-       offset = port - bdev.base_addr;
-
-       switch (offset) {
-       case VIRTIO_PCI_HOST_FEATURES:
-               ioport__write32(data, bdev.host_features);
-               break;
-       case VIRTIO_PCI_GUEST_FEATURES:
-       case VIRTIO_PCI_QUEUE_SEL:
-       case VIRTIO_PCI_QUEUE_NOTIFY:
-               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_BLN_QUEUE_SIZE);
-               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;
-       default:
-               ret = virtio_bln_dev_in(data, offset, size);
-               break;
-       };
-
-       return ret;
-}
-
 static bool virtio_bln_do_io_request(struct kvm *kvm, struct bln_dev *bdev, 
struct virt_queue *queue)
 {
        struct iovec iov[VIRTIO_BLN_QUEUE_SIZE];
@@ -182,13 +115,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);
-               virt_queue__trigger_irq(vq, bdev.pci_hdr.irq_line, &bdev.isr, 
kvm);
+               virtio_pci__signal_vq(kvm, &bdev.vpci, VIRTIO_BLN_STATS);
                return;
        }
 
        while (virt_queue__available(vq)) {
                virtio_bln_do_io_request(kvm, &bdev, vq);
-               virt_queue__trigger_irq(vq, bdev.pci_hdr.irq_line, &bdev.isr, 
kvm);
+               virtio_pci__signal_vq(kvm, &bdev.vpci, vq - bdev.vqs);
        }
 }
 
@@ -197,82 +130,13 @@ static void ioevent_callback(struct kvm *kvm, void *param)
        thread_pool__do_job(param);
 }
 
-static bool virtio_bln_pci_io_out(struct ioport *ioport, struct kvm *kvm, u16 
port, void *data, int size)
-{
-       unsigned long offset;
-       bool ret = true;
-       struct ioevent ioevent;
-
-       offset = port - bdev.base_addr;
-
-       switch (offset) {
-       case VIRTIO_MSI_QUEUE_VECTOR:
-       case VIRTIO_PCI_GUEST_FEATURES:
-               break;
-       case VIRTIO_PCI_QUEUE_PFN: {
-               struct virt_queue *queue;
-               void *p;
-
-               compat__remove_message(bdev.compat_id);
-
-               queue                   = &bdev.vqs[bdev.queue_selector];
-               queue->pfn              = ioport__read32(data);
-               p                       = guest_pfn_to_host(kvm, queue->pfn);
-
-               vring_init(&queue->vring, VIRTIO_BLN_QUEUE_SIZE, p, 
VIRTIO_PCI_VRING_ALIGN);
-
-               thread_pool__init_job(&bdev.jobs[bdev.queue_selector], kvm, 
virtio_bln_do_io, queue);
-
-               ioevent = (struct ioevent) {
-                       .io_addr                = bdev.base_addr + 
VIRTIO_PCI_QUEUE_NOTIFY,
-                       .io_len                 = sizeof(u16),
-                       .fn                     = ioevent_callback,
-                       .fn_ptr                 = 
&bdev.jobs[bdev.queue_selector],
-                       .datamatch              = bdev.queue_selector,
-                       .fn_kvm                 = kvm,
-                       .fd                     = eventfd(0, 0),
-               };
-
-               ioeventfd__add_event(&ioevent);
-
-               break;
-       }
-       case VIRTIO_PCI_QUEUE_SEL:
-               bdev.queue_selector     = ioport__read16(data);
-               break;
-       case VIRTIO_PCI_QUEUE_NOTIFY: {
-               u16 queue_index;
-               queue_index             = ioport__read16(data);
-               thread_pool__do_job(&bdev.jobs[queue_index]);
-               break;
-       }
-       case VIRTIO_PCI_STATUS:
-               bdev.status             = ioport__read8(data);
-               break;
-       case VIRTIO_MSI_CONFIG_VECTOR:
-               bdev.config_vector      = VIRTIO_MSI_NO_VECTOR;
-               break;
-       default:
-               ret = virtio_bln_dev_out(data, offset, size);
-               break;
-       };
-
-       return ret;
-}
-
-static struct ioport_operations virtio_bln_io_ops = {
-       .io_in                          = virtio_bln_pci_io_in,
-       .io_out                         = virtio_bln_pci_io_out,
-};
-
 static int virtio_bln__collect_stats(void)
 {
        u64 tmp;
 
        virt_queue__set_used_elem(&bdev.vqs[VIRTIO_BLN_STATS], 
bdev.cur_stat_head,
                                  sizeof(struct virtio_balloon_stat));
-       virt_queue__trigger_irq(&bdev.vqs[VIRTIO_BLN_STATS], 
bdev.pci_hdr.irq_line,
-                               &bdev.isr, kvm);
+       virtio_pci__signal_vq(kvm, &bdev.vpci, VIRTIO_BLN_STATS);
 
        if (read(bdev.stat_waitfd, &tmp, sizeof(tmp)) <= 0)
                return -EFAULT;
@@ -332,44 +196,107 @@ static void handle_sigmem(int sig)
        }
 
        /* Notify that the configuration space has changed */
-       bdev.isr = VIRTIO_PCI_ISR_CONFIG;
-       kvm__irq_line(kvm, bdev.pci_hdr.irq_line, 1);
+       virtio_pci__signal_config(kvm, &bdev.vpci);
 }
 
-void virtio_bln__init(struct kvm *kvm)
+static void set_config(struct kvm *kvm, void *dev, u8 data, u32 offset)
 {
-       u8 pin, line, dev;
-       u16 bdev_base_addr;
+       struct bln_dev *bdev = dev;
 
-       signal(SIGKVMADDMEM, handle_sigmem);
-       signal(SIGKVMDELMEM, handle_sigmem);
-       signal(SIGKVMMEMSTAT, handle_sigmem);
+       ((u8 *)(&bdev->config))[offset] = data;
+}
+
+static u8 get_config(struct kvm *kvm, void *dev, u32 offset)
+{
+       struct bln_dev *bdev = dev;
 
-       bdev_base_addr = ioport__register(IOPORT_EMPTY, &virtio_bln_io_ops, 
IOPORT_SIZE, &bdev);
-
-       bdev.pci_hdr = (struct pci_device_header) {
-               .vendor_id              = PCI_VENDOR_ID_REDHAT_QUMRANET,
-               .device_id              = PCI_DEVICE_ID_VIRTIO_BLN,
-               .header_type            = PCI_HEADER_TYPE_NORMAL,
-               .revision_id            = 0,
-               .class                  = 0x010000,
-               .subsys_vendor_id       = 
PCI_SUBSYSTEM_VENDOR_ID_REDHAT_QUMRANET,
-               .subsys_id              = VIRTIO_ID_BALLOON,
-               .bar[0]                 = bdev_base_addr | 
PCI_BASE_ADDRESS_SPACE_IO,
+       return ((u8 *)(&bdev->config))[offset];
+}
+
+static u32 get_host_features(struct kvm *kvm, void *dev)
+{
+       return 1 << VIRTIO_BALLOON_F_STATS_VQ;
+}
+
+static void set_guest_features(struct kvm *kvm, void *dev, u32 features)
+{
+       struct bln_dev *bdev = dev;
+
+       bdev->features = features;
+}
+
+static int init_vq(struct kvm *kvm, void *dev, u32 vq, u32 pfn)
+{
+       struct bln_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);
+
+       thread_pool__init_job(&bdev->jobs[vq], kvm, virtio_bln_do_io, queue);
+       vring_init(&queue->vring, VIRTIO_BLN_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->jobs[vq],
+               .datamatch      = vq,
+               .fn_kvm         = kvm,
+               .fd             = eventfd(0, 0),
        };
 
-       bdev.base_addr = bdev_base_addr;
+       ioeventfd__add_event(&ioevent);
 
-       if (irq__register_device(VIRTIO_ID_BALLOON, &dev, &pin, &line) < 0)
-               return;
+       return 0;
+}
+
+static int notify_vq(struct kvm *kvm, void *dev, u32 vq)
+{
+       struct bln_dev *bdev = dev;
+
+       thread_pool__do_job(&bdev->jobs[vq]);
+
+       return 0;
+}
+
+static int get_pfn_vq(struct kvm *kvm, void *dev, u32 vq)
+{
+       struct bln_dev *bdev = dev;
+
+       return bdev->vqs[vq].pfn;
+}
+
+static int get_size_vq(struct kvm *kvm, void *dev, u32 vq)
+{
+       return VIRTIO_BLN_QUEUE_SIZE;
+}
+
+void virtio_bln__init(struct kvm *kvm)
+{
+       signal(SIGKVMADDMEM, handle_sigmem);
+       signal(SIGKVMDELMEM, handle_sigmem);
+       signal(SIGKVMMEMSTAT, handle_sigmem);
 
-       bdev.pci_hdr.irq_pin    = pin;
-       bdev.pci_hdr.irq_line   = line;
-       bdev.host_features      = 1 << VIRTIO_BALLOON_F_STATS_VQ;
        bdev.stat_waitfd        = eventfd(0, 0);
        memset(&bdev.config, 0, sizeof(struct virtio_balloon_config));
 
-       pci__register(&bdev.pci_hdr, dev);
+       virtio_pci__init(kvm, &bdev.vpci, &bdev, PCI_DEVICE_ID_VIRTIO_BLN, 
VIRTIO_ID_BALLOON);
+       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,
+       };
 
        bdev.compat_id = compat__add_message("virtio-balloon device was not 
detected",
                                                "While you have requested a 
virtio-balloon device, "
-- 
1.7.6

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

Reply via email to