From: Maxime Coquelin <maxime.coquelin@redhat.com>
To: dev@dpdk.org, tiwei.bie@intel.com, zhihong.wang@intel.com,
anatoly.burakov@intel.com
Cc: Maxime Coquelin <maxime.coquelin@redhat.com>
Subject: [dpdk-dev] [PATCH 1/4] eal: add new API to register contiguous external memory
Date: Fri, 13 Dec 2019 15:13:19 +0100 [thread overview]
Message-ID: <20191213141322.32730-2-maxime.coquelin@redhat.com> (raw)
In-Reply-To: <20191213141322.32730-1-maxime.coquelin@redhat.com>
This new API allows to pass a file descriptor while
registering external and contiguous memory in the IOVA space.
This is required for using Virtio-user PMD with application
using external memory for the mbuf's buffers, like Seastar
or VPP.
FD is only attached to the segments if single_file_segment
option is enabled.
Signed-off-by: Maxime Coquelin <maxime.coquelin@redhat.com>
---
lib/librte_eal/common/eal_common_memory.c | 75 +++++++++++++++++++++-
lib/librte_eal/common/include/rte_memory.h | 46 +++++++++++++
lib/librte_eal/common/malloc_heap.c | 17 ++++-
lib/librte_eal/common/malloc_heap.h | 2 +-
lib/librte_eal/common/rte_malloc.c | 2 +-
lib/librte_eal/rte_eal_version.map | 3 +
6 files changed, 141 insertions(+), 4 deletions(-)
diff --git a/lib/librte_eal/common/eal_common_memory.c b/lib/librte_eal/common/eal_common_memory.c
index 4a9cc1f19a..7a4b371828 100644
--- a/lib/librte_eal/common/eal_common_memory.c
+++ b/lib/librte_eal/common/eal_common_memory.c
@@ -772,6 +772,79 @@ rte_memseg_get_fd_offset(const struct rte_memseg *ms, size_t *offset)
return ret;
}
+int
+rte_extmem_register_contig(void *va_addr, size_t len, rte_iova_t iova_addr,
+ size_t page_sz, int fd)
+{
+ struct rte_mem_config *mcfg = rte_eal_get_configuration()->mem_config;
+ rte_iova_t *iova_addrs = NULL;
+ unsigned int socket_id, n, i;
+ int ret = 0;
+
+ if (va_addr == NULL || page_sz == 0 || len == 0 ||
+ !rte_is_power_of_2(page_sz) ||
+ RTE_ALIGN(len, page_sz) != len ||
+ ((len % page_sz) != 0 ||
+ !rte_is_aligned(va_addr, page_sz))) {
+ rte_errno = EINVAL;
+ return -1;
+ }
+
+ n = len / page_sz;
+ if (iova_addr != 0) {
+ iova_addrs = malloc(n * sizeof(*iova_addrs));
+ if (iova_addrs == NULL) {
+ rte_errno = -ENOMEM;
+ return -1;
+ }
+
+ for (i = 0; i < n; i++)
+ iova_addrs[i] = iova_addr + n * page_sz;
+
+ }
+
+
+ if (fd >= 0 && !internal_config.single_file_segments) {
+ RTE_LOG(INFO, EAL, "FD won't be attached to the external memory," \
+ " requires single file segments\n");
+ fd = -1;
+ }
+ rte_mcfg_mem_write_lock();
+
+ /* make sure the segment doesn't already exist */
+ if (malloc_heap_find_external_seg(va_addr, len) != NULL) {
+ rte_errno = EEXIST;
+ ret = -1;
+ goto unlock;
+ }
+
+ /* get next available socket ID */
+ socket_id = mcfg->next_socket_id;
+ if (socket_id > INT32_MAX) {
+ RTE_LOG(ERR, EAL, "Cannot assign new socket ID's\n");
+ rte_errno = ENOSPC;
+ ret = -1;
+ goto unlock;
+ }
+
+ /* we can create a new memseg */
+ if (malloc_heap_create_external_seg(va_addr, iova_addrs, n,
+ page_sz, "extmem_contig", socket_id, fd) == NULL) {
+ ret = -1;
+ goto unlock;
+ }
+
+ /* memseg list successfully created - increment next socket ID */
+ mcfg->next_socket_id++;
+unlock:
+ rte_mcfg_mem_write_unlock();
+
+ if (iova_addrs != NULL)
+ free(iova_addrs);
+
+ return ret;
+}
+
int
rte_extmem_register(void *va_addr, size_t len, rte_iova_t iova_addrs[],
unsigned int n_pages, size_t page_sz)
@@ -809,7 +882,7 @@ rte_extmem_register(void *va_addr, size_t len, rte_iova_t iova_addrs[],
/* we can create a new memseg */
n = len / page_sz;
if (malloc_heap_create_external_seg(va_addr, iova_addrs, n,
- page_sz, "extmem", socket_id) == NULL) {
+ page_sz, "extmem", socket_id, -1) == NULL) {
ret = -1;
goto unlock;
}
diff --git a/lib/librte_eal/common/include/rte_memory.h b/lib/librte_eal/common/include/rte_memory.h
index 3d8d0bd697..e274e47e5e 100644
--- a/lib/librte_eal/common/include/rte_memory.h
+++ b/lib/librte_eal/common/include/rte_memory.h
@@ -451,6 +451,10 @@ rte_memseg_get_fd_offset_thread_unsafe(const struct rte_memseg *ms,
* is NULL.
* @param page_sz
* Page size of the underlying memory
+ * @param fd
+ * File descriptor for the external memory region registered. Must be set to
+ * -1 if no FD, and ignored if single-segment isn't not used or if iova
+ * aren't contiguous (iova_addrs != NULL).
*
* @return
* - 0 on success
@@ -461,6 +465,48 @@ rte_memseg_get_fd_offset_thread_unsafe(const struct rte_memseg *ms,
*/
__rte_experimental
int
+rte_extmem_register_contig(void *va_addr, size_t len, rte_iova_t iova_addr,
+ size_t page_sz, int fd);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Register external contiguous memory chunk with DPDK.
+ *
+ * @note Using this API is mutually exclusive with ``rte_malloc`` family of
+ * API's.
+ *
+ * @note This API will not perform any DMA mapping. It is expected that user
+ * will do that themselves.
+ *
+ * @note Before accessing this memory in other processes, it needs to be
+ * attached in each of those processes by calling ``rte_extmem_attach`` in
+ * each other process.
+ *
+ * @param va_addr
+ * Start of virtual area to register. Must be aligned by ``page_sz``.
+ * @param len
+ * Length of virtual area to register. Must be aligned by ``page_sz``.
+ * @param iova_addr
+ * IOVA address for the contiguous memory chunck. Can be 0, in which case
+ * page IOVA addresses will be set to RTE_BAD_IOVA.
+ * @param page_sz
+ * Page size of the underlying memory
+ * @param fd
+ * File descriptor for the external memory region registered. Must be set to
+ * -1 if no FD, and ignored if single-segment isn't not used.
+ *
+ * @return
+ * - 0 on success
+ * - -1 in case of error, with rte_errno set to one of the following:
+ * EINVAL - one of the parameters was invalid
+ * EEXIST - memory chunk is already registered
+ * ENOSPC - no more space in internal config to store a new memory chunk
+ * ENOMEM - failed to allocate pages IOVA addresses
+ */
+__rte_experimental
+int
rte_extmem_register(void *va_addr, size_t len, rte_iova_t iova_addrs[],
unsigned int n_pages, size_t page_sz);
diff --git a/lib/librte_eal/common/malloc_heap.c b/lib/librte_eal/common/malloc_heap.c
index 842eb9de75..229ab6563c 100644
--- a/lib/librte_eal/common/malloc_heap.c
+++ b/lib/librte_eal/common/malloc_heap.c
@@ -1096,7 +1096,7 @@ destroy_elem(struct malloc_elem *elem, size_t len)
struct rte_memseg_list *
malloc_heap_create_external_seg(void *va_addr, rte_iova_t iova_addrs[],
unsigned int n_pages, size_t page_sz, const char *seg_name,
- unsigned int socket_id)
+ unsigned int socket_id, int fd)
{
struct rte_mem_config *mcfg = rte_eal_get_configuration()->mem_config;
char fbarray_name[RTE_FBARRAY_NAME_LEN];
@@ -1153,6 +1153,13 @@ malloc_heap_create_external_seg(void *va_addr, rte_iova_t iova_addrs[],
msl->version = 0;
msl->external = 1;
+ if (fd >= 0) {
+ int list_idx = msl - mcfg->memsegs;
+
+ if (eal_memalloc_set_seg_list_fd(list_idx, fd))
+ RTE_LOG(ERR, EAL, "Failed to set segment list FD\n");
+ }
+
return msl;
}
@@ -1202,10 +1209,18 @@ malloc_heap_find_external_seg(void *va_addr, size_t len)
int
malloc_heap_destroy_external_seg(struct rte_memseg_list *msl)
{
+ struct rte_mem_config *mcfg = rte_eal_get_configuration()->mem_config;
+ int list_idx;
+
/* destroy the fbarray backing this memory */
if (rte_fbarray_destroy(&msl->memseg_arr) < 0)
return -1;
+ list_idx = msl - mcfg->memsegs;
+ if (eal_memalloc_set_seg_list_fd(list_idx, -1))
+ RTE_LOG(ERR, EAL, "Failed to reset segment list FD\n");
+
+
/* reset the memseg list */
memset(msl, 0, sizeof(*msl));
diff --git a/lib/librte_eal/common/malloc_heap.h b/lib/librte_eal/common/malloc_heap.h
index 772736b53f..438ce908de 100644
--- a/lib/librte_eal/common/malloc_heap.h
+++ b/lib/librte_eal/common/malloc_heap.h
@@ -65,7 +65,7 @@ malloc_heap_destroy(struct malloc_heap *heap);
struct rte_memseg_list *
malloc_heap_create_external_seg(void *va_addr, rte_iova_t iova_addrs[],
unsigned int n_pages, size_t page_sz, const char *seg_name,
- unsigned int socket_id);
+ unsigned int socket_id, int fd);
struct rte_memseg_list *
malloc_heap_find_external_seg(void *va_addr, size_t len);
diff --git a/lib/librte_eal/common/rte_malloc.c b/lib/librte_eal/common/rte_malloc.c
index d6026a2b17..aa19b0517f 100644
--- a/lib/librte_eal/common/rte_malloc.c
+++ b/lib/librte_eal/common/rte_malloc.c
@@ -389,7 +389,7 @@ rte_malloc_heap_memory_add(const char *heap_name, void *va_addr, size_t len,
n = len / page_sz;
msl = malloc_heap_create_external_seg(va_addr, iova_addrs, n, page_sz,
- heap_name, heap->socket_id);
+ heap_name, heap->socket_id, -1);
if (msl == NULL) {
ret = -1;
goto unlock;
diff --git a/lib/librte_eal/rte_eal_version.map b/lib/librte_eal/rte_eal_version.map
index e38d02530c..ddcb4b0512 100644
--- a/lib/librte_eal/rte_eal_version.map
+++ b/lib/librte_eal/rte_eal_version.map
@@ -332,4 +332,7 @@ EXPERIMENTAL {
# added in 19.11
rte_log_get_stream;
rte_mcfg_get_single_file_segments;
+
+ # added in 20.02
+ rte_extmem_register_contig;
};
--
2.21.0
next prev parent reply other threads:[~2019-12-13 14:13 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-12-13 14:13 [dpdk-dev] [PATCH 0/4] Add external contiguous memory support to Virtio-user Maxime Coquelin
2019-12-13 14:13 ` Maxime Coquelin [this message]
2020-01-23 13:06 ` [dpdk-dev] [PATCH 1/4] eal: add new API to register contiguous external memory Burakov, Anatoly
2019-12-13 14:13 ` [dpdk-dev] [PATCH 2/4] eal: allow getting memory segment FD with " Maxime Coquelin
2019-12-13 14:13 ` [dpdk-dev] [PATCH 3/4] bus/vdev: add DMA mapping supprt Maxime Coquelin
2019-12-13 14:13 ` [dpdk-dev] [PATCH 4/4] net/virtio: add DMA mapping callback to virtio-user Maxime Coquelin
2020-01-08 16:11 ` [dpdk-dev] [PATCH 0/4] Add external contiguous memory support to Virtio-user Maxime Coquelin
2023-08-25 9:55 ` David Marchand
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=20191213141322.32730-2-maxime.coquelin@redhat.com \
--to=maxime.coquelin@redhat.com \
--cc=anatoly.burakov@intel.com \
--cc=dev@dpdk.org \
--cc=tiwei.bie@intel.com \
--cc=zhihong.wang@intel.com \
/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).