1*68c07d76SCédric Le Goater /* 2*68c07d76SCédric Le Goater * VFIO device 3*68c07d76SCédric Le Goater * 4*68c07d76SCédric Le Goater * Copyright Red Hat, Inc. 2012 5*68c07d76SCédric Le Goater * 6*68c07d76SCédric Le Goater * Authors: 7*68c07d76SCédric Le Goater * Alex Williamson <alex.williamson@redhat.com> 8*68c07d76SCédric Le Goater * 9*68c07d76SCédric Le Goater * This work is licensed under the terms of the GNU GPL, version 2. See 10*68c07d76SCédric Le Goater * the COPYING file in the top-level directory. 11*68c07d76SCédric Le Goater * 12*68c07d76SCédric Le Goater * Based on qemu-kvm device-assignment: 13*68c07d76SCédric Le Goater * Adapted for KVM by Qumranet. 14*68c07d76SCédric Le Goater * Copyright (c) 2007, Neocleus, Alex Novik (alex@neocleus.com) 15*68c07d76SCédric Le Goater * Copyright (c) 2007, Neocleus, Guy Zana (guy@neocleus.com) 16*68c07d76SCédric Le Goater * Copyright (C) 2008, Qumranet, Amit Shah (amit.shah@qumranet.com) 17*68c07d76SCédric Le Goater * Copyright (C) 2008, Red Hat, Amit Shah (amit.shah@redhat.com) 18*68c07d76SCédric Le Goater * Copyright (C) 2008, IBM, Muli Ben-Yehuda (muli@il.ibm.com) 19*68c07d76SCédric Le Goater */ 20*68c07d76SCédric Le Goater 21*68c07d76SCédric Le Goater #include "qemu/osdep.h" 22*68c07d76SCédric Le Goater #include <sys/ioctl.h> 23*68c07d76SCédric Le Goater 24*68c07d76SCédric Le Goater #include "hw/vfio/vfio-common.h" 25*68c07d76SCédric Le Goater #include "hw/vfio/pci.h" 26*68c07d76SCédric Le Goater #include "hw/hw.h" 27*68c07d76SCédric Le Goater #include "trace.h" 28*68c07d76SCédric Le Goater #include "qapi/error.h" 29*68c07d76SCédric Le Goater #include "qemu/error-report.h" 30*68c07d76SCédric Le Goater #include "qemu/units.h" 31*68c07d76SCédric Le Goater #include "monitor/monitor.h" 32*68c07d76SCédric Le Goater #include "vfio-helpers.h" 33*68c07d76SCédric Le Goater 34*68c07d76SCédric Le Goater /* 35*68c07d76SCédric Le Goater * Common VFIO interrupt disable 36*68c07d76SCédric Le Goater */ 37*68c07d76SCédric Le Goater void vfio_disable_irqindex(VFIODevice *vbasedev, int index) 38*68c07d76SCédric Le Goater { 39*68c07d76SCédric Le Goater struct vfio_irq_set irq_set = { 40*68c07d76SCédric Le Goater .argsz = sizeof(irq_set), 41*68c07d76SCédric Le Goater .flags = VFIO_IRQ_SET_DATA_NONE | VFIO_IRQ_SET_ACTION_TRIGGER, 42*68c07d76SCédric Le Goater .index = index, 43*68c07d76SCédric Le Goater .start = 0, 44*68c07d76SCédric Le Goater .count = 0, 45*68c07d76SCédric Le Goater }; 46*68c07d76SCédric Le Goater 47*68c07d76SCédric Le Goater ioctl(vbasedev->fd, VFIO_DEVICE_SET_IRQS, &irq_set); 48*68c07d76SCédric Le Goater } 49*68c07d76SCédric Le Goater 50*68c07d76SCédric Le Goater void vfio_unmask_single_irqindex(VFIODevice *vbasedev, int index) 51*68c07d76SCédric Le Goater { 52*68c07d76SCédric Le Goater struct vfio_irq_set irq_set = { 53*68c07d76SCédric Le Goater .argsz = sizeof(irq_set), 54*68c07d76SCédric Le Goater .flags = VFIO_IRQ_SET_DATA_NONE | VFIO_IRQ_SET_ACTION_UNMASK, 55*68c07d76SCédric Le Goater .index = index, 56*68c07d76SCédric Le Goater .start = 0, 57*68c07d76SCédric Le Goater .count = 1, 58*68c07d76SCédric Le Goater }; 59*68c07d76SCédric Le Goater 60*68c07d76SCédric Le Goater ioctl(vbasedev->fd, VFIO_DEVICE_SET_IRQS, &irq_set); 61*68c07d76SCédric Le Goater } 62*68c07d76SCédric Le Goater 63*68c07d76SCédric Le Goater void vfio_mask_single_irqindex(VFIODevice *vbasedev, int index) 64*68c07d76SCédric Le Goater { 65*68c07d76SCédric Le Goater struct vfio_irq_set irq_set = { 66*68c07d76SCédric Le Goater .argsz = sizeof(irq_set), 67*68c07d76SCédric Le Goater .flags = VFIO_IRQ_SET_DATA_NONE | VFIO_IRQ_SET_ACTION_MASK, 68*68c07d76SCédric Le Goater .index = index, 69*68c07d76SCédric Le Goater .start = 0, 70*68c07d76SCédric Le Goater .count = 1, 71*68c07d76SCédric Le Goater }; 72*68c07d76SCédric Le Goater 73*68c07d76SCédric Le Goater ioctl(vbasedev->fd, VFIO_DEVICE_SET_IRQS, &irq_set); 74*68c07d76SCédric Le Goater } 75*68c07d76SCédric Le Goater 76*68c07d76SCédric Le Goater static inline const char *action_to_str(int action) 77*68c07d76SCédric Le Goater { 78*68c07d76SCédric Le Goater switch (action) { 79*68c07d76SCédric Le Goater case VFIO_IRQ_SET_ACTION_MASK: 80*68c07d76SCédric Le Goater return "MASK"; 81*68c07d76SCédric Le Goater case VFIO_IRQ_SET_ACTION_UNMASK: 82*68c07d76SCédric Le Goater return "UNMASK"; 83*68c07d76SCédric Le Goater case VFIO_IRQ_SET_ACTION_TRIGGER: 84*68c07d76SCédric Le Goater return "TRIGGER"; 85*68c07d76SCédric Le Goater default: 86*68c07d76SCédric Le Goater return "UNKNOWN ACTION"; 87*68c07d76SCédric Le Goater } 88*68c07d76SCédric Le Goater } 89*68c07d76SCédric Le Goater 90*68c07d76SCédric Le Goater static const char *index_to_str(VFIODevice *vbasedev, int index) 91*68c07d76SCédric Le Goater { 92*68c07d76SCédric Le Goater if (vbasedev->type != VFIO_DEVICE_TYPE_PCI) { 93*68c07d76SCédric Le Goater return NULL; 94*68c07d76SCédric Le Goater } 95*68c07d76SCédric Le Goater 96*68c07d76SCédric Le Goater switch (index) { 97*68c07d76SCédric Le Goater case VFIO_PCI_INTX_IRQ_INDEX: 98*68c07d76SCédric Le Goater return "INTX"; 99*68c07d76SCédric Le Goater case VFIO_PCI_MSI_IRQ_INDEX: 100*68c07d76SCédric Le Goater return "MSI"; 101*68c07d76SCédric Le Goater case VFIO_PCI_MSIX_IRQ_INDEX: 102*68c07d76SCédric Le Goater return "MSIX"; 103*68c07d76SCédric Le Goater case VFIO_PCI_ERR_IRQ_INDEX: 104*68c07d76SCédric Le Goater return "ERR"; 105*68c07d76SCédric Le Goater case VFIO_PCI_REQ_IRQ_INDEX: 106*68c07d76SCédric Le Goater return "REQ"; 107*68c07d76SCédric Le Goater default: 108*68c07d76SCédric Le Goater return NULL; 109*68c07d76SCédric Le Goater } 110*68c07d76SCédric Le Goater } 111*68c07d76SCédric Le Goater 112*68c07d76SCédric Le Goater bool vfio_set_irq_signaling(VFIODevice *vbasedev, int index, int subindex, 113*68c07d76SCédric Le Goater int action, int fd, Error **errp) 114*68c07d76SCédric Le Goater { 115*68c07d76SCédric Le Goater ERRP_GUARD(); 116*68c07d76SCédric Le Goater g_autofree struct vfio_irq_set *irq_set = NULL; 117*68c07d76SCédric Le Goater int argsz; 118*68c07d76SCédric Le Goater const char *name; 119*68c07d76SCédric Le Goater int32_t *pfd; 120*68c07d76SCédric Le Goater 121*68c07d76SCédric Le Goater argsz = sizeof(*irq_set) + sizeof(*pfd); 122*68c07d76SCédric Le Goater 123*68c07d76SCédric Le Goater irq_set = g_malloc0(argsz); 124*68c07d76SCédric Le Goater irq_set->argsz = argsz; 125*68c07d76SCédric Le Goater irq_set->flags = VFIO_IRQ_SET_DATA_EVENTFD | action; 126*68c07d76SCédric Le Goater irq_set->index = index; 127*68c07d76SCédric Le Goater irq_set->start = subindex; 128*68c07d76SCédric Le Goater irq_set->count = 1; 129*68c07d76SCédric Le Goater pfd = (int32_t *)&irq_set->data; 130*68c07d76SCédric Le Goater *pfd = fd; 131*68c07d76SCédric Le Goater 132*68c07d76SCédric Le Goater if (!ioctl(vbasedev->fd, VFIO_DEVICE_SET_IRQS, irq_set)) { 133*68c07d76SCédric Le Goater return true; 134*68c07d76SCédric Le Goater } 135*68c07d76SCédric Le Goater 136*68c07d76SCédric Le Goater error_setg_errno(errp, errno, "VFIO_DEVICE_SET_IRQS failure"); 137*68c07d76SCédric Le Goater 138*68c07d76SCédric Le Goater name = index_to_str(vbasedev, index); 139*68c07d76SCédric Le Goater if (name) { 140*68c07d76SCédric Le Goater error_prepend(errp, "%s-%d: ", name, subindex); 141*68c07d76SCédric Le Goater } else { 142*68c07d76SCédric Le Goater error_prepend(errp, "index %d-%d: ", index, subindex); 143*68c07d76SCédric Le Goater } 144*68c07d76SCédric Le Goater error_prepend(errp, 145*68c07d76SCédric Le Goater "Failed to %s %s eventfd signaling for interrupt ", 146*68c07d76SCédric Le Goater fd < 0 ? "tear down" : "set up", action_to_str(action)); 147*68c07d76SCédric Le Goater return false; 148*68c07d76SCédric Le Goater } 149*68c07d76SCédric Le Goater 150*68c07d76SCédric Le Goater int vfio_get_region_info(VFIODevice *vbasedev, int index, 151*68c07d76SCédric Le Goater struct vfio_region_info **info) 152*68c07d76SCédric Le Goater { 153*68c07d76SCédric Le Goater size_t argsz = sizeof(struct vfio_region_info); 154*68c07d76SCédric Le Goater 155*68c07d76SCédric Le Goater *info = g_malloc0(argsz); 156*68c07d76SCédric Le Goater 157*68c07d76SCédric Le Goater (*info)->index = index; 158*68c07d76SCédric Le Goater retry: 159*68c07d76SCédric Le Goater (*info)->argsz = argsz; 160*68c07d76SCédric Le Goater 161*68c07d76SCédric Le Goater if (ioctl(vbasedev->fd, VFIO_DEVICE_GET_REGION_INFO, *info)) { 162*68c07d76SCédric Le Goater g_free(*info); 163*68c07d76SCédric Le Goater *info = NULL; 164*68c07d76SCédric Le Goater return -errno; 165*68c07d76SCédric Le Goater } 166*68c07d76SCédric Le Goater 167*68c07d76SCédric Le Goater if ((*info)->argsz > argsz) { 168*68c07d76SCédric Le Goater argsz = (*info)->argsz; 169*68c07d76SCédric Le Goater *info = g_realloc(*info, argsz); 170*68c07d76SCédric Le Goater 171*68c07d76SCédric Le Goater goto retry; 172*68c07d76SCédric Le Goater } 173*68c07d76SCédric Le Goater 174*68c07d76SCédric Le Goater return 0; 175*68c07d76SCédric Le Goater } 176*68c07d76SCédric Le Goater 177*68c07d76SCédric Le Goater int vfio_get_dev_region_info(VFIODevice *vbasedev, uint32_t type, 178*68c07d76SCédric Le Goater uint32_t subtype, struct vfio_region_info **info) 179*68c07d76SCédric Le Goater { 180*68c07d76SCédric Le Goater int i; 181*68c07d76SCédric Le Goater 182*68c07d76SCédric Le Goater for (i = 0; i < vbasedev->num_regions; i++) { 183*68c07d76SCédric Le Goater struct vfio_info_cap_header *hdr; 184*68c07d76SCédric Le Goater struct vfio_region_info_cap_type *cap_type; 185*68c07d76SCédric Le Goater 186*68c07d76SCédric Le Goater if (vfio_get_region_info(vbasedev, i, info)) { 187*68c07d76SCédric Le Goater continue; 188*68c07d76SCédric Le Goater } 189*68c07d76SCédric Le Goater 190*68c07d76SCédric Le Goater hdr = vfio_get_region_info_cap(*info, VFIO_REGION_INFO_CAP_TYPE); 191*68c07d76SCédric Le Goater if (!hdr) { 192*68c07d76SCédric Le Goater g_free(*info); 193*68c07d76SCédric Le Goater continue; 194*68c07d76SCédric Le Goater } 195*68c07d76SCédric Le Goater 196*68c07d76SCédric Le Goater cap_type = container_of(hdr, struct vfio_region_info_cap_type, header); 197*68c07d76SCédric Le Goater 198*68c07d76SCédric Le Goater trace_vfio_get_dev_region(vbasedev->name, i, 199*68c07d76SCédric Le Goater cap_type->type, cap_type->subtype); 200*68c07d76SCédric Le Goater 201*68c07d76SCédric Le Goater if (cap_type->type == type && cap_type->subtype == subtype) { 202*68c07d76SCédric Le Goater return 0; 203*68c07d76SCédric Le Goater } 204*68c07d76SCédric Le Goater 205*68c07d76SCédric Le Goater g_free(*info); 206*68c07d76SCédric Le Goater } 207*68c07d76SCédric Le Goater 208*68c07d76SCédric Le Goater *info = NULL; 209*68c07d76SCédric Le Goater return -ENODEV; 210*68c07d76SCédric Le Goater } 211*68c07d76SCédric Le Goater 212*68c07d76SCédric Le Goater bool vfio_has_region_cap(VFIODevice *vbasedev, int region, uint16_t cap_type) 213*68c07d76SCédric Le Goater { 214*68c07d76SCédric Le Goater g_autofree struct vfio_region_info *info = NULL; 215*68c07d76SCédric Le Goater bool ret = false; 216*68c07d76SCédric Le Goater 217*68c07d76SCédric Le Goater if (!vfio_get_region_info(vbasedev, region, &info)) { 218*68c07d76SCédric Le Goater if (vfio_get_region_info_cap(info, cap_type)) { 219*68c07d76SCédric Le Goater ret = true; 220*68c07d76SCédric Le Goater } 221*68c07d76SCédric Le Goater } 222*68c07d76SCédric Le Goater 223*68c07d76SCédric Le Goater return ret; 224*68c07d76SCédric Le Goater } 225*68c07d76SCédric Le Goater 226*68c07d76SCédric Le Goater bool vfio_device_get_name(VFIODevice *vbasedev, Error **errp) 227*68c07d76SCédric Le Goater { 228*68c07d76SCédric Le Goater ERRP_GUARD(); 229*68c07d76SCédric Le Goater struct stat st; 230*68c07d76SCédric Le Goater 231*68c07d76SCédric Le Goater if (vbasedev->fd < 0) { 232*68c07d76SCédric Le Goater if (stat(vbasedev->sysfsdev, &st) < 0) { 233*68c07d76SCédric Le Goater error_setg_errno(errp, errno, "no such host device"); 234*68c07d76SCédric Le Goater error_prepend(errp, VFIO_MSG_PREFIX, vbasedev->sysfsdev); 235*68c07d76SCédric Le Goater return false; 236*68c07d76SCédric Le Goater } 237*68c07d76SCédric Le Goater /* User may specify a name, e.g: VFIO platform device */ 238*68c07d76SCédric Le Goater if (!vbasedev->name) { 239*68c07d76SCédric Le Goater vbasedev->name = g_path_get_basename(vbasedev->sysfsdev); 240*68c07d76SCédric Le Goater } 241*68c07d76SCédric Le Goater } else { 242*68c07d76SCédric Le Goater if (!vbasedev->iommufd) { 243*68c07d76SCédric Le Goater error_setg(errp, "Use FD passing only with iommufd backend"); 244*68c07d76SCédric Le Goater return false; 245*68c07d76SCédric Le Goater } 246*68c07d76SCédric Le Goater /* 247*68c07d76SCédric Le Goater * Give a name with fd so any function printing out vbasedev->name 248*68c07d76SCédric Le Goater * will not break. 249*68c07d76SCédric Le Goater */ 250*68c07d76SCédric Le Goater if (!vbasedev->name) { 251*68c07d76SCédric Le Goater vbasedev->name = g_strdup_printf("VFIO_FD%d", vbasedev->fd); 252*68c07d76SCédric Le Goater } 253*68c07d76SCédric Le Goater } 254*68c07d76SCédric Le Goater 255*68c07d76SCédric Le Goater return true; 256*68c07d76SCédric Le Goater } 257*68c07d76SCédric Le Goater 258*68c07d76SCédric Le Goater void vfio_device_set_fd(VFIODevice *vbasedev, const char *str, Error **errp) 259*68c07d76SCédric Le Goater { 260*68c07d76SCédric Le Goater ERRP_GUARD(); 261*68c07d76SCédric Le Goater int fd = monitor_fd_param(monitor_cur(), str, errp); 262*68c07d76SCédric Le Goater 263*68c07d76SCédric Le Goater if (fd < 0) { 264*68c07d76SCédric Le Goater error_prepend(errp, "Could not parse remote object fd %s:", str); 265*68c07d76SCédric Le Goater return; 266*68c07d76SCédric Le Goater } 267*68c07d76SCédric Le Goater vbasedev->fd = fd; 268*68c07d76SCédric Le Goater } 269*68c07d76SCédric Le Goater 270*68c07d76SCédric Le Goater void vfio_device_init(VFIODevice *vbasedev, int type, VFIODeviceOps *ops, 271*68c07d76SCédric Le Goater DeviceState *dev, bool ram_discard) 272*68c07d76SCédric Le Goater { 273*68c07d76SCédric Le Goater vbasedev->type = type; 274*68c07d76SCédric Le Goater vbasedev->ops = ops; 275*68c07d76SCédric Le Goater vbasedev->dev = dev; 276*68c07d76SCédric Le Goater vbasedev->fd = -1; 277*68c07d76SCédric Le Goater 278*68c07d76SCédric Le Goater vbasedev->ram_block_discard_allowed = ram_discard; 279*68c07d76SCédric Le Goater } 280*68c07d76SCédric Le Goater 281*68c07d76SCédric Le Goater int vfio_device_get_aw_bits(VFIODevice *vdev) 282*68c07d76SCédric Le Goater { 283*68c07d76SCédric Le Goater /* 284*68c07d76SCédric Le Goater * iova_ranges is a sorted list. For old kernels that support 285*68c07d76SCédric Le Goater * VFIO but not support query of iova ranges, iova_ranges is NULL, 286*68c07d76SCédric Le Goater * in this case HOST_IOMMU_DEVICE_CAP_AW_BITS_MAX(64) is returned. 287*68c07d76SCédric Le Goater */ 288*68c07d76SCédric Le Goater GList *l = g_list_last(vdev->bcontainer->iova_ranges); 289*68c07d76SCédric Le Goater 290*68c07d76SCédric Le Goater if (l) { 291*68c07d76SCédric Le Goater Range *range = l->data; 292*68c07d76SCédric Le Goater return range_get_last_bit(range) + 1; 293*68c07d76SCédric Le Goater } 294*68c07d76SCédric Le Goater 295*68c07d76SCédric Le Goater return HOST_IOMMU_DEVICE_CAP_AW_BITS_MAX; 296*68c07d76SCédric Le Goater } 297*68c07d76SCédric Le Goater 298*68c07d76SCédric Le Goater bool vfio_device_is_mdev(VFIODevice *vbasedev) 299*68c07d76SCédric Le Goater { 300*68c07d76SCédric Le Goater g_autofree char *subsys = NULL; 301*68c07d76SCédric Le Goater g_autofree char *tmp = NULL; 302*68c07d76SCédric Le Goater 303*68c07d76SCédric Le Goater if (!vbasedev->sysfsdev) { 304*68c07d76SCédric Le Goater return false; 305*68c07d76SCédric Le Goater } 306*68c07d76SCédric Le Goater 307*68c07d76SCédric Le Goater tmp = g_strdup_printf("%s/subsystem", vbasedev->sysfsdev); 308*68c07d76SCédric Le Goater subsys = realpath(tmp, NULL); 309*68c07d76SCédric Le Goater return subsys && (strcmp(subsys, "/sys/bus/mdev") == 0); 310*68c07d76SCédric Le Goater } 311*68c07d76SCédric Le Goater 312*68c07d76SCédric Le Goater bool vfio_device_hiod_realize(VFIODevice *vbasedev, Error **errp) 313*68c07d76SCédric Le Goater { 314*68c07d76SCédric Le Goater HostIOMMUDevice *hiod = vbasedev->hiod; 315*68c07d76SCédric Le Goater 316*68c07d76SCédric Le Goater if (!hiod) { 317*68c07d76SCédric Le Goater return true; 318*68c07d76SCédric Le Goater } 319*68c07d76SCédric Le Goater 320*68c07d76SCédric Le Goater return HOST_IOMMU_DEVICE_GET_CLASS(hiod)->realize(hiod, vbasedev, errp); 321*68c07d76SCédric Le Goater } 322*68c07d76SCédric Le Goater 323*68c07d76SCédric Le Goater VFIODevice *vfio_get_vfio_device(Object *obj) 324*68c07d76SCédric Le Goater { 325*68c07d76SCédric Le Goater if (object_dynamic_cast(obj, TYPE_VFIO_PCI)) { 326*68c07d76SCédric Le Goater return &VFIO_PCI(obj)->vbasedev; 327*68c07d76SCédric Le Goater } else { 328*68c07d76SCédric Le Goater return NULL; 329*68c07d76SCédric Le Goater } 330*68c07d76SCédric Le Goater } 331