vfio: fix resource leak
[dpdk.git] / lib / librte_eal / linuxapp / eal / eal_pci_vfio.c
index ffa2dd0..10266f8 100644 (file)
@@ -74,6 +74,7 @@ EAL_REGISTER_TAILQ(rte_vfio_tailq)
 #define VFIO_GROUP_FMT "/dev/vfio/%u"
 #define VFIO_NOIOMMU_GROUP_FMT "/dev/vfio/noiommu-%u"
 #define VFIO_GET_REGION_ADDR(x) ((uint64_t) x << 40ULL)
+#define VFIO_GET_REGION_IDX(x) (x >> 40)
 
 /* per-process VFIO config */
 static struct vfio_config vfio_cfg;
@@ -534,6 +535,7 @@ pci_vfio_get_group_fd(int iommu_group_no)
                /* if the fd is valid, create a new group for it */
                if (vfio_cfg.vfio_group_idx == VFIO_MAX_GROUPS) {
                        RTE_LOG(ERR, EAL, "Maximum number of VFIO groups reached!\n");
+                       close(vfio_group_fd);
                        return -1;
                }
                vfio_cfg.vfio_groups[vfio_cfg.vfio_group_idx].group_no = iommu_group_no;
@@ -659,6 +661,7 @@ pci_vfio_map_resource(struct rte_pci_device *dev)
        struct pci_map *maps;
        uint32_t msix_table_offset = 0;
        uint32_t msix_table_size = 0;
+       uint32_t ioport_bar;
 
        dev->intr_handle.fd = -1;
        dev->intr_handle.type = RTE_INTR_HANDLE_UNKNOWN;
@@ -853,6 +856,25 @@ pci_vfio_map_resource(struct rte_pci_device *dev)
                        return -1;
                }
 
+               /* chk for io port region */
+               ret = pread64(vfio_dev_fd, &ioport_bar, sizeof(ioport_bar),
+                             VFIO_GET_REGION_ADDR(VFIO_PCI_CONFIG_REGION_INDEX)
+                             + PCI_BASE_ADDRESS_0 + i*4);
+
+               if (ret != sizeof(ioport_bar)) {
+                       RTE_LOG(ERR, EAL,
+                               "Cannot read command (%x) from config space!\n",
+                               PCI_BASE_ADDRESS_0 + i*4);
+                       return -1;
+               }
+
+               if (ioport_bar & PCI_BASE_ADDRESS_SPACE_IO) {
+                       RTE_LOG(INFO, EAL,
+                               "Ignore mapping IO port bar(%d) addr: %x\n",
+                                i, ioport_bar);
+                       continue;
+               }
+
                /* skip non-mmapable BARs */
                if ((reg.flags & VFIO_REGION_INFO_FLAG_MMAP) == 0)
                        continue;
@@ -979,30 +1001,41 @@ int
 pci_vfio_ioport_map(struct rte_pci_device *dev, int bar,
                    struct rte_pci_ioport *p)
 {
-       RTE_SET_USED(dev);
-       RTE_SET_USED(bar);
-       RTE_SET_USED(p);
-       return -1;
+       if (bar < VFIO_PCI_BAR0_REGION_INDEX ||
+           bar > VFIO_PCI_BAR5_REGION_INDEX) {
+               RTE_LOG(ERR, EAL, "invalid bar (%d)!\n", bar);
+               return -1;
+       }
+
+       p->dev = dev;
+       p->base = VFIO_GET_REGION_ADDR(bar);
+       return 0;
 }
 
 void
 pci_vfio_ioport_read(struct rte_pci_ioport *p,
                     void *data, size_t len, off_t offset)
 {
-       RTE_SET_USED(p);
-       RTE_SET_USED(data);
-       RTE_SET_USED(len);
-       RTE_SET_USED(offset);
+       const struct rte_intr_handle *intr_handle = &p->dev->intr_handle;
+
+       if (pread64(intr_handle->vfio_dev_fd, data,
+                   len, p->base + offset) <= 0)
+               RTE_LOG(ERR, EAL,
+                       "Can't read from PCI bar (%" PRIu64 ") : offset (%x)\n",
+                       VFIO_GET_REGION_IDX(p->base), (int)offset);
 }
 
 void
 pci_vfio_ioport_write(struct rte_pci_ioport *p,
                      const void *data, size_t len, off_t offset)
 {
-       RTE_SET_USED(p);
-       RTE_SET_USED(data);
-       RTE_SET_USED(len);
-       RTE_SET_USED(offset);
+       const struct rte_intr_handle *intr_handle = &p->dev->intr_handle;
+
+       if (pwrite64(intr_handle->vfio_dev_fd, data,
+                    len, p->base + offset) <= 0)
+               RTE_LOG(ERR, EAL,
+                       "Can't write to PCI bar (%" PRIu64 ") : offset (%x)\n",
+                       VFIO_GET_REGION_IDX(p->base), (int)offset);
 }
 
 int
@@ -1038,7 +1071,7 @@ pci_vfio_enable(void)
 
        /* return 0 if VFIO modules not loaded */
        if (vfio_available == 0) {
-               RTE_LOG(INFO, EAL, "VFIO modules not loaded, "
+               RTE_LOG(DEBUG, EAL, "VFIO modules not loaded, "
                        "skipping VFIO support...\n");
                return 0;
        }