static int vfio_populate_device(VFIODevice *vbasedev) { VFIOINTp *intp, *tmp; int i, ret = -1; VFIOPlatformDevice *vdev = container_of(vbasedev, VFIOPlatformDevice, vbasedev); if (!(vbasedev->flags & VFIO_DEVICE_FLAGS_PLATFORM)) { error_report("vfio: Um, this isn't a platform device"); return ret; } vdev->regions = g_new0(VFIORegion *, vbasedev->num_regions); for (i = 0; i < vbasedev->num_regions; i++) { struct vfio_region_info reg_info = { .argsz = sizeof(reg_info) }; VFIORegion *ptr; vdev->regions[i] = g_malloc0(sizeof(VFIORegion)); ptr = vdev->regions[i]; reg_info.index = i; ret = ioctl(vbasedev->fd, VFIO_DEVICE_GET_REGION_INFO, &reg_info); if (ret) { error_report("vfio: Error getting region %d info: %m", i); goto reg_error; } ptr->flags = reg_info.flags; ptr->size = reg_info.size; ptr->fd_offset = reg_info.offset; ptr->nr = i; ptr->vbasedev = vbasedev; trace_vfio_platform_populate_regions(ptr->nr, (unsigned long)ptr->flags, (unsigned long)ptr->size, ptr->vbasedev->fd, (unsigned long)ptr->fd_offset); } vdev->mmap_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL, vfio_intp_mmap_enable, vdev); QSIMPLEQ_INIT(&vdev->pending_intp_queue); for (i = 0; i < vbasedev->num_irqs; i++) { struct vfio_irq_info irq = { .argsz = sizeof(irq) }; irq.index = i; ret = ioctl(vbasedev->fd, VFIO_DEVICE_GET_IRQ_INFO, &irq); if (ret) { error_printf("vfio: error getting device %s irq info", vbasedev->name); goto irq_err; } else { trace_vfio_platform_populate_interrupts(irq.index, irq.count, irq.flags); intp = vfio_init_intp(vbasedev, irq); if (!intp) { error_report("vfio: Error installing IRQ %d up", i); goto irq_err; } } } return 0; irq_err: timer_del(vdev->mmap_timer); QLIST_FOREACH_SAFE(intp, &vdev->intp_list, next, tmp) { QLIST_REMOVE(intp, next); g_free(intp); } reg_error: for (i = 0; i < vbasedev->num_regions; i++) { g_free(vdev->regions[i]); } g_free(vdev->regions); return ret; }