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