DPDK patches and discussions
 help / color / mirror / Atom feed
From: Anatoly Burakov <anatoly.burakov@intel.com>
To: dev@dpdk.org
Cc: andras.kovacs@ericsson.com, laszlo.vadkeri@ericsson.com,
	keith.wiles@intel.com, benjamin.walker@intel.com,
	bruce.richardson@intel.com, thomas@monjalon.net,
	Pawel Wodkowski <pawelx.wodkowski@intel.com>
Subject: [dpdk-dev] [PATCH 22/23] vfio: allow to map other memory regions
Date: Tue, 19 Dec 2017 11:04:55 +0000	[thread overview]
Message-ID: <2d5b9ea71a32658efa24766933d07b5d2e29f25f.1513680516.git.anatoly.burakov@intel.com> (raw)
In-Reply-To: <cover.1513680516.git.anatoly.burakov@intel.com>
In-Reply-To: <cover.1513680516.git.anatoly.burakov@intel.com>

Currently it is not possible to use memory that is not owned by DPDK to
perform DMA. This scenarion might be used in vhost applications (like
SPDK) where guest send its own memory table. To fill this gap provide
API to allow registering arbitrary address in VFIO container.

Signed-off-by: Pawel Wodkowski <pawelx.wodkowski@intel.com>
Signed-off-by: Anatoly Burakov <anatoly.burakov@intel.com>
---
 lib/librte_eal/linuxapp/eal/eal_vfio.c | 150 ++++++++++++++++++++++++++++-----
 lib/librte_eal/linuxapp/eal/eal_vfio.h |  11 +++
 2 files changed, 140 insertions(+), 21 deletions(-)

diff --git a/lib/librte_eal/linuxapp/eal/eal_vfio.c b/lib/librte_eal/linuxapp/eal/eal_vfio.c
index 09dfc68..15d28ad 100644
--- a/lib/librte_eal/linuxapp/eal/eal_vfio.c
+++ b/lib/librte_eal/linuxapp/eal/eal_vfio.c
@@ -40,6 +40,7 @@
 #include <rte_memory.h>
 #include <rte_eal_memconfig.h>
 #include <rte_vfio.h>
+#include <rte_iommu.h>
 
 #include "eal_filesystem.h"
 #include "eal_vfio.h"
@@ -51,17 +52,35 @@
 static struct vfio_config vfio_cfg;
 
 static int vfio_type1_dma_map(int);
+static int vfio_type1_dma_mem_map(int, uint64_t, uint64_t, uint64_t, int);
 static int vfio_spapr_dma_map(int);
 static int vfio_noiommu_dma_map(int);
+static int vfio_noiommu_dma_mem_map(int, uint64_t, uint64_t, uint64_t, int);
 
 /* IOMMU types we support */
 static const struct vfio_iommu_type iommu_types[] = {
 	/* x86 IOMMU, otherwise known as type 1 */
-	{ RTE_VFIO_TYPE1, "Type 1", &vfio_type1_dma_map},
+	{
+		.type_id = RTE_VFIO_TYPE1,
+		.name = "Type 1",
+		.dma_map_func = &vfio_type1_dma_map,
+		.dma_user_map_func = &vfio_type1_dma_mem_map
+	},
 	/* ppc64 IOMMU, otherwise known as spapr */
-	{ RTE_VFIO_SPAPR, "sPAPR", &vfio_spapr_dma_map},
+	{
+		.type_id = RTE_VFIO_SPAPR,
+		.name = "sPAPR",
+		.dma_map_func = &vfio_spapr_dma_map,
+		.dma_user_map_func = NULL
+		// TODO: work with PPC64 people on enabling this, window size!
+	},
 	/* IOMMU-less mode */
-	{ RTE_VFIO_NOIOMMU, "No-IOMMU", &vfio_noiommu_dma_map},
+	{
+		.type_id = RTE_VFIO_NOIOMMU,
+		.name = "No-IOMMU",
+		.dma_map_func = &vfio_noiommu_dma_map,
+		.dma_user_map_func = &vfio_noiommu_dma_mem_map
+	},
 };
 
 int
@@ -362,9 +381,10 @@ rte_vfio_setup_device(const char *sysfs_base, const char *dev_addr,
 		 */
 		if (internal_config.process_type == RTE_PROC_PRIMARY &&
 				vfio_cfg.vfio_active_groups == 1) {
+			const struct vfio_iommu_type *t;
+
 			/* select an IOMMU type which we will be using */
-			const struct vfio_iommu_type *t =
-				vfio_set_iommu_type(vfio_cfg.vfio_container_fd);
+			t = vfio_set_iommu_type(vfio_cfg.vfio_container_fd);
 			if (!t) {
 				RTE_LOG(ERR, EAL,
 					"  %s failed to select IOMMU type\n",
@@ -382,6 +402,8 @@ rte_vfio_setup_device(const char *sysfs_base, const char *dev_addr,
 				clear_group(vfio_group_fd);
 				return -1;
 			}
+
+			vfio_cfg.vfio_iommu_type = t;
 		}
 	}
 
@@ -694,13 +716,52 @@ vfio_get_group_no(const char *sysfs_base,
 }
 
 static int
+vfio_type1_dma_mem_map(int vfio_container_fd, uint64_t vaddr, uint64_t iova,
+		uint64_t len, int do_map)
+{
+	struct vfio_iommu_type1_dma_map dma_map;
+	struct vfio_iommu_type1_dma_unmap dma_unmap;
+	int ret;
+
+	if (do_map != 0) {
+		memset(&dma_map, 0, sizeof(dma_map));
+		dma_map.argsz = sizeof(struct vfio_iommu_type1_dma_map);
+		dma_map.vaddr = vaddr;
+		dma_map.size = len;
+		dma_map.iova = iova;
+		dma_map.flags = VFIO_DMA_MAP_FLAG_READ | VFIO_DMA_MAP_FLAG_WRITE;
+
+		ret = ioctl(vfio_container_fd, VFIO_IOMMU_MAP_DMA, &dma_map);
+		if (ret) {
+			RTE_LOG(ERR, EAL, "  cannot set up DMA remapping, error %i (%s)\n",
+				errno, strerror(errno));
+				return -1;
+		}
+
+	} else {
+		memset(&dma_unmap, 0, sizeof(dma_unmap));
+		dma_unmap.argsz = sizeof(struct vfio_iommu_type1_dma_unmap);
+		dma_unmap.size = len;
+		dma_unmap.iova = iova;
+
+		ret = ioctl(vfio_container_fd, VFIO_IOMMU_UNMAP_DMA, &dma_unmap);
+		if (ret) {
+			RTE_LOG(ERR, EAL, "  cannot clear DMA remapping, error %i (%s)\n",
+					errno, strerror(errno));
+			return -1;
+		}
+	}
+
+	return 0;
+}
+
+static int
 vfio_type1_dma_map(int vfio_container_fd)
 {
-	int i, ret;
+	int i;
 
 	/* map all DPDK segments for DMA. use 1:1 PA to IOVA mapping */
 	for (i = 0; i < RTE_MAX_MEMSEG_LISTS; i++) {
-		struct vfio_iommu_type1_dma_map dma_map;
 		const struct rte_memseg_list *msl;
 		const struct rte_fbarray *arr;
 		int ms_idx, next_idx;
@@ -727,21 +788,9 @@ vfio_type1_dma_map(int vfio_container_fd)
 			len = ms->hugepage_sz;
 			hw_addr = ms->iova;
 
-			memset(&dma_map, 0, sizeof(dma_map));
-			dma_map.argsz = sizeof(struct vfio_iommu_type1_dma_map);
-			dma_map.vaddr = addr;
-			dma_map.size = len;
-			dma_map.iova = hw_addr;
-			dma_map.flags = VFIO_DMA_MAP_FLAG_READ | VFIO_DMA_MAP_FLAG_WRITE;
-
-			ret = ioctl(vfio_container_fd, VFIO_IOMMU_MAP_DMA, &dma_map);
-
-			if (ret) {
-				RTE_LOG(ERR, EAL, "  cannot set up DMA remapping, "
-						  "error %i (%s)\n", errno,
-						  strerror(errno));
+			if (vfio_type1_dma_mem_map(vfio_container_fd, addr,
+					hw_addr, len, 1))
 				return -1;
-			}
 		}
 	}
 
@@ -892,6 +941,49 @@ vfio_noiommu_dma_map(int __rte_unused vfio_container_fd)
 	return 0;
 }
 
+static int
+vfio_noiommu_dma_mem_map(int __rte_unused vfio_container_fd,
+			 uint64_t __rte_unused vaddr,
+			 uint64_t __rte_unused iova, uint64_t __rte_unused len,
+			 int __rte_unused do_map)
+{
+	/* No-IOMMU mode does not need DMA mapping */
+	return 0;
+}
+
+static int
+vfio_dma_mem_map(uint64_t vaddr, uint64_t iova, uint64_t len, int do_map)
+{
+	const struct vfio_iommu_type *t = vfio_cfg.vfio_iommu_type;
+
+	if (!t) {
+		RTE_LOG(ERR, EAL, "  VFIO support not initialized\n");
+		return -1;
+	}
+
+	if (!t->dma_user_map_func) {
+		RTE_LOG(ERR, EAL,
+			"  VFIO custom DMA region maping not supported by IOMMU %s\n",
+			t->name);
+		return -1;
+	}
+
+	return t->dma_user_map_func(vfio_cfg.vfio_container_fd, vaddr, iova,
+			len, do_map);
+}
+
+int
+rte_iommu_dma_map(uint64_t vaddr, uint64_t iova, uint64_t len)
+{
+	return vfio_dma_mem_map(vaddr, iova, len, 1);
+}
+
+int
+rte_iommu_dma_unmap(uint64_t vaddr, uint64_t iova, uint64_t len)
+{
+	return vfio_dma_mem_map(vaddr, iova, len, 0);
+}
+
 int
 rte_vfio_noiommu_is_enabled(void)
 {
@@ -911,4 +1003,20 @@ rte_vfio_noiommu_is_enabled(void)
 	return ret;
 }
 
+#else
+
+int
+rte_iommu_dma_map(uint64_t __rte_unused vaddr, __rte_unused uint64_t iova,
+		  __rte_unused uint64_t len)
+{
+	return 0;
+}
+
+int
+rte_iommu_dma_unmap(uint64_t __rte_unused vaddr, uint64_t __rte_unused iova,
+		    __rte_unused uint64_t len)
+{
+	return 0;
+}
+
 #endif
diff --git a/lib/librte_eal/linuxapp/eal/eal_vfio.h b/lib/librte_eal/linuxapp/eal/eal_vfio.h
index ba7892b..bb669f0 100644
--- a/lib/librte_eal/linuxapp/eal/eal_vfio.h
+++ b/lib/librte_eal/linuxapp/eal/eal_vfio.h
@@ -48,6 +48,7 @@
 
 #ifdef VFIO_PRESENT
 
+#include <stdint.h>
 #include <linux/vfio.h>
 
 #define RTE_VFIO_TYPE1 VFIO_TYPE1_IOMMU
@@ -139,6 +140,7 @@ struct vfio_config {
 	int vfio_enabled;
 	int vfio_container_fd;
 	int vfio_active_groups;
+	const struct vfio_iommu_type *vfio_iommu_type;
 	struct vfio_group vfio_groups[VFIO_MAX_GROUPS];
 };
 
@@ -148,9 +150,18 @@ struct vfio_config {
  * */
 typedef int (*vfio_dma_func_t)(int);
 
+/* Custom memory region DMA mapping function prototype.
+ * Takes VFIO container fd, virtual address, phisical address, length and
+ * operation type (0 to unmap 1 for map) as a parameters.
+ * Returns 0 on success, -1 on error.
+ **/
+typedef int (*vfio_dma_user_func_t)(int fd, uint64_t vaddr, uint64_t iova,
+		uint64_t len, int do_map);
+
 struct vfio_iommu_type {
 	int type_id;
 	const char *name;
+	vfio_dma_user_func_t dma_user_map_func;
 	vfio_dma_func_t dma_map_func;
 };
 
-- 
2.7.4

  parent reply	other threads:[~2017-12-19 11:05 UTC|newest]

Thread overview: 44+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-12-19 11:04 [dpdk-dev] [PATCH 00/23] Dynamic memory allocation for DPDK Anatoly Burakov
2017-12-19 11:04 ` [dpdk-dev] [PATCH 01/23] eal: move get_virtual_area out of linuxapp eal_memory.c Anatoly Burakov
2017-12-19 11:04 ` [dpdk-dev] [PATCH 02/23] eal: add function to report number of detected sockets Anatoly Burakov
2017-12-19 11:04 ` [dpdk-dev] [PATCH 03/23] eal: add rte_fbarray Anatoly Burakov
2017-12-19 11:04 ` [dpdk-dev] [PATCH 04/23] eal: move all locking to heap Anatoly Burakov
2017-12-19 11:04 ` [dpdk-dev] [PATCH 05/23] eal: protect malloc heap stats with a lock Anatoly Burakov
2017-12-19 11:04 ` [dpdk-dev] [PATCH 06/23] eal: make malloc a doubly-linked list Anatoly Burakov
2017-12-19 11:04 ` [dpdk-dev] [PATCH 07/23] eal: make malloc_elem_join_adjacent_free public Anatoly Burakov
2017-12-19 11:04 ` [dpdk-dev] [PATCH 08/23] eal: add "single file segments" command-line option Anatoly Burakov
2017-12-19 11:04 ` [dpdk-dev] [PATCH 09/23] eal: add "legacy memory" option Anatoly Burakov
2017-12-19 11:04 ` [dpdk-dev] [PATCH 10/23] eal: read hugepage counts from node-specific sysfs path Anatoly Burakov
2017-12-19 11:04 ` [dpdk-dev] [PATCH 11/23] eal: replace memseg with memseg lists Anatoly Burakov
2017-12-19 11:04 ` [dpdk-dev] [PATCH 12/23] eal: add support for dynamic memory allocation Anatoly Burakov
2017-12-19 11:04 ` [dpdk-dev] [PATCH 13/23] eal: make use of dynamic memory allocation for init Anatoly Burakov
2017-12-19 11:04 ` [dpdk-dev] [PATCH 14/23] eal: add support for dynamic unmapping of pages Anatoly Burakov
2017-12-19 11:04 ` [dpdk-dev] [PATCH 15/23] eal: add API to check if memory is physically contiguous Anatoly Burakov
2017-12-19 11:04 ` [dpdk-dev] [PATCH 16/23] eal: enable dynamic memory allocation/free on malloc/free Anatoly Burakov
2017-12-19 11:04 ` [dpdk-dev] [PATCH 17/23] eal: add backend support for contiguous memory allocation Anatoly Burakov
2017-12-19 11:04 ` [dpdk-dev] [PATCH 18/23] eal: add rte_malloc support for allocating contiguous memory Anatoly Burakov
2017-12-19 11:04 ` [dpdk-dev] [PATCH 19/23] eal: enable reserving physically contiguous memzones Anatoly Burakov
2017-12-19 11:04 ` [dpdk-dev] [PATCH 20/23] eal: make memzones use rte_fbarray Anatoly Burakov
     [not found] ` <cover.1513594170.git.anatoly.burakov@intel.com>
2017-12-19 11:04   ` [dpdk-dev] [RFC 01/23] eal/memory: move get_virtual_area out of linuxapp eal_memory.c Anatoly Burakov
2017-12-19 11:15     ` Burakov, Anatoly
2017-12-19 11:04   ` [dpdk-dev] [RFC 02/23] eal/lcore: add function to report number of detected sockets Anatoly Burakov
2017-12-19 11:04   ` [dpdk-dev] [RFC 04/23] eal/malloc: move all locking to heap Anatoly Burakov
2017-12-19 11:04   ` [dpdk-dev] [RFC 05/23] eal/malloc: protect malloc heap stats with a lock Anatoly Burakov
2017-12-19 11:04   ` [dpdk-dev] [RFC 06/23] eal/malloc: make malloc a doubly-linked list Anatoly Burakov
2017-12-19 11:04   ` [dpdk-dev] [RFC 07/23] eal/malloc: make malloc_elem_join_adjacent_free public Anatoly Burakov
2017-12-19 11:04   ` [dpdk-dev] [RFC 10/23] eal: populate hugepage counts from socket-specific sysfs path Anatoly Burakov
2017-12-19 11:04   ` [dpdk-dev] [RFC 12/23] eal/memalloc: add support for dynamic memory allocation Anatoly Burakov
2017-12-19 11:04   ` [dpdk-dev] [RFC 13/23] eal/memory: make use of dynamic memory allocation for init Anatoly Burakov
2017-12-19 11:04   ` [dpdk-dev] [RFC 14/23] eal/memory: add support for dynamic unmapping of pages Anatoly Burakov
2017-12-19 11:04   ` [dpdk-dev] [RFC 15/23] eal/memalloc: add function to check if memory is physically contiguous Anatoly Burakov
2017-12-19 11:04   ` [dpdk-dev] [RFC 16/23] eal/malloc: enable dynamic memory allocation/free on malloc/free Anatoly Burakov
2017-12-19 11:04   ` [dpdk-dev] [RFC 17/23] eal/malloc: add backend support for contiguous memory allocation Anatoly Burakov
2017-12-19 11:04   ` [dpdk-dev] [RFC 18/23] eal/malloc: add rte_malloc support for allocating contiguous memory Anatoly Burakov
2017-12-19 11:04   ` [dpdk-dev] [RFC 19/23] eal/memzone: add support for reserving physically contiguous memzones Anatoly Burakov
2017-12-19 11:04   ` [dpdk-dev] [RFC 20/23] eal/memzone: make memzones use rte_fbarray Anatoly Burakov
2017-12-19 11:04   ` [dpdk-dev] [RFC 21/23] lib/mempool: add support for the new memory allocation methods Anatoly Burakov
2017-12-19 11:04   ` [dpdk-dev] [RFC 23/23] eal/memalloc: register/unregister memory with VFIO when alloc/free pages Anatoly Burakov
2017-12-19 11:04 ` [dpdk-dev] [PATCH 21/23] mempool: add support for the new memory allocation methods Anatoly Burakov
2017-12-19 11:04 ` Anatoly Burakov [this message]
2017-12-19 11:04 ` [dpdk-dev] [PATCH 23/23] eal: map/unmap memory with VFIO when alloc/free pages Anatoly Burakov
2017-12-19 11:15 ` [dpdk-dev] [PATCH 00/23] Dynamic memory allocation for DPDK Burakov, Anatoly

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=2d5b9ea71a32658efa24766933d07b5d2e29f25f.1513680516.git.anatoly.burakov@intel.com \
    --to=anatoly.burakov@intel.com \
    --cc=andras.kovacs@ericsson.com \
    --cc=benjamin.walker@intel.com \
    --cc=bruce.richardson@intel.com \
    --cc=dev@dpdk.org \
    --cc=keith.wiles@intel.com \
    --cc=laszlo.vadkeri@ericsson.com \
    --cc=pawelx.wodkowski@intel.com \
    --cc=thomas@monjalon.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).