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