1 /* 2 * low level and IOMMU backend agnostic helpers used by VFIO devices, 3 * related to regions, interrupts, capabilities 4 * 5 * Copyright Red Hat, Inc. 2012 6 * 7 * Authors: 8 * Alex Williamson <alex.williamson@redhat.com> 9 * 10 * This work is licensed under the terms of the GNU GPL, version 2. See 11 * the COPYING file in the top-level directory. 12 * 13 * Based on qemu-kvm device-assignment: 14 * Adapted for KVM by Qumranet. 15 * Copyright (c) 2007, Neocleus, Alex Novik (alex@neocleus.com) 16 * Copyright (c) 2007, Neocleus, Guy Zana (guy@neocleus.com) 17 * Copyright (C) 2008, Qumranet, Amit Shah (amit.shah@qumranet.com) 18 * Copyright (C) 2008, Red Hat, Amit Shah (amit.shah@redhat.com) 19 * Copyright (C) 2008, IBM, Muli Ben-Yehuda (muli@il.ibm.com) 20 */ 21 22 #include "qemu/osdep.h" 23 #include <sys/ioctl.h> 24 25 #include "system/kvm.h" 26 #include "hw/vfio/vfio-device.h" 27 #include "hw/hw.h" 28 #include "qapi/error.h" 29 #include "vfio-helpers.h" 30 31 int vfio_bitmap_alloc(VFIOBitmap *vbmap, hwaddr size) 32 { 33 vbmap->pages = REAL_HOST_PAGE_ALIGN(size) / qemu_real_host_page_size(); 34 vbmap->size = ROUND_UP(vbmap->pages, sizeof(__u64) * BITS_PER_BYTE) / 35 BITS_PER_BYTE; 36 vbmap->bitmap = g_try_malloc0(vbmap->size); 37 if (!vbmap->bitmap) { 38 return -ENOMEM; 39 } 40 41 return 0; 42 } 43 44 struct vfio_info_cap_header * 45 vfio_get_cap(void *ptr, uint32_t cap_offset, uint16_t id) 46 { 47 struct vfio_info_cap_header *hdr; 48 49 for (hdr = ptr + cap_offset; hdr != ptr; hdr = ptr + hdr->next) { 50 if (hdr->id == id) { 51 return hdr; 52 } 53 } 54 55 return NULL; 56 } 57 58 struct vfio_info_cap_header * 59 vfio_get_region_info_cap(struct vfio_region_info *info, uint16_t id) 60 { 61 if (!(info->flags & VFIO_REGION_INFO_FLAG_CAPS)) { 62 return NULL; 63 } 64 65 return vfio_get_cap((void *)info, info->cap_offset, id); 66 } 67 68 struct vfio_info_cap_header * 69 vfio_get_device_info_cap(struct vfio_device_info *info, uint16_t id) 70 { 71 if (!(info->flags & VFIO_DEVICE_FLAGS_CAPS)) { 72 return NULL; 73 } 74 75 return vfio_get_cap((void *)info, info->cap_offset, id); 76 } 77 78 struct vfio_info_cap_header * 79 vfio_get_iommu_type1_info_cap(struct vfio_iommu_type1_info *info, uint16_t id) 80 { 81 if (!(info->flags & VFIO_IOMMU_INFO_CAPS)) { 82 return NULL; 83 } 84 85 return vfio_get_cap((void *)info, info->cap_offset, id); 86 } 87 88 bool vfio_get_info_dma_avail(struct vfio_iommu_type1_info *info, 89 unsigned int *avail) 90 { 91 struct vfio_info_cap_header *hdr; 92 struct vfio_iommu_type1_info_dma_avail *cap; 93 94 /* If the capability cannot be found, assume no DMA limiting */ 95 hdr = vfio_get_iommu_type1_info_cap(info, 96 VFIO_IOMMU_TYPE1_INFO_DMA_AVAIL); 97 if (!hdr) { 98 return false; 99 } 100 101 if (avail != NULL) { 102 cap = (void *) hdr; 103 *avail = cap->avail; 104 } 105 106 return true; 107 } 108 109 #ifdef CONFIG_KVM 110 /* 111 * We have a single VFIO pseudo device per KVM VM. Once created it lives 112 * for the life of the VM. Closing the file descriptor only drops our 113 * reference to it and the device's reference to kvm. Therefore once 114 * initialized, this file descriptor is only released on QEMU exit and 115 * we'll re-use it should another vfio device be attached before then. 116 */ 117 int vfio_kvm_device_fd = -1; 118 #endif 119 120 int vfio_kvm_device_add_fd(int fd, Error **errp) 121 { 122 #ifdef CONFIG_KVM 123 struct kvm_device_attr attr = { 124 .group = KVM_DEV_VFIO_FILE, 125 .attr = KVM_DEV_VFIO_FILE_ADD, 126 .addr = (uint64_t)(unsigned long)&fd, 127 }; 128 129 if (!kvm_enabled()) { 130 return 0; 131 } 132 133 if (vfio_kvm_device_fd < 0) { 134 struct kvm_create_device cd = { 135 .type = KVM_DEV_TYPE_VFIO, 136 }; 137 138 if (kvm_vm_ioctl(kvm_state, KVM_CREATE_DEVICE, &cd)) { 139 error_setg_errno(errp, errno, "Failed to create KVM VFIO device"); 140 return -errno; 141 } 142 143 vfio_kvm_device_fd = cd.fd; 144 } 145 146 if (ioctl(vfio_kvm_device_fd, KVM_SET_DEVICE_ATTR, &attr)) { 147 error_setg_errno(errp, errno, "Failed to add fd %d to KVM VFIO device", 148 fd); 149 return -errno; 150 } 151 #endif 152 return 0; 153 } 154 155 int vfio_kvm_device_del_fd(int fd, Error **errp) 156 { 157 #ifdef CONFIG_KVM 158 struct kvm_device_attr attr = { 159 .group = KVM_DEV_VFIO_FILE, 160 .attr = KVM_DEV_VFIO_FILE_DEL, 161 .addr = (uint64_t)(unsigned long)&fd, 162 }; 163 164 if (vfio_kvm_device_fd < 0) { 165 error_setg(errp, "KVM VFIO device isn't created yet"); 166 return -EINVAL; 167 } 168 169 if (ioctl(vfio_kvm_device_fd, KVM_SET_DEVICE_ATTR, &attr)) { 170 error_setg_errno(errp, errno, 171 "Failed to remove fd %d from KVM VFIO device", fd); 172 return -errno; 173 } 174 #endif 175 return 0; 176 } 177 178 struct vfio_device_info *vfio_get_device_info(int fd) 179 { 180 struct vfio_device_info *info; 181 uint32_t argsz = sizeof(*info); 182 183 info = g_malloc0(argsz); 184 185 retry: 186 info->argsz = argsz; 187 188 if (ioctl(fd, VFIO_DEVICE_GET_INFO, info)) { 189 g_free(info); 190 return NULL; 191 } 192 193 if (info->argsz > argsz) { 194 argsz = info->argsz; 195 info = g_realloc(info, argsz); 196 goto retry; 197 } 198 199 return info; 200 } 201