git: 9bec868253c2 - main - libmlx5: External memory binding for HW resources
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Wed, 16 Sep 2026 14:13:07 UTC
The branch main has been updated by kib:
URL: https://cgit.FreeBSD.org/src/commit/?id=9bec868253c26055b58448db9ea8157f6d251079
commit 9bec868253c26055b58448db9ea8157f6d251079
Author: Vag Singh <vag.singh@oneconvergence.com>
AuthorDate: 2025-08-14 06:40:16 +0000
Commit: Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2026-09-16 14:12:08 +0000
libmlx5: External memory binding for HW resources
[PATCH 19/31] FreeBSD OFED support for DPDK MLX5 PMD
Add a new DV API mlx5dv_set_context_attr() to enable setting an external
memory allocator. This API will allow the application to use specific
decisions about the memory allocation of HW resources (e.g. DV objects).
Some examples are managing numa pinning per object, managing a
hugepages resource pool, shared memory regions.
Also extend mlx5dv_get_qp() to return UAR mapping info. This can allow a
process to share its doorbell access with secondary process by re-mmap
the UAR address on the device and make it accessible as a user space
address.
Differential revision: https://reviews.freebsd.org/D32193
MFC after: 1 month
---
contrib/ofed/libmlx5/buf.c | 51 +++++++++++++++++++++++++++++++++++++++-
contrib/ofed/libmlx5/cq.c | 2 +-
contrib/ofed/libmlx5/dbrec.c | 13 ++++++++--
contrib/ofed/libmlx5/libmlx5.map | 1 +
contrib/ofed/libmlx5/mlx5.c | 16 +++++++++++++
contrib/ofed/libmlx5/mlx5.h | 9 ++++++-
contrib/ofed/libmlx5/mlx5dv.h | 20 ++++++++++++++++
contrib/ofed/libmlx5/verbs.c | 9 ++++---
8 files changed, 113 insertions(+), 8 deletions(-)
diff --git a/contrib/ofed/libmlx5/buf.c b/contrib/ofed/libmlx5/buf.c
index df0f65352fb8..d12e5e7804bb 100644
--- a/contrib/ofed/libmlx5/buf.c
+++ b/contrib/ofed/libmlx5/buf.c
@@ -320,6 +320,36 @@ static void free_huge_buf(struct mlx5_context *ctx, struct mlx5_buf *buf)
mlx5_spin_unlock(&ctx->hugetlb_lock);
}
+void mlx5_free_buf_extern(struct mlx5_context *ctx, struct mlx5_buf *buf)
+{
+ ibv_dofork_range(buf->buf, buf->length);
+ ctx->extern_alloc.free(buf->buf, ctx->extern_alloc.data);
+}
+
+int mlx5_alloc_buf_extern(struct mlx5_context *ctx, struct mlx5_buf *buf,
+ size_t size)
+{
+ void *addr;
+
+ addr = ctx->extern_alloc.alloc(size, ctx->extern_alloc.data);
+ if (addr || size == 0) {
+ if (ibv_dontfork_range(addr, size)) {
+ mlx5_dbg(stderr, MLX5_DBG_CONTIG,
+ "External mode dontfork_range failed\n");
+ ctx->extern_alloc.free(addr,
+ ctx->extern_alloc.data);
+ return -1;
+ }
+ buf->buf = addr;
+ buf->length = size;
+ buf->type = MLX5_ALLOC_TYPE_EXTERNAL;
+ return 0;
+ }
+
+ mlx5_dbg(stderr, MLX5_DBG_CONTIG, "External alloc failed\n");
+ return -1;
+}
+
int mlx5_alloc_prefered_buf(struct mlx5_context *mctx,
struct mlx5_buf *buf,
size_t size, int page_size,
@@ -362,6 +392,9 @@ int mlx5_alloc_prefered_buf(struct mlx5_context *mctx,
"Contig allocation failed, fallback to default mode\n");
}
+ if (type == MLX5_ALLOC_TYPE_EXTERNAL)
+ return mlx5_alloc_buf_extern(mctx, buf, size);
+
return mlx5_alloc_buf(buf, size, page_size);
}
@@ -382,6 +415,11 @@ int mlx5_free_actual_buf(struct mlx5_context *ctx, struct mlx5_buf *buf)
case MLX5_ALLOC_TYPE_CONTIG:
mlx5_free_buf_contig(ctx, buf);
break;
+
+ case MLX5_ALLOC_TYPE_EXTERNAL:
+ mlx5_free_buf_extern(ctx, buf);
+ break;
+
default:
fprintf(stderr, "Bad allocation type\n");
}
@@ -414,7 +452,13 @@ static uint32_t mlx5_get_block_order(uint32_t v)
return r;
}
-void mlx5_get_alloc_type(const char *component,
+bool mlx5_is_extern_alloc(struct mlx5_context *context)
+{
+ return context->extern_alloc.alloc && context->extern_alloc.free;
+}
+
+void mlx5_get_alloc_type(struct mlx5_context *context,
+ const char *component,
enum mlx5_alloc_type *alloc_type,
enum mlx5_alloc_type default_type)
@@ -422,6 +466,11 @@ void mlx5_get_alloc_type(const char *component,
char *env_value;
char name[128];
+ if (mlx5_is_extern_alloc(context)) {
+ *alloc_type = MLX5_ALLOC_TYPE_EXTERNAL;
+ return;
+ }
+
snprintf(name, sizeof(name), "%s_ALLOC_TYPE", component);
*alloc_type = default_type;
diff --git a/contrib/ofed/libmlx5/cq.c b/contrib/ofed/libmlx5/cq.c
index a23cd4416f24..66c29dec3ec0 100644
--- a/contrib/ofed/libmlx5/cq.c
+++ b/contrib/ofed/libmlx5/cq.c
@@ -1499,7 +1499,7 @@ int mlx5_alloc_cq_buf(struct mlx5_context *mctx, struct mlx5_cq *cq,
if (mlx5_use_huge("HUGE_CQ"))
default_type = MLX5_ALLOC_TYPE_HUGE;
- mlx5_get_alloc_type(MLX5_CQ_PREFIX, &type, default_type);
+ mlx5_get_alloc_type(mctx, MLX5_CQ_PREFIX, &type, default_type);
ret = mlx5_alloc_prefered_buf(mctx, buf,
align(nent * cqe_sz, dev->page_size),
diff --git a/contrib/ofed/libmlx5/dbrec.c b/contrib/ofed/libmlx5/dbrec.c
index 20e37cac8cf6..17aee0ba20ee 100644
--- a/contrib/ofed/libmlx5/dbrec.c
+++ b/contrib/ofed/libmlx5/dbrec.c
@@ -53,6 +53,7 @@ static struct mlx5_db_page *__add_page(struct mlx5_context *context)
int pp;
int i;
int nlong;
+ int ret;
pp = ps / context->cache_line_size;
nlong = (pp + 8 * sizeof(long) - 1) / (8 * sizeof(long));
@@ -61,7 +62,11 @@ static struct mlx5_db_page *__add_page(struct mlx5_context *context)
if (!page)
return NULL;
- if (mlx5_alloc_buf(&page->buf, ps, ps)) {
+ if (mlx5_is_extern_alloc(context))
+ ret = mlx5_alloc_buf_extern(context, &page->buf, ps);
+ else
+ ret = mlx5_alloc_buf(&page->buf, ps, ps);
+ if (ret) {
free(page);
return NULL;
}
@@ -139,7 +144,11 @@ void mlx5_free_db(struct mlx5_context *context, __be32 *db)
if (page->next)
page->next->prev = page->prev;
- mlx5_free_buf(&page->buf);
+ if (page->buf.type == MLX5_ALLOC_TYPE_EXTERNAL)
+ mlx5_free_buf_extern(context, &page->buf);
+ else
+ mlx5_free_buf(&page->buf);
+
free(page);
}
diff --git a/contrib/ofed/libmlx5/libmlx5.map b/contrib/ofed/libmlx5/libmlx5.map
index e7fe9f416970..09d886d14e15 100644
--- a/contrib/ofed/libmlx5/libmlx5.map
+++ b/contrib/ofed/libmlx5/libmlx5.map
@@ -15,4 +15,5 @@ MLX5_1.1 {
MLX5_1.2 {
global:
mlx5dv_init_obj;
+ mlx5dv_set_context_attr;
} MLX5_1.1;
diff --git a/contrib/ofed/libmlx5/mlx5.c b/contrib/ofed/libmlx5/mlx5.c
index b3eba331d89f..5737680db93b 100644
--- a/contrib/ofed/libmlx5/mlx5.c
+++ b/contrib/ofed/libmlx5/mlx5.c
@@ -796,6 +796,22 @@ int mlx5dv_init_obj_1_0(struct mlx5dv_obj *obj, uint64_t obj_type)
__asm__(".symver mlx5dv_init_obj_1_2, mlx5dv_init_obj@@MLX5_1.2");
__asm__(".symver mlx5dv_init_obj_1_0, mlx5dv_init_obj@MLX5_1.0");
+int mlx5dv_set_context_attr(struct ibv_context *ibv_ctx,
+ enum mlx5dv_set_ctx_attr_type type, void *attr)
+{
+ struct mlx5_context *ctx = to_mctx(ibv_ctx);
+
+ switch (type) {
+ case MLX5DV_CTX_ATTR_BUF_ALLOCATORS:
+ ctx->extern_alloc = *((struct mlx5dv_ctx_allocators *)attr);
+ break;
+ default:
+ return ENOTSUP;
+ }
+
+ return 0;
+}
+
static void adjust_uar_info(struct mlx5_device *mdev,
struct mlx5_context *context,
struct mlx5_alloc_ucontext_resp resp)
diff --git a/contrib/ofed/libmlx5/mlx5.h b/contrib/ofed/libmlx5/mlx5.h
index dbd17db62ffd..45082243a56c 100644
--- a/contrib/ofed/libmlx5/mlx5.h
+++ b/contrib/ofed/libmlx5/mlx5.h
@@ -162,6 +162,7 @@ enum mlx5_alloc_type {
MLX5_ALLOC_TYPE_CONTIG,
MLX5_ALLOC_TYPE_PREFER_HUGE,
MLX5_ALLOC_TYPE_PREFER_CONTIG,
+ MLX5_ALLOC_TYPE_EXTERNAL,
MLX5_ALLOC_TYPE_ALL
};
@@ -268,6 +269,7 @@ struct mlx5_context {
uint32_t uar_size;
uint64_t vendor_cap_flags; /* Use enum mlx5_vendor_cap_flags */
struct mlx5dv_cqe_comp_caps cqe_comp_caps;
+ struct mlx5dv_ctx_allocators extern_alloc;
};
struct mlx5_bitmap {
@@ -558,10 +560,15 @@ int mlx5_alloc_prefered_buf(struct mlx5_context *mctx,
enum mlx5_alloc_type alloc_type,
const char *component);
int mlx5_free_actual_buf(struct mlx5_context *ctx, struct mlx5_buf *buf);
-void mlx5_get_alloc_type(const char *component,
+void mlx5_get_alloc_type(struct mlx5_context *context,
+ const char *component,
enum mlx5_alloc_type *alloc_type,
enum mlx5_alloc_type default_alloc_type);
int mlx5_use_huge(const char *key);
+bool mlx5_is_extern_alloc(struct mlx5_context *context);
+int mlx5_alloc_buf_extern(struct mlx5_context *ctx, struct mlx5_buf *buf,
+ size_t size);
+void mlx5_free_buf_extern(struct mlx5_context *ctx, struct mlx5_buf *buf);
__be32 *mlx5_alloc_dbrec(struct mlx5_context *context);
void mlx5_free_db(struct mlx5_context *context, __be32 *db);
diff --git a/contrib/ofed/libmlx5/mlx5dv.h b/contrib/ofed/libmlx5/mlx5dv.h
index 734303c1ca38..9555d9e2851f 100644
--- a/contrib/ofed/libmlx5/mlx5dv.h
+++ b/contrib/ofed/libmlx5/mlx5dv.h
@@ -621,4 +621,24 @@ void mlx5dv_set_eth_seg(struct mlx5_wqe_eth_seg *seg, uint8_t cs_flags,
seg->inline_hdr_sz = htobe16(inline_hdr_sz);
memcpy(seg->inline_hdr_start, inline_hdr_start, inline_hdr_sz);
}
+
+enum mlx5dv_set_ctx_attr_type {
+ MLX5DV_CTX_ATTR_BUF_ALLOCATORS = 1,
+};
+
+struct mlx5dv_ctx_allocators {
+ void *(*alloc)(size_t size, void *priv_data);
+ void (*free)(void *ptr, void *priv_data);
+ void *data;
+};
+
+/*
+ * Generic context attributes set API
+ *
+ * Returns 0 on success, or the value of errno on failure
+ * (which indicates the failure reason).
+ */
+int mlx5dv_set_context_attr(struct ibv_context *context,
+ enum mlx5dv_set_ctx_attr_type type, void *attr);
+
#endif /* _MLX5DV_H_ */
diff --git a/contrib/ofed/libmlx5/verbs.c b/contrib/ofed/libmlx5/verbs.c
index 5d97758738af..db77b0d20cd1 100644
--- a/contrib/ofed/libmlx5/verbs.c
+++ b/contrib/ofed/libmlx5/verbs.c
@@ -1093,7 +1093,7 @@ static int mlx5_alloc_qp_buf(struct ibv_context *context,
if (mlx5_use_huge(qp_huge_key))
default_alloc_type = MLX5_ALLOC_TYPE_HUGE;
- mlx5_get_alloc_type(MLX5_QP_PREFIX, &alloc_type,
+ mlx5_get_alloc_type(to_mctx(context), MLX5_QP_PREFIX, &alloc_type,
default_alloc_type);
err = mlx5_alloc_prefered_buf(to_mctx(context), &qp->buf,
@@ -2031,7 +2031,10 @@ static int mlx5_alloc_rwq_buf(struct ibv_context *context,
int size)
{
int err;
- enum mlx5_alloc_type default_alloc_type = MLX5_ALLOC_TYPE_PREFER_CONTIG;
+ enum mlx5_alloc_type alloc_type;
+
+ mlx5_get_alloc_type(to_mctx(context), MLX5_RWQ_PREFIX,
+ &alloc_type, MLX5_ALLOC_TYPE_ANON);
rwq->rq.wrid = malloc(rwq->rq.wqe_cnt * sizeof(uint64_t));
if (!rwq->rq.wrid) {
@@ -2043,7 +2046,7 @@ static int mlx5_alloc_rwq_buf(struct ibv_context *context,
align(rwq->buf_size, to_mdev
(context->device)->page_size),
to_mdev(context->device)->page_size,
- default_alloc_type,
+ alloc_type,
MLX5_RWQ_PREFIX);
if (err) {