util.h (1641B)
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