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-evsel.c (4904B)


      1// SPDX-License-Identifier: GPL-2.0
      2#include <stdarg.h>
      3#include <stdio.h>
      4#include <linux/perf_event.h>
      5#include <perf/cpumap.h>
      6#include <perf/threadmap.h>
      7#include <perf/evsel.h>
      8#include <internal/tests.h>
      9#include "tests.h"
     10
     11static int libperf_print(enum libperf_print_level level,
     12			 const char *fmt, va_list ap)
     13{
     14	return vfprintf(stderr, fmt, ap);
     15}
     16
     17static int test_stat_cpu(void)
     18{
     19	struct perf_cpu_map *cpus;
     20	struct perf_evsel *evsel;
     21	struct perf_event_attr attr = {
     22		.type	= PERF_TYPE_SOFTWARE,
     23		.config	= PERF_COUNT_SW_CPU_CLOCK,
     24	};
     25	int err, idx;
     26
     27	cpus = perf_cpu_map__new(NULL);
     28	__T("failed to create cpus", cpus);
     29
     30	evsel = perf_evsel__new(&attr);
     31	__T("failed to create evsel", evsel);
     32
     33	err = perf_evsel__open(evsel, cpus, NULL);
     34	__T("failed to open evsel", err == 0);
     35
     36	for (idx = 0; idx < perf_cpu_map__nr(cpus); idx++) {
     37		struct perf_counts_values counts = { .val = 0 };
     38
     39		perf_evsel__read(evsel, idx, 0, &counts);
     40		__T("failed to read value for evsel", counts.val != 0);
     41	}
     42
     43	perf_evsel__close(evsel);
     44	perf_evsel__delete(evsel);
     45
     46	perf_cpu_map__put(cpus);
     47	return 0;
     48}
     49
     50static int test_stat_thread(void)
     51{
     52	struct perf_counts_values counts = { .val = 0 };
     53	struct perf_thread_map *threads;
     54	struct perf_evsel *evsel;
     55	struct perf_event_attr attr = {
     56		.type	= PERF_TYPE_SOFTWARE,
     57		.config	= PERF_COUNT_SW_TASK_CLOCK,
     58	};
     59	int err;
     60
     61	threads = perf_thread_map__new_dummy();
     62	__T("failed to create threads", threads);
     63
     64	perf_thread_map__set_pid(threads, 0, 0);
     65
     66	evsel = perf_evsel__new(&attr);
     67	__T("failed to create evsel", evsel);
     68
     69	err = perf_evsel__open(evsel, NULL, threads);
     70	__T("failed to open evsel", err == 0);
     71
     72	perf_evsel__read(evsel, 0, 0, &counts);
     73	__T("failed to read value for evsel", counts.val != 0);
     74
     75	perf_evsel__close(evsel);
     76	perf_evsel__delete(evsel);
     77
     78	perf_thread_map__put(threads);
     79	return 0;
     80}
     81
     82static int test_stat_thread_enable(void)
     83{
     84	struct perf_counts_values counts = { .val = 0 };
     85	struct perf_thread_map *threads;
     86	struct perf_evsel *evsel;
     87	struct perf_event_attr attr = {
     88		.type	  = PERF_TYPE_SOFTWARE,
     89		.config	  = PERF_COUNT_SW_TASK_CLOCK,
     90		.disabled = 1,
     91	};
     92	int err;
     93
     94	threads = perf_thread_map__new_dummy();
     95	__T("failed to create threads", threads);
     96
     97	perf_thread_map__set_pid(threads, 0, 0);
     98
     99	evsel = perf_evsel__new(&attr);
    100	__T("failed to create evsel", evsel);
    101
    102	err = perf_evsel__open(evsel, NULL, threads);
    103	__T("failed to open evsel", err == 0);
    104
    105	perf_evsel__read(evsel, 0, 0, &counts);
    106	__T("failed to read value for evsel", counts.val == 0);
    107
    108	err = perf_evsel__enable(evsel);
    109	__T("failed to enable evsel", err == 0);
    110
    111	perf_evsel__read(evsel, 0, 0, &counts);
    112	__T("failed to read value for evsel", counts.val != 0);
    113
    114	err = perf_evsel__disable(evsel);
    115	__T("failed to enable evsel", err == 0);
    116
    117	perf_evsel__close(evsel);
    118	perf_evsel__delete(evsel);
    119
    120	perf_thread_map__put(threads);
    121	return 0;
    122}
    123
    124static int test_stat_user_read(int event)
    125{
    126	struct perf_counts_values counts = { .val = 0 };
    127	struct perf_thread_map *threads;
    128	struct perf_evsel *evsel;
    129	struct perf_event_mmap_page *pc;
    130	struct perf_event_attr attr = {
    131		.type	= PERF_TYPE_HARDWARE,
    132		.config	= event,
    133#ifdef __aarch64__
    134		.config1 = 0x2,		/* Request user access */
    135#endif
    136	};
    137	int err, i;
    138
    139	threads = perf_thread_map__new_dummy();
    140	__T("failed to create threads", threads);
    141
    142	perf_thread_map__set_pid(threads, 0, 0);
    143
    144	evsel = perf_evsel__new(&attr);
    145	__T("failed to create evsel", evsel);
    146
    147	err = perf_evsel__open(evsel, NULL, threads);
    148	__T("failed to open evsel", err == 0);
    149
    150	err = perf_evsel__mmap(evsel, 0);
    151	__T("failed to mmap evsel", err == 0);
    152
    153	pc = perf_evsel__mmap_base(evsel, 0, 0);
    154	__T("failed to get mmapped address", pc);
    155
    156#if defined(__i386__) || defined(__x86_64__) || defined(__aarch64__)
    157	__T("userspace counter access not supported", pc->cap_user_rdpmc);
    158	__T("userspace counter access not enabled", pc->index);
    159	__T("userspace counter width not set", pc->pmc_width >= 32);
    160#endif
    161
    162	perf_evsel__read(evsel, 0, 0, &counts);
    163	__T("failed to read value for evsel", counts.val != 0);
    164
    165	for (i = 0; i < 5; i++) {
    166		volatile int count = 0x10000 << i;
    167		__u64 start, end, last = 0;
    168
    169		__T_VERBOSE("\tloop = %u, ", count);
    170
    171		perf_evsel__read(evsel, 0, 0, &counts);
    172		start = counts.val;
    173
    174		while (count--) ;
    175
    176		perf_evsel__read(evsel, 0, 0, &counts);
    177		end = counts.val;
    178
    179		__T("invalid counter data", (end - start) > last);
    180		last = end - start;
    181		__T_VERBOSE("count = %llu\n", end - start);
    182	}
    183
    184	perf_evsel__munmap(evsel);
    185	perf_evsel__close(evsel);
    186	perf_evsel__delete(evsel);
    187
    188	perf_thread_map__put(threads);
    189	return 0;
    190}
    191
    192int test_evsel(int argc, char **argv)
    193{
    194	__T_START;
    195
    196	libperf_init(libperf_print);
    197
    198	test_stat_cpu();
    199	test_stat_thread();
    200	test_stat_thread_enable();
    201	test_stat_user_read(PERF_COUNT_HW_INSTRUCTIONS);
    202	test_stat_user_read(PERF_COUNT_HW_CPU_CYCLES);
    203
    204	__T_END;
    205	return tests_failed == 0 ? 0 : -1;
    206}