11e09f52fSYi Liu /* 21e09f52fSYi Liu * low level and IOMMU backend agnostic helpers used by VFIO devices, 31e09f52fSYi Liu * related to regions, interrupts, capabilities 41e09f52fSYi Liu * 51e09f52fSYi Liu * Copyright Red Hat, Inc. 2012 61e09f52fSYi Liu * 71e09f52fSYi Liu * Authors: 81e09f52fSYi Liu * Alex Williamson <alex.williamson@redhat.com> 91e09f52fSYi Liu * 101e09f52fSYi Liu * This work is licensed under the terms of the GNU GPL, version 2. See 111e09f52fSYi Liu * the COPYING file in the top-level directory. 121e09f52fSYi Liu * 131e09f52fSYi Liu * Based on qemu-kvm device-assignment: 141e09f52fSYi Liu * Adapted for KVM by Qumranet. 151e09f52fSYi Liu * Copyright (c) 2007, Neocleus, Alex Novik (alex@neocleus.com) 161e09f52fSYi Liu * Copyright (c) 2007, Neocleus, Guy Zana (guy@neocleus.com) 171e09f52fSYi Liu * Copyright (C) 2008, Qumranet, Amit Shah (amit.shah@qumranet.com) 181e09f52fSYi Liu * Copyright (C) 2008, Red Hat, Amit Shah (amit.shah@redhat.com) 191e09f52fSYi Liu * Copyright (C) 2008, IBM, Muli Ben-Yehuda (muli@il.ibm.com) 201e09f52fSYi Liu */ 211e09f52fSYi Liu 221e09f52fSYi Liu #include "qemu/osdep.h" 231e09f52fSYi Liu #include <sys/ioctl.h> 241e09f52fSYi Liu 2554525613SCédric Le Goater #include "system/kvm.h" 261e09f52fSYi Liu #include "hw/vfio/vfio-common.h" 271e09f52fSYi Liu #include "hw/hw.h" 281e09f52fSYi Liu #include "qapi/error.h" 29ac28680dSCédric Le Goater #include "vfio-helpers.h" 301e09f52fSYi Liu 311e09f52fSYi Liu int vfio_bitmap_alloc(VFIOBitmap *vbmap, hwaddr size) 321e09f52fSYi Liu { 331e09f52fSYi Liu vbmap->pages = REAL_HOST_PAGE_ALIGN(size) / qemu_real_host_page_size(); 341e09f52fSYi Liu vbmap->size = ROUND_UP(vbmap->pages, sizeof(__u64) * BITS_PER_BYTE) / 351e09f52fSYi Liu BITS_PER_BYTE; 361e09f52fSYi Liu vbmap->bitmap = g_try_malloc0(vbmap->size); 371e09f52fSYi Liu if (!vbmap->bitmap) { 381e09f52fSYi Liu return -ENOMEM; 391e09f52fSYi Liu } 401e09f52fSYi Liu 411e09f52fSYi Liu return 0; 421e09f52fSYi Liu } 431e09f52fSYi Liu 441e09f52fSYi Liu struct vfio_info_cap_header * 451e09f52fSYi Liu vfio_get_cap(void *ptr, uint32_t cap_offset, uint16_t id) 461e09f52fSYi Liu { 471e09f52fSYi Liu struct vfio_info_cap_header *hdr; 481e09f52fSYi Liu 491e09f52fSYi Liu for (hdr = ptr + cap_offset; hdr != ptr; hdr = ptr + hdr->next) { 501e09f52fSYi Liu if (hdr->id == id) { 511e09f52fSYi Liu return hdr; 521e09f52fSYi Liu } 531e09f52fSYi Liu } 541e09f52fSYi Liu 551e09f52fSYi Liu return NULL; 561e09f52fSYi Liu } 571e09f52fSYi Liu 581e09f52fSYi Liu struct vfio_info_cap_header * 591e09f52fSYi Liu vfio_get_region_info_cap(struct vfio_region_info *info, uint16_t id) 601e09f52fSYi Liu { 611e09f52fSYi Liu if (!(info->flags & VFIO_REGION_INFO_FLAG_CAPS)) { 621e09f52fSYi Liu return NULL; 631e09f52fSYi Liu } 641e09f52fSYi Liu 651e09f52fSYi Liu return vfio_get_cap((void *)info, info->cap_offset, id); 661e09f52fSYi Liu } 671e09f52fSYi Liu 681e09f52fSYi Liu struct vfio_info_cap_header * 691e09f52fSYi Liu vfio_get_device_info_cap(struct vfio_device_info *info, uint16_t id) 701e09f52fSYi Liu { 711e09f52fSYi Liu if (!(info->flags & VFIO_DEVICE_FLAGS_CAPS)) { 721e09f52fSYi Liu return NULL; 731e09f52fSYi Liu } 741e09f52fSYi Liu 751e09f52fSYi Liu return vfio_get_cap((void *)info, info->cap_offset, id); 761e09f52fSYi Liu } 771e09f52fSYi Liu 78f6d7f5d0SCédric Le Goater struct vfio_info_cap_header * 79f6d7f5d0SCédric Le Goater vfio_get_iommu_type1_info_cap(struct vfio_iommu_type1_info *info, uint16_t id) 80f6d7f5d0SCédric Le Goater { 81f6d7f5d0SCédric Le Goater if (!(info->flags & VFIO_IOMMU_INFO_CAPS)) { 82f6d7f5d0SCédric Le Goater return NULL; 83f6d7f5d0SCédric Le Goater } 84f6d7f5d0SCédric Le Goater 85f6d7f5d0SCédric Le Goater return vfio_get_cap((void *)info, info->cap_offset, id); 86f6d7f5d0SCédric Le Goater } 87f6d7f5d0SCédric Le Goater 88f6d7f5d0SCédric Le Goater bool vfio_get_info_dma_avail(struct vfio_iommu_type1_info *info, 89f6d7f5d0SCédric Le Goater unsigned int *avail) 90f6d7f5d0SCédric Le Goater { 91f6d7f5d0SCédric Le Goater struct vfio_info_cap_header *hdr; 92f6d7f5d0SCédric Le Goater struct vfio_iommu_type1_info_dma_avail *cap; 93f6d7f5d0SCédric Le Goater 94f6d7f5d0SCédric Le Goater /* If the capability cannot be found, assume no DMA limiting */ 95f6d7f5d0SCédric Le Goater hdr = vfio_get_iommu_type1_info_cap(info, 96f6d7f5d0SCédric Le Goater VFIO_IOMMU_TYPE1_INFO_DMA_AVAIL); 97f6d7f5d0SCédric Le Goater if (!hdr) { 98f6d7f5d0SCédric Le Goater return false; 99f6d7f5d0SCédric Le Goater } 100f6d7f5d0SCédric Le Goater 101f6d7f5d0SCédric Le Goater if (avail != NULL) { 102f6d7f5d0SCédric Le Goater cap = (void *) hdr; 103f6d7f5d0SCédric Le Goater *avail = cap->avail; 104f6d7f5d0SCédric Le Goater } 105f6d7f5d0SCédric Le Goater 106f6d7f5d0SCédric Le Goater return true; 107f6d7f5d0SCédric Le Goater } 108f6d7f5d0SCédric Le Goater 109*c3fbdba1SCédric Le Goater #ifdef CONFIG_KVM 110*c3fbdba1SCédric Le Goater /* 111*c3fbdba1SCédric Le Goater * We have a single VFIO pseudo device per KVM VM. Once created it lives 112*c3fbdba1SCédric Le Goater * for the life of the VM. Closing the file descriptor only drops our 113*c3fbdba1SCédric Le Goater * reference to it and the device's reference to kvm. Therefore once 114*c3fbdba1SCédric Le Goater * initialized, this file descriptor is only released on QEMU exit and 115*c3fbdba1SCédric Le Goater * we'll re-use it should another vfio device be attached before then. 116*c3fbdba1SCédric Le Goater */ 117*c3fbdba1SCédric Le Goater int vfio_kvm_device_fd = -1; 118*c3fbdba1SCédric Le Goater #endif 119*c3fbdba1SCédric Le Goater 12054525613SCédric Le Goater int vfio_kvm_device_add_fd(int fd, Error **errp) 12154525613SCédric Le Goater { 12254525613SCédric Le Goater #ifdef CONFIG_KVM 12354525613SCédric Le Goater struct kvm_device_attr attr = { 12454525613SCédric Le Goater .group = KVM_DEV_VFIO_FILE, 12554525613SCédric Le Goater .attr = KVM_DEV_VFIO_FILE_ADD, 12654525613SCédric Le Goater .addr = (uint64_t)(unsigned long)&fd, 12754525613SCédric Le Goater }; 12854525613SCédric Le Goater 12954525613SCédric Le Goater if (!kvm_enabled()) { 13054525613SCédric Le Goater return 0; 13154525613SCédric Le Goater } 13254525613SCédric Le Goater 13354525613SCédric Le Goater if (vfio_kvm_device_fd < 0) { 13454525613SCédric Le Goater struct kvm_create_device cd = { 13554525613SCédric Le Goater .type = KVM_DEV_TYPE_VFIO, 13654525613SCédric Le Goater }; 13754525613SCédric Le Goater 13854525613SCédric Le Goater if (kvm_vm_ioctl(kvm_state, KVM_CREATE_DEVICE, &cd)) { 13954525613SCédric Le Goater error_setg_errno(errp, errno, "Failed to create KVM VFIO device"); 14054525613SCédric Le Goater return -errno; 14154525613SCédric Le Goater } 14254525613SCédric Le Goater 14354525613SCédric Le Goater vfio_kvm_device_fd = cd.fd; 14454525613SCédric Le Goater } 14554525613SCédric Le Goater 14654525613SCédric Le Goater if (ioctl(vfio_kvm_device_fd, KVM_SET_DEVICE_ATTR, &attr)) { 14754525613SCédric Le Goater error_setg_errno(errp, errno, "Failed to add fd %d to KVM VFIO device", 14854525613SCédric Le Goater fd); 14954525613SCédric Le Goater return -errno; 15054525613SCédric Le Goater } 15154525613SCédric Le Goater #endif 15254525613SCédric Le Goater return 0; 15354525613SCédric Le Goater } 15454525613SCédric Le Goater 15554525613SCédric Le Goater int vfio_kvm_device_del_fd(int fd, Error **errp) 15654525613SCédric Le Goater { 15754525613SCédric Le Goater #ifdef CONFIG_KVM 15854525613SCédric Le Goater struct kvm_device_attr attr = { 15954525613SCédric Le Goater .group = KVM_DEV_VFIO_FILE, 16054525613SCédric Le Goater .attr = KVM_DEV_VFIO_FILE_DEL, 16154525613SCédric Le Goater .addr = (uint64_t)(unsigned long)&fd, 16254525613SCédric Le Goater }; 16354525613SCédric Le Goater 16454525613SCédric Le Goater if (vfio_kvm_device_fd < 0) { 16554525613SCédric Le Goater error_setg(errp, "KVM VFIO device isn't created yet"); 16654525613SCédric Le Goater return -EINVAL; 16754525613SCédric Le Goater } 16854525613SCédric Le Goater 16954525613SCédric Le Goater if (ioctl(vfio_kvm_device_fd, KVM_SET_DEVICE_ATTR, &attr)) { 17054525613SCédric Le Goater error_setg_errno(errp, errno, 17154525613SCédric Le Goater "Failed to remove fd %d from KVM VFIO device", fd); 17254525613SCédric Le Goater return -errno; 17354525613SCédric Le Goater } 17454525613SCédric Le Goater #endif 17554525613SCédric Le Goater return 0; 17654525613SCédric Le Goater } 17754525613SCédric Le Goater 178005b8d10SCédric Le Goater struct vfio_device_info *vfio_get_device_info(int fd) 179005b8d10SCédric Le Goater { 180005b8d10SCédric Le Goater struct vfio_device_info *info; 181005b8d10SCédric Le Goater uint32_t argsz = sizeof(*info); 182005b8d10SCédric Le Goater 183005b8d10SCédric Le Goater info = g_malloc0(argsz); 184005b8d10SCédric Le Goater 185005b8d10SCédric Le Goater retry: 186005b8d10SCédric Le Goater info->argsz = argsz; 187005b8d10SCédric Le Goater 188005b8d10SCédric Le Goater if (ioctl(fd, VFIO_DEVICE_GET_INFO, info)) { 189005b8d10SCédric Le Goater g_free(info); 190005b8d10SCédric Le Goater return NULL; 191005b8d10SCédric Le Goater } 192005b8d10SCédric Le Goater 193005b8d10SCédric Le Goater if (info->argsz > argsz) { 194005b8d10SCédric Le Goater argsz = info->argsz; 195005b8d10SCédric Le Goater info = g_realloc(info, argsz); 196005b8d10SCédric Le Goater goto retry; 197005b8d10SCédric Le Goater } 198005b8d10SCédric Le Goater 199005b8d10SCédric Le Goater return info; 200005b8d10SCédric Le Goater } 201