[PATCH 7/8] net/ena: fix virtual address calc for unaligned BARs
Shai Brandes
shaibran at amazon.com
Wed May 21 16:05:52 CEST 2025
On 64K page systems, DPDK `pci_uio` driver aligns the physical
address to a 64K boundary before assigning a virtual address.
If the original physical BAR address is not 64K-aligned,
this adjustment leads to an incorrect mapping.
The fix ensures that the BAR virtual address received in the driver
accounts for both PAGE size and BAR physical offset to correctly map
each BAR. The fix is compatible for every PAGE size and applies to
every used BAR
Example:
- BAR0 physical address:
0x80208000 (not 64K-aligned)
- DPDK aligned physical address:
0x80208000 -> 0x80200000 (masking 0x8000 offset)
- DPDK mapped physical to virtual address:
0x80200000 -> 0x1140000000
- Driver accessed BAR0 virtual address:
0x1140000000 (causing init failure)
- Add correct offset to driver BAR0 address:
0x1140000000 + 0x8000 (init success)
Fixes: 1173fca25af9 ("ena: add polling-mode driver")
Cc: stable at dpdk.org
Signed-off-by: Amit Bernstein <amitbern at amazon.com>
Signed-off-by: Shai Brandes <shaibran at amazon.com>
Reviewed-by: Yosef Raisman <yraisman at amazon.com>
---
doc/guides/rel_notes/release_25_07.rst | 1 +
drivers/net/ena/ena_ethdev.c | 14 ++++++++++++--
drivers/net/ena/ena_ethdev.h | 4 ++++
3 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/doc/guides/rel_notes/release_25_07.rst b/doc/guides/rel_notes/release_25_07.rst
index 662b0db49e..ce42b81a24 100644
--- a/doc/guides/rel_notes/release_25_07.rst
+++ b/doc/guides/rel_notes/release_25_07.rst
@@ -63,6 +63,7 @@ New Features
or enabling of interrupts when operating in control path interrupt mode.
* Fixed an issue where the device might be incorrectly reported as unresponsive when using
polling-based admin queue functionality with a poll interval of less than 500 milliseconds.
+ * Fixed BAR mapping logic to handle 64K page alignment correctly, ensuring accurate offset adjustment.
* **Added Mucse rnp net driver.**
diff --git a/drivers/net/ena/ena_ethdev.c b/drivers/net/ena/ena_ethdev.c
index 182e063bf4..bdb4938231 100644
--- a/drivers/net/ena/ena_ethdev.c
+++ b/drivers/net/ena/ena_ethdev.c
@@ -2285,6 +2285,16 @@ static int ena_init_once(void)
return 0;
}
+/*
+ * Retrieve the correct PCI BAR virtual address, accounting for physical
+ * address alignment to PAGE boundary.
+ */
+static void *pci_bar_addr(struct rte_pci_device *pci_dev, uint32_t bar)
+{
+ struct rte_mem_resource *resource = &pci_dev->mem_resource[bar];
+ return RTE_PTR_ADD(resource->addr, resource->phys_addr & PAGE_MASK);
+}
+
static int eth_ena_dev_init(struct rte_eth_dev *eth_dev)
{
struct ena_calc_queue_size_ctx calc_queue_ctx = { 0 };
@@ -2330,8 +2340,7 @@ static int eth_ena_dev_init(struct rte_eth_dev *eth_dev)
intr_handle = pci_dev->intr_handle;
- adapter->regs = pci_dev->mem_resource[ENA_REGS_BAR].addr;
- adapter->dev_mem_base = pci_dev->mem_resource[ENA_MEM_BAR].addr;
+ adapter->regs = pci_bar_addr(pci_dev, ENA_REGS_BAR);
if (!adapter->regs) {
PMD_INIT_LOG_LINE(CRIT, "Failed to access registers BAR(%d)",
@@ -2340,6 +2349,7 @@ static int eth_ena_dev_init(struct rte_eth_dev *eth_dev)
}
ena_dev->reg_bar = adapter->regs;
+ adapter->dev_mem_base = pci_bar_addr(pci_dev, ENA_MEM_BAR);
/* Pass device data as a pointer which can be passed to the IO functions
* by the ena_com (for example - the memory allocation).
*/
diff --git a/drivers/net/ena/ena_ethdev.h b/drivers/net/ena/ena_ethdev.h
index e5d23e2e27..1d5d4456dc 100644
--- a/drivers/net/ena/ena_ethdev.h
+++ b/drivers/net/ena/ena_ethdev.h
@@ -16,8 +16,12 @@
#include <rte_timer.h>
#include <rte_dev.h>
#include <rte_net.h>
+#include <rte_eal_paging.h>
#include "ena_com.h"
+#ifndef PAGE_MASK
+#define PAGE_MASK (rte_mem_page_size() - 1)
+#endif
#define ENA_REGS_BAR 0
#define ENA_MEM_BAR 2
--
2.17.1
More information about the dev
mailing list