eal: move common header files
[dpdk.git] / lib / librte_eal / linux / eal / eal_memory.c
index 28a78a5..7a9c97f 100644 (file)
@@ -69,6 +69,26 @@ static int phys_addrs_available = -1;
 
 #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.
  */
@@ -811,6 +831,7 @@ alloc_memseg_list(struct rte_memseg_list *msl, uint64_t page_sz,
        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);
@@ -832,7 +853,8 @@ alloc_va_space(struct rte_memseg_list *msl)
        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");
@@ -1318,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
@@ -1373,17 +1397,32 @@ 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
                 * fd needs to be set up.
@@ -1656,6 +1695,7 @@ eal_legacy_hugepage_init(void)
                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);
@@ -1904,7 +1944,7 @@ eal_legacy_hugepage_attach(void)
                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 */
@@ -1912,13 +1952,13 @@ eal_legacy_hugepage_attach(void)
                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;
@@ -1926,7 +1966,7 @@ eal_legacy_hugepage_attach(void)
                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 */
@@ -1939,18 +1979,15 @@ eal_legacy_hugepage_attach(void)
        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)