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

transhuge-stress.c (2921B)


      1/*
      2 * Stress test for transparent huge pages, memory compaction and migration.
      3 *
      4 * Authors: Konstantin Khlebnikov <koct9i@gmail.com>
      5 *
      6 * This is free and unencumbered software released into the public domain.
      7 */
      8
      9#include <stdlib.h>
     10#include <stdio.h>
     11#include <stdint.h>
     12#include <err.h>
     13#include <time.h>
     14#include <unistd.h>
     15#include <fcntl.h>
     16#include <string.h>
     17#include <sys/mman.h>
     18#include "util.h"
     19
     20int backing_fd = -1;
     21int mmap_flags = MAP_ANONYMOUS | MAP_NORESERVE | MAP_PRIVATE;
     22#define PROT_RW (PROT_READ | PROT_WRITE)
     23
     24int main(int argc, char **argv)
     25{
     26	size_t ram, len;
     27	void *ptr, *p;
     28	struct timespec a, b;
     29	int i = 0;
     30	char *name = NULL;
     31	double s;
     32	uint8_t *map;
     33	size_t map_len;
     34	int pagemap_fd;
     35
     36	ram = sysconf(_SC_PHYS_PAGES);
     37	if (ram > SIZE_MAX / sysconf(_SC_PAGESIZE) / 4)
     38		ram = SIZE_MAX / 4;
     39	else
     40		ram *= sysconf(_SC_PAGESIZE);
     41	len = ram;
     42
     43	while (++i < argc) {
     44		if (!strcmp(argv[i], "-h"))
     45			errx(1, "usage: %s [size in MiB]", argv[0]);
     46		else if (!strcmp(argv[i], "-f"))
     47			name = argv[++i];
     48		else
     49			len = atoll(argv[i]) << 20;
     50	}
     51
     52	if (name) {
     53		backing_fd = open(name, O_RDWR);
     54		if (backing_fd == -1)
     55			errx(2, "open %s", name);
     56		mmap_flags = MAP_SHARED;
     57	}
     58
     59	warnx("allocate %zd transhuge pages, using %zd MiB virtual memory"
     60	      " and %zd MiB of ram", len >> HPAGE_SHIFT, len >> 20,
     61	      ram >> (20 + HPAGE_SHIFT - PAGE_SHIFT - 1));
     62
     63	pagemap_fd = open("/proc/self/pagemap", O_RDONLY);
     64	if (pagemap_fd < 0)
     65		err(2, "open pagemap");
     66
     67	len -= len % HPAGE_SIZE;
     68	ptr = mmap(NULL, len + HPAGE_SIZE, PROT_RW, mmap_flags, backing_fd, 0);
     69	if (ptr == MAP_FAILED)
     70		err(2, "initial mmap");
     71	ptr += HPAGE_SIZE - (uintptr_t)ptr % HPAGE_SIZE;
     72
     73	if (madvise(ptr, len, MADV_HUGEPAGE))
     74		err(2, "MADV_HUGEPAGE");
     75
     76	map_len = ram >> (HPAGE_SHIFT - 1);
     77	map = malloc(map_len);
     78	if (!map)
     79		errx(2, "map malloc");
     80
     81	while (1) {
     82		int nr_succeed = 0, nr_failed = 0, nr_pages = 0;
     83
     84		memset(map, 0, map_len);
     85
     86		clock_gettime(CLOCK_MONOTONIC, &a);
     87		for (p = ptr; p < ptr + len; p += HPAGE_SIZE) {
     88			int64_t pfn;
     89
     90			pfn = allocate_transhuge(p, pagemap_fd);
     91
     92			if (pfn < 0) {
     93				nr_failed++;
     94			} else {
     95				size_t idx = pfn >> (HPAGE_SHIFT - PAGE_SHIFT);
     96
     97				nr_succeed++;
     98				if (idx >= map_len) {
     99					map = realloc(map, idx + 1);
    100					if (!map)
    101						errx(2, "map realloc");
    102					memset(map + map_len, 0, idx + 1 - map_len);
    103					map_len = idx + 1;
    104				}
    105				if (!map[idx])
    106					nr_pages++;
    107				map[idx] = 1;
    108			}
    109
    110			/* split transhuge page, keep last page */
    111			if (madvise(p, HPAGE_SIZE - PAGE_SIZE, MADV_DONTNEED))
    112				err(2, "MADV_DONTNEED");
    113		}
    114		clock_gettime(CLOCK_MONOTONIC, &b);
    115		s = b.tv_sec - a.tv_sec + (b.tv_nsec - a.tv_nsec) / 1000000000.;
    116
    117		warnx("%.3f s/loop, %.3f ms/page, %10.3f MiB/s\t"
    118		      "%4d succeed, %4d failed, %4d different pages",
    119		      s, s * 1000 / (len >> HPAGE_SHIFT), len / s / (1 << 20),
    120		      nr_succeed, nr_failed, nr_pages);
    121	}
    122}