Make virtio not require UIO for some security reasons, this is to match 6Wind's virtio-net-pmd.
Signed-off-by: Changchun Ouyang <changchun.ouyang at intel.com> --- lib/librte_eal/common/include/rte_pci.h | 2 + lib/librte_eal/linuxapp/eal/eal_pci.c | 3 +- lib/librte_pmd_virtio/virtio_ethdev.c | 75 ++++++++++++++++++++++++++++++++- 3 files changed, 77 insertions(+), 3 deletions(-) diff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h index 66ed793..2021b3b 100644 --- a/lib/librte_eal/common/include/rte_pci.h +++ b/lib/librte_eal/common/include/rte_pci.h @@ -193,6 +193,8 @@ struct rte_pci_driver { /** Device needs PCI BAR mapping (done with either IGB_UIO or VFIO) */ #define RTE_PCI_DRV_NEED_MAPPING 0x0001 +/** Device needs port IO(done with /proc/ioports) */ +#define RTE_PCI_DRV_IO_PORT 0x0002 /** Device driver must be registered several times until failure - deprecated */ #pragma GCC poison RTE_PCI_DRV_MULTIPLE /** Device needs to be unbound even if no module is provided */ diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c b/lib/librte_eal/linuxapp/eal/eal_pci.c index b5f5410..dd60793 100644 --- a/lib/librte_eal/linuxapp/eal/eal_pci.c +++ b/lib/librte_eal/linuxapp/eal/eal_pci.c @@ -573,7 +573,8 @@ rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr, struct rte_pci_device *d #endif /* map resources for devices that use igb_uio */ ret = pci_map_device(dev); - if (ret != 0) + if ((ret != 0) && + ((dr->drv_flags & RTE_PCI_DRV_IO_PORT) == 0)) return ret; } else if (dr->drv_flags & RTE_PCI_DRV_FORCE_UNBIND && rte_eal_process_type() == RTE_PROC_PRIMARY) { diff --git a/lib/librte_pmd_virtio/virtio_ethdev.c b/lib/librte_pmd_virtio/virtio_ethdev.c index 1ec29e1..4490a06 100644 --- a/lib/librte_pmd_virtio/virtio_ethdev.c +++ b/lib/librte_pmd_virtio/virtio_ethdev.c @@ -961,6 +961,69 @@ static int virtio_resource_init(struct rte_pci_device *pci_dev) start, size); return 0; } + +/* Extract I/O port numbers from proc/ioports */ +static int virtio_resource_init_by_ioport(struct rte_pci_device *pci_dev) +{ + uint16_t start, end; + int size; + FILE* fp; + char* line = NULL; + char pci_id[16]; + int found = 0; + size_t linesz; + + snprintf(pci_id, sizeof(pci_id), PCI_PRI_FMT, + pci_dev->addr.domain, + pci_dev->addr.bus, + pci_dev->addr.devid, + pci_dev->addr.function); + + fp = fopen("/proc/ioports", "r"); + if (fp == NULL) { + PMD_INIT_LOG(ERR, "%s(): can't open ioports", __func__); + return -1; + } + + while (getdelim(&line, &linesz, '\n', fp) > 0) { + char* ptr = line; + char* left; + int n; + + n = strcspn(ptr, ":"); + ptr[n]= 0; + left = &ptr[n+1]; + + while (*left && isspace(*left)) + left++; + + if (!strncmp(left, pci_id, strlen(pci_id))) { + found = 1; + + while (*ptr && isspace(*ptr)) + ptr++; + + sscanf(ptr, "%04hx-%04hx", &start, &end); + size = end - start + 1; + + break; + } + } + + free(line); + fclose(fp); + + if (!found) + return -1; + + pci_dev->mem_resource[0].addr = (void *)(uintptr_t)(uint32_t)start; + pci_dev->mem_resource[0].len = (uint64_t)size; + PMD_INIT_LOG(DEBUG, + "PCI Port IO found start=0x%lx with size=0x%lx", + start, size); + return 0; +} + #else static int virtio_has_msix(const struct rte_pci_addr *loc __rte_unused) @@ -974,6 +1037,12 @@ static int virtio_resource_init(struct rte_pci_device *pci_dev __rte_unused) /* no setup required */ return 0; } + +static int virtio_resource_init_by_ioport(struct rte_pci_device *pci_dev) +{ + /* no setup required */ + return 0; +} #endif /* @@ -1039,7 +1108,8 @@ eth_virtio_dev_init(__rte_unused struct eth_driver *eth_drv, pci_dev = eth_dev->pci_dev; if (virtio_resource_init(pci_dev) < 0) - return -1; + if (virtio_resource_init_by_ioport(pci_dev) < 0) + return -1; hw->use_msix = virtio_has_msix(&pci_dev->addr); hw->io_base = (uint32_t)(uintptr_t)pci_dev->mem_resource[0].addr; @@ -1136,7 +1206,8 @@ static struct eth_driver rte_virtio_pmd = { { .name = "rte_virtio_pmd", .id_table = pci_id_virtio_map, - .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC, + .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_IO_PORT |\ + RTE_PCI_DRV_INTR_LSC, }, .eth_dev_init = eth_virtio_dev_init, .dev_private_size = sizeof(struct virtio_hw), -- 1.8.4.2