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