xref: /aosp_15_r20/external/linux-kselftest/tools/testing/selftests/vm/util.h (revision 053f45be4e351dfd5e965df293cd45b779f579ee)
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