diff options
author | Damjan Marion <damarion@cisco.com> | 2018-03-09 16:05:56 +0100 |
---|---|---|
committer | Florin Coras <florin.coras@gmail.com> | 2018-03-09 19:20:32 +0000 |
commit | 51c52c0adc9bf79ca6508ee1327d3b972e80b5c6 (patch) | |
tree | 70936cd041b0faf511592c46c5c69948e7a95f91 | |
parent | fef3f7bd0ae43586540533e7ee1a7cc910ccb16d (diff) |
dpdk: move DPDK vfio hack to dpdk plugin
Change-Id: I806cbf8c6c49643fe6c317bcceab93c1b9d441ab
Signed-off-by: Damjan Marion <damarion@cisco.com>
-rw-r--r-- | src/plugins/dpdk/buffer.c | 69 | ||||
-rw-r--r-- | src/vlib/linux/physmem.c | 16 | ||||
-rw-r--r-- | src/vlib/linux/vfio.c | 34 | ||||
-rw-r--r-- | src/vlib/linux/vfio.h | 1 |
4 files changed, 70 insertions, 50 deletions
diff --git a/src/plugins/dpdk/buffer.c b/src/plugins/dpdk/buffer.c index f6379a1da4a..47d66484b3d 100644 --- a/src/plugins/dpdk/buffer.c +++ b/src/plugins/dpdk/buffer.c @@ -43,6 +43,10 @@ * Allocate/free network buffers. */ +#include <unistd.h> +#include <linux/vfio.h> +#include <sys/ioctl.h> + #include <rte_config.h> #include <rte_common.h> @@ -71,11 +75,13 @@ #include <rte_version.h> #include <vlib/vlib.h> +#include <vlib/unix/unix.h> +#include <vlib/pci/pci.h> +#include <vlib/linux/vfio.h> #include <vnet/vnet.h> #include <dpdk/device/dpdk.h> #include <dpdk/device/dpdk_priv.h> - STATIC_ASSERT (VLIB_BUFFER_PRE_DATA_SIZE == RTE_PKTMBUF_HEADROOM, "VLIB_BUFFER_PRE_DATA_SIZE must be equal to RTE_PKTMBUF_HEADROOM"); @@ -91,6 +97,7 @@ typedef struct typedef struct { + int vfio_container_fd; dpdk_buffer_per_thread_data *ptd; } dpdk_buffer_main_t; @@ -459,11 +466,38 @@ dpdk_packet_template_init (vlib_main_t * vm, vlib_worker_thread_barrier_release (vm); } +static clib_error_t * +scan_vfio_fd (void *arg, u8 * path_name, u8 * file_name) +{ + dpdk_buffer_main_t *dbm = &dpdk_buffer_main; + linux_vfio_main_t *lvm = &vfio_main; + const char fn[] = "/dev/vfio/vfio"; + char buff[sizeof (fn)] = { 0 }; + int fd; + u8 *path = format (0, "%v%c", path_name, 0); + + if (readlink ((char *) path, buff, sizeof (fn)) + 1 != sizeof (fn)) + goto done; + + if (strncmp (fn, buff, sizeof (fn))) + goto done; + + fd = atoi ((char *) file_name); + if (fd != lvm->container_fd) + dbm->vfio_container_fd = fd; + +done: + vec_free (path); + return 0; +} + clib_error_t * dpdk_pool_create (vlib_main_t * vm, u8 * pool_name, u32 elt_size, u32 num_elts, u32 pool_priv_size, u16 cache_size, u8 numa, - struct rte_mempool **_mp, vlib_physmem_region_index_t * pri) + struct rte_mempool ** _mp, + vlib_physmem_region_index_t * pri) { + dpdk_buffer_main_t *dbm = &dpdk_buffer_main; struct rte_mempool *mp; vlib_physmem_region_t *pr; clib_error_t *error = 0; @@ -501,6 +535,33 @@ dpdk_pool_create (vlib_main_t * vm, u8 * pool_name, u32 elt_size, _mp[0] = mp; + /* DPDK currently doesn't provide API to map DMA memory for empty mempool + so we are using this hack, will be nice to have at least API to get + VFIO container FD */ + if (dbm->vfio_container_fd == -1) + foreach_directory_file ("/proc/self/fd", scan_vfio_fd, 0, 0); + + if (dbm->vfio_container_fd != -1) + { + struct vfio_iommu_type1_dma_map dm = { 0 }; + int i, rv = 0; + dm.argsz = sizeof (struct vfio_iommu_type1_dma_map); + dm.flags = VFIO_DMA_MAP_FLAG_READ | VFIO_DMA_MAP_FLAG_WRITE; + + /* *INDENT-OFF* */ + vec_foreach_index (i, pr->page_table) + { + dm.vaddr = pointer_to_uword (pr->mem) + (i << pr->log2_page_size); + dm.size = 1 << pr->log2_page_size; + dm.iova = pr->page_table[i]; + if ((rv = ioctl (dbm->vfio_container_fd, VFIO_IOMMU_MAP_DMA, &dm))) + break; + } + /* *INDENT-ON* */ + if (rv != 0 && rv != EINVAL) + clib_unix_warning ("ioctl(VFIO_IOMMU_MAP_DMA) pool '%s'", pool_name); + } + return 0; } @@ -665,8 +726,12 @@ dpdk_buffer_init (vlib_main_t * vm) { dpdk_buffer_main_t *dbm = &dpdk_buffer_main; vlib_thread_main_t *tm = vlib_get_thread_main (); + vec_validate_aligned (dbm->ptd, tm->n_vlib_mains - 1, CLIB_CACHE_LINE_BYTES); + + dbm->vfio_container_fd = -1; + return 0; } diff --git a/src/vlib/linux/physmem.c b/src/vlib/linux/physmem.c index cf2961b4cf9..1a449921857 100644 --- a/src/vlib/linux/physmem.c +++ b/src/vlib/linux/physmem.c @@ -174,16 +174,8 @@ unix_physmem_region_alloc (vlib_main_t * vm, char *name, u32 size, } } -#if 0 - if ((vpm->flags & VLIB_PHYSMEM_MAIN_F_HAVE_IOMMU) || - (vpm->flags & VLIB_PHYSMEM_MAIN_F_HAVE_PAGEMAP) == 0) - for (i = 0; i < pr->n_pages; i++) - vec_add1 (pr->page_table, pointer_to_uword (pr->mem) + - i * (1 << pr->log2_page_size)); - else -#endif - pr->page_table = clib_mem_vm_get_paddr (pr->mem, pr->log2_page_size, - pr->n_pages); + pr->page_table = clib_mem_vm_get_paddr (pr->mem, pr->log2_page_size, + pr->n_pages); linux_vfio_dma_map_regions (vm); @@ -224,7 +216,6 @@ clib_error_t * unix_physmem_init (vlib_main_t * vm) { vlib_physmem_main_t *vpm = &physmem_main; - linux_vfio_main_t *lvm = &vfio_main; clib_error_t *error = 0; u64 *pt = 0; @@ -241,9 +232,6 @@ unix_physmem_init (vlib_main_t * vm) if ((error = linux_vfio_init (vm))) return error; - if (lvm->flags & LINUX_VFIO_F_HAVE_IOMMU) - vpm->flags |= VLIB_PHYSMEM_MAIN_F_HAVE_IOMMU; - vm->os_physmem_alloc_aligned = unix_physmem_alloc_aligned; vm->os_physmem_free = unix_physmem_free; vm->os_physmem_region_alloc = unix_physmem_region_alloc; diff --git a/src/vlib/linux/vfio.c b/src/vlib/linux/vfio.c index e39bf01fdc0..621dfb2ce01 100644 --- a/src/vlib/linux/vfio.c +++ b/src/vlib/linux/vfio.c @@ -73,7 +73,7 @@ map_regions (vlib_main_t * vm, int fd) int rv; dm.vaddr = pointer_to_uword (pr->mem) + (i << pr->log2_page_size); dm.size = 1 << pr->log2_page_size; - dm.iova = pr->page_table[i]; + dm.iova = dm.vaddr; if ((rv = ioctl (fd, VFIO_IOMMU_MAP_DMA, &dm))) return rv; } @@ -82,30 +82,6 @@ map_regions (vlib_main_t * vm, int fd) return 0; } -static clib_error_t * -scan_vfio_fd (void *arg, u8 * path_name, u8 * file_name) -{ - linux_vfio_main_t *lvm = &vfio_main; - const char fn[] = "/dev/vfio/vfio"; - char buff[sizeof (fn)] = { 0 }; - int fd; - u8 *path = format (0, "%v%c", path_name, 0); - - if (readlink ((char *) path, buff, sizeof (fn)) + 1 != sizeof (fn)) - goto done; - - if (strncmp (fn, buff, sizeof (fn))) - goto done; - - fd = atoi ((char *) file_name); - if (fd != lvm->container_fd) - lvm->ext_container_fd = atoi ((char *) file_name); - -done: - vec_free (path); - return 0; -} - void linux_vfio_dma_map_regions (vlib_main_t * vm) { @@ -113,12 +89,6 @@ linux_vfio_dma_map_regions (vlib_main_t * vm) if (lvm->container_fd != -1) map_regions (vm, lvm->container_fd); - - if (lvm->ext_container_fd == -1) - foreach_directory_file ("/proc/self/fd", scan_vfio_fd, 0, 0); - - if (lvm->ext_container_fd != -1) - map_regions (vm, lvm->ext_container_fd); } static linux_pci_vfio_iommu_group_t * @@ -252,8 +222,6 @@ linux_vfio_init (vlib_main_t * vm) linux_vfio_main_t *lvm = &vfio_main; int fd; - lvm->ext_container_fd = -1; - fd = open ("/dev/vfio/vfio", O_RDWR); /* check if iommu is available */ diff --git a/src/vlib/linux/vfio.h b/src/vlib/linux/vfio.h index 8e0758cf2e4..e23cee19931 100644 --- a/src/vlib/linux/vfio.h +++ b/src/vlib/linux/vfio.h @@ -28,7 +28,6 @@ typedef struct u32 flags; #define LINUX_VFIO_F_HAVE_IOMMU (1 << 0) int container_fd; - int ext_container_fd; /* container fd used by external library, i.e DPDK */ /* VFIO */ int iommu_mode; |