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

attr.c (5452B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * The struct perf_event_attr test support.
      4 *
      5 * This test is embedded inside into perf directly and is governed
      6 * by the PERF_TEST_ATTR environment variable and hook inside
      7 * sys_perf_event_open function.
      8 *
      9 * The general idea is to store 'struct perf_event_attr' details for
     10 * each event created within single perf command. Each event details
     11 * are stored into separate text file. Once perf command is finished
     12 * these files can be checked for values we expect for command.
     13 *
     14 * Besides 'struct perf_event_attr' values we also store 'fd' and
     15 * 'group_fd' values to allow checking for groups created.
     16 *
     17 * This all is triggered by setting PERF_TEST_ATTR environment variable.
     18 * It must contain name of existing directory with access and write
     19 * permissions. All the event text files are stored there.
     20 */
     21
     22#include <debug.h>
     23#include <errno.h>
     24#include <inttypes.h>
     25#include <stdlib.h>
     26#include <stdio.h>
     27#include <linux/types.h>
     28#include <linux/kernel.h>
     29#include <sys/param.h>
     30#include <sys/types.h>
     31#include <sys/stat.h>
     32#include <unistd.h>
     33#include <subcmd/exec-cmd.h>
     34#include "event.h"
     35#include "util.h"
     36#include "tests.h"
     37#include "pmu.h"
     38
     39#define ENV "PERF_TEST_ATTR"
     40
     41static char *dir;
     42static bool ready;
     43
     44void test_attr__init(void)
     45{
     46	dir = getenv(ENV);
     47	test_attr__enabled = (dir != NULL);
     48}
     49
     50#define BUFSIZE 1024
     51
     52#define __WRITE_ASS(str, fmt, data)					\
     53do {									\
     54	char buf[BUFSIZE];						\
     55	size_t size;							\
     56									\
     57	size = snprintf(buf, BUFSIZE, #str "=%"fmt "\n", data);		\
     58	if (1 != fwrite(buf, size, 1, file)) {				\
     59		perror("test attr - failed to write event file");	\
     60		fclose(file);						\
     61		return -1;						\
     62	}								\
     63									\
     64} while (0)
     65
     66#define WRITE_ASS(field, fmt) __WRITE_ASS(field, fmt, attr->field)
     67
     68static int store_event(struct perf_event_attr *attr, pid_t pid, struct perf_cpu cpu,
     69		       int fd, int group_fd, unsigned long flags)
     70{
     71	FILE *file;
     72	char path[PATH_MAX];
     73
     74	if (!ready)
     75		return 0;
     76
     77	snprintf(path, PATH_MAX, "%s/event-%d-%llu-%d", dir,
     78		 attr->type, attr->config, fd);
     79
     80	file = fopen(path, "w+");
     81	if (!file) {
     82		perror("test attr - failed to open event file");
     83		return -1;
     84	}
     85
     86	if (fprintf(file, "[event-%d-%llu-%d]\n",
     87		    attr->type, attr->config, fd) < 0) {
     88		perror("test attr - failed to write event file");
     89		fclose(file);
     90		return -1;
     91	}
     92
     93	/* syscall arguments */
     94	__WRITE_ASS(fd,       "d", fd);
     95	__WRITE_ASS(group_fd, "d", group_fd);
     96	__WRITE_ASS(cpu,      "d", cpu.cpu);
     97	__WRITE_ASS(pid,      "d", pid);
     98	__WRITE_ASS(flags,   "lu", flags);
     99
    100	/* struct perf_event_attr */
    101	WRITE_ASS(type,   PRIu32);
    102	WRITE_ASS(size,   PRIu32);
    103	WRITE_ASS(config,  "llu");
    104	WRITE_ASS(sample_period, "llu");
    105	WRITE_ASS(sample_type,   "llu");
    106	WRITE_ASS(read_format,   "llu");
    107	WRITE_ASS(disabled,       "d");
    108	WRITE_ASS(inherit,        "d");
    109	WRITE_ASS(pinned,         "d");
    110	WRITE_ASS(exclusive,      "d");
    111	WRITE_ASS(exclude_user,   "d");
    112	WRITE_ASS(exclude_kernel, "d");
    113	WRITE_ASS(exclude_hv,     "d");
    114	WRITE_ASS(exclude_idle,   "d");
    115	WRITE_ASS(mmap,           "d");
    116	WRITE_ASS(comm,           "d");
    117	WRITE_ASS(freq,           "d");
    118	WRITE_ASS(inherit_stat,   "d");
    119	WRITE_ASS(enable_on_exec, "d");
    120	WRITE_ASS(task,           "d");
    121	WRITE_ASS(watermark,      "d");
    122	WRITE_ASS(precise_ip,     "d");
    123	WRITE_ASS(mmap_data,      "d");
    124	WRITE_ASS(sample_id_all,  "d");
    125	WRITE_ASS(exclude_host,   "d");
    126	WRITE_ASS(exclude_guest,  "d");
    127	WRITE_ASS(exclude_callchain_kernel, "d");
    128	WRITE_ASS(exclude_callchain_user, "d");
    129	WRITE_ASS(mmap2,	  "d");
    130	WRITE_ASS(comm_exec,	  "d");
    131	WRITE_ASS(context_switch, "d");
    132	WRITE_ASS(write_backward, "d");
    133	WRITE_ASS(namespaces,	  "d");
    134	WRITE_ASS(use_clockid,    "d");
    135	WRITE_ASS(wakeup_events, PRIu32);
    136	WRITE_ASS(bp_type, PRIu32);
    137	WRITE_ASS(config1, "llu");
    138	WRITE_ASS(config2, "llu");
    139	WRITE_ASS(branch_sample_type, "llu");
    140	WRITE_ASS(sample_regs_user,   "llu");
    141	WRITE_ASS(sample_stack_user,  PRIu32);
    142
    143	fclose(file);
    144	return 0;
    145}
    146
    147void test_attr__open(struct perf_event_attr *attr, pid_t pid, struct perf_cpu cpu,
    148		     int fd, int group_fd, unsigned long flags)
    149{
    150	int errno_saved = errno;
    151
    152	if ((fd != -1) && store_event(attr, pid, cpu, fd, group_fd, flags)) {
    153		pr_err("test attr FAILED");
    154		exit(128);
    155	}
    156
    157	errno = errno_saved;
    158}
    159
    160void test_attr__ready(void)
    161{
    162	if (unlikely(test_attr__enabled) && !ready)
    163		ready = true;
    164}
    165
    166static int run_dir(const char *d, const char *perf)
    167{
    168	char v[] = "-vvvvv";
    169	int vcnt = min(verbose, (int) sizeof(v) - 1);
    170	char cmd[3*PATH_MAX];
    171
    172	if (verbose > 0)
    173		vcnt++;
    174
    175	scnprintf(cmd, 3*PATH_MAX, PYTHON " %s/attr.py -d %s/attr/ -p %s %.*s",
    176		  d, d, perf, vcnt, v);
    177
    178	return system(cmd) ? TEST_FAIL : TEST_OK;
    179}
    180
    181static int test__attr(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
    182{
    183	struct stat st;
    184	char path_perf[PATH_MAX];
    185	char path_dir[PATH_MAX];
    186	char *exec_path;
    187
    188	if (perf_pmu__has_hybrid())
    189		return TEST_SKIP;
    190
    191	/* First try development tree tests. */
    192	if (!lstat("./tests", &st))
    193		return run_dir("./tests", "./perf");
    194
    195	exec_path = get_argv_exec_path();
    196	if (exec_path == NULL)
    197		return -1;
    198
    199	/* Then installed path. */
    200	snprintf(path_dir,  PATH_MAX, "%s/tests", exec_path);
    201	snprintf(path_perf, PATH_MAX, "%s/perf", BINDIR);
    202	free(exec_path);
    203
    204	if (!lstat(path_dir, &st) &&
    205	    !lstat(path_perf, &st))
    206		return run_dir(path_dir, path_perf);
    207
    208	return TEST_SKIP;
    209}
    210
    211DEFINE_SUITE("Setup struct perf_event_attr", attr);