X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvlib%2Flinux%2Fvfio.c;h=53eed8bfbe97dfc71da60119125f74487bf6fb4d;hb=7d426535b4e98731193cc0265b83f2336dcdf5b3;hp=dffe49ce7b268950d3d366bd648c6b8259b8e482;hpb=1ba0fa4bfa3dcc9bd754b8b0b6a7c5045f9ba0dd;p=vpp.git diff --git a/src/vlib/linux/vfio.c b/src/vlib/linux/vfio.c index dffe49ce7b2..53eed8bfbe9 100644 --- a/src/vlib/linux/vfio.c +++ b/src/vlib/linux/vfio.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016 Cisco and/or its affiliates. + * Copyright (c) 2018 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -12,30 +12,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/* - * pci.c: Linux user space PCI bus management. - * - * Copyright (c) 2008 Eliot Dresselhaus - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ #include #include @@ -52,12 +28,17 @@ #include #include +#ifndef VFIO_NOIOMMU_IOMMU +#define VFIO_NOIOMMU_IOMMU 8 +#endif + linux_vfio_main_t vfio_main; static int map_regions (vlib_main_t * vm, int fd) { - vlib_physmem_main_t *vpm = &vm->physmem_main; + vlib_physmem_main_t *vpm = &physmem_main; + linux_vfio_main_t *lvm = &vfio_main; vlib_physmem_region_t *pr; struct vfio_iommu_type1_dma_map dm = { 0 }; int i; @@ -73,39 +54,24 @@ 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; + vlib_log_debug (lvm->log_default, "map DMA va:0x%lx iova:%lx " + "size:0x%lx", dm.vaddr, dm.iova, dm.size); + if ((rv = ioctl (fd, VFIO_IOMMU_MAP_DMA, &dm))) - return rv; + { + vlib_log_err (lvm->log_default, "map DMA va:0x%lx iova:%lx " + "size:0x%lx failed, error %s (errno %d)", + dm.vaddr, dm.iova, dm.size, strerror (errno), + errno); + return rv; + } } }); /* *INDENT-ON* */ 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 +79,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 * @@ -133,7 +93,7 @@ get_vfio_iommu_group (int group) } static clib_error_t * -open_vfio_iommu_group (int group) +open_vfio_iommu_group (int group, int is_noiommu) { linux_vfio_main_t *lvm = &vfio_main; linux_pci_vfio_iommu_group_t *g; @@ -148,7 +108,7 @@ open_vfio_iommu_group (int group) g->refcnt++; return 0; } - s = format (s, "/dev/vfio/%u%c", group, 0); + s = format (s, "/dev/vfio/%s%u%c", is_noiommu ? "noiommu-" : "", group, 0); fd = open ((char *) s, O_RDWR); if (fd < 0) return clib_error_return_unix (0, "open '%s'", s); @@ -178,13 +138,17 @@ open_vfio_iommu_group (int group) if (lvm->iommu_mode == 0) { - if (ioctl (lvm->container_fd, VFIO_SET_IOMMU, VFIO_TYPE1_IOMMU) < 0) + if (is_noiommu) + lvm->iommu_mode = VFIO_NOIOMMU_IOMMU; + else + lvm->iommu_mode = VFIO_TYPE1_IOMMU; + + if (ioctl (lvm->container_fd, VFIO_SET_IOMMU, lvm->iommu_mode) < 0) { err = clib_error_return_unix (0, "ioctl(VFIO_SET_IOMMU) " "'/dev/vfio/vfio'"); goto error; } - lvm->iommu_mode = VFIO_TYPE1_IOMMU; } @@ -208,6 +172,7 @@ linux_vfio_group_get_device_fd (vlib_pci_addr_t * addr, int *fdp) int iommu_group; u8 *tmpstr; int fd; + int is_noiommu = 0; s = format (s, "/sys/bus/pci/devices/%U/iommu_group", format_vlib_pci_addr, addr); @@ -225,7 +190,20 @@ linux_vfio_group_get_device_fd (vlib_pci_addr_t * addr, int *fdp) } vec_reset_length (s); - if ((err = open_vfio_iommu_group (iommu_group))) + s = + format (s, "/sys/bus/pci/devices/%U/iommu_group/name", + format_vlib_pci_addr, addr); + err = clib_sysfs_read ((char *) s, "%s", &tmpstr); + if (err == 0) + { + if (strncmp ((char *) tmpstr, "vfio-noiommu", 12) == 0) + is_noiommu = 1; + vec_free (tmpstr); + } + else + clib_error_free (err); + vec_reset_length (s); + if ((err = open_vfio_iommu_group (iommu_group, is_noiommu))) return err; g = get_vfio_iommu_group (iommu_group); @@ -252,7 +230,7 @@ linux_vfio_init (vlib_main_t * vm) linux_vfio_main_t *lvm = &vfio_main; int fd; - lvm->ext_container_fd = -1; + lvm->log_default = vlib_log_register_class ("vfio", 0); fd = open ("/dev/vfio/vfio", O_RDWR); @@ -264,8 +242,19 @@ linux_vfio_init (vlib_main_t * vm) close (fd); fd = -1; } - else if (ioctl (fd, VFIO_CHECK_EXTENSION, VFIO_TYPE1_IOMMU) == 1) - lvm->flags |= LINUX_VFIO_F_HAVE_IOMMU; + else + { + if (ioctl (fd, VFIO_CHECK_EXTENSION, VFIO_TYPE1_IOMMU) == 1) + { + lvm->flags |= LINUX_VFIO_F_HAVE_IOMMU; + vlib_log_info (lvm->log_default, "type 1 IOMMU mode supported"); + } + if (ioctl (fd, VFIO_CHECK_EXTENSION, VFIO_NOIOMMU_IOMMU) == 1) + { + lvm->flags |= LINUX_VFIO_F_HAVE_NOIOMMU; + vlib_log_info (lvm->log_default, "NOIOMMU mode supported"); + } + } } lvm->iommu_pool_index_by_group = hash_create (0, sizeof (uword));