cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

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