yeahuh / rpms / qemu-kvm

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