218e99
From 3f6f409e0c66e7f67d8830ffce9576ca306853ff Mon Sep 17 00:00:00 2001
218e99
From: Alex Williamson <alex.williamson@redhat.com>
218e99
Date: Tue, 5 Nov 2013 17:51:11 +0100
218e99
Subject: [PATCH 21/25] vfio-pci: Make use of new KVM-VFIO device
218e99
218e99
RH-Author: Alex Williamson <alex.williamson@redhat.com>
218e99
Message-id: <20131105175111.19705.95280.stgit@bling.home>
218e99
Patchwork-id: 55443
218e99
O-Subject: [RHEL7 qemu-kvm PATCH 2/2] vfio-pci: Make use of new KVM-VFIO device
218e99
Bugzilla: 1025474
218e99
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
218e99
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
218e99
RH-Acked-by: Michael S. Tsirkin <mst@redhat.com>
218e99
218e99
Bugzilla: 1025474
218e99
Upstream: Posted - http://lists.nongnu.org/archive/html/qemu-devel/2013-11/msg00091.html
218e99
218e99
Add and remove groups from the KVM virtual VFIO device as we make
218e99
use of them.  This allows KVM to optimize for performance and
218e99
correctness based on properties of the group.
218e99
218e99
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
218e99
---
218e99
 hw/misc/vfio.c |   65 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
218e99
 1 file changed, 65 insertions(+)
218e99
218e99
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
218e99
---
218e99
 hw/misc/vfio.c |   65 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
218e99
 1 files changed, 65 insertions(+), 0 deletions(-)
218e99
218e99
diff --git a/hw/misc/vfio.c b/hw/misc/vfio.c
218e99
index 331ae5f..b7f213b 100644
218e99
--- a/hw/misc/vfio.c
218e99
+++ b/hw/misc/vfio.c
218e99
@@ -208,6 +208,15 @@ static QLIST_HEAD(, VFIOContainer)
218e99
 static QLIST_HEAD(, VFIOGroup)
218e99
     group_list = QLIST_HEAD_INITIALIZER(group_list);
218e99
 
218e99
+/*
218e99
+ * We have a single VFIO pseudo device per KVM VM.  Once created it lives
218e99
+ * for the life of the VM.  Closing the file descriptor only drops our
218e99
+ * reference to it and the device's reference to kvm.  Therefore once
218e99
+ * initialized, this file descriptor is only released on QEMU exit and
218e99
+ * we'll re-use it should another vfio device be attached before then.
218e99
+ */
218e99
+static int vfio_kvm_device_fd = -1;
218e99
+
218e99
 static void vfio_disable_interrupts(VFIODevice *vdev);
218e99
 static uint32_t vfio_pci_read_config(PCIDevice *pdev, uint32_t addr, int len);
218e99
 static void vfio_pci_write_config(PCIDevice *pdev, uint32_t addr,
218e99
@@ -3033,6 +3042,59 @@ static void vfio_pci_reset_handler(void *opaque)
218e99
     }
218e99
 }
218e99
 
218e99
+static void vfio_kvm_device_add_group(VFIOGroup *group)
218e99
+{
218e99
+#ifdef CONFIG_KVM
218e99
+    struct kvm_device_attr attr = {
218e99
+        .group = KVM_DEV_VFIO_GROUP,
218e99
+        .attr = KVM_DEV_VFIO_GROUP_ADD,
218e99
+        .addr = (uint64_t)(unsigned long)&group->fd,
218e99
+    };
218e99
+
218e99
+    if (!kvm_enabled()) {
218e99
+        return;
218e99
+    }
218e99
+
218e99
+    if (vfio_kvm_device_fd < 0) {
218e99
+        struct kvm_create_device cd = {
218e99
+            .type = KVM_DEV_TYPE_VFIO,
218e99
+        };
218e99
+
218e99
+        if (kvm_vm_ioctl(kvm_state, KVM_CREATE_DEVICE, &cd)) {
218e99
+            DPRINTF("KVM_CREATE_DEVICE: %m\n");
218e99
+            return;
218e99
+        }
218e99
+
218e99
+        vfio_kvm_device_fd = cd.fd;
218e99
+    }
218e99
+
218e99
+    if (ioctl(vfio_kvm_device_fd, KVM_SET_DEVICE_ATTR, &attr)) {
218e99
+        error_report("Failed to add group %d to KVM VFIO device: %m",
218e99
+                     group->groupid);
218e99
+    }
218e99
+#endif
218e99
+}
218e99
+
218e99
+static void vfio_kvm_device_del_group(VFIOGroup *group)
218e99
+{
218e99
+#ifdef CONFIG_KVM
218e99
+    struct kvm_device_attr attr = {
218e99
+        .group = KVM_DEV_VFIO_GROUP,
218e99
+        .attr = KVM_DEV_VFIO_GROUP_DEL,
218e99
+        .addr = (uint64_t)(unsigned long)&group->fd,
218e99
+    };
218e99
+
218e99
+    if (vfio_kvm_device_fd < 0) {
218e99
+        return;
218e99
+    }
218e99
+
218e99
+    if (ioctl(vfio_kvm_device_fd, KVM_SET_DEVICE_ATTR, &attr)) {
218e99
+        error_report("Failed to remove group %d to KVM VFIO device: %m",
218e99
+                     group->groupid);
218e99
+    }
218e99
+#endif
218e99
+}
218e99
+
218e99
 static int vfio_connect_container(VFIOGroup *group)
218e99
 {
218e99
     VFIOContainer *container;
218e99
@@ -3181,6 +3243,8 @@ static VFIOGroup *vfio_get_group(int groupid)
218e99
 
218e99
     QLIST_INSERT_HEAD(&group_list, group, next);
218e99
 
218e99
+    vfio_kvm_device_add_group(group);
218e99
+
218e99
     return group;
218e99
 }
218e99
 
218e99
@@ -3190,6 +3254,7 @@ static void vfio_put_group(VFIOGroup *group)
218e99
         return;
218e99
     }
218e99
 
218e99
+    vfio_kvm_device_del_group(group);
218e99
     vfio_disconnect_container(group);
218e99
     QLIST_REMOVE(group, next);
218e99
     DPRINTF("vfio_put_group: close group->fd\n");
218e99
-- 
218e99
1.7.1
218e99