#define RANDOMIZE_VA_SPACE_FILE "/proc/sys/kernel/randomize_va_space"
+uint64_t eal_get_baseaddr(void)
+{
+ /*
+ * Linux kernel uses a really high address as starting address for
+ * serving mmaps calls. If there exists addressing limitations and IOVA
+ * mode is VA, this starting address is likely too high for those
+ * devices. However, it is possible to use a lower address in the
+ * process virtual address space as with 64 bits there is a lot of
+ * available space.
+ *
+ * Current known limitations are 39 or 40 bits. Setting the starting
+ * address at 4GB implies there are 508GB or 1020GB for mapping the
+ * available hugepages. This is likely enough for most systems, although
+ * a device with addressing limitations should call
+ * rte_mem_check_dma_mask for ensuring all memory is within supported
+ * range.
+ */
+ return 0x100000000ULL;
+}
+
/*
* Get physical address of any mapped virtual address in the current process.
*/
msl->page_sz = page_sz;
msl->socket_id = socket_id;
msl->base_va = NULL;
+ msl->heap = 1; /* mark it as a heap segment */
RTE_LOG(DEBUG, EAL, "Memseg list allocated: 0x%zxkB at socket %i\n",
(size_t)page_sz >> 10, socket_id);
addr = eal_get_virtual_area(msl->base_va, &mem_sz, page_sz, 0, flags);
if (addr == NULL) {
if (rte_errno == EADDRNOTAVAIL)
- RTE_LOG(ERR, EAL, "Could not mmap %llu bytes at [%p] - please use '--base-virtaddr' option\n",
+ RTE_LOG(ERR, EAL, "Could not mmap %llu bytes at [%p] - "
+ "please use '--" OPT_BASE_VIRTADDR "' option\n",
(unsigned long long)mem_sz, msl->base_va);
else
RTE_LOG(ERR, EAL, "Cannot reserve memory\n");
/* 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
}
}
#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
* fd needs to be set up.
mem_sz = msl->len;
munmap(msl->base_va, mem_sz);
msl->base_va = NULL;
+ msl->heap = 0;
/* destroy backing fbarray */
rte_fbarray_destroy(&msl->memseg_arr);
if (flock(fd, LOCK_SH) < 0) {
RTE_LOG(DEBUG, EAL, "%s(): Locking file failed: %s\n",
__func__, strerror(errno));
- goto fd_error;
+ goto mmap_error;
}
/* find segment data */
if (msl == NULL) {
RTE_LOG(DEBUG, EAL, "%s(): Cannot find memseg list\n",
__func__);
- goto fd_error;
+ goto mmap_error;
}
ms = rte_mem_virt2memseg(map_addr, msl);
if (ms == NULL) {
RTE_LOG(DEBUG, EAL, "%s(): Cannot find memseg\n",
__func__);
- goto fd_error;
+ goto mmap_error;
}
msl_idx = msl - mcfg->memsegs;
if (ms_idx < 0) {
RTE_LOG(DEBUG, EAL, "%s(): Cannot find memseg idx\n",
__func__);
- goto fd_error;
+ goto mmap_error;
}
/* store segment fd internally */
close(fd_hugepage);
return 0;
+mmap_error:
+ munmap(hp[i].final_va, hp[i].size);
fd_error:
close(fd);
error:
- /* map all segments into memory to make sure we get the addrs */
- cur_seg = 0;
- for (cur_seg = 0; cur_seg < i; cur_seg++) {
- struct hugepage_file *hf = &hp[i];
- size_t map_sz = hf->size;
- void *map_addr = hf->final_va;
+ /* unwind mmap's done so far */
+ for (cur_seg = 0; cur_seg < i; cur_seg++)
+ munmap(hp[cur_seg].final_va, hp[cur_seg].size);
- munmap(map_addr, map_sz);
- }
if (hp != NULL && hp != MAP_FAILED)
munmap(hp, size);
if (fd_hugepage >= 0)