util.h 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. #ifndef __KSELFTEST_VM_UTIL_H
  3. #define __KSELFTEST_VM_UTIL_H
  4. #include <stdint.h>
  5. #include <sys/mman.h>
  6. #include <err.h>
  7. #include <string.h> /* ffsl() */
  8. #include <unistd.h> /* _SC_PAGESIZE */
  9. static unsigned int __page_size;
  10. static unsigned int __page_shift;
  11. static inline unsigned int page_size(void)
  12. {
  13. if (!__page_size)
  14. __page_size = sysconf(_SC_PAGESIZE);
  15. return __page_size;
  16. }
  17. static inline unsigned int page_shift(void)
  18. {
  19. if (!__page_shift)
  20. __page_shift = (ffsl(page_size()) - 1);
  21. return __page_shift;
  22. }
  23. #define PAGE_SHIFT (page_shift())
  24. #define PAGE_SIZE (page_size())
  25. /*
  26. * On ppc64 this will only work with radix 2M hugepage size
  27. */
  28. #define HPAGE_SHIFT 21
  29. #define HPAGE_SIZE (1 << HPAGE_SHIFT)
  30. #define PAGEMAP_PRESENT(ent) (((ent) & (1ull << 63)) != 0)
  31. #define PAGEMAP_PFN(ent) ((ent) & ((1ull << 55) - 1))
  32. static inline int64_t allocate_transhuge(void *ptr, int pagemap_fd)
  33. {
  34. uint64_t ent[2];
  35. /* drop pmd */
  36. if (mmap(ptr, HPAGE_SIZE, PROT_READ | PROT_WRITE,
  37. MAP_FIXED | MAP_ANONYMOUS |
  38. MAP_NORESERVE | MAP_PRIVATE, -1, 0) != ptr)
  39. errx(2, "mmap transhuge");
  40. if (madvise(ptr, HPAGE_SIZE, MADV_HUGEPAGE))
  41. err(2, "MADV_HUGEPAGE");
  42. /* allocate transparent huge page */
  43. *(volatile void **)ptr = ptr;
  44. if (pread(pagemap_fd, ent, sizeof(ent),
  45. (uintptr_t)ptr >> (PAGE_SHIFT - 3)) != sizeof(ent))
  46. err(2, "read pagemap");
  47. if (PAGEMAP_PRESENT(ent[0]) && PAGEMAP_PRESENT(ent[1]) &&
  48. PAGEMAP_PFN(ent[0]) + 1 == PAGEMAP_PFN(ent[1]) &&
  49. !(PAGEMAP_PFN(ent[0]) & ((1 << (HPAGE_SHIFT - PAGE_SHIFT)) - 1)))
  50. return PAGEMAP_PFN(ent[0]);
  51. return -1;
  52. }
  53. #endif