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

test_overhead_user.c (4225B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/* Copyright (c) 2016 Facebook
      3 */
      4#define _GNU_SOURCE
      5#include <sched.h>
      6#include <errno.h>
      7#include <stdio.h>
      8#include <sys/types.h>
      9#include <asm/unistd.h>
     10#include <fcntl.h>
     11#include <unistd.h>
     12#include <assert.h>
     13#include <sys/wait.h>
     14#include <stdlib.h>
     15#include <signal.h>
     16#include <linux/bpf.h>
     17#include <string.h>
     18#include <time.h>
     19#include <bpf/bpf.h>
     20#include <bpf/libbpf.h>
     21
     22#define MAX_CNT 1000000
     23
     24static struct bpf_link *links[2];
     25static struct bpf_object *obj;
     26static int cnt;
     27
     28static __u64 time_get_ns(void)
     29{
     30	struct timespec ts;
     31
     32	clock_gettime(CLOCK_MONOTONIC, &ts);
     33	return ts.tv_sec * 1000000000ull + ts.tv_nsec;
     34}
     35
     36static void test_task_rename(int cpu)
     37{
     38	__u64 start_time;
     39	char buf[] = "test\n";
     40	int i, fd;
     41
     42	fd = open("/proc/self/comm", O_WRONLY|O_TRUNC);
     43	if (fd < 0) {
     44		printf("couldn't open /proc\n");
     45		exit(1);
     46	}
     47	start_time = time_get_ns();
     48	for (i = 0; i < MAX_CNT; i++) {
     49		if (write(fd, buf, sizeof(buf)) < 0) {
     50			printf("task rename failed: %s\n", strerror(errno));
     51			close(fd);
     52			return;
     53		}
     54	}
     55	printf("task_rename:%d: %lld events per sec\n",
     56	       cpu, MAX_CNT * 1000000000ll / (time_get_ns() - start_time));
     57	close(fd);
     58}
     59
     60static void test_urandom_read(int cpu)
     61{
     62	__u64 start_time;
     63	char buf[4];
     64	int i, fd;
     65
     66	fd = open("/dev/urandom", O_RDONLY);
     67	if (fd < 0) {
     68		printf("couldn't open /dev/urandom\n");
     69		exit(1);
     70	}
     71	start_time = time_get_ns();
     72	for (i = 0; i < MAX_CNT; i++) {
     73		if (read(fd, buf, sizeof(buf)) < 0) {
     74			printf("failed to read from /dev/urandom: %s\n", strerror(errno));
     75			close(fd);
     76			return;
     77		}
     78	}
     79	printf("urandom_read:%d: %lld events per sec\n",
     80	       cpu, MAX_CNT * 1000000000ll / (time_get_ns() - start_time));
     81	close(fd);
     82}
     83
     84static void loop(int cpu, int flags)
     85{
     86	cpu_set_t cpuset;
     87
     88	CPU_ZERO(&cpuset);
     89	CPU_SET(cpu, &cpuset);
     90	sched_setaffinity(0, sizeof(cpuset), &cpuset);
     91
     92	if (flags & 1)
     93		test_task_rename(cpu);
     94	if (flags & 2)
     95		test_urandom_read(cpu);
     96}
     97
     98static void run_perf_test(int tasks, int flags)
     99{
    100	pid_t pid[tasks];
    101	int i;
    102
    103	for (i = 0; i < tasks; i++) {
    104		pid[i] = fork();
    105		if (pid[i] == 0) {
    106			loop(i, flags);
    107			exit(0);
    108		} else if (pid[i] == -1) {
    109			printf("couldn't spawn #%d process\n", i);
    110			exit(1);
    111		}
    112	}
    113	for (i = 0; i < tasks; i++) {
    114		int status;
    115
    116		assert(waitpid(pid[i], &status, 0) == pid[i]);
    117		assert(status == 0);
    118	}
    119}
    120
    121static int load_progs(char *filename)
    122{
    123	struct bpf_program *prog;
    124	int err = 0;
    125
    126	obj = bpf_object__open_file(filename, NULL);
    127	err = libbpf_get_error(obj);
    128	if (err < 0) {
    129		fprintf(stderr, "ERROR: opening BPF object file failed\n");
    130		return err;
    131	}
    132
    133	/* load BPF program */
    134	err = bpf_object__load(obj);
    135	if (err < 0) {
    136		fprintf(stderr, "ERROR: loading BPF object file failed\n");
    137		return err;
    138	}
    139
    140	bpf_object__for_each_program(prog, obj) {
    141		links[cnt] = bpf_program__attach(prog);
    142		err = libbpf_get_error(links[cnt]);
    143		if (err < 0) {
    144			fprintf(stderr, "ERROR: bpf_program__attach failed\n");
    145			links[cnt] = NULL;
    146			return err;
    147		}
    148		cnt++;
    149	}
    150
    151	return err;
    152}
    153
    154static void unload_progs(void)
    155{
    156	while (cnt)
    157		bpf_link__destroy(links[--cnt]);
    158
    159	bpf_object__close(obj);
    160}
    161
    162int main(int argc, char **argv)
    163{
    164	int num_cpu = sysconf(_SC_NPROCESSORS_ONLN);
    165	int test_flags = ~0;
    166	char filename[256];
    167	int err = 0;
    168
    169
    170	if (argc > 1)
    171		test_flags = atoi(argv[1]) ? : test_flags;
    172	if (argc > 2)
    173		num_cpu = atoi(argv[2]) ? : num_cpu;
    174
    175	if (test_flags & 0x3) {
    176		printf("BASE\n");
    177		run_perf_test(num_cpu, test_flags);
    178	}
    179
    180	if (test_flags & 0xC) {
    181		snprintf(filename, sizeof(filename),
    182			 "%s_kprobe_kern.o", argv[0]);
    183
    184		printf("w/KPROBE\n");
    185		err = load_progs(filename);
    186		if (!err)
    187			run_perf_test(num_cpu, test_flags >> 2);
    188
    189		unload_progs();
    190	}
    191
    192	if (test_flags & 0x30) {
    193		snprintf(filename, sizeof(filename),
    194			 "%s_tp_kern.o", argv[0]);
    195		printf("w/TRACEPOINT\n");
    196		err = load_progs(filename);
    197		if (!err)
    198			run_perf_test(num_cpu, test_flags >> 4);
    199
    200		unload_progs();
    201	}
    202
    203	if (test_flags & 0xC0) {
    204		snprintf(filename, sizeof(filename),
    205			 "%s_raw_tp_kern.o", argv[0]);
    206		printf("w/RAW_TRACEPOINT\n");
    207		err = load_progs(filename);
    208		if (!err)
    209			run_perf_test(num_cpu, test_flags >> 6);
    210
    211		unload_progs();
    212	}
    213
    214	return err;
    215}