From 476d2f1d4c03be3a8fb6eecbb5d92ffac59fe783 Mon Sep 17 00:00:00 2001 From: Ilias Apalodimas Date: Thu, 21 Sep 2017 14:19:13 +0300 Subject: Fucntions for mapping/unmapping DMA buffers --- test.c | 122 +++++++++++++++++++++++++++++++++++++++-------------------- vfio-netem.c | 15 ++++++-- 2 files changed, 93 insertions(+), 44 deletions(-) diff --git a/test.c b/test.c index 974df08..704aba4 100644 --- a/test.c +++ b/test.c @@ -14,17 +14,83 @@ const char glob_uuid[] = "d0b24768-9c51-11e7-8de5-c7b0c2769e69"; #define TEST_SIZE 1024 * 1024 +/* + * @fd: container fd + * @sz: requested size + * @vaddr: virtual address + */ +int dma_map_type1(int fd, unsigned long sz, void *vaddr) +{ + int ret; + struct vfio_iommu_type1_dma_map dma_map; + + /* Allocate some space and setup a DMA mapping */ + vaddr = mmap(NULL, (size_t)sz, PROT_READ, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (vaddr == MAP_FAILED) { + printf("Failed to map memory\n"); + return -ENOMEM; + } + + memset(&dma_map, 0, sizeof(dma_map)); + dma_map.argsz = sizeof(dma_map); + dma_map.vaddr = (unsigned long)vaddr; + dma_map.size = sz; + dma_map.iova = 0; + dma_map.flags = VFIO_DMA_MAP_FLAG_READ | VFIO_DMA_MAP_FLAG_WRITE; + + ret = ioctl(fd, VFIO_IOMMU_MAP_DMA, &dma_map); + if (ret) + printf("Failed to map DMA memory (%s)\n", strerror(errno)); + + return ret; +} + +int dma_unmap_type1(int fd, unsigned long sz, void *vaddr) +{ + int ret; + struct vfio_iommu_type1_dma_unmap dma_unmap; + + memset(&dma_unmap, 0, sizeof(dma_unmap)); + dma_unmap.argsz = sizeof(dma_unmap); + dma_unmap.size = sz; + dma_unmap.iova = 0; + ret = ioctl(fd, VFIO_IOMMU_UNMAP_DMA, &dma_unmap); + if (ret) + printf("Failed to unmap DMA memory (%s)\n", strerror(errno)); + + ret = munmap(vaddr, (size_t)sz); + if (vaddr == MAP_FAILED) { + printf("Failed to unmap memory\n"); + return -ENOMEM; + } + + return ret; +} + +int rtl_8169_remap(void) +{ +#if 0 + if (i == 2) { + ((uint8_t *)map)[80] = 0xc0; + dma_map_type1(container, TEST_SIZE, &vaddr); + + ((uint64_t *)map)[32] = (unsigned long)&vaddr; + //dma_unmap_type1(container, TEST_SIZE, &vaddr); + } +#endif + return 0; +} + +#define DBG int main(int argc, char* argv[]) { - int container, group, device, i, ret; + int container, group, device, i; struct vfio_group_status group_status = { .argsz = sizeof(group_status) }; struct vfio_device_info device_info = { .argsz = sizeof(device_info) }; struct vfio_iommu_type1_info iommu_info = { .argsz = sizeof(iommu_info) }; struct vfio_region_info region_info = { .argsz = sizeof(region_info) }; - struct vfio_iommu_type1_dma_map dma_map = { .argsz = sizeof(dma_map) }; - struct vfio_iommu_type1_dma_unmap dma_unmap = { .argsz = sizeof(dma_unmap) }; void *map; - size_t sz; /* Create a new container */ container = open("/dev/vfio/vfio", O_RDWR); @@ -77,24 +143,30 @@ int main(int argc, char* argv[]) continue; } - printf("Region:%d size %lu, offset 0x%lx, flags 0x%x\n", i, - (unsigned long)region_info.size, - (unsigned long)region_info.offset, region_info.flags); + printf("## Region:%d size %lu, offset 0x%lx, flags 0x%x ##\n", + i, (unsigned long)region_info.size, + (unsigned long)region_info.offset, region_info.flags); if (region_info.flags & VFIO_REGION_INFO_FLAG_MMAP) { - int j; map = mmap(NULL, (size_t)region_info.size, - PROT_READ, MAP_SHARED, device, + PROT_READ | PROT_WRITE, MAP_SHARED, device, (off_t)region_info.offset); if (map == MAP_FAILED) { printf("mmap failed\n"); continue; } +#ifdef DBG + int j; + size_t sz; sz = region_info.size / sizeof(uint32_t *); for (j = 0; j < sz; j++) { - printf("%08x\n", ((uint32_t *)map)[j]); + if (!(j % 8) && j != 0) + printf("\n"); + + printf("%08x ", ((uint32_t *)map)[j]); } printf("\n"); +#endif /* fwrite(map, 1, region_info.size > 16 ? 16 : region_info.size, stdout); @@ -103,38 +175,8 @@ int main(int argc, char* argv[]) munmap(map, (size_t)region_info.size); } } - /* sample DMA mapping */ - /* Allocate some space and setup a DMA mapping */ - map = mmap(NULL, TEST_SIZE, PROT_READ, - MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); - if (map == MAP_FAILED) { - printf("Failed to allocate memory\n"); - goto out; - } - - dma_map.vaddr = (unsigned long)map; - dma_map.flags = VFIO_DMA_MAP_FLAG_READ; - dma_map.size = TEST_SIZE; - dma_map.iova = 0; - ret = ioctl(container, VFIO_IOMMU_MAP_DMA, &dma_map); - if (ret) { - printf("Failed to map memory (%s)\n", strerror(errno)); - goto out; - } - printf("DMA Mapping: ["); - fwrite(map, 1, region_info.size, stdout); - printf("]\n"); - /* unmap */ - dma_unmap.size = dma_map.size; - dma_unmap.iova = 0; - ret = ioctl(container, VFIO_IOMMU_UNMAP_DMA, &dma_unmap); - if (ret) { - printf("Failed to unmap memory (%s)\n", strerror(errno)); - goto out; - } return 0; - out: return -1; } diff --git a/vfio-netem.c b/vfio-netem.c index 183b375..324c80c 100644 --- a/vfio-netem.c +++ b/vfio-netem.c @@ -207,7 +207,7 @@ static long vfio_net_ioctl(struct mdev_device *mdev, unsigned int cmd, return -EINVAL; info.flags = VFIO_DEVICE_FLAGS_PCI; - /* info.flags |= VFIO_DEVICE_FLAGS_RESET; */ + info.flags |= VFIO_DEVICE_FLAGS_RESET; info.num_regions = VFIO_PCI_NUM_REGIONS; info.num_irqs = 1; @@ -241,7 +241,7 @@ static long vfio_net_ioctl(struct mdev_device *mdev, unsigned int cmd, info.flags = VFIO_REGION_INFO_FLAG_READ | VFIO_REGION_INFO_FLAG_WRITE; - /* FIXME this isn't always the case vfio-pci has checks */ + /* FIXME not all BARS are not mappable */ info.flags |= VFIO_REGION_INFO_FLAG_MMAP; #if 0 if (vdev->bar_mmap_supported[info.index]) { @@ -259,10 +259,17 @@ static long vfio_net_ioctl(struct mdev_device *mdev, unsigned int cmd, } return copy_to_user((void __user *)arg, &info, minsz) ? - -EFAULT : 0; + -EFAULT : 0; + } else if (cmd == VFIO_DEVICE_RESET) { + /* + * FIXME check if hardware supports this before blindly + * resetting + */ + return pci_try_reset_function(pdev); } + return 0; } @@ -301,7 +308,7 @@ int vfio_vring_init(struct device *dev) err = mdev_register_device(dev, &vfio_net_ops); if (!err) - dev_info(dev, "MDEV-NETEM: Register for driver%s", + dev_info(dev, "MDEV-NETEM: Register for driver %s", pdev->driver->name); return err; -- cgit v1.2.3