> Hi Slava, > > Gentle ping on this patch, following up on the earlier pings from > Sep 11 and Oct 27. > > In the v1 discussion you mentioned the patch mostly looked good to > you and gave three suggestions — all of them are incorporated in v2 > (see the changelog): > https://patches.dpdk.org/project/dpdk/patch/[email protected]/ > > Our replies to your v1 comments, including the root cause analysis > (reg_end == hugepage_end causing the alignment to be skipped), are > here: > https://patches.dpdk.org/project/dpdk/patch/[email protected]/ > > The patch fixes a ~30% performance regression with CX7 under SMMU > (intra-NUMA pinning on Kunpeng SoC). It has been pending for about > three months — we'd really appreciate your final review. Happy to > dig further into why the hugepage placement differs between pinning > configurations, or provide more test data, if that helps. > > Thanks! > Shuaisong & Xingui
On 2026/10/27 19:32, Shuaisong Yang wrote: > Hi mlx5 team, just a gentle ping on this patch when you have a moment. Thanks! > > On 2026/9/11 14:33, yangxingui wrote: >> Kindly ping for review... >> >> On 2026/8/11 16:52, Xingui Yang wrote: >>> From: Shuaisong Yang <[email protected]> >>> >>> On Kunpeng SoC with mlx CX7, dpdk-l3fwd with intra-NUMA core pinning >>> under SMMU nonstrict/strict mode shows about 30% performance degradation >>> compared to cross-NUMA pinning. With SMMU disabled or passthrough mode, >>> intra-NUMA performs as expected (slightly better than cross-NUMA). >>> >>> CX7 in NUMA1 >>> NUMA node0 CPU(s): 0-39 >>> NUMA node1 CPU(s): 40-79 >>> >>> intra-NUMA: >>> dpdk-l3fwd -l 40-55 -n 4 -a 0000:17:00.1,mprq_en=1 -- -p 0x1 -P \ >>> --config='(0,0,40),(0,1,41),(0,2,42),(0,3,43),(0,4,44),\ >>> (0,5,45),(0,6,46),(0,7,47),(0,8,48),(0,9,49),\ >>> (0,10,50),(0,11,51),(0,12,52),(0,13,53),\ >>> (0,14,54),(0,15,55)' \ >>> --rx-queue-size=4096 --tx-queue-size=4096 --rx-burst=64 >>> >>> cross-NUMA: >>> dpdk-l3fwd -l 11-26 -n 4 -a 0000:17:00.1,mprq_en=1 -- -p 0x1 -P \ >>> --config='(0,0,11),(0,1,12),(0,2,13),(0,3,14),(0,4,15),\ >>> (0,5,16),(0,6,17),(0,7,18),(0,8,19),(0,9,20),\ >>> (0,10,21),(0,11,22),(0,12,23),(0,13,24),\ >>> (0,14,25),(0,15,26)' \ >>> --rx-queue-size=4096 --tx-queue-size=4096 --rx-burst=64 >>> >>> The root cause is that under SMMU enabled mode, the mempool allocated >>> for intra-NUMA pinning is aligned to system page size instead of >>> hugepage size, while cross-NUMA pinning correctly uses hugepage size >>> alignment. This causes high TLB miss rates under SMMU. >>> >>> Align all memory ranges to hugepage boundaries during mempool >>> registration to ensure hugepage_sz alignment, thereby reducing TLB >>> misses and fixing the intra-NUMA performance degradation. >>> >>> Fixes: 690b2a88c2f7 ("common/mlx5: add mempool registration facilities") >>> Cc: [email protected] >>> >>> Signed-off-by: Shuaisong Yang <[email protected]> >>> Signed-off-by: Xingui Yang <[email protected]> >>> --- >>> v2: >>> - Address review comments from Slava: >>> - Call rte_mem_virt2memseg_list() in a single point inside the loop. >>> - Skip the alignment block when hugepage_sz equals rte_mem_page_size(), >>> since mlx5_mempool_get_chunks() has already done the alignment. >>> - Skip the alignment for external memory with early goto, since ranges >>> are already aligned to the correct page size. >>> --- >>> .mailmap | 1 + >>> drivers/common/mlx5/mlx5_common_mr.c | 72 +++++++++++++++++++--------- >>> 2 files changed, 51 insertions(+), 22 deletions(-) >>> >>> diff --git a/.mailmap b/.mailmap >>> index fcb3d1bb3f..c8ba648d3c 100644 >>> --- a/.mailmap >>> +++ b/.mailmap >>> @@ -1999,3 +1999,4 @@ Zongyu Wu <[email protected]> >>> Zorik Machulsky <[email protected]> >>> Zyta Szpak <[email protected]> <[email protected]> >>> Zyta Szpak <[email protected]> <[email protected]> >>> +Shuaisong Yang <[email protected]> >>> diff --git a/drivers/common/mlx5/mlx5_common_mr.c >>> b/drivers/common/mlx5/mlx5_common_mr.c >>> index aa2d5e88a4..f9e1ec7468 100644 >>> --- a/drivers/common/mlx5/mlx5_common_mr.c >>> +++ b/drivers/common/mlx5/mlx5_common_mr.c >>> @@ -1524,7 +1524,11 @@ mlx5_get_mempool_ranges(struct rte_mempool *mp, bool >>> is_extmem, >>> * @param[in] is_extmem >>> * Whether the pool is contains only external pinned buffers. >>> * @param[out] out >>> - * Receives memory ranges to register, aligned to the system page size. >>> + * Receives memory ranges to register. For non-external memory, ranges >>> + * are aligned to the hugepage size if all ranges are on hugepages >>> + * of the same size, otherwise aligned to the system page size. >>> + * For external memory, ranges are kept as returned by >>> + * mlx5_get_mempool_ranges() (already aligned to the page size). >>> * The caller must release them with free(). >>> * @param[out] out_n >>> * Receives the number of @p out items. >>> @@ -1541,7 +1545,8 @@ mlx5_mempool_reg_analyze(struct rte_mempool *mp, bool >>> is_extmem, >>> { >>> struct mlx5_range *ranges = NULL; >>> unsigned int i, ranges_n = 0; >>> - struct rte_memseg_list *msl; >>> + bool same_hugepage_sz = true; >>> + uint64_t hugepage_sz = 0; >>> if (mlx5_get_mempool_ranges(mp, is_extmem, &ranges, &ranges_n) < 0) >>> { >>> DRV_LOG(ERR, "Cannot get address ranges for mempool %s", >>> @@ -1550,34 +1555,57 @@ mlx5_mempool_reg_analyze(struct rte_mempool *mp, >>> bool is_extmem, >>> } >>> /* Check if the hugepage of the pool can be shared. */ >>> *share_hugepage = false; >>> - msl = rte_mem_virt2memseg_list((void *)ranges[0].start); >>> - if (msl != NULL) { >>> - uint64_t hugepage_sz = 0; >>> + if (is_extmem) >>> + goto out; >>> + /* Check that all ranges are on pages of the same size. */ >>> + for (i = 0; i < ranges_n; i++) { >>> + struct rte_memseg_list *range_msl = >>> + rte_mem_virt2memseg_list((void *)ranges[i].start); >>> + >>> + if (range_msl == NULL) { >>> + same_hugepage_sz = false; >>> + break; >>> + } >>> + if (hugepage_sz == 0) { >>> + hugepage_sz = range_msl->page_sz; >>> + } else if (range_msl->page_sz != hugepage_sz) { >>> + same_hugepage_sz = false; >>> + break; >>> + } >>> + } >>> + /* >>> + * Align ranges to the hugepage boundaries and merge adjacent ones. >>> + * If the entire pool fits in a single hugepage, the MR for this >>> + * hugepage can be shared across mempools. >>> + */ >>> + if (same_hugepage_sz && hugepage_sz > rte_mem_page_size()) { >>> + unsigned int orig_ranges_n = ranges_n; >>> - /* Check that all ranges are on pages of the same size. */ >>> for (i = 0; i < ranges_n; i++) { >>> - if (hugepage_sz != 0 && hugepage_sz != msl->page_sz) >>> - break; >>> - hugepage_sz = msl->page_sz; >>> + ranges[i].start = RTE_ALIGN_FLOOR(ranges[i].start, >>> + hugepage_sz); >>> + ranges[i].end = RTE_ALIGN_CEIL(ranges[i].end, >>> + hugepage_sz); >>> } >>> - if (i == ranges_n) { >>> - /* >>> - * If the entire pool is within one hugepage, >>> - * combine all ranges into one of the hugepage size. >>> - */ >>> - uintptr_t reg_start = ranges[0].start; >>> - uintptr_t reg_end = ranges[ranges_n - 1].end; >>> - uintptr_t hugepage_start = >>> - RTE_ALIGN_FLOOR(reg_start, hugepage_sz); >>> - uintptr_t hugepage_end = hugepage_start + hugepage_sz; >>> - if (reg_end < hugepage_end) { >>> - ranges[0].start = hugepage_start; >>> + ranges_n = 1; >>> + for (i = 1; i < orig_ranges_n; i++) { >>> + if (ranges[ranges_n - 1].end >= ranges[i].start) >>> + ranges[ranges_n - 1].end = >>> + RTE_MAX(ranges[ranges_n - 1].end, >>> + ranges[i].end); >>> + else >>> + ranges[ranges_n++] = ranges[i]; >>> + } >>> + if (ranges_n == 1) { >>> + uintptr_t hugepage_end = ranges[0].start + hugepage_sz; >>> + >>> + if (ranges[0].end <= hugepage_end) { >>> ranges[0].end = hugepage_end; >>> - ranges_n = 1; >>> *share_hugepage = true; >>> } >>> } >>> } >>> +out: >>> *out = ranges; >>> *out_n = ranges_n; >>> return 0; >>> >

