168c07d76SCédric Le Goater /* 268c07d76SCédric Le Goater * VFIO device 368c07d76SCédric Le Goater * 468c07d76SCédric Le Goater * Copyright Red Hat, Inc. 2012 568c07d76SCédric Le Goater * 668c07d76SCédric Le Goater * Authors: 768c07d76SCédric Le Goater * Alex Williamson <alex.williamson@redhat.com> 868c07d76SCédric Le Goater * 968c07d76SCédric Le Goater * This work is licensed under the terms of the GNU GPL, version 2. See 1068c07d76SCédric Le Goater * the COPYING file in the top-level directory. 1168c07d76SCédric Le Goater * 1268c07d76SCédric Le Goater * Based on qemu-kvm device-assignment: 1368c07d76SCédric Le Goater * Adapted for KVM by Qumranet. 1468c07d76SCédric Le Goater * Copyright (c) 2007, Neocleus, Alex Novik (alex@neocleus.com) 1568c07d76SCédric Le Goater * Copyright (c) 2007, Neocleus, Guy Zana (guy@neocleus.com) 1668c07d76SCédric Le Goater * Copyright (C) 2008, Qumranet, Amit Shah (amit.shah@qumranet.com) 1768c07d76SCédric Le Goater * Copyright (C) 2008, Red Hat, Amit Shah (amit.shah@redhat.com) 1868c07d76SCédric Le Goater * Copyright (C) 2008, IBM, Muli Ben-Yehuda (muli@il.ibm.com) 1968c07d76SCédric Le Goater */ 2068c07d76SCédric Le Goater 2168c07d76SCédric Le Goater #include "qemu/osdep.h" 2268c07d76SCédric Le Goater #include <sys/ioctl.h> 2368c07d76SCédric Le Goater 2468c07d76SCédric Le Goater #include "hw/vfio/vfio-common.h" 2568c07d76SCédric Le Goater #include "hw/vfio/pci.h" 2668c07d76SCédric Le Goater #include "hw/hw.h" 2768c07d76SCédric Le Goater #include "trace.h" 2868c07d76SCédric Le Goater #include "qapi/error.h" 2968c07d76SCédric Le Goater #include "qemu/error-report.h" 3068c07d76SCédric Le Goater #include "qemu/units.h" 3168c07d76SCédric Le Goater #include "monitor/monitor.h" 3268c07d76SCédric Le Goater #include "vfio-helpers.h" 3368c07d76SCédric Le Goater 34a997b506SCédric Le Goater VFIODeviceList vfio_device_list = 35a997b506SCédric Le Goater QLIST_HEAD_INITIALIZER(vfio_device_list); 36a997b506SCédric Le Goater 3768c07d76SCédric Le Goater /* 3868c07d76SCédric Le Goater * Common VFIO interrupt disable 3968c07d76SCédric Le Goater */ 4068c07d76SCédric Le Goater void vfio_disable_irqindex(VFIODevice *vbasedev, int index) 4168c07d76SCédric Le Goater { 4268c07d76SCédric Le Goater struct vfio_irq_set irq_set = { 4368c07d76SCédric Le Goater .argsz = sizeof(irq_set), 4468c07d76SCédric Le Goater .flags = VFIO_IRQ_SET_DATA_NONE | VFIO_IRQ_SET_ACTION_TRIGGER, 4568c07d76SCédric Le Goater .index = index, 4668c07d76SCédric Le Goater .start = 0, 4768c07d76SCédric Le Goater .count = 0, 4868c07d76SCédric Le Goater }; 4968c07d76SCédric Le Goater 5068c07d76SCédric Le Goater ioctl(vbasedev->fd, VFIO_DEVICE_SET_IRQS, &irq_set); 5168c07d76SCédric Le Goater } 5268c07d76SCédric Le Goater 5368c07d76SCédric Le Goater void vfio_unmask_single_irqindex(VFIODevice *vbasedev, int index) 5468c07d76SCédric Le Goater { 5568c07d76SCédric Le Goater struct vfio_irq_set irq_set = { 5668c07d76SCédric Le Goater .argsz = sizeof(irq_set), 5768c07d76SCédric Le Goater .flags = VFIO_IRQ_SET_DATA_NONE | VFIO_IRQ_SET_ACTION_UNMASK, 5868c07d76SCédric Le Goater .index = index, 5968c07d76SCédric Le Goater .start = 0, 6068c07d76SCédric Le Goater .count = 1, 6168c07d76SCédric Le Goater }; 6268c07d76SCédric Le Goater 6368c07d76SCédric Le Goater ioctl(vbasedev->fd, VFIO_DEVICE_SET_IRQS, &irq_set); 6468c07d76SCédric Le Goater } 6568c07d76SCédric Le Goater 6668c07d76SCédric Le Goater void vfio_mask_single_irqindex(VFIODevice *vbasedev, int index) 6768c07d76SCédric Le Goater { 6868c07d76SCédric Le Goater struct vfio_irq_set irq_set = { 6968c07d76SCédric Le Goater .argsz = sizeof(irq_set), 7068c07d76SCédric Le Goater .flags = VFIO_IRQ_SET_DATA_NONE | VFIO_IRQ_SET_ACTION_MASK, 7168c07d76SCédric Le Goater .index = index, 7268c07d76SCédric Le Goater .start = 0, 7368c07d76SCédric Le Goater .count = 1, 7468c07d76SCédric Le Goater }; 7568c07d76SCédric Le Goater 7668c07d76SCédric Le Goater ioctl(vbasedev->fd, VFIO_DEVICE_SET_IRQS, &irq_set); 7768c07d76SCédric Le Goater } 7868c07d76SCédric Le Goater 7968c07d76SCédric Le Goater static inline const char *action_to_str(int action) 8068c07d76SCédric Le Goater { 8168c07d76SCédric Le Goater switch (action) { 8268c07d76SCédric Le Goater case VFIO_IRQ_SET_ACTION_MASK: 8368c07d76SCédric Le Goater return "MASK"; 8468c07d76SCédric Le Goater case VFIO_IRQ_SET_ACTION_UNMASK: 8568c07d76SCédric Le Goater return "UNMASK"; 8668c07d76SCédric Le Goater case VFIO_IRQ_SET_ACTION_TRIGGER: 8768c07d76SCédric Le Goater return "TRIGGER"; 8868c07d76SCédric Le Goater default: 8968c07d76SCédric Le Goater return "UNKNOWN ACTION"; 9068c07d76SCédric Le Goater } 9168c07d76SCédric Le Goater } 9268c07d76SCédric Le Goater 9368c07d76SCédric Le Goater static const char *index_to_str(VFIODevice *vbasedev, int index) 9468c07d76SCédric Le Goater { 9568c07d76SCédric Le Goater if (vbasedev->type != VFIO_DEVICE_TYPE_PCI) { 9668c07d76SCédric Le Goater return NULL; 9768c07d76SCédric Le Goater } 9868c07d76SCédric Le Goater 9968c07d76SCédric Le Goater switch (index) { 10068c07d76SCédric Le Goater case VFIO_PCI_INTX_IRQ_INDEX: 10168c07d76SCédric Le Goater return "INTX"; 10268c07d76SCédric Le Goater case VFIO_PCI_MSI_IRQ_INDEX: 10368c07d76SCédric Le Goater return "MSI"; 10468c07d76SCédric Le Goater case VFIO_PCI_MSIX_IRQ_INDEX: 10568c07d76SCédric Le Goater return "MSIX"; 10668c07d76SCédric Le Goater case VFIO_PCI_ERR_IRQ_INDEX: 10768c07d76SCédric Le Goater return "ERR"; 10868c07d76SCédric Le Goater case VFIO_PCI_REQ_IRQ_INDEX: 10968c07d76SCédric Le Goater return "REQ"; 11068c07d76SCédric Le Goater default: 11168c07d76SCédric Le Goater return NULL; 11268c07d76SCédric Le Goater } 11368c07d76SCédric Le Goater } 11468c07d76SCédric Le Goater 11568c07d76SCédric Le Goater bool vfio_set_irq_signaling(VFIODevice *vbasedev, int index, int subindex, 11668c07d76SCédric Le Goater int action, int fd, Error **errp) 11768c07d76SCédric Le Goater { 11868c07d76SCédric Le Goater ERRP_GUARD(); 11968c07d76SCédric Le Goater g_autofree struct vfio_irq_set *irq_set = NULL; 12068c07d76SCédric Le Goater int argsz; 12168c07d76SCédric Le Goater const char *name; 12268c07d76SCédric Le Goater int32_t *pfd; 12368c07d76SCédric Le Goater 12468c07d76SCédric Le Goater argsz = sizeof(*irq_set) + sizeof(*pfd); 12568c07d76SCédric Le Goater 12668c07d76SCédric Le Goater irq_set = g_malloc0(argsz); 12768c07d76SCédric Le Goater irq_set->argsz = argsz; 12868c07d76SCédric Le Goater irq_set->flags = VFIO_IRQ_SET_DATA_EVENTFD | action; 12968c07d76SCédric Le Goater irq_set->index = index; 13068c07d76SCédric Le Goater irq_set->start = subindex; 13168c07d76SCédric Le Goater irq_set->count = 1; 13268c07d76SCédric Le Goater pfd = (int32_t *)&irq_set->data; 13368c07d76SCédric Le Goater *pfd = fd; 13468c07d76SCédric Le Goater 13568c07d76SCédric Le Goater if (!ioctl(vbasedev->fd, VFIO_DEVICE_SET_IRQS, irq_set)) { 13668c07d76SCédric Le Goater return true; 13768c07d76SCédric Le Goater } 13868c07d76SCédric Le Goater 13968c07d76SCédric Le Goater error_setg_errno(errp, errno, "VFIO_DEVICE_SET_IRQS failure"); 14068c07d76SCédric Le Goater 14168c07d76SCédric Le Goater name = index_to_str(vbasedev, index); 14268c07d76SCédric Le Goater if (name) { 14368c07d76SCédric Le Goater error_prepend(errp, "%s-%d: ", name, subindex); 14468c07d76SCédric Le Goater } else { 14568c07d76SCédric Le Goater error_prepend(errp, "index %d-%d: ", index, subindex); 14668c07d76SCédric Le Goater } 14768c07d76SCédric Le Goater error_prepend(errp, 14868c07d76SCédric Le Goater "Failed to %s %s eventfd signaling for interrupt ", 14968c07d76SCédric Le Goater fd < 0 ? "tear down" : "set up", action_to_str(action)); 15068c07d76SCédric Le Goater return false; 15168c07d76SCédric Le Goater } 15268c07d76SCédric Le Goater 15368c07d76SCédric Le Goater int vfio_get_region_info(VFIODevice *vbasedev, int index, 15468c07d76SCédric Le Goater struct vfio_region_info **info) 15568c07d76SCédric Le Goater { 15668c07d76SCédric Le Goater size_t argsz = sizeof(struct vfio_region_info); 15768c07d76SCédric Le Goater 15868c07d76SCédric Le Goater *info = g_malloc0(argsz); 15968c07d76SCédric Le Goater 16068c07d76SCédric Le Goater (*info)->index = index; 16168c07d76SCédric Le Goater retry: 16268c07d76SCédric Le Goater (*info)->argsz = argsz; 16368c07d76SCédric Le Goater 16468c07d76SCédric Le Goater if (ioctl(vbasedev->fd, VFIO_DEVICE_GET_REGION_INFO, *info)) { 16568c07d76SCédric Le Goater g_free(*info); 16668c07d76SCédric Le Goater *info = NULL; 16768c07d76SCédric Le Goater return -errno; 16868c07d76SCédric Le Goater } 16968c07d76SCédric Le Goater 17068c07d76SCédric Le Goater if ((*info)->argsz > argsz) { 17168c07d76SCédric Le Goater argsz = (*info)->argsz; 17268c07d76SCédric Le Goater *info = g_realloc(*info, argsz); 17368c07d76SCédric Le Goater 17468c07d76SCédric Le Goater goto retry; 17568c07d76SCédric Le Goater } 17668c07d76SCédric Le Goater 17768c07d76SCédric Le Goater return 0; 17868c07d76SCédric Le Goater } 17968c07d76SCédric Le Goater 18068c07d76SCédric Le Goater int vfio_get_dev_region_info(VFIODevice *vbasedev, uint32_t type, 18168c07d76SCédric Le Goater uint32_t subtype, struct vfio_region_info **info) 18268c07d76SCédric Le Goater { 18368c07d76SCédric Le Goater int i; 18468c07d76SCédric Le Goater 18568c07d76SCédric Le Goater for (i = 0; i < vbasedev->num_regions; i++) { 18668c07d76SCédric Le Goater struct vfio_info_cap_header *hdr; 18768c07d76SCédric Le Goater struct vfio_region_info_cap_type *cap_type; 18868c07d76SCédric Le Goater 18968c07d76SCédric Le Goater if (vfio_get_region_info(vbasedev, i, info)) { 19068c07d76SCédric Le Goater continue; 19168c07d76SCédric Le Goater } 19268c07d76SCédric Le Goater 19368c07d76SCédric Le Goater hdr = vfio_get_region_info_cap(*info, VFIO_REGION_INFO_CAP_TYPE); 19468c07d76SCédric Le Goater if (!hdr) { 19568c07d76SCédric Le Goater g_free(*info); 19668c07d76SCédric Le Goater continue; 19768c07d76SCédric Le Goater } 19868c07d76SCédric Le Goater 19968c07d76SCédric Le Goater cap_type = container_of(hdr, struct vfio_region_info_cap_type, header); 20068c07d76SCédric Le Goater 20168c07d76SCédric Le Goater trace_vfio_get_dev_region(vbasedev->name, i, 20268c07d76SCédric Le Goater cap_type->type, cap_type->subtype); 20368c07d76SCédric Le Goater 20468c07d76SCédric Le Goater if (cap_type->type == type && cap_type->subtype == subtype) { 20568c07d76SCédric Le Goater return 0; 20668c07d76SCédric Le Goater } 20768c07d76SCédric Le Goater 20868c07d76SCédric Le Goater g_free(*info); 20968c07d76SCédric Le Goater } 21068c07d76SCédric Le Goater 21168c07d76SCédric Le Goater *info = NULL; 21268c07d76SCédric Le Goater return -ENODEV; 21368c07d76SCédric Le Goater } 21468c07d76SCédric Le Goater 21568c07d76SCédric Le Goater bool vfio_has_region_cap(VFIODevice *vbasedev, int region, uint16_t cap_type) 21668c07d76SCédric Le Goater { 21768c07d76SCédric Le Goater g_autofree struct vfio_region_info *info = NULL; 21868c07d76SCédric Le Goater bool ret = false; 21968c07d76SCédric Le Goater 22068c07d76SCédric Le Goater if (!vfio_get_region_info(vbasedev, region, &info)) { 22168c07d76SCédric Le Goater if (vfio_get_region_info_cap(info, cap_type)) { 22268c07d76SCédric Le Goater ret = true; 22368c07d76SCédric Le Goater } 22468c07d76SCédric Le Goater } 22568c07d76SCédric Le Goater 22668c07d76SCédric Le Goater return ret; 22768c07d76SCédric Le Goater } 22868c07d76SCédric Le Goater 22968c07d76SCédric Le Goater bool vfio_device_get_name(VFIODevice *vbasedev, Error **errp) 23068c07d76SCédric Le Goater { 23168c07d76SCédric Le Goater ERRP_GUARD(); 23268c07d76SCédric Le Goater struct stat st; 23368c07d76SCédric Le Goater 23468c07d76SCédric Le Goater if (vbasedev->fd < 0) { 23568c07d76SCédric Le Goater if (stat(vbasedev->sysfsdev, &st) < 0) { 23668c07d76SCédric Le Goater error_setg_errno(errp, errno, "no such host device"); 23768c07d76SCédric Le Goater error_prepend(errp, VFIO_MSG_PREFIX, vbasedev->sysfsdev); 23868c07d76SCédric Le Goater return false; 23968c07d76SCédric Le Goater } 24068c07d76SCédric Le Goater /* User may specify a name, e.g: VFIO platform device */ 24168c07d76SCédric Le Goater if (!vbasedev->name) { 24268c07d76SCédric Le Goater vbasedev->name = g_path_get_basename(vbasedev->sysfsdev); 24368c07d76SCédric Le Goater } 24468c07d76SCédric Le Goater } else { 24568c07d76SCédric Le Goater if (!vbasedev->iommufd) { 24668c07d76SCédric Le Goater error_setg(errp, "Use FD passing only with iommufd backend"); 24768c07d76SCédric Le Goater return false; 24868c07d76SCédric Le Goater } 24968c07d76SCédric Le Goater /* 25068c07d76SCédric Le Goater * Give a name with fd so any function printing out vbasedev->name 25168c07d76SCédric Le Goater * will not break. 25268c07d76SCédric Le Goater */ 25368c07d76SCédric Le Goater if (!vbasedev->name) { 25468c07d76SCédric Le Goater vbasedev->name = g_strdup_printf("VFIO_FD%d", vbasedev->fd); 25568c07d76SCédric Le Goater } 25668c07d76SCédric Le Goater } 25768c07d76SCédric Le Goater 25868c07d76SCédric Le Goater return true; 25968c07d76SCédric Le Goater } 26068c07d76SCédric Le Goater 26168c07d76SCédric Le Goater void vfio_device_set_fd(VFIODevice *vbasedev, const char *str, Error **errp) 26268c07d76SCédric Le Goater { 26368c07d76SCédric Le Goater ERRP_GUARD(); 26468c07d76SCédric Le Goater int fd = monitor_fd_param(monitor_cur(), str, errp); 26568c07d76SCédric Le Goater 26668c07d76SCédric Le Goater if (fd < 0) { 26768c07d76SCédric Le Goater error_prepend(errp, "Could not parse remote object fd %s:", str); 26868c07d76SCédric Le Goater return; 26968c07d76SCédric Le Goater } 27068c07d76SCédric Le Goater vbasedev->fd = fd; 27168c07d76SCédric Le Goater } 27268c07d76SCédric Le Goater 27368c07d76SCédric Le Goater void vfio_device_init(VFIODevice *vbasedev, int type, VFIODeviceOps *ops, 27468c07d76SCédric Le Goater DeviceState *dev, bool ram_discard) 27568c07d76SCédric Le Goater { 27668c07d76SCédric Le Goater vbasedev->type = type; 27768c07d76SCédric Le Goater vbasedev->ops = ops; 27868c07d76SCédric Le Goater vbasedev->dev = dev; 27968c07d76SCédric Le Goater vbasedev->fd = -1; 28068c07d76SCédric Le Goater 28168c07d76SCédric Le Goater vbasedev->ram_block_discard_allowed = ram_discard; 28268c07d76SCédric Le Goater } 28368c07d76SCédric Le Goater 28468c07d76SCédric Le Goater int vfio_device_get_aw_bits(VFIODevice *vdev) 28568c07d76SCédric Le Goater { 28668c07d76SCédric Le Goater /* 28768c07d76SCédric Le Goater * iova_ranges is a sorted list. For old kernels that support 28868c07d76SCédric Le Goater * VFIO but not support query of iova ranges, iova_ranges is NULL, 28968c07d76SCédric Le Goater * in this case HOST_IOMMU_DEVICE_CAP_AW_BITS_MAX(64) is returned. 29068c07d76SCédric Le Goater */ 29168c07d76SCédric Le Goater GList *l = g_list_last(vdev->bcontainer->iova_ranges); 29268c07d76SCédric Le Goater 29368c07d76SCédric Le Goater if (l) { 29468c07d76SCédric Le Goater Range *range = l->data; 29568c07d76SCédric Le Goater return range_get_last_bit(range) + 1; 29668c07d76SCédric Le Goater } 29768c07d76SCédric Le Goater 29868c07d76SCédric Le Goater return HOST_IOMMU_DEVICE_CAP_AW_BITS_MAX; 29968c07d76SCédric Le Goater } 30068c07d76SCédric Le Goater 30168c07d76SCédric Le Goater bool vfio_device_is_mdev(VFIODevice *vbasedev) 30268c07d76SCédric Le Goater { 30368c07d76SCédric Le Goater g_autofree char *subsys = NULL; 30468c07d76SCédric Le Goater g_autofree char *tmp = NULL; 30568c07d76SCédric Le Goater 30668c07d76SCédric Le Goater if (!vbasedev->sysfsdev) { 30768c07d76SCédric Le Goater return false; 30868c07d76SCédric Le Goater } 30968c07d76SCédric Le Goater 31068c07d76SCédric Le Goater tmp = g_strdup_printf("%s/subsystem", vbasedev->sysfsdev); 31168c07d76SCédric Le Goater subsys = realpath(tmp, NULL); 31268c07d76SCédric Le Goater return subsys && (strcmp(subsys, "/sys/bus/mdev") == 0); 31368c07d76SCédric Le Goater } 31468c07d76SCédric Le Goater 31568c07d76SCédric Le Goater bool vfio_device_hiod_realize(VFIODevice *vbasedev, Error **errp) 31668c07d76SCédric Le Goater { 31768c07d76SCédric Le Goater HostIOMMUDevice *hiod = vbasedev->hiod; 31868c07d76SCédric Le Goater 31968c07d76SCédric Le Goater if (!hiod) { 32068c07d76SCédric Le Goater return true; 32168c07d76SCédric Le Goater } 32268c07d76SCédric Le Goater 32368c07d76SCédric Le Goater return HOST_IOMMU_DEVICE_GET_CLASS(hiod)->realize(hiod, vbasedev, errp); 32468c07d76SCédric Le Goater } 32568c07d76SCédric Le Goater 32668c07d76SCédric Le Goater VFIODevice *vfio_get_vfio_device(Object *obj) 32768c07d76SCédric Le Goater { 32868c07d76SCédric Le Goater if (object_dynamic_cast(obj, TYPE_VFIO_PCI)) { 32968c07d76SCédric Le Goater return &VFIO_PCI(obj)->vbasedev; 33068c07d76SCédric Le Goater } else { 33168c07d76SCédric Le Goater return NULL; 33268c07d76SCédric Le Goater } 33368c07d76SCédric Le Goater } 334*923b1141SCédric Le Goater 335*923b1141SCédric Le Goater bool vfio_attach_device(char *name, VFIODevice *vbasedev, 336*923b1141SCédric Le Goater AddressSpace *as, Error **errp) 337*923b1141SCédric Le Goater { 338*923b1141SCédric Le Goater const VFIOIOMMUClass *ops = 339*923b1141SCédric Le Goater VFIO_IOMMU_CLASS(object_class_by_name(TYPE_VFIO_IOMMU_LEGACY)); 340*923b1141SCédric Le Goater HostIOMMUDevice *hiod = NULL; 341*923b1141SCédric Le Goater 342*923b1141SCédric Le Goater if (vbasedev->iommufd) { 343*923b1141SCédric Le Goater ops = VFIO_IOMMU_CLASS(object_class_by_name(TYPE_VFIO_IOMMU_IOMMUFD)); 344*923b1141SCédric Le Goater } 345*923b1141SCédric Le Goater 346*923b1141SCédric Le Goater assert(ops); 347*923b1141SCédric Le Goater 348*923b1141SCédric Le Goater 349*923b1141SCédric Le Goater if (!vbasedev->mdev) { 350*923b1141SCédric Le Goater hiod = HOST_IOMMU_DEVICE(object_new(ops->hiod_typename)); 351*923b1141SCédric Le Goater vbasedev->hiod = hiod; 352*923b1141SCédric Le Goater } 353*923b1141SCédric Le Goater 354*923b1141SCédric Le Goater if (!ops->attach_device(name, vbasedev, as, errp)) { 355*923b1141SCédric Le Goater object_unref(hiod); 356*923b1141SCédric Le Goater vbasedev->hiod = NULL; 357*923b1141SCédric Le Goater return false; 358*923b1141SCédric Le Goater } 359*923b1141SCédric Le Goater 360*923b1141SCédric Le Goater return true; 361*923b1141SCédric Le Goater } 362*923b1141SCédric Le Goater 363*923b1141SCédric Le Goater void vfio_detach_device(VFIODevice *vbasedev) 364*923b1141SCédric Le Goater { 365*923b1141SCédric Le Goater if (!vbasedev->bcontainer) { 366*923b1141SCédric Le Goater return; 367*923b1141SCédric Le Goater } 368*923b1141SCédric Le Goater object_unref(vbasedev->hiod); 369*923b1141SCédric Le Goater VFIO_IOMMU_GET_CLASS(vbasedev->bcontainer)->detach_device(vbasedev); 370*923b1141SCédric Le Goater } 371