diff options
Diffstat (limited to 'src/vlib')
-rw-r--r-- | src/vlib/linux/pci.c | 39 | ||||
-rw-r--r-- | src/vlib/linux/vfio.c | 56 | ||||
-rw-r--r-- | src/vlib/linux/vfio.h | 2 |
3 files changed, 77 insertions, 20 deletions
diff --git a/src/vlib/linux/pci.c b/src/vlib/linux/pci.c index 722fb888117..168acde7288 100644 --- a/src/vlib/linux/pci.c +++ b/src/vlib/linux/pci.c @@ -966,13 +966,7 @@ add_device_vfio (vlib_main_t * vm, linux_pci_device_t * p, goto error; } - pci_log_debug (vm, p, "%s region_info index:%u size:0x%lx offset:0x%lx " - "flags: %s%s%s(0x%x)", __func__, - reg.index, reg.size, reg.offset, - reg.flags & VFIO_REGION_INFO_FLAG_READ ? "rd " : "", - reg.flags & VFIO_REGION_INFO_FLAG_WRITE ? "wr " : "", - reg.flags & VFIO_REGION_INFO_FLAG_MMAP ? "mmap " : "", - reg.flags); + pci_log_debug (vm, p, "%s %U", __func__, format_vfio_region_info, ®); p->config_offset = reg.offset; p->config_fd = p->fd; @@ -1087,23 +1081,28 @@ vlib_pci_region (vlib_main_t * vm, vlib_pci_dev_handle_t h, u32 bar, int *fd, } else if (p->type == LINUX_PCI_DEVICE_TYPE_VFIO) { - struct vfio_region_info reg = { 0 }; - reg.argsz = sizeof (struct vfio_region_info); - reg.index = bar; - if (ioctl (p->fd, VFIO_DEVICE_GET_REGION_INFO, ®) < 0) + struct vfio_region_info *r; + u32 sz = sizeof (struct vfio_region_info); + again: + r = clib_mem_alloc (sz); + clib_memset (r, 0, sz); + r->argsz = sz; + r->index = bar; + if (ioctl (p->fd, VFIO_DEVICE_GET_REGION_INFO, r) < 0) return clib_error_return_unix (0, "ioctl(VFIO_DEVICE_GET_INFO) " "'%U'", format_vlib_pci_addr, &p->addr); + if (sz != r->argsz) + { + sz = r->argsz; + clib_mem_free (r); + goto again; + } _fd = p->fd; - _size = reg.size; - _offset = reg.offset; - pci_log_debug (vm, p, "%s region_info index:%u size:0x%lx offset:0x%lx " - "flags: %s%s%s(0x%x)", __func__, - reg.index, reg.size, reg.offset, - reg.flags & VFIO_REGION_INFO_FLAG_READ ? "rd " : "", - reg.flags & VFIO_REGION_INFO_FLAG_WRITE ? "wr " : "", - reg.flags & VFIO_REGION_INFO_FLAG_MMAP ? "mmap " : "", - reg.flags); + _size = r->size; + _offset = r->offset; + pci_log_debug (vm, p, "%s %U", __func__, format_vfio_region_info, r); + clib_mem_free (r); } else ASSERT (0); diff --git a/src/vlib/linux/vfio.c b/src/vlib/linux/vfio.c index 1ed99ceee55..33de135965b 100644 --- a/src/vlib/linux/vfio.c +++ b/src/vlib/linux/vfio.c @@ -246,6 +246,62 @@ linux_vfio_init (vlib_main_t * vm) return 0; } +u8 * +format_vfio_region_info (u8 * s, va_list * args) +{ + struct vfio_region_info *r = va_arg (*args, struct vfio_region_info *); + + s = format (s, "region_info index:%u size:0x%lx offset:0x%lx flags:", + r->index, r->size, r->offset); + + if (r->flags & VFIO_REGION_INFO_FLAG_READ) + s = format (s, " rd"); + + if (r->flags & VFIO_REGION_INFO_FLAG_WRITE) + s = format (s, " wr"); + + if (r->flags & VFIO_REGION_INFO_FLAG_MMAP) + s = format (s, " mmap"); + +#ifdef VFIO_REGION_INFO_FLAG_CAPS + if (r->flags & VFIO_REGION_INFO_FLAG_CAPS) + s = format (s, " caps"); +#endif + + s = format (s, " (0x%x)", r->flags); + +#ifdef VFIO_REGION_INFO_FLAG_CAPS + u32 cap_offset; + + if ((r->flags & VFIO_REGION_INFO_FLAG_CAPS) == 0) + return s; + + s = format (s, "\n caps:"); + cap_offset = r->cap_offset; + + do + { + struct vfio_info_cap_header *cap = (void *) r + cap_offset; +#ifdef VFIO_REGION_INFO_CAP_SPARSE_MMAP + if (cap->id == VFIO_REGION_INFO_CAP_SPARSE_MMAP) + s = format (s, " sparse-mmap"); +#endif +#ifdef VFIO_REGION_INFO_CAP_TYPE + if (cap->id == VFIO_REGION_INFO_CAP_TYPE) + s = format (s, " type"); +#endif +#ifdef VFIO_REGION_INFO_CAP_MSIX_MAPPABLE + if (cap->id == VFIO_REGION_INFO_CAP_MSIX_MAPPABLE) + s = format (s, " msix-mappable"); +#endif + cap_offset = cap->next; + } + while (cap_offset); +#endif + + return s; +} + /* * fd.io coding-style-patch-verification: ON * diff --git a/src/vlib/linux/vfio.h b/src/vlib/linux/vfio.h index c1d815664c9..fe4f0f75346 100644 --- a/src/vlib/linux/vfio.h +++ b/src/vlib/linux/vfio.h @@ -49,6 +49,8 @@ clib_error_t *vfio_map_physmem_page (vlib_main_t * vm, void *addr); clib_error_t *linux_vfio_group_get_device_fd (vlib_pci_addr_t * addr, int *fd, int *is_noiommu); +format_function_t format_vfio_region_info; + #endif /* included_vlib_linux_vfio_h */ |