From 4236694f0ae466b174a73a29df4cfa94753793f0 Mon Sep 17 00:00:00 2001 From: Anatoly Burakov Date: Fri, 7 Feb 2020 11:11:14 +0000 Subject: [PATCH] mem: preallocate VA space in no-huge mode When --no-huge mode is used, the memory is currently allocated with mmap(NULL, ...). This is fine in most cases, but can fail in cases where DPDK is run on a machine with an IOMMU that is of more limited address width than that of a VA, because we're not specifying the address hint for mmap() call. Fix it by preallocating VA space before mapping it. Cc: stable@dpdk.org Signed-off-by: Anatoly Burakov Tested-by: David Marchand Tested-by: Jun W Zhou --- lib/librte_eal/linux/eal/eal_memory.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/lib/librte_eal/linux/eal/eal_memory.c b/lib/librte_eal/linux/eal/eal_memory.c index 5604c2a7c0..7a9c97ff88 100644 --- a/lib/librte_eal/linux/eal/eal_memory.c +++ b/lib/librte_eal/linux/eal/eal_memory.c @@ -1340,6 +1340,8 @@ eal_legacy_hugepage_init(void) /* hugetlbfs can be disabled */ if (internal_config.no_hugetlbfs) { + void *prealloc_addr; + size_t mem_sz; struct rte_memseg_list *msl; int n_segs, cur_seg, fd, flags; #ifdef MEMFD_SUPPORTED @@ -1395,17 +1397,31 @@ eal_legacy_hugepage_init(void) } } #endif - addr = mmap(NULL, internal_config.memory, PROT_READ | PROT_WRITE, - flags, fd, 0); - if (addr == MAP_FAILED) { + /* preallocate address space for the memory, so that it can be + * fit into the DMA mask. + */ + mem_sz = internal_config.memory; + prealloc_addr = eal_get_virtual_area( + NULL, &mem_sz, page_sz, 0, 0); + if (prealloc_addr == NULL) { + RTE_LOG(ERR, EAL, + "%s: reserving memory area failed: " + "%s\n", + __func__, strerror(errno)); + return -1; + } + addr = mmap(prealloc_addr, mem_sz, PROT_READ | PROT_WRITE, + flags | MAP_FIXED, fd, 0); + if (addr == MAP_FAILED || addr != prealloc_addr) { RTE_LOG(ERR, EAL, "%s: mmap() failed: %s\n", __func__, strerror(errno)); + munmap(prealloc_addr, mem_sz); return -1; } msl->base_va = addr; msl->page_sz = page_sz; msl->socket_id = 0; - msl->len = internal_config.memory; + msl->len = mem_sz; msl->heap = 1; /* we're in single-file segments mode, so only the segment list -- 2.20.1