1*6078a454SJean-Philippe Brucker #include "kvm/irq.h" 2*6078a454SJean-Philippe Brucker #include "kvm/kvm.h" 3*6078a454SJean-Philippe Brucker #include "kvm/kvm-cpu.h" 4*6078a454SJean-Philippe Brucker #include "kvm/vfio.h" 5*6078a454SJean-Philippe Brucker 6*6078a454SJean-Philippe Brucker #include <sys/ioctl.h> 7*6078a454SJean-Philippe Brucker #include <sys/eventfd.h> 8*6078a454SJean-Philippe Brucker 9*6078a454SJean-Philippe Brucker /* Wrapper around UAPI vfio_irq_set */ 10*6078a454SJean-Philippe Brucker struct vfio_irq_eventfd { 11*6078a454SJean-Philippe Brucker struct vfio_irq_set irq; 12*6078a454SJean-Philippe Brucker int fd; 13*6078a454SJean-Philippe Brucker }; 14*6078a454SJean-Philippe Brucker 15*6078a454SJean-Philippe Brucker static void vfio_pci_cfg_read(struct kvm *kvm, struct pci_device_header *pci_hdr, 16*6078a454SJean-Philippe Brucker u8 offset, void *data, int sz) 17*6078a454SJean-Philippe Brucker { 18*6078a454SJean-Philippe Brucker struct vfio_region_info *info; 19*6078a454SJean-Philippe Brucker struct vfio_pci_device *pdev; 20*6078a454SJean-Philippe Brucker struct vfio_device *vdev; 21*6078a454SJean-Philippe Brucker char base[sz]; 22*6078a454SJean-Philippe Brucker 23*6078a454SJean-Philippe Brucker pdev = container_of(pci_hdr, struct vfio_pci_device, hdr); 24*6078a454SJean-Philippe Brucker vdev = container_of(pdev, struct vfio_device, pci); 25*6078a454SJean-Philippe Brucker info = &vdev->regions[VFIO_PCI_CONFIG_REGION_INDEX].info; 26*6078a454SJean-Philippe Brucker 27*6078a454SJean-Philippe Brucker /* Dummy read in case of side-effects */ 28*6078a454SJean-Philippe Brucker if (pread(vdev->fd, base, sz, info->offset + offset) != sz) 29*6078a454SJean-Philippe Brucker vfio_dev_warn(vdev, "failed to read %d bytes from Configuration Space at 0x%x", 30*6078a454SJean-Philippe Brucker sz, offset); 31*6078a454SJean-Philippe Brucker } 32*6078a454SJean-Philippe Brucker 33*6078a454SJean-Philippe Brucker static void vfio_pci_cfg_write(struct kvm *kvm, struct pci_device_header *pci_hdr, 34*6078a454SJean-Philippe Brucker u8 offset, void *data, int sz) 35*6078a454SJean-Philippe Brucker { 36*6078a454SJean-Philippe Brucker struct vfio_region_info *info; 37*6078a454SJean-Philippe Brucker struct vfio_pci_device *pdev; 38*6078a454SJean-Philippe Brucker struct vfio_device *vdev; 39*6078a454SJean-Philippe Brucker void *base = pci_hdr; 40*6078a454SJean-Philippe Brucker 41*6078a454SJean-Philippe Brucker pdev = container_of(pci_hdr, struct vfio_pci_device, hdr); 42*6078a454SJean-Philippe Brucker vdev = container_of(pdev, struct vfio_device, pci); 43*6078a454SJean-Philippe Brucker info = &vdev->regions[VFIO_PCI_CONFIG_REGION_INDEX].info; 44*6078a454SJean-Philippe Brucker 45*6078a454SJean-Philippe Brucker if (pwrite(vdev->fd, data, sz, info->offset + offset) != sz) 46*6078a454SJean-Philippe Brucker vfio_dev_warn(vdev, "Failed to write %d bytes to Configuration Space at 0x%x", 47*6078a454SJean-Philippe Brucker sz, offset); 48*6078a454SJean-Philippe Brucker 49*6078a454SJean-Philippe Brucker if (pread(vdev->fd, base + offset, sz, info->offset + offset) != sz) 50*6078a454SJean-Philippe Brucker vfio_dev_warn(vdev, "Failed to read %d bytes from Configuration Space at 0x%x", 51*6078a454SJean-Philippe Brucker sz, offset); 52*6078a454SJean-Philippe Brucker } 53*6078a454SJean-Philippe Brucker 54*6078a454SJean-Philippe Brucker static int vfio_pci_parse_caps(struct vfio_device *vdev) 55*6078a454SJean-Philippe Brucker { 56*6078a454SJean-Philippe Brucker struct vfio_pci_device *pdev = &vdev->pci; 57*6078a454SJean-Philippe Brucker 58*6078a454SJean-Philippe Brucker if (!(pdev->hdr.status & PCI_STATUS_CAP_LIST)) 59*6078a454SJean-Philippe Brucker return 0; 60*6078a454SJean-Philippe Brucker 61*6078a454SJean-Philippe Brucker pdev->hdr.status &= ~PCI_STATUS_CAP_LIST; 62*6078a454SJean-Philippe Brucker pdev->hdr.capabilities = 0; 63*6078a454SJean-Philippe Brucker 64*6078a454SJean-Philippe Brucker /* TODO: install virtual capabilities */ 65*6078a454SJean-Philippe Brucker 66*6078a454SJean-Philippe Brucker return 0; 67*6078a454SJean-Philippe Brucker } 68*6078a454SJean-Philippe Brucker 69*6078a454SJean-Philippe Brucker static int vfio_pci_parse_cfg_space(struct vfio_device *vdev) 70*6078a454SJean-Philippe Brucker { 71*6078a454SJean-Philippe Brucker ssize_t sz = PCI_STD_HEADER_SIZEOF; 72*6078a454SJean-Philippe Brucker struct vfio_region_info *info; 73*6078a454SJean-Philippe Brucker struct vfio_pci_device *pdev = &vdev->pci; 74*6078a454SJean-Philippe Brucker 75*6078a454SJean-Philippe Brucker if (vdev->info.num_regions < VFIO_PCI_CONFIG_REGION_INDEX) { 76*6078a454SJean-Philippe Brucker vfio_dev_err(vdev, "Config Space not found"); 77*6078a454SJean-Philippe Brucker return -ENODEV; 78*6078a454SJean-Philippe Brucker } 79*6078a454SJean-Philippe Brucker 80*6078a454SJean-Philippe Brucker info = &vdev->regions[VFIO_PCI_CONFIG_REGION_INDEX].info; 81*6078a454SJean-Philippe Brucker *info = (struct vfio_region_info) { 82*6078a454SJean-Philippe Brucker .argsz = sizeof(*info), 83*6078a454SJean-Philippe Brucker .index = VFIO_PCI_CONFIG_REGION_INDEX, 84*6078a454SJean-Philippe Brucker }; 85*6078a454SJean-Philippe Brucker 86*6078a454SJean-Philippe Brucker ioctl(vdev->fd, VFIO_DEVICE_GET_REGION_INFO, info); 87*6078a454SJean-Philippe Brucker if (!info->size) { 88*6078a454SJean-Philippe Brucker vfio_dev_err(vdev, "Config Space has size zero?!"); 89*6078a454SJean-Philippe Brucker return -EINVAL; 90*6078a454SJean-Philippe Brucker } 91*6078a454SJean-Philippe Brucker 92*6078a454SJean-Philippe Brucker if (pread(vdev->fd, &pdev->hdr, sz, info->offset) != sz) { 93*6078a454SJean-Philippe Brucker vfio_dev_err(vdev, "failed to read %zd bytes of Config Space", sz); 94*6078a454SJean-Philippe Brucker return -EIO; 95*6078a454SJean-Philippe Brucker } 96*6078a454SJean-Philippe Brucker 97*6078a454SJean-Philippe Brucker /* Strip bit 7, that indicates multifunction */ 98*6078a454SJean-Philippe Brucker pdev->hdr.header_type &= 0x7f; 99*6078a454SJean-Philippe Brucker 100*6078a454SJean-Philippe Brucker if (pdev->hdr.header_type != PCI_HEADER_TYPE_NORMAL) { 101*6078a454SJean-Philippe Brucker vfio_dev_err(vdev, "unsupported header type %u", 102*6078a454SJean-Philippe Brucker pdev->hdr.header_type); 103*6078a454SJean-Philippe Brucker return -EOPNOTSUPP; 104*6078a454SJean-Philippe Brucker } 105*6078a454SJean-Philippe Brucker 106*6078a454SJean-Philippe Brucker vfio_pci_parse_caps(vdev); 107*6078a454SJean-Philippe Brucker 108*6078a454SJean-Philippe Brucker return 0; 109*6078a454SJean-Philippe Brucker } 110*6078a454SJean-Philippe Brucker 111*6078a454SJean-Philippe Brucker static int vfio_pci_fixup_cfg_space(struct vfio_device *vdev) 112*6078a454SJean-Philippe Brucker { 113*6078a454SJean-Philippe Brucker int i; 114*6078a454SJean-Philippe Brucker ssize_t hdr_sz; 115*6078a454SJean-Philippe Brucker struct vfio_region_info *info; 116*6078a454SJean-Philippe Brucker struct vfio_pci_device *pdev = &vdev->pci; 117*6078a454SJean-Philippe Brucker 118*6078a454SJean-Philippe Brucker /* Enable exclusively MMIO and bus mastering */ 119*6078a454SJean-Philippe Brucker pdev->hdr.command &= ~PCI_COMMAND_IO; 120*6078a454SJean-Philippe Brucker pdev->hdr.command |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; 121*6078a454SJean-Philippe Brucker 122*6078a454SJean-Philippe Brucker /* Initialise the BARs */ 123*6078a454SJean-Philippe Brucker for (i = VFIO_PCI_BAR0_REGION_INDEX; i <= VFIO_PCI_BAR5_REGION_INDEX; ++i) { 124*6078a454SJean-Philippe Brucker struct vfio_region *region = &vdev->regions[i]; 125*6078a454SJean-Philippe Brucker u64 base = region->guest_phys_addr; 126*6078a454SJean-Philippe Brucker 127*6078a454SJean-Philippe Brucker if (!base) 128*6078a454SJean-Philippe Brucker continue; 129*6078a454SJean-Philippe Brucker 130*6078a454SJean-Philippe Brucker pdev->hdr.bar_size[i] = region->info.size; 131*6078a454SJean-Philippe Brucker 132*6078a454SJean-Philippe Brucker /* Construct a fake reg to match what we've mapped. */ 133*6078a454SJean-Philippe Brucker pdev->hdr.bar[i] = (base & PCI_BASE_ADDRESS_MEM_MASK) | 134*6078a454SJean-Philippe Brucker PCI_BASE_ADDRESS_SPACE_MEMORY | 135*6078a454SJean-Philippe Brucker PCI_BASE_ADDRESS_MEM_TYPE_32; 136*6078a454SJean-Philippe Brucker } 137*6078a454SJean-Philippe Brucker 138*6078a454SJean-Philippe Brucker /* I really can't be bothered to support cardbus. */ 139*6078a454SJean-Philippe Brucker pdev->hdr.card_bus = 0; 140*6078a454SJean-Philippe Brucker 141*6078a454SJean-Philippe Brucker /* 142*6078a454SJean-Philippe Brucker * Nuke the expansion ROM for now. If we want to do this properly, 143*6078a454SJean-Philippe Brucker * we need to save its size somewhere and map into the guest. 144*6078a454SJean-Philippe Brucker */ 145*6078a454SJean-Philippe Brucker pdev->hdr.exp_rom_bar = 0; 146*6078a454SJean-Philippe Brucker 147*6078a454SJean-Philippe Brucker /* Install our fake Configuration Space */ 148*6078a454SJean-Philippe Brucker info = &vdev->regions[VFIO_PCI_CONFIG_REGION_INDEX].info; 149*6078a454SJean-Philippe Brucker hdr_sz = PCI_DEV_CFG_SIZE; 150*6078a454SJean-Philippe Brucker if (pwrite(vdev->fd, &pdev->hdr, hdr_sz, info->offset) != hdr_sz) { 151*6078a454SJean-Philippe Brucker vfio_dev_err(vdev, "failed to write %zd bytes to Config Space", 152*6078a454SJean-Philippe Brucker hdr_sz); 153*6078a454SJean-Philippe Brucker return -EIO; 154*6078a454SJean-Philippe Brucker } 155*6078a454SJean-Philippe Brucker 156*6078a454SJean-Philippe Brucker /* Register callbacks for cfg accesses */ 157*6078a454SJean-Philippe Brucker pdev->hdr.cfg_ops = (struct pci_config_operations) { 158*6078a454SJean-Philippe Brucker .read = vfio_pci_cfg_read, 159*6078a454SJean-Philippe Brucker .write = vfio_pci_cfg_write, 160*6078a454SJean-Philippe Brucker }; 161*6078a454SJean-Philippe Brucker 162*6078a454SJean-Philippe Brucker pdev->hdr.irq_type = IRQ_TYPE_LEVEL_HIGH; 163*6078a454SJean-Philippe Brucker 164*6078a454SJean-Philippe Brucker return 0; 165*6078a454SJean-Philippe Brucker } 166*6078a454SJean-Philippe Brucker 167*6078a454SJean-Philippe Brucker static int vfio_pci_configure_bar(struct kvm *kvm, struct vfio_device *vdev, 168*6078a454SJean-Philippe Brucker size_t nr) 169*6078a454SJean-Philippe Brucker { 170*6078a454SJean-Philippe Brucker int ret; 171*6078a454SJean-Philippe Brucker size_t map_size; 172*6078a454SJean-Philippe Brucker struct vfio_region *region = &vdev->regions[nr]; 173*6078a454SJean-Philippe Brucker 174*6078a454SJean-Philippe Brucker if (nr >= vdev->info.num_regions) 175*6078a454SJean-Philippe Brucker return 0; 176*6078a454SJean-Philippe Brucker 177*6078a454SJean-Philippe Brucker region->info = (struct vfio_region_info) { 178*6078a454SJean-Philippe Brucker .argsz = sizeof(region->info), 179*6078a454SJean-Philippe Brucker .index = nr, 180*6078a454SJean-Philippe Brucker }; 181*6078a454SJean-Philippe Brucker 182*6078a454SJean-Philippe Brucker ret = ioctl(vdev->fd, VFIO_DEVICE_GET_REGION_INFO, ®ion->info); 183*6078a454SJean-Philippe Brucker if (ret) { 184*6078a454SJean-Philippe Brucker ret = -errno; 185*6078a454SJean-Philippe Brucker vfio_dev_err(vdev, "cannot get info for BAR %zu", nr); 186*6078a454SJean-Philippe Brucker return ret; 187*6078a454SJean-Philippe Brucker } 188*6078a454SJean-Philippe Brucker 189*6078a454SJean-Philippe Brucker /* Ignore invalid or unimplemented regions */ 190*6078a454SJean-Philippe Brucker if (!region->info.size) 191*6078a454SJean-Philippe Brucker return 0; 192*6078a454SJean-Philippe Brucker 193*6078a454SJean-Philippe Brucker /* Grab some MMIO space in the guest */ 194*6078a454SJean-Philippe Brucker map_size = ALIGN(region->info.size, PAGE_SIZE); 195*6078a454SJean-Philippe Brucker region->guest_phys_addr = pci_get_io_space_block(map_size); 196*6078a454SJean-Philippe Brucker 197*6078a454SJean-Philippe Brucker /* 198*6078a454SJean-Philippe Brucker * Map the BARs into the guest. We'll later need to update 199*6078a454SJean-Philippe Brucker * configuration space to reflect our allocation. 200*6078a454SJean-Philippe Brucker */ 201*6078a454SJean-Philippe Brucker ret = vfio_map_region(kvm, vdev, region); 202*6078a454SJean-Philippe Brucker if (ret) 203*6078a454SJean-Philippe Brucker return ret; 204*6078a454SJean-Philippe Brucker 205*6078a454SJean-Philippe Brucker return 0; 206*6078a454SJean-Philippe Brucker } 207*6078a454SJean-Philippe Brucker 208*6078a454SJean-Philippe Brucker static int vfio_pci_configure_dev_regions(struct kvm *kvm, 209*6078a454SJean-Philippe Brucker struct vfio_device *vdev) 210*6078a454SJean-Philippe Brucker { 211*6078a454SJean-Philippe Brucker int ret; 212*6078a454SJean-Philippe Brucker u32 bar; 213*6078a454SJean-Philippe Brucker size_t i; 214*6078a454SJean-Philippe Brucker bool is_64bit = false; 215*6078a454SJean-Philippe Brucker struct vfio_pci_device *pdev = &vdev->pci; 216*6078a454SJean-Philippe Brucker 217*6078a454SJean-Philippe Brucker ret = vfio_pci_parse_cfg_space(vdev); 218*6078a454SJean-Philippe Brucker if (ret) 219*6078a454SJean-Philippe Brucker return ret; 220*6078a454SJean-Philippe Brucker 221*6078a454SJean-Philippe Brucker for (i = VFIO_PCI_BAR0_REGION_INDEX; i <= VFIO_PCI_BAR5_REGION_INDEX; ++i) { 222*6078a454SJean-Philippe Brucker /* Ignore top half of 64-bit BAR */ 223*6078a454SJean-Philippe Brucker if (i % 2 && is_64bit) 224*6078a454SJean-Philippe Brucker continue; 225*6078a454SJean-Philippe Brucker 226*6078a454SJean-Philippe Brucker ret = vfio_pci_configure_bar(kvm, vdev, i); 227*6078a454SJean-Philippe Brucker if (ret) 228*6078a454SJean-Philippe Brucker return ret; 229*6078a454SJean-Philippe Brucker 230*6078a454SJean-Philippe Brucker bar = pdev->hdr.bar[i]; 231*6078a454SJean-Philippe Brucker is_64bit = (bar & PCI_BASE_ADDRESS_SPACE) == 232*6078a454SJean-Philippe Brucker PCI_BASE_ADDRESS_SPACE_MEMORY && 233*6078a454SJean-Philippe Brucker bar & PCI_BASE_ADDRESS_MEM_TYPE_64; 234*6078a454SJean-Philippe Brucker } 235*6078a454SJean-Philippe Brucker 236*6078a454SJean-Philippe Brucker /* We've configured the BARs, fake up a Configuration Space */ 237*6078a454SJean-Philippe Brucker return vfio_pci_fixup_cfg_space(vdev); 238*6078a454SJean-Philippe Brucker } 239*6078a454SJean-Philippe Brucker 240*6078a454SJean-Philippe Brucker static int vfio_pci_enable_intx(struct kvm *kvm, struct vfio_device *vdev) 241*6078a454SJean-Philippe Brucker { 242*6078a454SJean-Philippe Brucker int ret; 243*6078a454SJean-Philippe Brucker int trigger_fd, unmask_fd; 244*6078a454SJean-Philippe Brucker struct vfio_irq_eventfd trigger; 245*6078a454SJean-Philippe Brucker struct vfio_irq_eventfd unmask; 246*6078a454SJean-Philippe Brucker struct vfio_pci_device *pdev = &vdev->pci; 247*6078a454SJean-Philippe Brucker int gsi = pdev->hdr.irq_line - KVM_IRQ_OFFSET; 248*6078a454SJean-Philippe Brucker 249*6078a454SJean-Philippe Brucker struct vfio_irq_info irq_info = { 250*6078a454SJean-Philippe Brucker .argsz = sizeof(irq_info), 251*6078a454SJean-Philippe Brucker .index = VFIO_PCI_INTX_IRQ_INDEX, 252*6078a454SJean-Philippe Brucker }; 253*6078a454SJean-Philippe Brucker 254*6078a454SJean-Philippe Brucker ret = ioctl(vdev->fd, VFIO_DEVICE_GET_IRQ_INFO, &irq_info); 255*6078a454SJean-Philippe Brucker if (ret || irq_info.count == 0) { 256*6078a454SJean-Philippe Brucker vfio_dev_err(vdev, "no INTx reported by VFIO"); 257*6078a454SJean-Philippe Brucker return -ENODEV; 258*6078a454SJean-Philippe Brucker } 259*6078a454SJean-Philippe Brucker 260*6078a454SJean-Philippe Brucker if (!(irq_info.flags & VFIO_IRQ_INFO_EVENTFD)) { 261*6078a454SJean-Philippe Brucker vfio_dev_err(vdev, "interrupt not eventfd capable"); 262*6078a454SJean-Philippe Brucker return -EINVAL; 263*6078a454SJean-Philippe Brucker } 264*6078a454SJean-Philippe Brucker 265*6078a454SJean-Philippe Brucker if (!(irq_info.flags & VFIO_IRQ_INFO_AUTOMASKED)) { 266*6078a454SJean-Philippe Brucker vfio_dev_err(vdev, "INTx interrupt not AUTOMASKED"); 267*6078a454SJean-Philippe Brucker return -EINVAL; 268*6078a454SJean-Philippe Brucker } 269*6078a454SJean-Philippe Brucker 270*6078a454SJean-Philippe Brucker /* 271*6078a454SJean-Philippe Brucker * PCI IRQ is level-triggered, so we use two eventfds. trigger_fd 272*6078a454SJean-Philippe Brucker * signals an interrupt from host to guest, and unmask_fd signals the 273*6078a454SJean-Philippe Brucker * deassertion of the line from guest to host. 274*6078a454SJean-Philippe Brucker */ 275*6078a454SJean-Philippe Brucker trigger_fd = eventfd(0, 0); 276*6078a454SJean-Philippe Brucker if (trigger_fd < 0) { 277*6078a454SJean-Philippe Brucker vfio_dev_err(vdev, "failed to create trigger eventfd"); 278*6078a454SJean-Philippe Brucker return trigger_fd; 279*6078a454SJean-Philippe Brucker } 280*6078a454SJean-Philippe Brucker 281*6078a454SJean-Philippe Brucker unmask_fd = eventfd(0, 0); 282*6078a454SJean-Philippe Brucker if (unmask_fd < 0) { 283*6078a454SJean-Philippe Brucker vfio_dev_err(vdev, "failed to create unmask eventfd"); 284*6078a454SJean-Philippe Brucker close(trigger_fd); 285*6078a454SJean-Philippe Brucker return unmask_fd; 286*6078a454SJean-Philippe Brucker } 287*6078a454SJean-Philippe Brucker 288*6078a454SJean-Philippe Brucker ret = irq__add_irqfd(kvm, gsi, trigger_fd, unmask_fd); 289*6078a454SJean-Philippe Brucker if (ret) 290*6078a454SJean-Philippe Brucker goto err_close; 291*6078a454SJean-Philippe Brucker 292*6078a454SJean-Philippe Brucker trigger.irq = (struct vfio_irq_set) { 293*6078a454SJean-Philippe Brucker .argsz = sizeof(trigger), 294*6078a454SJean-Philippe Brucker .flags = VFIO_IRQ_SET_DATA_EVENTFD | VFIO_IRQ_SET_ACTION_TRIGGER, 295*6078a454SJean-Philippe Brucker .index = VFIO_PCI_INTX_IRQ_INDEX, 296*6078a454SJean-Philippe Brucker .start = 0, 297*6078a454SJean-Philippe Brucker .count = 1, 298*6078a454SJean-Philippe Brucker }; 299*6078a454SJean-Philippe Brucker trigger.fd = trigger_fd; 300*6078a454SJean-Philippe Brucker 301*6078a454SJean-Philippe Brucker ret = ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, &trigger); 302*6078a454SJean-Philippe Brucker if (ret < 0) { 303*6078a454SJean-Philippe Brucker vfio_dev_err(vdev, "failed to setup VFIO IRQ"); 304*6078a454SJean-Philippe Brucker goto err_delete_line; 305*6078a454SJean-Philippe Brucker } 306*6078a454SJean-Philippe Brucker 307*6078a454SJean-Philippe Brucker unmask.irq = (struct vfio_irq_set) { 308*6078a454SJean-Philippe Brucker .argsz = sizeof(unmask), 309*6078a454SJean-Philippe Brucker .flags = VFIO_IRQ_SET_DATA_EVENTFD | VFIO_IRQ_SET_ACTION_UNMASK, 310*6078a454SJean-Philippe Brucker .index = VFIO_PCI_INTX_IRQ_INDEX, 311*6078a454SJean-Philippe Brucker .start = 0, 312*6078a454SJean-Philippe Brucker .count = 1, 313*6078a454SJean-Philippe Brucker }; 314*6078a454SJean-Philippe Brucker unmask.fd = unmask_fd; 315*6078a454SJean-Philippe Brucker 316*6078a454SJean-Philippe Brucker ret = ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, &unmask); 317*6078a454SJean-Philippe Brucker if (ret < 0) { 318*6078a454SJean-Philippe Brucker vfio_dev_err(vdev, "failed to setup unmask IRQ"); 319*6078a454SJean-Philippe Brucker goto err_remove_event; 320*6078a454SJean-Philippe Brucker } 321*6078a454SJean-Philippe Brucker 322*6078a454SJean-Philippe Brucker return 0; 323*6078a454SJean-Philippe Brucker 324*6078a454SJean-Philippe Brucker err_remove_event: 325*6078a454SJean-Philippe Brucker /* Remove trigger event */ 326*6078a454SJean-Philippe Brucker trigger.irq.flags = VFIO_IRQ_SET_DATA_NONE | VFIO_IRQ_SET_ACTION_TRIGGER; 327*6078a454SJean-Philippe Brucker trigger.irq.count = 0; 328*6078a454SJean-Philippe Brucker ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, &trigger); 329*6078a454SJean-Philippe Brucker 330*6078a454SJean-Philippe Brucker err_delete_line: 331*6078a454SJean-Philippe Brucker irq__del_irqfd(kvm, gsi, trigger_fd); 332*6078a454SJean-Philippe Brucker 333*6078a454SJean-Philippe Brucker err_close: 334*6078a454SJean-Philippe Brucker close(trigger_fd); 335*6078a454SJean-Philippe Brucker close(unmask_fd); 336*6078a454SJean-Philippe Brucker return ret; 337*6078a454SJean-Philippe Brucker } 338*6078a454SJean-Philippe Brucker 339*6078a454SJean-Philippe Brucker static int vfio_pci_configure_dev_irqs(struct kvm *kvm, struct vfio_device *vdev) 340*6078a454SJean-Philippe Brucker { 341*6078a454SJean-Philippe Brucker struct vfio_pci_device *pdev = &vdev->pci; 342*6078a454SJean-Philippe Brucker 343*6078a454SJean-Philippe Brucker struct vfio_irq_info irq_info = { 344*6078a454SJean-Philippe Brucker .argsz = sizeof(irq_info), 345*6078a454SJean-Philippe Brucker .index = VFIO_PCI_INTX_IRQ_INDEX, 346*6078a454SJean-Philippe Brucker }; 347*6078a454SJean-Philippe Brucker 348*6078a454SJean-Philippe Brucker if (!pdev->hdr.irq_pin) { 349*6078a454SJean-Philippe Brucker /* TODO: add MSI support */ 350*6078a454SJean-Philippe Brucker vfio_dev_err(vdev, "INTx not available, MSI-X not implemented"); 351*6078a454SJean-Philippe Brucker return -ENOSYS; 352*6078a454SJean-Philippe Brucker } 353*6078a454SJean-Philippe Brucker 354*6078a454SJean-Philippe Brucker return vfio_pci_enable_intx(kvm, vdev); 355*6078a454SJean-Philippe Brucker } 356*6078a454SJean-Philippe Brucker 357*6078a454SJean-Philippe Brucker int vfio_pci_setup_device(struct kvm *kvm, struct vfio_device *vdev) 358*6078a454SJean-Philippe Brucker { 359*6078a454SJean-Philippe Brucker int ret; 360*6078a454SJean-Philippe Brucker 361*6078a454SJean-Philippe Brucker ret = vfio_pci_configure_dev_regions(kvm, vdev); 362*6078a454SJean-Philippe Brucker if (ret) { 363*6078a454SJean-Philippe Brucker vfio_dev_err(vdev, "failed to configure regions"); 364*6078a454SJean-Philippe Brucker return ret; 365*6078a454SJean-Philippe Brucker } 366*6078a454SJean-Philippe Brucker 367*6078a454SJean-Philippe Brucker vdev->dev_hdr = (struct device_header) { 368*6078a454SJean-Philippe Brucker .bus_type = DEVICE_BUS_PCI, 369*6078a454SJean-Philippe Brucker .data = &vdev->pci.hdr, 370*6078a454SJean-Philippe Brucker }; 371*6078a454SJean-Philippe Brucker 372*6078a454SJean-Philippe Brucker ret = device__register(&vdev->dev_hdr); 373*6078a454SJean-Philippe Brucker if (ret) { 374*6078a454SJean-Philippe Brucker vfio_dev_err(vdev, "failed to register VFIO device"); 375*6078a454SJean-Philippe Brucker return ret; 376*6078a454SJean-Philippe Brucker } 377*6078a454SJean-Philippe Brucker 378*6078a454SJean-Philippe Brucker ret = vfio_pci_configure_dev_irqs(kvm, vdev); 379*6078a454SJean-Philippe Brucker if (ret) { 380*6078a454SJean-Philippe Brucker vfio_dev_err(vdev, "failed to configure IRQs"); 381*6078a454SJean-Philippe Brucker return ret; 382*6078a454SJean-Philippe Brucker } 383*6078a454SJean-Philippe Brucker 384*6078a454SJean-Philippe Brucker return 0; 385*6078a454SJean-Philippe Brucker } 386*6078a454SJean-Philippe Brucker 387*6078a454SJean-Philippe Brucker void vfio_pci_teardown_device(struct kvm *kvm, struct vfio_device *vdev) 388*6078a454SJean-Philippe Brucker { 389*6078a454SJean-Philippe Brucker size_t i; 390*6078a454SJean-Philippe Brucker 391*6078a454SJean-Philippe Brucker for (i = 0; i < vdev->info.num_regions; i++) 392*6078a454SJean-Philippe Brucker vfio_unmap_region(kvm, &vdev->regions[i]); 393*6078a454SJean-Philippe Brucker 394*6078a454SJean-Philippe Brucker device__unregister(&vdev->dev_hdr); 395*6078a454SJean-Philippe Brucker } 396