X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=lib%2Flibrte_eal%2Flinux%2Feal%2Feal_memory.c;h=7a9c97ff8854e799a1f30cb34937a554d2d213ac;hb=9c1e0dc39a03c95447095241eaf3764d2e0dd003;hp=319352521e55222230fea093920b310a32e9da2a;hpb=70d284ab8262e81600d76456c7819af2913aa164;p=dpdk.git diff --git a/lib/librte_eal/linux/eal/eal_memory.c b/lib/librte_eal/linux/eal/eal_memory.c index 319352521e..7a9c97ff88 100644 --- a/lib/librte_eal/linux/eal/eal_memory.c +++ b/lib/librte_eal/linux/eal/eal_memory.c @@ -3,7 +3,6 @@ * Copyright(c) 2013 6WIND S.A. */ -#define _FILE_OFFSET_BITS 64 #include #include #include @@ -39,7 +38,6 @@ #include #include #include -#include #include #include #include @@ -47,6 +45,7 @@ #include "eal_private.h" #include "eal_memalloc.h" +#include "eal_memcfg.h" #include "eal_internal_cfg.h" #include "eal_filesystem.h" #include "eal_hugepages.h" @@ -66,32 +65,28 @@ * zone as well as a physical contiguous zone. */ -static bool phys_addrs_available = true; +static int phys_addrs_available = -1; #define RANDOMIZE_VA_SPACE_FILE "/proc/sys/kernel/randomize_va_space" -static void -test_phys_addrs_available(void) +uint64_t eal_get_baseaddr(void) { - uint64_t tmp = 0; - phys_addr_t physaddr; - - if (!rte_eal_has_hugepages()) { - RTE_LOG(ERR, EAL, - "Started without hugepages support, physical addresses not available\n"); - phys_addrs_available = false; - return; - } - - physaddr = rte_mem_virt2phy(&tmp); - if (physaddr == RTE_BAD_PHYS_ADDR) { - if (rte_eal_iova_mode() == RTE_IOVA_PA) - RTE_LOG(ERR, EAL, - "Cannot obtain physical addresses: %s. " - "Only vfio will function.\n", - strerror(errno)); - phys_addrs_available = false; - } + /* + * 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; } /* @@ -106,8 +101,7 @@ rte_mem_virt2phy(const void *virtaddr) int page_size; off_t offset; - /* Cannot parse /proc/self/pagemap, no need to log errors everywhere */ - if (!phys_addrs_available) + if (phys_addrs_available == 0) return RTE_BAD_IOVA; /* standard page size */ @@ -713,7 +707,7 @@ remap_segment(struct hugepage_file *hugepages, int seg_start, int seg_end) return -1; } -#ifdef RTE_ARCH_PPC64 +#ifdef RTE_ARCH_PPC_64 /* for PPC64 we go through the list backwards */ for (cur_page = seg_end - 1; cur_page >= seg_start; cur_page--, ms_idx++) { @@ -837,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); @@ -858,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"); @@ -1089,6 +1085,7 @@ remap_needed_hugepages(struct hugepage_file *hugepages, int n_pages) return 0; } +__rte_unused /* function is unused on 32-bit builds */ static inline uint64_t get_socket_mem_size(int socket) { @@ -1336,8 +1333,6 @@ eal_legacy_hugepage_init(void) int nr_hugefiles, nr_hugepages = 0; void *addr; - test_phys_addrs_available(); - memset(used_hp, 0, sizeof(used_hp)); /* get pointer to global configuration */ @@ -1345,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 @@ -1400,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. @@ -1443,7 +1455,7 @@ eal_legacy_hugepage_init(void) if (mcfg->dma_maskbits && rte_mem_check_dma_mask_thread_unsafe(mcfg->dma_maskbits)) { RTE_LOG(ERR, EAL, - "%s(): couldnt allocate memory due to IOVA exceeding limits of current DMA mask.\n", + "%s(): couldn't allocate memory due to IOVA exceeding limits of current DMA mask.\n", __func__); if (rte_eal_iova_mode() == RTE_IOVA_VA && rte_eal_using_phys_addrs()) @@ -1516,7 +1528,7 @@ eal_legacy_hugepage_init(void) continue; } - if (phys_addrs_available && + if (rte_eal_using_phys_addrs() && rte_eal_iova_mode() != RTE_IOVA_VA) { /* find physical addresses for each hugepage */ if (find_physaddrs(&tmp_hp[hp_offset], hpi) < 0) { @@ -1683,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); @@ -1735,8 +1748,6 @@ eal_hugepage_init(void) uint64_t memory[RTE_MAX_NUMA_NODES]; int hp_sz_idx, socket_id; - test_phys_addrs_available(); - memset(used_hp, 0, sizeof(used_hp)); for (hp_sz_idx = 0; @@ -1879,8 +1890,6 @@ eal_legacy_hugepage_attach(void) "into secondary processes\n"); } - test_phys_addrs_available(); - fd_hugepage = open(eal_hugepage_data_path(), O_RDONLY); if (fd_hugepage < 0) { RTE_LOG(ERR, EAL, "Could not open %s\n", @@ -1935,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 */ @@ -1943,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; @@ -1957,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 */ @@ -1970,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) @@ -2020,6 +2026,15 @@ rte_eal_hugepage_attach(void) int rte_eal_using_phys_addrs(void) { + if (phys_addrs_available == -1) { + uint64_t tmp = 0; + + if (rte_eal_has_hugepages() != 0 && + rte_mem_virt2phy(&tmp) != RTE_BAD_PHYS_ADDR) + phys_addrs_available = 1; + else + phys_addrs_available = 0; + } return phys_addrs_available; }