vppinfra: autodetect default hugepage size
[vpp.git] / src / vppinfra / linux / mem.c
index bceb3b2..6a551ec 100644 (file)
 #define F_SEAL_WRITE    0x0008 /* prevent writes */
 #endif
 
+
+uword
+clib_mem_get_page_size (void)
+{
+  return getpagesize ();
+}
+
+uword
+clib_mem_get_default_hugepage_size (void)
+{
+  unformat_input_t input;
+  static u32 size = 0;
+  int fd;
+
+  if (size)
+    goto done;
+
+  if ((fd = open ("/proc/meminfo", 0)) == -1)
+    return 0;
+
+  unformat_init_clib_file (&input, fd);
+
+  while (unformat_check_input (&input) != UNFORMAT_END_OF_INPUT)
+    {
+      if (unformat (&input, "Hugepagesize:%_%u kB", &size))
+       ;
+      else
+       unformat_skip_line (&input);
+    }
+  unformat_free (&input);
+  close (fd);
+done:
+  return 1024ULL * size;
+}
+
 u64
 clib_mem_vm_get_page_size (int fd)
 {
@@ -73,7 +108,59 @@ clib_mem_vm_randomize_va (uword * requested_va, u32 log2_page_size)
   else
     bit_mask = 0;
 
-  *requested_va += (clib_cpu_time_now () & bit_mask) * (1 << log2_page_size);
+  *requested_va +=
+    (clib_cpu_time_now () & bit_mask) * (1ull << log2_page_size);
+}
+
+#ifndef MFD_HUGETLB
+#define MFD_HUGETLB 0x0004U
+#endif
+
+clib_error_t *
+clib_mem_create_hugetlb_fd (char *name, int *fdp)
+{
+  clib_error_t *err = 0;
+  int fd = -1;
+  static int memfd_hugetlb_supported = 1;
+  char *mount_dir;
+  char template[] = "/tmp/hugepage_mount.XXXXXX";
+  u8 *filename;
+
+  ASSERT (name);
+
+  if (memfd_hugetlb_supported)
+    {
+      if ((fd = memfd_create (name, MFD_HUGETLB)) != -1)
+       goto done;
+
+      /* avoid further tries if memfd MFD_HUGETLB is not supported */
+      if (errno == EINVAL && strnlen (name, 256) <= 249)
+       memfd_hugetlb_supported = 0;
+    }
+
+  mount_dir = mkdtemp (template);
+  if (mount_dir == 0)
+    return clib_error_return_unix (0, "mkdtemp \'%s\'", template);
+
+  if (mount ("none", (char *) mount_dir, "hugetlbfs", 0, NULL))
+    {
+      rmdir ((char *) mount_dir);
+      err = clib_error_return_unix (0, "mount hugetlb directory '%s'",
+                                   mount_dir);
+    }
+
+  filename = format (0, "%s/%s%c", mount_dir, name, 0);
+  fd = open ((char *) filename, O_CREAT | O_RDWR, 0755);
+  umount2 ((char *) mount_dir, MNT_DETACH);
+  rmdir ((char *) mount_dir);
+
+  if (fd == -1)
+    err = clib_error_return_unix (0, "open");
+
+done:
+  if (fd != -1)
+    fdp[0] = fd;
+  return err;
 }
 
 clib_error_t *
@@ -118,32 +205,9 @@ clib_mem_vm_ext_alloc (clib_mem_vm_alloc_t * a)
       /* if hugepages are needed we need to create mount point */
       if (a->flags & CLIB_MEM_VM_F_HUGETLB)
        {
-         char *mount_dir;
-         char template[] = "/tmp/hugepage_mount.XXXXXX";
-
-         mount_dir = mkdtemp (template);
-         if (mount_dir == 0)
-           return clib_error_return_unix (0, "mkdtemp \'%s\'", template);
+         if ((err = clib_mem_create_hugetlb_fd (a->name, &fd)))
+           goto error;
 
-         if (mount ("none", (char *) mount_dir, "hugetlbfs", 0, NULL))
-           {
-             rmdir ((char *) mount_dir);
-             err = clib_error_return_unix (0, "mount hugetlb directory '%s'",
-                                           mount_dir);
-             goto error;
-           }
-
-         filename = format (0, "%s/%s%c", mount_dir, a->name, 0);
-
-         if ((fd = open ((char *) filename, O_CREAT | O_RDWR, 0755)) == -1)
-           {
-             umount2 ((char *) mount_dir, MNT_DETACH);
-             rmdir ((char *) mount_dir);
-             err = clib_error_return_unix (0, "open");
-             goto error;
-           }
-         umount2 ((char *) mount_dir, MNT_DETACH);
-         rmdir ((char *) mount_dir);
          mmap_flags |= MAP_LOCKED;
        }
       else
@@ -192,8 +256,7 @@ clib_mem_vm_ext_alloc (clib_mem_vm_alloc_t * a)
 
   if (a->flags & CLIB_MEM_VM_F_HUGETLB_PREALLOC)
     {
-      err = clib_sysfs_prealloc_hugepages (a->numa_node,
-                                          1 << (log2_page_size - 10),
+      err = clib_sysfs_prealloc_hugepages (a->numa_node, log2_page_size,
                                           n_pages);
       if (err)
        goto error;
@@ -252,6 +315,17 @@ done:
   return err;
 }
 
+void
+clib_mem_vm_ext_free (clib_mem_vm_alloc_t * a)
+{
+  if (a != 0)
+    {
+      clib_mem_vm_free (a->addr, 1ull << a->log2_page_size);
+      if (a->fd != -1)
+       close (a->fd);
+    }
+}
+
 u64 *
 clib_mem_vm_get_paddr (void *mem, int log2_page_size, int n_pages)
 {