Re: [PATCH] common/mlx5: fix high SMMU TLB miss with mempool alignment

yangxingui <[email protected]>
Newsgroups org.dpdk.dev
Message-ID <[email protected]>
Hi Slava,

Thanks for the review.

On 2026/8/6 15:56, Slava Ovsiienko wrote:
> Hi,
> 
> Why does cross-NUMA pinning cause the huge page size alignment?

In practice, scenarios involving intra-NUMA binding encounter issues 
with huge-page alignment.

Even with the loop bug (alignment block always entered), there is a
second issue: the if (reg_end < hugepage_end) gate uses strict <
instead of <=.
Runtime data with 1 GB hugepages on Kunpeng SoC + CX7 (NUMA1), MPRQ
enabled, 16 cores, 16 queues, queue-size 4096:
intra-NUMA (-l 40-55, all on NUMA1):
   reg_start       = 0x121b76f000
   reg_end         = 0x1240000000
   hugepage_start  = 0x1200000000
   hugepage_end    = 0x1240000000
Here reg_end == hugepage_end, so reg_end < hugepage_end is false.
Alignment is skipped, reg_start stays at 0x121b76f000 (not aligned to
the 1 GB boundary) → high TLB miss rate under SMMU.
cross-NUMA (-l 11-26, all on NUMA0, CX7 on NUMA1):
   reg_start       = 0x11d93b5000
   reg_end         = 0x11fdc46000
   hugepage_start  = 0x11c0000000
   hugepage_end    = 0x1200000000
Here reg_end (0x11fdc46000) < hugepage_end (0x1200000000) is true.
Alignment runs: reg_start → hugepage_start, reg_end → hugepage_end
→ MR is hugepage-aligned → no excessive TLB misses.
In both cases the mempool (~585 MB) fits within a single 1 GB hugepage
and reg_start is NOT aligned. The only difference is whether reg_end
happens to coincide with hugepage_end. The intra-NUMA case happens to
fill the hugepage to its exact end, which makes the < check fail.
The mempool is always allocated on NUMA1 via rte_mempool_create with
numa_node = dev->device->numa_node. We don't yet have a definitive
explanation for why the placement differs between the two pinning
configurations — it likely depends on the hugepage allocator's internal
state. But the key point is that alignment should not depend on this
coincidence; reg_start should be aligned regardless of where reg_end
falls.

> It seems we have a bug in the current code (and the patch fixes it somehow ) -
> the loop  "/* Check that all ranges are on pages of the same size. */"
> does not depend on iteration variable "I" and always runs till the end.
You are right about the loop bug — the original
loop always runs to completion because it uses msl->page_sz (fetched
once before the loop) instead of each range's own memseg list. Our
patch fixes this by calling rte_mem_virt2memseg_list() inside the loop.
> 
> The patch mostly looks good to me, there are just my 5 cents to improve:
> 
> 1.
>>    	msl = rte_mem_virt2memseg_list((void *)ranges[0].start);
> We could move this into the checking loop inside (prefertable). Or start the loop from i=1.
> Just to have rte_mem_virt2memseg_list() call in single point.
>>    	if (msl != NULL) {
>> -		uint64_t hugepage_sz = 0;
>> +		hugepage_sz = msl->page_sz;


> 2.
>> +	if (same_hugepage_sz && hugepage_sz > 0) {
>> +		unsigned int orig_ranges_n = ranges_n;
> No sense to run this code if hugepage_sz is equal to rte_mem_page_size (),
> all alignment and range merging is done by mlx5_mempool_get_chunks().
> 
> 3. Also, I would be careful about external memory. All ranges are already
> aligned to the correct page sizes, so let's add "if !is_extmem" checking.
> 

I will update the version based on your suggestions.

Thanks,
Xingui
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.