/*
 * Copyright (c) 2017 Cisco and/or its affiliates.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at:
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#define _GNU_SOURCE
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/mount.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <linux/mempolicy.h>
#include <linux/memfd.h>

#include <vppinfra/clib.h>
#include <vppinfra/mem.h>
#include <vppinfra/time.h>
#include <vppinfra/format.h>
#include <vppinfra/clib_error.h>
#include <vppinfra/linux/syscall.h>
#include <vppinfra/linux/sysfs.h>

#ifndef F_LINUX_SPECIFIC_BASE
#define F_LINUX_SPECIFIC_BASE 1024
#endif

#ifndef F_ADD_SEALS
#define F_ADD_SEALS (F_LINUX_SPECIFIC_BASE + 9)
#define F_GET_SEALS (F_LINUX_SPECIFIC_BASE + 10)

#define F_SEAL_SEAL     0x0001	/* prevent further seals from being set */
#define F_SEAL_SHRINK   0x0002	/* prevent file from shrinking */
#define F_SEAL_GROW     0x0004	/* prevent file from growing */
#define F_SEAL_WRITE    0x0008	/* prevent writes */
#endif

uword
clib_mem_vm_get_page_size (int fd)
{
  struct stat st = { 0 };
  if (fstat (fd, &st) == -1)
    return 0;
  return st.st_blksize;
}

int
clib_mem_vm_get_log2_page_size (int fd)
{
  return min_log2 (clib_mem_vm_get_page_size (fd));
}

void
clib_mem_vm_randomize_va (uword * requested_va, u32 log2_page_size)
{
  u8 bit_mask = 15;

  if (log2_page_size <= 12)
    bit_mask = 15;
  else if (log2_page_size > 12 && log2_page_size <= 16)
    bit_mask = 3;
  else
    bit_mask = 0;

  *requested_va += (clib_cpu_time_now () & bit_mask) * (1 << log2_page_size);
}

clib_error_t *
clib_mem_vm_ext_alloc (clib_mem_vm_alloc_t * a)
{
  int fd = -1;
  clib_error_t *err = 0;
  void *addr = 0;
  u8 *filename = 0;
  int mmap_flags = 0;
  int log2_page_size;
  int n_pages;
  int old_mpol = -1;
  u64 old_mask[16] = { 0 };

  /* save old numa mem policy if needed */
  if (a->flags & (CLIB_MEM_VM_F_NUMA_PREFER | CLIB_MEM_VM_F_NUMA_FORCE))
    {
      int rv;
      rv = get_mempolicy (&old_mpol, old_mask, sizeof (old_mask) * 8 + 1,
			  0, 0);

      if (rv == -1)
	{
	  if (a->numa_node != 0 && (a->flags & CLIB_MEM_VM_F_NUMA_FORCE) != 0)
	    {
	      err = clib_error_return_unix (0, "get_mempolicy");
	      goto error;
	    }
	  else
	    old_mpol = -1;
	}
    }

  if (a->flags & CLIB_MEM_VM_F_LOCKED)
    mmap_flags |= MAP_LOCKED;

  /* if we are creating shared segment, we need file descriptor */
  if (a->flags & CLIB_MEM_VM_F_SHARED)
    {
      mmap_flags |= MAP_SHARED;
      /* 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))
	    {
	      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)
	    {
	      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;
	    }
	}

      log2_page_size = clib_mem_vm_get_log2_page_size (fd);
      if (log2_page_size == 0)
	{
	  err = clib_error_return_unix (0, "cannot determine page size");
	  goto error;
	}

      if (a->requested_va)
	{
	  clib_mem_vm_randomize_va (&a->requested_va, log2_page_size);
	  mmap_flags |= MAP_FIXED;
	}
    }
  else				/* not CLIB_MEM_VM_F_SHARED */
    {
      mmap_flags |= MAP_PRIVATE | MAP_ANONYMOUS;
      if (a->flags & CLIB_MEM_VM_F_HUGETLB)
	{
	  mmap_flags |= MAP_HUGETLB;
	  log2_page_size = 21;
	}
      else
	{
	  log2_page_size = min_log2 (sysconf (_SC_PAGESIZE));
	}
    }

  n_pages = ((a->size - 1) >> log2_page_size) + 1;

  if (a->flags & CLIB_MEM_VM_F_HUGETLB_PREALLOC)
    {
      err = clib_sysfs_prealloc_hugepages (a->numa_node,
					   1 << (log2_page_size - 10),
					   n_pages);
      if (err)
	goto error;

    }

  if (fd != -1)
    if ((ftruncate (fd, (u64) n_pages * (1 << log2_page_size))) == -1)
      {
	err = clib_error_return_unix (0, "ftruncate");
	goto error;
      }

  if (old_mpol != -1)
    {
      int rv;
      u64 mask[16] = { 0 };
      mask[0] = 1 << a->numa_node;
      rv = set_mempolicy (MPOL_BIND, mask, sizeof (mask) * 8 + 1);
      if (rv)
	{
	  err = clib_error_return_unix (0, "set_mempolicy");
	  goto error;
	}
    }

  addr = mmap (uword_to_pointer (a->requested_va, void *), a->size,
	       (PROT_READ | PROT_WRITE), mmap_flags, fd, 0);
  if (addr == MAP_FAILED)
    {
      err = clib_error_return_unix (0, "mmap");
      goto error;
    }

  /* re-apply old numa memory policy */
  if (old_mpol != -1 &&
      set_mempolicy (old_mpol, old_mask, sizeof (old_mask) * 8 + 1) == -1)
    {
      err = clib_error_return_unix (0, "set_mempolicy");
      goto error;
    }

  a->log2_page_size = log2_page_size;
  a->n_pages = n_pages;
  a->addr = addr;
  a->fd = fd;
  goto done;

error:
  if (fd != -1)
    close (fd);

done:
  vec_free (filename);
  return err;
}

u64 *
clib_mem_vm_get_paddr (void *mem, int log2_page_size, int n_pages)
{
  int pagesize = sysconf (_SC_PAGESIZE);
  int fd;
  int i;
  u64 *r = 0;

  if ((fd = open ((char *) "/proc/self/pagemap", O_RDONLY)) == -1)
    return 0;

  for (i = 0; i < n_pages; i++)
    {
      u64 seek, pagemap = 0;
      uword vaddr = pointer_to_uword (mem) + (((u64) i) << log2_page_size);
      seek = ((u64) vaddr / pagesize) * sizeof (u64);
      if (lseek (fd, seek, SEEK_SET) != seek)
	goto done;

      if (read (fd, &pagemap, sizeof (pagemap)) != (sizeof (pagemap)))
	goto done;

      if ((pagemap & (1ULL << 63)) == 0)
	goto done;

      pagemap &= pow2_mask (55);
      vec_add1 (r, pagemap * pagesize);
    }

done:
  close (fd);
  if (vec_len (r) != n_pages)
    {
      vec_free (r);
      return 0;
    }
  return r;
}

clib_error_t *
clib_mem_vm_ext_map (clib_mem_vm_map_t * a)
{
  int mmap_flags = MAP_SHARED;
  void *addr;

  if (a->requested_va)
    mmap_flags |= MAP_FIXED;

  addr = (void *) mmap (uword_to_pointer (a->requested_va, void *), a->size,
			PROT_READ | PROT_WRITE, mmap_flags, a->fd, 0);

  if (addr == MAP_FAILED)
    return clib_error_return_unix (0, "mmap");

  a->addr = addr;
  return 0;
}

/*
 * fd.io coding-style-patch-verification: ON
 *
 * Local Variables:
 * eval: (c-set-style "gnu")
 * End:
 */
