From: Jun Yang <[email protected]>

Add a dpaax_enter_destructor() function that drivers call at the start
of their RTE_FINI destructors to signal that the process is tearing
down. Subsequent attempts to free EAL-backed memory (such as IOVA table
entries) are then skipped, avoiding use-after-free crashes when the EAL
has already unmapped hugepages before per-driver destructors run.

Callers updated: dpaa_bus, dpaa_mempool, dpaa_ethdev.

Signed-off-by: Jun Yang <[email protected]>
---
 drivers/bus/dpaa/dpaa_bus.c             |  1 +
 drivers/common/dpaax/compat.h           | 22 +++++++++++++++++-----
 drivers/common/dpaax/dpaax_iova_table.c | 25 ++++++++++++++++++++++++-
 drivers/mempool/dpaa/dpaa_mempool.c     |  7 ++++---
 drivers/net/dpaa/dpaa_ethdev.c          |  1 +
 5 files changed, 47 insertions(+), 9 deletions(-)

diff --git a/drivers/bus/dpaa/dpaa_bus.c b/drivers/bus/dpaa/dpaa_bus.c
index 16892b5247..01bfaacbf7 100644
--- a/drivers/bus/dpaa/dpaa_bus.c
+++ b/drivers/bus/dpaa/dpaa_bus.c
@@ -915,6 +915,7 @@ RTE_FINI_PRIO(dpaa_cleanup, 102)
        if (!dpaa_bus_global_init)
                return;
 
+       dpaax_enter_destructor();
        /* cleanup portals in case non-graceful exit */
        RTE_LCORE_FOREACH_WORKER(lcore_id) {
                /* Check for non zero id */
diff --git a/drivers/common/dpaax/compat.h b/drivers/common/dpaax/compat.h
index d0635255da..b826a55de2 100644
--- a/drivers/common/dpaax/compat.h
+++ b/drivers/common/dpaax/compat.h
@@ -2,7 +2,7 @@
  *
  * Copyright 2011 Freescale Semiconductor, Inc.
  * All rights reserved.
- * Copyright 2019-2020 NXP
+ * Copyright 2019-2020, 2026 NXP
  *
  */
 
@@ -336,11 +336,23 @@ static inline void copy_bytes(void *dest, const void 
*src, size_t sz)
 #define copy_bytes memcpy
 #endif
 
-/* Allocator stuff */
-#define kmalloc(sz, t) rte_malloc(NULL, sz, 0)
-#define kzalloc(sz, t)  rte_zmalloc(NULL, sz, 0)
+__rte_internal
+void dpaax_enter_destructor(void);
+__rte_internal
+int is_dpaax_in_destructor(void);
+
+/* Allocator stuff, make sure the eal memory pool is available when calling.*/
+#define kmalloc(sz, _t) ((void)(_t), rte_malloc(NULL, sz, 0))
+#define kzalloc(sz, _t) ((void)(_t), rte_zmalloc(NULL, sz, 0))
 #define vmalloc(sz)    rte_malloc(NULL, sz, 0)
-#define kfree(p)       rte_free(p)
+
+#define kfree(p) \
+({ \
+       if (!is_dpaax_in_destructor()) \
+               rte_free(p); \
+       else \
+               pr_debug("Eal memory has been destroyed.\n"); \
+})
 
 static inline unsigned long get_zeroed_page(gfp_t __foo __rte_unused)
 {
diff --git a/drivers/common/dpaax/dpaax_iova_table.c 
b/drivers/common/dpaax/dpaax_iova_table.c
index 1220d9654b..d53b24d4f4 100644
--- a/drivers/common/dpaax/dpaax_iova_table.c
+++ b/drivers/common/dpaax/dpaax_iova_table.c
@@ -1,17 +1,40 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright 2018-2023 NXP
+ * Copyright 2018-2023,2026 NXP
  */
 
 #include <eal_export.h>
 #include <rte_memory.h>
 
 #include "dpaax_iova_table.h"
+#include "compat.h"
 #include "dpaax_logs.h"
 
 /* Global table reference */
 RTE_EXPORT_INTERNAL_SYMBOL(dpaax_iova_table_p)
 struct dpaax_iova_table *dpaax_iova_table_p;
 
+/*
+ * Track whether the process is executing DPDK destructors. During
+ * teardown the EAL memory subsystem may already be gone, so freeing
+ * EAL memory from a DPAAx destructor is unsafe. Drivers mark the
+ * destructor context via dpaax_enter_destructor() so that kfree()
+ * (see compat.h) can skip rte_free() in that window.
+ */
+static int s_dpaax_in_destructor;
+
+RTE_EXPORT_INTERNAL_SYMBOL(dpaax_enter_destructor)
+void dpaax_enter_destructor(void)
+{
+       s_dpaax_in_destructor = 1;
+}
+
+RTE_EXPORT_INTERNAL_SYMBOL(is_dpaax_in_destructor)
+int is_dpaax_in_destructor(void)
+{
+       return s_dpaax_in_destructor;
+}
+
+
 static int dpaax_handle_memevents(void);
 
 /* A structure representing the device-tree node available in 
/proc/device-tree.
diff --git a/drivers/mempool/dpaa/dpaa_mempool.c 
b/drivers/mempool/dpaa/dpaa_mempool.c
index 1687700482..d2c68ac747 100644
--- a/drivers/mempool/dpaa/dpaa_mempool.c
+++ b/drivers/mempool/dpaa/dpaa_mempool.c
@@ -517,15 +517,16 @@ RTE_FINI_PRIO(dpaa_mpool_finish, RTE_PRIORITY_104)
 {
        uint16_t bpid;
 
+       dpaax_enter_destructor();
+
        for (bpid = 0; bpid < DPAA_MAX_BPOOLS; bpid++) {
                if (s_dpaa_bpid_allocated_flag[bpid].used) {
                        bman_free_bpid(bpid, 
s_dpaa_bpid_allocated_flag[bpid].flags);
                        s_dpaa_bpid_allocated_flag[bpid].used = false;
                }
        }
-       /** The rte_dpaa_bpid_info and bman_pool from EAL mem have been released
-        * with EAL mem pool being destroyed.
-        */
+       rte_free(rte_dpaa_bpid_info);
+       rte_dpaa_bpid_info = NULL;
 }
 
 RTE_MEMPOOL_REGISTER_OPS(dpaa_mpool_ops);
diff --git a/drivers/net/dpaa/dpaa_ethdev.c b/drivers/net/dpaa/dpaa_ethdev.c
index 1751a7dd1a..d6da3a329a 100644
--- a/drivers/net/dpaa/dpaa_ethdev.c
+++ b/drivers/net/dpaa/dpaa_ethdev.c
@@ -2824,6 +2824,7 @@ RTE_FINI_PRIO(dpaa_finish, 103)
        struct rte_eth_dev *dev;
 
        PMD_INIT_FUNC_TRACE();
+       dpaax_enter_destructor();
        /* For secondary, primary will do all the cleanup */
        if (rte_eal_process_type() != RTE_PROC_PRIMARY)
                return;
-- 
2.25.1

Reply via email to