vfio-pci: Make use of new KVM-VFIO device

Add and remove groups from the KVM virtual VFIO device as we make
use of them.  This allows KVM to optimize for performance and
correctness based on properties of the group.

Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
This commit is contained in:
Alex Williamson 2013-12-06 11:16:13 -07:00
parent bf63839ffa
commit 5b49ab188f

View File

@ -208,6 +208,17 @@ static QLIST_HEAD(, VFIOContainer)
static QLIST_HEAD(, VFIOGroup)
group_list = QLIST_HEAD_INITIALIZER(group_list);
#ifdef CONFIG_KVM
/*
* We have a single VFIO pseudo device per KVM VM. Once created it lives
* for the life of the VM. Closing the file descriptor only drops our
* reference to it and the device's reference to kvm. Therefore once
* initialized, this file descriptor is only released on QEMU exit and
* we'll re-use it should another vfio device be attached before then.
*/
static int vfio_kvm_device_fd = -1;
#endif
static void vfio_disable_interrupts(VFIODevice *vdev);
static uint32_t vfio_pci_read_config(PCIDevice *pdev, uint32_t addr, int len);
static void vfio_pci_write_config(PCIDevice *pdev, uint32_t addr,
@ -3041,6 +3052,59 @@ static void vfio_pci_reset_handler(void *opaque)
}
}
static void vfio_kvm_device_add_group(VFIOGroup *group)
{
#ifdef CONFIG_KVM
struct kvm_device_attr attr = {
.group = KVM_DEV_VFIO_GROUP,
.attr = KVM_DEV_VFIO_GROUP_ADD,
.addr = (uint64_t)(unsigned long)&group->fd,
};
if (!kvm_enabled()) {
return;
}
if (vfio_kvm_device_fd < 0) {
struct kvm_create_device cd = {
.type = KVM_DEV_TYPE_VFIO,
};
if (kvm_vm_ioctl(kvm_state, KVM_CREATE_DEVICE, &cd)) {
DPRINTF("KVM_CREATE_DEVICE: %m\n");
return;
}
vfio_kvm_device_fd = cd.fd;
}
if (ioctl(vfio_kvm_device_fd, KVM_SET_DEVICE_ATTR, &attr)) {
error_report("Failed to add group %d to KVM VFIO device: %m",
group->groupid);
}
#endif
}
static void vfio_kvm_device_del_group(VFIOGroup *group)
{
#ifdef CONFIG_KVM
struct kvm_device_attr attr = {
.group = KVM_DEV_VFIO_GROUP,
.attr = KVM_DEV_VFIO_GROUP_DEL,
.addr = (uint64_t)(unsigned long)&group->fd,
};
if (vfio_kvm_device_fd < 0) {
return;
}
if (ioctl(vfio_kvm_device_fd, KVM_SET_DEVICE_ATTR, &attr)) {
error_report("Failed to remove group %d to KVM VFIO device: %m",
group->groupid);
}
#endif
}
static int vfio_connect_container(VFIOGroup *group)
{
VFIOContainer *container;
@ -3189,6 +3253,8 @@ static VFIOGroup *vfio_get_group(int groupid)
QLIST_INSERT_HEAD(&group_list, group, next);
vfio_kvm_device_add_group(group);
return group;
}
@ -3198,6 +3264,7 @@ static void vfio_put_group(VFIOGroup *group)
return;
}
vfio_kvm_device_del_group(group);
vfio_disconnect_container(group);
QLIST_REMOVE(group, next);
DPRINTF("vfio_put_group: close group->fd\n");