static VFIOGroup *vfio_get_group(int groupid, AddressSpace *as) { VFIOGroup *group; char path[32]; struct vfio_group_status status = { .argsz = sizeof(status) }; QLIST_FOREACH(group, &group_list, next) { if (group->groupid == groupid) { /* Found it. Now is it already in the right context? */ if (group->container->space->as == as) { return group; } else { error_report("vfio: group %d used in multiple address spaces", group->groupid); return NULL; } } } group = g_malloc0(sizeof(*group)); snprintf(path, sizeof(path), "/dev/vfio/%d", groupid); group->fd = qemu_open(path, O_RDWR); if (group->fd < 0) { error_report("vfio: error opening %s: %m", path); goto free_group_exit; } if (ioctl(group->fd, VFIO_GROUP_GET_STATUS, &status)) { error_report("vfio: error getting group status: %m"); goto close_fd_exit; } if (!(status.flags & VFIO_GROUP_FLAGS_VIABLE)) { error_report("vfio: error, group %d is not viable, please ensure " "all devices within the iommu_group are bound to their " "vfio bus driver.", groupid); goto close_fd_exit; } group->groupid = groupid; QLIST_INIT(&group->device_list); if (vfio_connect_container(group, as)) { error_report("vfio: failed to setup container for group %d", groupid); goto close_fd_exit; } if (QLIST_EMPTY(&group_list)) { qemu_register_reset(vfio_pci_reset_handler, NULL); } QLIST_INSERT_HEAD(&group_list, group, next); vfio_kvm_device_add_group(group); return group; close_fd_exit: close(group->fd); free_group_exit: g_free(group); return NULL; }