eal: add 64-bit log2 function
[dpdk.git] / lib / librte_eal / linuxapp / eal / eal_memalloc.c
index f6a0098..60a0a68 100644 (file)
 #include <sys/time.h>
 #include <signal.h>
 #include <setjmp.h>
+#ifdef F_ADD_SEALS /* if file sealing is supported, so is memfd */
+#include <linux/memfd.h>
+#define MEMFD_SUPPORTED
+#endif
 #ifdef RTE_EAL_NUMA_AWARE_HUGEPAGES
 #include <numa.h>
 #include <numaif.h>
@@ -53,20 +57,21 @@ const int anonymous_hugepages_supported =
 #endif
 
 /*
- * we don't actually care if memfd itself is supported - we only need to check
- * if memfd supports hugetlbfs, as that already implies memfd support.
+ * we've already checked memfd support at compile-time, but we also need to
+ * check if we can create hugepage files with memfd.
  *
  * also, this is not a constant, because while we may be *compiled* with memfd
  * hugetlbfs support, we might not be *running* on a system that supports memfd
  * and/or memfd with hugetlbfs, so we need to be able to adjust this flag at
  * runtime, and fall back to anonymous memory.
  */
-int memfd_create_supported =
+static int memfd_create_supported =
 #ifdef MFD_HUGETLB
-#define MEMFD_SUPPORTED
                1;
+#define RTE_MFD_HUGETLB MFD_HUGETLB
 #else
                0;
+#define RTE_MFD_HUGETLB 4U
 #endif
 
 /*
@@ -208,28 +213,13 @@ get_file_size(int fd)
        return st.st_size;
 }
 
-static inline uint32_t
-bsf64(uint64_t v)
-{
-       return (uint32_t)__builtin_ctzll(v);
-}
-
-static inline uint32_t
-log2_u64(uint64_t v)
-{
-       if (v == 0)
-               return 0;
-       v = rte_align64pow2(v);
-       return bsf64(v);
-}
-
 static int
 pagesz_flags(uint64_t page_sz)
 {
        /* as per mmap() manpage, all page sizes are log2 of page size
         * shifted by MAP_HUGE_SHIFT
         */
-       int log2 = log2_u64(page_sz);
+       int log2 = rte_log2_u64(page_sz);
        return log2 << RTE_MAP_HUGE_SHIFT;
 }
 
@@ -338,12 +328,12 @@ get_seg_memfd(struct hugepage_info *hi __rte_unused,
        int fd;
        char segname[250]; /* as per manpage, limit is 249 bytes plus null */
 
+       int flags = RTE_MFD_HUGETLB | pagesz_flags(hi->hugepage_sz);
+
        if (internal_config.single_file_segments) {
                fd = fd_list[list_idx].memseg_list_fd;
 
                if (fd < 0) {
-                       int flags = MFD_HUGETLB | pagesz_flags(hi->hugepage_sz);
-
                        snprintf(segname, sizeof(segname), "seg_%i", list_idx);
                        fd = memfd_create(segname, flags);
                        if (fd < 0) {
@@ -357,8 +347,6 @@ get_seg_memfd(struct hugepage_info *hi __rte_unused,
                fd = fd_list[list_idx].fds[seg_idx];
 
                if (fd < 0) {
-                       int flags = MFD_HUGETLB | pagesz_flags(hi->hugepage_sz);
-
                        snprintf(segname, sizeof(segname), "seg_%i-%i",
                                        list_idx, seg_idx);
                        fd = memfd_create(segname, flags);
@@ -753,9 +741,6 @@ mapped:
        munmap(addr, alloc_sz);
 unmapped:
        flags = MAP_FIXED;
-#ifdef RTE_ARCH_PPC_64
-       flags |= MAP_HUGETLB;
-#endif
        new_addr = eal_get_virtual_area(addr, &alloc_sz, alloc_sz, 0, flags);
        if (new_addr != addr) {
                if (new_addr != NULL)
@@ -1529,6 +1514,10 @@ eal_memalloc_set_seg_fd(int list_idx, int seg_idx, int fd)
 {
        struct rte_mem_config *mcfg = rte_eal_get_configuration()->mem_config;
 
+       /* single file segments mode doesn't support individual segment fd's */
+       if (internal_config.single_file_segments)
+               return -ENOTSUP;
+
        /* if list is not allocated, allocate it */
        if (fd_list[list_idx].len == 0) {
                int len = mcfg->memsegs[list_idx].memseg_arr.len;
@@ -1541,10 +1530,43 @@ eal_memalloc_set_seg_fd(int list_idx, int seg_idx, int fd)
        return 0;
 }
 
+int
+eal_memalloc_set_seg_list_fd(int list_idx, int fd)
+{
+       struct rte_mem_config *mcfg = rte_eal_get_configuration()->mem_config;
+
+       /* non-single file segment mode doesn't support segment list fd's */
+       if (!internal_config.single_file_segments)
+               return -ENOTSUP;
+
+       /* if list is not allocated, allocate it */
+       if (fd_list[list_idx].len == 0) {
+               int len = mcfg->memsegs[list_idx].memseg_arr.len;
+
+               if (alloc_list(list_idx, len) < 0)
+                       return -ENOMEM;
+       }
+
+       fd_list[list_idx].memseg_list_fd = fd;
+
+       return 0;
+}
+
 int
 eal_memalloc_get_seg_fd(int list_idx, int seg_idx)
 {
        int fd;
+
+       if (internal_config.in_memory || internal_config.no_hugetlbfs) {
+#ifndef MEMFD_SUPPORTED
+               /* in in-memory or no-huge mode, we rely on memfd support */
+               return -ENOTSUP;
+#endif
+               /* memfd supported, but hugetlbfs memfd may not be */
+               if (!internal_config.no_hugetlbfs && !memfd_create_supported)
+                       return -ENOTSUP;
+       }
+
        if (internal_config.single_file_segments) {
                fd = fd_list[list_idx].memseg_list_fd;
        } else if (fd_list[list_idx].len == 0) {
@@ -1568,7 +1590,7 @@ test_memfd_create(void)
                int pagesz_flag = pagesz_flags(pagesz);
                int flags;
 
-               flags = pagesz_flag | MFD_HUGETLB;
+               flags = pagesz_flag | RTE_MFD_HUGETLB;
                int fd = memfd_create("test", flags);
                if (fd < 0) {
                        /* we failed - let memalloc know this isn't working */
@@ -1592,6 +1614,16 @@ eal_memalloc_get_seg_fd_offset(int list_idx, int seg_idx, size_t *offset)
 {
        struct rte_mem_config *mcfg = rte_eal_get_configuration()->mem_config;
 
+       if (internal_config.in_memory || internal_config.no_hugetlbfs) {
+#ifndef MEMFD_SUPPORTED
+               /* in in-memory or no-huge mode, we rely on memfd support */
+               return -ENOTSUP;
+#endif
+               /* memfd supported, but hugetlbfs memfd may not be */
+               if (!internal_config.no_hugetlbfs && !memfd_create_supported)
+                       return -ENOTSUP;
+       }
+
        /* fd_list not initialized? */
        if (fd_list[list_idx].len == 0)
                return -ENODEV;