* [PATCH 0/2] implement missing APIs on FreeBSD
@ 2026-05-25 17:13 Bruce Richardson
2026-05-25 17:13 ` [PATCH 1/2] eal/freebsd: fix memseg addresses in EAL VA mode Bruce Richardson
` (2 more replies)
0 siblings, 3 replies; 5+ messages in thread
From: Bruce Richardson @ 2026-05-25 17:13 UTC (permalink / raw)
To: dev; +Cc: Bruce Richardson
The APIs for converting a virtual address to an IOVA or a physical
address were implemented only as stubs on FreeBSD, but unfortunately
they are used by drivers such as "igc", part of e1000, causing the
drivers to fail on BSD. A workaround would be to change the use of these
functions with the rte_malloc equivalents (e.g. rte_malloc_virt2iova) -
which do work on FreeBSD - but a better solution is just to replace the
stubs with proper implementations in FreeBSD-specific EAL flags.
Bruce Richardson (2):
eal/freebsd: fix memseg addresses in IOVA_AS_VA mode
eal/freebsd: implement virtual to IOVA translation fn
app/test/test_memory.c | 67 ++++++++++++++++++++++++++++++++++++
lib/eal/freebsd/eal_memory.c | 27 +++++++++++----
2 files changed, 88 insertions(+), 6 deletions(-)
--
2.53.0
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 1/2] eal/freebsd: fix memseg addresses in EAL VA mode
2026-05-25 17:13 [PATCH 0/2] implement missing APIs on FreeBSD Bruce Richardson
@ 2026-05-25 17:13 ` Bruce Richardson
2026-05-25 17:13 ` [PATCH 2/2] eal/freebsd: implement virtual to IOVA translation fn Bruce Richardson
2026-06-01 20:12 ` [PATCH 0/2] implement missing APIs on FreeBSD Thomas Monjalon
2 siblings, 0 replies; 5+ messages in thread
From: Bruce Richardson @ 2026-05-25 17:13 UTC (permalink / raw)
To: dev; +Cc: Bruce Richardson, stable
In BSD, when mapping the contigmem segments, the iova is unconditionally
set to the physical address, irrespective of the actual IOVA mode.
Change this to use virtual addresses when iova mode is IOVA_AS_VA.
Fixes: 764bf26873b9 ("add FreeBSD support")
Cc: stable@dpdk.org
Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
---
lib/eal/freebsd/eal_memory.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/lib/eal/freebsd/eal_memory.c b/lib/eal/freebsd/eal_memory.c
index cd608db9f9..e56d149a22 100644
--- a/lib/eal/freebsd/eal_memory.c
+++ b/lib/eal/freebsd/eal_memory.c
@@ -214,7 +214,10 @@ rte_eal_hugepage_init(void)
}
seg->addr = addr;
- seg->iova = physaddr;
+ if (rte_eal_iova_mode() == RTE_IOVA_VA)
+ seg->iova = (uintptr_t)addr;
+ else
+ seg->iova = physaddr;
seg->hugepage_sz = page_sz;
seg->len = page_sz;
seg->nchannel = mcfg->nchannel;
--
2.53.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 2/2] eal/freebsd: implement virtual to IOVA translation fn
2026-05-25 17:13 [PATCH 0/2] implement missing APIs on FreeBSD Bruce Richardson
2026-05-25 17:13 ` [PATCH 1/2] eal/freebsd: fix memseg addresses in EAL VA mode Bruce Richardson
@ 2026-05-25 17:13 ` Bruce Richardson
2026-05-25 18:23 ` Lewis Donzis
2026-06-01 20:12 ` [PATCH 0/2] implement missing APIs on FreeBSD Thomas Monjalon
2 siblings, 1 reply; 5+ messages in thread
From: Bruce Richardson @ 2026-05-25 17:13 UTC (permalink / raw)
To: dev; +Cc: Bruce Richardson, Lewis Donzis
The function rte_mem_virt2iova() function was always returning BAD_IOVA
on FreeBSD as it was not implemented. Unfortunately, this function was
used by some drivers - expecting it to work as they used addresses from
rte_malloc calls. Implement this call on FreeBSD to fix things and
enable more drivers on BSD. To verify the function works as expected
add a basic unit test to the memory_autotest for it.
At the same time, we can trivially use this to implement the
rte_mem_virt2phy function for the case of using contigmem where IOVAs
are physical addresses.
Reported-by: Lewis Donzis <lew@perftech.com>
Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
---
NOTE: This is one of those patches that could be either a bugfix or a
feature. For now, I'm treating it as adding new feature support, though
in doing so it enables previously broken drivers.
---
app/test/test_memory.c | 67 ++++++++++++++++++++++++++++++++++++
lib/eal/freebsd/eal_memory.c | 22 +++++++++---
2 files changed, 84 insertions(+), 5 deletions(-)
diff --git a/app/test/test_memory.c b/app/test/test_memory.c
index 628714c0b8..260d5ed8f8 100644
--- a/app/test/test_memory.c
+++ b/app/test/test_memory.c
@@ -8,6 +8,7 @@
#include <rte_eal.h>
#include <rte_errno.h>
#include <rte_memory.h>
+#include <rte_malloc.h>
#include <rte_common.h>
#include <rte_memzone.h>
@@ -75,6 +76,68 @@ check_seg_fds(const struct rte_memseg_list *msl, const struct rte_memseg *ms,
return 0;
}
+static int
+check_malloc_virt2iova(void)
+{
+ const size_t alloc_sz = 128;
+ const size_t off = 32;
+ struct rte_memseg *ms;
+ char *p;
+ rte_iova_t iova, iova_off;
+
+ p = rte_malloc("memory_autotest", alloc_sz, RTE_CACHE_LINE_SIZE);
+ if (p == NULL) {
+ printf("rte_malloc failed\n");
+ return -1;
+ }
+
+ iova = rte_mem_virt2iova(p);
+ if (iova == RTE_BAD_IOVA) {
+ printf("rte_mem_virt2iova failed for rte_malloc pointer\n");
+ rte_free(p);
+ return -1;
+ }
+
+ ms = rte_mem_virt2memseg(p, NULL);
+ if (ms == NULL) {
+ printf("failed to resolve memseg for rte_malloc pointer\n");
+ rte_free(p);
+ return -1;
+ }
+
+ if (rte_eal_iova_mode() == RTE_IOVA_PA) {
+ if (ms->iova == RTE_BAD_IOVA || iova < ms->iova ||
+ iova >= ms->iova + ms->len) {
+ printf("translated iova is outside memseg range\n");
+ rte_free(p);
+ return -1;
+ }
+
+ phys_addr_t physaddr = rte_mem_virt2phy(p);
+ if (physaddr == RTE_BAD_PHYS_ADDR || physaddr != iova) {
+ printf("rte_mem_virt2phy failed for rte_malloc pointer\n");
+ rte_free(p);
+ return -1;
+ }
+ } else if (rte_eal_iova_mode() == RTE_IOVA_VA) {
+ if (iova != (uintptr_t)p) {
+ printf("rte_mem_virt2iova did not return VA in VA mode\n");
+ rte_free(p);
+ return -1;
+ }
+ }
+
+ iova_off = rte_mem_virt2iova(p + off);
+ if (iova_off == RTE_BAD_IOVA || iova_off != iova + off) {
+ printf("translated iova for interior pointer is invalid\n");
+ rte_free(p);
+ return -1;
+ }
+
+ rte_free(p);
+ return 0;
+}
+
static int
test_memory(void)
{
@@ -107,6 +170,10 @@ test_memory(void)
return -1;
}
+ ret = check_malloc_virt2iova();
+ if (ret < 0)
+ return ret;
+
return 0;
}
diff --git a/lib/eal/freebsd/eal_memory.c b/lib/eal/freebsd/eal_memory.c
index e56d149a22..6952b38630 100644
--- a/lib/eal/freebsd/eal_memory.c
+++ b/lib/eal/freebsd/eal_memory.c
@@ -40,16 +40,28 @@ RTE_EXPORT_SYMBOL(rte_mem_virt2phy)
phys_addr_t
rte_mem_virt2phy(const void *virtaddr)
{
- /* XXX not implemented. This function is only used by
- * rte_mempool_virt2iova() when hugepages are disabled. */
- (void)virtaddr;
- return RTE_BAD_IOVA;
+ /* not implemented for FreeBSD when not using contigmem memory */
+ if (virtaddr == NULL || rte_eal_iova_mode() != RTE_IOVA_PA)
+ return RTE_BAD_IOVA;
+ /* when IOVA == PA, return the IOVA */
+ return rte_mem_virt2iova(virtaddr);
}
+
RTE_EXPORT_SYMBOL(rte_mem_virt2iova)
rte_iova_t
rte_mem_virt2iova(const void *virtaddr)
{
- return rte_mem_virt2phy(virtaddr);
+ if (virtaddr == NULL)
+ return RTE_BAD_IOVA;
+
+ if (rte_eal_iova_mode() == RTE_IOVA_VA)
+ return (uintptr_t)virtaddr;
+
+ const struct rte_memseg *ms = rte_mem_virt2memseg(virtaddr, NULL);
+ if (ms != NULL && ms->iova != RTE_BAD_IOVA)
+ return ms->iova + RTE_PTR_DIFF(virtaddr, ms->addr);
+
+ return RTE_BAD_IOVA;
}
int
--
2.53.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH 2/2] eal/freebsd: implement virtual to IOVA translation fn
2026-05-25 17:13 ` [PATCH 2/2] eal/freebsd: implement virtual to IOVA translation fn Bruce Richardson
@ 2026-05-25 18:23 ` Lewis Donzis
0 siblings, 0 replies; 5+ messages in thread
From: Lewis Donzis @ 2026-05-25 18:23 UTC (permalink / raw)
To: Bruce Richardson; +Cc: dev
Tested with igc driver, which previously failed and now works properly.
----- On May 25, 2026, at 12:13 PM, Bruce Richardson bruce.richardson@intel.com wrote:
> The function rte_mem_virt2iova() function was always returning BAD_IOVA
> on FreeBSD as it was not implemented. Unfortunately, this function was
> used by some drivers - expecting it to work as they used addresses from
> rte_malloc calls. Implement this call on FreeBSD to fix things and
> enable more drivers on BSD. To verify the function works as expected
> add a basic unit test to the memory_autotest for it.
>
> At the same time, we can trivially use this to implement the
> rte_mem_virt2phy function for the case of using contigmem where IOVAs
> are physical addresses.
>
> Reported-by: Lewis Donzis <lew@perftech.com>
Tested-by: Lewis Donzis <lew@perftech.com>
> Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
> ---
>
> NOTE: This is one of those patches that could be either a bugfix or a
> feature. For now, I'm treating it as adding new feature support, though
> in doing so it enables previously broken drivers.
> ---
> app/test/test_memory.c | 67 ++++++++++++++++++++++++++++++++++++
> lib/eal/freebsd/eal_memory.c | 22 +++++++++---
> 2 files changed, 84 insertions(+), 5 deletions(-)
>
> diff --git a/app/test/test_memory.c b/app/test/test_memory.c
> index 628714c0b8..260d5ed8f8 100644
> --- a/app/test/test_memory.c
> +++ b/app/test/test_memory.c
> @@ -8,6 +8,7 @@
> #include <rte_eal.h>
> #include <rte_errno.h>
> #include <rte_memory.h>
> +#include <rte_malloc.h>
> #include <rte_common.h>
> #include <rte_memzone.h>
>
> @@ -75,6 +76,68 @@ check_seg_fds(const struct rte_memseg_list *msl, const struct
> rte_memseg *ms,
> return 0;
> }
>
> +static int
> +check_malloc_virt2iova(void)
> +{
> + const size_t alloc_sz = 128;
> + const size_t off = 32;
> + struct rte_memseg *ms;
> + char *p;
> + rte_iova_t iova, iova_off;
> +
> + p = rte_malloc("memory_autotest", alloc_sz, RTE_CACHE_LINE_SIZE);
> + if (p == NULL) {
> + printf("rte_malloc failed\n");
> + return -1;
> + }
> +
> + iova = rte_mem_virt2iova(p);
> + if (iova == RTE_BAD_IOVA) {
> + printf("rte_mem_virt2iova failed for rte_malloc pointer\n");
> + rte_free(p);
> + return -1;
> + }
> +
> + ms = rte_mem_virt2memseg(p, NULL);
> + if (ms == NULL) {
> + printf("failed to resolve memseg for rte_malloc pointer\n");
> + rte_free(p);
> + return -1;
> + }
> +
> + if (rte_eal_iova_mode() == RTE_IOVA_PA) {
> + if (ms->iova == RTE_BAD_IOVA || iova < ms->iova ||
> + iova >= ms->iova + ms->len) {
> + printf("translated iova is outside memseg range\n");
> + rte_free(p);
> + return -1;
> + }
> +
> + phys_addr_t physaddr = rte_mem_virt2phy(p);
> + if (physaddr == RTE_BAD_PHYS_ADDR || physaddr != iova) {
> + printf("rte_mem_virt2phy failed for rte_malloc pointer\n");
> + rte_free(p);
> + return -1;
> + }
> + } else if (rte_eal_iova_mode() == RTE_IOVA_VA) {
> + if (iova != (uintptr_t)p) {
> + printf("rte_mem_virt2iova did not return VA in VA mode\n");
> + rte_free(p);
> + return -1;
> + }
> + }
> +
> + iova_off = rte_mem_virt2iova(p + off);
> + if (iova_off == RTE_BAD_IOVA || iova_off != iova + off) {
> + printf("translated iova for interior pointer is invalid\n");
> + rte_free(p);
> + return -1;
> + }
> +
> + rte_free(p);
> + return 0;
> +}
> +
> static int
> test_memory(void)
> {
> @@ -107,6 +170,10 @@ test_memory(void)
> return -1;
> }
>
> + ret = check_malloc_virt2iova();
> + if (ret < 0)
> + return ret;
> +
> return 0;
> }
>
> diff --git a/lib/eal/freebsd/eal_memory.c b/lib/eal/freebsd/eal_memory.c
> index e56d149a22..6952b38630 100644
> --- a/lib/eal/freebsd/eal_memory.c
> +++ b/lib/eal/freebsd/eal_memory.c
> @@ -40,16 +40,28 @@ RTE_EXPORT_SYMBOL(rte_mem_virt2phy)
> phys_addr_t
> rte_mem_virt2phy(const void *virtaddr)
> {
> - /* XXX not implemented. This function is only used by
> - * rte_mempool_virt2iova() when hugepages are disabled. */
> - (void)virtaddr;
> - return RTE_BAD_IOVA;
> + /* not implemented for FreeBSD when not using contigmem memory */
> + if (virtaddr == NULL || rte_eal_iova_mode() != RTE_IOVA_PA)
> + return RTE_BAD_IOVA;
> + /* when IOVA == PA, return the IOVA */
> + return rte_mem_virt2iova(virtaddr);
> }
> +
> RTE_EXPORT_SYMBOL(rte_mem_virt2iova)
> rte_iova_t
> rte_mem_virt2iova(const void *virtaddr)
> {
> - return rte_mem_virt2phy(virtaddr);
> + if (virtaddr == NULL)
> + return RTE_BAD_IOVA;
> +
> + if (rte_eal_iova_mode() == RTE_IOVA_VA)
> + return (uintptr_t)virtaddr;
> +
> + const struct rte_memseg *ms = rte_mem_virt2memseg(virtaddr, NULL);
> + if (ms != NULL && ms->iova != RTE_BAD_IOVA)
> + return ms->iova + RTE_PTR_DIFF(virtaddr, ms->addr);
> +
> + return RTE_BAD_IOVA;
> }
>
> int
> --
> 2.53.0
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH 0/2] implement missing APIs on FreeBSD
2026-05-25 17:13 [PATCH 0/2] implement missing APIs on FreeBSD Bruce Richardson
2026-05-25 17:13 ` [PATCH 1/2] eal/freebsd: fix memseg addresses in EAL VA mode Bruce Richardson
2026-05-25 17:13 ` [PATCH 2/2] eal/freebsd: implement virtual to IOVA translation fn Bruce Richardson
@ 2026-06-01 20:12 ` Thomas Monjalon
2 siblings, 0 replies; 5+ messages in thread
From: Thomas Monjalon @ 2026-06-01 20:12 UTC (permalink / raw)
To: Bruce Richardson; +Cc: dev
25/05/2026 19:13, Bruce Richardson:
> The APIs for converting a virtual address to an IOVA or a physical
> address were implemented only as stubs on FreeBSD, but unfortunately
> they are used by drivers such as "igc", part of e1000, causing the
> drivers to fail on BSD. A workaround would be to change the use of these
> functions with the rte_malloc equivalents (e.g. rte_malloc_virt2iova) -
> which do work on FreeBSD - but a better solution is just to replace the
> stubs with proper implementations in FreeBSD-specific EAL flags.
>
> Bruce Richardson (2):
> eal/freebsd: fix memseg addresses in IOVA_AS_VA mode
> eal/freebsd: implement virtual to IOVA translation fn
Applied, thanks.
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-06-01 20:12 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-25 17:13 [PATCH 0/2] implement missing APIs on FreeBSD Bruce Richardson
2026-05-25 17:13 ` [PATCH 1/2] eal/freebsd: fix memseg addresses in EAL VA mode Bruce Richardson
2026-05-25 17:13 ` [PATCH 2/2] eal/freebsd: implement virtual to IOVA translation fn Bruce Richardson
2026-05-25 18:23 ` Lewis Donzis
2026-06-01 20:12 ` [PATCH 0/2] implement missing APIs on FreeBSD Thomas Monjalon
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox