Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
0002 
0003 #ifndef __KSELFTEST_VM_UTIL_H
0004 #define __KSELFTEST_VM_UTIL_H
0005 
0006 #include <stdint.h>
0007 #include <sys/mman.h>
0008 #include <err.h>
0009 #include <string.h> /* ffsl() */
0010 #include <unistd.h> /* _SC_PAGESIZE */
0011 
0012 static unsigned int __page_size;
0013 static unsigned int __page_shift;
0014 
0015 static inline unsigned int page_size(void)
0016 {
0017     if (!__page_size)
0018         __page_size = sysconf(_SC_PAGESIZE);
0019     return __page_size;
0020 }
0021 
0022 static inline unsigned int page_shift(void)
0023 {
0024     if (!__page_shift)
0025         __page_shift = (ffsl(page_size()) - 1);
0026     return __page_shift;
0027 }
0028 
0029 #define PAGE_SHIFT  (page_shift())
0030 #define PAGE_SIZE   (page_size())
0031 /*
0032  * On ppc64 this will only work with radix 2M hugepage size
0033  */
0034 #define HPAGE_SHIFT 21
0035 #define HPAGE_SIZE (1 << HPAGE_SHIFT)
0036 
0037 #define PAGEMAP_PRESENT(ent)    (((ent) & (1ull << 63)) != 0)
0038 #define PAGEMAP_PFN(ent)    ((ent) & ((1ull << 55) - 1))
0039 
0040 
0041 static inline int64_t allocate_transhuge(void *ptr, int pagemap_fd)
0042 {
0043     uint64_t ent[2];
0044 
0045     /* drop pmd */
0046     if (mmap(ptr, HPAGE_SIZE, PROT_READ | PROT_WRITE,
0047          MAP_FIXED | MAP_ANONYMOUS |
0048          MAP_NORESERVE | MAP_PRIVATE, -1, 0) != ptr)
0049         errx(2, "mmap transhuge");
0050 
0051     if (madvise(ptr, HPAGE_SIZE, MADV_HUGEPAGE))
0052         err(2, "MADV_HUGEPAGE");
0053 
0054     /* allocate transparent huge page */
0055     *(volatile void **)ptr = ptr;
0056 
0057     if (pread(pagemap_fd, ent, sizeof(ent),
0058           (uintptr_t)ptr >> (PAGE_SHIFT - 3)) != sizeof(ent))
0059         err(2, "read pagemap");
0060 
0061     if (PAGEMAP_PRESENT(ent[0]) && PAGEMAP_PRESENT(ent[1]) &&
0062         PAGEMAP_PFN(ent[0]) + 1 == PAGEMAP_PFN(ent[1]) &&
0063         !(PAGEMAP_PFN(ent[0]) & ((1 << (HPAGE_SHIFT - PAGE_SHIFT)) - 1)))
0064         return PAGEMAP_PFN(ent[0]);
0065 
0066     return -1;
0067 }
0068 
0069 #endif