aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIlias Apalodimas <ilias.apalodimas@linaro.org>2017-10-06 13:09:39 +0300
committerIlias Apalodimas <ilias.apalodimas@linaro.org>2017-10-06 13:09:39 +0300
commit5798d785e263d18d62c1e698551a7bc932addca8 (patch)
treee4ccef0488d42b80131167d726ce775c8fc89bc6
parentb53f7b98be89a8c908ce4d87018329b3bb15ab04 (diff)
Managed to map/pin DMA memory
-rw-r--r--.gitignore4
-rw-r--r--README7
-rwxr-xr-xbuild.sh4
-rw-r--r--ether-test.c (renamed from test.c)1
-rw-r--r--vfio-iommu-map-unmap.c161
-rw-r--r--vfio-netem.c26
6 files changed, 185 insertions, 18 deletions
diff --git a/.gitignore b/.gitignore
index f45ab32..8d716c0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,7 +3,9 @@
*.cmd
Module.symvers
modules.order
-test_dma
vfio-netem.mod.c
.tmp_versions/
tags
+ether_test
+map_unmap
+
diff --git a/README b/README
index a62cce1..ff0b8ac 100644
--- a/README
+++ b/README
@@ -20,3 +20,10 @@ sudo ./pcimem /sys/devices/pci0000:00/0000:00:1c.3/0000:04:00.0/resource2 0 w
sudo ./pcimem /sys/devices/pci0000:00/0000:00:1c.3/0000:04:00.0/resource4 16368 w
run ./test_dma
+
+# Enable kernel debug
+echo file drivers/iommu/iommu.c line 1533-1600 +p > /sys/kernel/debug/dynamic_debug/control
+or
+echo file drivers/iommu/iommu.c func iommu_map +p > /sys/kernel/debug/dynamic_debug/control
+or
+echo file drivers/iommu/iommu.c +p > /sys/kernel/debug/dynamic_debug/control
diff --git a/build.sh b/build.sh
index 2053d28..54ef7e7 100755
--- a/build.sh
+++ b/build.sh
@@ -2,7 +2,9 @@
what=$1
if [ -n "$1" -a "$1" = 'clean' ]; then
make -C /lib/modules/`uname -r`/build M=`pwd` modules clean
+ rm map_unmap ether_test -f
else
make -C /lib/modules/`uname -r`/build M=`pwd` modules
- gcc test.c -o test_dma -Werror -Wall -Wunused -O2
+ gcc ether-test.c -o ether_test -Werror -Wall -Wunused -O2
+ gcc vfio-iommu-map-unmap.c -o map_unmap -Werror -Wall -Wunused -O2
fi
diff --git a/test.c b/ether-test.c
index 764b8d3..002aaf6 100644
--- a/test.c
+++ b/ether-test.c
@@ -13,6 +13,7 @@
#include "reg_api.h"
const char glob_uuid[] = "d0b24768-9c51-11e7-8de5-c7b0c2769e69";
+/* iommu alignment */
#define TEST_SIZE 1024 * 1024
#define EOR (1 << 30)
#define OWN (1 << 31)
diff --git a/vfio-iommu-map-unmap.c b/vfio-iommu-map-unmap.c
new file mode 100644
index 0000000..a5d5c46
--- /dev/null
+++ b/vfio-iommu-map-unmap.c
@@ -0,0 +1,161 @@
+#include <errno.h>
+#include <libgen.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <linux/ioctl.h>
+#include <linux/vfio.h>
+
+#define MAP_SIZE (1UL * 1024 * 1024 * 1024)
+#define MAP_CHUNK (4 * 1024)
+#define REALLOC_INTERVAL 30
+
+void usage(char *name)
+{
+ printf("usage: %s <group id> <allocs> \n", name);
+}
+
+int main(int argc, char **argv)
+{
+ int ret, container, group;
+ char path[64];
+ unsigned long i, count, max;
+ void **maps;
+ struct vfio_group_status group_status = {
+ .argsz = sizeof(group_status)
+ };
+ struct vfio_iommu_type1_dma_map dma_map = {
+ .argsz = sizeof(dma_map)
+ };
+ struct vfio_iommu_type1_dma_unmap dma_unmap = {
+ .argsz = sizeof(dma_unmap)
+ };
+
+ if (argc != 3) {
+ usage(argv[0]);
+ return -1;
+ }
+
+ container = open("/dev/vfio/vfio", O_RDWR);
+ if (container < 0) {
+ printf("Failed to open /dev/vfio/vfio, %d (%s)\n",
+ container, strerror(errno));
+ return container;
+ }
+
+ snprintf(path, sizeof(path), "/dev/vfio/%d", atoi(argv[1]));
+ group = open(path, O_RDWR);
+ if (group < 0) {
+ printf("Failed to open %s, %d (%s)\n",
+ path, group, strerror(errno));
+ return group;
+ }
+ max = atoi(argv[2]);
+
+ ret = ioctl(group, VFIO_GROUP_GET_STATUS, &group_status);
+ if (ret) {
+ printf("ioctl(VFIO_GROUP_GET_STATUS) failed\n");
+ return ret;
+ }
+
+ if (!(group_status.flags & VFIO_GROUP_FLAGS_VIABLE)) {
+ printf("Group not viable, are all devices attached to vfio?\n");
+ return -1;
+ }
+
+ ret = ioctl(group, VFIO_GROUP_SET_CONTAINER, &container);
+ if (ret) {
+ printf("Failed to set group container\n");
+ return ret;
+ }
+
+ ret = ioctl(container, VFIO_SET_IOMMU, VFIO_TYPE1_IOMMU);
+ if (ret) {
+ printf("Failed to set IOMMU\n");
+ return ret;
+ }
+
+ /* Test code */
+ dma_map.flags = VFIO_DMA_MAP_FLAG_READ | VFIO_DMA_MAP_FLAG_WRITE;
+ dma_map.size = MAP_CHUNK;
+ dma_unmap.size = MAP_SIZE;
+ dma_unmap.iova = 0;
+
+ /* Track our mmaps for re-use */
+ maps = malloc(sizeof(void *) * (MAP_SIZE/dma_map.size));
+ if (!maps) {
+ printf("Failed to allocate map (%s)\n", strerror(errno));
+ return -1;
+ }
+
+ memset(maps, 0, sizeof(void *) * (MAP_SIZE/dma_map.size));
+
+ for (count = 0; count < max; count++) {
+
+ /* Every REALLOC_INTERVAL, dump our mappings to give THP something to collapse */
+ if (count % REALLOC_INTERVAL == 0) {
+ for (i = 0; i < MAP_SIZE/dma_map.size; i++) {
+ if (maps[i]) {
+ munmap(maps[i], dma_map.size);
+ maps[i] = NULL;
+ }
+ }
+ if (count) {
+ printf("\t%ld\n", count);
+ //return 0;
+ }
+ printf("|");
+ fflush(stdout);
+ }
+
+ /* Map MAP_CHUNK at a time, each chunk is pinned on map, so THP can't do anything until unmap */
+ for (i = dma_map.iova = 0; i < MAP_SIZE/dma_map.size; i++, dma_map.iova += dma_map.size) {
+ if (!maps[i]) {
+ maps[i] = mmap(NULL, dma_map.size,
+ PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ if (maps[i] == MAP_FAILED) {
+ printf("Failed to mmap memory (%s)\n", strerror(errno));
+ return -1;
+ }
+ }
+
+ ret = madvise(maps[i], dma_map.size, MADV_HUGEPAGE);
+ if (ret) {
+ printf("Madvise failed (%s)\n", strerror(errno));
+ }
+
+ dma_map.vaddr = (unsigned long)maps[i];
+
+ ret = ioctl(container, VFIO_IOMMU_MAP_DMA, &dma_map);
+ if (ret) {
+ printf("Failed to map memory (%s)\n",
+ strerror(errno));
+ return ret;
+ }
+ }
+
+ printf("+");
+ fflush(stdout);
+
+ /* Unmap everything at once */
+ ret = ioctl(container, VFIO_IOMMU_UNMAP_DMA, &dma_unmap);
+ if (ret) {
+ printf("Failed to unmap memory (%s)\n", strerror(errno));
+ return ret;
+ }
+
+ printf("-");
+ fflush(stdout);
+ }
+ printf("\n");
+
+ return 0;
+}
diff --git a/vfio-netem.c b/vfio-netem.c
index 2083007..97ff951 100644
--- a/vfio-netem.c
+++ b/vfio-netem.c
@@ -138,19 +138,16 @@ static const struct attribute_group *vfio_attr_groups[] = {
static int vfio_net_create(struct kobject *kobj, struct mdev_device *mdev)
{
- struct device *dev = mdev_parent_dev(mdev);
- //struct iommu_domain *domain;
-
- dev_info(dev, "MDEV-NETEM: Create on parent\n");
- //domain = iommu_get_domain_for_dev(dev);
- //if (domain)
- //iommu_detach_device(domain, dev);
- if (dev && dev->driver && dev->driver->name)
- printk("AA %s\n", dev->driver->name);
+ struct device *dev = mdev_parent_dev(mdev);
+ struct iommu_domain *domain;
- if (dev->parent && dev->parent->driver && dev->parent->driver->name)
- printk("BB %s\n", dev->parent->driver->name);
+ dev_info(dev, "MDEV-NETEM: Create mdev for %s\n", dev_name(dev));
+ domain = iommu_get_domain_for_dev(dev->parent->parent->parent);
+ if (domain) {
+ printk("AA Detach domain\n");
+ iommu_detach_device(domain, dev->parent->parent->parent);
+ }
/* Inherit parent's iommu_ops */
if (dev && dev->parent && dev->parent->bus &&
@@ -158,7 +155,8 @@ static int vfio_net_create(struct kobject *kobj, struct mdev_device *mdev)
mdev->dev.bus->iommu_ops = dev->parent->bus->iommu_ops;
//XXX dont do that
//mdev->dev.iommu_group = dev->parent->iommu_group;
- dev_info(dev, "MDEV-NETEM: Set mdev iommu_ops\n");
+ dev_info(dev, "MDEV-NETEM: Inherit %s iommu_ops\n",
+ dev_name(dev->parent));
}
return 0;
@@ -338,9 +336,6 @@ 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",
- pdev->driver->name);
return err;
@@ -351,7 +346,6 @@ out_inv_dev:
void vfio_vring_destroy(struct device *dev)
{
- dev_info(dev, "MDEV-NETEM: Unregistering\n");
mdev_unregister_device(dev);
}