Default huge page size to the regular page size
[vpp.git] / src / vppinfra / linux / mem.c
index bceb3b2..407e923 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 the kernel doesn't support hugepages, /proc/meminfo won't
+   * say anything about it. Use the regular page size as a default.
+   */
+  size = clib_mem_get_page_size () / 1024;
+
+  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)
+clib_mem_get_fd_page_size (int fd)
 {
   struct stat st = { 0 };
   if (fstat (fd, &st) == -1)
@@ -56,9 +97,9 @@ clib_mem_vm_get_page_size (int fd)
 }
 
 int
-clib_mem_vm_get_log2_page_size (int fd)
+clib_mem_get_fd_log2_page_size (int fd)
 {
-  return min_log2 (clib_mem_vm_get_page_size (fd));
+  return min_log2 (clib_mem_get_fd_page_size (fd));
 }
 
 void
@@ -73,7 +114,79 @@ 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_fd (char *name, int *fdp)
+{
+  int fd;
+
+  ASSERT (name);
+
+  if ((fd = memfd_create (name, MFD_ALLOW_SEALING)) == -1)
+    return clib_error_return_unix (0, "memfd_create");
+
+  if ((fcntl (fd, F_ADD_SEALS, F_SEAL_SHRINK)) == -1)
+    {
+      close (fd);
+      return clib_error_return_unix (0, "fcntl (F_ADD_SEALS)");
+    }
+
+  *fdp = fd;
+  return 0;
+}
+
+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,50 +231,18 @@ 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 (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 ((err = clib_mem_create_hugetlb_fd (a->name, &fd)))
+           goto error;
 
-         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
        {
-         if ((fd = memfd_create (a->name, MFD_ALLOW_SEALING)) == -1)
-           {
-             err = clib_error_return_unix (0, "memfd_create");
-             goto error;
-           }
-
-         if ((fcntl (fd, F_ADD_SEALS, F_SEAL_SHRINK)) == -1)
-           {
-             err = clib_error_return_unix (0, "fcntl (F_ADD_SEALS)");
-             goto error;
-           }
+         if ((err = clib_mem_create_fd (a->name, &fd)))
+           goto error;
        }
 
-      log2_page_size = clib_mem_vm_get_log2_page_size (fd);
+      log2_page_size = clib_mem_get_fd_log2_page_size (fd);
       if (log2_page_size == 0)
        {
          err = clib_error_return_unix (0, "cannot determine page size");
@@ -192,8 +273,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 +332,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)
 {