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

pmu.c (4063B)


      1// SPDX-License-Identifier: GPL-2.0
      2#include "parse-events.h"
      3#include "pmu.h"
      4#include "tests.h"
      5#include <errno.h>
      6#include <stdio.h>
      7#include <linux/kernel.h>
      8#include <linux/limits.h>
      9
     10/* Simulated format definitions. */
     11static struct test_format {
     12	const char *name;
     13	const char *value;
     14} test_formats[] = {
     15	{ "krava01", "config:0-1,62-63\n", },
     16	{ "krava02", "config:10-17\n", },
     17	{ "krava03", "config:5\n", },
     18	{ "krava11", "config1:0,2,4,6,8,20-28\n", },
     19	{ "krava12", "config1:63\n", },
     20	{ "krava13", "config1:45-47\n", },
     21	{ "krava21", "config2:0-3,10-13,20-23,30-33,40-43,50-53,60-63\n", },
     22	{ "krava22", "config2:8,18,48,58\n", },
     23	{ "krava23", "config2:28-29,38\n", },
     24};
     25
     26/* Simulated users input. */
     27static struct parse_events_term test_terms[] = {
     28	{
     29		.config    = (char *) "krava01",
     30		.val.num   = 15,
     31		.type_val  = PARSE_EVENTS__TERM_TYPE_NUM,
     32		.type_term = PARSE_EVENTS__TERM_TYPE_USER,
     33	},
     34	{
     35		.config    = (char *) "krava02",
     36		.val.num   = 170,
     37		.type_val  = PARSE_EVENTS__TERM_TYPE_NUM,
     38		.type_term = PARSE_EVENTS__TERM_TYPE_USER,
     39	},
     40	{
     41		.config    = (char *) "krava03",
     42		.val.num   = 1,
     43		.type_val  = PARSE_EVENTS__TERM_TYPE_NUM,
     44		.type_term = PARSE_EVENTS__TERM_TYPE_USER,
     45	},
     46	{
     47		.config    = (char *) "krava11",
     48		.val.num   = 27,
     49		.type_val  = PARSE_EVENTS__TERM_TYPE_NUM,
     50		.type_term = PARSE_EVENTS__TERM_TYPE_USER,
     51	},
     52	{
     53		.config    = (char *) "krava12",
     54		.val.num   = 1,
     55		.type_val  = PARSE_EVENTS__TERM_TYPE_NUM,
     56		.type_term = PARSE_EVENTS__TERM_TYPE_USER,
     57	},
     58	{
     59		.config    = (char *) "krava13",
     60		.val.num   = 2,
     61		.type_val  = PARSE_EVENTS__TERM_TYPE_NUM,
     62		.type_term = PARSE_EVENTS__TERM_TYPE_USER,
     63	},
     64	{
     65		.config    = (char *) "krava21",
     66		.val.num   = 119,
     67		.type_val  = PARSE_EVENTS__TERM_TYPE_NUM,
     68		.type_term = PARSE_EVENTS__TERM_TYPE_USER,
     69	},
     70	{
     71		.config    = (char *) "krava22",
     72		.val.num   = 11,
     73		.type_val  = PARSE_EVENTS__TERM_TYPE_NUM,
     74		.type_term = PARSE_EVENTS__TERM_TYPE_USER,
     75	},
     76	{
     77		.config    = (char *) "krava23",
     78		.val.num   = 2,
     79		.type_val  = PARSE_EVENTS__TERM_TYPE_NUM,
     80		.type_term = PARSE_EVENTS__TERM_TYPE_USER,
     81	},
     82};
     83
     84/*
     85 * Prepare format directory data, exported by kernel
     86 * at /sys/bus/event_source/devices/<dev>/format.
     87 */
     88static char *test_format_dir_get(void)
     89{
     90	static char dir[PATH_MAX];
     91	unsigned int i;
     92
     93	snprintf(dir, PATH_MAX, "/tmp/perf-pmu-test-format-XXXXXX");
     94	if (!mkdtemp(dir))
     95		return NULL;
     96
     97	for (i = 0; i < ARRAY_SIZE(test_formats); i++) {
     98		static char name[PATH_MAX];
     99		struct test_format *format = &test_formats[i];
    100		FILE *file;
    101
    102		scnprintf(name, PATH_MAX, "%s/%s", dir, format->name);
    103
    104		file = fopen(name, "w");
    105		if (!file)
    106			return NULL;
    107
    108		if (1 != fwrite(format->value, strlen(format->value), 1, file))
    109			break;
    110
    111		fclose(file);
    112	}
    113
    114	return dir;
    115}
    116
    117/* Cleanup format directory. */
    118static int test_format_dir_put(char *dir)
    119{
    120	char buf[PATH_MAX];
    121	snprintf(buf, PATH_MAX, "rm -f %s/*\n", dir);
    122	if (system(buf))
    123		return -1;
    124
    125	snprintf(buf, PATH_MAX, "rmdir %s\n", dir);
    126	return system(buf);
    127}
    128
    129static struct list_head *test_terms_list(void)
    130{
    131	static LIST_HEAD(terms);
    132	unsigned int i;
    133
    134	for (i = 0; i < ARRAY_SIZE(test_terms); i++)
    135		list_add_tail(&test_terms[i].list, &terms);
    136
    137	return &terms;
    138}
    139
    140static int test__pmu(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
    141{
    142	char *format = test_format_dir_get();
    143	LIST_HEAD(formats);
    144	struct list_head *terms = test_terms_list();
    145	int ret;
    146
    147	if (!format)
    148		return -EINVAL;
    149
    150	do {
    151		struct perf_event_attr attr;
    152
    153		memset(&attr, 0, sizeof(attr));
    154
    155		ret = perf_pmu__format_parse(format, &formats);
    156		if (ret)
    157			break;
    158
    159		ret = perf_pmu__config_terms("perf-pmu-test", &formats, &attr,
    160					     terms, false, NULL);
    161		if (ret)
    162			break;
    163
    164		ret = -EINVAL;
    165
    166		if (attr.config  != 0xc00000000002a823)
    167			break;
    168		if (attr.config1 != 0x8000400000000145)
    169			break;
    170		if (attr.config2 != 0x0400000020041d07)
    171			break;
    172
    173		ret = 0;
    174	} while (0);
    175
    176	perf_pmu__del_formats(&formats);
    177	test_format_dir_put(format);
    178	return ret;
    179}
    180
    181DEFINE_SUITE("Parse perf pmu format", pmu);